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:
Stephan Diestelhorst
2014-06-16 14:59:44 +01:00
parent bf23847072
commit 4422d1322a
6 changed files with 87 additions and 6 deletions

View File

@@ -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 &section)
{
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);
}

View File

@@ -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 &section);

View File

@@ -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 &section)
{
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;

View File

@@ -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.
*/

View File

@@ -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",

View File

@@ -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.