mirror of
https://github.com/Ed94/gencpp.git
synced 2024-12-22 15:54:45 -08:00
168 lines
4.1 KiB
C++
168 lines
4.1 KiB
C++
#ifdef GEN_INTELLISENSE_DIRECTIVES
|
|
# pragma once
|
|
# include "filesystem.cpp"
|
|
#endif
|
|
|
|
#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 scast( u64, lo ) | ( scast( 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
|