mem: Add precharge all (PREA) to the DRAM controller
authorAndreas Hansson <andreas.hansson@arm.com>
Fri, 9 May 2014 22:58:48 +0000 (18:58 -0400)
committerAndreas Hansson <andreas.hansson@arm.com>
Fri, 9 May 2014 22:58:48 +0000 (18:58 -0400)
This patch adds the basic ingredients for a precharge all operation,
to be used in conjunction with DRAM power modelling.

Currently we do not try and apply any cleverness when precharging all
banks, thus even if only a single bank is open we use PREA as opposed
to PRE. At the moment we only have a single tRP (tRPpb), and do not
model the slightly longer all-bank precharge constraint (tRPab).

src/mem/dram_ctrl.cc

index 2da4b76099a60745fb5ceb313fef88cd679af46e..b5566c88dafb8daf333724f835778c8a3fbca75d 100644 (file)
@@ -850,6 +850,9 @@ DRAMCtrl::prechargeBank(Bank& bank, Tick pre_at)
 
     bank.openRow = Bank::NO_ROW;
 
+    // no precharge allowed before this one
+    bank.preAllowedAt = pre_at;
+
     Tick pre_done_at = pre_at + tRP;
 
     bank.actAllowedAt = std::max(bank.actAllowedAt, pre_done_at);
@@ -1305,16 +1308,34 @@ DRAMCtrl::processRefreshEvent()
         // precharge any active bank if we are not already in the idle
         // state
         if (pwrState != PWR_IDLE) {
+            // at the moment, we use a precharge all even if there is
+            // only a single bank open
             DPRINTF(DRAM, "Precharging all\n");
+
+            // first determine when we can precharge
+            Tick pre_at = curTick();
             for (int i = 0; i < ranksPerChannel; i++) {
                 for (int j = 0; j < banksPerRank; j++) {
-                    if (banks[i][j].openRow != Bank::NO_ROW) {
-                        // respect both causality and any existing bank
-                        // constraints
-                        Tick pre_at = std::max(banks[i][j].preAllowedAt,
-                                                curTick());
+                    // respect both causality and any existing bank
+                    // constraints, some banks could already have a
+                    // (auto) precharge scheduled
+                    pre_at = std::max(banks[i][j].preAllowedAt, pre_at);
+                }
+            }
 
+            // make sure all banks are precharged, and for those that
+            // already are, update their availability
+            Tick act_allowed_at = pre_at + tRP;
+
+            for (int i = 0; i < ranksPerChannel; i++) {
+                for (int j = 0; j < banksPerRank; j++) {
+                    if (banks[i][j].openRow != Bank::NO_ROW) {
                         prechargeBank(banks[i][j], pre_at);
+                    } else {
+                        banks[i][j].actAllowedAt =
+                            std::max(banks[i][j].actAllowedAt, act_allowed_at);
+                        banks[i][j].preAllowedAt =
+                            std::max(banks[i][j].preAllowedAt, pre_at);
                     }
                 }
             }