mshr.cc revision 5314
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 441809SN/A#include "sim/host.hh" 455543Ssaidi@eecs.umich.edu#include "base/misc.hh" 461809SN/A#include "mem/cache/cache.hh" 473113Sgblack@eecs.umich.edu 487075Snate@binkert.orgusing namespace std; 493113Sgblack@eecs.umich.edu 501999SN/AMSHR::MSHR() 517075Snate@binkert.org{ 527075Snate@binkert.org inService = false; 537075Snate@binkert.org ntargets = 0; 54360SN/A threadNum = -1; 552474SN/A targets = new TargetList(); 565543Ssaidi@eecs.umich.edu deferredTargets = new TargetList(); 572462SN/A} 581354SN/A 596216Snate@binkert.org 606658Snate@binkert.orgMSHR::TargetList::TargetList() 612474SN/A : needsExclusive(false), hasUpgrade(false) 622680Sktlim@umich.edu{} 632474SN/A 642474SN/A 657678Sgblack@eecs.umich.eduinline void 666640Svince@csl.cornell.eduMSHR::TargetList::add(PacketPtr pkt, Tick readyTime, 671354SN/A Counter order, bool cpuSide) 68360SN/A{ 69360SN/A if (cpuSide) { 70360SN/A if (pkt->needsExclusive()) { 71360SN/A needsExclusive = true; 72360SN/A } 73360SN/A 74360SN/A if (pkt->cmd == MemCmd::UpgradeReq) { 75360SN/A hasUpgrade = true; 76378SN/A } 771450SN/A 783114Sgblack@eecs.umich.edu MSHR *mshr = dynamic_cast<MSHR*>(pkt->senderState); 79360SN/A if (mshr != NULL) { 805543Ssaidi@eecs.umich.edu assert(!mshr->downstreamPending); 815543Ssaidi@eecs.umich.edu mshr->downstreamPending = true; 825543Ssaidi@eecs.umich.edu } 83360SN/A } 84360SN/A 85360SN/A push_back(Target(pkt, readyTime, order, cpuSide)); 86360SN/A} 87360SN/A 882680Sktlim@umich.edu 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) { 97360SN/A if (i->pkt->cmd == MemCmd::UpgradeReq) { 98360SN/A i->pkt->cmd = MemCmd::ReadExReq; 99360SN/A DPRINTF(Cache, "Replacing UpgradeReq with ReadExReq\n"); 1003114Sgblack@eecs.umich.edu } 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} 119360SN/A 120360SN/A 121360SN/Abool 1222400SN/AMSHR::TargetList::checkFunctional(PacketPtr pkt) 123360SN/A{ 1242461SN/A Iterator end_i = end(); 1255543Ssaidi@eecs.umich.edu for (Iterator i = begin(); i != end_i; ++i) { 126360SN/A if (pkt->checkFunctional(i->pkt)) { 127360SN/A return true; 128360SN/A } 129360SN/A } 130360SN/A 1312400SN/A return false; 132360SN/A} 1332461SN/A 1345543Ssaidi@eecs.umich.edu 135360SN/Avoid 136360SN/AMSHR::TargetList:: 137360SN/Aprint(std::ostream &os, int verbosity, const std::string &prefix) const 138360SN/A{ 139360SN/A ConstIterator end_i = end(); 140360SN/A for (ConstIterator i = begin(); i != end_i; ++i) { 141360SN/A ccprintf(os, "%s%s: ", prefix, i->isCpuSide() ? "cpu" : "mem"); 142360SN/A i->pkt->print(os, verbosity, ""); 143360SN/A } 144360SN/A} 145360SN/A 146360SN/A 147360SN/Avoid 1485543Ssaidi@eecs.umich.eduMSHR::allocate(Addr _addr, int _size, PacketPtr target, 149360SN/A Tick whenReady, Counter _order) 150360SN/A{ 151360SN/A addr = _addr; 152360SN/A size = _size; 153360SN/A readyTime = whenReady; 154360SN/A order = _order; 155360SN/A assert(target); 156360SN/A isCacheFill = false; 157360SN/A _isUncacheable = target->req->isUncacheable(); 158360SN/A inService = false; 159360SN/A downstreamPending = false; 160360SN/A threadNum = 0; 161360SN/A ntargets = 1; 162360SN/A // Don't know of a case where we would allocate a new MSHR for a 163360SN/A // snoop (mem-side request), so set cpuSide to true here. 164360SN/A assert(targets->isReset()); 165360SN/A targets->add(target, whenReady, _order, true); 1665543Ssaidi@eecs.umich.edu assert(deferredTargets->isReset()); 1675543Ssaidi@eecs.umich.edu pendingInvalidate = false; 168502SN/A pendingShared = false; 169360SN/A data = NULL; 170360SN/A} 171360SN/A 172360SN/A 173360SN/Abool 174360SN/AMSHR::markInService() 175360SN/A{ 176360SN/A assert(!inService); 177360SN/A if (isSimpleForward()) { 178360SN/A // we just forwarded the request packet & don't expect a 179360SN/A // response, so get rid of it 180378SN/A assert(getNumTargets() == 1); 1811706SN/A popTarget(); 1823114Sgblack@eecs.umich.edu return true; 183378SN/A } 184378SN/A inService = true; 185378SN/A if (!downstreamPending) { 186378SN/A // let upstream caches know that the request has made it to a 187378SN/A // level where it's going to get a response 1881706SN/A targets->clearDownstreamPending(); 1893114Sgblack@eecs.umich.edu } 190360SN/A return false; 1916109Ssanchezd@stanford.edu} 1921706SN/A 1933114Sgblack@eecs.umich.edu 194378SN/Avoid 1956109Ssanchezd@stanford.eduMSHR::deallocate() 1966109Ssanchezd@stanford.edu{ 1976109Ssanchezd@stanford.edu assert(targets->empty()); 1986109Ssanchezd@stanford.edu targets->resetFlags(); 199378SN/A assert(deferredTargets->isReset()); 2001706SN/A assert(ntargets == 0); 2013114Sgblack@eecs.umich.edu inService = false; 202378SN/A //allocIter = NULL; 2035748SSteve.Reinhardt@amd.com //readyIter = NULL; 2045748SSteve.Reinhardt@amd.com} 2055748SSteve.Reinhardt@amd.com 206378SN/A/* 207378SN/A * Adds a target to an MSHR 2081706SN/A */ 2093114Sgblack@eecs.umich.eduvoid 210378SN/AMSHR::allocateTarget(PacketPtr pkt, Tick whenReady, Counter _order) 211378SN/A{ 2121706SN/A // if there's a request already in service for this MSHR, we will 2133114Sgblack@eecs.umich.edu // have to defer the new target until after the response if any of 214378SN/A // the following are true: 215378SN/A // - there are other targets already deferred 2161706SN/A // - there's a pending invalidate to be applied after the response 2173114Sgblack@eecs.umich.edu // comes back (but before this target is processed) 218378SN/A // - the outstanding request is for a non-exclusive block and this 219378SN/A // target requires an exclusive block 2201706SN/A if (inService && 2213114Sgblack@eecs.umich.edu (!deferredTargets->empty() || pendingInvalidate || 222378SN/A (!targets->needsExclusive && pkt->needsExclusive()))) { 2234118Sgblack@eecs.umich.edu // need to put on deferred list 2244118Sgblack@eecs.umich.edu deferredTargets->add(pkt, whenReady, _order, true); 2254118Sgblack@eecs.umich.edu } else { 2264118Sgblack@eecs.umich.edu // no request outstanding, or still OK to append to 227378SN/A // outstanding request 2281706SN/A targets->add(pkt, whenReady, _order, true); 2293114Sgblack@eecs.umich.edu } 230378SN/A 231378SN/A ++ntargets; 2321706SN/A} 2333114Sgblack@eecs.umich.edu 234360SN/Abool 2355513SMichael.Adler@intel.comMSHR::handleSnoop(PacketPtr pkt, Counter _order) 2365513SMichael.Adler@intel.com{ 2375513SMichael.Adler@intel.com if (!inService || (pkt->isExpressSnoop() && downstreamPending)) { 2385513SMichael.Adler@intel.com // Request has not been issued yet, or it's been issued 2395513SMichael.Adler@intel.com // locally but is buffered unissued at some downstream cache 2405513SMichael.Adler@intel.com // which is forwarding us this snoop. Either way, the packet 2415513SMichael.Adler@intel.com // we're snooping logically precedes this MSHR's request, so 2425513SMichael.Adler@intel.com // the snoop has no impact on the MSHR, but must be processed 243511SN/A // in the standard way by the cache. The only exception is 2441706SN/A // that if we're an L2+ cache buffering an UpgradeReq from a 2453114Sgblack@eecs.umich.edu // higher-level cache, and the snoop is invalidating, then our 246511SN/A // buffered upgrades must be converted to read exclusives, 2475513SMichael.Adler@intel.com // since the upper-level cache no longer has a valid copy. 2485513SMichael.Adler@intel.com // That is, even though the upper-level cache got out on its 2495513SMichael.Adler@intel.com // local bus first, some other invalidating transaction 2505513SMichael.Adler@intel.com // reached the global bus before the upgrade did. 251511SN/A if (pkt->needsExclusive()) { 2521706SN/A targets->replaceUpgrades(); 2533114Sgblack@eecs.umich.edu deferredTargets->replaceUpgrades(); 2541706SN/A } 2551706SN/A 2561706SN/A return false; 2571706SN/A } 2583114Sgblack@eecs.umich.edu 2591706SN/A // From here on down, the request issued by this MSHR logically 2601706SN/A // precedes the request we're snooping. 2611706SN/A 2621706SN/A if (pkt->needsExclusive()) { 2633114Sgblack@eecs.umich.edu // snooped request still precedes the re-request we'll have to 2641706SN/A // issue for deferred targets, if any... 265511SN/A deferredTargets->replaceUpgrades(); 2666703Svince@csl.cornell.edu } 2676703Svince@csl.cornell.edu 2686703Svince@csl.cornell.edu if (pendingInvalidate) { 2696703Svince@csl.cornell.edu // a prior snoop has already appended an invalidation, so 2706685Stjones1@inf.ed.ac.uk // logically we don't have the block anymore; no need for 2716685Stjones1@inf.ed.ac.uk // further snooping. 2726685Stjones1@inf.ed.ac.uk return true; 2736685Stjones1@inf.ed.ac.uk } 2746685Stjones1@inf.ed.ac.uk 2755513SMichael.Adler@intel.com if (targets->needsExclusive || pkt->needsExclusive()) { 2765513SMichael.Adler@intel.com // actual target device (typ. PhysicalMemory) will delete the 2775513SMichael.Adler@intel.com // packet on reception, so we need to save a copy here 2785513SMichael.Adler@intel.com PacketPtr cp_pkt = new Packet(pkt, true); 2795513SMichael.Adler@intel.com targets->add(cp_pkt, curTick, _order, false); 2801999SN/A ++ntargets; 2811999SN/A 2823114Sgblack@eecs.umich.edu if (targets->needsExclusive) { 2831999SN/A // We're awaiting an exclusive copy, so ownership is pending. 2841999SN/A // It's up to us to respond once the data arrives. 2851999SN/A pkt->assertMemInhibit(); 2861999SN/A pkt->setSupplyExclusive(); 2873114Sgblack@eecs.umich.edu } else { 2881999SN/A // Someone else may respond before we get around to 2893079Sstever@eecs.umich.edu // processing this snoop, which means the copied request 2903079Sstever@eecs.umich.edu // pointer will no longer be valid 2913114Sgblack@eecs.umich.edu cp_pkt->req = NULL; 2923079Sstever@eecs.umich.edu } 2932093SN/A 2942093SN/A if (pkt->needsExclusive()) { 2953114Sgblack@eecs.umich.edu // This transaction will take away our pending copy 2962093SN/A pendingInvalidate = true; 2972687Sksewell@umich.edu } 2982687Sksewell@umich.edu } else { 2993114Sgblack@eecs.umich.edu // Read to a read: no conflict, so no need to record as 3002687Sksewell@umich.edu // target, but make sure neither reader thinks he's getting an 3012238SN/A // exclusive copy 3022238SN/A pendingShared = true; 3033114Sgblack@eecs.umich.edu pkt->assertShared(); 3042238SN/A } 3052238SN/A 3062238SN/A return true; 3073114Sgblack@eecs.umich.edu} 3082238SN/A 3092238SN/A 3102238SN/Abool 3113114Sgblack@eecs.umich.eduMSHR::promoteDeferredTargets() 3122238SN/A{ 3132238SN/A assert(targets->empty()); 3142238SN/A if (deferredTargets->empty()) { 3153114Sgblack@eecs.umich.edu return false; 3162238SN/A } 3172238SN/A 3182238SN/A // swap targets & deferredTargets lists 3193114Sgblack@eecs.umich.edu TargetList *tmp = targets; 3202238SN/A targets = deferredTargets; 3212238SN/A deferredTargets = tmp; 3222238SN/A 3233114Sgblack@eecs.umich.edu assert(targets->size() == ntargets); 3242238SN/A 3252238SN/A // clear deferredTargets flags 3262238SN/A deferredTargets->resetFlags(); 3273114Sgblack@eecs.umich.edu 3282238SN/A pendingInvalidate = false; 3296109Ssanchezd@stanford.edu pendingShared = false; 3306109Ssanchezd@stanford.edu order = targets->front().order; 3316109Ssanchezd@stanford.edu readyTime = std::max(curTick, targets->front().readyTime); 3322238SN/A 3332238SN/A return true; 3342238SN/A} 3352238SN/A 3362238SN/A 3373114Sgblack@eecs.umich.eduvoid 3382238SN/AMSHR::handleFill(Packet *pkt, CacheBlk *blk) 3392238SN/A{ 3402238SN/A if (pendingShared) { 3413114Sgblack@eecs.umich.edu // we snooped another read while this read was in 3422238SN/A // service... assert shared line on its behalf 3432238SN/A pkt->assertShared(); 3442238SN/A } 3453114Sgblack@eecs.umich.edu 3462238SN/A if (!pkt->sharedAsserted() && !pendingInvalidate 3472238SN/A && deferredTargets->needsExclusive) { 3482238SN/A // We got an exclusive response, but we have deferred targets 3493114Sgblack@eecs.umich.edu // which are waiting to request an exclusive copy (not because 3502238SN/A // of a pending invalidate). This can happen if the original 3512238SN/A // request was for a read-only (non-exclusive) block, but we 3521354SN/A // got an exclusive copy anyway because of the E part of the 3531354SN/A // MOESI/MESI protocol. Since we got the exclusive copy 3541354SN/A // there's no need to defer the targets, so move them up to 3551354SN/A // the regular target list. 3561354SN/A assert(!targets->needsExclusive); 3571354SN/A targets->needsExclusive = true; 3581354SN/A // this clears out deferredTargets too 3591354SN/A targets->splice(targets->end(), *deferredTargets); 3601354SN/A deferredTargets->resetFlags(); 3611354SN/A } 3621354SN/A} 3631354SN/A 3641354SN/A 3651354SN/Abool 3667823Ssteve.reinhardt@amd.comMSHR::checkFunctional(PacketPtr pkt) 3671354SN/A{ 3681354SN/A // For printing, we treat the MSHR as a whole as single entity. 3691354SN/A // For other requests, we iterate over the individual targets 3701354SN/A // since that's where the actual data lies. 371360SN/A if (pkt->isPrint()) { 372360SN/A pkt->checkFunctional(this, addr, size, NULL); 373360SN/A return false; 374360SN/A } else { 375360SN/A return (targets->checkFunctional(pkt) || 376360SN/A deferredTargets->checkFunctional(pkt)); 377360SN/A } 3783113Sgblack@eecs.umich.edu} 3793113Sgblack@eecs.umich.edu 3803113Sgblack@eecs.umich.edu 3813113Sgblack@eecs.umich.eduvoid 3823113Sgblack@eecs.umich.eduMSHR::print(std::ostream &os, int verbosity, const std::string &prefix) const 3833113Sgblack@eecs.umich.edu{ 3843113Sgblack@eecs.umich.edu ccprintf(os, "%s[%x:%x] %s %s %s state: %s %s %s %s\n", 3853113Sgblack@eecs.umich.edu prefix, addr, addr+size-1, 3863113Sgblack@eecs.umich.edu isCacheFill ? "Fill" : "", 3873113Sgblack@eecs.umich.edu needsExclusive() ? "Excl" : "", 3883113Sgblack@eecs.umich.edu _isUncacheable ? "Unc" : "", 3893113Sgblack@eecs.umich.edu inService ? "InSvc" : "", 3903113Sgblack@eecs.umich.edu downstreamPending ? "DwnPend" : "", 3913113Sgblack@eecs.umich.edu pendingInvalidate ? "PendInv" : "", 3923113Sgblack@eecs.umich.edu pendingShared ? "PendShared" : ""); 3933113Sgblack@eecs.umich.edu 3944189Sgblack@eecs.umich.edu ccprintf(os, "%s Targets:\n", prefix); 3954189Sgblack@eecs.umich.edu targets->print(os, verbosity, prefix + " "); 3963113Sgblack@eecs.umich.edu if (!deferredTargets->empty()) { 3973113Sgblack@eecs.umich.edu ccprintf(os, "%s Deferred Targets:\n", prefix); 3983113Sgblack@eecs.umich.edu deferredTargets->print(os, verbosity, prefix + " "); 3993113Sgblack@eecs.umich.edu } 4003113Sgblack@eecs.umich.edu} 4013113Sgblack@eecs.umich.edu 4023113Sgblack@eecs.umich.eduMSHR::~MSHR() 4033277Sgblack@eecs.umich.edu{ 4045515SMichael.Adler@intel.com} 4055515SMichael.Adler@intel.com