mshr.cc revision 10424
1360SN/A/*
210850SGiacomo.Gabrielli@arm.com * Copyright (c) 2012-2013 ARM Limited
310796Sbrandon.potter@amd.com * All rights reserved.
410027SChris.Adeniyi-Jones@arm.com *
510027SChris.Adeniyi-Jones@arm.com * The license below extends only to copyright in the software and shall
610027SChris.Adeniyi-Jones@arm.com * not be construed as granting a license to any other intellectual
710027SChris.Adeniyi-Jones@arm.com * property including but not limited to intellectual property relating
810027SChris.Adeniyi-Jones@arm.com * to a hardware implementation of the functionality of the software
910027SChris.Adeniyi-Jones@arm.com * licensed hereunder.  You may use the software subject to the license
1010027SChris.Adeniyi-Jones@arm.com * terms below provided that you ensure that this notice is replicated
1110027SChris.Adeniyi-Jones@arm.com * unmodified and in its entirety in all distributions of the software,
1210027SChris.Adeniyi-Jones@arm.com * modified or unmodified, in source code or in binary form.
1310027SChris.Adeniyi-Jones@arm.com *
1410027SChris.Adeniyi-Jones@arm.com * Copyright (c) 2002-2005 The Regents of The University of Michigan
151458SN/A * Copyright (c) 2010 Advanced Micro Devices, Inc.
16360SN/A * All rights reserved.
17360SN/A *
18360SN/A * Redistribution and use in source and binary forms, with or without
19360SN/A * modification, are permitted provided that the following conditions are
20360SN/A * met: redistributions of source code must retain the above copyright
21360SN/A * notice, this list of conditions and the following disclaimer;
22360SN/A * redistributions in binary form must reproduce the above copyright
23360SN/A * notice, this list of conditions and the following disclaimer in the
24360SN/A * documentation and/or other materials provided with the distribution;
25360SN/A * neither the name of the copyright holders nor the names of its
26360SN/A * contributors may be used to endorse or promote products derived from
27360SN/A * this software without specific prior written permission.
28360SN/A *
29360SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30360SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31360SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
32360SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
33360SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
34360SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
35360SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
36360SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37360SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38360SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
39360SN/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
43360SN/A */
44360SN/A
451354SN/A/**
461354SN/A * @file
47360SN/A * Miss Status and Handling Register (MSHR) definitions.
4812018Sandreas.sandberg@arm.com */
4912018Sandreas.sandberg@arm.com
5012018Sandreas.sandberg@arm.com#include <algorithm>
5112018Sandreas.sandberg@arm.com#include <cassert>
5212018Sandreas.sandberg@arm.com#include <string>
5312018Sandreas.sandberg@arm.com#include <vector>
5412018Sandreas.sandberg@arm.com
552064SN/A#include "base/misc.hh"
56360SN/A#include "base/types.hh"
57360SN/A#include "debug/Cache.hh"
58360SN/A#include "mem/cache/cache.hh"
59360SN/A#include "mem/cache/mshr.hh"
60360SN/A#include "sim/core.hh"
61360SN/A
6213936SAndrea.Mondelli@ucf.eduusing namespace std;
6313933Sbrandon.potter@amd.com
6413933Sbrandon.potter@amd.comMSHR::MSHR() : readyTime(0), _isUncacheable(false), downstreamPending(false),
6513933Sbrandon.potter@amd.com               pendingDirty(false), postInvalidate(false),
6613936SAndrea.Mondelli@ucf.edu               postDowngrade(false), queue(NULL), order(0), addr(0), size(0),
6713936SAndrea.Mondelli@ucf.edu               isSecure(false), inService(false), isForward(false),
6813936SAndrea.Mondelli@ucf.edu               threadNum(InvalidThreadID), data(NULL)
6913933Sbrandon.potter@amd.com{
7013933Sbrandon.potter@amd.com}
711809SN/A
7211800Sbrandon.potter@amd.com
7311392Sbrandon.potter@amd.comMSHR::TargetList::TargetList()
741809SN/A    : needsExclusive(false), hasUpgrade(false)
7511392Sbrandon.potter@amd.com{}
7613902Sbrandon.potter@amd.com
7713570Sbrandon.potter@amd.com
7813902Sbrandon.potter@amd.cominline void
7911383Sbrandon.potter@amd.comMSHR::TargetList::add(PacketPtr pkt, Tick readyTime,
8013568Sbrandon.potter@amd.com                      Counter order, Target::Source source, bool markPending)
813113Sgblack@eecs.umich.edu{
828229Snate@binkert.org    if (source != Target::FromSnoop) {
8313570Sbrandon.potter@amd.com        if (pkt->needsExclusive()) {
848229Snate@binkert.org            needsExclusive = true;
8511594Santhony.gutierrez@amd.com        }
867075Snate@binkert.org
878229Snate@binkert.org        // StoreCondReq is effectively an upgrade if it's in an MSHR
8811856Sbrandon.potter@amd.com        // since it would have been failed already if we didn't have a
897075Snate@binkert.org        // read-only copy
90360SN/A        if (pkt->isUpgrade() || pkt->cmd == MemCmd::StoreCondReq) {
9112461Sgabeblack@google.com            hasUpgrade = true;
9211886Sbrandon.potter@amd.com        }
9311800Sbrandon.potter@amd.com    }
9411392Sbrandon.potter@amd.com
9512334Sgabeblack@google.com    if (markPending) {
961354SN/A        // Iterate over the SenderState stack and see if we find
976216Snate@binkert.org        // an MSHR entry. If we do, set the downstreamPending
986658Snate@binkert.org        // flag. Otherwise, do nothing.
992474SN/A        MSHR *mshr = pkt->findNextSenderState<MSHR>();
1002680Sktlim@umich.edu        if (mshr != NULL) {
1018229Snate@binkert.org            assert(!mshr->downstreamPending);
10211886Sbrandon.potter@amd.com            mshr->downstreamPending = true;
10310496Ssteve.reinhardt@amd.com        }
10411911SBrandon.Potter@amd.com    }
1058229Snate@binkert.org
10611794Sbrandon.potter@amd.com    push_back(Target(pkt, readyTime, order, source, markPending));
10711886Sbrandon.potter@amd.com}
10810497Ssteve.reinhardt@amd.com
10911794Sbrandon.potter@amd.com
110360SN/Astatic void
11113629SAndrea.Mondelli@ucf.edureplaceUpgrade(PacketPtr pkt)
11213629SAndrea.Mondelli@ucf.edu{
11313629SAndrea.Mondelli@ucf.edu    if (pkt->cmd == MemCmd::UpgradeReq) {
11413629SAndrea.Mondelli@ucf.edu        pkt->cmd = MemCmd::ReadExReq;
115360SN/A        DPRINTF(Cache, "Replacing UpgradeReq with ReadExReq\n");
116360SN/A    } else if (pkt->cmd == MemCmd::SCUpgradeReq) {
117360SN/A        pkt->cmd = MemCmd::SCUpgradeFailReq;
118360SN/A        DPRINTF(Cache, "Replacing SCUpgradeReq with SCUpgradeFailReq\n");
119360SN/A    } else if (pkt->cmd == MemCmd::StoreCondReq) {
120360SN/A        pkt->cmd = MemCmd::StoreCondFailReq;
121360SN/A        DPRINTF(Cache, "Replacing StoreCondReq with StoreCondFailReq\n");
122360SN/A    }
12313933Sbrandon.potter@amd.com}
124360SN/A
125378SN/A
12613995Sbrandon.potter@amd.comvoid
127378SN/AMSHR::TargetList::replaceUpgrades()
128378SN/A{
129378SN/A    if (!hasUpgrade)
130378SN/A        return;
131378SN/A
13213995Sbrandon.potter@amd.com    Iterator end_i = end();
133360SN/A    for (Iterator i = begin(); i != end_i; ++i) {
13411760Sbrandon.potter@amd.com        replaceUpgrade(i->pkt);
13513995Sbrandon.potter@amd.com    }
13611760Sbrandon.potter@amd.com
1376109Ssanchezd@stanford.edu    hasUpgrade = false;
13813995Sbrandon.potter@amd.com}
139378SN/A
1406109Ssanchezd@stanford.edu
14113995Sbrandon.potter@amd.comvoid
1426109Ssanchezd@stanford.eduMSHR::TargetList::clearDownstreamPending()
14311886Sbrandon.potter@amd.com{
14413995Sbrandon.potter@amd.com    Iterator end_i = end();
14511886Sbrandon.potter@amd.com    for (Iterator i = begin(); i != end_i; ++i) {
146378SN/A        if (i->markedPending) {
14713995Sbrandon.potter@amd.com            // Iterate over the SenderState stack and see if we find
148378SN/A            // an MSHR entry. If we find one, clear the
1495748SSteve.Reinhardt@amd.com            // downstreamPending flag by calling
15013995Sbrandon.potter@amd.com            // clearDownstreamPending(). This recursively clears the
151378SN/A            // downstreamPending flag in all caches this packet has
152378SN/A            // passed through.
15313995Sbrandon.potter@amd.com            MSHR *mshr = i->pkt->findNextSenderState<MSHR>();
154378SN/A            if (mshr != NULL) {
155378SN/A                mshr->clearDownstreamPending();
15613995Sbrandon.potter@amd.com            }
157378SN/A        }
1584118Sgblack@eecs.umich.edu    }
15913995Sbrandon.potter@amd.com}
1604118Sgblack@eecs.umich.edu
161378SN/A
16213995Sbrandon.potter@amd.combool
163378SN/AMSHR::TargetList::checkFunctional(PacketPtr pkt)
16413568Sbrandon.potter@amd.com{
16513995Sbrandon.potter@amd.com    Iterator end_i = end();
16613568Sbrandon.potter@amd.com    for (Iterator i = begin(); i != end_i; ++i) {
167378SN/A        if (pkt->checkFunctional(i->pkt)) {
16813995Sbrandon.potter@amd.com            return true;
169360SN/A        }
1705513SMichael.Adler@intel.com    }
17113995Sbrandon.potter@amd.com
1725513SMichael.Adler@intel.com    return false;
17310203SAli.Saidi@ARM.com}
17413995Sbrandon.potter@amd.com
17510203SAli.Saidi@ARM.com
17613995Sbrandon.potter@amd.comvoid
1775513SMichael.Adler@intel.comMSHR::TargetList::
178511SN/Aprint(std::ostream &os, int verbosity, const std::string &prefix) const
17913995Sbrandon.potter@amd.com{
18010633Smichaelupton@gmail.com    ConstIterator end_i = end();
18113995Sbrandon.potter@amd.com    for (ConstIterator i = begin(); i != end_i; ++i) {
182511SN/A        const char *s;
18312795Smattdsinclair@gmail.com        switch (i->source) {
18413995Sbrandon.potter@amd.com          case Target::FromCPU:
18512795Smattdsinclair@gmail.com            s = "FromCPU";
18612796Smattdsinclair@gmail.com            break;
18713995Sbrandon.potter@amd.com          case Target::FromSnoop:
18812796Smattdsinclair@gmail.com            s = "FromSnoop";
1895513SMichael.Adler@intel.com            break;
19013995Sbrandon.potter@amd.com          case Target::FromPrefetcher:
1915513SMichael.Adler@intel.com            s = "FromPrefetcher";
19213031Sbrandon.potter@amd.com            break;
19313995Sbrandon.potter@amd.com          default:
19413031Sbrandon.potter@amd.com            s = "";
19513031Sbrandon.potter@amd.com            break;
19613995Sbrandon.potter@amd.com        }
19713031Sbrandon.potter@amd.com        ccprintf(os, "%s%s: ", prefix, s);
19813031Sbrandon.potter@amd.com        i->pkt->print(os, verbosity, "");
19913995Sbrandon.potter@amd.com    }
20013031Sbrandon.potter@amd.com}
201511SN/A
20213995Sbrandon.potter@amd.com
2031706SN/Avoid
2041706SN/AMSHR::allocate(Addr _addr, int _size, PacketPtr target, Tick whenReady,
2051706SN/A               Counter _order)
20613995Sbrandon.potter@amd.com{
2071706SN/A    addr = _addr;
2081706SN/A    size = _size;
2091706SN/A    isSecure = target->isSecure();
21013995Sbrandon.potter@amd.com    readyTime = whenReady;
2111706SN/A    order = _order;
212511SN/A    assert(target);
2136703Svince@csl.cornell.edu    isForward = false;
21413995Sbrandon.potter@amd.com    _isUncacheable = target->req->isUncacheable();
2156703Svince@csl.cornell.edu    inService = false;
2166685Stjones1@inf.ed.ac.uk    downstreamPending = false;
21713995Sbrandon.potter@amd.com    threadNum = 0;
2186685Stjones1@inf.ed.ac.uk    assert(targets.isReset());
2196685Stjones1@inf.ed.ac.uk    // Don't know of a case where we would allocate a new MSHR for a
2205513SMichael.Adler@intel.com    // snoop (mem-side request), so set source according to request here
22113995Sbrandon.potter@amd.com    Target::Source source = (target->cmd == MemCmd::HardPFReq) ?
2225513SMichael.Adler@intel.com        Target::FromPrefetcher : Target::FromCPU;
22311885Sbrandon.potter@amd.com    targets.add(target, whenReady, _order, source, true);
22413995Sbrandon.potter@amd.com    assert(deferredTargets.isReset());
2255513SMichael.Adler@intel.com    data = NULL;
2261999SN/A}
22713995Sbrandon.potter@amd.com
2281999SN/A
22911885Sbrandon.potter@amd.comvoid
23013995Sbrandon.potter@amd.comMSHR::clearDownstreamPending()
2311999SN/A{
2321999SN/A    assert(downstreamPending);
23313995Sbrandon.potter@amd.com    downstreamPending = false;
2341999SN/A    // recursively clear flag on any MSHRs we will be forwarding
2353079Sstever@eecs.umich.edu    // responses to
23613995Sbrandon.potter@amd.com    targets.clearDownstreamPending();
2373079Sstever@eecs.umich.edu}
23811908SBrandon.Potter@amd.com
23913995Sbrandon.potter@amd.combool
24011908SBrandon.Potter@amd.comMSHR::markInService(PacketPtr pkt)
24111875Sbrandon.potter@amd.com{
24213995Sbrandon.potter@amd.com    assert(!inService);
2432093SN/A    if (isForwardNoResponse()) {
2442687Sksewell@umich.edu        // we just forwarded the request packet & don't expect a
24513995Sbrandon.potter@amd.com        // response, so get rid of it
2462687Sksewell@umich.edu        assert(getNumTargets() == 1);
2472238SN/A        popTarget();
24813995Sbrandon.potter@amd.com        return true;
2492238SN/A    }
25011908SBrandon.Potter@amd.com
25113995Sbrandon.potter@amd.com    assert(pkt != NULL);
25211908SBrandon.Potter@amd.com    inService = true;
25311908SBrandon.Potter@amd.com    pendingDirty = (targets.needsExclusive ||
25413995Sbrandon.potter@amd.com                    (!pkt->sharedAsserted() && pkt->memInhibitAsserted()));
25513995Sbrandon.potter@amd.com    postInvalidate = postDowngrade = false;
25611908SBrandon.Potter@amd.com
2572238SN/A    if (!downstreamPending) {
25813995Sbrandon.potter@amd.com        // let upstream caches know that the request has made it to a
2592238SN/A        // level where it's going to get a response
26013571Sbrandon.potter@amd.com        targets.clearDownstreamPending();
26113995Sbrandon.potter@amd.com    }
26213571Sbrandon.potter@amd.com    return false;
26313568Sbrandon.potter@amd.com}
26413995Sbrandon.potter@amd.com
26513568Sbrandon.potter@amd.com
26613568Sbrandon.potter@amd.comvoid
26713995Sbrandon.potter@amd.comMSHR::deallocate()
26813568Sbrandon.potter@amd.com{
26913568Sbrandon.potter@amd.com    assert(targets.empty());
27013995Sbrandon.potter@amd.com    targets.resetFlags();
27113568Sbrandon.potter@amd.com    assert(deferredTargets.isReset());
27213448Sciro.santilli@arm.com    inService = false;
27313031Sbrandon.potter@amd.com}
27413995Sbrandon.potter@amd.com
27513448Sciro.santilli@arm.com/*
27613031Sbrandon.potter@amd.com * Adds a target to an MSHR
27713539Sjavier.setoain@arm.com */
27813539Sjavier.setoain@arm.comvoid
27913995Sbrandon.potter@amd.comMSHR::allocateTarget(PacketPtr pkt, Tick whenReady, Counter _order)
28013539Sjavier.setoain@arm.com{
28113539Sjavier.setoain@arm.com    // if there's a request already in service for this MSHR, we will
28213569Sbrandon.potter@amd.com    // have to defer the new target until after the response if any of
28313995Sbrandon.potter@amd.com    // the following are true:
28413569Sbrandon.potter@amd.com    // - there are other targets already deferred
28513569Sbrandon.potter@amd.com    // - there's a pending invalidate to be applied after the response
28613995Sbrandon.potter@amd.com    //   comes back (but before this target is processed)
28713569Sbrandon.potter@amd.com    // - this target requires an exclusive block and either we're not
28813569Sbrandon.potter@amd.com    //   getting an exclusive block back or we have already snooped
28913995Sbrandon.potter@amd.com    //   another read request that will downgrade our exclusive block
29013569Sbrandon.potter@amd.com    //   to shared
29113569Sbrandon.potter@amd.com
29213995Sbrandon.potter@amd.com    // assume we'd never issue a prefetch when we've got an
29313569Sbrandon.potter@amd.com    // outstanding miss
29413031Sbrandon.potter@amd.com    assert(pkt->cmd != MemCmd::HardPFReq);
29513995Sbrandon.potter@amd.com
2962238SN/A    if (inService &&
2972238SN/A        (!deferredTargets.empty() || hasPostInvalidate() ||
29813995Sbrandon.potter@amd.com         (pkt->needsExclusive() &&
2992238SN/A          (!isPendingDirty() || hasPostDowngrade() || isForward)))) {
3002238SN/A        // need to put on deferred list
30113995Sbrandon.potter@amd.com        if (hasPostInvalidate())
3022238SN/A            replaceUpgrade(pkt);
3032238SN/A        deferredTargets.add(pkt, whenReady, _order, Target::FromCPU, true);
30413995Sbrandon.potter@amd.com    } else {
3052238SN/A        // No request outstanding, or still OK to append to
3062238SN/A        // outstanding request: append to regular target list.  Only
30713995Sbrandon.potter@amd.com        // mark pending if current request hasn't been issued yet
3082238SN/A        // (isn't in service).
3099455Smitch.hayenga+gem5@gmail.com        targets.add(pkt, whenReady, _order, Target::FromCPU, !inService);
31013995Sbrandon.potter@amd.com    }
31113995Sbrandon.potter@amd.com}
31211851Sbrandon.potter@amd.com
3139455Smitch.hayenga+gem5@gmail.combool
31413571Sbrandon.potter@amd.comMSHR::handleSnoop(PacketPtr pkt, Counter _order)
31513995Sbrandon.potter@amd.com{
31613571Sbrandon.potter@amd.com    DPRINTF(Cache, "%s for %s address %x size %d\n", __func__,
31713571Sbrandon.potter@amd.com            pkt->cmdString(), pkt->getAddr(), pkt->getSize());
31813995Sbrandon.potter@amd.com    if (!inService || (pkt->isExpressSnoop() && downstreamPending)) {
31913571Sbrandon.potter@amd.com        // Request has not been issued yet, or it's been issued
32013571Sbrandon.potter@amd.com        // locally but is buffered unissued at some downstream cache
32113995Sbrandon.potter@amd.com        // which is forwarding us this snoop.  Either way, the packet
32213571Sbrandon.potter@amd.com        // we're snooping logically precedes this MSHR's request, so
3239112Smarc.orr@gmail.com        // the snoop has no impact on the MSHR, but must be processed
32411906SBrandon.Potter@amd.com        // in the standard way by the cache.  The only exception is
32511906SBrandon.Potter@amd.com        // that if we're an L2+ cache buffering an UpgradeReq from a
3269112Smarc.orr@gmail.com        // higher-level cache, and the snoop is invalidating, then our
3279112Smarc.orr@gmail.com        // buffered upgrades must be converted to read exclusives,
32813995Sbrandon.potter@amd.com        // since the upper-level cache no longer has a valid copy.
3299112Smarc.orr@gmail.com        // That is, even though the upper-level cache got out on its
33011911SBrandon.Potter@amd.com        // local bus first, some other invalidating transaction
3319112Smarc.orr@gmail.com        // reached the global bus before the upgrade did.
33211911SBrandon.Potter@amd.com        if (pkt->needsExclusive()) {
33313995Sbrandon.potter@amd.com            targets.replaceUpgrades();
33413995Sbrandon.potter@amd.com            deferredTargets.replaceUpgrades();
33511911SBrandon.Potter@amd.com        }
33611911SBrandon.Potter@amd.com
33711911SBrandon.Potter@amd.com        return false;
33813642Sqtt2@cornell.edu    }
33913642Sqtt2@cornell.edu
34013642Sqtt2@cornell.edu    // From here on down, the request issued by this MSHR logically
3419112Smarc.orr@gmail.com    // precedes the request we're snooping.
34211911SBrandon.Potter@amd.com    if (pkt->needsExclusive()) {
34311911SBrandon.Potter@amd.com        // snooped request still precedes the re-request we'll have to
34411911SBrandon.Potter@amd.com        // issue for deferred targets, if any...
34511911SBrandon.Potter@amd.com        deferredTargets.replaceUpgrades();
3469238Slluc.alvarez@bsc.es    }
34713642Sqtt2@cornell.edu
3489112Smarc.orr@gmail.com    if (hasPostInvalidate()) {
34911911SBrandon.Potter@amd.com        // a prior snoop has already appended an invalidation, so
3509112Smarc.orr@gmail.com        // logically we don't have the block anymore; no need for
35113642Sqtt2@cornell.edu        // further snooping.
35211911SBrandon.Potter@amd.com        return true;
35311911SBrandon.Potter@amd.com    }
35411911SBrandon.Potter@amd.com
35511911SBrandon.Potter@amd.com    if (isPendingDirty() || pkt->isInvalidate()) {
3569112Smarc.orr@gmail.com        // We need to save and replay the packet in two cases:
35711911SBrandon.Potter@amd.com        // 1. We're awaiting an exclusive copy, so ownership is pending,
35811911SBrandon.Potter@amd.com        //    and we need to respond after we receive data.
35911911SBrandon.Potter@amd.com        // 2. It's an invalidation (e.g., UpgradeReq), and we need
36011911SBrandon.Potter@amd.com        //    to forward the snoop up the hierarchy after the current
36111911SBrandon.Potter@amd.com        //    transaction completes.
36211911SBrandon.Potter@amd.com
3639112Smarc.orr@gmail.com        // Actual target device (typ. a memory) will delete the
3649112Smarc.orr@gmail.com        // packet on reception, so we need to save a copy here.
36513642Sqtt2@cornell.edu        PacketPtr cp_pkt = new Packet(pkt, true);
36613642Sqtt2@cornell.edu        targets.add(cp_pkt, curTick(), _order, Target::FromSnoop,
36713642Sqtt2@cornell.edu                     downstreamPending && targets.needsExclusive);
36813642Sqtt2@cornell.edu
36913642Sqtt2@cornell.edu        if (isPendingDirty()) {
37011911SBrandon.Potter@amd.com            pkt->assertMemInhibit();
3719112Smarc.orr@gmail.com            pkt->setSupplyExclusive();
37211911SBrandon.Potter@amd.com        }
37311911SBrandon.Potter@amd.com
37413642Sqtt2@cornell.edu        if (pkt->needsExclusive()) {
37513642Sqtt2@cornell.edu            // This transaction will take away our pending copy
37613650Smw828@cornell.edu            postInvalidate = true;
37713650Smw828@cornell.edu        }
37813650Smw828@cornell.edu    }
37913650Smw828@cornell.edu
38013650Smw828@cornell.edu    if (!pkt->needsExclusive()) {
38113650Smw828@cornell.edu        // This transaction will get a read-shared copy, downgrading
38213650Smw828@cornell.edu        // our copy if we had an exclusive one
38313650Smw828@cornell.edu        postDowngrade = true;
38413650Smw828@cornell.edu        pkt->assertShared();
38513650Smw828@cornell.edu    }
38613650Smw828@cornell.edu
38713650Smw828@cornell.edu    return true;
38813650Smw828@cornell.edu}
38913650Smw828@cornell.edu
39013651Smw828@cornell.edu
39113651Smw828@cornell.edubool
39213651Smw828@cornell.eduMSHR::promoteDeferredTargets()
39313651Smw828@cornell.edu{
39413651Smw828@cornell.edu    assert(targets.empty());
39513651Smw828@cornell.edu    if (deferredTargets.empty()) {
39613651Smw828@cornell.edu        return false;
39713651Smw828@cornell.edu    }
39813651Smw828@cornell.edu
39913651Smw828@cornell.edu    // swap targets & deferredTargets lists
40013651Smw828@cornell.edu    std::swap(targets, deferredTargets);
40113651Smw828@cornell.edu
40213651Smw828@cornell.edu    // clear deferredTargets flags
40313651Smw828@cornell.edu    deferredTargets.resetFlags();
40413651Smw828@cornell.edu
40513651Smw828@cornell.edu    order = targets.front().order;
40613651Smw828@cornell.edu    readyTime = std::max(curTick(), targets.front().readyTime);
40713651Smw828@cornell.edu
40813651Smw828@cornell.edu    return true;
40913651Smw828@cornell.edu}
41013651Smw828@cornell.edu
41113651Smw828@cornell.edu
41213651Smw828@cornell.eduvoid
41313651Smw828@cornell.eduMSHR::handleFill(Packet *pkt, CacheBlk *blk)
41413651Smw828@cornell.edu{
41513651Smw828@cornell.edu    if (!pkt->sharedAsserted()
41613651Smw828@cornell.edu        && !(hasPostInvalidate() || hasPostDowngrade())
41713651Smw828@cornell.edu        && deferredTargets.needsExclusive) {
41813651Smw828@cornell.edu        // We got an exclusive response, but we have deferred targets
41913651Smw828@cornell.edu        // which are waiting to request an exclusive copy (not because
42013651Smw828@cornell.edu        // of a pending invalidate).  This can happen if the original
42113651Smw828@cornell.edu        // request was for a read-only (non-exclusive) block, but we
42213651Smw828@cornell.edu        // got an exclusive copy anyway because of the E part of the
42313651Smw828@cornell.edu        // MOESI/MESI protocol.  Since we got the exclusive copy
42413651Smw828@cornell.edu        // there's no need to defer the targets, so move them up to
42513651Smw828@cornell.edu        // the regular target list.
42613651Smw828@cornell.edu        assert(!targets.needsExclusive);
42713651Smw828@cornell.edu        targets.needsExclusive = true;
42813651Smw828@cornell.edu        // if any of the deferred targets were upper-level cache
42913651Smw828@cornell.edu        // requests marked downstreamPending, need to clear that
43013651Smw828@cornell.edu        assert(!downstreamPending);  // not pending here anymore
43113651Smw828@cornell.edu        deferredTargets.clearDownstreamPending();
43213651Smw828@cornell.edu        // this clears out deferredTargets too
43313651Smw828@cornell.edu        targets.splice(targets.end(), deferredTargets);
43413651Smw828@cornell.edu        deferredTargets.resetFlags();
43513651Smw828@cornell.edu    }
43613651Smw828@cornell.edu}
43713651Smw828@cornell.edu
43813651Smw828@cornell.edu
43913651Smw828@cornell.edubool
44013651Smw828@cornell.eduMSHR::checkFunctional(PacketPtr pkt)
44113651Smw828@cornell.edu{
44213651Smw828@cornell.edu    // For printing, we treat the MSHR as a whole as single entity.
44313651Smw828@cornell.edu    // For other requests, we iterate over the individual targets
44413651Smw828@cornell.edu    // since that's where the actual data lies.
44513651Smw828@cornell.edu    if (pkt->isPrint()) {
44613651Smw828@cornell.edu        pkt->checkFunctional(this, addr, isSecure, size, NULL);
44713651Smw828@cornell.edu        return false;
44813651Smw828@cornell.edu    } else {
44913651Smw828@cornell.edu        return (targets.checkFunctional(pkt) ||
45013651Smw828@cornell.edu                deferredTargets.checkFunctional(pkt));
45113651Smw828@cornell.edu    }
45213651Smw828@cornell.edu}
45313651Smw828@cornell.edu
45413651Smw828@cornell.edu
45513651Smw828@cornell.eduvoid
45613651Smw828@cornell.eduMSHR::print(std::ostream &os, int verbosity, const std::string &prefix) const
45713651Smw828@cornell.edu{
45813651Smw828@cornell.edu    ccprintf(os, "%s[%x:%x](%s) %s %s %s state: %s %s %s %s %s\n",
45913651Smw828@cornell.edu             prefix, addr, addr+size-1,
46013651Smw828@cornell.edu             isSecure ? "s" : "ns",
4619112Smarc.orr@gmail.com             isForward ? "Forward" : "",
46211911SBrandon.Potter@amd.com             isForwardNoResponse() ? "ForwNoResp" : "",
46311911SBrandon.Potter@amd.com             needsExclusive() ? "Excl" : "",
4649112Smarc.orr@gmail.com             _isUncacheable ? "Unc" : "",
4659112Smarc.orr@gmail.com             inService ? "InSvc" : "",
4662238SN/A             downstreamPending ? "DwnPend" : "",
4672238SN/A             hasPostInvalidate() ? "PostInv" : "",
4682238SN/A             hasPostDowngrade() ? "PostDowngr" : "");
46913995Sbrandon.potter@amd.com
4702238SN/A    ccprintf(os, "%s  Targets:\n", prefix);
4712238SN/A    targets.print(os, verbosity, prefix + "    ");
47213995Sbrandon.potter@amd.com    if (!deferredTargets.empty()) {
4732238SN/A        ccprintf(os, "%s  Deferred Targets:\n", prefix);
4742238SN/A        deferredTargets.print(os, verbosity, prefix + "      ");
47513995Sbrandon.potter@amd.com    }
4762238SN/A}
4772238SN/A
47813995Sbrandon.potter@amd.comstd::string
4792238SN/AMSHR::print() const
4802238SN/A{
4811354SN/A    ostringstream str;
4821354SN/A    print(str);
48310796Sbrandon.potter@amd.com    return str.str();
48410796Sbrandon.potter@amd.com}
4851354SN/A