2 * Copyright (c) 2012 ARM Limited
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder. You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
14 * Copyright (c) 2002-2005 The Regents of The University of Michigan
15 * All rights reserved.
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions are
19 * met: redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer;
21 * redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution;
24 * neither the name of the copyright holders nor the names of its
25 * contributors may be used to endorse or promote products derived from
26 * this software without specific prior written permission.
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40 * Authors: Nathan Binkert
45 #ifndef __BASE_ADDR_RANGE_HH__
46 #define __BASE_ADDR_RANGE_HH__
50 #include "base/bitfield.hh"
51 #include "base/cprintf.hh"
52 #include "base/misc.hh"
53 #include "base/types.hh"
60 /// Private fields for the start and end of the range
64 /// The high bit of the slice that is used for interleaving
67 /// The number of bits used for interleaving, set to 0 to disable
70 /// The value to compare the slice addr[high:(high - bits + 1)]
77 : _start(1), _end(0), intlvHighBit(0), intlvBits(0), intlvMatch(0)
80 AddrRange(Addr _start, Addr _end, uint8_t _intlv_high_bit,
81 uint8_t _intlv_bits, uint8_t _intlv_match)
82 : _start(_start), _end(_end), intlvHighBit(_intlv_high_bit),
83 intlvBits(_intlv_bits), intlvMatch(_intlv_match)
86 AddrRange(Addr _start, Addr _end)
87 : _start(_start), _end(_end), intlvHighBit(0), intlvBits(0),
92 * Create an address range by merging a collection of interleaved
95 * @param ranges Interleaved ranges to be merged
97 AddrRange(const std::vector<AddrRange>& ranges)
98 : _start(1), _end(0), intlvHighBit(0), intlvBits(0), intlvMatch(0)
100 if (!ranges.empty()) {
101 // get the values from the first one and check the others
102 _start = ranges.front()._start;
103 _end = ranges.front()._end;
104 intlvHighBit = ranges.front().intlvHighBit;
105 intlvBits = ranges.front().intlvBits;
107 if (ranges.size() != (ULL(1) << intlvBits))
108 fatal("Got %d ranges spanning %d interleaving bits\n",
109 ranges.size(), intlvBits);
112 for (std::vector<AddrRange>::const_iterator r = ranges.begin();
113 r != ranges.end(); ++r) {
115 fatal("Can only merge ranges with the same start, end "
116 "and interleaving bits\n");
118 if (r->intlvMatch != match)
119 fatal("Expected interleave match %d but got %d when "
120 "merging\n", match, r->intlvMatch);
124 // our range is complete and we can turn this into a
125 // non-interleaved range
132 * Determine if the range is interleaved or not.
134 * @return true if interleaved
136 bool interleaved() const { return intlvBits != 0; }
139 * Determing the interleaving granularity of the range.
141 * @return The size of the regions created by the interleaving bits
143 uint64_t granularity() const
145 return ULL(1) << (intlvHighBit - intlvBits);
149 * Determine the number of interleaved address stripes this range
152 * @return The number of stripes spanned by the interleaving bits
154 uint32_t stripes() const { return ULL(1) << intlvBits; }
157 * Get the size of the address range. For a case where
158 * interleaving is used we make the simplifying assumption that
159 * the size is a divisible by the size of the interleaving slice.
163 return (_end - _start + 1) >> intlvBits;
167 * Determine if the range is valid.
169 bool valid() const { return _start < _end; }
172 * Get the start address of the range.
174 Addr start() const { return _start; }
177 * Get a string representation of the range. This could
178 * alternatively be implemented as a operator<<, but at the moment
179 * that seems like overkill.
181 std::string to_string() const
184 return csprintf("[%#llx : %#llx], [%d : %d] = %d", _start, _end,
185 intlvHighBit, intlvHighBit - intlvBits + 1,
188 return csprintf("[%#llx : %#llx]", _start, _end);
192 * Determine if another range merges with the current one, i.e. if
193 * they are part of the same contigous range and have the same
196 * @param r Range to evaluate merging with
197 * @return true if the two ranges would merge
199 bool mergesWith(const AddrRange& r) const
201 return r._start == _start && r._end == _end &&
202 r.intlvHighBit == intlvHighBit &&
203 r.intlvBits == intlvBits;
207 * Determine if another range intersects this one, i.e. if there
208 * is an address that is both in this range and the other
209 * range. No check is made to ensure either range is valid.
211 * @param r Range to intersect with
212 * @return true if the intersection of the two ranges is not empty
214 bool intersects(const AddrRange& r) const
216 if (!interleaved()) {
217 return _start <= r._end && _end >= r._start;
220 // the current range is interleaved, split the check up in
223 // keep it simple and check if the address is within
225 return contains(r.start());
226 else if (!r.interleaved())
227 // be conservative and ignore the interleaving
228 return _start <= r._end && _end >= r._start;
229 else if (mergesWith(r))
230 // restrict the check to ranges that belong to the
232 return intlvMatch == r.intlvMatch;
234 panic("Cannot test intersection of interleaved range %s\n",
239 * Determine if this range is a subset of another range, i.e. if
240 * every address in this range is also in the other range. No
241 * check is made to ensure either range is valid.
243 * @param r Range to compare with
244 * @return true if the this range is a subset of the other one
246 bool isSubset(const AddrRange& r) const
249 panic("Cannot test subset of interleaved range %s\n", to_string());
250 return _start >= r._start && _end <= r._end;
254 * Determine if the range contains an address.
256 * @param a Address to compare with
257 * @return true if the address is in the range
259 bool contains(const Addr& a) const
261 // check if the address is in the range and if there is either
262 // no interleaving, or with interleaving also if the selected
263 // bits from the address match the interleaving value
264 return a >= _start && a <= _end &&
266 (bits(a, intlvHighBit, intlvHighBit - intlvBits + 1) ==
271 * Keep the operators away from SWIG.
276 * Less-than operator used to turn an STL map into a binary search
277 * tree of non-overlapping address ranges.
279 * @param r Range to compare with
280 * @return true if the start address is less than that of the other range
282 bool operator<(const AddrRange& r) const
284 if (_start != r._start)
285 return _start < r._start;
287 // for now assume that the end is also the same, and that
288 // we are looking at the same interleaving bits
289 return intlvMatch < r.intlvMatch;
296 RangeEx(Addr start, Addr end)
297 { return AddrRange(start, end - 1); }
300 RangeIn(Addr start, Addr end)
301 { return AddrRange(start, end); }
304 RangeSize(Addr start, Addr size)
305 { return AddrRange(start, start + size - 1); }
307 #endif // __BASE_ADDR_RANGE_HH__