diff options
Diffstat (limited to 'src/mem')
-rw-r--r-- | src/mem/cache/cache_impl.hh | 21 | ||||
-rw-r--r-- | src/mem/cache/miss/mshr.cc | 10 |
2 files changed, 22 insertions, 9 deletions
diff --git a/src/mem/cache/cache_impl.hh b/src/mem/cache/cache_impl.hh index efd7f4588..412d10599 100644 --- a/src/mem/cache/cache_impl.hh +++ b/src/mem/cache/cache_impl.hh @@ -148,7 +148,13 @@ void Cache<TagStore>::satisfyCpuSideRequest(PacketPtr pkt, BlkType *blk) { assert(blk); - assert(pkt->needsExclusive() ? blk->isWritable() : blk->isValid()); + // Occasionally this is not true... if we are a lower-level cache + // satisfying a string of Read and ReadEx requests from + // upper-level caches, a Read will mark the block as shared but we + // can satisfy a following ReadEx anyway since we can rely on the + // Read requester(s) to have buffered the ReadEx snoop and to + // invalidate their blocks after receiving them. + // assert(pkt->needsExclusive() ? blk->isWritable() : blk->isValid()); assert(pkt->getOffset(blkSize) + pkt->getSize() <= blkSize); // Check RMW operations first since both isRead() and @@ -727,7 +733,7 @@ Cache<TagStore>::handleResponse(PacketPtr pkt) Tick completion_time; if (blk != NULL) { satisfyCpuSideRequest(target->pkt, blk); - // How many bytes pass the first request is this one + // How many bytes past the first request is this one int transfer_offset = target->pkt->getOffset(blkSize) - initial_offset; if (transfer_offset < 0) { @@ -738,10 +744,9 @@ Cache<TagStore>::handleResponse(PacketPtr pkt) completion_time = tags->getHitLatency() + transfer_offset ? pkt->finishTime : pkt->firstWordTime; - if (!target->pkt->req->isUncacheable()) { - missLatency[target->pkt->cmdToIndex()][0/*pkt->req->getThreadNum()*/] += - completion_time - target->recvTime; - } + assert(!target->pkt->req->isUncacheable()); + missLatency[target->pkt->cmdToIndex()][0/*pkt->req->getThreadNum()*/] += + completion_time - target->recvTime; } else { // not a cache fill, just forwarding response completion_time = tags->getHitLatency() + pkt->finishTime; @@ -1004,7 +1009,9 @@ template<class TagStore> void Cache<TagStore>::snoopTiming(PacketPtr pkt) { - if (pkt->req->isUncacheable()) { + // Note that some deferred snoops don't have requests, since the + // original access may have already completed + if (pkt->req && pkt->req->isUncacheable()) { //Can't get a hit on an uncacheable address //Revisit this for multi level coherence return; diff --git a/src/mem/cache/miss/mshr.cc b/src/mem/cache/miss/mshr.cc index 9b05aea3f..7f216ad39 100644 --- a/src/mem/cache/miss/mshr.cc +++ b/src/mem/cache/miss/mshr.cc @@ -208,7 +208,7 @@ MSHR::allocateTarget(PacketPtr pkt, Tick whenReady, Counter _order) bool MSHR::handleSnoop(PacketPtr pkt, Counter _order) { - if (!inService || downstreamPending) { + 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 @@ -249,13 +249,19 @@ MSHR::handleSnoop(PacketPtr pkt, Counter _order) if (targets->needsExclusive || pkt->needsExclusive()) { // actual target device (typ. PhysicalMemory) will delete the // packet on reception, so we need to save a copy here - targets->add(new Packet(pkt), curTick, _order, false); + PacketPtr cp_pkt = new Packet(pkt); + targets->add(cp_pkt, curTick, _order, false); ++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(); + } 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()) { |