mem: Make the XBar responsible for tracking response routing
[gem5.git] / src / sim / clock_domain.cc
index 0d1836e83c00c1070d5f1799ce8c73eafdf44f3b..8f45bba0930138397a24c0b7665c56c39f16dae0 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013 ARM Limited
+ * Copyright (c) 2013-2014 ARM Limited
  * Copyright (c) 2013 Cornell University
  * All rights reserved
  *
  *          Akash Bagdia
  *          Andreas Hansson
  *          Christopher Torng
+ *          Stephan Diestelhorst
  */
 
+#include <algorithm>
+#include <functional>
+
 #include "debug/ClockDomain.hh"
 #include "params/ClockDomain.hh"
 #include "params/DerivedClockDomain.hh"
@@ -70,9 +74,37 @@ ClockDomain::voltage() const
 }
 
 SrcClockDomain::SrcClockDomain(const Params *p) :
-    ClockDomain(p, p->voltage_domain)
+    ClockDomain(p, p->voltage_domain),
+    freqOpPoints(p->clock),
+    _domainID(p->domain_id),
+    _perfLevel(p->init_perf_level)
 {
-    clockPeriod(p->clock);
+    VoltageDomain *vdom = p->voltage_domain;
+
+    fatal_if(freqOpPoints.empty(), "DVFS: Empty set of frequencies for "\
+             "domain %d %s\n", _domainID, name());
+
+    fatal_if(!vdom, "DVFS: Empty voltage domain specified for "\
+             "domain %d %s\n", _domainID, name());
+
+    fatal_if((vdom->numVoltages() > 1) &&
+             (vdom->numVoltages() != freqOpPoints.size()),
+             "DVFS: Number of frequency and voltage scaling points do "\
+             "not match: %d:%d ID: %d %s.\n", vdom->numVoltages(),
+             freqOpPoints.size(), _domainID, name());
+
+    // Frequency (& voltage) points should be declared in descending order,
+    // NOTE: Frequency is inverted to ticks, so checking for ascending ticks
+    fatal_if(!std::is_sorted(freqOpPoints.begin(), freqOpPoints.end()),
+             "DVFS: Frequency operation points not in descending order for "\
+             "domain with ID %d\n", _domainID);
+
+    fatal_if(_perfLevel >= freqOpPoints.size(), "DVFS: Initial DVFS point %d "\
+             "is outside of list for Domain ID: %d\n", _perfLevel, _domainID);
+
+    clockPeriod(freqOpPoints[_perfLevel]);
+
+    vdom->registerSrcClockDom(this);
 }
 
 void
@@ -99,6 +131,52 @@ SrcClockDomain::clockPeriod(Tick clock_period)
     }
 }
 
+void
+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);
+
+    _perfLevel = perf_level;
+
+    // Signal the voltage domain that we have changed our perf level so that the
+    // voltage domain can recompute its performance level
+    voltageDomain()->sanitiseVoltages();
+
+    // Integrated switching of the actual clock value, too
+    clockPeriod(clkPeriodAtPerfLevel());
+}
+
+void
+SrcClockDomain::serialize(std::ostream &os)
+{
+    SERIALIZE_SCALAR(_perfLevel);
+    ClockDomain::serialize(os);
+}
+
+void
+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);
+}
+
 SrcClockDomain *
 SrcClockDomainParams::create()
 {