mshr.cc revision 11177:524c44cf8278
12810Srdreslin@umich.edu/* 212500Snikos.nikoleris@arm.com * Copyright (c) 2012-2013, 2015 ARM Limited 311051Sandreas.hansson@arm.com * All rights reserved. 411051Sandreas.hansson@arm.com * 511051Sandreas.hansson@arm.com * The license below extends only to copyright in the software and shall 611051Sandreas.hansson@arm.com * not be construed as granting a license to any other intellectual 711051Sandreas.hansson@arm.com * property including but not limited to intellectual property relating 811051Sandreas.hansson@arm.com * to a hardware implementation of the functionality of the software 911051Sandreas.hansson@arm.com * licensed hereunder. You may use the software subject to the license 1011051Sandreas.hansson@arm.com * terms below provided that you ensure that this notice is replicated 1111051Sandreas.hansson@arm.com * unmodified and in its entirety in all distributions of the software, 1211051Sandreas.hansson@arm.com * modified or unmodified, in source code or in binary form. 1311051Sandreas.hansson@arm.com * 1411051Sandreas.hansson@arm.com * Copyright (c) 2002-2005 The Regents of The University of Michigan 1511051Sandreas.hansson@arm.com * Copyright (c) 2010 Advanced Micro Devices, Inc. 162810Srdreslin@umich.edu * All rights reserved. 172810Srdreslin@umich.edu * 182810Srdreslin@umich.edu * Redistribution and use in source and binary forms, with or without 192810Srdreslin@umich.edu * modification, are permitted provided that the following conditions are 202810Srdreslin@umich.edu * met: redistributions of source code must retain the above copyright 212810Srdreslin@umich.edu * notice, this list of conditions and the following disclaimer; 222810Srdreslin@umich.edu * redistributions in binary form must reproduce the above copyright 232810Srdreslin@umich.edu * notice, this list of conditions and the following disclaimer in the 242810Srdreslin@umich.edu * documentation and/or other materials provided with the distribution; 252810Srdreslin@umich.edu * neither the name of the copyright holders nor the names of its 262810Srdreslin@umich.edu * contributors may be used to endorse or promote products derived from 272810Srdreslin@umich.edu * this software without specific prior written permission. 282810Srdreslin@umich.edu * 292810Srdreslin@umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 302810Srdreslin@umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 312810Srdreslin@umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 322810Srdreslin@umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 332810Srdreslin@umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 342810Srdreslin@umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 352810Srdreslin@umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 362810Srdreslin@umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 372810Srdreslin@umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 382810Srdreslin@umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 392810Srdreslin@umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 402810Srdreslin@umich.edu * 412810Srdreslin@umich.edu * Authors: Erik Hallnor 4211051Sandreas.hansson@arm.com * Dave Greene 4311051Sandreas.hansson@arm.com */ 442810Srdreslin@umich.edu 4511051Sandreas.hansson@arm.com/** 4611051Sandreas.hansson@arm.com * @file 4712349Snikos.nikoleris@arm.com * Miss Status and Handling Register (MSHR) definitions. 482810Srdreslin@umich.edu */ 492810Srdreslin@umich.edu 502810Srdreslin@umich.edu#include <algorithm> 512810Srdreslin@umich.edu#include <cassert> 5211051Sandreas.hansson@arm.com#include <string> 532810Srdreslin@umich.edu#include <vector> 542810Srdreslin@umich.edu 5511051Sandreas.hansson@arm.com#include "base/misc.hh" 562810Srdreslin@umich.edu#include "base/types.hh" 5712724Snikos.nikoleris@arm.com#include "debug/Cache.hh" 5812724Snikos.nikoleris@arm.com#include "mem/cache/cache.hh" 5912724Snikos.nikoleris@arm.com#include "mem/cache/mshr.hh" 6012334Sgabeblack@google.com#include "sim/core.hh" 6112724Snikos.nikoleris@arm.com 6211051Sandreas.hansson@arm.comusing namespace std; 6311051Sandreas.hansson@arm.com 6411051Sandreas.hansson@arm.comMSHR::MSHR() : readyTime(0), _isUncacheable(false), downstreamPending(false), 6511288Ssteve.reinhardt@amd.com pendingDirty(false), 6612724Snikos.nikoleris@arm.com postInvalidate(false), postDowngrade(false), 6713223Sodanrc@yahoo.com.br queue(NULL), order(0), blkAddr(0), 6811051Sandreas.hansson@arm.com blkSize(0), isSecure(false), inService(false), 6912724Snikos.nikoleris@arm.com isForward(false), threadNum(InvalidThreadID), data(NULL) 7012724Snikos.nikoleris@arm.com{ 7112724Snikos.nikoleris@arm.com} 7212724Snikos.nikoleris@arm.com 7311051Sandreas.hansson@arm.com 7411053Sandreas.hansson@arm.comMSHR::TargetList::TargetList() 7511053Sandreas.hansson@arm.com : needsExclusive(false), hasUpgrade(false) 7612724Snikos.nikoleris@arm.com{} 7711051Sandreas.hansson@arm.com 7811051Sandreas.hansson@arm.com 7911051Sandreas.hansson@arm.cominline void 8011051Sandreas.hansson@arm.comMSHR::TargetList::add(PacketPtr pkt, Tick readyTime, 8111601Sandreas.hansson@arm.com Counter order, Target::Source source, bool markPending) 8211601Sandreas.hansson@arm.com{ 8311051Sandreas.hansson@arm.com if (source != Target::FromSnoop) { 8412724Snikos.nikoleris@arm.com if (pkt->needsExclusive()) { 8511051Sandreas.hansson@arm.com needsExclusive = true; 8612724Snikos.nikoleris@arm.com } 8711600Sandreas.hansson@arm.com 8811600Sandreas.hansson@arm.com // StoreCondReq is effectively an upgrade if it's in an MSHR 8911051Sandreas.hansson@arm.com // since it would have been failed already if we didn't have a 9011051Sandreas.hansson@arm.com // read-only copy 9111051Sandreas.hansson@arm.com if (pkt->isUpgrade() || pkt->cmd == MemCmd::StoreCondReq) { 9211284Sandreas.hansson@arm.com hasUpgrade = true; 9311051Sandreas.hansson@arm.com } 9411051Sandreas.hansson@arm.com } 9511051Sandreas.hansson@arm.com 9611602Sandreas.hansson@arm.com if (markPending) { 9711051Sandreas.hansson@arm.com // Iterate over the SenderState stack and see if we find 9811051Sandreas.hansson@arm.com // an MSHR entry. If we do, set the downstreamPending 9911284Sandreas.hansson@arm.com // flag. Otherwise, do nothing. 10011051Sandreas.hansson@arm.com MSHR *mshr = pkt->findNextSenderState<MSHR>(); 10111284Sandreas.hansson@arm.com if (mshr != NULL) { 10211602Sandreas.hansson@arm.com assert(!mshr->downstreamPending); 10311051Sandreas.hansson@arm.com mshr->downstreamPending = true; 10411051Sandreas.hansson@arm.com } else { 10511284Sandreas.hansson@arm.com // No need to clear downstreamPending later 10611051Sandreas.hansson@arm.com markPending = false; 10711284Sandreas.hansson@arm.com } 10811284Sandreas.hansson@arm.com } 10911284Sandreas.hansson@arm.com 11011051Sandreas.hansson@arm.com emplace_back(pkt, readyTime, order, source, markPending); 11111051Sandreas.hansson@arm.com} 11211051Sandreas.hansson@arm.com 11311284Sandreas.hansson@arm.com 11411284Sandreas.hansson@arm.comstatic void 11511284Sandreas.hansson@arm.comreplaceUpgrade(PacketPtr pkt) 11611284Sandreas.hansson@arm.com{ 11711051Sandreas.hansson@arm.com if (pkt->cmd == MemCmd::UpgradeReq) { 11811051Sandreas.hansson@arm.com pkt->cmd = MemCmd::ReadExReq; 11911051Sandreas.hansson@arm.com DPRINTF(Cache, "Replacing UpgradeReq with ReadExReq\n"); 12011284Sandreas.hansson@arm.com } else if (pkt->cmd == MemCmd::SCUpgradeReq) { 12111284Sandreas.hansson@arm.com pkt->cmd = MemCmd::SCUpgradeFailReq; 12211284Sandreas.hansson@arm.com DPRINTF(Cache, "Replacing SCUpgradeReq with SCUpgradeFailReq\n"); 12311197Sandreas.hansson@arm.com } else if (pkt->cmd == MemCmd::StoreCondReq) { 12411601Sandreas.hansson@arm.com pkt->cmd = MemCmd::StoreCondFailReq; 12511601Sandreas.hansson@arm.com DPRINTF(Cache, "Replacing StoreCondReq with StoreCondFailReq\n"); 12611601Sandreas.hansson@arm.com } 12711601Sandreas.hansson@arm.com} 12811601Sandreas.hansson@arm.com 12911601Sandreas.hansson@arm.com 13011601Sandreas.hansson@arm.comvoid 13111601Sandreas.hansson@arm.comMSHR::TargetList::replaceUpgrades() 13211197Sandreas.hansson@arm.com{ 13311601Sandreas.hansson@arm.com if (!hasUpgrade) 13411601Sandreas.hansson@arm.com return; 13511601Sandreas.hansson@arm.com 13611601Sandreas.hansson@arm.com for (auto& t : *this) { 13711601Sandreas.hansson@arm.com replaceUpgrade(t.pkt); 13811601Sandreas.hansson@arm.com } 13911601Sandreas.hansson@arm.com 14011051Sandreas.hansson@arm.com hasUpgrade = false; 14111051Sandreas.hansson@arm.com} 14211051Sandreas.hansson@arm.com 14311051Sandreas.hansson@arm.com 14411051Sandreas.hansson@arm.comvoid 14511284Sandreas.hansson@arm.comMSHR::TargetList::clearDownstreamPending() 14611284Sandreas.hansson@arm.com{ 14711051Sandreas.hansson@arm.com for (auto& t : *this) { 14811051Sandreas.hansson@arm.com if (t.markedPending) { 14911051Sandreas.hansson@arm.com // Iterate over the SenderState stack and see if we find 15011051Sandreas.hansson@arm.com // an MSHR entry. If we find one, clear the 15111284Sandreas.hansson@arm.com // downstreamPending flag by calling 15211051Sandreas.hansson@arm.com // clearDownstreamPending(). This recursively clears the 15311051Sandreas.hansson@arm.com // downstreamPending flag in all caches this packet has 15411051Sandreas.hansson@arm.com // passed through. 15511051Sandreas.hansson@arm.com MSHR *mshr = t.pkt->findNextSenderState<MSHR>(); 15611051Sandreas.hansson@arm.com if (mshr != NULL) { 15711051Sandreas.hansson@arm.com mshr->clearDownstreamPending(); 15811051Sandreas.hansson@arm.com } 15911051Sandreas.hansson@arm.com } 16011051Sandreas.hansson@arm.com } 16111051Sandreas.hansson@arm.com} 16211051Sandreas.hansson@arm.com 16311051Sandreas.hansson@arm.com 16411051Sandreas.hansson@arm.combool 16511051Sandreas.hansson@arm.comMSHR::TargetList::checkFunctional(PacketPtr pkt) 16611051Sandreas.hansson@arm.com{ 16711051Sandreas.hansson@arm.com for (auto& t : *this) { 16811051Sandreas.hansson@arm.com if (pkt->checkFunctional(t.pkt)) { 16912724Snikos.nikoleris@arm.com return true; 17012724Snikos.nikoleris@arm.com } 17112724Snikos.nikoleris@arm.com } 17212724Snikos.nikoleris@arm.com 17312724Snikos.nikoleris@arm.com return false; 17412724Snikos.nikoleris@arm.com} 17512724Snikos.nikoleris@arm.com 17611051Sandreas.hansson@arm.com 17711051Sandreas.hansson@arm.comvoid 17811051Sandreas.hansson@arm.comMSHR::TargetList::print(std::ostream &os, int verbosity, 17911051Sandreas.hansson@arm.com const std::string &prefix) const 18012723Snikos.nikoleris@arm.com{ 18111051Sandreas.hansson@arm.com for (auto& t : *this) { 18211051Sandreas.hansson@arm.com const char *s; 18311484Snikos.nikoleris@arm.com switch (t.source) { 18411051Sandreas.hansson@arm.com case Target::FromCPU: 18511051Sandreas.hansson@arm.com s = "FromCPU"; 18611051Sandreas.hansson@arm.com break; 18711051Sandreas.hansson@arm.com case Target::FromSnoop: 18811051Sandreas.hansson@arm.com s = "FromSnoop"; 18912724Snikos.nikoleris@arm.com break; 19011601Sandreas.hansson@arm.com case Target::FromPrefetcher: 19111601Sandreas.hansson@arm.com s = "FromPrefetcher"; 19211601Sandreas.hansson@arm.com break; 19311051Sandreas.hansson@arm.com default: 19411051Sandreas.hansson@arm.com s = ""; 19511051Sandreas.hansson@arm.com break; 19611051Sandreas.hansson@arm.com } 19711051Sandreas.hansson@arm.com ccprintf(os, "%s%s: ", prefix, s); 19812345Snikos.nikoleris@arm.com t.pkt->print(os, verbosity, ""); 19912345Snikos.nikoleris@arm.com } 20012345Snikos.nikoleris@arm.com} 20112345Snikos.nikoleris@arm.com 20211051Sandreas.hansson@arm.com 20311051Sandreas.hansson@arm.comvoid 20411051Sandreas.hansson@arm.comMSHR::allocate(Addr blk_addr, unsigned blk_size, PacketPtr target, 20511051Sandreas.hansson@arm.com Tick when_ready, Counter _order) 20611051Sandreas.hansson@arm.com{ 20711051Sandreas.hansson@arm.com blkAddr = blk_addr; 20811051Sandreas.hansson@arm.com blkSize = blk_size; 20911199Sandreas.hansson@arm.com isSecure = target->isSecure(); 21011199Sandreas.hansson@arm.com readyTime = when_ready; 21111199Sandreas.hansson@arm.com order = _order; 21211199Sandreas.hansson@arm.com assert(target); 21311199Sandreas.hansson@arm.com isForward = false; 21411051Sandreas.hansson@arm.com _isUncacheable = target->req->isUncacheable(); 21512345Snikos.nikoleris@arm.com inService = false; 21612345Snikos.nikoleris@arm.com downstreamPending = false; 21711051Sandreas.hansson@arm.com threadNum = 0; 21811051Sandreas.hansson@arm.com assert(targets.isReset()); 21911051Sandreas.hansson@arm.com // Don't know of a case where we would allocate a new MSHR for a 22011051Sandreas.hansson@arm.com // snoop (mem-side request), so set source according to request here 22111051Sandreas.hansson@arm.com Target::Source source = (target->cmd == MemCmd::HardPFReq) ? 22211051Sandreas.hansson@arm.com Target::FromPrefetcher : Target::FromCPU; 22311051Sandreas.hansson@arm.com targets.add(target, when_ready, _order, source, true); 22411051Sandreas.hansson@arm.com assert(deferredTargets.isReset()); 22511051Sandreas.hansson@arm.com data = NULL; 22611051Sandreas.hansson@arm.com} 22711051Sandreas.hansson@arm.com 22811051Sandreas.hansson@arm.com 22911051Sandreas.hansson@arm.comvoid 23011051Sandreas.hansson@arm.comMSHR::clearDownstreamPending() 23111051Sandreas.hansson@arm.com{ 23211051Sandreas.hansson@arm.com assert(downstreamPending); 23311051Sandreas.hansson@arm.com downstreamPending = false; 23411130Sali.jafri@arm.com // recursively clear flag on any MSHRs we will be forwarding 23511130Sali.jafri@arm.com // responses to 23611130Sali.jafri@arm.com targets.clearDownstreamPending(); 23711130Sali.jafri@arm.com} 23811130Sali.jafri@arm.com 23911130Sali.jafri@arm.combool 24011130Sali.jafri@arm.comMSHR::markInService(bool pending_dirty_resp) 24111130Sali.jafri@arm.com{ 24211130Sali.jafri@arm.com assert(!inService); 24312345Snikos.nikoleris@arm.com if (isForwardNoResponse()) { 24412345Snikos.nikoleris@arm.com // we just forwarded the request packet & don't expect a 24511130Sali.jafri@arm.com // response, so get rid of it 24611130Sali.jafri@arm.com assert(getNumTargets() == 1); 24711130Sali.jafri@arm.com popTarget(); 24811130Sali.jafri@arm.com return true; 24911130Sali.jafri@arm.com } 25011130Sali.jafri@arm.com 25112724Snikos.nikoleris@arm.com inService = true; 25211130Sali.jafri@arm.com pendingDirty = targets.needsExclusive || pending_dirty_resp; 25311130Sali.jafri@arm.com postInvalidate = postDowngrade = false; 25411130Sali.jafri@arm.com 25511130Sali.jafri@arm.com if (!downstreamPending) { 25611130Sali.jafri@arm.com // let upstream caches know that the request has made it to a 25711130Sali.jafri@arm.com // level where it's going to get a response 25812724Snikos.nikoleris@arm.com targets.clearDownstreamPending(); 25911130Sali.jafri@arm.com } 26011130Sali.jafri@arm.com return false; 26111130Sali.jafri@arm.com} 26211130Sali.jafri@arm.com 26311130Sali.jafri@arm.com 26411130Sali.jafri@arm.comvoid 26511130Sali.jafri@arm.comMSHR::deallocate() 26611130Sali.jafri@arm.com{ 26711130Sali.jafri@arm.com assert(targets.empty()); 26811051Sandreas.hansson@arm.com targets.resetFlags(); 26911051Sandreas.hansson@arm.com assert(deferredTargets.isReset()); 27011051Sandreas.hansson@arm.com inService = false; 27111051Sandreas.hansson@arm.com} 27211744Snikos.nikoleris@arm.com 27311051Sandreas.hansson@arm.com/* 27411276Sandreas.hansson@arm.com * Adds a target to an MSHR 27511276Sandreas.hansson@arm.com */ 27611276Sandreas.hansson@arm.comvoid 27711276Sandreas.hansson@arm.comMSHR::allocateTarget(PacketPtr pkt, Tick whenReady, Counter _order) 27811276Sandreas.hansson@arm.com{ 27911276Sandreas.hansson@arm.com // assume we'd never issue a prefetch when we've got an 28011276Sandreas.hansson@arm.com // outstanding miss 28111276Sandreas.hansson@arm.com assert(pkt->cmd != MemCmd::HardPFReq); 28211276Sandreas.hansson@arm.com 28311051Sandreas.hansson@arm.com // uncacheable accesses always allocate a new MSHR, and cacheable 28411276Sandreas.hansson@arm.com // accesses ignore any uncacheable MSHRs, thus we should never 28511276Sandreas.hansson@arm.com // have targets addded if originally allocated uncacheable 28611276Sandreas.hansson@arm.com assert(!_isUncacheable); 28711276Sandreas.hansson@arm.com 28811276Sandreas.hansson@arm.com // if there's a request already in service for this MSHR, we will 28911051Sandreas.hansson@arm.com // have to defer the new target until after the response if any of 29011051Sandreas.hansson@arm.com // the following are true: 29111051Sandreas.hansson@arm.com // - there are other targets already deferred 29211051Sandreas.hansson@arm.com // - there's a pending invalidate to be applied after the response 29311051Sandreas.hansson@arm.com // comes back (but before this target is processed) 29411051Sandreas.hansson@arm.com // - this target requires an exclusive block and either we're not 29511051Sandreas.hansson@arm.com // getting an exclusive block back or we have already snooped 29611051Sandreas.hansson@arm.com // another read request that will downgrade our exclusive block 29711051Sandreas.hansson@arm.com // to shared 29811051Sandreas.hansson@arm.com if (inService && 29911051Sandreas.hansson@arm.com (!deferredTargets.empty() || hasPostInvalidate() || 30012724Snikos.nikoleris@arm.com (pkt->needsExclusive() && 30111051Sandreas.hansson@arm.com (!isPendingDirty() || hasPostDowngrade() || isForward)))) { 30211051Sandreas.hansson@arm.com // need to put on deferred list 30311051Sandreas.hansson@arm.com if (hasPostInvalidate()) 30411051Sandreas.hansson@arm.com replaceUpgrade(pkt); 30511051Sandreas.hansson@arm.com deferredTargets.add(pkt, whenReady, _order, Target::FromCPU, true); 30611051Sandreas.hansson@arm.com } else { 30711051Sandreas.hansson@arm.com // No request outstanding, or still OK to append to 30811051Sandreas.hansson@arm.com // outstanding request: append to regular target list. Only 30911051Sandreas.hansson@arm.com // mark pending if current request hasn't been issued yet 31011051Sandreas.hansson@arm.com // (isn't in service). 31111051Sandreas.hansson@arm.com targets.add(pkt, whenReady, _order, Target::FromCPU, !inService); 31211051Sandreas.hansson@arm.com } 31311051Sandreas.hansson@arm.com} 31412630Snikos.nikoleris@arm.com 31512720Snikos.nikoleris@arm.combool 31612720Snikos.nikoleris@arm.comMSHR::handleSnoop(PacketPtr pkt, Counter _order) 31712720Snikos.nikoleris@arm.com{ 31812720Snikos.nikoleris@arm.com DPRINTF(Cache, "%s for %s addr %#llx size %d\n", __func__, 31912720Snikos.nikoleris@arm.com pkt->cmdString(), pkt->getAddr(), pkt->getSize()); 32012720Snikos.nikoleris@arm.com if (!inService || (pkt->isExpressSnoop() && downstreamPending)) { 32112720Snikos.nikoleris@arm.com // Request has not been issued yet, or it's been issued 32212724Snikos.nikoleris@arm.com // locally but is buffered unissued at some downstream cache 32312720Snikos.nikoleris@arm.com // which is forwarding us this snoop. Either way, the packet 32412720Snikos.nikoleris@arm.com // we're snooping logically precedes this MSHR's request, so 32512720Snikos.nikoleris@arm.com // the snoop has no impact on the MSHR, but must be processed 32612720Snikos.nikoleris@arm.com // in the standard way by the cache. The only exception is 32712720Snikos.nikoleris@arm.com // that if we're an L2+ cache buffering an UpgradeReq from a 32812720Snikos.nikoleris@arm.com // higher-level cache, and the snoop is invalidating, then our 32912724Snikos.nikoleris@arm.com // buffered upgrades must be converted to read exclusives, 33012724Snikos.nikoleris@arm.com // since the upper-level cache no longer has a valid copy. 33112724Snikos.nikoleris@arm.com // That is, even though the upper-level cache got out on its 33212724Snikos.nikoleris@arm.com // local bus first, some other invalidating transaction 33312724Snikos.nikoleris@arm.com // reached the global bus before the upgrade did. 33412724Snikos.nikoleris@arm.com if (pkt->needsExclusive()) { 33512724Snikos.nikoleris@arm.com targets.replaceUpgrades(); 33612724Snikos.nikoleris@arm.com deferredTargets.replaceUpgrades(); 33712724Snikos.nikoleris@arm.com } 33812724Snikos.nikoleris@arm.com 33912724Snikos.nikoleris@arm.com return false; 34012724Snikos.nikoleris@arm.com } 34112724Snikos.nikoleris@arm.com 34212724Snikos.nikoleris@arm.com // From here on down, the request issued by this MSHR logically 34312724Snikos.nikoleris@arm.com // precedes the request we're snooping. 34412724Snikos.nikoleris@arm.com if (pkt->needsExclusive()) { 34512724Snikos.nikoleris@arm.com // snooped request still precedes the re-request we'll have to 34612724Snikos.nikoleris@arm.com // issue for deferred targets, if any... 34712724Snikos.nikoleris@arm.com deferredTargets.replaceUpgrades(); 34812724Snikos.nikoleris@arm.com } 34912724Snikos.nikoleris@arm.com 35012724Snikos.nikoleris@arm.com if (hasPostInvalidate()) { 35112724Snikos.nikoleris@arm.com // a prior snoop has already appended an invalidation, so 35212724Snikos.nikoleris@arm.com // logically we don't have the block anymore; no need for 35312724Snikos.nikoleris@arm.com // further snooping. 35412720Snikos.nikoleris@arm.com return true; 35512720Snikos.nikoleris@arm.com } 35612724Snikos.nikoleris@arm.com 35712720Snikos.nikoleris@arm.com if (isPendingDirty() || pkt->isInvalidate()) { 35812720Snikos.nikoleris@arm.com // We need to save and replay the packet in two cases: 35912720Snikos.nikoleris@arm.com // 1. We're awaiting an exclusive copy, so ownership is pending, 36012720Snikos.nikoleris@arm.com // and we need to respond after we receive data. 36112720Snikos.nikoleris@arm.com // 2. It's an invalidation (e.g., UpgradeReq), and we need 36212720Snikos.nikoleris@arm.com // to forward the snoop up the hierarchy after the current 36312720Snikos.nikoleris@arm.com // transaction completes. 36412720Snikos.nikoleris@arm.com 36512720Snikos.nikoleris@arm.com // Actual target device (typ. a memory) will delete the 36612720Snikos.nikoleris@arm.com // packet on reception, so we need to save a copy here. 36712720Snikos.nikoleris@arm.com 36812720Snikos.nikoleris@arm.com // Clear flags and also allocate new data as the original 36912720Snikos.nikoleris@arm.com // packet data storage may have been deleted by the time we 37012720Snikos.nikoleris@arm.com // get to send this packet. 37112720Snikos.nikoleris@arm.com PacketPtr cp_pkt = nullptr; 37212720Snikos.nikoleris@arm.com 37312720Snikos.nikoleris@arm.com if (isPendingDirty()) { 37412720Snikos.nikoleris@arm.com // Case 1: The new packet will need to get the response from the 37512720Snikos.nikoleris@arm.com // MSHR already queued up here 37612720Snikos.nikoleris@arm.com cp_pkt = new Packet(pkt, true, true); 37712720Snikos.nikoleris@arm.com pkt->assertMemInhibit(); 37812720Snikos.nikoleris@arm.com // in the case of an uncacheable request there is no need 37912720Snikos.nikoleris@arm.com // to set the exclusive flag, but since the recipient does 38012749Sgiacomo.travaglini@arm.com // not care there is no harm in doing so 38112749Sgiacomo.travaglini@arm.com pkt->setSupplyExclusive(); 38212749Sgiacomo.travaglini@arm.com } else { 38312749Sgiacomo.travaglini@arm.com // Case 2: We only need to buffer the packet for information 38412720Snikos.nikoleris@arm.com // purposes; the original request can proceed without waiting 38512720Snikos.nikoleris@arm.com // => Create a copy of the request, as that may get deallocated as 38612720Snikos.nikoleris@arm.com // well 38712720Snikos.nikoleris@arm.com cp_pkt = new Packet(new Request(*pkt->req), pkt->cmd); 38812720Snikos.nikoleris@arm.com DPRINTF(Cache, "Copying packet %p -> %p and request %p -> %p\n", 38912720Snikos.nikoleris@arm.com pkt, cp_pkt, pkt->req, cp_pkt->req); 39012720Snikos.nikoleris@arm.com } 39112720Snikos.nikoleris@arm.com targets.add(cp_pkt, curTick(), _order, Target::FromSnoop, 39212720Snikos.nikoleris@arm.com downstreamPending && targets.needsExclusive); 39312720Snikos.nikoleris@arm.com 39412724Snikos.nikoleris@arm.com if (pkt->needsExclusive()) { 39512720Snikos.nikoleris@arm.com // This transaction will take away our pending copy 39612720Snikos.nikoleris@arm.com postInvalidate = true; 39712720Snikos.nikoleris@arm.com } 39812720Snikos.nikoleris@arm.com } 39912720Snikos.nikoleris@arm.com 40012720Snikos.nikoleris@arm.com if (!pkt->needsExclusive() && !pkt->req->isUncacheable()) { 40112724Snikos.nikoleris@arm.com // This transaction will get a read-shared copy, downgrading 40212720Snikos.nikoleris@arm.com // our copy if we had an exclusive one 40312720Snikos.nikoleris@arm.com postDowngrade = true; 40412720Snikos.nikoleris@arm.com pkt->assertShared(); 40511051Sandreas.hansson@arm.com } 40611051Sandreas.hansson@arm.com 40711830Sbaz21@cam.ac.uk return true; 40811051Sandreas.hansson@arm.com} 40911051Sandreas.hansson@arm.com 41011051Sandreas.hansson@arm.com 41111284Sandreas.hansson@arm.combool 41211051Sandreas.hansson@arm.comMSHR::promoteDeferredTargets() 41311284Sandreas.hansson@arm.com{ 41411284Sandreas.hansson@arm.com assert(targets.empty()); 41511744Snikos.nikoleris@arm.com if (deferredTargets.empty()) { 41611744Snikos.nikoleris@arm.com return false; 41711051Sandreas.hansson@arm.com } 41811284Sandreas.hansson@arm.com 41911284Sandreas.hansson@arm.com // swap targets & deferredTargets lists 42011284Sandreas.hansson@arm.com std::swap(targets, deferredTargets); 42111284Sandreas.hansson@arm.com 42211284Sandreas.hansson@arm.com // clear deferredTargets flags 42311334Sandreas.hansson@arm.com deferredTargets.resetFlags(); 42411284Sandreas.hansson@arm.com 42511334Sandreas.hansson@arm.com order = targets.front().order; 42611334Sandreas.hansson@arm.com readyTime = std::max(curTick(), targets.front().readyTime); 42711334Sandreas.hansson@arm.com 42811334Sandreas.hansson@arm.com return true; 42911284Sandreas.hansson@arm.com} 43011334Sandreas.hansson@arm.com 43111334Sandreas.hansson@arm.com 43211334Sandreas.hansson@arm.comvoid 43311334Sandreas.hansson@arm.comMSHR::promoteExclusive() 43411334Sandreas.hansson@arm.com{ 43511334Sandreas.hansson@arm.com if (deferredTargets.needsExclusive && 43611051Sandreas.hansson@arm.com !(hasPostInvalidate() || hasPostDowngrade())) { 43711334Sandreas.hansson@arm.com // We got an exclusive response, but we have deferred targets 43811334Sandreas.hansson@arm.com // which are waiting to request an exclusive copy (not because 43911334Sandreas.hansson@arm.com // of a pending invalidate). This can happen if the original 44011334Sandreas.hansson@arm.com // request was for a read-only (non-exclusive) block, but we 44111051Sandreas.hansson@arm.com // got an exclusive copy anyway because of the E part of the 44211334Sandreas.hansson@arm.com // MOESI/MESI protocol. Since we got the exclusive copy 44311334Sandreas.hansson@arm.com // there's no need to defer the targets, so move them up to 44411334Sandreas.hansson@arm.com // the regular target list. 44511051Sandreas.hansson@arm.com assert(!targets.needsExclusive); 44611334Sandreas.hansson@arm.com targets.needsExclusive = true; 44711334Sandreas.hansson@arm.com // if any of the deferred targets were upper-level cache 44811334Sandreas.hansson@arm.com // requests marked downstreamPending, need to clear that 44911334Sandreas.hansson@arm.com assert(!downstreamPending); // not pending here anymore 45011334Sandreas.hansson@arm.com deferredTargets.clearDownstreamPending(); 45111334Sandreas.hansson@arm.com // this clears out deferredTargets too 45211334Sandreas.hansson@arm.com targets.splice(targets.end(), deferredTargets); 45311051Sandreas.hansson@arm.com deferredTargets.resetFlags(); 45411334Sandreas.hansson@arm.com } 45511334Sandreas.hansson@arm.com} 45611334Sandreas.hansson@arm.com 45712724Snikos.nikoleris@arm.com 45811334Sandreas.hansson@arm.combool 45911334Sandreas.hansson@arm.comMSHR::checkFunctional(PacketPtr pkt) 46011334Sandreas.hansson@arm.com{ 46111334Sandreas.hansson@arm.com // For printing, we treat the MSHR as a whole as single entity. 46211051Sandreas.hansson@arm.com // For other requests, we iterate over the individual targets 46311284Sandreas.hansson@arm.com // since that's where the actual data lies. 46411284Sandreas.hansson@arm.com if (pkt->isPrint()) { 46511190Sandreas.hansson@arm.com pkt->checkFunctional(this, blkAddr, isSecure, blkSize, NULL); 46611051Sandreas.hansson@arm.com return false; 46711334Sandreas.hansson@arm.com } else { 46811334Sandreas.hansson@arm.com return (targets.checkFunctional(pkt) || 46911334Sandreas.hansson@arm.com deferredTargets.checkFunctional(pkt)); 47011334Sandreas.hansson@arm.com } 47111334Sandreas.hansson@arm.com} 47212630Snikos.nikoleris@arm.com 47311051Sandreas.hansson@arm.com 47411051Sandreas.hansson@arm.comvoid 47512724Snikos.nikoleris@arm.comMSHR::print(std::ostream &os, int verbosity, const std::string &prefix) const 47611051Sandreas.hansson@arm.com{ 47711051Sandreas.hansson@arm.com ccprintf(os, "%s[%#llx:%#llx](%s) %s %s %s state: %s %s %s %s %s\n", 47811051Sandreas.hansson@arm.com prefix, blkAddr, blkAddr + blkSize - 1, 47911452Sandreas.hansson@arm.com isSecure ? "s" : "ns", 48013350Snikos.nikoleris@arm.com isForward ? "Forward" : "", 48113350Snikos.nikoleris@arm.com isForwardNoResponse() ? "ForwNoResp" : "", 48211051Sandreas.hansson@arm.com needsExclusive() ? "Excl" : "", 48311452Sandreas.hansson@arm.com _isUncacheable ? "Unc" : "", 48411452Sandreas.hansson@arm.com inService ? "InSvc" : "", 48511452Sandreas.hansson@arm.com downstreamPending ? "DwnPend" : "", 48611051Sandreas.hansson@arm.com hasPostInvalidate() ? "PostInv" : "", 48711051Sandreas.hansson@arm.com hasPostDowngrade() ? "PostDowngr" : ""); 48811452Sandreas.hansson@arm.com 48911745Sandreas.hansson@arm.com ccprintf(os, "%s Targets:\n", prefix); 49012349Snikos.nikoleris@arm.com targets.print(os, verbosity, prefix + " "); 49111452Sandreas.hansson@arm.com if (!deferredTargets.empty()) { 49211452Sandreas.hansson@arm.com ccprintf(os, "%s Deferred Targets:\n", prefix); 49311452Sandreas.hansson@arm.com deferredTargets.print(os, verbosity, prefix + " "); 49411051Sandreas.hansson@arm.com } 49511051Sandreas.hansson@arm.com} 49611051Sandreas.hansson@arm.com 49711051Sandreas.hansson@arm.comstd::string 49811051Sandreas.hansson@arm.comMSHR::print() const 49911051Sandreas.hansson@arm.com{ 50011051Sandreas.hansson@arm.com ostringstream str; 50111051Sandreas.hansson@arm.com print(str); 50211051Sandreas.hansson@arm.com return str.str(); 50311051Sandreas.hansson@arm.com} 50413350Snikos.nikoleris@arm.com