+ EXPECT_TRUE(r1.isSubset(r2));
+ EXPECT_TRUE(r2.isSubset(r1));
+}
+
+TEST(AddrRangeTest, isSubsetNoOverlap)
+{
+ AddrRange r1(0x10, 0x20);
+ AddrRange r2(0x20, 0x22);
+
+ EXPECT_FALSE(r1.isSubset(r2));
+ EXPECT_FALSE(r2.isSubset(r1));
+}
+
+TEST(AddrRangeTest, isSubsetTrueSubset)
+{
+ AddrRange r1(0x10, 0x20);
+ AddrRange r2(0x15, 0x17);
+
+ EXPECT_TRUE(r2.isSubset(r1));
+ EXPECT_FALSE(r1.isSubset(r2));
+}
+
+TEST(AddrRangeTest, isSubsetPartialSubset)
+{
+ AddrRange r1(0x20, 0x30);
+ AddrRange r2(0x26, 0xF0);
+
+ EXPECT_FALSE(r1.isSubset(r2));
+ EXPECT_FALSE(r2.isSubset(r1));
+}
+
+TEST(AddrRangeTest, isSubsetInterleavedCompleteOverlap)
+{
+ AddrRange r1(0x00, 0x100, {0x40}, 0);
+ AddrRange r2(0x00, 0x40);
+
+ EXPECT_TRUE(r2.isSubset(r1));
+}
+
+TEST(AddrRangeTest, isSubsetInterleavedNoOverlap)
+{
+ AddrRange r1(0x00, 0x100, {0x40}, 1);
+ AddrRange r2(0x00, 0x40);
+
+ EXPECT_FALSE(r2.isSubset(r1));
+}
+
+TEST(AddrRangeTest, isSubsetInterleavedPartialOverlap)
+{
+ AddrRange r1(0x00, 0x100, {0x40}, 0);
+ AddrRange r2(0x10, 0x50);
+
+ EXPECT_FALSE(r2.isSubset(r1));
+}
+
+TEST(AddrRangeTest, Contains)
+{
+ AddrRange r(0xF0, 0xF5);
+
+ EXPECT_FALSE(r.contains(0xEF));
+ EXPECT_TRUE(r.contains(0xF0));
+ EXPECT_TRUE(r.contains(0xF1));
+ EXPECT_TRUE(r.contains(0xF2));
+ EXPECT_TRUE(r.contains(0xF3));
+ EXPECT_TRUE(r.contains(0xF4));
+ EXPECT_FALSE(r.contains(0xF5));
+ EXPECT_FALSE(r.contains(0xF6));
+}
+
+TEST(AddrRangeTest, ContainsInAnEmptyRange)
+{
+ AddrRange r(0x1, 0x1);
+
+ EXPECT_FALSE(r.contains(0x1));
+}
+
+TEST(AddrRangeTest, RemoveIntlvBits)
+{
+ AddrRange r(0x01, 0x10);
+
+ /*
+ * When there are no masks, AddrRange.removeIntlBits just returns the
+ * address parameter.
+ */
+ Addr a(56);
+ a = r.removeIntlvBits(a);
+ EXPECT_EQ(56, a);
+}
+
+TEST(AddrRangeTest, addIntlvBits)
+{
+ AddrRange r(0x01, 0x10);
+
+ /*
+ * As with AddrRange.removeIntlBits, when there are no masks,
+ * AddrRange.addIntlvBits just returns the address parameter.
+ */
+ Addr a(56);
+ a = r.addIntlvBits(a);
+ EXPECT_EQ(56, a);
+}
+
+TEST(AddrRangeTest, OffsetInRange)
+{
+ AddrRange r(0x01, 0xF0);
+ EXPECT_EQ(0x04, r.getOffset(0x5));
+}
+
+TEST(AddrRangeTest, OffsetOutOfRangeAfter)
+{
+ /*
+ * If the address is less than the range, MaxAddr is returned.
+ */
+ AddrRange r(0x01, 0xF0);
+ EXPECT_EQ(MaxAddr, r.getOffset(0xF0));
+}
+
+TEST(AddrRangeTest, OffsetOutOfRangeBefore)
+{
+ AddrRange r(0x05, 0xF0);
+ EXPECT_EQ(MaxAddr, r.getOffset(0x04));
+}
+
+/*
+ * 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));
+}