mshr.cc revision 9663
111731Sjason@lowepower.com/* 211731Sjason@lowepower.com * Copyright (c) 2012 ARM Limited 311731Sjason@lowepower.com * All rights reserved. 411731Sjason@lowepower.com * 511731Sjason@lowepower.com * The license below extends only to copyright in the software and shall 611731Sjason@lowepower.com * not be construed as granting a license to any other intellectual 711731Sjason@lowepower.com * property including but not limited to intellectual property relating 811731Sjason@lowepower.com * to a hardware implementation of the functionality of the software 911731Sjason@lowepower.com * licensed hereunder. You may use the software subject to the license 1011731Sjason@lowepower.com * terms below provided that you ensure that this notice is replicated 1111731Sjason@lowepower.com * unmodified and in its entirety in all distributions of the software, 1211731Sjason@lowepower.com * modified or unmodified, in source code or in binary form. 1311731Sjason@lowepower.com * 1411731Sjason@lowepower.com * Copyright (c) 2002-2005 The Regents of The University of Michigan 1511731Sjason@lowepower.com * Copyright (c) 2010 Advanced Micro Devices, Inc. 1611731Sjason@lowepower.com * All rights reserved. 1711731Sjason@lowepower.com * 1811731Sjason@lowepower.com * Redistribution and use in source and binary forms, with or without 1911731Sjason@lowepower.com * modification, are permitted provided that the following conditions are 2011731Sjason@lowepower.com * met: redistributions of source code must retain the above copyright 2111731Sjason@lowepower.com * notice, this list of conditions and the following disclaimer; 2211731Sjason@lowepower.com * redistributions in binary form must reproduce the above copyright 2311731Sjason@lowepower.com * notice, this list of conditions and the following disclaimer in the 2411731Sjason@lowepower.com * documentation and/or other materials provided with the distribution; 2511731Sjason@lowepower.com * neither the name of the copyright holders nor the names of its 2611731Sjason@lowepower.com * contributors may be used to endorse or promote products derived from 2711731Sjason@lowepower.com * this software without specific prior written permission. 2811731Sjason@lowepower.com * 2911731Sjason@lowepower.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 3011731Sjason@lowepower.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 3111731Sjason@lowepower.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 3211731Sjason@lowepower.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 3311731Sjason@lowepower.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 3411731Sjason@lowepower.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 3511731Sjason@lowepower.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 3611731Sjason@lowepower.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 3711731Sjason@lowepower.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3811731Sjason@lowepower.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 3911731Sjason@lowepower.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 4011731Sjason@lowepower.com * 4111731Sjason@lowepower.com * Authors: Erik Hallnor 4211731Sjason@lowepower.com * Dave Greene 4311731Sjason@lowepower.com */ 4411731Sjason@lowepower.com 4511731Sjason@lowepower.com/** 4611731Sjason@lowepower.com * @file 4711731Sjason@lowepower.com * Miss Status and Handling Register (MSHR) definitions. 4811731Sjason@lowepower.com */ 4911731Sjason@lowepower.com 5011731Sjason@lowepower.com#include <algorithm> 5111731Sjason@lowepower.com#include <cassert> 5211731Sjason@lowepower.com#include <string> 5311731Sjason@lowepower.com#include <vector> 5411731Sjason@lowepower.com 5511731Sjason@lowepower.com#include "base/misc.hh" 5611731Sjason@lowepower.com#include "base/types.hh" 5711731Sjason@lowepower.com#include "debug/Cache.hh" 5811731Sjason@lowepower.com#include "mem/cache/cache.hh" 5911731Sjason@lowepower.com#include "mem/cache/mshr.hh" 6011731Sjason@lowepower.com#include "sim/core.hh" 6111731Sjason@lowepower.com 6211731Sjason@lowepower.comusing namespace std; 6311731Sjason@lowepower.com 6411731Sjason@lowepower.comMSHR::MSHR() 6511731Sjason@lowepower.com{ 6611731Sjason@lowepower.com inService = false; 6711731Sjason@lowepower.com ntargets = 0; 6811731Sjason@lowepower.com threadNum = InvalidThreadID; 6911731Sjason@lowepower.com targets = new TargetList(); 7011731Sjason@lowepower.com deferredTargets = new TargetList(); 7111731Sjason@lowepower.com} 7211731Sjason@lowepower.com 7311731Sjason@lowepower.com 7411731Sjason@lowepower.comMSHR::TargetList::TargetList() 7511731Sjason@lowepower.com : needsExclusive(false), hasUpgrade(false) 7611731Sjason@lowepower.com{} 7711731Sjason@lowepower.com 7811731Sjason@lowepower.com 7911731Sjason@lowepower.cominline void 8011731Sjason@lowepower.comMSHR::TargetList::add(PacketPtr pkt, Tick readyTime, 8111731Sjason@lowepower.com Counter order, Target::Source source, bool markPending) 8211731Sjason@lowepower.com{ 8311731Sjason@lowepower.com if (source != Target::FromSnoop) { 8411731Sjason@lowepower.com if (pkt->needsExclusive()) { 8511731Sjason@lowepower.com needsExclusive = true; 8611731Sjason@lowepower.com } 8711731Sjason@lowepower.com 8812137Sar4jc@virginia.edu // StoreCondReq is effectively an upgrade if it's in an MSHR 8911731Sjason@lowepower.com // since it would have been failed already if we didn't have a 9011731Sjason@lowepower.com // read-only copy 9112137Sar4jc@virginia.edu if (pkt->isUpgrade() || pkt->cmd == MemCmd::StoreCondReq) { 9211731Sjason@lowepower.com hasUpgrade = true; 9311731Sjason@lowepower.com } 9411731Sjason@lowepower.com } 9511731Sjason@lowepower.com 9611731Sjason@lowepower.com if (markPending) { 9711731Sjason@lowepower.com // Iterate over the SenderState stack and see if we find 9811731Sjason@lowepower.com // an MSHR entry. If we do, set the downstreamPending 9911731Sjason@lowepower.com // flag. Otherwise, do nothing. 10011731Sjason@lowepower.com MSHR *mshr = pkt->findNextSenderState<MSHR>(); 10111731Sjason@lowepower.com if (mshr != NULL) { 10211731Sjason@lowepower.com assert(!mshr->downstreamPending); 10311731Sjason@lowepower.com mshr->downstreamPending = true; 10411731Sjason@lowepower.com } 10511731Sjason@lowepower.com } 10611731Sjason@lowepower.com 10711731Sjason@lowepower.com push_back(Target(pkt, readyTime, order, source, markPending)); 10811731Sjason@lowepower.com} 10911731Sjason@lowepower.com 11011731Sjason@lowepower.com 11111731Sjason@lowepower.comstatic void 11211731Sjason@lowepower.comreplaceUpgrade(PacketPtr pkt) 11311731Sjason@lowepower.com{ 11411731Sjason@lowepower.com if (pkt->cmd == MemCmd::UpgradeReq) { 11511731Sjason@lowepower.com pkt->cmd = MemCmd::ReadExReq; 11611731Sjason@lowepower.com DPRINTF(Cache, "Replacing UpgradeReq with ReadExReq\n"); 11711731Sjason@lowepower.com } else if (pkt->cmd == MemCmd::SCUpgradeReq) { 11811731Sjason@lowepower.com pkt->cmd = MemCmd::SCUpgradeFailReq; 11911731Sjason@lowepower.com DPRINTF(Cache, "Replacing SCUpgradeReq with SCUpgradeFailReq\n"); 12011731Sjason@lowepower.com } else if (pkt->cmd == MemCmd::StoreCondReq) { 12111731Sjason@lowepower.com pkt->cmd = MemCmd::StoreCondFailReq; 12211731Sjason@lowepower.com DPRINTF(Cache, "Replacing StoreCondReq with StoreCondFailReq\n"); 12311731Sjason@lowepower.com } 12411731Sjason@lowepower.com} 12511731Sjason@lowepower.com 12611731Sjason@lowepower.com 12711731Sjason@lowepower.comvoid 12811731Sjason@lowepower.comMSHR::TargetList::replaceUpgrades() 12911731Sjason@lowepower.com{ 13011731Sjason@lowepower.com if (!hasUpgrade) 13111731Sjason@lowepower.com return; 13211731Sjason@lowepower.com 13311731Sjason@lowepower.com Iterator end_i = end(); 13411731Sjason@lowepower.com for (Iterator i = begin(); i != end_i; ++i) { 13511731Sjason@lowepower.com replaceUpgrade(i->pkt); 13611731Sjason@lowepower.com } 13711731Sjason@lowepower.com 13811731Sjason@lowepower.com hasUpgrade = false; 13911731Sjason@lowepower.com} 14011731Sjason@lowepower.com 14111731Sjason@lowepower.com 14211731Sjason@lowepower.comvoid 14311731Sjason@lowepower.comMSHR::TargetList::clearDownstreamPending() 14411731Sjason@lowepower.com{ 14511731Sjason@lowepower.com Iterator end_i = end(); 14611731Sjason@lowepower.com for (Iterator i = begin(); i != end_i; ++i) { 14711731Sjason@lowepower.com if (i->markedPending) { 14811731Sjason@lowepower.com // Iterate over the SenderState stack and see if we find 14911731Sjason@lowepower.com // an MSHR entry. If we find one, clear the 15011731Sjason@lowepower.com // downstreamPending flag by calling 15111731Sjason@lowepower.com // clearDownstreamPending(). This recursively clears the 15211731Sjason@lowepower.com // downstreamPending flag in all caches this packet has 15311731Sjason@lowepower.com // passed through. 15411731Sjason@lowepower.com MSHR *mshr = i->pkt->findNextSenderState<MSHR>(); 15511731Sjason@lowepower.com if (mshr != NULL) { 15611731Sjason@lowepower.com mshr->clearDownstreamPending(); 15711731Sjason@lowepower.com } 15811731Sjason@lowepower.com } 15911731Sjason@lowepower.com } 16011731Sjason@lowepower.com} 16111731Sjason@lowepower.com 16211731Sjason@lowepower.com 16311731Sjason@lowepower.combool 16411731Sjason@lowepower.comMSHR::TargetList::checkFunctional(PacketPtr pkt) 16511731Sjason@lowepower.com{ 16611731Sjason@lowepower.com Iterator end_i = end(); 16711731Sjason@lowepower.com for (Iterator i = begin(); i != end_i; ++i) { 16811731Sjason@lowepower.com if (pkt->checkFunctional(i->pkt)) { 16911731Sjason@lowepower.com return true; 17011731Sjason@lowepower.com } 17111731Sjason@lowepower.com } 17211731Sjason@lowepower.com 17311731Sjason@lowepower.com return false; 17411731Sjason@lowepower.com} 17511731Sjason@lowepower.com 17611731Sjason@lowepower.com 17711731Sjason@lowepower.comvoid 17811731Sjason@lowepower.comMSHR::TargetList:: 17911731Sjason@lowepower.comprint(std::ostream &os, int verbosity, const std::string &prefix) const 18011731Sjason@lowepower.com{ 18111731Sjason@lowepower.com ConstIterator end_i = end(); 18211731Sjason@lowepower.com for (ConstIterator i = begin(); i != end_i; ++i) { 18311731Sjason@lowepower.com const char *s; 18411731Sjason@lowepower.com switch (i->source) { 18511731Sjason@lowepower.com case Target::FromCPU: 18611731Sjason@lowepower.com s = "FromCPU"; 18711731Sjason@lowepower.com break; 18811731Sjason@lowepower.com case Target::FromSnoop: 18911731Sjason@lowepower.com s = "FromSnoop"; 19011731Sjason@lowepower.com break; 19111731Sjason@lowepower.com case Target::FromPrefetcher: 19211731Sjason@lowepower.com s = "FromPrefetcher"; 19311731Sjason@lowepower.com break; 19411731Sjason@lowepower.com default: 19511731Sjason@lowepower.com s = ""; 19611731Sjason@lowepower.com break; 19711731Sjason@lowepower.com } 19811731Sjason@lowepower.com ccprintf(os, "%s%s: ", prefix, s); 19911731Sjason@lowepower.com i->pkt->print(os, verbosity, ""); 20011731Sjason@lowepower.com } 20111731Sjason@lowepower.com} 20211731Sjason@lowepower.com 20311731Sjason@lowepower.com 20411731Sjason@lowepower.comvoid 20511731Sjason@lowepower.comMSHR::allocate(Addr _addr, int _size, PacketPtr target, 20611731Sjason@lowepower.com Tick whenReady, Counter _order) 20711731Sjason@lowepower.com{ 20811731Sjason@lowepower.com addr = _addr; 20911731Sjason@lowepower.com size = _size; 21011731Sjason@lowepower.com readyTime = whenReady; 21111731Sjason@lowepower.com order = _order; 21211731Sjason@lowepower.com assert(target); 21311731Sjason@lowepower.com isForward = false; 21411731Sjason@lowepower.com _isUncacheable = target->req->isUncacheable(); 21511731Sjason@lowepower.com inService = false; 21611731Sjason@lowepower.com downstreamPending = false; 21711731Sjason@lowepower.com threadNum = 0; 21811731Sjason@lowepower.com ntargets = 1; 21911731Sjason@lowepower.com assert(targets->isReset()); 22011731Sjason@lowepower.com // Don't know of a case where we would allocate a new MSHR for a 22111731Sjason@lowepower.com // snoop (mem-side request), so set source according to request here 22211731Sjason@lowepower.com Target::Source source = (target->cmd == MemCmd::HardPFReq) ? 22311731Sjason@lowepower.com Target::FromPrefetcher : Target::FromCPU; 22411731Sjason@lowepower.com targets->add(target, whenReady, _order, source, true); 22511731Sjason@lowepower.com assert(deferredTargets->isReset()); 22611731Sjason@lowepower.com data = NULL; 22711731Sjason@lowepower.com} 22811731Sjason@lowepower.com 22911731Sjason@lowepower.com 23011731Sjason@lowepower.comvoid 23111731Sjason@lowepower.comMSHR::clearDownstreamPending() 23211731Sjason@lowepower.com{ 23311731Sjason@lowepower.com assert(downstreamPending); 23411731Sjason@lowepower.com downstreamPending = false; 23511731Sjason@lowepower.com // recursively clear flag on any MSHRs we will be forwarding 23611731Sjason@lowepower.com // responses to 23711731Sjason@lowepower.com targets->clearDownstreamPending(); 23811731Sjason@lowepower.com} 23911731Sjason@lowepower.com 24011731Sjason@lowepower.combool 24111731Sjason@lowepower.comMSHR::markInService(PacketPtr pkt) 24211731Sjason@lowepower.com{ 24311731Sjason@lowepower.com assert(!inService); 24411731Sjason@lowepower.com if (isForwardNoResponse()) { 24511731Sjason@lowepower.com // we just forwarded the request packet & don't expect a 24611731Sjason@lowepower.com // response, so get rid of it 24711731Sjason@lowepower.com assert(getNumTargets() == 1); 24811731Sjason@lowepower.com popTarget(); 24911731Sjason@lowepower.com return true; 25011731Sjason@lowepower.com } 25111731Sjason@lowepower.com inService = true; 25211731Sjason@lowepower.com pendingDirty = (targets->needsExclusive || 25311731Sjason@lowepower.com (!pkt->sharedAsserted() && pkt->memInhibitAsserted())); 25411731Sjason@lowepower.com postInvalidate = postDowngrade = false; 25511731Sjason@lowepower.com 25611731Sjason@lowepower.com if (!downstreamPending) { 25711731Sjason@lowepower.com // let upstream caches know that the request has made it to a 25811731Sjason@lowepower.com // level where it's going to get a response 25911731Sjason@lowepower.com targets->clearDownstreamPending(); 26011731Sjason@lowepower.com } 26111731Sjason@lowepower.com return false; 26211731Sjason@lowepower.com} 26311731Sjason@lowepower.com 26411731Sjason@lowepower.com 26511731Sjason@lowepower.comvoid 26611731Sjason@lowepower.comMSHR::deallocate() 26711731Sjason@lowepower.com{ 26811731Sjason@lowepower.com assert(targets->empty()); 26911731Sjason@lowepower.com targets->resetFlags(); 27011731Sjason@lowepower.com assert(deferredTargets->isReset()); 27111731Sjason@lowepower.com assert(ntargets == 0); 27211731Sjason@lowepower.com inService = false; 27311731Sjason@lowepower.com} 27411731Sjason@lowepower.com 27511731Sjason@lowepower.com/* 27611731Sjason@lowepower.com * Adds a target to an MSHR 27711731Sjason@lowepower.com */ 27811731Sjason@lowepower.comvoid 27911731Sjason@lowepower.comMSHR::allocateTarget(PacketPtr pkt, Tick whenReady, Counter _order) 28011731Sjason@lowepower.com{ 28111731Sjason@lowepower.com // if there's a request already in service for this MSHR, we will 28211731Sjason@lowepower.com // have to defer the new target until after the response if any of 28311731Sjason@lowepower.com // the following are true: 28411731Sjason@lowepower.com // - there are other targets already deferred 28511731Sjason@lowepower.com // - there's a pending invalidate to be applied after the response 28611731Sjason@lowepower.com // comes back (but before this target is processed) 28711731Sjason@lowepower.com // - this target requires an exclusive block and either we're not 28811731Sjason@lowepower.com // getting an exclusive block back or we have already snooped 28911731Sjason@lowepower.com // another read request that will downgrade our exclusive block 29011731Sjason@lowepower.com // to shared 29111731Sjason@lowepower.com 29212137Sar4jc@virginia.edu // assume we'd never issue a prefetch when we've got an 29311731Sjason@lowepower.com // outstanding miss 29411731Sjason@lowepower.com assert(pkt->cmd != MemCmd::HardPFReq); 29511731Sjason@lowepower.com 29611731Sjason@lowepower.com if (inService && 29711731Sjason@lowepower.com (!deferredTargets->empty() || hasPostInvalidate() || 29811731Sjason@lowepower.com (pkt->needsExclusive() && 29911731Sjason@lowepower.com (!isPendingDirty() || hasPostDowngrade() || isForward)))) { 30011731Sjason@lowepower.com // need to put on deferred list 30112137Sar4jc@virginia.edu if (hasPostInvalidate()) 30211731Sjason@lowepower.com replaceUpgrade(pkt); 30311731Sjason@lowepower.com deferredTargets->add(pkt, whenReady, _order, Target::FromCPU, true); 30411731Sjason@lowepower.com } else { 30512137Sar4jc@virginia.edu // No request outstanding, or still OK to append to 30611731Sjason@lowepower.com // outstanding request: append to regular target list. Only 30712137Sar4jc@virginia.edu // mark pending if current request hasn't been issued yet 30811731Sjason@lowepower.com // (isn't in service). 30912137Sar4jc@virginia.edu targets->add(pkt, whenReady, _order, Target::FromCPU, !inService); 31011731Sjason@lowepower.com } 31111731Sjason@lowepower.com 31211731Sjason@lowepower.com ++ntargets; 31311731Sjason@lowepower.com} 31411731Sjason@lowepower.com 31511731Sjason@lowepower.combool 31611731Sjason@lowepower.comMSHR::handleSnoop(PacketPtr pkt, Counter _order) 31711731Sjason@lowepower.com{ 31811731Sjason@lowepower.com DPRINTF(Cache, "%s for %s address %x size %d\n", __func__, 31911731Sjason@lowepower.com pkt->cmdString(), pkt->getAddr(), pkt->getSize()); 32011731Sjason@lowepower.com if (!inService || (pkt->isExpressSnoop() && downstreamPending)) { 32111731Sjason@lowepower.com // Request has not been issued yet, or it's been issued 32211731Sjason@lowepower.com // locally but is buffered unissued at some downstream cache 32311731Sjason@lowepower.com // which is forwarding us this snoop. Either way, the packet 32411731Sjason@lowepower.com // we're snooping logically precedes this MSHR's request, so 32511731Sjason@lowepower.com // the snoop has no impact on the MSHR, but must be processed 32611731Sjason@lowepower.com // in the standard way by the cache. The only exception is 32711731Sjason@lowepower.com // that if we're an L2+ cache buffering an UpgradeReq from a 32811731Sjason@lowepower.com // higher-level cache, and the snoop is invalidating, then our 32911731Sjason@lowepower.com // buffered upgrades must be converted to read exclusives, 33011731Sjason@lowepower.com // since the upper-level cache no longer has a valid copy. 33111731Sjason@lowepower.com // That is, even though the upper-level cache got out on its 33211731Sjason@lowepower.com // local bus first, some other invalidating transaction 33311731Sjason@lowepower.com // reached the global bus before the upgrade did. 33411731Sjason@lowepower.com if (pkt->needsExclusive()) { 33511731Sjason@lowepower.com targets->replaceUpgrades(); 33611731Sjason@lowepower.com deferredTargets->replaceUpgrades(); 33711731Sjason@lowepower.com } 33811731Sjason@lowepower.com 33911731Sjason@lowepower.com return false; 34011731Sjason@lowepower.com } 34111731Sjason@lowepower.com 34211731Sjason@lowepower.com // From here on down, the request issued by this MSHR logically 34311731Sjason@lowepower.com // precedes the request we're snooping. 34411731Sjason@lowepower.com if (pkt->needsExclusive()) { 34511731Sjason@lowepower.com // snooped request still precedes the re-request we'll have to 34611731Sjason@lowepower.com // issue for deferred targets, if any... 34711731Sjason@lowepower.com deferredTargets->replaceUpgrades(); 34811731Sjason@lowepower.com } 34911731Sjason@lowepower.com 35011731Sjason@lowepower.com if (hasPostInvalidate()) { 35111731Sjason@lowepower.com // a prior snoop has already appended an invalidation, so 35211731Sjason@lowepower.com // logically we don't have the block anymore; no need for 35311731Sjason@lowepower.com // further snooping. 35411731Sjason@lowepower.com return true; 35511731Sjason@lowepower.com } 35611731Sjason@lowepower.com 35711731Sjason@lowepower.com if (isPendingDirty() || pkt->isInvalidate()) { 35811731Sjason@lowepower.com // We need to save and replay the packet in two cases: 35911731Sjason@lowepower.com // 1. We're awaiting an exclusive copy, so ownership is pending, 36011731Sjason@lowepower.com // and we need to respond after we receive data. 36111731Sjason@lowepower.com // 2. It's an invalidation (e.g., UpgradeReq), and we need 36211731Sjason@lowepower.com // to forward the snoop up the hierarchy after the current 36311731Sjason@lowepower.com // transaction completes. 36411731Sjason@lowepower.com 36511731Sjason@lowepower.com // Actual target device (typ. a memory) will delete the 36611731Sjason@lowepower.com // packet on reception, so we need to save a copy here. 36711731Sjason@lowepower.com PacketPtr cp_pkt = new Packet(pkt, true); 36811731Sjason@lowepower.com targets->add(cp_pkt, curTick(), _order, Target::FromSnoop, 36911731Sjason@lowepower.com downstreamPending && targets->needsExclusive); 37011731Sjason@lowepower.com ++ntargets; 37111731Sjason@lowepower.com 37211731Sjason@lowepower.com if (isPendingDirty()) { 37311731Sjason@lowepower.com pkt->assertMemInhibit(); 37411731Sjason@lowepower.com pkt->setSupplyExclusive(); 37511731Sjason@lowepower.com } 37611731Sjason@lowepower.com 37711731Sjason@lowepower.com if (pkt->needsExclusive()) { 37811731Sjason@lowepower.com // This transaction will take away our pending copy 37911731Sjason@lowepower.com postInvalidate = true; 38011731Sjason@lowepower.com } 38111731Sjason@lowepower.com } 38211731Sjason@lowepower.com 38311731Sjason@lowepower.com if (!pkt->needsExclusive()) { 384 // This transaction will get a read-shared copy, downgrading 385 // our copy if we had an exclusive one 386 postDowngrade = true; 387 pkt->assertShared(); 388 } 389 390 return true; 391} 392 393 394bool 395MSHR::promoteDeferredTargets() 396{ 397 assert(targets->empty()); 398 if (deferredTargets->empty()) { 399 return false; 400 } 401 402 // swap targets & deferredTargets lists 403 TargetList *tmp = targets; 404 targets = deferredTargets; 405 deferredTargets = tmp; 406 407 assert(targets->size() == ntargets); 408 409 // clear deferredTargets flags 410 deferredTargets->resetFlags(); 411 412 order = targets->front().order; 413 readyTime = std::max(curTick(), targets->front().readyTime); 414 415 return true; 416} 417 418 419void 420MSHR::handleFill(Packet *pkt, CacheBlk *blk) 421{ 422 if (!pkt->sharedAsserted() 423 && !(hasPostInvalidate() || hasPostDowngrade()) 424 && deferredTargets->needsExclusive) { 425 // We got an exclusive response, but we have deferred targets 426 // which are waiting to request an exclusive copy (not because 427 // of a pending invalidate). This can happen if the original 428 // request was for a read-only (non-exclusive) block, but we 429 // got an exclusive copy anyway because of the E part of the 430 // MOESI/MESI protocol. Since we got the exclusive copy 431 // there's no need to defer the targets, so move them up to 432 // the regular target list. 433 assert(!targets->needsExclusive); 434 targets->needsExclusive = true; 435 // if any of the deferred targets were upper-level cache 436 // requests marked downstreamPending, need to clear that 437 assert(!downstreamPending); // not pending here anymore 438 deferredTargets->clearDownstreamPending(); 439 // this clears out deferredTargets too 440 targets->splice(targets->end(), *deferredTargets); 441 deferredTargets->resetFlags(); 442 } 443} 444 445 446bool 447MSHR::checkFunctional(PacketPtr pkt) 448{ 449 // For printing, we treat the MSHR as a whole as single entity. 450 // For other requests, we iterate over the individual targets 451 // since that's where the actual data lies. 452 if (pkt->isPrint()) { 453 pkt->checkFunctional(this, addr, size, NULL); 454 return false; 455 } else { 456 return (targets->checkFunctional(pkt) || 457 deferredTargets->checkFunctional(pkt)); 458 } 459} 460 461 462void 463MSHR::print(std::ostream &os, int verbosity, const std::string &prefix) const 464{ 465 ccprintf(os, "%s[%x:%x] %s %s %s state: %s %s %s %s\n", 466 prefix, addr, addr+size-1, 467 isForward ? "Forward" : "", 468 isForwardNoResponse() ? "ForwNoResp" : "", 469 needsExclusive() ? "Excl" : "", 470 _isUncacheable ? "Unc" : "", 471 inService ? "InSvc" : "", 472 downstreamPending ? "DwnPend" : "", 473 hasPostInvalidate() ? "PostInv" : "", 474 hasPostDowngrade() ? "PostDowngr" : ""); 475 476 ccprintf(os, "%s Targets:\n", prefix); 477 targets->print(os, verbosity, prefix + " "); 478 if (!deferredTargets->empty()) { 479 ccprintf(os, "%s Deferred Targets:\n", prefix); 480 deferredTargets->print(os, verbosity, prefix + " "); 481 } 482} 483 484std::string 485MSHR::print() const 486{ 487 ostringstream str; 488 print(str); 489 return str.str(); 490} 491 492MSHR::~MSHR() 493{ 494 delete[] targets; 495 delete[] deferredTargets; 496} 497