mshr.cc revision 10503
17405SAli.Saidi@ARM.com/*
211573SDylan.Johnson@ARM.com * Copyright (c) 2012-2013 ARM Limited
37405SAli.Saidi@ARM.com * All rights reserved.
47405SAli.Saidi@ARM.com *
57405SAli.Saidi@ARM.com * The license below extends only to copyright in the software and shall
67405SAli.Saidi@ARM.com * not be construed as granting a license to any other intellectual
77405SAli.Saidi@ARM.com * property including but not limited to intellectual property relating
87405SAli.Saidi@ARM.com * to a hardware implementation of the functionality of the software
97405SAli.Saidi@ARM.com * licensed hereunder.  You may use the software subject to the license
107405SAli.Saidi@ARM.com * terms below provided that you ensure that this notice is replicated
117405SAli.Saidi@ARM.com * unmodified and in its entirety in all distributions of the software,
127405SAli.Saidi@ARM.com * modified or unmodified, in source code or in binary form.
137405SAli.Saidi@ARM.com *
147405SAli.Saidi@ARM.com * Copyright (c) 2002-2005 The Regents of The University of Michigan
157405SAli.Saidi@ARM.com * Copyright (c) 2010 Advanced Micro Devices, Inc.
167405SAli.Saidi@ARM.com * All rights reserved.
177405SAli.Saidi@ARM.com *
187405SAli.Saidi@ARM.com * Redistribution and use in source and binary forms, with or without
197405SAli.Saidi@ARM.com * modification, are permitted provided that the following conditions are
207405SAli.Saidi@ARM.com * met: redistributions of source code must retain the above copyright
217405SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer;
227405SAli.Saidi@ARM.com * redistributions in binary form must reproduce the above copyright
237405SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer in the
247405SAli.Saidi@ARM.com * documentation and/or other materials provided with the distribution;
257405SAli.Saidi@ARM.com * neither the name of the copyright holders nor the names of its
267405SAli.Saidi@ARM.com * contributors may be used to endorse or promote products derived from
277405SAli.Saidi@ARM.com * this software without specific prior written permission.
287405SAli.Saidi@ARM.com *
297405SAli.Saidi@ARM.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
307405SAli.Saidi@ARM.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
317405SAli.Saidi@ARM.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
327405SAli.Saidi@ARM.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
337405SAli.Saidi@ARM.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
347405SAli.Saidi@ARM.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
357405SAli.Saidi@ARM.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
367405SAli.Saidi@ARM.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
377405SAli.Saidi@ARM.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
387405SAli.Saidi@ARM.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
397405SAli.Saidi@ARM.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
407405SAli.Saidi@ARM.com *
417405SAli.Saidi@ARM.com * Authors: Erik Hallnor
4210461SAndreas.Sandberg@ARM.com *          Dave Greene
439050Schander.sudanthi@arm.com */
448887Sgeoffrey.blake@arm.com
4510461SAndreas.Sandberg@ARM.com/**
468232Snate@binkert.org * @file
478232Snate@binkert.org * Miss Status and Handling Register (MSHR) definitions.
4810844Sandreas.sandberg@arm.com */
499384SAndreas.Sandberg@arm.com
507678Sgblack@eecs.umich.edu#include <algorithm>
518059SAli.Saidi@ARM.com#include <cassert>
528284SAli.Saidi@ARM.com#include <string>
537405SAli.Saidi@ARM.com#include <vector>
547405SAli.Saidi@ARM.com
557405SAli.Saidi@ARM.com#include "base/misc.hh"
567405SAli.Saidi@ARM.com#include "base/types.hh"
5710037SARM gem5 Developers#include "debug/Cache.hh"
5810037SARM gem5 Developers#include "mem/cache/cache.hh"
5911768SCurtis.Dunham@arm.com#include "mem/cache/mshr.hh"
6010037SARM gem5 Developers#include "sim/core.hh"
6110037SARM gem5 Developers
6210037SARM gem5 Developersusing namespace std;
6310037SARM gem5 Developers
6411768SCurtis.Dunham@arm.comMSHR::MSHR() : readyTime(0), _isUncacheable(false), downstreamPending(false),
6510037SARM gem5 Developers               pendingDirty(false), pendingClean(false),
6610037SARM gem5 Developers               postInvalidate(false), postDowngrade(false),
6711768SCurtis.Dunham@arm.com               _isObsolete(false), queue(NULL), order(0), addr(0),
6811768SCurtis.Dunham@arm.com               size(0), isSecure(false), inService(false),
6911768SCurtis.Dunham@arm.com               isForward(false), threadNum(InvalidThreadID), data(NULL)
7011768SCurtis.Dunham@arm.com{
7111768SCurtis.Dunham@arm.com}
7211768SCurtis.Dunham@arm.com
7311768SCurtis.Dunham@arm.com
7411768SCurtis.Dunham@arm.comMSHR::TargetList::TargetList()
7511768SCurtis.Dunham@arm.com    : needsExclusive(false), hasUpgrade(false)
7611768SCurtis.Dunham@arm.com{}
7711768SCurtis.Dunham@arm.com
7811768SCurtis.Dunham@arm.com
7910037SARM gem5 Developersinline void
8010037SARM gem5 DevelopersMSHR::TargetList::add(PacketPtr pkt, Tick readyTime,
8110037SARM gem5 Developers                      Counter order, Target::Source source, bool markPending)
8211768SCurtis.Dunham@arm.com{
8311768SCurtis.Dunham@arm.com    if (source != Target::FromSnoop) {
8411768SCurtis.Dunham@arm.com        if (pkt->needsExclusive()) {
8511768SCurtis.Dunham@arm.com            needsExclusive = true;
8611768SCurtis.Dunham@arm.com        }
8711768SCurtis.Dunham@arm.com
8811768SCurtis.Dunham@arm.com        // StoreCondReq is effectively an upgrade if it's in an MSHR
8911768SCurtis.Dunham@arm.com        // since it would have been failed already if we didn't have a
9010037SARM gem5 Developers        // read-only copy
9111768SCurtis.Dunham@arm.com        if (pkt->isUpgrade() || pkt->cmd == MemCmd::StoreCondReq) {
9211768SCurtis.Dunham@arm.com            hasUpgrade = true;
9311768SCurtis.Dunham@arm.com        }
9411768SCurtis.Dunham@arm.com    }
9510037SARM gem5 Developers
9611768SCurtis.Dunham@arm.com    if (markPending) {
9711768SCurtis.Dunham@arm.com        // Iterate over the SenderState stack and see if we find
9811768SCurtis.Dunham@arm.com        // an MSHR entry. If we do, set the downstreamPending
9911768SCurtis.Dunham@arm.com        // flag. Otherwise, do nothing.
10011768SCurtis.Dunham@arm.com        MSHR *mshr = pkt->findNextSenderState<MSHR>();
10111768SCurtis.Dunham@arm.com        if (mshr != NULL) {
10211768SCurtis.Dunham@arm.com            assert(!mshr->downstreamPending);
10311768SCurtis.Dunham@arm.com            mshr->downstreamPending = true;
10411768SCurtis.Dunham@arm.com        }
10511768SCurtis.Dunham@arm.com    }
10611768SCurtis.Dunham@arm.com
10711768SCurtis.Dunham@arm.com    push_back(Target(pkt, readyTime, order, source, markPending));
10811768SCurtis.Dunham@arm.com}
10911768SCurtis.Dunham@arm.com
11011768SCurtis.Dunham@arm.com
11111768SCurtis.Dunham@arm.comstatic void
11211768SCurtis.Dunham@arm.comreplaceUpgrade(PacketPtr pkt)
11311768SCurtis.Dunham@arm.com{
11410037SARM gem5 Developers    if (pkt->cmd == MemCmd::UpgradeReq) {
11511768SCurtis.Dunham@arm.com        pkt->cmd = MemCmd::ReadExReq;
11611768SCurtis.Dunham@arm.com        DPRINTF(Cache, "Replacing UpgradeReq with ReadExReq\n");
11711768SCurtis.Dunham@arm.com    } else if (pkt->cmd == MemCmd::SCUpgradeReq) {
11811768SCurtis.Dunham@arm.com        pkt->cmd = MemCmd::SCUpgradeFailReq;
11910037SARM gem5 Developers        DPRINTF(Cache, "Replacing SCUpgradeReq with SCUpgradeFailReq\n");
12011768SCurtis.Dunham@arm.com    } else if (pkt->cmd == MemCmd::StoreCondReq) {
12111768SCurtis.Dunham@arm.com        pkt->cmd = MemCmd::StoreCondFailReq;
12211768SCurtis.Dunham@arm.com        DPRINTF(Cache, "Replacing StoreCondReq with StoreCondFailReq\n");
12311768SCurtis.Dunham@arm.com    }
12411768SCurtis.Dunham@arm.com}
12511768SCurtis.Dunham@arm.com
12610037SARM gem5 Developers
12711768SCurtis.Dunham@arm.comvoid
12811768SCurtis.Dunham@arm.comMSHR::TargetList::replaceUpgrades()
12911768SCurtis.Dunham@arm.com{
13011768SCurtis.Dunham@arm.com    if (!hasUpgrade)
13111768SCurtis.Dunham@arm.com        return;
13211768SCurtis.Dunham@arm.com
13311768SCurtis.Dunham@arm.com    Iterator end_i = end();
13411768SCurtis.Dunham@arm.com    for (Iterator i = begin(); i != end_i; ++i) {
13511768SCurtis.Dunham@arm.com        replaceUpgrade(i->pkt);
13611768SCurtis.Dunham@arm.com    }
13711768SCurtis.Dunham@arm.com
13811768SCurtis.Dunham@arm.com    hasUpgrade = false;
13911768SCurtis.Dunham@arm.com}
14011768SCurtis.Dunham@arm.com
14111768SCurtis.Dunham@arm.com
14211768SCurtis.Dunham@arm.comvoid
14311768SCurtis.Dunham@arm.comMSHR::TargetList::clearDownstreamPending()
14411768SCurtis.Dunham@arm.com{
14511768SCurtis.Dunham@arm.com    Iterator end_i = end();
14611768SCurtis.Dunham@arm.com    for (Iterator i = begin(); i != end_i; ++i) {
14711768SCurtis.Dunham@arm.com        if (i->markedPending) {
14811768SCurtis.Dunham@arm.com            // Iterate over the SenderState stack and see if we find
14911768SCurtis.Dunham@arm.com            // an MSHR entry. If we find one, clear the
15011768SCurtis.Dunham@arm.com            // downstreamPending flag by calling
15111768SCurtis.Dunham@arm.com            // clearDownstreamPending(). This recursively clears the
15211768SCurtis.Dunham@arm.com            // downstreamPending flag in all caches this packet has
15311768SCurtis.Dunham@arm.com            // passed through.
15411768SCurtis.Dunham@arm.com            MSHR *mshr = i->pkt->findNextSenderState<MSHR>();
15511768SCurtis.Dunham@arm.com            if (mshr != NULL) {
15611768SCurtis.Dunham@arm.com                mshr->clearDownstreamPending();
15711768SCurtis.Dunham@arm.com            }
15811768SCurtis.Dunham@arm.com        }
15911768SCurtis.Dunham@arm.com    }
16011768SCurtis.Dunham@arm.com}
16111768SCurtis.Dunham@arm.com
16211768SCurtis.Dunham@arm.com
16311768SCurtis.Dunham@arm.combool
16411768SCurtis.Dunham@arm.comMSHR::TargetList::checkFunctional(PacketPtr pkt)
16511768SCurtis.Dunham@arm.com{
16611768SCurtis.Dunham@arm.com    Iterator end_i = end();
16711768SCurtis.Dunham@arm.com    for (Iterator i = begin(); i != end_i; ++i) {
16811768SCurtis.Dunham@arm.com        if (pkt->checkFunctional(i->pkt)) {
16911768SCurtis.Dunham@arm.com            return true;
17011768SCurtis.Dunham@arm.com        }
17111768SCurtis.Dunham@arm.com    }
17211768SCurtis.Dunham@arm.com
17311768SCurtis.Dunham@arm.com    return false;
17411768SCurtis.Dunham@arm.com}
17511768SCurtis.Dunham@arm.com
17611768SCurtis.Dunham@arm.com
17711768SCurtis.Dunham@arm.comvoid
17811768SCurtis.Dunham@arm.comMSHR::TargetList::
17911768SCurtis.Dunham@arm.comprint(std::ostream &os, int verbosity, const std::string &prefix) const
18011768SCurtis.Dunham@arm.com{
18111768SCurtis.Dunham@arm.com    ConstIterator end_i = end();
18211768SCurtis.Dunham@arm.com    for (ConstIterator i = begin(); i != end_i; ++i) {
18311768SCurtis.Dunham@arm.com        const char *s;
18411768SCurtis.Dunham@arm.com        switch (i->source) {
18511768SCurtis.Dunham@arm.com          case Target::FromCPU:
18611768SCurtis.Dunham@arm.com            s = "FromCPU";
18711768SCurtis.Dunham@arm.com            break;
18811768SCurtis.Dunham@arm.com          case Target::FromSnoop:
18911768SCurtis.Dunham@arm.com            s = "FromSnoop";
19011768SCurtis.Dunham@arm.com            break;
19111768SCurtis.Dunham@arm.com          case Target::FromPrefetcher:
19211768SCurtis.Dunham@arm.com            s = "FromPrefetcher";
19311768SCurtis.Dunham@arm.com            break;
19411768SCurtis.Dunham@arm.com          default:
19511768SCurtis.Dunham@arm.com            s = "";
19611768SCurtis.Dunham@arm.com            break;
19711768SCurtis.Dunham@arm.com        }
19811768SCurtis.Dunham@arm.com        ccprintf(os, "%s%s: ", prefix, s);
19911768SCurtis.Dunham@arm.com        i->pkt->print(os, verbosity, "");
20011768SCurtis.Dunham@arm.com    }
20111768SCurtis.Dunham@arm.com}
20211768SCurtis.Dunham@arm.com
20311768SCurtis.Dunham@arm.com
20410037SARM gem5 Developersvoid
20510037SARM gem5 DevelopersMSHR::allocate(Addr _addr, int _size, PacketPtr target, Tick whenReady,
20610037SARM gem5 Developers               Counter _order)
2079384SAndreas.Sandberg@arm.com{
20810461SAndreas.Sandberg@ARM.com    addr = _addr;
20910461SAndreas.Sandberg@ARM.com    size = _size;
21011165SRekai.GonzalezAlberquilla@arm.com    isSecure = target->isSecure();
21110461SAndreas.Sandberg@ARM.com    readyTime = whenReady;
21210461SAndreas.Sandberg@ARM.com    order = _order;
2139384SAndreas.Sandberg@arm.com    assert(target);
21411770SCurtis.Dunham@arm.com    isForward = false;
21510037SARM gem5 Developers    _isUncacheable = target->req->isUncacheable();
21610461SAndreas.Sandberg@ARM.com    inService = false;
21710461SAndreas.Sandberg@ARM.com    pendingClean = (target->cmd == MemCmd::WriteInvalidateReq);
21810461SAndreas.Sandberg@ARM.com    downstreamPending = false;
21910461SAndreas.Sandberg@ARM.com    _isObsolete = false;
22010461SAndreas.Sandberg@ARM.com    threadNum = 0;
22110461SAndreas.Sandberg@ARM.com    assert(targets.isReset());
22210609Sandreas.sandberg@arm.com    // Don't know of a case where we would allocate a new MSHR for a
22310609Sandreas.sandberg@arm.com    // snoop (mem-side request), so set source according to request here
22410609Sandreas.sandberg@arm.com    Target::Source source = (target->cmd == MemCmd::HardPFReq) ?
22510037SARM gem5 Developers        Target::FromPrefetcher : Target::FromCPU;
22610037SARM gem5 Developers    targets.add(target, whenReady, _order, source, true);
22710037SARM gem5 Developers    assert(deferredTargets.isReset());
22810037SARM gem5 Developers    data = NULL;
22911771SCurtis.Dunham@arm.com}
23010037SARM gem5 Developers
23110037SARM gem5 Developers
23210037SARM gem5 Developersvoid
23310037SARM gem5 DevelopersMSHR::clearDownstreamPending()
23410037SARM gem5 Developers{
23510037SARM gem5 Developers    assert(downstreamPending);
23611771SCurtis.Dunham@arm.com    downstreamPending = false;
23710037SARM gem5 Developers    // recursively clear flag on any MSHRs we will be forwarding
23810037SARM gem5 Developers    // responses to
23910037SARM gem5 Developers    targets.clearDownstreamPending();
24010037SARM gem5 Developers}
24110037SARM gem5 Developers
24210037SARM gem5 Developersbool
24311768SCurtis.Dunham@arm.comMSHR::markInService(PacketPtr pkt)
24411768SCurtis.Dunham@arm.com{
24510037SARM gem5 Developers    assert(!inService);
24610037SARM gem5 Developers    if (isForwardNoResponse()) {
24710037SARM gem5 Developers        // we just forwarded the request packet & don't expect a
24810037SARM gem5 Developers        // response, so get rid of it
2499384SAndreas.Sandberg@arm.com        assert(getNumTargets() == 1);
2509384SAndreas.Sandberg@arm.com        popTarget();
2519384SAndreas.Sandberg@arm.com        return true;
2529384SAndreas.Sandberg@arm.com    }
2539384SAndreas.Sandberg@arm.com
2549384SAndreas.Sandberg@arm.com    assert(pkt != NULL);
2559384SAndreas.Sandberg@arm.com    inService = true;
2569384SAndreas.Sandberg@arm.com    pendingDirty = ((targets.needsExclusive &&
2579384SAndreas.Sandberg@arm.com                     (pkt->cmd != MemCmd::WriteInvalidateReq)) ||
2587427Sgblack@eecs.umich.edu                    (!pkt->sharedAsserted() && pkt->memInhibitAsserted()));
2597427Sgblack@eecs.umich.edu    postInvalidate = postDowngrade = false;
2607427Sgblack@eecs.umich.edu
2619385SAndreas.Sandberg@arm.com    if (!downstreamPending) {
2629385SAndreas.Sandberg@arm.com        // let upstream caches know that the request has made it to a
2637427Sgblack@eecs.umich.edu        // level where it's going to get a response
2647427Sgblack@eecs.umich.edu        targets.clearDownstreamPending();
26510037SARM gem5 Developers    }
26610037SARM gem5 Developers    return false;
26710037SARM gem5 Developers}
26810037SARM gem5 Developers
26910037SARM gem5 Developers
27010037SARM gem5 Developersvoid
27110037SARM gem5 DevelopersMSHR::deallocate()
27210037SARM gem5 Developers{
27310037SARM gem5 Developers    assert(targets.empty());
27410037SARM gem5 Developers    targets.resetFlags();
27510037SARM gem5 Developers    assert(deferredTargets.isReset());
27610037SARM gem5 Developers    inService = false;
27710037SARM gem5 Developers}
27810037SARM gem5 Developers
2797427Sgblack@eecs.umich.edu/*
2807427Sgblack@eecs.umich.edu * Adds a target to an MSHR
2817427Sgblack@eecs.umich.edu */
2827427Sgblack@eecs.umich.eduvoid
2837427Sgblack@eecs.umich.eduMSHR::allocateTarget(PacketPtr pkt, Tick whenReady, Counter _order)
2847427Sgblack@eecs.umich.edu{
28510037SARM gem5 Developers    // if there's a request already in service for this MSHR, we will
28610037SARM gem5 Developers    // have to defer the new target until after the response if any of
28710037SARM gem5 Developers    // the following are true:
28810037SARM gem5 Developers    // - there are other targets already deferred
2897427Sgblack@eecs.umich.edu    // - there's a pending invalidate to be applied after the response
2907427Sgblack@eecs.umich.edu    //   comes back (but before this target is processed)
2917427Sgblack@eecs.umich.edu    // - this target requires an exclusive block and either we're not
29210037SARM gem5 Developers    //   getting an exclusive block back or we have already snooped
29310204SAli.Saidi@ARM.com    //   another read request that will downgrade our exclusive block
29410204SAli.Saidi@ARM.com    //   to shared
29510037SARM gem5 Developers
2967427Sgblack@eecs.umich.edu    // assume we'd never issue a prefetch when we've got an
29710037SARM gem5 Developers    // outstanding miss
2987427Sgblack@eecs.umich.edu    assert(pkt->cmd != MemCmd::HardPFReq);
29910037SARM gem5 Developers
3007427Sgblack@eecs.umich.edu    if (inService &&
3017427Sgblack@eecs.umich.edu        (!deferredTargets.empty() || hasPostInvalidate() ||
30210037SARM gem5 Developers         (pkt->needsExclusive() &&
3037427Sgblack@eecs.umich.edu          (!isPendingDirty() || hasPostDowngrade() || isForward)))) {
3047427Sgblack@eecs.umich.edu        // need to put on deferred list
3057427Sgblack@eecs.umich.edu        if (hasPostInvalidate())
3067427Sgblack@eecs.umich.edu            replaceUpgrade(pkt);
3077427Sgblack@eecs.umich.edu        deferredTargets.add(pkt, whenReady, _order, Target::FromCPU, true);
3087427Sgblack@eecs.umich.edu    } else {
3097427Sgblack@eecs.umich.edu        // No request outstanding, or still OK to append to
3107427Sgblack@eecs.umich.edu        // outstanding request: append to regular target list.  Only
3117427Sgblack@eecs.umich.edu        // mark pending if current request hasn't been issued yet
3127427Sgblack@eecs.umich.edu        // (isn't in service).
3137427Sgblack@eecs.umich.edu        targets.add(pkt, whenReady, _order, Target::FromCPU, !inService);
3147427Sgblack@eecs.umich.edu    }
3157427Sgblack@eecs.umich.edu}
3167427Sgblack@eecs.umich.edu
3177427Sgblack@eecs.umich.edubool
3187427Sgblack@eecs.umich.eduMSHR::handleSnoop(PacketPtr pkt, Counter _order)
3197427Sgblack@eecs.umich.edu{
3207427Sgblack@eecs.umich.edu    DPRINTF(Cache, "%s for %s address %x size %d\n", __func__,
3217427Sgblack@eecs.umich.edu            pkt->cmdString(), pkt->getAddr(), pkt->getSize());
3227427Sgblack@eecs.umich.edu    if (!inService || (pkt->isExpressSnoop() && downstreamPending)) {
3237427Sgblack@eecs.umich.edu        // Request has not been issued yet, or it's been issued
3247427Sgblack@eecs.umich.edu        // locally but is buffered unissued at some downstream cache
3257427Sgblack@eecs.umich.edu        // which is forwarding us this snoop.  Either way, the packet
3267436Sdam.sunwoo@arm.com        // we're snooping logically precedes this MSHR's request, so
3277436Sdam.sunwoo@arm.com        // the snoop has no impact on the MSHR, but must be processed
32810037SARM gem5 Developers        // in the standard way by the cache.  The only exception is
32910037SARM gem5 Developers        // that if we're an L2+ cache buffering an UpgradeReq from a
3307436Sdam.sunwoo@arm.com        // higher-level cache, and the snoop is invalidating, then our
3317436Sdam.sunwoo@arm.com        // buffered upgrades must be converted to read exclusives,
3327436Sdam.sunwoo@arm.com        // since the upper-level cache no longer has a valid copy.
3337436Sdam.sunwoo@arm.com        // That is, even though the upper-level cache got out on its
3347436Sdam.sunwoo@arm.com        // local bus first, some other invalidating transaction
3357436Sdam.sunwoo@arm.com        // reached the global bus before the upgrade did.
3367436Sdam.sunwoo@arm.com        if (pkt->needsExclusive()) {
3377436Sdam.sunwoo@arm.com            targets.replaceUpgrades();
3387436Sdam.sunwoo@arm.com            deferredTargets.replaceUpgrades();
3397436Sdam.sunwoo@arm.com        }
3407436Sdam.sunwoo@arm.com
3417436Sdam.sunwoo@arm.com        return false;
34210037SARM gem5 Developers    }
3437436Sdam.sunwoo@arm.com
3447436Sdam.sunwoo@arm.com    // From here on down, the request issued by this MSHR logically
3457436Sdam.sunwoo@arm.com    // precedes the request we're snooping.
3467436Sdam.sunwoo@arm.com    if (pkt->needsExclusive()) {
3477436Sdam.sunwoo@arm.com        // snooped request still precedes the re-request we'll have to
3487436Sdam.sunwoo@arm.com        // issue for deferred targets, if any...
3497436Sdam.sunwoo@arm.com        deferredTargets.replaceUpgrades();
3507436Sdam.sunwoo@arm.com    }
3517436Sdam.sunwoo@arm.com
3527436Sdam.sunwoo@arm.com    if (hasPostInvalidate()) {
3537436Sdam.sunwoo@arm.com        // a prior snoop has already appended an invalidation, so
3547436Sdam.sunwoo@arm.com        // logically we don't have the block anymore; no need for
3557436Sdam.sunwoo@arm.com        // further snooping.
3567436Sdam.sunwoo@arm.com        return true;
3577436Sdam.sunwoo@arm.com    }
3587436Sdam.sunwoo@arm.com
3597644Sali.saidi@arm.com    if (isPendingDirty() || pkt->isInvalidate()) {
3608147SAli.Saidi@ARM.com        // We need to save and replay the packet in two cases:
3619385SAndreas.Sandberg@arm.com        // 1. We're awaiting an exclusive copy, so ownership is pending,
3629385SAndreas.Sandberg@arm.com        //    and we need to respond after we receive data.
3639385SAndreas.Sandberg@arm.com        // 2. It's an invalidation (e.g., UpgradeReq), and we need
3649385SAndreas.Sandberg@arm.com        //    to forward the snoop up the hierarchy after the current
3659385SAndreas.Sandberg@arm.com        //    transaction completes.
3669385SAndreas.Sandberg@arm.com
3679385SAndreas.Sandberg@arm.com        // Actual target device (typ. a memory) will delete the
3689385SAndreas.Sandberg@arm.com        // packet on reception, so we need to save a copy here.
3699385SAndreas.Sandberg@arm.com        PacketPtr cp_pkt = new Packet(pkt, true);
3709385SAndreas.Sandberg@arm.com        targets.add(cp_pkt, curTick(), _order, Target::FromSnoop,
3719385SAndreas.Sandberg@arm.com                     downstreamPending && targets.needsExclusive);
3729385SAndreas.Sandberg@arm.com
3739385SAndreas.Sandberg@arm.com        // WriteInvalidates must writeback and should not be inhibited on
3749385SAndreas.Sandberg@arm.com        // account of its snoops discovering MSHRs wanting exclusive access
37510037SARM gem5 Developers        // to what it wrote.  We don't want to push this check higher,
37610037SARM gem5 Developers        // however, because we want to be sure to add an invalidating
37710037SARM gem5 Developers        // Target::FromSnoop, above.
37810037SARM gem5 Developers        if (isPendingDirty() && (pkt->cmd != MemCmd::WriteInvalidateReq)) {
37910037SARM gem5 Developers            pkt->assertMemInhibit();
38010037SARM gem5 Developers            pkt->setSupplyExclusive();
38110037SARM gem5 Developers        }
38210037SARM gem5 Developers
38310037SARM gem5 Developers        if (pkt->needsExclusive()) {
38410037SARM gem5 Developers            // This transaction will take away our pending copy
38510037SARM gem5 Developers            postInvalidate = true;
38610037SARM gem5 Developers
38710037SARM gem5 Developers            // Do not defer (i.e. return true) the snoop if the block is
38810037SARM gem5 Developers            // going to be clean once the MSHR completes, as the data is
38910037SARM gem5 Developers            // ready now.
39010037SARM gem5 Developers            if (isPendingClean()) {
3918147SAli.Saidi@ARM.com                return false;
3927427Sgblack@eecs.umich.edu            }
3937427Sgblack@eecs.umich.edu        }
3947427Sgblack@eecs.umich.edu    }
39510037SARM gem5 Developers
39610037SARM gem5 Developers    if (!pkt->needsExclusive()) {
39710037SARM gem5 Developers        // This transaction will get a read-shared copy, downgrading
39810037SARM gem5 Developers        // our copy if we had an exclusive one
39910037SARM gem5 Developers        postDowngrade = true;
40010037SARM gem5 Developers        pkt->assertShared();
40110037SARM gem5 Developers    }
40210037SARM gem5 Developers
40310037SARM gem5 Developers    return true;
40410037SARM gem5 Developers}
40510037SARM gem5 Developers
40610037SARM gem5 Developers
40710037SARM gem5 Developersbool
40810037SARM gem5 DevelopersMSHR::promoteDeferredTargets()
40910037SARM gem5 Developers{
41010037SARM gem5 Developers    assert(targets.empty());
41110037SARM gem5 Developers    if (deferredTargets.empty()) {
41210037SARM gem5 Developers        return false;
41310037SARM gem5 Developers    }
41410037SARM gem5 Developers
41510037SARM gem5 Developers    // swap targets & deferredTargets lists
41610037SARM gem5 Developers    std::swap(targets, deferredTargets);
41710037SARM gem5 Developers
41810037SARM gem5 Developers    // clear deferredTargets flags
41910037SARM gem5 Developers    deferredTargets.resetFlags();
42010037SARM gem5 Developers
42110037SARM gem5 Developers    order = targets.front().order;
42210037SARM gem5 Developers    readyTime = std::max(curTick(), targets.front().readyTime);
42310037SARM gem5 Developers
42410037SARM gem5 Developers    return true;
42510037SARM gem5 Developers}
42610037SARM gem5 Developers
42710037SARM gem5 Developers
42810037SARM gem5 Developersvoid
42910037SARM gem5 DevelopersMSHR::handleFill(Packet *pkt, CacheBlk *blk)
43010037SARM gem5 Developers{
43111770SCurtis.Dunham@arm.com    if (!pkt->sharedAsserted()
43210037SARM gem5 Developers        && !(hasPostInvalidate() || hasPostDowngrade())
43311574SCurtis.Dunham@arm.com        && deferredTargets.needsExclusive) {
43411770SCurtis.Dunham@arm.com        // We got an exclusive response, but we have deferred targets
43511770SCurtis.Dunham@arm.com        // which are waiting to request an exclusive copy (not because
43610037SARM gem5 Developers        // of a pending invalidate).  This can happen if the original
43711770SCurtis.Dunham@arm.com        // request was for a read-only (non-exclusive) block, but we
43811770SCurtis.Dunham@arm.com        // got an exclusive copy anyway because of the E part of the
43910037SARM gem5 Developers        // MOESI/MESI protocol.  Since we got the exclusive copy
44010037SARM gem5 Developers        // there's no need to defer the targets, so move them up to
44110037SARM gem5 Developers        // the regular target list.
44210037SARM gem5 Developers        assert(!targets.needsExclusive);
44310037SARM gem5 Developers        targets.needsExclusive = true;
44410037SARM gem5 Developers        // if any of the deferred targets were upper-level cache
44510037SARM gem5 Developers        // requests marked downstreamPending, need to clear that
44610461SAndreas.Sandberg@ARM.com        assert(!downstreamPending);  // not pending here anymore
44710461SAndreas.Sandberg@ARM.com        deferredTargets.clearDownstreamPending();
44810461SAndreas.Sandberg@ARM.com        // this clears out deferredTargets too
44910461SAndreas.Sandberg@ARM.com        targets.splice(targets.end(), deferredTargets);
45010037SARM gem5 Developers        deferredTargets.resetFlags();
45110037SARM gem5 Developers    }
45210037SARM gem5 Developers}
45310037SARM gem5 Developers
45410037SARM gem5 Developers
45510037SARM gem5 Developersbool
45610037SARM gem5 DevelopersMSHR::checkFunctional(PacketPtr pkt)
45710037SARM gem5 Developers{
45810461SAndreas.Sandberg@ARM.com    // For printing, we treat the MSHR as a whole as single entity.
45910461SAndreas.Sandberg@ARM.com    // For other requests, we iterate over the individual targets
46010461SAndreas.Sandberg@ARM.com    // since that's where the actual data lies.
46110461SAndreas.Sandberg@ARM.com    if (pkt->isPrint()) {
46210461SAndreas.Sandberg@ARM.com        pkt->checkFunctional(this, addr, isSecure, size, NULL);
46310037SARM gem5 Developers        return false;
46410037SARM gem5 Developers    } else {
46510037SARM gem5 Developers        return (targets.checkFunctional(pkt) ||
46610037SARM gem5 Developers                deferredTargets.checkFunctional(pkt));
46710037SARM gem5 Developers    }
46811574SCurtis.Dunham@arm.com}
46910037SARM gem5 Developers
47010037SARM gem5 Developers
47110037SARM gem5 Developersvoid
47211574SCurtis.Dunham@arm.comMSHR::print(std::ostream &os, int verbosity, const std::string &prefix) const
47310037SARM gem5 Developers{
47410037SARM gem5 Developers    ccprintf(os, "%s[%x:%x](%s) %s %s %s state: %s %s %s %s %s\n",
47510037SARM gem5 Developers             prefix, addr, addr+size-1,
47610037SARM gem5 Developers             isSecure ? "s" : "ns",
47710037SARM gem5 Developers             isForward ? "Forward" : "",
47810037SARM gem5 Developers             isForwardNoResponse() ? "ForwNoResp" : "",
47910037SARM gem5 Developers             needsExclusive() ? "Excl" : "",
48010037SARM gem5 Developers             _isUncacheable ? "Unc" : "",
48110037SARM gem5 Developers             inService ? "InSvc" : "",
48210037SARM gem5 Developers             downstreamPending ? "DwnPend" : "",
4837405SAli.Saidi@ARM.com             hasPostInvalidate() ? "PostInv" : "",
48410035Sandreas.hansson@arm.com             hasPostDowngrade() ? "PostDowngr" : "");
4857405SAli.Saidi@ARM.com
4867405SAli.Saidi@ARM.com    ccprintf(os, "%s  Targets:\n", prefix);
4877614Sminkyu.jeong@arm.com    targets.print(os, verbosity, prefix + "    ");
48811771SCurtis.Dunham@arm.com    if (!deferredTargets.empty()) {
48911771SCurtis.Dunham@arm.com        ccprintf(os, "%s  Deferred Targets:\n", prefix);
49011771SCurtis.Dunham@arm.com        deferredTargets.print(os, verbosity, prefix + "      ");
49111771SCurtis.Dunham@arm.com    }
4927405SAli.Saidi@ARM.com}
4937405SAli.Saidi@ARM.com
4947405SAli.Saidi@ARM.comstd::string
4957405SAli.Saidi@ARM.comMSHR::print() const
4967405SAli.Saidi@ARM.com{
4977405SAli.Saidi@ARM.com    ostringstream str;
49810037SARM gem5 Developers    print(str);
49910037SARM gem5 Developers    return str.str();
50010037SARM gem5 Developers}
5019050Schander.sudanthi@arm.com