sim: Add support for dynamic frequency scaling
This patch provides support for DFS by having ClockedObjects register
themselves with their clock domain at construction time in a member list.
Using this list, a clock domain can update each member's tick to the
curTick() before modifying the clock period.

Committed by: Nilay Vaish <nilay@cs.wisc.edu>
diff --git a/src/sim/clock_domain.cc b/src/sim/clock_domain.cc
index 8b563d5..ff96f28 100644
--- a/src/sim/clock_domain.cc
+++ b/src/sim/clock_domain.cc
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2013 ARM Limited
+ * Copyright (c) 2013 Cornell University
  * All rights reserved
  *
  * The license below extends only to copyright in the software and shall
@@ -37,6 +38,7 @@
  * Authors: Vasileios Spiliopoulos
  *          Akash Bagdia
  *          Andreas Hansson
+ *          Christopher Torng
  */
 
 #include "debug/ClockDomain.hh"
@@ -45,6 +47,7 @@
 #include "params/SrcClockDomain.hh"
 #include "sim/clock_domain.hh"
 #include "sim/voltage_domain.hh"
+#include "sim/clocked_object.hh"
 
 double
 ClockDomain::voltage() const
@@ -65,6 +68,11 @@
         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,
@@ -105,6 +113,11 @@
 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;
diff --git a/src/sim/clock_domain.hh b/src/sim/clock_domain.hh
index 619f306..e6b7273 100644
--- a/src/sim/clock_domain.hh
+++ b/src/sim/clock_domain.hh
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2013 ARM Limited
+ * Copyright (c) 2013 Cornell University
  * All rights reserved
  *
  * The license below extends only to copyright in the software and shall
@@ -36,6 +37,7 @@
  *
  * Authors: Vasileios Spiliopoulos
  *          Akash Bagdia
+ *          Christopher Torng
  */
 
 /**
@@ -46,6 +48,8 @@
 #ifndef __SIM_CLOCK_DOMAIN_HH__
 #define __SIM_CLOCK_DOMAIN_HH__
 
+#include <algorithm>
+
 #include "base/statistics.hh"
 #include "params/ClockDomain.hh"
 #include "params/DerivedClockDomain.hh"
@@ -57,6 +61,7 @@
  */
 class DerivedClockDomain;
 class VoltageDomain;
+class ClockedObject;
 
 /**
  * The ClockDomain provides clock to group of clocked objects bundled
@@ -86,6 +91,12 @@
      */
     std::vector<DerivedClockDomain*> children;
 
+    /**
+     * Pointers to members of this clock domain, so that when the clock
+     * period changes, we can update each member's tick.
+     */
+    std::vector<ClockedObject*> members;
+
   public:
 
     typedef ClockDomainParams Params;
@@ -102,6 +113,18 @@
     inline Tick clockPeriod() const { return _clockPeriod; }
 
     /**
+     * Register a ClockedObject to this ClockDomain.
+     *
+     * @param ClockedObject to add as a member
+     */
+    void registerWithClockDomain(ClockedObject *c)
+    {
+        assert(c != NULL);
+        assert(std::find(members.begin(), members.end(), c) == members.end());
+        members.push_back(c);
+    }
+
+    /**
      * Get the voltage domain.
      *
      * @return Voltage domain this clock domain belongs to
@@ -145,6 +168,8 @@
      */
     void clockPeriod(Tick clock_period);
 
+    // Explicitly import the otherwise hidden clockPeriod
+    using ClockDomain::clockPeriod;
 };
 
 /**
diff --git a/src/sim/clocked_object.hh b/src/sim/clocked_object.hh
index 304397a..fb020f5 100644
--- a/src/sim/clocked_object.hh
+++ b/src/sim/clocked_object.hh
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2012-2013 ARM Limited
+ * Copyright (c) 2013 Cornell University
  * All rights reserved
  *
  * The license below extends only to copyright in the software and shall
@@ -35,6 +36,7 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  * Authors: Andreas Hansson
+ *          Christopher Torng
  */
 
 /**
@@ -118,6 +120,9 @@
     ClockedObject(const ClockedObjectParams* p) :
         SimObject(p), tick(0), cycle(0), clockDomain(*p->clk_domain)
     {
+        // Register with the clock domain, so that if the clock domain
+        // frequency changes, we can update this object's tick.
+        clockDomain.registerWithClockDomain(this);
     }
 
     /**
@@ -140,6 +145,15 @@
   public:
 
     /**
+     * Update the tick to the current tick.
+     *
+     */
+    inline void updateClockPeriod() const
+    {
+        update();
+    }
+
+    /**
      * Determine the tick when a cycle begins, by default the current
      * one, but the argument also enables the caller to determine a
      * future cycle.