blk->status |= BlkSecure;
}
}
- std::memcpy(blk->data, pkt->getPtr<uint8_t>(), blkSize);
if (pkt->cmd == MemCmd::Writeback) {
blk->status |= BlkDirty;
if (pkt->isSupplyExclusive()) {
// nothing else to do; writeback doesn't expect response
assert(!pkt->needsResponse());
} else if (pkt->cmd == MemCmd::WriteInvalidateReq) {
- assert(blk->isReadable()); // implicitly checks for Valid bit also
- blk->status |= (BlkDirty | BlkCanGoExclusive);
+ blk->status |= (BlkReadable | BlkDirty | BlkCanGoExclusive);
blk->status &= ~BlkWritable;
++fastWrites;
}
+ std::memcpy(blk->data, pkt->getPtr<uint8_t>(), blkSize);
DPRINTF(Cache, "%s new state is %s\n", __func__, blk->print());
incHitCount(pkt);
return true;
// there are cases (such as failed store conditionals or
// compare-and-swaps) where we'll demand an exclusive copy but
// end up not writing it.
+ // Caveat: if a Read takes a value from a WriteInvalidate MSHR,
+ // it will get marked Dirty even though it is Clean (once the
+ // WriteInvalidate completes). This is due to insufficient meta-
+ // data and overly presumptive interpretation of the inhibit flag.
+ // The result is an unnecessary extra writeback.
if (pkt->memInhibitAsserted())
blk->status |= BlkDirty;
}
using namespace std;
MSHR::MSHR() : readyTime(0), _isUncacheable(false), downstreamPending(false),
- pendingDirty(false), postInvalidate(false), postDowngrade(false),
- _isObsolete(false), queue(NULL), order(0), addr(0), size(0),
- isSecure(false), inService(false), isForward(false),
- threadNum(InvalidThreadID), data(NULL)
+ pendingDirty(false), pendingClean(false),
+ postInvalidate(false), postDowngrade(false),
+ _isObsolete(false), queue(NULL), order(0), addr(0),
+ size(0), isSecure(false), inService(false),
+ isForward(false), threadNum(InvalidThreadID), data(NULL)
{
}
isForward = false;
_isUncacheable = target->req->isUncacheable();
inService = false;
+ pendingClean = (target->cmd == MemCmd::WriteInvalidateReq);
downstreamPending = false;
_isObsolete = false;
threadNum = 0;
assert(pkt != NULL);
inService = true;
- pendingDirty = (targets.needsExclusive ||
+ pendingDirty = ((targets.needsExclusive &&
+ (pkt->cmd != MemCmd::WriteInvalidateReq)) ||
(!pkt->sharedAsserted() && pkt->memInhibitAsserted()));
postInvalidate = postDowngrade = false;
targets.add(cp_pkt, curTick(), _order, Target::FromSnoop,
downstreamPending && targets.needsExclusive);
- if (isPendingDirty()) {
+ // WriteInvalidates must writeback and should not be inhibited on
+ // account of its snoops discovering MSHRs wanting exclusive access
+ // to what it wrote. We don't want to push this check higher,
+ // however, because we want to be sure to add an invalidating
+ // Target::FromSnoop, above.
+ if (isPendingDirty() && (pkt->cmd != MemCmd::WriteInvalidateReq)) {
pkt->assertMemInhibit();
pkt->setSupplyExclusive();
}
if (pkt->needsExclusive()) {
// This transaction will take away our pending copy
postInvalidate = true;
+
+ // Do not defer (i.e. return true) the snoop if the block is
+ // going to be clean once the MSHR completes, as the data is
+ // ready now.
+ if (isPendingClean()) {
+ return false;
+ }
}
}