diff options
Diffstat (limited to 'src/mem')
-rw-r--r-- | src/mem/cache/cache_impl.hh | 39 | ||||
-rw-r--r-- | src/mem/cache/mshr_queue.cc | 16 | ||||
-rw-r--r-- | src/mem/cache/mshr_queue.hh | 6 | ||||
-rw-r--r-- | src/mem/packet.hh | 4 |
4 files changed, 65 insertions, 0 deletions
diff --git a/src/mem/cache/cache_impl.hh b/src/mem/cache/cache_impl.hh index e8e1876a0..00ba0d24f 100644 --- a/src/mem/cache/cache_impl.hh +++ b/src/mem/cache/cache_impl.hh @@ -1394,6 +1394,12 @@ Cache<TagStore>::handleSnoop(PacketPtr pkt, BlkType *blk, if (snoopPkt.sharedAsserted()) { pkt->assertShared(); } + // If this request is a prefetch and an + // upper level squashes the prefetch request, + // make sure to propogate the squash to the requester. + if (snoopPkt.prefetchSquashed()) { + pkt->setPrefetchSquashed(); + } } else { cpuSidePort->sendAtomicSnoop(pkt); if (!alreadyResponded && pkt->memInhibitAsserted()) { @@ -1420,6 +1426,17 @@ Cache<TagStore>::handleSnoop(PacketPtr pkt, BlkType *blk, bool respond = blk->isDirty() && pkt->needsResponse(); bool have_exclusive = blk->isWritable(); + // Invalidate any prefetch's from below that would strip write permissions + // MemCmd::HardPFReq is only observed by upstream caches. After missing + // above and in it's own cache, a new MemCmd::ReadReq is created that + // downstream caches observe. + if (pkt->cmd == MemCmd::HardPFReq) { + DPRINTF(Cache, "Squashing prefetch from lower cache %#x\n", + pkt->getAddr()); + pkt->setPrefetchSquashed(); + return; + } + if (pkt->isRead() && !invalidate) { assert(!needs_exclusive); pkt->assertShared(); @@ -1503,6 +1520,14 @@ Cache<TagStore>::recvTimingSnoopReq(PacketPtr pkt) Addr blk_addr = blockAlign(pkt->getAddr()); MSHR *mshr = mshrQueue.findMatch(blk_addr, is_secure); + // Squash any prefetch requests from below on MSHR hits + if (mshr && pkt->cmd == MemCmd::HardPFReq) { + DPRINTF(Cache, "Squashing prefetch from lower cache on mshr hit %#x\n", + pkt->getAddr()); + pkt->setPrefetchSquashed(); + return; + } + // Let the MSHR itself track the snoop and decide whether we want // to go ahead and do the regular cache snoop if (mshr && mshr->handleSnoop(pkt, order++)) { @@ -1730,6 +1755,20 @@ Cache<TagStore>::getTimingPacket() snoop_pkt.senderState = mshr; cpuSidePort->sendTimingSnoopReq(&snoop_pkt); + // Check to see if the prefetch was squashed by an upper cache + if (snoop_pkt.prefetchSquashed()) { + DPRINTF(Cache, "Prefetch squashed by upper cache. " + "Deallocating mshr target %#x.\n", mshr->addr); + + // Deallocate the mshr target + if (mshr->queue->forceDeallocateTarget(mshr)) { + // Clear block if this deallocation resulted freed an + // mshr when all had previously been utilized + clearBlocked((BlockedCause)(mshr->queue->index)); + } + return NULL; + } + if (snoop_pkt.memInhibitAsserted()) { markInService(mshr, &snoop_pkt); DPRINTF(Cache, "Upward snoop of prefetch for addr" diff --git a/src/mem/cache/mshr_queue.cc b/src/mem/cache/mshr_queue.cc index 3150b4f5d..7bfbb90f5 100644 --- a/src/mem/cache/mshr_queue.cc +++ b/src/mem/cache/mshr_queue.cc @@ -232,6 +232,22 @@ MSHRQueue::markPending(MSHR *mshr) mshr->readyIter = addToReadyList(mshr); } +bool +MSHRQueue::forceDeallocateTarget(MSHR *mshr) +{ + bool was_full = isFull(); + assert(mshr->hasTargets()); + // Pop the prefetch off of the target list + mshr->popTarget(); + // Delete mshr if no remaining targets + if (!mshr->hasTargets() && !mshr->promoteDeferredTargets()) { + deallocateOne(mshr); + } + + // Notify if MSHR queue no longer full + return was_full && !isFull(); +} + void MSHRQueue::squash(int threadNum) { diff --git a/src/mem/cache/mshr_queue.hh b/src/mem/cache/mshr_queue.hh index 9177433af..7ab3c7e74 100644 --- a/src/mem/cache/mshr_queue.hh +++ b/src/mem/cache/mshr_queue.hh @@ -194,6 +194,12 @@ class MSHRQueue : public Drainable void squash(int threadNum); /** + * Deallocate top target, possibly freeing the MSHR + * @return if MSHR queue is no longer full + */ + bool forceDeallocateTarget(MSHR *mshr); + + /** * Returns true if the pending list is not empty. * @return True if there are outstanding requests. */ diff --git a/src/mem/packet.hh b/src/mem/packet.hh index 4bdcc9a93..7b9e05945 100644 --- a/src/mem/packet.hh +++ b/src/mem/packet.hh @@ -260,6 +260,8 @@ class Packet : public Printable /// suppress the error if this packet encounters a functional /// access failure. static const FlagsType SUPPRESS_FUNC_ERROR = 0x00008000; + // Signal prefetch squash through express snoop flag + static const FlagsType PREFETCH_SNOOP_SQUASH = 0x00010000; Flags flags; @@ -522,6 +524,8 @@ class Packet : public Printable bool isSupplyExclusive() const { return flags.isSet(SUPPLY_EXCLUSIVE); } void setSuppressFuncError() { flags.set(SUPPRESS_FUNC_ERROR); } bool suppressFuncError() const { return flags.isSet(SUPPRESS_FUNC_ERROR); } + void setPrefetchSquashed() { flags.set(PREFETCH_SNOOP_SQUASH); } + bool prefetchSquashed() const { return flags.isSet(PREFETCH_SNOOP_SQUASH); } // Network error conditions... encapsulate them as methods since // their encoding keeps changing (from result field to command |