lsq_unit_impl.hh revision 2699:c255fef3daaa
12SN/A/* 21762SN/A * Copyright (c) 2004-2005 The Regents of The University of Michigan 32SN/A * All rights reserved. 42SN/A * 52SN/A * Redistribution and use in source and binary forms, with or without 62SN/A * modification, are permitted provided that the following conditions are 72SN/A * met: redistributions of source code must retain the above copyright 82SN/A * notice, this list of conditions and the following disclaimer; 92SN/A * redistributions in binary form must reproduce the above copyright 102SN/A * notice, this list of conditions and the following disclaimer in the 112SN/A * documentation and/or other materials provided with the distribution; 122SN/A * neither the name of the copyright holders nor the names of its 132SN/A * contributors may be used to endorse or promote products derived from 142SN/A * this software without specific prior written permission. 152SN/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. 272665Ssaidi@eecs.umich.edu * 282665Ssaidi@eecs.umich.edu * Authors: Kevin Lim 292665Ssaidi@eecs.umich.edu * Korey Sewell 302SN/A */ 312SN/A 322SN/A#include "cpu/checker/cpu.hh" 332SN/A#include "cpu/o3/lsq_unit.hh" 342SN/A#include "base/str.hh" 352SN/A#include "mem/request.hh" 361354SN/A 371354SN/Atemplate<class Impl> 382SN/ALSQUnit<Impl>::WritebackEvent::WritebackEvent(DynInstPtr &_inst, PacketPtr _pkt, 392SN/A LSQUnit *lsq_ptr) 405501Snate@binkert.org : Event(&mainEventQueue), inst(_inst), pkt(_pkt), lsqPtr(lsq_ptr) 415546Snate@binkert.org{ 422SN/A this->setFlags(Event::AutoDelete); 432SN/A} 442SN/A 452SN/Atemplate<class Impl> 4656SN/Avoid 475769Snate@binkert.orgLSQUnit<Impl>::WritebackEvent::process() 482361SN/A{ 491354SN/A if (!lsqPtr->isSwitchedOut()) { 506216Snate@binkert.org lsqPtr->writeback(inst, pkt); 5156SN/A } 522SN/A delete pkt; 535543Ssaidi@eecs.umich.edu} 542SN/A 551354SN/Atemplate<class Impl> 561354SN/Aconst char * 572SN/ALSQUnit<Impl>::WritebackEvent::description() 582SN/A{ 592SN/A return "Store writeback event"; 602SN/A} 615501Snate@binkert.org 625501Snate@binkert.orgtemplate<class Impl> 632SN/Avoid 64395SN/ALSQUnit<Impl>::completeDataAccess(PacketPtr pkt) 652SN/A{ 662SN/A LSQSenderState *state = dynamic_cast<LSQSenderState *>(pkt->senderState); 672SN/A DynInstPtr inst = state->inst; 685769Snate@binkert.org DPRINTF(IEW, "Writeback event [sn:%lli]\n", inst->seqNum); 695769Snate@binkert.org DPRINTF(Activity, "Activity: Writeback event [sn:%lli]\n", inst->seqNum); 705769Snate@binkert.org 715769Snate@binkert.org //iewStage->ldstQueue.removeMSHR(inst->threadNumber,inst->seqNum); 725769Snate@binkert.org 735769Snate@binkert.org if (isSwitchedOut() || inst->isSquashed()) { 745769Snate@binkert.org delete state; 755769Snate@binkert.org delete pkt; 765769Snate@binkert.org return; 775769Snate@binkert.org } else { 785769Snate@binkert.org if (!state->noWB) { 795769Snate@binkert.org writeback(inst, pkt); 805774Snate@binkert.org } 815774Snate@binkert.org 825774Snate@binkert.org if (inst->isStore()) { 835769Snate@binkert.org completeStore(state->idx); 842SN/A } 855502Snate@binkert.org } 865502Snate@binkert.org 875502Snate@binkert.org delete state; 885503Snate@binkert.org delete pkt; 895503Snate@binkert.org} 905502Snate@binkert.org 915502Snate@binkert.orgtemplate <class Impl> 925502Snate@binkert.orgTick 935502Snate@binkert.orgLSQUnit<Impl>::DcachePort::recvAtomic(PacketPtr pkt) 945502Snate@binkert.org{ 955502Snate@binkert.org panic("O3CPU model does not work with atomic mode!"); 965502Snate@binkert.org return curTick; 975602Snate@binkert.org} 985602Snate@binkert.org 995501Snate@binkert.orgtemplate <class Impl> 1005543Ssaidi@eecs.umich.eduvoid 1015543Ssaidi@eecs.umich.eduLSQUnit<Impl>::DcachePort::recvFunctional(PacketPtr pkt) 1025769Snate@binkert.org{ 1034016Sstever@eecs.umich.edu panic("O3CPU doesn't expect recvFunctional callback!"); 1044016Sstever@eecs.umich.edu} 1054016Sstever@eecs.umich.edu 1064016Sstever@eecs.umich.edutemplate <class Impl> 1074016Sstever@eecs.umich.eduvoid 1084016Sstever@eecs.umich.eduLSQUnit<Impl>::DcachePort::recvStatusChange(Status status) 1094016Sstever@eecs.umich.edu{ 1104016Sstever@eecs.umich.edu if (status == RangeChange) 1114016Sstever@eecs.umich.edu return; 1125501Snate@binkert.org 1135605Snate@binkert.org panic("O3CPU doesn't expect recvStatusChange callback!"); 1145605Snate@binkert.org} 1155605Snate@binkert.org 1165605Snate@binkert.orgtemplate <class Impl> 1175501Snate@binkert.orgbool 1184016Sstever@eecs.umich.eduLSQUnit<Impl>::DcachePort::recvTiming(PacketPtr pkt) 1195577SSteve.Reinhardt@amd.com{ 1205501Snate@binkert.org lsq->completeDataAccess(pkt); 1215501Snate@binkert.org return true; 1225501Snate@binkert.org} 1235502Snate@binkert.org 1245502Snate@binkert.orgtemplate <class Impl> 1255605Snate@binkert.orgvoid 1265502Snate@binkert.orgLSQUnit<Impl>::DcachePort::recvRetry() 1275502Snate@binkert.org{ 1285605Snate@binkert.org lsq->recvRetry(); 1295605Snate@binkert.org} 1305605Snate@binkert.org 1315577SSteve.Reinhardt@amd.comtemplate <class Impl> 1325502Snate@binkert.orgLSQUnit<Impl>::LSQUnit() 1335502Snate@binkert.org : loads(0), stores(0), storesToWB(0), stalled(false), 1345502Snate@binkert.org isStoreBlocked(false), isLoadBlocked(false), 1355502Snate@binkert.org loadBlockedHandled(false) 1362SN/A{ 1375769Snate@binkert.org} 1385769Snate@binkert.org 1395769Snate@binkert.orgtemplate<class Impl> 1405769Snate@binkert.orgvoid 1415769Snate@binkert.orgLSQUnit<Impl>::init(Params *params, unsigned maxLQEntries, 1425769Snate@binkert.org unsigned maxSQEntries, unsigned id) 1432SN/A{ 1445769Snate@binkert.org DPRINTF(LSQUnit, "Creating LSQUnit%i object.\n",id); 1455769Snate@binkert.org 1465769Snate@binkert.org switchedOut = false; 1475769Snate@binkert.org 1485769Snate@binkert.org lsqID = id; 1495769Snate@binkert.org 1502SN/A // Add 1 for the sentinel entry (they are circular queues). 1515769Snate@binkert.org LQEntries = maxLQEntries + 1; 1525769Snate@binkert.org SQEntries = maxSQEntries + 1; 1535769Snate@binkert.org 1545769Snate@binkert.org loadQueue.resize(LQEntries); 1555769Snate@binkert.org storeQueue.resize(SQEntries); 1565769Snate@binkert.org 1575769Snate@binkert.org loadHead = loadTail = 0; 1585769Snate@binkert.org 1595769Snate@binkert.org storeHead = storeWBIdx = storeTail = 0; 1605769Snate@binkert.org 1615769Snate@binkert.org usedPorts = 0; 1625769Snate@binkert.org cachePorts = params->cachePorts; 1635769Snate@binkert.org 1645769Snate@binkert.org mem = params->mem; 1655769Snate@binkert.org 1665769Snate@binkert.org memDepViolator = NULL; 1675769Snate@binkert.org 1685769Snate@binkert.org blockedLoadSeqNum = 0; 1695769Snate@binkert.org} 1705769Snate@binkert.org 1715769Snate@binkert.orgtemplate<class Impl> 1725769Snate@binkert.orgvoid 1735769Snate@binkert.orgLSQUnit<Impl>::setCPU(FullCPU *cpu_ptr) 1745769Snate@binkert.org{ 1755769Snate@binkert.org cpu = cpu_ptr; 1765769Snate@binkert.org dcachePort = new DcachePort(cpu, this); 1775769Snate@binkert.org 1785769Snate@binkert.org Port *mem_dport = mem->getPort(""); 1795501Snate@binkert.org dcachePort->setPeer(mem_dport); 1805543Ssaidi@eecs.umich.edu mem_dport->setPeer(dcachePort); 1812SN/A 1822SN/A if (cpu->checker) { 183396SN/A cpu->checker->setDcachePort(dcachePort); 184396SN/A } 185396SN/A} 186396SN/A 187396SN/Atemplate<class Impl> 1885501Snate@binkert.orgstd::string 1895543Ssaidi@eecs.umich.eduLSQUnit<Impl>::name() const 1905501Snate@binkert.org{ 1913329Sstever@eecs.umich.edu if (Impl::MaxThreads == 1) { 1923329Sstever@eecs.umich.edu return iewStage->name() + ".lsq"; 1933329Sstever@eecs.umich.edu } else { 1943329Sstever@eecs.umich.edu return iewStage->name() + ".lsq.thread." + to_string(lsqID); 1953329Sstever@eecs.umich.edu } 1963329Sstever@eecs.umich.edu} 1973329Sstever@eecs.umich.edu 1983329Sstever@eecs.umich.edutemplate<class Impl> 1995543Ssaidi@eecs.umich.eduvoid 200396SN/ALSQUnit<Impl>::clearLQ() 2013329Sstever@eecs.umich.edu{ 2023329Sstever@eecs.umich.edu loadQueue.clear(); 2033329Sstever@eecs.umich.edu} 2043329Sstever@eecs.umich.edu 2055543Ssaidi@eecs.umich.edutemplate<class Impl> 2063329Sstever@eecs.umich.eduvoid 207396SN/ALSQUnit<Impl>::clearSQ() 208396SN/A{ 209396SN/A storeQueue.clear(); 2105543Ssaidi@eecs.umich.edu} 211396SN/A 212396SN/Atemplate<class Impl> 2135543Ssaidi@eecs.umich.eduvoid 214396SN/ALSQUnit<Impl>::switchOut() 215396SN/A{ 216396SN/A switchedOut = true; 217396SN/A for (int i = 0; i < loadQueue.size(); ++i) 2185543Ssaidi@eecs.umich.edu loadQueue[i] = NULL; 219396SN/A 220396SN/A assert(storesToWB == 0); 221396SN/A} 2225543Ssaidi@eecs.umich.edu 223396SN/Atemplate<class Impl> 224396SN/Avoid 225396SN/ALSQUnit<Impl>::takeOverFrom() 2265543Ssaidi@eecs.umich.edu{ 227396SN/A switchedOut = false; 2284075Sbinkertn@umich.edu loads = stores = storesToWB = 0; 2294075Sbinkertn@umich.edu 2304075Sbinkertn@umich.edu loadHead = loadTail = 0; 231396SN/A 232396SN/A storeHead = storeWBIdx = storeTail = 0; 2335543Ssaidi@eecs.umich.edu 2345501Snate@binkert.org usedPorts = 0; 2355501Snate@binkert.org 2365543Ssaidi@eecs.umich.edu memDepViolator = NULL; 237396SN/A 238396SN/A blockedLoadSeqNum = 0; 2392SN/A 2402SN/A stalled = false; 2412SN/A isLoadBlocked = false; 2422SN/A loadBlockedHandled = false; 2435605Snate@binkert.org} 2445769Snate@binkert.org 245224SN/Atemplate<class Impl> 2464016Sstever@eecs.umich.eduvoid 2475501Snate@binkert.orgLSQUnit<Impl>::resizeLQ(unsigned size) 2485605Snate@binkert.org{ 2495501Snate@binkert.org unsigned size_plus_sentinel = size + 1; 2505501Snate@binkert.org assert(size_plus_sentinel >= LQEntries); 2515774Snate@binkert.org 2525501Snate@binkert.org if (size_plus_sentinel > LQEntries) { 2535501Snate@binkert.org while (size_plus_sentinel > loadQueue.size()) { 2544016Sstever@eecs.umich.edu DynInstPtr dummy; 255224SN/A loadQueue.push_back(dummy); 256224SN/A LQEntries++; 2575768Snate@binkert.org } 2585768Snate@binkert.org } else { 259265SN/A LQEntries = size_plus_sentinel; 2605501Snate@binkert.org } 2615501Snate@binkert.org 2625501Snate@binkert.org} 2635501Snate@binkert.org 2645501Snate@binkert.orgtemplate<class Impl> 2655501Snate@binkert.orgvoid 2665501Snate@binkert.orgLSQUnit<Impl>::resizeSQ(unsigned size) 2675501Snate@binkert.org{ 2685501Snate@binkert.org unsigned size_plus_sentinel = size + 1; 2695501Snate@binkert.org if (size_plus_sentinel > SQEntries) { 2705501Snate@binkert.org while (size_plus_sentinel > storeQueue.size()) { 2715501Snate@binkert.org SQEntry dummy; 2725501Snate@binkert.org storeQueue.push_back(dummy); 2735501Snate@binkert.org SQEntries++; 2745501Snate@binkert.org } 2755501Snate@binkert.org } else { 2765501Snate@binkert.org SQEntries = size_plus_sentinel; 2775501Snate@binkert.org } 2785501Snate@binkert.org} 2795501Snate@binkert.org 2805501Snate@binkert.orgtemplate <class Impl> 2812SN/Avoid 2825769Snate@binkert.orgLSQUnit<Impl>::insert(DynInstPtr &inst) 2832SN/A{ 2842SN/A assert(inst->isMemRef()); 2855769Snate@binkert.org 2862SN/A assert(inst->isLoad() || inst->isStore()); 2872SN/A 2885769Snate@binkert.org if (inst->isLoad()) { 2892SN/A insertLoad(inst); 2902667Sstever@eecs.umich.edu } else { 2915769Snate@binkert.org insertStore(inst); 2922667Sstever@eecs.umich.edu } 2932SN/A 2942SN/A inst->setInLSQ(); 2952SN/A} 2962SN/A 2972SN/Atemplate <class Impl> 2982SN/Avoid 2995605Snate@binkert.orgLSQUnit<Impl>::insertLoad(DynInstPtr &load_inst) 3005501Snate@binkert.org{ 3015501Snate@binkert.org assert((loadTail + 1) % LQEntries != loadHead); 3022SN/A assert(loads < LQEntries); 3035501Snate@binkert.org 3045501Snate@binkert.org DPRINTF(LSQUnit, "Inserting load PC %#x, idx:%i [sn:%lli]\n", 3055501Snate@binkert.org load_inst->readPC(), loadTail, load_inst->seqNum); 3062SN/A 3072SN/A load_inst->lqIdx = loadTail; 3082SN/A 309224SN/A if (stores == 0) { 310224SN/A load_inst->sqIdx = -1; 311237SN/A } else { 3125605Snate@binkert.org load_inst->sqIdx = storeTail; 313571SN/A } 314571SN/A 3152SN/A loadQueue[loadTail] = load_inst; 3162SN/A 3172SN/A incrLdIdx(loadTail); 318395SN/A 3192SN/A ++loads; 3205605Snate@binkert.org} 321265SN/A 3222SN/Atemplate <class Impl> 3232SN/Avoid 3242SN/ALSQUnit<Impl>::insertStore(DynInstPtr &store_inst) 3252SN/A{ 3262SN/A // Make sure it is not full before inserting an instruction. 3272SN/A assert((storeTail + 1) % SQEntries != storeHead); 3282SN/A assert(stores < SQEntries); 329265SN/A 3302SN/A DPRINTF(LSQUnit, "Inserting store PC %#x, idx:%i [sn:%lli]\n", 3312SN/A store_inst->readPC(), storeTail, store_inst->seqNum); 332512SN/A 333265SN/A store_inst->sqIdx = storeTail; 3342SN/A store_inst->lqIdx = loadTail; 3355738Snate@binkert.org 3365738Snate@binkert.org storeQueue[storeTail] = SQEntry(store_inst); 3375738Snate@binkert.org 3382SN/A incrStIdx(storeTail); 3395501Snate@binkert.org 3402667Sstever@eecs.umich.edu ++stores; 3412SN/A} 3422SN/A 3432SN/Atemplate <class Impl> 3442SN/Atypename Impl::DynInstPtr 3455501Snate@binkert.orgLSQUnit<Impl>::getMemDepViolator() 3465501Snate@binkert.org{ 3475501Snate@binkert.org DynInstPtr temp = memDepViolator; 3482SN/A 3492SN/A memDepViolator = NULL; 3502SN/A 3512SN/A return temp; 3521634SN/A} 3531634SN/A 3541634SN/Atemplate <class Impl> 3551634SN/Aunsigned 3561634SN/ALSQUnit<Impl>::numFreeEntries() 3572SN/A{ 3582SN/A unsigned free_lq_entries = LQEntries - loads; 3592SN/A unsigned free_sq_entries = SQEntries - stores; 3602SN/A 3612SN/A // Both the LQ and SQ entries have an extra dummy entry to differentiate 3622SN/A // empty/full conditions. Subtract 1 from the free entries. 3632SN/A if (free_lq_entries < free_sq_entries) { 3642SN/A return free_lq_entries - 1; 3655501Snate@binkert.org } else { 3662SN/A return free_sq_entries - 1; 3675501Snate@binkert.org } 3682SN/A} 3692SN/A 3702SN/Atemplate <class Impl> 3715502Snate@binkert.orgint 3725502Snate@binkert.orgLSQUnit<Impl>::numLoadsReady() 3735605Snate@binkert.org{ 374217SN/A int load_idx = loadHead; 375237SN/A int retval = 0; 3765605Snate@binkert.org 3772SN/A while (load_idx != loadTail) { 3782SN/A assert(loadQueue[load_idx]); 3795605Snate@binkert.org 3805605Snate@binkert.org if (loadQueue[load_idx]->readyToIssue()) { 3815605Snate@binkert.org ++retval; 3825605Snate@binkert.org } 3835605Snate@binkert.org } 3845605Snate@binkert.org 3852SN/A return retval; 3865605Snate@binkert.org} 3875605Snate@binkert.org 3885605Snate@binkert.orgtemplate <class Impl> 3895605Snate@binkert.orgFault 3902SN/ALSQUnit<Impl>::executeLoad(DynInstPtr &inst) 3915605Snate@binkert.org{ 3925605Snate@binkert.org // Execute a specific load. 3935605Snate@binkert.org Fault load_fault = NoFault; 3945605Snate@binkert.org 3955605Snate@binkert.org DPRINTF(LSQUnit, "Executing load PC %#x, [sn:%lli]\n", 3965605Snate@binkert.org inst->readPC(),inst->seqNum); 3975605Snate@binkert.org 3985605Snate@binkert.org load_fault = inst->initiateAcc(); 3995605Snate@binkert.org 4005605Snate@binkert.org // If the instruction faulted, then we need to send it along to commit 4015605Snate@binkert.org // without the instruction completing. 4025605Snate@binkert.org if (load_fault != NoFault) { 4035605Snate@binkert.org // Send this instruction to commit, also make sure iew stage 4045605Snate@binkert.org // realizes there is activity. 4055605Snate@binkert.org iewStage->instToCommit(inst); 4065605Snate@binkert.org iewStage->activityThisCycle(); 4075605Snate@binkert.org } 4085605Snate@binkert.org 4095605Snate@binkert.org return load_fault; 4105605Snate@binkert.org} 4115605Snate@binkert.org 4125605Snate@binkert.orgtemplate <class Impl> 4135605Snate@binkert.orgFault 4145605Snate@binkert.orgLSQUnit<Impl>::executeStore(DynInstPtr &store_inst) 4155605Snate@binkert.org{ 4165605Snate@binkert.org using namespace TheISA; 4175605Snate@binkert.org // Make sure that a store exists. 4185605Snate@binkert.org assert(stores != 0); 4195605Snate@binkert.org 4205605Snate@binkert.org int store_idx = store_inst->sqIdx; 4215605Snate@binkert.org 4225605Snate@binkert.org DPRINTF(LSQUnit, "Executing store PC %#x [sn:%lli]\n", 4235605Snate@binkert.org store_inst->readPC(), store_inst->seqNum); 4245605Snate@binkert.org 4255605Snate@binkert.org // Check the recently completed loads to see if any match this store's 4265605Snate@binkert.org // address. If so, then we have a memory ordering violation. 4275605Snate@binkert.org int load_idx = store_inst->lqIdx; 4285605Snate@binkert.org 4295605Snate@binkert.org Fault store_fault = store_inst->initiateAcc(); 4305605Snate@binkert.org 4315605Snate@binkert.org if (storeQueue[store_idx].size == 0) { 4325605Snate@binkert.org DPRINTF(LSQUnit,"Fault on Store PC %#x, [sn:%lli],Size = 0\n", 4335605Snate@binkert.org store_inst->readPC(),store_inst->seqNum); 4345605Snate@binkert.org 4355605Snate@binkert.org return store_fault; 4365605Snate@binkert.org } 4375605Snate@binkert.org 4385605Snate@binkert.org assert(store_fault == NoFault); 4395605Snate@binkert.org 4405605Snate@binkert.org if (store_inst->isStoreConditional()) { 4415605Snate@binkert.org // Store conditionals need to set themselves as able to 4425605Snate@binkert.org // writeback if we haven't had a fault by here. 4435605Snate@binkert.org storeQueue[store_idx].canWB = true; 4445605Snate@binkert.org 4455605Snate@binkert.org ++storesToWB; 4465769Snate@binkert.org } 4475605Snate@binkert.org 4485605Snate@binkert.org if (!memDepViolator) { 4495605Snate@binkert.org while (load_idx != loadTail) { 4505605Snate@binkert.org // Really only need to check loads that have actually executed 4515605Snate@binkert.org // It's safe to check all loads because effAddr is set to 4525605Snate@binkert.org // InvalAddr when the dyn inst is created. 4535605Snate@binkert.org 4545605Snate@binkert.org // @todo: For now this is extra conservative, detecting a 4555605Snate@binkert.org // violation if the addresses match assuming all accesses 4565605Snate@binkert.org // are quad word accesses. 4575605Snate@binkert.org 4585605Snate@binkert.org // @todo: Fix this, magic number being used here 4595605Snate@binkert.org if ((loadQueue[load_idx]->effAddr >> 8) == 4605605Snate@binkert.org (store_inst->effAddr >> 8)) { 4615605Snate@binkert.org // A load incorrectly passed this store. Squash and refetch. 4625605Snate@binkert.org // For now return a fault to show that it was unsuccessful. 4635605Snate@binkert.org memDepViolator = loadQueue[load_idx]; 4645605Snate@binkert.org 4655605Snate@binkert.org return genMachineCheckFault(); 4665605Snate@binkert.org } 4675605Snate@binkert.org 4685605Snate@binkert.org incrLdIdx(load_idx); 4695605Snate@binkert.org } 4705605Snate@binkert.org 4712SN/A // If we've reached this point, there was no violation. 4725605Snate@binkert.org memDepViolator = NULL; 4732SN/A } 4745605Snate@binkert.org 4755605Snate@binkert.org return store_fault; 4765774Snate@binkert.org} 4775774Snate@binkert.org 4785774Snate@binkert.orgtemplate <class Impl> 4795605Snate@binkert.orgvoid 4805605Snate@binkert.orgLSQUnit<Impl>::commitLoad() 4815605Snate@binkert.org{ 4825769Snate@binkert.org assert(loadQueue[loadHead]); 4835605Snate@binkert.org 4845769Snate@binkert.org DPRINTF(LSQUnit, "Committing head load instruction, PC %#x\n", 4855605Snate@binkert.org loadQueue[loadHead]->readPC()); 4865769Snate@binkert.org 4875605Snate@binkert.org loadQueue[loadHead] = NULL; 4885605Snate@binkert.org 4895605Snate@binkert.org incrLdIdx(loadHead); 4902SN/A 4912SN/A --loads; 4922SN/A} 4935605Snate@binkert.org 4942SN/Atemplate <class Impl> 4955605Snate@binkert.orgvoid 4965774Snate@binkert.orgLSQUnit<Impl>::commitLoads(InstSeqNum &youngest_inst) 4975774Snate@binkert.org{ 4985774Snate@binkert.org assert(loads == 0 || loadQueue[loadHead]); 4995605Snate@binkert.org 5005605Snate@binkert.org while (loads != 0 && loadQueue[loadHead]->seqNum <= youngest_inst) { 5015605Snate@binkert.org commitLoad(); 5025769Snate@binkert.org } 5035769Snate@binkert.org} 5045605Snate@binkert.org 5055769Snate@binkert.orgtemplate <class Impl> 5065605Snate@binkert.orgvoid 5075605Snate@binkert.orgLSQUnit<Impl>::commitStores(InstSeqNum &youngest_inst) 5085605Snate@binkert.org{ 5095605Snate@binkert.org assert(stores == 0 || storeQueue[storeHead].inst); 5102SN/A 5112SN/A int store_idx = storeHead; 5122SN/A 5135605Snate@binkert.org while (store_idx != storeTail) { 5142SN/A assert(storeQueue[store_idx].inst); 5155605Snate@binkert.org // Mark any stores that are now committed and have not yet 5165605Snate@binkert.org // been marked as able to write back. 5175774Snate@binkert.org if (!storeQueue[store_idx].canWB) { 5185774Snate@binkert.org if (storeQueue[store_idx].inst->seqNum > youngest_inst) { 5195774Snate@binkert.org break; 5205605Snate@binkert.org } 5215605Snate@binkert.org DPRINTF(LSQUnit, "Marking store as able to write back, PC " 5225605Snate@binkert.org "%#x [sn:%lli]\n", 5235605Snate@binkert.org storeQueue[store_idx].inst->readPC(), 5245605Snate@binkert.org storeQueue[store_idx].inst->seqNum); 5255605Snate@binkert.org 5265769Snate@binkert.org storeQueue[store_idx].canWB = true; 5275769Snate@binkert.org 5285605Snate@binkert.org ++storesToWB; 5295769Snate@binkert.org } 5305605Snate@binkert.org 5315769Snate@binkert.org incrStIdx(store_idx); 5325605Snate@binkert.org } 5335605Snate@binkert.org} 5345605Snate@binkert.org 5352SN/Atemplate <class Impl> 5362SN/Avoid 5375502Snate@binkert.orgLSQUnit<Impl>::writebackStores() 5385502Snate@binkert.org{ 5395502Snate@binkert.org while (storesToWB > 0 && 5405502Snate@binkert.org storeWBIdx != storeTail && 5415502Snate@binkert.org storeQueue[storeWBIdx].inst && 5425502Snate@binkert.org storeQueue[storeWBIdx].canWB && 5435502Snate@binkert.org usedPorts < cachePorts) { 5445502Snate@binkert.org 5455502Snate@binkert.org if (isStoreBlocked) { 5465502Snate@binkert.org DPRINTF(LSQUnit, "Unable to write back any more stores, cache" 5475502Snate@binkert.org " is blocked!\n"); 5485502Snate@binkert.org break; 5495502Snate@binkert.org } 5505502Snate@binkert.org 5515502Snate@binkert.org // Store didn't write any data so no need to write it back to 5525502Snate@binkert.org // memory. 5535502Snate@binkert.org if (storeQueue[storeWBIdx].size == 0) { 5545502Snate@binkert.org completeStore(storeWBIdx); 5555502Snate@binkert.org 5565502Snate@binkert.org incrStIdx(storeWBIdx); 5575502Snate@binkert.org 5585502Snate@binkert.org continue; 5595502Snate@binkert.org } 5605502Snate@binkert.org 5615502Snate@binkert.org ++usedPorts; 5625502Snate@binkert.org 5635502Snate@binkert.org if (storeQueue[storeWBIdx].inst->isDataPrefetch()) { 5645502Snate@binkert.org incrStIdx(storeWBIdx); 5655502Snate@binkert.org 5665502Snate@binkert.org continue; 5675502Snate@binkert.org } 5685502Snate@binkert.org 5695502Snate@binkert.org assert(storeQueue[storeWBIdx].req); 5705502Snate@binkert.org assert(!storeQueue[storeWBIdx].committed); 5715502Snate@binkert.org 5725502Snate@binkert.org DynInstPtr inst = storeQueue[storeWBIdx].inst; 5735502Snate@binkert.org 5745502Snate@binkert.org Request *req = storeQueue[storeWBIdx].req; 5755605Snate@binkert.org storeQueue[storeWBIdx].committed = true; 5762SN/A 5771354SN/A assert(!inst->memData); 578 inst->memData = new uint8_t[64]; 579 memcpy(inst->memData, (uint8_t *)&storeQueue[storeWBIdx].data, 580 req->getSize()); 581 582 PacketPtr data_pkt = new Packet(req, Packet::WriteReq, Packet::Broadcast); 583 data_pkt->dataStatic(inst->memData); 584 585 LSQSenderState *state = new LSQSenderState; 586 state->isLoad = false; 587 state->idx = storeWBIdx; 588 state->inst = inst; 589 data_pkt->senderState = state; 590 591 DPRINTF(LSQUnit, "D-Cache: Writing back store idx:%i PC:%#x " 592 "to Addr:%#x, data:%#x [sn:%lli]\n", 593 storeWBIdx, storeQueue[storeWBIdx].inst->readPC(), 594 req->getPaddr(), *(inst->memData), 595 storeQueue[storeWBIdx].inst->seqNum); 596 597 // @todo: Remove this SC hack once the memory system handles it. 598 if (req->getFlags() & LOCKED) { 599 if (req->getFlags() & UNCACHEABLE) { 600 req->setScResult(2); 601 } else { 602 if (cpu->lockFlag) { 603 req->setScResult(1); 604 } else { 605 req->setScResult(0); 606 // Hack: Instantly complete this store. 607 completeDataAccess(data_pkt); 608 incrStIdx(storeWBIdx); 609 continue; 610 } 611 } 612 } else { 613 // Non-store conditionals do not need a writeback. 614 state->noWB = true; 615 } 616 617 if (!dcachePort->sendTiming(data_pkt)) { 618 // Need to handle becoming blocked on a store. 619 isStoreBlocked = true; 620 621 assert(retryPkt == NULL); 622 retryPkt = data_pkt; 623 } else { 624 storePostSend(data_pkt); 625 } 626 } 627 628 // Not sure this should set it to 0. 629 usedPorts = 0; 630 631 assert(stores >= 0 && storesToWB >= 0); 632} 633 634/*template <class Impl> 635void 636LSQUnit<Impl>::removeMSHR(InstSeqNum seqNum) 637{ 638 list<InstSeqNum>::iterator mshr_it = find(mshrSeqNums.begin(), 639 mshrSeqNums.end(), 640 seqNum); 641 642 if (mshr_it != mshrSeqNums.end()) { 643 mshrSeqNums.erase(mshr_it); 644 DPRINTF(LSQUnit, "Removing MSHR. count = %i\n",mshrSeqNums.size()); 645 } 646}*/ 647 648template <class Impl> 649void 650LSQUnit<Impl>::squash(const InstSeqNum &squashed_num) 651{ 652 DPRINTF(LSQUnit, "Squashing until [sn:%lli]!" 653 "(Loads:%i Stores:%i)\n", squashed_num, loads, stores); 654 655 int load_idx = loadTail; 656 decrLdIdx(load_idx); 657 658 while (loads != 0 && loadQueue[load_idx]->seqNum > squashed_num) { 659 DPRINTF(LSQUnit,"Load Instruction PC %#x squashed, " 660 "[sn:%lli]\n", 661 loadQueue[load_idx]->readPC(), 662 loadQueue[load_idx]->seqNum); 663 664 if (isStalled() && load_idx == stallingLoadIdx) { 665 stalled = false; 666 stallingStoreIsn = 0; 667 stallingLoadIdx = 0; 668 } 669 670 // Clear the smart pointer to make sure it is decremented. 671 loadQueue[load_idx]->squashed = true; 672 loadQueue[load_idx] = NULL; 673 --loads; 674 675 // Inefficient! 676 loadTail = load_idx; 677 678 decrLdIdx(load_idx); 679 } 680 681 if (isLoadBlocked) { 682 if (squashed_num < blockedLoadSeqNum) { 683 isLoadBlocked = false; 684 loadBlockedHandled = false; 685 blockedLoadSeqNum = 0; 686 } 687 } 688 689 int store_idx = storeTail; 690 decrStIdx(store_idx); 691 692 while (stores != 0 && 693 storeQueue[store_idx].inst->seqNum > squashed_num) { 694 // Instructions marked as can WB are already committed. 695 if (storeQueue[store_idx].canWB) { 696 break; 697 } 698 699 DPRINTF(LSQUnit,"Store Instruction PC %#x squashed, " 700 "idx:%i [sn:%lli]\n", 701 storeQueue[store_idx].inst->readPC(), 702 store_idx, storeQueue[store_idx].inst->seqNum); 703 704 // I don't think this can happen. It should have been cleared 705 // by the stalling load. 706 if (isStalled() && 707 storeQueue[store_idx].inst->seqNum == stallingStoreIsn) { 708 panic("Is stalled should have been cleared by stalling load!\n"); 709 stalled = false; 710 stallingStoreIsn = 0; 711 } 712 713 // Clear the smart pointer to make sure it is decremented. 714 storeQueue[store_idx].inst->squashed = true; 715 storeQueue[store_idx].inst = NULL; 716 storeQueue[store_idx].canWB = 0; 717 718 storeQueue[store_idx].req = NULL; 719 --stores; 720 721 // Inefficient! 722 storeTail = store_idx; 723 724 decrStIdx(store_idx); 725 } 726} 727 728template <class Impl> 729void 730LSQUnit<Impl>::storePostSend(Packet *pkt) 731{ 732 if (isStalled() && 733 storeQueue[storeWBIdx].inst->seqNum == stallingStoreIsn) { 734 DPRINTF(LSQUnit, "Unstalling, stalling store [sn:%lli] " 735 "load idx:%i\n", 736 stallingStoreIsn, stallingLoadIdx); 737 stalled = false; 738 stallingStoreIsn = 0; 739 iewStage->replayMemInst(loadQueue[stallingLoadIdx]); 740 } 741 742 if (!storeQueue[storeWBIdx].inst->isStoreConditional()) { 743 // The store is basically completed at this time. This 744 // only works so long as the checker doesn't try to 745 // verify the value in memory for stores. 746 storeQueue[storeWBIdx].inst->setCompleted(); 747 if (cpu->checker) { 748 cpu->checker->tick(storeQueue[storeWBIdx].inst); 749 } 750 } 751 752 if (pkt->result != Packet::Success) { 753 DPRINTF(LSQUnit,"D-Cache Write Miss on idx:%i!\n", 754 storeWBIdx); 755 756 DPRINTF(Activity, "Active st accessing mem miss [sn:%lli]\n", 757 storeQueue[storeWBIdx].inst->seqNum); 758 759 //mshrSeqNums.push_back(storeQueue[storeWBIdx].inst->seqNum); 760 761 //DPRINTF(LSQUnit, "Added MSHR. count = %i\n",mshrSeqNums.size()); 762 763 // @todo: Increment stat here. 764 } else { 765 DPRINTF(LSQUnit,"D-Cache: Write Hit on idx:%i !\n", 766 storeWBIdx); 767 768 DPRINTF(Activity, "Active st accessing mem hit [sn:%lli]\n", 769 storeQueue[storeWBIdx].inst->seqNum); 770 } 771 772 incrStIdx(storeWBIdx); 773} 774 775template <class Impl> 776void 777LSQUnit<Impl>::writeback(DynInstPtr &inst, PacketPtr pkt) 778{ 779 iewStage->wakeCPU(); 780 781 // Squashed instructions do not need to complete their access. 782 if (inst->isSquashed()) { 783 assert(!inst->isStore()); 784 return; 785 } 786 787 if (!inst->isExecuted()) { 788 inst->setExecuted(); 789 790 // Complete access to copy data to proper place. 791 inst->completeAcc(pkt); 792 } 793 794 // Need to insert instruction into queue to commit 795 iewStage->instToCommit(inst); 796 797 iewStage->activityThisCycle(); 798} 799 800template <class Impl> 801void 802LSQUnit<Impl>::completeStore(int store_idx) 803{ 804 assert(storeQueue[store_idx].inst); 805 storeQueue[store_idx].completed = true; 806 --storesToWB; 807 // A bit conservative because a store completion may not free up entries, 808 // but hopefully avoids two store completions in one cycle from making 809 // the CPU tick twice. 810 cpu->activityThisCycle(); 811 812 if (store_idx == storeHead) { 813 do { 814 incrStIdx(storeHead); 815 816 --stores; 817 } while (storeQueue[storeHead].completed && 818 storeHead != storeTail); 819 820 iewStage->updateLSQNextCycle = true; 821 } 822 823 DPRINTF(LSQUnit, "Completing store [sn:%lli], idx:%i, store head " 824 "idx:%i\n", 825 storeQueue[store_idx].inst->seqNum, store_idx, storeHead); 826 827 if (isStalled() && 828 storeQueue[store_idx].inst->seqNum == stallingStoreIsn) { 829 DPRINTF(LSQUnit, "Unstalling, stalling store [sn:%lli] " 830 "load idx:%i\n", 831 stallingStoreIsn, stallingLoadIdx); 832 stalled = false; 833 stallingStoreIsn = 0; 834 iewStage->replayMemInst(loadQueue[stallingLoadIdx]); 835 } 836 837 storeQueue[store_idx].inst->setCompleted(); 838 839 // Tell the checker we've completed this instruction. Some stores 840 // may get reported twice to the checker, but the checker can 841 // handle that case. 842 if (cpu->checker) { 843 cpu->checker->tick(storeQueue[store_idx].inst); 844 } 845} 846 847template <class Impl> 848void 849LSQUnit<Impl>::recvRetry() 850{ 851 if (isStoreBlocked) { 852 assert(retryPkt != NULL); 853 854 if (dcachePort->sendTiming(retryPkt)) { 855 storePostSend(retryPkt); 856 retryPkt = NULL; 857 isStoreBlocked = false; 858 } else { 859 // Still blocked! 860 } 861 } else if (isLoadBlocked) { 862 DPRINTF(LSQUnit, "Loads squash themselves and all younger insts, " 863 "no need to resend packet.\n"); 864 } else { 865 DPRINTF(LSQUnit, "Retry received but LSQ is no longer blocked.\n"); 866 } 867} 868 869template <class Impl> 870inline void 871LSQUnit<Impl>::incrStIdx(int &store_idx) 872{ 873 if (++store_idx >= SQEntries) 874 store_idx = 0; 875} 876 877template <class Impl> 878inline void 879LSQUnit<Impl>::decrStIdx(int &store_idx) 880{ 881 if (--store_idx < 0) 882 store_idx += SQEntries; 883} 884 885template <class Impl> 886inline void 887LSQUnit<Impl>::incrLdIdx(int &load_idx) 888{ 889 if (++load_idx >= LQEntries) 890 load_idx = 0; 891} 892 893template <class Impl> 894inline void 895LSQUnit<Impl>::decrLdIdx(int &load_idx) 896{ 897 if (--load_idx < 0) 898 load_idx += LQEntries; 899} 900 901template <class Impl> 902void 903LSQUnit<Impl>::dumpInsts() 904{ 905 cprintf("Load store queue: Dumping instructions.\n"); 906 cprintf("Load queue size: %i\n", loads); 907 cprintf("Load queue: "); 908 909 int load_idx = loadHead; 910 911 while (load_idx != loadTail && loadQueue[load_idx]) { 912 cprintf("%#x ", loadQueue[load_idx]->readPC()); 913 914 incrLdIdx(load_idx); 915 } 916 917 cprintf("Store queue size: %i\n", stores); 918 cprintf("Store queue: "); 919 920 int store_idx = storeHead; 921 922 while (store_idx != storeTail && storeQueue[store_idx].inst) { 923 cprintf("%#x ", storeQueue[store_idx].inst->readPC()); 924 925 incrStIdx(store_idx); 926 } 927 928 cprintf("\n"); 929} 930