mshr.cc revision 8232
19646SChris.Emmons@arm.com/* 210839Sandreas.sandberg@arm.com * Copyright (c) 2002-2005 The Regents of The University of Michigan 39646SChris.Emmons@arm.com * Copyright (c) 2010 Advanced Micro Devices, Inc. 49646SChris.Emmons@arm.com * All rights reserved. 59646SChris.Emmons@arm.com * 69646SChris.Emmons@arm.com * Redistribution and use in source and binary forms, with or without 79646SChris.Emmons@arm.com * modification, are permitted provided that the following conditions are 89646SChris.Emmons@arm.com * met: redistributions of source code must retain the above copyright 99646SChris.Emmons@arm.com * notice, this list of conditions and the following disclaimer; 109646SChris.Emmons@arm.com * redistributions in binary form must reproduce the above copyright 119646SChris.Emmons@arm.com * notice, this list of conditions and the following disclaimer in the 129646SChris.Emmons@arm.com * documentation and/or other materials provided with the distribution; 139646SChris.Emmons@arm.com * neither the name of the copyright holders nor the names of its 149646SChris.Emmons@arm.com * contributors may be used to endorse or promote products derived from 159646SChris.Emmons@arm.com * this software without specific prior written permission. 169646SChris.Emmons@arm.com * 179646SChris.Emmons@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 189646SChris.Emmons@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 199646SChris.Emmons@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 209646SChris.Emmons@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 219646SChris.Emmons@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 229646SChris.Emmons@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 239646SChris.Emmons@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 249646SChris.Emmons@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 259646SChris.Emmons@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 269646SChris.Emmons@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 279646SChris.Emmons@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 289646SChris.Emmons@arm.com * 299646SChris.Emmons@arm.com * Authors: Erik Hallnor 309646SChris.Emmons@arm.com * Dave Greene 319646SChris.Emmons@arm.com */ 329646SChris.Emmons@arm.com 339646SChris.Emmons@arm.com/** 349646SChris.Emmons@arm.com * @file 359646SChris.Emmons@arm.com * Miss Status and Handling Register (MSHR) definitions. 369646SChris.Emmons@arm.com */ 379646SChris.Emmons@arm.com 3811090Sandreas.sandberg@arm.com#include <algorithm> 399646SChris.Emmons@arm.com#include <cassert> 409646SChris.Emmons@arm.com#include <string> 419646SChris.Emmons@arm.com#include <vector> 429646SChris.Emmons@arm.com 439646SChris.Emmons@arm.com#include "base/misc.hh" 449646SChris.Emmons@arm.com#include "base/types.hh" 459646SChris.Emmons@arm.com#include "debug/Cache.hh" 469646SChris.Emmons@arm.com#include "mem/cache/cache.hh" 479646SChris.Emmons@arm.com#include "mem/cache/mshr.hh" 489646SChris.Emmons@arm.com#include "sim/core.hh" 499646SChris.Emmons@arm.com 509646SChris.Emmons@arm.comusing namespace std; 519646SChris.Emmons@arm.com 529646SChris.Emmons@arm.comMSHR::MSHR() 539646SChris.Emmons@arm.com{ 549646SChris.Emmons@arm.com inService = false; 559646SChris.Emmons@arm.com ntargets = 0; 569646SChris.Emmons@arm.com threadNum = InvalidThreadID; 579646SChris.Emmons@arm.com targets = new TargetList(); 589646SChris.Emmons@arm.com deferredTargets = new TargetList(); 599646SChris.Emmons@arm.com} 609646SChris.Emmons@arm.com 619646SChris.Emmons@arm.com 629646SChris.Emmons@arm.comMSHR::TargetList::TargetList() 639646SChris.Emmons@arm.com : needsExclusive(false), hasUpgrade(false) 649646SChris.Emmons@arm.com{} 6511090Sandreas.sandberg@arm.com 6611090Sandreas.sandberg@arm.com 6711090Sandreas.sandberg@arm.cominline void 6811090Sandreas.sandberg@arm.comMSHR::TargetList::add(PacketPtr pkt, Tick readyTime, 6911090Sandreas.sandberg@arm.com Counter order, Target::Source source, bool markPending) 7011090Sandreas.sandberg@arm.com{ 7111090Sandreas.sandberg@arm.com if (source != Target::FromSnoop) { 7211090Sandreas.sandberg@arm.com if (pkt->needsExclusive()) { 7311090Sandreas.sandberg@arm.com needsExclusive = true; 749646SChris.Emmons@arm.com } 759646SChris.Emmons@arm.com 769646SChris.Emmons@arm.com // StoreCondReq is effectively an upgrade if it's in an MSHR 779646SChris.Emmons@arm.com // since it would have been failed already if we didn't have a 789646SChris.Emmons@arm.com // read-only copy 799646SChris.Emmons@arm.com if (pkt->isUpgrade() || pkt->cmd == MemCmd::StoreCondReq) { 8010839Sandreas.sandberg@arm.com hasUpgrade = true; 819646SChris.Emmons@arm.com } 8210839Sandreas.sandberg@arm.com } 8310839Sandreas.sandberg@arm.com 849646SChris.Emmons@arm.com if (markPending) { 8511090Sandreas.sandberg@arm.com MSHR *mshr = dynamic_cast<MSHR*>(pkt->senderState); 869646SChris.Emmons@arm.com if (mshr != NULL) { 879646SChris.Emmons@arm.com assert(!mshr->downstreamPending); 889646SChris.Emmons@arm.com mshr->downstreamPending = true; 8911090Sandreas.sandberg@arm.com } 9011090Sandreas.sandberg@arm.com } 919646SChris.Emmons@arm.com 929646SChris.Emmons@arm.com push_back(Target(pkt, readyTime, order, source, markPending)); 939646SChris.Emmons@arm.com} 9411090Sandreas.sandberg@arm.com 9511090Sandreas.sandberg@arm.com 9611090Sandreas.sandberg@arm.comstatic void 979646SChris.Emmons@arm.comreplaceUpgrade(PacketPtr pkt) 9811091Sandreas.sandberg@arm.com{ 9911091Sandreas.sandberg@arm.com if (pkt->cmd == MemCmd::UpgradeReq) { 10011090Sandreas.sandberg@arm.com pkt->cmd = MemCmd::ReadExReq; 10111090Sandreas.sandberg@arm.com DPRINTF(Cache, "Replacing UpgradeReq with ReadExReq\n"); 10211090Sandreas.sandberg@arm.com } else if (pkt->cmd == MemCmd::SCUpgradeReq) { 10311090Sandreas.sandberg@arm.com pkt->cmd = MemCmd::SCUpgradeFailReq; 10411090Sandreas.sandberg@arm.com DPRINTF(Cache, "Replacing SCUpgradeReq with SCUpgradeFailReq\n"); 10511090Sandreas.sandberg@arm.com } else if (pkt->cmd == MemCmd::StoreCondReq) { 10611090Sandreas.sandberg@arm.com pkt->cmd = MemCmd::StoreCondFailReq; 10711090Sandreas.sandberg@arm.com DPRINTF(Cache, "Replacing StoreCondReq with StoreCondFailReq\n"); 10811090Sandreas.sandberg@arm.com } 10911090Sandreas.sandberg@arm.com} 11011090Sandreas.sandberg@arm.com 11111090Sandreas.sandberg@arm.com 11211090Sandreas.sandberg@arm.comvoid 11311090Sandreas.sandberg@arm.comMSHR::TargetList::replaceUpgrades() 11411090Sandreas.sandberg@arm.com{ 11511090Sandreas.sandberg@arm.com if (!hasUpgrade) 11611090Sandreas.sandberg@arm.com return; 11711090Sandreas.sandberg@arm.com 11811090Sandreas.sandberg@arm.com Iterator end_i = end(); 11911090Sandreas.sandberg@arm.com for (Iterator i = begin(); i != end_i; ++i) { 1209646SChris.Emmons@arm.com replaceUpgrade(i->pkt); 1219646SChris.Emmons@arm.com } 1229646SChris.Emmons@arm.com 1239646SChris.Emmons@arm.com hasUpgrade = false; 1249646SChris.Emmons@arm.com} 1259646SChris.Emmons@arm.com 1269646SChris.Emmons@arm.com 1279646SChris.Emmons@arm.comvoid 1289646SChris.Emmons@arm.comMSHR::TargetList::clearDownstreamPending() 1299646SChris.Emmons@arm.com{ 1309646SChris.Emmons@arm.com Iterator end_i = end(); 1319646SChris.Emmons@arm.com for (Iterator i = begin(); i != end_i; ++i) { 1329646SChris.Emmons@arm.com if (i->markedPending) { 1339646SChris.Emmons@arm.com MSHR *mshr = dynamic_cast<MSHR*>(i->pkt->senderState); 1349646SChris.Emmons@arm.com if (mshr != NULL) { 1359646SChris.Emmons@arm.com mshr->clearDownstreamPending(); 1369646SChris.Emmons@arm.com } 1379646SChris.Emmons@arm.com } 1389646SChris.Emmons@arm.com } 1399646SChris.Emmons@arm.com} 1409646SChris.Emmons@arm.com 1419646SChris.Emmons@arm.com 1429646SChris.Emmons@arm.combool 1439646SChris.Emmons@arm.comMSHR::TargetList::checkFunctional(PacketPtr pkt) 1449646SChris.Emmons@arm.com{ 14511090Sandreas.sandberg@arm.com Iterator end_i = end(); 14611090Sandreas.sandberg@arm.com for (Iterator i = begin(); i != end_i; ++i) { 1479646SChris.Emmons@arm.com if (pkt->checkFunctional(i->pkt)) { 1489646SChris.Emmons@arm.com return true; 14911090Sandreas.sandberg@arm.com } 1509646SChris.Emmons@arm.com } 1519646SChris.Emmons@arm.com 15211090Sandreas.sandberg@arm.com return false; 1539646SChris.Emmons@arm.com} 15411090Sandreas.sandberg@arm.com 15511090Sandreas.sandberg@arm.com 1569646SChris.Emmons@arm.comvoid 1579646SChris.Emmons@arm.comMSHR::TargetList:: 15811090Sandreas.sandberg@arm.comprint(std::ostream &os, int verbosity, const std::string &prefix) const 1599646SChris.Emmons@arm.com{ 16011090Sandreas.sandberg@arm.com ConstIterator end_i = end(); 16111090Sandreas.sandberg@arm.com for (ConstIterator i = begin(); i != end_i; ++i) { 16210839Sandreas.sandberg@arm.com const char *s; 1639646SChris.Emmons@arm.com switch (i->source) { 1649646SChris.Emmons@arm.com case Target::FromCPU: s = "FromCPU"; 1659646SChris.Emmons@arm.com case Target::FromSnoop: s = "FromSnoop"; 1669646SChris.Emmons@arm.com case Target::FromPrefetcher: s = "FromPrefetcher"; 1679646SChris.Emmons@arm.com default: s = ""; 1689646SChris.Emmons@arm.com } 1699646SChris.Emmons@arm.com ccprintf(os, "%s%s: ", prefix, s); 1709646SChris.Emmons@arm.com i->pkt->print(os, verbosity, ""); 1719646SChris.Emmons@arm.com } 1729646SChris.Emmons@arm.com} 1739646SChris.Emmons@arm.com 17411090Sandreas.sandberg@arm.com 17511090Sandreas.sandberg@arm.comvoid 17611090Sandreas.sandberg@arm.comMSHR::allocate(Addr _addr, int _size, PacketPtr target, 17711090Sandreas.sandberg@arm.com Tick whenReady, Counter _order) 1789646SChris.Emmons@arm.com{ 1799646SChris.Emmons@arm.com addr = _addr; 1809646SChris.Emmons@arm.com size = _size; 1819646SChris.Emmons@arm.com readyTime = whenReady; 1829646SChris.Emmons@arm.com order = _order; 1839646SChris.Emmons@arm.com assert(target); 1849646SChris.Emmons@arm.com isForward = false; 1859646SChris.Emmons@arm.com _isUncacheable = target->req->isUncacheable(); 1869646SChris.Emmons@arm.com inService = false; 1879646SChris.Emmons@arm.com downstreamPending = false; 1889646SChris.Emmons@arm.com threadNum = 0; 1899646SChris.Emmons@arm.com ntargets = 1; 1909646SChris.Emmons@arm.com assert(targets->isReset()); 1919646SChris.Emmons@arm.com // Don't know of a case where we would allocate a new MSHR for a 1929646SChris.Emmons@arm.com // snoop (mem-side request), so set source according to request here 1939646SChris.Emmons@arm.com Target::Source source = (target->cmd == MemCmd::HardPFReq) ? 1949646SChris.Emmons@arm.com Target::FromPrefetcher : Target::FromCPU; 1959646SChris.Emmons@arm.com targets->add(target, whenReady, _order, source, true); 1969646SChris.Emmons@arm.com assert(deferredTargets->isReset()); 1979646SChris.Emmons@arm.com data = NULL; 1989646SChris.Emmons@arm.com} 1999646SChris.Emmons@arm.com 2009646SChris.Emmons@arm.com 2019646SChris.Emmons@arm.comvoid 2029646SChris.Emmons@arm.comMSHR::clearDownstreamPending() 2039646SChris.Emmons@arm.com{ 2049646SChris.Emmons@arm.com assert(downstreamPending); 2059646SChris.Emmons@arm.com downstreamPending = false; 2069646SChris.Emmons@arm.com // recursively clear flag on any MSHRs we will be forwarding 2079646SChris.Emmons@arm.com // responses to 2089646SChris.Emmons@arm.com targets->clearDownstreamPending(); 2099646SChris.Emmons@arm.com} 2109646SChris.Emmons@arm.com 2119646SChris.Emmons@arm.combool 2129646SChris.Emmons@arm.comMSHR::markInService(PacketPtr pkt) 2139646SChris.Emmons@arm.com{ 2149646SChris.Emmons@arm.com assert(!inService); 2159646SChris.Emmons@arm.com if (isForwardNoResponse()) { 2169646SChris.Emmons@arm.com // we just forwarded the request packet & don't expect a 2179646SChris.Emmons@arm.com // response, so get rid of it 2189646SChris.Emmons@arm.com assert(getNumTargets() == 1); 2199646SChris.Emmons@arm.com popTarget(); 2209646SChris.Emmons@arm.com return true; 2219646SChris.Emmons@arm.com } 2229646SChris.Emmons@arm.com inService = true; 2239646SChris.Emmons@arm.com pendingDirty = (targets->needsExclusive || 2249646SChris.Emmons@arm.com (!pkt->sharedAsserted() && pkt->memInhibitAsserted())); 2259646SChris.Emmons@arm.com postInvalidate = postDowngrade = false; 2269646SChris.Emmons@arm.com 2279646SChris.Emmons@arm.com if (!downstreamPending) { 2289646SChris.Emmons@arm.com // let upstream caches know that the request has made it to a 2299646SChris.Emmons@arm.com // level where it's going to get a response 2309646SChris.Emmons@arm.com targets->clearDownstreamPending(); 2319646SChris.Emmons@arm.com } 23211090Sandreas.sandberg@arm.com return false; 23311090Sandreas.sandberg@arm.com} 23411090Sandreas.sandberg@arm.com 2359646SChris.Emmons@arm.com 2369646SChris.Emmons@arm.comvoid 2379646SChris.Emmons@arm.comMSHR::deallocate() 23811090Sandreas.sandberg@arm.com{ 2399646SChris.Emmons@arm.com assert(targets->empty()); 2409646SChris.Emmons@arm.com targets->resetFlags(); 2419646SChris.Emmons@arm.com assert(deferredTargets->isReset()); 2429646SChris.Emmons@arm.com assert(ntargets == 0); 2439646SChris.Emmons@arm.com inService = false; 2449646SChris.Emmons@arm.com} 2459646SChris.Emmons@arm.com 2469646SChris.Emmons@arm.com/* 2479646SChris.Emmons@arm.com * Adds a target to an MSHR 2489646SChris.Emmons@arm.com */ 2499646SChris.Emmons@arm.comvoid 2509646SChris.Emmons@arm.comMSHR::allocateTarget(PacketPtr pkt, Tick whenReady, Counter _order) 2519646SChris.Emmons@arm.com{ 2529646SChris.Emmons@arm.com // if there's a request already in service for this MSHR, we will 2539646SChris.Emmons@arm.com // have to defer the new target until after the response if any of 2549646SChris.Emmons@arm.com // the following are true: 2559646SChris.Emmons@arm.com // - there are other targets already deferred 25611090Sandreas.sandberg@arm.com // - there's a pending invalidate to be applied after the response 25711090Sandreas.sandberg@arm.com // comes back (but before this target is processed) 2589646SChris.Emmons@arm.com // - this target requires an exclusive block and either we're not 25911090Sandreas.sandberg@arm.com // getting an exclusive block back or we have already snooped 26011090Sandreas.sandberg@arm.com // another read request that will downgrade our exclusive block 26110839Sandreas.sandberg@arm.com // to shared 26211090Sandreas.sandberg@arm.com 26311090Sandreas.sandberg@arm.com // assume we'd never issue a prefetch when we've got an 26411090Sandreas.sandberg@arm.com // outstanding miss 26511090Sandreas.sandberg@arm.com assert(pkt->cmd != MemCmd::HardPFReq); 26611090Sandreas.sandberg@arm.com 26711090Sandreas.sandberg@arm.com if (inService && 26811090Sandreas.sandberg@arm.com (!deferredTargets->empty() || hasPostInvalidate() || 26911090Sandreas.sandberg@arm.com (pkt->needsExclusive() && 27011090Sandreas.sandberg@arm.com (!isPendingDirty() || hasPostDowngrade() || isForward)))) { 27111090Sandreas.sandberg@arm.com // need to put on deferred list 27211090Sandreas.sandberg@arm.com if (hasPostInvalidate()) 27311090Sandreas.sandberg@arm.com replaceUpgrade(pkt); 27411090Sandreas.sandberg@arm.com deferredTargets->add(pkt, whenReady, _order, Target::FromCPU, true); 27511090Sandreas.sandberg@arm.com } else { 27611090Sandreas.sandberg@arm.com // No request outstanding, or still OK to append to 27711090Sandreas.sandberg@arm.com // outstanding request: append to regular target list. Only 27811090Sandreas.sandberg@arm.com // mark pending if current request hasn't been issued yet 27911090Sandreas.sandberg@arm.com // (isn't in service). 28011090Sandreas.sandberg@arm.com targets->add(pkt, whenReady, _order, Target::FromCPU, !inService); 28111090Sandreas.sandberg@arm.com } 28211090Sandreas.sandberg@arm.com 28311090Sandreas.sandberg@arm.com ++ntargets; 28411090Sandreas.sandberg@arm.com} 28511090Sandreas.sandberg@arm.com 28611090Sandreas.sandberg@arm.combool 28711090Sandreas.sandberg@arm.comMSHR::handleSnoop(PacketPtr pkt, Counter _order) 28811090Sandreas.sandberg@arm.com{ 28911090Sandreas.sandberg@arm.com if (!inService || (pkt->isExpressSnoop() && downstreamPending)) { 29011090Sandreas.sandberg@arm.com // Request has not been issued yet, or it's been issued 29111090Sandreas.sandberg@arm.com // locally but is buffered unissued at some downstream cache 29211090Sandreas.sandberg@arm.com // which is forwarding us this snoop. Either way, the packet 29311090Sandreas.sandberg@arm.com // we're snooping logically precedes this MSHR's request, so 29411090Sandreas.sandberg@arm.com // the snoop has no impact on the MSHR, but must be processed 29511090Sandreas.sandberg@arm.com // in the standard way by the cache. The only exception is 29611090Sandreas.sandberg@arm.com // that if we're an L2+ cache buffering an UpgradeReq from a 29711090Sandreas.sandberg@arm.com // higher-level cache, and the snoop is invalidating, then our 29811090Sandreas.sandberg@arm.com // buffered upgrades must be converted to read exclusives, 29911090Sandreas.sandberg@arm.com // since the upper-level cache no longer has a valid copy. 30011090Sandreas.sandberg@arm.com // That is, even though the upper-level cache got out on its 30111090Sandreas.sandberg@arm.com // local bus first, some other invalidating transaction 30211090Sandreas.sandberg@arm.com // reached the global bus before the upgrade did. 30311090Sandreas.sandberg@arm.com if (pkt->needsExclusive()) { 30411090Sandreas.sandberg@arm.com targets->replaceUpgrades(); 30511090Sandreas.sandberg@arm.com deferredTargets->replaceUpgrades(); 30611090Sandreas.sandberg@arm.com } 30711090Sandreas.sandberg@arm.com 30811090Sandreas.sandberg@arm.com return false; 30911090Sandreas.sandberg@arm.com } 31011090Sandreas.sandberg@arm.com 31111090Sandreas.sandberg@arm.com // From here on down, the request issued by this MSHR logically 31211090Sandreas.sandberg@arm.com // precedes the request we're snooping. 31311090Sandreas.sandberg@arm.com if (pkt->needsExclusive()) { 31411090Sandreas.sandberg@arm.com // snooped request still precedes the re-request we'll have to 31511090Sandreas.sandberg@arm.com // issue for deferred targets, if any... 31611090Sandreas.sandberg@arm.com deferredTargets->replaceUpgrades(); 31711090Sandreas.sandberg@arm.com } 31811090Sandreas.sandberg@arm.com 31911090Sandreas.sandberg@arm.com if (hasPostInvalidate()) { 32011090Sandreas.sandberg@arm.com // a prior snoop has already appended an invalidation, so 32111090Sandreas.sandberg@arm.com // logically we don't have the block anymore; no need for 32211090Sandreas.sandberg@arm.com // further snooping. 32311090Sandreas.sandberg@arm.com return true; 32411090Sandreas.sandberg@arm.com } 32511090Sandreas.sandberg@arm.com 32611090Sandreas.sandberg@arm.com if (isPendingDirty() || pkt->isInvalidate()) { 32711090Sandreas.sandberg@arm.com // We need to save and replay the packet in two cases: 32811090Sandreas.sandberg@arm.com // 1. We're awaiting an exclusive copy, so ownership is pending, 32911090Sandreas.sandberg@arm.com // and we need to respond after we receive data. 33011090Sandreas.sandberg@arm.com // 2. It's an invalidation (e.g., UpgradeReq), and we need 33111090Sandreas.sandberg@arm.com // to forward the snoop up the hierarchy after the current 33211090Sandreas.sandberg@arm.com // transaction completes. 33311090Sandreas.sandberg@arm.com 33411090Sandreas.sandberg@arm.com // Actual target device (typ. PhysicalMemory) will delete the 33511090Sandreas.sandberg@arm.com // packet on reception, so we need to save a copy here. 33611090Sandreas.sandberg@arm.com PacketPtr cp_pkt = new Packet(pkt, true); 33711090Sandreas.sandberg@arm.com targets->add(cp_pkt, curTick(), _order, Target::FromSnoop, 33811090Sandreas.sandberg@arm.com downstreamPending && targets->needsExclusive); 33911090Sandreas.sandberg@arm.com ++ntargets; 34011090Sandreas.sandberg@arm.com 34111090Sandreas.sandberg@arm.com if (isPendingDirty()) { 34211090Sandreas.sandberg@arm.com pkt->assertMemInhibit(); 34311090Sandreas.sandberg@arm.com pkt->setSupplyExclusive(); 34411090Sandreas.sandberg@arm.com } 3459646SChris.Emmons@arm.com 3469646SChris.Emmons@arm.com if (pkt->needsExclusive()) { 34710839Sandreas.sandberg@arm.com // This transaction will take away our pending copy 3489646SChris.Emmons@arm.com postInvalidate = true; 3499646SChris.Emmons@arm.com } 3509646SChris.Emmons@arm.com } 3519646SChris.Emmons@arm.com 35211090Sandreas.sandberg@arm.com if (!pkt->needsExclusive()) { 35311090Sandreas.sandberg@arm.com // This transaction will get a read-shared copy, downgrading 35411090Sandreas.sandberg@arm.com // our copy if we had an exclusive one 35511090Sandreas.sandberg@arm.com postDowngrade = true; 35611090Sandreas.sandberg@arm.com pkt->assertShared(); 35711090Sandreas.sandberg@arm.com } 35811090Sandreas.sandberg@arm.com 3599646SChris.Emmons@arm.com return true; 36011090Sandreas.sandberg@arm.com} 36111090Sandreas.sandberg@arm.com 36211090Sandreas.sandberg@arm.com 36311090Sandreas.sandberg@arm.combool 3649646SChris.Emmons@arm.comMSHR::promoteDeferredTargets() 36511090Sandreas.sandberg@arm.com{ 36611090Sandreas.sandberg@arm.com assert(targets->empty()); 36711090Sandreas.sandberg@arm.com if (deferredTargets->empty()) { 3689646SChris.Emmons@arm.com return false; 36911090Sandreas.sandberg@arm.com } 37011090Sandreas.sandberg@arm.com 3719646SChris.Emmons@arm.com // swap targets & deferredTargets lists 37211090Sandreas.sandberg@arm.com TargetList *tmp = targets; 37311090Sandreas.sandberg@arm.com targets = deferredTargets; 37411090Sandreas.sandberg@arm.com deferredTargets = tmp; 3759646SChris.Emmons@arm.com 37611090Sandreas.sandberg@arm.com assert(targets->size() == ntargets); 37711090Sandreas.sandberg@arm.com 37811090Sandreas.sandberg@arm.com // clear deferredTargets flags 37911090Sandreas.sandberg@arm.com deferredTargets->resetFlags(); 3809646SChris.Emmons@arm.com 38111090Sandreas.sandberg@arm.com order = targets->front().order; 38211090Sandreas.sandberg@arm.com readyTime = std::max(curTick(), targets->front().readyTime); 3839646SChris.Emmons@arm.com 3849646SChris.Emmons@arm.com return true; 38511090Sandreas.sandberg@arm.com} 38611091Sandreas.sandberg@arm.com 38711091Sandreas.sandberg@arm.com 38811091Sandreas.sandberg@arm.comvoid 38911091Sandreas.sandberg@arm.comMSHR::handleFill(Packet *pkt, CacheBlk *blk) 39011091Sandreas.sandberg@arm.com{ 3919646SChris.Emmons@arm.com if (!pkt->sharedAsserted() 3929646SChris.Emmons@arm.com && !(hasPostInvalidate() || hasPostDowngrade()) 3939646SChris.Emmons@arm.com && deferredTargets->needsExclusive) { 394 // We got an exclusive response, but we have deferred targets 395 // which are waiting to request an exclusive copy (not because 396 // of a pending invalidate). This can happen if the original 397 // request was for a read-only (non-exclusive) block, but we 398 // got an exclusive copy anyway because of the E part of the 399 // MOESI/MESI protocol. Since we got the exclusive copy 400 // there's no need to defer the targets, so move them up to 401 // the regular target list. 402 assert(!targets->needsExclusive); 403 targets->needsExclusive = true; 404 // if any of the deferred targets were upper-level cache 405 // requests marked downstreamPending, need to clear that 406 assert(!downstreamPending); // not pending here anymore 407 deferredTargets->clearDownstreamPending(); 408 // this clears out deferredTargets too 409 targets->splice(targets->end(), *deferredTargets); 410 deferredTargets->resetFlags(); 411 } 412} 413 414 415bool 416MSHR::checkFunctional(PacketPtr pkt) 417{ 418 // For printing, we treat the MSHR as a whole as single entity. 419 // For other requests, we iterate over the individual targets 420 // since that's where the actual data lies. 421 if (pkt->isPrint()) { 422 pkt->checkFunctional(this, addr, size, NULL); 423 return false; 424 } else { 425 return (targets->checkFunctional(pkt) || 426 deferredTargets->checkFunctional(pkt)); 427 } 428} 429 430 431void 432MSHR::print(std::ostream &os, int verbosity, const std::string &prefix) const 433{ 434 ccprintf(os, "%s[%x:%x] %s %s %s state: %s %s %s %s\n", 435 prefix, addr, addr+size-1, 436 isForward ? "Forward" : "", 437 isForwardNoResponse() ? "ForwNoResp" : "", 438 needsExclusive() ? "Excl" : "", 439 _isUncacheable ? "Unc" : "", 440 inService ? "InSvc" : "", 441 downstreamPending ? "DwnPend" : "", 442 hasPostInvalidate() ? "PostInv" : "", 443 hasPostDowngrade() ? "PostDowngr" : ""); 444 445 ccprintf(os, "%s Targets:\n", prefix); 446 targets->print(os, verbosity, prefix + " "); 447 if (!deferredTargets->empty()) { 448 ccprintf(os, "%s Deferred Targets:\n", prefix); 449 deferredTargets->print(os, verbosity, prefix + " "); 450 } 451} 452 453MSHR::~MSHR() 454{ 455} 456