gem5 [DEVELOP-FOR-25.1]
Loading...
Searching...
No Matches
addr_range.hh
Go to the documentation of this file.
1/*
2 * Copyright (c) 2012, 2014, 2017-2019, 2021 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 <iterator>
46#include <list>
47#include <vector>
48
49#include "base/bitfield.hh"
50#include "base/cprintf.hh"
51#include "base/logging.hh"
52#include "base/types.hh"
53
54namespace gem5
55{
56
57class AddrRange;
58
65
82{
83
84 private:
85
91
98
100 uint8_t intlvMatch;
101
102 protected:
103 struct Dummy {};
104
105 // The dummy parameter Dummy distinguishes this from the other two argument
106 // constructor which takes two Addrs.
107 template <class Iterator>
108 AddrRange(Dummy, Iterator begin_it, Iterator end_it)
109 : _start(1), _end(0), intlvMatch(0)
110 {
111 if (begin_it != end_it) {
112 // get the values from the first one and check the others
113 _start = begin_it->_start;
114 _end = begin_it->_end;
115 masks = begin_it->masks;
116 intlvMatch = begin_it->intlvMatch;
117 }
118
119 auto count = std::distance(begin_it, end_it);
120 // either merge if got all ranges or keep this equal to the single
121 // interleaved range
122 if (count > 1) {
123 fatal_if(count != (1ULL << masks.size()),
124 "Got %d ranges spanning %d interleaving bits.",
125 count, masks.size());
126
127 uint8_t match = 0;
128 for (auto it = begin_it; it != end_it; it++) {
129 fatal_if(!mergesWith(*it),
130 "Can only merge ranges with the same start, end "
131 "and interleaving bits, %s %s.", to_string(),
132 it->to_string());
133
134 fatal_if(it->intlvMatch != match,
135 "Expected interleave match %d but got %d when "
136 "merging.", match, it->intlvMatch);
137 ++match;
138 }
139 masks.clear();
140 intlvMatch = 0;
141 }
142 }
143
144 public:
145
150 : _start(1), _end(0), intlvMatch(0)
151 {}
152
184 uint8_t _intlv_match)
185 : _start(_start), _end(_end), masks(_masks),
186 intlvMatch(_intlv_match)
187 {
188 // sanity checks
189 fatal_if(!masks.empty() && _intlv_match >= 1ULL << masks.size(),
190 "Match value %d does not fit in %d interleaving bits\n",
191 _intlv_match, masks.size());
192 }
193
220 AddrRange(Addr _start, Addr _end, uint8_t _intlv_high_bit,
221 uint8_t _xor_high_bit, uint8_t _intlv_bits,
222 uint8_t _intlv_match)
223 : _start(_start), _end(_end), masks(_intlv_bits),
224 intlvMatch(_intlv_match)
225 {
226 // sanity checks
227 fatal_if(_intlv_bits && _intlv_match >= 1ULL << _intlv_bits,
228 "Match value %d does not fit in %d interleaving bits\n",
229 _intlv_match, _intlv_bits);
230
231 // ignore the XOR bits if not interleaving
232 if (_intlv_bits && _xor_high_bit) {
233 if (_xor_high_bit == _intlv_high_bit) {
234 fatal("XOR and interleave high bit must be different\n");
235 } else if (_xor_high_bit > _intlv_high_bit) {
236 if ((_xor_high_bit - _intlv_high_bit) < _intlv_bits)
237 fatal("XOR and interleave high bit must be at least "
238 "%d bits apart\n", _intlv_bits);
239 } else {
240 if ((_intlv_high_bit - _xor_high_bit) < _intlv_bits) {
241 fatal("Interleave and XOR high bit must be at least "
242 "%d bits apart\n", _intlv_bits);
243 }
244 }
245 }
246
247 for (auto i = 0; i < _intlv_bits; i++) {
248 uint8_t bit1 = _intlv_high_bit - i;
249 Addr mask = (1ULL << bit1);
250 if (_xor_high_bit) {
251 uint8_t bit2 = _xor_high_bit - i;
252 mask |= (1ULL << bit2);
253 }
254 masks[_intlv_bits - i - 1] = mask;
255 }
256 }
257
261
271 : AddrRange(Dummy{}, ranges.begin(), ranges.end())
272 {}
274 : AddrRange(Dummy{}, ranges.begin(), ranges.end())
275 {}
276
284 bool interleaved() const { return masks.size() > 0; }
285
293 uint64_t
295 {
296 if (interleaved()) {
297 auto combined_mask = 0;
298 for (auto mask: masks) {
299 combined_mask |= mask;
300 }
301 const uint8_t lowest_bit = ctz64(combined_mask);
302 return 1ULL << lowest_bit;
303 } else {
304 return size();
305 }
306 }
307
316 uint32_t stripes() const { return 1ULL << masks.size(); }
317
325 Addr
326 size() const
327 {
328 return (_end - _start) >> masks.size();
329 }
330
336 bool valid() const { return _start <= _end; }
337
343 Addr start() const { return _start; }
344
350 Addr end() const { return _end; }
351
359 std::string
360 to_string() const
361 {
362 if (interleaved()) {
363 std::string str;
364 for (unsigned int i = 0; i < masks.size(); i++) {
365 str += " ";
366 Addr mask = masks[i];
367 while (mask) {
368 auto bit = ctz64(mask);
369 mask &= ~(1ULL << bit);
370 str += csprintf("a[%d]^", bit);
371 }
372 str += csprintf("\b=%d", bits(intlvMatch, i));
373 }
374 return csprintf("[%#llx:%#llx]%s", _start, _end, str);
375 } else {
376 return csprintf("[%#llx:%#llx]", _start, _end);
377 }
378 }
379
390 bool
391 mergesWith(const AddrRange& r) const
392 {
393 return r._start == _start && r._end == _end &&
394 r.masks == masks;
395 }
396
407 bool
408 intersects(const AddrRange& r) const
409 {
410 if (_start >= r._end || _end <= r._start) {
411 // start with the simple case of no overlap at all,
412 // applicable even if we have interleaved ranges
413 return false;
414 } else if (!interleaved() && !r.interleaved()) {
415 // if neither range is interleaved, we are done
416 return true;
417 }
418
419 // now it gets complicated, focus on the cases we care about
420 if (r.size() == 1) {
421 // keep it simple and check if the address is within
422 // this range
423 return contains(r.start());
424 } else if (mergesWith(r)) {
425 // restrict the check to ranges that belong to the
426 // same chunk
427 return intlvMatch == r.intlvMatch;
428 } else {
429 panic("Cannot test intersection of %s and %s\n",
430 to_string(), r.to_string());
431 }
432 }
433
444 bool
445 isSubset(const AddrRange& r) const
446 {
447 if (interleaved())
448 panic("Cannot test subset of interleaved range %s\n", to_string());
449
450 // This address range is not interleaved and therefore it
451 // suffices to check the upper bound, the lower bound and
452 // whether it would fit in a continuous segment of the input
453 // addr range.
454 if (r.interleaved()) {
455 if (r.contains(_start) && size() <= r.granularity()) {
456 // simplify checking for 1 element ranges
457 // no need to re-check r.contains(_end -1) if
458 // it is the same as _start
459 if (_start == _end - 1) {
460 return true;
461 }
462 //otherwise check if it also contains the end.
463 return r.contains(_end -1);
464 }
465 return false;
466 } else {
467
468 if (_end <= _start){
469 // Special case: if our range wraps around that is
470 // _end is 2^64 so it wraps to 0.
471 // In this case we will be a subset only if r._end
472 // also wraps around.
473 return _start >= r._start && r._end == 0;
474 } else if (r._end <= r._start){
475 // Special case: if r wraps around that is
476 // r._end is 2^64 so it wraps to 0.
477 // In this case we will be a subset only if our _start
478 // is within r._start/ _end does not matter
479 // because r wraps around.
480 return _start >= r._start;
481 } else {
482 // Normal case: Check if our range is completely within 'r'.
483 return _start >= r._start && _end <= r._end;
484 }
485
486 }
487 }
488
497 bool
498 contains(const Addr& a) const
499 {
500 // check if the address is in the range and if there is either
501 // no interleaving, or with interleaving also if the selected
502 // bits from the address match the interleaving value
503 bool in_range = a >= _start && a < _end;
504 if (in_range) {
505 auto sel = 0;
506 for (unsigned int i = 0; i < masks.size(); i++) {
507 Addr masked = a & masks[i];
508 // The result of an xor operation is 1 if the number
509 // of bits set is odd or 0 othersize, thefore it
510 // suffices to count the number of bits set to
511 // determine the i-th bit of sel.
512 sel |= (popCount(masked) % 2) << i;
513 }
514 return sel == intlvMatch;
515 }
516 return false;
517 }
518
543 inline Addr
545 {
546 // Directly return the address if the range is not interleaved
547 // to prevent undefined behavior.
548 if (!interleaved()) {
549 return a;
550 }
551
552 // Get the LSB set from each mask
553 auto masks_lsb = std::make_unique<int[]>(masks.size());
554 for (unsigned int i = 0; i < masks.size(); i++) {
555 masks_lsb[i] = ctz64(masks[i]);
556 }
557
558 // we need to sort the list of bits we will discard as we
559 // discard them one by one starting.
560 std::sort(masks_lsb.get(), masks_lsb.get() + masks.size());
561
562 for (unsigned int i = 0; i < masks.size(); i++) {
563 const int intlv_bit = masks_lsb[i];
564 if (intlv_bit > 0) {
565 // on every iteration we remove one bit from the input
566 // address, and therefore the lowest invtl_bit has
567 // also shifted to the right by i positions.
568 a = insertBits(a >> 1, intlv_bit - i - 1, 0, a);
569 } else {
570 a >>= 1;
571 }
572 }
573 return a;
574 }
575
582 inline Addr
584 {
585 // Directly return the address if the range is not interleaved
586 // to prevent undefined behavior.
587 if (!interleaved()) {
588 return a;
589 }
590
591 // Get the LSB set from each mask
592 auto masks_lsb = std::make_unique<int[]>(masks.size());
593 for (unsigned int i = 0; i < masks.size(); i++) {
594 masks_lsb[i] = ctz64(masks[i]);
595 }
596
597 // Add bits one-by-one from the LSB side.
598 std::sort(masks_lsb.get(), masks_lsb.get() + masks.size());
599 for (unsigned int i = 0; i < masks.size(); i++) {
600 const int intlv_bit = masks_lsb[i];
601 if (intlv_bit > 0) {
602 // on every iteration we add one bit from the input
603 // address, but the lowest invtl_bit in the iteration is
604 // always in the right position because they are sorted
605 // increasingly from the LSB
606 a = insertBits(a << 1, intlv_bit - 1, 0, a);
607 } else {
608 a <<= 1;
609 }
610 }
611
612 for (unsigned int i = 0; i < masks.size(); i++) {
613 const int lsb = ctz64(masks[i]);
614 const Addr intlv_bit = bits(intlvMatch, i);
615 // Calculate the mask ignoring the LSB
616 const Addr masked = a & masks[i] & ~(1 << lsb);
617 // Set the LSB of the mask to whatever satisfies the selector bit
618 a = insertBits(a, lsb, intlv_bit ^ popCount(masked));
619 }
620
621 return a;
622 }
623
637 Addr
638 getOffset(const Addr& a) const
639 {
640 bool in_range = a >= _start && a < _end;
641 if (!in_range) {
642 return MaxAddr;
643 }
644 if (interleaved()) {
646 } else {
647 return a - _start;
648 }
649 }
650
666 exclude(const AddrRangeList &exclude_ranges) const
667 {
668 assert(!interleaved());
669
670 auto sorted_ranges = exclude_ranges;
671 sorted_ranges.sort();
672
674
675 Addr next_start = start();
676 for (const auto &e : sorted_ranges) {
677 assert(!e.interleaved());
678 if (!intersects(e)) {
679 continue;
680 }
681
682 if (e.start() <= next_start) {
683 if (e.end() < end()) {
684 if (next_start < e.end()) {
685 next_start = e.end();
686 }
687 } else {
688 return ranges;
689 }
690 } else {
691 ranges.push_back(AddrRange(next_start, e.start()));
692 if (e.end() < end()) {
693 next_start = e.end();
694 } else {
695 return ranges;
696 }
697 }
698 }
699
700 if (next_start < end()) {
701 ranges.push_back(AddrRange(next_start, end()));
702 }
703
704 return ranges;
705 }
706
708 exclude(const AddrRange &excluded_range) const
709 {
710 return exclude(AddrRangeList{excluded_range});
711 }
712
722 bool
723 operator<(const AddrRange& r) const
724 {
725 if (_start != r._start) {
726 return _start < r._start;
727 } else {
728 // For now assume that the end is also the same.
729 // If both regions are interleaved, assume same interleaving,
730 // and compare intlvMatch values.
731 // Otherwise, return true if this address range is interleaved.
732 if (interleaved() && r.interleaved()) {
733 return intlvMatch < r.intlvMatch;
734 } else {
735 return interleaved();
736 }
737 }
738 }
739
743 bool
744 operator==(const AddrRange& r) const
745 {
746 if (_start != r._start) return false;
747 if (_end != r._end) return false;
748 if (masks != r.masks) return false;
749 if (intlvMatch != r.intlvMatch) return false;
750
751 return true;
752 }
753
757 bool
758 operator!=(const AddrRange& r) const
759 {
760 return !(*this == r);
761 }
762
767 operator&(const AddrRange& r) const
768 {
769 panic_if(this->interleaved() || r.interleaved(),
770 "Cannot calculate intersection of interleaved ranges.");
771 Addr start = std::max(this->_start, r._start);
772 Addr end = std::min(this->_end, r._end);
773 if (end <= start) {
774 return AddrRange(0, 0);
775 }
776 return AddrRange(start, end);
777 }
778};
779
780static inline AddrRangeList
781operator-(const AddrRange &range, const AddrRangeList &to_exclude)
782{
783 return range.exclude(to_exclude);
784}
785
786static inline AddrRangeList
787operator-(const AddrRange &range, const AddrRange &to_exclude)
788{
789 return range.exclude(to_exclude);
790}
791
792static inline AddrRangeList
794{
795 to_exclude.sort();
796
797 AddrRangeList ret;
798 for (const auto &range: base)
799 ret.splice(ret.end(), range.exclude(to_exclude));
800
801 return ret;
802}
803
804static inline AddrRangeList
805exclude(const AddrRangeList &base, const AddrRange &to_exclude)
806{
807 return exclude(base, AddrRangeList{to_exclude});
808}
809
810static inline AddrRangeList
811operator-(const AddrRangeList &base, const AddrRangeList &to_exclude)
812{
813 return exclude(base, to_exclude);
814}
815
816static inline AddrRangeList
818{
819 base = base - to_exclude;
820 return base;
821}
822
823static inline AddrRangeList
824operator-(const AddrRangeList &base, const AddrRange &to_exclude)
825{
826 return exclude(base, to_exclude);
827}
828
829static inline AddrRangeList
831{
832 base = base - to_exclude;
833 return base;
834}
835
839inline AddrRange
840RangeEx(Addr start, Addr end)
841{
842 return AddrRange(start, end);
843}
844
848inline AddrRange
849RangeIn(Addr start, Addr end)
850{
851 return AddrRange(start, end + 1);
852}
853
857inline AddrRange
858RangeSize(Addr start, Addr size)
859{
860 return AddrRange(start, start + size);
861}
862
863} // namespace gem5
864
865#endif // __BASE_ADDR_RANGE_HH__
Defines global host-dependent types: Counter, Tick, and (indirectly) {int,uint}{8,...
The AddrRange class encapsulates an address range, and supports a number of tests to check if two ran...
Definition addr_range.hh:82
uint8_t intlvMatch
The value to compare sel with.
AddrRange(Addr _start, Addr _end)
AddrRange(std::list< AddrRange > ranges)
AddrRangeList exclude(const AddrRange &excluded_range) const
AddrRange(Dummy, Iterator begin_it, Iterator end_it)
std::vector< Addr > masks
Each mask determines the bits we need to xor to get one bit of sel.
Definition addr_range.hh:97
Addr _start
Private fields for the start and end of the range _start is the beginning of the range (inclusive).
Definition addr_range.hh:89
STL list class.
Definition stl.hh:51
STL vector class.
Definition stl.hh:37
bool interleaved() const
Determine if the range is interleaved or not.
AddrRange operator&(const AddrRange &r) const
bool operator!=(const AddrRange &r) const
bool isSubset(const AddrRange &r) const
Determine if this range is a subset of another range, i.e.
AddrRange RangeEx(Addr start, Addr end)
AddrRange RangeSize(Addr start, Addr size)
Addr removeIntlvBits(Addr a) const
Remove the interleaving bits from an input address.
AddrRange(Addr _start, Addr _end, const std::vector< Addr > &_masks, uint8_t _intlv_match)
Construct an address range.
uint64_t granularity() const
Determing the interleaving granularity of the range.
AddrRange(std::vector< AddrRange > ranges)
Create an address range by merging a collection of interleaved ranges.
AddrRange RangeIn(Addr start, Addr end)
std::list< AddrRange > AddrRangeList
Convenience typedef for a collection of address ranges.
Definition addr_range.hh:64
AddrRangeList exclude(const AddrRangeList &exclude_ranges) const
Subtract a list of intervals from the range and return the resulting collection of ranges,...
uint32_t stripes() const
Determine the number of interleaved address stripes this range is part of.
bool valid() const
Determine if the range is valid.
bool contains(const Addr &a) const
Determine if the range contains an address.
Addr getOffset(const Addr &a) const
Determine the offset of an address within the range.
bool intersects(const AddrRange &r) const
Determine if another range intersects this one, i.e.
Addr end() const
Get the end address of the range.
bool mergesWith(const AddrRange &r) const
Determine if another range merges with the current one, i.e.
Addr start() const
Get the start address of the range.
Addr size() const
Get the size of the address range.
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...
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.
std::string to_string() const
Get a string representation of the range.
Addr addIntlvBits(Addr a) const
This method adds the interleaving bits removed by removeIntlvBits.
bool operator==(const AddrRange &r) const
constexpr T bits(T val, unsigned first, unsigned last)
Extract the bitfield from position 'first' to 'last' (inclusive) from 'val' and right justify it.
Definition bitfield.hh:79
constexpr int popCount(uint64_t val)
Returns the number of set ones in the provided value.
Definition bitfield.hh:415
constexpr T insertBits(T val, unsigned first, unsigned last, B bit_val)
Returns val with bits first to last set to the LSBs of bit_val.
Definition bitfield.hh:185
constexpr int ctz64(uint64_t value)
Count trailing zeros in a 64-bit value.
Definition bitfield.hh:487
#define panic(...)
This implements a cprintf based panic() function.
Definition logging.hh:220
#define fatal_if(cond,...)
Conditional fatal macro that checks the supplied condition and only causes a fatal error if the condi...
Definition logging.hh:268
#define fatal(...)
This implements a cprintf based fatal() function.
Definition logging.hh:232
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
Definition logging.hh:246
Bitfield< 3, 0 > mask
Definition pcstate.hh:63
Bitfield< 7 > i
Definition misc_types.hh:67
Bitfield< 9 > e
Definition misc_types.hh:65
Bitfield< 8 > a
Definition misc_types.hh:66
Copyright (c) 2024 Arm Limited All rights reserved.
Definition binary32.hh:36
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition types.hh:147
static AddrRangeList exclude(const AddrRangeList &base, AddrRangeList to_exclude)
std::string csprintf(const char *format, const Args &...args)
Definition cprintf.hh:161
static AddrRangeList operator-=(AddrRangeList &base, const AddrRangeList &to_exclude)
const Addr MaxAddr
Definition types.hh:171
static AddrRangeList operator-(const AddrRange &range, const AddrRangeList &to_exclude)

Generated on Mon Oct 27 2025 04:12:59 for gem5 by doxygen 1.14.0