mshr.cc revision 5314
16019Shines@cs.fsu.edu/*
27093Sgblack@eecs.umich.edu * Copyright (c) 2002-2005 The Regents of The University of Michigan
37093Sgblack@eecs.umich.edu * All rights reserved.
47093Sgblack@eecs.umich.edu *
57093Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without
67093Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are
77093Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright
87093Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer;
97093Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright
107093Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the
117093Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution;
127093Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its
137093Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from
146019Shines@cs.fsu.edu * this software without specific prior written permission.
156019Shines@cs.fsu.edu *
166019Shines@cs.fsu.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
176019Shines@cs.fsu.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
186019Shines@cs.fsu.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
196019Shines@cs.fsu.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
206019Shines@cs.fsu.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
216019Shines@cs.fsu.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
226019Shines@cs.fsu.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
236019Shines@cs.fsu.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
246019Shines@cs.fsu.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
256019Shines@cs.fsu.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
266019Shines@cs.fsu.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
276019Shines@cs.fsu.edu *
286019Shines@cs.fsu.edu * Authors: Erik Hallnor
296019Shines@cs.fsu.edu *          Dave Greene
306019Shines@cs.fsu.edu */
316019Shines@cs.fsu.edu
326019Shines@cs.fsu.edu/**
336019Shines@cs.fsu.edu * @file
346019Shines@cs.fsu.edu * Miss Status and Handling Register (MSHR) definitions.
356019Shines@cs.fsu.edu */
366019Shines@cs.fsu.edu
376019Shines@cs.fsu.edu#include <assert.h>
386019Shines@cs.fsu.edu#include <string>
396019Shines@cs.fsu.edu#include <vector>
406019Shines@cs.fsu.edu#include <algorithm>
416735Sgblack@eecs.umich.edu
426735Sgblack@eecs.umich.edu#include "mem/cache/miss/mshr.hh"
436019Shines@cs.fsu.edu#include "sim/core.hh" // for curTick
446019Shines@cs.fsu.edu#include "sim/host.hh"
456019Shines@cs.fsu.edu#include "base/misc.hh"
468229Snate@binkert.org#include "mem/cache/cache.hh"
478229Snate@binkert.org
486019Shines@cs.fsu.eduusing namespace std;
498232Snate@binkert.org
508782Sgblack@eecs.umich.eduMSHR::MSHR()
516019Shines@cs.fsu.edu{
526019Shines@cs.fsu.edu    inService = false;
536019Shines@cs.fsu.edu    ntargets = 0;
546019Shines@cs.fsu.edu    threadNum = -1;
557362Sgblack@eecs.umich.edu    targets = new TargetList();
566735Sgblack@eecs.umich.edu    deferredTargets = new TargetList();
576019Shines@cs.fsu.edu}
587362Sgblack@eecs.umich.edu
596735Sgblack@eecs.umich.edu
606019Shines@cs.fsu.eduMSHR::TargetList::TargetList()
617362Sgblack@eecs.umich.edu    : needsExclusive(false), hasUpgrade(false)
626735Sgblack@eecs.umich.edu{}
636019Shines@cs.fsu.edu
647362Sgblack@eecs.umich.edu
656735Sgblack@eecs.umich.eduinline void
666019Shines@cs.fsu.eduMSHR::TargetList::add(PacketPtr pkt, Tick readyTime,
677362Sgblack@eecs.umich.edu                      Counter order, bool cpuSide)
686735Sgblack@eecs.umich.edu{
696019Shines@cs.fsu.edu    if (cpuSide) {
707362Sgblack@eecs.umich.edu        if (pkt->needsExclusive()) {
716735Sgblack@eecs.umich.edu            needsExclusive = true;
726019Shines@cs.fsu.edu        }
737362Sgblack@eecs.umich.edu
746735Sgblack@eecs.umich.edu        if (pkt->cmd == MemCmd::UpgradeReq) {
756019Shines@cs.fsu.edu            hasUpgrade = true;
767652Sminkyu.jeong@arm.com        }
777652Sminkyu.jeong@arm.com
787652Sminkyu.jeong@arm.com        MSHR *mshr = dynamic_cast<MSHR*>(pkt->senderState);
798518Sgeoffrey.blake@arm.com        if (mshr != NULL) {
808518Sgeoffrey.blake@arm.com            assert(!mshr->downstreamPending);
816735Sgblack@eecs.umich.edu            mshr->downstreamPending = true;
827362Sgblack@eecs.umich.edu        }
836735Sgblack@eecs.umich.edu    }
846735Sgblack@eecs.umich.edu
856019Shines@cs.fsu.edu    push_back(Target(pkt, readyTime, order, cpuSide));
866735Sgblack@eecs.umich.edu}
877400SAli.Saidi@ARM.com
886735Sgblack@eecs.umich.edu
896735Sgblack@eecs.umich.eduvoid
906735Sgblack@eecs.umich.eduMSHR::TargetList::replaceUpgrades()
917400SAli.Saidi@ARM.com{
926735Sgblack@eecs.umich.edu    if (!hasUpgrade)
936735Sgblack@eecs.umich.edu        return;
946735Sgblack@eecs.umich.edu
956019Shines@cs.fsu.edu    Iterator end_i = end();
966019Shines@cs.fsu.edu    for (Iterator i = begin(); i != end_i; ++i) {
976019Shines@cs.fsu.edu        if (i->pkt->cmd == MemCmd::UpgradeReq) {
986735Sgblack@eecs.umich.edu            i->pkt->cmd = MemCmd::ReadExReq;
997678Sgblack@eecs.umich.edu            DPRINTF(Cache, "Replacing UpgradeReq with ReadExReq\n");
1006019Shines@cs.fsu.edu        }
1016735Sgblack@eecs.umich.edu    }
1026735Sgblack@eecs.umich.edu
1038782Sgblack@eecs.umich.edu    hasUpgrade = false;
1048782Sgblack@eecs.umich.edu}
1056735Sgblack@eecs.umich.edu
1066019Shines@cs.fsu.edu
1076735Sgblack@eecs.umich.eduvoid
1086735Sgblack@eecs.umich.eduMSHR::TargetList::clearDownstreamPending()
1098303SAli.Saidi@ARM.com{
1108303SAli.Saidi@ARM.com    Iterator end_i = end();
1118303SAli.Saidi@ARM.com    for (Iterator i = begin(); i != end_i; ++i) {
1128303SAli.Saidi@ARM.com        MSHR *mshr = dynamic_cast<MSHR*>(i->pkt->senderState);
1138303SAli.Saidi@ARM.com        if (mshr != NULL) {
1148303SAli.Saidi@ARM.com            assert(mshr->downstreamPending);
1157720Sgblack@eecs.umich.edu            mshr->downstreamPending = false;
1168205SAli.Saidi@ARM.com        }
1178205SAli.Saidi@ARM.com    }
1188205SAli.Saidi@ARM.com}
1196735Sgblack@eecs.umich.edu
1206735Sgblack@eecs.umich.edu
1216735Sgblack@eecs.umich.edubool
1226735Sgblack@eecs.umich.eduMSHR::TargetList::checkFunctional(PacketPtr pkt)
1236735Sgblack@eecs.umich.edu{
1247093Sgblack@eecs.umich.edu    Iterator end_i = end();
1256735Sgblack@eecs.umich.edu    for (Iterator i = begin(); i != end_i; ++i) {
1266735Sgblack@eecs.umich.edu        if (pkt->checkFunctional(i->pkt)) {
1276735Sgblack@eecs.umich.edu            return true;
1287302Sgblack@eecs.umich.edu        }
1296735Sgblack@eecs.umich.edu    }
1308518Sgeoffrey.blake@arm.com
1318518Sgeoffrey.blake@arm.com    return false;
1327720Sgblack@eecs.umich.edu}
1336735Sgblack@eecs.umich.edu
1346735Sgblack@eecs.umich.edu
1356735Sgblack@eecs.umich.eduvoid
1366735Sgblack@eecs.umich.eduMSHR::TargetList::
1376735Sgblack@eecs.umich.eduprint(std::ostream &os, int verbosity, const std::string &prefix) const
1386735Sgblack@eecs.umich.edu{
1396735Sgblack@eecs.umich.edu    ConstIterator end_i = end();
1406735Sgblack@eecs.umich.edu    for (ConstIterator i = begin(); i != end_i; ++i) {
1416735Sgblack@eecs.umich.edu        ccprintf(os, "%s%s: ", prefix, i->isCpuSide() ? "cpu" : "mem");
1426735Sgblack@eecs.umich.edu        i->pkt->print(os, verbosity, "");
1436735Sgblack@eecs.umich.edu    }
1446735Sgblack@eecs.umich.edu}
1456735Sgblack@eecs.umich.edu
1466735Sgblack@eecs.umich.edu
1476735Sgblack@eecs.umich.eduvoid
1486735Sgblack@eecs.umich.eduMSHR::allocate(Addr _addr, int _size, PacketPtr target,
1496735Sgblack@eecs.umich.edu               Tick whenReady, Counter _order)
1506735Sgblack@eecs.umich.edu{
1516735Sgblack@eecs.umich.edu    addr = _addr;
1526735Sgblack@eecs.umich.edu    size = _size;
1537093Sgblack@eecs.umich.edu    readyTime = whenReady;
1547093Sgblack@eecs.umich.edu    order = _order;
1557720Sgblack@eecs.umich.edu    assert(target);
1567585SAli.Saidi@arm.com    isCacheFill = false;
1577720Sgblack@eecs.umich.edu    _isUncacheable = target->req->isUncacheable();
1587720Sgblack@eecs.umich.edu    inService = false;
1597720Sgblack@eecs.umich.edu    downstreamPending = false;
1607720Sgblack@eecs.umich.edu    threadNum = 0;
1617720Sgblack@eecs.umich.edu    ntargets = 1;
1627720Sgblack@eecs.umich.edu    // Don't know of a case where we would allocate a new MSHR for a
1637720Sgblack@eecs.umich.edu    // snoop (mem-side request), so set cpuSide to true here.
1646019Shines@cs.fsu.edu    assert(targets->isReset());
1657189Sgblack@eecs.umich.edu    targets->add(target, whenReady, _order, true);
1667400SAli.Saidi@ARM.com    assert(deferredTargets->isReset());
1677678Sgblack@eecs.umich.edu    pendingInvalidate = false;
1687400SAli.Saidi@ARM.com    pendingShared = false;
1698782Sgblack@eecs.umich.edu    data = NULL;
1708782Sgblack@eecs.umich.edu}
1718782Sgblack@eecs.umich.edu
1728782Sgblack@eecs.umich.edu
1738205SAli.Saidi@ARM.combool
1747400SAli.Saidi@ARM.comMSHR::markInService()
1757400SAli.Saidi@ARM.com{
1767189Sgblack@eecs.umich.edu    assert(!inService);
1777678Sgblack@eecs.umich.edu    if (isSimpleForward()) {
1787189Sgblack@eecs.umich.edu        // we just forwarded the request packet & don't expect a
1798782Sgblack@eecs.umich.edu        // response, so get rid of it
1808782Sgblack@eecs.umich.edu        assert(getNumTargets() == 1);
1818806Sgblack@eecs.umich.edu        popTarget();
1828806Sgblack@eecs.umich.edu        return true;
1838806Sgblack@eecs.umich.edu    }
1848806Sgblack@eecs.umich.edu    inService = true;
1858806Sgblack@eecs.umich.edu    if (!downstreamPending) {
1868806Sgblack@eecs.umich.edu        // let upstream caches know that the request has made it to a
1878806Sgblack@eecs.umich.edu        // level where it's going to get a response
1888806Sgblack@eecs.umich.edu        targets->clearDownstreamPending();
1898806Sgblack@eecs.umich.edu    }
1908806Sgblack@eecs.umich.edu    return false;
1918806Sgblack@eecs.umich.edu}
1927189Sgblack@eecs.umich.edu
1938806Sgblack@eecs.umich.edu
1948806Sgblack@eecs.umich.eduvoid
1957189Sgblack@eecs.umich.eduMSHR::deallocate()
1967189Sgblack@eecs.umich.edu{
1977189Sgblack@eecs.umich.edu    assert(targets->empty());
1987197Sgblack@eecs.umich.edu    targets->resetFlags();
1997678Sgblack@eecs.umich.edu    assert(deferredTargets->isReset());
2007197Sgblack@eecs.umich.edu    assert(ntargets == 0);
2018782Sgblack@eecs.umich.edu    inService = false;
2028782Sgblack@eecs.umich.edu    //allocIter = NULL;
2038806Sgblack@eecs.umich.edu    //readyIter = NULL;
2048806Sgblack@eecs.umich.edu}
2057197Sgblack@eecs.umich.edu
2068806Sgblack@eecs.umich.edu/*
2078806Sgblack@eecs.umich.edu * Adds a target to an MSHR
2088806Sgblack@eecs.umich.edu */
2098806Sgblack@eecs.umich.eduvoid
2108806Sgblack@eecs.umich.eduMSHR::allocateTarget(PacketPtr pkt, Tick whenReady, Counter _order)
2118806Sgblack@eecs.umich.edu{
2128806Sgblack@eecs.umich.edu    // if there's a request already in service for this MSHR, we will
2138806Sgblack@eecs.umich.edu    // have to defer the new target until after the response if any of
2148806Sgblack@eecs.umich.edu    // the following are true:
2158806Sgblack@eecs.umich.edu    // - there are other targets already deferred
2168806Sgblack@eecs.umich.edu    // - there's a pending invalidate to be applied after the response
2177197Sgblack@eecs.umich.edu    //   comes back (but before this target is processed)
2187197Sgblack@eecs.umich.edu    // - the outstanding request is for a non-exclusive block and this
2197362Sgblack@eecs.umich.edu    //   target requires an exclusive block
2207362Sgblack@eecs.umich.edu    if (inService &&
2217678Sgblack@eecs.umich.edu        (!deferredTargets->empty() || pendingInvalidate ||
2227362Sgblack@eecs.umich.edu         (!targets->needsExclusive && pkt->needsExclusive()))) {
2238205SAli.Saidi@ARM.com        // need to put on deferred list
2247362Sgblack@eecs.umich.edu        deferredTargets->add(pkt, whenReady, _order, true);
2257362Sgblack@eecs.umich.edu    } else {
2267362Sgblack@eecs.umich.edu        // no request outstanding, or still OK to append to
2277362Sgblack@eecs.umich.edu        // outstanding request
2287362Sgblack@eecs.umich.edu        targets->add(pkt, whenReady, _order, true);
2297362Sgblack@eecs.umich.edu    }
2307362Sgblack@eecs.umich.edu
2317362Sgblack@eecs.umich.edu    ++ntargets;
2328314Sgeoffrey.blake@arm.com}
2338314Sgeoffrey.blake@arm.com
2347362Sgblack@eecs.umich.edubool
2357362Sgblack@eecs.umich.eduMSHR::handleSnoop(PacketPtr pkt, Counter _order)
2367652Sminkyu.jeong@arm.com{
2377678Sgblack@eecs.umich.edu    if (!inService || (pkt->isExpressSnoop() && downstreamPending)) {
2387652Sminkyu.jeong@arm.com        // Request has not been issued yet, or it's been issued
2397652Sminkyu.jeong@arm.com        // locally but is buffered unissued at some downstream cache
2407652Sminkyu.jeong@arm.com        // which is forwarding us this snoop.  Either way, the packet
2417652Sminkyu.jeong@arm.com        // we're snooping logically precedes this MSHR's request, so
2427652Sminkyu.jeong@arm.com        // the snoop has no impact on the MSHR, but must be processed
2437720Sgblack@eecs.umich.edu        // in the standard way by the cache.  The only exception is
2447720Sgblack@eecs.umich.edu        // that if we're an L2+ cache buffering an UpgradeReq from a
2457720Sgblack@eecs.umich.edu        // higher-level cache, and the snoop is invalidating, then our
2467720Sgblack@eecs.umich.edu        // buffered upgrades must be converted to read exclusives,
2477652Sminkyu.jeong@arm.com        // since the upper-level cache no longer has a valid copy.
2487652Sminkyu.jeong@arm.com        // That is, even though the upper-level cache got out on its
2497678Sgblack@eecs.umich.edu        // local bus first, some other invalidating transaction
2507678Sgblack@eecs.umich.edu        // reached the global bus before the upgrade did.
2517678Sgblack@eecs.umich.edu        if (pkt->needsExclusive()) {
2527678Sgblack@eecs.umich.edu            targets->replaceUpgrades();
2537362Sgblack@eecs.umich.edu            deferredTargets->replaceUpgrades();
2548518Sgeoffrey.blake@arm.com        }
2558518Sgeoffrey.blake@arm.com
2568518Sgeoffrey.blake@arm.com        return false;
2578806Sgblack@eecs.umich.edu    }
2588806Sgblack@eecs.umich.edu
2598806Sgblack@eecs.umich.edu    // From here on down, the request issued by this MSHR logically
2608806Sgblack@eecs.umich.edu    // precedes the request we're snooping.
2618806Sgblack@eecs.umich.edu
2628806Sgblack@eecs.umich.edu    if (pkt->needsExclusive()) {
2638806Sgblack@eecs.umich.edu        // snooped request still precedes the re-request we'll have to
2648806Sgblack@eecs.umich.edu        // issue for deferred targets, if any...
2658518Sgeoffrey.blake@arm.com        deferredTargets->replaceUpgrades();
2668518Sgeoffrey.blake@arm.com    }
2676735Sgblack@eecs.umich.edu
2686019Shines@cs.fsu.edu    if (pendingInvalidate) {
2696019Shines@cs.fsu.edu        // a prior snoop has already appended an invalidation, so
270        // logically we don't have the block anymore; no need for
271        // further snooping.
272        return true;
273    }
274
275    if (targets->needsExclusive || pkt->needsExclusive()) {
276        // actual target device (typ. PhysicalMemory) will delete the
277        // packet on reception, so we need to save a copy here
278        PacketPtr cp_pkt = new Packet(pkt, true);
279        targets->add(cp_pkt, curTick, _order, false);
280        ++ntargets;
281
282        if (targets->needsExclusive) {
283            // We're awaiting an exclusive copy, so ownership is pending.
284            // It's up to us to respond once the data arrives.
285            pkt->assertMemInhibit();
286            pkt->setSupplyExclusive();
287        } else {
288            // Someone else may respond before we get around to
289            // processing this snoop, which means the copied request
290            // pointer will no longer be valid
291            cp_pkt->req = NULL;
292        }
293
294        if (pkt->needsExclusive()) {
295            // This transaction will take away our pending copy
296            pendingInvalidate = true;
297        }
298    } else {
299        // Read to a read: no conflict, so no need to record as
300        // target, but make sure neither reader thinks he's getting an
301        // exclusive copy
302        pendingShared = true;
303        pkt->assertShared();
304    }
305
306    return true;
307}
308
309
310bool
311MSHR::promoteDeferredTargets()
312{
313    assert(targets->empty());
314    if (deferredTargets->empty()) {
315        return false;
316    }
317
318    // swap targets & deferredTargets lists
319    TargetList *tmp = targets;
320    targets = deferredTargets;
321    deferredTargets = tmp;
322
323    assert(targets->size() == ntargets);
324
325    // clear deferredTargets flags
326    deferredTargets->resetFlags();
327
328    pendingInvalidate = false;
329    pendingShared = false;
330    order = targets->front().order;
331    readyTime = std::max(curTick, targets->front().readyTime);
332
333    return true;
334}
335
336
337void
338MSHR::handleFill(Packet *pkt, CacheBlk *blk)
339{
340    if (pendingShared) {
341        // we snooped another read while this read was in
342        // service... assert shared line on its behalf
343        pkt->assertShared();
344    }
345
346    if (!pkt->sharedAsserted() && !pendingInvalidate
347        && deferredTargets->needsExclusive) {
348        // We got an exclusive response, but we have deferred targets
349        // which are waiting to request an exclusive copy (not because
350        // of a pending invalidate).  This can happen if the original
351        // request was for a read-only (non-exclusive) block, but we
352        // got an exclusive copy anyway because of the E part of the
353        // MOESI/MESI protocol.  Since we got the exclusive copy
354        // there's no need to defer the targets, so move them up to
355        // the regular target list.
356        assert(!targets->needsExclusive);
357        targets->needsExclusive = true;
358        // this clears out deferredTargets too
359        targets->splice(targets->end(), *deferredTargets);
360        deferredTargets->resetFlags();
361    }
362}
363
364
365bool
366MSHR::checkFunctional(PacketPtr pkt)
367{
368    // For printing, we treat the MSHR as a whole as single entity.
369    // For other requests, we iterate over the individual targets
370    // since that's where the actual data lies.
371    if (pkt->isPrint()) {
372        pkt->checkFunctional(this, addr, size, NULL);
373        return false;
374    } else {
375        return (targets->checkFunctional(pkt) ||
376                deferredTargets->checkFunctional(pkt));
377    }
378}
379
380
381void
382MSHR::print(std::ostream &os, int verbosity, const std::string &prefix) const
383{
384    ccprintf(os, "%s[%x:%x] %s %s %s state: %s %s %s %s\n",
385             prefix, addr, addr+size-1,
386             isCacheFill ? "Fill" : "",
387             needsExclusive() ? "Excl" : "",
388             _isUncacheable ? "Unc" : "",
389             inService ? "InSvc" : "",
390             downstreamPending ? "DwnPend" : "",
391             pendingInvalidate ? "PendInv" : "",
392             pendingShared ? "PendShared" : "");
393
394    ccprintf(os, "%s  Targets:\n", prefix);
395    targets->print(os, verbosity, prefix + "    ");
396    if (!deferredTargets->empty()) {
397        ccprintf(os, "%s  Deferred Targets:\n", prefix);
398        deferredTargets->print(os, verbosity, prefix + "      ");
399    }
400}
401
402MSHR::~MSHR()
403{
404}
405