From d53d04473e0d6ca1765f1117072eec59187a7f7b Mon Sep 17 00:00:00 2001 From: Andreas Hansson Date: Tue, 28 Aug 2012 14:30:31 -0400 Subject: Clock: Rework clocks to avoid tick-to-cycle transformations This patch introduces the notion of a clock update function that aims to avoid costly divisions when turning the current tick into a cycle. Each clocked object advances a private (hidden) cycle member and a tick member and uses these to implement functions for getting the tick of the next cycle, or the tick of a cycle some time in the future. In the different modules using the clocks, changes are made to avoid counting in ticks only to later translate to cycles. There are a few oddities in how the O3 and inorder CPU count idle cycles, as seen by a few locations where a cycle is subtracted in the calculation. This is done such that the regression does not change any stats, but should be revisited in a future patch. Another, much needed, change that is not done as part of this patch is to introduce a new typedef uint64_t Cycle to be able to at least hint at the unit of the variables counting Ticks vs Cycles. This will be done as a follow-up patch. As an additional follow up, the thread context still uses ticks for the book keeping of last activate and last suspend and this should probably also be changed into cycles as well. --- src/sim/clocked_object.hh | 89 ++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 73 insertions(+), 16 deletions(-) (limited to 'src/sim/clocked_object.hh') diff --git a/src/sim/clocked_object.hh b/src/sim/clocked_object.hh index 8ab637772..050a15a74 100644 --- a/src/sim/clocked_object.hh +++ b/src/sim/clocked_object.hh @@ -58,6 +58,14 @@ class ClockedObject : public SimObject private: + // the tick value of the next clock edge (>= curTick()) at the + // time of the last call to update() + mutable Tick tick; + + // The cycle counter value corresponding to the current value of + // 'tick' + mutable Tick cycle; + /** * Prevent inadvertent use of the copy constructor and assignment * operator by making them private. @@ -65,6 +73,34 @@ class ClockedObject : public SimObject ClockedObject(ClockedObject&); ClockedObject& operator=(ClockedObject&); + /** + * Align cycle and tick to the next clock edge if not already done. + */ + void update() const + { + // both tick and cycle are up-to-date and we are done, note + // that the >= is important as it captures cases where tick + // has already passed curTick() + if (tick >= curTick()) + return; + + // optimise for the common case and see if the tick should be + // advanced by a single clock period + tick += clock; + ++cycle; + + // see if we are done at this point + if (tick >= curTick()) + return; + + // 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 + Tick elapsedCycles = divCeil(curTick() - tick, clock); + cycle += elapsedCycles; + tick += elapsedCycles * clock; + } + protected: // Clock period in ticks @@ -74,7 +110,8 @@ class ClockedObject : public SimObject * Create a clocked object and set the clock based on the * parameters. */ - ClockedObject(const ClockedObjectParams* p) : SimObject(p), clock(p->clock) + ClockedObject(const ClockedObjectParams* p) : + SimObject(p), tick(0), cycle(0), clock(p->clock) { } /** @@ -85,33 +122,53 @@ class ClockedObject : public SimObject public: /** - * Based on the clock of the object, determine the tick when the - * next cycle begins, in other words, round the curTick() to the - * next tick that is a multiple of the clock. + * Determine the tick when a cycle begins, by default the current + * one, but the argument also enables the caller to determine a + * future cycle. * - * @return The tick when the next cycle starts + * @param cycles The number of cycles into the future + * + * @return The tick when the clock edge occurs */ - Tick nextCycle() const - { return divCeil(curTick(), clock) * clock; } + inline Tick clockEdge(int cycles = 0) const + { + // align tick to the next clock edge + update(); + + // figure out when this future cycle is + return tick + ticks(cycles); + } /** - * Determine the next cycle starting from a given tick instead of - * curTick(). + * Determine the current cycle, corresponding to a tick aligned to + * a clock edge. * - * @param begin_tick The tick to round to a clock edge + * @return The current cycle + */ + inline Tick curCycle() const + { + // align cycle to the next clock edge. + update(); + + return cycle; + } + + /** + * Based on the clock of the object, determine the tick when the + * next cycle begins, in other words, return the next clock edge. * - * @return The tick when the cycle after or on begin_tick starts + * @return The tick when the next cycle starts */ - Tick nextCycle(Tick begin_tick) const - { return divCeil(begin_tick, clock) * clock; } + Tick nextCycle() const + { return clockEdge(); } inline Tick frequency() const { return SimClock::Frequency / clock; } - inline Tick ticks(int numCycles) const { return clock * numCycles; } + inline Tick ticks(int cycles) const { return clock * cycles; } - inline Tick curCycle() const { return curTick() / clock; } + inline Tick clockPeriod() const { return clock; } - inline Tick tickToCycles(Tick val) const { return val / clock; } + inline Tick tickToCycle(Tick tick) const { return tick / clock; } }; -- cgit v1.2.3