--- /dev/null
+# Copyright (c) 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.
+#
+
+import sys
+
+from m5.params import *
+from m5.objects.PowerState import PowerState
+
+# A power domain groups multiple ClockedObjects and creates a
+# hierarchy in which follower ClockedObjects (caches for example) can
+# change power state depeding on what the leader objects (CPUs for
+# example) do. The power domain is the link between these.
+class PowerDomain(PowerState):
+ type = 'PowerDomain'
+ cxx_header = 'sim/power_domain.hh'
+
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")
+
+ # The objects which drive the power state of this object. If the list is
+ # empty, the object determines its power state independently.
+ leaders = VectorParam.PowerState(
+ [], "Objects which drive the power state of this object")
SimObject('SubSystem.py')
SimObject('RedirectPath.py')
SimObject('PowerState.py')
+SimObject('PowerDomain.py')
Source('async.cc')
Source('backtrace_%s.cc' % env['BACKTRACE_IMPL'])
Source('clocked_object.cc')
Source('mathexpr.cc')
Source('power_state.cc')
+Source('power_domain.cc')
GTest('byteswap.test', 'byteswap.test.cc', '../base/types.cc')
GTest('guest_abi.test', 'guest_abi.test.cc')
DebugFlag('VoltageDomain')
DebugFlag('DVFS')
DebugFlag('Vma')
+DebugFlag('PowerDomain')
CompoundFlag('SyscallAll', [ 'SyscallBase', 'SyscallVerbose'])
--- /dev/null
+/*
+ * Copyright (c) 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_domain.hh"
+
+#include <unordered_map>
+
+#include "debug/PowerDomain.hh"
+
+PowerDomain::PowerDomain(const PowerDomainParams* p) :
+ PowerState(p),
+ leaders(p->leaders),
+ pwrStateUpdateEvent(*this),
+ stats(*this)
+{
+ // Check if there is at least one leader
+ fatal_if(leaders.empty(), "No leaders registered in %s!)", name());
+
+ // Go over the leaders and register this power domain with them
+ for (auto leader : leaders) {
+ leader->setControlledDomain(this);
+ }
+
+ // We will assume a power domain to start in the most performant p-state
+ // This will be corrected during startup()
+ leaderTargetState = Enums::PwrState::ON;
+ _currState = Enums::PwrState::ON;
+}
+
+void
+PowerDomain::addFollower(PowerState* pwr_obj)
+{
+ DPRINTF(PowerDomain, "%s is a follower in %s\n", pwr_obj->name(), name());
+ followers.push_back(pwr_obj);
+}
+
+void
+PowerDomain::startup()
+{
+ DPRINTF(PowerDomain, "Checks at startup\n");
+ // Check if the leaders and followers have the correct power states.
+ DPRINTF(PowerDomain, "Checking power state of leaders & followers\n");
+ for (const auto &objs : { leaders, followers }) {
+ for (const auto &obj : objs) {
+ const auto & states = obj->getPossibleStates();
+ auto it = states.find(Enums::PwrState::ON);
+ fatal_if(it == states.end(),
+ "%s in %s does not have the required power states to be "
+ "part of a PowerDomain i.e. the ON state!", obj->name(),
+ name());
+ }
+ }
+
+ // Now all objects have been checked for the minimally required power
+ // states, calculate the possible power states for the domain. This is the
+ // intersection between the possible power states of the followers and
+ // leaders.
+ calculatePossiblePwrStates();
+
+ // Check that there is no objects which is both a leader and a
+ // follower.
+ DPRINTF(PowerDomain, "Checking for double entries\n");
+ for (auto follower : followers) {
+ for (auto leader : leaders) {
+ fatal_if(leader == follower, "%s is both a leader and follower"
+ " in %s\n!", leader->name(), name());
+ }
+ }
+ // Record the power states of the leaders and followers
+ DPRINTF(PowerDomain, "Recording the current power states in domain\n");
+ for (auto leader : leaders) {
+ Enums::PwrState pws = leader->get();
+ fatal_if(pws == Enums::PwrState::UNDEFINED,
+ "%s is in the UNDEFINED power state, not acceptable as "
+ "leader!", leader->name());
+ }
+
+ // Calculate the power state of the domain, only looking at leader
+ leaderTargetState = calculatePowerDomainState();
+ // Set the power states of the followers, based upon leaderTargetState.
+ setFollowerPowerStates();
+}
+
+bool
+PowerDomain::isPossiblePwrState(Enums::PwrState p_state)
+{
+ for (const auto &objs : { leaders, followers }) {
+ for (const auto &obj : objs) {
+ const auto &obj_states = obj->getPossibleStates();
+ if (obj_states.find(p_state) == obj_states.end()) {
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+void
+PowerDomain::calculatePossiblePwrStates()
+{
+ assert(possibleStates.empty());
+ for (auto p_state: leaders[0]->getPossibleStates()) {
+ if (isPossiblePwrState(p_state)) {
+ possibleStates.emplace(p_state);
+ DPRINTF(PowerDomain, "%u/%s is a p-state\n", p_state,
+ Enums::PwrStateStrings[p_state]);
+ }
+ }
+}
+
+Enums::PwrState
+PowerDomain::calculatePowerDomainState(
+ const std::vector<Enums::PwrState> &f_states)
+{
+ DPRINTF(PowerDomain, "Calculating the power state\n");
+ Enums::PwrState most_perf_state = Enums::PwrState::Num_PwrState;
+ std::string most_perf_leader;
+ for (auto leader : leaders) {
+ Enums::PwrState pw = leader->get();
+ if (pw < most_perf_state) {
+ most_perf_state = pw;
+ most_perf_leader = leader->name();
+ }
+ }
+ assert(most_perf_state != Enums::PwrState::Num_PwrState);
+ DPRINTF(PowerDomain, "Most performant leader is %s, at %u\n",
+ most_perf_leader, most_perf_state);
+
+ // If asked to check the power states of the followers (f_states contains
+ // the power states of the followers)
+ if (!f_states.empty()) {
+ for (Enums::PwrState f_pw : f_states ) {
+ // Ignore UNDEFINED state of follower, at startup the followers
+ // might be in the UNDEFINED state, PowerDomain will pull them up
+ if ((f_pw != Enums::PwrState::UNDEFINED) &&
+ (f_pw < most_perf_state)) {
+ most_perf_state = f_pw;
+ }
+ }
+ DPRINTF(PowerDomain, "Most performant state, including followers "
+ "is %u\n", most_perf_state);
+ }
+ return most_perf_state;
+}
+
+void
+PowerDomain::setFollowerPowerStates()
+{
+ // Loop over all followers and tell them to change their power state so
+ // they match that of the power domain (or a more performant power state)
+ std::vector<Enums::PwrState> matched_states;
+ for (auto follower : followers) {
+ Enums::PwrState actual_pws =
+ follower->matchPwrState(leaderTargetState);
+ matched_states.push_back(actual_pws);
+ assert(actual_pws <= leaderTargetState);
+ DPRINTF(PowerDomain, "%u matched domain power state (%u) with %u\n",
+ follower->name(), leaderTargetState,
+ actual_pws);
+ }
+ // Now the power states of the follower have been changed recalculate the
+ // power state of the domain as a whole, including followers
+ Enums::PwrState new_power_state =
+ calculatePowerDomainState(matched_states);
+ if (new_power_state != _currState) {
+ // Change in power state of the domain, so update. Updates in power
+ // state need to happen via set() so it can propagate to
+ // overarching power domains (if there are any).
+ DPRINTF(PowerDomain, "Updated power domain state to %u\n",
+ new_power_state);
+ set(new_power_state);
+ }
+}
+
+void
+PowerDomain::pwrStateChangeCallback(Enums::PwrState new_pwr_state,
+ PowerState* leader)
+{
+ DPRINTF(PowerDomain, "PwrState update to %u by %s\n", new_pwr_state,
+ leader->name());
+
+ Enums::PwrState old_target_state = leaderTargetState;
+ // Calculate the power state of the domain, based on the leaders
+ if (new_pwr_state < _currState) {
+ // The power state of the power domain always needs to match that of
+ // the most performant leader so no need to go over the other leaders
+ // The power state need to be changed via a the PwrStateCall() so any
+ // overarching power domains get informed
+ leaderTargetState = new_pwr_state;
+ } else {
+ // Need to calculate the newly required power state, based on the
+ // leaders only and change to that state.
+ leaderTargetState = calculatePowerDomainState();
+ }
+ if (old_target_state!= leaderTargetState) {
+ // The followers will try to match that power state requested by the
+ // leaders in in the update event, based upon the actual power state,
+ // we will 'officially' change the power state of the domain by calling
+ // set()
+ schedule(pwrStateUpdateEvent, curTick() + updateLatency);
+ DPRINTF(PowerDomain, "TargetState change from %u to %u, followers will"
+ "be updated in %u ticks\n", old_target_state,
+ leaderTargetState, updateLatency);
+ stats.numLeaderCallsChangingState++;
+ }
+ stats.numLeaderCalls++;
+}
+
+PowerDomain::PowerDomainStats::PowerDomainStats(PowerDomain &pd)
+ : Stats::Group(&pd),
+ ADD_STAT(numLeaderCalls,
+ "Number of calls by leaders to change power domain state"),
+ ADD_STAT(numLeaderCallsChangingState,
+ "Number of calls by leader to change power domain state "
+ "actually resulting in a power state change")
+{
+}
+
+void
+PowerDomain::PowerDomainStats::regStats()
+{
+ Stats::Group::regStats();
+
+ numLeaderCalls
+ .flags(Stats::nozero)
+ ;
+ numLeaderCallsChangingState
+ .flags(Stats::nozero)
+ ;
+}
+
+PowerDomain*
+PowerDomainParams::create()
+{
+ return new PowerDomain(this);
+}
--- /dev/null
+/*
+ * Copyright (c) 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.
+ *
+ */
+
+#ifndef __SIM_POWER_DOMAIN_HH__
+#define __SIM_POWER_DOMAIN_HH__
+
+#include <string>
+#include <vector>
+
+#include "base/statistics.hh"
+#include "params/PowerDomain.hh"
+#include "sim/clocked_object.hh"
+#include "sim/power_state.hh"
+
+/**
+ * The PowerDomain groups PowerState objects together to regulate their
+ * power states. As the PowerDomain itself is a PowerState object, you can
+ * create hierarchies of PowerDomains. All objects in a power domain will be in
+ * the power state of the domain OR a more performant one.
+ */
+class PowerDomain : public PowerState
+{
+ public:
+ PowerDomain(const PowerDomainParams* p);
+ typedef PowerDomainParams Params;
+ ~PowerDomain() override {};
+
+ /**
+ * During startup, the list of possible power states the
+ * PowerDomain can be in is populated, the power state of the
+ * PowerDomain is set and some assertions about the PowerState objects
+ * in the Domain are checked.
+ */
+ void startup() override;
+
+ /**
+ * Register the change in power state in one of the leader. The power
+ * domain will change its own power state if required and if there is a
+ * power state, it will schedule an event to update its followers
+ */
+ void pwrStateChangeCallback(Enums::PwrState new_pwr_state,
+ PowerState* leader);
+
+ /**
+ * Function called by a follower to register itself as
+ * a dependant of this power domain
+ */
+ void addFollower(PowerState* pwr_obj) override;
+
+ private:
+ /**
+ * Calculate the power state of the power domain, based upon the power
+ * states of the leaders. This will be called if one the leaders
+ * changes its power states.
+ * If no inputs are given, only the leaders will be polled on their
+ * power state. You can also pass a vector containing the power states
+ * which the followers returned when asked to match a certain power
+ * state (called from setFollowerPowerStates)
+ */
+ Enums::PwrState calculatePowerDomainState(
+ const std::vector<Enums::PwrState> &f_states={});
+
+ /**
+ * Check if a given p_state is available across all leaders and
+ * followers in this domain.
+ */
+ bool isPossiblePwrState(Enums::PwrState p_state);
+
+ /**
+ * Calculate the possible power states of the domain based upon the
+ * intersection of the power states of the individual objects within
+ * the domain. Done at startup.
+ */
+ void calculatePossiblePwrStates();
+
+ /**
+ * Update the followers of the newly updated power state. They are
+ * required to match the power state of the power domain i.e. go to the
+ * same power state or a more performant one
+ */
+ void setFollowerPowerStates();
+
+ private: /* Power domain attributes */
+ /**
+ * List of all leaders in the PowerDomain. A leader can
+ * independently change its power state and does not depend on the
+ * PowerDomain to change its power state. A leader needs to be a
+ * PowerState object and can also be another PowerDomain. Each
+ * PowerDomain needs to have at least one leader.
+ */
+ std::vector<PowerState*> leaders;
+
+ /**
+ * Power state requested by the leader. This is not necessarily the
+ * power state of the domain as whole (as that one depends on the
+ * matched power states of the followers
+ */
+ Enums::PwrState leaderTargetState;
+
+ /**
+ * List of all followers in the PowerDomain. The power state of the
+ * domain will determine the power state of the followers. A follower
+ * cannot change its power state independently.
+ */
+ std::vector<PowerState*> followers;
+
+ /**
+ * Latency with which power state changes of the leaders will ripple
+ * through to the followers.
+ */
+ const Tick updateLatency = 1;
+
+ /**
+ * Event to update the power states of the followers
+ */
+ EventWrapper<PowerDomain, &PowerDomain::setFollowerPowerStates>
+ pwrStateUpdateEvent;
+
+ protected:
+ struct PowerDomainStats : public Stats::Group
+ {
+ PowerDomainStats(PowerDomain &pd);
+
+ void regStats() override;
+
+ Stats::Scalar numLeaderCalls;
+ Stats::Scalar numLeaderCallsChangingState;
+ } stats;
+};
+
+#endif // __SIM_POWER_DOMAIN_HH__
#include "sim/power_state.hh"
#include "base/logging.hh"
+#include "debug/PowerDomain.hh"
+#include "sim/power_domain.hh"
PowerState::PowerState(const PowerStateParams *p) :
SimObject(p), _currState(p->default_state),
possibleStates(p->possible_states.begin(),
p->possible_states.end()),
- prvEvalTick(0), stats(*this)
+ stats(*this)
{
+ for (auto &pm: p->leaders) {
+ // Register this object as a follower. This object is
+ // dependent on pm for power state transitions
+ pm->addFollower(this);
+ }
+}
+
+void
+PowerState::setControlledDomain(PowerDomain* pwr_dom)
+{
+ // Only a power domain can register as dependant of a power stated
+ // object
+ controlledDomain = pwr_dom;
+ DPRINTF(PowerDomain, "%s is registered as controlled by %s \n",
+ pwr_dom->name(), name());
}
void
_currState = p;
stats.numTransitions++;
+
+ // Update the domain this object controls, if there is one
+ if (controlledDomain) {
+ controlledDomain->pwrStateChangeCallback(p, this);
+ }
+
+}
+
+Enums::PwrState
+PowerState::matchPwrState(Enums::PwrState p)
+{
+ // If the object is asked to match a power state, it has to be a follower
+ // and hence should not have a pointer to a powerDomain
+ assert(controlledDomain == nullptr);
+
+ // If we are already in this power state, ignore request
+ if (_currState == p) {
+ DPRINTF(PowerDomain, "Already in p-state %s requested to match \n",
+ Enums::PwrStateStrings[p]);
+ return _currState;
+ }
+
+ Enums::PwrState old_state = _currState;
+ if (possibleStates.find(p) != possibleStates.end()) {
+ // If this power state is allowed in this object, just go there
+ set(p);
+ } else {
+ // Loop over all power states in this object and find a power state
+ // which is more performant than the requested one (considering we
+ // cannot match it exactly)
+ for (auto rev_it = possibleStates.crbegin();
+ rev_it != possibleStates.crend(); rev_it++) {
+ if (*(rev_it) <= p) {
+ // This power state is the least performant power state that is
+ // still more performant than the requested one
+ DPRINTF(PowerDomain, "Best match for %s is %s \n",
+ Enums::PwrStateStrings[p],
+ Enums::PwrStateStrings[*(rev_it)]);
+ set(*(rev_it));
+ break;
+ }
+ }
+ }
+ // Check if the transition happened
+ // The only case in which the power state cannot change is if the
+ // object is already at in its most performant state.
+ warn_if((_currState == old_state) &&
+ possibleStates.find(_currState) != possibleStates.begin(),
+ "Transition to power state %s was not possible, SimObject already"
+ " in the most performance state %s",
+ Enums::PwrStateStrings[p], Enums::PwrStateStrings[_currState]);
+
+ stats.numPwrMatchStateTransitions++;
+ return _currState;
}
void
powerState(co),
ADD_STAT(numTransitions,
"Number of power state transitions"),
+ ADD_STAT(numPwrMatchStateTransitions,
+ "Number of power state transitions due match request"),
ADD_STAT(ticksClkGated,
"Distribution of time spent in the clock gated state"),
ADD_STAT(pwrStateResidencyTicks,
const PowerStateParams *p = powerState.params();
numTransitions.flags(nozero);
+ numPwrMatchStateTransitions.flags(nozero);
// Each sample is time in ticks
unsigned num_bins = std::max(p->clk_gate_bins, 10U);
#include "sim/core.hh"
#include "sim/sim_object.hh"
+class PowerDomain;
+
/**
* Helper class for objects that have power states. This class provides the
* basic functionality to change between power states.
return reinterpret_cast<const Params*>(_params);
}
+ virtual void addFollower(PowerState* pwr_obj) {};
+ void setControlledDomain(PowerDomain* pwr_dom);
+
void serialize(CheckpointOut &cp) const override;
void unserialize(CheckpointIn &cp) override;
*/
void computeStats();
+ /**
+ * Change the power state of this object to a power state equal to OR more
+ * performant than p. Returns the power state the object actually went to.
+ */
+ Enums::PwrState matchPwrState(Enums::PwrState p);
+
/**
* Return the power states this object can be in
*/
Enums::PwrState _currState;
/** The possible power states this object can be in */
- const std::set<Enums::PwrState> possibleStates;
+ std::set<Enums::PwrState> possibleStates;
/** Last tick the power stats were calculated */
Tick prvEvalTick = 0;
+ /**
+ * The power domain that this power state leads, nullptr if it
+ * doesn't lead any.
+ */
+ PowerDomain* controlledDomain = nullptr;
+
struct PowerStateStats : public Stats::Group
{
PowerStateStats(PowerState &ps);
PowerState &powerState;
Stats::Scalar numTransitions;
+ Stats::Scalar numPwrMatchStateTransitions;
Stats::Distribution ticksClkGated;
/** Tracks the time spent in each of the power states */
Stats::Vector pwrStateResidencyTicks;