summaryrefslogtreecommitdiff
path: root/src/sim/voltage_domain.cc
diff options
context:
space:
mode:
authorStephan Diestelhorst <stephan.diestelhorst@arm.com>2014-06-30 13:56:06 -0400
committerStephan Diestelhorst <stephan.diestelhorst@arm.com>2014-06-30 13:56:06 -0400
commit65cea4708e2f2f2cb361e12b6385d4bc29618223 (patch)
tree9f190702d43e89e2ddb44b6af363330f301ec8fb /src/sim/voltage_domain.cc
parent641e6028304187468b94753752555e9d082a77ac (diff)
downloadgem5-65cea4708e2f2f2cb361e12b6385d4bc29618223.tar.xz
power: Add basic DVFS support for gem5
Adds DVFS capabilities to gem5, by allowing users to specify lists for frequencies and voltages in SrcClockDomains and VoltageDomains respectively. A separate component, DVFSHandler, provides a small interface to change operating points of the associated domains. Clock domains will be linked to voltage domains and thus allow separate clock, but shared voltage lines. Currently all the valid performance-level updates are performed with a fixed transition latency as specified for the domain. Config file example: ... vd = VoltageDomain(voltage = ['1V','0.95V','0.90V','0.85V']) tsys.cluster1.clk_domain.clock = ['1GHz','700MHz','400MHz','230MHz'] tsys.cluster2.clk_domain.clock = ['1GHz','700MHz','400MHz','230MHz'] tsys.cluster1.clk_domain.domain_id = 0 tsys.cluster2.clk_domain.domain_id = 1 tsys.cluster1.clk_domain.voltage_domain = vd tsys.cluster2.clk_domain.voltage_domain = vd tsys.dvfs_handler.domains = [tsys.cluster1.clk_domain, tsys.cluster2.clk_domain] tsys.dvfs_handler.enable = True
Diffstat (limited to 'src/sim/voltage_domain.cc')
-rw-r--r--src/sim/voltage_domain.cc92
1 files changed, 80 insertions, 12 deletions
diff --git a/src/sim/voltage_domain.cc b/src/sim/voltage_domain.cc
index 461e672ea..b5673feda 100644
--- a/src/sim/voltage_domain.cc
+++ b/src/sim/voltage_domain.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012 ARM Limited
+ * Copyright (c) 2012-2014 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
@@ -38,36 +38,93 @@
* Akash Bagdia
*/
+#include <algorithm>
+
+#include "base/statistics.hh"
#include "debug/VoltageDomain.hh"
#include "params/VoltageDomain.hh"
#include "sim/sim_object.hh"
#include "sim/voltage_domain.hh"
VoltageDomain::VoltageDomain(const Params *p)
- : SimObject(p), _voltage(0)
+ : SimObject(p), voltageOpPoints(p->voltage), _perfLevel(0)
{
- voltage(p->voltage);
+ fatal_if(voltageOpPoints.empty(), "DVFS: Empty set of voltages for "\
+ "voltage domain %s\n", name());
+
+ // 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());
}
void
-VoltageDomain::voltage(double voltage)
+VoltageDomain::perfLevel(PerfLevel perf_level)
+{
+ chatty_assert(perf_level < voltageOpPoints.size(),
+ "DVFS: Requested voltage ID %d is outside the known "\
+ "range for domain %s.\n", perf_level, name());
+
+ _perfLevel = perf_level;
+
+ DPRINTF(VoltageDomain, "Setting voltage to %.3fV idx: %d for domain %s\n",
+ voltage(), perf_level, name());
+}
+
+bool
+VoltageDomain::sanitiseVoltages()
{
- if (voltage <= 0) {
- fatal("Voltage should be greater than zero.\n");
+ if (numVoltages() == 1)
+ return false;
+
+ // Find the highest requested performance level and update the voltage
+ // domain with it
+ PerfLevel perf_max = (PerfLevel)-1;
+ for (auto dit = srcClockChildren.begin(); dit != srcClockChildren.end(); ++dit) {
+ SrcClockDomain* d = *dit;
+ chatty_assert(d->voltageDomain() == this, "DVFS: Clock domain %s "\
+ "(id: %d) should not be registered with voltage domain "\
+ "%s\n", d->name(), d->domainID(), name());
+
+ PerfLevel perf = d->perfLevel();
+
+ DPRINTF(VoltageDomain, "DVFS: Clock domain %s (id: %d) requests perf "\
+ "level %d\n", d->name(), d->domainID(), perf);
+
+ // NOTE: Descending sort of performance levels: 0 - fast, 5 - slow
+ if (perf < perf_max) {
+ DPRINTF(VoltageDomain, "DVFS: Updating max perf level %d -> %d\n",
+ perf_max, perf);
+ perf_max = perf;
+ }
}
+ DPRINTF(VoltageDomain, "DVFS: Setting perf level of voltage domain %s "\
+ "from %d to %d.\n", name(), perfLevel(), perf_max);
- _voltage = voltage;
- DPRINTF(VoltageDomain,
- "Setting voltage to %f for domain %s\n", _voltage, name());
+ // Set the performance level
+ if (perf_max != perfLevel()) {
+ perfLevel(perf_max);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+void
+VoltageDomain::startup() {
+ bool changed = sanitiseVoltages();
+ if (changed) {
+ warn("DVFS: Perf level for voltage domain %s adapted to "\
+ "requested perf levels from source clock domains.\n", name());
+ }
}
void
VoltageDomain::regStats()
{
- using namespace Stats;
-
currentVoltage
- .scalar(_voltage)
+ .method(this, &VoltageDomain::voltage)
.name(params()->name + ".voltage")
.desc("Voltage in Volts")
;
@@ -78,3 +135,14 @@ VoltageDomainParams::create()
{
return new VoltageDomain(this);
}
+
+void
+VoltageDomain::serialize(std::ostream &os) {
+ SERIALIZE_SCALAR(_perfLevel);
+}
+
+void
+VoltageDomain::unserialize(Checkpoint *cp, const std::string &section) {
+ UNSERIALIZE_SCALAR(_perfLevel);
+ perfLevel(_perfLevel);
+}