From 4422d1322a8ed47bc9d743894ad47d82f33eba7c Mon Sep 17 00:00:00 2001 From: Stephan Diestelhorst Date: Mon, 16 Jun 2014 14:59:44 +0100 Subject: 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 --- src/sim/clock_domain.cc | 12 ++++++++++++ src/sim/clock_domain.hh | 1 + src/sim/dvfs_handler.cc | 21 +++++++++++++++++++++ src/sim/dvfs_handler.hh | 33 ++++++++++++++++++++++++++++++++- src/sim/voltage_domain.cc | 11 ++++++++--- src/sim/voltage_domain.hh | 15 +++++++++++++-- 6 files changed, 87 insertions(+), 6 deletions(-) (limited to 'src/sim') diff --git a/src/sim/clock_domain.cc b/src/sim/clock_domain.cc index 746ef12fd..8f45bba09 100644 --- a/src/sim/clock_domain.cc +++ b/src/sim/clock_domain.cc @@ -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); } diff --git a/src/sim/clock_domain.hh b/src/sim/clock_domain.hh index 946e5bd27..edf2340ad 100644 --- a/src/sim/clock_domain.hh +++ b/src/sim/clock_domain.hh @@ -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); diff --git a/src/sim/dvfs_handler.cc b/src/sim/dvfs_handler.cc index bb60b1850..f4fe760a2 100644 --- a/src/sim/dvfs_handler.cc +++ b/src/sim/dvfs_handler.cc @@ -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 domain_ids; std::vector perf_levels; diff --git a/src/sim/dvfs_handler.hh b/src/sim/dvfs_handler.hh index c8d962133..3ff08115a 100644 --- a/src/sim/dvfs_handler.hh +++ b/src/sim/dvfs_handler.hh @@ -52,13 +52,14 @@ #include +#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 Domains; Domains domains; + /** + * List of IDs avaiable in the domain list + */ + std::vector domainIDList; + /** * Clock domain of the system the handler is instantiated. */ diff --git a/src/sim/voltage_domain.cc b/src/sim/voltage_domain.cc index b5673feda..2b16d04b9 100644 --- a/src/sim/voltage_domain.cc +++ b/src/sim/voltage_domain.cc @@ -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()), "DVFS: Voltage "\ - "operation points not in descending order for voltage domain "\ - "%s\n", name()); + std::greater()), "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", diff --git a/src/sim/voltage_domain.hh b/src/sim/voltage_domain.hh index 3904c80c9..9ffbe7bbc 100644 --- a/src/sim/voltage_domain.hh +++ b/src/sim/voltage_domain.hh @@ -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. -- cgit v1.2.3