energy: Tighter checking of levels for DFS systems
authorStephan Diestelhorst <stephan.diestelhorst@arm.com>
Tue, 12 Aug 2014 18:00:44 +0000 (19:00 +0100)
committerStephan Diestelhorst <stephan.diestelhorst@arm.com>
Tue, 12 Aug 2014 18:00:44 +0000 (19:00 +0100)
There are cases where users might by accident / intention specify less voltage
operating points thatn frequency points.  We consider one of these cases
special: giving only a single voltage to a voltage domain effectively renders
it as a static domain.  This patch adds additional logic in the auxiliary parts
of the functionality to handle these cases properly (simple driver asking for
N>1 operating levels, we should return the same voltage for all of them) and
adds error checking code in the voltage domain.

src/sim/dvfs_handler.hh
src/sim/voltage_domain.hh

index 3ff08115a75cf1af154505315186672366734501..a8b78d08b6d82e5f76af8329ae447ab11778cd90 100644 (file)
@@ -137,7 +137,15 @@ class DVFSHandler : public SimObject
      */
     Tick clkPeriodAtPerfLevel(DomainID domain_id, PerfLevel perf_level) const
     {
-        return findDomain(domain_id)->clkPeriodAtPerfLevel(perf_level);
+        SrcClockDomain *d = findDomain(domain_id);
+        assert(d);
+        PerfLevel n = d->numPerfLevels();
+        if (perf_level < n)
+            return d->clkPeriodAtPerfLevel(perf_level);
+
+        warn("DVFSHandler %s reads illegal frequency level %u from "\
+             "SrcClockDomain %s. Returning 0\n", name(), perf_level, d->name());
+        return Tick(0);
     }
 
     /**
@@ -150,7 +158,25 @@ class DVFSHandler : public SimObject
      */
     double voltageAtPerfLevel(DomainID domain_id, PerfLevel perf_level) const
     {
-        return findDomain(domain_id)->voltageDomain()->voltage(perf_level);
+        VoltageDomain *d = findDomain(domain_id)->voltageDomain();
+        assert(d);
+        PerfLevel n = d->numVoltages();
+        if (perf_level < n)
+            return d->voltage(perf_level);
+
+        // Request outside of the range of the voltage domain
+        if (n == 1) {
+            DPRINTF(DVFS, "DVFS: Request for perf-level %i for single-point "\
+                    "voltage domain %s.  Returning voltage at level 0: %.2f "\
+                    "V\n", perf_level, d->name(), d->voltage(0));
+            // Special case for single point voltage domain -> same voltage for
+            // all points
+            return d->voltage(0);
+        }
+
+        warn("DVFSHandler %s reads illegal voltage level %u from "\
+             "VoltageDomain %s. Returning 0 V\n", name(), perf_level, d->name());
+        return 0.;
     }
 
     /**
index 9ffbe7bbc787e8c82c4a7c6975fa2fbfe55b10ad..ab96abad84ff92cc917957c5ebaa786e608a0fff 100644 (file)
@@ -77,6 +77,10 @@ class VoltageDomain : public SimObject
      */
     double voltage(PerfLevel perf_level) const
     {
+        chatty_assert(perf_level < numVoltages(), "VoltageDomain %s "\
+                      "request for voltage perf level %u is outside "\
+                      "of numVoltages %u", name(), perf_level,
+                      numVoltages());
         return voltageOpPoints[perf_level];
     }