2012-09-19 12:15:44 +02:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2012 ARM Limited
|
|
|
|
* All rights reserved
|
|
|
|
*
|
|
|
|
* The license below extends only to copyright in the software and shall
|
|
|
|
* not be construed as granting a license to any other intellectual
|
|
|
|
* property including but not limited to intellectual property relating
|
|
|
|
* to a hardware implementation of the functionality of the software
|
|
|
|
* licensed hereunder. You may use the software subject to the license
|
|
|
|
* terms below provided that you ensure that this notice is replicated
|
|
|
|
* unmodified and in its entirety in all distributions of the software,
|
|
|
|
* modified or unmodified, in source code or in binary form.
|
|
|
|
*
|
|
|
|
* Copyright (c) 2002-2005 The Regents of The University of Michigan
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions are
|
|
|
|
* met: redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer;
|
|
|
|
* redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution;
|
|
|
|
* neither the name of the copyright holders nor the names of its
|
|
|
|
* contributors may be used to endorse or promote products derived from
|
|
|
|
* this software without specific prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
|
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
|
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
|
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
|
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
*
|
|
|
|
* Authors: Nathan Binkert
|
|
|
|
* Steve Reinhardt
|
|
|
|
* Andreas Hansson
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef __BASE_ADDR_RANGE_HH__
|
|
|
|
#define __BASE_ADDR_RANGE_HH__
|
|
|
|
|
2013-01-07 19:05:38 +01:00
|
|
|
#include <vector>
|
|
|
|
|
2013-01-07 19:05:38 +01:00
|
|
|
#include "base/bitfield.hh"
|
2013-01-07 19:05:38 +01:00
|
|
|
#include "base/cprintf.hh"
|
2013-01-07 19:05:38 +01:00
|
|
|
#include "base/misc.hh"
|
2012-09-19 12:15:44 +02:00
|
|
|
#include "base/types.hh"
|
|
|
|
|
|
|
|
class AddrRange
|
|
|
|
{
|
|
|
|
|
2013-01-07 19:05:38 +01:00
|
|
|
private:
|
|
|
|
|
2013-01-07 19:05:38 +01:00
|
|
|
/// Private fields for the start and end of the range
|
2014-10-11 22:02:22 +02:00
|
|
|
/// Both _start and _end are part of the range.
|
2013-01-07 19:05:38 +01:00
|
|
|
Addr _start;
|
|
|
|
Addr _end;
|
2012-09-19 12:15:44 +02:00
|
|
|
|
2013-01-07 19:05:38 +01:00
|
|
|
/// The high bit of the slice that is used for interleaving
|
|
|
|
uint8_t intlvHighBit;
|
|
|
|
|
|
|
|
/// The number of bits used for interleaving, set to 0 to disable
|
|
|
|
uint8_t intlvBits;
|
|
|
|
|
|
|
|
/// The value to compare the slice addr[high:(high - bits + 1)]
|
|
|
|
/// with.
|
|
|
|
uint8_t intlvMatch;
|
|
|
|
|
2013-01-07 19:05:38 +01:00
|
|
|
public:
|
2012-09-19 12:15:44 +02:00
|
|
|
|
|
|
|
AddrRange()
|
2013-01-07 19:05:38 +01:00
|
|
|
: _start(1), _end(0), intlvHighBit(0), intlvBits(0), intlvMatch(0)
|
|
|
|
{}
|
|
|
|
|
|
|
|
AddrRange(Addr _start, Addr _end, uint8_t _intlv_high_bit,
|
|
|
|
uint8_t _intlv_bits, uint8_t _intlv_match)
|
|
|
|
: _start(_start), _end(_end), intlvHighBit(_intlv_high_bit),
|
|
|
|
intlvBits(_intlv_bits), intlvMatch(_intlv_match)
|
2012-09-19 12:15:44 +02:00
|
|
|
{}
|
|
|
|
|
|
|
|
AddrRange(Addr _start, Addr _end)
|
2013-01-07 19:05:38 +01:00
|
|
|
: _start(_start), _end(_end), intlvHighBit(0), intlvBits(0),
|
|
|
|
intlvMatch(0)
|
2012-09-19 12:15:44 +02:00
|
|
|
{}
|
|
|
|
|
2013-01-07 19:05:38 +01:00
|
|
|
/**
|
|
|
|
* Create an address range by merging a collection of interleaved
|
|
|
|
* ranges.
|
|
|
|
*
|
|
|
|
* @param ranges Interleaved ranges to be merged
|
|
|
|
*/
|
|
|
|
AddrRange(const std::vector<AddrRange>& ranges)
|
|
|
|
: _start(1), _end(0), intlvHighBit(0), intlvBits(0), intlvMatch(0)
|
|
|
|
{
|
|
|
|
if (!ranges.empty()) {
|
|
|
|
// get the values from the first one and check the others
|
|
|
|
_start = ranges.front()._start;
|
|
|
|
_end = ranges.front()._end;
|
|
|
|
intlvHighBit = ranges.front().intlvHighBit;
|
|
|
|
intlvBits = ranges.front().intlvBits;
|
|
|
|
|
|
|
|
if (ranges.size() != (ULL(1) << intlvBits))
|
|
|
|
fatal("Got %d ranges spanning %d interleaving bits\n",
|
|
|
|
ranges.size(), intlvBits);
|
|
|
|
|
|
|
|
uint8_t match = 0;
|
|
|
|
for (std::vector<AddrRange>::const_iterator r = ranges.begin();
|
|
|
|
r != ranges.end(); ++r) {
|
|
|
|
if (!mergesWith(*r))
|
|
|
|
fatal("Can only merge ranges with the same start, end "
|
|
|
|
"and interleaving bits\n");
|
|
|
|
|
|
|
|
if (r->intlvMatch != match)
|
|
|
|
fatal("Expected interleave match %d but got %d when "
|
|
|
|
"merging\n", match, r->intlvMatch);
|
|
|
|
++match;
|
|
|
|
}
|
|
|
|
|
|
|
|
// our range is complete and we can turn this into a
|
|
|
|
// non-interleaved range
|
|
|
|
intlvHighBit = 0;
|
|
|
|
intlvBits = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-01-07 19:05:38 +01:00
|
|
|
/**
|
|
|
|
* Determine if the range is interleaved or not.
|
|
|
|
*
|
|
|
|
* @return true if interleaved
|
|
|
|
*/
|
|
|
|
bool interleaved() const { return intlvBits != 0; }
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Determing the interleaving granularity of the range.
|
|
|
|
*
|
|
|
|
* @return The size of the regions created by the interleaving bits
|
|
|
|
*/
|
2013-03-07 11:55:03 +01:00
|
|
|
uint64_t granularity() const
|
|
|
|
{
|
2013-06-27 11:49:49 +02:00
|
|
|
return ULL(1) << (intlvHighBit - intlvBits + 1);
|
2013-03-07 11:55:03 +01:00
|
|
|
}
|
2013-01-07 19:05:38 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Determine the number of interleaved address stripes this range
|
|
|
|
* is part of.
|
|
|
|
*
|
|
|
|
* @return The number of stripes spanned by the interleaving bits
|
|
|
|
*/
|
|
|
|
uint32_t stripes() const { return ULL(1) << intlvBits; }
|
|
|
|
|
2013-01-07 19:05:38 +01:00
|
|
|
/**
|
|
|
|
* Get the size of the address range. For a case where
|
2013-01-07 19:05:38 +01:00
|
|
|
* interleaving is used we make the simplifying assumption that
|
|
|
|
* the size is a divisible by the size of the interleaving slice.
|
2013-01-07 19:05:38 +01:00
|
|
|
*/
|
2013-01-07 19:05:38 +01:00
|
|
|
Addr size() const
|
|
|
|
{
|
|
|
|
return (_end - _start + 1) >> intlvBits;
|
|
|
|
}
|
2013-01-07 19:05:38 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Determine if the range is valid.
|
|
|
|
*/
|
2014-10-11 22:02:22 +02:00
|
|
|
bool valid() const { return _start <= _end; }
|
2013-01-07 19:05:38 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the start address of the range.
|
|
|
|
*/
|
|
|
|
Addr start() const { return _start; }
|
2012-09-19 12:15:44 +02:00
|
|
|
|
2013-01-07 19:05:38 +01:00
|
|
|
/**
|
|
|
|
* Get a string representation of the range. This could
|
|
|
|
* alternatively be implemented as a operator<<, but at the moment
|
|
|
|
* that seems like overkill.
|
|
|
|
*/
|
|
|
|
std::string to_string() const
|
|
|
|
{
|
2013-01-07 19:05:38 +01:00
|
|
|
if (interleaved())
|
|
|
|
return csprintf("[%#llx : %#llx], [%d : %d] = %d", _start, _end,
|
|
|
|
intlvHighBit, intlvHighBit - intlvBits + 1,
|
|
|
|
intlvMatch);
|
|
|
|
else
|
|
|
|
return csprintf("[%#llx : %#llx]", _start, _end);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Determine if another range merges with the current one, i.e. if
|
|
|
|
* they are part of the same contigous range and have the same
|
|
|
|
* interleaving bits.
|
|
|
|
*
|
|
|
|
* @param r Range to evaluate merging with
|
|
|
|
* @return true if the two ranges would merge
|
|
|
|
*/
|
|
|
|
bool mergesWith(const AddrRange& r) const
|
|
|
|
{
|
|
|
|
return r._start == _start && r._end == _end &&
|
|
|
|
r.intlvHighBit == intlvHighBit &&
|
|
|
|
r.intlvBits == intlvBits;
|
2013-01-07 19:05:38 +01:00
|
|
|
}
|
2012-10-15 14:07:04 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Determine if another range intersects this one, i.e. if there
|
|
|
|
* is an address that is both in this range and the other
|
|
|
|
* range. No check is made to ensure either range is valid.
|
|
|
|
*
|
|
|
|
* @param r Range to intersect with
|
|
|
|
* @return true if the intersection of the two ranges is not empty
|
|
|
|
*/
|
|
|
|
bool intersects(const AddrRange& r) const
|
|
|
|
{
|
2013-01-07 19:05:38 +01:00
|
|
|
if (!interleaved()) {
|
|
|
|
return _start <= r._end && _end >= r._start;
|
|
|
|
}
|
|
|
|
|
|
|
|
// the current range is interleaved, split the check up in
|
|
|
|
// three cases
|
|
|
|
if (r.size() == 1)
|
|
|
|
// keep it simple and check if the address is within
|
|
|
|
// this range
|
|
|
|
return contains(r.start());
|
|
|
|
else if (!r.interleaved())
|
|
|
|
// be conservative and ignore the interleaving
|
|
|
|
return _start <= r._end && _end >= r._start;
|
|
|
|
else if (mergesWith(r))
|
|
|
|
// restrict the check to ranges that belong to the
|
|
|
|
// same chunk
|
|
|
|
return intlvMatch == r.intlvMatch;
|
|
|
|
else
|
|
|
|
panic("Cannot test intersection of interleaved range %s\n",
|
|
|
|
to_string());
|
2012-10-15 14:07:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Determine if this range is a subset of another range, i.e. if
|
|
|
|
* every address in this range is also in the other range. No
|
|
|
|
* check is made to ensure either range is valid.
|
|
|
|
*
|
|
|
|
* @param r Range to compare with
|
|
|
|
* @return true if the this range is a subset of the other one
|
|
|
|
*/
|
|
|
|
bool isSubset(const AddrRange& r) const
|
|
|
|
{
|
2013-01-07 19:05:38 +01:00
|
|
|
if (interleaved())
|
|
|
|
panic("Cannot test subset of interleaved range %s\n", to_string());
|
2013-01-07 19:05:38 +01:00
|
|
|
return _start >= r._start && _end <= r._end;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Determine if the range contains an address.
|
|
|
|
*
|
|
|
|
* @param a Address to compare with
|
|
|
|
* @return true if the address is in the range
|
|
|
|
*/
|
|
|
|
bool contains(const Addr& a) const
|
|
|
|
{
|
2013-01-07 19:05:38 +01:00
|
|
|
// check if the address is in the range and if there is either
|
|
|
|
// no interleaving, or with interleaving also if the selected
|
|
|
|
// bits from the address match the interleaving value
|
|
|
|
return a >= _start && a <= _end &&
|
2013-02-19 11:56:05 +01:00
|
|
|
(!interleaved() ||
|
2013-01-07 19:05:38 +01:00
|
|
|
(bits(a, intlvHighBit, intlvHighBit - intlvBits + 1) ==
|
|
|
|
intlvMatch));
|
2012-10-15 14:07:04 +02:00
|
|
|
}
|
2012-09-19 12:15:44 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Keep the operators away from SWIG.
|
|
|
|
*/
|
|
|
|
#ifndef SWIG
|
|
|
|
|
2013-01-07 19:05:38 +01:00
|
|
|
/**
|
|
|
|
* Less-than operator used to turn an STL map into a binary search
|
|
|
|
* tree of non-overlapping address ranges.
|
|
|
|
*
|
|
|
|
* @param r Range to compare with
|
|
|
|
* @return true if the start address is less than that of the other range
|
|
|
|
*/
|
|
|
|
bool operator<(const AddrRange& r) const
|
|
|
|
{
|
2013-01-07 19:05:38 +01:00
|
|
|
if (_start != r._start)
|
|
|
|
return _start < r._start;
|
|
|
|
else
|
|
|
|
// for now assume that the end is also the same, and that
|
|
|
|
// we are looking at the same interleaving bits
|
|
|
|
return intlvMatch < r.intlvMatch;
|
2013-01-07 19:05:38 +01:00
|
|
|
}
|
2012-09-19 12:15:44 +02:00
|
|
|
|
2013-01-07 19:05:38 +01:00
|
|
|
#endif // SWIG
|
|
|
|
};
|
2012-09-19 12:15:44 +02:00
|
|
|
|
|
|
|
inline AddrRange
|
|
|
|
RangeEx(Addr start, Addr end)
|
2013-01-07 19:05:38 +01:00
|
|
|
{ return AddrRange(start, end - 1); }
|
2012-09-19 12:15:44 +02:00
|
|
|
|
|
|
|
inline AddrRange
|
|
|
|
RangeIn(Addr start, Addr end)
|
2013-01-07 19:05:38 +01:00
|
|
|
{ return AddrRange(start, end); }
|
2012-09-19 12:15:44 +02:00
|
|
|
|
|
|
|
inline AddrRange
|
|
|
|
RangeSize(Addr start, Addr size)
|
2013-01-07 19:05:38 +01:00
|
|
|
{ return AddrRange(start, start + size - 1); }
|
2012-09-19 12:15:44 +02:00
|
|
|
|
|
|
|
#endif // __BASE_ADDR_RANGE_HH__
|