changeset 8a882e297eb2 in /z/repo/gem5
details: http://repo.gem5.org/gem5?cmd=changeset;node=8a882e297eb2
description:
        mem: Modify drain to ensure banks and power are idled

        Add constraint that all ranks have to be in PWR_IDLE
        before signaling drain complete

        This will ensure that the banks are all closed and the rank
        has exited any low-power states.

        On suspend, update the power stats to sync the DRAM power logic

        The logic maintains the location of the signalDrainDone
        method, which is still triggered from either:
        1) Read response event
        2) Next request event

        This ensures that the drain will complete in the READ bus
        state and minimizes the changes required.

        Change-Id: If1476e631ea7d5999fe50a0c9379c5967a90e3d1
        Reviewed-by: Radhika Jagtap <radhika.jag...@arm.com>

diffstat:

 src/mem/dram_ctrl.cc |  61 ++++++++++++++++++++++++++++++++++-----------------
 src/mem/dram_ctrl.hh |  20 +++++++++++++++++
 2 files changed, 61 insertions(+), 20 deletions(-)

diffs (151 lines):

diff -r 60d18201148d -r 8a882e297eb2 src/mem/dram_ctrl.cc
--- a/src/mem/dram_ctrl.cc      Thu Oct 13 19:22:10 2016 +0100
+++ b/src/mem/dram_ctrl.cc      Thu Oct 13 19:22:11 2016 +0100
@@ -684,7 +684,7 @@
     } else {
         // if there is nothing left in any queue, signal a drain
         if (drainState() == DrainState::Draining &&
-            writeQueue.empty() && readQueue.empty()) {
+            writeQueue.empty() && readQueue.empty() && allRanksDrained()) {
 
             DPRINTF(Drain, "DRAM controller done draining\n");
             signalDrainDone();
@@ -1288,8 +1288,11 @@
                 switch_to_writes = true;
             } else {
                 // check if we are drained
+                // not done draining until in PWR_IDLE state
+                // ensuring all banks are closed and
+                // have exited low power states
                 if (drainState() == DrainState::Draining &&
-                    respQueue.empty()) {
+                    respQueue.empty() && allRanksDrained()) {
 
                     DPRINTF(Drain, "DRAM controller done draining\n");
                     signalDrainDone();
@@ -1538,6 +1541,9 @@
 DRAMCtrl::Rank::suspend()
 {
     deschedule(refreshEvent);
+
+    // Update the stats
+    updatePowerStats();
 }
 
 void
@@ -1708,23 +1714,6 @@
         // at the moment this affects all ranks
         cmdList.push_back(Command(MemCommand::REF, 0, curTick()));
 
-        // All commands up to refresh have completed
-        // flush cmdList to DRAMPower
-        flushCmdList();
-
-        // update the counters for DRAMPower, passing false to
-        // indicate that this is not the last command in the
-        // list. DRAMPower requires this information for the
-        // correct calculation of the background energy at the end
-        // of the simulation. Ideally we would want to call this
-        // function with true once at the end of the
-        // simulation. However, the discarded energy is extremly
-        // small and does not effect the final results.
-        power.powerlib.updateCounters(false);
-
-        // call the energy function
-        power.powerlib.calcEnergy();
-
         // Update the stats
         updatePowerStats();
 
@@ -1833,6 +1822,23 @@
 void
 DRAMCtrl::Rank::updatePowerStats()
 {
+    // All commands up to refresh have completed
+    // flush cmdList to DRAMPower
+    flushCmdList();
+
+    // update the counters for DRAMPower, passing false to
+    // indicate that this is not the last command in the
+    // list. DRAMPower requires this information for the
+    // correct calculation of the background energy at the end
+    // of the simulation. Ideally we would want to call this
+    // function with true once at the end of the
+    // simulation. However, the discarded energy is extremly
+    // small and does not effect the final results.
+    power.powerlib.updateCounters(false);
+
+    // call the energy function
+    power.powerlib.calcEnergy();
+
     // Get the energy and power from DRAMPower
     Data::MemoryPowerModel::Energy energy =
         power.powerlib.getEnergy();
@@ -2182,7 +2188,9 @@
 {
     // if there is anything in any of our internal queues, keep track
     // of that as well
-    if (!(writeQueue.empty() && readQueue.empty() && respQueue.empty())) {
+    if (!(writeQueue.empty() && readQueue.empty() && respQueue.empty() &&
+          allRanksDrained())) {
+
         DPRINTF(Drain, "DRAM controller not drained, write: %d, read: %d,"
                 " resp: %d\n", writeQueue.size(), readQueue.size(),
                 respQueue.size());
@@ -2198,6 +2206,19 @@
     }
 }
 
+bool
+DRAMCtrl::allRanksDrained() const
+{
+    // true until proven false
+    bool all_ranks_drained = true;
+    for (auto r : ranks) {
+        // then verify that the power state is IDLE
+        // ensuring all banks are closed and rank is not in a low power state
+        all_ranks_drained = r->inPwrIdleState() && all_ranks_drained;
+    }
+    return all_ranks_drained;
+}
+
 void
 DRAMCtrl::drainResume()
 {
diff -r 60d18201148d -r 8a882e297eb2 src/mem/dram_ctrl.hh
--- a/src/mem/dram_ctrl.hh      Thu Oct 13 19:22:10 2016 +0100
+++ b/src/mem/dram_ctrl.hh      Thu Oct 13 19:22:11 2016 +0100
@@ -382,6 +382,15 @@
         bool isAvailable() const { return refreshState == REF_IDLE; }
 
         /**
+         * Check if the current rank has all banks closed and is not
+         * in a low power state
+         *
+         * @param Return true if the rank is idle from a bank
+         *        and power point of view
+         */
+        bool inPwrIdleState() const { return pwrState == PWR_IDLE; }
+
+        /**
          * Let the rank check if it was waiting for requests to drain
          * to allow it to transition states.
          */
@@ -913,6 +922,17 @@
     virtual void startup() override;
     virtual void drainResume() override;
 
+    /**
+     * Return true once refresh is complete for all ranks and there are no
+     * additional commands enqueued.  (only evaluated when draining)
+     * This will ensure that all banks are closed, power state is IDLE, and
+     * power stats have been updated
+     *
+     * @return true if all ranks have refreshed, with no commands enqueued
+     *
+     */
+    bool allRanksDrained() const;
+
   protected:
 
     Tick recvAtomic(PacketPtr pkt);
_______________________________________________
gem5-dev mailing list
gem5-dev@gem5.org
http://m5sim.org/mailman/listinfo/gem5-dev

Reply via email to