mshr.cc revision 4910
17405SAli.Saidi@ARM.com/* 211573SDylan.Johnson@ARM.com * Copyright (c) 2002-2005 The Regents of The University of Michigan 37405SAli.Saidi@ARM.com * All rights reserved. 47405SAli.Saidi@ARM.com * 57405SAli.Saidi@ARM.com * Redistribution and use in source and binary forms, with or without 67405SAli.Saidi@ARM.com * modification, are permitted provided that the following conditions are 77405SAli.Saidi@ARM.com * met: redistributions of source code must retain the above copyright 87405SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer; 97405SAli.Saidi@ARM.com * redistributions in binary form must reproduce the above copyright 107405SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer in the 117405SAli.Saidi@ARM.com * documentation and/or other materials provided with the distribution; 127405SAli.Saidi@ARM.com * neither the name of the copyright holders nor the names of its 137405SAli.Saidi@ARM.com * contributors may be used to endorse or promote products derived from 147405SAli.Saidi@ARM.com * this software without specific prior written permission. 157405SAli.Saidi@ARM.com * 167405SAli.Saidi@ARM.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 177405SAli.Saidi@ARM.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 187405SAli.Saidi@ARM.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 197405SAli.Saidi@ARM.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 207405SAli.Saidi@ARM.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 217405SAli.Saidi@ARM.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 227405SAli.Saidi@ARM.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 237405SAli.Saidi@ARM.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 247405SAli.Saidi@ARM.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 257405SAli.Saidi@ARM.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 267405SAli.Saidi@ARM.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 277405SAli.Saidi@ARM.com * 287405SAli.Saidi@ARM.com * Authors: Erik Hallnor 297405SAli.Saidi@ARM.com * Dave Greene 307405SAli.Saidi@ARM.com */ 317405SAli.Saidi@ARM.com 327405SAli.Saidi@ARM.com/** 337405SAli.Saidi@ARM.com * @file 347405SAli.Saidi@ARM.com * Miss Status and Handling Register (MSHR) definitions. 357405SAli.Saidi@ARM.com */ 367405SAli.Saidi@ARM.com 377405SAli.Saidi@ARM.com#include <assert.h> 387405SAli.Saidi@ARM.com#include <string> 397405SAli.Saidi@ARM.com#include <vector> 407405SAli.Saidi@ARM.com#include <algorithm> 417405SAli.Saidi@ARM.com 4210461SAndreas.Sandberg@ARM.com#include "mem/cache/miss/mshr.hh" 439050Schander.sudanthi@arm.com#include "sim/core.hh" // for curTick 448887Sgeoffrey.blake@arm.com#include "sim/host.hh" 4510461SAndreas.Sandberg@ARM.com#include "base/misc.hh" 468232Snate@binkert.org#include "mem/cache/cache.hh" 478232Snate@binkert.org 4810844Sandreas.sandberg@arm.comusing namespace std; 499384SAndreas.Sandberg@arm.com 507678Sgblack@eecs.umich.eduMSHR::MSHR() 518059SAli.Saidi@ARM.com{ 528284SAli.Saidi@ARM.com inService = false; 537405SAli.Saidi@ARM.com ntargets = 0; 547405SAli.Saidi@ARM.com threadNum = -1; 557405SAli.Saidi@ARM.com targets = new TargetList(); 567405SAli.Saidi@ARM.com deferredTargets = new TargetList(); 5710037SARM gem5 Developers} 5810037SARM gem5 Developers 5910037SARM gem5 Developers 6010037SARM gem5 DevelopersMSHR::TargetList::TargetList() 6110037SARM gem5 Developers : needsExclusive(false), hasUpgrade(false) 6210037SARM gem5 Developers{} 6310037SARM gem5 Developers 6410037SARM gem5 Developers 6510037SARM gem5 Developersinline void 6610037SARM gem5 DevelopersMSHR::TargetList::add(PacketPtr pkt, Tick readyTime, 6710037SARM gem5 Developers Counter order, bool cpuSide) 6810037SARM gem5 Developers{ 6910037SARM gem5 Developers if (cpuSide) { 7010037SARM gem5 Developers if (pkt->needsExclusive()) { 7110037SARM gem5 Developers needsExclusive = true; 7210037SARM gem5 Developers } 7310037SARM gem5 Developers 7410037SARM gem5 Developers if (pkt->cmd == MemCmd::UpgradeReq) { 7510037SARM gem5 Developers hasUpgrade = true; 7610037SARM gem5 Developers } 7710037SARM gem5 Developers 7810037SARM gem5 Developers MSHR *mshr = dynamic_cast<MSHR*>(pkt->senderState); 7910037SARM gem5 Developers if (mshr != NULL) { 8010037SARM gem5 Developers assert(!mshr->downstreamPending); 8110037SARM gem5 Developers mshr->downstreamPending = true; 8210037SARM gem5 Developers } 8310037SARM gem5 Developers } 8410037SARM gem5 Developers 8510037SARM gem5 Developers push_back(Target(pkt, readyTime, order, cpuSide)); 8610037SARM gem5 Developers} 8710037SARM gem5 Developers 8810037SARM gem5 Developers 8910037SARM gem5 Developersvoid 9010037SARM gem5 DevelopersMSHR::TargetList::replaceUpgrades() 9110037SARM gem5 Developers{ 9210037SARM gem5 Developers if (!hasUpgrade) 9310037SARM gem5 Developers return; 9410037SARM gem5 Developers 9510037SARM gem5 Developers Iterator end_i = end(); 9610037SARM gem5 Developers for (Iterator i = begin(); i != end_i; ++i) { 9710037SARM gem5 Developers if (i->pkt->cmd == MemCmd::UpgradeReq) { 9810037SARM gem5 Developers i->pkt->cmd = MemCmd::ReadExReq; 9910037SARM gem5 Developers DPRINTF(Cache, "Replacing UpgradeReq with ReadExReq\n"); 10010037SARM gem5 Developers } 10110037SARM gem5 Developers } 10210037SARM gem5 Developers 10310037SARM gem5 Developers hasUpgrade = false; 10410037SARM gem5 Developers} 10510037SARM gem5 Developers 10610037SARM gem5 Developers 10710037SARM gem5 Developersvoid 10810037SARM gem5 DevelopersMSHR::TargetList::clearDownstreamPending() 10910037SARM gem5 Developers{ 11010037SARM gem5 Developers Iterator end_i = end(); 11110037SARM gem5 Developers for (Iterator i = begin(); i != end_i; ++i) { 11210037SARM gem5 Developers MSHR *mshr = dynamic_cast<MSHR*>(i->pkt->senderState); 11310037SARM gem5 Developers if (mshr != NULL) { 11410037SARM gem5 Developers assert(mshr->downstreamPending); 11510037SARM gem5 Developers mshr->downstreamPending = false; 11610037SARM gem5 Developers } 11710037SARM gem5 Developers } 11810037SARM gem5 Developers} 11910037SARM gem5 Developers 12010037SARM gem5 Developers 12110037SARM gem5 Developersvoid 12210037SARM gem5 DevelopersMSHR::allocate(Addr _addr, int _size, PacketPtr target, 12310037SARM gem5 Developers Tick whenReady, Counter _order) 12410037SARM gem5 Developers{ 12510037SARM gem5 Developers addr = _addr; 12610037SARM gem5 Developers size = _size; 1279384SAndreas.Sandberg@arm.com readyTime = whenReady; 12810461SAndreas.Sandberg@ARM.com order = _order; 12910461SAndreas.Sandberg@ARM.com assert(target); 13011165SRekai.GonzalezAlberquilla@arm.com isCacheFill = false; 13110461SAndreas.Sandberg@ARM.com _isUncacheable = target->req->isUncacheable(); 13210461SAndreas.Sandberg@ARM.com inService = false; 1339384SAndreas.Sandberg@arm.com downstreamPending = false; 1349384SAndreas.Sandberg@arm.com threadNum = 0; 1359384SAndreas.Sandberg@arm.com ntargets = 1; 1369384SAndreas.Sandberg@arm.com // Don't know of a case where we would allocate a new MSHR for a 13710037SARM gem5 Developers // snoop (mem-side request), so set cpuSide to true here. 13810461SAndreas.Sandberg@ARM.com assert(targets->isReset()); 13910461SAndreas.Sandberg@ARM.com targets->add(target, whenReady, _order, true); 14010461SAndreas.Sandberg@ARM.com assert(deferredTargets->isReset()); 14110461SAndreas.Sandberg@ARM.com pendingInvalidate = false; 14210461SAndreas.Sandberg@ARM.com pendingShared = false; 14310461SAndreas.Sandberg@ARM.com data = NULL; 14410609Sandreas.sandberg@arm.com} 14510609Sandreas.sandberg@arm.com 14610609Sandreas.sandberg@arm.com 14710037SARM gem5 Developersbool 14810037SARM gem5 DevelopersMSHR::markInService() 14910037SARM gem5 Developers{ 15010037SARM gem5 Developers assert(!inService); 15110037SARM gem5 Developers if (isSimpleForward()) { 15210037SARM gem5 Developers // we just forwarded the request packet & don't expect a 15310037SARM gem5 Developers // response, so get rid of it 15410037SARM gem5 Developers assert(getNumTargets() == 1); 15510037SARM gem5 Developers popTarget(); 15610037SARM gem5 Developers return true; 15710037SARM gem5 Developers } 15810037SARM gem5 Developers inService = true; 15910037SARM gem5 Developers if (!downstreamPending) { 16010037SARM gem5 Developers // let upstream caches know that the request has made it to a 16110037SARM gem5 Developers // level where it's going to get a response 16210037SARM gem5 Developers targets->clearDownstreamPending(); 16310037SARM gem5 Developers } 16410037SARM gem5 Developers return false; 16510037SARM gem5 Developers} 16610037SARM gem5 Developers 16710037SARM gem5 Developers 16810037SARM gem5 Developersvoid 16910037SARM gem5 DevelopersMSHR::deallocate() 17010037SARM gem5 Developers{ 17110037SARM gem5 Developers assert(targets->empty()); 17210037SARM gem5 Developers targets->resetFlags(); 17310037SARM gem5 Developers assert(deferredTargets->isReset()); 1749384SAndreas.Sandberg@arm.com assert(ntargets == 0); 1759384SAndreas.Sandberg@arm.com inService = false; 1769384SAndreas.Sandberg@arm.com //allocIter = NULL; 1779384SAndreas.Sandberg@arm.com //readyIter = NULL; 1789384SAndreas.Sandberg@arm.com} 1799384SAndreas.Sandberg@arm.com 1809384SAndreas.Sandberg@arm.com/* 1819384SAndreas.Sandberg@arm.com * Adds a target to an MSHR 1829384SAndreas.Sandberg@arm.com */ 1837427Sgblack@eecs.umich.eduvoid 1847427Sgblack@eecs.umich.eduMSHR::allocateTarget(PacketPtr pkt, Tick whenReady, Counter _order) 1857427Sgblack@eecs.umich.edu{ 1869385SAndreas.Sandberg@arm.com // if there's a request already in service for this MSHR, we will 1879385SAndreas.Sandberg@arm.com // have to defer the new target until after the response if any of 1887427Sgblack@eecs.umich.edu // the following are true: 1897427Sgblack@eecs.umich.edu // - there are other targets already deferred 19010037SARM gem5 Developers // - there's a pending invalidate to be applied after the response 19110037SARM gem5 Developers // comes back (but before this target is processed) 19210037SARM gem5 Developers // - the outstanding request is for a non-exclusive block and this 19310037SARM gem5 Developers // target requires an exclusive block 19410037SARM gem5 Developers if (inService && 19510037SARM gem5 Developers (!deferredTargets->empty() || pendingInvalidate || 19610037SARM gem5 Developers (!targets->needsExclusive && pkt->needsExclusive()))) { 19710037SARM gem5 Developers // need to put on deferred list 19810037SARM gem5 Developers deferredTargets->add(pkt, whenReady, _order, true); 19910037SARM gem5 Developers } else { 20010037SARM gem5 Developers // no request outstanding, or still OK to append to 20110037SARM gem5 Developers // outstanding request 20210037SARM gem5 Developers targets->add(pkt, whenReady, _order, true); 20310037SARM gem5 Developers } 2047427Sgblack@eecs.umich.edu 2057427Sgblack@eecs.umich.edu ++ntargets; 2067427Sgblack@eecs.umich.edu} 2077427Sgblack@eecs.umich.edu 2087427Sgblack@eecs.umich.edubool 2097427Sgblack@eecs.umich.eduMSHR::handleSnoop(PacketPtr pkt, Counter _order) 21010037SARM gem5 Developers{ 21110037SARM gem5 Developers if (!inService || (pkt->isExpressSnoop() && downstreamPending)) { 21210037SARM gem5 Developers // Request has not been issued yet, or it's been issued 21310037SARM gem5 Developers // locally but is buffered unissued at some downstream cache 2147427Sgblack@eecs.umich.edu // which is forwarding us this snoop. Either way, the packet 2157427Sgblack@eecs.umich.edu // we're snooping logically precedes this MSHR's request, so 2167427Sgblack@eecs.umich.edu // the snoop has no impact on the MSHR, but must be processed 21710037SARM gem5 Developers // in the standard way by the cache. The only exception is 21810204SAli.Saidi@ARM.com // that if we're an L2+ cache buffering an UpgradeReq from a 21910204SAli.Saidi@ARM.com // higher-level cache, and the snoop is invalidating, then our 22010037SARM gem5 Developers // buffered upgrades must be converted to read exclusives, 2217427Sgblack@eecs.umich.edu // since the upper-level cache no longer has a valid copy. 22210037SARM gem5 Developers // That is, even though the upper-level cache got out on its 2237427Sgblack@eecs.umich.edu // local bus first, some other invalidating transaction 22410037SARM gem5 Developers // reached the global bus before the upgrade did. 2257427Sgblack@eecs.umich.edu if (pkt->needsExclusive()) { 2267427Sgblack@eecs.umich.edu targets->replaceUpgrades(); 22710037SARM gem5 Developers deferredTargets->replaceUpgrades(); 2287427Sgblack@eecs.umich.edu } 2297427Sgblack@eecs.umich.edu 2307427Sgblack@eecs.umich.edu return false; 2317427Sgblack@eecs.umich.edu } 2327427Sgblack@eecs.umich.edu 2337427Sgblack@eecs.umich.edu // From here on down, the request issued by this MSHR logically 2347427Sgblack@eecs.umich.edu // precedes the request we're snooping. 2357427Sgblack@eecs.umich.edu 2367427Sgblack@eecs.umich.edu if (pkt->needsExclusive()) { 2377427Sgblack@eecs.umich.edu // snooped request still precedes the re-request we'll have to 2387427Sgblack@eecs.umich.edu // issue for deferred targets, if any... 2397427Sgblack@eecs.umich.edu deferredTargets->replaceUpgrades(); 2407427Sgblack@eecs.umich.edu } 2417427Sgblack@eecs.umich.edu 2427427Sgblack@eecs.umich.edu if (pendingInvalidate) { 2437427Sgblack@eecs.umich.edu // a prior snoop has already appended an invalidation, so 2447427Sgblack@eecs.umich.edu // logically we don't have the block anymore; no need for 2457427Sgblack@eecs.umich.edu // further snooping. 2467427Sgblack@eecs.umich.edu return true; 2477427Sgblack@eecs.umich.edu } 2487427Sgblack@eecs.umich.edu 2497427Sgblack@eecs.umich.edu if (targets->needsExclusive || pkt->needsExclusive()) { 2507427Sgblack@eecs.umich.edu // actual target device (typ. PhysicalMemory) will delete the 2517436Sdam.sunwoo@arm.com // packet on reception, so we need to save a copy here 2527436Sdam.sunwoo@arm.com PacketPtr cp_pkt = new Packet(pkt); 25310037SARM gem5 Developers targets->add(cp_pkt, curTick, _order, false); 25410037SARM gem5 Developers ++ntargets; 2557436Sdam.sunwoo@arm.com 2567436Sdam.sunwoo@arm.com if (targets->needsExclusive) { 2577436Sdam.sunwoo@arm.com // We're awaiting an exclusive copy, so ownership is pending. 2587436Sdam.sunwoo@arm.com // It's up to us to respond once the data arrives. 2597436Sdam.sunwoo@arm.com pkt->assertMemInhibit(); 2607436Sdam.sunwoo@arm.com } else { 2617436Sdam.sunwoo@arm.com // Someone else may respond before we get around to 2627436Sdam.sunwoo@arm.com // processing this snoop, which means the copied request 2637436Sdam.sunwoo@arm.com // pointer will no longer be valid 2647436Sdam.sunwoo@arm.com cp_pkt->req = NULL; 2657436Sdam.sunwoo@arm.com } 2667436Sdam.sunwoo@arm.com 26710037SARM gem5 Developers if (pkt->needsExclusive()) { 2687436Sdam.sunwoo@arm.com // This transaction will take away our pending copy 2697436Sdam.sunwoo@arm.com pendingInvalidate = true; 2707436Sdam.sunwoo@arm.com } 2717436Sdam.sunwoo@arm.com } else { 2727436Sdam.sunwoo@arm.com // Read to a read: no conflict, so no need to record as 2737436Sdam.sunwoo@arm.com // target, but make sure neither reader thinks he's getting an 2747436Sdam.sunwoo@arm.com // exclusive copy 2757436Sdam.sunwoo@arm.com pendingShared = true; 2767436Sdam.sunwoo@arm.com pkt->assertShared(); 2777436Sdam.sunwoo@arm.com } 2787436Sdam.sunwoo@arm.com 2797436Sdam.sunwoo@arm.com return true; 2807436Sdam.sunwoo@arm.com} 2817436Sdam.sunwoo@arm.com 2827436Sdam.sunwoo@arm.com 2837436Sdam.sunwoo@arm.combool 2847644Sali.saidi@arm.comMSHR::promoteDeferredTargets() 2858147SAli.Saidi@ARM.com{ 2869385SAndreas.Sandberg@arm.com assert(targets->empty()); 2879385SAndreas.Sandberg@arm.com if (deferredTargets->empty()) { 2889385SAndreas.Sandberg@arm.com return false; 2899385SAndreas.Sandberg@arm.com } 2909385SAndreas.Sandberg@arm.com 2919385SAndreas.Sandberg@arm.com // swap targets & deferredTargets lists 2929385SAndreas.Sandberg@arm.com TargetList *tmp = targets; 2939385SAndreas.Sandberg@arm.com targets = deferredTargets; 2949385SAndreas.Sandberg@arm.com deferredTargets = tmp; 2959385SAndreas.Sandberg@arm.com 2969385SAndreas.Sandberg@arm.com assert(targets->size() == ntargets); 2979385SAndreas.Sandberg@arm.com 2989385SAndreas.Sandberg@arm.com // clear deferredTargets flags 2999385SAndreas.Sandberg@arm.com deferredTargets->resetFlags(); 3009385SAndreas.Sandberg@arm.com 3019385SAndreas.Sandberg@arm.com pendingInvalidate = false; 3029385SAndreas.Sandberg@arm.com pendingShared = false; 3039385SAndreas.Sandberg@arm.com order = targets->front().order; 30410037SARM gem5 Developers readyTime = std::max(curTick, targets->front().readyTime); 30510037SARM gem5 Developers 30610037SARM gem5 Developers return true; 30710037SARM gem5 Developers} 30810037SARM gem5 Developers 30910037SARM gem5 Developers 31010037SARM gem5 Developersvoid 31110037SARM gem5 DevelopersMSHR::handleFill(Packet *pkt, CacheBlk *blk) 31210037SARM gem5 Developers{ 31310037SARM gem5 Developers if (pendingShared) { 31410037SARM gem5 Developers // we snooped another read while this read was in 31510037SARM gem5 Developers // service... assert shared line on its behalf 31610037SARM gem5 Developers pkt->assertShared(); 31710037SARM gem5 Developers } 31810037SARM gem5 Developers} 31910037SARM gem5 Developers 3208147SAli.Saidi@ARM.com 3217427Sgblack@eecs.umich.eduvoid 3227427Sgblack@eecs.umich.eduMSHR::dump() 3237427Sgblack@eecs.umich.edu{ 32410037SARM gem5 Developers ccprintf(cerr, 32510037SARM gem5 Developers "inService: %d thread: %d\n" 32610037SARM gem5 Developers "Addr: %x ntargets %d\n" 32710037SARM gem5 Developers "Targets:\n", 32810037SARM gem5 Developers inService, threadNum, addr, ntargets); 32910037SARM gem5 Developers#if 0 33010037SARM gem5 Developers TargetListIterator tar_it = targets->begin(); 33110037SARM gem5 Developers for (int i = 0; i < ntargets; i++) { 33210037SARM gem5 Developers assert(tar_it != targets->end()); 33310037SARM gem5 Developers 33410037SARM gem5 Developers ccprintf(cerr, "\t%d: Addr: %x cmd: %s\n", 33510037SARM gem5 Developers i, tar_it->pkt->getAddr(), tar_it->pkt->cmdString()); 33610037SARM gem5 Developers 33710037SARM gem5 Developers tar_it++; 33810037SARM gem5 Developers } 33910037SARM gem5 Developers#endif 34010037SARM gem5 Developers ccprintf(cerr, "\n"); 34110037SARM gem5 Developers} 34210037SARM gem5 Developers 34310037SARM gem5 DevelopersMSHR::~MSHR() 34410037SARM gem5 Developers{ 34510037SARM gem5 Developers} 34610037SARM gem5 Developers