From: Steve Reinhardt Date: Tue, 26 Jun 2007 21:53:15 +0000 (-0700) Subject: Handle replacement of block with pending upgrade. X-Git-Tag: m5_2.0_beta4~195^2~50^2~32 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=7dacbcf49262605a75e461149ec7bd7a00fca7b7;p=gem5.git Handle replacement of block with pending upgrade. src/mem/cache/tags/lru.cc: Add some replacement DPRINTFs --HG-- extra : convert_revision : 7993ec24d6af7e7774d04ce36f20e3f43f887fd9 --- diff --git a/src/mem/cache/cache_impl.hh b/src/mem/cache/cache_impl.hh index 48efc5ca3..d01adde78 100644 --- a/src/mem/cache/cache_impl.hh +++ b/src/mem/cache/cache_impl.hh @@ -300,7 +300,6 @@ Cache::timingAccess(PacketPtr pkt) return true; } - PacketList writebacks; int lat = hitLatency; bool satisfied = false; @@ -319,6 +318,8 @@ Cache::timingAccess(PacketPtr pkt) } #if 0 + PacketList writebacks; + // If this is a block size write/hint (WH64) allocate the block here // if the coherence protocol allows it. /** @todo make the fast write alloc (wh64) work with coherence. */ @@ -338,7 +339,6 @@ Cache::timingAccess(PacketPtr pkt) ++fastWrites; } } -#endif // copy writebacks to write buffer while (!writebacks.empty()) { @@ -346,6 +346,7 @@ Cache::timingAccess(PacketPtr pkt) allocateBuffer(wbPkt, time, true); writebacks.pop_front(); } +#endif bool needsResponse = pkt->needsResponse(); @@ -676,6 +677,15 @@ Cache::handleResponse(PacketPtr pkt) DPRINTF(Cache, "Block for addr %x being updated in Cache\n", pkt->getAddr()); BlkType *blk = tags->findBlock(pkt->getAddr()); + + if (blk == NULL && pkt->cmd == MemCmd::UpgradeResp) { + if (!mshr->handleReplacedPendingUpgrade(pkt)) { + mq->markPending(mshr); + requestMemSideBus((RequestCause)mq->index, pkt->finishTime); + return; + } + } + PacketList writebacks; blk = handleFill(pkt, blk, writebacks); deallocate = satisfyMSHR(mshr, pkt, blk); @@ -747,15 +757,20 @@ Cache::handleFill(PacketPtr pkt, BlkType *blk, Addr addr = pkt->getAddr(); if (blk == NULL) { - // better have read new data + // better have read new data... assert(pkt->isRead()); // need to do a replacement blk = tags->findReplacement(addr, writebacks); if (blk->isValid()) { + Addr repl_addr = tags->regenerateBlkAddr(blk->tag, blk->set); + MSHR *repl_mshr = mshrQueue.findMatch(repl_addr); + if (repl_mshr) { + repl_mshr->handleReplacement(blk, blkSize); + } + DPRINTF(Cache, "replacement: replacing %x with %x: %s\n", - tags->regenerateBlkAddr(blk->tag, blk->set), addr, - blk->isDirty() ? "writeback" : "clean"); + repl_addr, addr, blk->isDirty() ? "writeback" : "clean"); if (blk->isDirty()) { // Save writeback packet for handling by caller @@ -992,7 +1007,7 @@ Cache::getNextMSHR() return conflict_mshr; } - // No conclifts; issue read + // No conflicts; issue read return miss_mshr; } diff --git a/src/mem/cache/miss/mshr.cc b/src/mem/cache/miss/mshr.cc index fc8d2175e..ca5e38601 100644 --- a/src/mem/cache/miss/mshr.cc +++ b/src/mem/cache/miss/mshr.cc @@ -75,6 +75,8 @@ MSHR::allocate(Addr _addr, int _size, PacketPtr target, assert(deferredTargets.empty()); deferredNeedsExclusive = false; pendingInvalidate = false; + replacedPendingUpgrade = false; + data = NULL; } void @@ -170,6 +172,57 @@ MSHR::promoteDeferredTargets() } +void +MSHR::handleReplacement(CacheBlk *blk, int blkSize) +{ + // must be an outstanding upgrade request on block we're about to + // replace... + assert(!blk->isWritable()); + assert(needsExclusive); + replacedPendingUpgrade = true; + + // if it's dirty, just remember what happened and allow the + // writeback to continue. we'll reissue a ReadEx later whether + // the upgrade succeeds or not + if (blk->isDirty()) { + replacedPendingUpgradeDirty = true; + return; + } + + // if not dirty, we need to save it off as it will be only valid + // copy in system if upgrade is successful (and may need to be + // written back then, as the current owner if any will be + // invalidating its block) + replacedPendingUpgradeDirty = false; + data = new uint8_t[blkSize]; + std::memcpy(data, blk->data, blkSize); +} + + +bool +MSHR::handleReplacedPendingUpgrade(Packet *pkt) +{ + // @TODO: if upgrade is nacked and replacedPendingUpgradeDirty is true, then we need to writeback the data (or rel + assert(pkt->cmd == MemCmd::UpgradeResp); + assert(replacedPendingUpgrade); + replacedPendingUpgrade = false; // reset + if (replacedPendingUpgradeDirty) { + // we wrote back the previous copy; just reissue as a ReadEx + return false; + } + + // previous copy was not dirty, but we are now owner... fake out + // cache by taking saved data and converting UpgradeResp to + // ReadExResp + assert(data); + pkt->cmd = MemCmd::ReadExResp; + pkt->setData(data); + delete [] data; + data = NULL; + return true; +} + + void MSHR::dump() { diff --git a/src/mem/cache/miss/mshr.hh b/src/mem/cache/miss/mshr.hh index 92288cf52..a9380d99a 100644 --- a/src/mem/cache/miss/mshr.hh +++ b/src/mem/cache/miss/mshr.hh @@ -105,12 +105,20 @@ class MSHR : public Packet::SenderState bool deferredNeedsExclusive; bool pendingInvalidate; + /** Is there a pending upgrade that got replaced? */ + bool replacedPendingUpgrade; + bool replacedPendingUpgradeDirty; /** Thread number of the miss. */ short threadNum; /** The number of currently allocated targets. */ short ntargets; + + /** Data buffer (if needed). Currently used only for pending + * upgrade handling. */ + uint8_t *data; + /** * Pointer to this MSHR on the ready list. * @sa MissQueue, MSHRQueue::readyList @@ -204,6 +212,9 @@ public: bool promoteDeferredTargets(); + void handleReplacement(CacheBlk *blk, int blkSize); + bool handleReplacedPendingUpgrade(Packet *pkt); + /** * Prints the contents of this MSHR to stderr. */ diff --git a/src/mem/cache/tags/lru.cc b/src/mem/cache/tags/lru.cc index 334312aaf..fa46aff7b 100644 --- a/src/mem/cache/tags/lru.cc +++ b/src/mem/cache/tags/lru.cc @@ -173,6 +173,8 @@ LRU::findBlock(Addr addr, int &lat) if (blk != NULL) { // move this block to head of the MRU list sets[set].moveToHead(blk); + DPRINTF(Cache, "set %x: moving blk %x to MRU\n", + set, regenerateBlkAddr(tag, set)); if (blk->whenReady > curTick && blk->whenReady - curTick > hitLatency) { lat = blk->whenReady - curTick; @@ -214,6 +216,8 @@ LRU::findReplacement(Addr addr, PacketList &writebacks) } } + DPRINTF(Cache, "set %x: selecting blk %x for replacement\n", + set, regenerateBlkAddr(blk->tag, set)); return blk; }