/***************************************************************************** * * File: PrecisionTimer.cpp * Project: Osmose emulator. * * Description: This class handle accurate timer measure, using rdtsc pentium * instruction. This code compile with gcc, under Linux, and windows. See in * PrecisionTimer.h for more information about Sleep(millis)/sleep(sec) issues. * * Author: Vedder Bruno * Date: 19/04/2004 * URL: http://bcz.emu-france.com/ *****************************************************************************/ #include "PrecisionTimer.h" #define rdtsc(val) __asm__ __volatile__ ("rdtsc" : "=A" (val)) /*--------------------------------------------------------------------*/ /* Default Constructor initialise values to -1; */ /*--------------------------------------------------------------------*/ PrecisionTimer::PrecisionTimer() { T0 = (unsigned long long)-1; T1 = (unsigned long long)-1; tick_per_second = (unsigned long long)-1; mode = ONE_SHOT; values_number = VALUES_BUFFER_SIZE; cumulative_buffer = NULL; cumul_buffer_index = 0; average_duration = 0.0; verbose = true; } /*--------------------------------------------------------------------*/ /* Calibration Process. s is in second. The longer is the calibration */ /* more accurate is the measure. */ /*--------------------------------------------------------------------*/ void PrecisionTimer::calibrate(int s) { unsigned long long start; unsigned long long stop; if (verbose) { cout << "Calibrating:" << dec<< s << " seconds." << endl; } rdtsc(start); PORTABLE_SLEEP_FUNC; rdtsc(stop); tick_per_second = (unsigned long long) ( stop - start ); tick_per_second = (tick_per_second / s); if (verbose) { cout << "tick_per_second is: " << dec << tick_per_second << endl; cout << "CPU seems to run at " << dec <<(tick_per_second / 1000000.0) << "Mhz." << endl; } } /*--------------------------------------------------------------------*/ /* Execute rdtsc pentium instruction store result into T0. */ /*--------------------------------------------------------------------*/ void PrecisionTimer::start() { rdtsc(T0); } /*--------------------------------------------------------------------*/ /* Execute rdtsc pentium instruction store result into T1. */ /* This method returns true if a value is available from measure: */ /* -Always true in ONE_SHOT mode */ /* -True when CUMULATIVE mode has enought value to compute average */ /* duration else false. */ /*--------------------------------------------------------------------*/ bool PrecisionTimer::stop() { bool ret = false; rdtsc(T1); if (mode == CUMULATIVE) { cumulative_buffer[cumul_buffer_index] = getOneShotDuration(); cumul_buffer_index++; // We have enough values: display average length. if (cumul_buffer_index == values_number) { double total_duration = 0.0; for (unsigned int i =0; i < values_number; i++) { total_duration += cumulative_buffer[i]; } average_duration = total_duration / values_number; if (verbose) { cout << "Average length = " << dec << average_duration << " ("<< dec << values_number << " values)." <