lsq_unit_impl.hh revision 3221:669a04468c0d
12SN/A/* 211147Smitch.hayenga@arm.com * Copyright (c) 2004-2005 The Regents of The University of Michigan 39920Syasuko.eckert@amd.com * All rights reserved. 47338SAli.Saidi@ARM.com * 57338SAli.Saidi@ARM.com * Redistribution and use in source and binary forms, with or without 67338SAli.Saidi@ARM.com * modification, are permitted provided that the following conditions are 77338SAli.Saidi@ARM.com * met: redistributions of source code must retain the above copyright 87338SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer; 97338SAli.Saidi@ARM.com * redistributions in binary form must reproduce the above copyright 107338SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer in the 117338SAli.Saidi@ARM.com * documentation and/or other materials provided with the distribution; 127338SAli.Saidi@ARM.com * neither the name of the copyright holders nor the names of its 137338SAli.Saidi@ARM.com * contributors may be used to endorse or promote products derived from 147338SAli.Saidi@ARM.com * this software without specific prior written permission. 151762SN/A * 162SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 172SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 182SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 192SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 202SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 212SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 222SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 232SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 242SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 252SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 262SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272SN/A * 282SN/A * Authors: Kevin Lim 292SN/A * Korey Sewell 302SN/A */ 312SN/A 322SN/A#include "config/use_checker.hh" 332SN/A 342SN/A#include "cpu/o3/lsq.hh" 352SN/A#include "cpu/o3/lsq_unit.hh" 362SN/A#include "base/str.hh" 372SN/A#include "mem/packet.hh" 382SN/A#include "mem/request.hh" 392SN/A 402665Ssaidi@eecs.umich.edu#if USE_CHECKER 412665Ssaidi@eecs.umich.edu#include "cpu/checker/cpu.hh" 422SN/A#endif 432SN/A 4411793Sbrandon.potter@amd.comtemplate<class Impl> 4511793Sbrandon.potter@amd.comLSQUnit<Impl>::WritebackEvent::WritebackEvent(DynInstPtr &_inst, PacketPtr _pkt, 468779Sgblack@eecs.umich.edu LSQUnit *lsq_ptr) 478779Sgblack@eecs.umich.edu : Event(&mainEventQueue), inst(_inst), pkt(_pkt), lsqPtr(lsq_ptr) 488779Sgblack@eecs.umich.edu{ 492439SN/A this->setFlags(Event::AutoDelete); 508779Sgblack@eecs.umich.edu} 516216Snate@binkert.org 52146SN/Atemplate<class Impl> 53146SN/Avoid 5411793Sbrandon.potter@amd.comLSQUnit<Impl>::WritebackEvent::process() 55146SN/A{ 56146SN/A if (!lsqPtr->isSwitchedOut()) { 57146SN/A lsqPtr->writeback(inst, pkt); 586216Snate@binkert.org } 596658Snate@binkert.org delete pkt; 601717SN/A} 618887Sgeoffrey.blake@arm.com 628887Sgeoffrey.blake@arm.comtemplate<class Impl> 63146SN/Aconst char * 6410061Sandreas@sandberg.pp.seLSQUnit<Impl>::WritebackEvent::description() 651977SN/A{ 6611147Smitch.hayenga@arm.com return "Store writeback event"; 672683Sktlim@umich.edu} 681717SN/A 69146SN/Atemplate<class Impl> 702683Sktlim@umich.eduvoid 718232Snate@binkert.orgLSQUnit<Impl>::completeDataAccess(PacketPtr pkt) 728232Snate@binkert.org{ 738232Snate@binkert.org LSQSenderState *state = dynamic_cast<LSQSenderState *>(pkt->senderState); 748779Sgblack@eecs.umich.edu DynInstPtr inst = state->inst; 753348Sbinkertn@umich.edu DPRINTF(IEW, "Writeback event [sn:%lli]\n", inst->seqNum); 766105Ssteve.reinhardt@amd.com DPRINTF(Activity, "Activity: Writeback event [sn:%lli]\n", inst->seqNum); 776216Snate@binkert.org 782036SN/A //iewStage->ldstQueue.removeMSHR(inst->threadNumber,inst->seqNum); 79146SN/A 808817Sgblack@eecs.umich.edu if (isSwitchedOut() || inst->isSquashed()) { 818793Sgblack@eecs.umich.edu iewStage->decrWb(inst->seqNum); 8256SN/A delete state; 8356SN/A delete pkt; 84695SN/A return; 852901Ssaidi@eecs.umich.edu } else { 862SN/A if (!state->noWB) { 872SN/A writeback(inst, pkt); 882449SN/A } 891355SN/A 905529Snate@binkert.org if (inst->isStore()) { 9110061Sandreas@sandberg.pp.se completeStore(state->idx); 9211147Smitch.hayenga@arm.com } 9310061Sandreas@sandberg.pp.se } 9411147Smitch.hayenga@arm.com 9511147Smitch.hayenga@arm.com delete state; 9611147Smitch.hayenga@arm.com delete pkt; 97224SN/A} 9811147Smitch.hayenga@arm.com 992SN/Atemplate <class Impl> 10011147Smitch.hayenga@arm.comLSQUnit<Impl>::LSQUnit() 10111147Smitch.hayenga@arm.com : loads(0), stores(0), storesToWB(0), stalled(false), 10211147Smitch.hayenga@arm.com isStoreBlocked(false), isLoadBlocked(false), 10311147Smitch.hayenga@arm.com loadBlockedHandled(false) 10411147Smitch.hayenga@arm.com{ 10511147Smitch.hayenga@arm.com} 10611147Smitch.hayenga@arm.com 10711147Smitch.hayenga@arm.comtemplate<class Impl> 10811147Smitch.hayenga@arm.comvoid 10911147Smitch.hayenga@arm.comLSQUnit<Impl>::init(Params *params, LSQ *lsq_ptr, unsigned maxLQEntries, 11011147Smitch.hayenga@arm.com unsigned maxSQEntries, unsigned id) 11111147Smitch.hayenga@arm.com{ 1122SN/A DPRINTF(LSQUnit, "Creating LSQUnit%i object.\n",id); 1138733Sgeoffrey.blake@arm.com 11411147Smitch.hayenga@arm.com switchedOut = false; 11511147Smitch.hayenga@arm.com 11611147Smitch.hayenga@arm.com lsq = lsq_ptr; 1178733Sgeoffrey.blake@arm.com 1188733Sgeoffrey.blake@arm.com lsqID = id; 1198733Sgeoffrey.blake@arm.com 1208733Sgeoffrey.blake@arm.com // Add 1 for the sentinel entry (they are circular queues). 12111147Smitch.hayenga@arm.com LQEntries = maxLQEntries + 1; 12211147Smitch.hayenga@arm.com SQEntries = maxSQEntries + 1; 1238733Sgeoffrey.blake@arm.com 1248733Sgeoffrey.blake@arm.com loadQueue.resize(LQEntries); 1258733Sgeoffrey.blake@arm.com storeQueue.resize(SQEntries); 12611147Smitch.hayenga@arm.com 1278733Sgeoffrey.blake@arm.com loadHead = loadTail = 0; 12811147Smitch.hayenga@arm.com 12911147Smitch.hayenga@arm.com storeHead = storeWBIdx = storeTail = 0; 13011147Smitch.hayenga@arm.com 13111147Smitch.hayenga@arm.com usedPorts = 0; 1322SN/A cachePorts = params->cachePorts; 13311147Smitch.hayenga@arm.com 13411147Smitch.hayenga@arm.com memDepViolator = NULL; 13511147Smitch.hayenga@arm.com 1364377Sgblack@eecs.umich.edu blockedLoadSeqNum = 0; 13711147Smitch.hayenga@arm.com} 13811147Smitch.hayenga@arm.com 13911147Smitch.hayenga@arm.comtemplate<class Impl> 14011147Smitch.hayenga@arm.comvoid 14111147Smitch.hayenga@arm.comLSQUnit<Impl>::setCPU(O3CPU *cpu_ptr) 14211147Smitch.hayenga@arm.com{ 1435169Ssaidi@eecs.umich.edu cpu = cpu_ptr; 14411147Smitch.hayenga@arm.com 14511147Smitch.hayenga@arm.com#if USE_CHECKER 14611147Smitch.hayenga@arm.com if (cpu->checker) { 14711147Smitch.hayenga@arm.com cpu->checker->setDcachePort(dcachePort); 14811147Smitch.hayenga@arm.com } 14911147Smitch.hayenga@arm.com#endif 15011147Smitch.hayenga@arm.com} 15111147Smitch.hayenga@arm.com 15211147Smitch.hayenga@arm.comtemplate<class Impl> 15311147Smitch.hayenga@arm.comstd::string 15411147Smitch.hayenga@arm.comLSQUnit<Impl>::name() const 15511147Smitch.hayenga@arm.com{ 15611147Smitch.hayenga@arm.com if (Impl::MaxThreads == 1) { 15711147Smitch.hayenga@arm.com return iewStage->name() + ".lsq"; 15811147Smitch.hayenga@arm.com } else { 15911147Smitch.hayenga@arm.com return iewStage->name() + ".lsq.thread." + to_string(lsqID); 16011147Smitch.hayenga@arm.com } 16111147Smitch.hayenga@arm.com} 16211147Smitch.hayenga@arm.com 16311147Smitch.hayenga@arm.comtemplate<class Impl> 16411147Smitch.hayenga@arm.comvoid 16511147Smitch.hayenga@arm.comLSQUnit<Impl>::regStats() 16611147Smitch.hayenga@arm.com{ 16711147Smitch.hayenga@arm.com lsqForwLoads 16811147Smitch.hayenga@arm.com .name(name() + ".forwLoads") 16911147Smitch.hayenga@arm.com .desc("Number of loads that had data forwarded from stores"); 17011147Smitch.hayenga@arm.com 17111147Smitch.hayenga@arm.com invAddrLoads 17211147Smitch.hayenga@arm.com .name(name() + ".invAddrLoads") 17311147Smitch.hayenga@arm.com .desc("Number of loads ignored due to an invalid address"); 17411147Smitch.hayenga@arm.com 17511147Smitch.hayenga@arm.com lsqSquashedLoads 17611147Smitch.hayenga@arm.com .name(name() + ".squashedLoads") 17711147Smitch.hayenga@arm.com .desc("Number of loads squashed"); 17811147Smitch.hayenga@arm.com 17911147Smitch.hayenga@arm.com lsqIgnoredResponses 18011147Smitch.hayenga@arm.com .name(name() + ".ignoredResponses") 18111147Smitch.hayenga@arm.com .desc("Number of memory responses ignored because the instruction is squashed"); 18211147Smitch.hayenga@arm.com 18311147Smitch.hayenga@arm.com lsqMemOrderViolation 18411147Smitch.hayenga@arm.com .name(name() + ".memOrderViolation") 18511147Smitch.hayenga@arm.com .desc("Number of memory ordering violations"); 18611147Smitch.hayenga@arm.com 18711147Smitch.hayenga@arm.com lsqSquashedStores 18811147Smitch.hayenga@arm.com .name(name() + ".squashedStores") 18911147Smitch.hayenga@arm.com .desc("Number of stores squashed"); 19011147Smitch.hayenga@arm.com 19111147Smitch.hayenga@arm.com invAddrSwpfs 19211147Smitch.hayenga@arm.com .name(name() + ".invAddrSwpfs") 19311147Smitch.hayenga@arm.com .desc("Number of software prefetches ignored due to an invalid address"); 19411147Smitch.hayenga@arm.com 19511147Smitch.hayenga@arm.com lsqBlockedLoads 19611147Smitch.hayenga@arm.com .name(name() + ".blockedLoads") 19711147Smitch.hayenga@arm.com .desc("Number of blocked loads due to partial load-store forwarding"); 19811147Smitch.hayenga@arm.com 19911147Smitch.hayenga@arm.com lsqRescheduledLoads 20011147Smitch.hayenga@arm.com .name(name() + ".rescheduledLoads") 20111147Smitch.hayenga@arm.com .desc("Number of loads that were rescheduled"); 20211147Smitch.hayenga@arm.com 20311147Smitch.hayenga@arm.com lsqCacheBlocked 20411147Smitch.hayenga@arm.com .name(name() + ".cacheBlocked") 20511147Smitch.hayenga@arm.com .desc("Number of times an access to memory failed due to the cache being blocked"); 20611147Smitch.hayenga@arm.com} 2072SN/A 2082SN/Atemplate<class Impl> 2092623SN/Avoid 2102SN/ALSQUnit<Impl>::clearLQ() 2112SN/A{ 2122SN/A loadQueue.clear(); 213180SN/A} 2148737Skoansin.tan@gmail.com 215393SN/Atemplate<class Impl> 216393SN/Avoid 217393SN/ALSQUnit<Impl>::clearSQ() 218393SN/A{ 219384SN/A storeQueue.clear(); 220189SN/A} 221189SN/A 2222623SN/Atemplate<class Impl> 2232SN/Avoid 224729SN/ALSQUnit<Impl>::switchOut() 225334SN/A{ 2262SN/A switchedOut = true; 2272SN/A for (int i = 0; i < loadQueue.size(); ++i) { 22811147Smitch.hayenga@arm.com assert(!loadQueue[i]); 22911147Smitch.hayenga@arm.com loadQueue[i] = NULL; 2308834Satgutier@umich.edu } 23111147Smitch.hayenga@arm.com 23211147Smitch.hayenga@arm.com assert(storesToWB == 0); 23311147Smitch.hayenga@arm.com} 2342SN/A 23511147Smitch.hayenga@arm.comtemplate<class Impl> 23611147Smitch.hayenga@arm.comvoid 23711147Smitch.hayenga@arm.comLSQUnit<Impl>::takeOverFrom() 23811147Smitch.hayenga@arm.com{ 2397897Shestness@cs.utexas.edu switchedOut = false; 24011147Smitch.hayenga@arm.com loads = stores = storesToWB = 0; 24111147Smitch.hayenga@arm.com 24211147Smitch.hayenga@arm.com loadHead = loadTail = 0; 24311147Smitch.hayenga@arm.com 2447897Shestness@cs.utexas.edu storeHead = storeWBIdx = storeTail = 0; 24511147Smitch.hayenga@arm.com 24611147Smitch.hayenga@arm.com usedPorts = 0; 24711147Smitch.hayenga@arm.com 24811147Smitch.hayenga@arm.com memDepViolator = NULL; 2497897Shestness@cs.utexas.edu 25011147Smitch.hayenga@arm.com blockedLoadSeqNum = 0; 25111147Smitch.hayenga@arm.com 25211147Smitch.hayenga@arm.com stalled = false; 25311147Smitch.hayenga@arm.com isLoadBlocked = false; 2547897Shestness@cs.utexas.edu loadBlockedHandled = false; 25511147Smitch.hayenga@arm.com} 25611147Smitch.hayenga@arm.com 25711147Smitch.hayenga@arm.comtemplate<class Impl> 25811147Smitch.hayenga@arm.comvoid 2597897Shestness@cs.utexas.eduLSQUnit<Impl>::resizeLQ(unsigned size) 26011147Smitch.hayenga@arm.com{ 26111147Smitch.hayenga@arm.com unsigned size_plus_sentinel = size + 1; 26211147Smitch.hayenga@arm.com assert(size_plus_sentinel >= LQEntries); 26311147Smitch.hayenga@arm.com 2647897Shestness@cs.utexas.edu if (size_plus_sentinel > LQEntries) { 26511147Smitch.hayenga@arm.com while (size_plus_sentinel > loadQueue.size()) { 26611147Smitch.hayenga@arm.com DynInstPtr dummy; 26711147Smitch.hayenga@arm.com loadQueue.push_back(dummy); 26811147Smitch.hayenga@arm.com LQEntries++; 2697897Shestness@cs.utexas.edu } 27011147Smitch.hayenga@arm.com } else { 27111147Smitch.hayenga@arm.com LQEntries = size_plus_sentinel; 27211147Smitch.hayenga@arm.com } 27311147Smitch.hayenga@arm.com 2747897Shestness@cs.utexas.edu} 27511147Smitch.hayenga@arm.com 27611147Smitch.hayenga@arm.comtemplate<class Impl> 27711147Smitch.hayenga@arm.comvoid 27811147Smitch.hayenga@arm.comLSQUnit<Impl>::resizeSQ(unsigned size) 2797897Shestness@cs.utexas.edu{ 28011147Smitch.hayenga@arm.com unsigned size_plus_sentinel = size + 1; 28111147Smitch.hayenga@arm.com if (size_plus_sentinel > SQEntries) { 28211147Smitch.hayenga@arm.com while (size_plus_sentinel > storeQueue.size()) { 28311147Smitch.hayenga@arm.com SQEntry dummy; 2847897Shestness@cs.utexas.edu storeQueue.push_back(dummy); 28511147Smitch.hayenga@arm.com SQEntries++; 28611147Smitch.hayenga@arm.com } 28711147Smitch.hayenga@arm.com } else { 28811147Smitch.hayenga@arm.com SQEntries = size_plus_sentinel; 2899920Syasuko.eckert@amd.com } 29011147Smitch.hayenga@arm.com} 29111147Smitch.hayenga@arm.com 29211147Smitch.hayenga@arm.comtemplate <class Impl> 29311147Smitch.hayenga@arm.comvoid 2949920Syasuko.eckert@amd.comLSQUnit<Impl>::insert(DynInstPtr &inst) 29511147Smitch.hayenga@arm.com{ 29611147Smitch.hayenga@arm.com assert(inst->isMemRef()); 29711147Smitch.hayenga@arm.com 29811147Smitch.hayenga@arm.com assert(inst->isLoad() || inst->isStore()); 29911147Smitch.hayenga@arm.com 3007897Shestness@cs.utexas.edu if (inst->isLoad()) { 30111147Smitch.hayenga@arm.com insertLoad(inst); 30211147Smitch.hayenga@arm.com } else { 30311147Smitch.hayenga@arm.com insertStore(inst); 30411147Smitch.hayenga@arm.com } 30511147Smitch.hayenga@arm.com 3067897Shestness@cs.utexas.edu inst->setInLSQ(); 30711147Smitch.hayenga@arm.com} 30811147Smitch.hayenga@arm.com 30911147Smitch.hayenga@arm.comtemplate <class Impl> 31011147Smitch.hayenga@arm.comvoid 3112SN/ALSQUnit<Impl>::insertLoad(DynInstPtr &load_inst) 31211147Smitch.hayenga@arm.com{ 31311147Smitch.hayenga@arm.com assert((loadTail + 1) % LQEntries != loadHead); 31411147Smitch.hayenga@arm.com assert(loads < LQEntries); 31511147Smitch.hayenga@arm.com 3161001SN/A DPRINTF(LSQUnit, "Inserting load PC %#x, idx:%i [sn:%lli]\n", 31711147Smitch.hayenga@arm.com load_inst->readPC(), loadTail, load_inst->seqNum); 31811147Smitch.hayenga@arm.com 31911147Smitch.hayenga@arm.com load_inst->lqIdx = loadTail; 32011147Smitch.hayenga@arm.com 3212SN/A if (stores == 0) { 32211147Smitch.hayenga@arm.com load_inst->sqIdx = -1; 32311147Smitch.hayenga@arm.com } else { 32411147Smitch.hayenga@arm.com load_inst->sqIdx = storeTail; 32511147Smitch.hayenga@arm.com } 3267897Shestness@cs.utexas.edu 32711147Smitch.hayenga@arm.com loadQueue[loadTail] = load_inst; 32811147Smitch.hayenga@arm.com 32911147Smitch.hayenga@arm.com incrLdIdx(loadTail); 33011147Smitch.hayenga@arm.com 3317897Shestness@cs.utexas.edu ++loads; 33211147Smitch.hayenga@arm.com} 33311147Smitch.hayenga@arm.com 33411147Smitch.hayenga@arm.comtemplate <class Impl> 33511147Smitch.hayenga@arm.comvoid 3362SN/ALSQUnit<Impl>::insertStore(DynInstPtr &store_inst) 33711147Smitch.hayenga@arm.com{ 33811147Smitch.hayenga@arm.com // Make sure it is not full before inserting an instruction. 33911147Smitch.hayenga@arm.com assert((storeTail + 1) % SQEntries != storeHead); 34011147Smitch.hayenga@arm.com assert(stores < SQEntries); 3412SN/A 34211147Smitch.hayenga@arm.com DPRINTF(LSQUnit, "Inserting store PC %#x, idx:%i [sn:%lli]\n", 34311147Smitch.hayenga@arm.com store_inst->readPC(), storeTail, store_inst->seqNum); 34411147Smitch.hayenga@arm.com 34511147Smitch.hayenga@arm.com store_inst->sqIdx = storeTail; 34611147Smitch.hayenga@arm.com store_inst->lqIdx = loadTail; 34711147Smitch.hayenga@arm.com 34811147Smitch.hayenga@arm.com storeQueue[storeTail] = SQEntry(store_inst); 34911147Smitch.hayenga@arm.com 35011147Smitch.hayenga@arm.com incrStIdx(storeTail); 35111147Smitch.hayenga@arm.com 35211147Smitch.hayenga@arm.com ++stores; 35311147Smitch.hayenga@arm.com} 35411147Smitch.hayenga@arm.com 35511147Smitch.hayenga@arm.comtemplate <class Impl> 35611147Smitch.hayenga@arm.comtypename Impl::DynInstPtr 35711147Smitch.hayenga@arm.comLSQUnit<Impl>::getMemDepViolator() 35811147Smitch.hayenga@arm.com{ 35911147Smitch.hayenga@arm.com DynInstPtr temp = memDepViolator; 36011147Smitch.hayenga@arm.com 36111147Smitch.hayenga@arm.com memDepViolator = NULL; 36211147Smitch.hayenga@arm.com 36311147Smitch.hayenga@arm.com return temp; 36411147Smitch.hayenga@arm.com} 36511147Smitch.hayenga@arm.com 36611147Smitch.hayenga@arm.comtemplate <class Impl> 36711147Smitch.hayenga@arm.comunsigned 36811147Smitch.hayenga@arm.comLSQUnit<Impl>::numFreeEntries() 36911147Smitch.hayenga@arm.com{ 37011147Smitch.hayenga@arm.com unsigned free_lq_entries = LQEntries - loads; 37111147Smitch.hayenga@arm.com unsigned free_sq_entries = SQEntries - stores; 37211147Smitch.hayenga@arm.com 37311147Smitch.hayenga@arm.com // Both the LQ and SQ entries have an extra dummy entry to differentiate 37411147Smitch.hayenga@arm.com // empty/full conditions. Subtract 1 from the free entries. 37511147Smitch.hayenga@arm.com if (free_lq_entries < free_sq_entries) { 37611147Smitch.hayenga@arm.com return free_lq_entries - 1; 37711147Smitch.hayenga@arm.com } else { 37811147Smitch.hayenga@arm.com return free_sq_entries - 1; 37911147Smitch.hayenga@arm.com } 38011147Smitch.hayenga@arm.com} 38111147Smitch.hayenga@arm.com 38211147Smitch.hayenga@arm.comtemplate <class Impl> 38310193SCurtis.Dunham@arm.comint 3842SN/ALSQUnit<Impl>::numLoadsReady() 3852SN/A{ 3862SN/A int load_idx = loadHead; 3872623SN/A int retval = 0; 388334SN/A 38911147Smitch.hayenga@arm.com while (load_idx != loadTail) { 39011147Smitch.hayenga@arm.com assert(loadQueue[load_idx]); 39111147Smitch.hayenga@arm.com 392334SN/A if (loadQueue[load_idx]->readyToIssue()) { 393334SN/A ++retval; 394334SN/A } 39510905Sandreas.sandberg@arm.com } 3962SN/A 3979448SAndreas.Sandberg@ARM.com return retval; 3989448SAndreas.Sandberg@ARM.com} 39911147Smitch.hayenga@arm.com 4002SN/Atemplate <class Impl> 4012SN/AFault 4022SN/ALSQUnit<Impl>::executeLoad(DynInstPtr &inst) 40310905Sandreas.sandberg@arm.com{ 4042SN/A // Execute a specific load. 40511147Smitch.hayenga@arm.com Fault load_fault = NoFault; 4062SN/A 4072SN/A DPRINTF(LSQUnit, "Executing load PC %#x, [sn:%lli]\n", 4082SN/A inst->readPC(),inst->seqNum); 4096221Snate@binkert.org 4102SN/A load_fault = inst->initiateAcc(); 4112SN/A 4122SN/A // If the instruction faulted, then we need to send it along to commit 4132SN/A // without the instruction completing. 4142623SN/A if (load_fault != NoFault) { 4152SN/A // Send this instruction to commit, also make sure iew stage 41611147Smitch.hayenga@arm.com // realizes there is activity. 4172SN/A // Mark it as executed unless it is an uncached load that 4182SN/A // needs to hit the head of commit. 4192SN/A if (!(inst->req->getFlags() & UNCACHEABLE) || inst->isAtCommit()) { 42011151Smitch.hayenga@arm.com inst->setExecuted(); 4212SN/A } 42211151Smitch.hayenga@arm.com iewStage->instToCommit(inst); 42311151Smitch.hayenga@arm.com iewStage->activityThisCycle(); 42411151Smitch.hayenga@arm.com } 42511151Smitch.hayenga@arm.com 42611151Smitch.hayenga@arm.com return load_fault; 42711147Smitch.hayenga@arm.com} 4282SN/A 4292SN/Atemplate <class Impl> 4302SN/AFault 4312623SN/ALSQUnit<Impl>::executeStore(DynInstPtr &store_inst) 4322SN/A{ 43311147Smitch.hayenga@arm.com using namespace TheISA; 43411147Smitch.hayenga@arm.com // Make sure that a store exists. 43511147Smitch.hayenga@arm.com assert(stores != 0); 43611147Smitch.hayenga@arm.com 4375704Snate@binkert.org int store_idx = store_inst->sqIdx; 43811150Smitch.hayenga@arm.com 4392SN/A DPRINTF(LSQUnit, "Executing store PC %#x [sn:%lli]\n", 4403520Sgblack@eecs.umich.edu store_inst->readPC(), store_inst->seqNum); 44111147Smitch.hayenga@arm.com 44211150Smitch.hayenga@arm.com // Check the recently completed loads to see if any match this store's 4433520Sgblack@eecs.umich.edu // address. If so, then we have a memory ordering violation. 4449023Sgblack@eecs.umich.edu int load_idx = store_inst->lqIdx; 4452SN/A 4462SN/A Fault store_fault = store_inst->initiateAcc(); 4472623SN/A 4482SN/A if (storeQueue[store_idx].size == 0) { 4492623SN/A DPRINTF(LSQUnit,"Fault on Store PC %#x, [sn:%lli],Size = 0\n", 4505894Sgblack@eecs.umich.edu store_inst->readPC(),store_inst->seqNum); 4512662Sstever@eecs.umich.edu 4522623SN/A return store_fault; 45311147Smitch.hayenga@arm.com } 45411147Smitch.hayenga@arm.com 45511147Smitch.hayenga@arm.com assert(store_fault == NoFault); 4567720Sgblack@eecs.umich.edu 4574495Sacolyte@umich.edu if (store_inst->isStoreConditional()) { 4582623SN/A // Store conditionals need to set themselves as able to 4597720Sgblack@eecs.umich.edu // writeback if we haven't had a fault by here. 4602623SN/A storeQueue[store_idx].canWB = true; 46111147Smitch.hayenga@arm.com 4628832SAli.Saidi@ARM.com ++storesToWB; 4638832SAli.Saidi@ARM.com } 4642623SN/A 4652623SN/A if (!memDepViolator) { 4662623SN/A while (load_idx != loadTail) { 4672623SN/A // Really only need to check loads that have actually executed 4682623SN/A // It's safe to check all loads because effAddr is set to 4692623SN/A // InvalAddr when the dyn inst is created. 47011147Smitch.hayenga@arm.com 47111147Smitch.hayenga@arm.com // @todo: For now this is extra conservative, detecting a 47211147Smitch.hayenga@arm.com // violation if the addresses match assuming all accesses 4732SN/A // are quad word accesses. 4742683Sktlim@umich.edu 4752427SN/A // @todo: Fix this, magic number being used here 4762683Sktlim@umich.edu if ((loadQueue[load_idx]->effAddr >> 8) == 4772427SN/A (store_inst->effAddr >> 8)) { 4782SN/A // A load incorrectly passed this store. Squash and refetch. 4792623SN/A // For now return a fault to show that it was unsuccessful. 48011147Smitch.hayenga@arm.com memDepViolator = loadQueue[load_idx]; 4817897Shestness@cs.utexas.edu ++lsqMemOrderViolation; 4822SN/A 4832623SN/A return genMachineCheckFault(); 4842623SN/A } 4854377Sgblack@eecs.umich.edu 4867720Sgblack@eecs.umich.edu incrLdIdx(load_idx); 4874377Sgblack@eecs.umich.edu } 4887720Sgblack@eecs.umich.edu 48911147Smitch.hayenga@arm.com // If we've reached this point, there was no violation. 4907720Sgblack@eecs.umich.edu memDepViolator = NULL; 4917720Sgblack@eecs.umich.edu } 4925665Sgblack@eecs.umich.edu 4935665Sgblack@eecs.umich.edu return store_fault; 4944181Sgblack@eecs.umich.edu} 4954181Sgblack@eecs.umich.edu 4969023Sgblack@eecs.umich.edutemplate <class Impl> 4979023Sgblack@eecs.umich.eduvoid 4984181Sgblack@eecs.umich.eduLSQUnit<Impl>::commitLoad() 4994182Sgblack@eecs.umich.edu{ 50011147Smitch.hayenga@arm.com assert(loadQueue[loadHead]); 50111321Ssteve.reinhardt@amd.com 5029023Sgblack@eecs.umich.edu DPRINTF(LSQUnit, "Committing head load instruction, PC %#x\n", 5034593Sgblack@eecs.umich.edu loadQueue[loadHead]->readPC()); 5049023Sgblack@eecs.umich.edu 5054377Sgblack@eecs.umich.edu loadQueue[loadHead] = NULL; 5069023Sgblack@eecs.umich.edu 5074377Sgblack@eecs.umich.edu incrLdIdx(loadHead); 5089023Sgblack@eecs.umich.edu 5099023Sgblack@eecs.umich.edu --loads; 51011147Smitch.hayenga@arm.com} 5117720Sgblack@eecs.umich.edu 5124377Sgblack@eecs.umich.edutemplate <class Impl> 51311147Smitch.hayenga@arm.comvoid 51411147Smitch.hayenga@arm.comLSQUnit<Impl>::commitLoads(InstSeqNum &youngest_inst) 5154377Sgblack@eecs.umich.edu{ 5164181Sgblack@eecs.umich.edu assert(loads == 0 || loadQueue[loadHead]); 5174181Sgblack@eecs.umich.edu 5184181Sgblack@eecs.umich.edu while (loads != 0 && loadQueue[loadHead]->seqNum <= youngest_inst) { 5194539Sgblack@eecs.umich.edu commitLoad(); 5203276Sgblack@eecs.umich.edu } 52111147Smitch.hayenga@arm.com} 52211147Smitch.hayenga@arm.com 5233280Sgblack@eecs.umich.edutemplate <class Impl> 5243280Sgblack@eecs.umich.eduvoid 5253276Sgblack@eecs.umich.eduLSQUnit<Impl>::commitStores(InstSeqNum &youngest_inst) 5263276Sgblack@eecs.umich.edu{ 5273276Sgblack@eecs.umich.edu assert(stores == 0 || storeQueue[storeHead].inst); 5287720Sgblack@eecs.umich.edu 5293276Sgblack@eecs.umich.edu int store_idx = storeHead; 5303276Sgblack@eecs.umich.edu 5314181Sgblack@eecs.umich.edu while (store_idx != storeTail) { 5328955Sgblack@eecs.umich.edu assert(storeQueue[store_idx].inst); 5334522Ssaidi@eecs.umich.edu // Mark any stores that are now committed and have not yet 53411147Smitch.hayenga@arm.com // been marked as able to write back. 5357720Sgblack@eecs.umich.edu if (!storeQueue[store_idx].canWB) { 5362470SN/A if (storeQueue[store_idx].inst->seqNum > youngest_inst) { 5378955Sgblack@eecs.umich.edu break; 5384181Sgblack@eecs.umich.edu } 5394522Ssaidi@eecs.umich.edu DPRINTF(LSQUnit, "Marking store as able to write back, PC " 5404181Sgblack@eecs.umich.edu "%#x [sn:%lli]\n", 54110061Sandreas@sandberg.pp.se storeQueue[store_idx].inst->readPC(), 54211147Smitch.hayenga@arm.com storeQueue[store_idx].inst->seqNum); 54311147Smitch.hayenga@arm.com 54410061Sandreas@sandberg.pp.se storeQueue[store_idx].canWB = true; 54510061Sandreas@sandberg.pp.se 54610061Sandreas@sandberg.pp.se ++storesToWB; 54711147Smitch.hayenga@arm.com } 54810061Sandreas@sandberg.pp.se 54911147Smitch.hayenga@arm.com incrStIdx(store_idx); 55011147Smitch.hayenga@arm.com } 55110061Sandreas@sandberg.pp.se} 55210061Sandreas@sandberg.pp.se 55311147Smitch.hayenga@arm.comtemplate <class Impl> 55410061Sandreas@sandberg.pp.sevoid 5552623SN/ALSQUnit<Impl>::writebackStores() 5562623SN/A{ 5572623SN/A while (storesToWB > 0 && 5582623SN/A storeWBIdx != storeTail && 5592623SN/A storeQueue[storeWBIdx].inst && 56011147Smitch.hayenga@arm.com storeQueue[storeWBIdx].canWB && 56111147Smitch.hayenga@arm.com usedPorts < cachePorts) { 56211147Smitch.hayenga@arm.com 5637720Sgblack@eecs.umich.edu if (isStoreBlocked || lsq->cacheBlocked()) { 5647720Sgblack@eecs.umich.edu DPRINTF(LSQUnit, "Unable to write back any more stores, cache" 56511147Smitch.hayenga@arm.com " is blocked!\n"); 5667720Sgblack@eecs.umich.edu break; 5678780Sgblack@eecs.umich.edu } 56811147Smitch.hayenga@arm.com 5697720Sgblack@eecs.umich.edu // Store didn't write any data so no need to write it back to 57011147Smitch.hayenga@arm.com // memory. 57111147Smitch.hayenga@arm.com if (storeQueue[storeWBIdx].size == 0) { 5722623SN/A completeStore(storeWBIdx); 5732683Sktlim@umich.edu 5742623SN/A incrStIdx(storeWBIdx); 5752SN/A 5762623SN/A continue; 57711147Smitch.hayenga@arm.com } 5782SN/A 5792SN/A ++usedPorts; 5802623SN/A 58111147Smitch.hayenga@arm.com if (storeQueue[storeWBIdx].inst->isDataPrefetch()) { 58211147Smitch.hayenga@arm.com incrStIdx(storeWBIdx); 5832623SN/A 5842SN/A continue; 5855953Ssaidi@eecs.umich.edu } 58611147Smitch.hayenga@arm.com 5875953Ssaidi@eecs.umich.edu assert(storeQueue[storeWBIdx].req); 5885953Ssaidi@eecs.umich.edu assert(!storeQueue[storeWBIdx].committed); 58910061Sandreas@sandberg.pp.se 59011147Smitch.hayenga@arm.com DynInstPtr inst = storeQueue[storeWBIdx].inst; 59110061Sandreas@sandberg.pp.se 59210061Sandreas@sandberg.pp.se Request *req = storeQueue[storeWBIdx].req; 5937897Shestness@cs.utexas.edu storeQueue[storeWBIdx].committed = true; 5947897Shestness@cs.utexas.edu 5957897Shestness@cs.utexas.edu assert(!inst->memData); 59611147Smitch.hayenga@arm.com inst->memData = new uint8_t[64]; 59711147Smitch.hayenga@arm.com memcpy(inst->memData, (uint8_t *)&storeQueue[storeWBIdx].data, 5987897Shestness@cs.utexas.edu req->getSize()); 5997897Shestness@cs.utexas.edu 6007897Shestness@cs.utexas.edu PacketPtr data_pkt = new Packet(req, Packet::WriteReq, Packet::Broadcast); 6017897Shestness@cs.utexas.edu data_pkt->dataStatic(inst->memData); 60211147Smitch.hayenga@arm.com 60311147Smitch.hayenga@arm.com LSQSenderState *state = new LSQSenderState; 6047897Shestness@cs.utexas.edu state->isLoad = false; 60511147Smitch.hayenga@arm.com state->idx = storeWBIdx; 6067897Shestness@cs.utexas.edu state->inst = inst; 6077897Shestness@cs.utexas.edu data_pkt->senderState = state; 60811147Smitch.hayenga@arm.com 6097897Shestness@cs.utexas.edu DPRINTF(LSQUnit, "D-Cache: Writing back store idx:%i PC:%#x " 61011147Smitch.hayenga@arm.com "to Addr:%#x, data:%#x [sn:%lli]\n", 6117897Shestness@cs.utexas.edu storeWBIdx, inst->readPC(), 6127897Shestness@cs.utexas.edu req->getPaddr(), *(inst->memData), 61311147Smitch.hayenga@arm.com inst->seqNum); 6147897Shestness@cs.utexas.edu 61511147Smitch.hayenga@arm.com // @todo: Remove this SC hack once the memory system handles it. 6167897Shestness@cs.utexas.edu if (req->getFlags() & LOCKED) { 6177897Shestness@cs.utexas.edu if (req->getFlags() & UNCACHEABLE) { 61811147Smitch.hayenga@arm.com req->setScResult(2); 6197897Shestness@cs.utexas.edu } else { 62011147Smitch.hayenga@arm.com if (cpu->lockFlag) { 6217897Shestness@cs.utexas.edu req->setScResult(1); 62211147Smitch.hayenga@arm.com DPRINTF(LSQUnit, "Store conditional [sn:%lli] succeeded.", 6237897Shestness@cs.utexas.edu inst->seqNum); 6247897Shestness@cs.utexas.edu } else { 6257897Shestness@cs.utexas.edu req->setScResult(0); 62611147Smitch.hayenga@arm.com // Hack: Instantly complete this store. 62710193SCurtis.Dunham@arm.com// completeDataAccess(data_pkt); 6288780Sgblack@eecs.umich.edu DPRINTF(LSQUnit, "Store conditional [sn:%lli] failed. " 6298780Sgblack@eecs.umich.edu "Instantly completing it.\n", 6302644Sstever@eecs.umich.edu inst->seqNum); 6312644Sstever@eecs.umich.edu WritebackEvent *wb = new WritebackEvent(inst, data_pkt, this); 6324046Sbinkertn@umich.edu wb->schedule(curTick + 1); 6334046Sbinkertn@umich.edu delete state; 6344046Sbinkertn@umich.edu completeStore(storeWBIdx); 6352644Sstever@eecs.umich.edu incrStIdx(storeWBIdx); 63610464SAndreas.Sandberg@ARM.com continue; 63710464SAndreas.Sandberg@ARM.com } 63810464SAndreas.Sandberg@ARM.com } 6392623SN/A } else { 6402SN/A // Non-store conditionals do not need a writeback. 6412623SN/A state->noWB = true; 64210379Sandreas.hansson@arm.com } 6432623SN/A 64411147Smitch.hayenga@arm.com if (!dcachePort->sendTiming(data_pkt)) { 64511147Smitch.hayenga@arm.com if (data_pkt->result == Packet::BadAddress) { 64611147Smitch.hayenga@arm.com panic("LSQ sent out a bad address for a completed store!"); 64710061Sandreas@sandberg.pp.se } 64810061Sandreas@sandberg.pp.se // Need to handle becoming blocked on a store. 6494377Sgblack@eecs.umich.edu DPRINTF(IEW, "D-Cache became blcoked when writing [sn:%lli], will" 65011147Smitch.hayenga@arm.com "retry later\n", 6512090SN/A inst->seqNum); 6523905Ssaidi@eecs.umich.edu isStoreBlocked = true; 65311147Smitch.hayenga@arm.com ++lsqCacheBlocked; 6549023Sgblack@eecs.umich.edu assert(retryPkt == NULL); 6554377Sgblack@eecs.umich.edu retryPkt = data_pkt; 6567720Sgblack@eecs.umich.edu lsq->setRetryTid(lsqID); 6577720Sgblack@eecs.umich.edu } else { 6587720Sgblack@eecs.umich.edu storePostSend(data_pkt); 6597720Sgblack@eecs.umich.edu } 6607720Sgblack@eecs.umich.edu } 6617720Sgblack@eecs.umich.edu 6623276Sgblack@eecs.umich.edu // Not sure this should set it to 0. 6632SN/A usedPorts = 0; 66410061Sandreas@sandberg.pp.se 66510061Sandreas@sandberg.pp.se assert(stores >= 0 && storesToWB >= 0); 66610061Sandreas@sandberg.pp.se} 66710061Sandreas@sandberg.pp.se 66810061Sandreas@sandberg.pp.se/*template <class Impl> 66910061Sandreas@sandberg.pp.sevoid 67011147Smitch.hayenga@arm.comLSQUnit<Impl>::removeMSHR(InstSeqNum seqNum) 67110061Sandreas@sandberg.pp.se{ 67211147Smitch.hayenga@arm.com list<InstSeqNum>::iterator mshr_it = find(mshrSeqNums.begin(), 67310061Sandreas@sandberg.pp.se mshrSeqNums.end(), 67410061Sandreas@sandberg.pp.se seqNum); 67511147Smitch.hayenga@arm.com 67611147Smitch.hayenga@arm.com if (mshr_it != mshrSeqNums.end()) { 67710061Sandreas@sandberg.pp.se mshrSeqNums.erase(mshr_it); 67810061Sandreas@sandberg.pp.se DPRINTF(LSQUnit, "Removing MSHR. count = %i\n",mshrSeqNums.size()); 6792SN/A } 6802SN/A}*/ 6819461Snilay@cs.wisc.edu 6829461Snilay@cs.wisc.edutemplate <class Impl> 6839461Snilay@cs.wisc.eduvoid 6849461Snilay@cs.wisc.eduLSQUnit<Impl>::squash(const InstSeqNum &squashed_num) 68511147Smitch.hayenga@arm.com{ 68611147Smitch.hayenga@arm.com DPRINTF(LSQUnit, "Squashing until [sn:%lli]!" 6879461Snilay@cs.wisc.edu "(Loads:%i Stores:%i)\n", squashed_num, loads, stores); 688 689 int load_idx = loadTail; 690 decrLdIdx(load_idx); 691 692 while (loads != 0 && loadQueue[load_idx]->seqNum > squashed_num) { 693 DPRINTF(LSQUnit,"Load Instruction PC %#x squashed, " 694 "[sn:%lli]\n", 695 loadQueue[load_idx]->readPC(), 696 loadQueue[load_idx]->seqNum); 697 698 if (isStalled() && load_idx == stallingLoadIdx) { 699 stalled = false; 700 stallingStoreIsn = 0; 701 stallingLoadIdx = 0; 702 } 703 704 // Clear the smart pointer to make sure it is decremented. 705 loadQueue[load_idx]->setSquashed(); 706 loadQueue[load_idx] = NULL; 707 --loads; 708 709 // Inefficient! 710 loadTail = load_idx; 711 712 decrLdIdx(load_idx); 713 ++lsqSquashedLoads; 714 } 715 716 if (isLoadBlocked) { 717 if (squashed_num < blockedLoadSeqNum) { 718 isLoadBlocked = false; 719 loadBlockedHandled = false; 720 blockedLoadSeqNum = 0; 721 } 722 } 723 724 int store_idx = storeTail; 725 decrStIdx(store_idx); 726 727 while (stores != 0 && 728 storeQueue[store_idx].inst->seqNum > squashed_num) { 729 // Instructions marked as can WB are already committed. 730 if (storeQueue[store_idx].canWB) { 731 break; 732 } 733 734 DPRINTF(LSQUnit,"Store Instruction PC %#x squashed, " 735 "idx:%i [sn:%lli]\n", 736 storeQueue[store_idx].inst->readPC(), 737 store_idx, storeQueue[store_idx].inst->seqNum); 738 739 // I don't think this can happen. It should have been cleared 740 // by the stalling load. 741 if (isStalled() && 742 storeQueue[store_idx].inst->seqNum == stallingStoreIsn) { 743 panic("Is stalled should have been cleared by stalling load!\n"); 744 stalled = false; 745 stallingStoreIsn = 0; 746 } 747 748 // Clear the smart pointer to make sure it is decremented. 749 storeQueue[store_idx].inst->setSquashed(); 750 storeQueue[store_idx].inst = NULL; 751 storeQueue[store_idx].canWB = 0; 752 753 storeQueue[store_idx].req = NULL; 754 --stores; 755 756 // Inefficient! 757 storeTail = store_idx; 758 759 decrStIdx(store_idx); 760 ++lsqSquashedStores; 761 } 762} 763 764template <class Impl> 765void 766LSQUnit<Impl>::storePostSend(Packet *pkt) 767{ 768 if (isStalled() && 769 storeQueue[storeWBIdx].inst->seqNum == stallingStoreIsn) { 770 DPRINTF(LSQUnit, "Unstalling, stalling store [sn:%lli] " 771 "load idx:%i\n", 772 stallingStoreIsn, stallingLoadIdx); 773 stalled = false; 774 stallingStoreIsn = 0; 775 iewStage->replayMemInst(loadQueue[stallingLoadIdx]); 776 } 777 778 if (!storeQueue[storeWBIdx].inst->isStoreConditional()) { 779 // The store is basically completed at this time. This 780 // only works so long as the checker doesn't try to 781 // verify the value in memory for stores. 782 storeQueue[storeWBIdx].inst->setCompleted(); 783#if USE_CHECKER 784 if (cpu->checker) { 785 cpu->checker->verify(storeQueue[storeWBIdx].inst); 786 } 787#endif 788 } 789 790 if (pkt->result != Packet::Success) { 791 DPRINTF(LSQUnit,"D-Cache Write Miss on idx:%i!\n", 792 storeWBIdx); 793 794 DPRINTF(Activity, "Active st accessing mem miss [sn:%lli]\n", 795 storeQueue[storeWBIdx].inst->seqNum); 796 797 //mshrSeqNums.push_back(storeQueue[storeWBIdx].inst->seqNum); 798 799 //DPRINTF(LSQUnit, "Added MSHR. count = %i\n",mshrSeqNums.size()); 800 801 // @todo: Increment stat here. 802 } else { 803 DPRINTF(LSQUnit,"D-Cache: Write Hit on idx:%i !\n", 804 storeWBIdx); 805 806 DPRINTF(Activity, "Active st accessing mem hit [sn:%lli]\n", 807 storeQueue[storeWBIdx].inst->seqNum); 808 } 809 810 incrStIdx(storeWBIdx); 811} 812 813template <class Impl> 814void 815LSQUnit<Impl>::writeback(DynInstPtr &inst, PacketPtr pkt) 816{ 817 iewStage->wakeCPU(); 818 819 // Squashed instructions do not need to complete their access. 820 if (inst->isSquashed()) { 821 iewStage->decrWb(inst->seqNum); 822 assert(!inst->isStore()); 823 ++lsqIgnoredResponses; 824 return; 825 } 826 827 if (!inst->isExecuted()) { 828 inst->setExecuted(); 829 830 // Complete access to copy data to proper place. 831 inst->completeAcc(pkt); 832 } 833 834 // Need to insert instruction into queue to commit 835 iewStage->instToCommit(inst); 836 837 iewStage->activityThisCycle(); 838} 839 840template <class Impl> 841void 842LSQUnit<Impl>::completeStore(int store_idx) 843{ 844 assert(storeQueue[store_idx].inst); 845 storeQueue[store_idx].completed = true; 846 --storesToWB; 847 // A bit conservative because a store completion may not free up entries, 848 // but hopefully avoids two store completions in one cycle from making 849 // the CPU tick twice. 850 cpu->wakeCPU(); 851 cpu->activityThisCycle(); 852 853 if (store_idx == storeHead) { 854 do { 855 incrStIdx(storeHead); 856 857 --stores; 858 } while (storeQueue[storeHead].completed && 859 storeHead != storeTail); 860 861 iewStage->updateLSQNextCycle = true; 862 } 863 864 DPRINTF(LSQUnit, "Completing store [sn:%lli], idx:%i, store head " 865 "idx:%i\n", 866 storeQueue[store_idx].inst->seqNum, store_idx, storeHead); 867 868 if (isStalled() && 869 storeQueue[store_idx].inst->seqNum == stallingStoreIsn) { 870 DPRINTF(LSQUnit, "Unstalling, stalling store [sn:%lli] " 871 "load idx:%i\n", 872 stallingStoreIsn, stallingLoadIdx); 873 stalled = false; 874 stallingStoreIsn = 0; 875 iewStage->replayMemInst(loadQueue[stallingLoadIdx]); 876 } 877 878 storeQueue[store_idx].inst->setCompleted(); 879 880 // Tell the checker we've completed this instruction. Some stores 881 // may get reported twice to the checker, but the checker can 882 // handle that case. 883#if USE_CHECKER 884 if (cpu->checker) { 885 cpu->checker->verify(storeQueue[store_idx].inst); 886 } 887#endif 888} 889 890template <class Impl> 891void 892LSQUnit<Impl>::recvRetry() 893{ 894 if (isStoreBlocked) { 895 assert(retryPkt != NULL); 896 897 if (dcachePort->sendTiming(retryPkt)) { 898 if (retryPkt->result == Packet::BadAddress) { 899 panic("LSQ sent out a bad address for a completed store!"); 900 } 901 storePostSend(retryPkt); 902 retryPkt = NULL; 903 isStoreBlocked = false; 904 lsq->setRetryTid(-1); 905 } else { 906 // Still blocked! 907 ++lsqCacheBlocked; 908 lsq->setRetryTid(lsqID); 909 } 910 } else if (isLoadBlocked) { 911 DPRINTF(LSQUnit, "Loads squash themselves and all younger insts, " 912 "no need to resend packet.\n"); 913 } else { 914 DPRINTF(LSQUnit, "Retry received but LSQ is no longer blocked.\n"); 915 } 916} 917 918template <class Impl> 919inline void 920LSQUnit<Impl>::incrStIdx(int &store_idx) 921{ 922 if (++store_idx >= SQEntries) 923 store_idx = 0; 924} 925 926template <class Impl> 927inline void 928LSQUnit<Impl>::decrStIdx(int &store_idx) 929{ 930 if (--store_idx < 0) 931 store_idx += SQEntries; 932} 933 934template <class Impl> 935inline void 936LSQUnit<Impl>::incrLdIdx(int &load_idx) 937{ 938 if (++load_idx >= LQEntries) 939 load_idx = 0; 940} 941 942template <class Impl> 943inline void 944LSQUnit<Impl>::decrLdIdx(int &load_idx) 945{ 946 if (--load_idx < 0) 947 load_idx += LQEntries; 948} 949 950template <class Impl> 951void 952LSQUnit<Impl>::dumpInsts() 953{ 954 cprintf("Load store queue: Dumping instructions.\n"); 955 cprintf("Load queue size: %i\n", loads); 956 cprintf("Load queue: "); 957 958 int load_idx = loadHead; 959 960 while (load_idx != loadTail && loadQueue[load_idx]) { 961 cprintf("%#x ", loadQueue[load_idx]->readPC()); 962 963 incrLdIdx(load_idx); 964 } 965 966 cprintf("Store queue size: %i\n", stores); 967 cprintf("Store queue: "); 968 969 int store_idx = storeHead; 970 971 while (store_idx != storeTail && storeQueue[store_idx].inst) { 972 cprintf("%#x ", storeQueue[store_idx].inst->readPC()); 973 974 incrStIdx(store_idx); 975 } 976 977 cprintf("\n"); 978} 979