syscall_emul: file descriptor interface changes
[gem5.git] / src / sim / clock_domain.cc
index 262ae904cb06f903dc8122c68fc09a9717848868..60c688b1a0a5ab2a28ea53e097d08186246aac5c 100644 (file)
@@ -1,5 +1,6 @@
 /*
- * Copyright (c) 2013 ARM Limited
+ * Copyright (c) 2013-2014 ARM Limited
+ * Copyright (c) 2013 Cornell University
  * All rights reserved
  *
  * The license below extends only to copyright in the software and shall
  * Authors: Vasileios Spiliopoulos
  *          Akash Bagdia
  *          Andreas Hansson
+ *          Christopher Torng
+ *          Stephan Diestelhorst
  */
 
+#include <algorithm>
+#include <functional>
+
 #include "debug/ClockDomain.hh"
 #include "params/ClockDomain.hh"
 #include "params/DerivedClockDomain.hh"
 #include "params/SrcClockDomain.hh"
 #include "sim/clock_domain.hh"
+#include "sim/voltage_domain.hh"
+#include "sim/clocked_object.hh"
+
+void
+ClockDomain::regStats()
+{
+    using namespace Stats;
+
+    // Expose the current clock period as a stat for observability in
+    // the dumps
+    currentClock
+        .scalar(_clockPeriod)
+        .name(params()->name + ".clock")
+        .desc("Clock period in ticks")
+        ;
+}
 
-SrcClockDomain::SrcClockDomain(const Params *p) : ClockDomain(p)
+double
+ClockDomain::voltage() const
 {
-    clockPeriod(p->clock);
+    return _voltageDomain->voltage();
+}
+
+SrcClockDomain::SrcClockDomain(const Params *p) :
+    ClockDomain(p, p->voltage_domain),
+    freqOpPoints(p->clock),
+    _domainID(p->domain_id),
+    _perfLevel(p->init_perf_level)
+{
+    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
@@ -57,6 +114,11 @@ SrcClockDomain::clockPeriod(Tick clock_period)
         fatal("%s has a clock period of zero\n", name());
     }
 
+    // Align all members to the current tick
+    for (auto m = members.begin(); m != members.end(); ++m) {
+        (*m)->updateClockPeriod();
+    }
+
     _clockPeriod = clock_period;
 
     DPRINTF(ClockDomain,
@@ -69,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(CheckpointOut &cp) const
+{
+    SERIALIZE_SCALAR(_perfLevel);
+    ClockDomain::serialize(cp);
+}
+
+void
+SrcClockDomain::unserialize(CheckpointIn &cp)
+{
+    ClockDomain::unserialize(cp);
+    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()
 {
@@ -76,7 +184,7 @@ SrcClockDomainParams::create()
 }
 
 DerivedClockDomain::DerivedClockDomain(const Params *p) :
-    ClockDomain(p),
+    ClockDomain(p, p->clk_domain->voltageDomain()),
     parent(*p->clk_domain),
     clockDivider(p->clk_divider)
 {
@@ -97,6 +205,11 @@ DerivedClockDomain::DerivedClockDomain(const Params *p) :
 void
 DerivedClockDomain::updateClockPeriod()
 {
+    // Align all members to the current tick
+    for (auto m = members.begin(); m != members.end(); ++m) {
+        (*m)->updateClockPeriod();
+    }
+
     // recalculate the clock period, relying on the fact that changes
     // propagate downwards in the tree
     _clockPeriod = parent.clockPeriod() * clockDivider;