mshr.cc revision 10922:5ee72f4b2931
12SN/A/*
28703Sandreas.hansson@arm.com * Copyright (c) 2012-2013, 2015 ARM Limited
38703Sandreas.hansson@arm.com * All rights reserved.
48703Sandreas.hansson@arm.com *
58703Sandreas.hansson@arm.com * The license below extends only to copyright in the software and shall
68703Sandreas.hansson@arm.com * not be construed as granting a license to any other intellectual
78703Sandreas.hansson@arm.com * property including but not limited to intellectual property relating
88703Sandreas.hansson@arm.com * to a hardware implementation of the functionality of the software
98703Sandreas.hansson@arm.com * licensed hereunder.  You may use the software subject to the license
108703Sandreas.hansson@arm.com * terms below provided that you ensure that this notice is replicated
118703Sandreas.hansson@arm.com * unmodified and in its entirety in all distributions of the software,
128703Sandreas.hansson@arm.com * modified or unmodified, in source code or in binary form.
138703Sandreas.hansson@arm.com *
141762SN/A * Copyright (c) 2002-2005 The Regents of The University of Michigan
157897Shestness@cs.utexas.edu * Copyright (c) 2010 Advanced Micro Devices, Inc.
162SN/A * All rights reserved.
172SN/A *
182SN/A * Redistribution and use in source and binary forms, with or without
192SN/A * modification, are permitted provided that the following conditions are
202SN/A * met: redistributions of source code must retain the above copyright
212SN/A * notice, this list of conditions and the following disclaimer;
222SN/A * redistributions in binary form must reproduce the above copyright
232SN/A * notice, this list of conditions and the following disclaimer in the
242SN/A * documentation and/or other materials provided with the distribution;
252SN/A * neither the name of the copyright holders nor the names of its
262SN/A * contributors may be used to endorse or promote products derived from
272SN/A * this software without specific prior written permission.
282SN/A *
292SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
302SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
312SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
322SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
332SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
342SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
352SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
362SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
372SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
382SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
392SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
402665Ssaidi@eecs.umich.edu *
412665Ssaidi@eecs.umich.edu * Authors: Erik Hallnor
422665Ssaidi@eecs.umich.edu *          Dave Greene
432665Ssaidi@eecs.umich.edu */
447897Shestness@cs.utexas.edu
452SN/A/**
462SN/A * @file
472SN/A * Miss Status and Handling Register (MSHR) definitions.
482SN/A */
492SN/A
502SN/A#include <algorithm>
5175SN/A#include <cassert>
522SN/A#include <string>
532439SN/A#include <vector>
542439SN/A
55603SN/A#include "base/misc.hh"
56603SN/A#include "base/types.hh"
574762Snate@binkert.org#include "debug/Cache.hh"
588769Sgblack@eecs.umich.edu#include "mem/cache/cache.hh"
598852Sandreas.hansson@arm.com#include "mem/cache/mshr.hh"
608703Sandreas.hansson@arm.com#include "sim/core.hh"
612520SN/A
624762Snate@binkert.orgusing namespace std;
636658Snate@binkert.org
641634SN/AMSHR::MSHR() : readyTime(0), _isUncacheable(false), downstreamPending(false),
658769Sgblack@eecs.umich.edu               pendingDirty(false),
668769Sgblack@eecs.umich.edu               postInvalidate(false), postDowngrade(false),
671634SN/A               queue(NULL), order(0), blkAddr(0),
682521SN/A               blkSize(0), isSecure(false), inService(false),
69803SN/A               isForward(false), threadNum(InvalidThreadID), data(NULL)
708769Sgblack@eecs.umich.edu{
712SN/A}
728703Sandreas.hansson@arm.com
732SN/A
748703Sandreas.hansson@arm.comMSHR::TargetList::TargetList()
758703Sandreas.hansson@arm.com    : needsExclusive(false), hasUpgrade(false)
768703Sandreas.hansson@arm.com{}
778703Sandreas.hansson@arm.com
788703Sandreas.hansson@arm.com
798703Sandreas.hansson@arm.cominline void
808703Sandreas.hansson@arm.comMSHR::TargetList::add(PacketPtr pkt, Tick readyTime,
818703Sandreas.hansson@arm.com                      Counter order, Target::Source source, bool markPending)
828703Sandreas.hansson@arm.com{
838703Sandreas.hansson@arm.com    if (source != Target::FromSnoop) {
848703Sandreas.hansson@arm.com        if (pkt->needsExclusive()) {
858703Sandreas.hansson@arm.com            needsExclusive = true;
868703Sandreas.hansson@arm.com        }
878703Sandreas.hansson@arm.com
888703Sandreas.hansson@arm.com        // StoreCondReq is effectively an upgrade if it's in an MSHR
898703Sandreas.hansson@arm.com        // since it would have been failed already if we didn't have a
908703Sandreas.hansson@arm.com        // read-only copy
918703Sandreas.hansson@arm.com        if (pkt->isUpgrade() || pkt->cmd == MemCmd::StoreCondReq) {
928703Sandreas.hansson@arm.com            hasUpgrade = true;
938703Sandreas.hansson@arm.com        }
948703Sandreas.hansson@arm.com    }
958703Sandreas.hansson@arm.com
968703Sandreas.hansson@arm.com    if (markPending) {
978711Sandreas.hansson@arm.com        // Iterate over the SenderState stack and see if we find
988711Sandreas.hansson@arm.com        // an MSHR entry. If we do, set the downstreamPending
998711Sandreas.hansson@arm.com        // flag. Otherwise, do nothing.
1008711Sandreas.hansson@arm.com        MSHR *mshr = pkt->findNextSenderState<MSHR>();
1018711Sandreas.hansson@arm.com        if (mshr != NULL) {
1028711Sandreas.hansson@arm.com            assert(!mshr->downstreamPending);
1038711Sandreas.hansson@arm.com            mshr->downstreamPending = true;
1048703Sandreas.hansson@arm.com        }
1058703Sandreas.hansson@arm.com    }
1068703Sandreas.hansson@arm.com
1078703Sandreas.hansson@arm.com    emplace_back(pkt, readyTime, order, source, markPending);
1088703Sandreas.hansson@arm.com}
109603SN/A
1102901Ssaidi@eecs.umich.edu
1118703Sandreas.hansson@arm.comstatic void
1128706Sandreas.hansson@arm.comreplaceUpgrade(PacketPtr pkt)
1138706Sandreas.hansson@arm.com{
1148706Sandreas.hansson@arm.com    if (pkt->cmd == MemCmd::UpgradeReq) {
1158706Sandreas.hansson@arm.com        pkt->cmd = MemCmd::ReadExReq;
1168706Sandreas.hansson@arm.com        DPRINTF(Cache, "Replacing UpgradeReq with ReadExReq\n");
1178706Sandreas.hansson@arm.com    } else if (pkt->cmd == MemCmd::SCUpgradeReq) {
1188852Sandreas.hansson@arm.com        pkt->cmd = MemCmd::SCUpgradeFailReq;
1198703Sandreas.hansson@arm.com        DPRINTF(Cache, "Replacing SCUpgradeReq with SCUpgradeFailReq\n");
1208703Sandreas.hansson@arm.com    } else if (pkt->cmd == MemCmd::StoreCondReq) {
1218703Sandreas.hansson@arm.com        pkt->cmd = MemCmd::StoreCondFailReq;
1228703Sandreas.hansson@arm.com        DPRINTF(Cache, "Replacing StoreCondReq with StoreCondFailReq\n");
1238852Sandreas.hansson@arm.com    }
1248703Sandreas.hansson@arm.com}
1258852Sandreas.hansson@arm.com
1268703Sandreas.hansson@arm.com
1278703Sandreas.hansson@arm.comvoid
1288703Sandreas.hansson@arm.comMSHR::TargetList::replaceUpgrades()
1298703Sandreas.hansson@arm.com{
1308703Sandreas.hansson@arm.com    if (!hasUpgrade)
1318703Sandreas.hansson@arm.com        return;
1322902Ssaidi@eecs.umich.edu
1332902Ssaidi@eecs.umich.edu    for (auto& t : *this) {
1344762Snate@binkert.org        replaceUpgrade(t.pkt);
1354762Snate@binkert.org    }
1364762Snate@binkert.org
1374762Snate@binkert.org    hasUpgrade = false;
1384762Snate@binkert.org}
1394762Snate@binkert.org
1402901Ssaidi@eecs.umich.edu
1412901Ssaidi@eecs.umich.eduvoid
1422901Ssaidi@eecs.umich.eduMSHR::TargetList::clearDownstreamPending()
1432901Ssaidi@eecs.umich.edu{
1442901Ssaidi@eecs.umich.edu    for (auto& t : *this) {
1454762Snate@binkert.org        if (t.markedPending) {
1462901Ssaidi@eecs.umich.edu            // Iterate over the SenderState stack and see if we find
1472521SN/A            // an MSHR entry. If we find one, clear the
1482SN/A            // downstreamPending flag by calling
1492SN/A            // clearDownstreamPending(). This recursively clears the
1502680Sktlim@umich.edu            // downstreamPending flag in all caches this packet has
1515714Shsul@eecs.umich.edu            // passed through.
1521806SN/A            MSHR *mshr = t.pkt->findNextSenderState<MSHR>();
1536221Snate@binkert.org            if (mshr != NULL) {
1545713Shsul@eecs.umich.edu                mshr->clearDownstreamPending();
1555713Shsul@eecs.umich.edu            }
1565713Shsul@eecs.umich.edu        }
1575713Shsul@eecs.umich.edu    }
1585714Shsul@eecs.umich.edu}
1591806SN/A
1606227Snate@binkert.org
1615714Shsul@eecs.umich.edubool
1621806SN/AMSHR::TargetList::checkFunctional(PacketPtr pkt)
163180SN/A{
1646029Ssteve.reinhardt@amd.com    for (auto& t : *this) {
1656029Ssteve.reinhardt@amd.com        if (pkt->checkFunctional(t.pkt)) {
1666029Ssteve.reinhardt@amd.com            return true;
1676029Ssteve.reinhardt@amd.com        }
1688460SAli.Saidi@ARM.com    }
1698460SAli.Saidi@ARM.com
1708460SAli.Saidi@ARM.com    return false;
1718460SAli.Saidi@ARM.com}
1728460SAli.Saidi@ARM.com
1738460SAli.Saidi@ARM.com
1748460SAli.Saidi@ARM.comvoid
1758460SAli.Saidi@ARM.comMSHR::TargetList::print(std::ostream &os, int verbosity,
1768765Sgblack@eecs.umich.edu                        const std::string &prefix) const
1778765Sgblack@eecs.umich.edu{
1782378SN/A    for (auto& t : *this) {
1792378SN/A        const char *s;
1802520SN/A        switch (t.source) {
1812520SN/A          case Target::FromCPU:
1828852Sandreas.hansson@arm.com            s = "FromCPU";
1838852Sandreas.hansson@arm.com            break;
1842520SN/A          case Target::FromSnoop:
1851885SN/A            s = "FromSnoop";
1861070SN/A            break;
187954SN/A          case Target::FromPrefetcher:
1881070SN/A            s = "FromPrefetcher";
1891070SN/A            break;
1901070SN/A          default:
1911070SN/A            s = "";
1921070SN/A            break;
1931070SN/A        }
1941070SN/A        ccprintf(os, "%s%s: ", prefix, s);
1951070SN/A        t.pkt->print(os, verbosity, "");
1961070SN/A    }
1971070SN/A}
1981070SN/A
1991070SN/A
2007580SAli.Saidi@arm.comvoid
2017580SAli.Saidi@arm.comMSHR::allocate(Addr blk_addr, unsigned blk_size, PacketPtr target,
2027580SAli.Saidi@arm.com               Tick when_ready, Counter _order)
2037580SAli.Saidi@arm.com{
2047580SAli.Saidi@arm.com    blkAddr = blk_addr;
2057580SAli.Saidi@arm.com    blkSize = blk_size;
2067580SAli.Saidi@arm.com    isSecure = target->isSecure();
2077580SAli.Saidi@arm.com    readyTime = when_ready;
2084997Sgblack@eecs.umich.edu    order = _order;
2097770SAli.Saidi@ARM.com    assert(target);
2104997Sgblack@eecs.umich.edu    isForward = false;
2114997Sgblack@eecs.umich.edu    _isUncacheable = target->req->isUncacheable();
2124997Sgblack@eecs.umich.edu    inService = false;
2134997Sgblack@eecs.umich.edu    downstreamPending = false;
2147770SAli.Saidi@ARM.com    threadNum = 0;
2154997Sgblack@eecs.umich.edu    assert(targets.isReset());
2164997Sgblack@eecs.umich.edu    // Don't know of a case where we would allocate a new MSHR for a
2175795Ssaidi@eecs.umich.edu    // snoop (mem-side request), so set source according to request here
2185795Ssaidi@eecs.umich.edu    Target::Source source = (target->cmd == MemCmd::HardPFReq) ?
2195795Ssaidi@eecs.umich.edu        Target::FromPrefetcher : Target::FromCPU;
2205795Ssaidi@eecs.umich.edu    targets.add(target, when_ready, _order, source, true);
2215795Ssaidi@eecs.umich.edu    assert(deferredTargets.isReset());
2225795Ssaidi@eecs.umich.edu    data = NULL;
2231885SN/A}
2244762Snate@binkert.org
2257914SBrad.Beckmann@amd.com
2267914SBrad.Beckmann@amd.comvoid
2278666SPrakash.Ramrakhyani@arm.comMSHR::clearDownstreamPending()
2287914SBrad.Beckmann@amd.com{
2297914SBrad.Beckmann@amd.com    assert(downstreamPending);
2308832SAli.Saidi@ARM.com    downstreamPending = false;
2318832SAli.Saidi@ARM.com    // recursively clear flag on any MSHRs we will be forwarding
2328832SAli.Saidi@ARM.com    // responses to
2338832SAli.Saidi@ARM.com    targets.clearDownstreamPending();
2348832SAli.Saidi@ARM.com}
2358832SAli.Saidi@ARM.com
2368832SAli.Saidi@ARM.combool
2377914SBrad.Beckmann@amd.comMSHR::markInService(bool pending_dirty_resp)
2388832SAli.Saidi@ARM.com{
2398832SAli.Saidi@ARM.com    assert(!inService);
2408832SAli.Saidi@ARM.com    if (isForwardNoResponse()) {
2418832SAli.Saidi@ARM.com        // we just forwarded the request packet & don't expect a
2428832SAli.Saidi@ARM.com        // response, so get rid of it
2438832SAli.Saidi@ARM.com        assert(getNumTargets() == 1);
2448832SAli.Saidi@ARM.com        popTarget();
2458832SAli.Saidi@ARM.com        return true;
2468832SAli.Saidi@ARM.com    }
2478832SAli.Saidi@ARM.com
2488832SAli.Saidi@ARM.com    inService = true;
2498832SAli.Saidi@ARM.com    pendingDirty = targets.needsExclusive || pending_dirty_resp;
2508832SAli.Saidi@ARM.com    postInvalidate = postDowngrade = false;
2518832SAli.Saidi@ARM.com
2528832SAli.Saidi@ARM.com    if (!downstreamPending) {
2538832SAli.Saidi@ARM.com        // let upstream caches know that the request has made it to a
2548832SAli.Saidi@ARM.com        // level where it's going to get a response
2558832SAli.Saidi@ARM.com        targets.clearDownstreamPending();
2568832SAli.Saidi@ARM.com    }
2578832SAli.Saidi@ARM.com    return false;
2588832SAli.Saidi@ARM.com}
2598666SPrakash.Ramrakhyani@arm.com
2607914SBrad.Beckmann@amd.com
2617914SBrad.Beckmann@amd.comvoid
2627914SBrad.Beckmann@amd.comMSHR::deallocate()
2637914SBrad.Beckmann@amd.com{
2648666SPrakash.Ramrakhyani@arm.com    assert(targets.empty());
2657914SBrad.Beckmann@amd.com    targets.resetFlags();
2667914SBrad.Beckmann@amd.com    assert(deferredTargets.isReset());
2677914SBrad.Beckmann@amd.com    inService = false;
2687914SBrad.Beckmann@amd.com}
2697914SBrad.Beckmann@amd.com
2707914SBrad.Beckmann@amd.com/*
2717914SBrad.Beckmann@amd.com * Adds a target to an MSHR
2727914SBrad.Beckmann@amd.com */
2737914SBrad.Beckmann@amd.comvoid
2747914SBrad.Beckmann@amd.comMSHR::allocateTarget(PacketPtr pkt, Tick whenReady, Counter _order)
2757914SBrad.Beckmann@amd.com{
2767914SBrad.Beckmann@amd.com    // assume we'd never issue a prefetch when we've got an
2777914SBrad.Beckmann@amd.com    // outstanding miss
2787914SBrad.Beckmann@amd.com    assert(pkt->cmd != MemCmd::HardPFReq);
2797914SBrad.Beckmann@amd.com
2807914SBrad.Beckmann@amd.com    // uncacheable accesses always allocate a new MSHR, and cacheable
2817914SBrad.Beckmann@amd.com    // accesses ignore any uncacheable MSHRs, thus we should never
2827914SBrad.Beckmann@amd.com    // have targets addded if originally allocated uncacheable
2837914SBrad.Beckmann@amd.com    assert(!_isUncacheable);
2847914SBrad.Beckmann@amd.com
2857914SBrad.Beckmann@amd.com    // if there's a request already in service for this MSHR, we will
2867914SBrad.Beckmann@amd.com    // have to defer the new target until after the response if any of
2877914SBrad.Beckmann@amd.com    // the following are true:
2887914SBrad.Beckmann@amd.com    // - there are other targets already deferred
2897914SBrad.Beckmann@amd.com    // - there's a pending invalidate to be applied after the response
2907914SBrad.Beckmann@amd.com    //   comes back (but before this target is processed)
2917914SBrad.Beckmann@amd.com    // - this target requires an exclusive block and either we're not
2927914SBrad.Beckmann@amd.com    //   getting an exclusive block back or we have already snooped
2937914SBrad.Beckmann@amd.com    //   another read request that will downgrade our exclusive block
2947914SBrad.Beckmann@amd.com    //   to shared
2957914SBrad.Beckmann@amd.com    if (inService &&
2967914SBrad.Beckmann@amd.com        (!deferredTargets.empty() || hasPostInvalidate() ||
2972901Ssaidi@eecs.umich.edu         (pkt->needsExclusive() &&
2988666SPrakash.Ramrakhyani@arm.com          (!isPendingDirty() || hasPostDowngrade() || isForward)))) {
2998666SPrakash.Ramrakhyani@arm.com        // need to put on deferred list
3008666SPrakash.Ramrakhyani@arm.com        if (hasPostInvalidate())
3018666SPrakash.Ramrakhyani@arm.com            replaceUpgrade(pkt);
3028666SPrakash.Ramrakhyani@arm.com        deferredTargets.add(pkt, whenReady, _order, Target::FromCPU, true);
3038666SPrakash.Ramrakhyani@arm.com    } else {
3048666SPrakash.Ramrakhyani@arm.com        // No request outstanding, or still OK to append to
3058666SPrakash.Ramrakhyani@arm.com        // outstanding request: append to regular target list.  Only
3061885SN/A        // mark pending if current request hasn't been issued yet
3071885SN/A        // (isn't in service).
3081885SN/A        targets.add(pkt, whenReady, _order, Target::FromCPU, !inService);
3091885SN/A    }
3101885SN/A}
3118769Sgblack@eecs.umich.edu
3128769Sgblack@eecs.umich.edubool
3138769Sgblack@eecs.umich.eduMSHR::handleSnoop(PacketPtr pkt, Counter _order)
3148769Sgblack@eecs.umich.edu{
3151885SN/A    DPRINTF(Cache, "%s for %s addr %#llx size %d\n", __func__,
3161885SN/A            pkt->cmdString(), pkt->getAddr(), pkt->getSize());
3171885SN/A    if (!inService || (pkt->isExpressSnoop() && downstreamPending)) {
3181885SN/A        // Request has not been issued yet, or it's been issued
3191885SN/A        // locally but is buffered unissued at some downstream cache
3201885SN/A        // which is forwarding us this snoop.  Either way, the packet
3212989Ssaidi@eecs.umich.edu        // we're snooping logically precedes this MSHR's request, so
3221885SN/A        // the snoop has no impact on the MSHR, but must be processed
3231913SN/A        // in the standard way by the cache.  The only exception is
3241885SN/A        // that if we're an L2+ cache buffering an UpgradeReq from a
3251885SN/A        // higher-level cache, and the snoop is invalidating, then our
3261885SN/A        // buffered upgrades must be converted to read exclusives,
3271885SN/A        // since the upper-level cache no longer has a valid copy.
3281885SN/A        // That is, even though the upper-level cache got out on its
3291885SN/A        // local bus first, some other invalidating transaction
3301885SN/A        // reached the global bus before the upgrade did.
3311885SN/A        if (pkt->needsExclusive()) {
3321885SN/A            targets.replaceUpgrades();
3331885SN/A            deferredTargets.replaceUpgrades();
3341885SN/A        }
3352989Ssaidi@eecs.umich.edu
3361885SN/A        return false;
3371885SN/A    }
3381885SN/A
3391885SN/A    // From here on down, the request issued by this MSHR logically
34077SN/A    // precedes the request we're snooping.
3416658Snate@binkert.org    if (pkt->needsExclusive()) {
3421070SN/A        // snooped request still precedes the re-request we'll have to
3433960Sgblack@eecs.umich.edu        // issue for deferred targets, if any...
3441070SN/A        deferredTargets.replaceUpgrades();
3451070SN/A    }
3464762Snate@binkert.org
3471070SN/A    if (hasPostInvalidate()) {
3482158SN/A        // a prior snoop has already appended an invalidation, so
3492158SN/A        // logically we don't have the block anymore; no need for
3501070SN/A        // further snooping.
3512158SN/A        return true;
3521070SN/A    }
3532SN/A
3542SN/A    if (isPendingDirty() || pkt->isInvalidate()) {
3557733SAli.Saidi@ARM.com        // We need to save and replay the packet in two cases:
3561129SN/A        // 1. We're awaiting an exclusive copy, so ownership is pending,
3572158SN/A        //    and we need to respond after we receive data.
3582158SN/A        // 2. It's an invalidation (e.g., UpgradeReq), and we need
3591070SN/A        //    to forward the snoop up the hierarchy after the current
3602378SN/A        //    transaction completes.
3611070SN/A
3621070SN/A        // Actual target device (typ. a memory) will delete the
3631070SN/A        // packet on reception, so we need to save a copy here.
3641070SN/A
3651070SN/A        // Clear flags and also allocate new data as the original
3661070SN/A        // packet data storage may have been deleted by the time we
3671070SN/A        // get to send this packet.
3681070SN/A        PacketPtr cp_pkt = nullptr;
3691070SN/A
3701070SN/A        if (isPendingDirty()) {
3711070SN/A            // Case 1: The new packet will need to get the response from the
3721070SN/A            // MSHR already queued up here
3731070SN/A            cp_pkt = new Packet(pkt, true, true);
3741070SN/A            pkt->assertMemInhibit();
3751070SN/A            // in the case of an uncacheable request there is no need
3761070SN/A            // to set the exclusive flag, but since the recipient does
3771070SN/A            // not care there is no harm in doing so
3781070SN/A            pkt->setSupplyExclusive();
3798601Ssteve.reinhardt@amd.com        } else {
3808601Ssteve.reinhardt@amd.com            // Case 2: We only need to buffer the packet for information
3818601Ssteve.reinhardt@amd.com            // purposes; the original request can proceed without waiting
3822378SN/A            // => Create a copy of the request, as that may get deallocated as
3835718Shsul@eecs.umich.edu            // well
3845713Shsul@eecs.umich.edu            cp_pkt = new Packet(new Request(*pkt->req), pkt->cmd);
3851070SN/A            DPRINTF(Cache, "Copying packet %p -> %p and request %p -> %p\n",
3861070SN/A                    pkt, cp_pkt, pkt->req, cp_pkt->req);
3871070SN/A        }
3887897Shestness@cs.utexas.edu        targets.add(cp_pkt, curTick(), _order, Target::FromSnoop,
3892SN/A                    downstreamPending && targets.needsExclusive);
39077SN/A
3917897Shestness@cs.utexas.edu        if (pkt->needsExclusive()) {
3927897Shestness@cs.utexas.edu            // This transaction will take away our pending copy
3938666SPrakash.Ramrakhyani@arm.com            postInvalidate = true;
3948666SPrakash.Ramrakhyani@arm.com        }
3957897Shestness@cs.utexas.edu    }
3962SN/A
3972SN/A    if (!pkt->needsExclusive() && !pkt->req->isUncacheable()) {
3982SN/A        // This transaction will get a read-shared copy, downgrading
3992SN/A        // our copy if we had an exclusive one
4002SN/A        postDowngrade = true;
4012SN/A        pkt->assertShared();
4022SN/A    }
4032SN/A
4042SN/A    return true;
4052SN/A}
4062158SN/A
4072158SN/A
4082SN/Abool
4092SN/AMSHR::promoteDeferredTargets()
4102SN/A{
411    assert(targets.empty());
412    if (deferredTargets.empty()) {
413        return false;
414    }
415
416    // swap targets & deferredTargets lists
417    std::swap(targets, deferredTargets);
418
419    // clear deferredTargets flags
420    deferredTargets.resetFlags();
421
422    order = targets.front().order;
423    readyTime = std::max(curTick(), targets.front().readyTime);
424
425    return true;
426}
427
428
429void
430MSHR::handleFill(PacketPtr pkt, CacheBlk *blk)
431{
432    if (!pkt->sharedAsserted()
433        && !(hasPostInvalidate() || hasPostDowngrade())
434        && deferredTargets.needsExclusive) {
435        // We got an exclusive response, but we have deferred targets
436        // which are waiting to request an exclusive copy (not because
437        // of a pending invalidate).  This can happen if the original
438        // request was for a read-only (non-exclusive) block, but we
439        // got an exclusive copy anyway because of the E part of the
440        // MOESI/MESI protocol.  Since we got the exclusive copy
441        // there's no need to defer the targets, so move them up to
442        // the regular target list.
443        assert(!targets.needsExclusive);
444        targets.needsExclusive = true;
445        // if any of the deferred targets were upper-level cache
446        // requests marked downstreamPending, need to clear that
447        assert(!downstreamPending);  // not pending here anymore
448        deferredTargets.clearDownstreamPending();
449        // this clears out deferredTargets too
450        targets.splice(targets.end(), deferredTargets);
451        deferredTargets.resetFlags();
452    }
453}
454
455
456bool
457MSHR::checkFunctional(PacketPtr pkt)
458{
459    // For printing, we treat the MSHR as a whole as single entity.
460    // For other requests, we iterate over the individual targets
461    // since that's where the actual data lies.
462    if (pkt->isPrint()) {
463        pkt->checkFunctional(this, blkAddr, isSecure, blkSize, NULL);
464        return false;
465    } else {
466        return (targets.checkFunctional(pkt) ||
467                deferredTargets.checkFunctional(pkt));
468    }
469}
470
471
472void
473MSHR::print(std::ostream &os, int verbosity, const std::string &prefix) const
474{
475    ccprintf(os, "%s[%#llx:%#llx](%s) %s %s %s state: %s %s %s %s %s\n",
476             prefix, blkAddr, blkAddr + blkSize - 1,
477             isSecure ? "s" : "ns",
478             isForward ? "Forward" : "",
479             isForwardNoResponse() ? "ForwNoResp" : "",
480             needsExclusive() ? "Excl" : "",
481             _isUncacheable ? "Unc" : "",
482             inService ? "InSvc" : "",
483             downstreamPending ? "DwnPend" : "",
484             hasPostInvalidate() ? "PostInv" : "",
485             hasPostDowngrade() ? "PostDowngr" : "");
486
487    ccprintf(os, "%s  Targets:\n", prefix);
488    targets.print(os, verbosity, prefix + "    ");
489    if (!deferredTargets.empty()) {
490        ccprintf(os, "%s  Deferred Targets:\n", prefix);
491        deferredTargets.print(os, verbosity, prefix + "      ");
492    }
493}
494
495std::string
496MSHR::print() const
497{
498    ostringstream str;
499    print(str);
500    return str.str();
501}
502