Handle replacement of block with pending upgrade.
authorSteve Reinhardt <stever@eecs.umich.edu>
Tue, 26 Jun 2007 21:53:15 +0000 (14:53 -0700)
committerSteve Reinhardt <stever@eecs.umich.edu>
Tue, 26 Jun 2007 21:53:15 +0000 (14:53 -0700)
src/mem/cache/tags/lru.cc:
    Add some replacement DPRINTFs

--HG--
extra : convert_revision : 7993ec24d6af7e7774d04ce36f20e3f43f887fd9

src/mem/cache/cache_impl.hh
src/mem/cache/miss/mshr.cc
src/mem/cache/miss/mshr.hh
src/mem/cache/tags/lru.cc

index 48efc5ca3f976fbabe01ca958c466c48cfa59014..d01adde78094d113bdce28921d6f878218202717 100644 (file)
@@ -300,7 +300,6 @@ Cache<TagStore,Coherence>::timingAccess(PacketPtr pkt)
         return true;
     }
 
-    PacketList writebacks;
     int lat = hitLatency;
     bool satisfied = false;
 
@@ -319,6 +318,8 @@ Cache<TagStore,Coherence>::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<TagStore,Coherence>::timingAccess(PacketPtr pkt)
             ++fastWrites;
         }
     }
-#endif
 
     // copy writebacks to write buffer
     while (!writebacks.empty()) {
@@ -346,6 +346,7 @@ Cache<TagStore,Coherence>::timingAccess(PacketPtr pkt)
         allocateBuffer(wbPkt, time, true);
         writebacks.pop_front();
     }
+#endif
 
     bool needsResponse = pkt->needsResponse();
 
@@ -676,6 +677,15 @@ Cache<TagStore,Coherence>::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<TagStore,Coherence>::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<TagStore,Coherence>::getNextMSHR()
             return conflict_mshr;
         }
 
-        // No conclifts; issue read
+        // No conflicts; issue read
         return miss_mshr;
     }
 
index fc8d2175ef11d82603f04d39ff3cd8c13b4f4010..ca5e386012c9829b71141100de3d30da1894eb5e 100644 (file)
@@ -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()
 {
index 92288cf523006000567dbc154a81424ae69de001..a9380d99a30a12b2af000a4863901402e02b889d 100644 (file)
@@ -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.
      */
index 334312aaf04d0f0ff20bcf92ee055690843080f3..fa46aff7b55794609ef808a550fd45796f7e4ca4 100644 (file)
@@ -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;
 }