-
Notifications
You must be signed in to change notification settings - Fork 60
/
timecounters.h
87 lines (68 loc) · 2.25 KB
/
timecounters.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
// timercounters.h
//
// Reading cycle counter and gettimeofday counter, on various architectures
// Also Pause() to slow down speculation in spin loops and give cycles to any hyperthread
//
// Copyright 2022 Richard L. Sites
#ifndef __TIMERCOUNTERS_H__
#define __TIMERCOUNTERS_H__
/* Add others as you find and test them */
#define Isx86_64 defined(__x86_64)
#define IsAmd_64 Isx86_64 && defined(__znver1)
#define IsIntel_64 Isx86_64 && !defined(__znver1)
#define IsArm_64 defined(__aarch64__)
#define IsRPi4 defined(__ARM_ARCH) && (__ARM_ARCH == 8)
#define IsRPi4_64 IsRPi4 && IsArm_64
#define IsRiscv defined(__riscv)
#include <sys/time.h> // gettimeofday
#if Isx86_64
#include <x86intrin.h> // __rdtsc()
#endif
// Return a constant-rate "cycle" counter
inline int64_t GetCycles() {
#if Isx86_64
// Increments once per cycle, implemented as increment by N every N (~35) cycles
return __rdtsc();
#elif IsRPi4_64
// Increments once per 27.778 cycles for RPi4-B at 54 MHz counter and 1.5GHz CPU clock
// Call it 28 cycles
uint64_t counter_value;
asm volatile("mrs %x0, cntvct_el0" : "=r"(counter_value));
return counter_value * 28;
#elif IsRiscv
// Increments at unknown rate, might be 1 usec
#define CSR_CYCLE 0xc00
#define CSR_TIME 0xc01
#define CSR_INSTRET 0xc02
#ifdef __ASSEMBLY__
#define __ASM_STR(x) x
#else
#define __ASM_STR(x) #x
#endif
#define csr_read(csr) \
({ \
unsigned long __v; \
__asm__ __volatile__ ("csrr %0, " __ASM_STR(csr) \
: "=r" (__v) : \
: "memory"); \
__v; \
})
return csr_read(CSR_TIME);
#else
#error Need cycle counter defines for your architecture
#endif
}
// Return current time of day as microseconds since January 1, 1970
inline int64_t GetUsec() {
struct timeval tv;
gettimeofday(&tv, NULL);
return (tv.tv_sec * 1000000l) + tv.tv_usec;
}
inline void Pause() {
#if Isx86_64
__pause();
#else
// Nothing on Arm, etc.
#endif
}
#endif // __TIMERCOUNTERS_H__