sim: Initialize Drainable::_drainState to the system's state
[gem5.git] / src / sim / clocked_object.hh
index b0aaa17210fab62cd165eebd62160f92907fe4d8..d878f4704b274bfb3d2a34297a75a56987d8ae06 100644 (file)
@@ -1,5 +1,6 @@
 /*
- * Copyright (c) 2012 ARM Limited
+ * 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
  */
 
 /**
@@ -49,6 +51,7 @@
 #include "base/misc.hh"
 #include "params/ClockedObject.hh"
 #include "sim/core.hh"
+#include "sim/clock_domain.hh"
 #include "sim/sim_object.hh"
 
 /**
@@ -76,7 +79,8 @@ class ClockedObject : public SimObject
     ClockedObject& operator=(ClockedObject&);
 
     /**
-     *  Align cycle and tick to the next clock edge if not already done.
+     *  Align cycle and tick to the next clock edge if not already done. When
+     *  complete, tick must be at least curTick().
      */
     void update() const
     {
@@ -88,7 +92,7 @@ class ClockedObject : public SimObject
 
         // optimise for the common case and see if the tick should be
         // advanced by a single clock period
-        tick += clock;
+        tick += clockPeriod();
         ++cycle;
 
         // see if we are done at this point
@@ -98,26 +102,28 @@ class ClockedObject : public SimObject
         // if not, we have to recalculate the cycle and tick, we
         // perform the calculations in terms of relative cycles to
         // allow changes to the clock period in the future
-        Cycles elapsedCycles(divCeil(curTick() - tick, clock));
+        Cycles elapsedCycles(divCeil(curTick() - tick, clockPeriod()));
         cycle += elapsedCycles;
-        tick += elapsedCycles * clock;
+        tick += elapsedCycles * clockPeriod();
     }
 
-  protected:
+    /**
+     * The clock domain this clocked object belongs to
+     */
+    ClockDomain &clockDomain;
 
-    // Clock period in ticks
-    Tick clock;
+  protected:
 
     /**
-     * Create a clocked object and set the clock based on the
+     * Create a clocked object and set the clock domain based on the
      * parameters.
      */
     ClockedObject(const ClockedObjectParams* p) :
-        SimObject(p), tick(0), cycle(0), clock(p->clock)
+        SimObject(p), tick(0), cycle(0), clockDomain(*p->clk_domain)
     {
-        if (clock == 0) {
-            fatal("%s has a clock period of zero\n", name());
-        }
+        // Register with the clock domain, so that if the clock domain
+        // frequency changes, we can update this object's tick.
+        clockDomain.registerWithClockDomain(this);
     }
 
     /**
@@ -132,21 +138,35 @@ class ClockedObject : public SimObject
      */
     void resetClock() const
     {
-        Cycles elapsedCycles(divCeil(curTick(), clock));
+        Cycles elapsedCycles(divCeil(curTick(), clockPeriod()));
         cycle = elapsedCycles;
-        tick = elapsedCycles * clock;
+        tick = elapsedCycles * clockPeriod();
     }
 
   public:
 
     /**
-     * Determine the tick when a cycle begins, by default the current
-     * one, but the argument also enables the caller to determine a
-     * future cycle.
+     * 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. When
+     * curTick() is on a clock edge, the number of cycles in the parameter is
+     * added to curTick() to be returned. When curTick() is not aligned to a
+     * clock edge, the number of cycles in the parameter is added to the next
+     * clock edge.
      *
      * @param cycles The number of cycles into the future
      *
-     * @return The tick when the clock edge occurs
+     * @return The start tick when the requested clock edge occurs. Precisely,
+     * this tick can be
+     *     curTick() + [0, clockPeriod()) + clockPeriod() * cycles
      */
     inline Tick clockEdge(Cycles cycles = Cycles(0)) const
     {
@@ -154,14 +174,16 @@ class ClockedObject : public SimObject
         update();
 
         // figure out when this future cycle is
-        return tick + clock * cycles;
+        return tick + clockPeriod() * cycles;
     }
 
     /**
      * Determine the current cycle, corresponding to a tick aligned to
      * a clock edge.
      *
-     * @return The current cycle count
+     * @return When curTick() is on a clock edge, return the Cycle corresponding
+     * to that clock edge. When curTick() is not on a clock edge, return the
+     * Cycle corresponding to the next clock edge.
      */
     inline Cycles curCycle() const
     {
@@ -172,20 +194,30 @@ class ClockedObject : public SimObject
     }
 
     /**
-     * Based on the clock of the object, determine the tick when the
-     * next cycle begins, in other words, return the next clock edge.
+     * Based on the clock of the object, determine the start tick of the first
+     * cycle that is at least one cycle in the future. When curTick() is at the
+     * current cycle edge, this returns the next clock edge. When calling this
+     * during the middle of a cycle, this returns 2 clock edges in the future.
      *
-     * @return The tick when the next cycle starts
+     * @return The start tick of the first cycle that is at least one cycle in
+     * the future. Precisely, the returned tick can be in the range
+     *     curTick() + [clockPeriod(), 2 * clockPeriod())
      */
     Tick nextCycle() const
-    { return clockEdge(); }
+    { return clockEdge(Cycles(1)); }
 
-    inline uint64_t frequency() const { return SimClock::Frequency / clock; }
+    inline uint64_t frequency() const
+    {
+        return SimClock::Frequency / clockPeriod();
+    }
 
-    inline Tick clockPeriod() const { return clock; }
+    inline Tick clockPeriod() const
+    {
+        return clockDomain.clockPeriod();
+    }
 
-    inline Cycles ticksToCycles(Tick tick) const
-    { return Cycles(tick / clock); }
+    inline Cycles ticksToCycles(Tick t) const
+    { return Cycles(divCeil(t, clockPeriod())); }
 
 };