mshr.cc revision 4908
1360SN/A/* 210850SGiacomo.Gabrielli@arm.com * Copyright (c) 2002-2005 The Regents of The University of Michigan 310796Sbrandon.potter@amd.com * All rights reserved. 410027SChris.Adeniyi-Jones@arm.com * 510027SChris.Adeniyi-Jones@arm.com * Redistribution and use in source and binary forms, with or without 610027SChris.Adeniyi-Jones@arm.com * modification, are permitted provided that the following conditions are 710027SChris.Adeniyi-Jones@arm.com * met: redistributions of source code must retain the above copyright 810027SChris.Adeniyi-Jones@arm.com * notice, this list of conditions and the following disclaimer; 910027SChris.Adeniyi-Jones@arm.com * redistributions in binary form must reproduce the above copyright 1010027SChris.Adeniyi-Jones@arm.com * notice, this list of conditions and the following disclaimer in the 1110027SChris.Adeniyi-Jones@arm.com * documentation and/or other materials provided with the distribution; 1210027SChris.Adeniyi-Jones@arm.com * neither the name of the copyright holders nor the names of its 1310027SChris.Adeniyi-Jones@arm.com * contributors may be used to endorse or promote products derived from 1410027SChris.Adeniyi-Jones@arm.com * this software without specific prior written permission. 151458SN/A * 16360SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17360SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18360SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19360SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20360SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21360SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22360SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23360SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24360SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25360SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26360SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27360SN/A * 28360SN/A * Authors: Erik Hallnor 29360SN/A * Dave Greene 30360SN/A */ 31360SN/A 32360SN/A/** 33360SN/A * @file 34360SN/A * Miss Status and Handling Register (MSHR) definitions. 35360SN/A */ 36360SN/A 37360SN/A#include <assert.h> 38360SN/A#include <string> 39360SN/A#include <vector> 402665Ssaidi@eecs.umich.edu#include <algorithm> 412665Ssaidi@eecs.umich.edu 422665Ssaidi@eecs.umich.edu#include "mem/cache/miss/mshr.hh" 43360SN/A#include "sim/core.hh" // for curTick 44360SN/A#include "sim/host.hh" 451354SN/A#include "base/misc.hh" 461354SN/A#include "mem/cache/cache.hh" 47360SN/A 482764Sstever@eecs.umich.eduusing namespace std; 499202Spalle@lyckegaard.dk 509202Spalle@lyckegaard.dkMSHR::MSHR() 512064SN/A{ 5211799Sbrandon.potter@amd.com inService = false; 5311799Sbrandon.potter@amd.com ntargets = 0; 5411799Sbrandon.potter@amd.com threadNum = -1; 5511799Sbrandon.potter@amd.com targets = new TargetList(); 5611799Sbrandon.potter@amd.com deferredTargets = new TargetList(); 5711799Sbrandon.potter@amd.com} 58360SN/A 59360SN/A 60360SN/AMSHR::TargetList::TargetList() 61360SN/A : needsExclusive(false), hasUpgrade(false) 62360SN/A{} 63360SN/A 641809SN/A 6511800Sbrandon.potter@amd.cominline void 6611392Sbrandon.potter@amd.comMSHR::TargetList::add(PacketPtr pkt, Tick readyTime, 671809SN/A Counter order, bool cpuSide) 6811392Sbrandon.potter@amd.com{ 6911383Sbrandon.potter@amd.com if (cpuSide) { 703113Sgblack@eecs.umich.edu if (pkt->needsExclusive()) { 7111799Sbrandon.potter@amd.com needsExclusive = true; 7211759Sbrandon.potter@amd.com } 7311812Sbaz21@cam.ac.uk 7411812Sbaz21@cam.ac.uk if (pkt->cmd == MemCmd::UpgradeReq) { 7511799Sbrandon.potter@amd.com hasUpgrade = true; 768229Snate@binkert.org } 778229Snate@binkert.org 7811594Santhony.gutierrez@amd.com MSHR *mshr = dynamic_cast<MSHR*>(pkt->senderState); 797075Snate@binkert.org if (mshr != NULL) { 808229Snate@binkert.org assert(!mshr->downstreamPending); 8111856Sbrandon.potter@amd.com mshr->downstreamPending = true; 827075Snate@binkert.org } 83360SN/A } 8411886Sbrandon.potter@amd.com 8511800Sbrandon.potter@amd.com push_back(Target(pkt, readyTime, order, cpuSide)); 8611392Sbrandon.potter@amd.com} 872462SN/A 881354SN/A 896216Snate@binkert.orgvoid 906658Snate@binkert.orgMSHR::TargetList::replaceUpgrades() 912474SN/A{ 922680Sktlim@umich.edu if (!hasUpgrade) 938229Snate@binkert.org return; 9411886Sbrandon.potter@amd.com 9510496Ssteve.reinhardt@amd.com Iterator end_i = end(); 968229Snate@binkert.org for (Iterator i = begin(); i != end_i; ++i) { 9711794Sbrandon.potter@amd.com if (i->pkt->cmd == MemCmd::UpgradeReq) { 9811886Sbrandon.potter@amd.com i->pkt->cmd = MemCmd::ReadExReq; 9910497Ssteve.reinhardt@amd.com DPRINTF(Cache, "Replacing UpgradeReq with ReadExReq\n"); 10011794Sbrandon.potter@amd.com } 101360SN/A } 102360SN/A 103360SN/A hasUpgrade = false; 104360SN/A} 105360SN/A 106360SN/A 107360SN/Avoid 108360SN/AMSHR::TargetList::clearDownstreamPending() 109360SN/A{ 110360SN/A Iterator end_i = end(); 111378SN/A for (Iterator i = begin(); i != end_i; ++i) { 1121706SN/A MSHR *mshr = dynamic_cast<MSHR*>(i->pkt->senderState); 11311851Sbrandon.potter@amd.com if (mshr != NULL) { 114378SN/A assert(mshr->downstreamPending); 115378SN/A mshr->downstreamPending = false; 116378SN/A } 117378SN/A } 118378SN/A} 1191706SN/A 12011851Sbrandon.potter@amd.com 121360SN/Avoid 12211760Sbrandon.potter@amd.comMSHR::allocate(Addr _addr, int _size, PacketPtr target, 12311760Sbrandon.potter@amd.com Tick whenReady, Counter _order) 12411851Sbrandon.potter@amd.com{ 12511760Sbrandon.potter@amd.com addr = _addr; 1266109Ssanchezd@stanford.edu size = _size; 1271706SN/A readyTime = whenReady; 12811851Sbrandon.potter@amd.com order = _order; 129378SN/A assert(target); 1306109Ssanchezd@stanford.edu isCacheFill = false; 1316109Ssanchezd@stanford.edu _isUncacheable = target->req->isUncacheable(); 13211851Sbrandon.potter@amd.com inService = false; 1336109Ssanchezd@stanford.edu downstreamPending = false; 13411886Sbrandon.potter@amd.com threadNum = 0; 13511886Sbrandon.potter@amd.com ntargets = 1; 13611886Sbrandon.potter@amd.com // Don't know of a case where we would allocate a new MSHR for a 13711886Sbrandon.potter@amd.com // snoop (mem-side request), so set cpuSide to true here. 138378SN/A assert(targets->isReset()); 1391706SN/A targets->add(target, whenReady, _order, true); 14011851Sbrandon.potter@amd.com assert(deferredTargets->isReset()); 141378SN/A pendingInvalidate = false; 1425748SSteve.Reinhardt@amd.com pendingShared = false; 1435748SSteve.Reinhardt@amd.com data = NULL; 14411851Sbrandon.potter@amd.com} 145378SN/A 146378SN/A 1471706SN/Abool 14811851Sbrandon.potter@amd.comMSHR::markInService() 149378SN/A{ 15011886Sbrandon.potter@amd.com assert(!inService); 1511706SN/A if (isSimpleForward()) { 15211851Sbrandon.potter@amd.com // we just forwarded the request packet & don't expect a 153378SN/A // response, so get rid of it 154378SN/A assert(getNumTargets() == 1); 1551706SN/A popTarget(); 15611851Sbrandon.potter@amd.com return true; 157378SN/A } 158378SN/A inService = true; 1591706SN/A if (!downstreamPending) { 16011851Sbrandon.potter@amd.com // let upstream caches know that the request has made it to a 161378SN/A // level where it's going to get a response 1624118Sgblack@eecs.umich.edu targets->clearDownstreamPending(); 1634118Sgblack@eecs.umich.edu } 16411851Sbrandon.potter@amd.com return false; 1654118Sgblack@eecs.umich.edu} 166378SN/A 1671706SN/A 16811851Sbrandon.potter@amd.comvoid 169378SN/AMSHR::deallocate() 170378SN/A{ 1711706SN/A assert(targets->empty()); 17211851Sbrandon.potter@amd.com targets->resetFlags(); 173360SN/A assert(deferredTargets->isReset()); 1745513SMichael.Adler@intel.com assert(ntargets == 0); 1755513SMichael.Adler@intel.com inService = false; 17611851Sbrandon.potter@amd.com //allocIter = NULL; 1775513SMichael.Adler@intel.com //readyIter = NULL; 17810203SAli.Saidi@ARM.com} 17910203SAli.Saidi@ARM.com 18011851Sbrandon.potter@amd.com/* 18110203SAli.Saidi@ARM.com * Adds a target to an MSHR 1825513SMichael.Adler@intel.com */ 18311851Sbrandon.potter@amd.comvoid 1845513SMichael.Adler@intel.comMSHR::allocateTarget(PacketPtr pkt, Tick whenReady, Counter _order) 185511SN/A{ 18610633Smichaelupton@gmail.com // if there's a request already in service for this MSHR, we will 18711851Sbrandon.potter@amd.com // have to defer the new target until after the response if any of 18810633Smichaelupton@gmail.com // the following are true: 1891706SN/A // - there are other targets already deferred 19011851Sbrandon.potter@amd.com // - there's a pending invalidate to be applied after the response 191511SN/A // comes back (but before this target is processed) 1925513SMichael.Adler@intel.com // - the outstanding request is for a non-exclusive block and this 1935513SMichael.Adler@intel.com // target requires an exclusive block 19411851Sbrandon.potter@amd.com if (inService && 1955513SMichael.Adler@intel.com (!deferredTargets->empty() || pendingInvalidate || 196511SN/A (!targets->needsExclusive && pkt->needsExclusive()))) { 1971706SN/A // need to put on deferred list 19811851Sbrandon.potter@amd.com deferredTargets->add(pkt, whenReady, _order, true); 1991706SN/A } else { 2001706SN/A // no request outstanding, or still OK to append to 2011706SN/A // outstanding request 2021706SN/A targets->add(pkt, whenReady, _order, true); 20311851Sbrandon.potter@amd.com } 2041706SN/A 2051706SN/A ++ntargets; 2061706SN/A} 2071706SN/A 20811851Sbrandon.potter@amd.combool 2091706SN/AMSHR::handleSnoop(PacketPtr pkt, Counter _order) 210511SN/A{ 2116703Svince@csl.cornell.edu if (!inService || downstreamPending) { 2126703Svince@csl.cornell.edu // Request has not been issued yet, or it's been issued 21311851Sbrandon.potter@amd.com // locally but is buffered unissued at some downstream cache 2146703Svince@csl.cornell.edu // which is forwarding us this snoop. Either way, the packet 2156685Stjones1@inf.ed.ac.uk // we're snooping logically precedes this MSHR's request, so 2166685Stjones1@inf.ed.ac.uk // the snoop has no impact on the MSHR, but must be processed 21711851Sbrandon.potter@amd.com // in the standard way by the cache. The only exception is 2186685Stjones1@inf.ed.ac.uk // that if we're an L2+ cache buffering an UpgradeReq from a 2196685Stjones1@inf.ed.ac.uk // higher-level cache, and the snoop is invalidating, then our 2205513SMichael.Adler@intel.com // buffered upgrades must be converted to read exclusives, 2215513SMichael.Adler@intel.com // since the upper-level cache no longer has a valid copy. 22211851Sbrandon.potter@amd.com // That is, even though the upper-level cache got out on its 2235513SMichael.Adler@intel.com // local bus first, some other invalidating transaction 22411885Sbrandon.potter@amd.com // reached the global bus before the upgrade did. 22511885Sbrandon.potter@amd.com if (pkt->needsExclusive()) { 22611885Sbrandon.potter@amd.com targets->replaceUpgrades(); 2275513SMichael.Adler@intel.com deferredTargets->replaceUpgrades(); 2281999SN/A } 2291999SN/A 23011851Sbrandon.potter@amd.com return false; 2311999SN/A } 23211885Sbrandon.potter@amd.com 23311885Sbrandon.potter@amd.com // From here on down, the request issued by this MSHR logically 23411885Sbrandon.potter@amd.com // precedes the request we're snooping. 2351999SN/A 2361999SN/A if (pkt->needsExclusive()) { 2371999SN/A // snooped request still precedes the re-request we'll have to 23811851Sbrandon.potter@amd.com // issue for deferred targets, if any... 2391999SN/A deferredTargets->replaceUpgrades(); 2403079Sstever@eecs.umich.edu } 2413079Sstever@eecs.umich.edu 24211851Sbrandon.potter@amd.com if (pendingInvalidate) { 2433079Sstever@eecs.umich.edu // a prior snoop has already appended an invalidation, so 24411908SBrandon.Potter@amd.com // logically we don't have the block anymore; no need for 24511908SBrandon.Potter@amd.com // further snooping. 24611908SBrandon.Potter@amd.com return true; 24711908SBrandon.Potter@amd.com } 24811875Sbrandon.potter@amd.com 2492093SN/A if (targets->needsExclusive || pkt->needsExclusive()) { 25011851Sbrandon.potter@amd.com // actual target device (typ. PhysicalMemory) will delete the 2512093SN/A // packet on reception, so we need to save a copy here 2522687Sksewell@umich.edu targets->add(new Packet(pkt), curTick, _order, false); 2532687Sksewell@umich.edu ++ntargets; 25411851Sbrandon.potter@amd.com 2552687Sksewell@umich.edu if (targets->needsExclusive) { 2562238SN/A // We're awaiting an exclusive copy, so ownership is pending. 2572238SN/A // It's up to us to respond once the data arrives. 25811851Sbrandon.potter@amd.com pkt->assertMemInhibit(); 2592238SN/A } 26011908SBrandon.Potter@amd.com 26111908SBrandon.Potter@amd.com if (pkt->needsExclusive()) { 26211908SBrandon.Potter@amd.com // This transaction will take away our pending copy 26311908SBrandon.Potter@amd.com pendingInvalidate = true; 26411908SBrandon.Potter@amd.com } 26511908SBrandon.Potter@amd.com } else { 26611908SBrandon.Potter@amd.com // Read to a read: no conflict, so no need to record as 26711908SBrandon.Potter@amd.com // target, but make sure neither reader thinks he's getting an 2682238SN/A // exclusive copy 2692238SN/A pendingShared = true; 27011851Sbrandon.potter@amd.com pkt->assertShared(); 2712238SN/A } 2722238SN/A 2732238SN/A return true; 27411851Sbrandon.potter@amd.com} 2752238SN/A 2762238SN/A 2772238SN/Abool 27811851Sbrandon.potter@amd.comMSHR::promoteDeferredTargets() 2792238SN/A{ 2802238SN/A assert(targets->empty()); 2812238SN/A if (deferredTargets->empty()) { 28211851Sbrandon.potter@amd.com return false; 2832238SN/A } 2842238SN/A 2852238SN/A // swap targets & deferredTargets lists 28611851Sbrandon.potter@amd.com TargetList *tmp = targets; 2872238SN/A targets = deferredTargets; 2882238SN/A deferredTargets = tmp; 2892238SN/A 29011851Sbrandon.potter@amd.com assert(targets->size() == ntargets); 2912238SN/A 2929455Smitch.hayenga+gem5@gmail.com // clear deferredTargets flags 2939455Smitch.hayenga+gem5@gmail.com deferredTargets->resetFlags(); 29411851Sbrandon.potter@amd.com 29510203SAli.Saidi@ARM.com pendingInvalidate = false; 29611851Sbrandon.potter@amd.com pendingShared = false; 29711851Sbrandon.potter@amd.com order = targets->front().order; 2989455Smitch.hayenga+gem5@gmail.com readyTime = std::max(curTick, targets->front().readyTime); 2999112Smarc.orr@gmail.com 30011906SBrandon.Potter@amd.com return true; 30111906SBrandon.Potter@amd.com} 3029112Smarc.orr@gmail.com 3039112Smarc.orr@gmail.com 30411851Sbrandon.potter@amd.comvoid 3059112Smarc.orr@gmail.comMSHR::handleFill(Packet *pkt, CacheBlk *blk) 3069112Smarc.orr@gmail.com{ 3079112Smarc.orr@gmail.com if (pendingShared) { 3089112Smarc.orr@gmail.com // we snooped another read while this read was in 3099112Smarc.orr@gmail.com // service... assert shared line on its behalf 3109112Smarc.orr@gmail.com pkt->assertShared(); 3119112Smarc.orr@gmail.com } 3129112Smarc.orr@gmail.com} 3139112Smarc.orr@gmail.com 3149112Smarc.orr@gmail.com 3159112Smarc.orr@gmail.comvoid 3169112Smarc.orr@gmail.comMSHR::dump() 3179112Smarc.orr@gmail.com{ 3189112Smarc.orr@gmail.com ccprintf(cerr, 3199112Smarc.orr@gmail.com "inService: %d thread: %d\n" 32011886Sbrandon.potter@amd.com "Addr: %x ntargets %d\n" 3219112Smarc.orr@gmail.com "Targets:\n", 3229112Smarc.orr@gmail.com inService, threadNum, addr, ntargets); 3239238Slluc.alvarez@bsc.es#if 0 3249112Smarc.orr@gmail.com TargetListIterator tar_it = targets->begin(); 3259112Smarc.orr@gmail.com for (int i = 0; i < ntargets; i++) { 3269112Smarc.orr@gmail.com assert(tar_it != targets->end()); 32711886Sbrandon.potter@amd.com 3289112Smarc.orr@gmail.com ccprintf(cerr, "\t%d: Addr: %x cmd: %s\n", 3299112Smarc.orr@gmail.com i, tar_it->pkt->getAddr(), tar_it->pkt->cmdString()); 3309112Smarc.orr@gmail.com 3319112Smarc.orr@gmail.com tar_it++; 3329112Smarc.orr@gmail.com } 3339112Smarc.orr@gmail.com#endif 33411367Sandreas.hansson@arm.com ccprintf(cerr, "\n"); 3359112Smarc.orr@gmail.com} 33611321Ssteve.reinhardt@amd.com 33711886Sbrandon.potter@amd.comMSHR::~MSHR() 3389112Smarc.orr@gmail.com{ 3399112Smarc.orr@gmail.com} 3409112Smarc.orr@gmail.com