mshr.cc
来自「M5,一个功能强大的多处理器系统模拟器.很多针对处理器架构,性能的研究都使用它作」· CC 代码 · 共 425 行
CC
425 行
/* * Copyright (c) 2002, 2003, 2004, 2005 * The Regents of The University of Michigan * All Rights Reserved * * This code is part of the M5 simulator. * * Permission is granted to use, copy, create derivative works and * redistribute this software and such derivative works for any * purpose, so long as the copyright notice above, this grant of * permission, and the disclaimer below appear in all copies made; and * so long as the name of The University of Michigan is not used in * any advertising or publicity pertaining to the use or distribution * of this software without specific, written prior authorization. * * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION FROM THE * UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY PURPOSE, AND * WITHOUT WARRANTY BY THE UNIVERSITY OF MICHIGAN OF ANY KIND, EITHER * EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE. THE REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE * LIABLE FOR ANY DAMAGES, INCLUDING DIRECT, SPECIAL, INDIRECT, * INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM * ARISING OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF SUCH * DAMAGES. * * Authors: Erik G. Hallnor * David A. Greene *//** * @file * Miss Status and Handling Register (MSHR) definitions. */#include <assert.h>#include <string>#include <vector>#include <algorithm>#include "mem/cache/mshr.hh"#include "sim/core.hh" // for curTick#include "sim/host.hh"#include "base/misc.hh"#include "mem/cache/cache.hh"using namespace std;MSHR::MSHR(){ inService = false; ntargets = 0; threadNum = -1; targets = new TargetList(); deferredTargets = new TargetList();}MSHR::TargetList::TargetList() : needsExclusive(false), hasUpgrade(false){}inline voidMSHR::TargetList::add(PacketPtr pkt, Tick readyTime, Counter order, bool cpuSide, bool markPending){ if (cpuSide) { if (pkt->needsExclusive()) { needsExclusive = true; } if (pkt->cmd == MemCmd::UpgradeReq) { hasUpgrade = true; } } if (markPending) { MSHR *mshr = dynamic_cast<MSHR*>(pkt->senderState); if (mshr != NULL) { assert(!mshr->downstreamPending); mshr->downstreamPending = true; } } push_back(Target(pkt, readyTime, order, cpuSide, markPending));}voidMSHR::TargetList::replaceUpgrades(){ if (!hasUpgrade) return; Iterator end_i = end(); for (Iterator i = begin(); i != end_i; ++i) { if (i->pkt->cmd == MemCmd::UpgradeReq) { i->pkt->cmd = MemCmd::ReadExReq; DPRINTF(Cache, "Replacing UpgradeReq with ReadExReq\n"); } } hasUpgrade = false;}voidMSHR::TargetList::clearDownstreamPending(){ Iterator end_i = end(); for (Iterator i = begin(); i != end_i; ++i) { if (i->markedPending) { MSHR *mshr = dynamic_cast<MSHR*>(i->pkt->senderState); if (mshr != NULL) { mshr->clearDownstreamPending(); } } }}boolMSHR::TargetList::checkFunctional(PacketPtr pkt){ Iterator end_i = end(); for (Iterator i = begin(); i != end_i; ++i) { if (pkt->checkFunctional(i->pkt)) { return true; } } return false;}voidMSHR::TargetList::print(std::ostream &os, int verbosity, const std::string &prefix) const{ ConstIterator end_i = end(); for (ConstIterator i = begin(); i != end_i; ++i) { ccprintf(os, "%s%s: ", prefix, i->isCpuSide() ? "cpu" : "mem"); i->pkt->print(os, verbosity, ""); }}voidMSHR::allocate(Addr _addr, int _size, PacketPtr target, Tick whenReady, Counter _order){ addr = _addr; size = _size; readyTime = whenReady; order = _order; assert(target); isCacheFill = false; _isUncacheable = target->req->isUncacheable(); inService = false; downstreamPending = false; threadNum = 0; ntargets = 1; // Don't know of a case where we would allocate a new MSHR for a // snoop (mem-side request), so set cpuSide to true here. assert(targets->isReset()); targets->add(target, whenReady, _order, true, true); assert(deferredTargets->isReset()); pendingInvalidate = false; pendingShared = false; data = NULL;}voidMSHR::clearDownstreamPending(){ assert(downstreamPending); downstreamPending = false; // recursively clear flag on any MSHRs we will be forwarding // responses to targets->clearDownstreamPending();}boolMSHR::markInService(){ assert(!inService); if (isSimpleForward()) { // we just forwarded the request packet & don't expect a // response, so get rid of it assert(getNumTargets() == 1); popTarget(); return true; } inService = true; if (!downstreamPending) { // let upstream caches know that the request has made it to a // level where it's going to get a response targets->clearDownstreamPending(); } return false;}voidMSHR::deallocate(){ assert(targets->empty()); targets->resetFlags(); assert(deferredTargets->isReset()); assert(ntargets == 0); inService = false; //allocIter = NULL; //readyIter = NULL;}/* * Adds a target to an MSHR */voidMSHR::allocateTarget(PacketPtr pkt, Tick whenReady, Counter _order){ // if there's a request already in service for this MSHR, we will // have to defer the new target until after the response if any of // the following are true: // - there are other targets already deferred // - there's a pending invalidate to be applied after the response // comes back (but before this target is processed) // - the outstanding request is for a non-exclusive block and this // target requires an exclusive block if (inService && (!deferredTargets->empty() || pendingInvalidate || (!targets->needsExclusive && pkt->needsExclusive()))) { // need to put on deferred list deferredTargets->add(pkt, whenReady, _order, true, true); } else { // No request outstanding, or still OK to append to // outstanding request: append to regular target list. Only // mark pending if current request hasn't been issued yet // (isn't in service). targets->add(pkt, whenReady, _order, true, !inService); } ++ntargets;}boolMSHR::handleSnoop(PacketPtr pkt, Counter _order){ if (!inService || (pkt->isExpressSnoop() && downstreamPending)) { // Request has not been issued yet, or it's been issued // locally but is buffered unissued at some downstream cache // which is forwarding us this snoop. Either way, the packet // we're snooping logically precedes this MSHR's request, so // the snoop has no impact on the MSHR, but must be processed // in the standard way by the cache. The only exception is // that if we're an L2+ cache buffering an UpgradeReq from a // higher-level cache, and the snoop is invalidating, then our // buffered upgrades must be converted to read exclusives, // since the upper-level cache no longer has a valid copy. // That is, even though the upper-level cache got out on its // local bus first, some other invalidating transaction // reached the global bus before the upgrade did. if (pkt->needsExclusive()) { targets->replaceUpgrades(); deferredTargets->replaceUpgrades(); } return false; } // From here on down, the request issued by this MSHR logically // precedes the request we're snooping. if (pkt->needsExclusive()) { // snooped request still precedes the re-request we'll have to // issue for deferred targets, if any... deferredTargets->replaceUpgrades(); } if (pendingInvalidate) { // a prior snoop has already appended an invalidation, so // logically we don't have the block anymore; no need for // further snooping. return true; } if (targets->needsExclusive || pkt->needsExclusive()) { // actual target device (typ. PhysicalMemory) will delete the // packet on reception, so we need to save a copy here PacketPtr cp_pkt = new Packet(pkt, true); targets->add(cp_pkt, curTick, _order, false, downstreamPending && targets->needsExclusive); ++ntargets; if (targets->needsExclusive) { // We're awaiting an exclusive copy, so ownership is pending. // It's up to us to respond once the data arrives. pkt->assertMemInhibit(); pkt->setSupplyExclusive(); } else { // Someone else may respond before we get around to // processing this snoop, which means the copied request // pointer will no longer be valid cp_pkt->req = NULL; } if (pkt->needsExclusive()) { // This transaction will take away our pending copy pendingInvalidate = true; } } else { // Read to a read: no conflict, so no need to record as // target, but make sure neither reader thinks he's getting an // exclusive copy pendingShared = true; pkt->assertShared(); } return true;}boolMSHR::promoteDeferredTargets(){ assert(targets->empty()); if (deferredTargets->empty()) { return false; } // swap targets & deferredTargets lists TargetList *tmp = targets; targets = deferredTargets; deferredTargets = tmp; assert(targets->size() == ntargets); // clear deferredTargets flags deferredTargets->resetFlags(); pendingInvalidate = false; pendingShared = false; order = targets->front().order; readyTime = std::max(curTick, targets->front().readyTime); return true;}voidMSHR::handleFill(Packet *pkt, CacheBlk *blk){ if (pendingShared) { // we snooped another read while this read was in // service... assert shared line on its behalf pkt->assertShared(); } if (!pkt->sharedAsserted() && !pendingInvalidate && deferredTargets->needsExclusive) { // We got an exclusive response, but we have deferred targets // which are waiting to request an exclusive copy (not because // of a pending invalidate). This can happen if the original // request was for a read-only (non-exclusive) block, but we // got an exclusive copy anyway because of the E part of the // MOESI/MESI protocol. Since we got the exclusive copy // there's no need to defer the targets, so move them up to // the regular target list. assert(!targets->needsExclusive); targets->needsExclusive = true; // if any of the deferred targets were upper-level cache // requests marked downstreamPending, need to clear that assert(!downstreamPending); // not pending here anymore deferredTargets->clearDownstreamPending(); // this clears out deferredTargets too targets->splice(targets->end(), *deferredTargets); deferredTargets->resetFlags(); }}boolMSHR::checkFunctional(PacketPtr pkt){ // For printing, we treat the MSHR as a whole as single entity. // For other requests, we iterate over the individual targets // since that's where the actual data lies. if (pkt->isPrint()) { pkt->checkFunctional(this, addr, size, NULL); return false; } else { return (targets->checkFunctional(pkt) || deferredTargets->checkFunctional(pkt)); }}voidMSHR::print(std::ostream &os, int verbosity, const std::string &prefix) const{ ccprintf(os, "%s[%x:%x] %s %s %s state: %s %s %s %s\n", prefix, addr, addr+size-1, isCacheFill ? "Fill" : "", needsExclusive() ? "Excl" : "", _isUncacheable ? "Unc" : "", inService ? "InSvc" : "", downstreamPending ? "DwnPend" : "", pendingInvalidate ? "PendInv" : "", pendingShared ? "PendShared" : ""); ccprintf(os, "%s Targets:\n", prefix); targets->print(os, verbosity, prefix + " "); if (!deferredTargets->empty()) { ccprintf(os, "%s Deferred Targets:\n", prefix); deferredTargets->print(os, verbosity, prefix + " "); }}MSHR::~MSHR(){}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?