StopWatch with no floating-point

Post your example source code and application notes to share with others
Post Reply
joepasquariello
Posts: 81
Joined: Mon Apr 28, 2008 7:32 am

StopWatch with no floating-point

Post by joepasquariello » Thu Mar 17, 2011 6:34 pm

If you'd like to be able to use Larry's excellent StopWatch utility without bringing in floating-point support, you can replace the existing StopWatchReadTime() with the one shown below, which uses 64-bit integers and returns the elapsed time in clocks. It does exactly what Larry's original does, but with no floating-point math.

Working in clocks is definitely not as intuitive as in seconds. Also shown below are macros to convert clocks to seconds (double) and microseconds (integer). If you use floating-point in your own program, or you call the macro that converts to seconds, nothing will have been saved relative to Larry's original in terms of using floating-point code. Note that if you use the SEC2USEC macro, the calculation in the macro will overflow for times > ~4000 seconds. The SEC2MSEC macro is good to ~4,000,000 seconds. You could even create a function that chooses reasonable units for display based on the number of ticks, or that emulates the "%g" format used in Larry's test program.

If you want to work in seconds, Larry's original function is exactly equivalent to the macro call shown below. Note that if you call this macro, your program will require

double seconds = CLK2SEC( StopWatchReadTime(timer) );

The only other change I made to StopWatch.cpp was to declare variable PS as "DWORD" instead of "int". All of the integer calculations should be unsigned, so I wanted to be sure that there wouldn't be any signed intermediate results in the last line of the function.

The integer-only version executes in about 6 us, while the original takes 45-50 us, all of which is currently in the critical section, which might be important in some applications. I've only tested this on the 5234. Tomorrow I'll try it on the 5213, but I think it will be good.

Comments appreciated.

Joe

// integer-only version of StopWatchReadTime() that returns time in cpu clocks
unsigned long long StopWatchReadTime( int Timer )
{
DWORD lo, hi, trr;
USER_ENTER_CRITICAL();
lo = ReadStopWatchLow(Timer);
hi = HighTimerReg[Timer];
#ifdef MCF5272
if (Timer == 1) trr = sim.timer2.trr;
else if (Timer == 2) trr = sim.timer3.trr;
else trr = sim.timer4.trr;
#else
trr = sim.timer[Timer].trr;
#endif
USER_EXIT_CRITICAL();
return ( (lo + hi*(trr + 1ULL)) * (PS + 1ULL) );
}

// declaration for StopWatch.h
unsigned long long StopWatchReadTime( int Timer = DEFAULT_TIMER );

#define TIME_PER_CLK (1.0 / NB_CPU_CLK)

// macros for converting clocks to engineering units
#define CLK2SECF(x) ( (double) ((x)*TIME_PER_CLK) ) // uses floating point!
#define CLK2USEC(x) ( (unsigned long long) (((x)*1000000UL)/NB_CPU_CLK) )
#define CLK2MSEC(x) ( (unsigned long long) (((x)*1000UL)/NB_CPU_CLK) )
#define CLK2SEC(x) ( (unsigned long long) (((x)*1UL)/NB_CPU_CLK) )

// examples using iprintf() and printf(). note "%llu" format for unsigned long long.
unsigned long long clocks = StopWatchReadTime();
iprintf("The total time elapsed was %llu clocks\r\n", clocks );
iprintf("The total time elapsed was %llu us\r\n", CLK2USEC(clocks) );
printf("The total time elapsed was %g seconds\r\n", CLK2SEC(clocks) );

// program output for example code above. note clocks and us are > 32 bits.
The total time elapsed was 34560385890 clocks
The total time elapsed was 468755233 us
The total time elapsed was 468.755 seconds

Post Reply