mshr.cc revision 5270
12221SN/A/* 22221SN/A * Copyright (c) 2002-2005 The Regents of The University of Michigan 32221SN/A * All rights reserved. 42221SN/A * 52221SN/A * Redistribution and use in source and binary forms, with or without 62221SN/A * modification, are permitted provided that the following conditions are 72221SN/A * met: redistributions of source code must retain the above copyright 82221SN/A * notice, this list of conditions and the following disclaimer; 92221SN/A * redistributions in binary form must reproduce the above copyright 102221SN/A * notice, this list of conditions and the following disclaimer in the 112221SN/A * documentation and/or other materials provided with the distribution; 122221SN/A * neither the name of the copyright holders nor the names of its 132221SN/A * contributors may be used to endorse or promote products derived from 142221SN/A * this software without specific prior written permission. 152221SN/A * 162221SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 172221SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 182221SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 192221SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 202221SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 212221SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 222221SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 232221SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 242221SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 252221SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 262221SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272665Ssaidi@eecs.umich.edu * 282665Ssaidi@eecs.umich.edu * Authors: Erik Hallnor 292665Ssaidi@eecs.umich.edu * Dave Greene 302221SN/A */ 312221SN/A 323415Sgblack@eecs.umich.edu/** 333415Sgblack@eecs.umich.edu * @file 342223SN/A * Miss Status and Handling Register (MSHR) definitions. 353415Sgblack@eecs.umich.edu */ 363578Sgblack@eecs.umich.edu 373415Sgblack@eecs.umich.edu#include <assert.h> 383415Sgblack@eecs.umich.edu#include <string> 393523Sgblack@eecs.umich.edu#include <vector> 403415Sgblack@eecs.umich.edu#include <algorithm> 412680Sktlim@umich.edu 422800Ssaidi@eecs.umich.edu#include "mem/cache/miss/mshr.hh" 433523Sgblack@eecs.umich.edu#include "sim/core.hh" // for curTick 443415Sgblack@eecs.umich.edu#include "sim/host.hh" 452800Ssaidi@eecs.umich.edu#include "base/misc.hh" 462800Ssaidi@eecs.umich.edu#include "mem/cache/cache.hh" 472221SN/A 483415Sgblack@eecs.umich.eduusing namespace std; 493415Sgblack@eecs.umich.edu 502223SN/AMSHR::MSHR() 512221SN/A{ 522221SN/A inService = false; 533573Sgblack@eecs.umich.edu ntargets = 0; 543576Sgblack@eecs.umich.edu threadNum = -1; 553576Sgblack@eecs.umich.edu targets = new TargetList(); 562221SN/A deferredTargets = new TargetList(); 573573Sgblack@eecs.umich.edu} 583576Sgblack@eecs.umich.edu 593576Sgblack@eecs.umich.edu 602221SN/AMSHR::TargetList::TargetList() 613573Sgblack@eecs.umich.edu : needsExclusive(false), hasUpgrade(false) 623576Sgblack@eecs.umich.edu{} 633576Sgblack@eecs.umich.edu 642221SN/A 653573Sgblack@eecs.umich.eduinline void 663576Sgblack@eecs.umich.eduMSHR::TargetList::add(PacketPtr pkt, Tick readyTime, 673576Sgblack@eecs.umich.edu Counter order, bool cpuSide) 682221SN/A{ 693573Sgblack@eecs.umich.edu if (cpuSide) { 703576Sgblack@eecs.umich.edu if (pkt->needsExclusive()) { 713576Sgblack@eecs.umich.edu needsExclusive = true; 722221SN/A } 733573Sgblack@eecs.umich.edu 743576Sgblack@eecs.umich.edu if (pkt->cmd == MemCmd::UpgradeReq) { 753576Sgblack@eecs.umich.edu hasUpgrade = true; 762221SN/A } 773573Sgblack@eecs.umich.edu 783576Sgblack@eecs.umich.edu MSHR *mshr = dynamic_cast<MSHR*>(pkt->senderState); 793576Sgblack@eecs.umich.edu if (mshr != NULL) { 803576Sgblack@eecs.umich.edu assert(!mshr->downstreamPending); 813576Sgblack@eecs.umich.edu mshr->downstreamPending = true; 823576Sgblack@eecs.umich.edu } 833576Sgblack@eecs.umich.edu } 843576Sgblack@eecs.umich.edu 852221SN/A push_back(Target(pkt, readyTime, order, cpuSide)); 863573Sgblack@eecs.umich.edu} 873576Sgblack@eecs.umich.edu 883576Sgblack@eecs.umich.edu 892221SN/Avoid 903573Sgblack@eecs.umich.eduMSHR::TargetList::replaceUpgrades() 913576Sgblack@eecs.umich.edu{ 923576Sgblack@eecs.umich.edu if (!hasUpgrade) 932221SN/A return; 943573Sgblack@eecs.umich.edu 953576Sgblack@eecs.umich.edu Iterator end_i = end(); 963576Sgblack@eecs.umich.edu for (Iterator i = begin(); i != end_i; ++i) { 973576Sgblack@eecs.umich.edu if (i->pkt->cmd == MemCmd::UpgradeReq) { 983576Sgblack@eecs.umich.edu i->pkt->cmd = MemCmd::ReadExReq; 993576Sgblack@eecs.umich.edu DPRINTF(Cache, "Replacing UpgradeReq with ReadExReq\n"); 1003576Sgblack@eecs.umich.edu } 1013576Sgblack@eecs.umich.edu } 1023576Sgblack@eecs.umich.edu 1033576Sgblack@eecs.umich.edu hasUpgrade = false; 1043576Sgblack@eecs.umich.edu} 1053576Sgblack@eecs.umich.edu 1063576Sgblack@eecs.umich.edu 1072221SN/Avoid 1083573Sgblack@eecs.umich.eduMSHR::TargetList::clearDownstreamPending() 1093576Sgblack@eecs.umich.edu{ 1103576Sgblack@eecs.umich.edu Iterator end_i = end(); 1112221SN/A for (Iterator i = begin(); i != end_i; ++i) { 1123573Sgblack@eecs.umich.edu MSHR *mshr = dynamic_cast<MSHR*>(i->pkt->senderState); 1133576Sgblack@eecs.umich.edu if (mshr != NULL) { 1143576Sgblack@eecs.umich.edu assert(mshr->downstreamPending); 1152221SN/A mshr->downstreamPending = false; 1163573Sgblack@eecs.umich.edu } 1173576Sgblack@eecs.umich.edu } 1183576Sgblack@eecs.umich.edu} 1192221SN/A 1203573Sgblack@eecs.umich.edu 1213576Sgblack@eecs.umich.edubool 1223576Sgblack@eecs.umich.eduMSHR::TargetList::checkFunctional(PacketPtr pkt) 1232221SN/A{ 1243573Sgblack@eecs.umich.edu Iterator end_i = end(); 1253576Sgblack@eecs.umich.edu for (Iterator i = begin(); i != end_i; ++i) { 1263576Sgblack@eecs.umich.edu if (pkt->checkFunctional(i->pkt)) { 1272221SN/A return true; 1283573Sgblack@eecs.umich.edu } 1293576Sgblack@eecs.umich.edu } 1303576Sgblack@eecs.umich.edu 1312223SN/A return false; 1323573Sgblack@eecs.umich.edu} 1333576Sgblack@eecs.umich.edu 1343576Sgblack@eecs.umich.edu 1352223SN/Avoid 1363573Sgblack@eecs.umich.eduMSHR::allocate(Addr _addr, int _size, PacketPtr target, 1373576Sgblack@eecs.umich.edu Tick whenReady, Counter _order) 1383576Sgblack@eecs.umich.edu{ 1392223SN/A addr = _addr; 1403573Sgblack@eecs.umich.edu size = _size; 1413576Sgblack@eecs.umich.edu readyTime = whenReady; 1423576Sgblack@eecs.umich.edu order = _order; 1432223SN/A assert(target); 1443573Sgblack@eecs.umich.edu isCacheFill = false; 1453576Sgblack@eecs.umich.edu _isUncacheable = target->req->isUncacheable(); 1463576Sgblack@eecs.umich.edu inService = false; 1473576Sgblack@eecs.umich.edu downstreamPending = false; 1483576Sgblack@eecs.umich.edu threadNum = 0; 1493576Sgblack@eecs.umich.edu ntargets = 1; 1503576Sgblack@eecs.umich.edu // Don't know of a case where we would allocate a new MSHR for a 1513576Sgblack@eecs.umich.edu // snoop (mem-side request), so set cpuSide to true here. 1522223SN/A assert(targets->isReset()); 1533573Sgblack@eecs.umich.edu targets->add(target, whenReady, _order, true); 1543576Sgblack@eecs.umich.edu assert(deferredTargets->isReset()); 1553576Sgblack@eecs.umich.edu pendingInvalidate = false; 1562223SN/A pendingShared = false; 1573573Sgblack@eecs.umich.edu data = NULL; 1583576Sgblack@eecs.umich.edu} 1593576Sgblack@eecs.umich.edu 1602223SN/A 1613573Sgblack@eecs.umich.edubool 1623576Sgblack@eecs.umich.eduMSHR::markInService() 1633576Sgblack@eecs.umich.edu{ 1642223SN/A assert(!inService); 1653573Sgblack@eecs.umich.edu if (isSimpleForward()) { 1663576Sgblack@eecs.umich.edu // we just forwarded the request packet & don't expect a 1673576Sgblack@eecs.umich.edu // response, so get rid of it 1682223SN/A assert(getNumTargets() == 1); 1693573Sgblack@eecs.umich.edu popTarget(); 1703576Sgblack@eecs.umich.edu return true; 1713576Sgblack@eecs.umich.edu } 1722223SN/A inService = true; 1733573Sgblack@eecs.umich.edu if (!downstreamPending) { 1743576Sgblack@eecs.umich.edu // let upstream caches know that the request has made it to a 1753576Sgblack@eecs.umich.edu // level where it's going to get a response 1762223SN/A targets->clearDownstreamPending(); 1773573Sgblack@eecs.umich.edu } 1783576Sgblack@eecs.umich.edu return false; 1793576Sgblack@eecs.umich.edu} 1802223SN/A 1813573Sgblack@eecs.umich.edu 1823576Sgblack@eecs.umich.eduvoid 1833576Sgblack@eecs.umich.eduMSHR::deallocate() 1842223SN/A{ 1853573Sgblack@eecs.umich.edu assert(targets->empty()); 1863576Sgblack@eecs.umich.edu targets->resetFlags(); 1873576Sgblack@eecs.umich.edu assert(deferredTargets->isReset()); 1882223SN/A assert(ntargets == 0); 1893573Sgblack@eecs.umich.edu inService = false; 1903576Sgblack@eecs.umich.edu //allocIter = NULL; 1913576Sgblack@eecs.umich.edu //readyIter = NULL; 1922223SN/A} 1933576Sgblack@eecs.umich.edu 1943576Sgblack@eecs.umich.edu/* 1953576Sgblack@eecs.umich.edu * Adds a target to an MSHR 1963576Sgblack@eecs.umich.edu */ 1972527SN/Avoid 1983573Sgblack@eecs.umich.eduMSHR::allocateTarget(PacketPtr pkt, Tick whenReady, Counter _order) 1993576Sgblack@eecs.umich.edu{ 2003576Sgblack@eecs.umich.edu // if there's a request already in service for this MSHR, we will 2012223SN/A // have to defer the new target until after the response if any of 2023573Sgblack@eecs.umich.edu // the following are true: 2033576Sgblack@eecs.umich.edu // - there are other targets already deferred 2043576Sgblack@eecs.umich.edu // - there's a pending invalidate to be applied after the response 2052223SN/A // comes back (but before this target is processed) 2063573Sgblack@eecs.umich.edu // - the outstanding request is for a non-exclusive block and this 2073576Sgblack@eecs.umich.edu // target requires an exclusive block 2083576Sgblack@eecs.umich.edu if (inService && 2092223SN/A (!deferredTargets->empty() || pendingInvalidate || 2103573Sgblack@eecs.umich.edu (!targets->needsExclusive && pkt->needsExclusive()))) { 2113576Sgblack@eecs.umich.edu // need to put on deferred list 2123576Sgblack@eecs.umich.edu deferredTargets->add(pkt, whenReady, _order, true); 2132223SN/A } else { 2143573Sgblack@eecs.umich.edu // no request outstanding, or still OK to append to 2153576Sgblack@eecs.umich.edu // outstanding request 2163576Sgblack@eecs.umich.edu targets->add(pkt, whenReady, _order, true); 2172223SN/A } 2183573Sgblack@eecs.umich.edu 2193576Sgblack@eecs.umich.edu ++ntargets; 2203576Sgblack@eecs.umich.edu} 2213576Sgblack@eecs.umich.edu 2223576Sgblack@eecs.umich.edubool 2233576Sgblack@eecs.umich.eduMSHR::handleSnoop(PacketPtr pkt, Counter _order) 2243576Sgblack@eecs.umich.edu{ 2253576Sgblack@eecs.umich.edu if (!inService || (pkt->isExpressSnoop() && downstreamPending)) { 2263576Sgblack@eecs.umich.edu // Request has not been issued yet, or it's been issued 2273576Sgblack@eecs.umich.edu // locally but is buffered unissued at some downstream cache 2283576Sgblack@eecs.umich.edu // which is forwarding us this snoop. Either way, the packet 2293576Sgblack@eecs.umich.edu // we're snooping logically precedes this MSHR's request, so 2303576Sgblack@eecs.umich.edu // the snoop has no impact on the MSHR, but must be processed 2313576Sgblack@eecs.umich.edu // in the standard way by the cache. The only exception is 2323576Sgblack@eecs.umich.edu // that if we're an L2+ cache buffering an UpgradeReq from a 2333576Sgblack@eecs.umich.edu // higher-level cache, and the snoop is invalidating, then our 2343576Sgblack@eecs.umich.edu // buffered upgrades must be converted to read exclusives, 2353576Sgblack@eecs.umich.edu // since the upper-level cache no longer has a valid copy. 2363576Sgblack@eecs.umich.edu // That is, even though the upper-level cache got out on its 2373576Sgblack@eecs.umich.edu // local bus first, some other invalidating transaction 2383576Sgblack@eecs.umich.edu // reached the global bus before the upgrade did. 2393576Sgblack@eecs.umich.edu if (pkt->needsExclusive()) { 2403576Sgblack@eecs.umich.edu targets->replaceUpgrades(); 2413576Sgblack@eecs.umich.edu deferredTargets->replaceUpgrades(); 2423576Sgblack@eecs.umich.edu } 2433576Sgblack@eecs.umich.edu 2443576Sgblack@eecs.umich.edu return false; 2453576Sgblack@eecs.umich.edu } 2463576Sgblack@eecs.umich.edu 2473576Sgblack@eecs.umich.edu // From here on down, the request issued by this MSHR logically 2483576Sgblack@eecs.umich.edu // precedes the request we're snooping. 2493576Sgblack@eecs.umich.edu 2503576Sgblack@eecs.umich.edu if (pkt->needsExclusive()) { 2513576Sgblack@eecs.umich.edu // snooped request still precedes the re-request we'll have to 2523576Sgblack@eecs.umich.edu // issue for deferred targets, if any... 2533576Sgblack@eecs.umich.edu deferredTargets->replaceUpgrades(); 2543576Sgblack@eecs.umich.edu } 2553576Sgblack@eecs.umich.edu 2563576Sgblack@eecs.umich.edu if (pendingInvalidate) { 2573576Sgblack@eecs.umich.edu // a prior snoop has already appended an invalidation, so 2583576Sgblack@eecs.umich.edu // logically we don't have the block anymore; no need for 2593576Sgblack@eecs.umich.edu // further snooping. 2603576Sgblack@eecs.umich.edu return true; 2613576Sgblack@eecs.umich.edu } 2623576Sgblack@eecs.umich.edu 2633576Sgblack@eecs.umich.edu if (targets->needsExclusive || pkt->needsExclusive()) { 2643576Sgblack@eecs.umich.edu // actual target device (typ. PhysicalMemory) will delete the 2652223SN/A // packet on reception, so we need to save a copy here 2662800Ssaidi@eecs.umich.edu PacketPtr cp_pkt = new Packet(pkt, true); 2673573Sgblack@eecs.umich.edu targets->add(cp_pkt, curTick, _order, false); 2683576Sgblack@eecs.umich.edu ++ntargets; 2693576Sgblack@eecs.umich.edu 2702800Ssaidi@eecs.umich.edu if (targets->needsExclusive) { 2712800Ssaidi@eecs.umich.edu // We're awaiting an exclusive copy, so ownership is pending. 2723415Sgblack@eecs.umich.edu // It's up to us to respond once the data arrives. 2733578Sgblack@eecs.umich.edu pkt->assertMemInhibit(); 2743578Sgblack@eecs.umich.edu pkt->setSupplyExclusive(); 2753415Sgblack@eecs.umich.edu } else { 2763415Sgblack@eecs.umich.edu // Someone else may respond before we get around to 2773578Sgblack@eecs.umich.edu // processing this snoop, which means the copied request 2783415Sgblack@eecs.umich.edu // pointer will no longer be valid 2793578Sgblack@eecs.umich.edu cp_pkt->req = NULL; 2803578Sgblack@eecs.umich.edu } 2813578Sgblack@eecs.umich.edu 2823578Sgblack@eecs.umich.edu if (pkt->needsExclusive()) { 2833578Sgblack@eecs.umich.edu // This transaction will take away our pending copy 2843578Sgblack@eecs.umich.edu pendingInvalidate = true; 2853578Sgblack@eecs.umich.edu } 2863595Sgblack@eecs.umich.edu } else { 2873746Sgblack@eecs.umich.edu // Read to a read: no conflict, so no need to record as 2883746Sgblack@eecs.umich.edu // target, but make sure neither reader thinks he's getting an 2893746Sgblack@eecs.umich.edu // exclusive copy 2903746Sgblack@eecs.umich.edu pendingShared = true; 2913746Sgblack@eecs.umich.edu pkt->assertShared(); 2923578Sgblack@eecs.umich.edu } 2933578Sgblack@eecs.umich.edu 2943578Sgblack@eecs.umich.edu return true; 2953578Sgblack@eecs.umich.edu} 2963578Sgblack@eecs.umich.edu 2973578Sgblack@eecs.umich.edu 2983578Sgblack@eecs.umich.edubool 2993578Sgblack@eecs.umich.eduMSHR::promoteDeferredTargets() 3003578Sgblack@eecs.umich.edu{ 3013578Sgblack@eecs.umich.edu assert(targets->empty()); 3023578Sgblack@eecs.umich.edu if (deferredTargets->empty()) { 3033578Sgblack@eecs.umich.edu return false; 3043578Sgblack@eecs.umich.edu } 3053578Sgblack@eecs.umich.edu 3063578Sgblack@eecs.umich.edu // swap targets & deferredTargets lists 3073578Sgblack@eecs.umich.edu TargetList *tmp = targets; 3083578Sgblack@eecs.umich.edu targets = deferredTargets; 3093578Sgblack@eecs.umich.edu deferredTargets = tmp; 3103578Sgblack@eecs.umich.edu 3113578Sgblack@eecs.umich.edu assert(targets->size() == ntargets); 3123578Sgblack@eecs.umich.edu 3133578Sgblack@eecs.umich.edu // clear deferredTargets flags 3143578Sgblack@eecs.umich.edu deferredTargets->resetFlags(); 3153578Sgblack@eecs.umich.edu 3163578Sgblack@eecs.umich.edu pendingInvalidate = false; 3173578Sgblack@eecs.umich.edu pendingShared = false; 3183578Sgblack@eecs.umich.edu order = targets->front().order; 3193578Sgblack@eecs.umich.edu readyTime = std::max(curTick, targets->front().readyTime); 3203578Sgblack@eecs.umich.edu 3213578Sgblack@eecs.umich.edu return true; 3223578Sgblack@eecs.umich.edu} 3233578Sgblack@eecs.umich.edu 3243578Sgblack@eecs.umich.edu 3253578Sgblack@eecs.umich.eduvoid 3263578Sgblack@eecs.umich.eduMSHR::handleFill(Packet *pkt, CacheBlk *blk) 3273578Sgblack@eecs.umich.edu{ 3283578Sgblack@eecs.umich.edu if (pendingShared) { 3293578Sgblack@eecs.umich.edu // we snooped another read while this read was in 3303578Sgblack@eecs.umich.edu // service... assert shared line on its behalf 3313578Sgblack@eecs.umich.edu pkt->assertShared(); 3323578Sgblack@eecs.umich.edu } 3333578Sgblack@eecs.umich.edu 3343578Sgblack@eecs.umich.edu if (!pkt->sharedAsserted() && !pendingInvalidate 3353578Sgblack@eecs.umich.edu && deferredTargets->needsExclusive) { 3363578Sgblack@eecs.umich.edu // We got an exclusive response, but we have deferred targets 3373578Sgblack@eecs.umich.edu // which are waiting to request an exclusive copy (not because 3383578Sgblack@eecs.umich.edu // of a pending invalidate). This can happen if the original 3393578Sgblack@eecs.umich.edu // request was for a read-only (non-exclusive) block, but we 3403578Sgblack@eecs.umich.edu // got an exclusive copy anyway because of the E part of the 3413578Sgblack@eecs.umich.edu // MOESI/MESI protocol. Since we got the exclusive copy 3423578Sgblack@eecs.umich.edu // there's no need to defer the targets, so move them up to 3433578Sgblack@eecs.umich.edu // the regular target list. 3443578Sgblack@eecs.umich.edu assert(!targets->needsExclusive); 3453578Sgblack@eecs.umich.edu targets->needsExclusive = true; 3463578Sgblack@eecs.umich.edu // this clears out deferredTargets too 3473578Sgblack@eecs.umich.edu targets->splice(targets->end(), *deferredTargets); 3483746Sgblack@eecs.umich.edu deferredTargets->resetFlags(); 3493746Sgblack@eecs.umich.edu } 3503578Sgblack@eecs.umich.edu} 3513746Sgblack@eecs.umich.edu 3523746Sgblack@eecs.umich.edu 3533746Sgblack@eecs.umich.eduvoid 3543578Sgblack@eecs.umich.eduMSHR::dump() 3553578Sgblack@eecs.umich.edu{ 3563578Sgblack@eecs.umich.edu ccprintf(cerr, 3573578Sgblack@eecs.umich.edu "inService: %d thread: %d\n" 3583578Sgblack@eecs.umich.edu "Addr: %x ntargets %d\n" 3593578Sgblack@eecs.umich.edu "Targets:\n", 3603578Sgblack@eecs.umich.edu inService, threadNum, addr, ntargets); 3613578Sgblack@eecs.umich.edu#if 0 3623578Sgblack@eecs.umich.edu TargetListIterator tar_it = targets->begin(); 3633578Sgblack@eecs.umich.edu for (int i = 0; i < ntargets; i++) { 3643578Sgblack@eecs.umich.edu assert(tar_it != targets->end()); 3653578Sgblack@eecs.umich.edu 3663578Sgblack@eecs.umich.edu ccprintf(cerr, "\t%d: Addr: %x cmd: %s\n", 3673578Sgblack@eecs.umich.edu i, tar_it->pkt->getAddr(), tar_it->pkt->cmdString()); 3683578Sgblack@eecs.umich.edu 3693578Sgblack@eecs.umich.edu tar_it++; 3703578Sgblack@eecs.umich.edu } 3713578Sgblack@eecs.umich.edu#endif 3723578Sgblack@eecs.umich.edu ccprintf(cerr, "\n"); 3733578Sgblack@eecs.umich.edu} 3743578Sgblack@eecs.umich.edu 3753578Sgblack@eecs.umich.eduMSHR::~MSHR() 3763578Sgblack@eecs.umich.edu{ 3773578Sgblack@eecs.umich.edu} 3783578Sgblack@eecs.umich.edu