diff options
-rw-r--r-- | src/sim/clock_domain.cc | 12 | ||||
-rw-r--r-- | src/sim/clock_domain.hh | 1 | ||||
-rw-r--r-- | src/sim/dvfs_handler.cc | 21 | ||||
-rw-r--r-- | src/sim/dvfs_handler.hh | 33 | ||||
-rw-r--r-- | src/sim/voltage_domain.cc | 11 | ||||
-rw-r--r-- | src/sim/voltage_domain.hh | 15 |
6 files changed, 87 insertions, 6 deletions
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<DomainID> domain_ids; std::vector<PerfLevel> 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 <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. @@ -80,6 +81,18 @@ class DVFSHandler : public SimObject 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 * @return Domain ID known to handler? @@ -128,6 +141,19 @@ class DVFSHandler : public SimObject } /** + * 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. * * @param domain_id Domain ID to query @@ -154,6 +180,11 @@ class DVFSHandler : public SimObject Domains domains; /** + * List of IDs avaiable in the domain list + */ + std::vector<DomainID> domainIDList; + + /** * Clock domain of the system the handler is instantiated. */ SrcClockDomain* sysClkDomain; 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<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", 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. |