mshr.cc revision 4670
19243SN/A/*
210206Sandreas.hansson@arm.com * Copyright (c) 2002-2005 The Regents of The University of Michigan
39243SN/A * All rights reserved.
49243SN/A *
59243SN/A * Redistribution and use in source and binary forms, with or without
69243SN/A * modification, are permitted provided that the following conditions are
79243SN/A * met: redistributions of source code must retain the above copyright
89243SN/A * notice, this list of conditions and the following disclaimer;
99243SN/A * redistributions in binary form must reproduce the above copyright
109243SN/A * notice, this list of conditions and the following disclaimer in the
119243SN/A * documentation and/or other materials provided with the distribution;
129243SN/A * neither the name of the copyright holders nor the names of its
139243SN/A * contributors may be used to endorse or promote products derived from
149831SN/A * this software without specific prior written permission.
159831SN/A *
169831SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
179243SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
189243SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
199243SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
209243SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
219243SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
229243SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
239243SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
249243SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
259243SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
269243SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
279243SN/A *
289243SN/A * Authors: Erik Hallnor
299243SN/A *          Dave Greene
309243SN/A */
319243SN/A
329243SN/A/**
339243SN/A * @file
349243SN/A * Miss Status and Handling Register (MSHR) definitions.
359243SN/A */
369243SN/A
379243SN/A#include <assert.h>
389243SN/A#include <string>
399243SN/A#include <vector>
409243SN/A#include <algorithm>
419243SN/A
429967SN/A#include "mem/cache/miss/mshr.hh"
439243SN/A#include "sim/core.hh" // for curTick
449243SN/A#include "sim/host.hh"
459243SN/A#include "base/misc.hh"
469243SN/A#include "mem/cache/cache.hh"
4710146Sandreas.hansson@arm.com
489243SN/Ausing namespace std;
499243SN/A
5010146Sandreas.hansson@arm.comMSHR::MSHR()
5110146Sandreas.hansson@arm.com{
529243SN/A    inService = false;
539488SN/A    ntargets = 0;
549488SN/A    threadNum = -1;
559243SN/A}
569243SN/A
579243SN/Avoid
589243SN/AMSHR::allocate(Addr _addr, int _size, PacketPtr target,
599243SN/A               Tick when, Counter _order)
609243SN/A{
6110146Sandreas.hansson@arm.com    addr = _addr;
629243SN/A    size = _size;
639243SN/A    readyTick = when;
649243SN/A    order = _order;
6510146Sandreas.hansson@arm.com    assert(target);
6610146Sandreas.hansson@arm.com    isCacheFill = false;
6710146Sandreas.hansson@arm.com    needsExclusive = target->needsExclusive();
689243SN/A    _isUncacheable = target->req->isUncacheable();
699243SN/A    inService = false;
709243SN/A    threadNum = 0;
719243SN/A    ntargets = 1;
729243SN/A    // Don't know of a case where we would allocate a new MSHR for a
739243SN/A    // snoop (mem-side request), so set cpuSide to true here.
749243SN/A    targets.push_back(Target(target, when, _order, true));
759243SN/A    assert(deferredTargets.empty());
769243SN/A    deferredNeedsExclusive = false;
779243SN/A    pendingInvalidate = false;
789243SN/A    pendingShared = false;
799243SN/A    replacedPendingUpgrade = false;
809243SN/A    data = NULL;
819243SN/A}
829243SN/A
8310146Sandreas.hansson@arm.comvoid
849243SN/AMSHR::deallocate()
859243SN/A{
869243SN/A    assert(targets.empty());
879243SN/A    assert(deferredTargets.empty());
889243SN/A    assert(ntargets == 0);
899243SN/A    inService = false;
909243SN/A    //allocIter = NULL;
919243SN/A    //readyIter = NULL;
929243SN/A}
939243SN/A
9410146Sandreas.hansson@arm.com/*
959243SN/A * Adds a target to an MSHR
969243SN/A */
979243SN/Avoid
9810146Sandreas.hansson@arm.comMSHR::allocateTarget(PacketPtr target, Tick when, Counter _order)
999243SN/A{
1009243SN/A    if (inService) {
1019243SN/A        if (!deferredTargets.empty() || pendingInvalidate ||
1029243SN/A            (!needsExclusive && target->needsExclusive())) {
1039243SN/A            // need to put on deferred list
1049243SN/A            deferredTargets.push_back(Target(target, when, _order, true));
1059243SN/A            if (target->needsExclusive()) {
1069243SN/A                deferredNeedsExclusive = true;
1079243SN/A            }
1089243SN/A        } else {
1099243SN/A            // still OK to append to outstanding request
1109243SN/A            targets.push_back(Target(target, when, _order, true));
1119243SN/A        }
1129243SN/A    } else {
1139243SN/A        if (target->needsExclusive()) {
1149243SN/A            needsExclusive = true;
1159243SN/A        }
1169243SN/A
1179243SN/A        targets.push_back(Target(target, when, _order, true));
1189243SN/A    }
1199243SN/A
1209243SN/A    ++ntargets;
1219243SN/A}
1229243SN/A
1239243SN/Avoid
1249243SN/AMSHR::allocateSnoopTarget(PacketPtr pkt, Tick when, Counter _order)
1259243SN/A{
1269243SN/A    assert(inService); // don't bother to call otherwise
1279243SN/A
1289243SN/A    if (pendingInvalidate) {
1299243SN/A        // a prior snoop has already appended an invalidation, so
13010206Sandreas.hansson@arm.com        // logically we don't have the block anymore...
13110206Sandreas.hansson@arm.com        return;
1329243SN/A    }
13310206Sandreas.hansson@arm.com
13410206Sandreas.hansson@arm.com    DPRINTF(Cache, "deferred snoop on %x: %s %s\n", addr,
13510206Sandreas.hansson@arm.com            needsExclusive ? "needsExclusive" : "",
13610206Sandreas.hansson@arm.com            pkt->needsExclusive() ? "pkt->needsExclusive()" : "");
13710206Sandreas.hansson@arm.com
13810206Sandreas.hansson@arm.com    if (needsExclusive || pkt->needsExclusive()) {
13910206Sandreas.hansson@arm.com        // actual target device (typ. PhysicalMemory) will delete the
14010206Sandreas.hansson@arm.com        // packet on reception, so we need to save a copy here
1419243SN/A        targets.push_back(Target(new Packet(pkt), when, _order, false));
1429488SN/A        ++ntargets;
1439969SN/A
1449488SN/A        if (needsExclusive) {
1459243SN/A            // We're awaiting an exclusive copy, so ownership is pending.
1469727SN/A            // It's up to us to respond once the data arrives.
1479727SN/A            pkt->assertMemInhibit();
1489727SN/A        }
1499727SN/A
1509243SN/A        if (pkt->needsExclusive()) {
1519243SN/A            // This transaction will take away our pending copy
1529243SN/A            pendingInvalidate = true;
1539243SN/A        }
1549243SN/A    } else {
1559243SN/A        // Read to a read: no conflict, so no need to record as
1569243SN/A        // target, but make sure neither reader thinks he's getting an
1579243SN/A        // exclusive copy
1589243SN/A        pendingShared = true;
1599243SN/A        pkt->assertShared();
1609243SN/A    }
1619243SN/A}
1629969SN/A
1639243SN/A
16410141SN/Abool
1659727SN/AMSHR::promoteDeferredTargets()
1669727SN/A{
1679727SN/A    if (deferredTargets.empty()) {
1689969SN/A        return false;
16910141SN/A    }
1709243SN/A
1719243SN/A    assert(targets.empty());
1729243SN/A    targets = deferredTargets;
1739243SN/A    deferredTargets.clear();
1749831SN/A    assert(targets.size() == ntargets);
1759831SN/A
1769831SN/A    needsExclusive = deferredNeedsExclusive;
1779831SN/A    pendingInvalidate = false;
1789831SN/A    pendingShared = false;
1799831SN/A    deferredNeedsExclusive = false;
1809831SN/A    order = targets.front().order;
1819831SN/A    readyTick = std::max(curTick, targets.front().time);
1829831SN/A
1839831SN/A    return true;
1849831SN/A}
1859831SN/A
1869831SN/A
1879831SN/Avoid
1889831SN/AMSHR::handleReplacement(CacheBlk *blk, int blkSize)
1899831SN/A{
1909831SN/A    // must be an outstanding upgrade request on block we're about to
1919831SN/A    // replace...
1929831SN/A    assert(!blk->isWritable());
1939831SN/A    assert(needsExclusive);
1949831SN/A    replacedPendingUpgrade = true;
1959243SN/A
1969243SN/A    // if it's dirty, just remember what happened and allow the
1979243SN/A    // writeback to continue.  we'll reissue a ReadEx later whether
1989243SN/A    // the upgrade succeeds or not
1999243SN/A    if (blk->isDirty()) {
2009243SN/A        replacedPendingUpgradeDirty = true;
2019243SN/A        return;
2029243SN/A    }
2039243SN/A
2049243SN/A    // if not dirty, we need to save it off as it will be only valid
2059243SN/A    // copy in system if upgrade is successful (and may need to be
2069243SN/A    // written back then, as the current owner if any will be
2079243SN/A    // invalidating its block)
2089243SN/A    replacedPendingUpgradeDirty = false;
2099243SN/A    data = new uint8_t[blkSize];
2109243SN/A    std::memcpy(data, blk->data, blkSize);
2119966SN/A}
2129966SN/A
2139243SN/A
2149243SN/Abool
2159967SN/AMSHR::handleFill(Packet *pkt, CacheBlk *blk)
2169243SN/A{
2179831SN/A    if (replacedPendingUpgrade) {
2189831SN/A        // block was replaced while upgrade request was in service
2199967SN/A        assert(pkt->cmd == MemCmd::UpgradeResp);
2209967SN/A        assert(blk == NULL);
2219967SN/A        assert(replacedPendingUpgrade);
2229967SN/A        replacedPendingUpgrade = false; // reset
2239967SN/A        if (replacedPendingUpgradeDirty) {
2249967SN/A            // we wrote back the previous copy; just reissue as a ReadEx
2259967SN/A            return false;
2269831SN/A        }
2279831SN/A
2289831SN/A        // previous copy was not dirty, but we are now owner...  fake out
2299831SN/A        // cache by taking saved data and converting UpgradeResp to
2309831SN/A        // ReadExResp
2319832SN/A        assert(data);
2329831SN/A        pkt->cmd = MemCmd::ReadExResp;
2339831SN/A        pkt->setData(data);
2349831SN/A        delete [] data;
2359831SN/A        data = NULL;
2369831SN/A    } else if (pendingShared) {
2379832SN/A        // we snooped another read while this read was in
2389831SN/A        // service... assert shared line on its behalf
2399831SN/A        pkt->assertShared();
2409831SN/A    }
2419831SN/A
2429831SN/A    return true;
2439831SN/A}
2449967SN/A
2459243SN/A
2469967SN/Avoid
2479967SN/AMSHR::dump()
2489967SN/A{
2499243SN/A    ccprintf(cerr,
2509967SN/A             "inService: %d thread: %d\n"
2519967SN/A             "Addr: %x ntargets %d\n"
2529967SN/A             "Targets:\n",
2539243SN/A             inService, threadNum, addr, ntargets);
2549243SN/A
2559243SN/A    TargetListIterator tar_it = targets.begin();
2569243SN/A    for (int i = 0; i < ntargets; i++) {
2579243SN/A        assert(tar_it != targets.end());
2589243SN/A
25910206Sandreas.hansson@arm.com        ccprintf(cerr, "\t%d: Addr: %x cmd: %s\n",
26010206Sandreas.hansson@arm.com                 i, tar_it->pkt->getAddr(), tar_it->pkt->cmdString());
2619243SN/A
2629243SN/A        tar_it++;
2639243SN/A    }
26410146Sandreas.hansson@arm.com    ccprintf(cerr, "\n");
2659243SN/A}
2669243SN/A
26710146Sandreas.hansson@arm.comMSHR::~MSHR()
2689243SN/A{
2699243SN/A}
27010146Sandreas.hansson@arm.com