mshr.cc revision 4920
1360SN/A/*
21458SN/A * Copyright (c) 2002-2005 The Regents of The University of Michigan
3360SN/A * All rights reserved.
4360SN/A *
5360SN/A * Redistribution and use in source and binary forms, with or without
6360SN/A * modification, are permitted provided that the following conditions are
7360SN/A * met: redistributions of source code must retain the above copyright
8360SN/A * notice, this list of conditions and the following disclaimer;
9360SN/A * redistributions in binary form must reproduce the above copyright
10360SN/A * notice, this list of conditions and the following disclaimer in the
11360SN/A * documentation and/or other materials provided with the distribution;
12360SN/A * neither the name of the copyright holders nor the names of its
13360SN/A * contributors may be used to endorse or promote products derived from
14360SN/A * this software without specific prior written permission.
15360SN/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.
272665Ssaidi@eecs.umich.edu *
282665Ssaidi@eecs.umich.edu * Authors: Erik Hallnor
292665Ssaidi@eecs.umich.edu *          Dave Greene
30360SN/A */
31360SN/A
321354SN/A/**
331354SN/A * @file
34360SN/A * Miss Status and Handling Register (MSHR) definitions.
352764Sstever@eecs.umich.edu */
362764Sstever@eecs.umich.edu
372064SN/A#include <assert.h>
38360SN/A#include <string>
39360SN/A#include <vector>
40360SN/A#include <algorithm>
41360SN/A
42360SN/A#include "mem/cache/miss/mshr.hh"
43360SN/A#include "sim/core.hh" // for curTick
441354SN/A#include "sim/host.hh"
45360SN/A#include "base/misc.hh"
461809SN/A#include "mem/cache/cache.hh"
475543Ssaidi@eecs.umich.edu
481809SN/Ausing namespace std;
493113Sgblack@eecs.umich.edu
503113Sgblack@eecs.umich.eduMSHR::MSHR()
511999SN/A{
52360SN/A    inService = false;
532474SN/A    ntargets = 0;
545543Ssaidi@eecs.umich.edu    threadNum = -1;
552462SN/A    targets = new TargetList();
561354SN/A    deferredTargets = new TargetList();
576216Snate@binkert.org}
586658Snate@binkert.org
592474SN/A
602680Sktlim@umich.eduMSHR::TargetList::TargetList()
612474SN/A    : needsExclusive(false), hasUpgrade(false)
622474SN/A{}
636640Svince@csl.cornell.edu
641354SN/A
65360SN/Ainline void
66360SN/AMSHR::TargetList::add(PacketPtr pkt, Tick readyTime,
67360SN/A                      Counter order, bool cpuSide)
68360SN/A{
69360SN/A    if (cpuSide) {
70360SN/A        if (pkt->needsExclusive()) {
71360SN/A            needsExclusive = true;
72360SN/A        }
73378SN/A
741450SN/A        if (pkt->cmd == MemCmd::UpgradeReq) {
753114Sgblack@eecs.umich.edu            hasUpgrade = true;
76360SN/A        }
775543Ssaidi@eecs.umich.edu
785543Ssaidi@eecs.umich.edu        MSHR *mshr = dynamic_cast<MSHR*>(pkt->senderState);
795543Ssaidi@eecs.umich.edu        if (mshr != NULL) {
80360SN/A            assert(!mshr->downstreamPending);
81360SN/A            mshr->downstreamPending = true;
82360SN/A        }
83360SN/A    }
84360SN/A
852680Sktlim@umich.edu    push_back(Target(pkt, readyTime, order, cpuSide));
86360SN/A}
87360SN/A
88360SN/A
89360SN/Avoid
90360SN/AMSHR::TargetList::replaceUpgrades()
91360SN/A{
92360SN/A    if (!hasUpgrade)
93360SN/A        return;
94360SN/A
95360SN/A    Iterator end_i = end();
96360SN/A    for (Iterator i = begin(); i != end_i; ++i) {
973114Sgblack@eecs.umich.edu        if (i->pkt->cmd == MemCmd::UpgradeReq) {
98360SN/A            i->pkt->cmd = MemCmd::ReadExReq;
99360SN/A            DPRINTF(Cache, "Replacing UpgradeReq with ReadExReq\n");
100360SN/A        }
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();
111360SN/A    for (Iterator i = begin(); i != end_i; ++i) {
112360SN/A        MSHR *mshr = dynamic_cast<MSHR*>(i->pkt->senderState);
113360SN/A        if (mshr != NULL) {
114360SN/A            assert(mshr->downstreamPending);
115360SN/A            mshr->downstreamPending = false;
116360SN/A        }
117360SN/A    }
118360SN/A}
1192400SN/A
120360SN/A
1212461SN/Abool
1225543Ssaidi@eecs.umich.eduMSHR::TargetList::checkFunctional(PacketPtr pkt)
123360SN/A{
124360SN/A    Iterator end_i = end();
125360SN/A    for (Iterator i = begin(); i != end_i; ++i) {
126360SN/A        if (pkt->checkFunctional(i->pkt)) {
127360SN/A            return true;
1282400SN/A        }
129360SN/A    }
1302461SN/A
1315543Ssaidi@eecs.umich.edu    return false;
132360SN/A}
133360SN/A
134360SN/A
135360SN/Avoid
136360SN/AMSHR::allocate(Addr _addr, int _size, PacketPtr target,
137360SN/A               Tick whenReady, Counter _order)
138360SN/A{
139360SN/A    addr = _addr;
140360SN/A    size = _size;
141360SN/A    readyTime = whenReady;
142360SN/A    order = _order;
143360SN/A    assert(target);
144360SN/A    isCacheFill = false;
1455543Ssaidi@eecs.umich.edu    _isUncacheable = target->req->isUncacheable();
146360SN/A    inService = false;
147360SN/A    downstreamPending = false;
148360SN/A    threadNum = 0;
149360SN/A    ntargets = 1;
150360SN/A    // Don't know of a case where we would allocate a new MSHR for a
151360SN/A    // snoop (mem-side request), so set cpuSide to true here.
152360SN/A    assert(targets->isReset());
153360SN/A    targets->add(target, whenReady, _order, true);
154360SN/A    assert(deferredTargets->isReset());
155360SN/A    pendingInvalidate = false;
156360SN/A    pendingShared = false;
157360SN/A    data = NULL;
158360SN/A}
159360SN/A
160360SN/A
161360SN/Abool
162360SN/AMSHR::markInService()
1635543Ssaidi@eecs.umich.edu{
1645543Ssaidi@eecs.umich.edu    assert(!inService);
165502SN/A    if (isSimpleForward()) {
166360SN/A        // we just forwarded the request packet & don't expect a
167360SN/A        // response, so get rid of it
168360SN/A        assert(getNumTargets() == 1);
169360SN/A        popTarget();
170360SN/A        return true;
171360SN/A    }
172360SN/A    inService = true;
173360SN/A    if (!downstreamPending) {
174360SN/A        // let upstream caches know that the request has made it to a
175360SN/A        // level where it's going to get a response
176360SN/A        targets->clearDownstreamPending();
177378SN/A    }
1781706SN/A    return false;
1793114Sgblack@eecs.umich.edu}
180378SN/A
181378SN/A
182378SN/Avoid
183378SN/AMSHR::deallocate()
184378SN/A{
1851706SN/A    assert(targets->empty());
1863114Sgblack@eecs.umich.edu    targets->resetFlags();
187360SN/A    assert(deferredTargets->isReset());
1886109Ssanchezd@stanford.edu    assert(ntargets == 0);
1891706SN/A    inService = false;
1903114Sgblack@eecs.umich.edu    //allocIter = NULL;
191378SN/A    //readyIter = NULL;
1926109Ssanchezd@stanford.edu}
1936109Ssanchezd@stanford.edu
1946109Ssanchezd@stanford.edu/*
1956109Ssanchezd@stanford.edu * Adds a target to an MSHR
196378SN/A */
1971706SN/Avoid
1983114Sgblack@eecs.umich.eduMSHR::allocateTarget(PacketPtr pkt, Tick whenReady, Counter _order)
199378SN/A{
2005748SSteve.Reinhardt@amd.com    // if there's a request already in service for this MSHR, we will
2015748SSteve.Reinhardt@amd.com    // have to defer the new target until after the response if any of
2025748SSteve.Reinhardt@amd.com    // the following are true:
203378SN/A    // - there are other targets already deferred
204378SN/A    // - there's a pending invalidate to be applied after the response
2051706SN/A    //   comes back (but before this target is processed)
2063114Sgblack@eecs.umich.edu    // - the outstanding request is for a non-exclusive block and this
207378SN/A    //   target requires an exclusive block
208378SN/A    if (inService &&
2091706SN/A        (!deferredTargets->empty() || pendingInvalidate ||
2103114Sgblack@eecs.umich.edu         (!targets->needsExclusive && pkt->needsExclusive()))) {
211378SN/A        // need to put on deferred list
212378SN/A        deferredTargets->add(pkt, whenReady, _order, true);
2131706SN/A    } else {
2143114Sgblack@eecs.umich.edu        // no request outstanding, or still OK to append to
215378SN/A        // outstanding request
216378SN/A        targets->add(pkt, whenReady, _order, true);
2171706SN/A    }
2183114Sgblack@eecs.umich.edu
219378SN/A    ++ntargets;
2204118Sgblack@eecs.umich.edu}
2214118Sgblack@eecs.umich.edu
2224118Sgblack@eecs.umich.edubool
2234118Sgblack@eecs.umich.eduMSHR::handleSnoop(PacketPtr pkt, Counter _order)
224378SN/A{
2251706SN/A    if (!inService || (pkt->isExpressSnoop() && downstreamPending)) {
2263114Sgblack@eecs.umich.edu        // Request has not been issued yet, or it's been issued
227378SN/A        // locally but is buffered unissued at some downstream cache
228378SN/A        // which is forwarding us this snoop.  Either way, the packet
2291706SN/A        // we're snooping logically precedes this MSHR's request, so
2303114Sgblack@eecs.umich.edu        // the snoop has no impact on the MSHR, but must be processed
231360SN/A        // in the standard way by the cache.  The only exception is
2325513SMichael.Adler@intel.com        // that if we're an L2+ cache buffering an UpgradeReq from a
2335513SMichael.Adler@intel.com        // higher-level cache, and the snoop is invalidating, then our
2345513SMichael.Adler@intel.com        // buffered upgrades must be converted to read exclusives,
2355513SMichael.Adler@intel.com        // since the upper-level cache no longer has a valid copy.
2365513SMichael.Adler@intel.com        // That is, even though the upper-level cache got out on its
2375513SMichael.Adler@intel.com        // local bus first, some other invalidating transaction
2385513SMichael.Adler@intel.com        // reached the global bus before the upgrade did.
2395513SMichael.Adler@intel.com        if (pkt->needsExclusive()) {
240511SN/A            targets->replaceUpgrades();
2411706SN/A            deferredTargets->replaceUpgrades();
2423114Sgblack@eecs.umich.edu        }
243511SN/A
2445513SMichael.Adler@intel.com        return false;
2455513SMichael.Adler@intel.com    }
2465513SMichael.Adler@intel.com
2475513SMichael.Adler@intel.com    // From here on down, the request issued by this MSHR logically
248511SN/A    // precedes the request we're snooping.
2491706SN/A
2503114Sgblack@eecs.umich.edu    if (pkt->needsExclusive()) {
2511706SN/A        // snooped request still precedes the re-request we'll have to
2521706SN/A        // issue for deferred targets, if any...
2531706SN/A        deferredTargets->replaceUpgrades();
2541706SN/A    }
2553114Sgblack@eecs.umich.edu
2561706SN/A    if (pendingInvalidate) {
2571706SN/A        // a prior snoop has already appended an invalidation, so
2581706SN/A        // logically we don't have the block anymore; no need for
2591706SN/A        // further snooping.
2603114Sgblack@eecs.umich.edu        return true;
2611706SN/A    }
262511SN/A
2635513SMichael.Adler@intel.com    if (targets->needsExclusive || pkt->needsExclusive()) {
2645513SMichael.Adler@intel.com        // actual target device (typ. PhysicalMemory) will delete the
2655513SMichael.Adler@intel.com        // packet on reception, so we need to save a copy here
2665513SMichael.Adler@intel.com        PacketPtr cp_pkt = new Packet(pkt);
2675513SMichael.Adler@intel.com        targets->add(cp_pkt, curTick, _order, false);
2681999SN/A        ++ntargets;
2691999SN/A
2703114Sgblack@eecs.umich.edu        if (targets->needsExclusive) {
2711999SN/A            // We're awaiting an exclusive copy, so ownership is pending.
2721999SN/A            // It's up to us to respond once the data arrives.
2731999SN/A            pkt->assertMemInhibit();
2741999SN/A            pkt->setSupplyExclusive();
2753114Sgblack@eecs.umich.edu        } else {
2761999SN/A            // Someone else may respond before we get around to
2773079Sstever@eecs.umich.edu            // processing this snoop, which means the copied request
2783079Sstever@eecs.umich.edu            // pointer will no longer be valid
2793114Sgblack@eecs.umich.edu            cp_pkt->req = NULL;
2803079Sstever@eecs.umich.edu        }
2812093SN/A
2822093SN/A        if (pkt->needsExclusive()) {
2833114Sgblack@eecs.umich.edu            // This transaction will take away our pending copy
2842093SN/A            pendingInvalidate = true;
2852687Sksewell@umich.edu        }
2862687Sksewell@umich.edu    } else {
2873114Sgblack@eecs.umich.edu        // Read to a read: no conflict, so no need to record as
2882687Sksewell@umich.edu        // target, but make sure neither reader thinks he's getting an
2892238SN/A        // exclusive copy
2902238SN/A        pendingShared = true;
2913114Sgblack@eecs.umich.edu        pkt->assertShared();
2922238SN/A    }
2932238SN/A
2942238SN/A    return true;
2953114Sgblack@eecs.umich.edu}
2962238SN/A
2972238SN/A
2982238SN/Abool
2993114Sgblack@eecs.umich.eduMSHR::promoteDeferredTargets()
3002238SN/A{
3012238SN/A    assert(targets->empty());
3022238SN/A    if (deferredTargets->empty()) {
3033114Sgblack@eecs.umich.edu        return false;
3042238SN/A    }
3052238SN/A
3062238SN/A    // swap targets & deferredTargets lists
3073114Sgblack@eecs.umich.edu    TargetList *tmp = targets;
3082238SN/A    targets = deferredTargets;
3092238SN/A    deferredTargets = tmp;
3102238SN/A
3113114Sgblack@eecs.umich.edu    assert(targets->size() == ntargets);
3122238SN/A
3132238SN/A    // clear deferredTargets flags
3142238SN/A    deferredTargets->resetFlags();
3153114Sgblack@eecs.umich.edu
3162238SN/A    pendingInvalidate = false;
3176109Ssanchezd@stanford.edu    pendingShared = false;
3186109Ssanchezd@stanford.edu    order = targets->front().order;
3196109Ssanchezd@stanford.edu    readyTime = std::max(curTick, targets->front().readyTime);
3202238SN/A
3212238SN/A    return true;
3222238SN/A}
3232238SN/A
3242238SN/A
3253114Sgblack@eecs.umich.eduvoid
3262238SN/AMSHR::handleFill(Packet *pkt, CacheBlk *blk)
3272238SN/A{
3282238SN/A    if (pendingShared) {
3293114Sgblack@eecs.umich.edu        // we snooped another read while this read was in
3302238SN/A        // service... assert shared line on its behalf
3312238SN/A        pkt->assertShared();
3322238SN/A    }
3333114Sgblack@eecs.umich.edu}
3342238SN/A
3352238SN/A
3362238SN/Avoid
3373114Sgblack@eecs.umich.eduMSHR::dump()
3382238SN/A{
3392238SN/A    ccprintf(cerr,
3401354SN/A             "inService: %d thread: %d\n"
3411354SN/A             "Addr: %x ntargets %d\n"
3421354SN/A             "Targets:\n",
3431354SN/A             inService, threadNum, addr, ntargets);
3441354SN/A#if 0
3451354SN/A    TargetListIterator tar_it = targets->begin();
3461354SN/A    for (int i = 0; i < ntargets; i++) {
3471354SN/A        assert(tar_it != targets->end());
3481354SN/A
3491354SN/A        ccprintf(cerr, "\t%d: Addr: %x cmd: %s\n",
3501354SN/A                 i, tar_it->pkt->getAddr(), tar_it->pkt->cmdString());
3511354SN/A
3521354SN/A        tar_it++;
3531354SN/A    }
3541609SN/A#endif
3551354SN/A    ccprintf(cerr, "\n");
3561354SN/A}
3571354SN/A
3581354SN/AMSHR::~MSHR()
359360SN/A{
360360SN/A}
361360SN/A