mshr.cc revision 4916
16167SN/A/*
26167SN/A * Copyright (c) 2002-2005 The Regents of The University of Michigan
36167SN/A * All rights reserved.
410036SAli.Saidi@ARM.com *
58835SAli.Saidi@ARM.com * Redistribution and use in source and binary forms, with or without
610036SAli.Saidi@ARM.com * modification, are permitted provided that the following conditions are
77935SN/A * met: redistributions of source code must retain the above copyright
87935SN/A * notice, this list of conditions and the following disclaimer;
97935SN/A * redistributions in binary form must reproduce the above copyright
106167SN/A * notice, this list of conditions and the following disclaimer in the
116167SN/A * documentation and/or other materials provided with the distribution;
126167SN/A * neither the name of the copyright holders nor the names of its
1310526Snilay@cs.wisc.edu * contributors may be used to endorse or promote products derived from
148835SAli.Saidi@ARM.com * this software without specific prior written permission.
159864Snilay@cs.wisc.edu *
169864Snilay@cs.wisc.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1710036SAli.Saidi@ARM.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1811312Santhony.gutierrez@amd.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
198835SAli.Saidi@ARM.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
208835SAli.Saidi@ARM.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2110315Snilay@cs.wisc.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
228835SAli.Saidi@ARM.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2310093Snilay@cs.wisc.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
247935SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
259864Snilay@cs.wisc.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2610526Snilay@cs.wisc.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2710736Snilay@cs.wisc.edu *
2811219Snilay@cs.wisc.edu * Authors: Erik Hallnor
298721SN/A *          Dave Greene
308835SAli.Saidi@ARM.com */
318835SAli.Saidi@ARM.com
3211440SCurtis.Dunham@arm.com/**
3311440SCurtis.Dunham@arm.com * @file
347935SN/A * Miss Status and Handling Register (MSHR) definitions.
357935SN/A */
367935SN/A
377935SN/A#include <assert.h>
387935SN/A#include <string>
397935SN/A#include <vector>
407935SN/A#include <algorithm>
418983Snate@binkert.org
426167SN/A#include "mem/cache/miss/mshr.hh"
439864Snilay@cs.wisc.edu#include "sim/core.hh" // for curTick
449864Snilay@cs.wisc.edu#include "sim/host.hh"
459864Snilay@cs.wisc.edu#include "base/misc.hh"
4610315Snilay@cs.wisc.edu#include "mem/cache/cache.hh"
4710036SAli.Saidi@ARM.com
4810315Snilay@cs.wisc.eduusing namespace std;
499864Snilay@cs.wisc.edu
509864Snilay@cs.wisc.eduMSHR::MSHR()
516167SN/A{
526167SN/A    inService = false;
539864Snilay@cs.wisc.edu    ntargets = 0;
5410093Snilay@cs.wisc.edu    threadNum = -1;
556167SN/A    targets = new TargetList();
569864Snilay@cs.wisc.edu    deferredTargets = new TargetList();
576167SN/A}
586167SN/A
598835SAli.Saidi@ARM.com
606167SN/AMSHR::TargetList::TargetList()
616167SN/A    : needsExclusive(false), hasUpgrade(false)
6210036SAli.Saidi@ARM.com{}
636167SN/A
646167SN/A
658835SAli.Saidi@ARM.cominline void
669469Snilay@cs.wisc.eduMSHR::TargetList::add(PacketPtr pkt, Tick readyTime,
676167SN/A                      Counter order, bool cpuSide)
686167SN/A{
696167SN/A    if (cpuSide) {
706167SN/A        if (pkt->needsExclusive()) {
716167SN/A            needsExclusive = true;
726167SN/A        }
738835SAli.Saidi@ARM.com
746167SN/A        if (pkt->cmd == MemCmd::UpgradeReq) {
759864Snilay@cs.wisc.edu            hasUpgrade = true;
7610229Snilay@cs.wisc.edu        }
779469Snilay@cs.wisc.edu
786167SN/A        MSHR *mshr = dynamic_cast<MSHR*>(pkt->senderState);
796167SN/A        if (mshr != NULL) {
806167SN/A            assert(!mshr->downstreamPending);
819469Snilay@cs.wisc.edu            mshr->downstreamPending = true;
829469Snilay@cs.wisc.edu        }
836167SN/A    }
849864Snilay@cs.wisc.edu
859864Snilay@cs.wisc.edu    push_back(Target(pkt, readyTime, order, cpuSide));
869864Snilay@cs.wisc.edu}
8710315Snilay@cs.wisc.edu
8810036SAli.Saidi@ARM.com
8910315Snilay@cs.wisc.eduvoid
909864Snilay@cs.wisc.eduMSHR::TargetList::replaceUpgrades()
919864Snilay@cs.wisc.edu{
926167SN/A    if (!hasUpgrade)
936167SN/A        return;
9410036SAli.Saidi@ARM.com
956167SN/A    Iterator end_i = end();
966167SN/A    for (Iterator i = begin(); i != end_i; ++i) {
978835SAli.Saidi@ARM.com        if (i->pkt->cmd == MemCmd::UpgradeReq) {
988835SAli.Saidi@ARM.com            i->pkt->cmd = MemCmd::ReadExReq;
9910036SAli.Saidi@ARM.com            DPRINTF(Cache, "Replacing UpgradeReq with ReadExReq\n");
1008835SAli.Saidi@ARM.com        }
1019469Snilay@cs.wisc.edu    }
1029469Snilay@cs.wisc.edu
10310036SAli.Saidi@ARM.com    hasUpgrade = false;
1049469Snilay@cs.wisc.edu}
1059469Snilay@cs.wisc.edu
10610036SAli.Saidi@ARM.com
1079469Snilay@cs.wisc.eduvoid
1086167SN/AMSHR::TargetList::clearDownstreamPending()
1096167SN/A{
11010036SAli.Saidi@ARM.com    Iterator end_i = end();
1116167SN/A    for (Iterator i = begin(); i != end_i; ++i) {
1126167SN/A        MSHR *mshr = dynamic_cast<MSHR*>(i->pkt->senderState);
1136167SN/A        if (mshr != NULL) {
1146167SN/A            assert(mshr->downstreamPending);
11510036SAli.Saidi@ARM.com            mshr->downstreamPending = false;
1166167SN/A        }
1176167SN/A    }
1186167SN/A}
1196167SN/A
1206167SN/A
12110736Snilay@cs.wisc.eduvoid
1226167SN/AMSHR::allocate(Addr _addr, int _size, PacketPtr target,
1236167SN/A               Tick whenReady, Counter _order)
1246167SN/A{
1256167SN/A    addr = _addr;
12610036SAli.Saidi@ARM.com    size = _size;
12711390Ssteve.reinhardt@amd.com    readyTime = whenReady;
1286167SN/A    order = _order;
1296167SN/A    assert(target);
13010736Snilay@cs.wisc.edu    isCacheFill = false;
1316167SN/A    _isUncacheable = target->req->isUncacheable();
1326167SN/A    inService = false;
1336167SN/A    downstreamPending = false;
1346167SN/A    threadNum = 0;
1356167SN/A    ntargets = 1;
1366167SN/A    // Don't know of a case where we would allocate a new MSHR for a
1376167SN/A    // snoop (mem-side request), so set cpuSide to true here.
13810451Snilay@cs.wisc.edu    assert(targets->isReset());
1396167SN/A    targets->add(target, whenReady, _order, true);
14010315Snilay@cs.wisc.edu    assert(deferredTargets->isReset());
14110315Snilay@cs.wisc.edu    pendingInvalidate = false;
14210315Snilay@cs.wisc.edu    pendingShared = false;
14310315Snilay@cs.wisc.edu    data = NULL;
14410315Snilay@cs.wisc.edu}
14510315Snilay@cs.wisc.edu
14610315Snilay@cs.wisc.edu
14710315Snilay@cs.wisc.edubool
14810526Snilay@cs.wisc.eduMSHR::markInService()
14910526Snilay@cs.wisc.edu{
15010526Snilay@cs.wisc.edu    assert(!inService);
15110526Snilay@cs.wisc.edu    if (isSimpleForward()) {
15210526Snilay@cs.wisc.edu        // we just forwarded the request packet & don't expect a
15310526Snilay@cs.wisc.edu        // response, so get rid of it
15410526Snilay@cs.wisc.edu        assert(getNumTargets() == 1);
15510526Snilay@cs.wisc.edu        popTarget();
15610526Snilay@cs.wisc.edu        return true;
15710526Snilay@cs.wisc.edu    }
15810526Snilay@cs.wisc.edu    inService = true;
15910526Snilay@cs.wisc.edu    if (!downstreamPending) {
16010526Snilay@cs.wisc.edu        // let upstream caches know that the request has made it to a
16110526Snilay@cs.wisc.edu        // level where it's going to get a response
16210526Snilay@cs.wisc.edu        targets->clearDownstreamPending();
16310526Snilay@cs.wisc.edu    }
16410526Snilay@cs.wisc.edu    return false;
16510526Snilay@cs.wisc.edu}
16610526Snilay@cs.wisc.edu
16710526Snilay@cs.wisc.edu
16810526Snilay@cs.wisc.eduvoid
16910526Snilay@cs.wisc.eduMSHR::deallocate()
17010526Snilay@cs.wisc.edu{
17110526Snilay@cs.wisc.edu    assert(targets->empty());
17210526Snilay@cs.wisc.edu    targets->resetFlags();
17310526Snilay@cs.wisc.edu    assert(deferredTargets->isReset());
17410526Snilay@cs.wisc.edu    assert(ntargets == 0);
17510736Snilay@cs.wisc.edu    inService = false;
17610526Snilay@cs.wisc.edu    //allocIter = NULL;
17710526Snilay@cs.wisc.edu    //readyIter = NULL;
17810526Snilay@cs.wisc.edu}
17910526Snilay@cs.wisc.edu
1809864Snilay@cs.wisc.edu/*
1819864Snilay@cs.wisc.edu * Adds a target to an MSHR
18210526Snilay@cs.wisc.edu */
18310526Snilay@cs.wisc.eduvoid
18410526Snilay@cs.wisc.eduMSHR::allocateTarget(PacketPtr pkt, Tick whenReady, Counter _order)
18510526Snilay@cs.wisc.edu{
18610526Snilay@cs.wisc.edu    // if there's a request already in service for this MSHR, we will
18710036SAli.Saidi@ARM.com    // have to defer the new target until after the response if any of
1889469Snilay@cs.wisc.edu    // the following are true:
18910526Snilay@cs.wisc.edu    // - there are other targets already deferred
19010526Snilay@cs.wisc.edu    // - there's a pending invalidate to be applied after the response
19110526Snilay@cs.wisc.edu    //   comes back (but before this target is processed)
19210526Snilay@cs.wisc.edu    // - the outstanding request is for a non-exclusive block and this
19310526Snilay@cs.wisc.edu    //   target requires an exclusive block
19410526Snilay@cs.wisc.edu    if (inService &&
19510526Snilay@cs.wisc.edu        (!deferredTargets->empty() || pendingInvalidate ||
19610526Snilay@cs.wisc.edu         (!targets->needsExclusive && pkt->needsExclusive()))) {
19710526Snilay@cs.wisc.edu        // need to put on deferred list
19810526Snilay@cs.wisc.edu        deferredTargets->add(pkt, whenReady, _order, true);
19910526Snilay@cs.wisc.edu    } else {
20010526Snilay@cs.wisc.edu        // no request outstanding, or still OK to append to
20110526Snilay@cs.wisc.edu        // outstanding request
20210526Snilay@cs.wisc.edu        targets->add(pkt, whenReady, _order, true);
20310526Snilay@cs.wisc.edu    }
20410526Snilay@cs.wisc.edu
20510526Snilay@cs.wisc.edu    ++ntargets;
20610526Snilay@cs.wisc.edu}
20710526Snilay@cs.wisc.edu
20810526Snilay@cs.wisc.edubool
20910526Snilay@cs.wisc.eduMSHR::handleSnoop(PacketPtr pkt, Counter _order)
21010526Snilay@cs.wisc.edu{
21110526Snilay@cs.wisc.edu    if (!inService || (pkt->isExpressSnoop() && downstreamPending)) {
21210526Snilay@cs.wisc.edu        // Request has not been issued yet, or it's been issued
21310526Snilay@cs.wisc.edu        // locally but is buffered unissued at some downstream cache
21410526Snilay@cs.wisc.edu        // which is forwarding us this snoop.  Either way, the packet
21510526Snilay@cs.wisc.edu        // we're snooping logically precedes this MSHR's request, so
21610526Snilay@cs.wisc.edu        // the snoop has no impact on the MSHR, but must be processed
21710526Snilay@cs.wisc.edu        // in the standard way by the cache.  The only exception is
21810526Snilay@cs.wisc.edu        // that if we're an L2+ cache buffering an UpgradeReq from a
21910526Snilay@cs.wisc.edu        // higher-level cache, and the snoop is invalidating, then our
22010526Snilay@cs.wisc.edu        // buffered upgrades must be converted to read exclusives,
22110526Snilay@cs.wisc.edu        // since the upper-level cache no longer has a valid copy.
22210526Snilay@cs.wisc.edu        // That is, even though the upper-level cache got out on its
22310526Snilay@cs.wisc.edu        // local bus first, some other invalidating transaction
2249469Snilay@cs.wisc.edu        // reached the global bus before the upgrade did.
2259469Snilay@cs.wisc.edu        if (pkt->needsExclusive()) {
2269469Snilay@cs.wisc.edu            targets->replaceUpgrades();
22710036SAli.Saidi@ARM.com            deferredTargets->replaceUpgrades();
22810736Snilay@cs.wisc.edu        }
22910036SAli.Saidi@ARM.com
2309469Snilay@cs.wisc.edu        return false;
2319864Snilay@cs.wisc.edu    }
23210036SAli.Saidi@ARM.com
23310036SAli.Saidi@ARM.com    // From here on down, the request issued by this MSHR logically
23410526Snilay@cs.wisc.edu    // precedes the request we're snooping.
23510036SAli.Saidi@ARM.com
23611219Snilay@cs.wisc.edu    if (pkt->needsExclusive()) {
23710526Snilay@cs.wisc.edu        // snooped request still precedes the re-request we'll have to
2389469Snilay@cs.wisc.edu        // issue for deferred targets, if any...
2399469Snilay@cs.wisc.edu        deferredTargets->replaceUpgrades();
2409864Snilay@cs.wisc.edu    }
2419864Snilay@cs.wisc.edu
2429864Snilay@cs.wisc.edu    if (pendingInvalidate) {
24310315Snilay@cs.wisc.edu        // a prior snoop has already appended an invalidation, so
24410036SAli.Saidi@ARM.com        // logically we don't have the block anymore; no need for
24510315Snilay@cs.wisc.edu        // further snooping.
2469864Snilay@cs.wisc.edu        return true;
2479864Snilay@cs.wisc.edu    }
2489469Snilay@cs.wisc.edu
2496928SN/A    if (targets->needsExclusive || pkt->needsExclusive()) {
25011023Sjthestness@gmail.com        // actual target device (typ. PhysicalMemory) will delete the
2516928SN/A        // packet on reception, so we need to save a copy here
2529864Snilay@cs.wisc.edu        PacketPtr cp_pkt = new Packet(pkt);
25310036SAli.Saidi@ARM.com        targets->add(cp_pkt, curTick, _order, false);
2549469Snilay@cs.wisc.edu        ++ntargets;
2556928SN/A
25611023Sjthestness@gmail.com        if (targets->needsExclusive) {
25711023Sjthestness@gmail.com            // We're awaiting an exclusive copy, so ownership is pending.
25810036SAli.Saidi@ARM.com            // It's up to us to respond once the data arrives.
25911023Sjthestness@gmail.com            pkt->assertMemInhibit();
2606928SN/A            pkt->setSupplyExclusive();
2616928SN/A        } else {
26211023Sjthestness@gmail.com            // Someone else may respond before we get around to
26311023Sjthestness@gmail.com            // processing this snoop, which means the copied request
26411023Sjthestness@gmail.com            // pointer will no longer be valid
2658540SN/A            cp_pkt->req = NULL;
26610526Snilay@cs.wisc.edu        }
26710526Snilay@cs.wisc.edu
2689864Snilay@cs.wisc.edu        if (pkt->needsExclusive()) {
2696928SN/A            // This transaction will take away our pending copy
27010526Snilay@cs.wisc.edu            pendingInvalidate = true;
2716928SN/A        }
2729469Snilay@cs.wisc.edu    } else {
2736928SN/A        // Read to a read: no conflict, so no need to record as
27410036SAli.Saidi@ARM.com        // target, but make sure neither reader thinks he's getting an
2759469Snilay@cs.wisc.edu        // exclusive copy
2769864Snilay@cs.wisc.edu        pendingShared = true;
2776928SN/A        pkt->assertShared();
2786928SN/A    }
27911023Sjthestness@gmail.com
28011023Sjthestness@gmail.com    return true;
28111023Sjthestness@gmail.com}
28211023Sjthestness@gmail.com
28311023Sjthestness@gmail.com
28411023Sjthestness@gmail.combool
28511023Sjthestness@gmail.comMSHR::promoteDeferredTargets()
28611023Sjthestness@gmail.com{
28711023Sjthestness@gmail.com    assert(targets->empty());
28811023Sjthestness@gmail.com    if (deferredTargets->empty()) {
28911023Sjthestness@gmail.com        return false;
29011023Sjthestness@gmail.com    }
29111023Sjthestness@gmail.com
29211023Sjthestness@gmail.com    // swap targets & deferredTargets lists
29311023Sjthestness@gmail.com    TargetList *tmp = targets;
29411023Sjthestness@gmail.com    targets = deferredTargets;
29511023Sjthestness@gmail.com    deferredTargets = tmp;
29611023Sjthestness@gmail.com
29711023Sjthestness@gmail.com    assert(targets->size() == ntargets);
29811023Sjthestness@gmail.com
29911023Sjthestness@gmail.com    // clear deferredTargets flags
30011023Sjthestness@gmail.com    deferredTargets->resetFlags();
30111023Sjthestness@gmail.com
30211023Sjthestness@gmail.com    pendingInvalidate = false;
30311023Sjthestness@gmail.com    pendingShared = false;
30411023Sjthestness@gmail.com    order = targets->front().order;
30511023Sjthestness@gmail.com    readyTime = std::max(curTick, targets->front().readyTime);
30611023Sjthestness@gmail.com
30711023Sjthestness@gmail.com    return true;
30811023Sjthestness@gmail.com}
30911023Sjthestness@gmail.com
31011023Sjthestness@gmail.com
31111023Sjthestness@gmail.comvoid
31211023Sjthestness@gmail.comMSHR::handleFill(Packet *pkt, CacheBlk *blk)
31311023Sjthestness@gmail.com{
31411023Sjthestness@gmail.com    if (pendingShared) {
31511023Sjthestness@gmail.com        // we snooped another read while this read was in
31611023Sjthestness@gmail.com        // service... assert shared line on its behalf
31711023Sjthestness@gmail.com        pkt->assertShared();
31811023Sjthestness@gmail.com    }
31911023Sjthestness@gmail.com}
32011023Sjthestness@gmail.com
32111023Sjthestness@gmail.com
32211023Sjthestness@gmail.comvoid
32311023Sjthestness@gmail.comMSHR::dump()
32411023Sjthestness@gmail.com{
32511023Sjthestness@gmail.com    ccprintf(cerr,
3269469Snilay@cs.wisc.edu             "inService: %d thread: %d\n"
3277935SN/A             "Addr: %x ntargets %d\n"
32811023Sjthestness@gmail.com             "Targets:\n",
3297935SN/A             inService, threadNum, addr, ntargets);
3309469Snilay@cs.wisc.edu#if 0
3317935SN/A    TargetListIterator tar_it = targets->begin();
33210315Snilay@cs.wisc.edu    for (int i = 0; i < ntargets; i++) {
33310036SAli.Saidi@ARM.com        assert(tar_it != targets->end());
33410036SAli.Saidi@ARM.com
33511023Sjthestness@gmail.com        ccprintf(cerr, "\t%d: Addr: %x cmd: %s\n",
3367935SN/A                 i, tar_it->pkt->getAddr(), tar_it->pkt->cmdString());
33711023Sjthestness@gmail.com
3387935SN/A        tar_it++;
3397935SN/A    }
34011023Sjthestness@gmail.com#endif
34111023Sjthestness@gmail.com    ccprintf(cerr, "\n");
34211023Sjthestness@gmail.com}
3438540SN/A
3448835SAli.Saidi@ARM.comMSHR::~MSHR()
3459469Snilay@cs.wisc.edu{
34610526Snilay@cs.wisc.edu}
3479864Snilay@cs.wisc.edu