mshr.cc revision 5314
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
441809SN/A#include "sim/host.hh"
455543Ssaidi@eecs.umich.edu#include "base/misc.hh"
461809SN/A#include "mem/cache/cache.hh"
473113Sgblack@eecs.umich.edu
487075Snate@binkert.orgusing namespace std;
493113Sgblack@eecs.umich.edu
501999SN/AMSHR::MSHR()
517075Snate@binkert.org{
527075Snate@binkert.org    inService = false;
537075Snate@binkert.org    ntargets = 0;
54360SN/A    threadNum = -1;
552474SN/A    targets = new TargetList();
565543Ssaidi@eecs.umich.edu    deferredTargets = new TargetList();
572462SN/A}
581354SN/A
596216Snate@binkert.org
606658Snate@binkert.orgMSHR::TargetList::TargetList()
612474SN/A    : needsExclusive(false), hasUpgrade(false)
622680Sktlim@umich.edu{}
632474SN/A
642474SN/A
657678Sgblack@eecs.umich.eduinline void
666640Svince@csl.cornell.eduMSHR::TargetList::add(PacketPtr pkt, Tick readyTime,
671354SN/A                      Counter order, bool cpuSide)
68360SN/A{
69360SN/A    if (cpuSide) {
70360SN/A        if (pkt->needsExclusive()) {
71360SN/A            needsExclusive = true;
72360SN/A        }
73360SN/A
74360SN/A        if (pkt->cmd == MemCmd::UpgradeReq) {
75360SN/A            hasUpgrade = true;
76378SN/A        }
771450SN/A
783114Sgblack@eecs.umich.edu        MSHR *mshr = dynamic_cast<MSHR*>(pkt->senderState);
79360SN/A        if (mshr != NULL) {
805543Ssaidi@eecs.umich.edu            assert(!mshr->downstreamPending);
815543Ssaidi@eecs.umich.edu            mshr->downstreamPending = true;
825543Ssaidi@eecs.umich.edu        }
83360SN/A    }
84360SN/A
85360SN/A    push_back(Target(pkt, readyTime, order, cpuSide));
86360SN/A}
87360SN/A
882680Sktlim@umich.edu
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) {
97360SN/A        if (i->pkt->cmd == MemCmd::UpgradeReq) {
98360SN/A            i->pkt->cmd = MemCmd::ReadExReq;
99360SN/A            DPRINTF(Cache, "Replacing UpgradeReq with ReadExReq\n");
1003114Sgblack@eecs.umich.edu        }
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}
119360SN/A
120360SN/A
121360SN/Abool
1222400SN/AMSHR::TargetList::checkFunctional(PacketPtr pkt)
123360SN/A{
1242461SN/A    Iterator end_i = end();
1255543Ssaidi@eecs.umich.edu    for (Iterator i = begin(); i != end_i; ++i) {
126360SN/A        if (pkt->checkFunctional(i->pkt)) {
127360SN/A            return true;
128360SN/A        }
129360SN/A    }
130360SN/A
1312400SN/A    return false;
132360SN/A}
1332461SN/A
1345543Ssaidi@eecs.umich.edu
135360SN/Avoid
136360SN/AMSHR::TargetList::
137360SN/Aprint(std::ostream &os, int verbosity, const std::string &prefix) const
138360SN/A{
139360SN/A    ConstIterator end_i = end();
140360SN/A    for (ConstIterator i = begin(); i != end_i; ++i) {
141360SN/A        ccprintf(os, "%s%s: ", prefix, i->isCpuSide() ? "cpu" : "mem");
142360SN/A        i->pkt->print(os, verbosity, "");
143360SN/A    }
144360SN/A}
145360SN/A
146360SN/A
147360SN/Avoid
1485543Ssaidi@eecs.umich.eduMSHR::allocate(Addr _addr, int _size, PacketPtr target,
149360SN/A               Tick whenReady, Counter _order)
150360SN/A{
151360SN/A    addr = _addr;
152360SN/A    size = _size;
153360SN/A    readyTime = whenReady;
154360SN/A    order = _order;
155360SN/A    assert(target);
156360SN/A    isCacheFill = false;
157360SN/A    _isUncacheable = target->req->isUncacheable();
158360SN/A    inService = false;
159360SN/A    downstreamPending = false;
160360SN/A    threadNum = 0;
161360SN/A    ntargets = 1;
162360SN/A    // Don't know of a case where we would allocate a new MSHR for a
163360SN/A    // snoop (mem-side request), so set cpuSide to true here.
164360SN/A    assert(targets->isReset());
165360SN/A    targets->add(target, whenReady, _order, true);
1665543Ssaidi@eecs.umich.edu    assert(deferredTargets->isReset());
1675543Ssaidi@eecs.umich.edu    pendingInvalidate = false;
168502SN/A    pendingShared = false;
169360SN/A    data = NULL;
170360SN/A}
171360SN/A
172360SN/A
173360SN/Abool
174360SN/AMSHR::markInService()
175360SN/A{
176360SN/A    assert(!inService);
177360SN/A    if (isSimpleForward()) {
178360SN/A        // we just forwarded the request packet & don't expect a
179360SN/A        // response, so get rid of it
180378SN/A        assert(getNumTargets() == 1);
1811706SN/A        popTarget();
1823114Sgblack@eecs.umich.edu        return true;
183378SN/A    }
184378SN/A    inService = true;
185378SN/A    if (!downstreamPending) {
186378SN/A        // let upstream caches know that the request has made it to a
187378SN/A        // level where it's going to get a response
1881706SN/A        targets->clearDownstreamPending();
1893114Sgblack@eecs.umich.edu    }
190360SN/A    return false;
1916109Ssanchezd@stanford.edu}
1921706SN/A
1933114Sgblack@eecs.umich.edu
194378SN/Avoid
1956109Ssanchezd@stanford.eduMSHR::deallocate()
1966109Ssanchezd@stanford.edu{
1976109Ssanchezd@stanford.edu    assert(targets->empty());
1986109Ssanchezd@stanford.edu    targets->resetFlags();
199378SN/A    assert(deferredTargets->isReset());
2001706SN/A    assert(ntargets == 0);
2013114Sgblack@eecs.umich.edu    inService = false;
202378SN/A    //allocIter = NULL;
2035748SSteve.Reinhardt@amd.com    //readyIter = NULL;
2045748SSteve.Reinhardt@amd.com}
2055748SSteve.Reinhardt@amd.com
206378SN/A/*
207378SN/A * Adds a target to an MSHR
2081706SN/A */
2093114Sgblack@eecs.umich.eduvoid
210378SN/AMSHR::allocateTarget(PacketPtr pkt, Tick whenReady, Counter _order)
211378SN/A{
2121706SN/A    // if there's a request already in service for this MSHR, we will
2133114Sgblack@eecs.umich.edu    // have to defer the new target until after the response if any of
214378SN/A    // the following are true:
215378SN/A    // - there are other targets already deferred
2161706SN/A    // - there's a pending invalidate to be applied after the response
2173114Sgblack@eecs.umich.edu    //   comes back (but before this target is processed)
218378SN/A    // - the outstanding request is for a non-exclusive block and this
219378SN/A    //   target requires an exclusive block
2201706SN/A    if (inService &&
2213114Sgblack@eecs.umich.edu        (!deferredTargets->empty() || pendingInvalidate ||
222378SN/A         (!targets->needsExclusive && pkt->needsExclusive()))) {
2234118Sgblack@eecs.umich.edu        // need to put on deferred list
2244118Sgblack@eecs.umich.edu        deferredTargets->add(pkt, whenReady, _order, true);
2254118Sgblack@eecs.umich.edu    } else {
2264118Sgblack@eecs.umich.edu        // no request outstanding, or still OK to append to
227378SN/A        // outstanding request
2281706SN/A        targets->add(pkt, whenReady, _order, true);
2293114Sgblack@eecs.umich.edu    }
230378SN/A
231378SN/A    ++ntargets;
2321706SN/A}
2333114Sgblack@eecs.umich.edu
234360SN/Abool
2355513SMichael.Adler@intel.comMSHR::handleSnoop(PacketPtr pkt, Counter _order)
2365513SMichael.Adler@intel.com{
2375513SMichael.Adler@intel.com    if (!inService || (pkt->isExpressSnoop() && downstreamPending)) {
2385513SMichael.Adler@intel.com        // Request has not been issued yet, or it's been issued
2395513SMichael.Adler@intel.com        // locally but is buffered unissued at some downstream cache
2405513SMichael.Adler@intel.com        // which is forwarding us this snoop.  Either way, the packet
2415513SMichael.Adler@intel.com        // we're snooping logically precedes this MSHR's request, so
2425513SMichael.Adler@intel.com        // the snoop has no impact on the MSHR, but must be processed
243511SN/A        // in the standard way by the cache.  The only exception is
2441706SN/A        // that if we're an L2+ cache buffering an UpgradeReq from a
2453114Sgblack@eecs.umich.edu        // higher-level cache, and the snoop is invalidating, then our
246511SN/A        // buffered upgrades must be converted to read exclusives,
2475513SMichael.Adler@intel.com        // since the upper-level cache no longer has a valid copy.
2485513SMichael.Adler@intel.com        // That is, even though the upper-level cache got out on its
2495513SMichael.Adler@intel.com        // local bus first, some other invalidating transaction
2505513SMichael.Adler@intel.com        // reached the global bus before the upgrade did.
251511SN/A        if (pkt->needsExclusive()) {
2521706SN/A            targets->replaceUpgrades();
2533114Sgblack@eecs.umich.edu            deferredTargets->replaceUpgrades();
2541706SN/A        }
2551706SN/A
2561706SN/A        return false;
2571706SN/A    }
2583114Sgblack@eecs.umich.edu
2591706SN/A    // From here on down, the request issued by this MSHR logically
2601706SN/A    // precedes the request we're snooping.
2611706SN/A
2621706SN/A    if (pkt->needsExclusive()) {
2633114Sgblack@eecs.umich.edu        // snooped request still precedes the re-request we'll have to
2641706SN/A        // issue for deferred targets, if any...
265511SN/A        deferredTargets->replaceUpgrades();
2666703Svince@csl.cornell.edu    }
2676703Svince@csl.cornell.edu
2686703Svince@csl.cornell.edu    if (pendingInvalidate) {
2696703Svince@csl.cornell.edu        // a prior snoop has already appended an invalidation, so
2706685Stjones1@inf.ed.ac.uk        // logically we don't have the block anymore; no need for
2716685Stjones1@inf.ed.ac.uk        // further snooping.
2726685Stjones1@inf.ed.ac.uk        return true;
2736685Stjones1@inf.ed.ac.uk    }
2746685Stjones1@inf.ed.ac.uk
2755513SMichael.Adler@intel.com    if (targets->needsExclusive || pkt->needsExclusive()) {
2765513SMichael.Adler@intel.com        // actual target device (typ. PhysicalMemory) will delete the
2775513SMichael.Adler@intel.com        // packet on reception, so we need to save a copy here
2785513SMichael.Adler@intel.com        PacketPtr cp_pkt = new Packet(pkt, true);
2795513SMichael.Adler@intel.com        targets->add(cp_pkt, curTick, _order, false);
2801999SN/A        ++ntargets;
2811999SN/A
2823114Sgblack@eecs.umich.edu        if (targets->needsExclusive) {
2831999SN/A            // We're awaiting an exclusive copy, so ownership is pending.
2841999SN/A            // It's up to us to respond once the data arrives.
2851999SN/A            pkt->assertMemInhibit();
2861999SN/A            pkt->setSupplyExclusive();
2873114Sgblack@eecs.umich.edu        } else {
2881999SN/A            // Someone else may respond before we get around to
2893079Sstever@eecs.umich.edu            // processing this snoop, which means the copied request
2903079Sstever@eecs.umich.edu            // pointer will no longer be valid
2913114Sgblack@eecs.umich.edu            cp_pkt->req = NULL;
2923079Sstever@eecs.umich.edu        }
2932093SN/A
2942093SN/A        if (pkt->needsExclusive()) {
2953114Sgblack@eecs.umich.edu            // This transaction will take away our pending copy
2962093SN/A            pendingInvalidate = true;
2972687Sksewell@umich.edu        }
2982687Sksewell@umich.edu    } else {
2993114Sgblack@eecs.umich.edu        // Read to a read: no conflict, so no need to record as
3002687Sksewell@umich.edu        // target, but make sure neither reader thinks he's getting an
3012238SN/A        // exclusive copy
3022238SN/A        pendingShared = true;
3033114Sgblack@eecs.umich.edu        pkt->assertShared();
3042238SN/A    }
3052238SN/A
3062238SN/A    return true;
3073114Sgblack@eecs.umich.edu}
3082238SN/A
3092238SN/A
3102238SN/Abool
3113114Sgblack@eecs.umich.eduMSHR::promoteDeferredTargets()
3122238SN/A{
3132238SN/A    assert(targets->empty());
3142238SN/A    if (deferredTargets->empty()) {
3153114Sgblack@eecs.umich.edu        return false;
3162238SN/A    }
3172238SN/A
3182238SN/A    // swap targets & deferredTargets lists
3193114Sgblack@eecs.umich.edu    TargetList *tmp = targets;
3202238SN/A    targets = deferredTargets;
3212238SN/A    deferredTargets = tmp;
3222238SN/A
3233114Sgblack@eecs.umich.edu    assert(targets->size() == ntargets);
3242238SN/A
3252238SN/A    // clear deferredTargets flags
3262238SN/A    deferredTargets->resetFlags();
3273114Sgblack@eecs.umich.edu
3282238SN/A    pendingInvalidate = false;
3296109Ssanchezd@stanford.edu    pendingShared = false;
3306109Ssanchezd@stanford.edu    order = targets->front().order;
3316109Ssanchezd@stanford.edu    readyTime = std::max(curTick, targets->front().readyTime);
3322238SN/A
3332238SN/A    return true;
3342238SN/A}
3352238SN/A
3362238SN/A
3373114Sgblack@eecs.umich.eduvoid
3382238SN/AMSHR::handleFill(Packet *pkt, CacheBlk *blk)
3392238SN/A{
3402238SN/A    if (pendingShared) {
3413114Sgblack@eecs.umich.edu        // we snooped another read while this read was in
3422238SN/A        // service... assert shared line on its behalf
3432238SN/A        pkt->assertShared();
3442238SN/A    }
3453114Sgblack@eecs.umich.edu
3462238SN/A    if (!pkt->sharedAsserted() && !pendingInvalidate
3472238SN/A        && deferredTargets->needsExclusive) {
3482238SN/A        // We got an exclusive response, but we have deferred targets
3493114Sgblack@eecs.umich.edu        // which are waiting to request an exclusive copy (not because
3502238SN/A        // of a pending invalidate).  This can happen if the original
3512238SN/A        // request was for a read-only (non-exclusive) block, but we
3521354SN/A        // got an exclusive copy anyway because of the E part of the
3531354SN/A        // MOESI/MESI protocol.  Since we got the exclusive copy
3541354SN/A        // there's no need to defer the targets, so move them up to
3551354SN/A        // the regular target list.
3561354SN/A        assert(!targets->needsExclusive);
3571354SN/A        targets->needsExclusive = true;
3581354SN/A        // this clears out deferredTargets too
3591354SN/A        targets->splice(targets->end(), *deferredTargets);
3601354SN/A        deferredTargets->resetFlags();
3611354SN/A    }
3621354SN/A}
3631354SN/A
3641354SN/A
3651354SN/Abool
3667823Ssteve.reinhardt@amd.comMSHR::checkFunctional(PacketPtr pkt)
3671354SN/A{
3681354SN/A    // For printing, we treat the MSHR as a whole as single entity.
3691354SN/A    // For other requests, we iterate over the individual targets
3701354SN/A    // since that's where the actual data lies.
371360SN/A    if (pkt->isPrint()) {
372360SN/A        pkt->checkFunctional(this, addr, size, NULL);
373360SN/A        return false;
374360SN/A    } else {
375360SN/A        return (targets->checkFunctional(pkt) ||
376360SN/A                deferredTargets->checkFunctional(pkt));
377360SN/A    }
3783113Sgblack@eecs.umich.edu}
3793113Sgblack@eecs.umich.edu
3803113Sgblack@eecs.umich.edu
3813113Sgblack@eecs.umich.eduvoid
3823113Sgblack@eecs.umich.eduMSHR::print(std::ostream &os, int verbosity, const std::string &prefix) const
3833113Sgblack@eecs.umich.edu{
3843113Sgblack@eecs.umich.edu    ccprintf(os, "%s[%x:%x] %s %s %s state: %s %s %s %s\n",
3853113Sgblack@eecs.umich.edu             prefix, addr, addr+size-1,
3863113Sgblack@eecs.umich.edu             isCacheFill ? "Fill" : "",
3873113Sgblack@eecs.umich.edu             needsExclusive() ? "Excl" : "",
3883113Sgblack@eecs.umich.edu             _isUncacheable ? "Unc" : "",
3893113Sgblack@eecs.umich.edu             inService ? "InSvc" : "",
3903113Sgblack@eecs.umich.edu             downstreamPending ? "DwnPend" : "",
3913113Sgblack@eecs.umich.edu             pendingInvalidate ? "PendInv" : "",
3923113Sgblack@eecs.umich.edu             pendingShared ? "PendShared" : "");
3933113Sgblack@eecs.umich.edu
3944189Sgblack@eecs.umich.edu    ccprintf(os, "%s  Targets:\n", prefix);
3954189Sgblack@eecs.umich.edu    targets->print(os, verbosity, prefix + "    ");
3963113Sgblack@eecs.umich.edu    if (!deferredTargets->empty()) {
3973113Sgblack@eecs.umich.edu        ccprintf(os, "%s  Deferred Targets:\n", prefix);
3983113Sgblack@eecs.umich.edu        deferredTargets->print(os, verbosity, prefix + "      ");
3993113Sgblack@eecs.umich.edu    }
4003113Sgblack@eecs.umich.edu}
4013113Sgblack@eecs.umich.edu
4023113Sgblack@eecs.umich.eduMSHR::~MSHR()
4033277Sgblack@eecs.umich.edu{
4045515SMichael.Adler@intel.com}
4055515SMichael.Adler@intel.com