base, mem: Disambiguate if an addr range is contained or overlaps
authorNikos Nikoleris <nikos.nikoleris@arm.com>
Wed, 18 Apr 2018 10:56:08 +0000 (11:56 +0100)
committerNikos Nikoleris <nikos.nikoleris@arm.com>
Tue, 19 Jun 2018 14:24:25 +0000 (14:24 +0000)
We need to determined whether an address range is fully contained or
it overlaps with an address range in the address range in the mmap. As
an example, we use address range maps to associate ports to address
ranges and we determine which port we will forward the request based
on which address range contains the addresses accessed by the
request. We also need to make sure that when we add a new port to the
address range map, its address range does not overlap with any of the
existing ports.

This patch splits the function find() into two functions contains()
and intersects() to implement this distinct functionality. It also
changes the xbar and the physical memory to use the right function.

Change-Id: If3fd3f774a16b27db2df76dc04f1d61824938008
Reviewed-on: https://gem5-review.googlesource.com/11115
Reviewed-by: Daniel Carvalho <odanrc@yahoo.com.br>
Maintainer: Nikos Nikoleris <nikos.nikoleris@arm.com>

src/base/addr_range_map.hh
src/mem/physical.cc
src/mem/xbar.cc
src/unittest/rangemaptest.cc

index 30bd62456d5063742b7baa9e17261635edfcd18a..5c627bef562d753c671166a78dd02126c7c188e0 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012 ARM Limited
+ * Copyright (c) 2012, 2018 ARM Limited
  * All rights reserved
  *
  * The license below extends only to copyright in the software and shall
@@ -59,71 +59,63 @@ class AddrRangeMap
 {
   private:
     typedef std::map<AddrRange, V> RangeMap;
-    RangeMap tree;
 
   public:
     typedef typename RangeMap::iterator iterator;
     typedef typename RangeMap::const_iterator const_iterator;
 
+    /**
+     * Find entry that contains the given address range
+     *
+     * Searches through the ranges in the address map and returns an
+     * iterator to the entry which range is a superset of the input
+     * address range. Returns end() if none found.
+     *
+     * @param r An input address range
+     * @return An iterator that contains the input address range
+     */
     const_iterator
-    find(const AddrRange &r) const
+    contains(const AddrRange &r) const
     {
-        if (tree.empty())
-            return tree.end();
-
-        const_iterator i = tree.upper_bound(r);
-
-        if (i == tree.begin()) {
-            if (i->first.intersects(r)) {
-                return i;
-            } else {
-                return tree.end();
-            }
-        }
-
-        --i;
-
-        if (i->first.intersects(r))
-            return i;
-
-        // if we are looking at an interleaved range, also step
-        // backwards through the ranges while we are looking at ranges
-        // that are part of the same contigous chunk
-        if (i->first.interleaved()) {
-            AddrRange orig_range = i->first;
-
-            while (i != tree.begin() && i->first.mergesWith(orig_range)) {
-                --i;
-                if (i->first.intersects(r)) {
-                    return i;
-                }
-            }
-
-            // we could leave the loop based on reaching the first
-            // element, so we must still check for an intersection
-            if (i->first.intersects(r))
-                return i;
-        }
-
-        return tree.end();
+        return find(r, [r](const AddrRange r1) { return r.isSubset(r1); });
     }
 
+    /**
+     * Find entry that contains the given address
+     *
+     * Searches through the ranges in the address map and returns an
+     * iterator to the entry which range is a superset of the input
+     * address. Returns end() if none found.
+     *
+     * @param r An input address
+     * @return An iterator that contains the input address
+     */
     const_iterator
-    find(const Addr &r) const
+    contains(Addr r) const
     {
-        return find(RangeSize(r, 1));
+        return contains(RangeSize(r, 1));
     }
 
-    bool
-    intersect(const AddrRange &r) const
+    /**
+     * Find entry that intersects with the given address range
+     *
+     * Searches through the ranges in the address map and returns an
+     * iterator to the first entry which range intersects with the
+     * input address.
+     *
+     * @param r An input address
+     * @return An iterator that intersects with the input address range
+     */
+    const_iterator
+    intersects(const AddrRange &r) const
     {
-        return find(r) != tree.end();
+        return find(r, [r](const AddrRange r1) { return r.intersects(r1); });
     }
 
     const_iterator
     insert(const AddrRange &r, const V& d)
     {
-        if (intersect(r))
+        if (intersects(r) != end())
             return tree.end();
 
         return tree.insert(std::make_pair(r, d)).first;
@@ -182,6 +174,44 @@ class AddrRangeMap
     {
         return tree.empty();
     }
+
+  private:
+    /**
+     * Find entry that satisfies a condition on an address range
+     *
+     * Searches through the ranges in the address map and returns an
+     * iterator to the entry that satisfies the input conidition on
+     * the input address range. Returns end() if none found.
+     *
+     * @param r An input address range
+     * @param f A condition on an address range
+     * @return An iterator that contains the input address range
+     */
+    const_iterator
+    find(const AddrRange &r, std::function<bool(const AddrRange)> cond) const
+    {
+        const_iterator next = tree.upper_bound(r);
+        if (next != end() && cond(next->first)) {
+            return next;
+        }
+        if (next == begin())
+            return end();
+        next--;
+
+        const_iterator i;
+        do {
+            i = next;
+            if (cond(i->first)) {
+                return i;
+            }
+            // Keep looking if the next range merges with the current one.
+        } while (next != begin() &&
+                 (--next)->first.mergesWith(i->first));
+
+        return end();
+    }
+
+    RangeMap tree;
 };
 
 #endif //__BASE_ADDR_RANGE_MAP_HH__
index 586f1c4756bed9e0ce93847efe63a7ce772328c4..c7dbb3bcb6e454529d007a03d7687e212c763e1b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2014 ARM Limited
+ * Copyright (c) 2012, 2014, 2018 ARM Limited
  * All rights reserved
  *
  * The license below extends only to copyright in the software and shall
@@ -241,7 +241,7 @@ PhysicalMemory::isMemAddr(Addr addr) const
         return true;
     } else {
         // lookup in the interval tree
-        const auto& r = addrMap.find(addr);
+        const auto& r = addrMap.contains(addr);
         if (r == addrMap.end()) {
             // not in the cache, and not in the tree
             return false;
@@ -298,7 +298,7 @@ PhysicalMemory::access(PacketPtr pkt)
     } else {
         // do not update the cache here, as we typically call
         // isMemAddr before calling access
-        const auto& m = addrMap.find(addr);
+        const auto& m = addrMap.contains(addr);
         assert(m != addrMap.end());
         m->second->access(pkt);
     }
@@ -314,7 +314,7 @@ PhysicalMemory::functionalAccess(PacketPtr pkt)
     } else {
         // do not update the cache here, as we typically call
         // isMemAddr before calling functionalAccess
-        const auto& m = addrMap.find(addr);
+        const auto& m = addrMap.contains(addr);
         assert(m != addrMap.end());
         m->second->functionalAccess(pkt);
     }
@@ -406,7 +406,7 @@ PhysicalMemory::unserialize(CheckpointIn &cp)
     UNSERIALIZE_CONTAINER(lal_addr);
     UNSERIALIZE_CONTAINER(lal_cid);
     for (size_t i = 0; i < lal_addr.size(); ++i) {
-        const auto& m = addrMap.find(lal_addr[i]);
+        const auto& m = addrMap.contains(lal_addr[i]);
         m->second->addLockedAddr(LockedAddr(lal_addr[i], lal_cid[i]));
     }
 
index db0bf180e7794acf392b84e9128b7afb5d4943b8..1984a94aab1e4b3d04cf98768e3c61353efbb02f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011-2015 ARM Limited
+ * Copyright (c) 2011-2015, 2018 ARM Limited
  * All rights reserved
  *
  * The license below extends only to copyright in the software and shall
@@ -333,7 +333,7 @@ BaseXBar::findPort(Addr addr)
         return dest_id;
 
     // Check the address map interval tree
-    auto i = portMap.find(addr);
+    auto i = portMap.contains(addr);
     if (i != portMap.end()) {
         dest_id = i->second;
         updatePortCache(dest_id, i->first);
@@ -420,8 +420,9 @@ BaseXBar::recvRangeChange(PortID master_port_id)
             DPRINTF(AddrRanges, "Adding range %s for id %d\n",
                     r.to_string(), master_port_id);
             if (portMap.insert(r, master_port_id) == portMap.end()) {
-                PortID conflict_id = portMap.find(r)->second;
-                fatal("%s has two ports responding within range %s:\n\t%s\n\t%s\n",
+                PortID conflict_id = portMap.intersects(r)->second;
+                fatal("%s has two ports responding within range "
+                      "%s:\n\t%s\n\t%s\n",
                       name(),
                       r.to_string(),
                       masterPorts[master_port_id]->getSlavePort().name(),
@@ -496,7 +497,7 @@ BaseXBar::recvRangeChange(PortID master_port_id)
             }
         }
 
-        // also check that no range partially overlaps with the
+        // also check that no range partially intersects with the
         // default range, this has to be done after all ranges are set
         // as there are no guarantees for when the default range is
         // update with respect to the other ones
index 6975f66efa799dd35df6c97ca0cbbd6936205bee..88e1c4d667a7a14d907f5fc5b1b4d362885ff422 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012 ARM Limited
+ * Copyright (c) 2012, 2018 ARM Limited
  * All rights reserved
  *
  * The license below extends only to copyright in the software and shall
@@ -59,11 +59,14 @@ main()
     i = r.insert(RangeIn(60, 90), 3);
     assert(i != r.end());
 
-    i = r.find(RangeIn(20, 30));
+    i = r.intersects(RangeIn(20, 30));
     assert(i != r.end());
     cout << i->first.to_string() << " " << i->second << endl;
 
-    i = r.find(RangeIn(55, 55));
+    i = r.contains(RangeIn(55, 55));
+    assert(i == r.end());
+
+    i = r.intersects(RangeIn(55, 55));
     assert(i == r.end());
 
     i = r.insert(RangeIn(0, 12), 1);
@@ -72,7 +75,7 @@ main()
     i = r.insert(RangeIn(0, 9), 1);
     assert(i != r.end());
 
-    i = r.find(RangeIn(20, 30));
+    i = r.contains(RangeIn(20, 30));
     assert(i != r.end());
     cout << i->first.to_string() << " " << i->second << endl;