mshr.cc revision 4908
1360SN/A/*
210850SGiacomo.Gabrielli@arm.com * Copyright (c) 2002-2005 The Regents of The University of Michigan
310796Sbrandon.potter@amd.com * All rights reserved.
410027SChris.Adeniyi-Jones@arm.com *
510027SChris.Adeniyi-Jones@arm.com * Redistribution and use in source and binary forms, with or without
610027SChris.Adeniyi-Jones@arm.com * modification, are permitted provided that the following conditions are
710027SChris.Adeniyi-Jones@arm.com * met: redistributions of source code must retain the above copyright
810027SChris.Adeniyi-Jones@arm.com * notice, this list of conditions and the following disclaimer;
910027SChris.Adeniyi-Jones@arm.com * redistributions in binary form must reproduce the above copyright
1010027SChris.Adeniyi-Jones@arm.com * notice, this list of conditions and the following disclaimer in the
1110027SChris.Adeniyi-Jones@arm.com * documentation and/or other materials provided with the distribution;
1210027SChris.Adeniyi-Jones@arm.com * neither the name of the copyright holders nor the names of its
1310027SChris.Adeniyi-Jones@arm.com * contributors may be used to endorse or promote products derived from
1410027SChris.Adeniyi-Jones@arm.com * this software without specific prior written permission.
151458SN/A *
16360SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17360SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18360SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19360SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20360SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21360SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22360SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23360SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24360SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25360SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26360SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27360SN/A *
28360SN/A * Authors: Erik Hallnor
29360SN/A *          Dave Greene
30360SN/A */
31360SN/A
32360SN/A/**
33360SN/A * @file
34360SN/A * Miss Status and Handling Register (MSHR) definitions.
35360SN/A */
36360SN/A
37360SN/A#include <assert.h>
38360SN/A#include <string>
39360SN/A#include <vector>
402665Ssaidi@eecs.umich.edu#include <algorithm>
412665Ssaidi@eecs.umich.edu
422665Ssaidi@eecs.umich.edu#include "mem/cache/miss/mshr.hh"
43360SN/A#include "sim/core.hh" // for curTick
44360SN/A#include "sim/host.hh"
451354SN/A#include "base/misc.hh"
461354SN/A#include "mem/cache/cache.hh"
47360SN/A
482764Sstever@eecs.umich.eduusing namespace std;
499202Spalle@lyckegaard.dk
509202Spalle@lyckegaard.dkMSHR::MSHR()
512064SN/A{
5211799Sbrandon.potter@amd.com    inService = false;
5311799Sbrandon.potter@amd.com    ntargets = 0;
5411799Sbrandon.potter@amd.com    threadNum = -1;
5511799Sbrandon.potter@amd.com    targets = new TargetList();
5611799Sbrandon.potter@amd.com    deferredTargets = new TargetList();
5711799Sbrandon.potter@amd.com}
58360SN/A
59360SN/A
60360SN/AMSHR::TargetList::TargetList()
61360SN/A    : needsExclusive(false), hasUpgrade(false)
62360SN/A{}
63360SN/A
641809SN/A
6511800Sbrandon.potter@amd.cominline void
6611392Sbrandon.potter@amd.comMSHR::TargetList::add(PacketPtr pkt, Tick readyTime,
671809SN/A                      Counter order, bool cpuSide)
6811392Sbrandon.potter@amd.com{
6911383Sbrandon.potter@amd.com    if (cpuSide) {
703113Sgblack@eecs.umich.edu        if (pkt->needsExclusive()) {
7111799Sbrandon.potter@amd.com            needsExclusive = true;
7211759Sbrandon.potter@amd.com        }
7311812Sbaz21@cam.ac.uk
7411812Sbaz21@cam.ac.uk        if (pkt->cmd == MemCmd::UpgradeReq) {
7511799Sbrandon.potter@amd.com            hasUpgrade = true;
768229Snate@binkert.org        }
778229Snate@binkert.org
7811594Santhony.gutierrez@amd.com        MSHR *mshr = dynamic_cast<MSHR*>(pkt->senderState);
797075Snate@binkert.org        if (mshr != NULL) {
808229Snate@binkert.org            assert(!mshr->downstreamPending);
8111856Sbrandon.potter@amd.com            mshr->downstreamPending = true;
827075Snate@binkert.org        }
83360SN/A    }
8411886Sbrandon.potter@amd.com
8511800Sbrandon.potter@amd.com    push_back(Target(pkt, readyTime, order, cpuSide));
8611392Sbrandon.potter@amd.com}
872462SN/A
881354SN/A
896216Snate@binkert.orgvoid
906658Snate@binkert.orgMSHR::TargetList::replaceUpgrades()
912474SN/A{
922680Sktlim@umich.edu    if (!hasUpgrade)
938229Snate@binkert.org        return;
9411886Sbrandon.potter@amd.com
9510496Ssteve.reinhardt@amd.com    Iterator end_i = end();
968229Snate@binkert.org    for (Iterator i = begin(); i != end_i; ++i) {
9711794Sbrandon.potter@amd.com        if (i->pkt->cmd == MemCmd::UpgradeReq) {
9811886Sbrandon.potter@amd.com            i->pkt->cmd = MemCmd::ReadExReq;
9910497Ssteve.reinhardt@amd.com            DPRINTF(Cache, "Replacing UpgradeReq with ReadExReq\n");
10011794Sbrandon.potter@amd.com        }
101360SN/A    }
102360SN/A
103360SN/A    hasUpgrade = false;
104360SN/A}
105360SN/A
106360SN/A
107360SN/Avoid
108360SN/AMSHR::TargetList::clearDownstreamPending()
109360SN/A{
110360SN/A    Iterator end_i = end();
111378SN/A    for (Iterator i = begin(); i != end_i; ++i) {
1121706SN/A        MSHR *mshr = dynamic_cast<MSHR*>(i->pkt->senderState);
11311851Sbrandon.potter@amd.com        if (mshr != NULL) {
114378SN/A            assert(mshr->downstreamPending);
115378SN/A            mshr->downstreamPending = false;
116378SN/A        }
117378SN/A    }
118378SN/A}
1191706SN/A
12011851Sbrandon.potter@amd.com
121360SN/Avoid
12211760Sbrandon.potter@amd.comMSHR::allocate(Addr _addr, int _size, PacketPtr target,
12311760Sbrandon.potter@amd.com               Tick whenReady, Counter _order)
12411851Sbrandon.potter@amd.com{
12511760Sbrandon.potter@amd.com    addr = _addr;
1266109Ssanchezd@stanford.edu    size = _size;
1271706SN/A    readyTime = whenReady;
12811851Sbrandon.potter@amd.com    order = _order;
129378SN/A    assert(target);
1306109Ssanchezd@stanford.edu    isCacheFill = false;
1316109Ssanchezd@stanford.edu    _isUncacheable = target->req->isUncacheable();
13211851Sbrandon.potter@amd.com    inService = false;
1336109Ssanchezd@stanford.edu    downstreamPending = false;
13411886Sbrandon.potter@amd.com    threadNum = 0;
13511886Sbrandon.potter@amd.com    ntargets = 1;
13611886Sbrandon.potter@amd.com    // Don't know of a case where we would allocate a new MSHR for a
13711886Sbrandon.potter@amd.com    // snoop (mem-side request), so set cpuSide to true here.
138378SN/A    assert(targets->isReset());
1391706SN/A    targets->add(target, whenReady, _order, true);
14011851Sbrandon.potter@amd.com    assert(deferredTargets->isReset());
141378SN/A    pendingInvalidate = false;
1425748SSteve.Reinhardt@amd.com    pendingShared = false;
1435748SSteve.Reinhardt@amd.com    data = NULL;
14411851Sbrandon.potter@amd.com}
145378SN/A
146378SN/A
1471706SN/Abool
14811851Sbrandon.potter@amd.comMSHR::markInService()
149378SN/A{
15011886Sbrandon.potter@amd.com    assert(!inService);
1511706SN/A    if (isSimpleForward()) {
15211851Sbrandon.potter@amd.com        // we just forwarded the request packet & don't expect a
153378SN/A        // response, so get rid of it
154378SN/A        assert(getNumTargets() == 1);
1551706SN/A        popTarget();
15611851Sbrandon.potter@amd.com        return true;
157378SN/A    }
158378SN/A    inService = true;
1591706SN/A    if (!downstreamPending) {
16011851Sbrandon.potter@amd.com        // let upstream caches know that the request has made it to a
161378SN/A        // level where it's going to get a response
1624118Sgblack@eecs.umich.edu        targets->clearDownstreamPending();
1634118Sgblack@eecs.umich.edu    }
16411851Sbrandon.potter@amd.com    return false;
1654118Sgblack@eecs.umich.edu}
166378SN/A
1671706SN/A
16811851Sbrandon.potter@amd.comvoid
169378SN/AMSHR::deallocate()
170378SN/A{
1711706SN/A    assert(targets->empty());
17211851Sbrandon.potter@amd.com    targets->resetFlags();
173360SN/A    assert(deferredTargets->isReset());
1745513SMichael.Adler@intel.com    assert(ntargets == 0);
1755513SMichael.Adler@intel.com    inService = false;
17611851Sbrandon.potter@amd.com    //allocIter = NULL;
1775513SMichael.Adler@intel.com    //readyIter = NULL;
17810203SAli.Saidi@ARM.com}
17910203SAli.Saidi@ARM.com
18011851Sbrandon.potter@amd.com/*
18110203SAli.Saidi@ARM.com * Adds a target to an MSHR
1825513SMichael.Adler@intel.com */
18311851Sbrandon.potter@amd.comvoid
1845513SMichael.Adler@intel.comMSHR::allocateTarget(PacketPtr pkt, Tick whenReady, Counter _order)
185511SN/A{
18610633Smichaelupton@gmail.com    // if there's a request already in service for this MSHR, we will
18711851Sbrandon.potter@amd.com    // have to defer the new target until after the response if any of
18810633Smichaelupton@gmail.com    // the following are true:
1891706SN/A    // - there are other targets already deferred
19011851Sbrandon.potter@amd.com    // - there's a pending invalidate to be applied after the response
191511SN/A    //   comes back (but before this target is processed)
1925513SMichael.Adler@intel.com    // - the outstanding request is for a non-exclusive block and this
1935513SMichael.Adler@intel.com    //   target requires an exclusive block
19411851Sbrandon.potter@amd.com    if (inService &&
1955513SMichael.Adler@intel.com        (!deferredTargets->empty() || pendingInvalidate ||
196511SN/A         (!targets->needsExclusive && pkt->needsExclusive()))) {
1971706SN/A        // need to put on deferred list
19811851Sbrandon.potter@amd.com        deferredTargets->add(pkt, whenReady, _order, true);
1991706SN/A    } else {
2001706SN/A        // no request outstanding, or still OK to append to
2011706SN/A        // outstanding request
2021706SN/A        targets->add(pkt, whenReady, _order, true);
20311851Sbrandon.potter@amd.com    }
2041706SN/A
2051706SN/A    ++ntargets;
2061706SN/A}
2071706SN/A
20811851Sbrandon.potter@amd.combool
2091706SN/AMSHR::handleSnoop(PacketPtr pkt, Counter _order)
210511SN/A{
2116703Svince@csl.cornell.edu    if (!inService || downstreamPending) {
2126703Svince@csl.cornell.edu        // Request has not been issued yet, or it's been issued
21311851Sbrandon.potter@amd.com        // locally but is buffered unissued at some downstream cache
2146703Svince@csl.cornell.edu        // which is forwarding us this snoop.  Either way, the packet
2156685Stjones1@inf.ed.ac.uk        // we're snooping logically precedes this MSHR's request, so
2166685Stjones1@inf.ed.ac.uk        // the snoop has no impact on the MSHR, but must be processed
21711851Sbrandon.potter@amd.com        // in the standard way by the cache.  The only exception is
2186685Stjones1@inf.ed.ac.uk        // that if we're an L2+ cache buffering an UpgradeReq from a
2196685Stjones1@inf.ed.ac.uk        // higher-level cache, and the snoop is invalidating, then our
2205513SMichael.Adler@intel.com        // buffered upgrades must be converted to read exclusives,
2215513SMichael.Adler@intel.com        // since the upper-level cache no longer has a valid copy.
22211851Sbrandon.potter@amd.com        // That is, even though the upper-level cache got out on its
2235513SMichael.Adler@intel.com        // local bus first, some other invalidating transaction
22411885Sbrandon.potter@amd.com        // reached the global bus before the upgrade did.
22511885Sbrandon.potter@amd.com        if (pkt->needsExclusive()) {
22611885Sbrandon.potter@amd.com            targets->replaceUpgrades();
2275513SMichael.Adler@intel.com            deferredTargets->replaceUpgrades();
2281999SN/A        }
2291999SN/A
23011851Sbrandon.potter@amd.com        return false;
2311999SN/A    }
23211885Sbrandon.potter@amd.com
23311885Sbrandon.potter@amd.com    // From here on down, the request issued by this MSHR logically
23411885Sbrandon.potter@amd.com    // precedes the request we're snooping.
2351999SN/A
2361999SN/A    if (pkt->needsExclusive()) {
2371999SN/A        // snooped request still precedes the re-request we'll have to
23811851Sbrandon.potter@amd.com        // issue for deferred targets, if any...
2391999SN/A        deferredTargets->replaceUpgrades();
2403079Sstever@eecs.umich.edu    }
2413079Sstever@eecs.umich.edu
24211851Sbrandon.potter@amd.com    if (pendingInvalidate) {
2433079Sstever@eecs.umich.edu        // a prior snoop has already appended an invalidation, so
24411908SBrandon.Potter@amd.com        // logically we don't have the block anymore; no need for
24511908SBrandon.Potter@amd.com        // further snooping.
24611908SBrandon.Potter@amd.com        return true;
24711908SBrandon.Potter@amd.com    }
24811875Sbrandon.potter@amd.com
2492093SN/A    if (targets->needsExclusive || pkt->needsExclusive()) {
25011851Sbrandon.potter@amd.com        // actual target device (typ. PhysicalMemory) will delete the
2512093SN/A        // packet on reception, so we need to save a copy here
2522687Sksewell@umich.edu        targets->add(new Packet(pkt), curTick, _order, false);
2532687Sksewell@umich.edu        ++ntargets;
25411851Sbrandon.potter@amd.com
2552687Sksewell@umich.edu        if (targets->needsExclusive) {
2562238SN/A            // We're awaiting an exclusive copy, so ownership is pending.
2572238SN/A            // It's up to us to respond once the data arrives.
25811851Sbrandon.potter@amd.com            pkt->assertMemInhibit();
2592238SN/A        }
26011908SBrandon.Potter@amd.com
26111908SBrandon.Potter@amd.com        if (pkt->needsExclusive()) {
26211908SBrandon.Potter@amd.com            // This transaction will take away our pending copy
26311908SBrandon.Potter@amd.com            pendingInvalidate = true;
26411908SBrandon.Potter@amd.com        }
26511908SBrandon.Potter@amd.com    } else {
26611908SBrandon.Potter@amd.com        // Read to a read: no conflict, so no need to record as
26711908SBrandon.Potter@amd.com        // target, but make sure neither reader thinks he's getting an
2682238SN/A        // exclusive copy
2692238SN/A        pendingShared = true;
27011851Sbrandon.potter@amd.com        pkt->assertShared();
2712238SN/A    }
2722238SN/A
2732238SN/A    return true;
27411851Sbrandon.potter@amd.com}
2752238SN/A
2762238SN/A
2772238SN/Abool
27811851Sbrandon.potter@amd.comMSHR::promoteDeferredTargets()
2792238SN/A{
2802238SN/A    assert(targets->empty());
2812238SN/A    if (deferredTargets->empty()) {
28211851Sbrandon.potter@amd.com        return false;
2832238SN/A    }
2842238SN/A
2852238SN/A    // swap targets & deferredTargets lists
28611851Sbrandon.potter@amd.com    TargetList *tmp = targets;
2872238SN/A    targets = deferredTargets;
2882238SN/A    deferredTargets = tmp;
2892238SN/A
29011851Sbrandon.potter@amd.com    assert(targets->size() == ntargets);
2912238SN/A
2929455Smitch.hayenga+gem5@gmail.com    // clear deferredTargets flags
2939455Smitch.hayenga+gem5@gmail.com    deferredTargets->resetFlags();
29411851Sbrandon.potter@amd.com
29510203SAli.Saidi@ARM.com    pendingInvalidate = false;
29611851Sbrandon.potter@amd.com    pendingShared = false;
29711851Sbrandon.potter@amd.com    order = targets->front().order;
2989455Smitch.hayenga+gem5@gmail.com    readyTime = std::max(curTick, targets->front().readyTime);
2999112Smarc.orr@gmail.com
30011906SBrandon.Potter@amd.com    return true;
30111906SBrandon.Potter@amd.com}
3029112Smarc.orr@gmail.com
3039112Smarc.orr@gmail.com
30411851Sbrandon.potter@amd.comvoid
3059112Smarc.orr@gmail.comMSHR::handleFill(Packet *pkt, CacheBlk *blk)
3069112Smarc.orr@gmail.com{
3079112Smarc.orr@gmail.com    if (pendingShared) {
3089112Smarc.orr@gmail.com        // we snooped another read while this read was in
3099112Smarc.orr@gmail.com        // service... assert shared line on its behalf
3109112Smarc.orr@gmail.com        pkt->assertShared();
3119112Smarc.orr@gmail.com    }
3129112Smarc.orr@gmail.com}
3139112Smarc.orr@gmail.com
3149112Smarc.orr@gmail.com
3159112Smarc.orr@gmail.comvoid
3169112Smarc.orr@gmail.comMSHR::dump()
3179112Smarc.orr@gmail.com{
3189112Smarc.orr@gmail.com    ccprintf(cerr,
3199112Smarc.orr@gmail.com             "inService: %d thread: %d\n"
32011886Sbrandon.potter@amd.com             "Addr: %x ntargets %d\n"
3219112Smarc.orr@gmail.com             "Targets:\n",
3229112Smarc.orr@gmail.com             inService, threadNum, addr, ntargets);
3239238Slluc.alvarez@bsc.es#if 0
3249112Smarc.orr@gmail.com    TargetListIterator tar_it = targets->begin();
3259112Smarc.orr@gmail.com    for (int i = 0; i < ntargets; i++) {
3269112Smarc.orr@gmail.com        assert(tar_it != targets->end());
32711886Sbrandon.potter@amd.com
3289112Smarc.orr@gmail.com        ccprintf(cerr, "\t%d: Addr: %x cmd: %s\n",
3299112Smarc.orr@gmail.com                 i, tar_it->pkt->getAddr(), tar_it->pkt->cmdString());
3309112Smarc.orr@gmail.com
3319112Smarc.orr@gmail.com        tar_it++;
3329112Smarc.orr@gmail.com    }
3339112Smarc.orr@gmail.com#endif
33411367Sandreas.hansson@arm.com    ccprintf(cerr, "\n");
3359112Smarc.orr@gmail.com}
33611321Ssteve.reinhardt@amd.com
33711886Sbrandon.potter@amd.comMSHR::~MSHR()
3389112Smarc.orr@gmail.com{
3399112Smarc.orr@gmail.com}
3409112Smarc.orr@gmail.com