mshr.cc revision 9663
111731Sjason@lowepower.com/*
211731Sjason@lowepower.com * Copyright (c) 2012 ARM Limited
311731Sjason@lowepower.com * All rights reserved.
411731Sjason@lowepower.com *
511731Sjason@lowepower.com * The license below extends only to copyright in the software and shall
611731Sjason@lowepower.com * not be construed as granting a license to any other intellectual
711731Sjason@lowepower.com * property including but not limited to intellectual property relating
811731Sjason@lowepower.com * to a hardware implementation of the functionality of the software
911731Sjason@lowepower.com * licensed hereunder.  You may use the software subject to the license
1011731Sjason@lowepower.com * terms below provided that you ensure that this notice is replicated
1111731Sjason@lowepower.com * unmodified and in its entirety in all distributions of the software,
1211731Sjason@lowepower.com * modified or unmodified, in source code or in binary form.
1311731Sjason@lowepower.com *
1411731Sjason@lowepower.com * Copyright (c) 2002-2005 The Regents of The University of Michigan
1511731Sjason@lowepower.com * Copyright (c) 2010 Advanced Micro Devices, Inc.
1611731Sjason@lowepower.com * All rights reserved.
1711731Sjason@lowepower.com *
1811731Sjason@lowepower.com * Redistribution and use in source and binary forms, with or without
1911731Sjason@lowepower.com * modification, are permitted provided that the following conditions are
2011731Sjason@lowepower.com * met: redistributions of source code must retain the above copyright
2111731Sjason@lowepower.com * notice, this list of conditions and the following disclaimer;
2211731Sjason@lowepower.com * redistributions in binary form must reproduce the above copyright
2311731Sjason@lowepower.com * notice, this list of conditions and the following disclaimer in the
2411731Sjason@lowepower.com * documentation and/or other materials provided with the distribution;
2511731Sjason@lowepower.com * neither the name of the copyright holders nor the names of its
2611731Sjason@lowepower.com * contributors may be used to endorse or promote products derived from
2711731Sjason@lowepower.com * this software without specific prior written permission.
2811731Sjason@lowepower.com *
2911731Sjason@lowepower.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
3011731Sjason@lowepower.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3111731Sjason@lowepower.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
3211731Sjason@lowepower.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
3311731Sjason@lowepower.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
3411731Sjason@lowepower.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
3511731Sjason@lowepower.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3611731Sjason@lowepower.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3711731Sjason@lowepower.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3811731Sjason@lowepower.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3911731Sjason@lowepower.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
4011731Sjason@lowepower.com *
4111731Sjason@lowepower.com * Authors: Erik Hallnor
4211731Sjason@lowepower.com *          Dave Greene
4311731Sjason@lowepower.com */
4411731Sjason@lowepower.com
4511731Sjason@lowepower.com/**
4611731Sjason@lowepower.com * @file
4711731Sjason@lowepower.com * Miss Status and Handling Register (MSHR) definitions.
4811731Sjason@lowepower.com */
4911731Sjason@lowepower.com
5011731Sjason@lowepower.com#include <algorithm>
5111731Sjason@lowepower.com#include <cassert>
5211731Sjason@lowepower.com#include <string>
5311731Sjason@lowepower.com#include <vector>
5411731Sjason@lowepower.com
5511731Sjason@lowepower.com#include "base/misc.hh"
5611731Sjason@lowepower.com#include "base/types.hh"
5711731Sjason@lowepower.com#include "debug/Cache.hh"
5811731Sjason@lowepower.com#include "mem/cache/cache.hh"
5911731Sjason@lowepower.com#include "mem/cache/mshr.hh"
6011731Sjason@lowepower.com#include "sim/core.hh"
6111731Sjason@lowepower.com
6211731Sjason@lowepower.comusing namespace std;
6311731Sjason@lowepower.com
6411731Sjason@lowepower.comMSHR::MSHR()
6511731Sjason@lowepower.com{
6611731Sjason@lowepower.com    inService = false;
6711731Sjason@lowepower.com    ntargets = 0;
6811731Sjason@lowepower.com    threadNum = InvalidThreadID;
6911731Sjason@lowepower.com    targets = new TargetList();
7011731Sjason@lowepower.com    deferredTargets = new TargetList();
7111731Sjason@lowepower.com}
7211731Sjason@lowepower.com
7311731Sjason@lowepower.com
7411731Sjason@lowepower.comMSHR::TargetList::TargetList()
7511731Sjason@lowepower.com    : needsExclusive(false), hasUpgrade(false)
7611731Sjason@lowepower.com{}
7711731Sjason@lowepower.com
7811731Sjason@lowepower.com
7911731Sjason@lowepower.cominline void
8011731Sjason@lowepower.comMSHR::TargetList::add(PacketPtr pkt, Tick readyTime,
8111731Sjason@lowepower.com                      Counter order, Target::Source source, bool markPending)
8211731Sjason@lowepower.com{
8311731Sjason@lowepower.com    if (source != Target::FromSnoop) {
8411731Sjason@lowepower.com        if (pkt->needsExclusive()) {
8511731Sjason@lowepower.com            needsExclusive = true;
8611731Sjason@lowepower.com        }
8711731Sjason@lowepower.com
8812137Sar4jc@virginia.edu        // StoreCondReq is effectively an upgrade if it's in an MSHR
8911731Sjason@lowepower.com        // since it would have been failed already if we didn't have a
9011731Sjason@lowepower.com        // read-only copy
9112137Sar4jc@virginia.edu        if (pkt->isUpgrade() || pkt->cmd == MemCmd::StoreCondReq) {
9211731Sjason@lowepower.com            hasUpgrade = true;
9311731Sjason@lowepower.com        }
9411731Sjason@lowepower.com    }
9511731Sjason@lowepower.com
9611731Sjason@lowepower.com    if (markPending) {
9711731Sjason@lowepower.com        // Iterate over the SenderState stack and see if we find
9811731Sjason@lowepower.com        // an MSHR entry. If we do, set the downstreamPending
9911731Sjason@lowepower.com        // flag. Otherwise, do nothing.
10011731Sjason@lowepower.com        MSHR *mshr = pkt->findNextSenderState<MSHR>();
10111731Sjason@lowepower.com        if (mshr != NULL) {
10211731Sjason@lowepower.com            assert(!mshr->downstreamPending);
10311731Sjason@lowepower.com            mshr->downstreamPending = true;
10411731Sjason@lowepower.com        }
10511731Sjason@lowepower.com    }
10611731Sjason@lowepower.com
10711731Sjason@lowepower.com    push_back(Target(pkt, readyTime, order, source, markPending));
10811731Sjason@lowepower.com}
10911731Sjason@lowepower.com
11011731Sjason@lowepower.com
11111731Sjason@lowepower.comstatic void
11211731Sjason@lowepower.comreplaceUpgrade(PacketPtr pkt)
11311731Sjason@lowepower.com{
11411731Sjason@lowepower.com    if (pkt->cmd == MemCmd::UpgradeReq) {
11511731Sjason@lowepower.com        pkt->cmd = MemCmd::ReadExReq;
11611731Sjason@lowepower.com        DPRINTF(Cache, "Replacing UpgradeReq with ReadExReq\n");
11711731Sjason@lowepower.com    } else if (pkt->cmd == MemCmd::SCUpgradeReq) {
11811731Sjason@lowepower.com        pkt->cmd = MemCmd::SCUpgradeFailReq;
11911731Sjason@lowepower.com        DPRINTF(Cache, "Replacing SCUpgradeReq with SCUpgradeFailReq\n");
12011731Sjason@lowepower.com    } else if (pkt->cmd == MemCmd::StoreCondReq) {
12111731Sjason@lowepower.com        pkt->cmd = MemCmd::StoreCondFailReq;
12211731Sjason@lowepower.com        DPRINTF(Cache, "Replacing StoreCondReq with StoreCondFailReq\n");
12311731Sjason@lowepower.com    }
12411731Sjason@lowepower.com}
12511731Sjason@lowepower.com
12611731Sjason@lowepower.com
12711731Sjason@lowepower.comvoid
12811731Sjason@lowepower.comMSHR::TargetList::replaceUpgrades()
12911731Sjason@lowepower.com{
13011731Sjason@lowepower.com    if (!hasUpgrade)
13111731Sjason@lowepower.com        return;
13211731Sjason@lowepower.com
13311731Sjason@lowepower.com    Iterator end_i = end();
13411731Sjason@lowepower.com    for (Iterator i = begin(); i != end_i; ++i) {
13511731Sjason@lowepower.com        replaceUpgrade(i->pkt);
13611731Sjason@lowepower.com    }
13711731Sjason@lowepower.com
13811731Sjason@lowepower.com    hasUpgrade = false;
13911731Sjason@lowepower.com}
14011731Sjason@lowepower.com
14111731Sjason@lowepower.com
14211731Sjason@lowepower.comvoid
14311731Sjason@lowepower.comMSHR::TargetList::clearDownstreamPending()
14411731Sjason@lowepower.com{
14511731Sjason@lowepower.com    Iterator end_i = end();
14611731Sjason@lowepower.com    for (Iterator i = begin(); i != end_i; ++i) {
14711731Sjason@lowepower.com        if (i->markedPending) {
14811731Sjason@lowepower.com            // Iterate over the SenderState stack and see if we find
14911731Sjason@lowepower.com            // an MSHR entry. If we find one, clear the
15011731Sjason@lowepower.com            // downstreamPending flag by calling
15111731Sjason@lowepower.com            // clearDownstreamPending(). This recursively clears the
15211731Sjason@lowepower.com            // downstreamPending flag in all caches this packet has
15311731Sjason@lowepower.com            // passed through.
15411731Sjason@lowepower.com            MSHR *mshr = i->pkt->findNextSenderState<MSHR>();
15511731Sjason@lowepower.com            if (mshr != NULL) {
15611731Sjason@lowepower.com                mshr->clearDownstreamPending();
15711731Sjason@lowepower.com            }
15811731Sjason@lowepower.com        }
15911731Sjason@lowepower.com    }
16011731Sjason@lowepower.com}
16111731Sjason@lowepower.com
16211731Sjason@lowepower.com
16311731Sjason@lowepower.combool
16411731Sjason@lowepower.comMSHR::TargetList::checkFunctional(PacketPtr pkt)
16511731Sjason@lowepower.com{
16611731Sjason@lowepower.com    Iterator end_i = end();
16711731Sjason@lowepower.com    for (Iterator i = begin(); i != end_i; ++i) {
16811731Sjason@lowepower.com        if (pkt->checkFunctional(i->pkt)) {
16911731Sjason@lowepower.com            return true;
17011731Sjason@lowepower.com        }
17111731Sjason@lowepower.com    }
17211731Sjason@lowepower.com
17311731Sjason@lowepower.com    return false;
17411731Sjason@lowepower.com}
17511731Sjason@lowepower.com
17611731Sjason@lowepower.com
17711731Sjason@lowepower.comvoid
17811731Sjason@lowepower.comMSHR::TargetList::
17911731Sjason@lowepower.comprint(std::ostream &os, int verbosity, const std::string &prefix) const
18011731Sjason@lowepower.com{
18111731Sjason@lowepower.com    ConstIterator end_i = end();
18211731Sjason@lowepower.com    for (ConstIterator i = begin(); i != end_i; ++i) {
18311731Sjason@lowepower.com        const char *s;
18411731Sjason@lowepower.com        switch (i->source) {
18511731Sjason@lowepower.com          case Target::FromCPU:
18611731Sjason@lowepower.com            s = "FromCPU";
18711731Sjason@lowepower.com            break;
18811731Sjason@lowepower.com          case Target::FromSnoop:
18911731Sjason@lowepower.com            s = "FromSnoop";
19011731Sjason@lowepower.com            break;
19111731Sjason@lowepower.com          case Target::FromPrefetcher:
19211731Sjason@lowepower.com            s = "FromPrefetcher";
19311731Sjason@lowepower.com            break;
19411731Sjason@lowepower.com          default:
19511731Sjason@lowepower.com            s = "";
19611731Sjason@lowepower.com            break;
19711731Sjason@lowepower.com        }
19811731Sjason@lowepower.com        ccprintf(os, "%s%s: ", prefix, s);
19911731Sjason@lowepower.com        i->pkt->print(os, verbosity, "");
20011731Sjason@lowepower.com    }
20111731Sjason@lowepower.com}
20211731Sjason@lowepower.com
20311731Sjason@lowepower.com
20411731Sjason@lowepower.comvoid
20511731Sjason@lowepower.comMSHR::allocate(Addr _addr, int _size, PacketPtr target,
20611731Sjason@lowepower.com               Tick whenReady, Counter _order)
20711731Sjason@lowepower.com{
20811731Sjason@lowepower.com    addr = _addr;
20911731Sjason@lowepower.com    size = _size;
21011731Sjason@lowepower.com    readyTime = whenReady;
21111731Sjason@lowepower.com    order = _order;
21211731Sjason@lowepower.com    assert(target);
21311731Sjason@lowepower.com    isForward = false;
21411731Sjason@lowepower.com    _isUncacheable = target->req->isUncacheable();
21511731Sjason@lowepower.com    inService = false;
21611731Sjason@lowepower.com    downstreamPending = false;
21711731Sjason@lowepower.com    threadNum = 0;
21811731Sjason@lowepower.com    ntargets = 1;
21911731Sjason@lowepower.com    assert(targets->isReset());
22011731Sjason@lowepower.com    // Don't know of a case where we would allocate a new MSHR for a
22111731Sjason@lowepower.com    // snoop (mem-side request), so set source according to request here
22211731Sjason@lowepower.com    Target::Source source = (target->cmd == MemCmd::HardPFReq) ?
22311731Sjason@lowepower.com        Target::FromPrefetcher : Target::FromCPU;
22411731Sjason@lowepower.com    targets->add(target, whenReady, _order, source, true);
22511731Sjason@lowepower.com    assert(deferredTargets->isReset());
22611731Sjason@lowepower.com    data = NULL;
22711731Sjason@lowepower.com}
22811731Sjason@lowepower.com
22911731Sjason@lowepower.com
23011731Sjason@lowepower.comvoid
23111731Sjason@lowepower.comMSHR::clearDownstreamPending()
23211731Sjason@lowepower.com{
23311731Sjason@lowepower.com    assert(downstreamPending);
23411731Sjason@lowepower.com    downstreamPending = false;
23511731Sjason@lowepower.com    // recursively clear flag on any MSHRs we will be forwarding
23611731Sjason@lowepower.com    // responses to
23711731Sjason@lowepower.com    targets->clearDownstreamPending();
23811731Sjason@lowepower.com}
23911731Sjason@lowepower.com
24011731Sjason@lowepower.combool
24111731Sjason@lowepower.comMSHR::markInService(PacketPtr pkt)
24211731Sjason@lowepower.com{
24311731Sjason@lowepower.com    assert(!inService);
24411731Sjason@lowepower.com    if (isForwardNoResponse()) {
24511731Sjason@lowepower.com        // we just forwarded the request packet & don't expect a
24611731Sjason@lowepower.com        // response, so get rid of it
24711731Sjason@lowepower.com        assert(getNumTargets() == 1);
24811731Sjason@lowepower.com        popTarget();
24911731Sjason@lowepower.com        return true;
25011731Sjason@lowepower.com    }
25111731Sjason@lowepower.com    inService = true;
25211731Sjason@lowepower.com    pendingDirty = (targets->needsExclusive ||
25311731Sjason@lowepower.com                    (!pkt->sharedAsserted() && pkt->memInhibitAsserted()));
25411731Sjason@lowepower.com    postInvalidate = postDowngrade = false;
25511731Sjason@lowepower.com
25611731Sjason@lowepower.com    if (!downstreamPending) {
25711731Sjason@lowepower.com        // let upstream caches know that the request has made it to a
25811731Sjason@lowepower.com        // level where it's going to get a response
25911731Sjason@lowepower.com        targets->clearDownstreamPending();
26011731Sjason@lowepower.com    }
26111731Sjason@lowepower.com    return false;
26211731Sjason@lowepower.com}
26311731Sjason@lowepower.com
26411731Sjason@lowepower.com
26511731Sjason@lowepower.comvoid
26611731Sjason@lowepower.comMSHR::deallocate()
26711731Sjason@lowepower.com{
26811731Sjason@lowepower.com    assert(targets->empty());
26911731Sjason@lowepower.com    targets->resetFlags();
27011731Sjason@lowepower.com    assert(deferredTargets->isReset());
27111731Sjason@lowepower.com    assert(ntargets == 0);
27211731Sjason@lowepower.com    inService = false;
27311731Sjason@lowepower.com}
27411731Sjason@lowepower.com
27511731Sjason@lowepower.com/*
27611731Sjason@lowepower.com * Adds a target to an MSHR
27711731Sjason@lowepower.com */
27811731Sjason@lowepower.comvoid
27911731Sjason@lowepower.comMSHR::allocateTarget(PacketPtr pkt, Tick whenReady, Counter _order)
28011731Sjason@lowepower.com{
28111731Sjason@lowepower.com    // if there's a request already in service for this MSHR, we will
28211731Sjason@lowepower.com    // have to defer the new target until after the response if any of
28311731Sjason@lowepower.com    // the following are true:
28411731Sjason@lowepower.com    // - there are other targets already deferred
28511731Sjason@lowepower.com    // - there's a pending invalidate to be applied after the response
28611731Sjason@lowepower.com    //   comes back (but before this target is processed)
28711731Sjason@lowepower.com    // - this target requires an exclusive block and either we're not
28811731Sjason@lowepower.com    //   getting an exclusive block back or we have already snooped
28911731Sjason@lowepower.com    //   another read request that will downgrade our exclusive block
29011731Sjason@lowepower.com    //   to shared
29111731Sjason@lowepower.com
29212137Sar4jc@virginia.edu    // assume we'd never issue a prefetch when we've got an
29311731Sjason@lowepower.com    // outstanding miss
29411731Sjason@lowepower.com    assert(pkt->cmd != MemCmd::HardPFReq);
29511731Sjason@lowepower.com
29611731Sjason@lowepower.com    if (inService &&
29711731Sjason@lowepower.com        (!deferredTargets->empty() || hasPostInvalidate() ||
29811731Sjason@lowepower.com         (pkt->needsExclusive() &&
29911731Sjason@lowepower.com          (!isPendingDirty() || hasPostDowngrade() || isForward)))) {
30011731Sjason@lowepower.com        // need to put on deferred list
30112137Sar4jc@virginia.edu        if (hasPostInvalidate())
30211731Sjason@lowepower.com            replaceUpgrade(pkt);
30311731Sjason@lowepower.com        deferredTargets->add(pkt, whenReady, _order, Target::FromCPU, true);
30411731Sjason@lowepower.com    } else {
30512137Sar4jc@virginia.edu        // No request outstanding, or still OK to append to
30611731Sjason@lowepower.com        // outstanding request: append to regular target list.  Only
30712137Sar4jc@virginia.edu        // mark pending if current request hasn't been issued yet
30811731Sjason@lowepower.com        // (isn't in service).
30912137Sar4jc@virginia.edu        targets->add(pkt, whenReady, _order, Target::FromCPU, !inService);
31011731Sjason@lowepower.com    }
31111731Sjason@lowepower.com
31211731Sjason@lowepower.com    ++ntargets;
31311731Sjason@lowepower.com}
31411731Sjason@lowepower.com
31511731Sjason@lowepower.combool
31611731Sjason@lowepower.comMSHR::handleSnoop(PacketPtr pkt, Counter _order)
31711731Sjason@lowepower.com{
31811731Sjason@lowepower.com    DPRINTF(Cache, "%s for %s address %x size %d\n", __func__,
31911731Sjason@lowepower.com            pkt->cmdString(), pkt->getAddr(), pkt->getSize());
32011731Sjason@lowepower.com    if (!inService || (pkt->isExpressSnoop() && downstreamPending)) {
32111731Sjason@lowepower.com        // Request has not been issued yet, or it's been issued
32211731Sjason@lowepower.com        // locally but is buffered unissued at some downstream cache
32311731Sjason@lowepower.com        // which is forwarding us this snoop.  Either way, the packet
32411731Sjason@lowepower.com        // we're snooping logically precedes this MSHR's request, so
32511731Sjason@lowepower.com        // the snoop has no impact on the MSHR, but must be processed
32611731Sjason@lowepower.com        // in the standard way by the cache.  The only exception is
32711731Sjason@lowepower.com        // that if we're an L2+ cache buffering an UpgradeReq from a
32811731Sjason@lowepower.com        // higher-level cache, and the snoop is invalidating, then our
32911731Sjason@lowepower.com        // buffered upgrades must be converted to read exclusives,
33011731Sjason@lowepower.com        // since the upper-level cache no longer has a valid copy.
33111731Sjason@lowepower.com        // That is, even though the upper-level cache got out on its
33211731Sjason@lowepower.com        // local bus first, some other invalidating transaction
33311731Sjason@lowepower.com        // reached the global bus before the upgrade did.
33411731Sjason@lowepower.com        if (pkt->needsExclusive()) {
33511731Sjason@lowepower.com            targets->replaceUpgrades();
33611731Sjason@lowepower.com            deferredTargets->replaceUpgrades();
33711731Sjason@lowepower.com        }
33811731Sjason@lowepower.com
33911731Sjason@lowepower.com        return false;
34011731Sjason@lowepower.com    }
34111731Sjason@lowepower.com
34211731Sjason@lowepower.com    // From here on down, the request issued by this MSHR logically
34311731Sjason@lowepower.com    // precedes the request we're snooping.
34411731Sjason@lowepower.com    if (pkt->needsExclusive()) {
34511731Sjason@lowepower.com        // snooped request still precedes the re-request we'll have to
34611731Sjason@lowepower.com        // issue for deferred targets, if any...
34711731Sjason@lowepower.com        deferredTargets->replaceUpgrades();
34811731Sjason@lowepower.com    }
34911731Sjason@lowepower.com
35011731Sjason@lowepower.com    if (hasPostInvalidate()) {
35111731Sjason@lowepower.com        // a prior snoop has already appended an invalidation, so
35211731Sjason@lowepower.com        // logically we don't have the block anymore; no need for
35311731Sjason@lowepower.com        // further snooping.
35411731Sjason@lowepower.com        return true;
35511731Sjason@lowepower.com    }
35611731Sjason@lowepower.com
35711731Sjason@lowepower.com    if (isPendingDirty() || pkt->isInvalidate()) {
35811731Sjason@lowepower.com        // We need to save and replay the packet in two cases:
35911731Sjason@lowepower.com        // 1. We're awaiting an exclusive copy, so ownership is pending,
36011731Sjason@lowepower.com        //    and we need to respond after we receive data.
36111731Sjason@lowepower.com        // 2. It's an invalidation (e.g., UpgradeReq), and we need
36211731Sjason@lowepower.com        //    to forward the snoop up the hierarchy after the current
36311731Sjason@lowepower.com        //    transaction completes.
36411731Sjason@lowepower.com
36511731Sjason@lowepower.com        // Actual target device (typ. a memory) will delete the
36611731Sjason@lowepower.com        // packet on reception, so we need to save a copy here.
36711731Sjason@lowepower.com        PacketPtr cp_pkt = new Packet(pkt, true);
36811731Sjason@lowepower.com        targets->add(cp_pkt, curTick(), _order, Target::FromSnoop,
36911731Sjason@lowepower.com                     downstreamPending && targets->needsExclusive);
37011731Sjason@lowepower.com        ++ntargets;
37111731Sjason@lowepower.com
37211731Sjason@lowepower.com        if (isPendingDirty()) {
37311731Sjason@lowepower.com            pkt->assertMemInhibit();
37411731Sjason@lowepower.com            pkt->setSupplyExclusive();
37511731Sjason@lowepower.com        }
37611731Sjason@lowepower.com
37711731Sjason@lowepower.com        if (pkt->needsExclusive()) {
37811731Sjason@lowepower.com            // This transaction will take away our pending copy
37911731Sjason@lowepower.com            postInvalidate = true;
38011731Sjason@lowepower.com        }
38111731Sjason@lowepower.com    }
38211731Sjason@lowepower.com
38311731Sjason@lowepower.com    if (!pkt->needsExclusive()) {
384        // This transaction will get a read-shared copy, downgrading
385        // our copy if we had an exclusive one
386        postDowngrade = true;
387        pkt->assertShared();
388    }
389
390    return true;
391}
392
393
394bool
395MSHR::promoteDeferredTargets()
396{
397    assert(targets->empty());
398    if (deferredTargets->empty()) {
399        return false;
400    }
401
402    // swap targets & deferredTargets lists
403    TargetList *tmp = targets;
404    targets = deferredTargets;
405    deferredTargets = tmp;
406
407    assert(targets->size() == ntargets);
408
409    // clear deferredTargets flags
410    deferredTargets->resetFlags();
411
412    order = targets->front().order;
413    readyTime = std::max(curTick(), targets->front().readyTime);
414
415    return true;
416}
417
418
419void
420MSHR::handleFill(Packet *pkt, CacheBlk *blk)
421{
422    if (!pkt->sharedAsserted()
423        && !(hasPostInvalidate() || hasPostDowngrade())
424        && deferredTargets->needsExclusive) {
425        // We got an exclusive response, but we have deferred targets
426        // which are waiting to request an exclusive copy (not because
427        // of a pending invalidate).  This can happen if the original
428        // request was for a read-only (non-exclusive) block, but we
429        // got an exclusive copy anyway because of the E part of the
430        // MOESI/MESI protocol.  Since we got the exclusive copy
431        // there's no need to defer the targets, so move them up to
432        // the regular target list.
433        assert(!targets->needsExclusive);
434        targets->needsExclusive = true;
435        // if any of the deferred targets were upper-level cache
436        // requests marked downstreamPending, need to clear that
437        assert(!downstreamPending);  // not pending here anymore
438        deferredTargets->clearDownstreamPending();
439        // this clears out deferredTargets too
440        targets->splice(targets->end(), *deferredTargets);
441        deferredTargets->resetFlags();
442    }
443}
444
445
446bool
447MSHR::checkFunctional(PacketPtr pkt)
448{
449    // For printing, we treat the MSHR as a whole as single entity.
450    // For other requests, we iterate over the individual targets
451    // since that's where the actual data lies.
452    if (pkt->isPrint()) {
453        pkt->checkFunctional(this, addr, size, NULL);
454        return false;
455    } else {
456        return (targets->checkFunctional(pkt) ||
457                deferredTargets->checkFunctional(pkt));
458    }
459}
460
461
462void
463MSHR::print(std::ostream &os, int verbosity, const std::string &prefix) const
464{
465    ccprintf(os, "%s[%x:%x] %s %s %s state: %s %s %s %s\n",
466             prefix, addr, addr+size-1,
467             isForward ? "Forward" : "",
468             isForwardNoResponse() ? "ForwNoResp" : "",
469             needsExclusive() ? "Excl" : "",
470             _isUncacheable ? "Unc" : "",
471             inService ? "InSvc" : "",
472             downstreamPending ? "DwnPend" : "",
473             hasPostInvalidate() ? "PostInv" : "",
474             hasPostDowngrade() ? "PostDowngr" : "");
475
476    ccprintf(os, "%s  Targets:\n", prefix);
477    targets->print(os, verbosity, prefix + "    ");
478    if (!deferredTargets->empty()) {
479        ccprintf(os, "%s  Deferred Targets:\n", prefix);
480        deferredTargets->print(os, verbosity, prefix + "      ");
481    }
482}
483
484std::string
485MSHR::print() const
486{
487    ostringstream str;
488    print(str);
489    return str.str();
490}
491
492MSHR::~MSHR()
493{
494    delete[] targets;
495    delete[] deferredTargets;
496}
497