gem5  v20.0.0.0
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
addr_range.hh
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2012, 2014, 2017-2019 ARM Limited
3  * All rights reserved
4  *
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.
13  *
14  * Copyright (c) 2002-2005 The Regents of The University of Michigan
15  * All rights reserved.
16  *
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.
27  *
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.
39  */
40 
41 #ifndef __BASE_ADDR_RANGE_HH__
42 #define __BASE_ADDR_RANGE_HH__
43 
44 #include <algorithm>
45 #include <list>
46 #include <vector>
47 
48 #include "base/bitfield.hh"
49 #include "base/cprintf.hh"
50 #include "base/logging.hh"
51 #include "base/types.hh"
52 
68 class AddrRange
69 {
70 
71  private:
72 
78 
85 
87  uint8_t intlvMatch;
88 
89  public:
90 
92  : _start(1), _end(0), intlvMatch(0)
93  {}
94 
123  AddrRange(Addr _start, Addr _end, const std::vector<Addr> &_masks,
124  uint8_t _intlv_match)
125  : _start(_start), _end(_end), masks(_masks),
126  intlvMatch(_intlv_match)
127  {
128  // sanity checks
129  fatal_if(!masks.empty() && _intlv_match >= ULL(1) << masks.size(),
130  "Match value %d does not fit in %d interleaving bits\n",
131  _intlv_match, masks.size());
132  }
133 
158  AddrRange(Addr _start, Addr _end, uint8_t _intlv_high_bit,
159  uint8_t _xor_high_bit, uint8_t _intlv_bits,
160  uint8_t _intlv_match)
161  : _start(_start), _end(_end), masks(_intlv_bits),
162  intlvMatch(_intlv_match)
163  {
164  // sanity checks
165  fatal_if(_intlv_bits && _intlv_match >= ULL(1) << _intlv_bits,
166  "Match value %d does not fit in %d interleaving bits\n",
167  _intlv_match, _intlv_bits);
168 
169  // ignore the XOR bits if not interleaving
170  if (_intlv_bits && _xor_high_bit) {
171  if (_xor_high_bit == _intlv_high_bit) {
172  fatal("XOR and interleave high bit must be different\n");
173  } else if (_xor_high_bit > _intlv_high_bit) {
174  if ((_xor_high_bit - _intlv_high_bit) < _intlv_bits)
175  fatal("XOR and interleave high bit must be at least "
176  "%d bits apart\n", _intlv_bits);
177  } else {
178  if ((_intlv_high_bit - _xor_high_bit) < _intlv_bits) {
179  fatal("Interleave and XOR high bit must be at least "
180  "%d bits apart\n", _intlv_bits);
181  }
182  }
183  }
184 
185  for (auto i = 0; i < _intlv_bits; i++) {
186  uint8_t bit1 = _intlv_high_bit - i;
187  Addr mask = (1ULL << bit1);
188  if (_xor_high_bit) {
189  uint8_t bit2 = _xor_high_bit - i;
190  mask |= (1ULL << bit2);
191  }
192  masks[_intlv_bits - i - 1] = mask;
193  }
194  }
195 
196  AddrRange(Addr _start, Addr _end)
197  : _start(_start), _end(_end), intlvMatch(0)
198  {}
199 
207  : _start(1), _end(0), intlvMatch(0)
208  {
209  if (!ranges.empty()) {
210  // get the values from the first one and check the others
211  _start = ranges.front()._start;
212  _end = ranges.front()._end;
213  masks = ranges.front().masks;
214  intlvMatch = ranges.front().intlvMatch;
215  }
216  // either merge if got all ranges or keep this equal to the single
217  // interleaved range
218  if (ranges.size() > 1) {
219 
220  if (ranges.size() != (ULL(1) << masks.size()))
221  fatal("Got %d ranges spanning %d interleaving bits\n",
222  ranges.size(), masks.size());
223 
224  uint8_t match = 0;
225  for (const auto& r : ranges) {
226  if (!mergesWith(r))
227  fatal("Can only merge ranges with the same start, end "
228  "and interleaving bits, %s %s\n", to_string(),
229  r.to_string());
230 
231  if (r.intlvMatch != match)
232  fatal("Expected interleave match %d but got %d when "
233  "merging\n", match, r.intlvMatch);
234  ++match;
235  }
236  masks.clear();
237  intlvMatch = 0;
238  }
239  }
240 
246  bool interleaved() const { return masks.size() > 0; }
247 
253  uint64_t granularity() const
254  {
255  if (interleaved()) {
256  auto combined_mask = 0;
257  for (auto mask: masks) {
258  combined_mask |= mask;
259  }
260  const uint8_t lowest_bit = ctz64(combined_mask);
261  return ULL(1) << lowest_bit;
262  } else {
263  return size();
264  }
265  }
266 
273  uint32_t stripes() const { return ULL(1) << masks.size(); }
274 
280  Addr size() const
281  {
282  return (_end - _start) >> masks.size();
283  }
284 
288  bool valid() const { return _start <= _end; }
289 
293  Addr start() const { return _start; }
294 
298  Addr end() const { return _end; }
299 
305  std::string to_string() const
306  {
307  if (interleaved()) {
308  std::string str;
309  for (int i = 0; i < masks.size(); i++) {
310  str += " ";
311  Addr mask = masks[i];
312  while (mask) {
313  auto bit = ctz64(mask);
314  mask &= ~(1ULL << bit);
315  str += csprintf("a[%d]^", bit);
316  }
317  str += csprintf("\b=%d", bits(intlvMatch, i));
318  }
319  return csprintf("[%#llx:%#llx]%s", _start, _end, str);
320  } else {
321  return csprintf("[%#llx:%#llx]", _start, _end);
322  }
323  }
324 
333  bool mergesWith(const AddrRange& r) const
334  {
335  return r._start == _start && r._end == _end &&
336  r.masks == masks;
337  }
338 
347  bool intersects(const AddrRange& r) const
348  {
349  if (_start >= r._end || _end <= r._start)
350  // start with the simple case of no overlap at all,
351  // applicable even if we have interleaved ranges
352  return false;
353  else if (!interleaved() && !r.interleaved())
354  // if neither range is interleaved, we are done
355  return true;
356 
357  // now it gets complicated, focus on the cases we care about
358  if (r.size() == 1)
359  // keep it simple and check if the address is within
360  // this range
361  return contains(r.start());
362  else if (mergesWith(r))
363  // restrict the check to ranges that belong to the
364  // same chunk
365  return intlvMatch == r.intlvMatch;
366  else
367  panic("Cannot test intersection of %s and %s\n",
368  to_string(), r.to_string());
369  }
370 
379  bool isSubset(const AddrRange& r) const
380  {
381  if (interleaved())
382  panic("Cannot test subset of interleaved range %s\n", to_string());
383 
384  // This address range is not interleaved and therefore it
385  // suffices to check the upper bound, the lower bound and
386  // whether it would fit in a continuous segment of the input
387  // addr range.
388  if (r.interleaved()) {
389  return r.contains(_start) && r.contains(_end - 1) &&
390  size() <= r.granularity();
391  } else {
392  return _start >= r._start && _end <= r._end;
393  }
394  }
395 
402  bool contains(const Addr& a) const
403  {
404  // check if the address is in the range and if there is either
405  // no interleaving, or with interleaving also if the selected
406  // bits from the address match the interleaving value
407  bool in_range = a >= _start && a < _end;
408  if (in_range) {
409  auto sel = 0;
410  for (int i = 0; i < masks.size(); i++) {
411  Addr masked = a & masks[i];
412  // The result of an xor operation is 1 if the number
413  // of bits set is odd or 0 othersize, thefore it
414  // suffices to count the number of bits set to
415  // determine the i-th bit of sel.
416  sel |= (popCount(masked) % 2) << i;
417  }
418  return sel == intlvMatch;
419  }
420  return false;
421  }
422 
445  inline Addr removeIntlvBits(Addr a) const
446  {
447  // Get the LSB set from each mask
448  int masks_lsb[masks.size()];
449  for (int i = 0; i < masks.size(); i++) {
450  masks_lsb[i] = ctz64(masks[i]);
451  }
452 
453  // we need to sort the list of bits we will discard as we
454  // discard them one by one starting.
455  std::sort(masks_lsb, masks_lsb + masks.size());
456 
457  for (int i = 0; i < masks.size(); i++) {
458  const int intlv_bit = masks_lsb[i];
459  if (intlv_bit > 0) {
460  // on every iteration we remove one bit from the input
461  // address, and therefore the lowest invtl_bit has
462  // also shifted to the right by i positions.
463  a = insertBits(a >> 1, intlv_bit - i - 1, 0, a);
464  } else {
465  a >>= 1;
466  }
467  }
468  return a;
469  }
470 
475  inline Addr addIntlvBits(Addr a) const
476  {
477  // Get the LSB set from each mask
478  int masks_lsb[masks.size()];
479  for (int i = 0; i < masks.size(); i++) {
480  masks_lsb[i] = ctz64(masks[i]);
481  }
482 
483  // Add bits one-by-one from the LSB side.
484  std::sort(masks_lsb, masks_lsb + masks.size());
485  for (int i = 0; i < masks.size(); i++) {
486  const int intlv_bit = masks_lsb[i];
487  if (intlv_bit > 0) {
488  // on every iteration we add one bit from the input
489  // address, and therefore the lowest invtl_bit has
490  // also shifted to the left by i positions.
491  a = insertBits(a << 1, intlv_bit + i - 1, 0, a);
492  } else {
493  a <<= 1;
494  }
495  }
496 
497  for (int i = 0; i < masks.size(); i++) {
498  const int lsb = ctz64(masks[i]);
499  const Addr intlv_bit = bits(intlvMatch, i);
500  // Calculate the mask ignoring the LSB
501  const Addr masked = a & masks[i] & ~(1 << lsb);
502  // Set the LSB of the mask to whatever satisfies the selector bit
503  a = insertBits(a, lsb, intlv_bit ^ popCount(masked));
504  }
505 
506  return a;
507  }
508 
520  Addr getOffset(const Addr& a) const
521  {
522  bool in_range = a >= _start && a < _end;
523  if (!in_range) {
524  return MaxAddr;
525  }
526  if (interleaved()) {
527  return removeIntlvBits(a) - removeIntlvBits(_start);
528  } else {
529  return a - _start;
530  }
531  }
532 
540  bool operator<(const AddrRange& r) const
541  {
542  if (_start != r._start)
543  return _start < r._start;
544  else
545  // for now assume that the end is also the same, and that
546  // we are looking at the same interleaving bits
547  return intlvMatch < r.intlvMatch;
548  }
549 
550  bool operator==(const AddrRange& r) const
551  {
552  if (_start != r._start) return false;
553  if (_end != r._end) return false;
554  if (masks != r.masks) return false;
555  if (intlvMatch != r.intlvMatch) return false;
556 
557  return true;
558  }
559 
560  bool operator!=(const AddrRange& r) const
561  {
562  return !(*this == r);
563  }
564 };
565 
570 
571 inline AddrRange
573 { return AddrRange(start, end); }
574 
575 inline AddrRange
577 { return AddrRange(start, end + 1); }
578 
579 inline AddrRange
581 { return AddrRange(start, start + size); }
582 
583 #endif // __BASE_ADDR_RANGE_HH__
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:163
AddrRange RangeSize(Addr start, Addr size)
Definition: addr_range.hh:580
int ctz64(uint64_t value)
Count trailing zeros in a 64-bit value.
Definition: bitfield.hh:308
#define fatal(...)
This implements a cprintf based fatal() function.
Definition: logging.hh:171
const Addr MaxAddr
Definition: types.hh:164
Bitfield< 7 > i
bool operator!=(const AddrRange &r) const
Definition: addr_range.hh:560
std::list< AddrRange > AddrRangeList
Convenience typedef for a collection of address ranges.
Definition: addr_range.hh:569
uint64_t granularity() const
Determing the interleaving granularity of the range.
Definition: addr_range.hh:253
bool contains(const Addr &a) const
Determine if the range contains an address.
Definition: addr_range.hh:402
Bitfield< 8 > a
bool isSubset(const AddrRange &r) const
Determine if this range is a subset of another range, i.e.
Definition: addr_range.hh:379
std::vector< Addr > masks
Each mask determines the bits we need to xor to get one bit of sel.
Definition: addr_range.hh:84
uint8_t intlvMatch
The value to compare sel with.
Definition: addr_range.hh:87
Addr removeIntlvBits(Addr a) const
Remove the interleaving bits from an input address.
Definition: addr_range.hh:445
uint32_t stripes() const
Determine the number of interleaved address stripes this range is part of.
Definition: addr_range.hh:273
int popCount(uint64_t val)
Returns the number of set ones in the provided value.
Definition: bitfield.hh:248
bool intersects(const AddrRange &r) const
Determine if another range intersects this one, i.e.
Definition: addr_range.hh:347
bool valid() const
Determine if the range is valid.
Definition: addr_range.hh:288
Addr _start
Private fields for the start and end of the range _start is the beginning of the range (inclusive)...
Definition: addr_range.hh:76
The AddrRange class encapsulates an address range, and supports a number of tests to check if two ran...
Definition: addr_range.hh:68
AddrRange(const std::vector< AddrRange > &ranges)
Create an address range by merging a collection of interleaved ranges.
Definition: addr_range.hh:206
std::string csprintf(const char *format, const Args &...args)
Definition: cprintf.hh:158
Addr end() const
Get the end address of the range.
Definition: addr_range.hh:298
Addr addIntlvBits(Addr a) const
This method adds the interleaving bits removed by removeIntlvBits.
Definition: addr_range.hh:475
bool operator<(const AddrRange &r) const
Less-than operator used to turn an STL map into a binary search tree of non-overlapping address range...
Definition: addr_range.hh:540
#define fatal_if(cond,...)
Conditional fatal macro that checks the supplied condition and only causes a fatal error if the condi...
Definition: logging.hh:199
T insertBits(T val, int first, int last, B bit_val)
Returns val with bits first to last set to the LSBs of bit_val.
Definition: bitfield.hh:131
Addr _end
Definition: addr_range.hh:77
AddrRange RangeIn(Addr start, Addr end)
Definition: addr_range.hh:576
AddrRange(Addr _start, Addr _end)
Definition: addr_range.hh:196
Defines global host-dependent types: Counter, Tick, and (indirectly) {int,uint}{8,16,32,64}_t.
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:140
#define ULL(N)
uint64_t constant
Definition: types.hh:48
AddrRange RangeEx(Addr start, Addr end)
Definition: addr_range.hh:572
bool operator==(const AddrRange &r) const
Definition: addr_range.hh:550
bool mergesWith(const AddrRange &r) const
Determine if another range merges with the current one, i.e.
Definition: addr_range.hh:333
bool interleaved() const
Determine if the range is interleaved or not.
Definition: addr_range.hh:246
AddrRange(Addr _start, Addr _end, const std::vector< Addr > &_masks, uint8_t _intlv_match)
Construct an address range.
Definition: addr_range.hh:123
AddrRange(Addr _start, Addr _end, uint8_t _intlv_high_bit, uint8_t _xor_high_bit, uint8_t _intlv_bits, uint8_t _intlv_match)
Legacy constructor of AddrRange.
Definition: addr_range.hh:158
Addr start() const
Get the start address of the range.
Definition: addr_range.hh:293
Addr getOffset(const Addr &a) const
Determine the offset of an address within the range.
Definition: addr_range.hh:520
Addr size() const
Get the size of the address range.
Definition: addr_range.hh:280
Bitfield< 3, 0 > mask
Definition: types.hh:62
std::string to_string() const
Get a string representation of the range.
Definition: addr_range.hh:305
T bits(T val, int first, int last)
Extract the bitfield from position &#39;first&#39; to &#39;last&#39; (inclusive) from &#39;val&#39; and right justify it...
Definition: bitfield.hh:71

Generated on Thu May 28 2020 16:21:29 for gem5 by doxygen 1.8.13