if not isinstance(cpu, m5.objects.BaseCPU):
continue
- cpu.default_p_state = "ON"
+ cpu.power_state.default_state = "ON"
cpu.power_model = CpuPowerModel(cpu.path())
# Example power model for the L2 Cache of the bigCluster
if not isinstance(l2, m5.objects.Cache):
continue
- l2.default_p_state = "ON"
+ l2.power_state.default_state = "ON"
l2.power_model = L2PowerModel(l2.path())
bL.instantiate(options)
}
if (_switchedOut)
- ClockedObject::pwrState(Enums::PwrState::OFF);
+ powerState->set(Enums::PwrState::OFF);
// Assumption CPU start to operate instantaneously without any latency
- if (ClockedObject::pwrState() == Enums::PwrState::UNDEFINED)
- ClockedObject::pwrState(Enums::PwrState::ON);
+ if (powerState->get() == Enums::PwrState::UNDEFINED)
+ powerState->set(Enums::PwrState::ON);
}
return;
}
- if (ClockedObject::pwrState() == Enums::PwrState::CLK_GATED &&
+ if (powerState->get() == Enums::PwrState::CLK_GATED &&
powerGatingOnIdle) {
assert(!enterPwrGatingEvent.scheduled());
// Schedule a power gating event when clock gated for the specified
if (enterPwrGatingEvent.scheduled())
deschedule(enterPwrGatingEvent);
// For any active thread running, update CPU power state to active (ON)
- ClockedObject::pwrState(Enums::PwrState::ON);
+ powerState->set(Enums::PwrState::ON);
updateCycleCounters(CPU_STATE_WAKEUP);
}
updateCycleCounters(CPU_STATE_SLEEP);
// All CPU threads suspended, enter lower power state for the CPU
- ClockedObject::pwrState(Enums::PwrState::CLK_GATED);
+ powerState->set(Enums::PwrState::CLK_GATED);
// If pwrGatingLatency is set to 0 then this mechanism is disabled
if (powerGatingOnIdle) {
void
BaseCPU::enterPwrGating(void)
{
- ClockedObject::pwrState(Enums::PwrState::OFF);
+ powerState->set(Enums::PwrState::OFF);
}
void
flushTLBs();
// Go to the power gating state
- ClockedObject::pwrState(Enums::PwrState::OFF);
+ powerState->set(Enums::PwrState::OFF);
}
void
_pid = oldCPU->getPid();
_taskId = oldCPU->taskId();
// Take over the power state of the switchedOut CPU
- ClockedObject::pwrState(oldCPU->pwrState());
+ powerState->set(oldCPU->powerState->get());
previousState = oldCPU->previousState;
previousCycle = oldCPU->previousCycle;
npwrs->pc = 0;
}
}
- tc->getCpuPtr()->pwrState(Enums::PwrState::ON);
+ tc->getCpuPtr()->powerState->set(Enums::PwrState::ON);
}
void
pwrs->pc = 0;
// Clear power-on reason
pwrs->wk = 0;
- tc->getCpuPtr()->pwrState(Enums::PwrState::OFF);
+ tc->getCpuPtr()->powerState->set(Enums::PwrState::OFF);
}
void
-# Copyright (c) 2012, 2015-2016 ARM Limited
+# Copyright (c) 2012, 2015-2017, 2019-2020 ARM Limited
# All rights reserved.
#
# The license below extends only to copyright in the software and shall
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+from m5.objects.PowerState import PowerState
from m5.SimObject import SimObject
from m5.params import *
from m5.proxy import *
-# Enumerate set of allowed power states that can be used by a clocked object.
-# The list is kept generic to express a base minimal set.
-# State definition :-
-# Undefined: Invalid state, no power state derived information is available.
-# On: The logic block is actively running and consuming dynamic and leakage
-# energy depending on the amount of processing required.
-# Clk_gated: The clock circuity within the block is gated to save dynamic
-# energy, the power supply to the block is still on and leakage
-# energy is being consumed by the block.
-# Sram_retention: The SRAMs within the logic blocks are pulled into retention
-# state to reduce leakage energy further.
-# Off: The logic block is power gated and is not consuming any energy.
-class PwrState(Enum): vals = ['UNDEFINED',
- 'ON',
- 'CLK_GATED',
- 'SRAM_RETENTION',
- 'OFF']
-
class ClockedObject(SimObject):
type = 'ClockedObject'
abstract = True
# Power model for this ClockedObject
power_model = VectorParam.PowerModel([], "Power models")
- # Provide initial power state, should ideally get redefined in startup
- # routine
- default_p_state = Param.PwrState("UNDEFINED", "Default Power State")
+ power_state = Param.PowerState(PowerState(), "Power state")
- p_state_clk_gate_min = Param.Latency('1ns',"Min value of the distribution")
- p_state_clk_gate_max = Param.Latency('1s',"Max value of the distribution")
- p_state_clk_gate_bins = Param.Unsigned('20',
- "# bins in clk gated distribution")
--- /dev/null
+# Copyright (c) 2012, 2015-2017 ARM Limited
+# All rights reserved.
+#
+# The license below extends only to copyright in the software and shall
+# not be construed as granting a license to any other intellectual
+# property including but not limited to intellectual property relating
+# to a hardware implementation of the functionality of the software
+# licensed hereunder. You may use the software subject to the license
+# terms below provided that you ensure that this notice is replicated
+# unmodified and in its entirety in all distributions of the software,
+# modified or unmodified, in source code or in binary form.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met: redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer;
+# redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution;
+# neither the name of the copyright holders nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+from m5.SimObject import SimObject
+from m5.params import *
+from m5.proxy import *
+
+# Enumerate set of allowed power states that can be used by a clocked object.
+# The list is kept generic to express a base minimal set.
+# State definition :-
+# Undefined: Invalid state, no power state derived information is available.
+# On: The logic block is actively running and consuming dynamic and leakage
+# energy depending on the amount of processing required.
+# Clk_gated: The clock circuity within the block is gated to save dynamic
+# energy, the power supply to the block is still on and leakage
+# energy is being consumed by the block.
+# Sram_retention: The SRAMs within the logic blocks are pulled into retention
+# state to reduce leakage energy further.
+# Off: The logic block is power gated and is not consuming any energy.
+class PwrState(Enum): vals = [
+ 'UNDEFINED', 'ON', 'CLK_GATED', 'SRAM_RETENTION', 'OFF'
+]
+
+class PowerState(SimObject):
+ type = 'PowerState'
+ cxx_header = "sim/power_state.hh"
+
+ # Provide initial power state, should ideally get redefined in startup
+ # routine
+ default_state = Param.PwrState("UNDEFINED", "Default Power State")
+
+ clk_gate_min = Param.Latency('1ns',"Min value of the distribution")
+ clk_gate_max = Param.Latency('1s',"Max value of the distribution")
+ clk_gate_bins = Param.Unsigned('20', "# bins in clk gated distribution")
SimObject('DVFSHandler.py')
SimObject('SubSystem.py')
SimObject('RedirectPath.py')
+SimObject('PowerState.py')
Source('async.cc')
Source('backtrace_%s.cc' % env['BACKTRACE_IMPL'])
Source('dvfs_handler.cc')
Source('clocked_object.cc')
Source('mathexpr.cc')
+Source('power_state.cc')
GTest('byteswap.test', 'byteswap.test.cc', '../base/types.cc')
GTest('guest_abi.test', 'guest_abi.test.cc')
/*
- * Copyright (c) 2015-2016 ARM Limited
+ * Copyright (c) 2015-2017, 2019-2020 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
#include "sim/power/power_model.hh"
ClockedObject::ClockedObject(const ClockedObjectParams *p) :
- SimObject(p), Clocked(*p->clk_domain),
- _currPwrState(p->default_p_state),
- prvEvalTick(0),
- stats(*this)
+ SimObject(p), Clocked(*p->clk_domain), powerState(p->power_state)
{
// Register the power_model with the object
+ // Slightly counter-intuitively, power models need to to register with the
+ // clocked object and not the power stated object because the power model
+ // needs information from the clock domain, which is an attribute of the
+ // clocked object.
for (auto & power_model: p->power_model)
power_model->setClockedObject(this);
}
void
ClockedObject::serialize(CheckpointOut &cp) const
{
- unsigned int currPwrState = (unsigned int)_currPwrState;
-
- SERIALIZE_SCALAR(currPwrState);
- SERIALIZE_SCALAR(prvEvalTick);
+ powerState->serialize(cp);
}
-
void
ClockedObject::unserialize(CheckpointIn &cp)
{
- unsigned int currPwrState;
-
- UNSERIALIZE_SCALAR(currPwrState);
- UNSERIALIZE_SCALAR(prvEvalTick);
-
- _currPwrState = Enums::PwrState(currPwrState);
-}
-
-void
-ClockedObject::pwrState(Enums::PwrState p)
-{
- // Function should ideally be called only when there is a state change
- if (_currPwrState == p) {
- warn_once("ClockedObject: Already in the requested power state, " \
- "request ignored");
- return;
- }
-
- // No need to compute stats if in the same tick, update state though. This
- // can happen in cases like a) during start of the simulation multiple
- // state changes happens in init/startup phase, b) one takes a decision to
- // migrate state but decides to reverts back to the original state in the
- // same tick if other conditions are not met elsewhere.
- // Any state change related stats would have been recorded on previous call
- // to the pwrState() function.
- if (prvEvalTick == curTick() && curTick() != 0) {
- warn("ClockedObject %s: More than one power state change request "\
- "encountered within the same simulation tick %d",
- name(), prvEvalTick);
- _currPwrState = p;
- return;
- }
-
- // Record stats for previous state.
- computeStats();
-
- _currPwrState = p;
-
- stats.numPwrStateTransitions++;
-}
-
-void
-ClockedObject::computeStats()
-{
- // Calculate time elapsed from last (valid) state change
- Tick elapsed_time = curTick() - prvEvalTick;
-
- stats.pwrStateResidencyTicks[_currPwrState] += elapsed_time;
-
- // Time spent in CLK_GATED state, this might change depending on
- // transition to other low power states in respective simulation
- // objects.
- if (_currPwrState == Enums::PwrState::CLK_GATED) {
- stats.pwrStateClkGateDist.sample(elapsed_time);
- }
-
- prvEvalTick = curTick();
-}
-
-std::vector<double>
-ClockedObject::pwrStateWeights() const
-{
- // Get residency stats
- std::vector<double> ret;
- Stats::VCounter residencies;
- stats.pwrStateResidencyTicks.value(residencies);
-
- // Account for current state too!
- Tick elapsed_time = curTick() - prvEvalTick;
- residencies[_currPwrState] += elapsed_time;
-
- ret.resize(Enums::PwrState::Num_PwrState);
- for (unsigned i = 0; i < Enums::PwrState::Num_PwrState; i++)
- ret[i] = residencies[i] / \
- (stats.pwrStateResidencyTicks.total() + elapsed_time);
-
- return ret;
-}
-
-
-ClockedObject::ClockedObjectStats::ClockedObjectStats(ClockedObject &co)
- : Stats::Group(&co),
- clockedObject(co),
- ADD_STAT(numPwrStateTransitions,
- "Number of power state transitions"),
- ADD_STAT(pwrStateClkGateDist,
- "Distribution of time spent in the clock gated state"),
- ADD_STAT(pwrStateResidencyTicks,
- "Cumulative time (in ticks) in various power states")
-{
-}
-
-void
-ClockedObject::ClockedObjectStats::regStats()
-{
- Stats::Group::regStats();
-
- using namespace Stats;
-
- const ClockedObjectParams *p = clockedObject.params();
-
- numPwrStateTransitions.flags(nozero);
-
- // Each sample is time in ticks
- unsigned num_bins = std::max(p->p_state_clk_gate_bins, 10U);
- pwrStateClkGateDist
- .init(p->p_state_clk_gate_min, p->p_state_clk_gate_max,
- (p->p_state_clk_gate_max / num_bins))
- .flags(pdf | nozero | nonan)
- ;
-
- pwrStateResidencyTicks
- .init(Enums::PwrState::Num_PwrState)
- .flags(nozero)
- ;
- for (int i = 0; i < Enums::PwrState::Num_PwrState; i++) {
- pwrStateResidencyTicks.subname(i, Enums::PwrStateStrings[i]);
- }
-
- numPwrStateTransitions = 0;
-}
-
-void
-ClockedObject::ClockedObjectStats::preDumpStats()
-{
- Stats::Group::preDumpStats();
-
- /**
- * For every stats dump, the power state residency and other distribution
- * stats should be computed just before the dump to ensure correct stats
- * value being reported for current dump window. It avoids things like
- * having any unreported time spent in a power state to be forwarded to the
- * next dump window which might have rather unpleasant effects (like
- * perturbing the distribution stats).
- */
- clockedObject.computeStats();
+ powerState->unserialize(cp);
}
/*
- * Copyright (c) 2012-2013, 2015-2016 ARM Limited
+ * Copyright (c) 2012-2013, 2015-2017, 2019-2020 ARM Limited
* Copyright (c) 2013 Cornell University
* All rights reserved
*
#ifndef __SIM_CLOCKED_OBJECT_HH__
#define __SIM_CLOCKED_OBJECT_HH__
-#include "base/callback.hh"
-#include "base/intmath.hh"
-#include "enums/PwrState.hh"
+
#include "params/ClockedObject.hh"
#include "sim/core.hh"
#include "sim/clock_domain.hh"
+#include "sim/power_state.hh"
#include "sim/sim_object.hh"
/**
void serialize(CheckpointOut &cp) const override;
void unserialize(CheckpointIn &cp) override;
- Enums::PwrState pwrState() const { return _currPwrState; }
-
- std::string
- pwrStateName() const
- {
- return Enums::PwrStateStrings[_currPwrState];
- }
-
- /** Returns the percentage residency for each power state */
- std::vector<double> pwrStateWeights() const;
-
- /**
- * Record stats values like state residency by computing the time
- * difference from previous update. Also, updates the previous evaluation
- * tick once all stats are recorded.
- * Usually called on power state change and stats dump callback.
- */
- void computeStats();
-
- void pwrState(Enums::PwrState);
-
- protected:
-
- /** To keep track of the current power state */
- Enums::PwrState _currPwrState;
-
- Tick prvEvalTick;
-
- struct ClockedObjectStats : public Stats::Group
- {
- ClockedObjectStats(ClockedObject &co);
-
- void regStats() override;
- void preDumpStats() override;
-
- ClockedObject &clockedObject;
- Stats::Scalar numPwrStateTransitions;
- Stats::Distribution pwrStateClkGateDist;
- Stats::Vector pwrStateResidencyTicks;
- } stats;
+ PowerState *powerState;
};
#endif //__SIM_CLOCKED_OBJECT_HH__
// This power model only collects static data
return 0;
}
- std::vector<double> w = clocked_object->pwrStateWeights();
+ std::vector<double> w = clocked_object->powerState->getWeights();
// Same number of states (excluding UNDEFINED)
assert(w.size() - 1 == states_pm.size());
{
assert(clocked_object);
- std::vector<double> w = clocked_object->pwrStateWeights();
+ std::vector<double> w = clocked_object->powerState->getWeights();
if (power_model_type == Enums::PMType::Dynamic) {
// This power model only collects dynamic data
--- /dev/null
+/*
+ * Copyright (c) 2015-2017, 2019-2020 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder. You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "sim/power_state.hh"
+
+#include "base/logging.hh"
+
+PowerState::PowerState(const PowerStateParams *p) :
+ SimObject(p), _currState(p->default_state),
+ stats(*this)
+{
+}
+
+void
+PowerState::serialize(CheckpointOut &cp) const
+{
+ unsigned int currState = (unsigned int)_currState;
+
+ SERIALIZE_SCALAR(currState);
+ SERIALIZE_SCALAR(prvEvalTick);
+}
+
+void
+PowerState::unserialize(CheckpointIn &cp)
+{
+ unsigned int currState;
+
+ UNSERIALIZE_SCALAR(currState);
+ UNSERIALIZE_SCALAR(prvEvalTick);
+
+ _currState = Enums::PwrState(currState);
+}
+
+void
+PowerState::set(Enums::PwrState p)
+{
+ // Function should ideally be called only when there is a state change
+ if (_currState == p) {
+ warn_once("PowerState: Already in the requested power state, "
+ "request ignored");
+ return;
+ }
+
+ // No need to compute stats if in the same tick, update state though. This
+ // can happen in cases like a) during start of the simulation multiple
+ // state changes happens in init/startup phase, b) one takes a decision to
+ // migrate state but decides to reverts back to the original state in the
+ // same tick if other conditions are not met elsewhere.
+ // Any state change related stats would have been recorded on previous call
+ // to this function.
+ if (prvEvalTick == curTick() && curTick() != 0) {
+ warn("PowerState: More than one power state change request "
+ "encountered within the same simulation tick");
+ _currState = p;
+ return;
+ }
+
+ // Record stats for previous state.
+ computeStats();
+
+ _currState = p;
+
+ stats.numTransitions++;
+}
+
+void
+PowerState::computeStats()
+{
+ // Calculate time elapsed from last (valid) state change
+ Tick elapsed_time = curTick() - prvEvalTick;
+
+ stats.pwrStateResidencyTicks[_currState] += elapsed_time;
+
+ // Time spent in CLK_GATED state, this might change depending on
+ // transition to other low power states in respective simulation
+ // objects.
+ if (_currState == Enums::PwrState::CLK_GATED) {
+ stats.ticksClkGated.sample(elapsed_time);
+ }
+
+ prvEvalTick = curTick();
+}
+
+std::vector<double>
+PowerState::getWeights() const
+{
+ // Get residency stats
+ std::vector<double> ret;
+ Stats::VCounter residencies;
+ stats.pwrStateResidencyTicks.value(residencies);
+
+ // Account for current state too!
+ Tick elapsed_time = curTick() - prvEvalTick;
+ residencies[_currState] += elapsed_time;
+
+ ret.resize(Enums::PwrState::Num_PwrState);
+ for (unsigned i = 0; i < Enums::PwrState::Num_PwrState; i++)
+ ret[i] = residencies[i] / \
+ (stats.pwrStateResidencyTicks.total() + elapsed_time);
+
+ return ret;
+}
+
+PowerState::PowerStateStats::PowerStateStats(PowerState &co)
+ : Stats::Group(&co),
+ powerState(co),
+ ADD_STAT(numTransitions,
+ "Number of power state transitions"),
+ ADD_STAT(ticksClkGated,
+ "Distribution of time spent in the clock gated state"),
+ ADD_STAT(pwrStateResidencyTicks,
+ "Cumulative time (in ticks) in various power states")
+{
+}
+
+void
+PowerState::PowerStateStats::regStats()
+{
+ Stats::Group::regStats();
+
+ using namespace Stats;
+
+ const PowerStateParams *p = powerState.params();
+
+ numTransitions.flags(nozero);
+
+ // Each sample is time in ticks
+ unsigned num_bins = std::max(p->clk_gate_bins, 10U);
+ ticksClkGated
+ .init(p->clk_gate_min, p->clk_gate_max,
+ (p->clk_gate_max / num_bins))
+ .flags(pdf | nozero | nonan)
+ ;
+
+ pwrStateResidencyTicks
+ .init(Enums::PwrState::Num_PwrState)
+ .flags(nozero)
+ ;
+ for (int i = 0; i < Enums::PwrState::Num_PwrState; i++) {
+ pwrStateResidencyTicks.subname(i, Enums::PwrStateStrings[i]);
+ }
+
+ numTransitions = 0;
+}
+
+void
+PowerState::PowerStateStats::preDumpStats()
+{
+ Stats::Group::preDumpStats();
+
+ /**
+ * For every stats dump, the power state residency and other distribution
+ * stats should be computed just before the dump to ensure correct stats
+ * value being reported for current dump window. It avoids things like
+ * having any unreported time spent in a power state to be forwarded to the
+ * next dump window which might have rather unpleasant effects (like
+ * perturbing the distribution stats).
+ */
+ powerState.computeStats();
+}
+
+PowerState*
+PowerStateParams::create()
+{
+ return new PowerState(this);
+}
--- /dev/null
+/*
+ * Copyright (c) 2015-2017, 2020 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder. You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ * PowerState declaration and implementation.
+ */
+
+#ifndef __SIM_POWER_STATE_HH__
+#define __SIM_POWER_STATE_HH__
+
+#include <set>
+
+#include "base/callback.hh"
+#include "base/statistics.hh"
+#include "enums/PwrState.hh"
+#include "params/PowerState.hh"
+#include "sim/core.hh"
+#include "sim/sim_object.hh"
+
+/**
+ * Helper class for objects that have power states. This class provides the
+ * basic functionality to change between power states.
+ */
+class PowerState : public SimObject
+{
+ public:
+ PowerState(const PowerStateParams *p);
+
+ /** Parameters of PowerState object */
+ typedef PowerStateParams Params;
+ const Params* params() const
+ {
+ return reinterpret_cast<const Params*>(_params);
+ }
+
+ void serialize(CheckpointOut &cp) const override;
+ void unserialize(CheckpointIn &cp) override;
+
+ /**
+ * Change the power state of this object to the power state p
+ */
+ void set(Enums::PwrState p);
+
+
+ inline Enums::PwrState get() const
+ {
+ return _currState;
+ }
+
+ inline std::string getName() const
+ {
+ return Enums::PwrStateStrings[_currState];
+ }
+
+ /** Returns the percentage residency for each power state */
+ std::vector<double> getWeights() const;
+
+ /**
+ * Record stats values like state residency by computing the time
+ * difference from previous update. Also, updates the previous evaluation
+ * tick once all stats are recorded.
+ * Usually called on power state change and stats dump callback.
+ */
+ void computeStats();
+
+ protected:
+
+ /** To keep track of the current power state */
+ Enums::PwrState _currState;
+
+ /** Last tick the power stats were calculated */
+ Tick prvEvalTick = 0;
+
+ struct PowerStateStats : public Stats::Group
+ {
+ PowerStateStats(PowerState &ps);
+
+ void regStats() override;
+ void preDumpStats() override;
+
+ PowerState &powerState;
+
+ Stats::Scalar numTransitions;
+ Stats::Distribution ticksClkGated;
+ /** Tracks the time spent in each of the power states */
+ Stats::Vector pwrStateResidencyTicks;
+ } stats;
+};
+
+class PowerStateDumpCallback : public Callback
+{
+ PowerState *co;
+ public:
+ PowerStateDumpCallback(PowerState *co_t) : co(co_t) {}
+ virtual void process() { co->computeStats(); };
+};
+
+#endif //__SIM_POWER_STATE_HH__