mshr.cc revision 10821
17405SAli.Saidi@ARM.com/* 27405SAli.Saidi@ARM.com * Copyright (c) 2012-2013, 2015 ARM Limited 37405SAli.Saidi@ARM.com * All rights reserved. 47405SAli.Saidi@ARM.com * 57405SAli.Saidi@ARM.com * The license below extends only to copyright in the software and shall 67405SAli.Saidi@ARM.com * not be construed as granting a license to any other intellectual 77405SAli.Saidi@ARM.com * property including but not limited to intellectual property relating 87405SAli.Saidi@ARM.com * to a hardware implementation of the functionality of the software 97405SAli.Saidi@ARM.com * licensed hereunder. You may use the software subject to the license 107405SAli.Saidi@ARM.com * terms below provided that you ensure that this notice is replicated 117405SAli.Saidi@ARM.com * unmodified and in its entirety in all distributions of the software, 127405SAli.Saidi@ARM.com * modified or unmodified, in source code or in binary form. 137405SAli.Saidi@ARM.com * 147405SAli.Saidi@ARM.com * Copyright (c) 2002-2005 The Regents of The University of Michigan 157405SAli.Saidi@ARM.com * Copyright (c) 2010 Advanced Micro Devices, Inc. 167405SAli.Saidi@ARM.com * All rights reserved. 177405SAli.Saidi@ARM.com * 187405SAli.Saidi@ARM.com * Redistribution and use in source and binary forms, with or without 197405SAli.Saidi@ARM.com * modification, are permitted provided that the following conditions are 207405SAli.Saidi@ARM.com * met: redistributions of source code must retain the above copyright 217405SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer; 227405SAli.Saidi@ARM.com * redistributions in binary form must reproduce the above copyright 237405SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer in the 247405SAli.Saidi@ARM.com * documentation and/or other materials provided with the distribution; 257405SAli.Saidi@ARM.com * neither the name of the copyright holders nor the names of its 267405SAli.Saidi@ARM.com * contributors may be used to endorse or promote products derived from 277405SAli.Saidi@ARM.com * this software without specific prior written permission. 287405SAli.Saidi@ARM.com * 297405SAli.Saidi@ARM.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 307405SAli.Saidi@ARM.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 317405SAli.Saidi@ARM.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 327405SAli.Saidi@ARM.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 337405SAli.Saidi@ARM.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 347405SAli.Saidi@ARM.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 357405SAli.Saidi@ARM.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 367405SAli.Saidi@ARM.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 377405SAli.Saidi@ARM.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 387405SAli.Saidi@ARM.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 397405SAli.Saidi@ARM.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 407405SAli.Saidi@ARM.com * 417405SAli.Saidi@ARM.com * Authors: Erik Hallnor 427405SAli.Saidi@ARM.com * Dave Greene 437405SAli.Saidi@ARM.com */ 447405SAli.Saidi@ARM.com 457405SAli.Saidi@ARM.com/** 467405SAli.Saidi@ARM.com * @file 477405SAli.Saidi@ARM.com * Miss Status and Handling Register (MSHR) definitions. 487405SAli.Saidi@ARM.com */ 497405SAli.Saidi@ARM.com 507405SAli.Saidi@ARM.com#include <algorithm> 517405SAli.Saidi@ARM.com#include <cassert> 527405SAli.Saidi@ARM.com#include <string> 537405SAli.Saidi@ARM.com#include <vector> 547405SAli.Saidi@ARM.com 557405SAli.Saidi@ARM.com#include "base/misc.hh" 567405SAli.Saidi@ARM.com#include "base/types.hh" 577405SAli.Saidi@ARM.com#include "debug/Cache.hh" 587405SAli.Saidi@ARM.com#include "mem/cache/cache.hh" 597405SAli.Saidi@ARM.com#include "mem/cache/mshr.hh" 607405SAli.Saidi@ARM.com#include "sim/core.hh" 617405SAli.Saidi@ARM.com 627405SAli.Saidi@ARM.comusing namespace std; 637405SAli.Saidi@ARM.com 647405SAli.Saidi@ARM.comMSHR::MSHR() : readyTime(0), _isUncacheable(false), downstreamPending(false), 657405SAli.Saidi@ARM.com pendingDirty(false), 667405SAli.Saidi@ARM.com postInvalidate(false), postDowngrade(false), 677405SAli.Saidi@ARM.com queue(NULL), order(0), blkAddr(0), 687405SAli.Saidi@ARM.com blkSize(0), isSecure(false), inService(false), 697405SAli.Saidi@ARM.com isForward(false), threadNum(InvalidThreadID), data(NULL) 707405SAli.Saidi@ARM.com{ 717405SAli.Saidi@ARM.com} 727405SAli.Saidi@ARM.com 737405SAli.Saidi@ARM.com 747405SAli.Saidi@ARM.comMSHR::TargetList::TargetList() 757405SAli.Saidi@ARM.com : needsExclusive(false), hasUpgrade(false) 767405SAli.Saidi@ARM.com{} 777405SAli.Saidi@ARM.com 787405SAli.Saidi@ARM.com 797405SAli.Saidi@ARM.cominline void 807405SAli.Saidi@ARM.comMSHR::TargetList::add(PacketPtr pkt, Tick readyTime, 817405SAli.Saidi@ARM.com Counter order, Target::Source source, bool markPending) 827405SAli.Saidi@ARM.com{ 837405SAli.Saidi@ARM.com if (source != Target::FromSnoop) { 847405SAli.Saidi@ARM.com if (pkt->needsExclusive()) { 857405SAli.Saidi@ARM.com needsExclusive = true; 867405SAli.Saidi@ARM.com } 877405SAli.Saidi@ARM.com 887405SAli.Saidi@ARM.com // StoreCondReq is effectively an upgrade if it's in an MSHR 897405SAli.Saidi@ARM.com // since it would have been failed already if we didn't have a 907405SAli.Saidi@ARM.com // read-only copy 917405SAli.Saidi@ARM.com if (pkt->isUpgrade() || pkt->cmd == MemCmd::StoreCondReq) { 927405SAli.Saidi@ARM.com hasUpgrade = true; 937405SAli.Saidi@ARM.com } 947405SAli.Saidi@ARM.com } 957405SAli.Saidi@ARM.com 967405SAli.Saidi@ARM.com if (markPending) { 977405SAli.Saidi@ARM.com // Iterate over the SenderState stack and see if we find 987405SAli.Saidi@ARM.com // an MSHR entry. If we do, set the downstreamPending 997405SAli.Saidi@ARM.com // flag. Otherwise, do nothing. 1007405SAli.Saidi@ARM.com MSHR *mshr = pkt->findNextSenderState<MSHR>(); 1017405SAli.Saidi@ARM.com if (mshr != NULL) { 1027405SAli.Saidi@ARM.com assert(!mshr->downstreamPending); 1037405SAli.Saidi@ARM.com mshr->downstreamPending = true; 1047405SAli.Saidi@ARM.com } 1057405SAli.Saidi@ARM.com } 1067405SAli.Saidi@ARM.com 1077405SAli.Saidi@ARM.com emplace_back(Target(pkt, readyTime, order, source, markPending)); 1087405SAli.Saidi@ARM.com} 1097405SAli.Saidi@ARM.com 1107405SAli.Saidi@ARM.com 1117405SAli.Saidi@ARM.comstatic void 1127405SAli.Saidi@ARM.comreplaceUpgrade(PacketPtr pkt) 1137405SAli.Saidi@ARM.com{ 1147405SAli.Saidi@ARM.com if (pkt->cmd == MemCmd::UpgradeReq) { 1157405SAli.Saidi@ARM.com pkt->cmd = MemCmd::ReadExReq; 1167405SAli.Saidi@ARM.com DPRINTF(Cache, "Replacing UpgradeReq with ReadExReq\n"); 1177405SAli.Saidi@ARM.com } else if (pkt->cmd == MemCmd::SCUpgradeReq) { 1187405SAli.Saidi@ARM.com pkt->cmd = MemCmd::SCUpgradeFailReq; 1197405SAli.Saidi@ARM.com DPRINTF(Cache, "Replacing SCUpgradeReq with SCUpgradeFailReq\n"); 1207405SAli.Saidi@ARM.com } else if (pkt->cmd == MemCmd::StoreCondReq) { 1217405SAli.Saidi@ARM.com pkt->cmd = MemCmd::StoreCondFailReq; 1227405SAli.Saidi@ARM.com DPRINTF(Cache, "Replacing StoreCondReq with StoreCondFailReq\n"); 1237405SAli.Saidi@ARM.com } 1247405SAli.Saidi@ARM.com} 1257405SAli.Saidi@ARM.com 1267405SAli.Saidi@ARM.com 1277405SAli.Saidi@ARM.comvoid 1287405SAli.Saidi@ARM.comMSHR::TargetList::replaceUpgrades() 1297405SAli.Saidi@ARM.com{ 1307405SAli.Saidi@ARM.com if (!hasUpgrade) 1317405SAli.Saidi@ARM.com return; 1327405SAli.Saidi@ARM.com 1337405SAli.Saidi@ARM.com for (auto& t : *this) { 1347405SAli.Saidi@ARM.com replaceUpgrade(t.pkt); 1357405SAli.Saidi@ARM.com } 1367405SAli.Saidi@ARM.com 1377405SAli.Saidi@ARM.com hasUpgrade = false; 1387405SAli.Saidi@ARM.com} 1397405SAli.Saidi@ARM.com 1407405SAli.Saidi@ARM.com 1417405SAli.Saidi@ARM.comvoid 1427405SAli.Saidi@ARM.comMSHR::TargetList::clearDownstreamPending() 1437405SAli.Saidi@ARM.com{ 1447405SAli.Saidi@ARM.com for (auto& t : *this) { 1457405SAli.Saidi@ARM.com if (t.markedPending) { 1467405SAli.Saidi@ARM.com // Iterate over the SenderState stack and see if we find 1477405SAli.Saidi@ARM.com // an MSHR entry. If we find one, clear the 1487405SAli.Saidi@ARM.com // downstreamPending flag by calling 1497405SAli.Saidi@ARM.com // clearDownstreamPending(). This recursively clears the 1507405SAli.Saidi@ARM.com // downstreamPending flag in all caches this packet has 1517405SAli.Saidi@ARM.com // passed through. 1527405SAli.Saidi@ARM.com MSHR *mshr = t.pkt->findNextSenderState<MSHR>(); 1537405SAli.Saidi@ARM.com if (mshr != NULL) { 1547405SAli.Saidi@ARM.com mshr->clearDownstreamPending(); 1557405SAli.Saidi@ARM.com } 1567405SAli.Saidi@ARM.com } 1577405SAli.Saidi@ARM.com } 1587405SAli.Saidi@ARM.com} 1597405SAli.Saidi@ARM.com 1607405SAli.Saidi@ARM.com 1617405SAli.Saidi@ARM.combool 1627408Sgblack@eecs.umich.eduMSHR::TargetList::checkFunctional(PacketPtr pkt) 1637405SAli.Saidi@ARM.com{ 1647405SAli.Saidi@ARM.com for (auto& t : *this) { 1657405SAli.Saidi@ARM.com if (pkt->checkFunctional(t.pkt)) { 1667408Sgblack@eecs.umich.edu return true; 1677408Sgblack@eecs.umich.edu } 1687408Sgblack@eecs.umich.edu } 1697408Sgblack@eecs.umich.edu 1707408Sgblack@eecs.umich.edu return false; 1717408Sgblack@eecs.umich.edu} 1727408Sgblack@eecs.umich.edu 1737408Sgblack@eecs.umich.edu 1747408Sgblack@eecs.umich.eduvoid 1757408Sgblack@eecs.umich.eduMSHR::TargetList::print(std::ostream &os, int verbosity, 1767408Sgblack@eecs.umich.edu const std::string &prefix) const 1777408Sgblack@eecs.umich.edu{ 1787405SAli.Saidi@ARM.com for (auto& t : *this) { 1797408Sgblack@eecs.umich.edu const char *s; 1807408Sgblack@eecs.umich.edu switch (t.source) { 1817408Sgblack@eecs.umich.edu case Target::FromCPU: 1827408Sgblack@eecs.umich.edu s = "FromCPU"; 1837408Sgblack@eecs.umich.edu break; 1847408Sgblack@eecs.umich.edu case Target::FromSnoop: 1857408Sgblack@eecs.umich.edu s = "FromSnoop"; 1867408Sgblack@eecs.umich.edu break; 1877408Sgblack@eecs.umich.edu case Target::FromPrefetcher: 1887408Sgblack@eecs.umich.edu s = "FromPrefetcher"; 1897408Sgblack@eecs.umich.edu break; 1907408Sgblack@eecs.umich.edu default: 1917408Sgblack@eecs.umich.edu s = ""; 1927408Sgblack@eecs.umich.edu break; 1937408Sgblack@eecs.umich.edu } 1947408Sgblack@eecs.umich.edu ccprintf(os, "%s%s: ", prefix, s); 1957408Sgblack@eecs.umich.edu t.pkt->print(os, verbosity, ""); 1967408Sgblack@eecs.umich.edu } 1977408Sgblack@eecs.umich.edu} 1987408Sgblack@eecs.umich.edu 1997408Sgblack@eecs.umich.edu 2007408Sgblack@eecs.umich.eduvoid 2017408Sgblack@eecs.umich.eduMSHR::allocate(Addr blk_addr, unsigned blk_size, PacketPtr target, 2027408Sgblack@eecs.umich.edu Tick when_ready, Counter _order) 2037408Sgblack@eecs.umich.edu{ 2047408Sgblack@eecs.umich.edu blkAddr = blk_addr; 2057408Sgblack@eecs.umich.edu blkSize = blk_size; 2067408Sgblack@eecs.umich.edu isSecure = target->isSecure(); 2077408Sgblack@eecs.umich.edu readyTime = when_ready; 2087408Sgblack@eecs.umich.edu order = _order; 2097408Sgblack@eecs.umich.edu assert(target); 2107408Sgblack@eecs.umich.edu isForward = false; 2117408Sgblack@eecs.umich.edu _isUncacheable = target->req->isUncacheable(); 2127408Sgblack@eecs.umich.edu inService = false; 2137408Sgblack@eecs.umich.edu downstreamPending = false; 2147408Sgblack@eecs.umich.edu threadNum = 0; 2157408Sgblack@eecs.umich.edu assert(targets.isReset()); 2167408Sgblack@eecs.umich.edu // Don't know of a case where we would allocate a new MSHR for a 2177408Sgblack@eecs.umich.edu // snoop (mem-side request), so set source according to request here 2187408Sgblack@eecs.umich.edu Target::Source source = (target->cmd == MemCmd::HardPFReq) ? 2197408Sgblack@eecs.umich.edu Target::FromPrefetcher : Target::FromCPU; 2207408Sgblack@eecs.umich.edu targets.add(target, when_ready, _order, source, true); 2217408Sgblack@eecs.umich.edu assert(deferredTargets.isReset()); 2227408Sgblack@eecs.umich.edu data = NULL; 2237408Sgblack@eecs.umich.edu} 2247408Sgblack@eecs.umich.edu 2257408Sgblack@eecs.umich.edu 2267408Sgblack@eecs.umich.eduvoid 2277408Sgblack@eecs.umich.eduMSHR::clearDownstreamPending() 2287408Sgblack@eecs.umich.edu{ 2297408Sgblack@eecs.umich.edu assert(downstreamPending); 2307408Sgblack@eecs.umich.edu downstreamPending = false; 2317408Sgblack@eecs.umich.edu // recursively clear flag on any MSHRs we will be forwarding 2327408Sgblack@eecs.umich.edu // responses to 2337408Sgblack@eecs.umich.edu targets.clearDownstreamPending(); 2347408Sgblack@eecs.umich.edu} 2357408Sgblack@eecs.umich.edu 2367408Sgblack@eecs.umich.edubool 2377408Sgblack@eecs.umich.eduMSHR::markInService(bool pending_dirty_resp) 2387408Sgblack@eecs.umich.edu{ 2397408Sgblack@eecs.umich.edu assert(!inService); 2407408Sgblack@eecs.umich.edu if (isForwardNoResponse()) { 2417408Sgblack@eecs.umich.edu // we just forwarded the request packet & don't expect a 2427408Sgblack@eecs.umich.edu // response, so get rid of it 2437408Sgblack@eecs.umich.edu assert(getNumTargets() == 1); 2447408Sgblack@eecs.umich.edu popTarget(); 2457408Sgblack@eecs.umich.edu return true; 2467408Sgblack@eecs.umich.edu } 2477408Sgblack@eecs.umich.edu 2487408Sgblack@eecs.umich.edu inService = true; 2497408Sgblack@eecs.umich.edu pendingDirty = targets.needsExclusive || pending_dirty_resp; 2507408Sgblack@eecs.umich.edu postInvalidate = postDowngrade = false; 2517408Sgblack@eecs.umich.edu 2527408Sgblack@eecs.umich.edu if (!downstreamPending) { 2537408Sgblack@eecs.umich.edu // let upstream caches know that the request has made it to a 2547408Sgblack@eecs.umich.edu // level where it's going to get a response 2557408Sgblack@eecs.umich.edu targets.clearDownstreamPending(); 2567408Sgblack@eecs.umich.edu } 2577408Sgblack@eecs.umich.edu return false; 2587408Sgblack@eecs.umich.edu} 2597408Sgblack@eecs.umich.edu 2607408Sgblack@eecs.umich.edu 2617408Sgblack@eecs.umich.eduvoid 2627408Sgblack@eecs.umich.eduMSHR::deallocate() 2637408Sgblack@eecs.umich.edu{ 2647408Sgblack@eecs.umich.edu assert(targets.empty()); 2657408Sgblack@eecs.umich.edu targets.resetFlags(); 2667408Sgblack@eecs.umich.edu assert(deferredTargets.isReset()); 2677408Sgblack@eecs.umich.edu inService = false; 2687408Sgblack@eecs.umich.edu} 2697408Sgblack@eecs.umich.edu 2707408Sgblack@eecs.umich.edu/* 2717408Sgblack@eecs.umich.edu * Adds a target to an MSHR 2727408Sgblack@eecs.umich.edu */ 2737408Sgblack@eecs.umich.eduvoid 2747408Sgblack@eecs.umich.eduMSHR::allocateTarget(PacketPtr pkt, Tick whenReady, Counter _order) 2757408Sgblack@eecs.umich.edu{ 2767408Sgblack@eecs.umich.edu // assume we'd never issue a prefetch when we've got an 2777408Sgblack@eecs.umich.edu // outstanding miss 2787408Sgblack@eecs.umich.edu assert(pkt->cmd != MemCmd::HardPFReq); 2797408Sgblack@eecs.umich.edu 2807408Sgblack@eecs.umich.edu // uncacheable accesses always allocate a new MSHR, and cacheable 2817408Sgblack@eecs.umich.edu // accesses ignore any uncacheable MSHRs, thus we should never 2827408Sgblack@eecs.umich.edu // have targets addded if originally allocated uncacheable 2837408Sgblack@eecs.umich.edu assert(!_isUncacheable); 2847408Sgblack@eecs.umich.edu 2857408Sgblack@eecs.umich.edu // if there's a request already in service for this MSHR, we will 2867408Sgblack@eecs.umich.edu // have to defer the new target until after the response if any of 2877405SAli.Saidi@ARM.com // the following are true: 2887405SAli.Saidi@ARM.com // - there are other targets already deferred 2897405SAli.Saidi@ARM.com // - there's a pending invalidate to be applied after the response 2907405SAli.Saidi@ARM.com // comes back (but before this target is processed) 2917405SAli.Saidi@ARM.com // - this target requires an exclusive block and either we're not 2927405SAli.Saidi@ARM.com // getting an exclusive block back or we have already snooped 2937405SAli.Saidi@ARM.com // another read request that will downgrade our exclusive block 294 // to shared 295 if (inService && 296 (!deferredTargets.empty() || hasPostInvalidate() || 297 (pkt->needsExclusive() && 298 (!isPendingDirty() || hasPostDowngrade() || isForward)))) { 299 // need to put on deferred list 300 if (hasPostInvalidate()) 301 replaceUpgrade(pkt); 302 deferredTargets.add(pkt, whenReady, _order, Target::FromCPU, true); 303 } else { 304 // No request outstanding, or still OK to append to 305 // outstanding request: append to regular target list. Only 306 // mark pending if current request hasn't been issued yet 307 // (isn't in service). 308 targets.add(pkt, whenReady, _order, Target::FromCPU, !inService); 309 } 310} 311 312bool 313MSHR::handleSnoop(PacketPtr pkt, Counter _order) 314{ 315 DPRINTF(Cache, "%s for %s addr %#llx size %d\n", __func__, 316 pkt->cmdString(), pkt->getAddr(), pkt->getSize()); 317 if (!inService || (pkt->isExpressSnoop() && downstreamPending)) { 318 // Request has not been issued yet, or it's been issued 319 // locally but is buffered unissued at some downstream cache 320 // which is forwarding us this snoop. Either way, the packet 321 // we're snooping logically precedes this MSHR's request, so 322 // the snoop has no impact on the MSHR, but must be processed 323 // in the standard way by the cache. The only exception is 324 // that if we're an L2+ cache buffering an UpgradeReq from a 325 // higher-level cache, and the snoop is invalidating, then our 326 // buffered upgrades must be converted to read exclusives, 327 // since the upper-level cache no longer has a valid copy. 328 // That is, even though the upper-level cache got out on its 329 // local bus first, some other invalidating transaction 330 // reached the global bus before the upgrade did. 331 if (pkt->needsExclusive()) { 332 targets.replaceUpgrades(); 333 deferredTargets.replaceUpgrades(); 334 } 335 336 return false; 337 } 338 339 // From here on down, the request issued by this MSHR logically 340 // precedes the request we're snooping. 341 if (pkt->needsExclusive()) { 342 // snooped request still precedes the re-request we'll have to 343 // issue for deferred targets, if any... 344 deferredTargets.replaceUpgrades(); 345 } 346 347 if (hasPostInvalidate()) { 348 // a prior snoop has already appended an invalidation, so 349 // logically we don't have the block anymore; no need for 350 // further snooping. 351 return true; 352 } 353 354 if (isPendingDirty() || pkt->isInvalidate()) { 355 // We need to save and replay the packet in two cases: 356 // 1. We're awaiting an exclusive copy, so ownership is pending, 357 // and we need to respond after we receive data. 358 // 2. It's an invalidation (e.g., UpgradeReq), and we need 359 // to forward the snoop up the hierarchy after the current 360 // transaction completes. 361 362 // Actual target device (typ. a memory) will delete the 363 // packet on reception, so we need to save a copy here. 364 365 // Clear flags and also allocate new data as the original 366 // packet data storage may have been deleted by the time we 367 // get to send this packet. 368 PacketPtr cp_pkt = new Packet(pkt, true, true); 369 targets.add(cp_pkt, curTick(), _order, Target::FromSnoop, 370 downstreamPending && targets.needsExclusive); 371 372 if (isPendingDirty()) { 373 pkt->assertMemInhibit(); 374 // in the case of an uncacheable request there is no need 375 // to set the exclusive flag, but since the recipient does 376 // not care there is no harm in doing so 377 pkt->setSupplyExclusive(); 378 } 379 380 if (pkt->needsExclusive()) { 381 // This transaction will take away our pending copy 382 postInvalidate = true; 383 } 384 } 385 386 if (!pkt->needsExclusive() && !pkt->req->isUncacheable()) { 387 // This transaction will get a read-shared copy, downgrading 388 // our copy if we had an exclusive one 389 postDowngrade = true; 390 pkt->assertShared(); 391 } 392 393 return true; 394} 395 396 397bool 398MSHR::promoteDeferredTargets() 399{ 400 assert(targets.empty()); 401 if (deferredTargets.empty()) { 402 return false; 403 } 404 405 // swap targets & deferredTargets lists 406 std::swap(targets, deferredTargets); 407 408 // clear deferredTargets flags 409 deferredTargets.resetFlags(); 410 411 order = targets.front().order; 412 readyTime = std::max(curTick(), targets.front().readyTime); 413 414 return true; 415} 416 417 418void 419MSHR::handleFill(PacketPtr pkt, CacheBlk *blk) 420{ 421 if (!pkt->sharedAsserted() 422 && !(hasPostInvalidate() || hasPostDowngrade()) 423 && deferredTargets.needsExclusive) { 424 // We got an exclusive response, but we have deferred targets 425 // which are waiting to request an exclusive copy (not because 426 // of a pending invalidate). This can happen if the original 427 // request was for a read-only (non-exclusive) block, but we 428 // got an exclusive copy anyway because of the E part of the 429 // MOESI/MESI protocol. Since we got the exclusive copy 430 // there's no need to defer the targets, so move them up to 431 // the regular target list. 432 assert(!targets.needsExclusive); 433 targets.needsExclusive = true; 434 // if any of the deferred targets were upper-level cache 435 // requests marked downstreamPending, need to clear that 436 assert(!downstreamPending); // not pending here anymore 437 deferredTargets.clearDownstreamPending(); 438 // this clears out deferredTargets too 439 targets.splice(targets.end(), deferredTargets); 440 deferredTargets.resetFlags(); 441 } 442} 443 444 445bool 446MSHR::checkFunctional(PacketPtr pkt) 447{ 448 // For printing, we treat the MSHR as a whole as single entity. 449 // For other requests, we iterate over the individual targets 450 // since that's where the actual data lies. 451 if (pkt->isPrint()) { 452 pkt->checkFunctional(this, blkAddr, isSecure, blkSize, NULL); 453 return false; 454 } else { 455 return (targets.checkFunctional(pkt) || 456 deferredTargets.checkFunctional(pkt)); 457 } 458} 459 460 461void 462MSHR::print(std::ostream &os, int verbosity, const std::string &prefix) const 463{ 464 ccprintf(os, "%s[%#llx:%#llx](%s) %s %s %s state: %s %s %s %s %s\n", 465 prefix, blkAddr, blkAddr + blkSize - 1, 466 isSecure ? "s" : "ns", 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