mshr.cc revision 4920
1360SN/A/* 21458SN/A * Copyright (c) 2002-2005 The Regents of The University of Michigan 3360SN/A * All rights reserved. 4360SN/A * 5360SN/A * Redistribution and use in source and binary forms, with or without 6360SN/A * modification, are permitted provided that the following conditions are 7360SN/A * met: redistributions of source code must retain the above copyright 8360SN/A * notice, this list of conditions and the following disclaimer; 9360SN/A * redistributions in binary form must reproduce the above copyright 10360SN/A * notice, this list of conditions and the following disclaimer in the 11360SN/A * documentation and/or other materials provided with the distribution; 12360SN/A * neither the name of the copyright holders nor the names of its 13360SN/A * contributors may be used to endorse or promote products derived from 14360SN/A * this software without specific prior written permission. 15360SN/A * 16360SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17360SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18360SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19360SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20360SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21360SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22360SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23360SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24360SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25360SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26360SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272665Ssaidi@eecs.umich.edu * 282665Ssaidi@eecs.umich.edu * Authors: Erik Hallnor 292665Ssaidi@eecs.umich.edu * Dave Greene 30360SN/A */ 31360SN/A 321354SN/A/** 331354SN/A * @file 34360SN/A * Miss Status and Handling Register (MSHR) definitions. 352764Sstever@eecs.umich.edu */ 362764Sstever@eecs.umich.edu 372064SN/A#include <assert.h> 38360SN/A#include <string> 39360SN/A#include <vector> 40360SN/A#include <algorithm> 41360SN/A 42360SN/A#include "mem/cache/miss/mshr.hh" 43360SN/A#include "sim/core.hh" // for curTick 441354SN/A#include "sim/host.hh" 45360SN/A#include "base/misc.hh" 461809SN/A#include "mem/cache/cache.hh" 475543Ssaidi@eecs.umich.edu 481809SN/Ausing namespace std; 493113Sgblack@eecs.umich.edu 503113Sgblack@eecs.umich.eduMSHR::MSHR() 511999SN/A{ 52360SN/A inService = false; 532474SN/A ntargets = 0; 545543Ssaidi@eecs.umich.edu threadNum = -1; 552462SN/A targets = new TargetList(); 561354SN/A deferredTargets = new TargetList(); 576216Snate@binkert.org} 586658Snate@binkert.org 592474SN/A 602680Sktlim@umich.eduMSHR::TargetList::TargetList() 612474SN/A : needsExclusive(false), hasUpgrade(false) 622474SN/A{} 636640Svince@csl.cornell.edu 641354SN/A 65360SN/Ainline void 66360SN/AMSHR::TargetList::add(PacketPtr pkt, Tick readyTime, 67360SN/A Counter order, bool cpuSide) 68360SN/A{ 69360SN/A if (cpuSide) { 70360SN/A if (pkt->needsExclusive()) { 71360SN/A needsExclusive = true; 72360SN/A } 73378SN/A 741450SN/A if (pkt->cmd == MemCmd::UpgradeReq) { 753114Sgblack@eecs.umich.edu hasUpgrade = true; 76360SN/A } 775543Ssaidi@eecs.umich.edu 785543Ssaidi@eecs.umich.edu MSHR *mshr = dynamic_cast<MSHR*>(pkt->senderState); 795543Ssaidi@eecs.umich.edu if (mshr != NULL) { 80360SN/A assert(!mshr->downstreamPending); 81360SN/A mshr->downstreamPending = true; 82360SN/A } 83360SN/A } 84360SN/A 852680Sktlim@umich.edu push_back(Target(pkt, readyTime, order, cpuSide)); 86360SN/A} 87360SN/A 88360SN/A 89360SN/Avoid 90360SN/AMSHR::TargetList::replaceUpgrades() 91360SN/A{ 92360SN/A if (!hasUpgrade) 93360SN/A return; 94360SN/A 95360SN/A Iterator end_i = end(); 96360SN/A for (Iterator i = begin(); i != end_i; ++i) { 973114Sgblack@eecs.umich.edu if (i->pkt->cmd == MemCmd::UpgradeReq) { 98360SN/A i->pkt->cmd = MemCmd::ReadExReq; 99360SN/A DPRINTF(Cache, "Replacing UpgradeReq with ReadExReq\n"); 100360SN/A } 101360SN/A } 102360SN/A 103360SN/A hasUpgrade = false; 104360SN/A} 105360SN/A 106360SN/A 107360SN/Avoid 108360SN/AMSHR::TargetList::clearDownstreamPending() 109360SN/A{ 110360SN/A Iterator end_i = end(); 111360SN/A for (Iterator i = begin(); i != end_i; ++i) { 112360SN/A MSHR *mshr = dynamic_cast<MSHR*>(i->pkt->senderState); 113360SN/A if (mshr != NULL) { 114360SN/A assert(mshr->downstreamPending); 115360SN/A mshr->downstreamPending = false; 116360SN/A } 117360SN/A } 118360SN/A} 1192400SN/A 120360SN/A 1212461SN/Abool 1225543Ssaidi@eecs.umich.eduMSHR::TargetList::checkFunctional(PacketPtr pkt) 123360SN/A{ 124360SN/A Iterator end_i = end(); 125360SN/A for (Iterator i = begin(); i != end_i; ++i) { 126360SN/A if (pkt->checkFunctional(i->pkt)) { 127360SN/A return true; 1282400SN/A } 129360SN/A } 1302461SN/A 1315543Ssaidi@eecs.umich.edu return false; 132360SN/A} 133360SN/A 134360SN/A 135360SN/Avoid 136360SN/AMSHR::allocate(Addr _addr, int _size, PacketPtr target, 137360SN/A Tick whenReady, Counter _order) 138360SN/A{ 139360SN/A addr = _addr; 140360SN/A size = _size; 141360SN/A readyTime = whenReady; 142360SN/A order = _order; 143360SN/A assert(target); 144360SN/A isCacheFill = false; 1455543Ssaidi@eecs.umich.edu _isUncacheable = target->req->isUncacheable(); 146360SN/A inService = false; 147360SN/A downstreamPending = false; 148360SN/A threadNum = 0; 149360SN/A ntargets = 1; 150360SN/A // Don't know of a case where we would allocate a new MSHR for a 151360SN/A // snoop (mem-side request), so set cpuSide to true here. 152360SN/A assert(targets->isReset()); 153360SN/A targets->add(target, whenReady, _order, true); 154360SN/A assert(deferredTargets->isReset()); 155360SN/A pendingInvalidate = false; 156360SN/A pendingShared = false; 157360SN/A data = NULL; 158360SN/A} 159360SN/A 160360SN/A 161360SN/Abool 162360SN/AMSHR::markInService() 1635543Ssaidi@eecs.umich.edu{ 1645543Ssaidi@eecs.umich.edu assert(!inService); 165502SN/A if (isSimpleForward()) { 166360SN/A // we just forwarded the request packet & don't expect a 167360SN/A // response, so get rid of it 168360SN/A assert(getNumTargets() == 1); 169360SN/A popTarget(); 170360SN/A return true; 171360SN/A } 172360SN/A inService = true; 173360SN/A if (!downstreamPending) { 174360SN/A // let upstream caches know that the request has made it to a 175360SN/A // level where it's going to get a response 176360SN/A targets->clearDownstreamPending(); 177378SN/A } 1781706SN/A return false; 1793114Sgblack@eecs.umich.edu} 180378SN/A 181378SN/A 182378SN/Avoid 183378SN/AMSHR::deallocate() 184378SN/A{ 1851706SN/A assert(targets->empty()); 1863114Sgblack@eecs.umich.edu targets->resetFlags(); 187360SN/A assert(deferredTargets->isReset()); 1886109Ssanchezd@stanford.edu assert(ntargets == 0); 1891706SN/A inService = false; 1903114Sgblack@eecs.umich.edu //allocIter = NULL; 191378SN/A //readyIter = NULL; 1926109Ssanchezd@stanford.edu} 1936109Ssanchezd@stanford.edu 1946109Ssanchezd@stanford.edu/* 1956109Ssanchezd@stanford.edu * Adds a target to an MSHR 196378SN/A */ 1971706SN/Avoid 1983114Sgblack@eecs.umich.eduMSHR::allocateTarget(PacketPtr pkt, Tick whenReady, Counter _order) 199378SN/A{ 2005748SSteve.Reinhardt@amd.com // if there's a request already in service for this MSHR, we will 2015748SSteve.Reinhardt@amd.com // have to defer the new target until after the response if any of 2025748SSteve.Reinhardt@amd.com // the following are true: 203378SN/A // - there are other targets already deferred 204378SN/A // - there's a pending invalidate to be applied after the response 2051706SN/A // comes back (but before this target is processed) 2063114Sgblack@eecs.umich.edu // - the outstanding request is for a non-exclusive block and this 207378SN/A // target requires an exclusive block 208378SN/A if (inService && 2091706SN/A (!deferredTargets->empty() || pendingInvalidate || 2103114Sgblack@eecs.umich.edu (!targets->needsExclusive && pkt->needsExclusive()))) { 211378SN/A // need to put on deferred list 212378SN/A deferredTargets->add(pkt, whenReady, _order, true); 2131706SN/A } else { 2143114Sgblack@eecs.umich.edu // no request outstanding, or still OK to append to 215378SN/A // outstanding request 216378SN/A targets->add(pkt, whenReady, _order, true); 2171706SN/A } 2183114Sgblack@eecs.umich.edu 219378SN/A ++ntargets; 2204118Sgblack@eecs.umich.edu} 2214118Sgblack@eecs.umich.edu 2224118Sgblack@eecs.umich.edubool 2234118Sgblack@eecs.umich.eduMSHR::handleSnoop(PacketPtr pkt, Counter _order) 224378SN/A{ 2251706SN/A if (!inService || (pkt->isExpressSnoop() && downstreamPending)) { 2263114Sgblack@eecs.umich.edu // Request has not been issued yet, or it's been issued 227378SN/A // locally but is buffered unissued at some downstream cache 228378SN/A // which is forwarding us this snoop. Either way, the packet 2291706SN/A // we're snooping logically precedes this MSHR's request, so 2303114Sgblack@eecs.umich.edu // the snoop has no impact on the MSHR, but must be processed 231360SN/A // in the standard way by the cache. The only exception is 2325513SMichael.Adler@intel.com // that if we're an L2+ cache buffering an UpgradeReq from a 2335513SMichael.Adler@intel.com // higher-level cache, and the snoop is invalidating, then our 2345513SMichael.Adler@intel.com // buffered upgrades must be converted to read exclusives, 2355513SMichael.Adler@intel.com // since the upper-level cache no longer has a valid copy. 2365513SMichael.Adler@intel.com // That is, even though the upper-level cache got out on its 2375513SMichael.Adler@intel.com // local bus first, some other invalidating transaction 2385513SMichael.Adler@intel.com // reached the global bus before the upgrade did. 2395513SMichael.Adler@intel.com if (pkt->needsExclusive()) { 240511SN/A targets->replaceUpgrades(); 2411706SN/A deferredTargets->replaceUpgrades(); 2423114Sgblack@eecs.umich.edu } 243511SN/A 2445513SMichael.Adler@intel.com return false; 2455513SMichael.Adler@intel.com } 2465513SMichael.Adler@intel.com 2475513SMichael.Adler@intel.com // From here on down, the request issued by this MSHR logically 248511SN/A // precedes the request we're snooping. 2491706SN/A 2503114Sgblack@eecs.umich.edu if (pkt->needsExclusive()) { 2511706SN/A // snooped request still precedes the re-request we'll have to 2521706SN/A // issue for deferred targets, if any... 2531706SN/A deferredTargets->replaceUpgrades(); 2541706SN/A } 2553114Sgblack@eecs.umich.edu 2561706SN/A if (pendingInvalidate) { 2571706SN/A // a prior snoop has already appended an invalidation, so 2581706SN/A // logically we don't have the block anymore; no need for 2591706SN/A // further snooping. 2603114Sgblack@eecs.umich.edu return true; 2611706SN/A } 262511SN/A 2635513SMichael.Adler@intel.com if (targets->needsExclusive || pkt->needsExclusive()) { 2645513SMichael.Adler@intel.com // actual target device (typ. PhysicalMemory) will delete the 2655513SMichael.Adler@intel.com // packet on reception, so we need to save a copy here 2665513SMichael.Adler@intel.com PacketPtr cp_pkt = new Packet(pkt); 2675513SMichael.Adler@intel.com targets->add(cp_pkt, curTick, _order, false); 2681999SN/A ++ntargets; 2691999SN/A 2703114Sgblack@eecs.umich.edu if (targets->needsExclusive) { 2711999SN/A // We're awaiting an exclusive copy, so ownership is pending. 2721999SN/A // It's up to us to respond once the data arrives. 2731999SN/A pkt->assertMemInhibit(); 2741999SN/A pkt->setSupplyExclusive(); 2753114Sgblack@eecs.umich.edu } else { 2761999SN/A // Someone else may respond before we get around to 2773079Sstever@eecs.umich.edu // processing this snoop, which means the copied request 2783079Sstever@eecs.umich.edu // pointer will no longer be valid 2793114Sgblack@eecs.umich.edu cp_pkt->req = NULL; 2803079Sstever@eecs.umich.edu } 2812093SN/A 2822093SN/A if (pkt->needsExclusive()) { 2833114Sgblack@eecs.umich.edu // This transaction will take away our pending copy 2842093SN/A pendingInvalidate = true; 2852687Sksewell@umich.edu } 2862687Sksewell@umich.edu } else { 2873114Sgblack@eecs.umich.edu // Read to a read: no conflict, so no need to record as 2882687Sksewell@umich.edu // target, but make sure neither reader thinks he's getting an 2892238SN/A // exclusive copy 2902238SN/A pendingShared = true; 2913114Sgblack@eecs.umich.edu pkt->assertShared(); 2922238SN/A } 2932238SN/A 2942238SN/A return true; 2953114Sgblack@eecs.umich.edu} 2962238SN/A 2972238SN/A 2982238SN/Abool 2993114Sgblack@eecs.umich.eduMSHR::promoteDeferredTargets() 3002238SN/A{ 3012238SN/A assert(targets->empty()); 3022238SN/A if (deferredTargets->empty()) { 3033114Sgblack@eecs.umich.edu return false; 3042238SN/A } 3052238SN/A 3062238SN/A // swap targets & deferredTargets lists 3073114Sgblack@eecs.umich.edu TargetList *tmp = targets; 3082238SN/A targets = deferredTargets; 3092238SN/A deferredTargets = tmp; 3102238SN/A 3113114Sgblack@eecs.umich.edu assert(targets->size() == ntargets); 3122238SN/A 3132238SN/A // clear deferredTargets flags 3142238SN/A deferredTargets->resetFlags(); 3153114Sgblack@eecs.umich.edu 3162238SN/A pendingInvalidate = false; 3176109Ssanchezd@stanford.edu pendingShared = false; 3186109Ssanchezd@stanford.edu order = targets->front().order; 3196109Ssanchezd@stanford.edu readyTime = std::max(curTick, targets->front().readyTime); 3202238SN/A 3212238SN/A return true; 3222238SN/A} 3232238SN/A 3242238SN/A 3253114Sgblack@eecs.umich.eduvoid 3262238SN/AMSHR::handleFill(Packet *pkt, CacheBlk *blk) 3272238SN/A{ 3282238SN/A if (pendingShared) { 3293114Sgblack@eecs.umich.edu // we snooped another read while this read was in 3302238SN/A // service... assert shared line on its behalf 3312238SN/A pkt->assertShared(); 3322238SN/A } 3333114Sgblack@eecs.umich.edu} 3342238SN/A 3352238SN/A 3362238SN/Avoid 3373114Sgblack@eecs.umich.eduMSHR::dump() 3382238SN/A{ 3392238SN/A ccprintf(cerr, 3401354SN/A "inService: %d thread: %d\n" 3411354SN/A "Addr: %x ntargets %d\n" 3421354SN/A "Targets:\n", 3431354SN/A inService, threadNum, addr, ntargets); 3441354SN/A#if 0 3451354SN/A TargetListIterator tar_it = targets->begin(); 3461354SN/A for (int i = 0; i < ntargets; i++) { 3471354SN/A assert(tar_it != targets->end()); 3481354SN/A 3491354SN/A ccprintf(cerr, "\t%d: Addr: %x cmd: %s\n", 3501354SN/A i, tar_it->pkt->getAddr(), tar_it->pkt->cmdString()); 3511354SN/A 3521354SN/A tar_it++; 3531354SN/A } 3541609SN/A#endif 3551354SN/A ccprintf(cerr, "\n"); 3561354SN/A} 3571354SN/A 3581354SN/AMSHR::~MSHR() 359360SN/A{ 360360SN/A} 361360SN/A