From fb5fc11da49938660ea22c336964677cdba890e1 Mon Sep 17 00:00:00 2001 From: David Guillen Fandos Date: Mon, 6 Jun 2016 17:16:43 +0100 Subject: pwr: Low-power idle power state for idle CPUs Add functionality to the BaseCPU that will put the entire CPU into a low-power idle state whenever all threads in it are idle. Change-Id: I984d1656eb0a4863c87ceacd773d2d10de5cfd2b --- src/cpu/base.cc | 29 ++++++++++++++++++++++++++++- src/cpu/base.hh | 5 +++-- src/cpu/minor/cpu.cc | 4 ++++ src/cpu/o3/cpu.cc | 4 ++++ src/cpu/simple/atomic.cc | 3 +++ src/cpu/simple/timing.cc | 4 ++++ 6 files changed, 46 insertions(+), 3 deletions(-) (limited to 'src/cpu') diff --git a/src/cpu/base.cc b/src/cpu/base.cc index fbd8af99a..aaf5a7a93 100644 --- a/src/cpu/base.cc +++ b/src/cpu/base.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2012 ARM Limited + * Copyright (c) 2011-2012,2016 ARM Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -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 @@ -474,6 +480,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() { diff --git a/src/cpu/base.hh b/src/cpu/base.hh index 748602c25..6622339e0 100644 --- a/src/cpu/base.hh +++ b/src/cpu/base.hh @@ -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) {} diff --git a/src/cpu/minor/cpu.cc b/src/cpu/minor/cpu.cc index 7e53a87f6..79807a2a7 100644 --- a/src/cpu/minor/cpu.cc +++ b/src/cpu/minor/cpu.cc @@ -290,6 +290,8 @@ MinorCPU::activateContext(ThreadID thread_id) threads[thread_id]->activate(); wakeupOnEvent(Minor::Pipeline::CPUStageId); pipeline->wakeupFetch(); + + BaseCPU::activateContext(thread_id); } void @@ -298,6 +300,8 @@ MinorCPU::suspendContext(ThreadID thread_id) DPRINTF(MinorCPU, "SuspendContext %d\n", thread_id); threads[thread_id]->suspend(); + + BaseCPU::suspendContext(thread_id); } void diff --git a/src/cpu/o3/cpu.cc b/src/cpu/o3/cpu.cc index 79ad705bf..73174e4a9 100644 --- a/src/cpu/o3/cpu.cc +++ b/src/cpu/o3/cpu.cc @@ -735,6 +735,8 @@ FullO3CPU::activateContext(ThreadID tid) lastActivatedCycle = curTick(); _status = Running; + + BaseCPU::activateContext(tid); } } @@ -755,6 +757,8 @@ FullO3CPU::suspendContext(ThreadID tid) } DPRINTF(Quiesce, "Suspending Context\n"); + + BaseCPU::suspendContext(tid); } template diff --git a/src/cpu/simple/atomic.cc b/src/cpu/simple/atomic.cc index 3996b33ca..a8e97f14c 100644 --- a/src/cpu/simple/atomic.cc +++ b/src/cpu/simple/atomic.cc @@ -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); } diff --git a/src/cpu/simple/timing.cc b/src/cpu/simple/timing.cc index 6b63d894f..515d6b23c 100644 --- a/src/cpu/simple/timing.cc +++ b/src/cpu/simple/timing.cc @@ -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 -- cgit v1.2.3