power: Low-power idle power state for idle CPUs
authorAkash Bagdia <akash.bagdia@ARM.com>
Tue, 9 Dec 2014 10:42:08 +0000 (10:42 +0000)
committerAkash Bagdia <akash.bagdia@ARM.com>
Tue, 9 Dec 2014 10:42:08 +0000 (10:42 +0000)
Add functionality to the BaseCPU that will put the entire CPU into a low-power
idle state whenever all threads in it are idle.

src/cpu/base.cc
src/cpu/base.hh
src/cpu/minor/cpu.cc
src/cpu/o3/cpu.cc
src/cpu/simple/atomic.cc
src/cpu/simple/timing.cc

index 624843f425e55c46cab3433373ddf803119cce35..0f9fe49ea1bf0e422fba42924072a396f1ef2ed4 100644 (file)
@@ -64,6 +64,7 @@
 #include "debug/SyscallVerbose.hh"
 #include "mem/page_table.hh"
 #include "params/BaseCPU.hh"
+#include "sim/clocked_object.hh"
 #include "sim/full_system.hh"
 #include "sim/process.hh"
 #include "sim/sim_events.hh"
@@ -355,6 +356,11 @@ BaseCPU::startup()
     if (params()->progress_interval) {
         new CPUProgressEvent(this, params()->progress_interval);
     }
+
+    // Assumption CPU start to operate instantaneously without any latency
+    if (ClockedObject::pwrState() == Enums::PwrState::UNDEFINED)
+        ClockedObject::pwrState(Enums::PwrState::ON);
+
 }
 
 ProbePoints::PMUUPtr
@@ -472,6 +478,27 @@ BaseCPU::findContext(ThreadContext *tc)
     return 0;
 }
 
+void
+BaseCPU::activateContext(ThreadID thread_num)
+{
+    // For any active thread running, update CPU power state to active (ON)
+    ClockedObject::pwrState(Enums::PwrState::ON);
+}
+
+void
+BaseCPU::suspendContext(ThreadID thread_num)
+{
+    // Check if all threads are suspended
+    for (auto t : threadContexts) {
+        if (t->status() != ThreadContext::Suspended) {
+            return;
+        }
+    }
+
+    // All CPU threads suspended, enter lower power state for the CPU
+    ClockedObject::pwrState(Enums::PwrState::CLK_GATED);
+}
+
 void
 BaseCPU::switchOut()
 {
index 438c38812fa790083daca49634a10a542d62a03e..f01aa71f32bd86fea2ffbfd3bdf7adb4353e2081 100644 (file)
@@ -279,10 +279,11 @@ class BaseCPU : public MemObject
     Trace::InstTracer * getTracer() { return tracer; }
 
     /// Notify the CPU that the indicated context is now active.
-    virtual void activateContext(ThreadID thread_num) {}
+    virtual void activateContext(ThreadID thread_num);
 
     /// Notify the CPU that the indicated context is now suspended.
-    virtual void suspendContext(ThreadID thread_num) {}
+    /// Check if possible to enter a lower power state
+    virtual void suspendContext(ThreadID thread_num);
 
     /// Notify the CPU that the indicated context is now halted.
     virtual void haltContext(ThreadID thread_num) {}
index cd39a8b93e305ce2c9740923ce1eed3dfc8a3495..a707c6045586f2ad0609fd2f21903d318b423426 100644 (file)
@@ -287,6 +287,8 @@ MinorCPU::activateContext(ThreadID thread_id)
     threads[thread_id]->activate();
     wakeupOnEvent(Minor::Pipeline::CPUStageId);
     pipeline->wakeupFetch();
+
+    BaseCPU::activateContext(thread_id);
 }
 
 void
@@ -295,6 +297,8 @@ MinorCPU::suspendContext(ThreadID thread_id)
     DPRINTF(MinorCPU, "SuspendContext %d\n", thread_id);
 
     threads[thread_id]->suspend();
+
+    BaseCPU::suspendContext(thread_id);
 }
 
 void
index 79ad705bf934427d1264c46df7525eb3126d6083..73174e4a92e21405d666cdb6939efc9022b670f0 100644 (file)
@@ -735,6 +735,8 @@ FullO3CPU<Impl>::activateContext(ThreadID tid)
         lastActivatedCycle = curTick();
 
         _status = Running;
+
+        BaseCPU::activateContext(tid);
     }
 }
 
@@ -755,6 +757,8 @@ FullO3CPU<Impl>::suspendContext(ThreadID tid)
     }
 
     DPRINTF(Quiesce, "Suspending Context\n");
+
+    BaseCPU::suspendContext(tid);
 }
 
 template <class Impl>
index f3e14d40199044bebc3e2917d3182d0e8ba98afc..3cd6c16669239b7e6dcbc91456d1c500e9430580 100644 (file)
@@ -247,6 +247,8 @@ AtomicSimpleCPU::activateContext(ThreadID thread_num)
         == activeThreads.end()) {
         activeThreads.push_back(thread_num);
     }
+
+    BaseCPU::activateContext(thread_num);
 }
 
 
@@ -273,6 +275,7 @@ AtomicSimpleCPU::suspendContext(ThreadID thread_num)
         }
     }
 
+    BaseCPU::suspendContext(thread_num);
 }
 
 
index 43f4eb9f4590d5e74720d4c499f15e32800447e9..c99f9c475941ed71db1bb2d610a856cede16440f 100644 (file)
@@ -218,6 +218,8 @@ TimingSimpleCPU::activateContext(ThreadID thread_num)
          == activeThreads.end()) {
         activeThreads.push_back(thread_num);
     }
+
+    BaseCPU::activateContext(thread_num);
 }
 
 
@@ -243,6 +245,8 @@ TimingSimpleCPU::suspendContext(ThreadID thread_num)
             deschedule(fetchEvent);
         }
     }
+
+    BaseCPU::suspendContext(thread_num);
 }
 
 bool