From: Andreas Sandberg Date: Wed, 9 Oct 2019 08:45:51 +0000 (+0100) Subject: base: Add classes that encapsulate a channel address X-Git-Tag: v19.0.0.0~432 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=e0419b2530d2a63af9c55cc3d370719e65baca1f;p=gem5.git base: Add classes that encapsulate a channel address There are cases where the memory system needs to reason about channel-local addresses. These are currently represented using the Addr and AddrRange classes. This is not ideal since it doesn't provide any type safety when working with global addresses and channel-local addresses. This is particularly problematic when porting existing components to work in multi-channel configurations. This changeset introduces the new ChannelAddr and ChannelAddrRange classes. These classes encapsulate channel-local addresses in a contiguous address space. These can, for example, be used in a memory controller to represent a flat address space when calculating timings or in a sectored cache. Change-Id: I45d4061ebc8507a10d0a4577b28796dc5ec7a469 Signed-off-by: Andreas Sandberg Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/21600 Reviewed-by: Bobby R. Bruce Reviewed-by: Daniel Carvalho Reviewed-by: Nikos Nikoleris Reviewed-by: Jason Lowe-Power Maintainer: Jason Lowe-Power Tested-by: kokoro --- diff --git a/src/base/SConscript b/src/base/SConscript index b4b381bf1..129110fef 100644 --- a/src/base/SConscript +++ b/src/base/SConscript @@ -40,6 +40,7 @@ Source('imgwriter.cc') Source('bmpwriter.cc') Source('callback.cc') GTest('callback.test', 'callback.test.cc', 'callback.cc') +Source('channel_addr.cc') Source('cprintf.cc', add_tags='gtest lib') GTest('cprintf.test', 'cprintf.test.cc') Source('debug.cc') @@ -90,6 +91,7 @@ if env['USE_HDF5']: GTest('addr_range.test', 'addr_range.test.cc') GTest('addr_range_map.test', 'addr_range_map.test.cc') GTest('bitunion.test', 'bitunion.test.cc') +GTest('channel_addr.test', 'channel_addr.test.cc') GTest('circlebuf.test', 'circlebuf.test.cc') GTest('circular_queue.test', 'circular_queue.test.cc') GTest('sat_counter.test', 'sat_counter.test.cc') diff --git a/src/base/channel_addr.cc b/src/base/channel_addr.cc new file mode 100644 index 000000000..c50f94cc3 --- /dev/null +++ b/src/base/channel_addr.cc @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2019 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. + * + * 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: Andreas Sandberg + */ + +#include "base/channel_addr.hh" + +#include "base/logging.hh" + +ChannelAddrRange::ChannelAddrRange(AddrRange ch_range, Addr start, Addr end) + : ChannelAddrRange(ChannelAddr(ch_range, start), + ChannelAddr(ch_range, end)) +{ + panic_if(!ch_range.valid(), "Invalid channel range."); +} + +ChannelAddrRange::ChannelAddrRange(AddrRange ch_range, AddrRange range) + : ChannelAddrRange(ch_range, range.start(), range.end()) +{ + panic_if(range.interleaved(), + "Only contiguous ranges can be mapped onto an interleaved range"); +} + + +std::ostream & +operator<<(std::ostream &out, const ChannelAddr &addr) +{ + return out << (ChannelAddr::Type)addr; +} diff --git a/src/base/channel_addr.hh b/src/base/channel_addr.hh new file mode 100644 index 000000000..abb01be59 --- /dev/null +++ b/src/base/channel_addr.hh @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2019 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. + * + * 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: Andreas Sandberg + */ + +#ifndef __BASE_CHANNEL_ADDR_HH__ +#define __BASE_CHANNEL_ADDR_HH__ + +#include + +#include "base/addr_range.hh" + +/** + * Class holding a guest address in a contiguous channel-local address + * space. + */ +class ChannelAddr +{ + public: + using Type = Addr; + + /** Explicit constructor assigning a value. */ + explicit constexpr ChannelAddr(Type _a) : a(_a) { } + + /** Converting back to the value type. */ + explicit constexpr operator Type() const { return a; } + + /** Converting back to the value type. */ + constexpr Type value() const { return a; } + + constexpr ChannelAddr() : a(0) { } + + ChannelAddr(const AddrRange &range, Addr _a) + : a(range.removeIntlvBits(_a)) {} + + ChannelAddr(const ChannelAddr &) = default; + ChannelAddr &operator=(const ChannelAddr &) = default; + + + Addr getPA(const AddrRange &range) const { + return range.addIntlvBits(a); + } + + constexpr ChannelAddr operator|(const Type b) const { + return ChannelAddr(a | b); + } + constexpr ChannelAddr operator&(const Type b) const { + return ChannelAddr(a & b); + } + + constexpr ChannelAddr operator>>(const int b) const { + return ChannelAddr(a >> b); + } + + constexpr ChannelAddr operator<<(const int b) const { + return ChannelAddr(a << b); + } + + constexpr ChannelAddr operator*(const Type &b) const { + return ChannelAddr(a * b); + } + + constexpr ChannelAddr operator/(const Type &b) const { + return ChannelAddr(a / b); + } + + constexpr ChannelAddr operator+(const Type &b) const { + return ChannelAddr(a + b); + } + + constexpr ChannelAddr operator-(const Type &b) const { + return ChannelAddr(a - b); + } + + constexpr ChannelAddr operator|(const ChannelAddr &b) const { + return ChannelAddr(a | b.a); + } + + constexpr ChannelAddr operator&(const ChannelAddr &b) const { + return ChannelAddr(a & b.a); + } + + constexpr ChannelAddr operator^(const ChannelAddr &b) const { + return ChannelAddr(a ^ b.a); + } + + constexpr ChannelAddr operator+(const ChannelAddr &b) const { + return ChannelAddr(a + b.a); + } + + constexpr ChannelAddr operator-(const ChannelAddr &b) const { + return ChannelAddr(a - b.a); + } + + constexpr bool operator>(const ChannelAddr &b) const { return a > b.a; } + constexpr bool operator>=(const ChannelAddr &b) const { return a >= b.a; } + constexpr bool operator<(const ChannelAddr &b) const { return a < b.a; } + constexpr bool operator<=(const ChannelAddr &b) const { return a <= b.a; } + constexpr bool operator==(const ChannelAddr &b) const { return a == b.a; } + constexpr bool operator!=(const ChannelAddr &b) const { return a != b.a; } + + private: + /** Member holding the actual value. */ + Type a; +}; + +/** + * The ChanneelAddrRange class describes a contiguous range of + * addresses in a contiguous channel-local address space. + */ +class ChannelAddrRange +{ + public: + constexpr ChannelAddrRange() + : ChannelAddrRange(ChannelAddr(1), ChannelAddr(0)) {} + + constexpr ChannelAddrRange(ChannelAddr start, ChannelAddr end) + : _start(start), _end(end) {} + + ChannelAddrRange(AddrRange ch_range, Addr start, Addr end); + ChannelAddrRange(AddrRange ch_range, AddrRange range); + + constexpr ChannelAddrRange(const ChannelAddrRange &) = default; + + constexpr ChannelAddr size() const { return _end - _start + 1; } + + constexpr bool valid() const { return _start <= _end; } + + constexpr ChannelAddr start() const { return _start; } + constexpr ChannelAddr end() const { return _end; } + + constexpr bool contains(ChannelAddr a) const { + return a >= _start && a <= _end; + } + + protected: + ChannelAddr _start; + ChannelAddr _end; +}; + +namespace std +{ + template<> + struct hash + { + typedef ChannelAddr argument_type; + typedef std::size_t result_type; + + result_type + operator()(argument_type const &a) const noexcept { + return std::hash{}( + static_cast(a)); + } + }; +} + +std::ostream &operator<<(std::ostream &out, const ChannelAddr &addr); + +#endif // __BASE_CHANNEL_ADDR_HH__ diff --git a/src/base/channel_addr.test.cc b/src/base/channel_addr.test.cc new file mode 100644 index 000000000..877b9211e --- /dev/null +++ b/src/base/channel_addr.test.cc @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2019 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. + * + * 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: Andreas Sandberg + */ + +#include + +#include "base/channel_addr.hh" + +/* Default range should be invalid */ +TEST(ChannelAddrRange, DefaultInvalid) +{ + ChannelAddrRange default_range; + + EXPECT_FALSE(default_range.valid()); +} + +/* Ensure that range bounds are inclusive */ +TEST(ChannelAddrRange, Range) +{ + ChannelAddrRange range(ChannelAddr(1), ChannelAddr(3)); + + EXPECT_FALSE(range.contains(ChannelAddr(0))); + EXPECT_TRUE(range.contains(ChannelAddr(1))); + EXPECT_TRUE(range.contains(ChannelAddr(2))); + EXPECT_TRUE(range.contains(ChannelAddr(3))); + EXPECT_FALSE(range.contains(ChannelAddr(4))); + + EXPECT_EQ(range.start(), ChannelAddr(1)); + EXPECT_EQ(range.end(), ChannelAddr(3)); + EXPECT_EQ(range.size(), ChannelAddr(3)); +}