+/*
+ * The following tests check the behavior of AddrRange when initialized with
+ * a start and end address, as well as masks to distinguish interleaving bits.
+ */
+TEST(AddrRangeTest, LsbInterleavingMask)
+{
+ Addr start = 0x00;
+ Addr end = 0xFF;
+ std::vector<Addr> masks;
+ /*
+ * The address is in range if the LSB is set, i.e. is the value is odd.
+ */
+ masks.push_back(1);
+ uint8_t intlv_match = 1;
+
+ AddrRange r(start, end, masks, intlv_match);
+ EXPECT_TRUE(r.valid());
+ EXPECT_EQ(start, r.start());
+ EXPECT_EQ(end, r.end());
+ /*
+ * With interleaving, it's assumed the size is equal to
+ * start - end >> [number of masks].
+ */
+ EXPECT_EQ(0x7F, r.size());
+ /*
+ * The Granularity, the size of regions created by the interleaving bits,
+ * which, in this case, is one.
+ */
+ EXPECT_EQ(1, r.granularity());
+ EXPECT_TRUE(r.interleaved());
+ EXPECT_EQ(ULL(2), r.stripes());
+ EXPECT_EQ("[0:0xff] a[0]^\b=1", r.to_string());
+}
+
+TEST(AddrRangeTest, TwoInterleavingMasks)
+{
+ Addr start = 0x0000;
+ Addr end = 0xFFFF;
+ std::vector<Addr> masks;
+ /*
+ * There are two marks, the two LSBs.
+ */
+ masks.push_back(1);
+ masks.push_back((1 << 1));
+ uint8_t intlv_match = (1 << 1) | 1;
+
+ AddrRange r(start, end, masks, intlv_match);
+ EXPECT_TRUE(r.valid());
+ EXPECT_EQ(start, r.start());
+ EXPECT_EQ(end, r.end());
+
+ EXPECT_EQ(0x3FFF, r.size());
+ EXPECT_TRUE(r.interleaved());
+ EXPECT_EQ(ULL(4), r.stripes());
+ EXPECT_EQ("[0:0xffff] a[0]^\b=1 a[1]^\b=1", r.to_string());
+}
+
+TEST(AddrRangeTest, ComplexInterleavingMasks)
+{
+ Addr start = 0x0000;
+ Addr end = 0xFFFF;
+ std::vector<Addr> masks;
+ masks.push_back((1 << 1) | 1);
+ masks.push_back((ULL(1) << 63) | (ULL(1) << 62));
+ uint8_t intlv_match = 0;
+
+ AddrRange r(start, end, masks, intlv_match);
+ EXPECT_TRUE(r.valid());
+ EXPECT_EQ(start, r.start());
+ EXPECT_EQ(end, r.end());
+
+ EXPECT_EQ(0x3FFF, r.size());
+ EXPECT_TRUE(r.interleaved());
+ EXPECT_EQ(ULL(4), r.stripes());
+ EXPECT_EQ("[0:0xffff] a[0]^a[1]^\b=0 a[62]^a[63]^\b=0", r.to_string());
+}
+
+TEST(AddrRangeTest, InterleavingAddressesMergesWith)
+{
+ Addr start1 = 0x0000;
+ Addr end1 = 0xFFFF;
+ std::vector<Addr> masks;
+ masks.push_back((1 << 29) | (1 << 20) | (1 << 10) | 1);
+ masks.push_back((1 << 2));
+ uint8_t intlv_match1 = 0;
+ AddrRange r1(start1, end1, masks, intlv_match1);
+
+ Addr start2 = 0x0000;
+ Addr end2 = 0xFFFF;
+ uint8_t intlv_match2 = 1; // intlv_match may differ.
+ AddrRange r2(start2, end2, masks, intlv_match2);
+
+ EXPECT_TRUE(r1.mergesWith(r2));
+ EXPECT_TRUE(r2.mergesWith(r1));
+}
+
+TEST(AddrRangeTest, InterleavingAddressesDoNotMergeWith)
+{
+ Addr start1 = 0x0000;
+ Addr end1 = 0xFFFF;
+ std::vector<Addr> masks1;
+ masks1.push_back((1 << 29) | (1 << 20) | (1 << 10) | 1);
+ masks1.push_back((1 << 2));
+ uint8_t intlv_match1 = 0;
+ AddrRange r1(start1, end1, masks1, intlv_match1);
+
+ Addr start2 = 0x0000;
+ Addr end2 = 0xFFFF;
+ std::vector<Addr> masks2;
+ masks2.push_back((1 << 29) | (1 << 20) | (1 << 10) | 1);
+ masks2.push_back((1 << 3)); // Different mask here.
+ uint8_t intlv_match2 = 1; // intlv_match may differ.
+ AddrRange r2(start2, end2, masks2, intlv_match2);
+
+ EXPECT_FALSE(r1.mergesWith(r2));
+ EXPECT_FALSE(r2.mergesWith(r1));
+}
+
+TEST(AddrRangeTest, InterleavingAddressesDoNotIntersect)
+{
+ /*
+ * Range 1: all the odd addresses between 0x0000 and 0xFFFF.
+ */
+ Addr start1 = 0x0000;
+ Addr end1 = 0xFFFF;
+ std::vector<Addr> masks1;
+ masks1.push_back(1);
+ uint8_t intlv_match1 = 1;
+ AddrRange r1(start1, end1, masks1, intlv_match1);
+
+ /*
+ * Range 2: all the even addresses between 0x0000 and 0xFFFF. These
+ * addresses should thereby not intersect.
+ */
+ Addr start2 = 0x0000;
+ Addr end2 = 0xFFFF;
+ std::vector<Addr> masks2;
+ masks2.push_back(1);
+ uint8_t intv_match2 = 0;
+ AddrRange r2(start2, end2, masks2, intv_match2);
+
+ EXPECT_FALSE(r1.intersects(r2));
+ EXPECT_FALSE(r2.intersects(r1));
+}
+
+TEST(AddrRangeTest, InterleavingAddressesIntersectsViaMerging)
+{
+ Addr start1 = 0x0000;
+ Addr end1 = 0xFFFF;
+ std::vector<Addr> masks1;
+ masks1.push_back((1 << 29) | (1 << 20) | (1 << 10) | 1);
+ masks1.push_back((1 << 2));
+ uint8_t intlv_match1 = 0;
+ AddrRange r1(start1, end1, masks1, intlv_match1);
+
+ Addr start2 = 0x0000;
+ Addr end2 = 0xFFFF;
+ std::vector<Addr> masks2;
+ masks2.push_back((1 << 29) | (1 << 20) | (1 << 10) | 1);
+ masks2.push_back((1 << 2));
+ uint8_t intlv_match2 = 0;
+ AddrRange r2(start2, end2, masks2, intlv_match2);
+
+ EXPECT_TRUE(r1.intersects(r2));
+ EXPECT_TRUE(r2.intersects(r1));
+}
+
+TEST(AddrRangeTest, InterleavingAddressesDoesNotIntersectViaMerging)
+{
+ Addr start1 = 0x0000;
+ Addr end1 = 0xFFFF;
+ std::vector<Addr> masks1;
+ masks1.push_back((1 << 29) | (1 << 20) | (1 << 10) | 1);
+ masks1.push_back((1 << 2));
+ uint8_t intlv_match1 = 0;
+ AddrRange r1(start1, end1, masks1, intlv_match1);
+
+ Addr start2 = 0x0000;
+ Addr end2 = 0xFFFF;
+ std::vector<Addr> masks2;
+ masks2.push_back((1 << 29) | (1 << 20) | (1 << 10) | 1);
+ masks2.push_back((1 << 2));
+ /*
+ * These addresses can merge, but their intlv_match values differ. They
+ * therefore do not intersect.
+ */
+ uint8_t intlv_match2 = 1;
+ AddrRange r2(start2, end2, masks2, intlv_match2);
+
+ EXPECT_FALSE(r1.intersects(r2));
+ EXPECT_FALSE(r2.intersects(r1));
+}
+
+/*
+ * The following tests were created to test more complex cases where
+ * interleaving addresses may intersect. However, the "intersects" function
+ * does not cover all cases (a "Cannot test intersection..." exception will
+ * be thrown outside of very simple checks to see if an intersection occurs).
+ * The tests below accurately test whether two ranges intersect but, for now,
+ * code has yet to be implemented to utilize these tests. They are therefore
+ * disabled, but may be enabled at a later date if/when the "intersects"
+ * function is enhanced.
+ */
+TEST(AddrRangeTest, DISABLED_InterleavingAddressesIntersect)
+{
+ /*
+ * Range 1: all the odd addresses between 0x0000 and 0xFFFF.
+ */
+ Addr start1 = 0x0000;
+ Addr end1 = 0xFFFF;
+ std::vector<Addr> masks1;
+ masks1.push_back(1);
+ uint8_t intlv_match1 = 0;
+ AddrRange r1(start1, end1, masks1, intlv_match1);
+
+ /*
+ * Range 2: all the addresses divisible by 4 between 0x0000 and
+ * 0xFFFF. These addresses should thereby intersect.
+ */
+ Addr start2 = 0x0000;
+ Addr end2 = 0xFFFF;
+ std::vector<Addr> masks2;
+ masks2.push_back(1 << 2);
+ uint8_t intlv_match2 = 1;
+ AddrRange r2(start2, end2, masks2, intlv_match2);
+
+ EXPECT_TRUE(r1.intersects(r2));
+ EXPECT_TRUE(r2.intersects(r1));
+}
+
+TEST(AddrRangeTest, DISABLED_InterleavingAddressesIntersectsOnOneByteAddress)
+{
+ /*
+ * Range: all the odd addresses between 0x0000 and 0xFFFF.
+ */
+ Addr start = 0x0000;
+ Addr end = 0xFFFF;
+ std::vector<Addr> masks;
+ masks.push_back(1);
+ uint8_t intlv_match = 1;
+ AddrRange r1(start, end, masks, intlv_match);
+
+ AddrRange r2(0x0000, 0x0001);
+
+ EXPECT_FALSE(r1.intersects(r2));
+ EXPECT_FALSE(r2.intersects(r1));
+}
+
+TEST(AddrRangeTest,
+ DISABLED_InterleavingAddressesDoesNotIntersectOnOneByteAddress)
+{
+ /*
+ * Range: all the odd addresses between 0x0000 and 0xFFFF.
+ */
+ Addr start = 0x0000;
+ Addr end = 0xFFFF;
+ std::vector<Addr> masks;
+ masks.push_back(1);
+ uint8_t intlv_match = 1;
+ AddrRange r1(start, end, masks, intlv_match);
+
+ AddrRange r2(0x0001, 0x0002);
+
+ EXPECT_TRUE(r1.intersects(r2));
+ EXPECT_TRUE(r2.intersects(r1));
+}
+
+
+/*
+ * The following three tests were created to test the addr_range.isSubset
+ * function for Interleaving address ranges. However, for now, this
+ * functionality has not been implemented. These tests are therefore disabled.
+ */
+TEST(AddrRangeTest, DISABLED_InterleavingAddressIsSubset)
+{
+ // Range 1: all the even addresses between 0x0000 and 0xFFFF.
+ Addr start1 = 0x0000;
+ Addr end1 = 0xFFFF;
+ std::vector<Addr> masks1;
+ masks1.push_back(1);
+ uint8_t intlv_match1 = 0;
+ AddrRange r1(start1, end1, masks1, intlv_match1);
+
+ // Range 2: all the even addresses between 0xF000 and 0x0FFF, this is
+ // a subset of Range 1.
+ Addr start2 = 0xF000;
+ Addr end2 = 0x0FFF;
+ std::vector<Addr> masks2;
+ masks2.push_back(1);
+ uint8_t intlv_match2 = 0;
+ AddrRange r2(start2, end2, masks2, intlv_match2);
+
+ EXPECT_TRUE(r1.isSubset(r2));
+ EXPECT_TRUE(r2.isSubset(r1));
+}
+
+TEST(AddrRangeTest, DISABLED_InterleavingAddressIsNotSubset)
+{
+ //Range 1: all the even addresses between 0x0000 and 0xFFFF.
+ Addr start1 = 0x0000;
+ Addr end1 = 0xFFFF;
+ std::vector<Addr> masks1;
+ masks1.push_back(1);
+ uint8_t intlv_match1 = 0;
+ AddrRange r1(start1, end1, masks1, intlv_match1);
+
+
+ // Range 2: all the odd addresses between 0xF000 and 0x0FFF, this is
+ //a subset of Range 1.
+ Addr start2 = 0xF000;
+ Addr end2 = 0x0FFF;
+ std::vector<Addr> masks2;
+ masks2.push_back(1);
+ uint8_t intlv_match2 = 1;
+ AddrRange r2(start2, end2, masks2, intlv_match2);
+
+ EXPECT_FALSE(r1.isSubset(r2));
+ EXPECT_FALSE(r2.isSubset(r1));
+}
+
+TEST(AddrRangeTest, DISABLED_InterleavingAddressContains)
+{
+ /*
+ * Range: all the address between 0x0 and 0xFF which have both the 1st
+ * and 5th bits 1, or both are 0
+ */
+ Addr start = 0x00;
+ Addr end = 0xFF;
+ std::vector<Addr> masks;
+ masks.push_back((1 << 4) | 1);
+ uint8_t intlv_match = 0;
+ AddrRange r(start, end, masks, intlv_match);
+
+ for (Addr addr = start; addr < end; addr++) {
+ if (((addr & 1) && ((1 << 4) & addr)) || // addr[0] && addr[4]
+ (!(addr & 1) && !((1 << 4) & addr))) { //!addr[0] && !addr[4]
+ EXPECT_TRUE(r.contains(addr));
+ } else {
+ EXPECT_FALSE(r.contains(addr));