mshr.cc revision 5875
12810SN/A/* 22810SN/A * Copyright (c) 2002-2005 The Regents of The University of Michigan 32810SN/A * All rights reserved. 42810SN/A * 52810SN/A * Redistribution and use in source and binary forms, with or without 62810SN/A * modification, are permitted provided that the following conditions are 72810SN/A * met: redistributions of source code must retain the above copyright 82810SN/A * notice, this list of conditions and the following disclaimer; 92810SN/A * redistributions in binary form must reproduce the above copyright 102810SN/A * notice, this list of conditions and the following disclaimer in the 112810SN/A * documentation and/or other materials provided with the distribution; 122810SN/A * neither the name of the copyright holders nor the names of its 132810SN/A * contributors may be used to endorse or promote products derived from 142810SN/A * this software without specific prior written permission. 152810SN/A * 162810SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 172810SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 182810SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 192810SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 202810SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 212810SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 222810SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 232810SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 242810SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 252810SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 262810SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272810SN/A * 282810SN/A * Authors: Erik Hallnor 292810SN/A * Dave Greene 302810SN/A */ 312810SN/A 322810SN/A/** 332810SN/A * @file 342810SN/A * Miss Status and Handling Register (MSHR) definitions. 352810SN/A */ 362810SN/A 372810SN/A#include <assert.h> 382810SN/A#include <string> 392810SN/A#include <vector> 404666SN/A#include <algorithm> 412810SN/A 425338Sstever@gmail.com#include "mem/cache/mshr.hh" 434167SN/A#include "sim/core.hh" // for curTick 442810SN/A#include "sim/host.hh" 452810SN/A#include "base/misc.hh" 462810SN/A#include "mem/cache/cache.hh" 472810SN/A 482810SN/Ausing namespace std; 492810SN/A 502810SN/AMSHR::MSHR() 512810SN/A{ 522810SN/A inService = false; 532810SN/A ntargets = 0; 542813SN/A threadNum = -1; 554903SN/A targets = new TargetList(); 564903SN/A deferredTargets = new TargetList(); 572810SN/A} 582810SN/A 594903SN/A 604903SN/AMSHR::TargetList::TargetList() 614903SN/A : needsExclusive(false), hasUpgrade(false) 624903SN/A{} 634903SN/A 644903SN/A 654903SN/Ainline void 664908SN/AMSHR::TargetList::add(PacketPtr pkt, Tick readyTime, 675875Ssteve.reinhardt@amd.com Counter order, Target::Source source, bool markPending) 684903SN/A{ 695875Ssteve.reinhardt@amd.com if (source != Target::FromSnoop) { 704903SN/A if (pkt->needsExclusive()) { 714903SN/A needsExclusive = true; 724903SN/A } 734903SN/A 744903SN/A if (pkt->cmd == MemCmd::UpgradeReq) { 754903SN/A hasUpgrade = true; 764903SN/A } 775318SN/A } 784908SN/A 795318SN/A if (markPending) { 804908SN/A MSHR *mshr = dynamic_cast<MSHR*>(pkt->senderState); 814908SN/A if (mshr != NULL) { 824908SN/A assert(!mshr->downstreamPending); 834908SN/A mshr->downstreamPending = true; 844908SN/A } 854903SN/A } 864903SN/A 875875Ssteve.reinhardt@amd.com push_back(Target(pkt, readyTime, order, source, markPending)); 884903SN/A} 894903SN/A 904903SN/A 914903SN/Avoid 924903SN/AMSHR::TargetList::replaceUpgrades() 934903SN/A{ 944903SN/A if (!hasUpgrade) 954903SN/A return; 964903SN/A 974903SN/A Iterator end_i = end(); 984903SN/A for (Iterator i = begin(); i != end_i; ++i) { 994903SN/A if (i->pkt->cmd == MemCmd::UpgradeReq) { 1004903SN/A i->pkt->cmd = MemCmd::ReadExReq; 1014903SN/A DPRINTF(Cache, "Replacing UpgradeReq with ReadExReq\n"); 1024903SN/A } 1034903SN/A } 1044903SN/A 1054903SN/A hasUpgrade = false; 1064903SN/A} 1074903SN/A 1084903SN/A 1092810SN/Avoid 1104908SN/AMSHR::TargetList::clearDownstreamPending() 1114908SN/A{ 1124908SN/A Iterator end_i = end(); 1134908SN/A for (Iterator i = begin(); i != end_i; ++i) { 1145318SN/A if (i->markedPending) { 1155318SN/A MSHR *mshr = dynamic_cast<MSHR*>(i->pkt->senderState); 1165318SN/A if (mshr != NULL) { 1175318SN/A mshr->clearDownstreamPending(); 1185318SN/A } 1194908SN/A } 1204908SN/A } 1214908SN/A} 1224908SN/A 1234908SN/A 1244920SN/Abool 1254920SN/AMSHR::TargetList::checkFunctional(PacketPtr pkt) 1264920SN/A{ 1274920SN/A Iterator end_i = end(); 1284920SN/A for (Iterator i = begin(); i != end_i; ++i) { 1294920SN/A if (pkt->checkFunctional(i->pkt)) { 1304920SN/A return true; 1314920SN/A } 1324920SN/A } 1334920SN/A 1344920SN/A return false; 1354920SN/A} 1364920SN/A 1374920SN/A 1384908SN/Avoid 1395314SN/AMSHR::TargetList:: 1405314SN/Aprint(std::ostream &os, int verbosity, const std::string &prefix) const 1415314SN/A{ 1425314SN/A ConstIterator end_i = end(); 1435314SN/A for (ConstIterator i = begin(); i != end_i; ++i) { 1445875Ssteve.reinhardt@amd.com const char *s; 1455875Ssteve.reinhardt@amd.com switch (i->source) { 1465875Ssteve.reinhardt@amd.com case Target::FromCPU: s = "FromCPU"; 1475875Ssteve.reinhardt@amd.com case Target::FromSnoop: s = "FromSnoop"; 1485875Ssteve.reinhardt@amd.com case Target::FromPrefetcher: s = "FromPrefetcher"; 1495875Ssteve.reinhardt@amd.com default: s = ""; 1505875Ssteve.reinhardt@amd.com } 1515875Ssteve.reinhardt@amd.com ccprintf(os, "%s%s: ", prefix, s); 1525314SN/A i->pkt->print(os, verbosity, ""); 1535314SN/A } 1545314SN/A} 1555314SN/A 1565314SN/A 1575314SN/Avoid 1584666SN/AMSHR::allocate(Addr _addr, int _size, PacketPtr target, 1594871SN/A Tick whenReady, Counter _order) 1602810SN/A{ 1612885SN/A addr = _addr; 1624626SN/A size = _size; 1634871SN/A readyTime = whenReady; 1644666SN/A order = _order; 1654626SN/A assert(target); 1665730SSteve.Reinhardt@amd.com isForward = false; 1674626SN/A _isUncacheable = target->req->isUncacheable(); 1684626SN/A inService = false; 1694908SN/A downstreamPending = false; 1704626SN/A threadNum = 0; 1714626SN/A ntargets = 1; 1725875Ssteve.reinhardt@amd.com assert(targets->isReset()); 1734626SN/A // Don't know of a case where we would allocate a new MSHR for a 1745875Ssteve.reinhardt@amd.com // snoop (mem-side request), so set source according to request here 1755875Ssteve.reinhardt@amd.com Target::Source source = (target->cmd == MemCmd::HardPFReq) ? 1765875Ssteve.reinhardt@amd.com Target::FromPrefetcher : Target::FromCPU; 1775875Ssteve.reinhardt@amd.com targets->add(target, whenReady, _order, source, true); 1784903SN/A assert(deferredTargets->isReset()); 1794665SN/A pendingInvalidate = false; 1804670SN/A pendingShared = false; 1814668SN/A data = NULL; 1822810SN/A} 1832810SN/A 1844908SN/A 1855318SN/Avoid 1865318SN/AMSHR::clearDownstreamPending() 1875318SN/A{ 1885318SN/A assert(downstreamPending); 1895318SN/A downstreamPending = false; 1905318SN/A // recursively clear flag on any MSHRs we will be forwarding 1915318SN/A // responses to 1925318SN/A targets->clearDownstreamPending(); 1935318SN/A} 1945318SN/A 1954908SN/Abool 1964908SN/AMSHR::markInService() 1974908SN/A{ 1984908SN/A assert(!inService); 1995730SSteve.Reinhardt@amd.com if (isForwardNoResponse()) { 2004908SN/A // we just forwarded the request packet & don't expect a 2014908SN/A // response, so get rid of it 2024908SN/A assert(getNumTargets() == 1); 2034908SN/A popTarget(); 2044908SN/A return true; 2054908SN/A } 2064908SN/A inService = true; 2074908SN/A if (!downstreamPending) { 2084908SN/A // let upstream caches know that the request has made it to a 2094908SN/A // level where it's going to get a response 2104908SN/A targets->clearDownstreamPending(); 2114908SN/A } 2124908SN/A return false; 2134908SN/A} 2144908SN/A 2154908SN/A 2162810SN/Avoid 2172810SN/AMSHR::deallocate() 2182810SN/A{ 2194903SN/A assert(targets->empty()); 2204903SN/A targets->resetFlags(); 2214903SN/A assert(deferredTargets->isReset()); 2222810SN/A assert(ntargets == 0); 2232810SN/A inService = false; 2242989SN/A //allocIter = NULL; 2252989SN/A //readyIter = NULL; 2262810SN/A} 2272810SN/A 2282810SN/A/* 2292810SN/A * Adds a target to an MSHR 2302810SN/A */ 2312810SN/Avoid 2324903SN/AMSHR::allocateTarget(PacketPtr pkt, Tick whenReady, Counter _order) 2332810SN/A{ 2344903SN/A // if there's a request already in service for this MSHR, we will 2354903SN/A // have to defer the new target until after the response if any of 2364903SN/A // the following are true: 2374903SN/A // - there are other targets already deferred 2384903SN/A // - there's a pending invalidate to be applied after the response 2394903SN/A // comes back (but before this target is processed) 2404903SN/A // - the outstanding request is for a non-exclusive block and this 2414903SN/A // target requires an exclusive block 2425875Ssteve.reinhardt@amd.com 2435875Ssteve.reinhardt@amd.com // assume we'd never issue a prefetch when we've got an 2445875Ssteve.reinhardt@amd.com // outstanding miss 2455875Ssteve.reinhardt@amd.com assert(pkt->cmd != MemCmd::HardPFReq); 2465875Ssteve.reinhardt@amd.com 2474903SN/A if (inService && 2484903SN/A (!deferredTargets->empty() || pendingInvalidate || 2494903SN/A (!targets->needsExclusive && pkt->needsExclusive()))) { 2504903SN/A // need to put on deferred list 2515875Ssteve.reinhardt@amd.com deferredTargets->add(pkt, whenReady, _order, Target::FromCPU, true); 2524665SN/A } else { 2535318SN/A // No request outstanding, or still OK to append to 2545318SN/A // outstanding request: append to regular target list. Only 2555318SN/A // mark pending if current request hasn't been issued yet 2565318SN/A // (isn't in service). 2575875Ssteve.reinhardt@amd.com targets->add(pkt, whenReady, _order, Target::FromCPU, !inService); 2582810SN/A } 2592810SN/A 2602810SN/A ++ntargets; 2614665SN/A} 2624665SN/A 2634902SN/Abool 2644902SN/AMSHR::handleSnoop(PacketPtr pkt, Counter _order) 2654665SN/A{ 2664910SN/A if (!inService || (pkt->isExpressSnoop() && downstreamPending)) { 2674903SN/A // Request has not been issued yet, or it's been issued 2684903SN/A // locally but is buffered unissued at some downstream cache 2694903SN/A // which is forwarding us this snoop. Either way, the packet 2704903SN/A // we're snooping logically precedes this MSHR's request, so 2714903SN/A // the snoop has no impact on the MSHR, but must be processed 2724903SN/A // in the standard way by the cache. The only exception is 2734903SN/A // that if we're an L2+ cache buffering an UpgradeReq from a 2744903SN/A // higher-level cache, and the snoop is invalidating, then our 2754903SN/A // buffered upgrades must be converted to read exclusives, 2764903SN/A // since the upper-level cache no longer has a valid copy. 2774903SN/A // That is, even though the upper-level cache got out on its 2784903SN/A // local bus first, some other invalidating transaction 2794903SN/A // reached the global bus before the upgrade did. 2804903SN/A if (pkt->needsExclusive()) { 2814903SN/A targets->replaceUpgrades(); 2824903SN/A deferredTargets->replaceUpgrades(); 2834903SN/A } 2844903SN/A 2854902SN/A return false; 2864902SN/A } 2874665SN/A 2884903SN/A // From here on down, the request issued by this MSHR logically 2894903SN/A // precedes the request we're snooping. 2904903SN/A 2914903SN/A if (pkt->needsExclusive()) { 2924903SN/A // snooped request still precedes the re-request we'll have to 2934903SN/A // issue for deferred targets, if any... 2944903SN/A deferredTargets->replaceUpgrades(); 2954903SN/A } 2964903SN/A 2974665SN/A if (pendingInvalidate) { 2984665SN/A // a prior snoop has already appended an invalidation, so 2994903SN/A // logically we don't have the block anymore; no need for 3004903SN/A // further snooping. 3014902SN/A return true; 3024665SN/A } 3034665SN/A 3044903SN/A if (targets->needsExclusive || pkt->needsExclusive()) { 3054670SN/A // actual target device (typ. PhysicalMemory) will delete the 3064670SN/A // packet on reception, so we need to save a copy here 3074970SN/A PacketPtr cp_pkt = new Packet(pkt, true); 3085875Ssteve.reinhardt@amd.com targets->add(cp_pkt, curTick, _order, Target::FromSnoop, 3095318SN/A downstreamPending && targets->needsExclusive); 3104670SN/A ++ntargets; 3114670SN/A 3124903SN/A if (targets->needsExclusive) { 3134670SN/A // We're awaiting an exclusive copy, so ownership is pending. 3144670SN/A // It's up to us to respond once the data arrives. 3154670SN/A pkt->assertMemInhibit(); 3164916SN/A pkt->setSupplyExclusive(); 3174910SN/A } else { 3184910SN/A // Someone else may respond before we get around to 3194910SN/A // processing this snoop, which means the copied request 3204910SN/A // pointer will no longer be valid 3214910SN/A cp_pkt->req = NULL; 3224670SN/A } 3234670SN/A 3244670SN/A if (pkt->needsExclusive()) { 3254670SN/A // This transaction will take away our pending copy 3264670SN/A pendingInvalidate = true; 3274670SN/A } 3284670SN/A } else { 3294670SN/A // Read to a read: no conflict, so no need to record as 3304670SN/A // target, but make sure neither reader thinks he's getting an 3314670SN/A // exclusive copy 3324670SN/A pendingShared = true; 3334670SN/A pkt->assertShared(); 3344667SN/A } 3354902SN/A 3364902SN/A return true; 3374665SN/A} 3384665SN/A 3394665SN/A 3404665SN/Abool 3414665SN/AMSHR::promoteDeferredTargets() 3424665SN/A{ 3434903SN/A assert(targets->empty()); 3444903SN/A if (deferredTargets->empty()) { 3454665SN/A return false; 3464665SN/A } 3474665SN/A 3484903SN/A // swap targets & deferredTargets lists 3494903SN/A TargetList *tmp = targets; 3504665SN/A targets = deferredTargets; 3514903SN/A deferredTargets = tmp; 3522810SN/A 3534903SN/A assert(targets->size() == ntargets); 3544903SN/A 3554903SN/A // clear deferredTargets flags 3564903SN/A deferredTargets->resetFlags(); 3574903SN/A 3584665SN/A pendingInvalidate = false; 3594670SN/A pendingShared = false; 3604903SN/A order = targets->front().order; 3614903SN/A readyTime = std::max(curTick, targets->front().readyTime); 3624665SN/A 3634665SN/A return true; 3642810SN/A} 3652810SN/A 3662810SN/A 3672810SN/Avoid 3684670SN/AMSHR::handleFill(Packet *pkt, CacheBlk *blk) 3694668SN/A{ 3704671SN/A if (pendingShared) { 3714670SN/A // we snooped another read while this read was in 3724670SN/A // service... assert shared line on its behalf 3734670SN/A pkt->assertShared(); 3744668SN/A } 3755270SN/A 3765270SN/A if (!pkt->sharedAsserted() && !pendingInvalidate 3775270SN/A && deferredTargets->needsExclusive) { 3785270SN/A // We got an exclusive response, but we have deferred targets 3795270SN/A // which are waiting to request an exclusive copy (not because 3805270SN/A // of a pending invalidate). This can happen if the original 3815270SN/A // request was for a read-only (non-exclusive) block, but we 3825270SN/A // got an exclusive copy anyway because of the E part of the 3835270SN/A // MOESI/MESI protocol. Since we got the exclusive copy 3845270SN/A // there's no need to defer the targets, so move them up to 3855270SN/A // the regular target list. 3865270SN/A assert(!targets->needsExclusive); 3875270SN/A targets->needsExclusive = true; 3885318SN/A // if any of the deferred targets were upper-level cache 3895318SN/A // requests marked downstreamPending, need to clear that 3905318SN/A assert(!downstreamPending); // not pending here anymore 3915318SN/A deferredTargets->clearDownstreamPending(); 3925270SN/A // this clears out deferredTargets too 3935270SN/A targets->splice(targets->end(), *deferredTargets); 3945270SN/A deferredTargets->resetFlags(); 3955270SN/A } 3964668SN/A} 3974668SN/A 3984668SN/A 3995314SN/Abool 4005314SN/AMSHR::checkFunctional(PacketPtr pkt) 4015314SN/A{ 4025314SN/A // For printing, we treat the MSHR as a whole as single entity. 4035314SN/A // For other requests, we iterate over the individual targets 4045314SN/A // since that's where the actual data lies. 4055314SN/A if (pkt->isPrint()) { 4065314SN/A pkt->checkFunctional(this, addr, size, NULL); 4075314SN/A return false; 4085314SN/A } else { 4095314SN/A return (targets->checkFunctional(pkt) || 4105314SN/A deferredTargets->checkFunctional(pkt)); 4115314SN/A } 4125314SN/A} 4135314SN/A 4145314SN/A 4154668SN/Avoid 4165314SN/AMSHR::print(std::ostream &os, int verbosity, const std::string &prefix) const 4172810SN/A{ 4185314SN/A ccprintf(os, "%s[%x:%x] %s %s %s state: %s %s %s %s\n", 4195314SN/A prefix, addr, addr+size-1, 4205730SSteve.Reinhardt@amd.com isForward ? "Forward" : "", 4215730SSteve.Reinhardt@amd.com isForwardNoResponse() ? "ForwNoResp" : "", 4225314SN/A needsExclusive() ? "Excl" : "", 4235314SN/A _isUncacheable ? "Unc" : "", 4245314SN/A inService ? "InSvc" : "", 4255314SN/A downstreamPending ? "DwnPend" : "", 4265314SN/A pendingInvalidate ? "PendInv" : "", 4275314SN/A pendingShared ? "PendShared" : ""); 4282810SN/A 4295314SN/A ccprintf(os, "%s Targets:\n", prefix); 4305314SN/A targets->print(os, verbosity, prefix + " "); 4315314SN/A if (!deferredTargets->empty()) { 4325314SN/A ccprintf(os, "%s Deferred Targets:\n", prefix); 4335314SN/A deferredTargets->print(os, verbosity, prefix + " "); 4342810SN/A } 4352810SN/A} 4362810SN/A 4372810SN/AMSHR::~MSHR() 4382810SN/A{ 4392810SN/A} 440