mshr.cc revision 5314
16019Shines@cs.fsu.edu/* 27093Sgblack@eecs.umich.edu * Copyright (c) 2002-2005 The Regents of The University of Michigan 37093Sgblack@eecs.umich.edu * All rights reserved. 47093Sgblack@eecs.umich.edu * 57093Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without 67093Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are 77093Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright 87093Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer; 97093Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright 107093Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the 117093Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution; 127093Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its 137093Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from 146019Shines@cs.fsu.edu * this software without specific prior written permission. 156019Shines@cs.fsu.edu * 166019Shines@cs.fsu.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 176019Shines@cs.fsu.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 186019Shines@cs.fsu.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 196019Shines@cs.fsu.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 206019Shines@cs.fsu.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 216019Shines@cs.fsu.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 226019Shines@cs.fsu.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 236019Shines@cs.fsu.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 246019Shines@cs.fsu.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 256019Shines@cs.fsu.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 266019Shines@cs.fsu.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 276019Shines@cs.fsu.edu * 286019Shines@cs.fsu.edu * Authors: Erik Hallnor 296019Shines@cs.fsu.edu * Dave Greene 306019Shines@cs.fsu.edu */ 316019Shines@cs.fsu.edu 326019Shines@cs.fsu.edu/** 336019Shines@cs.fsu.edu * @file 346019Shines@cs.fsu.edu * Miss Status and Handling Register (MSHR) definitions. 356019Shines@cs.fsu.edu */ 366019Shines@cs.fsu.edu 376019Shines@cs.fsu.edu#include <assert.h> 386019Shines@cs.fsu.edu#include <string> 396019Shines@cs.fsu.edu#include <vector> 406019Shines@cs.fsu.edu#include <algorithm> 416735Sgblack@eecs.umich.edu 426735Sgblack@eecs.umich.edu#include "mem/cache/miss/mshr.hh" 436019Shines@cs.fsu.edu#include "sim/core.hh" // for curTick 446019Shines@cs.fsu.edu#include "sim/host.hh" 456019Shines@cs.fsu.edu#include "base/misc.hh" 468229Snate@binkert.org#include "mem/cache/cache.hh" 478229Snate@binkert.org 486019Shines@cs.fsu.eduusing namespace std; 498232Snate@binkert.org 508782Sgblack@eecs.umich.eduMSHR::MSHR() 516019Shines@cs.fsu.edu{ 526019Shines@cs.fsu.edu inService = false; 536019Shines@cs.fsu.edu ntargets = 0; 546019Shines@cs.fsu.edu threadNum = -1; 557362Sgblack@eecs.umich.edu targets = new TargetList(); 566735Sgblack@eecs.umich.edu deferredTargets = new TargetList(); 576019Shines@cs.fsu.edu} 587362Sgblack@eecs.umich.edu 596735Sgblack@eecs.umich.edu 606019Shines@cs.fsu.eduMSHR::TargetList::TargetList() 617362Sgblack@eecs.umich.edu : needsExclusive(false), hasUpgrade(false) 626735Sgblack@eecs.umich.edu{} 636019Shines@cs.fsu.edu 647362Sgblack@eecs.umich.edu 656735Sgblack@eecs.umich.eduinline void 666019Shines@cs.fsu.eduMSHR::TargetList::add(PacketPtr pkt, Tick readyTime, 677362Sgblack@eecs.umich.edu Counter order, bool cpuSide) 686735Sgblack@eecs.umich.edu{ 696019Shines@cs.fsu.edu if (cpuSide) { 707362Sgblack@eecs.umich.edu if (pkt->needsExclusive()) { 716735Sgblack@eecs.umich.edu needsExclusive = true; 726019Shines@cs.fsu.edu } 737362Sgblack@eecs.umich.edu 746735Sgblack@eecs.umich.edu if (pkt->cmd == MemCmd::UpgradeReq) { 756019Shines@cs.fsu.edu hasUpgrade = true; 767652Sminkyu.jeong@arm.com } 777652Sminkyu.jeong@arm.com 787652Sminkyu.jeong@arm.com MSHR *mshr = dynamic_cast<MSHR*>(pkt->senderState); 798518Sgeoffrey.blake@arm.com if (mshr != NULL) { 808518Sgeoffrey.blake@arm.com assert(!mshr->downstreamPending); 816735Sgblack@eecs.umich.edu mshr->downstreamPending = true; 827362Sgblack@eecs.umich.edu } 836735Sgblack@eecs.umich.edu } 846735Sgblack@eecs.umich.edu 856019Shines@cs.fsu.edu push_back(Target(pkt, readyTime, order, cpuSide)); 866735Sgblack@eecs.umich.edu} 877400SAli.Saidi@ARM.com 886735Sgblack@eecs.umich.edu 896735Sgblack@eecs.umich.eduvoid 906735Sgblack@eecs.umich.eduMSHR::TargetList::replaceUpgrades() 917400SAli.Saidi@ARM.com{ 926735Sgblack@eecs.umich.edu if (!hasUpgrade) 936735Sgblack@eecs.umich.edu return; 946735Sgblack@eecs.umich.edu 956019Shines@cs.fsu.edu Iterator end_i = end(); 966019Shines@cs.fsu.edu for (Iterator i = begin(); i != end_i; ++i) { 976019Shines@cs.fsu.edu if (i->pkt->cmd == MemCmd::UpgradeReq) { 986735Sgblack@eecs.umich.edu i->pkt->cmd = MemCmd::ReadExReq; 997678Sgblack@eecs.umich.edu DPRINTF(Cache, "Replacing UpgradeReq with ReadExReq\n"); 1006019Shines@cs.fsu.edu } 1016735Sgblack@eecs.umich.edu } 1026735Sgblack@eecs.umich.edu 1038782Sgblack@eecs.umich.edu hasUpgrade = false; 1048782Sgblack@eecs.umich.edu} 1056735Sgblack@eecs.umich.edu 1066019Shines@cs.fsu.edu 1076735Sgblack@eecs.umich.eduvoid 1086735Sgblack@eecs.umich.eduMSHR::TargetList::clearDownstreamPending() 1098303SAli.Saidi@ARM.com{ 1108303SAli.Saidi@ARM.com Iterator end_i = end(); 1118303SAli.Saidi@ARM.com for (Iterator i = begin(); i != end_i; ++i) { 1128303SAli.Saidi@ARM.com MSHR *mshr = dynamic_cast<MSHR*>(i->pkt->senderState); 1138303SAli.Saidi@ARM.com if (mshr != NULL) { 1148303SAli.Saidi@ARM.com assert(mshr->downstreamPending); 1157720Sgblack@eecs.umich.edu mshr->downstreamPending = false; 1168205SAli.Saidi@ARM.com } 1178205SAli.Saidi@ARM.com } 1188205SAli.Saidi@ARM.com} 1196735Sgblack@eecs.umich.edu 1206735Sgblack@eecs.umich.edu 1216735Sgblack@eecs.umich.edubool 1226735Sgblack@eecs.umich.eduMSHR::TargetList::checkFunctional(PacketPtr pkt) 1236735Sgblack@eecs.umich.edu{ 1247093Sgblack@eecs.umich.edu Iterator end_i = end(); 1256735Sgblack@eecs.umich.edu for (Iterator i = begin(); i != end_i; ++i) { 1266735Sgblack@eecs.umich.edu if (pkt->checkFunctional(i->pkt)) { 1276735Sgblack@eecs.umich.edu return true; 1287302Sgblack@eecs.umich.edu } 1296735Sgblack@eecs.umich.edu } 1308518Sgeoffrey.blake@arm.com 1318518Sgeoffrey.blake@arm.com return false; 1327720Sgblack@eecs.umich.edu} 1336735Sgblack@eecs.umich.edu 1346735Sgblack@eecs.umich.edu 1356735Sgblack@eecs.umich.eduvoid 1366735Sgblack@eecs.umich.eduMSHR::TargetList:: 1376735Sgblack@eecs.umich.eduprint(std::ostream &os, int verbosity, const std::string &prefix) const 1386735Sgblack@eecs.umich.edu{ 1396735Sgblack@eecs.umich.edu ConstIterator end_i = end(); 1406735Sgblack@eecs.umich.edu for (ConstIterator i = begin(); i != end_i; ++i) { 1416735Sgblack@eecs.umich.edu ccprintf(os, "%s%s: ", prefix, i->isCpuSide() ? "cpu" : "mem"); 1426735Sgblack@eecs.umich.edu i->pkt->print(os, verbosity, ""); 1436735Sgblack@eecs.umich.edu } 1446735Sgblack@eecs.umich.edu} 1456735Sgblack@eecs.umich.edu 1466735Sgblack@eecs.umich.edu 1476735Sgblack@eecs.umich.eduvoid 1486735Sgblack@eecs.umich.eduMSHR::allocate(Addr _addr, int _size, PacketPtr target, 1496735Sgblack@eecs.umich.edu Tick whenReady, Counter _order) 1506735Sgblack@eecs.umich.edu{ 1516735Sgblack@eecs.umich.edu addr = _addr; 1526735Sgblack@eecs.umich.edu size = _size; 1537093Sgblack@eecs.umich.edu readyTime = whenReady; 1547093Sgblack@eecs.umich.edu order = _order; 1557720Sgblack@eecs.umich.edu assert(target); 1567585SAli.Saidi@arm.com isCacheFill = false; 1577720Sgblack@eecs.umich.edu _isUncacheable = target->req->isUncacheable(); 1587720Sgblack@eecs.umich.edu inService = false; 1597720Sgblack@eecs.umich.edu downstreamPending = false; 1607720Sgblack@eecs.umich.edu threadNum = 0; 1617720Sgblack@eecs.umich.edu ntargets = 1; 1627720Sgblack@eecs.umich.edu // Don't know of a case where we would allocate a new MSHR for a 1637720Sgblack@eecs.umich.edu // snoop (mem-side request), so set cpuSide to true here. 1646019Shines@cs.fsu.edu assert(targets->isReset()); 1657189Sgblack@eecs.umich.edu targets->add(target, whenReady, _order, true); 1667400SAli.Saidi@ARM.com assert(deferredTargets->isReset()); 1677678Sgblack@eecs.umich.edu pendingInvalidate = false; 1687400SAli.Saidi@ARM.com pendingShared = false; 1698782Sgblack@eecs.umich.edu data = NULL; 1708782Sgblack@eecs.umich.edu} 1718782Sgblack@eecs.umich.edu 1728782Sgblack@eecs.umich.edu 1738205SAli.Saidi@ARM.combool 1747400SAli.Saidi@ARM.comMSHR::markInService() 1757400SAli.Saidi@ARM.com{ 1767189Sgblack@eecs.umich.edu assert(!inService); 1777678Sgblack@eecs.umich.edu if (isSimpleForward()) { 1787189Sgblack@eecs.umich.edu // we just forwarded the request packet & don't expect a 1798782Sgblack@eecs.umich.edu // response, so get rid of it 1808782Sgblack@eecs.umich.edu assert(getNumTargets() == 1); 1818806Sgblack@eecs.umich.edu popTarget(); 1828806Sgblack@eecs.umich.edu return true; 1838806Sgblack@eecs.umich.edu } 1848806Sgblack@eecs.umich.edu inService = true; 1858806Sgblack@eecs.umich.edu if (!downstreamPending) { 1868806Sgblack@eecs.umich.edu // let upstream caches know that the request has made it to a 1878806Sgblack@eecs.umich.edu // level where it's going to get a response 1888806Sgblack@eecs.umich.edu targets->clearDownstreamPending(); 1898806Sgblack@eecs.umich.edu } 1908806Sgblack@eecs.umich.edu return false; 1918806Sgblack@eecs.umich.edu} 1927189Sgblack@eecs.umich.edu 1938806Sgblack@eecs.umich.edu 1948806Sgblack@eecs.umich.eduvoid 1957189Sgblack@eecs.umich.eduMSHR::deallocate() 1967189Sgblack@eecs.umich.edu{ 1977189Sgblack@eecs.umich.edu assert(targets->empty()); 1987197Sgblack@eecs.umich.edu targets->resetFlags(); 1997678Sgblack@eecs.umich.edu assert(deferredTargets->isReset()); 2007197Sgblack@eecs.umich.edu assert(ntargets == 0); 2018782Sgblack@eecs.umich.edu inService = false; 2028782Sgblack@eecs.umich.edu //allocIter = NULL; 2038806Sgblack@eecs.umich.edu //readyIter = NULL; 2048806Sgblack@eecs.umich.edu} 2057197Sgblack@eecs.umich.edu 2068806Sgblack@eecs.umich.edu/* 2078806Sgblack@eecs.umich.edu * Adds a target to an MSHR 2088806Sgblack@eecs.umich.edu */ 2098806Sgblack@eecs.umich.eduvoid 2108806Sgblack@eecs.umich.eduMSHR::allocateTarget(PacketPtr pkt, Tick whenReady, Counter _order) 2118806Sgblack@eecs.umich.edu{ 2128806Sgblack@eecs.umich.edu // if there's a request already in service for this MSHR, we will 2138806Sgblack@eecs.umich.edu // have to defer the new target until after the response if any of 2148806Sgblack@eecs.umich.edu // the following are true: 2158806Sgblack@eecs.umich.edu // - there are other targets already deferred 2168806Sgblack@eecs.umich.edu // - there's a pending invalidate to be applied after the response 2177197Sgblack@eecs.umich.edu // comes back (but before this target is processed) 2187197Sgblack@eecs.umich.edu // - the outstanding request is for a non-exclusive block and this 2197362Sgblack@eecs.umich.edu // target requires an exclusive block 2207362Sgblack@eecs.umich.edu if (inService && 2217678Sgblack@eecs.umich.edu (!deferredTargets->empty() || pendingInvalidate || 2227362Sgblack@eecs.umich.edu (!targets->needsExclusive && pkt->needsExclusive()))) { 2238205SAli.Saidi@ARM.com // need to put on deferred list 2247362Sgblack@eecs.umich.edu deferredTargets->add(pkt, whenReady, _order, true); 2257362Sgblack@eecs.umich.edu } else { 2267362Sgblack@eecs.umich.edu // no request outstanding, or still OK to append to 2277362Sgblack@eecs.umich.edu // outstanding request 2287362Sgblack@eecs.umich.edu targets->add(pkt, whenReady, _order, true); 2297362Sgblack@eecs.umich.edu } 2307362Sgblack@eecs.umich.edu 2317362Sgblack@eecs.umich.edu ++ntargets; 2328314Sgeoffrey.blake@arm.com} 2338314Sgeoffrey.blake@arm.com 2347362Sgblack@eecs.umich.edubool 2357362Sgblack@eecs.umich.eduMSHR::handleSnoop(PacketPtr pkt, Counter _order) 2367652Sminkyu.jeong@arm.com{ 2377678Sgblack@eecs.umich.edu if (!inService || (pkt->isExpressSnoop() && downstreamPending)) { 2387652Sminkyu.jeong@arm.com // Request has not been issued yet, or it's been issued 2397652Sminkyu.jeong@arm.com // locally but is buffered unissued at some downstream cache 2407652Sminkyu.jeong@arm.com // which is forwarding us this snoop. Either way, the packet 2417652Sminkyu.jeong@arm.com // we're snooping logically precedes this MSHR's request, so 2427652Sminkyu.jeong@arm.com // the snoop has no impact on the MSHR, but must be processed 2437720Sgblack@eecs.umich.edu // in the standard way by the cache. The only exception is 2447720Sgblack@eecs.umich.edu // that if we're an L2+ cache buffering an UpgradeReq from a 2457720Sgblack@eecs.umich.edu // higher-level cache, and the snoop is invalidating, then our 2467720Sgblack@eecs.umich.edu // buffered upgrades must be converted to read exclusives, 2477652Sminkyu.jeong@arm.com // since the upper-level cache no longer has a valid copy. 2487652Sminkyu.jeong@arm.com // That is, even though the upper-level cache got out on its 2497678Sgblack@eecs.umich.edu // local bus first, some other invalidating transaction 2507678Sgblack@eecs.umich.edu // reached the global bus before the upgrade did. 2517678Sgblack@eecs.umich.edu if (pkt->needsExclusive()) { 2527678Sgblack@eecs.umich.edu targets->replaceUpgrades(); 2537362Sgblack@eecs.umich.edu deferredTargets->replaceUpgrades(); 2548518Sgeoffrey.blake@arm.com } 2558518Sgeoffrey.blake@arm.com 2568518Sgeoffrey.blake@arm.com return false; 2578806Sgblack@eecs.umich.edu } 2588806Sgblack@eecs.umich.edu 2598806Sgblack@eecs.umich.edu // From here on down, the request issued by this MSHR logically 2608806Sgblack@eecs.umich.edu // precedes the request we're snooping. 2618806Sgblack@eecs.umich.edu 2628806Sgblack@eecs.umich.edu if (pkt->needsExclusive()) { 2638806Sgblack@eecs.umich.edu // snooped request still precedes the re-request we'll have to 2648806Sgblack@eecs.umich.edu // issue for deferred targets, if any... 2658518Sgeoffrey.blake@arm.com deferredTargets->replaceUpgrades(); 2668518Sgeoffrey.blake@arm.com } 2676735Sgblack@eecs.umich.edu 2686019Shines@cs.fsu.edu if (pendingInvalidate) { 2696019Shines@cs.fsu.edu // a prior snoop has already appended an invalidation, so 270 // logically we don't have the block anymore; no need for 271 // further snooping. 272 return true; 273 } 274 275 if (targets->needsExclusive || pkt->needsExclusive()) { 276 // actual target device (typ. PhysicalMemory) will delete the 277 // packet on reception, so we need to save a copy here 278 PacketPtr cp_pkt = new Packet(pkt, true); 279 targets->add(cp_pkt, curTick, _order, false); 280 ++ntargets; 281 282 if (targets->needsExclusive) { 283 // We're awaiting an exclusive copy, so ownership is pending. 284 // It's up to us to respond once the data arrives. 285 pkt->assertMemInhibit(); 286 pkt->setSupplyExclusive(); 287 } else { 288 // Someone else may respond before we get around to 289 // processing this snoop, which means the copied request 290 // pointer will no longer be valid 291 cp_pkt->req = NULL; 292 } 293 294 if (pkt->needsExclusive()) { 295 // This transaction will take away our pending copy 296 pendingInvalidate = true; 297 } 298 } else { 299 // Read to a read: no conflict, so no need to record as 300 // target, but make sure neither reader thinks he's getting an 301 // exclusive copy 302 pendingShared = true; 303 pkt->assertShared(); 304 } 305 306 return true; 307} 308 309 310bool 311MSHR::promoteDeferredTargets() 312{ 313 assert(targets->empty()); 314 if (deferredTargets->empty()) { 315 return false; 316 } 317 318 // swap targets & deferredTargets lists 319 TargetList *tmp = targets; 320 targets = deferredTargets; 321 deferredTargets = tmp; 322 323 assert(targets->size() == ntargets); 324 325 // clear deferredTargets flags 326 deferredTargets->resetFlags(); 327 328 pendingInvalidate = false; 329 pendingShared = false; 330 order = targets->front().order; 331 readyTime = std::max(curTick, targets->front().readyTime); 332 333 return true; 334} 335 336 337void 338MSHR::handleFill(Packet *pkt, CacheBlk *blk) 339{ 340 if (pendingShared) { 341 // we snooped another read while this read was in 342 // service... assert shared line on its behalf 343 pkt->assertShared(); 344 } 345 346 if (!pkt->sharedAsserted() && !pendingInvalidate 347 && deferredTargets->needsExclusive) { 348 // We got an exclusive response, but we have deferred targets 349 // which are waiting to request an exclusive copy (not because 350 // of a pending invalidate). This can happen if the original 351 // request was for a read-only (non-exclusive) block, but we 352 // got an exclusive copy anyway because of the E part of the 353 // MOESI/MESI protocol. Since we got the exclusive copy 354 // there's no need to defer the targets, so move them up to 355 // the regular target list. 356 assert(!targets->needsExclusive); 357 targets->needsExclusive = true; 358 // this clears out deferredTargets too 359 targets->splice(targets->end(), *deferredTargets); 360 deferredTargets->resetFlags(); 361 } 362} 363 364 365bool 366MSHR::checkFunctional(PacketPtr pkt) 367{ 368 // For printing, we treat the MSHR as a whole as single entity. 369 // For other requests, we iterate over the individual targets 370 // since that's where the actual data lies. 371 if (pkt->isPrint()) { 372 pkt->checkFunctional(this, addr, size, NULL); 373 return false; 374 } else { 375 return (targets->checkFunctional(pkt) || 376 deferredTargets->checkFunctional(pkt)); 377 } 378} 379 380 381void 382MSHR::print(std::ostream &os, int verbosity, const std::string &prefix) const 383{ 384 ccprintf(os, "%s[%x:%x] %s %s %s state: %s %s %s %s\n", 385 prefix, addr, addr+size-1, 386 isCacheFill ? "Fill" : "", 387 needsExclusive() ? "Excl" : "", 388 _isUncacheable ? "Unc" : "", 389 inService ? "InSvc" : "", 390 downstreamPending ? "DwnPend" : "", 391 pendingInvalidate ? "PendInv" : "", 392 pendingShared ? "PendShared" : ""); 393 394 ccprintf(os, "%s Targets:\n", prefix); 395 targets->print(os, verbosity, prefix + " "); 396 if (!deferredTargets->empty()) { 397 ccprintf(os, "%s Deferred Targets:\n", prefix); 398 deferredTargets->print(os, verbosity, prefix + " "); 399 } 400} 401 402MSHR::~MSHR() 403{ 404} 405