changeset 436d5dde4bb7 in /z/repo/gem5
details: http://repo.gem5.org/gem5?cmd=changeset;node=436d5dde4bb7
description:
        ruby: fix deadlock bug in banked array resource checks

        The Ruby banked array resource checks (initiated from SLICC) did a 
check and
        allocate at the same time. If a transition needs more than one 
resource, then
        it might check/allocate resource #1, then fail to get resource #2. 
Another
        transition might then try to get the same resources, but in reverse 
order.
        Deadlock.

        This patch separates resource checking and resource reservation into two
        steps to avoid deadlock.

diffstat:

 src/mem/protocol/RubySlicc_Types.sm    |   2 +-
 src/mem/ruby/structures/BankedArray.cc |  28 +++++++++++++++++++++-------
 src/mem/ruby/structures/BankedArray.hh |   2 ++
 src/mem/ruby/structures/CacheMemory.cc |  12 +++++++++++-
 src/mem/ruby/structures/CacheMemory.hh |   2 +-
 5 files changed, 36 insertions(+), 10 deletions(-)

diffs (120 lines):

diff -r 9b3b9be42dd9 -r 436d5dde4bb7 src/mem/protocol/RubySlicc_Types.sm
--- a/src/mem/protocol/RubySlicc_Types.sm       Mon Jul 20 09:15:18 2015 -0500
+++ b/src/mem/protocol/RubySlicc_Types.sm       Mon Jul 20 09:15:18 2015 -0500
@@ -154,7 +154,7 @@
   Cycles getTagLatency();
   Cycles getDataLatency();
   void setMRU(Address);
-  void recordRequestType(CacheRequestType);
+  void recordRequestType(CacheRequestType, Address);
   bool checkResourceAvailable(CacheResourceType, Address);
 
   int getCacheSize();
diff -r 9b3b9be42dd9 -r 436d5dde4bb7 src/mem/ruby/structures/BankedArray.cc
--- a/src/mem/ruby/structures/BankedArray.cc    Mon Jul 20 09:15:18 2015 -0500
+++ b/src/mem/ruby/structures/BankedArray.cc    Mon Jul 20 09:15:18 2015 -0500
@@ -58,13 +58,29 @@
     assert(bank < banks);
 
     if (busyBanks[bank].endAccess >= curTick()) {
-        if (!(busyBanks[bank].startAccess == curTick() &&
-            busyBanks[bank].idx == idx)) {
             return false;
+    }
+
+    return true;
+}
+
+void
+BankedArray::reserve(int64 idx)
+{
+    if (accessLatency == 0)
+        return;
+
+    unsigned int bank = mapIndexToBank(idx);
+    assert(bank < banks);
+
+    if(busyBanks[bank].endAccess >= curTick()) {
+        if (busyBanks[bank].startAccess == curTick() &&
+             busyBanks[bank].idx == idx) {
+            // this is the same reservation (can happen when
+            // e.g., reserve the same resource for read and write)
+            return; // OK
         } else {
-            // We tried to allocate resources twice
-            // in the same cycle for the same addr
-            return true;
+            panic("BankedArray reservation error");
         }
     }
 
@@ -72,8 +88,6 @@
     busyBanks[bank].startAccess = curTick();
     busyBanks[bank].endAccess = curTick() +
         (accessLatency-1) * m_ruby_system->clockPeriod();
-
-    return true;
 }
 
 unsigned int
diff -r 9b3b9be42dd9 -r 436d5dde4bb7 src/mem/ruby/structures/BankedArray.hh
--- a/src/mem/ruby/structures/BankedArray.hh    Mon Jul 20 09:15:18 2015 -0500
+++ b/src/mem/ruby/structures/BankedArray.hh    Mon Jul 20 09:15:18 2015 -0500
@@ -70,6 +70,8 @@
     // This is so we don't get aliasing on blocks being replaced
     bool tryAccess(int64 idx);
 
+    void reserve(int64 idx);
+
     Cycles getLatency() const { return accessLatency; }
 };
 
diff -r 9b3b9be42dd9 -r 436d5dde4bb7 src/mem/ruby/structures/CacheMemory.cc
--- a/src/mem/ruby/structures/CacheMemory.cc    Mon Jul 20 09:15:18 2015 -0500
+++ b/src/mem/ruby/structures/CacheMemory.cc    Mon Jul 20 09:15:18 2015 -0500
@@ -528,22 +528,32 @@
         ;
 }
 
+// assumption: SLICC generated files will only call this function
+// once **all** resources are granted
 void
-CacheMemory::recordRequestType(CacheRequestType requestType)
+CacheMemory::recordRequestType(CacheRequestType requestType, Address addr)
 {
     DPRINTF(RubyStats, "Recorded statistic: %s\n",
             CacheRequestType_to_string(requestType));
     switch(requestType) {
     case CacheRequestType_DataArrayRead:
+        if (m_resource_stalls)
+            dataArray.reserve(addressToCacheSet(addr));
         numDataArrayReads++;
         return;
     case CacheRequestType_DataArrayWrite:
+        if (m_resource_stalls)
+            dataArray.reserve(addressToCacheSet(addr));
         numDataArrayWrites++;
         return;
     case CacheRequestType_TagArrayRead:
+        if (m_resource_stalls)
+            tagArray.reserve(addressToCacheSet(addr));
         numTagArrayReads++;
         return;
     case CacheRequestType_TagArrayWrite:
+        if (m_resource_stalls)
+            tagArray.reserve(addressToCacheSet(addr));
         numTagArrayWrites++;
         return;
     default:
diff -r 9b3b9be42dd9 -r 436d5dde4bb7 src/mem/ruby/structures/CacheMemory.hh
--- a/src/mem/ruby/structures/CacheMemory.hh    Mon Jul 20 09:15:18 2015 -0500
+++ b/src/mem/ruby/structures/CacheMemory.hh    Mon Jul 20 09:15:18 2015 -0500
@@ -117,7 +117,7 @@
 
     void regStats();
     bool checkResourceAvailable(CacheResourceType res, Address addr);
-    void recordRequestType(CacheRequestType requestType);
+    void recordRequestType(CacheRequestType requestType, Address addr);
 
   public:
     Stats::Scalar m_demand_hits;
_______________________________________________
gem5-dev mailing list
[email protected]
http://m5sim.org/mailman/listinfo/gem5-dev

Reply via email to