summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStephan Diestelhorst <stephan.diestelhorst@arm.com>2014-06-16 14:59:44 +0100
committerStephan Diestelhorst <stephan.diestelhorst@arm.com>2014-06-16 14:59:44 +0100
commit4422d1322a8ed47bc9d743894ad47d82f33eba7c (patch)
tree54aa0efe2365af7d41d41e78cba3dae9434f13ee
parentbf238470726b4cc5c0b34fcb349d767726fe53bc (diff)
downloadgem5-4422d1322a8ed47bc9d743894ad47d82f33eba7c.tar.xz
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>
-rw-r--r--src/sim/clock_domain.cc12
-rw-r--r--src/sim/clock_domain.hh1
-rw-r--r--src/sim/dvfs_handler.cc21
-rw-r--r--src/sim/dvfs_handler.hh33
-rw-r--r--src/sim/voltage_domain.cc11
-rw-r--r--src/sim/voltage_domain.hh15
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 &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);
}
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 &section);
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 &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;
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.