pwr: Adds logic to enter power gating for the cpu model
If the CPU has been clock gated for a sufficient amount of time (configurable via pwrGatingLatency), the CPU will go into the OFF power state. This does not model hardware, just behaviour. Change-Id: Ib3681d1ffa6ad25eba60f47b4020325f63472d43 Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com> Reviewed-on: https://gem5-review.googlesource.com/3969 Reviewed-by: Jason Lowe-Power <jason@lowepower.com> Maintainer: Andreas Sandberg <andreas.sandberg@arm.com>
This commit is contained in:
committed by
Andreas Sandberg
parent
d626f4f7aa
commit
c0d613adb4
@@ -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")
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user