lsq_unit_impl.hh revision 8545
16019Shines@cs.fsu.edu/* 26019Shines@cs.fsu.edu * Copyright (c) 2010 ARM Limited 310037SARM gem5 Developers * All rights reserved 47178Sgblack@eecs.umich.edu * 57178Sgblack@eecs.umich.edu * The license below extends only to copyright in the software and shall 67178Sgblack@eecs.umich.edu * not be construed as granting a license to any other intellectual 77178Sgblack@eecs.umich.edu * property including but not limited to intellectual property relating 87178Sgblack@eecs.umich.edu * to a hardware implementation of the functionality of the software 97178Sgblack@eecs.umich.edu * licensed hereunder. You may use the software subject to the license 107178Sgblack@eecs.umich.edu * terms below provided that you ensure that this notice is replicated 117178Sgblack@eecs.umich.edu * unmodified and in its entirety in all distributions of the software, 127178Sgblack@eecs.umich.edu * modified or unmodified, in source code or in binary form. 137178Sgblack@eecs.umich.edu * 147178Sgblack@eecs.umich.edu * Copyright (c) 2004-2005 The Regents of The University of Michigan 156019Shines@cs.fsu.edu * All rights reserved. 166019Shines@cs.fsu.edu * 176019Shines@cs.fsu.edu * Redistribution and use in source and binary forms, with or without 186019Shines@cs.fsu.edu * modification, are permitted provided that the following conditions are 196019Shines@cs.fsu.edu * met: redistributions of source code must retain the above copyright 206019Shines@cs.fsu.edu * notice, this list of conditions and the following disclaimer; 216019Shines@cs.fsu.edu * redistributions in binary form must reproduce the above copyright 226019Shines@cs.fsu.edu * notice, this list of conditions and the following disclaimer in the 236019Shines@cs.fsu.edu * documentation and/or other materials provided with the distribution; 246019Shines@cs.fsu.edu * neither the name of the copyright holders nor the names of its 256019Shines@cs.fsu.edu * contributors may be used to endorse or promote products derived from 266019Shines@cs.fsu.edu * this software without specific prior written permission. 276019Shines@cs.fsu.edu * 286019Shines@cs.fsu.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 296019Shines@cs.fsu.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 306019Shines@cs.fsu.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 316019Shines@cs.fsu.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 326019Shines@cs.fsu.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 336019Shines@cs.fsu.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 346019Shines@cs.fsu.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 356019Shines@cs.fsu.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 366019Shines@cs.fsu.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 376019Shines@cs.fsu.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 386019Shines@cs.fsu.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 396019Shines@cs.fsu.edu * 406019Shines@cs.fsu.edu * Authors: Kevin Lim 416019Shines@cs.fsu.edu * Korey Sewell 426019Shines@cs.fsu.edu */ 436019Shines@cs.fsu.edu 446019Shines@cs.fsu.edu#include "arch/locked_mem.hh" 456019Shines@cs.fsu.edu#include "base/str.hh" 466019Shines@cs.fsu.edu#include "config/the_isa.hh" 476019Shines@cs.fsu.edu#include "config/use_checker.hh" 487639Sgblack@eecs.umich.edu#include "cpu/o3/lsq.hh" 497639Sgblack@eecs.umich.edu#include "cpu/o3/lsq_unit.hh" 507639Sgblack@eecs.umich.edu#include "debug/Activity.hh" 517639Sgblack@eecs.umich.edu#include "debug/IEW.hh" 527639Sgblack@eecs.umich.edu#include "debug/LSQUnit.hh" 537639Sgblack@eecs.umich.edu#include "mem/packet.hh" 547639Sgblack@eecs.umich.edu#include "mem/request.hh" 557639Sgblack@eecs.umich.edu 567639Sgblack@eecs.umich.edu#if USE_CHECKER 577639Sgblack@eecs.umich.edu#include "cpu/checker/cpu.hh" 587639Sgblack@eecs.umich.edu#endif 597639Sgblack@eecs.umich.edu 607639Sgblack@eecs.umich.edutemplate<class Impl> 617639Sgblack@eecs.umich.eduLSQUnit<Impl>::WritebackEvent::WritebackEvent(DynInstPtr &_inst, PacketPtr _pkt, 627639Sgblack@eecs.umich.edu LSQUnit *lsq_ptr) 637639Sgblack@eecs.umich.edu : inst(_inst), pkt(_pkt), lsqPtr(lsq_ptr) 647639Sgblack@eecs.umich.edu{ 657639Sgblack@eecs.umich.edu this->setFlags(Event::AutoDelete); 667639Sgblack@eecs.umich.edu} 677639Sgblack@eecs.umich.edu 687639Sgblack@eecs.umich.edutemplate<class Impl> 697639Sgblack@eecs.umich.eduvoid 707639Sgblack@eecs.umich.eduLSQUnit<Impl>::WritebackEvent::process() 717639Sgblack@eecs.umich.edu{ 727639Sgblack@eecs.umich.edu if (!lsqPtr->isSwitchedOut()) { 737639Sgblack@eecs.umich.edu lsqPtr->writeback(inst, pkt); 747639Sgblack@eecs.umich.edu } 757639Sgblack@eecs.umich.edu 767639Sgblack@eecs.umich.edu if (pkt->senderState) 777639Sgblack@eecs.umich.edu delete pkt->senderState; 787639Sgblack@eecs.umich.edu 797639Sgblack@eecs.umich.edu delete pkt->req; 807639Sgblack@eecs.umich.edu delete pkt; 817639Sgblack@eecs.umich.edu} 827639Sgblack@eecs.umich.edu 837639Sgblack@eecs.umich.edutemplate<class Impl> 847639Sgblack@eecs.umich.educonst char * 857639Sgblack@eecs.umich.eduLSQUnit<Impl>::WritebackEvent::description() const 867639Sgblack@eecs.umich.edu{ 877639Sgblack@eecs.umich.edu return "Store writeback"; 887639Sgblack@eecs.umich.edu} 897639Sgblack@eecs.umich.edu 907639Sgblack@eecs.umich.edutemplate<class Impl> 917639Sgblack@eecs.umich.eduvoid 927639Sgblack@eecs.umich.eduLSQUnit<Impl>::completeDataAccess(PacketPtr pkt) 937639Sgblack@eecs.umich.edu{ 947356Sgblack@eecs.umich.edu LSQSenderState *state = dynamic_cast<LSQSenderState *>(pkt->senderState); 957356Sgblack@eecs.umich.edu DynInstPtr inst = state->inst; 967356Sgblack@eecs.umich.edu DPRINTF(IEW, "Writeback event [sn:%lli].\n", inst->seqNum); 977435Sgblack@eecs.umich.edu DPRINTF(Activity, "Activity: Writeback event [sn:%lli].\n", inst->seqNum); 987435Sgblack@eecs.umich.edu 997435Sgblack@eecs.umich.edu //iewStage->ldstQueue.removeMSHR(inst->threadNumber,inst->seqNum); 1007435Sgblack@eecs.umich.edu 1017435Sgblack@eecs.umich.edu assert(!pkt->wasNacked()); 1027435Sgblack@eecs.umich.edu 1037435Sgblack@eecs.umich.edu // If this is a split access, wait until all packets are received. 1047435Sgblack@eecs.umich.edu if (TheISA::HasUnalignedMemAcc && !state->complete()) { 1057435Sgblack@eecs.umich.edu delete pkt->req; 1067435Sgblack@eecs.umich.edu delete pkt; 1077435Sgblack@eecs.umich.edu return; 1087639Sgblack@eecs.umich.edu } 1097639Sgblack@eecs.umich.edu 1107639Sgblack@eecs.umich.edu if (isSwitchedOut() || inst->isSquashed()) { 1117435Sgblack@eecs.umich.edu iewStage->decrWb(inst->seqNum); 1127639Sgblack@eecs.umich.edu } else { 1137639Sgblack@eecs.umich.edu if (!state->noWB) { 1147639Sgblack@eecs.umich.edu if (!TheISA::HasUnalignedMemAcc || !state->isSplit || 1157639Sgblack@eecs.umich.edu !state->isLoad) { 1167639Sgblack@eecs.umich.edu writeback(inst, pkt); 1177639Sgblack@eecs.umich.edu } else { 1187639Sgblack@eecs.umich.edu writeback(inst, state->mainPkt); 1197639Sgblack@eecs.umich.edu } 1207639Sgblack@eecs.umich.edu } 1217639Sgblack@eecs.umich.edu 1227639Sgblack@eecs.umich.edu if (inst->isStore()) { 1237639Sgblack@eecs.umich.edu completeStore(state->idx); 1247639Sgblack@eecs.umich.edu } 1257639Sgblack@eecs.umich.edu } 1267639Sgblack@eecs.umich.edu 1277639Sgblack@eecs.umich.edu if (TheISA::HasUnalignedMemAcc && state->isSplit && state->isLoad) { 1287639Sgblack@eecs.umich.edu delete state->mainPkt->req; 1297639Sgblack@eecs.umich.edu delete state->mainPkt; 1307639Sgblack@eecs.umich.edu } 1317639Sgblack@eecs.umich.edu delete state; 1327639Sgblack@eecs.umich.edu delete pkt->req; 1337639Sgblack@eecs.umich.edu delete pkt; 1347639Sgblack@eecs.umich.edu} 1357639Sgblack@eecs.umich.edu 1367639Sgblack@eecs.umich.edutemplate <class Impl> 1377639Sgblack@eecs.umich.eduLSQUnit<Impl>::LSQUnit() 1387639Sgblack@eecs.umich.edu : loads(0), stores(0), storesToWB(0), cacheBlockMask(0), stalled(false), 1397639Sgblack@eecs.umich.edu isStoreBlocked(false), isLoadBlocked(false), 1407639Sgblack@eecs.umich.edu loadBlockedHandled(false), hasPendingPkt(false) 1417639Sgblack@eecs.umich.edu{ 1427639Sgblack@eecs.umich.edu} 1437639Sgblack@eecs.umich.edu 1447639Sgblack@eecs.umich.edutemplate<class Impl> 1457639Sgblack@eecs.umich.eduvoid 1468144SAli.Saidi@ARM.comLSQUnit<Impl>::init(O3CPU *cpu_ptr, IEW *iew_ptr, DerivO3CPUParams *params, 1477639Sgblack@eecs.umich.edu LSQ *lsq_ptr, unsigned maxLQEntries, unsigned maxSQEntries, 1487639Sgblack@eecs.umich.edu unsigned id) 1497639Sgblack@eecs.umich.edu{ 1507639Sgblack@eecs.umich.edu cpu = cpu_ptr; 1517639Sgblack@eecs.umich.edu iewStage = iew_ptr; 1527639Sgblack@eecs.umich.edu 1537639Sgblack@eecs.umich.edu DPRINTF(LSQUnit, "Creating LSQUnit%i object.\n",id); 15410037SARM gem5 Developers 1557639Sgblack@eecs.umich.edu switchedOut = false; 1567639Sgblack@eecs.umich.edu 1577639Sgblack@eecs.umich.edu cacheBlockMask = 0; 1587639Sgblack@eecs.umich.edu 1597639Sgblack@eecs.umich.edu lsq = lsq_ptr; 1607639Sgblack@eecs.umich.edu 1617639Sgblack@eecs.umich.edu lsqID = id; 1627639Sgblack@eecs.umich.edu 1637639Sgblack@eecs.umich.edu // Add 1 for the sentinel entry (they are circular queues). 1647639Sgblack@eecs.umich.edu LQEntries = maxLQEntries + 1; 1657639Sgblack@eecs.umich.edu SQEntries = maxSQEntries + 1; 16610037SARM gem5 Developers 1677639Sgblack@eecs.umich.edu loadQueue.resize(LQEntries); 1687639Sgblack@eecs.umich.edu storeQueue.resize(SQEntries); 1697639Sgblack@eecs.umich.edu 1707639Sgblack@eecs.umich.edu depCheckShift = params->LSQDepCheckShift; 1717639Sgblack@eecs.umich.edu checkLoads = params->LSQCheckLoads; 1727639Sgblack@eecs.umich.edu 1737639Sgblack@eecs.umich.edu loadHead = loadTail = 0; 1747639Sgblack@eecs.umich.edu 17510037SARM gem5 Developers storeHead = storeWBIdx = storeTail = 0; 1767639Sgblack@eecs.umich.edu 1777639Sgblack@eecs.umich.edu usedPorts = 0; 17810037SARM gem5 Developers cachePorts = params->cachePorts; 1797639Sgblack@eecs.umich.edu 1807639Sgblack@eecs.umich.edu retryPkt = NULL; 18110037SARM gem5 Developers memDepViolator = NULL; 1827591SAli.Saidi@ARM.com 1837639Sgblack@eecs.umich.edu blockedLoadSeqNum = 0; 1847435Sgblack@eecs.umich.edu} 1857435Sgblack@eecs.umich.edu 1867639Sgblack@eecs.umich.edutemplate<class Impl> 18710037SARM gem5 Developersstd::string 1887639Sgblack@eecs.umich.eduLSQUnit<Impl>::name() const 1897639Sgblack@eecs.umich.edu{ 1907639Sgblack@eecs.umich.edu if (Impl::MaxThreads == 1) { 1917639Sgblack@eecs.umich.edu return iewStage->name() + ".lsq"; 1927639Sgblack@eecs.umich.edu } else { 1937639Sgblack@eecs.umich.edu return iewStage->name() + ".lsq.thread" + to_string(lsqID); 1947639Sgblack@eecs.umich.edu } 1957639Sgblack@eecs.umich.edu} 1967639Sgblack@eecs.umich.edu 1977639Sgblack@eecs.umich.edutemplate<class Impl> 1987639Sgblack@eecs.umich.eduvoid 1997639Sgblack@eecs.umich.eduLSQUnit<Impl>::regStats() 2007639Sgblack@eecs.umich.edu{ 2017639Sgblack@eecs.umich.edu lsqForwLoads 2027639Sgblack@eecs.umich.edu .name(name() + ".forwLoads") 2037639Sgblack@eecs.umich.edu .desc("Number of loads that had data forwarded from stores"); 2047639Sgblack@eecs.umich.edu 2057639Sgblack@eecs.umich.edu invAddrLoads 2067639Sgblack@eecs.umich.edu .name(name() + ".invAddrLoads") 2077639Sgblack@eecs.umich.edu .desc("Number of loads ignored due to an invalid address"); 2087639Sgblack@eecs.umich.edu 2097639Sgblack@eecs.umich.edu lsqSquashedLoads 2107639Sgblack@eecs.umich.edu .name(name() + ".squashedLoads") 2117639Sgblack@eecs.umich.edu .desc("Number of loads squashed"); 2127639Sgblack@eecs.umich.edu 2137639Sgblack@eecs.umich.edu lsqIgnoredResponses 2147639Sgblack@eecs.umich.edu .name(name() + ".ignoredResponses") 2157639Sgblack@eecs.umich.edu .desc("Number of memory responses ignored because the instruction is squashed"); 2167639Sgblack@eecs.umich.edu 2177639Sgblack@eecs.umich.edu lsqMemOrderViolation 2187639Sgblack@eecs.umich.edu .name(name() + ".memOrderViolation") 2197639Sgblack@eecs.umich.edu .desc("Number of memory ordering violations"); 22010037SARM gem5 Developers 2217591SAli.Saidi@ARM.com lsqSquashedStores 2227591SAli.Saidi@ARM.com .name(name() + ".squashedStores") 2237639Sgblack@eecs.umich.edu .desc("Number of stores squashed"); 2247639Sgblack@eecs.umich.edu 2257639Sgblack@eecs.umich.edu invAddrSwpfs 22610037SARM gem5 Developers .name(name() + ".invAddrSwpfs") 2277639Sgblack@eecs.umich.edu .desc("Number of software prefetches ignored due to an invalid address"); 2287639Sgblack@eecs.umich.edu 2297639Sgblack@eecs.umich.edu lsqBlockedLoads 2307639Sgblack@eecs.umich.edu .name(name() + ".blockedLoads") 2317639Sgblack@eecs.umich.edu .desc("Number of blocked loads due to partial load-store forwarding"); 2327639Sgblack@eecs.umich.edu 2337639Sgblack@eecs.umich.edu lsqRescheduledLoads 2347639Sgblack@eecs.umich.edu .name(name() + ".rescheduledLoads") 23510037SARM gem5 Developers .desc("Number of loads that were rescheduled"); 2367639Sgblack@eecs.umich.edu 2377639Sgblack@eecs.umich.edu lsqCacheBlocked 2387639Sgblack@eecs.umich.edu .name(name() + ".cacheBlocked") 23910037SARM gem5 Developers .desc("Number of times an access to memory failed due to the cache being blocked"); 2407639Sgblack@eecs.umich.edu} 2417639Sgblack@eecs.umich.edu 2427639Sgblack@eecs.umich.edutemplate<class Impl> 2437435Sgblack@eecs.umich.eduvoid 2447435Sgblack@eecs.umich.eduLSQUnit<Impl>::setDcachePort(Port *dcache_port) 2457639Sgblack@eecs.umich.edu{ 2467639Sgblack@eecs.umich.edu dcachePort = dcache_port; 2477639Sgblack@eecs.umich.edu 2487639Sgblack@eecs.umich.edu#if USE_CHECKER 2497639Sgblack@eecs.umich.edu if (cpu->checker) { 2507639Sgblack@eecs.umich.edu cpu->checker->setDcachePort(dcachePort); 2517639Sgblack@eecs.umich.edu } 2527639Sgblack@eecs.umich.edu#endif 25310037SARM gem5 Developers} 2547639Sgblack@eecs.umich.edu 25510037SARM gem5 Developerstemplate<class Impl> 2567639Sgblack@eecs.umich.eduvoid 2577639Sgblack@eecs.umich.eduLSQUnit<Impl>::clearLQ() 2587639Sgblack@eecs.umich.edu{ 2597639Sgblack@eecs.umich.edu loadQueue.clear(); 2607639Sgblack@eecs.umich.edu} 2617639Sgblack@eecs.umich.edu 2627639Sgblack@eecs.umich.edutemplate<class Impl> 2637639Sgblack@eecs.umich.eduvoid 2647639Sgblack@eecs.umich.eduLSQUnit<Impl>::clearSQ() 2657639Sgblack@eecs.umich.edu{ 2667639Sgblack@eecs.umich.edu storeQueue.clear(); 2677639Sgblack@eecs.umich.edu} 2687639Sgblack@eecs.umich.edu 2697639Sgblack@eecs.umich.edutemplate<class Impl> 2707639Sgblack@eecs.umich.eduvoid 2717639Sgblack@eecs.umich.eduLSQUnit<Impl>::switchOut() 2727639Sgblack@eecs.umich.edu{ 2737639Sgblack@eecs.umich.edu switchedOut = true; 2747639Sgblack@eecs.umich.edu for (int i = 0; i < loadQueue.size(); ++i) { 2757639Sgblack@eecs.umich.edu assert(!loadQueue[i]); 2767639Sgblack@eecs.umich.edu loadQueue[i] = NULL; 2777639Sgblack@eecs.umich.edu } 2787639Sgblack@eecs.umich.edu 2797639Sgblack@eecs.umich.edu assert(storesToWB == 0); 2807639Sgblack@eecs.umich.edu} 2817639Sgblack@eecs.umich.edu 2827639Sgblack@eecs.umich.edutemplate<class Impl> 2837639Sgblack@eecs.umich.eduvoid 2847639Sgblack@eecs.umich.eduLSQUnit<Impl>::takeOverFrom() 2857639Sgblack@eecs.umich.edu{ 2867639Sgblack@eecs.umich.edu switchedOut = false; 2877639Sgblack@eecs.umich.edu loads = stores = storesToWB = 0; 2887639Sgblack@eecs.umich.edu 2897639Sgblack@eecs.umich.edu loadHead = loadTail = 0; 2907639Sgblack@eecs.umich.edu 2917639Sgblack@eecs.umich.edu storeHead = storeWBIdx = storeTail = 0; 2927639Sgblack@eecs.umich.edu 2937639Sgblack@eecs.umich.edu usedPorts = 0; 2947639Sgblack@eecs.umich.edu 2957639Sgblack@eecs.umich.edu memDepViolator = NULL; 2967639Sgblack@eecs.umich.edu 2977639Sgblack@eecs.umich.edu blockedLoadSeqNum = 0; 2987639Sgblack@eecs.umich.edu 2997639Sgblack@eecs.umich.edu stalled = false; 3007639Sgblack@eecs.umich.edu isLoadBlocked = false; 3017639Sgblack@eecs.umich.edu loadBlockedHandled = false; 3027639Sgblack@eecs.umich.edu 3037639Sgblack@eecs.umich.edu // Just incase the memory system changed out from under us 3047639Sgblack@eecs.umich.edu cacheBlockMask = 0; 3057639Sgblack@eecs.umich.edu} 3067639Sgblack@eecs.umich.edu 3077639Sgblack@eecs.umich.edutemplate<class Impl> 3087639Sgblack@eecs.umich.eduvoid 3097639Sgblack@eecs.umich.eduLSQUnit<Impl>::resizeLQ(unsigned size) 3107639Sgblack@eecs.umich.edu{ 3117639Sgblack@eecs.umich.edu unsigned size_plus_sentinel = size + 1; 3127639Sgblack@eecs.umich.edu assert(size_plus_sentinel >= LQEntries); 3137639Sgblack@eecs.umich.edu 3147639Sgblack@eecs.umich.edu if (size_plus_sentinel > LQEntries) { 3157639Sgblack@eecs.umich.edu while (size_plus_sentinel > loadQueue.size()) { 3167639Sgblack@eecs.umich.edu DynInstPtr dummy; 3177639Sgblack@eecs.umich.edu loadQueue.push_back(dummy); 3187639Sgblack@eecs.umich.edu LQEntries++; 3197639Sgblack@eecs.umich.edu } 3207639Sgblack@eecs.umich.edu } else { 3217435Sgblack@eecs.umich.edu LQEntries = size_plus_sentinel; 3227435Sgblack@eecs.umich.edu } 3237639Sgblack@eecs.umich.edu 3247639Sgblack@eecs.umich.edu} 3257639Sgblack@eecs.umich.edu 3267591SAli.Saidi@ARM.comtemplate<class Impl> 3277639Sgblack@eecs.umich.eduvoid 3287639Sgblack@eecs.umich.eduLSQUnit<Impl>::resizeSQ(unsigned size) 3297435Sgblack@eecs.umich.edu{ 3307435Sgblack@eecs.umich.edu unsigned size_plus_sentinel = size + 1; 3317639Sgblack@eecs.umich.edu if (size_plus_sentinel > SQEntries) { 3327639Sgblack@eecs.umich.edu while (size_plus_sentinel > storeQueue.size()) { 3337435Sgblack@eecs.umich.edu SQEntry dummy; 3347435Sgblack@eecs.umich.edu storeQueue.push_back(dummy); 3357591SAli.Saidi@ARM.com SQEntries++; 3367435Sgblack@eecs.umich.edu } 3377435Sgblack@eecs.umich.edu } else { 3387435Sgblack@eecs.umich.edu SQEntries = size_plus_sentinel; 3397435Sgblack@eecs.umich.edu } 3407435Sgblack@eecs.umich.edu} 3417435Sgblack@eecs.umich.edu 3427435Sgblack@eecs.umich.edutemplate <class Impl> 3437435Sgblack@eecs.umich.eduvoid 3447435Sgblack@eecs.umich.eduLSQUnit<Impl>::insert(DynInstPtr &inst) 3457435Sgblack@eecs.umich.edu{ 3467435Sgblack@eecs.umich.edu assert(inst->isMemRef()); 3477639Sgblack@eecs.umich.edu 3487639Sgblack@eecs.umich.edu assert(inst->isLoad() || inst->isStore()); 3497639Sgblack@eecs.umich.edu 3507639Sgblack@eecs.umich.edu if (inst->isLoad()) { 3517639Sgblack@eecs.umich.edu insertLoad(inst); 3527639Sgblack@eecs.umich.edu } else { 3537639Sgblack@eecs.umich.edu insertStore(inst); 3547639Sgblack@eecs.umich.edu } 3557639Sgblack@eecs.umich.edu 3567639Sgblack@eecs.umich.edu inst->setInLSQ(); 3577639Sgblack@eecs.umich.edu} 3587639Sgblack@eecs.umich.edu 3597639Sgblack@eecs.umich.edutemplate <class Impl> 3607435Sgblack@eecs.umich.eduvoid 3617435Sgblack@eecs.umich.eduLSQUnit<Impl>::insertLoad(DynInstPtr &load_inst) 3627435Sgblack@eecs.umich.edu{ 3637639Sgblack@eecs.umich.edu assert((loadTail + 1) % LQEntries != loadHead); 3647639Sgblack@eecs.umich.edu assert(loads < LQEntries); 3657639Sgblack@eecs.umich.edu 3667435Sgblack@eecs.umich.edu DPRINTF(LSQUnit, "Inserting load PC %s, idx:%i [sn:%lli]\n", 3677639Sgblack@eecs.umich.edu load_inst->pcState(), loadTail, load_inst->seqNum); 3687639Sgblack@eecs.umich.edu 3697435Sgblack@eecs.umich.edu load_inst->lqIdx = loadTail; 3707435Sgblack@eecs.umich.edu 3717639Sgblack@eecs.umich.edu if (stores == 0) { 3727639Sgblack@eecs.umich.edu load_inst->sqIdx = -1; 3737639Sgblack@eecs.umich.edu } else { 3747639Sgblack@eecs.umich.edu load_inst->sqIdx = storeTail; 3757435Sgblack@eecs.umich.edu } 3767435Sgblack@eecs.umich.edu 3777435Sgblack@eecs.umich.edu loadQueue[loadTail] = load_inst; 3787639Sgblack@eecs.umich.edu 3797639Sgblack@eecs.umich.edu incrLdIdx(loadTail); 3807435Sgblack@eecs.umich.edu 3817435Sgblack@eecs.umich.edu ++loads; 3827435Sgblack@eecs.umich.edu} 3837435Sgblack@eecs.umich.edu 3847639Sgblack@eecs.umich.edutemplate <class Impl> 3857639Sgblack@eecs.umich.eduvoid 3867639Sgblack@eecs.umich.eduLSQUnit<Impl>::insertStore(DynInstPtr &store_inst) 3877639Sgblack@eecs.umich.edu{ 3887639Sgblack@eecs.umich.edu // Make sure it is not full before inserting an instruction. 3897435Sgblack@eecs.umich.edu assert((storeTail + 1) % SQEntries != storeHead); 3907639Sgblack@eecs.umich.edu assert(stores < SQEntries); 3917639Sgblack@eecs.umich.edu 3927639Sgblack@eecs.umich.edu DPRINTF(LSQUnit, "Inserting store PC %s, idx:%i [sn:%lli]\n", 3937639Sgblack@eecs.umich.edu store_inst->pcState(), storeTail, store_inst->seqNum); 3947639Sgblack@eecs.umich.edu 3957435Sgblack@eecs.umich.edu store_inst->sqIdx = storeTail; 3967639Sgblack@eecs.umich.edu store_inst->lqIdx = loadTail; 3977639Sgblack@eecs.umich.edu 3987639Sgblack@eecs.umich.edu storeQueue[storeTail] = SQEntry(store_inst); 3997639Sgblack@eecs.umich.edu 4007639Sgblack@eecs.umich.edu incrStIdx(storeTail); 4017435Sgblack@eecs.umich.edu 4027639Sgblack@eecs.umich.edu ++stores; 4037639Sgblack@eecs.umich.edu} 4047639Sgblack@eecs.umich.edu 4057639Sgblack@eecs.umich.edutemplate <class Impl> 4067639Sgblack@eecs.umich.edutypename Impl::DynInstPtr 4077435Sgblack@eecs.umich.eduLSQUnit<Impl>::getMemDepViolator() 4087435Sgblack@eecs.umich.edu{ 4097435Sgblack@eecs.umich.edu DynInstPtr temp = memDepViolator; 4107435Sgblack@eecs.umich.edu 4117639Sgblack@eecs.umich.edu memDepViolator = NULL; 4127639Sgblack@eecs.umich.edu 4137639Sgblack@eecs.umich.edu return temp; 4147639Sgblack@eecs.umich.edu} 4157639Sgblack@eecs.umich.edu 4167435Sgblack@eecs.umich.edutemplate <class Impl> 4177639Sgblack@eecs.umich.eduunsigned 4187639Sgblack@eecs.umich.eduLSQUnit<Impl>::numFreeEntries() 4197639Sgblack@eecs.umich.edu{ 4207639Sgblack@eecs.umich.edu unsigned free_lq_entries = LQEntries - loads; 4217639Sgblack@eecs.umich.edu unsigned free_sq_entries = SQEntries - stores; 4227435Sgblack@eecs.umich.edu 4237639Sgblack@eecs.umich.edu // Both the LQ and SQ entries have an extra dummy entry to differentiate 4247639Sgblack@eecs.umich.edu // empty/full conditions. Subtract 1 from the free entries. 4257639Sgblack@eecs.umich.edu if (free_lq_entries < free_sq_entries) { 4267639Sgblack@eecs.umich.edu return free_lq_entries - 1; 4277435Sgblack@eecs.umich.edu } else { 4287639Sgblack@eecs.umich.edu return free_sq_entries - 1; 4297639Sgblack@eecs.umich.edu } 4307639Sgblack@eecs.umich.edu} 4317639Sgblack@eecs.umich.edu 4327639Sgblack@eecs.umich.edutemplate <class Impl> 4337639Sgblack@eecs.umich.eduint 4347639Sgblack@eecs.umich.eduLSQUnit<Impl>::numLoadsReady() 4357639Sgblack@eecs.umich.edu{ 4367639Sgblack@eecs.umich.edu int load_idx = loadHead; 4377639Sgblack@eecs.umich.edu int retval = 0; 4387435Sgblack@eecs.umich.edu 4397435Sgblack@eecs.umich.edu while (load_idx != loadTail) { 4407435Sgblack@eecs.umich.edu assert(loadQueue[load_idx]); 4417639Sgblack@eecs.umich.edu 4427639Sgblack@eecs.umich.edu if (loadQueue[load_idx]->readyToIssue()) { 4437639Sgblack@eecs.umich.edu ++retval; 4447639Sgblack@eecs.umich.edu } 4457639Sgblack@eecs.umich.edu } 4467639Sgblack@eecs.umich.edu 4477639Sgblack@eecs.umich.edu return retval; 4487435Sgblack@eecs.umich.edu} 4497435Sgblack@eecs.umich.edu 4507435Sgblack@eecs.umich.edutemplate <class Impl> 4517435Sgblack@eecs.umich.eduvoid 4527435Sgblack@eecs.umich.eduLSQUnit<Impl>::checkSnoop(PacketPtr pkt) 4537639Sgblack@eecs.umich.edu{ 4547639Sgblack@eecs.umich.edu int load_idx = loadHead; 4557639Sgblack@eecs.umich.edu 4567639Sgblack@eecs.umich.edu if (!cacheBlockMask) { 4577639Sgblack@eecs.umich.edu assert(dcachePort); 4587639Sgblack@eecs.umich.edu Addr bs = dcachePort->peerBlockSize(); 4597639Sgblack@eecs.umich.edu 4607435Sgblack@eecs.umich.edu // Make sure we actually got a size 4617639Sgblack@eecs.umich.edu assert(bs != 0); 4627639Sgblack@eecs.umich.edu 4637639Sgblack@eecs.umich.edu cacheBlockMask = ~(bs - 1); 4647639Sgblack@eecs.umich.edu } 4657435Sgblack@eecs.umich.edu 4667435Sgblack@eecs.umich.edu // If this is the only load in the LSQ we don't care 4677435Sgblack@eecs.umich.edu if (load_idx == loadTail) 4687639Sgblack@eecs.umich.edu return; 4697639Sgblack@eecs.umich.edu incrLdIdx(load_idx); 4707435Sgblack@eecs.umich.edu 4717639Sgblack@eecs.umich.edu DPRINTF(LSQUnit, "Got snoop for address %#x\n", pkt->getAddr()); 4727639Sgblack@eecs.umich.edu Addr invalidate_addr = pkt->getAddr() & cacheBlockMask; 4737435Sgblack@eecs.umich.edu while (load_idx != loadTail) { 4747435Sgblack@eecs.umich.edu DynInstPtr ld_inst = loadQueue[load_idx]; 4757435Sgblack@eecs.umich.edu 4767639Sgblack@eecs.umich.edu if (!ld_inst->effAddrValid || ld_inst->uncacheable()) { 4777639Sgblack@eecs.umich.edu incrLdIdx(load_idx); 4787639Sgblack@eecs.umich.edu continue; 4797639Sgblack@eecs.umich.edu } 4807639Sgblack@eecs.umich.edu 4817639Sgblack@eecs.umich.edu Addr load_addr = ld_inst->physEffAddr & cacheBlockMask; 4827639Sgblack@eecs.umich.edu DPRINTF(LSQUnit, "-- inst [sn:%lli] load_addr: %#x to pktAddr:%#x\n", 4837435Sgblack@eecs.umich.edu ld_inst->seqNum, load_addr, invalidate_addr); 4847639Sgblack@eecs.umich.edu 4857639Sgblack@eecs.umich.edu if (load_addr == invalidate_addr) { 4867435Sgblack@eecs.umich.edu if (ld_inst->possibleLoadViolation) { 4877435Sgblack@eecs.umich.edu DPRINTF(LSQUnit, "Conflicting load at addr %#x [sn:%lli]\n", 4887435Sgblack@eecs.umich.edu ld_inst->physEffAddr, pkt->getAddr(), ld_inst->seqNum); 4897639Sgblack@eecs.umich.edu 4907639Sgblack@eecs.umich.edu // Mark the load for re-execution 4917639Sgblack@eecs.umich.edu ld_inst->fault = new ReExec; 4927639Sgblack@eecs.umich.edu } else { 4937639Sgblack@eecs.umich.edu // If a older load checks this and it's true 4947639Sgblack@eecs.umich.edu // then we might have missed the snoop 4957639Sgblack@eecs.umich.edu // in which case we need to invalidate to be sure 4967435Sgblack@eecs.umich.edu ld_inst->hitExternalSnoop = true; 4977639Sgblack@eecs.umich.edu } 4987639Sgblack@eecs.umich.edu } 4997435Sgblack@eecs.umich.edu incrLdIdx(load_idx); 5007435Sgblack@eecs.umich.edu } 5017435Sgblack@eecs.umich.edu return; 5027639Sgblack@eecs.umich.edu} 5037639Sgblack@eecs.umich.edu 5047435Sgblack@eecs.umich.edutemplate <class Impl> 5057639Sgblack@eecs.umich.eduFault 5067639Sgblack@eecs.umich.eduLSQUnit<Impl>::checkViolations(int load_idx, DynInstPtr &inst) 5077435Sgblack@eecs.umich.edu{ 5087435Sgblack@eecs.umich.edu Addr inst_eff_addr1 = inst->effAddr >> depCheckShift; 5097435Sgblack@eecs.umich.edu Addr inst_eff_addr2 = (inst->effAddr + inst->effSize - 1) >> depCheckShift; 5107639Sgblack@eecs.umich.edu 5117639Sgblack@eecs.umich.edu /** @todo in theory you only need to check an instruction that has executed 5127435Sgblack@eecs.umich.edu * however, there isn't a good way in the pipeline at the moment to check 5137435Sgblack@eecs.umich.edu * all instructions that will execute before the store writes back. Thus, 5147639Sgblack@eecs.umich.edu * like the implementation that came before it, we're overly conservative. 5157435Sgblack@eecs.umich.edu */ 5167435Sgblack@eecs.umich.edu while (load_idx != loadTail) { 5177639Sgblack@eecs.umich.edu DynInstPtr ld_inst = loadQueue[load_idx]; 5187639Sgblack@eecs.umich.edu if (!ld_inst->effAddrValid || ld_inst->uncacheable()) { 5197435Sgblack@eecs.umich.edu incrLdIdx(load_idx); 5207435Sgblack@eecs.umich.edu continue; 5217639Sgblack@eecs.umich.edu } 5227639Sgblack@eecs.umich.edu 5237435Sgblack@eecs.umich.edu Addr ld_eff_addr1 = ld_inst->effAddr >> depCheckShift; 5247435Sgblack@eecs.umich.edu Addr ld_eff_addr2 = 5257435Sgblack@eecs.umich.edu (ld_inst->effAddr + ld_inst->effSize - 1) >> depCheckShift; 5267435Sgblack@eecs.umich.edu 5277435Sgblack@eecs.umich.edu if (inst_eff_addr2 >= ld_eff_addr1 && inst_eff_addr1 <= ld_eff_addr2) { 5287639Sgblack@eecs.umich.edu if (inst->isLoad()) { 5297639Sgblack@eecs.umich.edu // If this load is to the same block as an external snoop 5307435Sgblack@eecs.umich.edu // invalidate that we've observed then the load needs to be 5317639Sgblack@eecs.umich.edu // squashed as it could have newer data 5327639Sgblack@eecs.umich.edu if (ld_inst->hitExternalSnoop) { 5337435Sgblack@eecs.umich.edu if (!memDepViolator || 5347435Sgblack@eecs.umich.edu ld_inst->seqNum < memDepViolator->seqNum) { 5357435Sgblack@eecs.umich.edu DPRINTF(LSQUnit, "Detected fault with inst [sn:%lli] " 5367639Sgblack@eecs.umich.edu " and [sn:%lli] at address %#x\n", inst->seqNum, 5377639Sgblack@eecs.umich.edu ld_inst->seqNum, ld_eff_addr1); 5387435Sgblack@eecs.umich.edu memDepViolator = ld_inst; 5397639Sgblack@eecs.umich.edu 5407639Sgblack@eecs.umich.edu ++lsqMemOrderViolation; 5417435Sgblack@eecs.umich.edu 5427435Sgblack@eecs.umich.edu return TheISA::genMachineCheckFault(); 5437435Sgblack@eecs.umich.edu } 5447435Sgblack@eecs.umich.edu } 5457435Sgblack@eecs.umich.edu 5467639Sgblack@eecs.umich.edu // Otherwise, mark the load has a possible load violation 5477639Sgblack@eecs.umich.edu // and if we see a snoop before it's commited, we need to squash 5487435Sgblack@eecs.umich.edu ld_inst->possibleLoadViolation = true; 5497639Sgblack@eecs.umich.edu DPRINTF(LSQUnit, "Found possible load violaiton at addr: %#x" 5507639Sgblack@eecs.umich.edu " between instructions [sn:%lli] and [sn:%lli]\n", 5517435Sgblack@eecs.umich.edu inst_eff_addr1, inst->seqNum, ld_inst->seqNum); 5527435Sgblack@eecs.umich.edu } else { 5537435Sgblack@eecs.umich.edu // A load/store incorrectly passed this store. 5547639Sgblack@eecs.umich.edu // Check if we already have a violator, or if it's newer 5557639Sgblack@eecs.umich.edu // squash and refetch. 5567435Sgblack@eecs.umich.edu if (memDepViolator && ld_inst->seqNum > memDepViolator->seqNum) 5577639Sgblack@eecs.umich.edu break; 5587639Sgblack@eecs.umich.edu 5597435Sgblack@eecs.umich.edu DPRINTF(LSQUnit, "Detected fault with inst [sn:%lli] and [sn:%lli]" 5607435Sgblack@eecs.umich.edu " at address %#x\n", inst->seqNum, ld_inst->seqNum, 5617435Sgblack@eecs.umich.edu ld_eff_addr1); 5628607Sgblack@eecs.umich.edu memDepViolator = ld_inst; 5638607Sgblack@eecs.umich.edu 5647435Sgblack@eecs.umich.edu ++lsqMemOrderViolation; 5658607Sgblack@eecs.umich.edu 5668607Sgblack@eecs.umich.edu return TheISA::genMachineCheckFault(); 5677435Sgblack@eecs.umich.edu } 5688607Sgblack@eecs.umich.edu } 5698607Sgblack@eecs.umich.edu 5707435Sgblack@eecs.umich.edu incrLdIdx(load_idx); 5717435Sgblack@eecs.umich.edu } 5727435Sgblack@eecs.umich.edu return NoFault; 5738607Sgblack@eecs.umich.edu} 5747435Sgblack@eecs.umich.edu 5757435Sgblack@eecs.umich.edu 5768607Sgblack@eecs.umich.edu 5778607Sgblack@eecs.umich.edu 5787435Sgblack@eecs.umich.edutemplate <class Impl> 5797435Sgblack@eecs.umich.eduFault 5807435Sgblack@eecs.umich.eduLSQUnit<Impl>::executeLoad(DynInstPtr &inst) 5817639Sgblack@eecs.umich.edu{ 5827639Sgblack@eecs.umich.edu using namespace TheISA; 5837435Sgblack@eecs.umich.edu // Execute a specific load. 5847639Sgblack@eecs.umich.edu Fault load_fault = NoFault; 5857639Sgblack@eecs.umich.edu 5867435Sgblack@eecs.umich.edu DPRINTF(LSQUnit, "Executing load PC %s, [sn:%lli]\n", 5877435Sgblack@eecs.umich.edu inst->pcState(), inst->seqNum); 5887435Sgblack@eecs.umich.edu 58910037SARM gem5 Developers assert(!inst->isSquashed()); 59010037SARM gem5 Developers 59110037SARM gem5 Developers load_fault = inst->initiateAcc(); 59210037SARM gem5 Developers 59310037SARM gem5 Developers if (inst->isTranslationDelayed() && 59410037SARM gem5 Developers load_fault == NoFault) 59510037SARM gem5 Developers return load_fault; 59610037SARM gem5 Developers 59710037SARM gem5 Developers // If the instruction faulted or predicated false, then we need to send it 59810037SARM gem5 Developers // along to commit without the instruction completing. 59910037SARM gem5 Developers if (load_fault != NoFault || inst->readPredicate() == false) { 60010037SARM gem5 Developers // Send this instruction to commit, also make sure iew stage 60110037SARM gem5 Developers // realizes there is activity. 60210037SARM gem5 Developers // Mark it as executed unless it is an uncached load that 60310037SARM gem5 Developers // needs to hit the head of commit. 60410037SARM gem5 Developers if (inst->readPredicate() == false) 60510037SARM gem5 Developers inst->forwardOldRegs(); 6067435Sgblack@eecs.umich.edu DPRINTF(LSQUnit, "Load [sn:%lli] not executed from %s\n", 6077435Sgblack@eecs.umich.edu inst->seqNum, 6087435Sgblack@eecs.umich.edu (load_fault != NoFault ? "fault" : "predication")); 6097435Sgblack@eecs.umich.edu if (!(inst->hasRequest() && inst->uncacheable()) || 6107435Sgblack@eecs.umich.edu inst->isAtCommit()) { 6117639Sgblack@eecs.umich.edu inst->setExecuted(); 6127639Sgblack@eecs.umich.edu } 6137639Sgblack@eecs.umich.edu iewStage->instToCommit(inst); 6147639Sgblack@eecs.umich.edu iewStage->activityThisCycle(); 6157639Sgblack@eecs.umich.edu } else if (!loadBlocked()) { 6167435Sgblack@eecs.umich.edu assert(inst->effAddrValid); 6177435Sgblack@eecs.umich.edu int load_idx = inst->lqIdx; 6187435Sgblack@eecs.umich.edu incrLdIdx(load_idx); 6197435Sgblack@eecs.umich.edu 6207435Sgblack@eecs.umich.edu if (checkLoads) 6217639Sgblack@eecs.umich.edu return checkViolations(load_idx, inst); 6227639Sgblack@eecs.umich.edu } 6237639Sgblack@eecs.umich.edu 6247639Sgblack@eecs.umich.edu return load_fault; 6257639Sgblack@eecs.umich.edu} 6267435Sgblack@eecs.umich.edu 6277639Sgblack@eecs.umich.edutemplate <class Impl> 6287639Sgblack@eecs.umich.eduFault 6297639Sgblack@eecs.umich.eduLSQUnit<Impl>::executeStore(DynInstPtr &store_inst) 6307639Sgblack@eecs.umich.edu{ 6317639Sgblack@eecs.umich.edu using namespace TheISA; 6327435Sgblack@eecs.umich.edu // Make sure that a store exists. 6337435Sgblack@eecs.umich.edu assert(stores != 0); 6347435Sgblack@eecs.umich.edu 6357435Sgblack@eecs.umich.edu int store_idx = store_inst->sqIdx; 6367435Sgblack@eecs.umich.edu 6377639Sgblack@eecs.umich.edu DPRINTF(LSQUnit, "Executing store PC %s [sn:%lli]\n", 6387639Sgblack@eecs.umich.edu store_inst->pcState(), store_inst->seqNum); 6397639Sgblack@eecs.umich.edu 6407639Sgblack@eecs.umich.edu assert(!store_inst->isSquashed()); 6417639Sgblack@eecs.umich.edu 6427435Sgblack@eecs.umich.edu // Check the recently completed loads to see if any match this store's 6437639Sgblack@eecs.umich.edu // address. If so, then we have a memory ordering violation. 6447639Sgblack@eecs.umich.edu int load_idx = store_inst->lqIdx; 6457639Sgblack@eecs.umich.edu 6467639Sgblack@eecs.umich.edu Fault store_fault = store_inst->initiateAcc(); 6477639Sgblack@eecs.umich.edu 6487435Sgblack@eecs.umich.edu if (store_inst->isTranslationDelayed() && 6497435Sgblack@eecs.umich.edu store_fault == NoFault) 6507435Sgblack@eecs.umich.edu return store_fault; 6517639Sgblack@eecs.umich.edu 6527639Sgblack@eecs.umich.edu if (store_inst->readPredicate() == false) 6537639Sgblack@eecs.umich.edu store_inst->forwardOldRegs(); 6547639Sgblack@eecs.umich.edu 6557639Sgblack@eecs.umich.edu if (storeQueue[store_idx].size == 0) { 6567435Sgblack@eecs.umich.edu DPRINTF(LSQUnit,"Fault on Store PC %s, [sn:%lli], Size = 0\n", 6577639Sgblack@eecs.umich.edu store_inst->pcState(), store_inst->seqNum); 6587639Sgblack@eecs.umich.edu 6597639Sgblack@eecs.umich.edu return store_fault; 6607639Sgblack@eecs.umich.edu } else if (store_inst->readPredicate() == false) { 6617639Sgblack@eecs.umich.edu DPRINTF(LSQUnit, "Store [sn:%lli] not executed from predication\n", 6627435Sgblack@eecs.umich.edu store_inst->seqNum); 6637435Sgblack@eecs.umich.edu return store_fault; 6647435Sgblack@eecs.umich.edu } 6657435Sgblack@eecs.umich.edu 6667435Sgblack@eecs.umich.edu assert(store_fault == NoFault); 6677435Sgblack@eecs.umich.edu 6687435Sgblack@eecs.umich.edu if (store_inst->isStoreConditional()) { 6697639Sgblack@eecs.umich.edu // Store conditionals need to set themselves as able to 6707639Sgblack@eecs.umich.edu // writeback if we haven't had a fault by here. 6717639Sgblack@eecs.umich.edu storeQueue[store_idx].canWB = true; 6727639Sgblack@eecs.umich.edu 6737639Sgblack@eecs.umich.edu ++storesToWB; 6747435Sgblack@eecs.umich.edu } 6757639Sgblack@eecs.umich.edu 6767639Sgblack@eecs.umich.edu return checkViolations(load_idx, store_inst); 6777639Sgblack@eecs.umich.edu 6787639Sgblack@eecs.umich.edu} 6797639Sgblack@eecs.umich.edu 6807435Sgblack@eecs.umich.edutemplate <class Impl> 6817435Sgblack@eecs.umich.eduvoid 6827435Sgblack@eecs.umich.eduLSQUnit<Impl>::commitLoad() 6837435Sgblack@eecs.umich.edu{ 6847435Sgblack@eecs.umich.edu assert(loadQueue[loadHead]); 6857435Sgblack@eecs.umich.edu 6867435Sgblack@eecs.umich.edu DPRINTF(LSQUnit, "Committing head load instruction, PC %s\n", 6877639Sgblack@eecs.umich.edu loadQueue[loadHead]->pcState()); 6887639Sgblack@eecs.umich.edu 6897639Sgblack@eecs.umich.edu loadQueue[loadHead] = NULL; 6907639Sgblack@eecs.umich.edu 6917639Sgblack@eecs.umich.edu incrLdIdx(loadHead); 6927435Sgblack@eecs.umich.edu 6937639Sgblack@eecs.umich.edu --loads; 6947639Sgblack@eecs.umich.edu} 6957639Sgblack@eecs.umich.edu 6967639Sgblack@eecs.umich.edutemplate <class Impl> 6977639Sgblack@eecs.umich.eduvoid 6987435Sgblack@eecs.umich.eduLSQUnit<Impl>::commitLoads(InstSeqNum &youngest_inst) 6997435Sgblack@eecs.umich.edu{ 7007435Sgblack@eecs.umich.edu assert(loads == 0 || loadQueue[loadHead]); 7017639Sgblack@eecs.umich.edu 7027639Sgblack@eecs.umich.edu while (loads != 0 && loadQueue[loadHead]->seqNum <= youngest_inst) { 7037639Sgblack@eecs.umich.edu commitLoad(); 7047639Sgblack@eecs.umich.edu } 7057639Sgblack@eecs.umich.edu} 7067435Sgblack@eecs.umich.edu 7077435Sgblack@eecs.umich.edutemplate <class Impl> 7087435Sgblack@eecs.umich.eduvoid 7097435Sgblack@eecs.umich.eduLSQUnit<Impl>::commitStores(InstSeqNum &youngest_inst) 7107435Sgblack@eecs.umich.edu{ 7117435Sgblack@eecs.umich.edu assert(stores == 0 || storeQueue[storeHead].inst); 7127435Sgblack@eecs.umich.edu 7137435Sgblack@eecs.umich.edu int store_idx = storeHead; 7147435Sgblack@eecs.umich.edu 7157435Sgblack@eecs.umich.edu while (store_idx != storeTail) { 7167435Sgblack@eecs.umich.edu assert(storeQueue[store_idx].inst); 7177639Sgblack@eecs.umich.edu // Mark any stores that are now committed and have not yet 7187639Sgblack@eecs.umich.edu // been marked as able to write back. 7197639Sgblack@eecs.umich.edu if (!storeQueue[store_idx].canWB) { 7207639Sgblack@eecs.umich.edu if (storeQueue[store_idx].inst->seqNum > youngest_inst) { 7217639Sgblack@eecs.umich.edu break; 7227435Sgblack@eecs.umich.edu } 7237639Sgblack@eecs.umich.edu DPRINTF(LSQUnit, "Marking store as able to write back, PC " 7247639Sgblack@eecs.umich.edu "%s [sn:%lli]\n", 7257639Sgblack@eecs.umich.edu storeQueue[store_idx].inst->pcState(), 7267639Sgblack@eecs.umich.edu storeQueue[store_idx].inst->seqNum); 7277639Sgblack@eecs.umich.edu 7287435Sgblack@eecs.umich.edu storeQueue[store_idx].canWB = true; 7297435Sgblack@eecs.umich.edu 7307435Sgblack@eecs.umich.edu ++storesToWB; 7317435Sgblack@eecs.umich.edu } 7327435Sgblack@eecs.umich.edu 7337639Sgblack@eecs.umich.edu incrStIdx(store_idx); 7347639Sgblack@eecs.umich.edu } 7357639Sgblack@eecs.umich.edu} 7367639Sgblack@eecs.umich.edu 7377639Sgblack@eecs.umich.edutemplate <class Impl> 7387435Sgblack@eecs.umich.eduvoid 7397639Sgblack@eecs.umich.eduLSQUnit<Impl>::writebackPendingStore() 7407639Sgblack@eecs.umich.edu{ 7417639Sgblack@eecs.umich.edu if (hasPendingPkt) { 7427639Sgblack@eecs.umich.edu assert(pendingPkt != NULL); 7437639Sgblack@eecs.umich.edu 7447435Sgblack@eecs.umich.edu // If the cache is blocked, this will store the packet for retry. 7457435Sgblack@eecs.umich.edu if (sendStore(pendingPkt)) { 7467435Sgblack@eecs.umich.edu storePostSend(pendingPkt); 7477639Sgblack@eecs.umich.edu } 7487639Sgblack@eecs.umich.edu pendingPkt = NULL; 7497639Sgblack@eecs.umich.edu hasPendingPkt = false; 7507639Sgblack@eecs.umich.edu } 7517639Sgblack@eecs.umich.edu} 7527435Sgblack@eecs.umich.edu 7537639Sgblack@eecs.umich.edutemplate <class Impl> 7547639Sgblack@eecs.umich.eduvoid 7557639Sgblack@eecs.umich.eduLSQUnit<Impl>::writebackStores() 7567639Sgblack@eecs.umich.edu{ 7577639Sgblack@eecs.umich.edu // First writeback the second packet from any split store that didn't 7587435Sgblack@eecs.umich.edu // complete last cycle because there weren't enough cache ports available. 7597435Sgblack@eecs.umich.edu if (TheISA::HasUnalignedMemAcc) { 7607435Sgblack@eecs.umich.edu writebackPendingStore(); 7617435Sgblack@eecs.umich.edu } 7627435Sgblack@eecs.umich.edu 7637435Sgblack@eecs.umich.edu while (storesToWB > 0 && 7647435Sgblack@eecs.umich.edu storeWBIdx != storeTail && 7657435Sgblack@eecs.umich.edu storeQueue[storeWBIdx].inst && 7667435Sgblack@eecs.umich.edu storeQueue[storeWBIdx].canWB && 7677435Sgblack@eecs.umich.edu usedPorts < cachePorts) { 7687639Sgblack@eecs.umich.edu 7697639Sgblack@eecs.umich.edu if (isStoreBlocked || lsq->cacheBlocked()) { 7707639Sgblack@eecs.umich.edu DPRINTF(LSQUnit, "Unable to write back any more stores, cache" 7717639Sgblack@eecs.umich.edu " is blocked!\n"); 7727435Sgblack@eecs.umich.edu break; 7737639Sgblack@eecs.umich.edu } 7747639Sgblack@eecs.umich.edu 7757639Sgblack@eecs.umich.edu // Store didn't write any data so no need to write it back to 7767639Sgblack@eecs.umich.edu // memory. 7777639Sgblack@eecs.umich.edu if (storeQueue[storeWBIdx].size == 0) { 7787853SMatt.Horsnell@ARM.com completeStore(storeWBIdx); 7797853SMatt.Horsnell@ARM.com 7807853SMatt.Horsnell@ARM.com incrStIdx(storeWBIdx); 7817853SMatt.Horsnell@ARM.com 7827853SMatt.Horsnell@ARM.com continue; 7837853SMatt.Horsnell@ARM.com } 7847853SMatt.Horsnell@ARM.com 7857853SMatt.Horsnell@ARM.com ++usedPorts; 7867853SMatt.Horsnell@ARM.com 7877435Sgblack@eecs.umich.edu if (storeQueue[storeWBIdx].inst->isDataPrefetch()) { 7887435Sgblack@eecs.umich.edu incrStIdx(storeWBIdx); 7897435Sgblack@eecs.umich.edu 7907639Sgblack@eecs.umich.edu continue; 7917639Sgblack@eecs.umich.edu } 7927639Sgblack@eecs.umich.edu 7937639Sgblack@eecs.umich.edu assert(storeQueue[storeWBIdx].req); 7947435Sgblack@eecs.umich.edu assert(!storeQueue[storeWBIdx].committed); 7957639Sgblack@eecs.umich.edu 7967639Sgblack@eecs.umich.edu if (TheISA::HasUnalignedMemAcc && storeQueue[storeWBIdx].isSplit) { 7977639Sgblack@eecs.umich.edu assert(storeQueue[storeWBIdx].sreqLow); 7987639Sgblack@eecs.umich.edu assert(storeQueue[storeWBIdx].sreqHigh); 7997435Sgblack@eecs.umich.edu } 8007435Sgblack@eecs.umich.edu 8017435Sgblack@eecs.umich.edu DynInstPtr inst = storeQueue[storeWBIdx].inst; 8027639Sgblack@eecs.umich.edu 8037639Sgblack@eecs.umich.edu Request *req = storeQueue[storeWBIdx].req; 8047639Sgblack@eecs.umich.edu RequestPtr sreqLow = storeQueue[storeWBIdx].sreqLow; 8057639Sgblack@eecs.umich.edu RequestPtr sreqHigh = storeQueue[storeWBIdx].sreqHigh; 8067639Sgblack@eecs.umich.edu 8077639Sgblack@eecs.umich.edu storeQueue[storeWBIdx].committed = true; 8087639Sgblack@eecs.umich.edu 8097639Sgblack@eecs.umich.edu assert(!inst->memData); 8107639Sgblack@eecs.umich.edu inst->memData = new uint8_t[64]; 8117639Sgblack@eecs.umich.edu 8127639Sgblack@eecs.umich.edu memcpy(inst->memData, storeQueue[storeWBIdx].data, req->getSize()); 8137639Sgblack@eecs.umich.edu 8147639Sgblack@eecs.umich.edu MemCmd command = 8157639Sgblack@eecs.umich.edu req->isSwap() ? MemCmd::SwapReq : 8167639Sgblack@eecs.umich.edu (req->isLLSC() ? MemCmd::StoreCondReq : MemCmd::WriteReq); 8177639Sgblack@eecs.umich.edu PacketPtr data_pkt; 8187639Sgblack@eecs.umich.edu PacketPtr snd_data_pkt = NULL; 8197639Sgblack@eecs.umich.edu 8207435Sgblack@eecs.umich.edu LSQSenderState *state = new LSQSenderState; 8217435Sgblack@eecs.umich.edu state->isLoad = false; 8227639Sgblack@eecs.umich.edu state->idx = storeWBIdx; 8237639Sgblack@eecs.umich.edu state->inst = inst; 8247639Sgblack@eecs.umich.edu 8257639Sgblack@eecs.umich.edu if (!TheISA::HasUnalignedMemAcc || !storeQueue[storeWBIdx].isSplit) { 8267435Sgblack@eecs.umich.edu 8277639Sgblack@eecs.umich.edu // Build a single data packet if the store isn't split. 8287639Sgblack@eecs.umich.edu data_pkt = new Packet(req, command, Packet::Broadcast); 8297639Sgblack@eecs.umich.edu data_pkt->dataStatic(inst->memData); 8307639Sgblack@eecs.umich.edu data_pkt->senderState = state; 8317435Sgblack@eecs.umich.edu } else { 8327435Sgblack@eecs.umich.edu // Create two packets if the store is split in two. 8337435Sgblack@eecs.umich.edu data_pkt = new Packet(sreqLow, command, Packet::Broadcast); 8347435Sgblack@eecs.umich.edu snd_data_pkt = new Packet(sreqHigh, command, Packet::Broadcast); 8357435Sgblack@eecs.umich.edu 8367435Sgblack@eecs.umich.edu data_pkt->dataStatic(inst->memData); 8377639Sgblack@eecs.umich.edu snd_data_pkt->dataStatic(inst->memData + sreqLow->getSize()); 8387639Sgblack@eecs.umich.edu 8397639Sgblack@eecs.umich.edu data_pkt->senderState = state; 8407639Sgblack@eecs.umich.edu snd_data_pkt->senderState = state; 8417435Sgblack@eecs.umich.edu 8427639Sgblack@eecs.umich.edu state->isSplit = true; 8437639Sgblack@eecs.umich.edu state->outstanding = 2; 8447639Sgblack@eecs.umich.edu 8457639Sgblack@eecs.umich.edu // Can delete the main request now. 8467435Sgblack@eecs.umich.edu delete req; 8477435Sgblack@eecs.umich.edu req = sreqLow; 8487435Sgblack@eecs.umich.edu } 8497639Sgblack@eecs.umich.edu 8507639Sgblack@eecs.umich.edu DPRINTF(LSQUnit, "D-Cache: Writing back store idx:%i PC:%s " 8517639Sgblack@eecs.umich.edu "to Addr:%#x, data:%#x [sn:%lli]\n", 8527639Sgblack@eecs.umich.edu storeWBIdx, inst->pcState(), 8537435Sgblack@eecs.umich.edu req->getPaddr(), (int)*(inst->memData), 8547435Sgblack@eecs.umich.edu inst->seqNum); 8557639Sgblack@eecs.umich.edu 8567639Sgblack@eecs.umich.edu // @todo: Remove this SC hack once the memory system handles it. 8577639Sgblack@eecs.umich.edu if (inst->isStoreConditional()) { 8587639Sgblack@eecs.umich.edu assert(!storeQueue[storeWBIdx].isSplit); 8597435Sgblack@eecs.umich.edu // Disable recording the result temporarily. Writing to 8607639Sgblack@eecs.umich.edu // misc regs normally updates the result, but this is not 8617639Sgblack@eecs.umich.edu // the desired behavior when handling store conditionals. 8627639Sgblack@eecs.umich.edu inst->recordResult = false; 8637639Sgblack@eecs.umich.edu bool success = TheISA::handleLockedWrite(inst.get(), req); 8647435Sgblack@eecs.umich.edu inst->recordResult = true; 8657435Sgblack@eecs.umich.edu 8667435Sgblack@eecs.umich.edu if (!success) { 8677435Sgblack@eecs.umich.edu // Instantly complete this store. 8687435Sgblack@eecs.umich.edu DPRINTF(LSQUnit, "Store conditional [sn:%lli] failed. " 8697435Sgblack@eecs.umich.edu "Instantly completing it.\n", 8707435Sgblack@eecs.umich.edu inst->seqNum); 8717435Sgblack@eecs.umich.edu WritebackEvent *wb = new WritebackEvent(inst, data_pkt, this); 8727435Sgblack@eecs.umich.edu cpu->schedule(wb, curTick() + 1); 8737435Sgblack@eecs.umich.edu completeStore(storeWBIdx); 8747435Sgblack@eecs.umich.edu incrStIdx(storeWBIdx); 8757435Sgblack@eecs.umich.edu continue; 8767435Sgblack@eecs.umich.edu } 8777435Sgblack@eecs.umich.edu } else { 8787639Sgblack@eecs.umich.edu // Non-store conditionals do not need a writeback. 8797639Sgblack@eecs.umich.edu state->noWB = true; 8807639Sgblack@eecs.umich.edu } 8817639Sgblack@eecs.umich.edu 8827639Sgblack@eecs.umich.edu bool split = 8837639Sgblack@eecs.umich.edu TheISA::HasUnalignedMemAcc && storeQueue[storeWBIdx].isSplit; 8847639Sgblack@eecs.umich.edu 8857639Sgblack@eecs.umich.edu ThreadContext *thread = cpu->tcBase(lsqID); 8867639Sgblack@eecs.umich.edu 8877639Sgblack@eecs.umich.edu if (req->isMmappedIpr()) { 8887639Sgblack@eecs.umich.edu assert(!inst->isStoreConditional()); 8897639Sgblack@eecs.umich.edu TheISA::handleIprWrite(thread, data_pkt); 8907639Sgblack@eecs.umich.edu delete data_pkt; 8917639Sgblack@eecs.umich.edu if (split) { 8927639Sgblack@eecs.umich.edu assert(snd_data_pkt->req->isMmappedIpr()); 8937639Sgblack@eecs.umich.edu TheISA::handleIprWrite(thread, snd_data_pkt); 8947639Sgblack@eecs.umich.edu delete snd_data_pkt; 8957639Sgblack@eecs.umich.edu delete sreqLow; 8967639Sgblack@eecs.umich.edu delete sreqHigh; 8977639Sgblack@eecs.umich.edu } 8987639Sgblack@eecs.umich.edu delete state; 8997639Sgblack@eecs.umich.edu delete req; 9007639Sgblack@eecs.umich.edu completeStore(storeWBIdx); 9017639Sgblack@eecs.umich.edu incrStIdx(storeWBIdx); 9027639Sgblack@eecs.umich.edu } else if (!sendStore(data_pkt)) { 9037639Sgblack@eecs.umich.edu DPRINTF(IEW, "D-Cache became blocked when writing [sn:%lli], will" 9047435Sgblack@eecs.umich.edu "retry later\n", 9057435Sgblack@eecs.umich.edu inst->seqNum); 9067435Sgblack@eecs.umich.edu 9077639Sgblack@eecs.umich.edu // Need to store the second packet, if split. 9087639Sgblack@eecs.umich.edu if (split) { 9097435Sgblack@eecs.umich.edu state->pktToSend = true; 9107639Sgblack@eecs.umich.edu state->pendingPacket = snd_data_pkt; 9117639Sgblack@eecs.umich.edu } 9127435Sgblack@eecs.umich.edu } else { 9137639Sgblack@eecs.umich.edu 9147639Sgblack@eecs.umich.edu // If split, try to send the second packet too 9157435Sgblack@eecs.umich.edu if (split) { 9167639Sgblack@eecs.umich.edu assert(snd_data_pkt); 9177639Sgblack@eecs.umich.edu 9187435Sgblack@eecs.umich.edu // Ensure there are enough ports to use. 9197435Sgblack@eecs.umich.edu if (usedPorts < cachePorts) { 9207639Sgblack@eecs.umich.edu ++usedPorts; 9217639Sgblack@eecs.umich.edu if (sendStore(snd_data_pkt)) { 9227435Sgblack@eecs.umich.edu storePostSend(snd_data_pkt); 9237435Sgblack@eecs.umich.edu } else { 9247435Sgblack@eecs.umich.edu DPRINTF(IEW, "D-Cache became blocked when writing" 9257435Sgblack@eecs.umich.edu " [sn:%lli] second packet, will retry later\n", 9267435Sgblack@eecs.umich.edu inst->seqNum); 9277639Sgblack@eecs.umich.edu } 9287639Sgblack@eecs.umich.edu } else { 9297435Sgblack@eecs.umich.edu 9307639Sgblack@eecs.umich.edu // Store the packet for when there's free ports. 9317639Sgblack@eecs.umich.edu assert(pendingPkt == NULL); 9327435Sgblack@eecs.umich.edu pendingPkt = snd_data_pkt; 9337435Sgblack@eecs.umich.edu hasPendingPkt = true; 9347435Sgblack@eecs.umich.edu } 9357639Sgblack@eecs.umich.edu } else { 9367639Sgblack@eecs.umich.edu 9377639Sgblack@eecs.umich.edu // Not a split store. 9387639Sgblack@eecs.umich.edu storePostSend(data_pkt); 9397639Sgblack@eecs.umich.edu } 9407639Sgblack@eecs.umich.edu } 9417639Sgblack@eecs.umich.edu } 9427639Sgblack@eecs.umich.edu 9437639Sgblack@eecs.umich.edu // Not sure this should set it to 0. 9447639Sgblack@eecs.umich.edu usedPorts = 0; 9457639Sgblack@eecs.umich.edu 9467639Sgblack@eecs.umich.edu assert(stores >= 0 && storesToWB >= 0); 9477435Sgblack@eecs.umich.edu} 9487435Sgblack@eecs.umich.edu 9497435Sgblack@eecs.umich.edu/*template <class Impl> 9507435Sgblack@eecs.umich.eduvoid 9517639Sgblack@eecs.umich.eduLSQUnit<Impl>::removeMSHR(InstSeqNum seqNum) 9527639Sgblack@eecs.umich.edu{ 9537435Sgblack@eecs.umich.edu list<InstSeqNum>::iterator mshr_it = find(mshrSeqNums.begin(), 9547639Sgblack@eecs.umich.edu mshrSeqNums.end(), 9557639Sgblack@eecs.umich.edu seqNum); 9567435Sgblack@eecs.umich.edu 9577435Sgblack@eecs.umich.edu if (mshr_it != mshrSeqNums.end()) { 9587435Sgblack@eecs.umich.edu mshrSeqNums.erase(mshr_it); 9597435Sgblack@eecs.umich.edu DPRINTF(LSQUnit, "Removing MSHR. count = %i\n",mshrSeqNums.size()); 9607639Sgblack@eecs.umich.edu } 9617639Sgblack@eecs.umich.edu}*/ 9627639Sgblack@eecs.umich.edu 9637435Sgblack@eecs.umich.edutemplate <class Impl> 9647639Sgblack@eecs.umich.eduvoid 9657639Sgblack@eecs.umich.eduLSQUnit<Impl>::squash(const InstSeqNum &squashed_num) 9667435Sgblack@eecs.umich.edu{ 9677435Sgblack@eecs.umich.edu DPRINTF(LSQUnit, "Squashing until [sn:%lli]!" 9687435Sgblack@eecs.umich.edu "(Loads:%i Stores:%i)\n", squashed_num, loads, stores); 9697435Sgblack@eecs.umich.edu 9707435Sgblack@eecs.umich.edu int load_idx = loadTail; 9717639Sgblack@eecs.umich.edu decrLdIdx(load_idx); 9727639Sgblack@eecs.umich.edu 9737435Sgblack@eecs.umich.edu while (loads != 0 && loadQueue[load_idx]->seqNum > squashed_num) { 9747435Sgblack@eecs.umich.edu DPRINTF(LSQUnit,"Load Instruction PC %s squashed, " 9757639Sgblack@eecs.umich.edu "[sn:%lli]\n", 9767639Sgblack@eecs.umich.edu loadQueue[load_idx]->pcState(), 9777639Sgblack@eecs.umich.edu loadQueue[load_idx]->seqNum); 9787639Sgblack@eecs.umich.edu 9797639Sgblack@eecs.umich.edu if (isStalled() && load_idx == stallingLoadIdx) { 9807639Sgblack@eecs.umich.edu stalled = false; 9817639Sgblack@eecs.umich.edu stallingStoreIsn = 0; 9827639Sgblack@eecs.umich.edu stallingLoadIdx = 0; 9837639Sgblack@eecs.umich.edu } 9847639Sgblack@eecs.umich.edu 9857639Sgblack@eecs.umich.edu // Clear the smart pointer to make sure it is decremented. 9867639Sgblack@eecs.umich.edu loadQueue[load_idx]->setSquashed(); 9877639Sgblack@eecs.umich.edu loadQueue[load_idx] = NULL; 9887639Sgblack@eecs.umich.edu --loads; 9897639Sgblack@eecs.umich.edu 9907639Sgblack@eecs.umich.edu // Inefficient! 9917639Sgblack@eecs.umich.edu loadTail = load_idx; 9927639Sgblack@eecs.umich.edu 9937639Sgblack@eecs.umich.edu decrLdIdx(load_idx); 9947639Sgblack@eecs.umich.edu ++lsqSquashedLoads; 9957639Sgblack@eecs.umich.edu } 9967639Sgblack@eecs.umich.edu 9977639Sgblack@eecs.umich.edu if (isLoadBlocked) { 9987435Sgblack@eecs.umich.edu if (squashed_num < blockedLoadSeqNum) { 9997435Sgblack@eecs.umich.edu isLoadBlocked = false; 10007435Sgblack@eecs.umich.edu loadBlockedHandled = false; 10017639Sgblack@eecs.umich.edu blockedLoadSeqNum = 0; 10027639Sgblack@eecs.umich.edu } 10037639Sgblack@eecs.umich.edu } 10047639Sgblack@eecs.umich.edu 10057639Sgblack@eecs.umich.edu if (memDepViolator && squashed_num < memDepViolator->seqNum) { 10067639Sgblack@eecs.umich.edu memDepViolator = NULL; 10077639Sgblack@eecs.umich.edu } 10087639Sgblack@eecs.umich.edu 10097639Sgblack@eecs.umich.edu int store_idx = storeTail; 10107639Sgblack@eecs.umich.edu decrStIdx(store_idx); 10117639Sgblack@eecs.umich.edu 10127639Sgblack@eecs.umich.edu while (stores != 0 && 10137639Sgblack@eecs.umich.edu storeQueue[store_idx].inst->seqNum > squashed_num) { 10147639Sgblack@eecs.umich.edu // Instructions marked as can WB are already committed. 10157639Sgblack@eecs.umich.edu if (storeQueue[store_idx].canWB) { 10167639Sgblack@eecs.umich.edu break; 10177639Sgblack@eecs.umich.edu } 10187639Sgblack@eecs.umich.edu 10197639Sgblack@eecs.umich.edu DPRINTF(LSQUnit,"Store Instruction PC %s squashed, " 10207639Sgblack@eecs.umich.edu "idx:%i [sn:%lli]\n", 10217435Sgblack@eecs.umich.edu storeQueue[store_idx].inst->pcState(), 10227435Sgblack@eecs.umich.edu store_idx, storeQueue[store_idx].inst->seqNum); 10237435Sgblack@eecs.umich.edu 10247435Sgblack@eecs.umich.edu // I don't think this can happen. It should have been cleared 10257435Sgblack@eecs.umich.edu // by the stalling load. 10267435Sgblack@eecs.umich.edu if (isStalled() && 10277435Sgblack@eecs.umich.edu storeQueue[store_idx].inst->seqNum == stallingStoreIsn) { 10287435Sgblack@eecs.umich.edu panic("Is stalled should have been cleared by stalling load!\n"); 10297435Sgblack@eecs.umich.edu stalled = false; 10307435Sgblack@eecs.umich.edu stallingStoreIsn = 0; 10317639Sgblack@eecs.umich.edu } 10327639Sgblack@eecs.umich.edu 10337639Sgblack@eecs.umich.edu // Clear the smart pointer to make sure it is decremented. 10347639Sgblack@eecs.umich.edu storeQueue[store_idx].inst->setSquashed(); 10357639Sgblack@eecs.umich.edu storeQueue[store_idx].inst = NULL; 10367639Sgblack@eecs.umich.edu storeQueue[store_idx].canWB = 0; 10377639Sgblack@eecs.umich.edu 10387639Sgblack@eecs.umich.edu // Must delete request now that it wasn't handed off to 10397639Sgblack@eecs.umich.edu // memory. This is quite ugly. @todo: Figure out the proper 10407639Sgblack@eecs.umich.edu // place to really handle request deletes. 10417435Sgblack@eecs.umich.edu delete storeQueue[store_idx].req; 10427435Sgblack@eecs.umich.edu if (TheISA::HasUnalignedMemAcc && storeQueue[store_idx].isSplit) { 10437639Sgblack@eecs.umich.edu delete storeQueue[store_idx].sreqLow; 10447639Sgblack@eecs.umich.edu delete storeQueue[store_idx].sreqHigh; 10457435Sgblack@eecs.umich.edu 10467639Sgblack@eecs.umich.edu storeQueue[store_idx].sreqLow = NULL; 10477639Sgblack@eecs.umich.edu storeQueue[store_idx].sreqHigh = NULL; 10487435Sgblack@eecs.umich.edu } 10497639Sgblack@eecs.umich.edu 10507639Sgblack@eecs.umich.edu storeQueue[store_idx].req = NULL; 10517435Sgblack@eecs.umich.edu --stores; 10527639Sgblack@eecs.umich.edu 10537639Sgblack@eecs.umich.edu // Inefficient! 10547435Sgblack@eecs.umich.edu storeTail = store_idx; 10557435Sgblack@eecs.umich.edu 10567639Sgblack@eecs.umich.edu decrStIdx(store_idx); 10577639Sgblack@eecs.umich.edu ++lsqSquashedStores; 10587435Sgblack@eecs.umich.edu } 10597639Sgblack@eecs.umich.edu} 10607639Sgblack@eecs.umich.edu 10617435Sgblack@eecs.umich.edutemplate <class Impl> 10627435Sgblack@eecs.umich.eduvoid 10637639Sgblack@eecs.umich.eduLSQUnit<Impl>::storePostSend(PacketPtr pkt) 10647639Sgblack@eecs.umich.edu{ 10657435Sgblack@eecs.umich.edu if (isStalled() && 10667435Sgblack@eecs.umich.edu storeQueue[storeWBIdx].inst->seqNum == stallingStoreIsn) { 10677639Sgblack@eecs.umich.edu DPRINTF(LSQUnit, "Unstalling, stalling store [sn:%lli] " 10687639Sgblack@eecs.umich.edu "load idx:%i\n", 10697435Sgblack@eecs.umich.edu stallingStoreIsn, stallingLoadIdx); 10707639Sgblack@eecs.umich.edu stalled = false; 10717639Sgblack@eecs.umich.edu stallingStoreIsn = 0; 10727435Sgblack@eecs.umich.edu iewStage->replayMemInst(loadQueue[stallingLoadIdx]); 10737435Sgblack@eecs.umich.edu } 10747435Sgblack@eecs.umich.edu 10757639Sgblack@eecs.umich.edu if (!storeQueue[storeWBIdx].inst->isStoreConditional()) { 10767639Sgblack@eecs.umich.edu // The store is basically completed at this time. This 10777435Sgblack@eecs.umich.edu // only works so long as the checker doesn't try to 10787639Sgblack@eecs.umich.edu // verify the value in memory for stores. 10797639Sgblack@eecs.umich.edu storeQueue[storeWBIdx].inst->setCompleted(); 10807435Sgblack@eecs.umich.edu#if USE_CHECKER 10817435Sgblack@eecs.umich.edu if (cpu->checker) { 10827639Sgblack@eecs.umich.edu cpu->checker->verify(storeQueue[storeWBIdx].inst); 10837639Sgblack@eecs.umich.edu } 10847435Sgblack@eecs.umich.edu#endif 10857639Sgblack@eecs.umich.edu } 10867639Sgblack@eecs.umich.edu 10877435Sgblack@eecs.umich.edu incrStIdx(storeWBIdx); 10887639Sgblack@eecs.umich.edu} 10897639Sgblack@eecs.umich.edu 10907435Sgblack@eecs.umich.edutemplate <class Impl> 10917639Sgblack@eecs.umich.eduvoid 10927639Sgblack@eecs.umich.eduLSQUnit<Impl>::writeback(DynInstPtr &inst, PacketPtr pkt) 10937435Sgblack@eecs.umich.edu{ 10947435Sgblack@eecs.umich.edu iewStage->wakeCPU(); 10957639Sgblack@eecs.umich.edu 10967435Sgblack@eecs.umich.edu // Squashed instructions do not need to complete their access. 10977435Sgblack@eecs.umich.edu if (inst->isSquashed()) { 10987639Sgblack@eecs.umich.edu iewStage->decrWb(inst->seqNum); 10997639Sgblack@eecs.umich.edu assert(!inst->isStore()); 11007435Sgblack@eecs.umich.edu ++lsqIgnoredResponses; 11017435Sgblack@eecs.umich.edu return; 11027639Sgblack@eecs.umich.edu } 11037639Sgblack@eecs.umich.edu 11047435Sgblack@eecs.umich.edu if (!inst->isExecuted()) { 11057639Sgblack@eecs.umich.edu inst->setExecuted(); 11067435Sgblack@eecs.umich.edu 11077435Sgblack@eecs.umich.edu // Complete access to copy data to proper place. 11087639Sgblack@eecs.umich.edu inst->completeAcc(pkt); 11097639Sgblack@eecs.umich.edu } 11107435Sgblack@eecs.umich.edu 11117435Sgblack@eecs.umich.edu // Need to insert instruction into queue to commit 11127639Sgblack@eecs.umich.edu iewStage->instToCommit(inst); 11137639Sgblack@eecs.umich.edu 11147435Sgblack@eecs.umich.edu iewStage->activityThisCycle(); 11157435Sgblack@eecs.umich.edu 11167435Sgblack@eecs.umich.edu // see if this load changed the PC 11177435Sgblack@eecs.umich.edu iewStage->checkMisprediction(inst); 11187435Sgblack@eecs.umich.edu} 11197435Sgblack@eecs.umich.edu 11207435Sgblack@eecs.umich.edutemplate <class Impl> 11217435Sgblack@eecs.umich.eduvoid 11227435Sgblack@eecs.umich.eduLSQUnit<Impl>::completeStore(int store_idx) 11237639Sgblack@eecs.umich.edu{ 11247639Sgblack@eecs.umich.edu assert(storeQueue[store_idx].inst); 11257639Sgblack@eecs.umich.edu storeQueue[store_idx].completed = true; 11267639Sgblack@eecs.umich.edu --storesToWB; 11277639Sgblack@eecs.umich.edu // A bit conservative because a store completion may not free up entries, 11287639Sgblack@eecs.umich.edu // but hopefully avoids two store completions in one cycle from making 11297639Sgblack@eecs.umich.edu // the CPU tick twice. 11307639Sgblack@eecs.umich.edu cpu->wakeCPU(); 11317639Sgblack@eecs.umich.edu cpu->activityThisCycle(); 11327639Sgblack@eecs.umich.edu 11337639Sgblack@eecs.umich.edu if (store_idx == storeHead) { 11347639Sgblack@eecs.umich.edu do { 11357435Sgblack@eecs.umich.edu incrStIdx(storeHead); 11367435Sgblack@eecs.umich.edu 11377639Sgblack@eecs.umich.edu --stores; 11387639Sgblack@eecs.umich.edu } while (storeQueue[storeHead].completed && 11397639Sgblack@eecs.umich.edu storeHead != storeTail); 11407639Sgblack@eecs.umich.edu 11417639Sgblack@eecs.umich.edu iewStage->updateLSQNextCycle = true; 11427639Sgblack@eecs.umich.edu } 11437639Sgblack@eecs.umich.edu 11447639Sgblack@eecs.umich.edu DPRINTF(LSQUnit, "Completing store [sn:%lli], idx:%i, store head " 11457639Sgblack@eecs.umich.edu "idx:%i\n", 11467639Sgblack@eecs.umich.edu storeQueue[store_idx].inst->seqNum, store_idx, storeHead); 11477639Sgblack@eecs.umich.edu 11487639Sgblack@eecs.umich.edu if (isStalled() && 11497639Sgblack@eecs.umich.edu storeQueue[store_idx].inst->seqNum == stallingStoreIsn) { 11507639Sgblack@eecs.umich.edu DPRINTF(LSQUnit, "Unstalling, stalling store [sn:%lli] " 11517639Sgblack@eecs.umich.edu "load idx:%i\n", 11527639Sgblack@eecs.umich.edu stallingStoreIsn, stallingLoadIdx); 11537639Sgblack@eecs.umich.edu stalled = false; 11547639Sgblack@eecs.umich.edu stallingStoreIsn = 0; 11557639Sgblack@eecs.umich.edu iewStage->replayMemInst(loadQueue[stallingLoadIdx]); 11567435Sgblack@eecs.umich.edu } 11577639Sgblack@eecs.umich.edu 11587639Sgblack@eecs.umich.edu storeQueue[store_idx].inst->setCompleted(); 11597639Sgblack@eecs.umich.edu 11607639Sgblack@eecs.umich.edu // Tell the checker we've completed this instruction. Some stores 11617435Sgblack@eecs.umich.edu // may get reported twice to the checker, but the checker can 11627639Sgblack@eecs.umich.edu // handle that case. 11637639Sgblack@eecs.umich.edu#if USE_CHECKER 11647639Sgblack@eecs.umich.edu if (cpu->checker) { 11657639Sgblack@eecs.umich.edu cpu->checker->verify(storeQueue[store_idx].inst); 11667639Sgblack@eecs.umich.edu } 11677639Sgblack@eecs.umich.edu#endif 11687639Sgblack@eecs.umich.edu} 11697639Sgblack@eecs.umich.edu 11707639Sgblack@eecs.umich.edutemplate <class Impl> 11717639Sgblack@eecs.umich.edubool 11727639Sgblack@eecs.umich.eduLSQUnit<Impl>::sendStore(PacketPtr data_pkt) 11737639Sgblack@eecs.umich.edu{ 11747639Sgblack@eecs.umich.edu if (!dcachePort->sendTiming(data_pkt)) { 11757639Sgblack@eecs.umich.edu // Need to handle becoming blocked on a store. 11767639Sgblack@eecs.umich.edu isStoreBlocked = true; 11777639Sgblack@eecs.umich.edu ++lsqCacheBlocked; 11787639Sgblack@eecs.umich.edu assert(retryPkt == NULL); 11797639Sgblack@eecs.umich.edu retryPkt = data_pkt; 11807639Sgblack@eecs.umich.edu lsq->setRetryTid(lsqID); 11817435Sgblack@eecs.umich.edu return false; 11827639Sgblack@eecs.umich.edu } 11837639Sgblack@eecs.umich.edu return true; 11847639Sgblack@eecs.umich.edu} 11857639Sgblack@eecs.umich.edu 11867435Sgblack@eecs.umich.edutemplate <class Impl> 11877639Sgblack@eecs.umich.eduvoid 11887639Sgblack@eecs.umich.eduLSQUnit<Impl>::recvRetry() 11897639Sgblack@eecs.umich.edu{ 11907639Sgblack@eecs.umich.edu if (isStoreBlocked) { 11917639Sgblack@eecs.umich.edu DPRINTF(LSQUnit, "Receiving retry: store blocked\n"); 11927639Sgblack@eecs.umich.edu assert(retryPkt != NULL); 11937639Sgblack@eecs.umich.edu 11947639Sgblack@eecs.umich.edu if (dcachePort->sendTiming(retryPkt)) { 11957639Sgblack@eecs.umich.edu LSQSenderState *state = 11967639Sgblack@eecs.umich.edu dynamic_cast<LSQSenderState *>(retryPkt->senderState); 11977639Sgblack@eecs.umich.edu 11987639Sgblack@eecs.umich.edu // Don't finish the store unless this is the last packet. 11997639Sgblack@eecs.umich.edu if (!TheISA::HasUnalignedMemAcc || !state->pktToSend || 12007639Sgblack@eecs.umich.edu state->pendingPacket == retryPkt) { 12017639Sgblack@eecs.umich.edu state->pktToSend = false; 12027639Sgblack@eecs.umich.edu storePostSend(retryPkt); 12037639Sgblack@eecs.umich.edu } 12047639Sgblack@eecs.umich.edu retryPkt = NULL; 12057639Sgblack@eecs.umich.edu isStoreBlocked = false; 12067435Sgblack@eecs.umich.edu lsq->setRetryTid(InvalidThreadID); 12077639Sgblack@eecs.umich.edu 12087639Sgblack@eecs.umich.edu // Send any outstanding packet. 12097639Sgblack@eecs.umich.edu if (TheISA::HasUnalignedMemAcc && state->pktToSend) { 12107639Sgblack@eecs.umich.edu assert(state->pendingPacket); 12117639Sgblack@eecs.umich.edu if (sendStore(state->pendingPacket)) { 12127639Sgblack@eecs.umich.edu storePostSend(state->pendingPacket); 12137639Sgblack@eecs.umich.edu } 12147639Sgblack@eecs.umich.edu } 12157639Sgblack@eecs.umich.edu } else { 12167639Sgblack@eecs.umich.edu // Still blocked! 12177639Sgblack@eecs.umich.edu ++lsqCacheBlocked; 12187639Sgblack@eecs.umich.edu lsq->setRetryTid(lsqID); 12197639Sgblack@eecs.umich.edu } 12207639Sgblack@eecs.umich.edu } else if (isLoadBlocked) { 12217639Sgblack@eecs.umich.edu DPRINTF(LSQUnit, "Loads squash themselves and all younger insts, " 12227639Sgblack@eecs.umich.edu "no need to resend packet.\n"); 12237639Sgblack@eecs.umich.edu } else { 12247639Sgblack@eecs.umich.edu DPRINTF(LSQUnit, "Retry received but LSQ is no longer blocked.\n"); 12257639Sgblack@eecs.umich.edu } 12267435Sgblack@eecs.umich.edu} 12277435Sgblack@eecs.umich.edu 12287435Sgblack@eecs.umich.edutemplate <class Impl> 12297435Sgblack@eecs.umich.eduinline void 12307639Sgblack@eecs.umich.eduLSQUnit<Impl>::incrStIdx(int &store_idx) 12317639Sgblack@eecs.umich.edu{ 12327639Sgblack@eecs.umich.edu if (++store_idx >= SQEntries) 12337639Sgblack@eecs.umich.edu store_idx = 0; 12347639Sgblack@eecs.umich.edu} 12357639Sgblack@eecs.umich.edu 12367639Sgblack@eecs.umich.edutemplate <class Impl> 12377639Sgblack@eecs.umich.eduinline void 12387435Sgblack@eecs.umich.eduLSQUnit<Impl>::decrStIdx(int &store_idx) 12397435Sgblack@eecs.umich.edu{ 12407435Sgblack@eecs.umich.edu if (--store_idx < 0) 12417435Sgblack@eecs.umich.edu store_idx += SQEntries; 12427435Sgblack@eecs.umich.edu} 12437639Sgblack@eecs.umich.edu 12447639Sgblack@eecs.umich.edutemplate <class Impl> 12457639Sgblack@eecs.umich.eduinline void 12467639Sgblack@eecs.umich.eduLSQUnit<Impl>::incrLdIdx(int &load_idx) 12477639Sgblack@eecs.umich.edu{ 12487639Sgblack@eecs.umich.edu if (++load_idx >= LQEntries) 12497639Sgblack@eecs.umich.edu load_idx = 0; 12507639Sgblack@eecs.umich.edu} 12517435Sgblack@eecs.umich.edu 12527435Sgblack@eecs.umich.edutemplate <class Impl> 12537639Sgblack@eecs.umich.eduinline void 12547639Sgblack@eecs.umich.eduLSQUnit<Impl>::decrLdIdx(int &load_idx) 12557639Sgblack@eecs.umich.edu{ 12567639Sgblack@eecs.umich.edu if (--load_idx < 0) 12577639Sgblack@eecs.umich.edu load_idx += LQEntries; 12587639Sgblack@eecs.umich.edu} 12597639Sgblack@eecs.umich.edu 12607639Sgblack@eecs.umich.edutemplate <class Impl> 12617639Sgblack@eecs.umich.eduvoid 12627639Sgblack@eecs.umich.eduLSQUnit<Impl>::dumpInsts() 12637639Sgblack@eecs.umich.edu{ 12647639Sgblack@eecs.umich.edu cprintf("Load store queue: Dumping instructions.\n"); 12657639Sgblack@eecs.umich.edu cprintf("Load queue size: %i\n", loads); 12667639Sgblack@eecs.umich.edu cprintf("Load queue: "); 12677639Sgblack@eecs.umich.edu 12687639Sgblack@eecs.umich.edu int load_idx = loadHead; 12697639Sgblack@eecs.umich.edu 12707639Sgblack@eecs.umich.edu while (load_idx != loadTail && loadQueue[load_idx]) { 12717639Sgblack@eecs.umich.edu cprintf("%s ", loadQueue[load_idx]->pcState()); 12727435Sgblack@eecs.umich.edu 12737639Sgblack@eecs.umich.edu incrLdIdx(load_idx); 12747639Sgblack@eecs.umich.edu } 12757639Sgblack@eecs.umich.edu 12767639Sgblack@eecs.umich.edu cprintf("Store queue size: %i\n", stores); 12777435Sgblack@eecs.umich.edu cprintf("Store queue: "); 12787639Sgblack@eecs.umich.edu 12797639Sgblack@eecs.umich.edu int store_idx = storeHead; 12807639Sgblack@eecs.umich.edu 12817639Sgblack@eecs.umich.edu while (store_idx != storeTail && storeQueue[store_idx].inst) { 12827639Sgblack@eecs.umich.edu cprintf("%s ", storeQueue[store_idx].inst->pcState()); 12837639Sgblack@eecs.umich.edu 12847639Sgblack@eecs.umich.edu incrStIdx(store_idx); 12857639Sgblack@eecs.umich.edu } 12867639Sgblack@eecs.umich.edu 12877639Sgblack@eecs.umich.edu cprintf("\n"); 12887639Sgblack@eecs.umich.edu} 12897639Sgblack@eecs.umich.edu