From b8c2fa6ba9850d079574ca6d7c91b93dcd3aacb8 Mon Sep 17 00:00:00 2001 From: Andreas Hansson Date: Mon, 7 Jan 2013 13:05:38 -0500 Subject: [PATCH] base: Add support for merging of interleaved address ranges This patch adds support for merging a vector of interleaved address ranges into a contigous range. The functionality will be used in the interconnect and the PhysicalMemory to transform interleaved memory ranges to contigous ranges before passing them on. The actual use of the merging is appearing in future patches. --- src/base/addr_range.hh | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/src/base/addr_range.hh b/src/base/addr_range.hh index edcc0bf2f..546d81611 100644 --- a/src/base/addr_range.hh +++ b/src/base/addr_range.hh @@ -45,6 +45,8 @@ #ifndef __BASE_ADDR_RANGE_HH__ #define __BASE_ADDR_RANGE_HH__ +#include + #include "base/bitfield.hh" #include "base/cprintf.hh" #include "base/misc.hh" @@ -86,6 +88,46 @@ class AddrRange intlvMatch(0) {} + /** + * Create an address range by merging a collection of interleaved + * ranges. + * + * @param ranges Interleaved ranges to be merged + */ + AddrRange(const std::vector& ranges) + : _start(1), _end(0), intlvHighBit(0), intlvBits(0), intlvMatch(0) + { + if (!ranges.empty()) { + // get the values from the first one and check the others + _start = ranges.front()._start; + _end = ranges.front()._end; + intlvHighBit = ranges.front().intlvHighBit; + intlvBits = ranges.front().intlvBits; + + if (ranges.size() != (ULL(1) << intlvBits)) + fatal("Got %d ranges spanning %d interleaving bits\n", + ranges.size(), intlvBits); + + uint8_t match = 0; + for (std::vector::const_iterator r = ranges.begin(); + r != ranges.end(); ++r) { + if (!mergesWith(*r)) + fatal("Can only merge ranges with the same start, end " + "and interleaving bits\n"); + + if (r->intlvMatch != match) + fatal("Expected interleave match %d but got %d when " + "merging\n", match, r->intlvMatch); + ++match; + } + + // our range is complete and we can turn this into a + // non-interleaved range + intlvHighBit = 0; + intlvBits = 0; + } + } + /** * Determine if the range is interleaved or not. * -- 2.30.2