summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Hashe <david.hashe@amd.com>2015-07-20 09:15:18 -0500
committerDavid Hashe <david.hashe@amd.com>2015-07-20 09:15:18 -0500
commit21aa5734a0f2c03263e26c66e5cd95ad64c70697 (patch)
tree43cf18ec392aea120c025bf818a0ce30efab201c
parent63a9f10de80a2a117aa06858e65dee2b6654762f (diff)
downloadgem5-21aa5734a0f2c03263e26c66e5cd95ad64c70697.tar.xz
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.
-rw-r--r--src/mem/protocol/RubySlicc_Types.sm2
-rw-r--r--src/mem/ruby/structures/BankedArray.cc28
-rw-r--r--src/mem/ruby/structures/BankedArray.hh2
-rw-r--r--src/mem/ruby/structures/CacheMemory.cc12
-rw-r--r--src/mem/ruby/structures/CacheMemory.hh2
5 files changed, 36 insertions, 10 deletions
diff --git a/src/mem/protocol/RubySlicc_Types.sm b/src/mem/protocol/RubySlicc_Types.sm
index 6c3c4168d..11159fd6c 100644
--- a/src/mem/protocol/RubySlicc_Types.sm
+++ b/src/mem/protocol/RubySlicc_Types.sm
@@ -154,7 +154,7 @@ structure (CacheMemory, external = "yes") {
Cycles getTagLatency();
Cycles getDataLatency();
void setMRU(Address);
- void recordRequestType(CacheRequestType);
+ void recordRequestType(CacheRequestType, Address);
bool checkResourceAvailable(CacheResourceType, Address);
int getCacheSize();
diff --git a/src/mem/ruby/structures/BankedArray.cc b/src/mem/ruby/structures/BankedArray.cc
index dbde2ab9a..8bc3cf584 100644
--- a/src/mem/ruby/structures/BankedArray.cc
+++ b/src/mem/ruby/structures/BankedArray.cc
@@ -58,13 +58,29 @@ BankedArray::tryAccess(int64 idx)
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 @@ BankedArray::tryAccess(int64 idx)
busyBanks[bank].startAccess = curTick();
busyBanks[bank].endAccess = curTick() +
(accessLatency-1) * m_ruby_system->clockPeriod();
-
- return true;
}
unsigned int
diff --git a/src/mem/ruby/structures/BankedArray.hh b/src/mem/ruby/structures/BankedArray.hh
index dbfee9994..438186944 100644
--- a/src/mem/ruby/structures/BankedArray.hh
+++ b/src/mem/ruby/structures/BankedArray.hh
@@ -70,6 +70,8 @@ class BankedArray
// 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 --git a/src/mem/ruby/structures/CacheMemory.cc b/src/mem/ruby/structures/CacheMemory.cc
index c802d8fb6..d08724cff 100644
--- a/src/mem/ruby/structures/CacheMemory.cc
+++ b/src/mem/ruby/structures/CacheMemory.cc
@@ -528,22 +528,32 @@ CacheMemory::regStats()
;
}
+// 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 --git a/src/mem/ruby/structures/CacheMemory.hh b/src/mem/ruby/structures/CacheMemory.hh
index c9c20d8b8..af5e680d8 100644
--- a/src/mem/ruby/structures/CacheMemory.hh
+++ b/src/mem/ruby/structures/CacheMemory.hh
@@ -117,7 +117,7 @@ class CacheMemory : public SimObject
void regStats();
bool checkResourceAvailable(CacheResourceType res, Address addr);
- void recordRequestType(CacheRequestType requestType);
+ void recordRequestType(CacheRequestType requestType, Address addr);
public:
Stats::Scalar m_demand_hits;