mshr.cc revision 10503
17405SAli.Saidi@ARM.com/* 211573SDylan.Johnson@ARM.com * Copyright (c) 2012-2013 ARM Limited 37405SAli.Saidi@ARM.com * All rights reserved. 47405SAli.Saidi@ARM.com * 57405SAli.Saidi@ARM.com * The license below extends only to copyright in the software and shall 67405SAli.Saidi@ARM.com * not be construed as granting a license to any other intellectual 77405SAli.Saidi@ARM.com * property including but not limited to intellectual property relating 87405SAli.Saidi@ARM.com * to a hardware implementation of the functionality of the software 97405SAli.Saidi@ARM.com * licensed hereunder. You may use the software subject to the license 107405SAli.Saidi@ARM.com * terms below provided that you ensure that this notice is replicated 117405SAli.Saidi@ARM.com * unmodified and in its entirety in all distributions of the software, 127405SAli.Saidi@ARM.com * modified or unmodified, in source code or in binary form. 137405SAli.Saidi@ARM.com * 147405SAli.Saidi@ARM.com * Copyright (c) 2002-2005 The Regents of The University of Michigan 157405SAli.Saidi@ARM.com * Copyright (c) 2010 Advanced Micro Devices, Inc. 167405SAli.Saidi@ARM.com * All rights reserved. 177405SAli.Saidi@ARM.com * 187405SAli.Saidi@ARM.com * Redistribution and use in source and binary forms, with or without 197405SAli.Saidi@ARM.com * modification, are permitted provided that the following conditions are 207405SAli.Saidi@ARM.com * met: redistributions of source code must retain the above copyright 217405SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer; 227405SAli.Saidi@ARM.com * redistributions in binary form must reproduce the above copyright 237405SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer in the 247405SAli.Saidi@ARM.com * documentation and/or other materials provided with the distribution; 257405SAli.Saidi@ARM.com * neither the name of the copyright holders nor the names of its 267405SAli.Saidi@ARM.com * contributors may be used to endorse or promote products derived from 277405SAli.Saidi@ARM.com * this software without specific prior written permission. 287405SAli.Saidi@ARM.com * 297405SAli.Saidi@ARM.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 307405SAli.Saidi@ARM.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 317405SAli.Saidi@ARM.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 327405SAli.Saidi@ARM.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 337405SAli.Saidi@ARM.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 347405SAli.Saidi@ARM.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 357405SAli.Saidi@ARM.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 367405SAli.Saidi@ARM.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 377405SAli.Saidi@ARM.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 387405SAli.Saidi@ARM.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 397405SAli.Saidi@ARM.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 407405SAli.Saidi@ARM.com * 417405SAli.Saidi@ARM.com * Authors: Erik Hallnor 4210461SAndreas.Sandberg@ARM.com * Dave Greene 439050Schander.sudanthi@arm.com */ 448887Sgeoffrey.blake@arm.com 4510461SAndreas.Sandberg@ARM.com/** 468232Snate@binkert.org * @file 478232Snate@binkert.org * Miss Status and Handling Register (MSHR) definitions. 4810844Sandreas.sandberg@arm.com */ 499384SAndreas.Sandberg@arm.com 507678Sgblack@eecs.umich.edu#include <algorithm> 518059SAli.Saidi@ARM.com#include <cassert> 528284SAli.Saidi@ARM.com#include <string> 537405SAli.Saidi@ARM.com#include <vector> 547405SAli.Saidi@ARM.com 557405SAli.Saidi@ARM.com#include "base/misc.hh" 567405SAli.Saidi@ARM.com#include "base/types.hh" 5710037SARM gem5 Developers#include "debug/Cache.hh" 5810037SARM gem5 Developers#include "mem/cache/cache.hh" 5911768SCurtis.Dunham@arm.com#include "mem/cache/mshr.hh" 6010037SARM gem5 Developers#include "sim/core.hh" 6110037SARM gem5 Developers 6210037SARM gem5 Developersusing namespace std; 6310037SARM gem5 Developers 6411768SCurtis.Dunham@arm.comMSHR::MSHR() : readyTime(0), _isUncacheable(false), downstreamPending(false), 6510037SARM gem5 Developers pendingDirty(false), pendingClean(false), 6610037SARM gem5 Developers postInvalidate(false), postDowngrade(false), 6711768SCurtis.Dunham@arm.com _isObsolete(false), queue(NULL), order(0), addr(0), 6811768SCurtis.Dunham@arm.com size(0), isSecure(false), inService(false), 6911768SCurtis.Dunham@arm.com isForward(false), threadNum(InvalidThreadID), data(NULL) 7011768SCurtis.Dunham@arm.com{ 7111768SCurtis.Dunham@arm.com} 7211768SCurtis.Dunham@arm.com 7311768SCurtis.Dunham@arm.com 7411768SCurtis.Dunham@arm.comMSHR::TargetList::TargetList() 7511768SCurtis.Dunham@arm.com : needsExclusive(false), hasUpgrade(false) 7611768SCurtis.Dunham@arm.com{} 7711768SCurtis.Dunham@arm.com 7811768SCurtis.Dunham@arm.com 7910037SARM gem5 Developersinline void 8010037SARM gem5 DevelopersMSHR::TargetList::add(PacketPtr pkt, Tick readyTime, 8110037SARM gem5 Developers Counter order, Target::Source source, bool markPending) 8211768SCurtis.Dunham@arm.com{ 8311768SCurtis.Dunham@arm.com if (source != Target::FromSnoop) { 8411768SCurtis.Dunham@arm.com if (pkt->needsExclusive()) { 8511768SCurtis.Dunham@arm.com needsExclusive = true; 8611768SCurtis.Dunham@arm.com } 8711768SCurtis.Dunham@arm.com 8811768SCurtis.Dunham@arm.com // StoreCondReq is effectively an upgrade if it's in an MSHR 8911768SCurtis.Dunham@arm.com // since it would have been failed already if we didn't have a 9010037SARM gem5 Developers // read-only copy 9111768SCurtis.Dunham@arm.com if (pkt->isUpgrade() || pkt->cmd == MemCmd::StoreCondReq) { 9211768SCurtis.Dunham@arm.com hasUpgrade = true; 9311768SCurtis.Dunham@arm.com } 9411768SCurtis.Dunham@arm.com } 9510037SARM gem5 Developers 9611768SCurtis.Dunham@arm.com if (markPending) { 9711768SCurtis.Dunham@arm.com // Iterate over the SenderState stack and see if we find 9811768SCurtis.Dunham@arm.com // an MSHR entry. If we do, set the downstreamPending 9911768SCurtis.Dunham@arm.com // flag. Otherwise, do nothing. 10011768SCurtis.Dunham@arm.com MSHR *mshr = pkt->findNextSenderState<MSHR>(); 10111768SCurtis.Dunham@arm.com if (mshr != NULL) { 10211768SCurtis.Dunham@arm.com assert(!mshr->downstreamPending); 10311768SCurtis.Dunham@arm.com mshr->downstreamPending = true; 10411768SCurtis.Dunham@arm.com } 10511768SCurtis.Dunham@arm.com } 10611768SCurtis.Dunham@arm.com 10711768SCurtis.Dunham@arm.com push_back(Target(pkt, readyTime, order, source, markPending)); 10811768SCurtis.Dunham@arm.com} 10911768SCurtis.Dunham@arm.com 11011768SCurtis.Dunham@arm.com 11111768SCurtis.Dunham@arm.comstatic void 11211768SCurtis.Dunham@arm.comreplaceUpgrade(PacketPtr pkt) 11311768SCurtis.Dunham@arm.com{ 11410037SARM gem5 Developers if (pkt->cmd == MemCmd::UpgradeReq) { 11511768SCurtis.Dunham@arm.com pkt->cmd = MemCmd::ReadExReq; 11611768SCurtis.Dunham@arm.com DPRINTF(Cache, "Replacing UpgradeReq with ReadExReq\n"); 11711768SCurtis.Dunham@arm.com } else if (pkt->cmd == MemCmd::SCUpgradeReq) { 11811768SCurtis.Dunham@arm.com pkt->cmd = MemCmd::SCUpgradeFailReq; 11910037SARM gem5 Developers DPRINTF(Cache, "Replacing SCUpgradeReq with SCUpgradeFailReq\n"); 12011768SCurtis.Dunham@arm.com } else if (pkt->cmd == MemCmd::StoreCondReq) { 12111768SCurtis.Dunham@arm.com pkt->cmd = MemCmd::StoreCondFailReq; 12211768SCurtis.Dunham@arm.com DPRINTF(Cache, "Replacing StoreCondReq with StoreCondFailReq\n"); 12311768SCurtis.Dunham@arm.com } 12411768SCurtis.Dunham@arm.com} 12511768SCurtis.Dunham@arm.com 12610037SARM gem5 Developers 12711768SCurtis.Dunham@arm.comvoid 12811768SCurtis.Dunham@arm.comMSHR::TargetList::replaceUpgrades() 12911768SCurtis.Dunham@arm.com{ 13011768SCurtis.Dunham@arm.com if (!hasUpgrade) 13111768SCurtis.Dunham@arm.com return; 13211768SCurtis.Dunham@arm.com 13311768SCurtis.Dunham@arm.com Iterator end_i = end(); 13411768SCurtis.Dunham@arm.com for (Iterator i = begin(); i != end_i; ++i) { 13511768SCurtis.Dunham@arm.com replaceUpgrade(i->pkt); 13611768SCurtis.Dunham@arm.com } 13711768SCurtis.Dunham@arm.com 13811768SCurtis.Dunham@arm.com hasUpgrade = false; 13911768SCurtis.Dunham@arm.com} 14011768SCurtis.Dunham@arm.com 14111768SCurtis.Dunham@arm.com 14211768SCurtis.Dunham@arm.comvoid 14311768SCurtis.Dunham@arm.comMSHR::TargetList::clearDownstreamPending() 14411768SCurtis.Dunham@arm.com{ 14511768SCurtis.Dunham@arm.com Iterator end_i = end(); 14611768SCurtis.Dunham@arm.com for (Iterator i = begin(); i != end_i; ++i) { 14711768SCurtis.Dunham@arm.com if (i->markedPending) { 14811768SCurtis.Dunham@arm.com // Iterate over the SenderState stack and see if we find 14911768SCurtis.Dunham@arm.com // an MSHR entry. If we find one, clear the 15011768SCurtis.Dunham@arm.com // downstreamPending flag by calling 15111768SCurtis.Dunham@arm.com // clearDownstreamPending(). This recursively clears the 15211768SCurtis.Dunham@arm.com // downstreamPending flag in all caches this packet has 15311768SCurtis.Dunham@arm.com // passed through. 15411768SCurtis.Dunham@arm.com MSHR *mshr = i->pkt->findNextSenderState<MSHR>(); 15511768SCurtis.Dunham@arm.com if (mshr != NULL) { 15611768SCurtis.Dunham@arm.com mshr->clearDownstreamPending(); 15711768SCurtis.Dunham@arm.com } 15811768SCurtis.Dunham@arm.com } 15911768SCurtis.Dunham@arm.com } 16011768SCurtis.Dunham@arm.com} 16111768SCurtis.Dunham@arm.com 16211768SCurtis.Dunham@arm.com 16311768SCurtis.Dunham@arm.combool 16411768SCurtis.Dunham@arm.comMSHR::TargetList::checkFunctional(PacketPtr pkt) 16511768SCurtis.Dunham@arm.com{ 16611768SCurtis.Dunham@arm.com Iterator end_i = end(); 16711768SCurtis.Dunham@arm.com for (Iterator i = begin(); i != end_i; ++i) { 16811768SCurtis.Dunham@arm.com if (pkt->checkFunctional(i->pkt)) { 16911768SCurtis.Dunham@arm.com return true; 17011768SCurtis.Dunham@arm.com } 17111768SCurtis.Dunham@arm.com } 17211768SCurtis.Dunham@arm.com 17311768SCurtis.Dunham@arm.com return false; 17411768SCurtis.Dunham@arm.com} 17511768SCurtis.Dunham@arm.com 17611768SCurtis.Dunham@arm.com 17711768SCurtis.Dunham@arm.comvoid 17811768SCurtis.Dunham@arm.comMSHR::TargetList:: 17911768SCurtis.Dunham@arm.comprint(std::ostream &os, int verbosity, const std::string &prefix) const 18011768SCurtis.Dunham@arm.com{ 18111768SCurtis.Dunham@arm.com ConstIterator end_i = end(); 18211768SCurtis.Dunham@arm.com for (ConstIterator i = begin(); i != end_i; ++i) { 18311768SCurtis.Dunham@arm.com const char *s; 18411768SCurtis.Dunham@arm.com switch (i->source) { 18511768SCurtis.Dunham@arm.com case Target::FromCPU: 18611768SCurtis.Dunham@arm.com s = "FromCPU"; 18711768SCurtis.Dunham@arm.com break; 18811768SCurtis.Dunham@arm.com case Target::FromSnoop: 18911768SCurtis.Dunham@arm.com s = "FromSnoop"; 19011768SCurtis.Dunham@arm.com break; 19111768SCurtis.Dunham@arm.com case Target::FromPrefetcher: 19211768SCurtis.Dunham@arm.com s = "FromPrefetcher"; 19311768SCurtis.Dunham@arm.com break; 19411768SCurtis.Dunham@arm.com default: 19511768SCurtis.Dunham@arm.com s = ""; 19611768SCurtis.Dunham@arm.com break; 19711768SCurtis.Dunham@arm.com } 19811768SCurtis.Dunham@arm.com ccprintf(os, "%s%s: ", prefix, s); 19911768SCurtis.Dunham@arm.com i->pkt->print(os, verbosity, ""); 20011768SCurtis.Dunham@arm.com } 20111768SCurtis.Dunham@arm.com} 20211768SCurtis.Dunham@arm.com 20311768SCurtis.Dunham@arm.com 20410037SARM gem5 Developersvoid 20510037SARM gem5 DevelopersMSHR::allocate(Addr _addr, int _size, PacketPtr target, Tick whenReady, 20610037SARM gem5 Developers Counter _order) 2079384SAndreas.Sandberg@arm.com{ 20810461SAndreas.Sandberg@ARM.com addr = _addr; 20910461SAndreas.Sandberg@ARM.com size = _size; 21011165SRekai.GonzalezAlberquilla@arm.com isSecure = target->isSecure(); 21110461SAndreas.Sandberg@ARM.com readyTime = whenReady; 21210461SAndreas.Sandberg@ARM.com order = _order; 2139384SAndreas.Sandberg@arm.com assert(target); 21411770SCurtis.Dunham@arm.com isForward = false; 21510037SARM gem5 Developers _isUncacheable = target->req->isUncacheable(); 21610461SAndreas.Sandberg@ARM.com inService = false; 21710461SAndreas.Sandberg@ARM.com pendingClean = (target->cmd == MemCmd::WriteInvalidateReq); 21810461SAndreas.Sandberg@ARM.com downstreamPending = false; 21910461SAndreas.Sandberg@ARM.com _isObsolete = false; 22010461SAndreas.Sandberg@ARM.com threadNum = 0; 22110461SAndreas.Sandberg@ARM.com assert(targets.isReset()); 22210609Sandreas.sandberg@arm.com // Don't know of a case where we would allocate a new MSHR for a 22310609Sandreas.sandberg@arm.com // snoop (mem-side request), so set source according to request here 22410609Sandreas.sandberg@arm.com Target::Source source = (target->cmd == MemCmd::HardPFReq) ? 22510037SARM gem5 Developers Target::FromPrefetcher : Target::FromCPU; 22610037SARM gem5 Developers targets.add(target, whenReady, _order, source, true); 22710037SARM gem5 Developers assert(deferredTargets.isReset()); 22810037SARM gem5 Developers data = NULL; 22911771SCurtis.Dunham@arm.com} 23010037SARM gem5 Developers 23110037SARM gem5 Developers 23210037SARM gem5 Developersvoid 23310037SARM gem5 DevelopersMSHR::clearDownstreamPending() 23410037SARM gem5 Developers{ 23510037SARM gem5 Developers assert(downstreamPending); 23611771SCurtis.Dunham@arm.com downstreamPending = false; 23710037SARM gem5 Developers // recursively clear flag on any MSHRs we will be forwarding 23810037SARM gem5 Developers // responses to 23910037SARM gem5 Developers targets.clearDownstreamPending(); 24010037SARM gem5 Developers} 24110037SARM gem5 Developers 24210037SARM gem5 Developersbool 24311768SCurtis.Dunham@arm.comMSHR::markInService(PacketPtr pkt) 24411768SCurtis.Dunham@arm.com{ 24510037SARM gem5 Developers assert(!inService); 24610037SARM gem5 Developers if (isForwardNoResponse()) { 24710037SARM gem5 Developers // we just forwarded the request packet & don't expect a 24810037SARM gem5 Developers // response, so get rid of it 2499384SAndreas.Sandberg@arm.com assert(getNumTargets() == 1); 2509384SAndreas.Sandberg@arm.com popTarget(); 2519384SAndreas.Sandberg@arm.com return true; 2529384SAndreas.Sandberg@arm.com } 2539384SAndreas.Sandberg@arm.com 2549384SAndreas.Sandberg@arm.com assert(pkt != NULL); 2559384SAndreas.Sandberg@arm.com inService = true; 2569384SAndreas.Sandberg@arm.com pendingDirty = ((targets.needsExclusive && 2579384SAndreas.Sandberg@arm.com (pkt->cmd != MemCmd::WriteInvalidateReq)) || 2587427Sgblack@eecs.umich.edu (!pkt->sharedAsserted() && pkt->memInhibitAsserted())); 2597427Sgblack@eecs.umich.edu postInvalidate = postDowngrade = false; 2607427Sgblack@eecs.umich.edu 2619385SAndreas.Sandberg@arm.com if (!downstreamPending) { 2629385SAndreas.Sandberg@arm.com // let upstream caches know that the request has made it to a 2637427Sgblack@eecs.umich.edu // level where it's going to get a response 2647427Sgblack@eecs.umich.edu targets.clearDownstreamPending(); 26510037SARM gem5 Developers } 26610037SARM gem5 Developers return false; 26710037SARM gem5 Developers} 26810037SARM gem5 Developers 26910037SARM gem5 Developers 27010037SARM gem5 Developersvoid 27110037SARM gem5 DevelopersMSHR::deallocate() 27210037SARM gem5 Developers{ 27310037SARM gem5 Developers assert(targets.empty()); 27410037SARM gem5 Developers targets.resetFlags(); 27510037SARM gem5 Developers assert(deferredTargets.isReset()); 27610037SARM gem5 Developers inService = false; 27710037SARM gem5 Developers} 27810037SARM gem5 Developers 2797427Sgblack@eecs.umich.edu/* 2807427Sgblack@eecs.umich.edu * Adds a target to an MSHR 2817427Sgblack@eecs.umich.edu */ 2827427Sgblack@eecs.umich.eduvoid 2837427Sgblack@eecs.umich.eduMSHR::allocateTarget(PacketPtr pkt, Tick whenReady, Counter _order) 2847427Sgblack@eecs.umich.edu{ 28510037SARM gem5 Developers // if there's a request already in service for this MSHR, we will 28610037SARM gem5 Developers // have to defer the new target until after the response if any of 28710037SARM gem5 Developers // the following are true: 28810037SARM gem5 Developers // - there are other targets already deferred 2897427Sgblack@eecs.umich.edu // - there's a pending invalidate to be applied after the response 2907427Sgblack@eecs.umich.edu // comes back (but before this target is processed) 2917427Sgblack@eecs.umich.edu // - this target requires an exclusive block and either we're not 29210037SARM gem5 Developers // getting an exclusive block back or we have already snooped 29310204SAli.Saidi@ARM.com // another read request that will downgrade our exclusive block 29410204SAli.Saidi@ARM.com // to shared 29510037SARM gem5 Developers 2967427Sgblack@eecs.umich.edu // assume we'd never issue a prefetch when we've got an 29710037SARM gem5 Developers // outstanding miss 2987427Sgblack@eecs.umich.edu assert(pkt->cmd != MemCmd::HardPFReq); 29910037SARM gem5 Developers 3007427Sgblack@eecs.umich.edu if (inService && 3017427Sgblack@eecs.umich.edu (!deferredTargets.empty() || hasPostInvalidate() || 30210037SARM gem5 Developers (pkt->needsExclusive() && 3037427Sgblack@eecs.umich.edu (!isPendingDirty() || hasPostDowngrade() || isForward)))) { 3047427Sgblack@eecs.umich.edu // need to put on deferred list 3057427Sgblack@eecs.umich.edu if (hasPostInvalidate()) 3067427Sgblack@eecs.umich.edu replaceUpgrade(pkt); 3077427Sgblack@eecs.umich.edu deferredTargets.add(pkt, whenReady, _order, Target::FromCPU, true); 3087427Sgblack@eecs.umich.edu } else { 3097427Sgblack@eecs.umich.edu // No request outstanding, or still OK to append to 3107427Sgblack@eecs.umich.edu // outstanding request: append to regular target list. Only 3117427Sgblack@eecs.umich.edu // mark pending if current request hasn't been issued yet 3127427Sgblack@eecs.umich.edu // (isn't in service). 3137427Sgblack@eecs.umich.edu targets.add(pkt, whenReady, _order, Target::FromCPU, !inService); 3147427Sgblack@eecs.umich.edu } 3157427Sgblack@eecs.umich.edu} 3167427Sgblack@eecs.umich.edu 3177427Sgblack@eecs.umich.edubool 3187427Sgblack@eecs.umich.eduMSHR::handleSnoop(PacketPtr pkt, Counter _order) 3197427Sgblack@eecs.umich.edu{ 3207427Sgblack@eecs.umich.edu DPRINTF(Cache, "%s for %s address %x size %d\n", __func__, 3217427Sgblack@eecs.umich.edu pkt->cmdString(), pkt->getAddr(), pkt->getSize()); 3227427Sgblack@eecs.umich.edu if (!inService || (pkt->isExpressSnoop() && downstreamPending)) { 3237427Sgblack@eecs.umich.edu // Request has not been issued yet, or it's been issued 3247427Sgblack@eecs.umich.edu // locally but is buffered unissued at some downstream cache 3257427Sgblack@eecs.umich.edu // which is forwarding us this snoop. Either way, the packet 3267436Sdam.sunwoo@arm.com // we're snooping logically precedes this MSHR's request, so 3277436Sdam.sunwoo@arm.com // the snoop has no impact on the MSHR, but must be processed 32810037SARM gem5 Developers // in the standard way by the cache. The only exception is 32910037SARM gem5 Developers // that if we're an L2+ cache buffering an UpgradeReq from a 3307436Sdam.sunwoo@arm.com // higher-level cache, and the snoop is invalidating, then our 3317436Sdam.sunwoo@arm.com // buffered upgrades must be converted to read exclusives, 3327436Sdam.sunwoo@arm.com // since the upper-level cache no longer has a valid copy. 3337436Sdam.sunwoo@arm.com // That is, even though the upper-level cache got out on its 3347436Sdam.sunwoo@arm.com // local bus first, some other invalidating transaction 3357436Sdam.sunwoo@arm.com // reached the global bus before the upgrade did. 3367436Sdam.sunwoo@arm.com if (pkt->needsExclusive()) { 3377436Sdam.sunwoo@arm.com targets.replaceUpgrades(); 3387436Sdam.sunwoo@arm.com deferredTargets.replaceUpgrades(); 3397436Sdam.sunwoo@arm.com } 3407436Sdam.sunwoo@arm.com 3417436Sdam.sunwoo@arm.com return false; 34210037SARM gem5 Developers } 3437436Sdam.sunwoo@arm.com 3447436Sdam.sunwoo@arm.com // From here on down, the request issued by this MSHR logically 3457436Sdam.sunwoo@arm.com // precedes the request we're snooping. 3467436Sdam.sunwoo@arm.com if (pkt->needsExclusive()) { 3477436Sdam.sunwoo@arm.com // snooped request still precedes the re-request we'll have to 3487436Sdam.sunwoo@arm.com // issue for deferred targets, if any... 3497436Sdam.sunwoo@arm.com deferredTargets.replaceUpgrades(); 3507436Sdam.sunwoo@arm.com } 3517436Sdam.sunwoo@arm.com 3527436Sdam.sunwoo@arm.com if (hasPostInvalidate()) { 3537436Sdam.sunwoo@arm.com // a prior snoop has already appended an invalidation, so 3547436Sdam.sunwoo@arm.com // logically we don't have the block anymore; no need for 3557436Sdam.sunwoo@arm.com // further snooping. 3567436Sdam.sunwoo@arm.com return true; 3577436Sdam.sunwoo@arm.com } 3587436Sdam.sunwoo@arm.com 3597644Sali.saidi@arm.com if (isPendingDirty() || pkt->isInvalidate()) { 3608147SAli.Saidi@ARM.com // We need to save and replay the packet in two cases: 3619385SAndreas.Sandberg@arm.com // 1. We're awaiting an exclusive copy, so ownership is pending, 3629385SAndreas.Sandberg@arm.com // and we need to respond after we receive data. 3639385SAndreas.Sandberg@arm.com // 2. It's an invalidation (e.g., UpgradeReq), and we need 3649385SAndreas.Sandberg@arm.com // to forward the snoop up the hierarchy after the current 3659385SAndreas.Sandberg@arm.com // transaction completes. 3669385SAndreas.Sandberg@arm.com 3679385SAndreas.Sandberg@arm.com // Actual target device (typ. a memory) will delete the 3689385SAndreas.Sandberg@arm.com // packet on reception, so we need to save a copy here. 3699385SAndreas.Sandberg@arm.com PacketPtr cp_pkt = new Packet(pkt, true); 3709385SAndreas.Sandberg@arm.com targets.add(cp_pkt, curTick(), _order, Target::FromSnoop, 3719385SAndreas.Sandberg@arm.com downstreamPending && targets.needsExclusive); 3729385SAndreas.Sandberg@arm.com 3739385SAndreas.Sandberg@arm.com // WriteInvalidates must writeback and should not be inhibited on 3749385SAndreas.Sandberg@arm.com // account of its snoops discovering MSHRs wanting exclusive access 37510037SARM gem5 Developers // to what it wrote. We don't want to push this check higher, 37610037SARM gem5 Developers // however, because we want to be sure to add an invalidating 37710037SARM gem5 Developers // Target::FromSnoop, above. 37810037SARM gem5 Developers if (isPendingDirty() && (pkt->cmd != MemCmd::WriteInvalidateReq)) { 37910037SARM gem5 Developers pkt->assertMemInhibit(); 38010037SARM gem5 Developers pkt->setSupplyExclusive(); 38110037SARM gem5 Developers } 38210037SARM gem5 Developers 38310037SARM gem5 Developers if (pkt->needsExclusive()) { 38410037SARM gem5 Developers // This transaction will take away our pending copy 38510037SARM gem5 Developers postInvalidate = true; 38610037SARM gem5 Developers 38710037SARM gem5 Developers // Do not defer (i.e. return true) the snoop if the block is 38810037SARM gem5 Developers // going to be clean once the MSHR completes, as the data is 38910037SARM gem5 Developers // ready now. 39010037SARM gem5 Developers if (isPendingClean()) { 3918147SAli.Saidi@ARM.com return false; 3927427Sgblack@eecs.umich.edu } 3937427Sgblack@eecs.umich.edu } 3947427Sgblack@eecs.umich.edu } 39510037SARM gem5 Developers 39610037SARM gem5 Developers if (!pkt->needsExclusive()) { 39710037SARM gem5 Developers // This transaction will get a read-shared copy, downgrading 39810037SARM gem5 Developers // our copy if we had an exclusive one 39910037SARM gem5 Developers postDowngrade = true; 40010037SARM gem5 Developers pkt->assertShared(); 40110037SARM gem5 Developers } 40210037SARM gem5 Developers 40310037SARM gem5 Developers return true; 40410037SARM gem5 Developers} 40510037SARM gem5 Developers 40610037SARM gem5 Developers 40710037SARM gem5 Developersbool 40810037SARM gem5 DevelopersMSHR::promoteDeferredTargets() 40910037SARM gem5 Developers{ 41010037SARM gem5 Developers assert(targets.empty()); 41110037SARM gem5 Developers if (deferredTargets.empty()) { 41210037SARM gem5 Developers return false; 41310037SARM gem5 Developers } 41410037SARM gem5 Developers 41510037SARM gem5 Developers // swap targets & deferredTargets lists 41610037SARM gem5 Developers std::swap(targets, deferredTargets); 41710037SARM gem5 Developers 41810037SARM gem5 Developers // clear deferredTargets flags 41910037SARM gem5 Developers deferredTargets.resetFlags(); 42010037SARM gem5 Developers 42110037SARM gem5 Developers order = targets.front().order; 42210037SARM gem5 Developers readyTime = std::max(curTick(), targets.front().readyTime); 42310037SARM gem5 Developers 42410037SARM gem5 Developers return true; 42510037SARM gem5 Developers} 42610037SARM gem5 Developers 42710037SARM gem5 Developers 42810037SARM gem5 Developersvoid 42910037SARM gem5 DevelopersMSHR::handleFill(Packet *pkt, CacheBlk *blk) 43010037SARM gem5 Developers{ 43111770SCurtis.Dunham@arm.com if (!pkt->sharedAsserted() 43210037SARM gem5 Developers && !(hasPostInvalidate() || hasPostDowngrade()) 43311574SCurtis.Dunham@arm.com && deferredTargets.needsExclusive) { 43411770SCurtis.Dunham@arm.com // We got an exclusive response, but we have deferred targets 43511770SCurtis.Dunham@arm.com // which are waiting to request an exclusive copy (not because 43610037SARM gem5 Developers // of a pending invalidate). This can happen if the original 43711770SCurtis.Dunham@arm.com // request was for a read-only (non-exclusive) block, but we 43811770SCurtis.Dunham@arm.com // got an exclusive copy anyway because of the E part of the 43910037SARM gem5 Developers // MOESI/MESI protocol. Since we got the exclusive copy 44010037SARM gem5 Developers // there's no need to defer the targets, so move them up to 44110037SARM gem5 Developers // the regular target list. 44210037SARM gem5 Developers assert(!targets.needsExclusive); 44310037SARM gem5 Developers targets.needsExclusive = true; 44410037SARM gem5 Developers // if any of the deferred targets were upper-level cache 44510037SARM gem5 Developers // requests marked downstreamPending, need to clear that 44610461SAndreas.Sandberg@ARM.com assert(!downstreamPending); // not pending here anymore 44710461SAndreas.Sandberg@ARM.com deferredTargets.clearDownstreamPending(); 44810461SAndreas.Sandberg@ARM.com // this clears out deferredTargets too 44910461SAndreas.Sandberg@ARM.com targets.splice(targets.end(), deferredTargets); 45010037SARM gem5 Developers deferredTargets.resetFlags(); 45110037SARM gem5 Developers } 45210037SARM gem5 Developers} 45310037SARM gem5 Developers 45410037SARM gem5 Developers 45510037SARM gem5 Developersbool 45610037SARM gem5 DevelopersMSHR::checkFunctional(PacketPtr pkt) 45710037SARM gem5 Developers{ 45810461SAndreas.Sandberg@ARM.com // For printing, we treat the MSHR as a whole as single entity. 45910461SAndreas.Sandberg@ARM.com // For other requests, we iterate over the individual targets 46010461SAndreas.Sandberg@ARM.com // since that's where the actual data lies. 46110461SAndreas.Sandberg@ARM.com if (pkt->isPrint()) { 46210461SAndreas.Sandberg@ARM.com pkt->checkFunctional(this, addr, isSecure, size, NULL); 46310037SARM gem5 Developers return false; 46410037SARM gem5 Developers } else { 46510037SARM gem5 Developers return (targets.checkFunctional(pkt) || 46610037SARM gem5 Developers deferredTargets.checkFunctional(pkt)); 46710037SARM gem5 Developers } 46811574SCurtis.Dunham@arm.com} 46910037SARM gem5 Developers 47010037SARM gem5 Developers 47110037SARM gem5 Developersvoid 47211574SCurtis.Dunham@arm.comMSHR::print(std::ostream &os, int verbosity, const std::string &prefix) const 47310037SARM gem5 Developers{ 47410037SARM gem5 Developers ccprintf(os, "%s[%x:%x](%s) %s %s %s state: %s %s %s %s %s\n", 47510037SARM gem5 Developers prefix, addr, addr+size-1, 47610037SARM gem5 Developers isSecure ? "s" : "ns", 47710037SARM gem5 Developers isForward ? "Forward" : "", 47810037SARM gem5 Developers isForwardNoResponse() ? "ForwNoResp" : "", 47910037SARM gem5 Developers needsExclusive() ? "Excl" : "", 48010037SARM gem5 Developers _isUncacheable ? "Unc" : "", 48110037SARM gem5 Developers inService ? "InSvc" : "", 48210037SARM gem5 Developers downstreamPending ? "DwnPend" : "", 4837405SAli.Saidi@ARM.com hasPostInvalidate() ? "PostInv" : "", 48410035Sandreas.hansson@arm.com hasPostDowngrade() ? "PostDowngr" : ""); 4857405SAli.Saidi@ARM.com 4867405SAli.Saidi@ARM.com ccprintf(os, "%s Targets:\n", prefix); 4877614Sminkyu.jeong@arm.com targets.print(os, verbosity, prefix + " "); 48811771SCurtis.Dunham@arm.com if (!deferredTargets.empty()) { 48911771SCurtis.Dunham@arm.com ccprintf(os, "%s Deferred Targets:\n", prefix); 49011771SCurtis.Dunham@arm.com deferredTargets.print(os, verbosity, prefix + " "); 49111771SCurtis.Dunham@arm.com } 4927405SAli.Saidi@ARM.com} 4937405SAli.Saidi@ARM.com 4947405SAli.Saidi@ARM.comstd::string 4957405SAli.Saidi@ARM.comMSHR::print() const 4967405SAli.Saidi@ARM.com{ 4977405SAli.Saidi@ARM.com ostringstream str; 49810037SARM gem5 Developers print(str); 49910037SARM gem5 Developers return str.str(); 50010037SARM gem5 Developers} 5019050Schander.sudanthi@arm.com