Gabe Black has uploaded this change for review. ( https://gem5-review.googlesource.com/c/public/gem5/+/50344 )

Change subject: misc: Use AddrRangeList more consistently in the AddrRange class.
......................................................................

misc: Use AddrRangeList more consistently in the AddrRange class.

We go through the trouble of defining an AddrRangeList typedef, but then
we don't use it consistently and use std::vector<AddrRange> instead.

This change converts the exclude method from using
std::vector<AddrRange> to AddrRangeList, and also adds a constructor
which takes an AddrRangeList.

Because there is a lot of code which uses the std::vector based
constructor, this change does not remove that method.

Change-Id: I1a03b25990025688aa760a67d3e7a2e8141384ce
---
M src/base/addr_range.hh
M src/base/addr_range.test.cc
M src/python/m5/SimObject.py
M src/python/m5/params.py
M src/python/pybind11/core.cc
5 files changed, 88 insertions(+), 85 deletions(-)



diff --git a/src/base/addr_range.hh b/src/base/addr_range.hh
index 291d376..90d9279 100644
--- a/src/base/addr_range.hh
+++ b/src/base/addr_range.hh
@@ -42,6 +42,7 @@
 #define __BASE_ADDR_RANGE_HH__

 #include <algorithm>
+#include <iterator>
 #include <list>
 #include <vector>

@@ -53,6 +54,15 @@
 namespace gem5
 {

+class AddrRange;
+
+/**
+ * Convenience typedef for a collection of address ranges
+ *
+ * @ingroup api_addr_range
+ */
+typedef std::list<AddrRange> AddrRangeList;
+
 /**
  * The AddrRange class encapsulates an address range, and supports a
  * number of tests to check if two ranges intersect, if a range
@@ -89,6 +99,46 @@
     /** The value to compare sel with. */
     uint8_t intlvMatch;

+  protected:
+    struct Dummy {};
+
+    template <class Iterator>
+    AddrRange(Dummy, Iterator begin_it, Iterator end_it)
+        : _start(1), _end(0), intlvMatch(0)
+    {
+        if (begin_it != end_it) {
+            // get the values from the first one and check the others
+            _start = begin_it->_start;
+            _end = begin_it->_end;
+            masks = begin_it->masks;
+            intlvMatch = begin_it->intlvMatch;
+        }
+
+        auto count = std::distance(begin_it, end_it);
+        // either merge if got all ranges or keep this equal to the single
+        // interleaved range
+        if (count > 1) {
+            fatal_if(count != (1ULL << masks.size()),
+                    "Got %d ranges spanning %d interleaving bits.",
+                    count, masks.size());
+
+            uint8_t match = 0;
+            for (auto it = begin_it; it != end_it; it++) {
+                fatal_if(!mergesWith(*it),
+                        "Can only merge ranges with the same start, end "
+                        "and interleaving bits, %s %s.", to_string(),
+                        it->to_string());
+
+                fatal_if(it->intlvMatch != match,
+                        "Expected interleave match %d but got %d when "
+                        "merging.", match, it->intlvMatch);
+                ++match;
+            }
+            masks.clear();
+            intlvMatch = 0;
+        }
+    }
+
   public:

     /**
@@ -215,40 +265,12 @@
      *
      * @ingroup api_addr_range
      */
-    AddrRange(const std::vector<AddrRange>& ranges)
-        : _start(1), _end(0), intlvMatch(0)
-    {
-        if (!ranges.empty()) {
-            // get the values from the first one and check the others
-            _start = ranges.front()._start;
-            _end = ranges.front()._end;
-            masks = ranges.front().masks;
-            intlvMatch = ranges.front().intlvMatch;
-        }
-        // either merge if got all ranges or keep this equal to the single
-        // interleaved range
-        if (ranges.size() > 1) {
-
-            if (ranges.size() != (1ULL << masks.size()))
-                fatal("Got %d ranges spanning %d interleaving bits\n",
-                      ranges.size(), masks.size());
-
-            uint8_t match = 0;
-            for (const auto& r : ranges) {
-                if (!mergesWith(r))
-                    fatal("Can only merge ranges with the same start, end "
-                          "and interleaving bits, %s %s\n", to_string(),
-                          r.to_string());
-
-                if (r.intlvMatch != match)
-                    fatal("Expected interleave match %d but got %d when "
-                          "merging\n", match, r.intlvMatch);
-                ++match;
-            }
-            masks.clear();
-            intlvMatch = 0;
-        }
-    }
+    AddrRange(std::vector<AddrRange> ranges)
+        : AddrRange(Dummy{}, ranges.begin(), ranges.end())
+    {}
+    AddrRange(std::list<AddrRange> ranges)
+        : AddrRange(Dummy{}, ranges.begin(), ranges.end())
+    {}

     /**
      * Determine if the range is interleaved or not.
@@ -599,15 +621,15 @@
      *
      * @ingroup api_addr_range
      */
-    std::vector<AddrRange>
-    exclude(const std::vector<AddrRange> &exclude_ranges) const
+    AddrRangeList
+    exclude(const AddrRangeList &exclude_ranges) const
     {
         assert(!interleaved());

         auto sorted_ranges = exclude_ranges;
-        std::sort(sorted_ranges.begin(), sorted_ranges.end());
+        sorted_ranges.sort();

-        std::vector<AddrRange> ranges;
+        std::list<AddrRange> ranges;

         Addr next_start = start();
         for (const auto &e : sorted_ranges) {
@@ -690,13 +712,6 @@
 };

 /**
- * Convenience typedef for a collection of address ranges
- *
- * @ingroup api_addr_range
- */
-typedef std::list<AddrRange> AddrRangeList;
-
-/**
  * @ingroup api_addr_range
  */
 inline AddrRange
diff --git a/src/base/addr_range.test.cc b/src/base/addr_range.test.cc
index 0f30ad5..ada9d3f 100644
--- a/src/base/addr_range.test.cc
+++ b/src/base/addr_range.test.cc
@@ -36,6 +36,7 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */

+#include <gmock/gmock.h>
 #include <gtest/gtest.h>

 #include <cmath>
@@ -45,6 +46,8 @@

 using namespace gem5;

+using testing::ElementsAre;
+
 TEST(AddrRangeTest, ValidRange)
 {
     AddrRange r;
@@ -921,10 +924,10 @@
 }

 /*
- * The AddrRange(std::vector<AddrRange>) constructor "merges" the interleaving
+ * The AddrRange(AddrRangeList) constructor "merges" the interleaving
* address ranges. It should be noted that this constructor simply checks that * these interleaving addresses can be merged then creates a new address from
- * the start and end addresses of the first address range in the vector.
+ * the start and end addresses of the first address range in the list.
  */
 TEST(AddrRangeTest, MergingInterleavingAddressRanges)
 {
@@ -942,7 +945,7 @@
     uint8_t intlv_match2 = 1;
     AddrRange r2(start2, end2, masks2, intlv_match2);

-    std::vector<AddrRange> to_merge;
+    AddrRangeList to_merge;
     to_merge.push_back(r1);
     to_merge.push_back(r2);

@@ -956,7 +959,7 @@
 TEST(AddrRangeTest, MergingInterleavingAddressRangesOneRange)
 {
     /*
-     * In the case where there is just one range in the vector, the merged
+     * In the case where there is just one range in the list, the merged
      * address range is equal to that range.
      */
     Addr start = 0x0000;
@@ -966,7 +969,7 @@
     uint8_t intlv_match = 0;
     AddrRange r(start, end, masks, intlv_match);

-    std::vector<AddrRange> to_merge;
+    AddrRangeList to_merge;
     to_merge.push_back(r);

     AddrRange output(to_merge);
@@ -1105,7 +1108,7 @@
  */
 TEST(AddrRangeTest, ExcludeAll)
 {
-    const std::vector<AddrRange> exclude_ranges{
+    const AddrRangeList exclude_ranges{
         AddrRange(0x0, 0x200)
     };

@@ -1129,7 +1132,7 @@
  */
 TEST(AddrRangeTest, ExcludeAllEqual)
 {
-    const std::vector<AddrRange> exclude_ranges{
+    const AddrRangeList exclude_ranges{
         AddrRange(0x0, 0x100)
     };

@@ -1153,7 +1156,7 @@
  */
 TEST(AddrRangeTest, ExcludeAllMultiple)
 {
-    const std::vector<AddrRange> exclude_ranges{
+    const AddrRangeList exclude_ranges{
         AddrRange(0x0, 0x30),
         AddrRange(0x30, 0x40),
         AddrRange(0x40, 0x120)
@@ -1183,7 +1186,7 @@
  */
 TEST(AddrRangeTest, ExcludeAllOverlapping)
 {
-    const std::vector<AddrRange> exclude_ranges{
+    const AddrRangeList exclude_ranges{
         AddrRange(0x0, 0x150),
         AddrRange(0x140, 0x220)
     };
@@ -1206,7 +1209,7 @@
  */
 TEST(AddrRangeTest, ExcludeEmpty)
 {
-    const std::vector<AddrRange> exclude_ranges;
+    const AddrRangeList exclude_ranges;

     AddrRange r(0x00, 0x100);
     auto ranges = r.exclude(exclude_ranges);
@@ -1230,7 +1233,7 @@
  */
 TEST(AddrRangeTest, NoExclusion)
 {
-    const std::vector<AddrRange> exclude_ranges{
+    const AddrRangeList exclude_ranges{
         AddrRange(0x100, 0x200)
     };

@@ -1257,7 +1260,7 @@
  */
 TEST(AddrRangeTest, DoubleExclusion)
 {
-    const std::vector<AddrRange> exclude_ranges{
+    const AddrRangeList exclude_ranges{
         AddrRange(0x000, 0x130),
         AddrRange(0x140, 0x170),
     };
@@ -1269,8 +1272,7 @@
     auto ranges = r.exclude(exclude_ranges);

     EXPECT_EQ(ranges.size(), 2);
-    EXPECT_EQ(ranges[0], expected_range1);
-    EXPECT_EQ(ranges[1], expected_range2);
+    EXPECT_THAT(ranges, ElementsAre(expected_range1, expected_range2));
 }

 /*
@@ -1289,7 +1291,7 @@
  */
 TEST(AddrRangeTest, MultipleExclusion)
 {
-    const std::vector<AddrRange> exclude_ranges{
+    const AddrRangeList exclude_ranges{
         AddrRange(0x000, 0x130),
         AddrRange(0x140, 0x170),
         AddrRange(0x180, 0x210)
@@ -1302,8 +1304,7 @@
     auto ranges = r.exclude(exclude_ranges);

     EXPECT_EQ(ranges.size(), 2);
-    EXPECT_EQ(ranges[0], expected_range1);
-    EXPECT_EQ(ranges[1], expected_range2);
+    EXPECT_THAT(ranges, ElementsAre(expected_range1, expected_range2));
 }

 /*
@@ -1324,7 +1325,7 @@
  */
 TEST(AddrRangeTest, MultipleExclusionOverlapping)
 {
-    const std::vector<AddrRange> exclude_ranges{
+    const AddrRangeList exclude_ranges{
         AddrRange(0x000, 0x130),
         AddrRange(0x140, 0x170),
         AddrRange(0x150, 0x210)
@@ -1336,7 +1337,7 @@
     auto ranges = r.exclude(exclude_ranges);

     EXPECT_EQ(ranges.size(), 1);
-    EXPECT_EQ(ranges[0], expected_range1);
+    EXPECT_THAT(ranges, ElementsAre(expected_range1));
 }

 /*
@@ -1359,7 +1360,7 @@
  */
 TEST(AddrRangeTest, ExclusionOverlapping)
 {
-    const std::vector<AddrRange> exclude_ranges{
+    const AddrRangeList exclude_ranges{
         AddrRange(0x120, 0x180),
         AddrRange(0x130, 0x170)
     };
@@ -1371,8 +1372,7 @@
     auto ranges = r.exclude(exclude_ranges);

     EXPECT_EQ(ranges.size(), 2);
-    EXPECT_EQ(ranges[0], expected_range1);
-    EXPECT_EQ(ranges[1], expected_range2);
+    EXPECT_THAT(ranges, ElementsAre(expected_range1, expected_range2));
 }

 /*
@@ -1393,7 +1393,7 @@
  */
 TEST(AddrRangeTest, MultipleExclusionUnsorted)
 {
-    const std::vector<AddrRange> exclude_ranges{
+    const AddrRangeList exclude_ranges{
         AddrRange(0x180, 0x210),
         AddrRange(0x000, 0x130),
         AddrRange(0x140, 0x170)
@@ -1406,8 +1406,7 @@
     auto ranges = r.exclude(exclude_ranges);

     EXPECT_EQ(ranges.size(), 2);
-    EXPECT_EQ(ranges[0], expected_range1);
-    EXPECT_EQ(ranges[1], expected_range2);
+    EXPECT_THAT(ranges, ElementsAre(expected_range1, expected_range2));
 }

 /*
@@ -1426,7 +1425,7 @@
 #ifdef NDEBUG
     GTEST_SKIP() << "Skipping as assetions are stripped from fast builds.";
 #endif
-    const std::vector<AddrRange> exclude_ranges{
+    const AddrRangeList exclude_ranges{
         AddrRange(0x180, 0x210),
     };

diff --git a/src/python/m5/SimObject.py b/src/python/m5/SimObject.py
index de7752c..d18d879 100644
--- a/src/python/m5/SimObject.py
+++ b/src/python/m5/SimObject.py
@@ -728,7 +728,6 @@

 #include "base/compiler.hh"
 #include "params/$cls.hh"
-#include "python/pybind11/core.hh"
 #include "sim/init.hh"
 #include "sim/sim_object.hh"

diff --git a/src/python/m5/params.py b/src/python/m5/params.py
index 8db8e6a..49f5a56 100644
--- a/src/python/m5/params.py
+++ b/src/python/m5/params.py
@@ -865,15 +865,10 @@
                          self.masks, int(self.intlvMatch))

     def exclude(self, ranges):
-        from _m5.range import AddrRangeVector
-
-        # The wrapped C++ class is assuming an AddrRangeVector
-        # We are therefore converting to it before excluding ranges
-        # and reconverting it into a list of AddrRange before returning
-        pybind_exclude = AddrRangeVector([ r.getValue() for r in ranges ])
+        pybind_exclude = list([ r.getValue() for r in ranges ])
         pybind_include = self.getValue().exclude(pybind_exclude)

-        return [ AddrRange(r.start(), r.end()) for r in pybind_include ]
+ return list([ AddrRange(r.start(), r.end()) for r in pybind_include ])

 # Boolean parameter type.  Python doesn't let you subclass bool, since
 # it doesn't want to let you create multiple instances of True and
diff --git a/src/python/pybind11/core.cc b/src/python/pybind11/core.cc
index 257ae23..6f4acd3 100644
--- a/src/python/pybind11/core.cc
+++ b/src/python/pybind11/core.cc
@@ -39,11 +39,10 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */

+#include "pybind11/operators.h"
 #include "pybind11/pybind11.h"
 #include "pybind11/stl.h"

-#include "python/pybind11/core.hh"
-
 #include <ctime>

 #include "base/addr_range.hh"
@@ -170,10 +169,6 @@
         .def("exclude", &AddrRange::exclude)
         ;

-    // We need to make vectors of AddrRange opaque to avoid weird
-    // memory allocation issues in PyBind's STL wrappers.
-    py::bind_vector<std::vector<AddrRange>>(m, "AddrRangeVector");
-
     m.def("RangeEx", &RangeEx);
     m.def("RangeIn", &RangeIn);
     m.def("RangeSize", &RangeSize);

--
To view, visit https://gem5-review.googlesource.com/c/public/gem5/+/50344
To unsubscribe, or for help writing mail filters, visit https://gem5-review.googlesource.com/settings

Gerrit-Project: public/gem5
Gerrit-Branch: develop
Gerrit-Change-Id: I1a03b25990025688aa760a67d3e7a2e8141384ce
Gerrit-Change-Number: 50344
Gerrit-PatchSet: 1
Gerrit-Owner: Gabe Black <[email protected]>
Gerrit-MessageType: newchange
_______________________________________________
gem5-dev mailing list -- [email protected]
To unsubscribe send an email to [email protected]
%(web_page_url)slistinfo%(cgiext)s/%(_internal_name)s

Reply via email to