DPRINTF(Cache, "mem inhibited on 0x%x: not responding\n",
pkt->getAddr());
assert(!pkt->req->isUncacheable());
+ // Special tweak for multilevel coherence: snoop downward here
+ // on invalidates since there may be other caches below here
+ // that have shared copies. Not necessary if we know that
+ // supplier had exclusive copy to begin with.
+ if (pkt->needsExclusive() && !pkt->isSupplyExclusive()) {
+ Packet *snoopPkt = new Packet(pkt, true); // clear flags
+ snoopPkt->setExpressSnoop();
+ snoopPkt->assertMemInhibit();
+ memSidePort->sendTiming(snoopPkt);
+ // main memory will delete snoopPkt
+ }
return true;
}
// we respond in atomic mode), so just figure out what to do now
// and then do it later
bool supply = blk->isDirty() && pkt->isRead() && !upperSupply;
+ bool have_exclusive = blk->isWritable();
bool invalidate = pkt->isInvalidate();
if (pkt->isRead() && !pkt->isInvalidate()) {
if (supply) {
assert(!pkt->memInhibitAsserted());
pkt->assertMemInhibit();
+ if (have_exclusive) {
+ pkt->setSupplyExclusive();
+ }
if (is_timing) {
doTimingSupplyResponse(pkt, blk->data, is_deferred);
} else {
// 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
MemInhibit,
Shared,
// Special control flags
+ /// Special timing-mode atomic snoop for multi-level coherence.
ExpressSnoop,
+ /// Does supplier have exclusive copy?
+ /// Useful for multi-level coherence.
+ SupplyExclusive,
NUM_PACKET_FLAGS
};
// Snoop flags
void assertMemInhibit() { flags[MemInhibit] = true; }
- void assertShared() { flags[Shared] = true; }
bool memInhibitAsserted() { return flags[MemInhibit]; }
+ void assertShared() { flags[Shared] = true; }
bool sharedAsserted() { return flags[Shared]; }
// Special control flags
void setExpressSnoop() { flags[ExpressSnoop] = true; }
bool isExpressSnoop() { return flags[ExpressSnoop]; }
+ void setSupplyExclusive() { flags[SupplyExclusive] = true; }
+ bool isSupplyExclusive() { return flags[SupplyExclusive]; }
// Network error conditions... encapsulate them as methods since
// their encoding keeps changing (from result field to command