mshr.cc revision 11484
17405SAli.Saidi@ARM.com/*
212667Schuan.zhu@arm.com * Copyright (c) 2012-2013, 2015-2016 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 */
4412406Sgabeblack@google.com
4512605Sgiacomo.travaglini@arm.com/**
4611793Sbrandon.potter@amd.com * @file
478887Sgeoffrey.blake@arm.com * Miss Status and Handling Register (MSHR) definitions.
488232Snate@binkert.org */
498232Snate@binkert.org
5010844Sandreas.sandberg@arm.com#include <algorithm>
5113531Sjairo.balart@metempsy.com#include <cassert>
5213531Sjairo.balart@metempsy.com#include <string>
539384SAndreas.Sandberg@arm.com#include <vector>
547678Sgblack@eecs.umich.edu
558059SAli.Saidi@ARM.com#include "base/misc.hh"
568284SAli.Saidi@ARM.com#include "base/types.hh"
577405SAli.Saidi@ARM.com#include "debug/Cache.hh"
587405SAli.Saidi@ARM.com#include "mem/cache/cache.hh"
597405SAli.Saidi@ARM.com#include "mem/cache/mshr.hh"
607405SAli.Saidi@ARM.com#include "sim/core.hh"
619384SAndreas.Sandberg@arm.com
6210461SAndreas.Sandberg@ARM.comusing namespace std;
6310461SAndreas.Sandberg@ARM.com
6411165SRekai.GonzalezAlberquilla@arm.comMSHR::MSHR() : downstreamPending(false),
6512109SRekai.GonzalezAlberquilla@arm.com               pendingModified(false),
6612714Sgiacomo.travaglini@arm.com               postInvalidate(false), postDowngrade(false),
6712714Sgiacomo.travaglini@arm.com               isForward(false), allocOnFill(false)
689384SAndreas.Sandberg@arm.com{
6911770SCurtis.Dunham@arm.com}
7010037SARM gem5 Developers
7110461SAndreas.Sandberg@ARM.comMSHR::TargetList::TargetList()
7210461SAndreas.Sandberg@ARM.com    : needsWritable(false), hasUpgrade(false)
7310461SAndreas.Sandberg@ARM.com{}
7410461SAndreas.Sandberg@ARM.com
7510461SAndreas.Sandberg@ARM.com
7610461SAndreas.Sandberg@ARM.cominline void
7710609Sandreas.sandberg@arm.comMSHR::TargetList::add(PacketPtr pkt, Tick readyTime,
7810609Sandreas.sandberg@arm.com                      Counter order, Target::Source source, bool markPending)
7910609Sandreas.sandberg@arm.com{
8010037SARM gem5 Developers    if (source != Target::FromSnoop) {
8110037SARM gem5 Developers        if (pkt->needsWritable()) {
8210037SARM gem5 Developers            needsWritable = true;
8310037SARM gem5 Developers        }
8411771SCurtis.Dunham@arm.com
8510037SARM gem5 Developers        // StoreCondReq is effectively an upgrade if it's in an MSHR
8610037SARM gem5 Developers        // since it would have been failed already if we didn't have a
8713173Sgiacomo.travaglini@arm.com        // read-only copy
8810037SARM gem5 Developers        if (pkt->isUpgrade() || pkt->cmd == MemCmd::StoreCondReq) {
8910037SARM gem5 Developers            hasUpgrade = true;
9013114Sgiacomo.travaglini@arm.com        }
9110037SARM gem5 Developers    }
9211771SCurtis.Dunham@arm.com
9310037SARM gem5 Developers    if (markPending) {
9413499Sgiacomo.travaglini@arm.com        // Iterate over the SenderState stack and see if we find
9510037SARM gem5 Developers        // an MSHR entry. If we do, set the downstreamPending
9613114Sgiacomo.travaglini@arm.com        // flag. Otherwise, do nothing.
9710037SARM gem5 Developers        MSHR *mshr = pkt->findNextSenderState<MSHR>();
9810037SARM gem5 Developers        if (mshr != nullptr) {
9913531Sjairo.balart@metempsy.com            assert(!mshr->downstreamPending);
10013531Sjairo.balart@metempsy.com            mshr->downstreamPending = true;
10113531Sjairo.balart@metempsy.com        } else {
10213531Sjairo.balart@metempsy.com            // No need to clear downstreamPending later
10313531Sjairo.balart@metempsy.com            markPending = false;
10413531Sjairo.balart@metempsy.com        }
10513531Sjairo.balart@metempsy.com    }
10612477SCurtis.Dunham@arm.com
10710037SARM gem5 Developers    emplace_back(pkt, readyTime, order, source, markPending);
10810037SARM gem5 Developers}
1099384SAndreas.Sandberg@arm.com
1109384SAndreas.Sandberg@arm.com
1119384SAndreas.Sandberg@arm.comstatic void
11212479SCurtis.Dunham@arm.comreplaceUpgrade(PacketPtr pkt)
11312479SCurtis.Dunham@arm.com{
1149384SAndreas.Sandberg@arm.com    // remember if the current packet has data allocated
1159384SAndreas.Sandberg@arm.com    bool has_data = pkt->hasData() || pkt->hasRespData();
1169384SAndreas.Sandberg@arm.com
1179384SAndreas.Sandberg@arm.com    if (pkt->cmd == MemCmd::UpgradeReq) {
1189384SAndreas.Sandberg@arm.com        pkt->cmd = MemCmd::ReadExReq;
1199384SAndreas.Sandberg@arm.com        DPRINTF(Cache, "Replacing UpgradeReq with ReadExReq\n");
1207427Sgblack@eecs.umich.edu    } else if (pkt->cmd == MemCmd::SCUpgradeReq) {
1217427Sgblack@eecs.umich.edu        pkt->cmd = MemCmd::SCUpgradeFailReq;
1227427Sgblack@eecs.umich.edu        DPRINTF(Cache, "Replacing SCUpgradeReq with SCUpgradeFailReq\n");
1239385SAndreas.Sandberg@arm.com    } else if (pkt->cmd == MemCmd::StoreCondReq) {
1249385SAndreas.Sandberg@arm.com        pkt->cmd = MemCmd::StoreCondFailReq;
1257427Sgblack@eecs.umich.edu        DPRINTF(Cache, "Replacing StoreCondReq with StoreCondFailReq\n");
1267427Sgblack@eecs.umich.edu    }
12710037SARM gem5 Developers
12813114Sgiacomo.travaglini@arm.com    if (!has_data) {
12910037SARM gem5 Developers        // there is no sensible way of setting the data field if the
13013114Sgiacomo.travaglini@arm.com        // new command actually would carry data
13113114Sgiacomo.travaglini@arm.com        assert(!pkt->hasData());
13213114Sgiacomo.travaglini@arm.com
13313114Sgiacomo.travaglini@arm.com        if (pkt->hasRespData()) {
13413114Sgiacomo.travaglini@arm.com            // we went from a packet that had no data (neither request,
13512690Sgiacomo.travaglini@arm.com            // nor response), to one that does, and therefore we need to
13610037SARM gem5 Developers            // actually allocate space for the data payload
1377427Sgblack@eecs.umich.edu            pkt->allocate();
1387427Sgblack@eecs.umich.edu        }
13910037SARM gem5 Developers    }
1407427Sgblack@eecs.umich.edu}
1417427Sgblack@eecs.umich.edu
1427427Sgblack@eecs.umich.edu
1437427Sgblack@eecs.umich.eduvoid
1447427Sgblack@eecs.umich.eduMSHR::TargetList::replaceUpgrades()
1457427Sgblack@eecs.umich.edu{
1467427Sgblack@eecs.umich.edu    if (!hasUpgrade)
1477427Sgblack@eecs.umich.edu        return;
1487427Sgblack@eecs.umich.edu
1497427Sgblack@eecs.umich.edu    for (auto& t : *this) {
1507427Sgblack@eecs.umich.edu        replaceUpgrade(t.pkt);
1517427Sgblack@eecs.umich.edu    }
1527427Sgblack@eecs.umich.edu
1537427Sgblack@eecs.umich.edu    hasUpgrade = false;
1547427Sgblack@eecs.umich.edu}
1557427Sgblack@eecs.umich.edu
1567427Sgblack@eecs.umich.edu
1577427Sgblack@eecs.umich.eduvoid
1587427Sgblack@eecs.umich.eduMSHR::TargetList::clearDownstreamPending()
1597427Sgblack@eecs.umich.edu{
1607427Sgblack@eecs.umich.edu    for (auto& t : *this) {
1617427Sgblack@eecs.umich.edu        if (t.markedPending) {
1627427Sgblack@eecs.umich.edu            // Iterate over the SenderState stack and see if we find
1637436Sdam.sunwoo@arm.com            // an MSHR entry. If we find one, clear the
1647436Sdam.sunwoo@arm.com            // downstreamPending flag by calling
16510037SARM gem5 Developers            // clearDownstreamPending(). This recursively clears the
16610037SARM gem5 Developers            // downstreamPending flag in all caches this packet has
1677436Sdam.sunwoo@arm.com            // passed through.
1687436Sdam.sunwoo@arm.com            MSHR *mshr = t.pkt->findNextSenderState<MSHR>();
1697436Sdam.sunwoo@arm.com            if (mshr != nullptr) {
1707436Sdam.sunwoo@arm.com                mshr->clearDownstreamPending();
1717436Sdam.sunwoo@arm.com            }
1727436Sdam.sunwoo@arm.com        }
1737436Sdam.sunwoo@arm.com    }
1747436Sdam.sunwoo@arm.com}
1757436Sdam.sunwoo@arm.com
1767436Sdam.sunwoo@arm.com
1777436Sdam.sunwoo@arm.combool
1787436Sdam.sunwoo@arm.comMSHR::TargetList::checkFunctional(PacketPtr pkt)
17913393Sgiacomo.travaglini@arm.com{
18010037SARM gem5 Developers    for (auto& t : *this) {
1817436Sdam.sunwoo@arm.com        if (pkt->checkFunctional(t.pkt)) {
1827436Sdam.sunwoo@arm.com            return true;
1837436Sdam.sunwoo@arm.com        }
1847436Sdam.sunwoo@arm.com    }
1857436Sdam.sunwoo@arm.com
1867436Sdam.sunwoo@arm.com    return false;
1877436Sdam.sunwoo@arm.com}
1887436Sdam.sunwoo@arm.com
1897436Sdam.sunwoo@arm.com
1907436Sdam.sunwoo@arm.comvoid
1917436Sdam.sunwoo@arm.comMSHR::TargetList::print(std::ostream &os, int verbosity,
1927436Sdam.sunwoo@arm.com                        const std::string &prefix) const
1937436Sdam.sunwoo@arm.com{
1947436Sdam.sunwoo@arm.com    for (auto& t : *this) {
1957436Sdam.sunwoo@arm.com        const char *s;
1967436Sdam.sunwoo@arm.com        switch (t.source) {
19713393Sgiacomo.travaglini@arm.com          case Target::FromCPU:
19813393Sgiacomo.travaglini@arm.com            s = "FromCPU";
19913393Sgiacomo.travaglini@arm.com            break;
20013393Sgiacomo.travaglini@arm.com          case Target::FromSnoop:
20113393Sgiacomo.travaglini@arm.com            s = "FromSnoop";
20213393Sgiacomo.travaglini@arm.com            break;
20313393Sgiacomo.travaglini@arm.com          case Target::FromPrefetcher:
20413393Sgiacomo.travaglini@arm.com            s = "FromPrefetcher";
20513393Sgiacomo.travaglini@arm.com            break;
20613393Sgiacomo.travaglini@arm.com          default:
20713393Sgiacomo.travaglini@arm.com            s = "";
20813393Sgiacomo.travaglini@arm.com            break;
20913393Sgiacomo.travaglini@arm.com        }
21013393Sgiacomo.travaglini@arm.com        ccprintf(os, "%s%s: ", prefix, s);
21113393Sgiacomo.travaglini@arm.com        t.pkt->print(os, verbosity, "");
21213393Sgiacomo.travaglini@arm.com    }
21313396Sgiacomo.travaglini@arm.com}
21413396Sgiacomo.travaglini@arm.com
21513396Sgiacomo.travaglini@arm.com
21613396Sgiacomo.travaglini@arm.comvoid
21713393Sgiacomo.travaglini@arm.comMSHR::allocate(Addr blk_addr, unsigned blk_size, PacketPtr target,
21813393Sgiacomo.travaglini@arm.com               Tick when_ready, Counter _order, bool alloc_on_fill)
21913393Sgiacomo.travaglini@arm.com{
22013393Sgiacomo.travaglini@arm.com    blkAddr = blk_addr;
22113393Sgiacomo.travaglini@arm.com    blkSize = blk_size;
22213393Sgiacomo.travaglini@arm.com    isSecure = target->isSecure();
22313393Sgiacomo.travaglini@arm.com    readyTime = when_ready;
22413393Sgiacomo.travaglini@arm.com    order = _order;
22513393Sgiacomo.travaglini@arm.com    assert(target);
22613393Sgiacomo.travaglini@arm.com    isForward = false;
22713393Sgiacomo.travaglini@arm.com    allocOnFill = alloc_on_fill;
22813393Sgiacomo.travaglini@arm.com    _isUncacheable = target->req->isUncacheable();
22913393Sgiacomo.travaglini@arm.com    inService = false;
23013393Sgiacomo.travaglini@arm.com    downstreamPending = false;
23113393Sgiacomo.travaglini@arm.com    assert(targets.isReset());
23213393Sgiacomo.travaglini@arm.com    // Don't know of a case where we would allocate a new MSHR for a
23313393Sgiacomo.travaglini@arm.com    // snoop (mem-side request), so set source according to request here
23413393Sgiacomo.travaglini@arm.com    Target::Source source = (target->cmd == MemCmd::HardPFReq) ?
2357644Sali.saidi@arm.com        Target::FromPrefetcher : Target::FromCPU;
2368147SAli.Saidi@ARM.com    targets.add(target, when_ready, _order, source, true);
2379385SAndreas.Sandberg@arm.com    assert(deferredTargets.isReset());
2389385SAndreas.Sandberg@arm.com}
23910037SARM gem5 Developers
24010037SARM gem5 Developers
24110037SARM gem5 Developersvoid
24210037SARM gem5 DevelopersMSHR::clearDownstreamPending()
24310037SARM gem5 Developers{
24410037SARM gem5 Developers    assert(downstreamPending);
24510037SARM gem5 Developers    downstreamPending = false;
24610037SARM gem5 Developers    // recursively clear flag on any MSHRs we will be forwarding
24710037SARM gem5 Developers    // responses to
24810037SARM gem5 Developers    targets.clearDownstreamPending();
24910037SARM gem5 Developers}
25010037SARM gem5 Developers
25110037SARM gem5 Developersvoid
25210037SARM gem5 DevelopersMSHR::markInService(bool pending_modified_resp)
25310037SARM gem5 Developers{
25410037SARM gem5 Developers    assert(!inService);
2558147SAli.Saidi@ARM.com
2567427Sgblack@eecs.umich.edu    inService = true;
2577427Sgblack@eecs.umich.edu    pendingModified = targets.needsWritable || pending_modified_resp;
2587427Sgblack@eecs.umich.edu    postInvalidate = postDowngrade = false;
25910037SARM gem5 Developers
26010037SARM gem5 Developers    if (!downstreamPending) {
26110037SARM gem5 Developers        // let upstream caches know that the request has made it to a
26210037SARM gem5 Developers        // level where it's going to get a response
26313396Sgiacomo.travaglini@arm.com        targets.clearDownstreamPending();
26410037SARM gem5 Developers    }
26510037SARM gem5 Developers}
26610037SARM gem5 Developers
26710037SARM gem5 Developers
26810037SARM gem5 Developersvoid
26910037SARM gem5 DevelopersMSHR::deallocate()
27010037SARM gem5 Developers{
27110037SARM gem5 Developers    assert(targets.empty());
27210037SARM gem5 Developers    targets.resetFlags();
27310037SARM gem5 Developers    assert(deferredTargets.isReset());
27410037SARM gem5 Developers    inService = false;
27510037SARM gem5 Developers}
27610037SARM gem5 Developers
27710037SARM gem5 Developers/*
27810037SARM gem5 Developers * Adds a target to an MSHR
27910037SARM gem5 Developers */
28010037SARM gem5 Developersvoid
28110037SARM gem5 DevelopersMSHR::allocateTarget(PacketPtr pkt, Tick whenReady, Counter _order,
28210037SARM gem5 Developers                     bool alloc_on_fill)
28310037SARM gem5 Developers{
28410037SARM gem5 Developers    // assume we'd never issue a prefetch when we've got an
28510037SARM gem5 Developers    // outstanding miss
28610037SARM gem5 Developers    assert(pkt->cmd != MemCmd::HardPFReq);
28710037SARM gem5 Developers
28810037SARM gem5 Developers    // uncacheable accesses always allocate a new MSHR, and cacheable
28910037SARM gem5 Developers    // accesses ignore any uncacheable MSHRs, thus we should never
29010037SARM gem5 Developers    // have targets addded if originally allocated uncacheable
29110037SARM gem5 Developers    assert(!_isUncacheable);
29210037SARM gem5 Developers
29310037SARM gem5 Developers    // potentially re-evaluate whether we should allocate on a fill or
29410037SARM gem5 Developers    // not
29511770SCurtis.Dunham@arm.com    allocOnFill = allocOnFill || alloc_on_fill;
29610037SARM gem5 Developers
29711574SCurtis.Dunham@arm.com    // if there's a request already in service for this MSHR, we will
29811770SCurtis.Dunham@arm.com    // have to defer the new target until after the response if any of
29911770SCurtis.Dunham@arm.com    // the following are true:
30010037SARM gem5 Developers    // - there are other targets already deferred
30111770SCurtis.Dunham@arm.com    // - there's a pending invalidate to be applied after the response
30211770SCurtis.Dunham@arm.com    //   comes back (but before this target is processed)
30310037SARM gem5 Developers    // - this target requires a writable block and either we're not
30410037SARM gem5 Developers    //   getting a writable block back or we have already snooped
30510037SARM gem5 Developers    //   another read request that will downgrade our writable block
30613114Sgiacomo.travaglini@arm.com    //   to non-writable (Shared or Owned)
30710037SARM gem5 Developers    if (inService &&
30813114Sgiacomo.travaglini@arm.com        (!deferredTargets.empty() || hasPostInvalidate() ||
30913114Sgiacomo.travaglini@arm.com         (pkt->needsWritable() &&
31013114Sgiacomo.travaglini@arm.com          (!isPendingModified() || hasPostDowngrade() || isForward)))) {
31113114Sgiacomo.travaglini@arm.com        // need to put on deferred list
31213114Sgiacomo.travaglini@arm.com        if (hasPostInvalidate())
31313114Sgiacomo.travaglini@arm.com            replaceUpgrade(pkt);
31413114Sgiacomo.travaglini@arm.com        deferredTargets.add(pkt, whenReady, _order, Target::FromCPU, true);
31513114Sgiacomo.travaglini@arm.com    } else {
31613114Sgiacomo.travaglini@arm.com        // No request outstanding, or still OK to append to
31713114Sgiacomo.travaglini@arm.com        // outstanding request: append to regular target list.  Only
31813114Sgiacomo.travaglini@arm.com        // mark pending if current request hasn't been issued yet
31913114Sgiacomo.travaglini@arm.com        // (isn't in service).
32013114Sgiacomo.travaglini@arm.com        targets.add(pkt, whenReady, _order, Target::FromCPU, !inService);
32113114Sgiacomo.travaglini@arm.com    }
32213114Sgiacomo.travaglini@arm.com}
32313114Sgiacomo.travaglini@arm.com
32413114Sgiacomo.travaglini@arm.combool
32513114Sgiacomo.travaglini@arm.comMSHR::handleSnoop(PacketPtr pkt, Counter _order)
32613114Sgiacomo.travaglini@arm.com{
32713499Sgiacomo.travaglini@arm.com    DPRINTF(Cache, "%s for %s addr %#llx size %d\n", __func__,
32813499Sgiacomo.travaglini@arm.com            pkt->cmdString(), pkt->getAddr(), pkt->getSize());
32913499Sgiacomo.travaglini@arm.com
33013499Sgiacomo.travaglini@arm.com    // when we snoop packets the needsWritable and isInvalidate flags
33113114Sgiacomo.travaglini@arm.com    // should always be the same, however, this assumes that we never
33213114Sgiacomo.travaglini@arm.com    // snoop writes as they are currently not marked as invalidations
33313114Sgiacomo.travaglini@arm.com    panic_if(pkt->needsWritable() != pkt->isInvalidate(),
33413114Sgiacomo.travaglini@arm.com             "%s got snoop %s to addr %#llx where needsWritable, "
33513114Sgiacomo.travaglini@arm.com             "does not match isInvalidate", name(), pkt->cmdString(),
33610037SARM gem5 Developers             pkt->getAddr());
33710037SARM gem5 Developers
33810037SARM gem5 Developers    if (!inService || (pkt->isExpressSnoop() && downstreamPending)) {
33910461SAndreas.Sandberg@ARM.com        // Request has not been issued yet, or it's been issued
34010461SAndreas.Sandberg@ARM.com        // locally but is buffered unissued at some downstream cache
34110461SAndreas.Sandberg@ARM.com        // which is forwarding us this snoop.  Either way, the packet
34210461SAndreas.Sandberg@ARM.com        // we're snooping logically precedes this MSHR's request, so
34310037SARM gem5 Developers        // the snoop has no impact on the MSHR, but must be processed
34410037SARM gem5 Developers        // in the standard way by the cache.  The only exception is
34510037SARM gem5 Developers        // that if we're an L2+ cache buffering an UpgradeReq from a
34610037SARM gem5 Developers        // higher-level cache, and the snoop is invalidating, then our
34710037SARM gem5 Developers        // buffered upgrades must be converted to read exclusives,
34813116Sgiacomo.travaglini@arm.com        // since the upper-level cache no longer has a valid copy.
34910037SARM gem5 Developers        // That is, even though the upper-level cache got out on its
35010461SAndreas.Sandberg@ARM.com        // local bus first, some other invalidating transaction
35110461SAndreas.Sandberg@ARM.com        // reached the global bus before the upgrade did.
35210461SAndreas.Sandberg@ARM.com        if (pkt->needsWritable()) {
35310461SAndreas.Sandberg@ARM.com            targets.replaceUpgrades();
35410461SAndreas.Sandberg@ARM.com            deferredTargets.replaceUpgrades();
35510037SARM gem5 Developers        }
35610037SARM gem5 Developers
35710037SARM gem5 Developers        return false;
35810037SARM gem5 Developers    }
35910037SARM gem5 Developers
36011574SCurtis.Dunham@arm.com    // From here on down, the request issued by this MSHR logically
36110037SARM gem5 Developers    // precedes the request we're snooping.
36210037SARM gem5 Developers    if (pkt->needsWritable()) {
36310037SARM gem5 Developers        // snooped request still precedes the re-request we'll have to
36411574SCurtis.Dunham@arm.com        // issue for deferred targets, if any...
36510037SARM gem5 Developers        deferredTargets.replaceUpgrades();
36610037SARM gem5 Developers    }
36710037SARM gem5 Developers
36810037SARM gem5 Developers    if (hasPostInvalidate()) {
36910037SARM gem5 Developers        // a prior snoop has already appended an invalidation, so
37010037SARM gem5 Developers        // logically we don't have the block anymore; no need for
37110037SARM gem5 Developers        // further snooping.
37213114Sgiacomo.travaglini@arm.com        return true;
37313173Sgiacomo.travaglini@arm.com    }
37413173Sgiacomo.travaglini@arm.com
37513173Sgiacomo.travaglini@arm.com    if (isPendingModified() || pkt->isInvalidate()) {
37613173Sgiacomo.travaglini@arm.com        // We need to save and replay the packet in two cases:
37710037SARM gem5 Developers        // 1. We're awaiting a writable copy (Modified or Exclusive),
37810037SARM gem5 Developers        //    so this MSHR is the orgering point, and we need to respond
37912972Sandreas.sandberg@arm.com        //    after we receive data.
38012972Sandreas.sandberg@arm.com        // 2. It's an invalidation (e.g., UpgradeReq), and we need
38112972Sandreas.sandberg@arm.com        //    to forward the snoop up the hierarchy after the current
38212972Sandreas.sandberg@arm.com        //    transaction completes.
38312972Sandreas.sandberg@arm.com
38413531Sjairo.balart@metempsy.com        // Start by determining if we will eventually respond or not,
38513531Sjairo.balart@metempsy.com        // matching the conditions checked in Cache::handleSnoop
38613531Sjairo.balart@metempsy.com        bool will_respond = isPendingModified() && pkt->needsResponse() &&
38713531Sjairo.balart@metempsy.com            pkt->cmd != MemCmd::InvalidateReq;
38813531Sjairo.balart@metempsy.com
38913531Sjairo.balart@metempsy.com        // The packet we are snooping may be deleted by the time we
39013531Sjairo.balart@metempsy.com        // actually process the target, and we consequently need to
39112972Sandreas.sandberg@arm.com        // save a copy here. Clear flags and also allocate new data as
39212972Sandreas.sandberg@arm.com        // the original packet data storage may have been deleted by
39312972Sandreas.sandberg@arm.com        // the time we get to process this packet. In the cases where
39413581Sgabeblack@google.com        // we are not responding after handling the snoop we also need
39510035Sandreas.hansson@arm.com        // to create a copy of the request to be on the safe side. In
3967405SAli.Saidi@ARM.com        // the latter case the cache is responsible for deleting both
3977405SAli.Saidi@ARM.com        // the packet and the request as part of handling the deferred
3987614Sminkyu.jeong@arm.com        // snoop.
39912478SCurtis.Dunham@arm.com        PacketPtr cp_pkt = will_respond ? new Packet(pkt, true, true) :
40012478SCurtis.Dunham@arm.com            new Packet(new Request(*pkt->req), pkt->cmd);
40112478SCurtis.Dunham@arm.com
40212478SCurtis.Dunham@arm.com        if (isPendingModified()) {
40312478SCurtis.Dunham@arm.com            // we are the ordering point, and will consequently
40412478SCurtis.Dunham@arm.com            // respond, and depending on whether the packet
40512478SCurtis.Dunham@arm.com            // needsWritable or not we either pass a Shared line or a
40612478SCurtis.Dunham@arm.com            // Modified line
40712478SCurtis.Dunham@arm.com            pkt->setCacheResponding();
40812478SCurtis.Dunham@arm.com
40912478SCurtis.Dunham@arm.com            // inform the cache hierarchy that this cache had the line
41012478SCurtis.Dunham@arm.com            // in the Modified state, even if the response is passed
41112478SCurtis.Dunham@arm.com            // as Shared (and thus non-writable)
41212478SCurtis.Dunham@arm.com            pkt->setResponderHadWritable();
41312478SCurtis.Dunham@arm.com
41412478SCurtis.Dunham@arm.com            // in the case of an uncacheable request there is no need
4157405SAli.Saidi@ARM.com            // to set the responderHadWritable flag, but since the
4167405SAli.Saidi@ARM.com            // recipient does not care there is no harm in doing so
4177405SAli.Saidi@ARM.com        }
41813581Sgabeblack@google.com        targets.add(cp_pkt, curTick(), _order, Target::FromSnoop,
4197405SAli.Saidi@ARM.com                    downstreamPending && targets.needsWritable);
4207405SAli.Saidi@ARM.com
42110037SARM gem5 Developers        if (pkt->needsWritable()) {
42210037SARM gem5 Developers            // This transaction will take away our pending copy
42310037SARM gem5 Developers            postInvalidate = true;
4249050Schander.sudanthi@arm.com        }
4257405SAli.Saidi@ARM.com    }
42610037SARM gem5 Developers
42710037SARM gem5 Developers    if (!pkt->needsWritable() && !pkt->req->isUncacheable()) {
4287720Sgblack@eecs.umich.edu        // This transaction will get a read-shared copy, downgrading
4297720Sgblack@eecs.umich.edu        // our copy if we had a writable one
4307405SAli.Saidi@ARM.com        postDowngrade = true;
4317405SAli.Saidi@ARM.com        // make sure that any downstream cache does not respond with a
4327757SAli.Saidi@ARM.com        // writable (and dirty) copy even if it has one, unless it was
43310037SARM gem5 Developers        // explicitly asked for one
43410037SARM gem5 Developers        pkt->setHasSharers();
43510037SARM gem5 Developers    }
43610037SARM gem5 Developers
43710037SARM gem5 Developers    return true;
43810037SARM gem5 Developers}
43910037SARM gem5 Developers
44010037SARM gem5 Developers
44110037SARM gem5 Developersbool
44210037SARM gem5 DevelopersMSHR::promoteDeferredTargets()
44310037SARM gem5 Developers{
44410037SARM gem5 Developers    assert(targets.empty());
44510037SARM gem5 Developers    if (deferredTargets.empty()) {
44610037SARM gem5 Developers        return false;
44710037SARM gem5 Developers    }
44810037SARM gem5 Developers
44910037SARM gem5 Developers    // swap targets & deferredTargets lists
45010037SARM gem5 Developers    std::swap(targets, deferredTargets);
45110037SARM gem5 Developers
45210037SARM gem5 Developers    // clear deferredTargets flags
45310037SARM gem5 Developers    deferredTargets.resetFlags();
45410037SARM gem5 Developers
45510037SARM gem5 Developers    order = targets.front().order;
45610037SARM gem5 Developers    readyTime = std::max(curTick(), targets.front().readyTime);
45710037SARM gem5 Developers
45810037SARM gem5 Developers    return true;
45910037SARM gem5 Developers}
46010037SARM gem5 Developers
46110037SARM gem5 Developers
46210037SARM gem5 Developersvoid
46310037SARM gem5 DevelopersMSHR::promoteWritable()
46410037SARM gem5 Developers{
46510037SARM gem5 Developers    if (deferredTargets.needsWritable &&
46612667Schuan.zhu@arm.com        !(hasPostInvalidate() || hasPostDowngrade())) {
46710037SARM gem5 Developers        // We got a writable response, but we have deferred targets
46810037SARM gem5 Developers        // which are waiting to request a writable copy (not because
46910037SARM gem5 Developers        // of a pending invalidate).  This can happen if the original
47010037SARM gem5 Developers        // request was for a read-only block, but we got a writable
47110037SARM gem5 Developers        // response anyway. Since we got the writable copy there's no
47210037SARM gem5 Developers        // need to defer the targets, so move them up to the regular
47313581Sgabeblack@google.com        // target list.
47410037SARM gem5 Developers        assert(!targets.needsWritable);
47510037SARM gem5 Developers        targets.needsWritable = true;
47610037SARM gem5 Developers        // if any of the deferred targets were upper-level cache
47710037SARM gem5 Developers        // requests marked downstreamPending, need to clear that
47810037SARM gem5 Developers        assert(!downstreamPending);  // not pending here anymore
4798284SAli.Saidi@ARM.com        deferredTargets.clearDownstreamPending();
48010037SARM gem5 Developers        // this clears out deferredTargets too
48113550Sgiacomo.travaglini@arm.com        targets.splice(targets.end(), deferredTargets);
48210037SARM gem5 Developers        deferredTargets.resetFlags();
48313550Sgiacomo.travaglini@arm.com    }
48410037SARM gem5 Developers}
48510037SARM gem5 Developers
48610037SARM gem5 Developers
48710037SARM gem5 Developersbool
48810037SARM gem5 DevelopersMSHR::checkFunctional(PacketPtr pkt)
48910037SARM gem5 Developers{
49010037SARM gem5 Developers    // For printing, we treat the MSHR as a whole as single entity.
49110037SARM gem5 Developers    // For other requests, we iterate over the individual targets
49210037SARM gem5 Developers    // since that's where the actual data lies.
49310037SARM gem5 Developers    if (pkt->isPrint()) {
49410037SARM gem5 Developers        pkt->checkFunctional(this, blkAddr, isSecure, blkSize, nullptr);
4959050Schander.sudanthi@arm.com        return false;
4968284SAli.Saidi@ARM.com    } else {
49710037SARM gem5 Developers        return (targets.checkFunctional(pkt) ||
49810037SARM gem5 Developers                deferredTargets.checkFunctional(pkt));
49910037SARM gem5 Developers    }
50010037SARM gem5 Developers}
50110037SARM gem5 Developers
50210037SARM gem5 Developersbool
50310037SARM gem5 DevelopersMSHR::sendPacket(Cache &cache)
5047405SAli.Saidi@ARM.com{
5057731SAli.Saidi@ARM.com    return cache.sendMSHRQueuePacket(this);
5068468Swade.walker@arm.com}
5078468Swade.walker@arm.com
5088468Swade.walker@arm.comvoid
5097405SAli.Saidi@ARM.comMSHR::print(std::ostream &os, int verbosity, const std::string &prefix) const
5107731SAli.Saidi@ARM.com{
5117405SAli.Saidi@ARM.com    ccprintf(os, "%s[%#llx:%#llx](%s) %s %s %s state: %s %s %s %s %s\n",
5127405SAli.Saidi@ARM.com             prefix, blkAddr, blkAddr + blkSize - 1,
51311809Sbaz21@cam.ac.uk             isSecure ? "s" : "ns",
51411809Sbaz21@cam.ac.uk             isForward ? "Forward" : "",
5159130Satgutier@umich.edu             allocOnFill ? "AllocOnFill" : "",
5169130Satgutier@umich.edu             needsWritable() ? "Wrtbl" : "",
5179130Satgutier@umich.edu             _isUncacheable ? "Unc" : "",
5189130Satgutier@umich.edu             inService ? "InSvc" : "",
5199814Sandreas.hansson@arm.com             downstreamPending ? "DwnPend" : "",
5209130Satgutier@umich.edu             hasPostInvalidate() ? "PostInv" : "",
5219130Satgutier@umich.edu             hasPostDowngrade() ? "PostDowngr" : "");
5229130Satgutier@umich.edu
5239130Satgutier@umich.edu    ccprintf(os, "%s  Targets:\n", prefix);
5249130Satgutier@umich.edu    targets.print(os, verbosity, prefix + "    ");
5259130Satgutier@umich.edu    if (!deferredTargets.empty()) {
5269130Satgutier@umich.edu        ccprintf(os, "%s  Deferred Targets:\n", prefix);
5279130Satgutier@umich.edu        deferredTargets.print(os, verbosity, prefix + "      ");
5289130Satgutier@umich.edu    }
5299130Satgutier@umich.edu}
5309130Satgutier@umich.edu
5319130Satgutier@umich.edustd::string
5329130Satgutier@umich.eduMSHR::print() const
5339130Satgutier@umich.edu{
5349130Satgutier@umich.edu    ostringstream str;
5359130Satgutier@umich.edu    print(str);
5369130Satgutier@umich.edu    return str.str();
5379130Satgutier@umich.edu}
5389130Satgutier@umich.edu