summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Hansson <andreas.hansson@arm.com>2013-03-01 13:20:19 -0500
committerAndreas Hansson <andreas.hansson@arm.com>2013-03-01 13:20:19 -0500
commitcafd38f36c4d71c3f3d6efaf0023aec2cfc51b32 (patch)
tree713f70f114707f5cd8765937c44e03f87ec0df01
parentc636a09e83b08c27ce60a0f1d13536d736a06926 (diff)
downloadgem5-cafd38f36c4d71c3f3d6efaf0023aec2cfc51b32.tar.xz
mem: Merge ranges in bus before passing them on
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.
-rw-r--r--src/mem/bus.cc114
-rw-r--r--src/mem/bus.hh3
2 files changed, 77 insertions, 40 deletions
diff --git a/src/mem/bus.cc b/src/mem/bus.cc
index 1de1ac1e3..d29422593 100644
--- a/src/mem/bus.cc
+++ b/src/mem/bus.cc
@@ -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
diff --git a/src/mem/bus.hh b/src/mem/bus.hh
index 35c206fa9..705a3a999 100644
--- a/src/mem/bus.hh
+++ b/src/mem/bus.hh
@@ -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;
/**