mem: Merge ranges in bus before passing them on
authorAndreas Hansson <andreas.hansson@arm.com>
Fri, 1 Mar 2013 18:20:19 +0000 (13:20 -0500)
committerAndreas Hansson <andreas.hansson@arm.com>
Fri, 1 Mar 2013 18:20:19 +0000 (13:20 -0500)
This patch adds basic merging of address ranges to the bus, such that
interleaved ranges are merged together before being passed on by the
bus. As such, the bus aggregates the address ranges of the connected
slave ports and then passes on the merged ranges through its master
ports. The bus thus hides the complexity of the interleaved ranges and
only exposes contigous ranges to the surrounding system.

As part of this patch, the bus ranges are also cached for any future
queries.

src/mem/bus.cc
src/mem/bus.hh

index 1de1ac1e36b6bc6a3bf4a9202c4af08abff1a7f1..d29422593214fd3971b8a5c6410988c1afa0a459 100644 (file)
@@ -442,31 +442,83 @@ BaseBus::recvRangeChange(PortID master_port_id)
     // modules, go ahead and tell our connected master modules in
     // turn, this effectively assumes a tree structure of the system
     if (gotAllAddrRanges) {
+        DPRINTF(BusAddrRanges, "Aggregating bus ranges\n");
+        busRanges.clear();
+
+        // start out with the default range
+        if (useDefaultRange) {
+            if (!gotAddrRanges[defaultPortID])
+                fatal("Bus %s uses default range, but none provided",
+                      name());
+
+            busRanges.push_back(defaultRange);
+            DPRINTF(BusAddrRanges, "-- Adding default %s\n",
+                    defaultRange.to_string());
+        }
+
+        // merge all interleaved ranges and add any range that is not
+        // a subset of the default range
+        std::vector<AddrRange> intlv_ranges;
+        for (AddrRangeMap<PortID>::const_iterator r = portMap.begin();
+             r != portMap.end(); ++r) {
+            // if the range is interleaved then save it for now
+            if (r->first.interleaved()) {
+                // if we already got interleaved ranges that are not
+                // part of the same range, then first do a merge
+                // before we add the new one
+                if (!intlv_ranges.empty() &&
+                    !intlv_ranges.back().mergesWith(r->first)) {
+                    DPRINTF(BusAddrRanges, "-- Merging range from %d ranges\n",
+                            intlv_ranges.size());
+                    AddrRange merged_range(intlv_ranges);
+                    // next decide if we keep the merged range or not
+                    if (!(useDefaultRange &&
+                          merged_range.isSubset(defaultRange))) {
+                        busRanges.push_back(merged_range);
+                        DPRINTF(BusAddrRanges, "-- Adding merged range %s\n",
+                                merged_range.to_string());
+                    }
+                    intlv_ranges.clear();
+                }
+                intlv_ranges.push_back(r->first);
+            } else {
+                // keep the current range if not a subset of the default
+                if (!(useDefaultRange &&
+                      r->first.isSubset(defaultRange))) {
+                    busRanges.push_back(r->first);
+                    DPRINTF(BusAddrRanges, "-- Adding range %s\n",
+                            r->first.to_string());
+                }
+            }
+        }
+
+        // if there is still interleaved ranges waiting to be merged,
+        // go ahead and do it
+        if (!intlv_ranges.empty()) {
+            DPRINTF(BusAddrRanges, "-- Merging range from %d ranges\n",
+                    intlv_ranges.size());
+            AddrRange merged_range(intlv_ranges);
+            if (!(useDefaultRange && merged_range.isSubset(defaultRange))) {
+                busRanges.push_back(merged_range);
+                DPRINTF(BusAddrRanges, "-- Adding merged range %s\n",
+                        merged_range.to_string());
+            }
+        }
+
         // also check that no range partially overlaps with the
         // default range, this has to be done after all ranges are set
         // as there are no guarantees for when the default range is
         // update with respect to the other ones
         if (useDefaultRange) {
-            for (PortID port_id = 0; port_id < masterPorts.size(); ++port_id) {
-                if (port_id == defaultPortID) {
-                    if (!gotAddrRanges[port_id])
-                        fatal("Bus %s uses default range, but none provided",
-                              name());
-                } else {
-                    AddrRangeList ranges =
-                        masterPorts[port_id]->getAddrRanges();
-
-                    for (AddrRangeConstIter r = ranges.begin();
-                         r != ranges.end(); ++r) {
-                        // see if the new range is partially
-                        // overlapping the default range
-                        if (r->intersects(defaultRange) &&
-                            !r->isSubset(defaultRange))
-                            fatal("Range %s intersects the " \
-                                  "default range of %s but is not a " \
-                                  "subset\n", r->to_string(), name());
-                    }
-                }
+            for (AddrRangeConstIter r = busRanges.begin();
+                 r != busRanges.end(); ++r) {
+                // see if the new range is partially
+                // overlapping the default range
+                if (r->intersects(defaultRange) &&
+                    !r->isSubset(defaultRange))
+                    fatal("Range %s intersects the "                    \
+                          "default range of %s but is not a "           \
+                          "subset\n", r->to_string(), name());
             }
         }
 
@@ -493,27 +545,9 @@ BaseBus::getAddrRanges() const
     // (CPU, cache, bridge etc) actually care about the ranges of the
     // ports they are connected to
 
-    DPRINTF(BusAddrRanges, "Received address range request, returning:\n");
-
-    // start out with the default range
-    AddrRangeList ranges;
-    if (useDefaultRange) {
-        ranges.push_back(defaultRange);
-        DPRINTF(BusAddrRanges, "  -- Default %s\n", defaultRange.to_string());
-    }
-
-    // add any range that is not a subset of the default range
-    for (PortMapConstIter p = portMap.begin(); p != portMap.end(); ++p) {
-        if (useDefaultRange && p->first.isSubset(defaultRange)) {
-            DPRINTF(BusAddrRanges, "  -- %s is a subset of default\n",
-                    p->first.to_string());
-        } else {
-            ranges.push_back(p->first);
-            DPRINTF(BusAddrRanges, "  -- %s\n", p->first.to_string());
-        }
-    }
+    DPRINTF(BusAddrRanges, "Received address range request\n");
 
-    return ranges;
+    return busRanges;
 }
 
 unsigned
index 35c206fa94369d47ed9fde9babac3ecd835df0fc..705a3a999cd2a9d6df943b49cd8abd717a4db14d 100644 (file)
@@ -232,6 +232,9 @@ class BaseBus : public MemObject
     typedef AddrRangeMap<PortID>::const_iterator PortMapConstIter;
     AddrRangeMap<PortID> portMap;
 
+    /** all contigous ranges seen by this bus */
+    AddrRangeList busRanges;
+
     AddrRange defaultRange;
 
     /**