From cafd38f36c4d71c3f3d6efaf0023aec2cfc51b32 Mon Sep 17 00:00:00 2001 From: Andreas Hansson Date: Fri, 1 Mar 2013 13:20:19 -0500 Subject: 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. --- src/mem/bus.cc | 114 +++++++++++++++++++++++++++++++++++++-------------------- src/mem/bus.hh | 3 ++ 2 files changed, 77 insertions(+), 40 deletions(-) (limited to 'src/mem') 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 intlv_ranges; + for (AddrRangeMap::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::const_iterator PortMapConstIter; AddrRangeMap portMap; + /** all contigous ranges seen by this bus */ + AddrRangeList busRanges; + AddrRange defaultRange; /** -- cgit v1.2.3