gem5 v24.0.0.0
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 return r.contains(_start) && r.contains(_end - 1) &&
456 size() <= r.granularity();
457 } else {
458
459 if (_end <= _start){
460 // Special case: if our range wraps around that is
461 // _end is 2^64 so it wraps to 0.
462 // In this case we will be a subset only if r._end
463 // also wraps around.
464 return _start >= r._start && r._end == 0;
465 } else if (r._end <= r._start){
466 // Special case: if r wraps around that is
467 // r._end is 2^64 so it wraps to 0.
468 // In this case we will be a subset only if our _start
469 // is within r._start/ _end does not matter
470 // because r wraps around.
471 return _start >= r._start;
472 } else {
473 // Normal case: Check if our range is completely within 'r'.
474 return _start >= r._start && _end <= r._end;
475 }
476
477 }
478 }
479
488 bool
489 contains(const Addr& a) const
490 {
491 // check if the address is in the range and if there is either
492 // no interleaving, or with interleaving also if the selected
493 // bits from the address match the interleaving value
494 bool in_range = a >= _start && a < _end;
495 if (in_range) {
496 auto sel = 0;
497 for (unsigned int i = 0; i < masks.size(); i++) {
498 Addr masked = a & masks[i];
499 // The result of an xor operation is 1 if the number
500 // of bits set is odd or 0 othersize, thefore it
501 // suffices to count the number of bits set to
502 // determine the i-th bit of sel.
503 sel |= (popCount(masked) % 2) << i;
504 }
505 return sel == intlvMatch;
506 }
507 return false;
508 }
509
534 inline Addr
536 {
537 // Directly return the address if the range is not interleaved
538 // to prevent undefined behavior.
539 if (!interleaved()) {
540 return a;
541 }
542
543 // Get the LSB set from each mask
544 int masks_lsb[masks.size()];
545 for (unsigned int i = 0; i < masks.size(); i++) {
546 masks_lsb[i] = ctz64(masks[i]);
547 }
548
549 // we need to sort the list of bits we will discard as we
550 // discard them one by one starting.
551 std::sort(masks_lsb, masks_lsb + masks.size());
552
553 for (unsigned int i = 0; i < masks.size(); i++) {
554 const int intlv_bit = masks_lsb[i];
555 if (intlv_bit > 0) {
556 // on every iteration we remove one bit from the input
557 // address, and therefore the lowest invtl_bit has
558 // also shifted to the right by i positions.
559 a = insertBits(a >> 1, intlv_bit - i - 1, 0, a);
560 } else {
561 a >>= 1;
562 }
563 }
564 return a;
565 }
566
573 inline Addr
575 {
576 // Directly return the address if the range is not interleaved
577 // to prevent undefined behavior.
578 if (!interleaved()) {
579 return a;
580 }
581
582 // Get the LSB set from each mask
583 int masks_lsb[masks.size()];
584 for (unsigned int i = 0; i < masks.size(); i++) {
585 masks_lsb[i] = ctz64(masks[i]);
586 }
587
588 // Add bits one-by-one from the LSB side.
589 std::sort(masks_lsb, masks_lsb + masks.size());
590 for (unsigned int i = 0; i < masks.size(); i++) {
591 const int intlv_bit = masks_lsb[i];
592 if (intlv_bit > 0) {
593 // on every iteration we add one bit from the input
594 // address, but the lowest invtl_bit in the iteration is
595 // always in the right position because they are sorted
596 // increasingly from the LSB
597 a = insertBits(a << 1, intlv_bit - 1, 0, a);
598 } else {
599 a <<= 1;
600 }
601 }
602
603 for (unsigned int i = 0; i < masks.size(); i++) {
604 const int lsb = ctz64(masks[i]);
605 const Addr intlv_bit = bits(intlvMatch, i);
606 // Calculate the mask ignoring the LSB
607 const Addr masked = a & masks[i] & ~(1 << lsb);
608 // Set the LSB of the mask to whatever satisfies the selector bit
609 a = insertBits(a, lsb, intlv_bit ^ popCount(masked));
610 }
611
612 return a;
613 }
614
628 Addr
629 getOffset(const Addr& a) const
630 {
631 bool in_range = a >= _start && a < _end;
632 if (!in_range) {
633 return MaxAddr;
634 }
635 if (interleaved()) {
637 } else {
638 return a - _start;
639 }
640 }
641
657 exclude(const AddrRangeList &exclude_ranges) const
658 {
659 assert(!interleaved());
660
661 auto sorted_ranges = exclude_ranges;
662 sorted_ranges.sort();
663
665
666 Addr next_start = start();
667 for (const auto &e : sorted_ranges) {
668 assert(!e.interleaved());
669 if (!intersects(e)) {
670 continue;
671 }
672
673 if (e.start() <= next_start) {
674 if (e.end() < end()) {
675 if (next_start < e.end()) {
676 next_start = e.end();
677 }
678 } else {
679 return ranges;
680 }
681 } else {
682 ranges.push_back(AddrRange(next_start, e.start()));
683 if (e.end() < end()) {
684 next_start = e.end();
685 } else {
686 return ranges;
687 }
688 }
689 }
690
691 if (next_start < end()) {
692 ranges.push_back(AddrRange(next_start, end()));
693 }
694
695 return ranges;
696 }
697
699 exclude(const AddrRange &excluded_range) const
700 {
701 return exclude(AddrRangeList{excluded_range});
702 }
703
713 bool
714 operator<(const AddrRange& r) const
715 {
716 if (_start != r._start) {
717 return _start < r._start;
718 } else {
719 // For now assume that the end is also the same.
720 // If both regions are interleaved, assume same interleaving,
721 // and compare intlvMatch values.
722 // Otherwise, return true if this address range is interleaved.
723 if (interleaved() && r.interleaved()) {
724 return intlvMatch < r.intlvMatch;
725 } else {
726 return interleaved();
727 }
728 }
729 }
730
734 bool
735 operator==(const AddrRange& r) const
736 {
737 if (_start != r._start) return false;
738 if (_end != r._end) return false;
739 if (masks != r.masks) return false;
740 if (intlvMatch != r.intlvMatch) return false;
741
742 return true;
743 }
744
748 bool
749 operator!=(const AddrRange& r) const
750 {
751 return !(*this == r);
752 }
753
758 operator&(const AddrRange& r) const
759 {
760 panic_if(this->interleaved() || r.interleaved(),
761 "Cannot calculate intersection of interleaved ranges.");
762 Addr start = std::max(this->_start, r._start);
763 Addr end = std::min(this->_end, r._end);
764 if (end <= start) {
765 return AddrRange(0, 0);
766 }
767 return AddrRange(start, end);
768 }
769};
770
771static inline AddrRangeList
772operator-(const AddrRange &range, const AddrRangeList &to_exclude)
773{
774 return range.exclude(to_exclude);
775}
776
777static inline AddrRangeList
778operator-(const AddrRange &range, const AddrRange &to_exclude)
779{
780 return range.exclude(to_exclude);
781}
782
783static inline AddrRangeList
785{
786 to_exclude.sort();
787
788 AddrRangeList ret;
789 for (const auto &range: base)
790 ret.splice(ret.end(), range.exclude(to_exclude));
791
792 return ret;
793}
794
795static inline AddrRangeList
796exclude(const AddrRangeList &base, const AddrRange &to_exclude)
797{
798 return exclude(base, AddrRangeList{to_exclude});
799}
800
801static inline AddrRangeList
802operator-(const AddrRangeList &base, const AddrRangeList &to_exclude)
803{
804 return exclude(base, to_exclude);
805}
806
807static inline AddrRangeList
809{
810 base = base - to_exclude;
811 return base;
812}
813
814static inline AddrRangeList
815operator-(const AddrRangeList &base, const AddrRange &to_exclude)
816{
817 return exclude(base, to_exclude);
818}
819
820static inline AddrRangeList
822{
823 base = base - to_exclude;
824 return base;
825}
826
830inline AddrRange
831RangeEx(Addr start, Addr end)
832{
833 return AddrRange(start, end);
834}
835
839inline AddrRange
840RangeIn(Addr start, Addr end)
841{
842 return AddrRange(start, end + 1);
843}
844
848inline AddrRange
849RangeSize(Addr start, Addr size)
850{
851 return AddrRange(start, start + size);
852}
853
854} // namespace gem5
855
856#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:188
#define fatal_if(cond,...)
Conditional fatal macro that checks the supplied condition and only causes a fatal error if the condi...
Definition logging.hh:236
#define fatal(...)
This implements a cprintf based fatal() function.
Definition logging.hh:200
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
Definition logging.hh:214
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
Bitfield< 51, 12 > base
Definition pagetable.hh:141
Copyright (c) 2024 - Pranith Kumar Copyright (c) 2020 Inria 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 Tue Jun 18 2024 16:24:00 for gem5 by doxygen 1.11.0