diff options
Diffstat (limited to 'src/sim/voltage_domain.cc')
-rw-r--r-- | src/sim/voltage_domain.cc | 92 |
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 §ion) { + UNSERIALIZE_SCALAR(_perfLevel); + perfLevel(_perfLevel); +} |