Port: Make getAddrRanges const
[gem5.git] / src / mem / cache / mshr.cc
index 100e6126ad616389192fa25b52b37ac83c6ff51a..6fa22c9b47315838c0fbaa8c0b2da04110c09bd4 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2002-2005 The Regents of The University of Michigan
+ * Copyright (c) 2010 Advanced Micro Devices, Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -41,6 +42,7 @@
 
 #include "base/misc.hh"
 #include "base/types.hh"
+#include "debug/Cache.hh"
 #include "mem/cache/cache.hh"
 #include "mem/cache/mshr.hh"
 #include "sim/core.hh"
@@ -71,7 +73,10 @@ MSHR::TargetList::add(PacketPtr pkt, Tick readyTime,
             needsExclusive = true;
         }
 
-        if (pkt->cmd == MemCmd::UpgradeReq) {
+        // StoreCondReq is effectively an upgrade if it's in an MSHR
+        // since it would have been failed already if we didn't have a
+        // read-only copy
+        if (pkt->isUpgrade() || pkt->cmd == MemCmd::StoreCondReq) {
             hasUpgrade = true;
         }
     }
@@ -88,6 +93,22 @@ MSHR::TargetList::add(PacketPtr pkt, Tick readyTime,
 }
 
 
+static void
+replaceUpgrade(PacketPtr pkt)
+{
+    if (pkt->cmd == MemCmd::UpgradeReq) {
+        pkt->cmd = MemCmd::ReadExReq;
+        DPRINTF(Cache, "Replacing UpgradeReq with ReadExReq\n");
+    } else if (pkt->cmd == MemCmd::SCUpgradeReq) {
+        pkt->cmd = MemCmd::SCUpgradeFailReq;
+        DPRINTF(Cache, "Replacing SCUpgradeReq with SCUpgradeFailReq\n");
+    } else if (pkt->cmd == MemCmd::StoreCondReq) {
+        pkt->cmd = MemCmd::StoreCondFailReq;
+        DPRINTF(Cache, "Replacing StoreCondReq with StoreCondFailReq\n");
+    }
+}
+
+
 void
 MSHR::TargetList::replaceUpgrades()
 {
@@ -96,10 +117,7 @@ MSHR::TargetList::replaceUpgrades()
 
     Iterator end_i = end();
     for (Iterator i = begin(); i != end_i; ++i) {
-        if (i->pkt->cmd == MemCmd::UpgradeReq) {
-            i->pkt->cmd = MemCmd::ReadExReq;
-            DPRINTF(Cache, "Replacing UpgradeReq with ReadExReq\n");
-        }
+        replaceUpgrade(i->pkt);
     }
 
     hasUpgrade = false;
@@ -143,10 +161,18 @@ print(std::ostream &os, int verbosity, const std::string &prefix) const
     for (ConstIterator i = begin(); i != end_i; ++i) {
         const char *s;
         switch (i->source) {
-          case Target::FromCPU: s = "FromCPU";
-          case Target::FromSnoop: s = "FromSnoop";
-          case Target::FromPrefetcher: s = "FromPrefetcher";
-          default: s = "";
+          case Target::FromCPU:
+            s = "FromCPU";
+            break;
+          case Target::FromSnoop:
+            s = "FromSnoop";
+            break;
+          case Target::FromPrefetcher:
+            s = "FromPrefetcher";
+            break;
+          default:
+            s = "";
+            break;
         }
         ccprintf(os, "%s%s: ", prefix, s);
         i->pkt->print(os, verbosity, "");
@@ -176,8 +202,6 @@ MSHR::allocate(Addr _addr, int _size, PacketPtr target,
         Target::FromPrefetcher : Target::FromCPU;
     targets->add(target, whenReady, _order, source, true);
     assert(deferredTargets->isReset());
-    pendingInvalidate = false;
-    pendingShared = false;
     data = NULL;
 }
 
@@ -193,7 +217,7 @@ MSHR::clearDownstreamPending()
 }
 
 bool
-MSHR::markInService()
+MSHR::markInService(PacketPtr pkt)
 {
     assert(!inService);
     if (isForwardNoResponse()) {
@@ -204,6 +228,10 @@ MSHR::markInService()
         return true;
     }
     inService = true;
+    pendingDirty = (targets->needsExclusive ||
+                    (!pkt->sharedAsserted() && pkt->memInhibitAsserted()));
+    postInvalidate = postDowngrade = false;
+
     if (!downstreamPending) {
         // let upstream caches know that the request has made it to a
         // level where it's going to get a response
@@ -221,8 +249,6 @@ MSHR::deallocate()
     assert(deferredTargets->isReset());
     assert(ntargets == 0);
     inService = false;
-    //allocIter = NULL;
-    //readyIter = NULL;
 }
 
 /*
@@ -237,17 +263,22 @@ MSHR::allocateTarget(PacketPtr pkt, Tick whenReady, Counter _order)
     // - there are other targets already deferred
     // - there's a pending invalidate to be applied after the response
     //   comes back (but before this target is processed)
-    // - the outstanding request is for a non-exclusive block and this
-    //   target requires an exclusive block
+    // - this target requires an exclusive block and either we're not
+    //   getting an exclusive block back or we have already snooped
+    //   another read request that will downgrade our exclusive block
+    //   to shared
 
     // assume we'd never issue a prefetch when we've got an
     // outstanding miss
     assert(pkt->cmd != MemCmd::HardPFReq);
 
     if (inService &&
-        (!deferredTargets->empty() || pendingInvalidate ||
-         (!targets->needsExclusive && pkt->needsExclusive()))) {
+        (!deferredTargets->empty() || hasPostInvalidate() ||
+         (pkt->needsExclusive() &&
+          (!isPendingDirty() || hasPostDowngrade() || isForward)))) {
         // need to put on deferred list
+        if (hasPostInvalidate())
+            replaceUpgrade(pkt);
         deferredTargets->add(pkt, whenReady, _order, Target::FromCPU, true);
     } else {
         // No request outstanding, or still OK to append to
@@ -287,49 +318,49 @@ MSHR::handleSnoop(PacketPtr pkt, Counter _order)
 
     // From here on down, the request issued by this MSHR logically
     // precedes the request we're snooping.
-
     if (pkt->needsExclusive()) {
         // snooped request still precedes the re-request we'll have to
         // issue for deferred targets, if any...
         deferredTargets->replaceUpgrades();
     }
 
-    if (pendingInvalidate) {
+    if (hasPostInvalidate()) {
         // a prior snoop has already appended an invalidation, so
         // logically we don't have the block anymore; no need for
         // further snooping.
         return true;
     }
 
-    if (targets->needsExclusive || pkt->needsExclusive()) {
-        // actual target device (typ. PhysicalMemory) will delete the
-        // packet on reception, so we need to save a copy here
+    if (isPendingDirty() || pkt->isInvalidate()) {
+        // We need to save and replay the packet in two cases:
+        // 1. We're awaiting an exclusive copy, so ownership is pending,
+        //    and we need to respond after we receive data.
+        // 2. It's an invalidation (e.g., UpgradeReq), and we need
+        //    to forward the snoop up the hierarchy after the current
+        //    transaction completes.
+        
+        // Actual target device (typ. a memory) will delete the
+        // packet on reception, so we need to save a copy here.
         PacketPtr cp_pkt = new Packet(pkt, true);
-        targets->add(cp_pkt, curTick, _order, Target::FromSnoop,
+        targets->add(cp_pkt, curTick(), _order, Target::FromSnoop,
                      downstreamPending && targets->needsExclusive);
         ++ntargets;
 
-        if (targets->needsExclusive) {
-            // We're awaiting an exclusive copy, so ownership is pending.
-            // It's up to us to respond once the data arrives.
+        if (isPendingDirty()) {
             pkt->assertMemInhibit();
             pkt->setSupplyExclusive();
-        } else {
-            // Someone else may respond before we get around to
-            // processing this snoop, which means the copied request
-            // pointer will no longer be valid
-            cp_pkt->req = NULL;
         }
 
         if (pkt->needsExclusive()) {
             // This transaction will take away our pending copy
-            pendingInvalidate = true;
+            postInvalidate = true;
         }
-    } else {
-        // Read to a read: no conflict, so no need to record as
-        // target, but make sure neither reader thinks he's getting an
-        // exclusive copy
-        pendingShared = true;
+    }
+
+    if (!pkt->needsExclusive()) {
+        // This transaction will get a read-shared copy, downgrading
+        // our copy if we had an exclusive one
+        postDowngrade = true;
         pkt->assertShared();
     }
 
@@ -355,10 +386,8 @@ MSHR::promoteDeferredTargets()
     // clear deferredTargets flags
     deferredTargets->resetFlags();
 
-    pendingInvalidate = false;
-    pendingShared = false;
     order = targets->front().order;
-    readyTime = std::max(curTick, targets->front().readyTime);
+    readyTime = std::max(curTick(), targets->front().readyTime);
 
     return true;
 }
@@ -367,13 +396,8 @@ MSHR::promoteDeferredTargets()
 void
 MSHR::handleFill(Packet *pkt, CacheBlk *blk)
 {
-    if (pendingShared) {
-        // we snooped another read while this read was in
-        // service... assert shared line on its behalf
-        pkt->assertShared();
-    }
-
-    if (!pkt->sharedAsserted() && !pendingInvalidate
+    if (!pkt->sharedAsserted()
+        && !(hasPostInvalidate() || hasPostDowngrade())
         && deferredTargets->needsExclusive) {
         // We got an exclusive response, but we have deferred targets
         // which are waiting to request an exclusive copy (not because
@@ -423,8 +447,8 @@ MSHR::print(std::ostream &os, int verbosity, const std::string &prefix) const
              _isUncacheable ? "Unc" : "",
              inService ? "InSvc" : "",
              downstreamPending ? "DwnPend" : "",
-             pendingInvalidate ? "PendInv" : "",
-             pendingShared ? "PendShared" : "");
+             hasPostInvalidate() ? "PostInv" : "",
+             hasPostDowngrade() ? "PostDowngr" : "");
 
     ccprintf(os, "%s  Targets:\n", prefix);
     targets->print(os, verbosity, prefix + "    ");
@@ -436,4 +460,6 @@ MSHR::print(std::ostream &os, int verbosity, const std::string &prefix) const
 
 MSHR::~MSHR()
 {
+    delete[] targets;
+    delete[] deferredTargets;
 }