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