addr_range.hh revision 9411
12SN/A/*
21762SN/A * Copyright (c) 2012 ARM Limited
35502Snate@binkert.org * All rights reserved
49983Sstever@gmail.com *
52SN/A * The license below extends only to copyright in the software and shall
62SN/A * not be construed as granting a license to any other intellectual
72SN/A * property including but not limited to intellectual property relating
82SN/A * to a hardware implementation of the functionality of the software
92SN/A * licensed hereunder.  You may use the software subject to the license
102SN/A * terms below provided that you ensure that this notice is replicated
112SN/A * unmodified and in its entirety in all distributions of the software,
122SN/A * modified or unmodified, in source code or in binary form.
132SN/A *
142SN/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
292665Ssaidi@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
302665Ssaidi@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
312665Ssaidi@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
322665Ssaidi@eecs.umich.edu * 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,
355501Snate@binkert.org * 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.
392SN/A *
405502Snate@binkert.org * Authors: Nathan Binkert
415501Snate@binkert.org *          Steve Reinhardt
425501Snate@binkert.org *          Andreas Hansson
431717SN/A */
448232Snate@binkert.org
455501Snate@binkert.org#ifndef __BASE_ADDR_RANGE_HH__
469356Snilay@cs.wisc.edu#define __BASE_ADDR_RANGE_HH__
472SN/A
482SN/A#include "base/bitfield.hh"
492SN/A#include "base/cprintf.hh"
509983Sstever@gmail.com#include "base/misc.hh"
519983Sstever@gmail.com#include "base/types.hh"
522SN/A
539983Sstever@gmail.comclass AddrRange
542SN/A{
559983Sstever@gmail.com
562SN/A  private:
572SN/A
589983Sstever@gmail.com    /// Private fields for the start and end of the range
599983Sstever@gmail.com    Addr _start;
609983Sstever@gmail.com    Addr _end;
619983Sstever@gmail.com
629983Sstever@gmail.com    /// The high bit of the slice that is used for interleaving
639983Sstever@gmail.com    uint8_t intlvHighBit;
649983Sstever@gmail.com
659983Sstever@gmail.com    /// The number of bits used for interleaving, set to 0 to disable
669983Sstever@gmail.com    uint8_t intlvBits;
679983Sstever@gmail.com
689983Sstever@gmail.com    /// The value to compare the slice addr[high:(high - bits + 1)]
699983Sstever@gmail.com    /// with.
709983Sstever@gmail.com    uint8_t intlvMatch;
719983Sstever@gmail.com
729983Sstever@gmail.com  public:
739983Sstever@gmail.com
742SN/A    AddrRange()
754017Sstever@eecs.umich.edu        : _start(1), _end(0), intlvHighBit(0), intlvBits(0), intlvMatch(0)
764016Sstever@eecs.umich.edu    {}
774017Sstever@eecs.umich.edu
784016Sstever@eecs.umich.edu    AddrRange(Addr _start, Addr _end, uint8_t _intlv_high_bit,
795768Snate@binkert.org              uint8_t _intlv_bits, uint8_t _intlv_match)
805768Snate@binkert.org        : _start(_start), _end(_end), intlvHighBit(_intlv_high_bit),
815774Snate@binkert.org          intlvBits(_intlv_bits), intlvMatch(_intlv_match)
827059Snate@binkert.org    {}
835768Snate@binkert.org
845768Snate@binkert.org    AddrRange(Addr _start, Addr _end)
855768Snate@binkert.org        : _start(_start), _end(_end), intlvHighBit(0), intlvBits(0),
865768Snate@binkert.org          intlvMatch(0)
875768Snate@binkert.org    {}
885768Snate@binkert.org
895768Snate@binkert.org    /**
905768Snate@binkert.org     * Determine if the range is interleaved or not.
915768Snate@binkert.org     *
925768Snate@binkert.org     * @return true if interleaved
935768Snate@binkert.org     */
945768Snate@binkert.org    bool interleaved() const { return intlvBits != 0; }
955768Snate@binkert.org
965602Snate@binkert.org    /**
975602Snate@binkert.org     * Determing the interleaving granularity of the range.
985502Snate@binkert.org     *
995503Snate@binkert.org     * @return The size of the regions created by the interleaving bits
1005502Snate@binkert.org     */
1015502Snate@binkert.org    uint64_t granularity() const { return ULL(1) << intlvHighBit; }
1025502Snate@binkert.org
1035502Snate@binkert.org    /**
1045502Snate@binkert.org     * Determine the number of interleaved address stripes this range
1055503Snate@binkert.org     * is part of.
1065502Snate@binkert.org     *
1075502Snate@binkert.org     * @return The number of stripes spanned by the interleaving bits
1085502Snate@binkert.org     */
1095502Snate@binkert.org    uint32_t stripes() const { return ULL(1) << intlvBits; }
1105503Snate@binkert.org
1115503Snate@binkert.org    /**
1125503Snate@binkert.org     * Get the size of the address range. For a case where
1135502Snate@binkert.org     * interleaving is used we make the simplifying assumption that
1145503Snate@binkert.org     * the size is a divisible by the size of the interleaving slice.
1155502Snate@binkert.org     */
1165502Snate@binkert.org    Addr size() const
1172SN/A    {
1182SN/A        return (_end - _start + 1) >> intlvBits;
1192SN/A    }
1205502Snate@binkert.org
1215502Snate@binkert.org    /**
1225602Snate@binkert.org     * Determine if the range is valid.
1235502Snate@binkert.org     */
1245502Snate@binkert.org    bool valid() const { return _start < _end; }
1252SN/A
1265502Snate@binkert.org    /**
1275502Snate@binkert.org     * Get the start address of the range.
1285503Snate@binkert.org     */
1295503Snate@binkert.org    Addr start() const { return _start; }
1305503Snate@binkert.org
1315503Snate@binkert.org    /**
1325503Snate@binkert.org     * Get a string representation of the range. This could
1335502Snate@binkert.org     * alternatively be implemented as a operator<<, but at the moment
1342SN/A     * that seems like overkill.
1355503Snate@binkert.org     */
1365503Snate@binkert.org    std::string to_string() const
1375602Snate@binkert.org    {
1385502Snate@binkert.org        if (interleaved())
1392SN/A            return csprintf("[%#llx : %#llx], [%d : %d] = %d", _start, _end,
1405602Snate@binkert.org                            intlvHighBit, intlvHighBit - intlvBits + 1,
1415602Snate@binkert.org                            intlvMatch);
1425502Snate@binkert.org        else
1435503Snate@binkert.org            return csprintf("[%#llx : %#llx]", _start, _end);
1445503Snate@binkert.org    }
1455502Snate@binkert.org
1465503Snate@binkert.org    /**
1475503Snate@binkert.org     * Determine if another range merges with the current one, i.e. if
1485503Snate@binkert.org     * they are part of the same contigous range and have the same
1495503Snate@binkert.org     * interleaving bits.
1505503Snate@binkert.org     *
1515503Snate@binkert.org     * @param r Range to evaluate merging with
1525503Snate@binkert.org     * @return true if the two ranges would merge
1535503Snate@binkert.org     */
1545503Snate@binkert.org    bool mergesWith(const AddrRange& r) const
1555503Snate@binkert.org    {
1565503Snate@binkert.org        return r._start == _start && r._end == _end &&
1575503Snate@binkert.org            r.intlvHighBit == intlvHighBit &&
1585503Snate@binkert.org            r.intlvBits == intlvBits;
1595503Snate@binkert.org    }
1605502Snate@binkert.org
1615502Snate@binkert.org    /**
1625503Snate@binkert.org     * Determine if another range intersects this one, i.e. if there
1635503Snate@binkert.org     * is an address that is both in this range and the other
1642SN/A     * range. No check is made to ensure either range is valid.
1655502Snate@binkert.org     *
1665503Snate@binkert.org     * @param r Range to intersect with
1675503Snate@binkert.org     * @return true if the intersection of the two ranges is not empty
1685503Snate@binkert.org     */
1692SN/A    bool intersects(const AddrRange& r) const
1702SN/A    {
1712SN/A        if (!interleaved()) {
1722SN/A            return _start <= r._end && _end >= r._start;
1732SN/A        }
1742SN/A
1755502Snate@binkert.org        // the current range is interleaved, split the check up in
1762SN/A        // three cases
1779983Sstever@gmail.com        if (r.size() == 1)
1789983Sstever@gmail.com            // keep it simple and check if the address is within
1795502Snate@binkert.org            // this range
1805502Snate@binkert.org            return contains(r.start());
1815502Snate@binkert.org        else if (!r.interleaved())
1825602Snate@binkert.org            // be conservative and ignore the interleaving
1832SN/A            return _start <= r._end && _end >= r._start;
1842SN/A        else if (mergesWith(r))
1852SN/A            // restrict the check to ranges that belong to the
1865502Snate@binkert.org            // same chunk
1872SN/A            return intlvMatch == r.intlvMatch;
1885502Snate@binkert.org        else
1895502Snate@binkert.org            panic("Cannot test intersection of interleaved range %s\n",
1902SN/A                  to_string());
1915502Snate@binkert.org    }
1922SN/A
1932SN/A    /**
1945502Snate@binkert.org     * Determine if this range is a subset of another range, i.e. if
1955502Snate@binkert.org     * every address in this range is also in the other range. No
1965502Snate@binkert.org     * check is made to ensure either range is valid.
1975503Snate@binkert.org     *
1985503Snate@binkert.org     * @param r Range to compare with
1995502Snate@binkert.org     * @return true if the this range is a subset of the other one
2005602Snate@binkert.org     */
2012SN/A    bool isSubset(const AddrRange& r) const
2022SN/A    {
2032667Sstever@eecs.umich.edu        if (interleaved())
2042SN/A            panic("Cannot test subset of interleaved range %s\n", to_string());
2052SN/A        return _start >= r._start && _end <= r._end;
2065503Snate@binkert.org    }
2075503Snate@binkert.org
2085769Snate@binkert.org    /**
2095502Snate@binkert.org     * Determine if the range contains an address.
2105503Snate@binkert.org     *
2115503Snate@binkert.org     * @param a Address to compare with
2125503Snate@binkert.org     * @return true if the address is in the range
2135503Snate@binkert.org     */
2145503Snate@binkert.org    bool contains(const Addr& a) const
2155503Snate@binkert.org    {
2165503Snate@binkert.org        // check if the address is in the range and if there is either
2175502Snate@binkert.org        // no interleaving, or with interleaving also if the selected
2185502Snate@binkert.org        // bits from the address match the interleaving value
2195503Snate@binkert.org        return a >= _start && a <= _end &&
2205502Snate@binkert.org            (interleaved() ||
2212SN/A             (bits(a, intlvHighBit, intlvHighBit - intlvBits + 1) ==
2222SN/A              intlvMatch));
2232667Sstever@eecs.umich.edu    }
2249356Snilay@cs.wisc.edu
2259356Snilay@cs.wisc.edu/**
2269356Snilay@cs.wisc.edu * Keep the operators away from SWIG.
2272SN/A */
2282667Sstever@eecs.umich.edu#ifndef SWIG
2299328SAli.Saidi@ARM.com
2309328SAli.Saidi@ARM.com    /**
2312667Sstever@eecs.umich.edu     * Less-than operator used to turn an STL map into a binary search
2322667Sstever@eecs.umich.edu     * tree of non-overlapping address ranges.
2332667Sstever@eecs.umich.edu     *
2345769Snate@binkert.org     * @param r Range to compare with
2352667Sstever@eecs.umich.edu     * @return true if the start address is less than that of the other range
2362SN/A     */
2375769Snate@binkert.org    bool operator<(const AddrRange& r) const
2382SN/A    {
2392667Sstever@eecs.umich.edu        if (_start != r._start)
2402667Sstever@eecs.umich.edu            return _start < r._start;
2412SN/A        else
2422SN/A            // for now assume that the end is also the same, and that
243224SN/A            // we are looking at the same interleaving bits
244224SN/A            return intlvMatch < r.intlvMatch;
245224SN/A    }
246224SN/A
247224SN/A#endif // SWIG
2485769Snate@binkert.org};
2495769Snate@binkert.org
250224SN/Ainline AddrRange
251224SN/ARangeEx(Addr start, Addr end)
252224SN/A{ return AddrRange(start, end - 1); }
253237SN/A
254224SN/Ainline AddrRange
2559983Sstever@gmail.comRangeIn(Addr start, Addr end)
2569983Sstever@gmail.com{ return AddrRange(start, end); }
2579983Sstever@gmail.com
2589983Sstever@gmail.cominline AddrRange
2599983Sstever@gmail.comRangeSize(Addr start, Addr size)
2605695Snate@binkert.org{ return AddrRange(start, start + size - 1); }
2619983Sstever@gmail.com
262224SN/A#endif // __BASE_ADDR_RANGE_HH__
263224SN/A