energy: Small extentions and fixes for DVFS handler
These additions allow easier interoperability with and querying from an additional controller which will be in a separate patch. Also adding warnings for changing the enabled state of the handler across checkpoint / resume and deviating from the state in the configuration. Contributed-by: Akash Bagdia <akash.bagdia@arm.com>
This commit is contained in:
@@ -136,6 +136,11 @@ SrcClockDomain::perfLevel(PerfLevel perf_level)
|
||||
{
|
||||
assert(validPerfLevel(perf_level));
|
||||
|
||||
if (perf_level == _perfLevel) {
|
||||
// Silently ignore identical overwrites
|
||||
return;
|
||||
}
|
||||
|
||||
DPRINTF(ClockDomain, "DVFS: Switching performance level of domain %s "\
|
||||
"(id: %d) from %d to %d\n", name(), domainID(), _perfLevel,
|
||||
perf_level);
|
||||
@@ -162,6 +167,13 @@ SrcClockDomain::unserialize(Checkpoint *cp, const std::string §ion)
|
||||
{
|
||||
ClockDomain::unserialize(cp, section);
|
||||
UNSERIALIZE_SCALAR(_perfLevel);
|
||||
}
|
||||
|
||||
void
|
||||
SrcClockDomain::startup()
|
||||
{
|
||||
// Perform proper clock update when all related components have been
|
||||
// created (i.e. after unserialization / object creation)
|
||||
perfLevel(_perfLevel);
|
||||
}
|
||||
|
||||
|
||||
@@ -237,6 +237,7 @@ class SrcClockDomain : public ClockDomain
|
||||
return freqOpPoints[perf_level];
|
||||
}
|
||||
|
||||
void startup();
|
||||
void serialize(std::ostream &os);
|
||||
void unserialize(Checkpoint *cp, const std::string §ion);
|
||||
|
||||
|
||||
@@ -81,12 +81,26 @@ DVFSHandler::DVFSHandler(const Params *p)
|
||||
// Create a dedicated event slot per known domain ID
|
||||
UpdateEvent *event = &updatePerfLevelEvents[domain_id];
|
||||
event->domainIDToSet = d->domainID();
|
||||
|
||||
// Add domain ID to the list of domains
|
||||
domainIDList.push_back(d->domainID());
|
||||
}
|
||||
UpdateEvent::dvfsHandler = this;
|
||||
}
|
||||
|
||||
DVFSHandler *DVFSHandler::UpdateEvent::dvfsHandler;
|
||||
|
||||
DVFSHandler::DomainID
|
||||
DVFSHandler::domainID(uint32_t index) const
|
||||
{
|
||||
fatal_if(index >= numDomains(), "DVFS: Requested index out of "\
|
||||
"bound, max value %d\n", (domainIDList.size() - 1));
|
||||
|
||||
assert(domains.find(domainIDList[index]) != domains.end());
|
||||
|
||||
return domainIDList[index];
|
||||
}
|
||||
|
||||
bool
|
||||
DVFSHandler::validDomainID(DomainID domain_id) const
|
||||
{
|
||||
@@ -186,8 +200,15 @@ DVFSHandler::serialize(std::ostream &os)
|
||||
void
|
||||
DVFSHandler::unserialize(Checkpoint *cp, const std::string §ion)
|
||||
{
|
||||
bool temp = enableHandler;
|
||||
|
||||
UNSERIALIZE_SCALAR(enableHandler);
|
||||
|
||||
if(temp != enableHandler) {
|
||||
warn("DVFS: Forcing enable handler status to unserialized value of %d",
|
||||
enableHandler);
|
||||
}
|
||||
|
||||
// Reconstruct the map of domain IDs and their scheduled events
|
||||
std::vector<DomainID> domain_ids;
|
||||
std::vector<PerfLevel> perf_levels;
|
||||
|
||||
@@ -52,13 +52,14 @@
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "debug/DVFS.hh"
|
||||
#include "params/ClockDomain.hh"
|
||||
#include "params/DVFSHandler.hh"
|
||||
#include "params/VoltageDomain.hh"
|
||||
#include "sim/clock_domain.hh"
|
||||
#include "sim/eventq.hh"
|
||||
#include "sim/sim_object.hh"
|
||||
|
||||
#include "sim/voltage_domain.hh"
|
||||
|
||||
/**
|
||||
* DVFS Handler class, maintains a list of all the domains it can handle.
|
||||
@@ -79,6 +80,18 @@ class DVFSHandler : public SimObject
|
||||
typedef SrcClockDomain::DomainID DomainID;
|
||||
typedef SrcClockDomain::PerfLevel PerfLevel;
|
||||
|
||||
/**
|
||||
* Get the number of domains assigned to this DVFS handler.
|
||||
* @return Number of domains
|
||||
*/
|
||||
uint32_t numDomains() const { return domainIDList.size(); }
|
||||
|
||||
/**
|
||||
* Get the n-th domain ID, from the domains managed by this handler.
|
||||
* @return Domain ID
|
||||
*/
|
||||
DomainID domainID(uint32_t index) const;
|
||||
|
||||
/**
|
||||
* Check whether a domain ID is known to the handler or not.
|
||||
* @param domain_id Domain ID to check
|
||||
@@ -127,6 +140,19 @@ class DVFSHandler : public SimObject
|
||||
return findDomain(domain_id)->clkPeriodAtPerfLevel(perf_level);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the voltage of the specified domain at the specified
|
||||
* performance level.
|
||||
* @param domain_id Domain ID to query
|
||||
* @param perf_level Performance level of interest
|
||||
* @return Voltage for the requested performance level of the respective
|
||||
* domain
|
||||
*/
|
||||
double voltageAtPerfLevel(DomainID domain_id, PerfLevel perf_level) const
|
||||
{
|
||||
return findDomain(domain_id)->voltageDomain()->voltage(perf_level);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the total number of available performance levels.
|
||||
*
|
||||
@@ -153,6 +179,11 @@ class DVFSHandler : public SimObject
|
||||
typedef std::map<DomainID, SrcClockDomain*> Domains;
|
||||
Domains domains;
|
||||
|
||||
/**
|
||||
* List of IDs avaiable in the domain list
|
||||
*/
|
||||
std::vector<DomainID> domainIDList;
|
||||
|
||||
/**
|
||||
* Clock domain of the system the handler is instantiated.
|
||||
*/
|
||||
|
||||
@@ -54,9 +54,9 @@ VoltageDomain::VoltageDomain(const Params *p)
|
||||
|
||||
// Voltages must be sorted in descending order.
|
||||
fatal_if(!std::is_sorted(voltageOpPoints.begin(), voltageOpPoints.end(),
|
||||
std::greater_equal<Voltages::value_type>()), "DVFS: Voltage "\
|
||||
"operation points not in descending order for voltage domain "\
|
||||
"%s\n", name());
|
||||
std::greater<Voltages::value_type>()), "DVFS: Voltage operation "\
|
||||
"points not in descending order for voltage domain %s\n",
|
||||
name());
|
||||
}
|
||||
|
||||
void
|
||||
@@ -66,6 +66,11 @@ VoltageDomain::perfLevel(PerfLevel perf_level)
|
||||
"DVFS: Requested voltage ID %d is outside the known "\
|
||||
"range for domain %s.\n", perf_level, name());
|
||||
|
||||
if (perf_level == _perfLevel) {
|
||||
// Silently ignore identical overwrites
|
||||
return;
|
||||
}
|
||||
|
||||
_perfLevel = perf_level;
|
||||
|
||||
DPRINTF(VoltageDomain, "Setting voltage to %.3fV idx: %d for domain %s\n",
|
||||
|
||||
@@ -60,6 +60,8 @@ class VoltageDomain : public SimObject
|
||||
typedef VoltageDomainParams Params;
|
||||
VoltageDomain(const Params *p);
|
||||
|
||||
typedef SrcClockDomain::PerfLevel PerfLevel;
|
||||
|
||||
/**
|
||||
* Get the current voltage.
|
||||
*
|
||||
@@ -67,9 +69,18 @@ class VoltageDomain : public SimObject
|
||||
*/
|
||||
double voltage() const { return voltageOpPoints[_perfLevel]; }
|
||||
|
||||
uint32_t numVoltages() const { return (uint32_t)voltageOpPoints.size(); }
|
||||
/**
|
||||
* Get the voltage at specified performance level.
|
||||
*
|
||||
* @param perf_level Performance level for which the voltage is requested
|
||||
* @return Voltage of the domain at specified performance level
|
||||
*/
|
||||
double voltage(PerfLevel perf_level) const
|
||||
{
|
||||
return voltageOpPoints[perf_level];
|
||||
}
|
||||
|
||||
typedef SrcClockDomain::PerfLevel PerfLevel;
|
||||
uint32_t numVoltages() const { return (uint32_t)voltageOpPoints.size(); }
|
||||
|
||||
/**
|
||||
* Set the voltage point of the domain.
|
||||
|
||||
Reference in New Issue
Block a user