/*
* Copyright (c) 2002-2005 The Regents of The University of Michigan
+ * Copyright (c) 2010 Advanced Micro Devices, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
#include "base/misc.hh"
#include "base/types.hh"
+#include "debug/Cache.hh"
#include "mem/cache/cache.hh"
#include "mem/cache/mshr.hh"
#include "sim/core.hh"
needsExclusive = true;
}
- if (pkt->cmd == MemCmd::UpgradeReq) {
+ // StoreCondReq is effectively an upgrade if it's in an MSHR
+ // since it would have been failed already if we didn't have a
+ // read-only copy
+ if (pkt->isUpgrade() || pkt->cmd == MemCmd::StoreCondReq) {
hasUpgrade = true;
}
}
}
+static void
+replaceUpgrade(PacketPtr pkt)
+{
+ if (pkt->cmd == MemCmd::UpgradeReq) {
+ pkt->cmd = MemCmd::ReadExReq;
+ DPRINTF(Cache, "Replacing UpgradeReq with ReadExReq\n");
+ } else if (pkt->cmd == MemCmd::SCUpgradeReq) {
+ pkt->cmd = MemCmd::SCUpgradeFailReq;
+ DPRINTF(Cache, "Replacing SCUpgradeReq with SCUpgradeFailReq\n");
+ } else if (pkt->cmd == MemCmd::StoreCondReq) {
+ pkt->cmd = MemCmd::StoreCondFailReq;
+ DPRINTF(Cache, "Replacing StoreCondReq with StoreCondFailReq\n");
+ }
+}
+
+
void
MSHR::TargetList::replaceUpgrades()
{
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");
- }
+ replaceUpgrade(i->pkt);
}
hasUpgrade = false;
for (ConstIterator i = begin(); i != end_i; ++i) {
const char *s;
switch (i->source) {
- case Target::FromCPU: s = "FromCPU";
- case Target::FromSnoop: s = "FromSnoop";
- case Target::FromPrefetcher: s = "FromPrefetcher";
- default: s = "";
+ case Target::FromCPU:
+ s = "FromCPU";
+ break;
+ case Target::FromSnoop:
+ s = "FromSnoop";
+ break;
+ case Target::FromPrefetcher:
+ s = "FromPrefetcher";
+ break;
+ default:
+ s = "";
+ break;
}
ccprintf(os, "%s%s: ", prefix, s);
i->pkt->print(os, verbosity, "");
Target::FromPrefetcher : Target::FromCPU;
targets->add(target, whenReady, _order, source, true);
assert(deferredTargets->isReset());
- pendingInvalidate = false;
- pendingShared = false;
data = NULL;
}
}
bool
-MSHR::markInService()
+MSHR::markInService(PacketPtr pkt)
{
assert(!inService);
if (isForwardNoResponse()) {
return true;
}
inService = true;
+ pendingDirty = (targets->needsExclusive ||
+ (!pkt->sharedAsserted() && pkt->memInhibitAsserted()));
+ postInvalidate = postDowngrade = false;
+
if (!downstreamPending) {
// let upstream caches know that the request has made it to a
// level where it's going to get a response
assert(deferredTargets->isReset());
assert(ntargets == 0);
inService = false;
- //allocIter = NULL;
- //readyIter = NULL;
}
/*
// - 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
+ // - this target requires an exclusive block and either we're not
+ // getting an exclusive block back or we have already snooped
+ // another read request that will downgrade our exclusive block
+ // to shared
// assume we'd never issue a prefetch when we've got an
// outstanding miss
assert(pkt->cmd != MemCmd::HardPFReq);
if (inService &&
- (!deferredTargets->empty() || pendingInvalidate ||
- (!targets->needsExclusive && pkt->needsExclusive()))) {
+ (!deferredTargets->empty() || hasPostInvalidate() ||
+ (pkt->needsExclusive() &&
+ (!isPendingDirty() || hasPostDowngrade() || isForward)))) {
// need to put on deferred list
+ if (hasPostInvalidate())
+ replaceUpgrade(pkt);
deferredTargets->add(pkt, whenReady, _order, Target::FromCPU, true);
} else {
// No request outstanding, or still OK to append to
// 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) {
+ if (hasPostInvalidate()) {
// 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
+ if (isPendingDirty() || pkt->isInvalidate()) {
+ // We need to save and replay the packet in two cases:
+ // 1. We're awaiting an exclusive copy, so ownership is pending,
+ // and we need to respond after we receive data.
+ // 2. It's an invalidation (e.g., UpgradeReq), and we need
+ // to forward the snoop up the hierarchy after the current
+ // transaction completes.
+
+ // Actual target device (typ. a memory) 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, Target::FromSnoop,
+ targets->add(cp_pkt, curTick(), _order, Target::FromSnoop,
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.
+ if (isPendingDirty()) {
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;
+ postInvalidate = 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;
+ }
+
+ if (!pkt->needsExclusive()) {
+ // This transaction will get a read-shared copy, downgrading
+ // our copy if we had an exclusive one
+ postDowngrade = true;
pkt->assertShared();
}
// clear deferredTargets flags
deferredTargets->resetFlags();
- pendingInvalidate = false;
- pendingShared = false;
order = targets->front().order;
- readyTime = std::max(curTick, targets->front().readyTime);
+ readyTime = std::max(curTick(), targets->front().readyTime);
return true;
}
void
MSHR::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
+ if (!pkt->sharedAsserted()
+ && !(hasPostInvalidate() || hasPostDowngrade())
&& deferredTargets->needsExclusive) {
// We got an exclusive response, but we have deferred targets
// which are waiting to request an exclusive copy (not because
_isUncacheable ? "Unc" : "",
inService ? "InSvc" : "",
downstreamPending ? "DwnPend" : "",
- pendingInvalidate ? "PendInv" : "",
- pendingShared ? "PendShared" : "");
+ hasPostInvalidate() ? "PostInv" : "",
+ hasPostDowngrade() ? "PostDowngr" : "");
ccprintf(os, "%s Targets:\n", prefix);
targets->print(os, verbosity, prefix + " ");
MSHR::~MSHR()
{
+ delete[] targets;
+ delete[] deferredTargets;
}