mshr.cc revision 11083:61b329833f74
110066Sandreas.hansson@arm.com/* 210066Sandreas.hansson@arm.com * Copyright (c) 2012-2013, 2015 ARM Limited 310066Sandreas.hansson@arm.com * All rights reserved. 410066Sandreas.hansson@arm.com * 510066Sandreas.hansson@arm.com * The license below extends only to copyright in the software and shall 610066Sandreas.hansson@arm.com * not be construed as granting a license to any other intellectual 710066Sandreas.hansson@arm.com * property including but not limited to intellectual property relating 810066Sandreas.hansson@arm.com * to a hardware implementation of the functionality of the software 910066Sandreas.hansson@arm.com * licensed hereunder. You may use the software subject to the license 1010066Sandreas.hansson@arm.com * terms below provided that you ensure that this notice is replicated 1110066Sandreas.hansson@arm.com * unmodified and in its entirety in all distributions of the software, 1210066Sandreas.hansson@arm.com * modified or unmodified, in source code or in binary form. 1310066Sandreas.hansson@arm.com * 1410066Sandreas.hansson@arm.com * Copyright (c) 2002-2005 The Regents of The University of Michigan 1510066Sandreas.hansson@arm.com * Copyright (c) 2010 Advanced Micro Devices, Inc. 1610066Sandreas.hansson@arm.com * All rights reserved. 1710066Sandreas.hansson@arm.com * 1810066Sandreas.hansson@arm.com * Redistribution and use in source and binary forms, with or without 1910066Sandreas.hansson@arm.com * modification, are permitted provided that the following conditions are 2010066Sandreas.hansson@arm.com * met: redistributions of source code must retain the above copyright 2110066Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer; 2210066Sandreas.hansson@arm.com * redistributions in binary form must reproduce the above copyright 2310066Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer in the 2410066Sandreas.hansson@arm.com * documentation and/or other materials provided with the distribution; 2510066Sandreas.hansson@arm.com * neither the name of the copyright holders nor the names of its 2610066Sandreas.hansson@arm.com * contributors may be used to endorse or promote products derived from 2710066Sandreas.hansson@arm.com * this software without specific prior written permission. 2810066Sandreas.hansson@arm.com * 2910066Sandreas.hansson@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 3010066Sandreas.hansson@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 3110066Sandreas.hansson@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 3210066Sandreas.hansson@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 3310066Sandreas.hansson@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 3410066Sandreas.hansson@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 3510066Sandreas.hansson@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 3610066Sandreas.hansson@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 3710066Sandreas.hansson@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3810066Sandreas.hansson@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 3910066Sandreas.hansson@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 4010066Sandreas.hansson@arm.com * 4110066Sandreas.hansson@arm.com * Authors: Erik Hallnor 4210066Sandreas.hansson@arm.com * Dave Greene 4310066Sandreas.hansson@arm.com */ 4410066Sandreas.hansson@arm.com 4510066Sandreas.hansson@arm.com/** 4610066Sandreas.hansson@arm.com * @file 4710066Sandreas.hansson@arm.com * Miss Status and Handling Register (MSHR) definitions. 4810066Sandreas.hansson@arm.com */ 4910066Sandreas.hansson@arm.com 5010066Sandreas.hansson@arm.com#include <algorithm> 5110066Sandreas.hansson@arm.com#include <cassert> 5210066Sandreas.hansson@arm.com#include <string> 5310296Sandreas.hansson@arm.com#include <vector> 5410066Sandreas.hansson@arm.com 5510066Sandreas.hansson@arm.com#include "base/misc.hh" 5610066Sandreas.hansson@arm.com#include "base/types.hh" 5710066Sandreas.hansson@arm.com#include "debug/Cache.hh" 5810066Sandreas.hansson@arm.com#include "mem/cache/cache.hh" 5910066Sandreas.hansson@arm.com#include "mem/cache/mshr.hh" 6010066Sandreas.hansson@arm.com#include "sim/core.hh" 6110066Sandreas.hansson@arm.com 6210066Sandreas.hansson@arm.comusing namespace std; 6310066Sandreas.hansson@arm.com 6410066Sandreas.hansson@arm.comMSHR::MSHR() : readyTime(0), _isUncacheable(false), downstreamPending(false), 6510066Sandreas.hansson@arm.com pendingDirty(false), 6610066Sandreas.hansson@arm.com postInvalidate(false), postDowngrade(false), 6710066Sandreas.hansson@arm.com queue(NULL), order(0), blkAddr(0), 6810066Sandreas.hansson@arm.com blkSize(0), isSecure(false), inService(false), 6910066Sandreas.hansson@arm.com isForward(false), threadNum(InvalidThreadID), data(NULL) 7010066Sandreas.hansson@arm.com{ 7110066Sandreas.hansson@arm.com} 7210066Sandreas.hansson@arm.com 7310066Sandreas.hansson@arm.com 7410066Sandreas.hansson@arm.comMSHR::TargetList::TargetList() 7510066Sandreas.hansson@arm.com : needsExclusive(false), hasUpgrade(false) 7610066Sandreas.hansson@arm.com{} 7710066Sandreas.hansson@arm.com 7810066Sandreas.hansson@arm.com 7910466Sandreas.hansson@arm.cominline void 8010466Sandreas.hansson@arm.comMSHR::TargetList::add(PacketPtr pkt, Tick readyTime, 8110066Sandreas.hansson@arm.com Counter order, Target::Source source, bool markPending) 8210066Sandreas.hansson@arm.com{ 8310066Sandreas.hansson@arm.com if (source != Target::FromSnoop) { 8410066Sandreas.hansson@arm.com if (pkt->needsExclusive()) { 8510066Sandreas.hansson@arm.com needsExclusive = true; 8610066Sandreas.hansson@arm.com } 8710066Sandreas.hansson@arm.com 8810066Sandreas.hansson@arm.com // StoreCondReq is effectively an upgrade if it's in an MSHR 8910066Sandreas.hansson@arm.com // since it would have been failed already if we didn't have a 9010066Sandreas.hansson@arm.com // read-only copy 9110066Sandreas.hansson@arm.com if (pkt->isUpgrade() || pkt->cmd == MemCmd::StoreCondReq) { 9210066Sandreas.hansson@arm.com hasUpgrade = true; 9310066Sandreas.hansson@arm.com } 9410066Sandreas.hansson@arm.com } 9510296Sandreas.hansson@arm.com 9610296Sandreas.hansson@arm.com if (markPending) { 9710066Sandreas.hansson@arm.com // Iterate over the SenderState stack and see if we find 9810066Sandreas.hansson@arm.com // an MSHR entry. If we do, set the downstreamPending 9910066Sandreas.hansson@arm.com // flag. Otherwise, do nothing. 10010066Sandreas.hansson@arm.com MSHR *mshr = pkt->findNextSenderState<MSHR>(); 10110066Sandreas.hansson@arm.com if (mshr != NULL) { 10210066Sandreas.hansson@arm.com assert(!mshr->downstreamPending); 10310066Sandreas.hansson@arm.com mshr->downstreamPending = true; 10410066Sandreas.hansson@arm.com } else { 10510066Sandreas.hansson@arm.com // No need to clear downstreamPending later 10610066Sandreas.hansson@arm.com markPending = false; 10710066Sandreas.hansson@arm.com } 10810066Sandreas.hansson@arm.com } 10910066Sandreas.hansson@arm.com 11010066Sandreas.hansson@arm.com emplace_back(pkt, readyTime, order, source, markPending); 11110066Sandreas.hansson@arm.com} 11210066Sandreas.hansson@arm.com 11310066Sandreas.hansson@arm.com 11410066Sandreas.hansson@arm.comstatic void 11510066Sandreas.hansson@arm.comreplaceUpgrade(PacketPtr pkt) 11610066Sandreas.hansson@arm.com{ 11710066Sandreas.hansson@arm.com if (pkt->cmd == MemCmd::UpgradeReq) { 11810066Sandreas.hansson@arm.com pkt->cmd = MemCmd::ReadExReq; 11910066Sandreas.hansson@arm.com DPRINTF(Cache, "Replacing UpgradeReq with ReadExReq\n"); 12010913Sandreas.sandberg@arm.com } else if (pkt->cmd == MemCmd::SCUpgradeReq) { 12110913Sandreas.sandberg@arm.com pkt->cmd = MemCmd::SCUpgradeFailReq; 12210066Sandreas.hansson@arm.com DPRINTF(Cache, "Replacing SCUpgradeReq with SCUpgradeFailReq\n"); 12310066Sandreas.hansson@arm.com } else if (pkt->cmd == MemCmd::StoreCondReq) { 12410066Sandreas.hansson@arm.com pkt->cmd = MemCmd::StoreCondFailReq; 12510066Sandreas.hansson@arm.com DPRINTF(Cache, "Replacing StoreCondReq with StoreCondFailReq\n"); 12610066Sandreas.hansson@arm.com } 12710066Sandreas.hansson@arm.com} 12810066Sandreas.hansson@arm.com 12910066Sandreas.hansson@arm.com 13010066Sandreas.hansson@arm.comvoid 13110066Sandreas.hansson@arm.comMSHR::TargetList::replaceUpgrades() 13210066Sandreas.hansson@arm.com{ 13310066Sandreas.hansson@arm.com if (!hasUpgrade) 13410066Sandreas.hansson@arm.com return; 13510066Sandreas.hansson@arm.com 13610066Sandreas.hansson@arm.com for (auto& t : *this) { 13710066Sandreas.hansson@arm.com replaceUpgrade(t.pkt); 13810066Sandreas.hansson@arm.com } 13910066Sandreas.hansson@arm.com 14010066Sandreas.hansson@arm.com hasUpgrade = false; 14110066Sandreas.hansson@arm.com} 14210066Sandreas.hansson@arm.com 14310066Sandreas.hansson@arm.com 14410066Sandreas.hansson@arm.comvoid 14510066Sandreas.hansson@arm.comMSHR::TargetList::clearDownstreamPending() 14610713Sandreas.hansson@arm.com{ 14710066Sandreas.hansson@arm.com for (auto& t : *this) { 14810066Sandreas.hansson@arm.com if (t.markedPending) { 14910066Sandreas.hansson@arm.com // Iterate over the SenderState stack and see if we find 15010066Sandreas.hansson@arm.com // an MSHR entry. If we find one, clear the 15110066Sandreas.hansson@arm.com // downstreamPending flag by calling 15210066Sandreas.hansson@arm.com // clearDownstreamPending(). This recursively clears the 15310066Sandreas.hansson@arm.com // downstreamPending flag in all caches this packet has 15410066Sandreas.hansson@arm.com // passed through. 15510066Sandreas.hansson@arm.com MSHR *mshr = t.pkt->findNextSenderState<MSHR>(); 15610066Sandreas.hansson@arm.com if (mshr != NULL) { 15710066Sandreas.hansson@arm.com mshr->clearDownstreamPending(); 15810066Sandreas.hansson@arm.com } 15910066Sandreas.hansson@arm.com } 16010066Sandreas.hansson@arm.com } 16110066Sandreas.hansson@arm.com} 16210066Sandreas.hansson@arm.com 16310066Sandreas.hansson@arm.com 16410066Sandreas.hansson@arm.combool 16510066Sandreas.hansson@arm.comMSHR::TargetList::checkFunctional(PacketPtr pkt) 16610066Sandreas.hansson@arm.com{ 16710066Sandreas.hansson@arm.com for (auto& t : *this) { 16810066Sandreas.hansson@arm.com if (pkt->checkFunctional(t.pkt)) { 16910066Sandreas.hansson@arm.com return true; 17010066Sandreas.hansson@arm.com } 17110066Sandreas.hansson@arm.com } 17210066Sandreas.hansson@arm.com 17310066Sandreas.hansson@arm.com return false; 17410066Sandreas.hansson@arm.com} 17510066Sandreas.hansson@arm.com 17610066Sandreas.hansson@arm.com 17710066Sandreas.hansson@arm.comvoid 17810066Sandreas.hansson@arm.comMSHR::TargetList::print(std::ostream &os, int verbosity, 17910066Sandreas.hansson@arm.com const std::string &prefix) const 18010066Sandreas.hansson@arm.com{ 18110066Sandreas.hansson@arm.com for (auto& t : *this) { 18210066Sandreas.hansson@arm.com const char *s; 18310066Sandreas.hansson@arm.com switch (t.source) { 18410066Sandreas.hansson@arm.com case Target::FromCPU: 18510066Sandreas.hansson@arm.com s = "FromCPU"; 18610066Sandreas.hansson@arm.com break; 18710066Sandreas.hansson@arm.com case Target::FromSnoop: 18810066Sandreas.hansson@arm.com s = "FromSnoop"; 18910066Sandreas.hansson@arm.com break; 19010066Sandreas.hansson@arm.com case Target::FromPrefetcher: 19110066Sandreas.hansson@arm.com s = "FromPrefetcher"; 19210066Sandreas.hansson@arm.com break; 19310066Sandreas.hansson@arm.com default: 19410066Sandreas.hansson@arm.com s = ""; 19510066Sandreas.hansson@arm.com break; 19610066Sandreas.hansson@arm.com } 19710066Sandreas.hansson@arm.com ccprintf(os, "%s%s: ", prefix, s); 19810066Sandreas.hansson@arm.com t.pkt->print(os, verbosity, ""); 19910066Sandreas.hansson@arm.com } 20010066Sandreas.hansson@arm.com} 20110066Sandreas.hansson@arm.com 20210066Sandreas.hansson@arm.com 20310066Sandreas.hansson@arm.comvoid 20410066Sandreas.hansson@arm.comMSHR::allocate(Addr blk_addr, unsigned blk_size, PacketPtr target, 20510066Sandreas.hansson@arm.com Tick when_ready, Counter _order) 20610066Sandreas.hansson@arm.com{ 20710066Sandreas.hansson@arm.com blkAddr = blk_addr; 20810066Sandreas.hansson@arm.com blkSize = blk_size; 20910066Sandreas.hansson@arm.com isSecure = target->isSecure(); 21010066Sandreas.hansson@arm.com readyTime = when_ready; 21110066Sandreas.hansson@arm.com order = _order; 21210066Sandreas.hansson@arm.com assert(target); 21310066Sandreas.hansson@arm.com isForward = false; 21410066Sandreas.hansson@arm.com _isUncacheable = target->req->isUncacheable(); 21510066Sandreas.hansson@arm.com inService = false; 21610066Sandreas.hansson@arm.com downstreamPending = false; 21710066Sandreas.hansson@arm.com threadNum = 0; 21810066Sandreas.hansson@arm.com assert(targets.isReset()); 21910066Sandreas.hansson@arm.com // Don't know of a case where we would allocate a new MSHR for a 22010066Sandreas.hansson@arm.com // snoop (mem-side request), so set source according to request here 22110066Sandreas.hansson@arm.com Target::Source source = (target->cmd == MemCmd::HardPFReq) ? 22210066Sandreas.hansson@arm.com Target::FromPrefetcher : Target::FromCPU; 22310066Sandreas.hansson@arm.com targets.add(target, when_ready, _order, source, true); 22410066Sandreas.hansson@arm.com assert(deferredTargets.isReset()); 22510066Sandreas.hansson@arm.com data = NULL; 22610066Sandreas.hansson@arm.com} 22710066Sandreas.hansson@arm.com 22810066Sandreas.hansson@arm.com 22910066Sandreas.hansson@arm.comvoid 23010066Sandreas.hansson@arm.comMSHR::clearDownstreamPending() 23110066Sandreas.hansson@arm.com{ 23210066Sandreas.hansson@arm.com assert(downstreamPending); 23310066Sandreas.hansson@arm.com downstreamPending = false; 23410066Sandreas.hansson@arm.com // recursively clear flag on any MSHRs we will be forwarding 23510066Sandreas.hansson@arm.com // responses to 23610066Sandreas.hansson@arm.com targets.clearDownstreamPending(); 23710066Sandreas.hansson@arm.com} 23810066Sandreas.hansson@arm.com 23910066Sandreas.hansson@arm.combool 24010066Sandreas.hansson@arm.comMSHR::markInService(bool pending_dirty_resp) 24110066Sandreas.hansson@arm.com{ 24210066Sandreas.hansson@arm.com assert(!inService); 24310713Sandreas.hansson@arm.com if (isForwardNoResponse()) { 24410066Sandreas.hansson@arm.com // we just forwarded the request packet & don't expect a 24510066Sandreas.hansson@arm.com // response, so get rid of it 24610066Sandreas.hansson@arm.com assert(getNumTargets() == 1); 24710066Sandreas.hansson@arm.com popTarget(); 24810066Sandreas.hansson@arm.com return true; 24910066Sandreas.hansson@arm.com } 25010066Sandreas.hansson@arm.com 25110066Sandreas.hansson@arm.com inService = true; 25210066Sandreas.hansson@arm.com pendingDirty = targets.needsExclusive || pending_dirty_resp; 25310066Sandreas.hansson@arm.com postInvalidate = postDowngrade = false; 25410066Sandreas.hansson@arm.com 25510066Sandreas.hansson@arm.com if (!downstreamPending) { 25610066Sandreas.hansson@arm.com // let upstream caches know that the request has made it to a 25710066Sandreas.hansson@arm.com // level where it's going to get a response 25810066Sandreas.hansson@arm.com targets.clearDownstreamPending(); 25910066Sandreas.hansson@arm.com } 26010066Sandreas.hansson@arm.com return false; 26110066Sandreas.hansson@arm.com} 26210066Sandreas.hansson@arm.com 26310066Sandreas.hansson@arm.com 26410066Sandreas.hansson@arm.comvoid 26510066Sandreas.hansson@arm.comMSHR::deallocate() 26610066Sandreas.hansson@arm.com{ 26710721SMarco.Balboni@ARM.com assert(targets.empty()); 26810721SMarco.Balboni@ARM.com targets.resetFlags(); 26910721SMarco.Balboni@ARM.com assert(deferredTargets.isReset()); 27010721SMarco.Balboni@ARM.com inService = false; 27110694SMarco.Balboni@ARM.com} 27210066Sandreas.hansson@arm.com 27310066Sandreas.hansson@arm.com/* 27410066Sandreas.hansson@arm.com * Adds a target to an MSHR 27510066Sandreas.hansson@arm.com */ 27610066Sandreas.hansson@arm.comvoid 27710066Sandreas.hansson@arm.comMSHR::allocateTarget(PacketPtr pkt, Tick whenReady, Counter _order) 27810066Sandreas.hansson@arm.com{ 27910066Sandreas.hansson@arm.com // assume we'd never issue a prefetch when we've got an 28010066Sandreas.hansson@arm.com // outstanding miss 28110066Sandreas.hansson@arm.com assert(pkt->cmd != MemCmd::HardPFReq); 28210721SMarco.Balboni@ARM.com 28310066Sandreas.hansson@arm.com // uncacheable accesses always allocate a new MSHR, and cacheable 28410066Sandreas.hansson@arm.com // accesses ignore any uncacheable MSHRs, thus we should never 28510066Sandreas.hansson@arm.com // have targets addded if originally allocated uncacheable 28610066Sandreas.hansson@arm.com assert(!_isUncacheable); 28710066Sandreas.hansson@arm.com 28810066Sandreas.hansson@arm.com // if there's a request already in service for this MSHR, we will 28910066Sandreas.hansson@arm.com // have to defer the new target until after the response if any of 29010066Sandreas.hansson@arm.com // the following are true: 29110066Sandreas.hansson@arm.com // - there are other targets already deferred 29210296Sandreas.hansson@arm.com // - there's a pending invalidate to be applied after the response 29310066Sandreas.hansson@arm.com // comes back (but before this target is processed) 29410066Sandreas.hansson@arm.com // - this target requires an exclusive block and either we're not 29510066Sandreas.hansson@arm.com // getting an exclusive block back or we have already snooped 29610066Sandreas.hansson@arm.com // another read request that will downgrade our exclusive block 29710066Sandreas.hansson@arm.com // to shared 29810066Sandreas.hansson@arm.com if (inService && 29910066Sandreas.hansson@arm.com (!deferredTargets.empty() || hasPostInvalidate() || 30010066Sandreas.hansson@arm.com (pkt->needsExclusive() && 30110066Sandreas.hansson@arm.com (!isPendingDirty() || hasPostDowngrade() || isForward)))) { 30210066Sandreas.hansson@arm.com // need to put on deferred list 30310066Sandreas.hansson@arm.com if (hasPostInvalidate()) 30410066Sandreas.hansson@arm.com replaceUpgrade(pkt); 30510066Sandreas.hansson@arm.com deferredTargets.add(pkt, whenReady, _order, Target::FromCPU, true); 30610066Sandreas.hansson@arm.com } else { 30710066Sandreas.hansson@arm.com // No request outstanding, or still OK to append to 30810066Sandreas.hansson@arm.com // outstanding request: append to regular target list. Only 30910066Sandreas.hansson@arm.com // mark pending if current request hasn't been issued yet 31010066Sandreas.hansson@arm.com // (isn't in service). 31110066Sandreas.hansson@arm.com targets.add(pkt, whenReady, _order, Target::FromCPU, !inService); 31210066Sandreas.hansson@arm.com } 31310066Sandreas.hansson@arm.com} 31410066Sandreas.hansson@arm.com 31510066Sandreas.hansson@arm.combool 31610066Sandreas.hansson@arm.comMSHR::handleSnoop(PacketPtr pkt, Counter _order) 31710066Sandreas.hansson@arm.com{ 31810066Sandreas.hansson@arm.com DPRINTF(Cache, "%s for %s addr %#llx size %d\n", __func__, 31910066Sandreas.hansson@arm.com pkt->cmdString(), pkt->getAddr(), pkt->getSize()); 32010296Sandreas.hansson@arm.com if (!inService || (pkt->isExpressSnoop() && downstreamPending)) { 32110066Sandreas.hansson@arm.com // Request has not been issued yet, or it's been issued 32210066Sandreas.hansson@arm.com // locally but is buffered unissued at some downstream cache 32310066Sandreas.hansson@arm.com // which is forwarding us this snoop. Either way, the packet 32410066Sandreas.hansson@arm.com // we're snooping logically precedes this MSHR's request, so 32510066Sandreas.hansson@arm.com // the snoop has no impact on the MSHR, but must be processed 32610066Sandreas.hansson@arm.com // in the standard way by the cache. The only exception is 32710066Sandreas.hansson@arm.com // that if we're an L2+ cache buffering an UpgradeReq from a 32810066Sandreas.hansson@arm.com // higher-level cache, and the snoop is invalidating, then our 32910066Sandreas.hansson@arm.com // buffered upgrades must be converted to read exclusives, 33010066Sandreas.hansson@arm.com // since the upper-level cache no longer has a valid copy. 33110066Sandreas.hansson@arm.com // That is, even though the upper-level cache got out on its 33210066Sandreas.hansson@arm.com // local bus first, some other invalidating transaction 33310066Sandreas.hansson@arm.com // reached the global bus before the upgrade did. 33410066Sandreas.hansson@arm.com if (pkt->needsExclusive()) { 33510066Sandreas.hansson@arm.com targets.replaceUpgrades(); 33610066Sandreas.hansson@arm.com deferredTargets.replaceUpgrades(); 33710066Sandreas.hansson@arm.com } 33810913Sandreas.sandberg@arm.com 33910913Sandreas.sandberg@arm.com return false; 34010066Sandreas.hansson@arm.com } 34110066Sandreas.hansson@arm.com 34210066Sandreas.hansson@arm.com // From here on down, the request issued by this MSHR logically 34310066Sandreas.hansson@arm.com // precedes the request we're snooping. 34410066Sandreas.hansson@arm.com if (pkt->needsExclusive()) { 34510066Sandreas.hansson@arm.com // snooped request still precedes the re-request we'll have to 34610066Sandreas.hansson@arm.com // issue for deferred targets, if any... 34710066Sandreas.hansson@arm.com deferredTargets.replaceUpgrades(); 34810066Sandreas.hansson@arm.com } 34910066Sandreas.hansson@arm.com 35010066Sandreas.hansson@arm.com if (hasPostInvalidate()) { 35110066Sandreas.hansson@arm.com // a prior snoop has already appended an invalidation, so 35210066Sandreas.hansson@arm.com // logically we don't have the block anymore; no need for 35310913Sandreas.sandberg@arm.com // further snooping. 35410066Sandreas.hansson@arm.com return true; 35510066Sandreas.hansson@arm.com } 35610066Sandreas.hansson@arm.com 35710913Sandreas.sandberg@arm.com if (isPendingDirty() || pkt->isInvalidate()) { 35810066Sandreas.hansson@arm.com // We need to save and replay the packet in two cases: 35910066Sandreas.hansson@arm.com // 1. We're awaiting an exclusive copy, so ownership is pending, 36010066Sandreas.hansson@arm.com // and we need to respond after we receive data. 36110066Sandreas.hansson@arm.com // 2. It's an invalidation (e.g., UpgradeReq), and we need 36210066Sandreas.hansson@arm.com // to forward the snoop up the hierarchy after the current 36310066Sandreas.hansson@arm.com // transaction completes. 36410066Sandreas.hansson@arm.com 36510066Sandreas.hansson@arm.com // Actual target device (typ. a memory) will delete the 36610066Sandreas.hansson@arm.com // packet on reception, so we need to save a copy here. 36710066Sandreas.hansson@arm.com 36810066Sandreas.hansson@arm.com // Clear flags and also allocate new data as the original 36910066Sandreas.hansson@arm.com // packet data storage may have been deleted by the time we 37010066Sandreas.hansson@arm.com // get to send this packet. 37110066Sandreas.hansson@arm.com PacketPtr cp_pkt = nullptr; 37210066Sandreas.hansson@arm.com 37310066Sandreas.hansson@arm.com if (isPendingDirty()) { 37410066Sandreas.hansson@arm.com // Case 1: The new packet will need to get the response from the 37510066Sandreas.hansson@arm.com // MSHR already queued up here 37610066Sandreas.hansson@arm.com cp_pkt = new Packet(pkt, true, true); 37710066Sandreas.hansson@arm.com pkt->assertMemInhibit(); 37810066Sandreas.hansson@arm.com // in the case of an uncacheable request there is no need 37910066Sandreas.hansson@arm.com // to set the exclusive flag, but since the recipient does 38010066Sandreas.hansson@arm.com // not care there is no harm in doing so 38110066Sandreas.hansson@arm.com pkt->setSupplyExclusive(); 38210066Sandreas.hansson@arm.com } else { 38310066Sandreas.hansson@arm.com // Case 2: We only need to buffer the packet for information 38410066Sandreas.hansson@arm.com // purposes; the original request can proceed without waiting 38510066Sandreas.hansson@arm.com // => Create a copy of the request, as that may get deallocated as 38610066Sandreas.hansson@arm.com // well 38710066Sandreas.hansson@arm.com cp_pkt = new Packet(new Request(*pkt->req), pkt->cmd); 38810066Sandreas.hansson@arm.com DPRINTF(Cache, "Copying packet %p -> %p and request %p -> %p\n", 38910066Sandreas.hansson@arm.com pkt, cp_pkt, pkt->req, cp_pkt->req); 39010066Sandreas.hansson@arm.com } 39110066Sandreas.hansson@arm.com targets.add(cp_pkt, curTick(), _order, Target::FromSnoop, 39210066Sandreas.hansson@arm.com downstreamPending && targets.needsExclusive); 39310713Sandreas.hansson@arm.com 39410066Sandreas.hansson@arm.com if (pkt->needsExclusive()) { 39510713Sandreas.hansson@arm.com // This transaction will take away our pending copy 39610066Sandreas.hansson@arm.com postInvalidate = true; 39710066Sandreas.hansson@arm.com } 39810066Sandreas.hansson@arm.com } 39910066Sandreas.hansson@arm.com 40010066Sandreas.hansson@arm.com if (!pkt->needsExclusive() && !pkt->req->isUncacheable()) { 40110066Sandreas.hansson@arm.com // This transaction will get a read-shared copy, downgrading 40210066Sandreas.hansson@arm.com // our copy if we had an exclusive one 403 postDowngrade = true; 404 pkt->assertShared(); 405 } 406 407 return true; 408} 409 410 411bool 412MSHR::promoteDeferredTargets() 413{ 414 assert(targets.empty()); 415 if (deferredTargets.empty()) { 416 return false; 417 } 418 419 // swap targets & deferredTargets lists 420 std::swap(targets, deferredTargets); 421 422 // clear deferredTargets flags 423 deferredTargets.resetFlags(); 424 425 order = targets.front().order; 426 readyTime = std::max(curTick(), targets.front().readyTime); 427 428 return true; 429} 430 431 432void 433MSHR::handleFill(PacketPtr pkt, CacheBlk *blk) 434{ 435 if (!pkt->sharedAsserted() 436 && !(hasPostInvalidate() || hasPostDowngrade()) 437 && deferredTargets.needsExclusive) { 438 // We got an exclusive response, but we have deferred targets 439 // which are waiting to request an exclusive copy (not because 440 // of a pending invalidate). This can happen if the original 441 // request was for a read-only (non-exclusive) block, but we 442 // got an exclusive copy anyway because of the E part of the 443 // MOESI/MESI protocol. Since we got the exclusive copy 444 // there's no need to defer the targets, so move them up to 445 // the regular target list. 446 assert(!targets.needsExclusive); 447 targets.needsExclusive = true; 448 // if any of the deferred targets were upper-level cache 449 // requests marked downstreamPending, need to clear that 450 assert(!downstreamPending); // not pending here anymore 451 deferredTargets.clearDownstreamPending(); 452 // this clears out deferredTargets too 453 targets.splice(targets.end(), deferredTargets); 454 deferredTargets.resetFlags(); 455 } 456} 457 458 459bool 460MSHR::checkFunctional(PacketPtr pkt) 461{ 462 // For printing, we treat the MSHR as a whole as single entity. 463 // For other requests, we iterate over the individual targets 464 // since that's where the actual data lies. 465 if (pkt->isPrint()) { 466 pkt->checkFunctional(this, blkAddr, isSecure, blkSize, NULL); 467 return false; 468 } else { 469 return (targets.checkFunctional(pkt) || 470 deferredTargets.checkFunctional(pkt)); 471 } 472} 473 474 475void 476MSHR::print(std::ostream &os, int verbosity, const std::string &prefix) const 477{ 478 ccprintf(os, "%s[%#llx:%#llx](%s) %s %s %s state: %s %s %s %s %s\n", 479 prefix, blkAddr, blkAddr + blkSize - 1, 480 isSecure ? "s" : "ns", 481 isForward ? "Forward" : "", 482 isForwardNoResponse() ? "ForwNoResp" : "", 483 needsExclusive() ? "Excl" : "", 484 _isUncacheable ? "Unc" : "", 485 inService ? "InSvc" : "", 486 downstreamPending ? "DwnPend" : "", 487 hasPostInvalidate() ? "PostInv" : "", 488 hasPostDowngrade() ? "PostDowngr" : ""); 489 490 ccprintf(os, "%s Targets:\n", prefix); 491 targets.print(os, verbosity, prefix + " "); 492 if (!deferredTargets.empty()) { 493 ccprintf(os, "%s Deferred Targets:\n", prefix); 494 deferredTargets.print(os, verbosity, prefix + " "); 495 } 496} 497 498std::string 499MSHR::print() const 500{ 501 ostringstream str; 502 print(str); 503 return str.str(); 504} 505