lsq_unit_impl.hh revision 9944
17322Sgblack@eecs.umich.edu 27322Sgblack@eecs.umich.edu/* 37322Sgblack@eecs.umich.edu * Copyright (c) 2010-2012 ARM Limited 47322Sgblack@eecs.umich.edu * All rights reserved 57322Sgblack@eecs.umich.edu * 67322Sgblack@eecs.umich.edu * The license below extends only to copyright in the software and shall 77322Sgblack@eecs.umich.edu * not be construed as granting a license to any other intellectual 87322Sgblack@eecs.umich.edu * property including but not limited to intellectual property relating 97322Sgblack@eecs.umich.edu * to a hardware implementation of the functionality of the software 107322Sgblack@eecs.umich.edu * licensed hereunder. You may use the software subject to the license 117322Sgblack@eecs.umich.edu * terms below provided that you ensure that this notice is replicated 127322Sgblack@eecs.umich.edu * unmodified and in its entirety in all distributions of the software, 137322Sgblack@eecs.umich.edu * modified or unmodified, in source code or in binary form. 147322Sgblack@eecs.umich.edu * 157322Sgblack@eecs.umich.edu * Copyright (c) 2004-2005 The Regents of The University of Michigan 167322Sgblack@eecs.umich.edu * All rights reserved. 177322Sgblack@eecs.umich.edu * 187322Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without 197322Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are 207322Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright 217322Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer; 227322Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright 237322Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the 247322Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution; 257322Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its 267322Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from 277322Sgblack@eecs.umich.edu * this software without specific prior written permission. 287322Sgblack@eecs.umich.edu * 297322Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 307322Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 317322Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 327322Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 337322Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 347322Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 357322Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 367322Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 377322Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 387322Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 397322Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 407376Sgblack@eecs.umich.edu * 417376Sgblack@eecs.umich.edu * Authors: Kevin Lim 427376Sgblack@eecs.umich.edu * Korey Sewell 437376Sgblack@eecs.umich.edu */ 447376Sgblack@eecs.umich.edu 457376Sgblack@eecs.umich.edu#ifndef __CPU_O3_LSQ_UNIT_IMPL_HH__ 467376Sgblack@eecs.umich.edu#define __CPU_O3_LSQ_UNIT_IMPL_HH__ 477376Sgblack@eecs.umich.edu 487376Sgblack@eecs.umich.edu#include "arch/generic/debugfaults.hh" 497376Sgblack@eecs.umich.edu#include "arch/locked_mem.hh" 507376Sgblack@eecs.umich.edu#include "base/str.hh" 517376Sgblack@eecs.umich.edu#include "config/the_isa.hh" 527376Sgblack@eecs.umich.edu#include "cpu/checker/cpu.hh" 537376Sgblack@eecs.umich.edu#include "cpu/o3/lsq.hh" 547376Sgblack@eecs.umich.edu#include "cpu/o3/lsq_unit.hh" 557376Sgblack@eecs.umich.edu#include "debug/Activity.hh" 567376Sgblack@eecs.umich.edu#include "debug/IEW.hh" 577376Sgblack@eecs.umich.edu#include "debug/LSQUnit.hh" 587376Sgblack@eecs.umich.edu#include "debug/O3PipeView.hh" 597376Sgblack@eecs.umich.edu#include "mem/packet.hh" 607376Sgblack@eecs.umich.edu#include "mem/request.hh" 617376Sgblack@eecs.umich.edu 627376Sgblack@eecs.umich.edutemplate<class Impl> 637376Sgblack@eecs.umich.eduLSQUnit<Impl>::WritebackEvent::WritebackEvent(DynInstPtr &_inst, PacketPtr _pkt, 647376Sgblack@eecs.umich.edu LSQUnit *lsq_ptr) 657376Sgblack@eecs.umich.edu : Event(Default_Pri, AutoDelete), 667376Sgblack@eecs.umich.edu inst(_inst), pkt(_pkt), lsqPtr(lsq_ptr) 677376Sgblack@eecs.umich.edu{ 687376Sgblack@eecs.umich.edu} 697376Sgblack@eecs.umich.edu 707376Sgblack@eecs.umich.edutemplate<class Impl> 717376Sgblack@eecs.umich.eduvoid 727376Sgblack@eecs.umich.eduLSQUnit<Impl>::WritebackEvent::process() 737376Sgblack@eecs.umich.edu{ 747376Sgblack@eecs.umich.edu assert(!lsqPtr->cpu->switchedOut()); 757376Sgblack@eecs.umich.edu 767376Sgblack@eecs.umich.edu lsqPtr->writeback(inst, pkt); 777376Sgblack@eecs.umich.edu 787376Sgblack@eecs.umich.edu if (pkt->senderState) 797376Sgblack@eecs.umich.edu delete pkt->senderState; 807376Sgblack@eecs.umich.edu 817376Sgblack@eecs.umich.edu delete pkt->req; 827376Sgblack@eecs.umich.edu delete pkt; 837376Sgblack@eecs.umich.edu} 847376Sgblack@eecs.umich.edu 857376Sgblack@eecs.umich.edutemplate<class Impl> 867376Sgblack@eecs.umich.educonst char * 877376Sgblack@eecs.umich.eduLSQUnit<Impl>::WritebackEvent::description() const 887376Sgblack@eecs.umich.edu{ 897376Sgblack@eecs.umich.edu return "Store writeback"; 907376Sgblack@eecs.umich.edu} 917376Sgblack@eecs.umich.edu 927376Sgblack@eecs.umich.edutemplate<class Impl> 937376Sgblack@eecs.umich.eduvoid 947376Sgblack@eecs.umich.eduLSQUnit<Impl>::completeDataAccess(PacketPtr pkt) 957376Sgblack@eecs.umich.edu{ 967376Sgblack@eecs.umich.edu LSQSenderState *state = dynamic_cast<LSQSenderState *>(pkt->senderState); 977376Sgblack@eecs.umich.edu DynInstPtr inst = state->inst; 987376Sgblack@eecs.umich.edu DPRINTF(IEW, "Writeback event [sn:%lli].\n", inst->seqNum); 997376Sgblack@eecs.umich.edu DPRINTF(Activity, "Activity: Writeback event [sn:%lli].\n", inst->seqNum); 1007376Sgblack@eecs.umich.edu 1017376Sgblack@eecs.umich.edu //iewStage->ldstQueue.removeMSHR(inst->threadNumber,inst->seqNum); 1027376Sgblack@eecs.umich.edu 1037376Sgblack@eecs.umich.edu // If this is a split access, wait until all packets are received. 1047376Sgblack@eecs.umich.edu if (TheISA::HasUnalignedMemAcc && !state->complete()) { 1057376Sgblack@eecs.umich.edu delete pkt->req; 1067376Sgblack@eecs.umich.edu delete pkt; 1077376Sgblack@eecs.umich.edu return; 1087376Sgblack@eecs.umich.edu } 1097376Sgblack@eecs.umich.edu 1107376Sgblack@eecs.umich.edu assert(!cpu->switchedOut()); 1117376Sgblack@eecs.umich.edu if (inst->isSquashed()) { 1127376Sgblack@eecs.umich.edu iewStage->decrWb(inst->seqNum); 1137376Sgblack@eecs.umich.edu } else { 1147376Sgblack@eecs.umich.edu if (!state->noWB) { 1157376Sgblack@eecs.umich.edu if (!TheISA::HasUnalignedMemAcc || !state->isSplit || 1167376Sgblack@eecs.umich.edu !state->isLoad) { 1177376Sgblack@eecs.umich.edu writeback(inst, pkt); 1187376Sgblack@eecs.umich.edu } else { 1197376Sgblack@eecs.umich.edu writeback(inst, state->mainPkt); 1207376Sgblack@eecs.umich.edu } 1217376Sgblack@eecs.umich.edu } 1227376Sgblack@eecs.umich.edu 1237376Sgblack@eecs.umich.edu if (inst->isStore()) { 1247376Sgblack@eecs.umich.edu completeStore(state->idx); 1257376Sgblack@eecs.umich.edu } 1267376Sgblack@eecs.umich.edu } 1277376Sgblack@eecs.umich.edu 1287376Sgblack@eecs.umich.edu if (TheISA::HasUnalignedMemAcc && state->isSplit && state->isLoad) { 1297376Sgblack@eecs.umich.edu delete state->mainPkt->req; 1307376Sgblack@eecs.umich.edu delete state->mainPkt; 1317376Sgblack@eecs.umich.edu } 1327376Sgblack@eecs.umich.edu delete state; 1337376Sgblack@eecs.umich.edu delete pkt->req; 1347376Sgblack@eecs.umich.edu delete pkt; 1357376Sgblack@eecs.umich.edu} 1367376Sgblack@eecs.umich.edu 1377376Sgblack@eecs.umich.edutemplate <class Impl> 1387376Sgblack@eecs.umich.eduLSQUnit<Impl>::LSQUnit() 1397376Sgblack@eecs.umich.edu : loads(0), stores(0), storesToWB(0), cacheBlockMask(0), stalled(false), 1407376Sgblack@eecs.umich.edu isStoreBlocked(false), isLoadBlocked(false), 1417376Sgblack@eecs.umich.edu loadBlockedHandled(false), storeInFlight(false), hasPendingPkt(false) 1427376Sgblack@eecs.umich.edu{ 1437376Sgblack@eecs.umich.edu} 1447376Sgblack@eecs.umich.edu 1457376Sgblack@eecs.umich.edutemplate<class Impl> 1467376Sgblack@eecs.umich.eduvoid 1477376Sgblack@eecs.umich.eduLSQUnit<Impl>::init(O3CPU *cpu_ptr, IEW *iew_ptr, DerivO3CPUParams *params, 1487376Sgblack@eecs.umich.edu LSQ *lsq_ptr, unsigned maxLQEntries, unsigned maxSQEntries, 1497376Sgblack@eecs.umich.edu unsigned id) 1507376Sgblack@eecs.umich.edu{ 1517376Sgblack@eecs.umich.edu cpu = cpu_ptr; 1527376Sgblack@eecs.umich.edu iewStage = iew_ptr; 1537376Sgblack@eecs.umich.edu 1547376Sgblack@eecs.umich.edu DPRINTF(LSQUnit, "Creating LSQUnit%i object.\n",id); 1557376Sgblack@eecs.umich.edu 1567376Sgblack@eecs.umich.edu lsq = lsq_ptr; 1577376Sgblack@eecs.umich.edu 1587376Sgblack@eecs.umich.edu lsqID = id; 1597376Sgblack@eecs.umich.edu 1607376Sgblack@eecs.umich.edu // Add 1 for the sentinel entry (they are circular queues). 1617376Sgblack@eecs.umich.edu LQEntries = maxLQEntries + 1; 1627376Sgblack@eecs.umich.edu SQEntries = maxSQEntries + 1; 1637376Sgblack@eecs.umich.edu 1647376Sgblack@eecs.umich.edu //Due to uint8_t index in LSQSenderState 1657376Sgblack@eecs.umich.edu assert(LQEntries <= 256); 1667376Sgblack@eecs.umich.edu assert(SQEntries <= 256); 1677376Sgblack@eecs.umich.edu 1687376Sgblack@eecs.umich.edu loadQueue.resize(LQEntries); 1697376Sgblack@eecs.umich.edu storeQueue.resize(SQEntries); 1707376Sgblack@eecs.umich.edu 1717376Sgblack@eecs.umich.edu depCheckShift = params->LSQDepCheckShift; 1727376Sgblack@eecs.umich.edu checkLoads = params->LSQCheckLoads; 1737376Sgblack@eecs.umich.edu cachePorts = params->cachePorts; 1747376Sgblack@eecs.umich.edu needsTSO = params->needsTSO; 1757376Sgblack@eecs.umich.edu 1767376Sgblack@eecs.umich.edu resetState(); 1777376Sgblack@eecs.umich.edu} 1787376Sgblack@eecs.umich.edu 1797376Sgblack@eecs.umich.edu 1807376Sgblack@eecs.umich.edutemplate<class Impl> 1817376Sgblack@eecs.umich.eduvoid 1827376Sgblack@eecs.umich.eduLSQUnit<Impl>::resetState() 1837376Sgblack@eecs.umich.edu{ 1847376Sgblack@eecs.umich.edu loads = stores = storesToWB = 0; 1857376Sgblack@eecs.umich.edu 1867376Sgblack@eecs.umich.edu loadHead = loadTail = 0; 1877376Sgblack@eecs.umich.edu 1887322Sgblack@eecs.umich.edu storeHead = storeWBIdx = storeTail = 0; 1897322Sgblack@eecs.umich.edu 1907322Sgblack@eecs.umich.edu usedPorts = 0; 1917322Sgblack@eecs.umich.edu 1927322Sgblack@eecs.umich.edu retryPkt = NULL; 1937322Sgblack@eecs.umich.edu memDepViolator = NULL; 1947396Sgblack@eecs.umich.edu 1957644Sali.saidi@arm.com blockedLoadSeqNum = 0; 1967640Sgblack@eecs.umich.edu 1977648SAli.Saidi@ARM.com stalled = false; 1987648SAli.Saidi@ARM.com isLoadBlocked = false; 1997396Sgblack@eecs.umich.edu loadBlockedHandled = false; 2007396Sgblack@eecs.umich.edu 2017322Sgblack@eecs.umich.edu cacheBlockMask = ~(cpu->cacheLineSize() - 1); 2027324Sgblack@eecs.umich.edu} 2037644Sali.saidi@arm.com 2047643Sgblack@eecs.umich.edutemplate<class Impl> 2057643Sgblack@eecs.umich.edustd::string 2067643Sgblack@eecs.umich.eduLSQUnit<Impl>::name() const 2077643Sgblack@eecs.umich.edu{ 2087643Sgblack@eecs.umich.edu if (Impl::MaxThreads == 1) { 2097643Sgblack@eecs.umich.edu return iewStage->name() + ".lsq"; 2107643Sgblack@eecs.umich.edu } else { 2117643Sgblack@eecs.umich.edu return iewStage->name() + ".lsq.thread" + to_string(lsqID); 2127643Sgblack@eecs.umich.edu } 2137643Sgblack@eecs.umich.edu} 2147396Sgblack@eecs.umich.edu 2157644Sali.saidi@arm.comtemplate<class Impl> 2167640Sgblack@eecs.umich.eduvoid 2177324Sgblack@eecs.umich.eduLSQUnit<Impl>::regStats() 2187396Sgblack@eecs.umich.edu{ 2197396Sgblack@eecs.umich.edu lsqForwLoads 2207324Sgblack@eecs.umich.edu .name(name() + ".forwLoads") 2217333Sgblack@eecs.umich.edu .desc("Number of loads that had data forwarded from stores"); 2227643Sgblack@eecs.umich.edu 2237644Sali.saidi@arm.com invAddrLoads 2247643Sgblack@eecs.umich.edu .name(name() + ".invAddrLoads") 2257643Sgblack@eecs.umich.edu .desc("Number of loads ignored due to an invalid address"); 2267643Sgblack@eecs.umich.edu 2277643Sgblack@eecs.umich.edu lsqSquashedLoads 2287643Sgblack@eecs.umich.edu .name(name() + ".squashedLoads") 2297643Sgblack@eecs.umich.edu .desc("Number of loads squashed"); 2307644Sali.saidi@arm.com 2317643Sgblack@eecs.umich.edu lsqIgnoredResponses 2327643Sgblack@eecs.umich.edu .name(name() + ".ignoredResponses") 2337396Sgblack@eecs.umich.edu .desc("Number of memory responses ignored because the instruction is squashed"); 2347392Sgblack@eecs.umich.edu 2357392Sgblack@eecs.umich.edu lsqMemOrderViolation 2367396Sgblack@eecs.umich.edu .name(name() + ".memOrderViolation") 2377396Sgblack@eecs.umich.edu .desc("Number of memory ordering violations"); 2387392Sgblack@eecs.umich.edu 2397392Sgblack@eecs.umich.edu lsqSquashedStores 2407644Sali.saidi@arm.com .name(name() + ".squashedStores") 2417643Sgblack@eecs.umich.edu .desc("Number of stores squashed"); 2427643Sgblack@eecs.umich.edu 2437643Sgblack@eecs.umich.edu invAddrSwpfs 2447643Sgblack@eecs.umich.edu .name(name() + ".invAddrSwpfs") 2457643Sgblack@eecs.umich.edu .desc("Number of software prefetches ignored due to an invalid address"); 2467643Sgblack@eecs.umich.edu 2477643Sgblack@eecs.umich.edu lsqBlockedLoads 2487643Sgblack@eecs.umich.edu .name(name() + ".blockedLoads") 2497643Sgblack@eecs.umich.edu .desc("Number of blocked loads due to partial load-store forwarding"); 2507643Sgblack@eecs.umich.edu 2517640Sgblack@eecs.umich.edu lsqRescheduledLoads 2527333Sgblack@eecs.umich.edu .name(name() + ".rescheduledLoads") 2537333Sgblack@eecs.umich.edu .desc("Number of loads that were rescheduled"); 2547396Sgblack@eecs.umich.edu 2557333Sgblack@eecs.umich.edu lsqCacheBlocked 2567333Sgblack@eecs.umich.edu .name(name() + ".cacheBlocked") 2577396Sgblack@eecs.umich.edu .desc("Number of times an access to memory failed due to the cache being blocked"); 2587396Sgblack@eecs.umich.edu} 2597333Sgblack@eecs.umich.edu 2607333Sgblack@eecs.umich.edutemplate<class Impl> 2617640Sgblack@eecs.umich.eduvoid 2627333Sgblack@eecs.umich.eduLSQUnit<Impl>::setDcachePort(MasterPort *dcache_port) 2637333Sgblack@eecs.umich.edu{ 2647333Sgblack@eecs.umich.edu dcachePort = dcache_port; 2657396Sgblack@eecs.umich.edu} 2667333Sgblack@eecs.umich.edu 2677333Sgblack@eecs.umich.edutemplate<class Impl> 2687396Sgblack@eecs.umich.eduvoid 2697396Sgblack@eecs.umich.eduLSQUnit<Impl>::clearLQ() 2707333Sgblack@eecs.umich.edu{ 2717333Sgblack@eecs.umich.edu loadQueue.clear(); 2727640Sgblack@eecs.umich.edu} 2737333Sgblack@eecs.umich.edu 2747333Sgblack@eecs.umich.edutemplate<class Impl> 2757333Sgblack@eecs.umich.eduvoid 2767333Sgblack@eecs.umich.eduLSQUnit<Impl>::clearSQ() 2777333Sgblack@eecs.umich.edu{ 2787396Sgblack@eecs.umich.edu storeQueue.clear(); 2797333Sgblack@eecs.umich.edu} 2807333Sgblack@eecs.umich.edu 2817396Sgblack@eecs.umich.edutemplate<class Impl> 2827396Sgblack@eecs.umich.eduvoid 2837333Sgblack@eecs.umich.eduLSQUnit<Impl>::drainSanityCheck() const 2847333Sgblack@eecs.umich.edu{ 2857640Sgblack@eecs.umich.edu for (int i = 0; i < loadQueue.size(); ++i) 2867333Sgblack@eecs.umich.edu assert(!loadQueue[i]); 2877333Sgblack@eecs.umich.edu 2887396Sgblack@eecs.umich.edu assert(storesToWB == 0); 2897333Sgblack@eecs.umich.edu assert(!retryPkt); 2907333Sgblack@eecs.umich.edu} 2917396Sgblack@eecs.umich.edu 2927396Sgblack@eecs.umich.edutemplate<class Impl> 2937333Sgblack@eecs.umich.eduvoid 2947333Sgblack@eecs.umich.eduLSQUnit<Impl>::takeOverFrom() 2957640Sgblack@eecs.umich.edu{ 2967333Sgblack@eecs.umich.edu resetState(); 2977333Sgblack@eecs.umich.edu} 2987333Sgblack@eecs.umich.edu 2997396Sgblack@eecs.umich.edutemplate<class Impl> 3007333Sgblack@eecs.umich.eduvoid 3017333Sgblack@eecs.umich.eduLSQUnit<Impl>::resizeLQ(unsigned size) 3027396Sgblack@eecs.umich.edu{ 3037396Sgblack@eecs.umich.edu unsigned size_plus_sentinel = size + 1; 3047333Sgblack@eecs.umich.edu assert(size_plus_sentinel >= LQEntries); 3057333Sgblack@eecs.umich.edu 3067640Sgblack@eecs.umich.edu if (size_plus_sentinel > LQEntries) { 3077333Sgblack@eecs.umich.edu while (size_plus_sentinel > loadQueue.size()) { 3087333Sgblack@eecs.umich.edu DynInstPtr dummy; 3097333Sgblack@eecs.umich.edu loadQueue.push_back(dummy); 3107333Sgblack@eecs.umich.edu LQEntries++; 3117333Sgblack@eecs.umich.edu } 3127396Sgblack@eecs.umich.edu } else { 3137333Sgblack@eecs.umich.edu LQEntries = size_plus_sentinel; 3147333Sgblack@eecs.umich.edu } 3157396Sgblack@eecs.umich.edu 3167396Sgblack@eecs.umich.edu assert(LQEntries <= 256); 3177333Sgblack@eecs.umich.edu} 3187333Sgblack@eecs.umich.edu 3197640Sgblack@eecs.umich.edutemplate<class Impl> 3207639Sgblack@eecs.umich.eduvoid 3217333Sgblack@eecs.umich.eduLSQUnit<Impl>::resizeSQ(unsigned size) 3227396Sgblack@eecs.umich.edu{ 3237333Sgblack@eecs.umich.edu unsigned size_plus_sentinel = size + 1; 3247333Sgblack@eecs.umich.edu if (size_plus_sentinel > SQEntries) { 3257396Sgblack@eecs.umich.edu while (size_plus_sentinel > storeQueue.size()) { 3267396Sgblack@eecs.umich.edu SQEntry dummy; 3277333Sgblack@eecs.umich.edu storeQueue.push_back(dummy); 3287333Sgblack@eecs.umich.edu SQEntries++; 3297640Sgblack@eecs.umich.edu } 3307639Sgblack@eecs.umich.edu } else { 3317333Sgblack@eecs.umich.edu SQEntries = size_plus_sentinel; 3327396Sgblack@eecs.umich.edu } 3337333Sgblack@eecs.umich.edu 3347333Sgblack@eecs.umich.edu assert(SQEntries <= 256); 3357396Sgblack@eecs.umich.edu} 3367396Sgblack@eecs.umich.edu 3377333Sgblack@eecs.umich.edutemplate <class Impl> 3387333Sgblack@eecs.umich.eduvoid 3397640Sgblack@eecs.umich.eduLSQUnit<Impl>::insert(DynInstPtr &inst) 3407333Sgblack@eecs.umich.edu{ 3417333Sgblack@eecs.umich.edu assert(inst->isMemRef()); 3427396Sgblack@eecs.umich.edu 3437333Sgblack@eecs.umich.edu assert(inst->isLoad() || inst->isStore()); 3447333Sgblack@eecs.umich.edu 3457396Sgblack@eecs.umich.edu if (inst->isLoad()) { 3467396Sgblack@eecs.umich.edu insertLoad(inst); 3477333Sgblack@eecs.umich.edu } else { 3487333Sgblack@eecs.umich.edu insertStore(inst); 3497640Sgblack@eecs.umich.edu } 3507639Sgblack@eecs.umich.edu 3517639Sgblack@eecs.umich.edu inst->setInLSQ(); 3527333Sgblack@eecs.umich.edu} 3537396Sgblack@eecs.umich.edu 3547333Sgblack@eecs.umich.edutemplate <class Impl> 3557333Sgblack@eecs.umich.eduvoid 3567396Sgblack@eecs.umich.eduLSQUnit<Impl>::insertLoad(DynInstPtr &load_inst) 3577396Sgblack@eecs.umich.edu{ 3587333Sgblack@eecs.umich.edu assert((loadTail + 1) % LQEntries != loadHead); 3597333Sgblack@eecs.umich.edu assert(loads < LQEntries); 3607640Sgblack@eecs.umich.edu 3617639Sgblack@eecs.umich.edu DPRINTF(LSQUnit, "Inserting load PC %s, idx:%i [sn:%lli]\n", 3627639Sgblack@eecs.umich.edu load_inst->pcState(), loadTail, load_inst->seqNum); 3637333Sgblack@eecs.umich.edu 3647396Sgblack@eecs.umich.edu load_inst->lqIdx = loadTail; 3657333Sgblack@eecs.umich.edu 3667333Sgblack@eecs.umich.edu if (stores == 0) { 3677396Sgblack@eecs.umich.edu load_inst->sqIdx = -1; 3687396Sgblack@eecs.umich.edu } else { 3697333Sgblack@eecs.umich.edu load_inst->sqIdx = storeTail; 3707333Sgblack@eecs.umich.edu } 3717640Sgblack@eecs.umich.edu 3727639Sgblack@eecs.umich.edu loadQueue[loadTail] = load_inst; 3737639Sgblack@eecs.umich.edu 3747333Sgblack@eecs.umich.edu incrLdIdx(loadTail); 3757396Sgblack@eecs.umich.edu 3767333Sgblack@eecs.umich.edu ++loads; 3777333Sgblack@eecs.umich.edu} 3787396Sgblack@eecs.umich.edu 3797396Sgblack@eecs.umich.edutemplate <class Impl> 3807333Sgblack@eecs.umich.eduvoid 3817333Sgblack@eecs.umich.eduLSQUnit<Impl>::insertStore(DynInstPtr &store_inst) 3827640Sgblack@eecs.umich.edu{ 3837639Sgblack@eecs.umich.edu // Make sure it is not full before inserting an instruction. 3847639Sgblack@eecs.umich.edu assert((storeTail + 1) % SQEntries != storeHead); 3857333Sgblack@eecs.umich.edu assert(stores < SQEntries); 3867396Sgblack@eecs.umich.edu 3877333Sgblack@eecs.umich.edu DPRINTF(LSQUnit, "Inserting store PC %s, idx:%i [sn:%lli]\n", 3887333Sgblack@eecs.umich.edu store_inst->pcState(), storeTail, store_inst->seqNum); 3897396Sgblack@eecs.umich.edu 3907396Sgblack@eecs.umich.edu store_inst->sqIdx = storeTail; 3917333Sgblack@eecs.umich.edu store_inst->lqIdx = loadTail; 3927333Sgblack@eecs.umich.edu 3937640Sgblack@eecs.umich.edu storeQueue[storeTail] = SQEntry(store_inst); 3947333Sgblack@eecs.umich.edu 3957333Sgblack@eecs.umich.edu incrStIdx(storeTail); 3967396Sgblack@eecs.umich.edu 3977333Sgblack@eecs.umich.edu ++stores; 3987333Sgblack@eecs.umich.edu} 3997396Sgblack@eecs.umich.edu 4007396Sgblack@eecs.umich.edutemplate <class Impl> 4017333Sgblack@eecs.umich.edutypename Impl::DynInstPtr 4027333Sgblack@eecs.umich.eduLSQUnit<Impl>::getMemDepViolator() 4037640Sgblack@eecs.umich.edu{ 4047333Sgblack@eecs.umich.edu DynInstPtr temp = memDepViolator; 4057333Sgblack@eecs.umich.edu 4067333Sgblack@eecs.umich.edu memDepViolator = NULL; 4077396Sgblack@eecs.umich.edu 4087333Sgblack@eecs.umich.edu return temp; 4097333Sgblack@eecs.umich.edu} 4107396Sgblack@eecs.umich.edu 4117396Sgblack@eecs.umich.edutemplate <class Impl> 4127333Sgblack@eecs.umich.eduunsigned 4137333Sgblack@eecs.umich.eduLSQUnit<Impl>::numFreeEntries() 4147640Sgblack@eecs.umich.edu{ 4157333Sgblack@eecs.umich.edu unsigned free_lq_entries = LQEntries - loads; 4167333Sgblack@eecs.umich.edu unsigned free_sq_entries = SQEntries - stores; 4177333Sgblack@eecs.umich.edu 4187396Sgblack@eecs.umich.edu // Both the LQ and SQ entries have an extra dummy entry to differentiate 4197333Sgblack@eecs.umich.edu // empty/full conditions. Subtract 1 from the free entries. 4207333Sgblack@eecs.umich.edu if (free_lq_entries < free_sq_entries) { 4217396Sgblack@eecs.umich.edu return free_lq_entries - 1; 4227396Sgblack@eecs.umich.edu } else { 4237333Sgblack@eecs.umich.edu return free_sq_entries - 1; 4247381Sgblack@eecs.umich.edu } 4257381Sgblack@eecs.umich.edu} 4267381Sgblack@eecs.umich.edu 4277381Sgblack@eecs.umich.edutemplate <class Impl> 4287381Sgblack@eecs.umich.eduvoid 4297381Sgblack@eecs.umich.eduLSQUnit<Impl>::checkSnoop(PacketPtr pkt) 4307381Sgblack@eecs.umich.edu{ 4317364Sgblack@eecs.umich.edu int load_idx = loadHead; 4327640Sgblack@eecs.umich.edu 4337643Sgblack@eecs.umich.edu // Unlock the cpu-local monitor when the CPU sees a snoop to a locked 4347396Sgblack@eecs.umich.edu // address. The CPU can speculatively execute a LL operation after a pending 4357643Sgblack@eecs.umich.edu // SC operation in the pipeline and that can make the cache monitor the CPU 4367364Sgblack@eecs.umich.edu // is connected to valid while it really shouldn't be. 4377396Sgblack@eecs.umich.edu for (int x = 0; x < cpu->numActiveThreads(); x++) { 4387639Sgblack@eecs.umich.edu ThreadContext *tc = cpu->getContext(x); 4397396Sgblack@eecs.umich.edu bool no_squash = cpu->thread[x]->noSquashFromTC; 4407640Sgblack@eecs.umich.edu cpu->thread[x]->noSquashFromTC = true; 4417643Sgblack@eecs.umich.edu TheISA::handleLockedSnoop(tc, pkt, cacheBlockMask); 4427396Sgblack@eecs.umich.edu cpu->thread[x]->noSquashFromTC = no_squash; 4437643Sgblack@eecs.umich.edu } 4447396Sgblack@eecs.umich.edu 4457396Sgblack@eecs.umich.edu // If this is the only load in the LSQ we don't care 4467396Sgblack@eecs.umich.edu if (load_idx == loadTail) 4477396Sgblack@eecs.umich.edu return; 4487396Sgblack@eecs.umich.edu incrLdIdx(load_idx); 4497396Sgblack@eecs.umich.edu 4507639Sgblack@eecs.umich.edu DPRINTF(LSQUnit, "Got snoop for address %#x\n", pkt->getAddr()); 4517396Sgblack@eecs.umich.edu Addr invalidate_addr = pkt->getAddr() & cacheBlockMask; 4527396Sgblack@eecs.umich.edu while (load_idx != loadTail) { 4537396Sgblack@eecs.umich.edu DynInstPtr ld_inst = loadQueue[load_idx]; 4547396Sgblack@eecs.umich.edu 4557396Sgblack@eecs.umich.edu if (!ld_inst->effAddrValid() || ld_inst->uncacheable()) { 4567364Sgblack@eecs.umich.edu incrLdIdx(load_idx); 4577396Sgblack@eecs.umich.edu continue; 4587396Sgblack@eecs.umich.edu } 4597365Sgblack@eecs.umich.edu 4607396Sgblack@eecs.umich.edu Addr load_addr = ld_inst->physEffAddr & cacheBlockMask; 4617396Sgblack@eecs.umich.edu DPRINTF(LSQUnit, "-- inst [sn:%lli] load_addr: %#x to pktAddr:%#x\n", 4627396Sgblack@eecs.umich.edu ld_inst->seqNum, load_addr, invalidate_addr); 4637396Sgblack@eecs.umich.edu 4647396Sgblack@eecs.umich.edu if (load_addr == invalidate_addr) { 4657396Sgblack@eecs.umich.edu if (ld_inst->possibleLoadViolation()) { 4667396Sgblack@eecs.umich.edu DPRINTF(LSQUnit, "Conflicting load at addr %#x [sn:%lli]\n", 4677396Sgblack@eecs.umich.edu ld_inst->physEffAddr, pkt->getAddr(), ld_inst->seqNum); 4687365Sgblack@eecs.umich.edu 4697396Sgblack@eecs.umich.edu // Mark the load for re-execution 4707396Sgblack@eecs.umich.edu ld_inst->fault = new ReExec; 4717366Sgblack@eecs.umich.edu } else { 4727396Sgblack@eecs.umich.edu // If a older load checks this and it's true 4737396Sgblack@eecs.umich.edu // then we might have missed the snoop 4747396Sgblack@eecs.umich.edu // in which case we need to invalidate to be sure 4757396Sgblack@eecs.umich.edu ld_inst->hitExternalSnoop(true); 4767366Sgblack@eecs.umich.edu } 4777396Sgblack@eecs.umich.edu } 4787396Sgblack@eecs.umich.edu incrLdIdx(load_idx); 4797396Sgblack@eecs.umich.edu } 4807396Sgblack@eecs.umich.edu return; 4817367Sgblack@eecs.umich.edu} 4827396Sgblack@eecs.umich.edu 4837396Sgblack@eecs.umich.edutemplate <class Impl> 4847396Sgblack@eecs.umich.eduFault 4857396Sgblack@eecs.umich.eduLSQUnit<Impl>::checkViolations(int load_idx, DynInstPtr &inst) 4867367Sgblack@eecs.umich.edu{ 4877396Sgblack@eecs.umich.edu Addr inst_eff_addr1 = inst->effAddr >> depCheckShift; 4887396Sgblack@eecs.umich.edu Addr inst_eff_addr2 = (inst->effAddr + inst->effSize - 1) >> depCheckShift; 4897396Sgblack@eecs.umich.edu 4907396Sgblack@eecs.umich.edu /** @todo in theory you only need to check an instruction that has executed 4917396Sgblack@eecs.umich.edu * however, there isn't a good way in the pipeline at the moment to check 4927396Sgblack@eecs.umich.edu * all instructions that will execute before the store writes back. Thus, 4937396Sgblack@eecs.umich.edu * like the implementation that came before it, we're overly conservative. 4947396Sgblack@eecs.umich.edu */ 4957368Sgblack@eecs.umich.edu while (load_idx != loadTail) { 4967396Sgblack@eecs.umich.edu DynInstPtr ld_inst = loadQueue[load_idx]; 4977396Sgblack@eecs.umich.edu if (!ld_inst->effAddrValid() || ld_inst->uncacheable()) { 4987368Sgblack@eecs.umich.edu incrLdIdx(load_idx); 4997396Sgblack@eecs.umich.edu continue; 5007396Sgblack@eecs.umich.edu } 5017396Sgblack@eecs.umich.edu 5027396Sgblack@eecs.umich.edu Addr ld_eff_addr1 = ld_inst->effAddr >> depCheckShift; 5037369Sgblack@eecs.umich.edu Addr ld_eff_addr2 = 5047396Sgblack@eecs.umich.edu (ld_inst->effAddr + ld_inst->effSize - 1) >> depCheckShift; 5057369Sgblack@eecs.umich.edu 5067396Sgblack@eecs.umich.edu if (inst_eff_addr2 >= ld_eff_addr1 && inst_eff_addr1 <= ld_eff_addr2) { 5077396Sgblack@eecs.umich.edu if (inst->isLoad()) { 5087396Sgblack@eecs.umich.edu // If this load is to the same block as an external snoop 5097396Sgblack@eecs.umich.edu // invalidate that we've observed then the load needs to be 5107369Sgblack@eecs.umich.edu // squashed as it could have newer data 5117396Sgblack@eecs.umich.edu if (ld_inst->hitExternalSnoop()) { 5127396Sgblack@eecs.umich.edu if (!memDepViolator || 5137396Sgblack@eecs.umich.edu ld_inst->seqNum < memDepViolator->seqNum) { 5147396Sgblack@eecs.umich.edu DPRINTF(LSQUnit, "Detected fault with inst [sn:%lli] " 5157396Sgblack@eecs.umich.edu "and [sn:%lli] at address %#x\n", 5167396Sgblack@eecs.umich.edu inst->seqNum, ld_inst->seqNum, ld_eff_addr1); 5177369Sgblack@eecs.umich.edu memDepViolator = ld_inst; 5187396Sgblack@eecs.umich.edu 5197396Sgblack@eecs.umich.edu ++lsqMemOrderViolation; 5207396Sgblack@eecs.umich.edu 5217396Sgblack@eecs.umich.edu return new GenericISA::M5PanicFault( 5227396Sgblack@eecs.umich.edu "Detected fault with inst [sn:%lli] and " 5237396Sgblack@eecs.umich.edu "[sn:%lli] at address %#x\n", 5247396Sgblack@eecs.umich.edu inst->seqNum, ld_inst->seqNum, ld_eff_addr1); 5257396Sgblack@eecs.umich.edu } 5267396Sgblack@eecs.umich.edu } 5277396Sgblack@eecs.umich.edu 5287396Sgblack@eecs.umich.edu // Otherwise, mark the load has a possible load violation 5297396Sgblack@eecs.umich.edu // and if we see a snoop before it's commited, we need to squash 5307381Sgblack@eecs.umich.edu ld_inst->possibleLoadViolation(true); 5317381Sgblack@eecs.umich.edu DPRINTF(LSQUnit, "Found possible load violaiton at addr: %#x" 5327381Sgblack@eecs.umich.edu " between instructions [sn:%lli] and [sn:%lli]\n", 5337381Sgblack@eecs.umich.edu inst_eff_addr1, inst->seqNum, ld_inst->seqNum); 5347381Sgblack@eecs.umich.edu } else { 5357381Sgblack@eecs.umich.edu // A load/store incorrectly passed this store. 5367381Sgblack@eecs.umich.edu // Check if we already have a violator, or if it's newer 5377370Sgblack@eecs.umich.edu // squash and refetch. 5387640Sgblack@eecs.umich.edu if (memDepViolator && ld_inst->seqNum > memDepViolator->seqNum) 5397643Sgblack@eecs.umich.edu break; 5407396Sgblack@eecs.umich.edu 5417639Sgblack@eecs.umich.edu DPRINTF(LSQUnit, "Detected fault with inst [sn:%lli] and " 5427639Sgblack@eecs.umich.edu "[sn:%lli] at address %#x\n", 5437639Sgblack@eecs.umich.edu inst->seqNum, ld_inst->seqNum, ld_eff_addr1); 5447643Sgblack@eecs.umich.edu memDepViolator = ld_inst; 5457370Sgblack@eecs.umich.edu 5467396Sgblack@eecs.umich.edu ++lsqMemOrderViolation; 5477370Sgblack@eecs.umich.edu 5487370Sgblack@eecs.umich.edu return new GenericISA::M5PanicFault("Detected fault with " 5497396Sgblack@eecs.umich.edu "inst [sn:%lli] and [sn:%lli] at address %#x\n", 5507396Sgblack@eecs.umich.edu inst->seqNum, ld_inst->seqNum, ld_eff_addr1); 5517370Sgblack@eecs.umich.edu } 5527370Sgblack@eecs.umich.edu } 5537640Sgblack@eecs.umich.edu 5547643Sgblack@eecs.umich.edu incrLdIdx(load_idx); 5557396Sgblack@eecs.umich.edu } 5567396Sgblack@eecs.umich.edu return NoFault; 5577639Sgblack@eecs.umich.edu} 5587396Sgblack@eecs.umich.edu 5597639Sgblack@eecs.umich.edu 5607639Sgblack@eecs.umich.edu 5617643Sgblack@eecs.umich.edu 5627396Sgblack@eecs.umich.edutemplate <class Impl> 5637396Sgblack@eecs.umich.eduFault 5647370Sgblack@eecs.umich.eduLSQUnit<Impl>::executeLoad(DynInstPtr &inst) 5657396Sgblack@eecs.umich.edu{ 5667370Sgblack@eecs.umich.edu using namespace TheISA; 5677370Sgblack@eecs.umich.edu // Execute a specific load. 5687396Sgblack@eecs.umich.edu Fault load_fault = NoFault; 5697396Sgblack@eecs.umich.edu 5707370Sgblack@eecs.umich.edu DPRINTF(LSQUnit, "Executing load PC %s, [sn:%lli]\n", 5717370Sgblack@eecs.umich.edu inst->pcState(), inst->seqNum); 5727640Sgblack@eecs.umich.edu 5737643Sgblack@eecs.umich.edu assert(!inst->isSquashed()); 5747396Sgblack@eecs.umich.edu 5757639Sgblack@eecs.umich.edu load_fault = inst->initiateAcc(); 5767639Sgblack@eecs.umich.edu 5777639Sgblack@eecs.umich.edu if (inst->isTranslationDelayed() && 5787643Sgblack@eecs.umich.edu load_fault == NoFault) 5797370Sgblack@eecs.umich.edu return load_fault; 5807396Sgblack@eecs.umich.edu 5817370Sgblack@eecs.umich.edu // If the instruction faulted or predicated false, then we need to send it 5827370Sgblack@eecs.umich.edu // along to commit without the instruction completing. 5837396Sgblack@eecs.umich.edu if (load_fault != NoFault || inst->readPredicate() == false) { 5847396Sgblack@eecs.umich.edu // Send this instruction to commit, also make sure iew stage 5857370Sgblack@eecs.umich.edu // realizes there is activity. 5867370Sgblack@eecs.umich.edu // Mark it as executed unless it is an uncached load that 5877640Sgblack@eecs.umich.edu // needs to hit the head of commit. 5887643Sgblack@eecs.umich.edu if (inst->readPredicate() == false) 5897396Sgblack@eecs.umich.edu inst->forwardOldRegs(); 5907396Sgblack@eecs.umich.edu DPRINTF(LSQUnit, "Load [sn:%lli] not executed from %s\n", 5917639Sgblack@eecs.umich.edu inst->seqNum, 5927396Sgblack@eecs.umich.edu (load_fault != NoFault ? "fault" : "predication")); 5937639Sgblack@eecs.umich.edu if (!(inst->hasRequest() && inst->uncacheable()) || 5947639Sgblack@eecs.umich.edu inst->isAtCommit()) { 5957643Sgblack@eecs.umich.edu inst->setExecuted(); 5967396Sgblack@eecs.umich.edu } 5977396Sgblack@eecs.umich.edu iewStage->instToCommit(inst); 5987370Sgblack@eecs.umich.edu iewStage->activityThisCycle(); 5997396Sgblack@eecs.umich.edu } else if (!loadBlocked()) { 6007370Sgblack@eecs.umich.edu assert(inst->effAddrValid()); 6017370Sgblack@eecs.umich.edu int load_idx = inst->lqIdx; 6027396Sgblack@eecs.umich.edu incrLdIdx(load_idx); 6037396Sgblack@eecs.umich.edu 6047370Sgblack@eecs.umich.edu if (checkLoads) 6057371Sgblack@eecs.umich.edu return checkViolations(load_idx, inst); 6067640Sgblack@eecs.umich.edu } 6077643Sgblack@eecs.umich.edu 6087396Sgblack@eecs.umich.edu return load_fault; 6097639Sgblack@eecs.umich.edu} 6107639Sgblack@eecs.umich.edu 6117639Sgblack@eecs.umich.edutemplate <class Impl> 6127643Sgblack@eecs.umich.eduFault 6137371Sgblack@eecs.umich.eduLSQUnit<Impl>::executeStore(DynInstPtr &store_inst) 6147396Sgblack@eecs.umich.edu{ 6157371Sgblack@eecs.umich.edu using namespace TheISA; 6167371Sgblack@eecs.umich.edu // Make sure that a store exists. 6177396Sgblack@eecs.umich.edu assert(stores != 0); 6187396Sgblack@eecs.umich.edu 6197371Sgblack@eecs.umich.edu int store_idx = store_inst->sqIdx; 6207371Sgblack@eecs.umich.edu 6217640Sgblack@eecs.umich.edu DPRINTF(LSQUnit, "Executing store PC %s [sn:%lli]\n", 6227643Sgblack@eecs.umich.edu store_inst->pcState(), store_inst->seqNum); 6237396Sgblack@eecs.umich.edu 6247396Sgblack@eecs.umich.edu assert(!store_inst->isSquashed()); 6257639Sgblack@eecs.umich.edu 6267396Sgblack@eecs.umich.edu // Check the recently completed loads to see if any match this store's 6277639Sgblack@eecs.umich.edu // address. If so, then we have a memory ordering violation. 6287639Sgblack@eecs.umich.edu int load_idx = store_inst->lqIdx; 6297643Sgblack@eecs.umich.edu 6307396Sgblack@eecs.umich.edu Fault store_fault = store_inst->initiateAcc(); 6317396Sgblack@eecs.umich.edu 6327371Sgblack@eecs.umich.edu if (store_inst->isTranslationDelayed() && 6337396Sgblack@eecs.umich.edu store_fault == NoFault) 6347371Sgblack@eecs.umich.edu return store_fault; 6357371Sgblack@eecs.umich.edu 6367396Sgblack@eecs.umich.edu if (store_inst->readPredicate() == false) 6377396Sgblack@eecs.umich.edu store_inst->forwardOldRegs(); 6387371Sgblack@eecs.umich.edu 6397371Sgblack@eecs.umich.edu if (storeQueue[store_idx].size == 0) { 6407640Sgblack@eecs.umich.edu DPRINTF(LSQUnit,"Fault on Store PC %s, [sn:%lli], Size = 0\n", 6417643Sgblack@eecs.umich.edu store_inst->pcState(), store_inst->seqNum); 6427396Sgblack@eecs.umich.edu 6437639Sgblack@eecs.umich.edu return store_fault; 6447639Sgblack@eecs.umich.edu } else if (store_inst->readPredicate() == false) { 6457639Sgblack@eecs.umich.edu DPRINTF(LSQUnit, "Store [sn:%lli] not executed from predication\n", 6467643Sgblack@eecs.umich.edu store_inst->seqNum); 6477371Sgblack@eecs.umich.edu return store_fault; 6487396Sgblack@eecs.umich.edu } 6497371Sgblack@eecs.umich.edu 6507371Sgblack@eecs.umich.edu assert(store_fault == NoFault); 6517396Sgblack@eecs.umich.edu 6527396Sgblack@eecs.umich.edu if (store_inst->isStoreConditional()) { 6537371Sgblack@eecs.umich.edu // Store conditionals need to set themselves as able to 6547371Sgblack@eecs.umich.edu // writeback if we haven't had a fault by here. 6557640Sgblack@eecs.umich.edu storeQueue[store_idx].canWB = true; 6567643Sgblack@eecs.umich.edu 6577396Sgblack@eecs.umich.edu ++storesToWB; 6587396Sgblack@eecs.umich.edu } 6597639Sgblack@eecs.umich.edu 6607396Sgblack@eecs.umich.edu return checkViolations(load_idx, store_inst); 6617639Sgblack@eecs.umich.edu 6627639Sgblack@eecs.umich.edu} 6637643Sgblack@eecs.umich.edu 6647396Sgblack@eecs.umich.edutemplate <class Impl> 6657396Sgblack@eecs.umich.eduvoid 6667371Sgblack@eecs.umich.eduLSQUnit<Impl>::commitLoad() 6677396Sgblack@eecs.umich.edu{ 6687371Sgblack@eecs.umich.edu assert(loadQueue[loadHead]); 6697371Sgblack@eecs.umich.edu 6707396Sgblack@eecs.umich.edu DPRINTF(LSQUnit, "Committing head load instruction, PC %s\n", 6717396Sgblack@eecs.umich.edu loadQueue[loadHead]->pcState()); 6727371Sgblack@eecs.umich.edu 6737371Sgblack@eecs.umich.edu loadQueue[loadHead] = NULL; 6747640Sgblack@eecs.umich.edu 6757643Sgblack@eecs.umich.edu incrLdIdx(loadHead); 6767639Sgblack@eecs.umich.edu 6777639Sgblack@eecs.umich.edu --loads; 6787643Sgblack@eecs.umich.edu} 6797371Sgblack@eecs.umich.edu 6807396Sgblack@eecs.umich.edutemplate <class Impl> 6817371Sgblack@eecs.umich.eduvoid 6827371Sgblack@eecs.umich.eduLSQUnit<Impl>::commitLoads(InstSeqNum &youngest_inst) 6837396Sgblack@eecs.umich.edu{ 6847396Sgblack@eecs.umich.edu assert(loads == 0 || loadQueue[loadHead]); 6857371Sgblack@eecs.umich.edu 6867371Sgblack@eecs.umich.edu while (loads != 0 && loadQueue[loadHead]->seqNum <= youngest_inst) { 6877640Sgblack@eecs.umich.edu commitLoad(); 6887643Sgblack@eecs.umich.edu } 6897396Sgblack@eecs.umich.edu} 6907396Sgblack@eecs.umich.edu 6917639Sgblack@eecs.umich.edutemplate <class Impl> 6927639Sgblack@eecs.umich.eduvoid 6937643Sgblack@eecs.umich.eduLSQUnit<Impl>::commitStores(InstSeqNum &youngest_inst) 6947396Sgblack@eecs.umich.edu{ 6957396Sgblack@eecs.umich.edu assert(stores == 0 || storeQueue[storeHead].inst); 6967371Sgblack@eecs.umich.edu 6977396Sgblack@eecs.umich.edu int store_idx = storeHead; 6987371Sgblack@eecs.umich.edu 6997371Sgblack@eecs.umich.edu while (store_idx != storeTail) { 7007396Sgblack@eecs.umich.edu assert(storeQueue[store_idx].inst); 7017396Sgblack@eecs.umich.edu // Mark any stores that are now committed and have not yet 7027371Sgblack@eecs.umich.edu // been marked as able to write back. 7037381Sgblack@eecs.umich.edu if (!storeQueue[store_idx].canWB) { 7047381Sgblack@eecs.umich.edu if (storeQueue[store_idx].inst->seqNum > youngest_inst) { 7057381Sgblack@eecs.umich.edu break; 7067381Sgblack@eecs.umich.edu } 7077381Sgblack@eecs.umich.edu DPRINTF(LSQUnit, "Marking store as able to write back, PC " 7087381Sgblack@eecs.umich.edu "%s [sn:%lli]\n", 7097381Sgblack@eecs.umich.edu storeQueue[store_idx].inst->pcState(), 7107373Sgblack@eecs.umich.edu storeQueue[store_idx].inst->seqNum); 7117640Sgblack@eecs.umich.edu 7127643Sgblack@eecs.umich.edu storeQueue[store_idx].canWB = true; 7137397Sgblack@eecs.umich.edu 7147381Sgblack@eecs.umich.edu ++storesToWB; 7157373Sgblack@eecs.umich.edu } 7167381Sgblack@eecs.umich.edu 7177639Sgblack@eecs.umich.edu incrStIdx(store_idx); 7187643Sgblack@eecs.umich.edu } 7197373Sgblack@eecs.umich.edu} 7207396Sgblack@eecs.umich.edu 7217373Sgblack@eecs.umich.edutemplate <class Impl> 7227373Sgblack@eecs.umich.eduvoid 7237396Sgblack@eecs.umich.eduLSQUnit<Impl>::writebackPendingStore() 7247396Sgblack@eecs.umich.edu{ 7257373Sgblack@eecs.umich.edu if (hasPendingPkt) { 7267373Sgblack@eecs.umich.edu assert(pendingPkt != NULL); 7277640Sgblack@eecs.umich.edu 7287643Sgblack@eecs.umich.edu // If the cache is blocked, this will store the packet for retry. 7297397Sgblack@eecs.umich.edu if (sendStore(pendingPkt)) { 7307381Sgblack@eecs.umich.edu storePostSend(pendingPkt); 7317397Sgblack@eecs.umich.edu } 7327397Sgblack@eecs.umich.edu pendingPkt = NULL; 7337639Sgblack@eecs.umich.edu hasPendingPkt = false; 7347643Sgblack@eecs.umich.edu } 7357397Sgblack@eecs.umich.edu} 7367397Sgblack@eecs.umich.edu 7377373Sgblack@eecs.umich.edutemplate <class Impl> 7387396Sgblack@eecs.umich.eduvoid 7397373Sgblack@eecs.umich.eduLSQUnit<Impl>::writebackStores() 7407373Sgblack@eecs.umich.edu{ 7417396Sgblack@eecs.umich.edu // First writeback the second packet from any split store that didn't 7427396Sgblack@eecs.umich.edu // complete last cycle because there weren't enough cache ports available. 7437373Sgblack@eecs.umich.edu if (TheISA::HasUnalignedMemAcc) { 7447373Sgblack@eecs.umich.edu writebackPendingStore(); 7457640Sgblack@eecs.umich.edu } 7467643Sgblack@eecs.umich.edu 7477397Sgblack@eecs.umich.edu while (storesToWB > 0 && 7487381Sgblack@eecs.umich.edu storeWBIdx != storeTail && 7497373Sgblack@eecs.umich.edu storeQueue[storeWBIdx].inst && 7507381Sgblack@eecs.umich.edu storeQueue[storeWBIdx].canWB && 7517639Sgblack@eecs.umich.edu ((!needsTSO) || (!storeInFlight)) && 7527643Sgblack@eecs.umich.edu usedPorts < cachePorts) { 7537373Sgblack@eecs.umich.edu 7547396Sgblack@eecs.umich.edu if (isStoreBlocked || lsq->cacheBlocked()) { 7557373Sgblack@eecs.umich.edu DPRINTF(LSQUnit, "Unable to write back any more stores, cache" 7567373Sgblack@eecs.umich.edu " is blocked!\n"); 7577396Sgblack@eecs.umich.edu break; 7587396Sgblack@eecs.umich.edu } 7597373Sgblack@eecs.umich.edu 7607373Sgblack@eecs.umich.edu // Store didn't write any data so no need to write it back to 7617640Sgblack@eecs.umich.edu // memory. 7627643Sgblack@eecs.umich.edu if (storeQueue[storeWBIdx].size == 0) { 7637397Sgblack@eecs.umich.edu completeStore(storeWBIdx); 7647381Sgblack@eecs.umich.edu 7657397Sgblack@eecs.umich.edu incrStIdx(storeWBIdx); 7667397Sgblack@eecs.umich.edu 7677639Sgblack@eecs.umich.edu continue; 7687643Sgblack@eecs.umich.edu } 7697397Sgblack@eecs.umich.edu 7707397Sgblack@eecs.umich.edu ++usedPorts; 7717373Sgblack@eecs.umich.edu 7727396Sgblack@eecs.umich.edu if (storeQueue[storeWBIdx].inst->isDataPrefetch()) { 7737373Sgblack@eecs.umich.edu incrStIdx(storeWBIdx); 7747373Sgblack@eecs.umich.edu 7757396Sgblack@eecs.umich.edu continue; 7767396Sgblack@eecs.umich.edu } 7777373Sgblack@eecs.umich.edu 7787373Sgblack@eecs.umich.edu assert(storeQueue[storeWBIdx].req); 7797640Sgblack@eecs.umich.edu assert(!storeQueue[storeWBIdx].committed); 7807643Sgblack@eecs.umich.edu 7817397Sgblack@eecs.umich.edu if (TheISA::HasUnalignedMemAcc && storeQueue[storeWBIdx].isSplit) { 7827397Sgblack@eecs.umich.edu assert(storeQueue[storeWBIdx].sreqLow); 7837381Sgblack@eecs.umich.edu assert(storeQueue[storeWBIdx].sreqHigh); 7847388Sgblack@eecs.umich.edu } 7857381Sgblack@eecs.umich.edu 7867639Sgblack@eecs.umich.edu DynInstPtr inst = storeQueue[storeWBIdx].inst; 7877643Sgblack@eecs.umich.edu 7887380Sgblack@eecs.umich.edu Request *req = storeQueue[storeWBIdx].req; 7897396Sgblack@eecs.umich.edu RequestPtr sreqLow = storeQueue[storeWBIdx].sreqLow; 7907380Sgblack@eecs.umich.edu RequestPtr sreqHigh = storeQueue[storeWBIdx].sreqHigh; 7917380Sgblack@eecs.umich.edu 7927396Sgblack@eecs.umich.edu storeQueue[storeWBIdx].committed = true; 7937396Sgblack@eecs.umich.edu 7947380Sgblack@eecs.umich.edu assert(!inst->memData); 7957380Sgblack@eecs.umich.edu inst->memData = new uint8_t[64]; 7967640Sgblack@eecs.umich.edu 7977643Sgblack@eecs.umich.edu memcpy(inst->memData, storeQueue[storeWBIdx].data, req->getSize()); 7987397Sgblack@eecs.umich.edu 7997397Sgblack@eecs.umich.edu MemCmd command = 8007397Sgblack@eecs.umich.edu req->isSwap() ? MemCmd::SwapReq : 8017397Sgblack@eecs.umich.edu (req->isLLSC() ? MemCmd::StoreCondReq : MemCmd::WriteReq); 8027397Sgblack@eecs.umich.edu PacketPtr data_pkt; 8037381Sgblack@eecs.umich.edu PacketPtr snd_data_pkt = NULL; 8047639Sgblack@eecs.umich.edu 8057643Sgblack@eecs.umich.edu LSQSenderState *state = new LSQSenderState; 8067380Sgblack@eecs.umich.edu state->isLoad = false; 8077380Sgblack@eecs.umich.edu state->idx = storeWBIdx; 8087396Sgblack@eecs.umich.edu state->inst = inst; 8097380Sgblack@eecs.umich.edu 8107380Sgblack@eecs.umich.edu if (!TheISA::HasUnalignedMemAcc || !storeQueue[storeWBIdx].isSplit) { 8117396Sgblack@eecs.umich.edu 8127396Sgblack@eecs.umich.edu // Build a single data packet if the store isn't split. 8137380Sgblack@eecs.umich.edu data_pkt = new Packet(req, command); 8147380Sgblack@eecs.umich.edu data_pkt->dataStatic(inst->memData); 8157640Sgblack@eecs.umich.edu data_pkt->senderState = state; 8167643Sgblack@eecs.umich.edu } else { 8177397Sgblack@eecs.umich.edu // Create two packets if the store is split in two. 8187397Sgblack@eecs.umich.edu data_pkt = new Packet(sreqLow, command); 8197381Sgblack@eecs.umich.edu snd_data_pkt = new Packet(sreqHigh, command); 8207388Sgblack@eecs.umich.edu 8217381Sgblack@eecs.umich.edu data_pkt->dataStatic(inst->memData); 8227639Sgblack@eecs.umich.edu snd_data_pkt->dataStatic(inst->memData + sreqLow->getSize()); 8237643Sgblack@eecs.umich.edu 8247380Sgblack@eecs.umich.edu data_pkt->senderState = state; 8257396Sgblack@eecs.umich.edu snd_data_pkt->senderState = state; 8267380Sgblack@eecs.umich.edu 8277380Sgblack@eecs.umich.edu state->isSplit = true; 8287396Sgblack@eecs.umich.edu state->outstanding = 2; 8297396Sgblack@eecs.umich.edu 8307380Sgblack@eecs.umich.edu // Can delete the main request now. 8317380Sgblack@eecs.umich.edu delete req; 8327640Sgblack@eecs.umich.edu req = sreqLow; 8337643Sgblack@eecs.umich.edu } 8347397Sgblack@eecs.umich.edu 8357397Sgblack@eecs.umich.edu DPRINTF(LSQUnit, "D-Cache: Writing back store idx:%i PC:%s " 8367397Sgblack@eecs.umich.edu "to Addr:%#x, data:%#x [sn:%lli]\n", 8377397Sgblack@eecs.umich.edu storeWBIdx, inst->pcState(), 8387397Sgblack@eecs.umich.edu req->getPaddr(), (int)*(inst->memData), 8397381Sgblack@eecs.umich.edu inst->seqNum); 8407639Sgblack@eecs.umich.edu 8417643Sgblack@eecs.umich.edu // @todo: Remove this SC hack once the memory system handles it. 8427380Sgblack@eecs.umich.edu if (inst->isStoreConditional()) { 8437380Sgblack@eecs.umich.edu assert(!storeQueue[storeWBIdx].isSplit); 8447396Sgblack@eecs.umich.edu // Disable recording the result temporarily. Writing to 8457380Sgblack@eecs.umich.edu // misc regs normally updates the result, but this is not 8467380Sgblack@eecs.umich.edu // the desired behavior when handling store conditionals. 8477396Sgblack@eecs.umich.edu inst->recordResult(false); 8487396Sgblack@eecs.umich.edu bool success = TheISA::handleLockedWrite(inst.get(), req); 8497380Sgblack@eecs.umich.edu inst->recordResult(true); 8507380Sgblack@eecs.umich.edu 8517640Sgblack@eecs.umich.edu if (!success) { 8527643Sgblack@eecs.umich.edu // Instantly complete this store. 8537397Sgblack@eecs.umich.edu DPRINTF(LSQUnit, "Store conditional [sn:%lli] failed. " 8547397Sgblack@eecs.umich.edu "Instantly completing it.\n", 8557380Sgblack@eecs.umich.edu inst->seqNum); 8567381Sgblack@eecs.umich.edu WritebackEvent *wb = new WritebackEvent(inst, data_pkt, this); 8577387Sgblack@eecs.umich.edu cpu->schedule(wb, curTick() + 1); 8587381Sgblack@eecs.umich.edu if (cpu->checker) { 8597639Sgblack@eecs.umich.edu // Make sure to set the LLSC data for verification 8607643Sgblack@eecs.umich.edu // if checker is loaded 8617373Sgblack@eecs.umich.edu inst->reqToVerify->setExtraData(0); 8627396Sgblack@eecs.umich.edu inst->completeAcc(data_pkt); 8637373Sgblack@eecs.umich.edu } 8647373Sgblack@eecs.umich.edu completeStore(storeWBIdx); 8657396Sgblack@eecs.umich.edu incrStIdx(storeWBIdx); 8667396Sgblack@eecs.umich.edu continue; 8677373Sgblack@eecs.umich.edu } 8687373Sgblack@eecs.umich.edu } else { 8697640Sgblack@eecs.umich.edu // Non-store conditionals do not need a writeback. 8707643Sgblack@eecs.umich.edu state->noWB = true; 8717397Sgblack@eecs.umich.edu } 8727397Sgblack@eecs.umich.edu 8737397Sgblack@eecs.umich.edu bool split = 8747380Sgblack@eecs.umich.edu TheISA::HasUnalignedMemAcc && storeQueue[storeWBIdx].isSplit; 8757397Sgblack@eecs.umich.edu 8767397Sgblack@eecs.umich.edu ThreadContext *thread = cpu->tcBase(lsqID); 8777381Sgblack@eecs.umich.edu 8787639Sgblack@eecs.umich.edu if (req->isMmappedIpr()) { 8797643Sgblack@eecs.umich.edu assert(!inst->isStoreConditional()); 8807373Sgblack@eecs.umich.edu TheISA::handleIprWrite(thread, data_pkt); 8817373Sgblack@eecs.umich.edu delete data_pkt; 8827396Sgblack@eecs.umich.edu if (split) { 8837373Sgblack@eecs.umich.edu assert(snd_data_pkt->req->isMmappedIpr()); 8847373Sgblack@eecs.umich.edu TheISA::handleIprWrite(thread, snd_data_pkt); 8857396Sgblack@eecs.umich.edu delete snd_data_pkt; 8867396Sgblack@eecs.umich.edu delete sreqLow; 8877373Sgblack@eecs.umich.edu delete sreqHigh; 8887373Sgblack@eecs.umich.edu } 8897640Sgblack@eecs.umich.edu delete state; 8907643Sgblack@eecs.umich.edu delete req; 8917397Sgblack@eecs.umich.edu completeStore(storeWBIdx); 8927397Sgblack@eecs.umich.edu incrStIdx(storeWBIdx); 8937380Sgblack@eecs.umich.edu } else if (!sendStore(data_pkt)) { 8947381Sgblack@eecs.umich.edu DPRINTF(IEW, "D-Cache became blocked when writing [sn:%lli], will" 8957387Sgblack@eecs.umich.edu "retry later\n", 8967381Sgblack@eecs.umich.edu inst->seqNum); 8977639Sgblack@eecs.umich.edu 8987643Sgblack@eecs.umich.edu // Need to store the second packet, if split. 8997373Sgblack@eecs.umich.edu if (split) { 9007396Sgblack@eecs.umich.edu state->pktToSend = true; 9017373Sgblack@eecs.umich.edu state->pendingPacket = snd_data_pkt; 9027373Sgblack@eecs.umich.edu } 9037396Sgblack@eecs.umich.edu } else { 9047396Sgblack@eecs.umich.edu 9057373Sgblack@eecs.umich.edu // If split, try to send the second packet too 9067373Sgblack@eecs.umich.edu if (split) { 9077640Sgblack@eecs.umich.edu assert(snd_data_pkt); 9087643Sgblack@eecs.umich.edu 9097397Sgblack@eecs.umich.edu // Ensure there are enough ports to use. 9107397Sgblack@eecs.umich.edu if (usedPorts < cachePorts) { 9117397Sgblack@eecs.umich.edu ++usedPorts; 9127380Sgblack@eecs.umich.edu if (sendStore(snd_data_pkt)) { 9137397Sgblack@eecs.umich.edu storePostSend(snd_data_pkt); 9147397Sgblack@eecs.umich.edu } else { 9157381Sgblack@eecs.umich.edu DPRINTF(IEW, "D-Cache became blocked when writing" 9167639Sgblack@eecs.umich.edu " [sn:%lli] second packet, will retry later\n", 9177643Sgblack@eecs.umich.edu inst->seqNum); 9187373Sgblack@eecs.umich.edu } 9197373Sgblack@eecs.umich.edu } else { 9207396Sgblack@eecs.umich.edu 9217373Sgblack@eecs.umich.edu // Store the packet for when there's free ports. 9227373Sgblack@eecs.umich.edu assert(pendingPkt == NULL); 9237396Sgblack@eecs.umich.edu pendingPkt = snd_data_pkt; 9247396Sgblack@eecs.umich.edu hasPendingPkt = true; 9257373Sgblack@eecs.umich.edu } 9267374Sgblack@eecs.umich.edu } else { 9277640Sgblack@eecs.umich.edu 9287643Sgblack@eecs.umich.edu // Not a split store. 9297397Sgblack@eecs.umich.edu storePostSend(data_pkt); 9307397Sgblack@eecs.umich.edu } 9317381Sgblack@eecs.umich.edu } 9327397Sgblack@eecs.umich.edu } 9337397Sgblack@eecs.umich.edu 9347639Sgblack@eecs.umich.edu // Not sure this should set it to 0. 9357643Sgblack@eecs.umich.edu usedPorts = 0; 9367397Sgblack@eecs.umich.edu 9377397Sgblack@eecs.umich.edu assert(stores >= 0 && storesToWB >= 0); 9387374Sgblack@eecs.umich.edu} 9397396Sgblack@eecs.umich.edu 9407374Sgblack@eecs.umich.edu/*template <class Impl> 9417374Sgblack@eecs.umich.eduvoid 9427396Sgblack@eecs.umich.eduLSQUnit<Impl>::removeMSHR(InstSeqNum seqNum) 9437396Sgblack@eecs.umich.edu{ 9447374Sgblack@eecs.umich.edu list<InstSeqNum>::iterator mshr_it = find(mshrSeqNums.begin(), 9457374Sgblack@eecs.umich.edu mshrSeqNums.end(), 9467640Sgblack@eecs.umich.edu seqNum); 9477643Sgblack@eecs.umich.edu 9487397Sgblack@eecs.umich.edu if (mshr_it != mshrSeqNums.end()) { 9497397Sgblack@eecs.umich.edu mshrSeqNums.erase(mshr_it); 9507397Sgblack@eecs.umich.edu DPRINTF(LSQUnit, "Removing MSHR. count = %i\n",mshrSeqNums.size()); 9517397Sgblack@eecs.umich.edu } 9527397Sgblack@eecs.umich.edu}*/ 9537381Sgblack@eecs.umich.edu 9547639Sgblack@eecs.umich.edutemplate <class Impl> 9557643Sgblack@eecs.umich.eduvoid 9567374Sgblack@eecs.umich.eduLSQUnit<Impl>::squash(const InstSeqNum &squashed_num) 9577396Sgblack@eecs.umich.edu{ 9587374Sgblack@eecs.umich.edu DPRINTF(LSQUnit, "Squashing until [sn:%lli]!" 9597374Sgblack@eecs.umich.edu "(Loads:%i Stores:%i)\n", squashed_num, loads, stores); 9607396Sgblack@eecs.umich.edu 9617396Sgblack@eecs.umich.edu int load_idx = loadTail; 9627374Sgblack@eecs.umich.edu decrLdIdx(load_idx); 9637377Sgblack@eecs.umich.edu 9647640Sgblack@eecs.umich.edu while (loads != 0 && loadQueue[load_idx]->seqNum > squashed_num) { 9657643Sgblack@eecs.umich.edu DPRINTF(LSQUnit,"Load Instruction PC %s squashed, " 9667398Sgblack@eecs.umich.edu "[sn:%lli]\n", 9677398Sgblack@eecs.umich.edu loadQueue[load_idx]->pcState(), 9687398Sgblack@eecs.umich.edu loadQueue[load_idx]->seqNum); 9697639Sgblack@eecs.umich.edu 9707639Sgblack@eecs.umich.edu if (isStalled() && load_idx == stallingLoadIdx) { 9717398Sgblack@eecs.umich.edu stalled = false; 9727639Sgblack@eecs.umich.edu stallingStoreIsn = 0; 9737643Sgblack@eecs.umich.edu stallingLoadIdx = 0; 9747398Sgblack@eecs.umich.edu } 9757398Sgblack@eecs.umich.edu 9767398Sgblack@eecs.umich.edu // Clear the smart pointer to make sure it is decremented. 9777398Sgblack@eecs.umich.edu loadQueue[load_idx]->setSquashed(); 9787398Sgblack@eecs.umich.edu loadQueue[load_idx] = NULL; 9797398Sgblack@eecs.umich.edu --loads; 9807398Sgblack@eecs.umich.edu 9817398Sgblack@eecs.umich.edu // Inefficient! 9827640Sgblack@eecs.umich.edu loadTail = load_idx; 9837643Sgblack@eecs.umich.edu 9847398Sgblack@eecs.umich.edu decrLdIdx(load_idx); 9857398Sgblack@eecs.umich.edu ++lsqSquashedLoads; 9867639Sgblack@eecs.umich.edu } 9877639Sgblack@eecs.umich.edu 9887398Sgblack@eecs.umich.edu if (isLoadBlocked) { 9897639Sgblack@eecs.umich.edu if (squashed_num < blockedLoadSeqNum) { 9907643Sgblack@eecs.umich.edu isLoadBlocked = false; 9917398Sgblack@eecs.umich.edu loadBlockedHandled = false; 9927398Sgblack@eecs.umich.edu blockedLoadSeqNum = 0; 9937398Sgblack@eecs.umich.edu } 9947398Sgblack@eecs.umich.edu } 9957398Sgblack@eecs.umich.edu 9967398Sgblack@eecs.umich.edu if (memDepViolator && squashed_num < memDepViolator->seqNum) { 9977398Sgblack@eecs.umich.edu memDepViolator = NULL; 9987398Sgblack@eecs.umich.edu } 9997640Sgblack@eecs.umich.edu 10007643Sgblack@eecs.umich.edu int store_idx = storeTail; 10017398Sgblack@eecs.umich.edu decrStIdx(store_idx); 10027398Sgblack@eecs.umich.edu 10037639Sgblack@eecs.umich.edu while (stores != 0 && 10047639Sgblack@eecs.umich.edu storeQueue[store_idx].inst->seqNum > squashed_num) { 10057639Sgblack@eecs.umich.edu // Instructions marked as can WB are already committed. 10067639Sgblack@eecs.umich.edu if (storeQueue[store_idx].canWB) { 10077639Sgblack@eecs.umich.edu break; 10087639Sgblack@eecs.umich.edu } 10097639Sgblack@eecs.umich.edu 10107643Sgblack@eecs.umich.edu DPRINTF(LSQUnit,"Store Instruction PC %s squashed, " 10117398Sgblack@eecs.umich.edu "idx:%i [sn:%lli]\n", 10127398Sgblack@eecs.umich.edu storeQueue[store_idx].inst->pcState(), 10137398Sgblack@eecs.umich.edu store_idx, storeQueue[store_idx].inst->seqNum); 10147398Sgblack@eecs.umich.edu 10157398Sgblack@eecs.umich.edu // I don't think this can happen. It should have been cleared 10167398Sgblack@eecs.umich.edu // by the stalling load. 10177398Sgblack@eecs.umich.edu if (isStalled() && 10187398Sgblack@eecs.umich.edu storeQueue[store_idx].inst->seqNum == stallingStoreIsn) { 10197640Sgblack@eecs.umich.edu panic("Is stalled should have been cleared by stalling load!\n"); 10207643Sgblack@eecs.umich.edu stalled = false; 10217398Sgblack@eecs.umich.edu stallingStoreIsn = 0; 10227398Sgblack@eecs.umich.edu } 10237639Sgblack@eecs.umich.edu 10247639Sgblack@eecs.umich.edu // Clear the smart pointer to make sure it is decremented. 10257639Sgblack@eecs.umich.edu storeQueue[store_idx].inst->setSquashed(); 10267639Sgblack@eecs.umich.edu storeQueue[store_idx].inst = NULL; 10277639Sgblack@eecs.umich.edu storeQueue[store_idx].canWB = 0; 10287639Sgblack@eecs.umich.edu 10297639Sgblack@eecs.umich.edu // Must delete request now that it wasn't handed off to 10307643Sgblack@eecs.umich.edu // memory. This is quite ugly. @todo: Figure out the proper 10317398Sgblack@eecs.umich.edu // place to really handle request deletes. 10327398Sgblack@eecs.umich.edu delete storeQueue[store_idx].req; 10337398Sgblack@eecs.umich.edu if (TheISA::HasUnalignedMemAcc && storeQueue[store_idx].isSplit) { 10347398Sgblack@eecs.umich.edu delete storeQueue[store_idx].sreqLow; 10357398Sgblack@eecs.umich.edu delete storeQueue[store_idx].sreqHigh; 10367398Sgblack@eecs.umich.edu 10377398Sgblack@eecs.umich.edu storeQueue[store_idx].sreqLow = NULL; 10387398Sgblack@eecs.umich.edu storeQueue[store_idx].sreqHigh = NULL; 10397640Sgblack@eecs.umich.edu } 10407643Sgblack@eecs.umich.edu 10417397Sgblack@eecs.umich.edu storeQueue[store_idx].req = NULL; 10427377Sgblack@eecs.umich.edu --stores; 10437377Sgblack@eecs.umich.edu 10447377Sgblack@eecs.umich.edu // Inefficient! 10457377Sgblack@eecs.umich.edu storeTail = store_idx; 10467377Sgblack@eecs.umich.edu 10477377Sgblack@eecs.umich.edu decrStIdx(store_idx); 10487377Sgblack@eecs.umich.edu ++lsqSquashedStores; 10497389Sgblack@eecs.umich.edu } 10507389Sgblack@eecs.umich.edu} 10517396Sgblack@eecs.umich.edu 10527389Sgblack@eecs.umich.edutemplate <class Impl> 10537396Sgblack@eecs.umich.eduvoid 10547389Sgblack@eecs.umich.eduLSQUnit<Impl>::storePostSend(PacketPtr pkt) 10557389Sgblack@eecs.umich.edu{ 10567377Sgblack@eecs.umich.edu if (isStalled() && 10577377Sgblack@eecs.umich.edu storeQueue[storeWBIdx].inst->seqNum == stallingStoreIsn) { 10587643Sgblack@eecs.umich.edu DPRINTF(LSQUnit, "Unstalling, stalling store [sn:%lli] " 10597377Sgblack@eecs.umich.edu "load idx:%i\n", 10607396Sgblack@eecs.umich.edu stallingStoreIsn, stallingLoadIdx); 10617377Sgblack@eecs.umich.edu stalled = false; 10627377Sgblack@eecs.umich.edu stallingStoreIsn = 0; 10637396Sgblack@eecs.umich.edu iewStage->replayMemInst(loadQueue[stallingLoadIdx]); 10647396Sgblack@eecs.umich.edu } 10657377Sgblack@eecs.umich.edu 10667377Sgblack@eecs.umich.edu if (!storeQueue[storeWBIdx].inst->isStoreConditional()) { 10677640Sgblack@eecs.umich.edu // The store is basically completed at this time. This 10687397Sgblack@eecs.umich.edu // only works so long as the checker doesn't try to 10697397Sgblack@eecs.umich.edu // verify the value in memory for stores. 10707643Sgblack@eecs.umich.edu storeQueue[storeWBIdx].inst->setCompleted(); 10717397Sgblack@eecs.umich.edu 10727397Sgblack@eecs.umich.edu if (cpu->checker) { 10737377Sgblack@eecs.umich.edu cpu->checker->verify(storeQueue[storeWBIdx].inst); 10747397Sgblack@eecs.umich.edu } 10757377Sgblack@eecs.umich.edu } 10767397Sgblack@eecs.umich.edu 10777377Sgblack@eecs.umich.edu if (needsTSO) { 10787377Sgblack@eecs.umich.edu storeInFlight = true; 10797389Sgblack@eecs.umich.edu } 10807397Sgblack@eecs.umich.edu 10817397Sgblack@eecs.umich.edu incrStIdx(storeWBIdx); 10827397Sgblack@eecs.umich.edu} 10837397Sgblack@eecs.umich.edu 10847389Sgblack@eecs.umich.edutemplate <class Impl> 10857389Sgblack@eecs.umich.eduvoid 10867377Sgblack@eecs.umich.eduLSQUnit<Impl>::writeback(DynInstPtr &inst, PacketPtr pkt) 10877377Sgblack@eecs.umich.edu{ 10887643Sgblack@eecs.umich.edu iewStage->wakeCPU(); 10897377Sgblack@eecs.umich.edu 10907396Sgblack@eecs.umich.edu // Squashed instructions do not need to complete their access. 10917377Sgblack@eecs.umich.edu if (inst->isSquashed()) { 10927377Sgblack@eecs.umich.edu iewStage->decrWb(inst->seqNum); 10937396Sgblack@eecs.umich.edu assert(!inst->isStore()); 10947396Sgblack@eecs.umich.edu ++lsqIgnoredResponses; 10957377Sgblack@eecs.umich.edu return; 10967377Sgblack@eecs.umich.edu } 10977640Sgblack@eecs.umich.edu 10987643Sgblack@eecs.umich.edu if (!inst->isExecuted()) { 10997397Sgblack@eecs.umich.edu inst->setExecuted(); 11007389Sgblack@eecs.umich.edu 11017389Sgblack@eecs.umich.edu // Complete access to copy data to proper place. 11027377Sgblack@eecs.umich.edu inst->completeAcc(pkt); 11037377Sgblack@eecs.umich.edu } 11047377Sgblack@eecs.umich.edu 11057377Sgblack@eecs.umich.edu // Need to insert instruction into queue to commit 11067377Sgblack@eecs.umich.edu iewStage->instToCommit(inst); 11077377Sgblack@eecs.umich.edu 11087377Sgblack@eecs.umich.edu iewStage->activityThisCycle(); 11097389Sgblack@eecs.umich.edu 11107389Sgblack@eecs.umich.edu // see if this load changed the PC 11117396Sgblack@eecs.umich.edu iewStage->checkMisprediction(inst); 11127389Sgblack@eecs.umich.edu} 11137389Sgblack@eecs.umich.edu 11147377Sgblack@eecs.umich.edutemplate <class Impl> 11157377Sgblack@eecs.umich.eduvoid 11167643Sgblack@eecs.umich.eduLSQUnit<Impl>::completeStore(int store_idx) 11177377Sgblack@eecs.umich.edu{ 11187396Sgblack@eecs.umich.edu assert(storeQueue[store_idx].inst); 11197377Sgblack@eecs.umich.edu storeQueue[store_idx].completed = true; 11207377Sgblack@eecs.umich.edu --storesToWB; 11217396Sgblack@eecs.umich.edu // A bit conservative because a store completion may not free up entries, 11227396Sgblack@eecs.umich.edu // but hopefully avoids two store completions in one cycle from making 11237377Sgblack@eecs.umich.edu // the CPU tick twice. 11247377Sgblack@eecs.umich.edu cpu->wakeCPU(); 11257640Sgblack@eecs.umich.edu cpu->activityThisCycle(); 11267389Sgblack@eecs.umich.edu 11277389Sgblack@eecs.umich.edu if (store_idx == storeHead) { 11287397Sgblack@eecs.umich.edu do { 11297643Sgblack@eecs.umich.edu incrStIdx(storeHead); 11307397Sgblack@eecs.umich.edu 11317397Sgblack@eecs.umich.edu --stores; 11327377Sgblack@eecs.umich.edu } while (storeQueue[storeHead].completed && 11337397Sgblack@eecs.umich.edu storeHead != storeTail); 11347377Sgblack@eecs.umich.edu 11357397Sgblack@eecs.umich.edu iewStage->updateLSQNextCycle = true; 11367377Sgblack@eecs.umich.edu } 11377377Sgblack@eecs.umich.edu 11387389Sgblack@eecs.umich.edu DPRINTF(LSQUnit, "Completing store [sn:%lli], idx:%i, store head " 11397397Sgblack@eecs.umich.edu "idx:%i\n", 11407397Sgblack@eecs.umich.edu storeQueue[store_idx].inst->seqNum, store_idx, storeHead); 11417389Sgblack@eecs.umich.edu 11427389Sgblack@eecs.umich.edu#if TRACING_ON 11437377Sgblack@eecs.umich.edu if (DTRACE(O3PipeView)) { 11447377Sgblack@eecs.umich.edu storeQueue[store_idx].inst->storeTick = 11457643Sgblack@eecs.umich.edu curTick() - storeQueue[store_idx].inst->fetchTick; 11467377Sgblack@eecs.umich.edu } 11477396Sgblack@eecs.umich.edu#endif 11487377Sgblack@eecs.umich.edu 11497377Sgblack@eecs.umich.edu if (isStalled() && 11507396Sgblack@eecs.umich.edu storeQueue[store_idx].inst->seqNum == stallingStoreIsn) { 11517396Sgblack@eecs.umich.edu DPRINTF(LSQUnit, "Unstalling, stalling store [sn:%lli] " 11527377Sgblack@eecs.umich.edu "load idx:%i\n", 11537389Sgblack@eecs.umich.edu stallingStoreIsn, stallingLoadIdx); 11547640Sgblack@eecs.umich.edu stalled = false; 11557643Sgblack@eecs.umich.edu stallingStoreIsn = 0; 11567397Sgblack@eecs.umich.edu iewStage->replayMemInst(loadQueue[stallingLoadIdx]); 11577389Sgblack@eecs.umich.edu } 11587389Sgblack@eecs.umich.edu 11597389Sgblack@eecs.umich.edu storeQueue[store_idx].inst->setCompleted(); 11607389Sgblack@eecs.umich.edu 11617389Sgblack@eecs.umich.edu if (needsTSO) { 11627389Sgblack@eecs.umich.edu storeInFlight = false; 11637389Sgblack@eecs.umich.edu } 11647389Sgblack@eecs.umich.edu 11657389Sgblack@eecs.umich.edu // Tell the checker we've completed this instruction. Some stores 11667389Sgblack@eecs.umich.edu // may get reported twice to the checker, but the checker can 11677643Sgblack@eecs.umich.edu // handle that case. 11687389Sgblack@eecs.umich.edu if (cpu->checker) { 11697396Sgblack@eecs.umich.edu cpu->checker->verify(storeQueue[store_idx].inst); 11707389Sgblack@eecs.umich.edu } 11717389Sgblack@eecs.umich.edu} 11727396Sgblack@eecs.umich.edu 11737396Sgblack@eecs.umich.edutemplate <class Impl> 11747389Sgblack@eecs.umich.edubool 11757389Sgblack@eecs.umich.eduLSQUnit<Impl>::sendStore(PacketPtr data_pkt) 11767640Sgblack@eecs.umich.edu{ 11777397Sgblack@eecs.umich.edu if (!dcachePort->sendTimingReq(data_pkt)) { 11787397Sgblack@eecs.umich.edu // Need to handle becoming blocked on a store. 11797643Sgblack@eecs.umich.edu isStoreBlocked = true; 11807397Sgblack@eecs.umich.edu ++lsqCacheBlocked; 11817397Sgblack@eecs.umich.edu assert(retryPkt == NULL); 11827389Sgblack@eecs.umich.edu retryPkt = data_pkt; 11837397Sgblack@eecs.umich.edu lsq->setRetryTid(lsqID); 11847389Sgblack@eecs.umich.edu return false; 11857397Sgblack@eecs.umich.edu } 11867389Sgblack@eecs.umich.edu return true; 11877389Sgblack@eecs.umich.edu} 11887389Sgblack@eecs.umich.edu 11897389Sgblack@eecs.umich.edutemplate <class Impl> 11907389Sgblack@eecs.umich.eduvoid 11917643Sgblack@eecs.umich.eduLSQUnit<Impl>::recvRetry() 11927389Sgblack@eecs.umich.edu{ 11937396Sgblack@eecs.umich.edu if (isStoreBlocked) { 11947389Sgblack@eecs.umich.edu DPRINTF(LSQUnit, "Receiving retry: store blocked\n"); 11957389Sgblack@eecs.umich.edu assert(retryPkt != NULL); 11967396Sgblack@eecs.umich.edu 11977396Sgblack@eecs.umich.edu LSQSenderState *state = 11987389Sgblack@eecs.umich.edu dynamic_cast<LSQSenderState *>(retryPkt->senderState); 11997389Sgblack@eecs.umich.edu 12007640Sgblack@eecs.umich.edu if (dcachePort->sendTimingReq(retryPkt)) { 12017643Sgblack@eecs.umich.edu // Don't finish the store unless this is the last packet. 12027397Sgblack@eecs.umich.edu if (!TheISA::HasUnalignedMemAcc || !state->pktToSend || 12037389Sgblack@eecs.umich.edu state->pendingPacket == retryPkt) { 12047389Sgblack@eecs.umich.edu state->pktToSend = false; 12057389Sgblack@eecs.umich.edu storePostSend(retryPkt); 12067389Sgblack@eecs.umich.edu } 12077389Sgblack@eecs.umich.edu retryPkt = NULL; 12087389Sgblack@eecs.umich.edu isStoreBlocked = false; 12097389Sgblack@eecs.umich.edu lsq->setRetryTid(InvalidThreadID); 12107389Sgblack@eecs.umich.edu 12117389Sgblack@eecs.umich.edu // Send any outstanding packet. 12127389Sgblack@eecs.umich.edu if (TheISA::HasUnalignedMemAcc && state->pktToSend) { 12137643Sgblack@eecs.umich.edu assert(state->pendingPacket); 12147389Sgblack@eecs.umich.edu if (sendStore(state->pendingPacket)) { 12157396Sgblack@eecs.umich.edu storePostSend(state->pendingPacket); 12167389Sgblack@eecs.umich.edu } 12177389Sgblack@eecs.umich.edu } 12187396Sgblack@eecs.umich.edu } else { 12197396Sgblack@eecs.umich.edu // Still blocked! 12207389Sgblack@eecs.umich.edu ++lsqCacheBlocked; 12217389Sgblack@eecs.umich.edu lsq->setRetryTid(lsqID); 12227640Sgblack@eecs.umich.edu } 12237397Sgblack@eecs.umich.edu } else if (isLoadBlocked) { 12247643Sgblack@eecs.umich.edu DPRINTF(LSQUnit, "Loads squash themselves and all younger insts, " 12257397Sgblack@eecs.umich.edu "no need to resend packet.\n"); 12267397Sgblack@eecs.umich.edu } else { 12277389Sgblack@eecs.umich.edu DPRINTF(LSQUnit, "Retry received but LSQ is no longer blocked.\n"); 12287397Sgblack@eecs.umich.edu } 12297389Sgblack@eecs.umich.edu} 12307397Sgblack@eecs.umich.edu 12317389Sgblack@eecs.umich.edutemplate <class Impl> 12327389Sgblack@eecs.umich.eduinline void 12337389Sgblack@eecs.umich.eduLSQUnit<Impl>::incrStIdx(int &store_idx) const 12347389Sgblack@eecs.umich.edu{ 12357389Sgblack@eecs.umich.edu if (++store_idx >= SQEntries) 12367643Sgblack@eecs.umich.edu store_idx = 0; 12377389Sgblack@eecs.umich.edu} 12387396Sgblack@eecs.umich.edu 12397389Sgblack@eecs.umich.edutemplate <class Impl> 12407389Sgblack@eecs.umich.eduinline void 12417396Sgblack@eecs.umich.eduLSQUnit<Impl>::decrStIdx(int &store_idx) const 12427396Sgblack@eecs.umich.edu{ 12437389Sgblack@eecs.umich.edu if (--store_idx < 0) 12447322Sgblack@eecs.umich.edu store_idx += SQEntries; 12457379Sgblack@eecs.umich.edu} 12467379Sgblack@eecs.umich.edu 12477379Sgblack@eecs.umich.edutemplate <class Impl> 12487379Sgblack@eecs.umich.eduinline void 12497379Sgblack@eecs.umich.eduLSQUnit<Impl>::incrLdIdx(int &load_idx) const 12507379Sgblack@eecs.umich.edu{ 12517379Sgblack@eecs.umich.edu if (++load_idx >= LQEntries) 12527640Sgblack@eecs.umich.edu load_idx = 0; 12537643Sgblack@eecs.umich.edu} 12547397Sgblack@eecs.umich.edu 12557397Sgblack@eecs.umich.edutemplate <class Impl> 12567381Sgblack@eecs.umich.eduinline void 12577379Sgblack@eecs.umich.eduLSQUnit<Impl>::decrLdIdx(int &load_idx) const 12587381Sgblack@eecs.umich.edu{ 12597639Sgblack@eecs.umich.edu if (--load_idx < 0) 12607643Sgblack@eecs.umich.edu load_idx += LQEntries; 12617379Sgblack@eecs.umich.edu} 12627396Sgblack@eecs.umich.edu 12637379Sgblack@eecs.umich.edutemplate <class Impl> 12647379Sgblack@eecs.umich.eduvoid 12657396Sgblack@eecs.umich.eduLSQUnit<Impl>::dumpInsts() const 12667396Sgblack@eecs.umich.edu{ 12677379Sgblack@eecs.umich.edu cprintf("Load store queue: Dumping instructions.\n"); 12687379Sgblack@eecs.umich.edu cprintf("Load queue size: %i\n", loads); 12697640Sgblack@eecs.umich.edu cprintf("Load queue: "); 12707643Sgblack@eecs.umich.edu 12717397Sgblack@eecs.umich.edu int load_idx = loadHead; 12727397Sgblack@eecs.umich.edu 12737397Sgblack@eecs.umich.edu while (load_idx != loadTail && loadQueue[load_idx]) { 12747397Sgblack@eecs.umich.edu const DynInstPtr &inst(loadQueue[load_idx]); 12757397Sgblack@eecs.umich.edu cprintf("%s.[sn:%i] ", inst->pcState(), inst->seqNum); 12767381Sgblack@eecs.umich.edu 12777639Sgblack@eecs.umich.edu incrLdIdx(load_idx); 12787643Sgblack@eecs.umich.edu } 12797379Sgblack@eecs.umich.edu cprintf("\n"); 12807379Sgblack@eecs.umich.edu 12817379Sgblack@eecs.umich.edu cprintf("Store queue size: %i\n", stores); 12827396Sgblack@eecs.umich.edu cprintf("Store queue: "); 12837379Sgblack@eecs.umich.edu 12847379Sgblack@eecs.umich.edu int store_idx = storeHead; 12857396Sgblack@eecs.umich.edu 12867396Sgblack@eecs.umich.edu while (store_idx != storeTail && storeQueue[store_idx].inst) { 12877379Sgblack@eecs.umich.edu const DynInstPtr &inst(storeQueue[store_idx].inst); 12887379Sgblack@eecs.umich.edu cprintf("%s.[sn:%i] ", inst->pcState(), inst->seqNum); 12897640Sgblack@eecs.umich.edu 12907643Sgblack@eecs.umich.edu incrStIdx(store_idx); 12917397Sgblack@eecs.umich.edu } 12927397Sgblack@eecs.umich.edu 12937381Sgblack@eecs.umich.edu cprintf("\n"); 12947379Sgblack@eecs.umich.edu} 12957381Sgblack@eecs.umich.edu 12967639Sgblack@eecs.umich.edu#endif//__CPU_O3_LSQ_UNIT_IMPL_HH__ 12977643Sgblack@eecs.umich.edu