mem: fix functional accesses to deal with coherence change
authorSteve Reinhardt <steve.reinhardt@amd.com>
Thu, 9 Sep 2010 18:40:19 +0000 (14:40 -0400)
committerSteve Reinhardt <steve.reinhardt@amd.com>
Thu, 9 Sep 2010 18:40:19 +0000 (14:40 -0400)
We can't just obliviously return the first valid cache block
we find any more... see comments for details.

src/mem/bridge.cc
src/mem/cache/cache_impl.hh
src/mem/packet.cc

index d0135fc9d107e55e4fbf5a2414f1bd69936adbca..668b492e8583357078366bba3e560c9f533b2804 100644 (file)
@@ -325,8 +325,10 @@ Bridge::BridgePort::recvFunctional(PacketPtr pkt)
     pkt->pushLabel(name());
 
     for (i = sendQueue.begin();  i != sendQueue.end(); ++i) {
-        if (pkt->checkFunctional((*i)->pkt))
+        if (pkt->checkFunctional((*i)->pkt)) {
+            pkt->makeResponse();
             return;
+        }
     }
 
     pkt->popLabel();
index 8d2806b8d2aeb96cec2da1ac9f8aabee02bdff79..3f3dc6877b55cd2f15c5a96d9eca21c75247a679 100644 (file)
@@ -759,21 +759,44 @@ Cache<TagStore>::functionalAccess(PacketPtr pkt,
 {
     Addr blk_addr = blockAlign(pkt->getAddr());
     BlkType *blk = tags->findBlock(pkt->getAddr());
+    MSHR *mshr = mshrQueue.findMatch(blk_addr);
 
     pkt->pushLabel(name());
 
     CacheBlkPrintWrapper cbpw(blk);
-    bool done =
-        (blk && pkt->checkFunctional(&cbpw, blk_addr, blkSize, blk->data))
+
+    // Note that just because an L2/L3 has valid data doesn't mean an
+    // L1 doesn't have a more up-to-date modified copy that still
+    // needs to be found.  As a result we always update the request if
+    // we have it, but only declare it satisfied if we are the owner.
+
+    // see if we have data at all (owned or otherwise)
+    bool have_data = blk && blk->isValid()
+        && pkt->checkFunctional(&cbpw, blk_addr, blkSize, blk->data);
+
+    // data we have is dirty if marked as such or if valid & ownership
+    // pending due to outstanding UpgradeReq
+    bool have_dirty =
+        have_data && (blk->isDirty() ||
+                      (mshr && mshr->inService && mshr->isPendingDirty()));
+
+    bool done = have_dirty
         || incomingPort->checkFunctional(pkt)
         || mshrQueue.checkFunctional(pkt, blk_addr)
         || writeBuffer.checkFunctional(pkt, blk_addr)
         || otherSidePort->checkFunctional(pkt);
 
+    DPRINTF(Cache, "functional %s %x %s%s%s\n",
+            pkt->cmdString(), pkt->getAddr(),
+            (blk && blk->isValid()) ? "valid " : "",
+            have_data ? "data " : "", done ? "done " : "");
+
     // We're leaving the cache, so pop cache->name() label
     pkt->popLabel();
 
-    if (!done) {
+    if (done) {
+        pkt->makeResponse();
+    } else {
         otherSidePort->sendFunctional(pkt);
     }
 }
index 001725e662afc36ce84617786c708ea2047af567..5eb2ecc4b02e56f82d66b686b2ce95f4772d7e7c 100644 (file)
@@ -179,7 +179,6 @@ Packet::checkFunctional(Printable *obj, Addr addr, int size, uint8_t *data)
         if (func_start >= val_start && func_end <= val_end) {
             allocate();
             memcpy(getPtr<uint8_t>(), data + offset, getSize());
-            makeResponse();
             return true;
         } else {
             // In this case the timing packet only partially satisfies