base,python: Expand AddrRange exclude and add subtraction operators.

Expand exclude to work with an AddrRange or AddrRangeList, define
versions to exclude both from an AddrRangeList, and make all available
through subtraction operators. Add -= operators for AddrRangeList with
another AddrRangeList or AddrRange.

Change-Id: Ic48f0c45a4809dbc51e1d3133e8319134aabe29e
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/50347
Tested-by: kokoro <noreply+kokoro@google.com>
Reviewed-by: Daniel Carvalho <odanrc@yahoo.com.br>
Maintainer: Daniel Carvalho <odanrc@yahoo.com.br>
This commit is contained in:
Gabe Black
2021-09-14 01:03:46 -07:00
parent 416939c5c2
commit e9b7f08abb
3 changed files with 199 additions and 1 deletions

View File

@@ -677,6 +677,12 @@ class AddrRange
return ranges;
}
AddrRangeList
exclude(const AddrRange &excluded_range) const
{
return exclude(AddrRangeList{excluded_range});
}
/**
* Less-than operator used to turn an STL map into a binary search
* tree of non-overlapping address ranges.
@@ -728,6 +734,62 @@ class AddrRange
}
};
static inline AddrRangeList
operator-(const AddrRange &range, const AddrRangeList &to_exclude)
{
return range.exclude(to_exclude);
}
static inline AddrRangeList
operator-(const AddrRange &range, const AddrRange &to_exclude)
{
return range.exclude(to_exclude);
}
static inline AddrRangeList
exclude(const AddrRangeList &base, AddrRangeList to_exclude)
{
to_exclude.sort();
AddrRangeList ret;
for (const auto &range: base)
ret.splice(ret.end(), range.exclude(to_exclude));
return ret;
}
static inline AddrRangeList
exclude(const AddrRangeList &base, const AddrRange &to_exclude)
{
return exclude(base, AddrRangeList{to_exclude});
}
static inline AddrRangeList
operator-(const AddrRangeList &base, const AddrRangeList &to_exclude)
{
return exclude(base, to_exclude);
}
static inline AddrRangeList
operator-=(AddrRangeList &base, const AddrRangeList &to_exclude)
{
base = base - to_exclude;
return base;
}
static inline AddrRangeList
operator-(const AddrRangeList &base, const AddrRange &to_exclude)
{
return exclude(base, to_exclude);
}
static inline AddrRangeList
operator-=(AddrRangeList &base, const AddrRange &to_exclude)
{
base = base - to_exclude;
return base;
}
/**
* @ingroup api_addr_range
*/

View File

@@ -1409,6 +1409,141 @@ TEST(AddrRangeTest, MultipleExclusionUnsorted)
EXPECT_THAT(ranges, ElementsAre(expected_range1, expected_range2));
}
TEST(AddrRangeTest, ExclusionOfSingleRange)
{
const AddrRange expected_range1(0x100, 0x140);
const AddrRange expected_range2(0x1c0, 0x200);
AddrRange r(0x100, 0x200);
auto ranges = r.exclude(AddrRange(0x140, 0x1c0));
EXPECT_EQ(ranges.size(), 2);
EXPECT_THAT(ranges, ElementsAre(expected_range1, expected_range2));
}
TEST(AddrRangeTest, ExclusionOfRangeFromRangeList)
{
AddrRangeList base({AddrRange(0x100, 0x200), AddrRange(0x300, 0x400)});
const AddrRange expected_range1(0x100, 0x180);
const AddrRange expected_range2(0x380, 0x400);
auto ranges = exclude(base, AddrRange(0x180, 0x380));
EXPECT_EQ(ranges.size(), 2);
EXPECT_THAT(ranges, ElementsAre(expected_range1, expected_range2));
}
TEST(AddrRangeTest, ExclusionOfRangeListFromRangeList)
{
AddrRangeList base({AddrRange(0x100, 0x200), AddrRange(0x300, 0x400)});
const AddrRange expected_range1(0x100, 0x140);
const AddrRange expected_range2(0x180, 0x200);
const AddrRange expected_range3(0x300, 0x340);
const AddrRange expected_range4(0x380, 0x400);
const AddrRangeList to_exclude({
AddrRange(0x140, 0x180), AddrRange(0x340, 0x380)});
auto ranges = exclude(base, to_exclude);
EXPECT_EQ(ranges.size(), 4);
EXPECT_THAT(ranges, ElementsAre(
expected_range1, expected_range2,
expected_range3, expected_range4));
}
TEST(AddrRangeTest, SubtractionOperatorRange)
{
const AddrRange expected_range1(0x100, 0x140);
const AddrRange expected_range2(0x1c0, 0x200);
AddrRange r(0x100, 0x200);
auto ranges = r - AddrRange(0x140, 0x1c0);
EXPECT_EQ(ranges.size(), 2);
EXPECT_THAT(ranges, ElementsAre(expected_range1, expected_range2));
}
TEST(AddrRangeTest, SubtractionOperatorRangeList)
{
const AddrRange expected_range1(0x100, 0x140);
const AddrRange expected_range2(0x160, 0x180);
const AddrRange expected_range3(0x1a0, 0x200);
AddrRange r(0x100, 0x200);
auto ranges = r - AddrRangeList(
{AddrRange(0x140, 0x160), AddrRange(0x180, 0x1a0)});
EXPECT_EQ(ranges.size(), 3);
EXPECT_THAT(ranges, ElementsAre(
expected_range1, expected_range2, expected_range3));
}
TEST(AddrRangeTest, SubtractionOfRangeFromRangeList)
{
AddrRangeList base({AddrRange(0x100, 0x200), AddrRange(0x300, 0x400)});
const AddrRange expected_range1(0x100, 0x180);
const AddrRange expected_range2(0x380, 0x400);
auto ranges = base - AddrRange(0x180, 0x380);
EXPECT_EQ(ranges.size(), 2);
EXPECT_THAT(ranges, ElementsAre(expected_range1, expected_range2));
}
TEST(AddrRangeTest, SubtractionOfRangeListFromRangeList)
{
AddrRangeList base({AddrRange(0x100, 0x200), AddrRange(0x300, 0x400)});
const AddrRange expected_range1(0x100, 0x140);
const AddrRange expected_range2(0x180, 0x200);
const AddrRange expected_range3(0x300, 0x340);
const AddrRange expected_range4(0x380, 0x400);
const AddrRangeList to_exclude({
AddrRange(0x140, 0x180), AddrRange(0x340, 0x380)});
auto ranges = base - to_exclude;
EXPECT_EQ(ranges.size(), 4);
EXPECT_THAT(ranges, ElementsAre(
expected_range1, expected_range2,
expected_range3, expected_range4));
}
TEST(AddrRangeTest, SubtractionAssignmentOfRangeFromRangeList)
{
AddrRangeList base({AddrRange(0x100, 0x200), AddrRange(0x300, 0x400)});
const AddrRange expected_range1(0x100, 0x180);
const AddrRange expected_range2(0x380, 0x400);
base -= AddrRange(0x180, 0x380);
EXPECT_EQ(base.size(), 2);
EXPECT_THAT(base, ElementsAre(expected_range1, expected_range2));
}
TEST(AddrRangeTest, SubtractionAssignmentOfRangeListFromRangeList)
{
AddrRangeList base({AddrRange(0x100, 0x200), AddrRange(0x300, 0x400)});
const AddrRange expected_range1(0x100, 0x140);
const AddrRange expected_range2(0x180, 0x200);
const AddrRange expected_range3(0x300, 0x340);
const AddrRange expected_range4(0x380, 0x400);
const AddrRangeList to_exclude({
AddrRange(0x140, 0x180), AddrRange(0x340, 0x380)});
base -= to_exclude;
EXPECT_EQ(base.size(), 4);
EXPECT_THAT(base, ElementsAre(
expected_range1, expected_range2,
expected_range3, expected_range4));
}
/*
* InterleavingRanges:
* The exclude method does not support interleaving ranges

View File

@@ -154,7 +154,8 @@ init_range(py::module_ &m_native)
.def("mergesWith", &AddrRange::mergesWith)
.def("intersects", &AddrRange::intersects)
.def("isSubset", &AddrRange::isSubset)
.def("exclude", &AddrRange::exclude)
.def("exclude", static_cast<AddrRangeList (AddrRange::*)(
const AddrRangeList &) const>(&AddrRange::exclude))
;
m.def("RangeEx", &RangeEx);