lsq_unit_impl.hh revision 3492
17087Snate@binkert.org/* 27087Snate@binkert.org * Copyright (c) 2004-2005 The Regents of The University of Michigan 37087Snate@binkert.org * All rights reserved. 47087Snate@binkert.org * 57087Snate@binkert.org * Redistribution and use in source and binary forms, with or without 67087Snate@binkert.org * modification, are permitted provided that the following conditions are 77087Snate@binkert.org * met: redistributions of source code must retain the above copyright 87087Snate@binkert.org * notice, this list of conditions and the following disclaimer; 97087Snate@binkert.org * redistributions in binary form must reproduce the above copyright 107087Snate@binkert.org * notice, this list of conditions and the following disclaimer in the 117087Snate@binkert.org * documentation and/or other materials provided with the distribution; 127087Snate@binkert.org * neither the name of the copyright holders nor the names of its 135359Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from 145359Sgblack@eecs.umich.edu * this software without specific prior written permission. 155359Sgblack@eecs.umich.edu * 165359Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 175359Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 185359Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 195359Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 205359Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 215359Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 225359Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 235359Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 245359Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 255359Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 265359Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 275359Sgblack@eecs.umich.edu * 285359Sgblack@eecs.umich.edu * Authors: Kevin Lim 295359Sgblack@eecs.umich.edu * Korey Sewell 305359Sgblack@eecs.umich.edu */ 315359Sgblack@eecs.umich.edu 325359Sgblack@eecs.umich.edu#include "config/use_checker.hh" 335359Sgblack@eecs.umich.edu 345359Sgblack@eecs.umich.edu#include "cpu/o3/lsq.hh" 355359Sgblack@eecs.umich.edu#include "cpu/o3/lsq_unit.hh" 365359Sgblack@eecs.umich.edu#include "base/str.hh" 375359Sgblack@eecs.umich.edu#include "mem/packet.hh" 385359Sgblack@eecs.umich.edu#include "mem/request.hh" 395359Sgblack@eecs.umich.edu 405359Sgblack@eecs.umich.edu#if USE_CHECKER 414561Sgblack@eecs.umich.edu#include "cpu/checker/cpu.hh" 424561Sgblack@eecs.umich.edu#endif 434561Sgblack@eecs.umich.edu 444561Sgblack@eecs.umich.edutemplate<class Impl> 454561Sgblack@eecs.umich.eduLSQUnit<Impl>::WritebackEvent::WritebackEvent(DynInstPtr &_inst, PacketPtr _pkt, 464561Sgblack@eecs.umich.edu LSQUnit *lsq_ptr) 474601Sgblack@eecs.umich.edu : Event(&mainEventQueue), inst(_inst), pkt(_pkt), lsqPtr(lsq_ptr) 484601Sgblack@eecs.umich.edu{ 494601Sgblack@eecs.umich.edu this->setFlags(Event::AutoDelete); 504601Sgblack@eecs.umich.edu} 514601Sgblack@eecs.umich.edu 524601Sgblack@eecs.umich.edutemplate<class Impl> 534601Sgblack@eecs.umich.eduvoid 544601Sgblack@eecs.umich.eduLSQUnit<Impl>::WritebackEvent::process() 554601Sgblack@eecs.umich.edu{ 564601Sgblack@eecs.umich.edu if (!lsqPtr->isSwitchedOut()) { 574601Sgblack@eecs.umich.edu lsqPtr->writeback(inst, pkt); 584601Sgblack@eecs.umich.edu } 594601Sgblack@eecs.umich.edu delete pkt; 604601Sgblack@eecs.umich.edu} 614601Sgblack@eecs.umich.edu 624601Sgblack@eecs.umich.edutemplate<class Impl> 634601Sgblack@eecs.umich.educonst char * 644601Sgblack@eecs.umich.eduLSQUnit<Impl>::WritebackEvent::description() 654601Sgblack@eecs.umich.edu{ 664601Sgblack@eecs.umich.edu return "Store writeback event"; 674601Sgblack@eecs.umich.edu} 684601Sgblack@eecs.umich.edu 694601Sgblack@eecs.umich.edutemplate<class Impl> 704601Sgblack@eecs.umich.eduvoid 714601Sgblack@eecs.umich.eduLSQUnit<Impl>::completeDataAccess(PacketPtr pkt) 724601Sgblack@eecs.umich.edu{ 734601Sgblack@eecs.umich.edu LSQSenderState *state = dynamic_cast<LSQSenderState *>(pkt->senderState); 744601Sgblack@eecs.umich.edu DynInstPtr inst = state->inst; 754601Sgblack@eecs.umich.edu DPRINTF(IEW, "Writeback event [sn:%lli]\n", inst->seqNum); 767620Sgblack@eecs.umich.edu DPRINTF(Activity, "Activity: Writeback event [sn:%lli]\n", inst->seqNum); 776345Sgblack@eecs.umich.edu 786345Sgblack@eecs.umich.edu //iewStage->ldstQueue.removeMSHR(inst->threadNumber,inst->seqNum); 796345Sgblack@eecs.umich.edu 805912Sgblack@eecs.umich.edu if (isSwitchedOut() || inst->isSquashed()) { 815912Sgblack@eecs.umich.edu iewStage->decrWb(inst->seqNum); 824601Sgblack@eecs.umich.edu delete state; 834601Sgblack@eecs.umich.edu delete pkt; 844601Sgblack@eecs.umich.edu return; 854601Sgblack@eecs.umich.edu } else { 864601Sgblack@eecs.umich.edu if (!state->noWB) { 874601Sgblack@eecs.umich.edu writeback(inst, pkt); 884601Sgblack@eecs.umich.edu } 894587Sgblack@eecs.umich.edu 904587Sgblack@eecs.umich.edu if (inst->isStore()) { 914587Sgblack@eecs.umich.edu completeStore(state->idx); 924587Sgblack@eecs.umich.edu } 934587Sgblack@eecs.umich.edu } 944587Sgblack@eecs.umich.edu 954587Sgblack@eecs.umich.edu delete state; 964587Sgblack@eecs.umich.edu delete pkt; 974587Sgblack@eecs.umich.edu} 984587Sgblack@eecs.umich.edu 994587Sgblack@eecs.umich.edutemplate <class Impl> 1004587Sgblack@eecs.umich.eduLSQUnit<Impl>::LSQUnit() 1015912Sgblack@eecs.umich.edu : loads(0), stores(0), storesToWB(0), stalled(false), 1024720Sgblack@eecs.umich.edu isStoreBlocked(false), isLoadBlocked(false), 1035920Sgblack@eecs.umich.edu loadBlockedHandled(false) 1044587Sgblack@eecs.umich.edu{ 1056736Sgblack@eecs.umich.edu} 1065920Sgblack@eecs.umich.edu 1075920Sgblack@eecs.umich.edutemplate<class Impl> 1084587Sgblack@eecs.umich.eduvoid 1094587Sgblack@eecs.umich.eduLSQUnit<Impl>::init(Params *params, LSQ *lsq_ptr, unsigned maxLQEntries, 1104587Sgblack@eecs.umich.edu unsigned maxSQEntries, unsigned id) 1114587Sgblack@eecs.umich.edu{ 1124587Sgblack@eecs.umich.edu DPRINTF(LSQUnit, "Creating LSQUnit%i object.\n",id); 1134587Sgblack@eecs.umich.edu 1144587Sgblack@eecs.umich.edu switchedOut = false; 1154587Sgblack@eecs.umich.edu 1164587Sgblack@eecs.umich.edu lsq = lsq_ptr; 1174587Sgblack@eecs.umich.edu 1184587Sgblack@eecs.umich.edu lsqID = id; 1194587Sgblack@eecs.umich.edu 1204587Sgblack@eecs.umich.edu // Add 1 for the sentinel entry (they are circular queues). 1214587Sgblack@eecs.umich.edu LQEntries = maxLQEntries + 1; 1224587Sgblack@eecs.umich.edu SQEntries = maxSQEntries + 1; 1234587Sgblack@eecs.umich.edu 1244587Sgblack@eecs.umich.edu loadQueue.resize(LQEntries); 1254587Sgblack@eecs.umich.edu storeQueue.resize(SQEntries); 1264587Sgblack@eecs.umich.edu 1274587Sgblack@eecs.umich.edu loadHead = loadTail = 0; 1284587Sgblack@eecs.umich.edu 1294587Sgblack@eecs.umich.edu storeHead = storeWBIdx = storeTail = 0; 1305912Sgblack@eecs.umich.edu 1314587Sgblack@eecs.umich.edu usedPorts = 0; 1324587Sgblack@eecs.umich.edu cachePorts = params->cachePorts; 1334587Sgblack@eecs.umich.edu 1344587Sgblack@eecs.umich.edu retryPkt = NULL; 1354587Sgblack@eecs.umich.edu memDepViolator = NULL; 1364587Sgblack@eecs.umich.edu 1374587Sgblack@eecs.umich.edu blockedLoadSeqNum = 0; 1384587Sgblack@eecs.umich.edu} 1394587Sgblack@eecs.umich.edu 1404587Sgblack@eecs.umich.edutemplate<class Impl> 1414587Sgblack@eecs.umich.eduvoid 1424587Sgblack@eecs.umich.eduLSQUnit<Impl>::setCPU(O3CPU *cpu_ptr) 1434587Sgblack@eecs.umich.edu{ 1444587Sgblack@eecs.umich.edu cpu = cpu_ptr; 1454587Sgblack@eecs.umich.edu 1465727Sgblack@eecs.umich.edu#if USE_CHECKER 1475002Sgblack@eecs.umich.edu if (cpu->checker) { 1484587Sgblack@eecs.umich.edu cpu->checker->setDcachePort(dcachePort); 1494587Sgblack@eecs.umich.edu } 1504587Sgblack@eecs.umich.edu#endif 1514587Sgblack@eecs.umich.edu} 1524587Sgblack@eecs.umich.edu 1534587Sgblack@eecs.umich.edutemplate<class Impl> 1544587Sgblack@eecs.umich.edustd::string 1554587Sgblack@eecs.umich.eduLSQUnit<Impl>::name() const 1564587Sgblack@eecs.umich.edu{ 1574587Sgblack@eecs.umich.edu if (Impl::MaxThreads == 1) { 1584587Sgblack@eecs.umich.edu return iewStage->name() + ".lsq"; 1594587Sgblack@eecs.umich.edu } else { 1604587Sgblack@eecs.umich.edu return iewStage->name() + ".lsq.thread." + to_string(lsqID); 1614587Sgblack@eecs.umich.edu } 1624587Sgblack@eecs.umich.edu} 1634587Sgblack@eecs.umich.edu 1644587Sgblack@eecs.umich.edutemplate<class Impl> 1654587Sgblack@eecs.umich.eduvoid 1664587Sgblack@eecs.umich.eduLSQUnit<Impl>::regStats() 1674587Sgblack@eecs.umich.edu{ 1684587Sgblack@eecs.umich.edu lsqForwLoads 1694587Sgblack@eecs.umich.edu .name(name() + ".forwLoads") 1704587Sgblack@eecs.umich.edu .desc("Number of loads that had data forwarded from stores"); 1714587Sgblack@eecs.umich.edu 1724587Sgblack@eecs.umich.edu invAddrLoads 1734587Sgblack@eecs.umich.edu .name(name() + ".invAddrLoads") 1744587Sgblack@eecs.umich.edu .desc("Number of loads ignored due to an invalid address"); 1754587Sgblack@eecs.umich.edu 1764587Sgblack@eecs.umich.edu lsqSquashedLoads 1775912Sgblack@eecs.umich.edu .name(name() + ".squashedLoads") 1784767Sgblack@eecs.umich.edu .desc("Number of loads squashed"); 1794720Sgblack@eecs.umich.edu 1805892Sgblack@eecs.umich.edu lsqIgnoredResponses 1814767Sgblack@eecs.umich.edu .name(name() + ".ignoredResponses") 1824720Sgblack@eecs.umich.edu .desc("Number of memory responses ignored because the instruction is squashed"); 1834587Sgblack@eecs.umich.edu 1844587Sgblack@eecs.umich.edu lsqMemOrderViolation 1854587Sgblack@eecs.umich.edu .name(name() + ".memOrderViolation") 1864587Sgblack@eecs.umich.edu .desc("Number of memory ordering violations"); 1874587Sgblack@eecs.umich.edu 1884587Sgblack@eecs.umich.edu lsqSquashedStores 1894587Sgblack@eecs.umich.edu .name(name() + ".squashedStores") 1904587Sgblack@eecs.umich.edu .desc("Number of stores squashed"); 1914587Sgblack@eecs.umich.edu 1924587Sgblack@eecs.umich.edu invAddrSwpfs 1934587Sgblack@eecs.umich.edu .name(name() + ".invAddrSwpfs") 1944587Sgblack@eecs.umich.edu .desc("Number of software prefetches ignored due to an invalid address"); 1954587Sgblack@eecs.umich.edu 1964587Sgblack@eecs.umich.edu lsqBlockedLoads 1974587Sgblack@eecs.umich.edu .name(name() + ".blockedLoads") 1984587Sgblack@eecs.umich.edu .desc("Number of blocked loads due to partial load-store forwarding"); 1994587Sgblack@eecs.umich.edu 2004587Sgblack@eecs.umich.edu lsqRescheduledLoads 2014587Sgblack@eecs.umich.edu .name(name() + ".rescheduledLoads") 2024587Sgblack@eecs.umich.edu .desc("Number of loads that were rescheduled"); 2034587Sgblack@eecs.umich.edu 2044587Sgblack@eecs.umich.edu lsqCacheBlocked 2055912Sgblack@eecs.umich.edu .name(name() + ".cacheBlocked") 2064587Sgblack@eecs.umich.edu .desc("Number of times an access to memory failed due to the cache being blocked"); 2074587Sgblack@eecs.umich.edu} 2084587Sgblack@eecs.umich.edu 2094587Sgblack@eecs.umich.edutemplate<class Impl> 2104587Sgblack@eecs.umich.eduvoid 2114587Sgblack@eecs.umich.eduLSQUnit<Impl>::clearLQ() 2125892Sgblack@eecs.umich.edu{ 2135892Sgblack@eecs.umich.edu loadQueue.clear(); 2144587Sgblack@eecs.umich.edu} 2155892Sgblack@eecs.umich.edu 2165892Sgblack@eecs.umich.edutemplate<class Impl> 2175892Sgblack@eecs.umich.eduvoid 2185892Sgblack@eecs.umich.eduLSQUnit<Impl>::clearSQ() 2194587Sgblack@eecs.umich.edu{ 2204587Sgblack@eecs.umich.edu storeQueue.clear(); 2214587Sgblack@eecs.umich.edu} 2224587Sgblack@eecs.umich.edu 2234587Sgblack@eecs.umich.edutemplate<class Impl> 2244587Sgblack@eecs.umich.eduvoid 2254587Sgblack@eecs.umich.eduLSQUnit<Impl>::switchOut() 2264587Sgblack@eecs.umich.edu{ 2274587Sgblack@eecs.umich.edu switchedOut = true; 2284587Sgblack@eecs.umich.edu for (int i = 0; i < loadQueue.size(); ++i) { 2294587Sgblack@eecs.umich.edu assert(!loadQueue[i]); 2304587Sgblack@eecs.umich.edu loadQueue[i] = NULL; 2314587Sgblack@eecs.umich.edu } 2324587Sgblack@eecs.umich.edu 2334587Sgblack@eecs.umich.edu assert(storesToWB == 0); 2344587Sgblack@eecs.umich.edu} 2354587Sgblack@eecs.umich.edu 2364587Sgblack@eecs.umich.edutemplate<class Impl> 2374587Sgblack@eecs.umich.eduvoid 2384561Sgblack@eecs.umich.eduLSQUnit<Impl>::takeOverFrom() 2394561Sgblack@eecs.umich.edu{ 2407620Sgblack@eecs.umich.edu switchedOut = false; 2416345Sgblack@eecs.umich.edu loads = stores = storesToWB = 0; 2426345Sgblack@eecs.umich.edu 2436345Sgblack@eecs.umich.edu loadHead = loadTail = 0; 2445912Sgblack@eecs.umich.edu 2455912Sgblack@eecs.umich.edu storeHead = storeWBIdx = storeTail = 0; 2464561Sgblack@eecs.umich.edu 2474561Sgblack@eecs.umich.edu usedPorts = 0; 2484587Sgblack@eecs.umich.edu 2494587Sgblack@eecs.umich.edu memDepViolator = NULL; 2504587Sgblack@eecs.umich.edu 2514587Sgblack@eecs.umich.edu blockedLoadSeqNum = 0; 2524561Sgblack@eecs.umich.edu 2534561Sgblack@eecs.umich.edu stalled = false; 2544561Sgblack@eecs.umich.edu isLoadBlocked = false; 2554561Sgblack@eecs.umich.edu loadBlockedHandled = false; 2564561Sgblack@eecs.umich.edu} 2577620Sgblack@eecs.umich.edu 2586345Sgblack@eecs.umich.edutemplate<class Impl> 2596345Sgblack@eecs.umich.eduvoid 2606345Sgblack@eecs.umich.eduLSQUnit<Impl>::resizeLQ(unsigned size) 2615912Sgblack@eecs.umich.edu{ 2625912Sgblack@eecs.umich.edu unsigned size_plus_sentinel = size + 1; 2637620Sgblack@eecs.umich.edu assert(size_plus_sentinel >= LQEntries); 2644587Sgblack@eecs.umich.edu 2654587Sgblack@eecs.umich.edu if (size_plus_sentinel > LQEntries) { 2665912Sgblack@eecs.umich.edu while (size_plus_sentinel > loadQueue.size()) { 2674561Sgblack@eecs.umich.edu DynInstPtr dummy; 2687626Sgblack@eecs.umich.edu loadQueue.push_back(dummy); 2694561Sgblack@eecs.umich.edu LQEntries++; 2704561Sgblack@eecs.umich.edu } 2714561Sgblack@eecs.umich.edu } else { 2724587Sgblack@eecs.umich.edu LQEntries = size_plus_sentinel; 2734587Sgblack@eecs.umich.edu } 2745912Sgblack@eecs.umich.edu 2755920Sgblack@eecs.umich.edu} 2764587Sgblack@eecs.umich.edu 2774587Sgblack@eecs.umich.edutemplate<class Impl> 2784587Sgblack@eecs.umich.eduvoid 2794587Sgblack@eecs.umich.eduLSQUnit<Impl>::resizeSQ(unsigned size) 2804712Sgblack@eecs.umich.edu{ 2815149Sgblack@eecs.umich.edu unsigned size_plus_sentinel = size + 1; 2825912Sgblack@eecs.umich.edu if (size_plus_sentinel > SQEntries) { 2835912Sgblack@eecs.umich.edu while (size_plus_sentinel > storeQueue.size()) { 2845912Sgblack@eecs.umich.edu SQEntry dummy; 2858102Sgblack@eecs.umich.edu storeQueue.push_back(dummy); 2865920Sgblack@eecs.umich.edu SQEntries++; 2876736Sgblack@eecs.umich.edu } 2888102Sgblack@eecs.umich.edu } else { 2895965Sgblack@eecs.umich.edu SQEntries = size_plus_sentinel; 2905965Sgblack@eecs.umich.edu } 2914587Sgblack@eecs.umich.edu} 2927620Sgblack@eecs.umich.edu 2937620Sgblack@eecs.umich.edutemplate <class Impl> 2944587Sgblack@eecs.umich.eduvoid 2954587Sgblack@eecs.umich.eduLSQUnit<Impl>::insert(DynInstPtr &inst) 2965912Sgblack@eecs.umich.edu{ 2974587Sgblack@eecs.umich.edu assert(inst->isMemRef()); 2988102Sgblack@eecs.umich.edu 2994587Sgblack@eecs.umich.edu assert(inst->isLoad() || inst->isStore()); 3004587Sgblack@eecs.umich.edu 3014587Sgblack@eecs.umich.edu if (inst->isLoad()) { 3024587Sgblack@eecs.umich.edu insertLoad(inst); 3035912Sgblack@eecs.umich.edu } else { 3045912Sgblack@eecs.umich.edu insertStore(inst); 3054587Sgblack@eecs.umich.edu } 3067967Sgblack@eecs.umich.edu 3077967Sgblack@eecs.umich.edu inst->setInLSQ(); 3087967Sgblack@eecs.umich.edu} 3097967Sgblack@eecs.umich.edu 3107967Sgblack@eecs.umich.edutemplate <class Impl> 3117967Sgblack@eecs.umich.eduvoid 3127967Sgblack@eecs.umich.eduLSQUnit<Impl>::insertLoad(DynInstPtr &load_inst) 3137967Sgblack@eecs.umich.edu{ 3147967Sgblack@eecs.umich.edu assert((loadTail + 1) % LQEntries != loadHead); 3157967Sgblack@eecs.umich.edu assert(loads < LQEntries); 3167967Sgblack@eecs.umich.edu 3177967Sgblack@eecs.umich.edu DPRINTF(LSQUnit, "Inserting load PC %#x, idx:%i [sn:%lli]\n", 3187967Sgblack@eecs.umich.edu load_inst->readPC(), loadTail, load_inst->seqNum); 3197967Sgblack@eecs.umich.edu 3207967Sgblack@eecs.umich.edu load_inst->lqIdx = loadTail; 3217967Sgblack@eecs.umich.edu 3227967Sgblack@eecs.umich.edu if (stores == 0) { 3237967Sgblack@eecs.umich.edu load_inst->sqIdx = -1; 3247967Sgblack@eecs.umich.edu } else { 3257967Sgblack@eecs.umich.edu load_inst->sqIdx = storeTail; 3267967Sgblack@eecs.umich.edu } 3277967Sgblack@eecs.umich.edu 3287967Sgblack@eecs.umich.edu loadQueue[loadTail] = load_inst; 3297967Sgblack@eecs.umich.edu 3307967Sgblack@eecs.umich.edu incrLdIdx(loadTail); 3317967Sgblack@eecs.umich.edu 3327967Sgblack@eecs.umich.edu ++loads; 3337967Sgblack@eecs.umich.edu} 3347967Sgblack@eecs.umich.edu 3357967Sgblack@eecs.umich.edutemplate <class Impl> 3367967Sgblack@eecs.umich.eduvoid 3377967Sgblack@eecs.umich.eduLSQUnit<Impl>::insertStore(DynInstPtr &store_inst) 3387967Sgblack@eecs.umich.edu{ 3397967Sgblack@eecs.umich.edu // Make sure it is not full before inserting an instruction. 3407967Sgblack@eecs.umich.edu assert((storeTail + 1) % SQEntries != storeHead); 3417967Sgblack@eecs.umich.edu assert(stores < SQEntries); 3427967Sgblack@eecs.umich.edu 3437967Sgblack@eecs.umich.edu DPRINTF(LSQUnit, "Inserting store PC %#x, idx:%i [sn:%lli]\n", 3447967Sgblack@eecs.umich.edu store_inst->readPC(), storeTail, store_inst->seqNum); 3457967Sgblack@eecs.umich.edu 3464587Sgblack@eecs.umich.edu store_inst->sqIdx = storeTail; 3474587Sgblack@eecs.umich.edu store_inst->lqIdx = loadTail; 3484587Sgblack@eecs.umich.edu 3494587Sgblack@eecs.umich.edu storeQueue[storeTail] = SQEntry(store_inst); 3504587Sgblack@eecs.umich.edu 3514587Sgblack@eecs.umich.edu incrStIdx(storeTail); 3524587Sgblack@eecs.umich.edu 3534587Sgblack@eecs.umich.edu ++stores; 3544587Sgblack@eecs.umich.edu} 3554587Sgblack@eecs.umich.edu 3565969Sgblack@eecs.umich.edutemplate <class Impl> 3575969Sgblack@eecs.umich.edutypename Impl::DynInstPtr 3585969Sgblack@eecs.umich.eduLSQUnit<Impl>::getMemDepViolator() 3594587Sgblack@eecs.umich.edu{ 3607967Sgblack@eecs.umich.edu DynInstPtr temp = memDepViolator; 3617967Sgblack@eecs.umich.edu 3624587Sgblack@eecs.umich.edu memDepViolator = NULL; 3634587Sgblack@eecs.umich.edu 3644587Sgblack@eecs.umich.edu return temp; 3654587Sgblack@eecs.umich.edu} 3664587Sgblack@eecs.umich.edu 3674587Sgblack@eecs.umich.edutemplate <class Impl> 3684587Sgblack@eecs.umich.eduunsigned 3694587Sgblack@eecs.umich.eduLSQUnit<Impl>::numFreeEntries() 3707967Sgblack@eecs.umich.edu{ 3717967Sgblack@eecs.umich.edu unsigned free_lq_entries = LQEntries - loads; 3727967Sgblack@eecs.umich.edu unsigned free_sq_entries = SQEntries - stores; 3737967Sgblack@eecs.umich.edu 3747967Sgblack@eecs.umich.edu // Both the LQ and SQ entries have an extra dummy entry to differentiate 3757967Sgblack@eecs.umich.edu // empty/full conditions. Subtract 1 from the free entries. 3767967Sgblack@eecs.umich.edu if (free_lq_entries < free_sq_entries) { 3777967Sgblack@eecs.umich.edu return free_lq_entries - 1; 3787967Sgblack@eecs.umich.edu } else { 3797967Sgblack@eecs.umich.edu return free_sq_entries - 1; 3807967Sgblack@eecs.umich.edu } 3814587Sgblack@eecs.umich.edu} 3827967Sgblack@eecs.umich.edu 3837967Sgblack@eecs.umich.edutemplate <class Impl> 3847967Sgblack@eecs.umich.eduint 3857967Sgblack@eecs.umich.eduLSQUnit<Impl>::numLoadsReady() 3865149Sgblack@eecs.umich.edu{ 3875912Sgblack@eecs.umich.edu int load_idx = loadHead; 3885912Sgblack@eecs.umich.edu int retval = 0; 3895920Sgblack@eecs.umich.edu 3905912Sgblack@eecs.umich.edu while (load_idx != loadTail) { 3915920Sgblack@eecs.umich.edu assert(loadQueue[load_idx]); 3925920Sgblack@eecs.umich.edu 3934587Sgblack@eecs.umich.edu if (loadQueue[load_idx]->readyToIssue()) { 3944587Sgblack@eecs.umich.edu ++retval; 3954587Sgblack@eecs.umich.edu } 3964587Sgblack@eecs.umich.edu } 3974587Sgblack@eecs.umich.edu 3987967Sgblack@eecs.umich.edu return retval; 3997967Sgblack@eecs.umich.edu} 4005912Sgblack@eecs.umich.edu 4017967Sgblack@eecs.umich.edutemplate <class Impl> 4027967Sgblack@eecs.umich.eduFault 4036079Sgblack@eecs.umich.eduLSQUnit<Impl>::executeLoad(DynInstPtr &inst) 4047967Sgblack@eecs.umich.edu{ 4057967Sgblack@eecs.umich.edu // Execute a specific load. 4067967Sgblack@eecs.umich.edu Fault load_fault = NoFault; 4074587Sgblack@eecs.umich.edu 4085892Sgblack@eecs.umich.edu DPRINTF(LSQUnit, "Executing load PC %#x, [sn:%lli]\n", 4095965Sgblack@eecs.umich.edu inst->readPC(),inst->seqNum); 4104587Sgblack@eecs.umich.edu 4114587Sgblack@eecs.umich.edu load_fault = inst->initiateAcc(); 4124587Sgblack@eecs.umich.edu 4134587Sgblack@eecs.umich.edu // If the instruction faulted, then we need to send it along to commit 4144587Sgblack@eecs.umich.edu // without the instruction completing. 4154587Sgblack@eecs.umich.edu if (load_fault != NoFault) { 4164587Sgblack@eecs.umich.edu // Send this instruction to commit, also make sure iew stage 4174587Sgblack@eecs.umich.edu // realizes there is activity. 4184679Sgblack@eecs.umich.edu // Mark it as executed unless it is an uncached load that 4195118Sgblack@eecs.umich.edu // needs to hit the head of commit. 4205892Sgblack@eecs.umich.edu if (!(inst->req->isUncacheable()) || inst->isAtCommit()) { 4215892Sgblack@eecs.umich.edu inst->setExecuted(); 4225912Sgblack@eecs.umich.edu } 4234587Sgblack@eecs.umich.edu iewStage->instToCommit(inst); 4244587Sgblack@eecs.umich.edu iewStage->activityThisCycle(); 4254587Sgblack@eecs.umich.edu } 4264587Sgblack@eecs.umich.edu 4274587Sgblack@eecs.umich.edu return load_fault; 4284587Sgblack@eecs.umich.edu} 4294587Sgblack@eecs.umich.edu 4305149Sgblack@eecs.umich.edutemplate <class Impl> 4315912Sgblack@eecs.umich.eduFault 4325912Sgblack@eecs.umich.eduLSQUnit<Impl>::executeStore(DynInstPtr &store_inst) 4335912Sgblack@eecs.umich.edu{ 4345912Sgblack@eecs.umich.edu using namespace TheISA; 4355920Sgblack@eecs.umich.edu // Make sure that a store exists. 4364587Sgblack@eecs.umich.edu assert(stores != 0); 4374587Sgblack@eecs.umich.edu 4384587Sgblack@eecs.umich.edu int store_idx = store_inst->sqIdx; 4394587Sgblack@eecs.umich.edu 4404587Sgblack@eecs.umich.edu DPRINTF(LSQUnit, "Executing store PC %#x [sn:%lli]\n", 4415919Sgblack@eecs.umich.edu store_inst->readPC(), store_inst->seqNum); 4426080Sgblack@eecs.umich.edu 4436080Sgblack@eecs.umich.edu // Check the recently completed loads to see if any match this store's 4445027Sgblack@eecs.umich.edu // address. If so, then we have a memory ordering violation. 4455892Sgblack@eecs.umich.edu int load_idx = store_inst->lqIdx; 4464601Sgblack@eecs.umich.edu 4474679Sgblack@eecs.umich.edu Fault store_fault = store_inst->initiateAcc(); 4485118Sgblack@eecs.umich.edu 4496056Sgblack@eecs.umich.edu if (storeQueue[store_idx].size == 0) { 4506056Sgblack@eecs.umich.edu DPRINTF(LSQUnit,"Fault on Store PC %#x, [sn:%lli],Size = 0\n", 4516056Sgblack@eecs.umich.edu store_inst->readPC(),store_inst->seqNum); 4524601Sgblack@eecs.umich.edu 4534601Sgblack@eecs.umich.edu return store_fault; 4544601Sgblack@eecs.umich.edu } 4554601Sgblack@eecs.umich.edu 4564601Sgblack@eecs.umich.edu assert(store_fault == NoFault); 4575149Sgblack@eecs.umich.edu 4585149Sgblack@eecs.umich.edu if (store_inst->isStoreConditional()) { 4594712Sgblack@eecs.umich.edu // Store conditionals need to set themselves as able to 4605920Sgblack@eecs.umich.edu // writeback if we haven't had a fault by here. 4614601Sgblack@eecs.umich.edu storeQueue[store_idx].canWB = true; 4624601Sgblack@eecs.umich.edu 4634601Sgblack@eecs.umich.edu ++storesToWB; 4644601Sgblack@eecs.umich.edu } 4655178Sgblack@eecs.umich.edu 4665178Sgblack@eecs.umich.edu if (!memDepViolator) { 4675359Sgblack@eecs.umich.edu while (load_idx != loadTail) { 4685359Sgblack@eecs.umich.edu // Really only need to check loads that have actually executed 4695912Sgblack@eecs.umich.edu // It's safe to check all loads because effAddr is set to 4705359Sgblack@eecs.umich.edu // InvalAddr when the dyn inst is created. 4715359Sgblack@eecs.umich.edu 4725359Sgblack@eecs.umich.edu // @todo: For now this is extra conservative, detecting a 4735359Sgblack@eecs.umich.edu // violation if the addresses match assuming all accesses 4745359Sgblack@eecs.umich.edu // are quad word accesses. 4755359Sgblack@eecs.umich.edu 4765912Sgblack@eecs.umich.edu // @todo: Fix this, magic number being used here 4775912Sgblack@eecs.umich.edu if ((loadQueue[load_idx]->effAddr >> 8) == 4786345Sgblack@eecs.umich.edu (store_inst->effAddr >> 8)) { 4795920Sgblack@eecs.umich.edu // A load incorrectly passed this store. Squash and refetch. 4805359Sgblack@eecs.umich.edu // For now return a fault to show that it was unsuccessful. 4815359Sgblack@eecs.umich.edu memDepViolator = loadQueue[load_idx]; 4825359Sgblack@eecs.umich.edu ++lsqMemOrderViolation; 4835359Sgblack@eecs.umich.edu 4845359Sgblack@eecs.umich.edu return genMachineCheckFault(); 4855178Sgblack@eecs.umich.edu } 4865178Sgblack@eecs.umich.edu 4875912Sgblack@eecs.umich.edu incrLdIdx(load_idx); 4885912Sgblack@eecs.umich.edu } 4896345Sgblack@eecs.umich.edu 4906624Sgblack@eecs.umich.edu // If we've reached this point, there was no violation. 4916624Sgblack@eecs.umich.edu memDepViolator = NULL; 4925178Sgblack@eecs.umich.edu } 4935178Sgblack@eecs.umich.edu 4945178Sgblack@eecs.umich.edu return store_fault; 4955178Sgblack@eecs.umich.edu} 4964587Sgblack@eecs.umich.edu 4974587Sgblack@eecs.umich.edutemplate <class Impl> 498void 499LSQUnit<Impl>::commitLoad() 500{ 501 assert(loadQueue[loadHead]); 502 503 DPRINTF(LSQUnit, "Committing head load instruction, PC %#x\n", 504 loadQueue[loadHead]->readPC()); 505 506 loadQueue[loadHead] = NULL; 507 508 incrLdIdx(loadHead); 509 510 --loads; 511} 512 513template <class Impl> 514void 515LSQUnit<Impl>::commitLoads(InstSeqNum &youngest_inst) 516{ 517 assert(loads == 0 || loadQueue[loadHead]); 518 519 while (loads != 0 && loadQueue[loadHead]->seqNum <= youngest_inst) { 520 commitLoad(); 521 } 522} 523 524template <class Impl> 525void 526LSQUnit<Impl>::commitStores(InstSeqNum &youngest_inst) 527{ 528 assert(stores == 0 || storeQueue[storeHead].inst); 529 530 int store_idx = storeHead; 531 532 while (store_idx != storeTail) { 533 assert(storeQueue[store_idx].inst); 534 // Mark any stores that are now committed and have not yet 535 // been marked as able to write back. 536 if (!storeQueue[store_idx].canWB) { 537 if (storeQueue[store_idx].inst->seqNum > youngest_inst) { 538 break; 539 } 540 DPRINTF(LSQUnit, "Marking store as able to write back, PC " 541 "%#x [sn:%lli]\n", 542 storeQueue[store_idx].inst->readPC(), 543 storeQueue[store_idx].inst->seqNum); 544 545 storeQueue[store_idx].canWB = true; 546 547 ++storesToWB; 548 } 549 550 incrStIdx(store_idx); 551 } 552} 553 554template <class Impl> 555void 556LSQUnit<Impl>::writebackStores() 557{ 558 while (storesToWB > 0 && 559 storeWBIdx != storeTail && 560 storeQueue[storeWBIdx].inst && 561 storeQueue[storeWBIdx].canWB && 562 usedPorts < cachePorts) { 563 564 if (isStoreBlocked || lsq->cacheBlocked()) { 565 DPRINTF(LSQUnit, "Unable to write back any more stores, cache" 566 " is blocked!\n"); 567 break; 568 } 569 570 // Store didn't write any data so no need to write it back to 571 // memory. 572 if (storeQueue[storeWBIdx].size == 0) { 573 completeStore(storeWBIdx); 574 575 incrStIdx(storeWBIdx); 576 577 continue; 578 } 579 580 ++usedPorts; 581 582 if (storeQueue[storeWBIdx].inst->isDataPrefetch()) { 583 incrStIdx(storeWBIdx); 584 585 continue; 586 } 587 588 assert(storeQueue[storeWBIdx].req); 589 assert(!storeQueue[storeWBIdx].committed); 590 591 DynInstPtr inst = storeQueue[storeWBIdx].inst; 592 593 Request *req = storeQueue[storeWBIdx].req; 594 storeQueue[storeWBIdx].committed = true; 595 596 assert(!inst->memData); 597 inst->memData = new uint8_t[64]; 598 memcpy(inst->memData, (uint8_t *)&storeQueue[storeWBIdx].data, 599 req->getSize()); 600 601 PacketPtr data_pkt = new Packet(req, Packet::WriteReq, Packet::Broadcast); 602 data_pkt->dataStatic(inst->memData); 603 604 LSQSenderState *state = new LSQSenderState; 605 state->isLoad = false; 606 state->idx = storeWBIdx; 607 state->inst = inst; 608 data_pkt->senderState = state; 609 610 DPRINTF(LSQUnit, "D-Cache: Writing back store idx:%i PC:%#x " 611 "to Addr:%#x, data:%#x [sn:%lli]\n", 612 storeWBIdx, inst->readPC(), 613 req->getPaddr(), *(inst->memData), 614 inst->seqNum); 615 616 // @todo: Remove this SC hack once the memory system handles it. 617 if (req->isLocked()) { 618 if (req->isUncacheable()) { 619 req->setScResult(2); 620 } else { 621 if (cpu->lockFlag) { 622 req->setScResult(1); 623 DPRINTF(LSQUnit, "Store conditional [sn:%lli] succeeded.", 624 inst->seqNum); 625 } else { 626 req->setScResult(0); 627 // Hack: Instantly complete this store. 628// completeDataAccess(data_pkt); 629 DPRINTF(LSQUnit, "Store conditional [sn:%lli] failed. " 630 "Instantly completing it.\n", 631 inst->seqNum); 632 WritebackEvent *wb = new WritebackEvent(inst, data_pkt, this); 633 wb->schedule(curTick + 1); 634 delete state; 635 completeStore(storeWBIdx); 636 incrStIdx(storeWBIdx); 637 continue; 638 } 639 } 640 } else { 641 // Non-store conditionals do not need a writeback. 642 state->noWB = true; 643 } 644 645 if (!dcachePort->sendTiming(data_pkt)) { 646 if (data_pkt->result == Packet::BadAddress) { 647 panic("LSQ sent out a bad address for a completed store!"); 648 } 649 // Need to handle becoming blocked on a store. 650 DPRINTF(IEW, "D-Cache became blcoked when writing [sn:%lli], will" 651 "retry later\n", 652 inst->seqNum); 653 isStoreBlocked = true; 654 ++lsqCacheBlocked; 655 assert(retryPkt == NULL); 656 retryPkt = data_pkt; 657 lsq->setRetryTid(lsqID); 658 } else { 659 storePostSend(data_pkt); 660 } 661 } 662 663 // Not sure this should set it to 0. 664 usedPorts = 0; 665 666 assert(stores >= 0 && storesToWB >= 0); 667} 668 669/*template <class Impl> 670void 671LSQUnit<Impl>::removeMSHR(InstSeqNum seqNum) 672{ 673 list<InstSeqNum>::iterator mshr_it = find(mshrSeqNums.begin(), 674 mshrSeqNums.end(), 675 seqNum); 676 677 if (mshr_it != mshrSeqNums.end()) { 678 mshrSeqNums.erase(mshr_it); 679 DPRINTF(LSQUnit, "Removing MSHR. count = %i\n",mshrSeqNums.size()); 680 } 681}*/ 682 683template <class Impl> 684void 685LSQUnit<Impl>::squash(const InstSeqNum &squashed_num) 686{ 687 DPRINTF(LSQUnit, "Squashing until [sn:%lli]!" 688 "(Loads:%i Stores:%i)\n", squashed_num, loads, stores); 689 690 int load_idx = loadTail; 691 decrLdIdx(load_idx); 692 693 while (loads != 0 && loadQueue[load_idx]->seqNum > squashed_num) { 694 DPRINTF(LSQUnit,"Load Instruction PC %#x squashed, " 695 "[sn:%lli]\n", 696 loadQueue[load_idx]->readPC(), 697 loadQueue[load_idx]->seqNum); 698 699 if (isStalled() && load_idx == stallingLoadIdx) { 700 stalled = false; 701 stallingStoreIsn = 0; 702 stallingLoadIdx = 0; 703 } 704 705 // Clear the smart pointer to make sure it is decremented. 706 loadQueue[load_idx]->setSquashed(); 707 loadQueue[load_idx] = NULL; 708 --loads; 709 710 // Inefficient! 711 loadTail = load_idx; 712 713 decrLdIdx(load_idx); 714 ++lsqSquashedLoads; 715 } 716 717 if (isLoadBlocked) { 718 if (squashed_num < blockedLoadSeqNum) { 719 isLoadBlocked = false; 720 loadBlockedHandled = false; 721 blockedLoadSeqNum = 0; 722 } 723 } 724 725 int store_idx = storeTail; 726 decrStIdx(store_idx); 727 728 while (stores != 0 && 729 storeQueue[store_idx].inst->seqNum > squashed_num) { 730 // Instructions marked as can WB are already committed. 731 if (storeQueue[store_idx].canWB) { 732 break; 733 } 734 735 DPRINTF(LSQUnit,"Store Instruction PC %#x squashed, " 736 "idx:%i [sn:%lli]\n", 737 storeQueue[store_idx].inst->readPC(), 738 store_idx, storeQueue[store_idx].inst->seqNum); 739 740 // I don't think this can happen. It should have been cleared 741 // by the stalling load. 742 if (isStalled() && 743 storeQueue[store_idx].inst->seqNum == stallingStoreIsn) { 744 panic("Is stalled should have been cleared by stalling load!\n"); 745 stalled = false; 746 stallingStoreIsn = 0; 747 } 748 749 // Clear the smart pointer to make sure it is decremented. 750 storeQueue[store_idx].inst->setSquashed(); 751 storeQueue[store_idx].inst = NULL; 752 storeQueue[store_idx].canWB = 0; 753 754 storeQueue[store_idx].req = NULL; 755 --stores; 756 757 // Inefficient! 758 storeTail = store_idx; 759 760 decrStIdx(store_idx); 761 ++lsqSquashedStores; 762 } 763} 764 765template <class Impl> 766void 767LSQUnit<Impl>::storePostSend(PacketPtr pkt) 768{ 769 if (isStalled() && 770 storeQueue[storeWBIdx].inst->seqNum == stallingStoreIsn) { 771 DPRINTF(LSQUnit, "Unstalling, stalling store [sn:%lli] " 772 "load idx:%i\n", 773 stallingStoreIsn, stallingLoadIdx); 774 stalled = false; 775 stallingStoreIsn = 0; 776 iewStage->replayMemInst(loadQueue[stallingLoadIdx]); 777 } 778 779 if (!storeQueue[storeWBIdx].inst->isStoreConditional()) { 780 // The store is basically completed at this time. This 781 // only works so long as the checker doesn't try to 782 // verify the value in memory for stores. 783 storeQueue[storeWBIdx].inst->setCompleted(); 784#if USE_CHECKER 785 if (cpu->checker) { 786 cpu->checker->verify(storeQueue[storeWBIdx].inst); 787 } 788#endif 789 } 790 791 if (pkt->result != Packet::Success) { 792 DPRINTF(LSQUnit,"D-Cache Write Miss on idx:%i!\n", 793 storeWBIdx); 794 795 DPRINTF(Activity, "Active st accessing mem miss [sn:%lli]\n", 796 storeQueue[storeWBIdx].inst->seqNum); 797 798 //mshrSeqNums.push_back(storeQueue[storeWBIdx].inst->seqNum); 799 800 //DPRINTF(LSQUnit, "Added MSHR. count = %i\n",mshrSeqNums.size()); 801 802 // @todo: Increment stat here. 803 } else { 804 DPRINTF(LSQUnit,"D-Cache: Write Hit on idx:%i !\n", 805 storeWBIdx); 806 807 DPRINTF(Activity, "Active st accessing mem hit [sn:%lli]\n", 808 storeQueue[storeWBIdx].inst->seqNum); 809 } 810 811 incrStIdx(storeWBIdx); 812} 813 814template <class Impl> 815void 816LSQUnit<Impl>::writeback(DynInstPtr &inst, PacketPtr pkt) 817{ 818 iewStage->wakeCPU(); 819 820 // Squashed instructions do not need to complete their access. 821 if (inst->isSquashed()) { 822 iewStage->decrWb(inst->seqNum); 823 assert(!inst->isStore()); 824 ++lsqIgnoredResponses; 825 return; 826 } 827 828 if (!inst->isExecuted()) { 829 inst->setExecuted(); 830 831 // Complete access to copy data to proper place. 832 inst->completeAcc(pkt); 833 } 834 835 // Need to insert instruction into queue to commit 836 iewStage->instToCommit(inst); 837 838 iewStage->activityThisCycle(); 839} 840 841template <class Impl> 842void 843LSQUnit<Impl>::completeStore(int store_idx) 844{ 845 assert(storeQueue[store_idx].inst); 846 storeQueue[store_idx].completed = true; 847 --storesToWB; 848 // A bit conservative because a store completion may not free up entries, 849 // but hopefully avoids two store completions in one cycle from making 850 // the CPU tick twice. 851 cpu->wakeCPU(); 852 cpu->activityThisCycle(); 853 854 if (store_idx == storeHead) { 855 do { 856 incrStIdx(storeHead); 857 858 --stores; 859 } while (storeQueue[storeHead].completed && 860 storeHead != storeTail); 861 862 iewStage->updateLSQNextCycle = true; 863 } 864 865 DPRINTF(LSQUnit, "Completing store [sn:%lli], idx:%i, store head " 866 "idx:%i\n", 867 storeQueue[store_idx].inst->seqNum, store_idx, storeHead); 868 869 if (isStalled() && 870 storeQueue[store_idx].inst->seqNum == stallingStoreIsn) { 871 DPRINTF(LSQUnit, "Unstalling, stalling store [sn:%lli] " 872 "load idx:%i\n", 873 stallingStoreIsn, stallingLoadIdx); 874 stalled = false; 875 stallingStoreIsn = 0; 876 iewStage->replayMemInst(loadQueue[stallingLoadIdx]); 877 } 878 879 storeQueue[store_idx].inst->setCompleted(); 880 881 // Tell the checker we've completed this instruction. Some stores 882 // may get reported twice to the checker, but the checker can 883 // handle that case. 884#if USE_CHECKER 885 if (cpu->checker) { 886 cpu->checker->verify(storeQueue[store_idx].inst); 887 } 888#endif 889} 890 891template <class Impl> 892void 893LSQUnit<Impl>::recvRetry() 894{ 895 if (isStoreBlocked) { 896 assert(retryPkt != NULL); 897 898 if (dcachePort->sendTiming(retryPkt)) { 899 if (retryPkt->result == Packet::BadAddress) { 900 panic("LSQ sent out a bad address for a completed store!"); 901 } 902 storePostSend(retryPkt); 903 retryPkt = NULL; 904 isStoreBlocked = false; 905 lsq->setRetryTid(-1); 906 } else { 907 // Still blocked! 908 ++lsqCacheBlocked; 909 lsq->setRetryTid(lsqID); 910 } 911 } else if (isLoadBlocked) { 912 DPRINTF(LSQUnit, "Loads squash themselves and all younger insts, " 913 "no need to resend packet.\n"); 914 } else { 915 DPRINTF(LSQUnit, "Retry received but LSQ is no longer blocked.\n"); 916 } 917} 918 919template <class Impl> 920inline void 921LSQUnit<Impl>::incrStIdx(int &store_idx) 922{ 923 if (++store_idx >= SQEntries) 924 store_idx = 0; 925} 926 927template <class Impl> 928inline void 929LSQUnit<Impl>::decrStIdx(int &store_idx) 930{ 931 if (--store_idx < 0) 932 store_idx += SQEntries; 933} 934 935template <class Impl> 936inline void 937LSQUnit<Impl>::incrLdIdx(int &load_idx) 938{ 939 if (++load_idx >= LQEntries) 940 load_idx = 0; 941} 942 943template <class Impl> 944inline void 945LSQUnit<Impl>::decrLdIdx(int &load_idx) 946{ 947 if (--load_idx < 0) 948 load_idx += LQEntries; 949} 950 951template <class Impl> 952void 953LSQUnit<Impl>::dumpInsts() 954{ 955 cprintf("Load store queue: Dumping instructions.\n"); 956 cprintf("Load queue size: %i\n", loads); 957 cprintf("Load queue: "); 958 959 int load_idx = loadHead; 960 961 while (load_idx != loadTail && loadQueue[load_idx]) { 962 cprintf("%#x ", loadQueue[load_idx]->readPC()); 963 964 incrLdIdx(load_idx); 965 } 966 967 cprintf("Store queue size: %i\n", stores); 968 cprintf("Store queue: "); 969 970 int store_idx = storeHead; 971 972 while (store_idx != storeTail && storeQueue[store_idx].inst) { 973 cprintf("%#x ", storeQueue[store_idx].inst->readPC()); 974 975 incrStIdx(store_idx); 976 } 977 978 cprintf("\n"); 979} 980