mem: Merge interleaved ranges when creating backing store
authorAndreas Hansson <andreas.hansson@arm.com>
Fri, 1 Mar 2013 18:20:21 +0000 (13:20 -0500)
committerAndreas Hansson <andreas.hansson@arm.com>
Fri, 1 Mar 2013 18:20:21 +0000 (13:20 -0500)
This patch adds merging of interleaved ranges before creating the
backing stores. The backing stores are always a contigous chunk of the
address space, and with this patch it is possible to have interleaved
memories in the system.

src/mem/physical.cc

index df106d8cce7308cb07544db7f20c5e97861c0d3c..4b7001eb59bfcc4ebdeeda7fc7f97214e006cb8d 100644 (file)
@@ -99,20 +99,41 @@ PhysicalMemory::PhysicalMemory(const string& _name,
     // space to be mapped to backing store, also remember what
     // memories constitute the range so we can go and find out if we
     // have to init their parts to zero
+    vector<AddrRange> intlv_ranges;
     vector<AbstractMemory*> curr_memories;
     for (AddrRangeMap<AbstractMemory*>::const_iterator r = addrMap.begin();
          r != addrMap.end(); ++r) {
         // simply skip past all memories that are null and hence do
         // not need any backing store
         if (!r->second->isNull()) {
-            // this will eventually be extended to support merging of
-            // interleaved address ranges, and although it might seem
-            // overly complicated at this point it will all be used
-            curr_memories.push_back(r->second);
-            createBackingStore(r->first, curr_memories);
-            curr_memories.clear();
+            // if the range is interleaved then save it for now
+            if (r->first.interleaved()) {
+                // if we already got interleaved ranges that are not
+                // part of the same range, then first do a merge
+                // before we add the new one
+                if (!intlv_ranges.empty() &&
+                    !intlv_ranges.back().mergesWith(r->first)) {
+                    AddrRange merged_range(intlv_ranges);
+                    createBackingStore(merged_range, curr_memories);
+                    intlv_ranges.clear();
+                    curr_memories.clear();
+                }
+                intlv_ranges.push_back(r->first);
+                curr_memories.push_back(r->second);
+            } else {
+                vector<AbstractMemory*> single_memory;
+                single_memory.push_back(r->second);
+                createBackingStore(r->first, single_memory);
+            }
         }
     }
+
+    // if there is still interleaved ranges waiting to be merged, go
+    // ahead and do it
+    if (!intlv_ranges.empty()) {
+        AddrRange merged_range(intlv_ranges);
+        createBackingStore(merged_range, curr_memories);
+    }
 }
 
 void