mem: Move DRAM interleaving check to init
authorAndreas Hansson <andreas.hansson@arm.com>
Tue, 20 Jan 2015 13:11:55 +0000 (08:11 -0500)
committerAndreas Hansson <andreas.hansson@arm.com>
Tue, 20 Jan 2015 13:11:55 +0000 (08:11 -0500)
This patch fixes a bug where the DRAM controller tried to access the
system cacheline size before the system pointer was initialised. It
also fixes a bug where the granularity is 0 (no interleaving).

src/mem/dram_ctrl.cc

index 44ac3d5125832f38c6b898a64eb48e32900e433b..e52f03588b1fbb7bdbfcd1a33edca383f4ad64f7 100644 (file)
@@ -69,7 +69,7 @@ DRAMCtrl::DRAMCtrl(const DRAMCtrlParams* p) :
     burstSize((devicesPerRank * burstLength * deviceBusWidth) / 8),
     rowBufferSize(devicesPerRank * deviceRowBufferSize),
     columnsPerRowBuffer(rowBufferSize / burstSize),
-    columnsPerStripe(range.granularity() / burstSize),
+    columnsPerStripe(range.interleaved() ? range.granularity() / burstSize : 1),
     ranksPerChannel(p->ranks_per_channel),
     bankGroupsPerRank(p->bank_groups_per_rank),
     bankGroupArch(p->bank_groups_per_rank > 0),
@@ -153,45 +153,6 @@ DRAMCtrl::DRAMCtrl(const DRAMCtrlParams* p) :
 
     rowsPerBank = capacity / (rowBufferSize * banksPerRank * ranksPerChannel);
 
-    // a bit of sanity checks on the interleaving
-    if (range.interleaved()) {
-        if (channels != range.stripes())
-            fatal("%s has %d interleaved address stripes but %d channel(s)\n",
-                  name(), range.stripes(), channels);
-
-        if (addrMapping == Enums::RoRaBaChCo) {
-            if (rowBufferSize != range.granularity()) {
-                fatal("Channel interleaving of %s doesn't match RoRaBaChCo "
-                      "address map\n", name());
-            }
-        } else if (addrMapping == Enums::RoRaBaCoCh ||
-                   addrMapping == Enums::RoCoRaBaCh) {
-            // for the interleavings with channel bits in the bottom,
-            // if the system uses a channel striping granularity that
-            // is larger than the DRAM burst size, then map the
-            // sequential accesses within a stripe to a number of
-            // columns in the DRAM, effectively placing some of the
-            // lower-order column bits as the least-significant bits
-            // of the address (above the ones denoting the burst size)
-            assert(columnsPerStripe >= 1);
-
-            // channel striping has to be done at a granularity that
-            // is equal or larger to a cache line
-            if (system()->cacheLineSize() > range.granularity()) {
-                fatal("Channel interleaving of %s must be at least as large "
-                      "as the cache line size\n", name());
-            }
-
-            // ...and equal or smaller than the row-buffer size
-            if (rowBufferSize < range.granularity()) {
-                fatal("Channel interleaving of %s must be at most as large "
-                      "as the row-buffer size\n", name());
-            }
-            // this is essentially the check above, so just to be sure
-            assert(columnsPerStripe <= columnsPerRowBuffer);
-        }
-    }
-
     // some basic sanity checks
     if (tREFI <= tRP || tREFI <= tRFC) {
         fatal("tREFI (%d) must be larger than tRP (%d) and tRFC (%d)\n",
@@ -239,6 +200,46 @@ DRAMCtrl::init()
     } else {
         port.sendRangeChange();
     }
+
+    // a bit of sanity checks on the interleaving, save it for here to
+    // ensure that the system pointer is initialised
+    if (range.interleaved()) {
+        if (channels != range.stripes())
+            fatal("%s has %d interleaved address stripes but %d channel(s)\n",
+                  name(), range.stripes(), channels);
+
+        if (addrMapping == Enums::RoRaBaChCo) {
+            if (rowBufferSize != range.granularity()) {
+                fatal("Channel interleaving of %s doesn't match RoRaBaChCo "
+                      "address map\n", name());
+            }
+        } else if (addrMapping == Enums::RoRaBaCoCh ||
+                   addrMapping == Enums::RoCoRaBaCh) {
+            // for the interleavings with channel bits in the bottom,
+            // if the system uses a channel striping granularity that
+            // is larger than the DRAM burst size, then map the
+            // sequential accesses within a stripe to a number of
+            // columns in the DRAM, effectively placing some of the
+            // lower-order column bits as the least-significant bits
+            // of the address (above the ones denoting the burst size)
+            assert(columnsPerStripe >= 1);
+
+            // channel striping has to be done at a granularity that
+            // is equal or larger to a cache line
+            if (system()->cacheLineSize() > range.granularity()) {
+                fatal("Channel interleaving of %s must be at least as large "
+                      "as the cache line size\n", name());
+            }
+
+            // ...and equal or smaller than the row-buffer size
+            if (rowBufferSize < range.granularity()) {
+                fatal("Channel interleaving of %s must be at most as large "
+                      "as the row-buffer size\n", name());
+            }
+            // this is essentially the check above, so just to be sure
+            assert(columnsPerStripe <= columnsPerRowBuffer);
+        }
+    }
 }
 
 void