mshr.cc revision 9543:a373b2e664ff
15086Sgblack@eecs.umich.edu/* 25086Sgblack@eecs.umich.edu * Copyright (c) 2002-2005 The Regents of The University of Michigan 35086Sgblack@eecs.umich.edu * Copyright (c) 2010 Advanced Micro Devices, Inc. 45086Sgblack@eecs.umich.edu * All rights reserved. 55086Sgblack@eecs.umich.edu * 65086Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without 75086Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are 85086Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright 95086Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer; 105086Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright 115086Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the 125086Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution; 135086Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its 145086Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from 155086Sgblack@eecs.umich.edu * this software without specific prior written permission. 165086Sgblack@eecs.umich.edu * 175086Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 185086Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 195086Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 205086Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 215086Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 225086Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 235086Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 245086Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 255086Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 265086Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 275086Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 285086Sgblack@eecs.umich.edu * 295086Sgblack@eecs.umich.edu * Authors: Erik Hallnor 305086Sgblack@eecs.umich.edu * Dave Greene 315086Sgblack@eecs.umich.edu */ 325086Sgblack@eecs.umich.edu 335086Sgblack@eecs.umich.edu/** 345086Sgblack@eecs.umich.edu * @file 355086Sgblack@eecs.umich.edu * Miss Status and Handling Register (MSHR) definitions. 365086Sgblack@eecs.umich.edu */ 375086Sgblack@eecs.umich.edu 385086Sgblack@eecs.umich.edu#include <algorithm> 395086Sgblack@eecs.umich.edu#include <cassert> 405086Sgblack@eecs.umich.edu#include <string> 415086Sgblack@eecs.umich.edu#include <vector> 425086Sgblack@eecs.umich.edu 435086Sgblack@eecs.umich.edu#include "base/misc.hh" 445086Sgblack@eecs.umich.edu#include "base/types.hh" 455086Sgblack@eecs.umich.edu#include "debug/Cache.hh" 465086Sgblack@eecs.umich.edu#include "mem/cache/cache.hh" 475086Sgblack@eecs.umich.edu#include "mem/cache/mshr.hh" 485086Sgblack@eecs.umich.edu#include "sim/core.hh" 495086Sgblack@eecs.umich.edu 505086Sgblack@eecs.umich.eduusing namespace std; 515086Sgblack@eecs.umich.edu 525086Sgblack@eecs.umich.eduMSHR::MSHR() 535086Sgblack@eecs.umich.edu{ 545086Sgblack@eecs.umich.edu inService = false; 555086Sgblack@eecs.umich.edu ntargets = 0; 565086Sgblack@eecs.umich.edu threadNum = InvalidThreadID; 575086Sgblack@eecs.umich.edu targets = new TargetList(); 585135Sgblack@eecs.umich.edu deferredTargets = new TargetList(); 595135Sgblack@eecs.umich.edu} 605135Sgblack@eecs.umich.edu 615086Sgblack@eecs.umich.edu 625135Sgblack@eecs.umich.eduMSHR::TargetList::TargetList() 635234Sgblack@eecs.umich.edu : needsExclusive(false), hasUpgrade(false) 645086Sgblack@eecs.umich.edu{} 655086Sgblack@eecs.umich.edu 665086Sgblack@eecs.umich.edu 675086Sgblack@eecs.umich.eduinline void 685086Sgblack@eecs.umich.eduMSHR::TargetList::add(PacketPtr pkt, Tick readyTime, 695086Sgblack@eecs.umich.edu Counter order, Target::Source source, bool markPending) 705086Sgblack@eecs.umich.edu{ 715086Sgblack@eecs.umich.edu if (source != Target::FromSnoop) { 725086Sgblack@eecs.umich.edu if (pkt->needsExclusive()) { 735086Sgblack@eecs.umich.edu needsExclusive = true; 745086Sgblack@eecs.umich.edu } 755135Sgblack@eecs.umich.edu 765135Sgblack@eecs.umich.edu // StoreCondReq is effectively an upgrade if it's in an MSHR 775135Sgblack@eecs.umich.edu // since it would have been failed already if we didn't have a 785135Sgblack@eecs.umich.edu // read-only copy 795135Sgblack@eecs.umich.edu if (pkt->isUpgrade() || pkt->cmd == MemCmd::StoreCondReq) { 805135Sgblack@eecs.umich.edu hasUpgrade = true; 815135Sgblack@eecs.umich.edu } 825135Sgblack@eecs.umich.edu } 835135Sgblack@eecs.umich.edu 845135Sgblack@eecs.umich.edu if (markPending) { 855135Sgblack@eecs.umich.edu // Iterate over the SenderState stack and see if we find 865135Sgblack@eecs.umich.edu // an MSHR entry. If we do, set the downstreamPending 875135Sgblack@eecs.umich.edu // flag. Otherwise, do nothing. 885135Sgblack@eecs.umich.edu MSHR *mshr = pkt->findNextSenderState<MSHR>(); 895135Sgblack@eecs.umich.edu if (mshr != NULL) { 905135Sgblack@eecs.umich.edu assert(!mshr->downstreamPending); 915135Sgblack@eecs.umich.edu mshr->downstreamPending = true; 925135Sgblack@eecs.umich.edu } 935135Sgblack@eecs.umich.edu } 945135Sgblack@eecs.umich.edu 955135Sgblack@eecs.umich.edu push_back(Target(pkt, readyTime, order, source, markPending)); 965135Sgblack@eecs.umich.edu} 975135Sgblack@eecs.umich.edu 985135Sgblack@eecs.umich.edu 995135Sgblack@eecs.umich.edustatic void 1005135Sgblack@eecs.umich.edureplaceUpgrade(PacketPtr pkt) 1015264Sgblack@eecs.umich.edu{ 1025135Sgblack@eecs.umich.edu if (pkt->cmd == MemCmd::UpgradeReq) { 1035135Sgblack@eecs.umich.edu pkt->cmd = MemCmd::ReadExReq; 1045135Sgblack@eecs.umich.edu DPRINTF(Cache, "Replacing UpgradeReq with ReadExReq\n"); 1055135Sgblack@eecs.umich.edu } else if (pkt->cmd == MemCmd::SCUpgradeReq) { 1065135Sgblack@eecs.umich.edu pkt->cmd = MemCmd::SCUpgradeFailReq; 1075264Sgblack@eecs.umich.edu DPRINTF(Cache, "Replacing SCUpgradeReq with SCUpgradeFailReq\n"); 1085135Sgblack@eecs.umich.edu } else if (pkt->cmd == MemCmd::StoreCondReq) { 1095135Sgblack@eecs.umich.edu pkt->cmd = MemCmd::StoreCondFailReq; 1105135Sgblack@eecs.umich.edu DPRINTF(Cache, "Replacing StoreCondReq with StoreCondFailReq\n"); 1115141Sgblack@eecs.umich.edu } 1125141Sgblack@eecs.umich.edu} 1135141Sgblack@eecs.umich.edu 1145141Sgblack@eecs.umich.edu 1155141Sgblack@eecs.umich.eduvoid 1165141Sgblack@eecs.umich.eduMSHR::TargetList::replaceUpgrades() 1175141Sgblack@eecs.umich.edu{ 1185135Sgblack@eecs.umich.edu if (!hasUpgrade) 1195135Sgblack@eecs.umich.edu return; 1205135Sgblack@eecs.umich.edu 1215289Sgblack@eecs.umich.edu Iterator end_i = end(); 1225135Sgblack@eecs.umich.edu for (Iterator i = begin(); i != end_i; ++i) { 1235141Sgblack@eecs.umich.edu replaceUpgrade(i->pkt); 1245135Sgblack@eecs.umich.edu } 1255135Sgblack@eecs.umich.edu 1265141Sgblack@eecs.umich.edu hasUpgrade = false; 1275141Sgblack@eecs.umich.edu} 1285141Sgblack@eecs.umich.edu 1295141Sgblack@eecs.umich.edu 1305141Sgblack@eecs.umich.eduvoid 1315141Sgblack@eecs.umich.eduMSHR::TargetList::clearDownstreamPending() 1325141Sgblack@eecs.umich.edu{ 1335135Sgblack@eecs.umich.edu Iterator end_i = end(); 1345289Sgblack@eecs.umich.edu for (Iterator i = begin(); i != end_i; ++i) { 1355289Sgblack@eecs.umich.edu if (i->markedPending) { 1365289Sgblack@eecs.umich.edu // Iterate over the SenderState stack and see if we find 1375289Sgblack@eecs.umich.edu // an MSHR entry. If we find one, clear the 1385135Sgblack@eecs.umich.edu // downstreamPending flag by calling 1395135Sgblack@eecs.umich.edu // clearDownstreamPending(). This recursively clears the 1405141Sgblack@eecs.umich.edu // downstreamPending flag in all caches this packet has 1415135Sgblack@eecs.umich.edu // passed through. 1425264Sgblack@eecs.umich.edu MSHR *mshr = i->pkt->findNextSenderState<MSHR>(); 1435135Sgblack@eecs.umich.edu if (mshr != NULL) { 1445135Sgblack@eecs.umich.edu mshr->clearDownstreamPending(); 1455135Sgblack@eecs.umich.edu } 1465294Sgblack@eecs.umich.edu } 1475294Sgblack@eecs.umich.edu } 1485135Sgblack@eecs.umich.edu} 1495135Sgblack@eecs.umich.edu 1505135Sgblack@eecs.umich.edu 1515135Sgblack@eecs.umich.edubool 1525294Sgblack@eecs.umich.eduMSHR::TargetList::checkFunctional(PacketPtr pkt) 1535294Sgblack@eecs.umich.edu{ 1545294Sgblack@eecs.umich.edu Iterator end_i = end(); 1555294Sgblack@eecs.umich.edu for (Iterator i = begin(); i != end_i; ++i) { 1565135Sgblack@eecs.umich.edu if (pkt->checkFunctional(i->pkt)) { 1575135Sgblack@eecs.umich.edu return true; 1585135Sgblack@eecs.umich.edu } 1595135Sgblack@eecs.umich.edu } 1605135Sgblack@eecs.umich.edu 1615135Sgblack@eecs.umich.edu return false; 1625135Sgblack@eecs.umich.edu} 1635135Sgblack@eecs.umich.edu 1645135Sgblack@eecs.umich.edu 1655135Sgblack@eecs.umich.eduvoid 1665135Sgblack@eecs.umich.eduMSHR::TargetList:: 1675135Sgblack@eecs.umich.eduprint(std::ostream &os, int verbosity, const std::string &prefix) const 1685135Sgblack@eecs.umich.edu{ 1695141Sgblack@eecs.umich.edu ConstIterator end_i = end(); 1705141Sgblack@eecs.umich.edu for (ConstIterator i = begin(); i != end_i; ++i) { 1715141Sgblack@eecs.umich.edu const char *s; 1725141Sgblack@eecs.umich.edu switch (i->source) { 1735141Sgblack@eecs.umich.edu case Target::FromCPU: 1745141Sgblack@eecs.umich.edu s = "FromCPU"; 1755141Sgblack@eecs.umich.edu break; 1765141Sgblack@eecs.umich.edu case Target::FromSnoop: 1775141Sgblack@eecs.umich.edu s = "FromSnoop"; 1785182Sgblack@eecs.umich.edu break; 1795141Sgblack@eecs.umich.edu case Target::FromPrefetcher: 1805141Sgblack@eecs.umich.edu s = "FromPrefetcher"; 1815141Sgblack@eecs.umich.edu break; 1825141Sgblack@eecs.umich.edu default: 1835141Sgblack@eecs.umich.edu s = ""; 1845141Sgblack@eecs.umich.edu break; 1855135Sgblack@eecs.umich.edu } 1865141Sgblack@eecs.umich.edu ccprintf(os, "%s%s: ", prefix, s); 1875141Sgblack@eecs.umich.edu i->pkt->print(os, verbosity, ""); 1885141Sgblack@eecs.umich.edu } 1895141Sgblack@eecs.umich.edu} 1905141Sgblack@eecs.umich.edu 1915141Sgblack@eecs.umich.edu 1925141Sgblack@eecs.umich.eduvoid 1935141Sgblack@eecs.umich.eduMSHR::allocate(Addr _addr, int _size, PacketPtr target, 1945141Sgblack@eecs.umich.edu Tick whenReady, Counter _order) 1955141Sgblack@eecs.umich.edu{ 1965141Sgblack@eecs.umich.edu addr = _addr; 1975141Sgblack@eecs.umich.edu size = _size; 1985135Sgblack@eecs.umich.edu readyTime = whenReady; 1995135Sgblack@eecs.umich.edu order = _order; 2005135Sgblack@eecs.umich.edu assert(target); 2015135Sgblack@eecs.umich.edu isForward = false; 2025135Sgblack@eecs.umich.edu _isUncacheable = target->req->isUncacheable(); 2035135Sgblack@eecs.umich.edu inService = false; 2045264Sgblack@eecs.umich.edu downstreamPending = false; 2055264Sgblack@eecs.umich.edu threadNum = 0; 2065135Sgblack@eecs.umich.edu ntargets = 1; 2075141Sgblack@eecs.umich.edu assert(targets->isReset()); 2085141Sgblack@eecs.umich.edu // Don't know of a case where we would allocate a new MSHR for a 2095135Sgblack@eecs.umich.edu // snoop (mem-side request), so set source according to request here 2105141Sgblack@eecs.umich.edu Target::Source source = (target->cmd == MemCmd::HardPFReq) ? 2115141Sgblack@eecs.umich.edu Target::FromPrefetcher : Target::FromCPU; 2125141Sgblack@eecs.umich.edu targets->add(target, whenReady, _order, source, true); 2135141Sgblack@eecs.umich.edu assert(deferredTargets->isReset()); 2145135Sgblack@eecs.umich.edu data = NULL; 2155141Sgblack@eecs.umich.edu} 2165141Sgblack@eecs.umich.edu 2175141Sgblack@eecs.umich.edu 2185141Sgblack@eecs.umich.eduvoid 2195141Sgblack@eecs.umich.eduMSHR::clearDownstreamPending() 2205141Sgblack@eecs.umich.edu{ 2215141Sgblack@eecs.umich.edu assert(downstreamPending); 2225141Sgblack@eecs.umich.edu downstreamPending = false; 2235141Sgblack@eecs.umich.edu // recursively clear flag on any MSHRs we will be forwarding 2245141Sgblack@eecs.umich.edu // responses to 2255141Sgblack@eecs.umich.edu targets->clearDownstreamPending(); 2265141Sgblack@eecs.umich.edu} 2275264Sgblack@eecs.umich.edu 2285141Sgblack@eecs.umich.edubool 2295141Sgblack@eecs.umich.eduMSHR::markInService(PacketPtr pkt) 2305141Sgblack@eecs.umich.edu{ 2315141Sgblack@eecs.umich.edu assert(!inService); 2325141Sgblack@eecs.umich.edu if (isForwardNoResponse()) { 2335141Sgblack@eecs.umich.edu // we just forwarded the request packet & don't expect a 2345141Sgblack@eecs.umich.edu // response, so get rid of it 2355141Sgblack@eecs.umich.edu assert(getNumTargets() == 1); 2365141Sgblack@eecs.umich.edu popTarget(); 2375141Sgblack@eecs.umich.edu return true; 2385141Sgblack@eecs.umich.edu } 2395141Sgblack@eecs.umich.edu inService = true; 2405141Sgblack@eecs.umich.edu pendingDirty = (targets->needsExclusive || 2415141Sgblack@eecs.umich.edu (!pkt->sharedAsserted() && pkt->memInhibitAsserted())); 2425141Sgblack@eecs.umich.edu postInvalidate = postDowngrade = false; 2435141Sgblack@eecs.umich.edu 2445141Sgblack@eecs.umich.edu if (!downstreamPending) { 2455135Sgblack@eecs.umich.edu // let upstream caches know that the request has made it to a 2465135Sgblack@eecs.umich.edu // level where it's going to get a response 2475135Sgblack@eecs.umich.edu targets->clearDownstreamPending(); 2485135Sgblack@eecs.umich.edu } 2495135Sgblack@eecs.umich.edu return false; 2505135Sgblack@eecs.umich.edu} 2515360Sgblack@eecs.umich.edu 2525360Sgblack@eecs.umich.edu 2535360Sgblack@eecs.umich.eduvoid 2545360Sgblack@eecs.umich.eduMSHR::deallocate() 2555360Sgblack@eecs.umich.edu{ 2565360Sgblack@eecs.umich.edu assert(targets->empty()); 2575360Sgblack@eecs.umich.edu targets->resetFlags(); 2585360Sgblack@eecs.umich.edu assert(deferredTargets->isReset()); 2595360Sgblack@eecs.umich.edu assert(ntargets == 0); 2605360Sgblack@eecs.umich.edu inService = false; 2615141Sgblack@eecs.umich.edu} 2625141Sgblack@eecs.umich.edu 2635141Sgblack@eecs.umich.edu/* 2645141Sgblack@eecs.umich.edu * Adds a target to an MSHR 2655141Sgblack@eecs.umich.edu */ 2665141Sgblack@eecs.umich.eduvoid 2675135Sgblack@eecs.umich.eduMSHR::allocateTarget(PacketPtr pkt, Tick whenReady, Counter _order) 2685135Sgblack@eecs.umich.edu{ 2695135Sgblack@eecs.umich.edu // if there's a request already in service for this MSHR, we will 2705135Sgblack@eecs.umich.edu // have to defer the new target until after the response if any of 2715234Sgblack@eecs.umich.edu // the following are true: 2725135Sgblack@eecs.umich.edu // - there are other targets already deferred 2735135Sgblack@eecs.umich.edu // - there's a pending invalidate to be applied after the response 2745135Sgblack@eecs.umich.edu // comes back (but before this target is processed) 2755135Sgblack@eecs.umich.edu // - this target requires an exclusive block and either we're not 2765135Sgblack@eecs.umich.edu // getting an exclusive block back or we have already snooped 2775135Sgblack@eecs.umich.edu // another read request that will downgrade our exclusive block 2785135Sgblack@eecs.umich.edu // to shared 2795135Sgblack@eecs.umich.edu 2805234Sgblack@eecs.umich.edu // assume we'd never issue a prefetch when we've got an 2815135Sgblack@eecs.umich.edu // outstanding miss 2825135Sgblack@eecs.umich.edu assert(pkt->cmd != MemCmd::HardPFReq); 2835135Sgblack@eecs.umich.edu 2845234Sgblack@eecs.umich.edu if (inService && 2855234Sgblack@eecs.umich.edu (!deferredTargets->empty() || hasPostInvalidate() || 2865234Sgblack@eecs.umich.edu (pkt->needsExclusive() && 2875234Sgblack@eecs.umich.edu (!isPendingDirty() || hasPostDowngrade() || isForward)))) { 2885234Sgblack@eecs.umich.edu // need to put on deferred list 2895234Sgblack@eecs.umich.edu if (hasPostInvalidate()) 2905234Sgblack@eecs.umich.edu replaceUpgrade(pkt); 2915234Sgblack@eecs.umich.edu deferredTargets->add(pkt, whenReady, _order, Target::FromCPU, true); 2925234Sgblack@eecs.umich.edu } else { 2935086Sgblack@eecs.umich.edu // No request outstanding, or still OK to append to 294 // outstanding request: append to regular target list. Only 295 // mark pending if current request hasn't been issued yet 296 // (isn't in service). 297 targets->add(pkt, whenReady, _order, Target::FromCPU, !inService); 298 } 299 300 ++ntargets; 301} 302 303bool 304MSHR::handleSnoop(PacketPtr pkt, Counter _order) 305{ 306 if (!inService || (pkt->isExpressSnoop() && downstreamPending)) { 307 // Request has not been issued yet, or it's been issued 308 // locally but is buffered unissued at some downstream cache 309 // which is forwarding us this snoop. Either way, the packet 310 // we're snooping logically precedes this MSHR's request, so 311 // the snoop has no impact on the MSHR, but must be processed 312 // in the standard way by the cache. The only exception is 313 // that if we're an L2+ cache buffering an UpgradeReq from a 314 // higher-level cache, and the snoop is invalidating, then our 315 // buffered upgrades must be converted to read exclusives, 316 // since the upper-level cache no longer has a valid copy. 317 // That is, even though the upper-level cache got out on its 318 // local bus first, some other invalidating transaction 319 // reached the global bus before the upgrade did. 320 if (pkt->needsExclusive()) { 321 targets->replaceUpgrades(); 322 deferredTargets->replaceUpgrades(); 323 } 324 325 return false; 326 } 327 328 // From here on down, the request issued by this MSHR logically 329 // precedes the request we're snooping. 330 if (pkt->needsExclusive()) { 331 // snooped request still precedes the re-request we'll have to 332 // issue for deferred targets, if any... 333 deferredTargets->replaceUpgrades(); 334 } 335 336 if (hasPostInvalidate()) { 337 // a prior snoop has already appended an invalidation, so 338 // logically we don't have the block anymore; no need for 339 // further snooping. 340 return true; 341 } 342 343 if (isPendingDirty() || pkt->isInvalidate()) { 344 // We need to save and replay the packet in two cases: 345 // 1. We're awaiting an exclusive copy, so ownership is pending, 346 // and we need to respond after we receive data. 347 // 2. It's an invalidation (e.g., UpgradeReq), and we need 348 // to forward the snoop up the hierarchy after the current 349 // transaction completes. 350 351 // Actual target device (typ. a memory) will delete the 352 // packet on reception, so we need to save a copy here. 353 PacketPtr cp_pkt = new Packet(pkt, true); 354 targets->add(cp_pkt, curTick(), _order, Target::FromSnoop, 355 downstreamPending && targets->needsExclusive); 356 ++ntargets; 357 358 if (isPendingDirty()) { 359 pkt->assertMemInhibit(); 360 pkt->setSupplyExclusive(); 361 } 362 363 if (pkt->needsExclusive()) { 364 // This transaction will take away our pending copy 365 postInvalidate = true; 366 } 367 } 368 369 if (!pkt->needsExclusive()) { 370 // This transaction will get a read-shared copy, downgrading 371 // our copy if we had an exclusive one 372 postDowngrade = true; 373 pkt->assertShared(); 374 } 375 376 return true; 377} 378 379 380bool 381MSHR::promoteDeferredTargets() 382{ 383 assert(targets->empty()); 384 if (deferredTargets->empty()) { 385 return false; 386 } 387 388 // swap targets & deferredTargets lists 389 TargetList *tmp = targets; 390 targets = deferredTargets; 391 deferredTargets = tmp; 392 393 assert(targets->size() == ntargets); 394 395 // clear deferredTargets flags 396 deferredTargets->resetFlags(); 397 398 order = targets->front().order; 399 readyTime = std::max(curTick(), targets->front().readyTime); 400 401 return true; 402} 403 404 405void 406MSHR::handleFill(Packet *pkt, CacheBlk *blk) 407{ 408 if (!pkt->sharedAsserted() 409 && !(hasPostInvalidate() || hasPostDowngrade()) 410 && deferredTargets->needsExclusive) { 411 // We got an exclusive response, but we have deferred targets 412 // which are waiting to request an exclusive copy (not because 413 // of a pending invalidate). This can happen if the original 414 // request was for a read-only (non-exclusive) block, but we 415 // got an exclusive copy anyway because of the E part of the 416 // MOESI/MESI protocol. Since we got the exclusive copy 417 // there's no need to defer the targets, so move them up to 418 // the regular target list. 419 assert(!targets->needsExclusive); 420 targets->needsExclusive = true; 421 // if any of the deferred targets were upper-level cache 422 // requests marked downstreamPending, need to clear that 423 assert(!downstreamPending); // not pending here anymore 424 deferredTargets->clearDownstreamPending(); 425 // this clears out deferredTargets too 426 targets->splice(targets->end(), *deferredTargets); 427 deferredTargets->resetFlags(); 428 } 429} 430 431 432bool 433MSHR::checkFunctional(PacketPtr pkt) 434{ 435 // For printing, we treat the MSHR as a whole as single entity. 436 // For other requests, we iterate over the individual targets 437 // since that's where the actual data lies. 438 if (pkt->isPrint()) { 439 pkt->checkFunctional(this, addr, size, NULL); 440 return false; 441 } else { 442 return (targets->checkFunctional(pkt) || 443 deferredTargets->checkFunctional(pkt)); 444 } 445} 446 447 448void 449MSHR::print(std::ostream &os, int verbosity, const std::string &prefix) const 450{ 451 ccprintf(os, "%s[%x:%x] %s %s %s state: %s %s %s %s\n", 452 prefix, addr, addr+size-1, 453 isForward ? "Forward" : "", 454 isForwardNoResponse() ? "ForwNoResp" : "", 455 needsExclusive() ? "Excl" : "", 456 _isUncacheable ? "Unc" : "", 457 inService ? "InSvc" : "", 458 downstreamPending ? "DwnPend" : "", 459 hasPostInvalidate() ? "PostInv" : "", 460 hasPostDowngrade() ? "PostDowngr" : ""); 461 462 ccprintf(os, "%s Targets:\n", prefix); 463 targets->print(os, verbosity, prefix + " "); 464 if (!deferredTargets->empty()) { 465 ccprintf(os, "%s Deferred Targets:\n", prefix); 466 deferredTargets->print(os, verbosity, prefix + " "); 467 } 468} 469 470MSHR::~MSHR() 471{ 472 delete[] targets; 473 delete[] deferredTargets; 474} 475