/*
- * 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
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Andreas Hansson
+ * Christopher Torng
*/
/**
#include "base/misc.hh"
#include "params/ClockedObject.hh"
#include "sim/core.hh"
+#include "sim/clock_domain.hh"
#include "sim/sim_object.hh"
/**
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
{
// 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
// 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);
}
/**
*/
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
{
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
{
}
/**
- * 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())); }
};