mem-ruby: fix downstream destinations

AddrRangeMap::intersects doesn't support ranges with different
interleavings, thus the current implementation of the destination
seach won't work in cases when different machines map the same address
with different interleaving.

The fixed implementation uses a different AddrRangeMap for each mach
type.

Change-Id: Idd0184da343c46c92a4c86f142938902096c2b1f
Signed-off-by: Tiago Mück <tiago.muck@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/63671
Tested-by: kokoro <noreply+kokoro@google.com>
Maintainer: Bobby Bruce <bbruce@ucdavis.edu>
Reviewed-by: Jason Lowe-Power <power.jg@gmail.com>
diff --git a/src/mem/ruby/slicc_interface/AbstractController.cc b/src/mem/ruby/slicc_interface/AbstractController.cc
index e11d780..2d13a5a 100644
--- a/src/mem/ruby/slicc_interface/AbstractController.cc
+++ b/src/mem/ruby/slicc_interface/AbstractController.cc
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017,2019-2021 ARM Limited
+ * Copyright (c) 2017,2019-2022 ARM Limited
  * All rights reserved.
  *
  * The license below extends only to copyright in the software and shall
@@ -96,15 +96,13 @@
         MachineID mid = abs_cntrl->getMachineID();
         const AddrRangeList &ranges = abs_cntrl->getAddrRanges();
         for (const auto &addr_range : ranges) {
-            auto i = downstreamAddrMap.intersects(addr_range);
-            if (i == downstreamAddrMap.end()) {
-                i = downstreamAddrMap.insert(addr_range, AddrMapEntry());
+            auto i = downstreamAddrMap.find(mid.getType());
+            if ((i != downstreamAddrMap.end()) &&
+                (i->second.intersects(addr_range) != i->second.end())) {
+                fatal("%s: %s mapped to multiple machines of the same type\n",
+                    name(), addr_range.to_string());
             }
-            AddrMapEntry &entry = i->second;
-            fatal_if(entry.count(mid.getType()) > 0,
-                     "%s: %s mapped to multiple machines of the same type\n",
-                     name(), addr_range.to_string());
-            entry[mid.getType()] = mid;
+            downstreamAddrMap[mid.getType()].insert(addr_range, mid);
         }
         downstreamDestinations.add(mid);
     }
@@ -419,23 +417,24 @@
 AbstractController::mapAddressToDownstreamMachine(Addr addr, MachineType mtype)
 const
 {
-    const auto i = downstreamAddrMap.contains(addr);
-    fatal_if(i == downstreamAddrMap.end(),
-      "%s: couldn't find mapping for address %x\n", name(), addr);
-
-    const AddrMapEntry &entry = i->second;
-    assert(!entry.empty());
-
     if (mtype == MachineType_NUM) {
-        fatal_if(entry.size() > 1,
-          "%s: address %x mapped to multiple machine types.\n", name(), addr);
-        return entry.begin()->second;
-    } else {
-        auto j = entry.find(mtype);
-        fatal_if(j == entry.end(),
-          "%s: couldn't find mapping for address %x\n", name(), addr);
-        return j->second;
+        // map to the first match
+        for (const auto &i : downstreamAddrMap) {
+            const auto mapping = i.second.contains(addr);
+            if (mapping != i.second.end())
+                return mapping->second;
+        }
     }
+    else {
+        const auto i = downstreamAddrMap.find(mtype);
+        if (i != downstreamAddrMap.end()) {
+            const auto mapping = i->second.contains(addr);
+            if (mapping != i->second.end())
+                return mapping->second;
+        }
+    }
+    fatal("%s: couldn't find mapping for address %x mtype=%s\n",
+        name(), addr, mtype);
 }
 
 
diff --git a/src/mem/ruby/slicc_interface/AbstractController.hh b/src/mem/ruby/slicc_interface/AbstractController.hh
index 19cfe51..a5ab5c2 100644
--- a/src/mem/ruby/slicc_interface/AbstractController.hh
+++ b/src/mem/ruby/slicc_interface/AbstractController.hh
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017,2019-2021 ARM Limited
+ * Copyright (c) 2017,2019-2022 ARM Limited
  * All rights reserved.
  *
  * The license below extends only to copyright in the software and shall
@@ -405,9 +405,8 @@
     /** The address range to which the controller responds on the CPU side. */
     const AddrRangeList addrRanges;
 
-    typedef std::unordered_map<MachineType, MachineID> AddrMapEntry;
-
-    AddrRangeMap<AddrMapEntry, 3> downstreamAddrMap;
+    std::unordered_map<MachineType, AddrRangeMap<MachineID, 3>>
+      downstreamAddrMap;
 
     NetDest downstreamDestinations;
     NetDest upstreamDestinations;