gencpp/project/dependencies/timing.cpp
Ed_ 5d7dfaf666 Heavy refactor..
Isolating large macros to their own directory (components/temp).
- Plan is to remove them soon with proper generation.

Added additional component files, separating the old data_structures header for a set of ast headers.
Header_end also had its inlines extracted out.
Necessary to complete the macro isolation.

ZPL parser dependencies were removed from the core library along with builder, its now generated in bootstrap as pare of making a gen_builder set of files.

Singleheader will be changed in next few commits to reflect this as well (By making builder deps and components a conditional option).

Tests are most likely all broken for now.
2023-08-03 11:01:43 -04:00

164 lines
4.0 KiB
C++

#pragma region Timing
#ifdef GEN_BENCHMARK
#if defined( GEN_COMPILER_MSVC ) && ! defined( __clang__ )
u64 read_cpu_time_stamp_counter( void )
{
return __rdtsc();
}
#elif defined( __i386__ )
u64 read_cpu_time_stamp_counter( void )
{
u64 x;
__asm__ volatile( ".byte 0x0f, 0x31" : "=A"( x ) );
return x;
}
#elif defined( __x86_64__ )
u64 read_cpu_time_stamp_counter( void )
{
u32 hi, lo;
__asm__ __volatile__( "rdtsc" : "=a"( lo ), "=d"( hi ) );
return ( zpl_cast( u64 ) lo ) | ( ( zpl_cast( u64 ) hi ) << 32 );
}
#elif defined( __powerpc__ )
u64 read_cpu_time_stamp_counter( void )
{
u64 result = 0;
u32 upper, lower, tmp;
__asm__ volatile(
"0: \n"
"\tmftbu %0 \n"
"\tmftb %1 \n"
"\tmftbu %2 \n"
"\tcmpw %2,%0 \n"
"\tbne 0b \n"
: "=r"( upper ), "=r"( lower ), "=r"( tmp )
);
result = upper;
result = result << 32;
result = result | lower;
return result;
}
#elif defined( GEN_SYSTEM_EMSCRIPTEN )
u64 read_cpu_time_stamp_counter( void )
{
return ( u64 )( emscripten_get_now() * 1e+6 );
}
#elif defined( GEN_CPU_ARM ) && ! defined( GEN_COMPILER_TINYC )
u64 read_cpu_time_stamp_counter( void )
{
# if defined( __aarch64__ )
int64_t r = 0;
asm volatile( "mrs %0, cntvct_el0" : "=r"( r ) );
# elif ( __ARM_ARCH >= 6 )
uint32_t r = 0;
uint32_t pmccntr;
uint32_t pmuseren;
uint32_t pmcntenset;
// Read the user mode perf monitor counter access permissions.
asm volatile( "mrc p15, 0, %0, c9, c14, 0" : "=r"( pmuseren ) );
if ( pmuseren & 1 )
{ // Allows reading perfmon counters for user mode code.
asm volatile( "mrc p15, 0, %0, c9, c12, 1" : "=r"( pmcntenset ) );
if ( pmcntenset & 0x80000000ul )
{ // Is it counting?
asm volatile( "mrc p15, 0, %0, c9, c13, 0" : "=r"( pmccntr ) );
// The counter is set up to count every 64th cycle
return ( ( int64_t )pmccntr ) * 64; // Should optimize to << 6
}
}
# else
# error "No suitable method for read_cpu_time_stamp_counter for this cpu type"
# endif
return r;
}
#else
u64 read_cpu_time_stamp_counter( void )
{
GEN_PANIC( "read_cpu_time_stamp_counter is not supported on this particular setup" );
return -0;
}
#endif
#if defined( GEN_SYSTEM_WINDOWS ) || defined( GEN_SYSTEM_CYGWIN )
u64 time_rel_ms( void )
{
local_persist LARGE_INTEGER win32_perf_count_freq = {};
u64 result;
LARGE_INTEGER counter;
local_persist LARGE_INTEGER win32_perf_counter = {};
if ( ! win32_perf_count_freq.QuadPart )
{
QueryPerformanceFrequency( &win32_perf_count_freq );
GEN_ASSERT( win32_perf_count_freq.QuadPart != 0 );
QueryPerformanceCounter( &win32_perf_counter );
}
QueryPerformanceCounter( &counter );
result = ( counter.QuadPart - win32_perf_counter.QuadPart ) * 1000 / ( win32_perf_count_freq.QuadPart );
return result;
}
#else
# if defined( GEN_SYSTEM_LINUX ) || defined( GEN_SYSTEM_FREEBSD ) || defined( GEN_SYSTEM_OPENBSD ) || defined( GEN_SYSTEM_EMSCRIPTEN )
u64 _unix_gettime( void )
{
struct timespec t;
u64 result;
clock_gettime( 1 /*CLOCK_MONOTONIC*/, &t );
result = 1000 * t.tv_sec + 1.0e-6 * t.tv_nsec;
return result;
}
# endif
u64 time_rel_ms( void )
{
# if defined( GEN_SYSTEM_OSX )
u64 result;
local_persist u64 timebase = 0;
local_persist u64 timestart = 0;
if ( ! timestart )
{
mach_timebase_info_data_t tb = { 0 };
mach_timebase_info( &tb );
timebase = tb.numer;
timebase /= tb.denom;
timestart = mach_absolute_time();
}
// NOTE: mach_absolute_time() returns things in nanoseconds
result = 1.0e-6 * ( mach_absolute_time() - timestart ) * timebase;
return result;
# else
local_persist u64 unix_timestart = 0.0;
if ( ! unix_timestart )
{
unix_timestart = _unix_gettime();
}
u64 now = _unix_gettime();
return ( now - unix_timestart );
# endif
}
#endif
f64 time_rel( void )
{
return ( f64 )( time_rel_ms() * 1e-3 );
}
#endif
#pragma endregion Timing