addr_range.hh revision 12977
12SN/A/* 212977Snikos.nikoleris@arm.com * Copyright (c) 2012, 2014, 2017-2018 ARM Limited 39235Sandreas.hansson@arm.com * All rights reserved 49235Sandreas.hansson@arm.com * 59235Sandreas.hansson@arm.com * The license below extends only to copyright in the software and shall 69235Sandreas.hansson@arm.com * not be construed as granting a license to any other intellectual 79235Sandreas.hansson@arm.com * property including but not limited to intellectual property relating 89235Sandreas.hansson@arm.com * to a hardware implementation of the functionality of the software 99235Sandreas.hansson@arm.com * licensed hereunder. You may use the software subject to the license 109235Sandreas.hansson@arm.com * terms below provided that you ensure that this notice is replicated 119235Sandreas.hansson@arm.com * unmodified and in its entirety in all distributions of the software, 129235Sandreas.hansson@arm.com * modified or unmodified, in source code or in binary form. 139235Sandreas.hansson@arm.com * 141762SN/A * Copyright (c) 2002-2005 The Regents of The University of Michigan 152SN/A * All rights reserved. 162SN/A * 172SN/A * Redistribution and use in source and binary forms, with or without 182SN/A * modification, are permitted provided that the following conditions are 192SN/A * met: redistributions of source code must retain the above copyright 202SN/A * notice, this list of conditions and the following disclaimer; 212SN/A * redistributions in binary form must reproduce the above copyright 222SN/A * notice, this list of conditions and the following disclaimer in the 232SN/A * documentation and/or other materials provided with the distribution; 242SN/A * neither the name of the copyright holders nor the names of its 252SN/A * contributors may be used to endorse or promote products derived from 262SN/A * this software without specific prior written permission. 272SN/A * 282SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 292SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 302SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 312SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 322SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 332SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 342SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 352SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 362SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 372SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 382SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 392665SN/A * 402665SN/A * Authors: Nathan Binkert 412665SN/A * Steve Reinhardt 429235Sandreas.hansson@arm.com * Andreas Hansson 432SN/A */ 442SN/A 459235Sandreas.hansson@arm.com#ifndef __BASE_ADDR_RANGE_HH__ 469235Sandreas.hansson@arm.com#define __BASE_ADDR_RANGE_HH__ 472SN/A 4812977Snikos.nikoleris@arm.com#include <algorithm> 4910481Sandreas.hansson@arm.com#include <list> 509412Sandreas.hansson@arm.com#include <vector> 519412Sandreas.hansson@arm.com 529411Sandreas.hansson@arm.com#include "base/bitfield.hh" 539405Sandreas.hansson@arm.com#include "base/cprintf.hh" 5412334Sgabeblack@google.com#include "base/logging.hh" 559235Sandreas.hansson@arm.com#include "base/types.hh" 569235Sandreas.hansson@arm.com 5710676Sandreas.hansson@arm.com/** 5810676Sandreas.hansson@arm.com * The AddrRange class encapsulates an address range, and supports a 5910676Sandreas.hansson@arm.com * number of tests to check if two ranges intersect, if a range 6010676Sandreas.hansson@arm.com * contains a specific address etc. Besides a basic range, the 6110676Sandreas.hansson@arm.com * AddrRange also support interleaved ranges, to stripe across cache 6210676Sandreas.hansson@arm.com * banks, or memory controllers. The interleaving is implemented by 6310676Sandreas.hansson@arm.com * allowing a number of bits of the address, at an arbitrary bit 6410676Sandreas.hansson@arm.com * position, to be used as interleaving bits with an associated 6510676Sandreas.hansson@arm.com * matching value. In addition, to prevent uniformly strided address 6610676Sandreas.hansson@arm.com * patterns from a very biased interleaving, we also allow basic 6710676Sandreas.hansson@arm.com * XOR-based hashing by specifying an additional set of bits to XOR 6810676Sandreas.hansson@arm.com * with before matching. 6910676Sandreas.hansson@arm.com * 7010676Sandreas.hansson@arm.com * The AddrRange is also able to coalesce a number of interleaved 7110676Sandreas.hansson@arm.com * ranges to a contiguous range. 7210676Sandreas.hansson@arm.com */ 739235Sandreas.hansson@arm.comclass AddrRange 742SN/A{ 752SN/A 769405Sandreas.hansson@arm.com private: 779405Sandreas.hansson@arm.com 789411Sandreas.hansson@arm.com /// Private fields for the start and end of the range 7910435Snilay@cs.wisc.edu /// Both _start and _end are part of the range. 809405Sandreas.hansson@arm.com Addr _start; 819405Sandreas.hansson@arm.com Addr _end; 829405Sandreas.hansson@arm.com 839411Sandreas.hansson@arm.com /// The high bit of the slice that is used for interleaving 849411Sandreas.hansson@arm.com uint8_t intlvHighBit; 859411Sandreas.hansson@arm.com 8610676Sandreas.hansson@arm.com /// The high bit of the slice used to XOR hash the value we match 8710676Sandreas.hansson@arm.com /// against, set to 0 to disable. 8810676Sandreas.hansson@arm.com uint8_t xorHighBit; 8910676Sandreas.hansson@arm.com 909411Sandreas.hansson@arm.com /// The number of bits used for interleaving, set to 0 to disable 919411Sandreas.hansson@arm.com uint8_t intlvBits; 929411Sandreas.hansson@arm.com 939411Sandreas.hansson@arm.com /// The value to compare the slice addr[high:(high - bits + 1)] 949411Sandreas.hansson@arm.com /// with. 959411Sandreas.hansson@arm.com uint8_t intlvMatch; 969411Sandreas.hansson@arm.com 979235Sandreas.hansson@arm.com public: 982SN/A 999235Sandreas.hansson@arm.com AddrRange() 10010676Sandreas.hansson@arm.com : _start(1), _end(0), intlvHighBit(0), xorHighBit(0), intlvBits(0), 10110676Sandreas.hansson@arm.com intlvMatch(0) 1029411Sandreas.hansson@arm.com {} 1039411Sandreas.hansson@arm.com 1049411Sandreas.hansson@arm.com AddrRange(Addr _start, Addr _end, uint8_t _intlv_high_bit, 10510676Sandreas.hansson@arm.com uint8_t _xor_high_bit, uint8_t _intlv_bits, 10610676Sandreas.hansson@arm.com uint8_t _intlv_match) 1079411Sandreas.hansson@arm.com : _start(_start), _end(_end), intlvHighBit(_intlv_high_bit), 10810676Sandreas.hansson@arm.com xorHighBit(_xor_high_bit), intlvBits(_intlv_bits), 10910676Sandreas.hansson@arm.com intlvMatch(_intlv_match) 11010676Sandreas.hansson@arm.com { 11110676Sandreas.hansson@arm.com // sanity checks 11210676Sandreas.hansson@arm.com fatal_if(intlvBits && intlvMatch >= ULL(1) << intlvBits, 11310676Sandreas.hansson@arm.com "Match value %d does not fit in %d interleaving bits\n", 11410676Sandreas.hansson@arm.com intlvMatch, intlvBits); 11510676Sandreas.hansson@arm.com 11610676Sandreas.hansson@arm.com // ignore the XOR bits if not interleaving 11710676Sandreas.hansson@arm.com if (intlvBits && xorHighBit) { 11810676Sandreas.hansson@arm.com if (xorHighBit == intlvHighBit) { 11910676Sandreas.hansson@arm.com fatal("XOR and interleave high bit must be different\n"); 12010676Sandreas.hansson@arm.com } else if (xorHighBit > intlvHighBit) { 12110676Sandreas.hansson@arm.com if ((xorHighBit - intlvHighBit) < intlvBits) 12210676Sandreas.hansson@arm.com fatal("XOR and interleave high bit must be at least " 12310676Sandreas.hansson@arm.com "%d bits apart\n", intlvBits); 12410676Sandreas.hansson@arm.com } else { 12510676Sandreas.hansson@arm.com if ((intlvHighBit - xorHighBit) < intlvBits) { 12610676Sandreas.hansson@arm.com fatal("Interleave and XOR high bit must be at least " 12710676Sandreas.hansson@arm.com "%d bits apart\n", intlvBits); 12810676Sandreas.hansson@arm.com } 12910676Sandreas.hansson@arm.com } 13010676Sandreas.hansson@arm.com } 13110676Sandreas.hansson@arm.com } 1329235Sandreas.hansson@arm.com 1339235Sandreas.hansson@arm.com AddrRange(Addr _start, Addr _end) 13410676Sandreas.hansson@arm.com : _start(_start), _end(_end), intlvHighBit(0), xorHighBit(0), 13510676Sandreas.hansson@arm.com intlvBits(0), intlvMatch(0) 1369235Sandreas.hansson@arm.com {} 1379235Sandreas.hansson@arm.com 1389405Sandreas.hansson@arm.com /** 1399412Sandreas.hansson@arm.com * Create an address range by merging a collection of interleaved 1409412Sandreas.hansson@arm.com * ranges. 1419412Sandreas.hansson@arm.com * 1429412Sandreas.hansson@arm.com * @param ranges Interleaved ranges to be merged 1439412Sandreas.hansson@arm.com */ 1449412Sandreas.hansson@arm.com AddrRange(const std::vector<AddrRange>& ranges) 14510676Sandreas.hansson@arm.com : _start(1), _end(0), intlvHighBit(0), xorHighBit(0), intlvBits(0), 14610676Sandreas.hansson@arm.com intlvMatch(0) 1479412Sandreas.hansson@arm.com { 1489412Sandreas.hansson@arm.com if (!ranges.empty()) { 1499412Sandreas.hansson@arm.com // get the values from the first one and check the others 1509412Sandreas.hansson@arm.com _start = ranges.front()._start; 1519412Sandreas.hansson@arm.com _end = ranges.front()._end; 1529412Sandreas.hansson@arm.com intlvHighBit = ranges.front().intlvHighBit; 15310676Sandreas.hansson@arm.com xorHighBit = ranges.front().xorHighBit; 1549412Sandreas.hansson@arm.com intlvBits = ranges.front().intlvBits; 1559412Sandreas.hansson@arm.com 1569412Sandreas.hansson@arm.com if (ranges.size() != (ULL(1) << intlvBits)) 1579412Sandreas.hansson@arm.com fatal("Got %d ranges spanning %d interleaving bits\n", 1589412Sandreas.hansson@arm.com ranges.size(), intlvBits); 1599412Sandreas.hansson@arm.com 1609412Sandreas.hansson@arm.com uint8_t match = 0; 16110676Sandreas.hansson@arm.com for (const auto& r : ranges) { 16210676Sandreas.hansson@arm.com if (!mergesWith(r)) 1639412Sandreas.hansson@arm.com fatal("Can only merge ranges with the same start, end " 1649412Sandreas.hansson@arm.com "and interleaving bits\n"); 1659412Sandreas.hansson@arm.com 16610676Sandreas.hansson@arm.com if (r.intlvMatch != match) 1679412Sandreas.hansson@arm.com fatal("Expected interleave match %d but got %d when " 16810676Sandreas.hansson@arm.com "merging\n", match, r.intlvMatch); 1699412Sandreas.hansson@arm.com ++match; 1709412Sandreas.hansson@arm.com } 1719412Sandreas.hansson@arm.com 1729412Sandreas.hansson@arm.com // our range is complete and we can turn this into a 1739412Sandreas.hansson@arm.com // non-interleaved range 1749412Sandreas.hansson@arm.com intlvHighBit = 0; 17510676Sandreas.hansson@arm.com xorHighBit = 0; 1769412Sandreas.hansson@arm.com intlvBits = 0; 1779412Sandreas.hansson@arm.com } 1789412Sandreas.hansson@arm.com } 1799412Sandreas.hansson@arm.com 1809412Sandreas.hansson@arm.com /** 1819411Sandreas.hansson@arm.com * Determine if the range is interleaved or not. 1829411Sandreas.hansson@arm.com * 1839411Sandreas.hansson@arm.com * @return true if interleaved 1849411Sandreas.hansson@arm.com */ 1859411Sandreas.hansson@arm.com bool interleaved() const { return intlvBits != 0; } 1869411Sandreas.hansson@arm.com 1879411Sandreas.hansson@arm.com /** 18810676Sandreas.hansson@arm.com * Determine if the range interleaving is hashed or not. 18910676Sandreas.hansson@arm.com */ 19010676Sandreas.hansson@arm.com bool hashed() const { return interleaved() && xorHighBit != 0; } 19110676Sandreas.hansson@arm.com 19210676Sandreas.hansson@arm.com /** 1939411Sandreas.hansson@arm.com * Determing the interleaving granularity of the range. 1949411Sandreas.hansson@arm.com * 1959411Sandreas.hansson@arm.com * @return The size of the regions created by the interleaving bits 1969411Sandreas.hansson@arm.com */ 1979581Sandreas.hansson@arm.com uint64_t granularity() const 1989581Sandreas.hansson@arm.com { 19912977Snikos.nikoleris@arm.com if (interleaved()) { 20012977Snikos.nikoleris@arm.com const uint8_t intlv_low_bit = intlvHighBit - intlvBits + 1; 20112977Snikos.nikoleris@arm.com if (hashed()) { 20212977Snikos.nikoleris@arm.com const uint8_t xor_low_bit = xorHighBit - intlvBits + 1; 20312977Snikos.nikoleris@arm.com return ULL(1) << std::min(intlv_low_bit, xor_low_bit); 20412977Snikos.nikoleris@arm.com } else { 20512977Snikos.nikoleris@arm.com return ULL(1) << intlv_low_bit; 20612977Snikos.nikoleris@arm.com } 20712977Snikos.nikoleris@arm.com } else { 20812977Snikos.nikoleris@arm.com return size(); 20912977Snikos.nikoleris@arm.com } 2109581Sandreas.hansson@arm.com } 2119411Sandreas.hansson@arm.com 2129411Sandreas.hansson@arm.com /** 2139411Sandreas.hansson@arm.com * Determine the number of interleaved address stripes this range 2149411Sandreas.hansson@arm.com * is part of. 2159411Sandreas.hansson@arm.com * 2169411Sandreas.hansson@arm.com * @return The number of stripes spanned by the interleaving bits 2179411Sandreas.hansson@arm.com */ 2189411Sandreas.hansson@arm.com uint32_t stripes() const { return ULL(1) << intlvBits; } 2199411Sandreas.hansson@arm.com 2209411Sandreas.hansson@arm.com /** 2219405Sandreas.hansson@arm.com * Get the size of the address range. For a case where 2229411Sandreas.hansson@arm.com * interleaving is used we make the simplifying assumption that 2239411Sandreas.hansson@arm.com * the size is a divisible by the size of the interleaving slice. 2249405Sandreas.hansson@arm.com */ 2259411Sandreas.hansson@arm.com Addr size() const 2269411Sandreas.hansson@arm.com { 2279411Sandreas.hansson@arm.com return (_end - _start + 1) >> intlvBits; 2289411Sandreas.hansson@arm.com } 229532SN/A 2309405Sandreas.hansson@arm.com /** 2319405Sandreas.hansson@arm.com * Determine if the range is valid. 2329405Sandreas.hansson@arm.com */ 23310435Snilay@cs.wisc.edu bool valid() const { return _start <= _end; } 2349405Sandreas.hansson@arm.com 2359405Sandreas.hansson@arm.com /** 2369405Sandreas.hansson@arm.com * Get the start address of the range. 2379405Sandreas.hansson@arm.com */ 2389405Sandreas.hansson@arm.com Addr start() const { return _start; } 2399405Sandreas.hansson@arm.com 2409405Sandreas.hansson@arm.com /** 24110678SCurtis.Dunham@arm.com * Get the end address of the range. 24210678SCurtis.Dunham@arm.com */ 24310678SCurtis.Dunham@arm.com Addr end() const { return _end; } 24410678SCurtis.Dunham@arm.com 24510678SCurtis.Dunham@arm.com /** 2469405Sandreas.hansson@arm.com * Get a string representation of the range. This could 2479405Sandreas.hansson@arm.com * alternatively be implemented as a operator<<, but at the moment 2489405Sandreas.hansson@arm.com * that seems like overkill. 2499405Sandreas.hansson@arm.com */ 2509405Sandreas.hansson@arm.com std::string to_string() const 2519405Sandreas.hansson@arm.com { 25210676Sandreas.hansson@arm.com if (interleaved()) { 25310676Sandreas.hansson@arm.com if (hashed()) { 25410676Sandreas.hansson@arm.com return csprintf("[%#llx : %#llx], [%d : %d] XOR [%d : %d] = %d", 25510676Sandreas.hansson@arm.com _start, _end, 25610676Sandreas.hansson@arm.com intlvHighBit, intlvHighBit - intlvBits + 1, 25710676Sandreas.hansson@arm.com xorHighBit, xorHighBit - intlvBits + 1, 25810676Sandreas.hansson@arm.com intlvMatch); 25910676Sandreas.hansson@arm.com } else { 26010676Sandreas.hansson@arm.com return csprintf("[%#llx : %#llx], [%d : %d] = %d", 26110676Sandreas.hansson@arm.com _start, _end, 26210676Sandreas.hansson@arm.com intlvHighBit, intlvHighBit - intlvBits + 1, 26310676Sandreas.hansson@arm.com intlvMatch); 26410676Sandreas.hansson@arm.com } 26510676Sandreas.hansson@arm.com } else { 2669411Sandreas.hansson@arm.com return csprintf("[%#llx : %#llx]", _start, _end); 26710676Sandreas.hansson@arm.com } 2689411Sandreas.hansson@arm.com } 2699411Sandreas.hansson@arm.com 2709411Sandreas.hansson@arm.com /** 2719411Sandreas.hansson@arm.com * Determine if another range merges with the current one, i.e. if 2729411Sandreas.hansson@arm.com * they are part of the same contigous range and have the same 2739411Sandreas.hansson@arm.com * interleaving bits. 2749411Sandreas.hansson@arm.com * 2759411Sandreas.hansson@arm.com * @param r Range to evaluate merging with 2769411Sandreas.hansson@arm.com * @return true if the two ranges would merge 2779411Sandreas.hansson@arm.com */ 2789411Sandreas.hansson@arm.com bool mergesWith(const AddrRange& r) const 2799411Sandreas.hansson@arm.com { 2809411Sandreas.hansson@arm.com return r._start == _start && r._end == _end && 2819411Sandreas.hansson@arm.com r.intlvHighBit == intlvHighBit && 28210676Sandreas.hansson@arm.com r.xorHighBit == xorHighBit && 2839411Sandreas.hansson@arm.com r.intlvBits == intlvBits; 2849405Sandreas.hansson@arm.com } 2859279Sandreas.hansson@arm.com 2869279Sandreas.hansson@arm.com /** 2879279Sandreas.hansson@arm.com * Determine if another range intersects this one, i.e. if there 2889279Sandreas.hansson@arm.com * is an address that is both in this range and the other 2899279Sandreas.hansson@arm.com * range. No check is made to ensure either range is valid. 2909279Sandreas.hansson@arm.com * 2919279Sandreas.hansson@arm.com * @param r Range to intersect with 2929279Sandreas.hansson@arm.com * @return true if the intersection of the two ranges is not empty 2939279Sandreas.hansson@arm.com */ 2949279Sandreas.hansson@arm.com bool intersects(const AddrRange& r) const 2959279Sandreas.hansson@arm.com { 29610853Sandreas.hansson@arm.com if (_start > r._end || _end < r._start) 29710853Sandreas.hansson@arm.com // start with the simple case of no overlap at all, 29810853Sandreas.hansson@arm.com // applicable even if we have interleaved ranges 29910853Sandreas.hansson@arm.com return false; 30010853Sandreas.hansson@arm.com else if (!interleaved() && !r.interleaved()) 30110853Sandreas.hansson@arm.com // if neither range is interleaved, we are done 30210853Sandreas.hansson@arm.com return true; 3039411Sandreas.hansson@arm.com 30410853Sandreas.hansson@arm.com // now it gets complicated, focus on the cases we care about 3059411Sandreas.hansson@arm.com if (r.size() == 1) 3069411Sandreas.hansson@arm.com // keep it simple and check if the address is within 3079411Sandreas.hansson@arm.com // this range 3089411Sandreas.hansson@arm.com return contains(r.start()); 3099411Sandreas.hansson@arm.com else if (mergesWith(r)) 3109411Sandreas.hansson@arm.com // restrict the check to ranges that belong to the 3119411Sandreas.hansson@arm.com // same chunk 3129411Sandreas.hansson@arm.com return intlvMatch == r.intlvMatch; 3139411Sandreas.hansson@arm.com else 31410853Sandreas.hansson@arm.com panic("Cannot test intersection of %s and %s\n", 31510853Sandreas.hansson@arm.com to_string(), r.to_string()); 3169279Sandreas.hansson@arm.com } 3179279Sandreas.hansson@arm.com 3189279Sandreas.hansson@arm.com /** 3199279Sandreas.hansson@arm.com * Determine if this range is a subset of another range, i.e. if 3209279Sandreas.hansson@arm.com * every address in this range is also in the other range. No 3219279Sandreas.hansson@arm.com * check is made to ensure either range is valid. 3229279Sandreas.hansson@arm.com * 3239279Sandreas.hansson@arm.com * @param r Range to compare with 3249279Sandreas.hansson@arm.com * @return true if the this range is a subset of the other one 3259279Sandreas.hansson@arm.com */ 3269279Sandreas.hansson@arm.com bool isSubset(const AddrRange& r) const 3279279Sandreas.hansson@arm.com { 3289411Sandreas.hansson@arm.com if (interleaved()) 3299411Sandreas.hansson@arm.com panic("Cannot test subset of interleaved range %s\n", to_string()); 33012977Snikos.nikoleris@arm.com 33112977Snikos.nikoleris@arm.com // This address range is not interleaved and therefore it 33212977Snikos.nikoleris@arm.com // suffices to check the upper bound, the lower bound and 33312977Snikos.nikoleris@arm.com // whether it would fit in a continuous segment of the input 33412977Snikos.nikoleris@arm.com // addr range. 33512977Snikos.nikoleris@arm.com if (r.interleaved()) { 33612977Snikos.nikoleris@arm.com return r.contains(_start) && r.contains(_end) && 33712977Snikos.nikoleris@arm.com size() <= r.granularity(); 33812977Snikos.nikoleris@arm.com } else { 33912977Snikos.nikoleris@arm.com return _start >= r._start && _end <= r._end; 34012977Snikos.nikoleris@arm.com } 3419279Sandreas.hansson@arm.com } 3429405Sandreas.hansson@arm.com 3439405Sandreas.hansson@arm.com /** 3449405Sandreas.hansson@arm.com * Determine if the range contains an address. 3459405Sandreas.hansson@arm.com * 3469405Sandreas.hansson@arm.com * @param a Address to compare with 3479405Sandreas.hansson@arm.com * @return true if the address is in the range 3489405Sandreas.hansson@arm.com */ 3499405Sandreas.hansson@arm.com bool contains(const Addr& a) const 3509405Sandreas.hansson@arm.com { 3519411Sandreas.hansson@arm.com // check if the address is in the range and if there is either 3529411Sandreas.hansson@arm.com // no interleaving, or with interleaving also if the selected 3539411Sandreas.hansson@arm.com // bits from the address match the interleaving value 35410676Sandreas.hansson@arm.com bool in_range = a >= _start && a <= _end; 35510676Sandreas.hansson@arm.com if (!interleaved()) { 35610676Sandreas.hansson@arm.com return in_range; 35710676Sandreas.hansson@arm.com } else if (in_range) { 35810676Sandreas.hansson@arm.com if (!hashed()) { 35910676Sandreas.hansson@arm.com return bits(a, intlvHighBit, intlvHighBit - intlvBits + 1) == 36010676Sandreas.hansson@arm.com intlvMatch; 36110676Sandreas.hansson@arm.com } else { 36210676Sandreas.hansson@arm.com return (bits(a, intlvHighBit, intlvHighBit - intlvBits + 1) ^ 36310676Sandreas.hansson@arm.com bits(a, xorHighBit, xorHighBit - intlvBits + 1)) == 36410676Sandreas.hansson@arm.com intlvMatch; 36510676Sandreas.hansson@arm.com } 36610676Sandreas.hansson@arm.com } 36710676Sandreas.hansson@arm.com return false; 3689405Sandreas.hansson@arm.com } 3692SN/A 3709405Sandreas.hansson@arm.com /** 37112065Snikos.nikoleris@arm.com * Remove the interleaving bits from an input address. 37212065Snikos.nikoleris@arm.com * 37312065Snikos.nikoleris@arm.com * This function returns a new address that doesn't have the bits 37412065Snikos.nikoleris@arm.com * that are use to determine which of the interleaved ranges it 37512065Snikos.nikoleris@arm.com * belongs to. 37612065Snikos.nikoleris@arm.com * 37712065Snikos.nikoleris@arm.com * e.g., if the input address is: 37812065Snikos.nikoleris@arm.com * ------------------------------- 37912065Snikos.nikoleris@arm.com * | prefix | intlvBits | suffix | 38012065Snikos.nikoleris@arm.com * ------------------------------- 38112065Snikos.nikoleris@arm.com * this function will return: 38212065Snikos.nikoleris@arm.com * ------------------------------- 38312065Snikos.nikoleris@arm.com * | 0 | prefix | suffix | 38412065Snikos.nikoleris@arm.com * ------------------------------- 38512065Snikos.nikoleris@arm.com * 38612065Snikos.nikoleris@arm.com * @param the input address 38712065Snikos.nikoleris@arm.com * @return the address without the interleaved bits 38812065Snikos.nikoleris@arm.com */ 38912065Snikos.nikoleris@arm.com inline Addr removeIntlvBits(const Addr &a) const 39012065Snikos.nikoleris@arm.com { 39112065Snikos.nikoleris@arm.com const auto intlv_low_bit = intlvHighBit - intlvBits + 1; 39212065Snikos.nikoleris@arm.com return insertBits(a >> intlvBits, intlv_low_bit - 1, 0, a); 39312065Snikos.nikoleris@arm.com } 39412065Snikos.nikoleris@arm.com 39512065Snikos.nikoleris@arm.com /** 39612065Snikos.nikoleris@arm.com * Determine the offset of an address within the range. 39712065Snikos.nikoleris@arm.com * 39812065Snikos.nikoleris@arm.com * This function returns the offset of the given address from the 39912065Snikos.nikoleris@arm.com * starting address discarding any bits that are used for 40012065Snikos.nikoleris@arm.com * interleaving. This way we can convert the input address to a 40112065Snikos.nikoleris@arm.com * new unique address in a continuous range that starts from 0. 40212065Snikos.nikoleris@arm.com * 40312065Snikos.nikoleris@arm.com * @param the input address 40412065Snikos.nikoleris@arm.com * @return the flat offset in the address range 40512065Snikos.nikoleris@arm.com */ 40612065Snikos.nikoleris@arm.com Addr getOffset(const Addr& a) const 40712065Snikos.nikoleris@arm.com { 40812065Snikos.nikoleris@arm.com bool in_range = a >= _start && a <= _end; 40912065Snikos.nikoleris@arm.com if (!in_range) { 41012065Snikos.nikoleris@arm.com return MaxAddr; 41112065Snikos.nikoleris@arm.com } 41212065Snikos.nikoleris@arm.com if (interleaved()) { 41312065Snikos.nikoleris@arm.com return removeIntlvBits(a) - removeIntlvBits(_start); 41412065Snikos.nikoleris@arm.com } else { 41512065Snikos.nikoleris@arm.com return a - _start; 41612065Snikos.nikoleris@arm.com } 41712065Snikos.nikoleris@arm.com } 41812065Snikos.nikoleris@arm.com 41912065Snikos.nikoleris@arm.com /** 4209405Sandreas.hansson@arm.com * Less-than operator used to turn an STL map into a binary search 4219405Sandreas.hansson@arm.com * tree of non-overlapping address ranges. 4229405Sandreas.hansson@arm.com * 4239405Sandreas.hansson@arm.com * @param r Range to compare with 4249405Sandreas.hansson@arm.com * @return true if the start address is less than that of the other range 4259405Sandreas.hansson@arm.com */ 4269405Sandreas.hansson@arm.com bool operator<(const AddrRange& r) const 4279405Sandreas.hansson@arm.com { 4289411Sandreas.hansson@arm.com if (_start != r._start) 4299411Sandreas.hansson@arm.com return _start < r._start; 4309411Sandreas.hansson@arm.com else 4319411Sandreas.hansson@arm.com // for now assume that the end is also the same, and that 4329411Sandreas.hansson@arm.com // we are looking at the same interleaving bits 4339411Sandreas.hansson@arm.com return intlvMatch < r.intlvMatch; 4349405Sandreas.hansson@arm.com } 435531SN/A 43610678SCurtis.Dunham@arm.com bool operator==(const AddrRange& r) const 43710678SCurtis.Dunham@arm.com { 43810678SCurtis.Dunham@arm.com if (_start != r._start) return false; 43910678SCurtis.Dunham@arm.com if (_end != r._end) return false; 44010678SCurtis.Dunham@arm.com if (intlvBits != r.intlvBits) return false; 44110678SCurtis.Dunham@arm.com if (intlvBits != 0) { 44210678SCurtis.Dunham@arm.com if (intlvHighBit != r.intlvHighBit) return false; 44310678SCurtis.Dunham@arm.com if (intlvMatch != r.intlvMatch) return false; 44410678SCurtis.Dunham@arm.com } 44510678SCurtis.Dunham@arm.com return true; 44610678SCurtis.Dunham@arm.com } 44710678SCurtis.Dunham@arm.com 44810678SCurtis.Dunham@arm.com bool operator!=(const AddrRange& r) const 44910678SCurtis.Dunham@arm.com { 45010678SCurtis.Dunham@arm.com return !(*this == r); 45110678SCurtis.Dunham@arm.com } 4529405Sandreas.hansson@arm.com}; 4532SN/A 45410481Sandreas.hansson@arm.com/** 45510481Sandreas.hansson@arm.com * Convenience typedef for a collection of address ranges 45610481Sandreas.hansson@arm.com */ 45710481Sandreas.hansson@arm.comtypedef std::list<AddrRange> AddrRangeList; 45810481Sandreas.hansson@arm.com 4599235Sandreas.hansson@arm.cominline AddrRange 4609235Sandreas.hansson@arm.comRangeEx(Addr start, Addr end) 4619405Sandreas.hansson@arm.com{ return AddrRange(start, end - 1); } 4622SN/A 4639235Sandreas.hansson@arm.cominline AddrRange 4649235Sandreas.hansson@arm.comRangeIn(Addr start, Addr end) 4659405Sandreas.hansson@arm.com{ return AddrRange(start, end); } 4662SN/A 4679235Sandreas.hansson@arm.cominline AddrRange 4689235Sandreas.hansson@arm.comRangeSize(Addr start, Addr size) 4699405Sandreas.hansson@arm.com{ return AddrRange(start, start + size - 1); } 4702SN/A 4719235Sandreas.hansson@arm.com#endif // __BASE_ADDR_RANGE_HH__ 472