lsq_unit_impl.hh revision 8949:3fa1ee293096
13569Sgblack@eecs.umich.edu/* 23569Sgblack@eecs.umich.edu * Copyright (c) 2010-2011 ARM Limited 33569Sgblack@eecs.umich.edu * All rights reserved 43569Sgblack@eecs.umich.edu * 53569Sgblack@eecs.umich.edu * The license below extends only to copyright in the software and shall 63569Sgblack@eecs.umich.edu * not be construed as granting a license to any other intellectual 73569Sgblack@eecs.umich.edu * property including but not limited to intellectual property relating 83569Sgblack@eecs.umich.edu * to a hardware implementation of the functionality of the software 93569Sgblack@eecs.umich.edu * licensed hereunder. You may use the software subject to the license 103569Sgblack@eecs.umich.edu * terms below provided that you ensure that this notice is replicated 113569Sgblack@eecs.umich.edu * unmodified and in its entirety in all distributions of the software, 123569Sgblack@eecs.umich.edu * modified or unmodified, in source code or in binary form. 133569Sgblack@eecs.umich.edu * 143569Sgblack@eecs.umich.edu * Copyright (c) 2004-2005 The Regents of The University of Michigan 153569Sgblack@eecs.umich.edu * All rights reserved. 163569Sgblack@eecs.umich.edu * 173569Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without 183569Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are 193569Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright 203569Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer; 213569Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright 223569Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the 233569Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution; 243569Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its 253569Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from 263569Sgblack@eecs.umich.edu * this software without specific prior written permission. 273569Sgblack@eecs.umich.edu * 283804Ssaidi@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 293569Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 303569Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 313918Ssaidi@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 323918Ssaidi@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 333804Ssaidi@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 343811Ssaidi@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 353569Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 363824Ssaidi@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 373811Ssaidi@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 383811Ssaidi@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 393823Ssaidi@eecs.umich.edu * 403823Ssaidi@eecs.umich.edu * Authors: Kevin Lim 413823Ssaidi@eecs.umich.edu * Korey Sewell 424762Snate@binkert.org */ 434762Snate@binkert.org 444103Ssaidi@eecs.umich.edu#include "arch/generic/debugfaults.hh" 453569Sgblack@eecs.umich.edu#include "arch/locked_mem.hh" 463804Ssaidi@eecs.umich.edu#include "base/str.hh" 473804Ssaidi@eecs.umich.edu#include "config/the_isa.hh" 484088Sbinkertn@umich.edu#include "cpu/checker/cpu.hh" 493569Sgblack@eecs.umich.edu#include "cpu/o3/lsq.hh" 503804Ssaidi@eecs.umich.edu#include "cpu/o3/lsq_unit.hh" 513881Ssaidi@eecs.umich.edu#include "debug/Activity.hh" 523881Ssaidi@eecs.umich.edu#include "debug/IEW.hh" 533804Ssaidi@eecs.umich.edu#include "debug/LSQUnit.hh" 543804Ssaidi@eecs.umich.edu#include "mem/packet.hh" 553804Ssaidi@eecs.umich.edu#include "mem/request.hh" 563804Ssaidi@eecs.umich.edu 573569Sgblack@eecs.umich.edutemplate<class Impl> 583804Ssaidi@eecs.umich.eduLSQUnit<Impl>::WritebackEvent::WritebackEvent(DynInstPtr &_inst, PacketPtr _pkt, 593918Ssaidi@eecs.umich.edu LSQUnit *lsq_ptr) 603881Ssaidi@eecs.umich.edu : Event(Default_Pri, AutoDelete), 613881Ssaidi@eecs.umich.edu inst(_inst), pkt(_pkt), lsqPtr(lsq_ptr) 623881Ssaidi@eecs.umich.edu{ 634990Sgblack@eecs.umich.edu} 644990Sgblack@eecs.umich.edu 654990Sgblack@eecs.umich.edutemplate<class Impl> 664990Sgblack@eecs.umich.eduvoid 674990Sgblack@eecs.umich.eduLSQUnit<Impl>::WritebackEvent::process() 684990Sgblack@eecs.umich.edu{ 694990Sgblack@eecs.umich.edu if (!lsqPtr->isSwitchedOut()) { 704990Sgblack@eecs.umich.edu lsqPtr->writeback(inst, pkt); 714990Sgblack@eecs.umich.edu } 723804Ssaidi@eecs.umich.edu 733569Sgblack@eecs.umich.edu if (pkt->senderState) 743804Ssaidi@eecs.umich.edu delete pkt->senderState; 753804Ssaidi@eecs.umich.edu 763804Ssaidi@eecs.umich.edu delete pkt->req; 773804Ssaidi@eecs.umich.edu delete pkt; 783881Ssaidi@eecs.umich.edu} 793804Ssaidi@eecs.umich.edu 803804Ssaidi@eecs.umich.edutemplate<class Impl> 813804Ssaidi@eecs.umich.educonst char * 823804Ssaidi@eecs.umich.eduLSQUnit<Impl>::WritebackEvent::description() const 833804Ssaidi@eecs.umich.edu{ 843804Ssaidi@eecs.umich.edu return "Store writeback"; 853804Ssaidi@eecs.umich.edu} 863569Sgblack@eecs.umich.edu 873569Sgblack@eecs.umich.edutemplate<class Impl> 883804Ssaidi@eecs.umich.eduvoid 893804Ssaidi@eecs.umich.eduLSQUnit<Impl>::completeDataAccess(PacketPtr pkt) 903826Ssaidi@eecs.umich.edu{ 913804Ssaidi@eecs.umich.edu LSQSenderState *state = dynamic_cast<LSQSenderState *>(pkt->senderState); 923569Sgblack@eecs.umich.edu DynInstPtr inst = state->inst; 933569Sgblack@eecs.umich.edu DPRINTF(IEW, "Writeback event [sn:%lli].\n", inst->seqNum); 943804Ssaidi@eecs.umich.edu DPRINTF(Activity, "Activity: Writeback event [sn:%lli].\n", inst->seqNum); 953826Ssaidi@eecs.umich.edu 963907Ssaidi@eecs.umich.edu //iewStage->ldstQueue.removeMSHR(inst->threadNumber,inst->seqNum); 973826Ssaidi@eecs.umich.edu 983811Ssaidi@eecs.umich.edu assert(!pkt->wasNacked()); 993836Ssaidi@eecs.umich.edu 1003915Ssaidi@eecs.umich.edu // If this is a split access, wait until all packets are received. 1013907Ssaidi@eecs.umich.edu if (TheISA::HasUnalignedMemAcc && !state->complete()) { 1023881Ssaidi@eecs.umich.edu delete pkt->req; 1033881Ssaidi@eecs.umich.edu delete pkt; 1043881Ssaidi@eecs.umich.edu return; 1053881Ssaidi@eecs.umich.edu } 1063907Ssaidi@eecs.umich.edu 1073881Ssaidi@eecs.umich.edu if (isSwitchedOut() || inst->isSquashed()) { 1083881Ssaidi@eecs.umich.edu iewStage->decrWb(inst->seqNum); 1093881Ssaidi@eecs.umich.edu } else { 1103881Ssaidi@eecs.umich.edu if (!state->noWB) { 1113881Ssaidi@eecs.umich.edu if (!TheISA::HasUnalignedMemAcc || !state->isSplit || 1123907Ssaidi@eecs.umich.edu !state->isLoad) { 1133907Ssaidi@eecs.umich.edu writeback(inst, pkt); 1143907Ssaidi@eecs.umich.edu } else { 1153907Ssaidi@eecs.umich.edu writeback(inst, state->mainPkt); 1163907Ssaidi@eecs.umich.edu } 1173907Ssaidi@eecs.umich.edu } 1183907Ssaidi@eecs.umich.edu 1193907Ssaidi@eecs.umich.edu if (inst->isStore()) { 1203907Ssaidi@eecs.umich.edu completeStore(state->idx); 1213907Ssaidi@eecs.umich.edu } 1223907Ssaidi@eecs.umich.edu } 1233907Ssaidi@eecs.umich.edu 1243907Ssaidi@eecs.umich.edu if (TheISA::HasUnalignedMemAcc && state->isSplit && state->isLoad) { 1253907Ssaidi@eecs.umich.edu delete state->mainPkt->req; 1263907Ssaidi@eecs.umich.edu delete state->mainPkt; 1273907Ssaidi@eecs.umich.edu } 1283907Ssaidi@eecs.umich.edu delete state; 1293907Ssaidi@eecs.umich.edu delete pkt->req; 1303907Ssaidi@eecs.umich.edu delete pkt; 1313907Ssaidi@eecs.umich.edu} 1323907Ssaidi@eecs.umich.edu 1333907Ssaidi@eecs.umich.edutemplate <class Impl> 1343907Ssaidi@eecs.umich.eduLSQUnit<Impl>::LSQUnit() 1353881Ssaidi@eecs.umich.edu : loads(0), stores(0), storesToWB(0), cacheBlockMask(0), stalled(false), 1363881Ssaidi@eecs.umich.edu isStoreBlocked(false), isLoadBlocked(false), 1373881Ssaidi@eecs.umich.edu loadBlockedHandled(false), storeInFlight(false), hasPendingPkt(false) 1383881Ssaidi@eecs.umich.edu{ 1393881Ssaidi@eecs.umich.edu} 1403881Ssaidi@eecs.umich.edu 1413881Ssaidi@eecs.umich.edutemplate<class Impl> 1423881Ssaidi@eecs.umich.eduvoid 1433881Ssaidi@eecs.umich.eduLSQUnit<Impl>::init(O3CPU *cpu_ptr, IEW *iew_ptr, DerivO3CPUParams *params, 1443881Ssaidi@eecs.umich.edu LSQ *lsq_ptr, unsigned maxLQEntries, unsigned maxSQEntries, 1453881Ssaidi@eecs.umich.edu unsigned id) 1463881Ssaidi@eecs.umich.edu{ 1473907Ssaidi@eecs.umich.edu cpu = cpu_ptr; 1483811Ssaidi@eecs.umich.edu iewStage = iew_ptr; 1493826Ssaidi@eecs.umich.edu 1503826Ssaidi@eecs.umich.edu DPRINTF(LSQUnit, "Creating LSQUnit%i object.\n",id); 1513826Ssaidi@eecs.umich.edu 1523826Ssaidi@eecs.umich.edu switchedOut = false; 1533881Ssaidi@eecs.umich.edu 1543881Ssaidi@eecs.umich.edu cacheBlockMask = 0; 1553881Ssaidi@eecs.umich.edu 1563881Ssaidi@eecs.umich.edu lsq = lsq_ptr; 1573881Ssaidi@eecs.umich.edu 1583881Ssaidi@eecs.umich.edu lsqID = id; 1593881Ssaidi@eecs.umich.edu 1603881Ssaidi@eecs.umich.edu // Add 1 for the sentinel entry (they are circular queues). 1613881Ssaidi@eecs.umich.edu LQEntries = maxLQEntries + 1; 1623881Ssaidi@eecs.umich.edu SQEntries = maxSQEntries + 1; 1633881Ssaidi@eecs.umich.edu 1643881Ssaidi@eecs.umich.edu loadQueue.resize(LQEntries); 1653881Ssaidi@eecs.umich.edu storeQueue.resize(SQEntries); 1663881Ssaidi@eecs.umich.edu 1673881Ssaidi@eecs.umich.edu depCheckShift = params->LSQDepCheckShift; 1683826Ssaidi@eecs.umich.edu checkLoads = params->LSQCheckLoads; 1693826Ssaidi@eecs.umich.edu 1703826Ssaidi@eecs.umich.edu loadHead = loadTail = 0; 1713826Ssaidi@eecs.umich.edu 1723826Ssaidi@eecs.umich.edu storeHead = storeWBIdx = storeTail = 0; 1733881Ssaidi@eecs.umich.edu 1743569Sgblack@eecs.umich.edu usedPorts = 0; 1753569Sgblack@eecs.umich.edu cachePorts = params->cachePorts; 1763881Ssaidi@eecs.umich.edu 1773804Ssaidi@eecs.umich.edu retryPkt = NULL; 1783881Ssaidi@eecs.umich.edu memDepViolator = NULL; 1793826Ssaidi@eecs.umich.edu 1803881Ssaidi@eecs.umich.edu blockedLoadSeqNum = 0; 1813881Ssaidi@eecs.umich.edu needsTSO = params->needsTSO; 1823881Ssaidi@eecs.umich.edu} 1833907Ssaidi@eecs.umich.edu 1843907Ssaidi@eecs.umich.edutemplate<class Impl> 1853929Ssaidi@eecs.umich.edustd::string 1863929Ssaidi@eecs.umich.eduLSQUnit<Impl>::name() const 1873907Ssaidi@eecs.umich.edu{ 1883907Ssaidi@eecs.umich.edu if (Impl::MaxThreads == 1) { 1893804Ssaidi@eecs.umich.edu return iewStage->name() + ".lsq"; 1903804Ssaidi@eecs.umich.edu } else { 1913881Ssaidi@eecs.umich.edu return iewStage->name() + ".lsq.thread" + to_string(lsqID); 1923804Ssaidi@eecs.umich.edu } 1933804Ssaidi@eecs.umich.edu} 1943804Ssaidi@eecs.umich.edu 1953804Ssaidi@eecs.umich.edutemplate<class Impl> 1963804Ssaidi@eecs.umich.eduvoid 1973804Ssaidi@eecs.umich.eduLSQUnit<Impl>::regStats() 1983804Ssaidi@eecs.umich.edu{ 1993569Sgblack@eecs.umich.edu lsqForwLoads 2003569Sgblack@eecs.umich.edu .name(name() + ".forwLoads") 2013569Sgblack@eecs.umich.edu .desc("Number of loads that had data forwarded from stores"); 2023863Ssaidi@eecs.umich.edu 2033863Ssaidi@eecs.umich.edu invAddrLoads 2043804Ssaidi@eecs.umich.edu .name(name() + ".invAddrLoads") 2053804Ssaidi@eecs.umich.edu .desc("Number of loads ignored due to an invalid address"); 2063804Ssaidi@eecs.umich.edu 2073804Ssaidi@eecs.umich.edu lsqSquashedLoads 2083804Ssaidi@eecs.umich.edu .name(name() + ".squashedLoads") 2093804Ssaidi@eecs.umich.edu .desc("Number of loads squashed"); 2103804Ssaidi@eecs.umich.edu 2113804Ssaidi@eecs.umich.edu lsqIgnoredResponses 2123804Ssaidi@eecs.umich.edu .name(name() + ".ignoredResponses") 2133569Sgblack@eecs.umich.edu .desc("Number of memory responses ignored because the instruction is squashed"); 2143804Ssaidi@eecs.umich.edu 2153804Ssaidi@eecs.umich.edu lsqMemOrderViolation 2163804Ssaidi@eecs.umich.edu .name(name() + ".memOrderViolation") 2174070Ssaidi@eecs.umich.edu .desc("Number of memory ordering violations"); 2184070Ssaidi@eecs.umich.edu 2193804Ssaidi@eecs.umich.edu lsqSquashedStores 2203804Ssaidi@eecs.umich.edu .name(name() + ".squashedStores") 2213804Ssaidi@eecs.umich.edu .desc("Number of stores squashed"); 2223804Ssaidi@eecs.umich.edu 2233804Ssaidi@eecs.umich.edu invAddrSwpfs 2243811Ssaidi@eecs.umich.edu .name(name() + ".invAddrSwpfs") 2253811Ssaidi@eecs.umich.edu .desc("Number of software prefetches ignored due to an invalid address"); 2263804Ssaidi@eecs.umich.edu 2273804Ssaidi@eecs.umich.edu lsqBlockedLoads 2283863Ssaidi@eecs.umich.edu .name(name() + ".blockedLoads") 2293804Ssaidi@eecs.umich.edu .desc("Number of blocked loads due to partial load-store forwarding"); 2303804Ssaidi@eecs.umich.edu 2313804Ssaidi@eecs.umich.edu lsqRescheduledLoads 2323804Ssaidi@eecs.umich.edu .name(name() + ".rescheduledLoads") 2333804Ssaidi@eecs.umich.edu .desc("Number of loads that were rescheduled"); 2343804Ssaidi@eecs.umich.edu 2353804Ssaidi@eecs.umich.edu lsqCacheBlocked 2363811Ssaidi@eecs.umich.edu .name(name() + ".cacheBlocked") 2373804Ssaidi@eecs.umich.edu .desc("Number of times an access to memory failed due to the cache being blocked"); 2383804Ssaidi@eecs.umich.edu} 2393804Ssaidi@eecs.umich.edu 2403804Ssaidi@eecs.umich.edutemplate<class Impl> 2413804Ssaidi@eecs.umich.eduvoid 2423826Ssaidi@eecs.umich.eduLSQUnit<Impl>::setDcachePort(MasterPort *dcache_port) 2433826Ssaidi@eecs.umich.edu{ 2444070Ssaidi@eecs.umich.edu dcachePort = dcache_port; 2454070Ssaidi@eecs.umich.edu} 2464070Ssaidi@eecs.umich.edu 2474070Ssaidi@eecs.umich.edutemplate<class Impl> 2483804Ssaidi@eecs.umich.eduvoid 2493804Ssaidi@eecs.umich.eduLSQUnit<Impl>::clearLQ() 2503804Ssaidi@eecs.umich.edu{ 2513804Ssaidi@eecs.umich.edu loadQueue.clear(); 2523804Ssaidi@eecs.umich.edu} 2533804Ssaidi@eecs.umich.edu 2543804Ssaidi@eecs.umich.edutemplate<class Impl> 2553804Ssaidi@eecs.umich.eduvoid 2563804Ssaidi@eecs.umich.eduLSQUnit<Impl>::clearSQ() 2573804Ssaidi@eecs.umich.edu{ 2583804Ssaidi@eecs.umich.edu storeQueue.clear(); 2593804Ssaidi@eecs.umich.edu} 2603826Ssaidi@eecs.umich.edu 2613826Ssaidi@eecs.umich.edutemplate<class Impl> 2623826Ssaidi@eecs.umich.eduvoid 2633863Ssaidi@eecs.umich.eduLSQUnit<Impl>::switchOut() 2643826Ssaidi@eecs.umich.edu{ 2653826Ssaidi@eecs.umich.edu switchedOut = true; 2663826Ssaidi@eecs.umich.edu for (int i = 0; i < loadQueue.size(); ++i) { 2673826Ssaidi@eecs.umich.edu assert(!loadQueue[i]); 2683826Ssaidi@eecs.umich.edu loadQueue[i] = NULL; 2693826Ssaidi@eecs.umich.edu } 2703826Ssaidi@eecs.umich.edu 2713826Ssaidi@eecs.umich.edu assert(storesToWB == 0); 2723826Ssaidi@eecs.umich.edu} 2733804Ssaidi@eecs.umich.edu 2743804Ssaidi@eecs.umich.edutemplate<class Impl> 2753804Ssaidi@eecs.umich.eduvoid 2763804Ssaidi@eecs.umich.eduLSQUnit<Impl>::takeOverFrom() 2773804Ssaidi@eecs.umich.edu{ 2783804Ssaidi@eecs.umich.edu switchedOut = false; 2793804Ssaidi@eecs.umich.edu loads = stores = storesToWB = 0; 2803863Ssaidi@eecs.umich.edu 2813863Ssaidi@eecs.umich.edu loadHead = loadTail = 0; 2823863Ssaidi@eecs.umich.edu 2833836Ssaidi@eecs.umich.edu storeHead = storeWBIdx = storeTail = 0; 2843836Ssaidi@eecs.umich.edu 2853804Ssaidi@eecs.umich.edu usedPorts = 0; 2863804Ssaidi@eecs.umich.edu 2873863Ssaidi@eecs.umich.edu memDepViolator = NULL; 2883804Ssaidi@eecs.umich.edu 2893804Ssaidi@eecs.umich.edu blockedLoadSeqNum = 0; 2903804Ssaidi@eecs.umich.edu 2913804Ssaidi@eecs.umich.edu stalled = false; 2923804Ssaidi@eecs.umich.edu isLoadBlocked = false; 2933804Ssaidi@eecs.umich.edu loadBlockedHandled = false; 2943804Ssaidi@eecs.umich.edu 2953863Ssaidi@eecs.umich.edu // Just incase the memory system changed out from under us 2963804Ssaidi@eecs.umich.edu cacheBlockMask = 0; 2973804Ssaidi@eecs.umich.edu} 2983804Ssaidi@eecs.umich.edu 2993804Ssaidi@eecs.umich.edutemplate<class Impl> 3003804Ssaidi@eecs.umich.eduvoid 3013881Ssaidi@eecs.umich.eduLSQUnit<Impl>::resizeLQ(unsigned size) 3023804Ssaidi@eecs.umich.edu{ 3033804Ssaidi@eecs.umich.edu unsigned size_plus_sentinel = size + 1; 3043804Ssaidi@eecs.umich.edu assert(size_plus_sentinel >= LQEntries); 3053804Ssaidi@eecs.umich.edu 3063804Ssaidi@eecs.umich.edu if (size_plus_sentinel > LQEntries) { 3073804Ssaidi@eecs.umich.edu while (size_plus_sentinel > loadQueue.size()) { 3083804Ssaidi@eecs.umich.edu DynInstPtr dummy; 3093804Ssaidi@eecs.umich.edu loadQueue.push_back(dummy); 3103863Ssaidi@eecs.umich.edu LQEntries++; 3113863Ssaidi@eecs.umich.edu } 3123836Ssaidi@eecs.umich.edu } else { 3133804Ssaidi@eecs.umich.edu LQEntries = size_plus_sentinel; 3143804Ssaidi@eecs.umich.edu } 3153804Ssaidi@eecs.umich.edu 3163881Ssaidi@eecs.umich.edu} 3173881Ssaidi@eecs.umich.edu 3183881Ssaidi@eecs.umich.edutemplate<class Impl> 3193804Ssaidi@eecs.umich.eduvoid 3203804Ssaidi@eecs.umich.eduLSQUnit<Impl>::resizeSQ(unsigned size) 3213804Ssaidi@eecs.umich.edu{ 3223804Ssaidi@eecs.umich.edu unsigned size_plus_sentinel = size + 1; 3233804Ssaidi@eecs.umich.edu if (size_plus_sentinel > SQEntries) { 3243804Ssaidi@eecs.umich.edu while (size_plus_sentinel > storeQueue.size()) { 3253804Ssaidi@eecs.umich.edu SQEntry dummy; 3263804Ssaidi@eecs.umich.edu storeQueue.push_back(dummy); 3273804Ssaidi@eecs.umich.edu SQEntries++; 3283804Ssaidi@eecs.umich.edu } 3293804Ssaidi@eecs.umich.edu } else { 3303804Ssaidi@eecs.umich.edu SQEntries = size_plus_sentinel; 3313804Ssaidi@eecs.umich.edu } 3323804Ssaidi@eecs.umich.edu} 3333863Ssaidi@eecs.umich.edu 3343836Ssaidi@eecs.umich.edutemplate <class Impl> 3353804Ssaidi@eecs.umich.eduvoid 3363804Ssaidi@eecs.umich.eduLSQUnit<Impl>::insert(DynInstPtr &inst) 3373881Ssaidi@eecs.umich.edu{ 3383881Ssaidi@eecs.umich.edu assert(inst->isMemRef()); 3393881Ssaidi@eecs.umich.edu 3403804Ssaidi@eecs.umich.edu assert(inst->isLoad() || inst->isStore()); 3413804Ssaidi@eecs.umich.edu 3423804Ssaidi@eecs.umich.edu if (inst->isLoad()) { 3433804Ssaidi@eecs.umich.edu insertLoad(inst); 3443804Ssaidi@eecs.umich.edu } else { 3453804Ssaidi@eecs.umich.edu insertStore(inst); 3463804Ssaidi@eecs.umich.edu } 3473804Ssaidi@eecs.umich.edu 3483804Ssaidi@eecs.umich.edu inst->setInLSQ(); 3493804Ssaidi@eecs.umich.edu} 3503804Ssaidi@eecs.umich.edu 3513804Ssaidi@eecs.umich.edutemplate <class Impl> 3523804Ssaidi@eecs.umich.eduvoid 3533804Ssaidi@eecs.umich.eduLSQUnit<Impl>::insertLoad(DynInstPtr &load_inst) 3543836Ssaidi@eecs.umich.edu{ 3553836Ssaidi@eecs.umich.edu assert((loadTail + 1) % LQEntries != loadHead); 3563881Ssaidi@eecs.umich.edu assert(loads < LQEntries); 3573907Ssaidi@eecs.umich.edu 3583804Ssaidi@eecs.umich.edu DPRINTF(LSQUnit, "Inserting load PC %s, idx:%i [sn:%lli]\n", 3593881Ssaidi@eecs.umich.edu load_inst->pcState(), loadTail, load_inst->seqNum); 3603881Ssaidi@eecs.umich.edu 3613804Ssaidi@eecs.umich.edu load_inst->lqIdx = loadTail; 3623907Ssaidi@eecs.umich.edu 3633804Ssaidi@eecs.umich.edu if (stores == 0) { 3643804Ssaidi@eecs.umich.edu load_inst->sqIdx = -1; 3653804Ssaidi@eecs.umich.edu } else { 3663804Ssaidi@eecs.umich.edu load_inst->sqIdx = storeTail; 3673804Ssaidi@eecs.umich.edu } 3683804Ssaidi@eecs.umich.edu 3693881Ssaidi@eecs.umich.edu loadQueue[loadTail] = load_inst; 3703881Ssaidi@eecs.umich.edu 3713881Ssaidi@eecs.umich.edu incrLdIdx(loadTail); 3723804Ssaidi@eecs.umich.edu 3733881Ssaidi@eecs.umich.edu ++loads; 3743881Ssaidi@eecs.umich.edu} 3753881Ssaidi@eecs.umich.edu 3763881Ssaidi@eecs.umich.edutemplate <class Impl> 3773804Ssaidi@eecs.umich.eduvoid 3783804Ssaidi@eecs.umich.eduLSQUnit<Impl>::insertStore(DynInstPtr &store_inst) 3793804Ssaidi@eecs.umich.edu{ 3803804Ssaidi@eecs.umich.edu // Make sure it is not full before inserting an instruction. 3813804Ssaidi@eecs.umich.edu assert((storeTail + 1) % SQEntries != storeHead); 3823804Ssaidi@eecs.umich.edu assert(stores < SQEntries); 3833881Ssaidi@eecs.umich.edu 3843881Ssaidi@eecs.umich.edu DPRINTF(LSQUnit, "Inserting store PC %s, idx:%i [sn:%lli]\n", 3853804Ssaidi@eecs.umich.edu store_inst->pcState(), storeTail, store_inst->seqNum); 3863881Ssaidi@eecs.umich.edu 3873881Ssaidi@eecs.umich.edu store_inst->sqIdx = storeTail; 3883881Ssaidi@eecs.umich.edu store_inst->lqIdx = loadTail; 3893804Ssaidi@eecs.umich.edu 3903804Ssaidi@eecs.umich.edu storeQueue[storeTail] = SQEntry(store_inst); 3913804Ssaidi@eecs.umich.edu 3923804Ssaidi@eecs.umich.edu incrStIdx(storeTail); 3933804Ssaidi@eecs.umich.edu 3943804Ssaidi@eecs.umich.edu ++stores; 3953804Ssaidi@eecs.umich.edu} 3963804Ssaidi@eecs.umich.edu 3973804Ssaidi@eecs.umich.edutemplate <class Impl> 3983804Ssaidi@eecs.umich.edutypename Impl::DynInstPtr 3993804Ssaidi@eecs.umich.eduLSQUnit<Impl>::getMemDepViolator() 4003804Ssaidi@eecs.umich.edu{ 4013804Ssaidi@eecs.umich.edu DynInstPtr temp = memDepViolator; 4023804Ssaidi@eecs.umich.edu 4033804Ssaidi@eecs.umich.edu memDepViolator = NULL; 4043804Ssaidi@eecs.umich.edu 4054990Sgblack@eecs.umich.edu return temp; 4063804Ssaidi@eecs.umich.edu} 4073804Ssaidi@eecs.umich.edu 4083804Ssaidi@eecs.umich.edutemplate <class Impl> 4093804Ssaidi@eecs.umich.eduunsigned 4103804Ssaidi@eecs.umich.eduLSQUnit<Impl>::numFreeEntries() 4113804Ssaidi@eecs.umich.edu{ 4123804Ssaidi@eecs.umich.edu unsigned free_lq_entries = LQEntries - loads; 4133804Ssaidi@eecs.umich.edu unsigned free_sq_entries = SQEntries - stores; 4143804Ssaidi@eecs.umich.edu 4153804Ssaidi@eecs.umich.edu // Both the LQ and SQ entries have an extra dummy entry to differentiate 4163804Ssaidi@eecs.umich.edu // empty/full conditions. Subtract 1 from the free entries. 4173804Ssaidi@eecs.umich.edu if (free_lq_entries < free_sq_entries) { 4183804Ssaidi@eecs.umich.edu return free_lq_entries - 1; 4193804Ssaidi@eecs.umich.edu } else { 4203804Ssaidi@eecs.umich.edu return free_sq_entries - 1; 4213826Ssaidi@eecs.umich.edu } 4224990Sgblack@eecs.umich.edu} 4233826Ssaidi@eecs.umich.edu 4243916Ssaidi@eecs.umich.edutemplate <class Impl> 4253916Ssaidi@eecs.umich.eduint 4263916Ssaidi@eecs.umich.eduLSQUnit<Impl>::numLoadsReady() 4274990Sgblack@eecs.umich.edu{ 4283826Ssaidi@eecs.umich.edu int load_idx = loadHead; 4293804Ssaidi@eecs.umich.edu int retval = 0; 4303804Ssaidi@eecs.umich.edu 4314990Sgblack@eecs.umich.edu while (load_idx != loadTail) { 4323804Ssaidi@eecs.umich.edu assert(loadQueue[load_idx]); 4333811Ssaidi@eecs.umich.edu 4343811Ssaidi@eecs.umich.edu if (loadQueue[load_idx]->readyToIssue()) { 4354990Sgblack@eecs.umich.edu ++retval; 4363804Ssaidi@eecs.umich.edu } 4373804Ssaidi@eecs.umich.edu } 4383804Ssaidi@eecs.umich.edu 4394990Sgblack@eecs.umich.edu return retval; 4403804Ssaidi@eecs.umich.edu} 4413804Ssaidi@eecs.umich.edu 4423811Ssaidi@eecs.umich.edutemplate <class Impl> 4433811Ssaidi@eecs.umich.eduvoid 4444990Sgblack@eecs.umich.eduLSQUnit<Impl>::checkSnoop(PacketPtr pkt) 4454990Sgblack@eecs.umich.edu{ 4463804Ssaidi@eecs.umich.edu int load_idx = loadHead; 4473804Ssaidi@eecs.umich.edu 4483804Ssaidi@eecs.umich.edu if (!cacheBlockMask) { 4493804Ssaidi@eecs.umich.edu assert(dcachePort); 4503804Ssaidi@eecs.umich.edu Addr bs = dcachePort->peerBlockSize(); 4514172Ssaidi@eecs.umich.edu 4523833Ssaidi@eecs.umich.edu // Make sure we actually got a size 4533836Ssaidi@eecs.umich.edu assert(bs != 0); 4543836Ssaidi@eecs.umich.edu 4553836Ssaidi@eecs.umich.edu cacheBlockMask = ~(bs - 1); 4563836Ssaidi@eecs.umich.edu } 4573836Ssaidi@eecs.umich.edu 4583836Ssaidi@eecs.umich.edu // If this is the only load in the LSQ we don't care 4593836Ssaidi@eecs.umich.edu if (load_idx == loadTail) 4603836Ssaidi@eecs.umich.edu return; 4613836Ssaidi@eecs.umich.edu incrLdIdx(load_idx); 4623836Ssaidi@eecs.umich.edu 4633836Ssaidi@eecs.umich.edu DPRINTF(LSQUnit, "Got snoop for address %#x\n", pkt->getAddr()); 4643836Ssaidi@eecs.umich.edu Addr invalidate_addr = pkt->getAddr() & cacheBlockMask; 4653836Ssaidi@eecs.umich.edu while (load_idx != loadTail) { 4663836Ssaidi@eecs.umich.edu DynInstPtr ld_inst = loadQueue[load_idx]; 4673836Ssaidi@eecs.umich.edu 4683836Ssaidi@eecs.umich.edu if (!ld_inst->effAddrValid || ld_inst->uncacheable()) { 4693836Ssaidi@eecs.umich.edu incrLdIdx(load_idx); 4703836Ssaidi@eecs.umich.edu continue; 4713836Ssaidi@eecs.umich.edu } 4723836Ssaidi@eecs.umich.edu 4733836Ssaidi@eecs.umich.edu Addr load_addr = ld_inst->physEffAddr & cacheBlockMask; 4743836Ssaidi@eecs.umich.edu DPRINTF(LSQUnit, "-- inst [sn:%lli] load_addr: %#x to pktAddr:%#x\n", 4753836Ssaidi@eecs.umich.edu ld_inst->seqNum, load_addr, invalidate_addr); 4763833Ssaidi@eecs.umich.edu 4773833Ssaidi@eecs.umich.edu if (load_addr == invalidate_addr) { 4783833Ssaidi@eecs.umich.edu if (ld_inst->possibleLoadViolation) { 4793833Ssaidi@eecs.umich.edu DPRINTF(LSQUnit, "Conflicting load at addr %#x [sn:%lli]\n", 4803833Ssaidi@eecs.umich.edu ld_inst->physEffAddr, pkt->getAddr(), ld_inst->seqNum); 4813833Ssaidi@eecs.umich.edu 4823833Ssaidi@eecs.umich.edu // Mark the load for re-execution 4833833Ssaidi@eecs.umich.edu ld_inst->fault = new ReExec; 4843833Ssaidi@eecs.umich.edu } else { 4853804Ssaidi@eecs.umich.edu // If a older load checks this and it's true 4863804Ssaidi@eecs.umich.edu // then we might have missed the snoop 4873804Ssaidi@eecs.umich.edu // in which case we need to invalidate to be sure 4883804Ssaidi@eecs.umich.edu ld_inst->hitExternalSnoop = true; 4893804Ssaidi@eecs.umich.edu } 4903833Ssaidi@eecs.umich.edu } 4913833Ssaidi@eecs.umich.edu incrLdIdx(load_idx); 4923811Ssaidi@eecs.umich.edu } 4933804Ssaidi@eecs.umich.edu return; 4943804Ssaidi@eecs.umich.edu} 4953804Ssaidi@eecs.umich.edu 4963804Ssaidi@eecs.umich.edutemplate <class Impl> 4973804Ssaidi@eecs.umich.eduFault 4983804Ssaidi@eecs.umich.eduLSQUnit<Impl>::checkViolations(int load_idx, DynInstPtr &inst) 4993804Ssaidi@eecs.umich.edu{ 5003833Ssaidi@eecs.umich.edu Addr inst_eff_addr1 = inst->effAddr >> depCheckShift; 5013804Ssaidi@eecs.umich.edu Addr inst_eff_addr2 = (inst->effAddr + inst->effSize - 1) >> depCheckShift; 5023804Ssaidi@eecs.umich.edu 5033833Ssaidi@eecs.umich.edu /** @todo in theory you only need to check an instruction that has executed 5043836Ssaidi@eecs.umich.edu * however, there isn't a good way in the pipeline at the moment to check 5053836Ssaidi@eecs.umich.edu * all instructions that will execute before the store writes back. Thus, 5063836Ssaidi@eecs.umich.edu * like the implementation that came before it, we're overly conservative. 5073836Ssaidi@eecs.umich.edu */ 5083804Ssaidi@eecs.umich.edu while (load_idx != loadTail) { 5093804Ssaidi@eecs.umich.edu DynInstPtr ld_inst = loadQueue[load_idx]; 5103804Ssaidi@eecs.umich.edu if (!ld_inst->effAddrValid || ld_inst->uncacheable()) { 5113836Ssaidi@eecs.umich.edu incrLdIdx(load_idx); 5123836Ssaidi@eecs.umich.edu continue; 5134990Sgblack@eecs.umich.edu } 5143804Ssaidi@eecs.umich.edu 5153804Ssaidi@eecs.umich.edu Addr ld_eff_addr1 = ld_inst->effAddr >> depCheckShift; 5163804Ssaidi@eecs.umich.edu Addr ld_eff_addr2 = 5173804Ssaidi@eecs.umich.edu (ld_inst->effAddr + ld_inst->effSize - 1) >> depCheckShift; 5183804Ssaidi@eecs.umich.edu 5193804Ssaidi@eecs.umich.edu if (inst_eff_addr2 >= ld_eff_addr1 && inst_eff_addr1 <= ld_eff_addr2) { 5203804Ssaidi@eecs.umich.edu if (inst->isLoad()) { 5214990Sgblack@eecs.umich.edu // If this load is to the same block as an external snoop 5223804Ssaidi@eecs.umich.edu // invalidate that we've observed then the load needs to be 5233804Ssaidi@eecs.umich.edu // squashed as it could have newer data 5243804Ssaidi@eecs.umich.edu if (ld_inst->hitExternalSnoop) { 5253833Ssaidi@eecs.umich.edu if (!memDepViolator || 5263836Ssaidi@eecs.umich.edu ld_inst->seqNum < memDepViolator->seqNum) { 5273804Ssaidi@eecs.umich.edu DPRINTF(LSQUnit, "Detected fault with inst [sn:%lli] " 5283804Ssaidi@eecs.umich.edu "and [sn:%lli] at address %#x\n", 5293804Ssaidi@eecs.umich.edu inst->seqNum, ld_inst->seqNum, ld_eff_addr1); 5303804Ssaidi@eecs.umich.edu memDepViolator = ld_inst; 5313804Ssaidi@eecs.umich.edu 5323804Ssaidi@eecs.umich.edu ++lsqMemOrderViolation; 5333804Ssaidi@eecs.umich.edu 5344990Sgblack@eecs.umich.edu return new GenericISA::M5PanicFault( 5353804Ssaidi@eecs.umich.edu "Detected fault with inst [sn:%lli] and " 5363804Ssaidi@eecs.umich.edu "[sn:%lli] at address %#x\n", 5373804Ssaidi@eecs.umich.edu inst->seqNum, ld_inst->seqNum, ld_eff_addr1); 5383804Ssaidi@eecs.umich.edu } 5393804Ssaidi@eecs.umich.edu } 5403804Ssaidi@eecs.umich.edu 5413804Ssaidi@eecs.umich.edu // Otherwise, mark the load has a possible load violation 5423804Ssaidi@eecs.umich.edu // and if we see a snoop before it's commited, we need to squash 5434990Sgblack@eecs.umich.edu ld_inst->possibleLoadViolation = true; 5444990Sgblack@eecs.umich.edu DPRINTF(LSQUnit, "Found possible load violaiton at addr: %#x" 5453804Ssaidi@eecs.umich.edu " between instructions [sn:%lli] and [sn:%lli]\n", 5463804Ssaidi@eecs.umich.edu inst_eff_addr1, inst->seqNum, ld_inst->seqNum); 5473804Ssaidi@eecs.umich.edu } else { 5483836Ssaidi@eecs.umich.edu // A load/store incorrectly passed this store. 5493836Ssaidi@eecs.umich.edu // Check if we already have a violator, or if it's newer 5503836Ssaidi@eecs.umich.edu // squash and refetch. 5513836Ssaidi@eecs.umich.edu if (memDepViolator && ld_inst->seqNum > memDepViolator->seqNum) 5523836Ssaidi@eecs.umich.edu break; 5533826Ssaidi@eecs.umich.edu 5543836Ssaidi@eecs.umich.edu DPRINTF(LSQUnit, "Detected fault with inst [sn:%lli] and " 5553836Ssaidi@eecs.umich.edu "[sn:%lli] at address %#x\n", 5563804Ssaidi@eecs.umich.edu inst->seqNum, ld_inst->seqNum, ld_eff_addr1); 5573804Ssaidi@eecs.umich.edu memDepViolator = ld_inst; 5583804Ssaidi@eecs.umich.edu 5593804Ssaidi@eecs.umich.edu ++lsqMemOrderViolation; 5603804Ssaidi@eecs.umich.edu 5613804Ssaidi@eecs.umich.edu return new GenericISA::M5PanicFault("Detected fault with " 5623804Ssaidi@eecs.umich.edu "inst [sn:%lli] and [sn:%lli] at address %#x\n", 5633804Ssaidi@eecs.umich.edu inst->seqNum, ld_inst->seqNum, ld_eff_addr1); 5643804Ssaidi@eecs.umich.edu } 5654172Ssaidi@eecs.umich.edu } 5663836Ssaidi@eecs.umich.edu 5673836Ssaidi@eecs.umich.edu incrLdIdx(load_idx); 5683836Ssaidi@eecs.umich.edu } 5693836Ssaidi@eecs.umich.edu return NoFault; 5703836Ssaidi@eecs.umich.edu} 5713836Ssaidi@eecs.umich.edu 5723833Ssaidi@eecs.umich.edu 5733836Ssaidi@eecs.umich.edu 5743836Ssaidi@eecs.umich.edu 5753836Ssaidi@eecs.umich.edutemplate <class Impl> 5763929Ssaidi@eecs.umich.eduFault 5773929Ssaidi@eecs.umich.eduLSQUnit<Impl>::executeLoad(DynInstPtr &inst) 5783929Ssaidi@eecs.umich.edu{ 5793836Ssaidi@eecs.umich.edu using namespace TheISA; 5803836Ssaidi@eecs.umich.edu // Execute a specific load. 5813836Ssaidi@eecs.umich.edu Fault load_fault = NoFault; 5823836Ssaidi@eecs.umich.edu 5833836Ssaidi@eecs.umich.edu DPRINTF(LSQUnit, "Executing load PC %s, [sn:%lli]\n", 5843836Ssaidi@eecs.umich.edu inst->pcState(), inst->seqNum); 5853836Ssaidi@eecs.umich.edu 5863836Ssaidi@eecs.umich.edu assert(!inst->isSquashed()); 5873836Ssaidi@eecs.umich.edu 5883836Ssaidi@eecs.umich.edu load_fault = inst->initiateAcc(); 5894090Ssaidi@eecs.umich.edu 5904090Ssaidi@eecs.umich.edu if (inst->isTranslationDelayed() && 5914090Ssaidi@eecs.umich.edu load_fault == NoFault) 5924989Sgblack@eecs.umich.edu return load_fault; 5934090Ssaidi@eecs.umich.edu 5944989Sgblack@eecs.umich.edu // If the instruction faulted or predicated false, then we need to send it 5954090Ssaidi@eecs.umich.edu // along to commit without the instruction completing. 5964090Ssaidi@eecs.umich.edu if (load_fault != NoFault || inst->readPredicate() == false) { 5974090Ssaidi@eecs.umich.edu // Send this instruction to commit, also make sure iew stage 5984090Ssaidi@eecs.umich.edu // realizes there is activity. 5994090Ssaidi@eecs.umich.edu // Mark it as executed unless it is an uncached load that 6004090Ssaidi@eecs.umich.edu // needs to hit the head of commit. 6014090Ssaidi@eecs.umich.edu if (inst->readPredicate() == false) 6024090Ssaidi@eecs.umich.edu inst->forwardOldRegs(); 6034090Ssaidi@eecs.umich.edu DPRINTF(LSQUnit, "Load [sn:%lli] not executed from %s\n", 6044090Ssaidi@eecs.umich.edu inst->seqNum, 6054090Ssaidi@eecs.umich.edu (load_fault != NoFault ? "fault" : "predication")); 6064090Ssaidi@eecs.umich.edu if (!(inst->hasRequest() && inst->uncacheable()) || 6074090Ssaidi@eecs.umich.edu inst->isAtCommit()) { 6084090Ssaidi@eecs.umich.edu inst->setExecuted(); 6094090Ssaidi@eecs.umich.edu } 6104090Ssaidi@eecs.umich.edu iewStage->instToCommit(inst); 6114090Ssaidi@eecs.umich.edu iewStage->activityThisCycle(); 6124090Ssaidi@eecs.umich.edu } else if (!loadBlocked()) { 6134090Ssaidi@eecs.umich.edu assert(inst->effAddrValid); 6144090Ssaidi@eecs.umich.edu int load_idx = inst->lqIdx; 6154090Ssaidi@eecs.umich.edu incrLdIdx(load_idx); 6164090Ssaidi@eecs.umich.edu 6174090Ssaidi@eecs.umich.edu if (checkLoads) 6184090Ssaidi@eecs.umich.edu return checkViolations(load_idx, inst); 6193836Ssaidi@eecs.umich.edu } 6203833Ssaidi@eecs.umich.edu 6213833Ssaidi@eecs.umich.edu return load_fault; 6223833Ssaidi@eecs.umich.edu} 6233833Ssaidi@eecs.umich.edu 6243833Ssaidi@eecs.umich.edutemplate <class Impl> 6253833Ssaidi@eecs.umich.eduFault 6263833Ssaidi@eecs.umich.eduLSQUnit<Impl>::executeStore(DynInstPtr &store_inst) 6273833Ssaidi@eecs.umich.edu{ 6283916Ssaidi@eecs.umich.edu using namespace TheISA; 6293833Ssaidi@eecs.umich.edu // Make sure that a store exists. 6303804Ssaidi@eecs.umich.edu assert(stores != 0); 6313832Ssaidi@eecs.umich.edu 6323832Ssaidi@eecs.umich.edu int store_idx = store_inst->sqIdx; 6333804Ssaidi@eecs.umich.edu 6343804Ssaidi@eecs.umich.edu DPRINTF(LSQUnit, "Executing store PC %s [sn:%lli]\n", 6353804Ssaidi@eecs.umich.edu store_inst->pcState(), store_inst->seqNum); 6363833Ssaidi@eecs.umich.edu 6373833Ssaidi@eecs.umich.edu assert(!store_inst->isSquashed()); 6383804Ssaidi@eecs.umich.edu 6393804Ssaidi@eecs.umich.edu // Check the recently completed loads to see if any match this store's 6403804Ssaidi@eecs.umich.edu // address. If so, then we have a memory ordering violation. 6413804Ssaidi@eecs.umich.edu int load_idx = store_inst->lqIdx; 6423804Ssaidi@eecs.umich.edu 6433804Ssaidi@eecs.umich.edu Fault store_fault = store_inst->initiateAcc(); 6443804Ssaidi@eecs.umich.edu 6453804Ssaidi@eecs.umich.edu if (store_inst->isTranslationDelayed() && 6463804Ssaidi@eecs.umich.edu store_fault == NoFault) 6473833Ssaidi@eecs.umich.edu return store_fault; 6483804Ssaidi@eecs.umich.edu 6493910Ssaidi@eecs.umich.edu if (store_inst->readPredicate() == false) 6503804Ssaidi@eecs.umich.edu store_inst->forwardOldRegs(); 6513910Ssaidi@eecs.umich.edu 6523804Ssaidi@eecs.umich.edu if (storeQueue[store_idx].size == 0) { 6534990Sgblack@eecs.umich.edu DPRINTF(LSQUnit,"Fault on Store PC %s, [sn:%lli], Size = 0\n", 6543804Ssaidi@eecs.umich.edu store_inst->pcState(), store_inst->seqNum); 6553804Ssaidi@eecs.umich.edu 6563910Ssaidi@eecs.umich.edu return store_fault; 6573910Ssaidi@eecs.umich.edu } else if (store_inst->readPredicate() == false) { 6584990Sgblack@eecs.umich.edu DPRINTF(LSQUnit, "Store [sn:%lli] not executed from predication\n", 6593804Ssaidi@eecs.umich.edu store_inst->seqNum); 6603804Ssaidi@eecs.umich.edu return store_fault; 6613804Ssaidi@eecs.umich.edu } 6623910Ssaidi@eecs.umich.edu 6633910Ssaidi@eecs.umich.edu assert(store_fault == NoFault); 6643910Ssaidi@eecs.umich.edu 6653910Ssaidi@eecs.umich.edu if (store_inst->isStoreConditional()) { 6663910Ssaidi@eecs.umich.edu // Store conditionals need to set themselves as able to 6673910Ssaidi@eecs.umich.edu // writeback if we haven't had a fault by here. 6683910Ssaidi@eecs.umich.edu storeQueue[store_idx].canWB = true; 6693910Ssaidi@eecs.umich.edu 6703910Ssaidi@eecs.umich.edu ++storesToWB; 6713910Ssaidi@eecs.umich.edu } 6723910Ssaidi@eecs.umich.edu 6733910Ssaidi@eecs.umich.edu return checkViolations(load_idx, store_inst); 6743910Ssaidi@eecs.umich.edu 6753902Ssaidi@eecs.umich.edu} 6763804Ssaidi@eecs.umich.edu 6773926Ssaidi@eecs.umich.edutemplate <class Impl> 6783804Ssaidi@eecs.umich.eduvoid 6793804Ssaidi@eecs.umich.eduLSQUnit<Impl>::commitLoad() 6804989Sgblack@eecs.umich.edu{ 6814989Sgblack@eecs.umich.edu assert(loadQueue[loadHead]); 6824989Sgblack@eecs.umich.edu 6834989Sgblack@eecs.umich.edu DPRINTF(LSQUnit, "Committing head load instruction, PC %s\n", 6844989Sgblack@eecs.umich.edu loadQueue[loadHead]->pcState()); 6854989Sgblack@eecs.umich.edu 6863856Ssaidi@eecs.umich.edu loadQueue[loadHead] = NULL; 6873804Ssaidi@eecs.umich.edu 6883804Ssaidi@eecs.umich.edu incrLdIdx(loadHead); 6894103Ssaidi@eecs.umich.edu 6904191Ssaidi@eecs.umich.edu --loads; 6914191Ssaidi@eecs.umich.edu} 6924191Ssaidi@eecs.umich.edu 6933824Ssaidi@eecs.umich.edutemplate <class Impl> 6944103Ssaidi@eecs.umich.eduvoid 6953804Ssaidi@eecs.umich.eduLSQUnit<Impl>::commitLoads(InstSeqNum &youngest_inst) 6963804Ssaidi@eecs.umich.edu{ 6973804Ssaidi@eecs.umich.edu assert(loads == 0 || loadQueue[loadHead]); 6983804Ssaidi@eecs.umich.edu 6993824Ssaidi@eecs.umich.edu while (loads != 0 && loadQueue[loadHead]->seqNum <= youngest_inst) { 7003824Ssaidi@eecs.umich.edu commitLoad(); 7013825Ssaidi@eecs.umich.edu } 7023825Ssaidi@eecs.umich.edu} 7033823Ssaidi@eecs.umich.edu 7043926Ssaidi@eecs.umich.edutemplate <class Impl> 7054989Sgblack@eecs.umich.eduvoid 7063823Ssaidi@eecs.umich.eduLSQUnit<Impl>::commitStores(InstSeqNum &youngest_inst) 7073804Ssaidi@eecs.umich.edu{ 7083804Ssaidi@eecs.umich.edu assert(stores == 0 || storeQueue[storeHead].inst); 7093826Ssaidi@eecs.umich.edu 7103826Ssaidi@eecs.umich.edu int store_idx = storeHead; 7114990Sgblack@eecs.umich.edu 7123826Ssaidi@eecs.umich.edu while (store_idx != storeTail) { 7133826Ssaidi@eecs.umich.edu assert(storeQueue[store_idx].inst); 7143826Ssaidi@eecs.umich.edu // Mark any stores that are now committed and have not yet 7153826Ssaidi@eecs.umich.edu // been marked as able to write back. 7163826Ssaidi@eecs.umich.edu if (!storeQueue[store_idx].canWB) { 7173826Ssaidi@eecs.umich.edu if (storeQueue[store_idx].inst->seqNum > youngest_inst) { 7183826Ssaidi@eecs.umich.edu break; 7194990Sgblack@eecs.umich.edu } 7203826Ssaidi@eecs.umich.edu DPRINTF(LSQUnit, "Marking store as able to write back, PC " 7213826Ssaidi@eecs.umich.edu "%s [sn:%lli]\n", 7223826Ssaidi@eecs.umich.edu storeQueue[store_idx].inst->pcState(), 7233826Ssaidi@eecs.umich.edu storeQueue[store_idx].inst->seqNum); 7243910Ssaidi@eecs.umich.edu 7253804Ssaidi@eecs.umich.edu storeQueue[store_idx].canWB = true; 7263804Ssaidi@eecs.umich.edu 7273804Ssaidi@eecs.umich.edu ++storesToWB; 7283804Ssaidi@eecs.umich.edu } 7293804Ssaidi@eecs.umich.edu 7303836Ssaidi@eecs.umich.edu incrStIdx(store_idx); 7313804Ssaidi@eecs.umich.edu } 7323804Ssaidi@eecs.umich.edu} 7333804Ssaidi@eecs.umich.edu 7343836Ssaidi@eecs.umich.edutemplate <class Impl> 7353804Ssaidi@eecs.umich.eduvoid 7363804Ssaidi@eecs.umich.eduLSQUnit<Impl>::writebackPendingStore() 7374990Sgblack@eecs.umich.edu{ 7383811Ssaidi@eecs.umich.edu if (hasPendingPkt) { 7393804Ssaidi@eecs.umich.edu assert(pendingPkt != NULL); 7403804Ssaidi@eecs.umich.edu 7413804Ssaidi@eecs.umich.edu // If the cache is blocked, this will store the packet for retry. 7423804Ssaidi@eecs.umich.edu if (sendStore(pendingPkt)) { 7433804Ssaidi@eecs.umich.edu storePostSend(pendingPkt); 7443804Ssaidi@eecs.umich.edu } 7453804Ssaidi@eecs.umich.edu pendingPkt = NULL; 7463928Ssaidi@eecs.umich.edu hasPendingPkt = false; 7474990Sgblack@eecs.umich.edu } 7484990Sgblack@eecs.umich.edu} 7493928Ssaidi@eecs.umich.edu 7503928Ssaidi@eecs.umich.edutemplate <class Impl> 7513804Ssaidi@eecs.umich.eduvoid 7523804Ssaidi@eecs.umich.eduLSQUnit<Impl>::writebackStores() 7534990Sgblack@eecs.umich.edu{ 7544990Sgblack@eecs.umich.edu // First writeback the second packet from any split store that didn't 7553804Ssaidi@eecs.umich.edu // complete last cycle because there weren't enough cache ports available. 7563804Ssaidi@eecs.umich.edu if (TheISA::HasUnalignedMemAcc) { 7573804Ssaidi@eecs.umich.edu writebackPendingStore(); 7583804Ssaidi@eecs.umich.edu } 7594990Sgblack@eecs.umich.edu 7604990Sgblack@eecs.umich.edu while (storesToWB > 0 && 7613804Ssaidi@eecs.umich.edu storeWBIdx != storeTail && 7623804Ssaidi@eecs.umich.edu storeQueue[storeWBIdx].inst && 7633804Ssaidi@eecs.umich.edu storeQueue[storeWBIdx].canWB && 7643928Ssaidi@eecs.umich.edu ((!needsTSO) || (!storeInFlight)) && 7654990Sgblack@eecs.umich.edu usedPorts < cachePorts) { 7664990Sgblack@eecs.umich.edu 7673928Ssaidi@eecs.umich.edu if (isStoreBlocked || lsq->cacheBlocked()) { 7683928Ssaidi@eecs.umich.edu DPRINTF(LSQUnit, "Unable to write back any more stores, cache" 7693928Ssaidi@eecs.umich.edu " is blocked!\n"); 7703928Ssaidi@eecs.umich.edu break; 7714090Ssaidi@eecs.umich.edu } 7723804Ssaidi@eecs.umich.edu 7733804Ssaidi@eecs.umich.edu // Store didn't write any data so no need to write it back to 7743836Ssaidi@eecs.umich.edu // memory. 7753836Ssaidi@eecs.umich.edu if (storeQueue[storeWBIdx].size == 0) { 7763881Ssaidi@eecs.umich.edu completeStore(storeWBIdx); 7773881Ssaidi@eecs.umich.edu 7783881Ssaidi@eecs.umich.edu incrStIdx(storeWBIdx); 7793881Ssaidi@eecs.umich.edu 7803881Ssaidi@eecs.umich.edu continue; 7813836Ssaidi@eecs.umich.edu } 7823836Ssaidi@eecs.umich.edu 7833836Ssaidi@eecs.umich.edu ++usedPorts; 7843836Ssaidi@eecs.umich.edu 7853836Ssaidi@eecs.umich.edu if (storeQueue[storeWBIdx].inst->isDataPrefetch()) { 7863836Ssaidi@eecs.umich.edu incrStIdx(storeWBIdx); 7873836Ssaidi@eecs.umich.edu 7883836Ssaidi@eecs.umich.edu continue; 7893881Ssaidi@eecs.umich.edu } 7903826Ssaidi@eecs.umich.edu 7913836Ssaidi@eecs.umich.edu assert(storeQueue[storeWBIdx].req); 7923836Ssaidi@eecs.umich.edu assert(!storeQueue[storeWBIdx].committed); 7933804Ssaidi@eecs.umich.edu 7944103Ssaidi@eecs.umich.edu if (TheISA::HasUnalignedMemAcc && storeQueue[storeWBIdx].isSplit) { 7953806Ssaidi@eecs.umich.edu assert(storeQueue[storeWBIdx].sreqLow); 7964103Ssaidi@eecs.umich.edu assert(storeQueue[storeWBIdx].sreqHigh); 7974103Ssaidi@eecs.umich.edu } 7984990Sgblack@eecs.umich.edu 7994103Ssaidi@eecs.umich.edu DynInstPtr inst = storeQueue[storeWBIdx].inst; 8004103Ssaidi@eecs.umich.edu 8014103Ssaidi@eecs.umich.edu Request *req = storeQueue[storeWBIdx].req; 8024103Ssaidi@eecs.umich.edu RequestPtr sreqLow = storeQueue[storeWBIdx].sreqLow; 8034103Ssaidi@eecs.umich.edu RequestPtr sreqHigh = storeQueue[storeWBIdx].sreqHigh; 8044103Ssaidi@eecs.umich.edu 8054103Ssaidi@eecs.umich.edu storeQueue[storeWBIdx].committed = true; 8064103Ssaidi@eecs.umich.edu 8074990Sgblack@eecs.umich.edu assert(!inst->memData); 8084103Ssaidi@eecs.umich.edu inst->memData = new uint8_t[64]; 8094103Ssaidi@eecs.umich.edu 8104103Ssaidi@eecs.umich.edu memcpy(inst->memData, storeQueue[storeWBIdx].data, req->getSize()); 8114103Ssaidi@eecs.umich.edu 8124103Ssaidi@eecs.umich.edu MemCmd command = 8133804Ssaidi@eecs.umich.edu req->isSwap() ? MemCmd::SwapReq : 8143806Ssaidi@eecs.umich.edu (req->isLLSC() ? MemCmd::StoreCondReq : MemCmd::WriteReq); 8153806Ssaidi@eecs.umich.edu PacketPtr data_pkt; 8164990Sgblack@eecs.umich.edu PacketPtr snd_data_pkt = NULL; 8173806Ssaidi@eecs.umich.edu 8183806Ssaidi@eecs.umich.edu LSQSenderState *state = new LSQSenderState; 8193824Ssaidi@eecs.umich.edu state->isLoad = false; 8203824Ssaidi@eecs.umich.edu state->idx = storeWBIdx; 8213824Ssaidi@eecs.umich.edu state->inst = inst; 8223824Ssaidi@eecs.umich.edu 8234990Sgblack@eecs.umich.edu if (!TheISA::HasUnalignedMemAcc || !storeQueue[storeWBIdx].isSplit) { 8243824Ssaidi@eecs.umich.edu 8253824Ssaidi@eecs.umich.edu // Build a single data packet if the store isn't split. 8263881Ssaidi@eecs.umich.edu data_pkt = new Packet(req, command); 8274990Sgblack@eecs.umich.edu data_pkt->dataStatic(inst->memData); 8283824Ssaidi@eecs.umich.edu data_pkt->senderState = state; 8293824Ssaidi@eecs.umich.edu } else { 8303824Ssaidi@eecs.umich.edu // Create two packets if the store is split in two. 8313824Ssaidi@eecs.umich.edu data_pkt = new Packet(sreqLow, command); 8323825Ssaidi@eecs.umich.edu snd_data_pkt = new Packet(sreqHigh, command); 8333825Ssaidi@eecs.umich.edu 8344990Sgblack@eecs.umich.edu data_pkt->dataStatic(inst->memData); 8354070Ssaidi@eecs.umich.edu snd_data_pkt->dataStatic(inst->memData + sreqLow->getSize()); 8363825Ssaidi@eecs.umich.edu 8374070Ssaidi@eecs.umich.edu data_pkt->senderState = state; 8383825Ssaidi@eecs.umich.edu snd_data_pkt->senderState = state; 8393825Ssaidi@eecs.umich.edu 8403825Ssaidi@eecs.umich.edu state->isSplit = true; 8413825Ssaidi@eecs.umich.edu state->outstanding = 2; 8423825Ssaidi@eecs.umich.edu 8433824Ssaidi@eecs.umich.edu // Can delete the main request now. 8443804Ssaidi@eecs.umich.edu delete req; 8453811Ssaidi@eecs.umich.edu req = sreqLow; 8463806Ssaidi@eecs.umich.edu } 8473806Ssaidi@eecs.umich.edu 8483806Ssaidi@eecs.umich.edu DPRINTF(LSQUnit, "D-Cache: Writing back store idx:%i PC:%s " 8493804Ssaidi@eecs.umich.edu "to Addr:%#x, data:%#x [sn:%lli]\n", 8503804Ssaidi@eecs.umich.edu storeWBIdx, inst->pcState(), 8513806Ssaidi@eecs.umich.edu req->getPaddr(), (int)*(inst->memData), 8523806Ssaidi@eecs.umich.edu inst->seqNum); 8533806Ssaidi@eecs.umich.edu 8543823Ssaidi@eecs.umich.edu // @todo: Remove this SC hack once the memory system handles it. 8553823Ssaidi@eecs.umich.edu if (inst->isStoreConditional()) { 8564070Ssaidi@eecs.umich.edu assert(!storeQueue[storeWBIdx].isSplit); 8573823Ssaidi@eecs.umich.edu // Disable recording the result temporarily. Writing to 8583823Ssaidi@eecs.umich.edu // misc regs normally updates the result, but this is not 8593823Ssaidi@eecs.umich.edu // the desired behavior when handling store conditionals. 8603823Ssaidi@eecs.umich.edu inst->recordResult = false; 8614990Sgblack@eecs.umich.edu bool success = TheISA::handleLockedWrite(inst.get(), req); 8624990Sgblack@eecs.umich.edu inst->recordResult = true; 8633823Ssaidi@eecs.umich.edu 8643823Ssaidi@eecs.umich.edu if (!success) { 8653823Ssaidi@eecs.umich.edu // Instantly complete this store. 8664172Ssaidi@eecs.umich.edu DPRINTF(LSQUnit, "Store conditional [sn:%lli] failed. " 8673823Ssaidi@eecs.umich.edu "Instantly completing it.\n", 8683823Ssaidi@eecs.umich.edu inst->seqNum); 8693823Ssaidi@eecs.umich.edu WritebackEvent *wb = new WritebackEvent(inst, data_pkt, this); 8703823Ssaidi@eecs.umich.edu cpu->schedule(wb, curTick() + 1); 8714172Ssaidi@eecs.umich.edu if (cpu->checker) { 8723823Ssaidi@eecs.umich.edu // Make sure to set the LLSC data for verification 8733823Ssaidi@eecs.umich.edu // if checker is loaded 8744172Ssaidi@eecs.umich.edu inst->reqToVerify->setExtraData(0); 8753823Ssaidi@eecs.umich.edu inst->completeAcc(data_pkt); 8763823Ssaidi@eecs.umich.edu } 8773823Ssaidi@eecs.umich.edu completeStore(storeWBIdx); 8783823Ssaidi@eecs.umich.edu incrStIdx(storeWBIdx); 8793823Ssaidi@eecs.umich.edu continue; 8803824Ssaidi@eecs.umich.edu } 8814172Ssaidi@eecs.umich.edu } else { 8823824Ssaidi@eecs.umich.edu // Non-store conditionals do not need a writeback. 8833824Ssaidi@eecs.umich.edu state->noWB = true; 8843823Ssaidi@eecs.umich.edu } 8853823Ssaidi@eecs.umich.edu 8864990Sgblack@eecs.umich.edu bool split = 8873823Ssaidi@eecs.umich.edu TheISA::HasUnalignedMemAcc && storeQueue[storeWBIdx].isSplit; 8883823Ssaidi@eecs.umich.edu 8893823Ssaidi@eecs.umich.edu ThreadContext *thread = cpu->tcBase(lsqID); 8904990Sgblack@eecs.umich.edu 8913823Ssaidi@eecs.umich.edu if (req->isMmappedIpr()) { 8923823Ssaidi@eecs.umich.edu assert(!inst->isStoreConditional()); 8933823Ssaidi@eecs.umich.edu TheISA::handleIprWrite(thread, data_pkt); 8944990Sgblack@eecs.umich.edu delete data_pkt; 8953823Ssaidi@eecs.umich.edu if (split) { 8963823Ssaidi@eecs.umich.edu assert(snd_data_pkt->req->isMmappedIpr()); 8973823Ssaidi@eecs.umich.edu TheISA::handleIprWrite(thread, snd_data_pkt); 8984990Sgblack@eecs.umich.edu delete snd_data_pkt; 8993823Ssaidi@eecs.umich.edu delete sreqLow; 9003823Ssaidi@eecs.umich.edu delete sreqHigh; 9013823Ssaidi@eecs.umich.edu } 9024990Sgblack@eecs.umich.edu delete state; 9033823Ssaidi@eecs.umich.edu delete req; 9043823Ssaidi@eecs.umich.edu completeStore(storeWBIdx); 9053823Ssaidi@eecs.umich.edu incrStIdx(storeWBIdx); 9064990Sgblack@eecs.umich.edu } else if (!sendStore(data_pkt)) { 9073823Ssaidi@eecs.umich.edu DPRINTF(IEW, "D-Cache became blocked when writing [sn:%lli], will" 9083823Ssaidi@eecs.umich.edu "retry later\n", 9093823Ssaidi@eecs.umich.edu inst->seqNum); 9104990Sgblack@eecs.umich.edu 9113823Ssaidi@eecs.umich.edu // Need to store the second packet, if split. 9123823Ssaidi@eecs.umich.edu if (split) { 9133823Ssaidi@eecs.umich.edu state->pktToSend = true; 9144990Sgblack@eecs.umich.edu state->pendingPacket = snd_data_pkt; 9153823Ssaidi@eecs.umich.edu } 9163823Ssaidi@eecs.umich.edu } else { 9173823Ssaidi@eecs.umich.edu 9184990Sgblack@eecs.umich.edu // If split, try to send the second packet too 9193823Ssaidi@eecs.umich.edu if (split) { 9203823Ssaidi@eecs.umich.edu assert(snd_data_pkt); 9213823Ssaidi@eecs.umich.edu 9224990Sgblack@eecs.umich.edu // Ensure there are enough ports to use. 9233823Ssaidi@eecs.umich.edu if (usedPorts < cachePorts) { 9243823Ssaidi@eecs.umich.edu ++usedPorts; 9253823Ssaidi@eecs.umich.edu if (sendStore(snd_data_pkt)) { 9264990Sgblack@eecs.umich.edu storePostSend(snd_data_pkt); 9273823Ssaidi@eecs.umich.edu } else { 9283823Ssaidi@eecs.umich.edu DPRINTF(IEW, "D-Cache became blocked when writing" 9293823Ssaidi@eecs.umich.edu " [sn:%lli] second packet, will retry later\n", 9304990Sgblack@eecs.umich.edu inst->seqNum); 9313823Ssaidi@eecs.umich.edu } 9323826Ssaidi@eecs.umich.edu } else { 9333912Ssaidi@eecs.umich.edu 9343826Ssaidi@eecs.umich.edu // Store the packet for when there's free ports. 9353823Ssaidi@eecs.umich.edu assert(pendingPkt == NULL); 9363823Ssaidi@eecs.umich.edu pendingPkt = snd_data_pkt; 9374172Ssaidi@eecs.umich.edu hasPendingPkt = true; 9383823Ssaidi@eecs.umich.edu } 9393826Ssaidi@eecs.umich.edu } else { 9403826Ssaidi@eecs.umich.edu 9413833Ssaidi@eecs.umich.edu // Not a split store. 9424990Sgblack@eecs.umich.edu storePostSend(data_pkt); 9433833Ssaidi@eecs.umich.edu } 9443833Ssaidi@eecs.umich.edu } 9453906Ssaidi@eecs.umich.edu } 9464990Sgblack@eecs.umich.edu 9473906Ssaidi@eecs.umich.edu // Not sure this should set it to 0. 9483826Ssaidi@eecs.umich.edu usedPorts = 0; 9494990Sgblack@eecs.umich.edu 9503826Ssaidi@eecs.umich.edu assert(stores >= 0 && storesToWB >= 0); 9513826Ssaidi@eecs.umich.edu} 9523826Ssaidi@eecs.umich.edu 9533826Ssaidi@eecs.umich.edu/*template <class Impl> 9543826Ssaidi@eecs.umich.eduvoid 9553823Ssaidi@eecs.umich.eduLSQUnit<Impl>::removeMSHR(InstSeqNum seqNum) 9563823Ssaidi@eecs.umich.edu{ 9573833Ssaidi@eecs.umich.edu list<InstSeqNum>::iterator mshr_it = find(mshrSeqNums.begin(), 9584990Sgblack@eecs.umich.edu mshrSeqNums.end(), 9593833Ssaidi@eecs.umich.edu seqNum); 9603833Ssaidi@eecs.umich.edu 9613906Ssaidi@eecs.umich.edu if (mshr_it != mshrSeqNums.end()) { 9624990Sgblack@eecs.umich.edu mshrSeqNums.erase(mshr_it); 9633906Ssaidi@eecs.umich.edu DPRINTF(LSQUnit, "Removing MSHR. count = %i\n",mshrSeqNums.size()); 9643906Ssaidi@eecs.umich.edu } 9654990Sgblack@eecs.umich.edu}*/ 9663906Ssaidi@eecs.umich.edu 9673826Ssaidi@eecs.umich.edutemplate <class Impl> 9684990Sgblack@eecs.umich.eduvoid 9693826Ssaidi@eecs.umich.eduLSQUnit<Impl>::squash(const InstSeqNum &squashed_num) 9703823Ssaidi@eecs.umich.edu{ 9714172Ssaidi@eecs.umich.edu DPRINTF(LSQUnit, "Squashing until [sn:%lli]!" 9723823Ssaidi@eecs.umich.edu "(Loads:%i Stores:%i)\n", squashed_num, loads, stores); 9733823Ssaidi@eecs.umich.edu 9743823Ssaidi@eecs.umich.edu int load_idx = loadTail; 9753823Ssaidi@eecs.umich.edu decrLdIdx(load_idx); 9763823Ssaidi@eecs.umich.edu 9773833Ssaidi@eecs.umich.edu while (loads != 0 && loadQueue[load_idx]->seqNum > squashed_num) { 9784070Ssaidi@eecs.umich.edu DPRINTF(LSQUnit,"Load Instruction PC %s squashed, " 9794990Sgblack@eecs.umich.edu "[sn:%lli]\n", 9804990Sgblack@eecs.umich.edu loadQueue[load_idx]->pcState(), 9814990Sgblack@eecs.umich.edu loadQueue[load_idx]->seqNum); 9824990Sgblack@eecs.umich.edu 9834990Sgblack@eecs.umich.edu if (isStalled() && load_idx == stallingLoadIdx) { 9843833Ssaidi@eecs.umich.edu stalled = false; 9853833Ssaidi@eecs.umich.edu stallingStoreIsn = 0; 9864070Ssaidi@eecs.umich.edu stallingLoadIdx = 0; 9874990Sgblack@eecs.umich.edu } 9884990Sgblack@eecs.umich.edu 9894990Sgblack@eecs.umich.edu // Clear the smart pointer to make sure it is decremented. 9904990Sgblack@eecs.umich.edu loadQueue[load_idx]->setSquashed(); 9914990Sgblack@eecs.umich.edu loadQueue[load_idx] = NULL; 9923833Ssaidi@eecs.umich.edu --loads; 9933899Ssaidi@eecs.umich.edu 9944070Ssaidi@eecs.umich.edu // Inefficient! 9954990Sgblack@eecs.umich.edu loadTail = load_idx; 9964990Sgblack@eecs.umich.edu 9974990Sgblack@eecs.umich.edu decrLdIdx(load_idx); 9984990Sgblack@eecs.umich.edu ++lsqSquashedLoads; 9994990Sgblack@eecs.umich.edu } 10003899Ssaidi@eecs.umich.edu 10013899Ssaidi@eecs.umich.edu if (isLoadBlocked) { 10024070Ssaidi@eecs.umich.edu if (squashed_num < blockedLoadSeqNum) { 10034990Sgblack@eecs.umich.edu isLoadBlocked = false; 10044990Sgblack@eecs.umich.edu loadBlockedHandled = false; 10054990Sgblack@eecs.umich.edu blockedLoadSeqNum = 0; 10064990Sgblack@eecs.umich.edu } 10074990Sgblack@eecs.umich.edu } 10083899Ssaidi@eecs.umich.edu 10094103Ssaidi@eecs.umich.edu if (memDepViolator && squashed_num < memDepViolator->seqNum) { 10104103Ssaidi@eecs.umich.edu memDepViolator = NULL; 10114103Ssaidi@eecs.umich.edu } 10124103Ssaidi@eecs.umich.edu 10134103Ssaidi@eecs.umich.edu int store_idx = storeTail; 10144103Ssaidi@eecs.umich.edu decrStIdx(store_idx); 10154103Ssaidi@eecs.umich.edu 10164103Ssaidi@eecs.umich.edu while (stores != 0 && 10173823Ssaidi@eecs.umich.edu storeQueue[store_idx].inst->seqNum > squashed_num) { 10183823Ssaidi@eecs.umich.edu // Instructions marked as can WB are already committed. 10193823Ssaidi@eecs.umich.edu if (storeQueue[store_idx].canWB) { 10203823Ssaidi@eecs.umich.edu break; 10213823Ssaidi@eecs.umich.edu } 10224870Sstever@eecs.umich.edu 10233823Ssaidi@eecs.umich.edu DPRINTF(LSQUnit,"Store Instruction PC %s squashed, " 10243806Ssaidi@eecs.umich.edu "idx:%i [sn:%lli]\n", 10253806Ssaidi@eecs.umich.edu storeQueue[store_idx].inst->pcState(), 10263806Ssaidi@eecs.umich.edu store_idx, storeQueue[store_idx].inst->seqNum); 10273806Ssaidi@eecs.umich.edu 10283806Ssaidi@eecs.umich.edu // I don't think this can happen. It should have been cleared 10293823Ssaidi@eecs.umich.edu // by the stalling load. 10303823Ssaidi@eecs.umich.edu if (isStalled() && 10313823Ssaidi@eecs.umich.edu storeQueue[store_idx].inst->seqNum == stallingStoreIsn) { 10323823Ssaidi@eecs.umich.edu panic("Is stalled should have been cleared by stalling load!\n"); 10333826Ssaidi@eecs.umich.edu stalled = false; 10343826Ssaidi@eecs.umich.edu stallingStoreIsn = 0; 10353826Ssaidi@eecs.umich.edu } 10363826Ssaidi@eecs.umich.edu 10373826Ssaidi@eecs.umich.edu // Clear the smart pointer to make sure it is decremented. 10383826Ssaidi@eecs.umich.edu storeQueue[store_idx].inst->setSquashed(); 10393863Ssaidi@eecs.umich.edu storeQueue[store_idx].inst = NULL; 10403863Ssaidi@eecs.umich.edu storeQueue[store_idx].canWB = 0; 10413863Ssaidi@eecs.umich.edu 10423826Ssaidi@eecs.umich.edu // Must delete request now that it wasn't handed off to 10433826Ssaidi@eecs.umich.edu // memory. This is quite ugly. @todo: Figure out the proper 10443825Ssaidi@eecs.umich.edu // place to really handle request deletes. 10453823Ssaidi@eecs.umich.edu delete storeQueue[store_idx].req; 10463823Ssaidi@eecs.umich.edu if (TheISA::HasUnalignedMemAcc && storeQueue[store_idx].isSplit) { 10474990Sgblack@eecs.umich.edu delete storeQueue[store_idx].sreqLow; 10484990Sgblack@eecs.umich.edu delete storeQueue[store_idx].sreqHigh; 10493823Ssaidi@eecs.umich.edu 10503823Ssaidi@eecs.umich.edu storeQueue[store_idx].sreqLow = NULL; 10513823Ssaidi@eecs.umich.edu storeQueue[store_idx].sreqHigh = NULL; 10524172Ssaidi@eecs.umich.edu } 10533823Ssaidi@eecs.umich.edu 10543823Ssaidi@eecs.umich.edu storeQueue[store_idx].req = NULL; 10553823Ssaidi@eecs.umich.edu --stores; 10563823Ssaidi@eecs.umich.edu 10574172Ssaidi@eecs.umich.edu // Inefficient! 10583823Ssaidi@eecs.umich.edu storeTail = store_idx; 10593823Ssaidi@eecs.umich.edu 10604172Ssaidi@eecs.umich.edu decrStIdx(store_idx); 10613823Ssaidi@eecs.umich.edu ++lsqSquashedStores; 10623823Ssaidi@eecs.umich.edu } 10633823Ssaidi@eecs.umich.edu} 10643823Ssaidi@eecs.umich.edu 10653823Ssaidi@eecs.umich.edutemplate <class Impl> 10663824Ssaidi@eecs.umich.eduvoid 10673825Ssaidi@eecs.umich.eduLSQUnit<Impl>::storePostSend(PacketPtr pkt) 10684172Ssaidi@eecs.umich.edu{ 10693824Ssaidi@eecs.umich.edu if (isStalled() && 10703824Ssaidi@eecs.umich.edu storeQueue[storeWBIdx].inst->seqNum == stallingStoreIsn) { 10713823Ssaidi@eecs.umich.edu DPRINTF(LSQUnit, "Unstalling, stalling store [sn:%lli] " 10723823Ssaidi@eecs.umich.edu "load idx:%i\n", 10734990Sgblack@eecs.umich.edu stallingStoreIsn, stallingLoadIdx); 10743823Ssaidi@eecs.umich.edu stalled = false; 10753823Ssaidi@eecs.umich.edu stallingStoreIsn = 0; 10763823Ssaidi@eecs.umich.edu iewStage->replayMemInst(loadQueue[stallingLoadIdx]); 10774990Sgblack@eecs.umich.edu } 10783823Ssaidi@eecs.umich.edu 10793823Ssaidi@eecs.umich.edu if (!storeQueue[storeWBIdx].inst->isStoreConditional()) { 10803823Ssaidi@eecs.umich.edu // The store is basically completed at this time. This 10814990Sgblack@eecs.umich.edu // only works so long as the checker doesn't try to 10823823Ssaidi@eecs.umich.edu // verify the value in memory for stores. 10833823Ssaidi@eecs.umich.edu storeQueue[storeWBIdx].inst->setCompleted(); 10843823Ssaidi@eecs.umich.edu 10854990Sgblack@eecs.umich.edu if (cpu->checker) { 10863823Ssaidi@eecs.umich.edu cpu->checker->verify(storeQueue[storeWBIdx].inst); 10873823Ssaidi@eecs.umich.edu } 10883823Ssaidi@eecs.umich.edu } 10894990Sgblack@eecs.umich.edu 10903823Ssaidi@eecs.umich.edu if (needsTSO) { 10913823Ssaidi@eecs.umich.edu storeInFlight = true; 10923823Ssaidi@eecs.umich.edu } 10934990Sgblack@eecs.umich.edu 10943823Ssaidi@eecs.umich.edu incrStIdx(storeWBIdx); 10953823Ssaidi@eecs.umich.edu} 10963823Ssaidi@eecs.umich.edu 10974990Sgblack@eecs.umich.edutemplate <class Impl> 10983823Ssaidi@eecs.umich.eduvoid 10993823Ssaidi@eecs.umich.eduLSQUnit<Impl>::writeback(DynInstPtr &inst, PacketPtr pkt) 11003823Ssaidi@eecs.umich.edu{ 11014990Sgblack@eecs.umich.edu iewStage->wakeCPU(); 11023823Ssaidi@eecs.umich.edu 11033823Ssaidi@eecs.umich.edu // Squashed instructions do not need to complete their access. 11043823Ssaidi@eecs.umich.edu if (inst->isSquashed()) { 11054990Sgblack@eecs.umich.edu iewStage->decrWb(inst->seqNum); 11063823Ssaidi@eecs.umich.edu assert(!inst->isStore()); 11073823Ssaidi@eecs.umich.edu ++lsqIgnoredResponses; 11083823Ssaidi@eecs.umich.edu return; 11094990Sgblack@eecs.umich.edu } 11103823Ssaidi@eecs.umich.edu 11113823Ssaidi@eecs.umich.edu if (!inst->isExecuted()) { 11123823Ssaidi@eecs.umich.edu inst->setExecuted(); 11134990Sgblack@eecs.umich.edu 11143823Ssaidi@eecs.umich.edu // Complete access to copy data to proper place. 11153823Ssaidi@eecs.umich.edu inst->completeAcc(pkt); 11163823Ssaidi@eecs.umich.edu } 11174990Sgblack@eecs.umich.edu 11183823Ssaidi@eecs.umich.edu // Need to insert instruction into queue to commit 11193825Ssaidi@eecs.umich.edu iewStage->instToCommit(inst); 11203825Ssaidi@eecs.umich.edu 11213825Ssaidi@eecs.umich.edu iewStage->activityThisCycle(); 11223825Ssaidi@eecs.umich.edu 11233823Ssaidi@eecs.umich.edu // see if this load changed the PC 11243823Ssaidi@eecs.umich.edu iewStage->checkMisprediction(inst); 11254172Ssaidi@eecs.umich.edu} 11263823Ssaidi@eecs.umich.edu 11273826Ssaidi@eecs.umich.edutemplate <class Impl> 11283826Ssaidi@eecs.umich.eduvoid 11293906Ssaidi@eecs.umich.eduLSQUnit<Impl>::completeStore(int store_idx) 11304990Sgblack@eecs.umich.edu{ 11313906Ssaidi@eecs.umich.edu assert(storeQueue[store_idx].inst); 11323826Ssaidi@eecs.umich.edu storeQueue[store_idx].completed = true; 11333916Ssaidi@eecs.umich.edu --storesToWB; 11344990Sgblack@eecs.umich.edu // A bit conservative because a store completion may not free up entries, 11353826Ssaidi@eecs.umich.edu // but hopefully avoids two store completions in one cycle from making 11363826Ssaidi@eecs.umich.edu // the CPU tick twice. 11373826Ssaidi@eecs.umich.edu cpu->wakeCPU(); 11383826Ssaidi@eecs.umich.edu cpu->activityThisCycle(); 11393826Ssaidi@eecs.umich.edu 11403826Ssaidi@eecs.umich.edu if (store_idx == storeHead) { 11413826Ssaidi@eecs.umich.edu do { 11423826Ssaidi@eecs.umich.edu incrStIdx(storeHead); 11433826Ssaidi@eecs.umich.edu 11444990Sgblack@eecs.umich.edu --stores; 11453826Ssaidi@eecs.umich.edu } while (storeQueue[storeHead].completed && 11463826Ssaidi@eecs.umich.edu storeHead != storeTail); 11474172Ssaidi@eecs.umich.edu 11483826Ssaidi@eecs.umich.edu iewStage->updateLSQNextCycle = true; 11493826Ssaidi@eecs.umich.edu } 11503826Ssaidi@eecs.umich.edu 11513826Ssaidi@eecs.umich.edu DPRINTF(LSQUnit, "Completing store [sn:%lli], idx:%i, store head " 11523826Ssaidi@eecs.umich.edu "idx:%i\n", 11533826Ssaidi@eecs.umich.edu storeQueue[store_idx].inst->seqNum, store_idx, storeHead); 11543826Ssaidi@eecs.umich.edu 11553826Ssaidi@eecs.umich.edu if (isStalled() && 11563826Ssaidi@eecs.umich.edu storeQueue[store_idx].inst->seqNum == stallingStoreIsn) { 11573826Ssaidi@eecs.umich.edu DPRINTF(LSQUnit, "Unstalling, stalling store [sn:%lli] " 11584990Sgblack@eecs.umich.edu "load idx:%i\n", 11593826Ssaidi@eecs.umich.edu stallingStoreIsn, stallingLoadIdx); 11603826Ssaidi@eecs.umich.edu stalled = false; 11614172Ssaidi@eecs.umich.edu stallingStoreIsn = 0; 11623826Ssaidi@eecs.umich.edu iewStage->replayMemInst(loadQueue[stallingLoadIdx]); 11633826Ssaidi@eecs.umich.edu } 11643826Ssaidi@eecs.umich.edu 11653826Ssaidi@eecs.umich.edu storeQueue[store_idx].inst->setCompleted(); 11663826Ssaidi@eecs.umich.edu 11673863Ssaidi@eecs.umich.edu if (needsTSO) { 11683863Ssaidi@eecs.umich.edu storeInFlight = false; 11693863Ssaidi@eecs.umich.edu } 11704172Ssaidi@eecs.umich.edu 11713863Ssaidi@eecs.umich.edu // Tell the checker we've completed this instruction. Some stores 11723863Ssaidi@eecs.umich.edu // may get reported twice to the checker, but the checker can 11734172Ssaidi@eecs.umich.edu // handle that case. 11743863Ssaidi@eecs.umich.edu if (cpu->checker) { 11753863Ssaidi@eecs.umich.edu cpu->checker->verify(storeQueue[store_idx].inst); 11763863Ssaidi@eecs.umich.edu } 11773863Ssaidi@eecs.umich.edu} 11783863Ssaidi@eecs.umich.edu 11793863Ssaidi@eecs.umich.edutemplate <class Impl> 11803863Ssaidi@eecs.umich.edubool 11813863Ssaidi@eecs.umich.eduLSQUnit<Impl>::sendStore(PacketPtr data_pkt) 11823863Ssaidi@eecs.umich.edu{ 11833863Ssaidi@eecs.umich.edu if (!dcachePort->sendTiming(data_pkt)) { 11843863Ssaidi@eecs.umich.edu // Need to handle becoming blocked on a store. 11853863Ssaidi@eecs.umich.edu isStoreBlocked = true; 11863863Ssaidi@eecs.umich.edu ++lsqCacheBlocked; 11873863Ssaidi@eecs.umich.edu assert(retryPkt == NULL); 11883863Ssaidi@eecs.umich.edu retryPkt = data_pkt; 11893863Ssaidi@eecs.umich.edu lsq->setRetryTid(lsqID); 11903863Ssaidi@eecs.umich.edu return false; 11913863Ssaidi@eecs.umich.edu } 11923863Ssaidi@eecs.umich.edu return true; 11933863Ssaidi@eecs.umich.edu} 11943863Ssaidi@eecs.umich.edu 11953863Ssaidi@eecs.umich.edutemplate <class Impl> 11963863Ssaidi@eecs.umich.eduvoid 11973863Ssaidi@eecs.umich.eduLSQUnit<Impl>::recvRetry() 11983863Ssaidi@eecs.umich.edu{ 11993863Ssaidi@eecs.umich.edu if (isStoreBlocked) { 12003863Ssaidi@eecs.umich.edu DPRINTF(LSQUnit, "Receiving retry: store blocked\n"); 12013863Ssaidi@eecs.umich.edu assert(retryPkt != NULL); 12023823Ssaidi@eecs.umich.edu 12033823Ssaidi@eecs.umich.edu LSQSenderState *state = 12043906Ssaidi@eecs.umich.edu dynamic_cast<LSQSenderState *>(retryPkt->senderState); 12054990Sgblack@eecs.umich.edu 12063906Ssaidi@eecs.umich.edu if (dcachePort->sendTiming(retryPkt)) { 12073826Ssaidi@eecs.umich.edu // Don't finish the store unless this is the last packet. 12083916Ssaidi@eecs.umich.edu if (!TheISA::HasUnalignedMemAcc || !state->pktToSend || 12094990Sgblack@eecs.umich.edu state->pendingPacket == retryPkt) { 12103826Ssaidi@eecs.umich.edu state->pktToSend = false; 12113823Ssaidi@eecs.umich.edu storePostSend(retryPkt); 12124172Ssaidi@eecs.umich.edu } 12133823Ssaidi@eecs.umich.edu retryPkt = NULL; 12143823Ssaidi@eecs.umich.edu isStoreBlocked = false; 12153823Ssaidi@eecs.umich.edu lsq->setRetryTid(InvalidThreadID); 12163823Ssaidi@eecs.umich.edu 12173823Ssaidi@eecs.umich.edu // Send any outstanding packet. 12183863Ssaidi@eecs.umich.edu if (TheISA::HasUnalignedMemAcc && state->pktToSend) { 12193863Ssaidi@eecs.umich.edu assert(state->pendingPacket); 12203863Ssaidi@eecs.umich.edu if (sendStore(state->pendingPacket)) { 12214172Ssaidi@eecs.umich.edu storePostSend(state->pendingPacket); 12223863Ssaidi@eecs.umich.edu } 12233863Ssaidi@eecs.umich.edu } 12244172Ssaidi@eecs.umich.edu } else { 12253863Ssaidi@eecs.umich.edu // Still blocked! 12263863Ssaidi@eecs.umich.edu ++lsqCacheBlocked; 12274172Ssaidi@eecs.umich.edu lsq->setRetryTid(lsqID); 12283863Ssaidi@eecs.umich.edu } 12293863Ssaidi@eecs.umich.edu } else if (isLoadBlocked) { 12303863Ssaidi@eecs.umich.edu DPRINTF(LSQUnit, "Loads squash themselves and all younger insts, " 12313863Ssaidi@eecs.umich.edu "no need to resend packet.\n"); 12323863Ssaidi@eecs.umich.edu } else { 12333863Ssaidi@eecs.umich.edu DPRINTF(LSQUnit, "Retry received but LSQ is no longer blocked.\n"); 12343863Ssaidi@eecs.umich.edu } 12353863Ssaidi@eecs.umich.edu} 12363863Ssaidi@eecs.umich.edu 12373863Ssaidi@eecs.umich.edutemplate <class Impl> 12383863Ssaidi@eecs.umich.eduinline void 12393863Ssaidi@eecs.umich.eduLSQUnit<Impl>::incrStIdx(int &store_idx) 12403863Ssaidi@eecs.umich.edu{ 12413863Ssaidi@eecs.umich.edu if (++store_idx >= SQEntries) 12423863Ssaidi@eecs.umich.edu store_idx = 0; 12433863Ssaidi@eecs.umich.edu} 12443863Ssaidi@eecs.umich.edu 12453863Ssaidi@eecs.umich.edutemplate <class Impl> 12463863Ssaidi@eecs.umich.eduinline void 12473863Ssaidi@eecs.umich.eduLSQUnit<Impl>::decrStIdx(int &store_idx) 12483863Ssaidi@eecs.umich.edu{ 12493863Ssaidi@eecs.umich.edu if (--store_idx < 0) 12503863Ssaidi@eecs.umich.edu store_idx += SQEntries; 12513863Ssaidi@eecs.umich.edu} 12524103Ssaidi@eecs.umich.edu 12534103Ssaidi@eecs.umich.edutemplate <class Impl> 12544103Ssaidi@eecs.umich.eduinline void 12554103Ssaidi@eecs.umich.eduLSQUnit<Impl>::incrLdIdx(int &load_idx) 12564103Ssaidi@eecs.umich.edu{ 12574103Ssaidi@eecs.umich.edu if (++load_idx >= LQEntries) 12584103Ssaidi@eecs.umich.edu load_idx = 0; 12594103Ssaidi@eecs.umich.edu} 12604103Ssaidi@eecs.umich.edu 12614103Ssaidi@eecs.umich.edutemplate <class Impl> 12624103Ssaidi@eecs.umich.eduinline void 12634103Ssaidi@eecs.umich.eduLSQUnit<Impl>::decrLdIdx(int &load_idx) 12644103Ssaidi@eecs.umich.edu{ 12653823Ssaidi@eecs.umich.edu if (--load_idx < 0) 12663823Ssaidi@eecs.umich.edu load_idx += LQEntries; 12673823Ssaidi@eecs.umich.edu} 12683823Ssaidi@eecs.umich.edu 12694870Sstever@eecs.umich.edutemplate <class Impl> 12703823Ssaidi@eecs.umich.eduvoid 12713806Ssaidi@eecs.umich.eduLSQUnit<Impl>::dumpInsts() 12723806Ssaidi@eecs.umich.edu{ 12733804Ssaidi@eecs.umich.edu cprintf("Load store queue: Dumping instructions.\n"); 12744070Ssaidi@eecs.umich.edu cprintf("Load queue size: %i\n", loads); 12754070Ssaidi@eecs.umich.edu cprintf("Load queue: "); 12764070Ssaidi@eecs.umich.edu 12774990Sgblack@eecs.umich.edu int load_idx = loadHead; 12784070Ssaidi@eecs.umich.edu 12794990Sgblack@eecs.umich.edu while (load_idx != loadTail && loadQueue[load_idx]) { 12804990Sgblack@eecs.umich.edu cprintf("%s ", loadQueue[load_idx]->pcState()); 12814990Sgblack@eecs.umich.edu 12824990Sgblack@eecs.umich.edu incrLdIdx(load_idx); 12834070Ssaidi@eecs.umich.edu } 12844990Sgblack@eecs.umich.edu 12854990Sgblack@eecs.umich.edu cprintf("Store queue size: %i\n", stores); 12864990Sgblack@eecs.umich.edu cprintf("Store queue: "); 12874990Sgblack@eecs.umich.edu 12884070Ssaidi@eecs.umich.edu int store_idx = storeHead; 12894990Sgblack@eecs.umich.edu 12904990Sgblack@eecs.umich.edu while (store_idx != storeTail && storeQueue[store_idx].inst) { 12914990Sgblack@eecs.umich.edu cprintf("%s ", storeQueue[store_idx].inst->pcState()); 12924990Sgblack@eecs.umich.edu 12934070Ssaidi@eecs.umich.edu incrStIdx(store_idx); 12944990Sgblack@eecs.umich.edu } 12954990Sgblack@eecs.umich.edu 12964990Sgblack@eecs.umich.edu cprintf("\n"); 12974990Sgblack@eecs.umich.edu} 12984070Ssaidi@eecs.umich.edu