diff options
-rw-r--r-- | src/cpu/BaseCPU.py | 4 | ||||
-rw-r--r-- | src/cpu/base.cc | 50 | ||||
-rw-r--r-- | src/cpu/base.hh | 12 | ||||
-rw-r--r-- | src/cpu/minor/cpu.cc | 11 | ||||
-rw-r--r-- | src/cpu/o3/cpu.cc | 6 | ||||
-rw-r--r-- | src/cpu/simple/atomic.cc | 8 | ||||
-rw-r--r-- | src/cpu/simple/timing.cc | 8 |
7 files changed, 91 insertions, 8 deletions
diff --git a/src/cpu/BaseCPU.py b/src/cpu/BaseCPU.py index fcae74207..0e131ae0a 100644 --- a/src/cpu/BaseCPU.py +++ b/src/cpu/BaseCPU.py @@ -1,4 +1,4 @@ -# Copyright (c) 2012-2013, 2015 ARM Limited +# Copyright (c) 2012-2013, 2015-2017 ARM Limited # All rights reserved. # # The license below extends only to copyright in the software and shall @@ -135,6 +135,8 @@ class BaseCPU(MemObject): cpu_id = Param.Int(-1, "CPU identifier") socket_id = Param.Unsigned(0, "Physical Socket identifier") numThreads = Param.Unsigned(1, "number of HW thread contexts") + pwr_gating_latency = Param.Cycles(300, + "Latency to enter power gating state when all contexts are suspended") function_trace = Param.Bool(False, "Enable function trace") function_trace_start = Param.Tick(0, "Tick to start function trace") diff --git a/src/cpu/base.cc b/src/cpu/base.cc index 6f76b8c6f..78cf4196c 100644 --- a/src/cpu/base.cc +++ b/src/cpu/base.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2012,2016 ARM Limited + * Copyright (c) 2011-2012,2016-2017 ARM Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -136,7 +136,9 @@ BaseCPU::BaseCPU(Params *p, bool is_checker) functionTraceStream(nullptr), currentFunctionStart(0), currentFunctionEnd(0), functionEntryTick(0), addressMonitor(p->numThreads), - syscallRetryLatency(p->syscallRetryLatency) + syscallRetryLatency(p->syscallRetryLatency), + pwrGatingLatency(p->pwr_gating_latency), + enterPwrGatingEvent([this]{ enterPwrGating(); }, name()) { // if Python did not provide a valid ID, do it here if (_cpuId == -1 ) { @@ -361,6 +363,9 @@ BaseCPU::startup() new CPUProgressEvent(this, params()->progress_interval); } + if (_switchedOut) + ClockedObject::pwrState(Enums::PwrState::OFF); + // Assumption CPU start to operate instantaneously without any latency if (ClockedObject::pwrState() == Enums::PwrState::UNDEFINED) ClockedObject::pwrState(Enums::PwrState::ON); @@ -472,6 +477,29 @@ BaseCPU::registerThreadContexts() } } +void +BaseCPU::deschedulePowerGatingEvent() +{ + if (enterPwrGatingEvent.scheduled()){ + deschedule(enterPwrGatingEvent); + } +} + +void +BaseCPU::schedulePowerGatingEvent() +{ + for (auto tc : threadContexts) { + if (tc->status() == ThreadContext::Active) + return; + } + + if (ClockedObject::pwrState() == Enums::PwrState::CLK_GATED) { + assert(!enterPwrGatingEvent.scheduled()); + // Schedule a power gating event when clock gated for the specified + // amount of time + schedule(enterPwrGatingEvent, clockEdge(pwrGatingLatency)); + } +} int BaseCPU::findContext(ThreadContext *tc) @@ -487,6 +515,10 @@ BaseCPU::findContext(ThreadContext *tc) void BaseCPU::activateContext(ThreadID thread_num) { + // Squash enter power gating event while cpu gets activated + if (enterPwrGatingEvent.scheduled()) + deschedule(enterPwrGatingEvent); + // For any active thread running, update CPU power state to active (ON) ClockedObject::pwrState(Enums::PwrState::ON); } @@ -503,6 +535,15 @@ BaseCPU::suspendContext(ThreadID thread_num) // All CPU threads suspended, enter lower power state for the CPU ClockedObject::pwrState(Enums::PwrState::CLK_GATED); + + //Schedule power gating event when clock gated for a configurable cycles + schedule(enterPwrGatingEvent, clockEdge(pwrGatingLatency)); +} + +void +BaseCPU::enterPwrGating(void) +{ + ClockedObject::pwrState(Enums::PwrState::OFF); } void @@ -516,6 +557,9 @@ BaseCPU::switchOut() // Flush all TLBs in the CPU to avoid having stale translations if // it gets switched in later. flushTLBs(); + + // Go to the power gating state + ClockedObject::pwrState(Enums::PwrState::OFF); } void @@ -527,6 +571,8 @@ BaseCPU::takeOverFrom(BaseCPU *oldCPU) assert(oldCPU != this); _pid = oldCPU->getPid(); _taskId = oldCPU->taskId(); + // Take over the power state of the switchedOut CPU + ClockedObject::pwrState(oldCPU->pwrState()); _switchedOut = false; ThreadID size = threadContexts.size(); diff --git a/src/cpu/base.hh b/src/cpu/base.hh index 79a4bf1d6..7039fcfbc 100644 --- a/src/cpu/base.hh +++ b/src/cpu/base.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2013 ARM Limited + * Copyright (c) 2011-2013, 2017 ARM Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -307,6 +307,11 @@ class BaseCPU : public MemObject void registerThreadContexts(); + // Functions to deschedule and reschedule the events to enter the + // power gating sleep before and after checkpoiting respectively. + void deschedulePowerGatingEvent(); + void schedulePowerGatingEvent(); + /** * Prepare for another CPU to take over execution. * @@ -583,6 +588,11 @@ class BaseCPU : public MemObject bool waitForRemoteGDB() const; Cycles syscallRetryLatency; + // Enables CPU to enter power gating on a configurable cycle count + protected: + const Cycles pwrGatingLatency; + void enterPwrGating(); + EventFunctionWrapper enterPwrGatingEvent; }; #endif // THE_ISA == NULL_ISA diff --git a/src/cpu/minor/cpu.cc b/src/cpu/minor/cpu.cc index ae4fda6f6..68c07675f 100644 --- a/src/cpu/minor/cpu.cc +++ b/src/cpu/minor/cpu.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2014 ARM Limited + * Copyright (c) 2012-2014, 2017 ARM Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -195,6 +195,9 @@ MinorCPU::startup() DrainState MinorCPU::drain() { + // Deschedule any power gating event (if any) + deschedulePowerGatingEvent(); + if (switchedOut()) { DPRINTF(Drain, "Minor CPU switched out, draining not needed.\n"); return DrainState::Drained; @@ -240,10 +243,14 @@ MinorCPU::drainResume() "'timing' mode.\n"); } - for (ThreadID tid = 0; tid < numThreads; tid++) + for (ThreadID tid = 0; tid < numThreads; tid++){ wakeup(tid); + } pipeline->drainResume(); + + // Reschedule any power gating event (if any) + schedulePowerGatingEvent(); } void diff --git a/src/cpu/o3/cpu.cc b/src/cpu/o3/cpu.cc index 0695711f1..091c3a6ad 100644 --- a/src/cpu/o3/cpu.cc +++ b/src/cpu/o3/cpu.cc @@ -1031,6 +1031,9 @@ template <class Impl> DrainState FullO3CPU<Impl>::drain() { + // Deschedule any power gating event (if any) + deschedulePowerGatingEvent(); + // If the CPU isn't doing anything, then return immediately. if (switchedOut()) return DrainState::Drained; @@ -1186,6 +1189,9 @@ FullO3CPU<Impl>::drainResume() assert(!tickEvent.scheduled()); if (_status == Running) schedule(tickEvent, nextCycle()); + + // Reschedule any power gating event (if any) + schedulePowerGatingEvent(); } template <class Impl> diff --git a/src/cpu/simple/atomic.cc b/src/cpu/simple/atomic.cc index c47686abc..9039e6137 100644 --- a/src/cpu/simple/atomic.cc +++ b/src/cpu/simple/atomic.cc @@ -1,6 +1,6 @@ /* * Copyright 2014 Google, Inc. - * Copyright (c) 2012-2013,2015 ARM Limited + * Copyright (c) 2012-2013,2015,2017 ARM Limited * All rights reserved. * * The license below extends only to copyright in the software and shall @@ -101,6 +101,9 @@ AtomicSimpleCPU::~AtomicSimpleCPU() DrainState AtomicSimpleCPU::drain() { + // Deschedule any power gating event (if any) + deschedulePowerGatingEvent(); + if (switchedOut()) return DrainState::Drained; @@ -163,6 +166,9 @@ AtomicSimpleCPU::drainResume() threadInfo[tid]->notIdleFraction = 0; } } + + // Reschedule any power gating event (if any) + schedulePowerGatingEvent(); } bool diff --git a/src/cpu/simple/timing.cc b/src/cpu/simple/timing.cc index d2cb6ee21..f57354d56 100644 --- a/src/cpu/simple/timing.cc +++ b/src/cpu/simple/timing.cc @@ -1,6 +1,6 @@ /* * Copyright 2014 Google, Inc. - * Copyright (c) 2010-2013,2015 ARM Limited + * Copyright (c) 2010-2013,2015,2017 ARM Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -94,6 +94,9 @@ TimingSimpleCPU::~TimingSimpleCPU() DrainState TimingSimpleCPU::drain() { + // Deschedule any power gating event (if any) + deschedulePowerGatingEvent(); + if (switchedOut()) return DrainState::Drained; @@ -146,6 +149,9 @@ TimingSimpleCPU::drainResume() } } + // Reschedule any power gating event (if any) + schedulePowerGatingEvent(); + system->totalNumInsts = 0; } |