mshr.cc revision 4916
16167SN/A/* 26167SN/A * Copyright (c) 2002-2005 The Regents of The University of Michigan 36167SN/A * All rights reserved. 410036SAli.Saidi@ARM.com * 58835SAli.Saidi@ARM.com * Redistribution and use in source and binary forms, with or without 610036SAli.Saidi@ARM.com * modification, are permitted provided that the following conditions are 77935SN/A * met: redistributions of source code must retain the above copyright 87935SN/A * notice, this list of conditions and the following disclaimer; 97935SN/A * redistributions in binary form must reproduce the above copyright 106167SN/A * notice, this list of conditions and the following disclaimer in the 116167SN/A * documentation and/or other materials provided with the distribution; 126167SN/A * neither the name of the copyright holders nor the names of its 1310526Snilay@cs.wisc.edu * contributors may be used to endorse or promote products derived from 148835SAli.Saidi@ARM.com * this software without specific prior written permission. 159864Snilay@cs.wisc.edu * 169864Snilay@cs.wisc.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1710036SAli.Saidi@ARM.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1811312Santhony.gutierrez@amd.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 198835SAli.Saidi@ARM.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 208835SAli.Saidi@ARM.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2110315Snilay@cs.wisc.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 228835SAli.Saidi@ARM.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2310093Snilay@cs.wisc.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 247935SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 259864Snilay@cs.wisc.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2610526Snilay@cs.wisc.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2710736Snilay@cs.wisc.edu * 2811219Snilay@cs.wisc.edu * Authors: Erik Hallnor 298721SN/A * Dave Greene 308835SAli.Saidi@ARM.com */ 318835SAli.Saidi@ARM.com 3211440SCurtis.Dunham@arm.com/** 3311440SCurtis.Dunham@arm.com * @file 347935SN/A * Miss Status and Handling Register (MSHR) definitions. 357935SN/A */ 367935SN/A 377935SN/A#include <assert.h> 387935SN/A#include <string> 397935SN/A#include <vector> 407935SN/A#include <algorithm> 418983Snate@binkert.org 426167SN/A#include "mem/cache/miss/mshr.hh" 439864Snilay@cs.wisc.edu#include "sim/core.hh" // for curTick 449864Snilay@cs.wisc.edu#include "sim/host.hh" 459864Snilay@cs.wisc.edu#include "base/misc.hh" 4610315Snilay@cs.wisc.edu#include "mem/cache/cache.hh" 4710036SAli.Saidi@ARM.com 4810315Snilay@cs.wisc.eduusing namespace std; 499864Snilay@cs.wisc.edu 509864Snilay@cs.wisc.eduMSHR::MSHR() 516167SN/A{ 526167SN/A inService = false; 539864Snilay@cs.wisc.edu ntargets = 0; 5410093Snilay@cs.wisc.edu threadNum = -1; 556167SN/A targets = new TargetList(); 569864Snilay@cs.wisc.edu deferredTargets = new TargetList(); 576167SN/A} 586167SN/A 598835SAli.Saidi@ARM.com 606167SN/AMSHR::TargetList::TargetList() 616167SN/A : needsExclusive(false), hasUpgrade(false) 6210036SAli.Saidi@ARM.com{} 636167SN/A 646167SN/A 658835SAli.Saidi@ARM.cominline void 669469Snilay@cs.wisc.eduMSHR::TargetList::add(PacketPtr pkt, Tick readyTime, 676167SN/A Counter order, bool cpuSide) 686167SN/A{ 696167SN/A if (cpuSide) { 706167SN/A if (pkt->needsExclusive()) { 716167SN/A needsExclusive = true; 726167SN/A } 738835SAli.Saidi@ARM.com 746167SN/A if (pkt->cmd == MemCmd::UpgradeReq) { 759864Snilay@cs.wisc.edu hasUpgrade = true; 7610229Snilay@cs.wisc.edu } 779469Snilay@cs.wisc.edu 786167SN/A MSHR *mshr = dynamic_cast<MSHR*>(pkt->senderState); 796167SN/A if (mshr != NULL) { 806167SN/A assert(!mshr->downstreamPending); 819469Snilay@cs.wisc.edu mshr->downstreamPending = true; 829469Snilay@cs.wisc.edu } 836167SN/A } 849864Snilay@cs.wisc.edu 859864Snilay@cs.wisc.edu push_back(Target(pkt, readyTime, order, cpuSide)); 869864Snilay@cs.wisc.edu} 8710315Snilay@cs.wisc.edu 8810036SAli.Saidi@ARM.com 8910315Snilay@cs.wisc.eduvoid 909864Snilay@cs.wisc.eduMSHR::TargetList::replaceUpgrades() 919864Snilay@cs.wisc.edu{ 926167SN/A if (!hasUpgrade) 936167SN/A return; 9410036SAli.Saidi@ARM.com 956167SN/A Iterator end_i = end(); 966167SN/A for (Iterator i = begin(); i != end_i; ++i) { 978835SAli.Saidi@ARM.com if (i->pkt->cmd == MemCmd::UpgradeReq) { 988835SAli.Saidi@ARM.com i->pkt->cmd = MemCmd::ReadExReq; 9910036SAli.Saidi@ARM.com DPRINTF(Cache, "Replacing UpgradeReq with ReadExReq\n"); 1008835SAli.Saidi@ARM.com } 1019469Snilay@cs.wisc.edu } 1029469Snilay@cs.wisc.edu 10310036SAli.Saidi@ARM.com hasUpgrade = false; 1049469Snilay@cs.wisc.edu} 1059469Snilay@cs.wisc.edu 10610036SAli.Saidi@ARM.com 1079469Snilay@cs.wisc.eduvoid 1086167SN/AMSHR::TargetList::clearDownstreamPending() 1096167SN/A{ 11010036SAli.Saidi@ARM.com Iterator end_i = end(); 1116167SN/A for (Iterator i = begin(); i != end_i; ++i) { 1126167SN/A MSHR *mshr = dynamic_cast<MSHR*>(i->pkt->senderState); 1136167SN/A if (mshr != NULL) { 1146167SN/A assert(mshr->downstreamPending); 11510036SAli.Saidi@ARM.com mshr->downstreamPending = false; 1166167SN/A } 1176167SN/A } 1186167SN/A} 1196167SN/A 1206167SN/A 12110736Snilay@cs.wisc.eduvoid 1226167SN/AMSHR::allocate(Addr _addr, int _size, PacketPtr target, 1236167SN/A Tick whenReady, Counter _order) 1246167SN/A{ 1256167SN/A addr = _addr; 12610036SAli.Saidi@ARM.com size = _size; 12711390Ssteve.reinhardt@amd.com readyTime = whenReady; 1286167SN/A order = _order; 1296167SN/A assert(target); 13010736Snilay@cs.wisc.edu isCacheFill = false; 1316167SN/A _isUncacheable = target->req->isUncacheable(); 1326167SN/A inService = false; 1336167SN/A downstreamPending = false; 1346167SN/A threadNum = 0; 1356167SN/A ntargets = 1; 1366167SN/A // Don't know of a case where we would allocate a new MSHR for a 1376167SN/A // snoop (mem-side request), so set cpuSide to true here. 13810451Snilay@cs.wisc.edu assert(targets->isReset()); 1396167SN/A targets->add(target, whenReady, _order, true); 14010315Snilay@cs.wisc.edu assert(deferredTargets->isReset()); 14110315Snilay@cs.wisc.edu pendingInvalidate = false; 14210315Snilay@cs.wisc.edu pendingShared = false; 14310315Snilay@cs.wisc.edu data = NULL; 14410315Snilay@cs.wisc.edu} 14510315Snilay@cs.wisc.edu 14610315Snilay@cs.wisc.edu 14710315Snilay@cs.wisc.edubool 14810526Snilay@cs.wisc.eduMSHR::markInService() 14910526Snilay@cs.wisc.edu{ 15010526Snilay@cs.wisc.edu assert(!inService); 15110526Snilay@cs.wisc.edu if (isSimpleForward()) { 15210526Snilay@cs.wisc.edu // we just forwarded the request packet & don't expect a 15310526Snilay@cs.wisc.edu // response, so get rid of it 15410526Snilay@cs.wisc.edu assert(getNumTargets() == 1); 15510526Snilay@cs.wisc.edu popTarget(); 15610526Snilay@cs.wisc.edu return true; 15710526Snilay@cs.wisc.edu } 15810526Snilay@cs.wisc.edu inService = true; 15910526Snilay@cs.wisc.edu if (!downstreamPending) { 16010526Snilay@cs.wisc.edu // let upstream caches know that the request has made it to a 16110526Snilay@cs.wisc.edu // level where it's going to get a response 16210526Snilay@cs.wisc.edu targets->clearDownstreamPending(); 16310526Snilay@cs.wisc.edu } 16410526Snilay@cs.wisc.edu return false; 16510526Snilay@cs.wisc.edu} 16610526Snilay@cs.wisc.edu 16710526Snilay@cs.wisc.edu 16810526Snilay@cs.wisc.eduvoid 16910526Snilay@cs.wisc.eduMSHR::deallocate() 17010526Snilay@cs.wisc.edu{ 17110526Snilay@cs.wisc.edu assert(targets->empty()); 17210526Snilay@cs.wisc.edu targets->resetFlags(); 17310526Snilay@cs.wisc.edu assert(deferredTargets->isReset()); 17410526Snilay@cs.wisc.edu assert(ntargets == 0); 17510736Snilay@cs.wisc.edu inService = false; 17610526Snilay@cs.wisc.edu //allocIter = NULL; 17710526Snilay@cs.wisc.edu //readyIter = NULL; 17810526Snilay@cs.wisc.edu} 17910526Snilay@cs.wisc.edu 1809864Snilay@cs.wisc.edu/* 1819864Snilay@cs.wisc.edu * Adds a target to an MSHR 18210526Snilay@cs.wisc.edu */ 18310526Snilay@cs.wisc.eduvoid 18410526Snilay@cs.wisc.eduMSHR::allocateTarget(PacketPtr pkt, Tick whenReady, Counter _order) 18510526Snilay@cs.wisc.edu{ 18610526Snilay@cs.wisc.edu // if there's a request already in service for this MSHR, we will 18710036SAli.Saidi@ARM.com // have to defer the new target until after the response if any of 1889469Snilay@cs.wisc.edu // the following are true: 18910526Snilay@cs.wisc.edu // - there are other targets already deferred 19010526Snilay@cs.wisc.edu // - there's a pending invalidate to be applied after the response 19110526Snilay@cs.wisc.edu // comes back (but before this target is processed) 19210526Snilay@cs.wisc.edu // - the outstanding request is for a non-exclusive block and this 19310526Snilay@cs.wisc.edu // target requires an exclusive block 19410526Snilay@cs.wisc.edu if (inService && 19510526Snilay@cs.wisc.edu (!deferredTargets->empty() || pendingInvalidate || 19610526Snilay@cs.wisc.edu (!targets->needsExclusive && pkt->needsExclusive()))) { 19710526Snilay@cs.wisc.edu // need to put on deferred list 19810526Snilay@cs.wisc.edu deferredTargets->add(pkt, whenReady, _order, true); 19910526Snilay@cs.wisc.edu } else { 20010526Snilay@cs.wisc.edu // no request outstanding, or still OK to append to 20110526Snilay@cs.wisc.edu // outstanding request 20210526Snilay@cs.wisc.edu targets->add(pkt, whenReady, _order, true); 20310526Snilay@cs.wisc.edu } 20410526Snilay@cs.wisc.edu 20510526Snilay@cs.wisc.edu ++ntargets; 20610526Snilay@cs.wisc.edu} 20710526Snilay@cs.wisc.edu 20810526Snilay@cs.wisc.edubool 20910526Snilay@cs.wisc.eduMSHR::handleSnoop(PacketPtr pkt, Counter _order) 21010526Snilay@cs.wisc.edu{ 21110526Snilay@cs.wisc.edu if (!inService || (pkt->isExpressSnoop() && downstreamPending)) { 21210526Snilay@cs.wisc.edu // Request has not been issued yet, or it's been issued 21310526Snilay@cs.wisc.edu // locally but is buffered unissued at some downstream cache 21410526Snilay@cs.wisc.edu // which is forwarding us this snoop. Either way, the packet 21510526Snilay@cs.wisc.edu // we're snooping logically precedes this MSHR's request, so 21610526Snilay@cs.wisc.edu // the snoop has no impact on the MSHR, but must be processed 21710526Snilay@cs.wisc.edu // in the standard way by the cache. The only exception is 21810526Snilay@cs.wisc.edu // that if we're an L2+ cache buffering an UpgradeReq from a 21910526Snilay@cs.wisc.edu // higher-level cache, and the snoop is invalidating, then our 22010526Snilay@cs.wisc.edu // buffered upgrades must be converted to read exclusives, 22110526Snilay@cs.wisc.edu // since the upper-level cache no longer has a valid copy. 22210526Snilay@cs.wisc.edu // That is, even though the upper-level cache got out on its 22310526Snilay@cs.wisc.edu // local bus first, some other invalidating transaction 2249469Snilay@cs.wisc.edu // reached the global bus before the upgrade did. 2259469Snilay@cs.wisc.edu if (pkt->needsExclusive()) { 2269469Snilay@cs.wisc.edu targets->replaceUpgrades(); 22710036SAli.Saidi@ARM.com deferredTargets->replaceUpgrades(); 22810736Snilay@cs.wisc.edu } 22910036SAli.Saidi@ARM.com 2309469Snilay@cs.wisc.edu return false; 2319864Snilay@cs.wisc.edu } 23210036SAli.Saidi@ARM.com 23310036SAli.Saidi@ARM.com // From here on down, the request issued by this MSHR logically 23410526Snilay@cs.wisc.edu // precedes the request we're snooping. 23510036SAli.Saidi@ARM.com 23611219Snilay@cs.wisc.edu if (pkt->needsExclusive()) { 23710526Snilay@cs.wisc.edu // snooped request still precedes the re-request we'll have to 2389469Snilay@cs.wisc.edu // issue for deferred targets, if any... 2399469Snilay@cs.wisc.edu deferredTargets->replaceUpgrades(); 2409864Snilay@cs.wisc.edu } 2419864Snilay@cs.wisc.edu 2429864Snilay@cs.wisc.edu if (pendingInvalidate) { 24310315Snilay@cs.wisc.edu // a prior snoop has already appended an invalidation, so 24410036SAli.Saidi@ARM.com // logically we don't have the block anymore; no need for 24510315Snilay@cs.wisc.edu // further snooping. 2469864Snilay@cs.wisc.edu return true; 2479864Snilay@cs.wisc.edu } 2489469Snilay@cs.wisc.edu 2496928SN/A if (targets->needsExclusive || pkt->needsExclusive()) { 25011023Sjthestness@gmail.com // actual target device (typ. PhysicalMemory) will delete the 2516928SN/A // packet on reception, so we need to save a copy here 2529864Snilay@cs.wisc.edu PacketPtr cp_pkt = new Packet(pkt); 25310036SAli.Saidi@ARM.com targets->add(cp_pkt, curTick, _order, false); 2549469Snilay@cs.wisc.edu ++ntargets; 2556928SN/A 25611023Sjthestness@gmail.com if (targets->needsExclusive) { 25711023Sjthestness@gmail.com // We're awaiting an exclusive copy, so ownership is pending. 25810036SAli.Saidi@ARM.com // It's up to us to respond once the data arrives. 25911023Sjthestness@gmail.com pkt->assertMemInhibit(); 2606928SN/A pkt->setSupplyExclusive(); 2616928SN/A } else { 26211023Sjthestness@gmail.com // Someone else may respond before we get around to 26311023Sjthestness@gmail.com // processing this snoop, which means the copied request 26411023Sjthestness@gmail.com // pointer will no longer be valid 2658540SN/A cp_pkt->req = NULL; 26610526Snilay@cs.wisc.edu } 26710526Snilay@cs.wisc.edu 2689864Snilay@cs.wisc.edu if (pkt->needsExclusive()) { 2696928SN/A // This transaction will take away our pending copy 27010526Snilay@cs.wisc.edu pendingInvalidate = true; 2716928SN/A } 2729469Snilay@cs.wisc.edu } else { 2736928SN/A // Read to a read: no conflict, so no need to record as 27410036SAli.Saidi@ARM.com // target, but make sure neither reader thinks he's getting an 2759469Snilay@cs.wisc.edu // exclusive copy 2769864Snilay@cs.wisc.edu pendingShared = true; 2776928SN/A pkt->assertShared(); 2786928SN/A } 27911023Sjthestness@gmail.com 28011023Sjthestness@gmail.com return true; 28111023Sjthestness@gmail.com} 28211023Sjthestness@gmail.com 28311023Sjthestness@gmail.com 28411023Sjthestness@gmail.combool 28511023Sjthestness@gmail.comMSHR::promoteDeferredTargets() 28611023Sjthestness@gmail.com{ 28711023Sjthestness@gmail.com assert(targets->empty()); 28811023Sjthestness@gmail.com if (deferredTargets->empty()) { 28911023Sjthestness@gmail.com return false; 29011023Sjthestness@gmail.com } 29111023Sjthestness@gmail.com 29211023Sjthestness@gmail.com // swap targets & deferredTargets lists 29311023Sjthestness@gmail.com TargetList *tmp = targets; 29411023Sjthestness@gmail.com targets = deferredTargets; 29511023Sjthestness@gmail.com deferredTargets = tmp; 29611023Sjthestness@gmail.com 29711023Sjthestness@gmail.com assert(targets->size() == ntargets); 29811023Sjthestness@gmail.com 29911023Sjthestness@gmail.com // clear deferredTargets flags 30011023Sjthestness@gmail.com deferredTargets->resetFlags(); 30111023Sjthestness@gmail.com 30211023Sjthestness@gmail.com pendingInvalidate = false; 30311023Sjthestness@gmail.com pendingShared = false; 30411023Sjthestness@gmail.com order = targets->front().order; 30511023Sjthestness@gmail.com readyTime = std::max(curTick, targets->front().readyTime); 30611023Sjthestness@gmail.com 30711023Sjthestness@gmail.com return true; 30811023Sjthestness@gmail.com} 30911023Sjthestness@gmail.com 31011023Sjthestness@gmail.com 31111023Sjthestness@gmail.comvoid 31211023Sjthestness@gmail.comMSHR::handleFill(Packet *pkt, CacheBlk *blk) 31311023Sjthestness@gmail.com{ 31411023Sjthestness@gmail.com if (pendingShared) { 31511023Sjthestness@gmail.com // we snooped another read while this read was in 31611023Sjthestness@gmail.com // service... assert shared line on its behalf 31711023Sjthestness@gmail.com pkt->assertShared(); 31811023Sjthestness@gmail.com } 31911023Sjthestness@gmail.com} 32011023Sjthestness@gmail.com 32111023Sjthestness@gmail.com 32211023Sjthestness@gmail.comvoid 32311023Sjthestness@gmail.comMSHR::dump() 32411023Sjthestness@gmail.com{ 32511023Sjthestness@gmail.com ccprintf(cerr, 3269469Snilay@cs.wisc.edu "inService: %d thread: %d\n" 3277935SN/A "Addr: %x ntargets %d\n" 32811023Sjthestness@gmail.com "Targets:\n", 3297935SN/A inService, threadNum, addr, ntargets); 3309469Snilay@cs.wisc.edu#if 0 3317935SN/A TargetListIterator tar_it = targets->begin(); 33210315Snilay@cs.wisc.edu for (int i = 0; i < ntargets; i++) { 33310036SAli.Saidi@ARM.com assert(tar_it != targets->end()); 33410036SAli.Saidi@ARM.com 33511023Sjthestness@gmail.com ccprintf(cerr, "\t%d: Addr: %x cmd: %s\n", 3367935SN/A i, tar_it->pkt->getAddr(), tar_it->pkt->cmdString()); 33711023Sjthestness@gmail.com 3387935SN/A tar_it++; 3397935SN/A } 34011023Sjthestness@gmail.com#endif 34111023Sjthestness@gmail.com ccprintf(cerr, "\n"); 34211023Sjthestness@gmail.com} 3438540SN/A 3448835SAli.Saidi@ARM.comMSHR::~MSHR() 3459469Snilay@cs.wisc.edu{ 34610526Snilay@cs.wisc.edu} 3479864Snilay@cs.wisc.edu