From c4903e088247ad187356864459d2e4be77d97154 Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Tue, 26 Jun 2007 23:30:30 -0700 Subject: [PATCH] Revamp replacement-of-upgrade handling. --HG-- extra : convert_revision : 9bc09d8ae6d50e6dfbb4ab21514612f9aa102a2e --- src/mem/cache/cache.hh | 3 +++ src/mem/cache/cache_impl.hh | 44 ++++++++++++++++++++++---------- src/mem/cache/miss/mshr.cc | 51 +------------------------------------ src/mem/cache/miss/mshr.hh | 6 +---- 4 files changed, 36 insertions(+), 68 deletions(-) diff --git a/src/mem/cache/cache.hh b/src/mem/cache/cache.hh index 161fb801d..9e8c35066 100644 --- a/src/mem/cache/cache.hh +++ b/src/mem/cache/cache.hh @@ -136,6 +136,9 @@ class Cache : public BaseCache /** Prefetcher */ BasePrefetcher *prefetcher; + /** Temporary cache block for occasional transitory use */ + BlkType *tempBlock; + /** * Can this cache should allocate a block on a line-sized write miss. */ diff --git a/src/mem/cache/cache_impl.hh b/src/mem/cache/cache_impl.hh index 599eecc82..3685bc8cb 100644 --- a/src/mem/cache/cache_impl.hh +++ b/src/mem/cache/cache_impl.hh @@ -58,6 +58,9 @@ Cache::Cache(const std::string &_name, doFastWrites(params.doFastWrites), prefetchMiss(params.prefetchMiss) { + tempBlock = new BlkType(); + tempBlock->data = new uint8_t[blkSize]; + cpuSidePort = new CpuSidePort(_name + "-cpu_side_port", this); memSidePort = new MemSidePort(_name + "-mem_side_port", this); cpuSidePort->setOtherPort(memSidePort); @@ -678,11 +681,8 @@ Cache::handleResponse(PacketPtr pkt) pkt->getAddr()); BlkType *blk = tags->findBlock(pkt->getAddr()); - if (!mshr->handleFill(pkt, blk)) { - mq->markPending(mshr); - requestMemSideBus((RequestCause)mq->index, pkt->finishTime); - return; - } + // give mshr a chance to do some dirty work + mshr->handleFill(pkt, blk); PacketList writebacks; blk = handleFill(pkt, blk, writebacks); @@ -693,6 +693,13 @@ Cache::handleResponse(PacketPtr pkt) allocateBuffer(wbPkt, time, true); writebacks.pop_front(); } + // if we used temp block, clear it out + if (blk == tempBlock) { + if (blk->isDirty()) { + allocateBuffer(writebackBlk(blk), time, true); + } + tags->invalidateBlk(blk); + } } else { if (pkt->req->isUncacheable()) { mshr_uncacheable_lat[pkt->cmd.toInt()][0/*pkt->req->getThreadNum()*/] += @@ -764,15 +771,26 @@ Cache::handleFill(PacketPtr pkt, BlkType *blk, Addr repl_addr = tags->regenerateBlkAddr(blk->tag, blk->set); MSHR *repl_mshr = mshrQueue.findMatch(repl_addr); if (repl_mshr) { - repl_mshr->handleReplacement(blk, blkSize); - } + // must be an outstanding upgrade request on block + // we're about to replace... + assert(!blk->isWritable()); + assert(repl_mshr->needsExclusive); + // too hard to replace block with transient state; + // just use temporary storage to complete the current + // request and then get rid of it + assert(!tempBlock->isValid()); + blk = tempBlock; + tempBlock->set = tags->extractSet(addr); + DPRINTF(Cache, "using temp block for %x\n", addr); + } else { + DPRINTF(Cache, "replacement: replacing %x with %x: %s\n", + repl_addr, addr, + blk->isDirty() ? "writeback" : "clean"); - DPRINTF(Cache, "replacement: replacing %x with %x: %s\n", - repl_addr, addr, blk->isDirty() ? "writeback" : "clean"); - - if (blk->isDirty()) { - // Save writeback packet for handling by caller - writebacks.push_back(writebackBlk(blk)); + if (blk->isDirty()) { + // Save writeback packet for handling by caller + writebacks.push_back(writebackBlk(blk)); + } } } diff --git a/src/mem/cache/miss/mshr.cc b/src/mem/cache/miss/mshr.cc index 23645cb27..63b3cacc2 100644 --- a/src/mem/cache/miss/mshr.cc +++ b/src/mem/cache/miss/mshr.cc @@ -76,7 +76,6 @@ MSHR::allocate(Addr _addr, int _size, PacketPtr target, deferredNeedsExclusive = false; pendingInvalidate = false; pendingShared = false; - replacedPendingUpgrade = false; data = NULL; } @@ -185,61 +184,13 @@ 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::handleFill(Packet *pkt, CacheBlk *blk) { - if (replacedPendingUpgrade) { - // block was replaced while upgrade request was in service - assert(pkt->cmd == MemCmd::UpgradeResp); - assert(blk == NULL); - 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; - } else if (pendingShared) { + if (pendingShared) { // we snooped another read while this read was in // service... assert shared line on its behalf pkt->assertShared(); } - - return true; } diff --git a/src/mem/cache/miss/mshr.hh b/src/mem/cache/miss/mshr.hh index 07fe5c96c..4db7b1cfe 100644 --- a/src/mem/cache/miss/mshr.hh +++ b/src/mem/cache/miss/mshr.hh @@ -106,9 +106,6 @@ class MSHR : public Packet::SenderState bool deferredNeedsExclusive; bool pendingInvalidate; bool pendingShared; - /** Is there a pending upgrade that got replaced? */ - bool replacedPendingUpgrade; - bool replacedPendingUpgradeDirty; /** Thread number of the miss. */ short threadNum; @@ -213,8 +210,7 @@ public: bool promoteDeferredTargets(); - void handleReplacement(CacheBlk *blk, int blkSize); - bool handleFill(Packet *pkt, CacheBlk *blk); + void handleFill(Packet *pkt, CacheBlk *blk); /** * Prints the contents of this MSHR to stderr.