diff options
author | Luís Marques <luismarques@lowrisc.org> | 2019-10-22 17:56:54 +0100 |
---|---|---|
committer | Andrew Waterman <andrew@sifive.com> | 2019-10-22 09:56:53 -0700 |
commit | 99d6d0a93f9c83b63343a00693d5085e3949fe1a (patch) | |
tree | 2be05e20bf3956c1578bd32055c6195117087b85 | |
parent | 78e61baf432bd2d796c5b1e0498af363967322f4 (diff) | |
download | pk-99d6d0a93f9c83b63343a00693d5085e3949fe1a.zip pk-99d6d0a93f9c83b63343a00693d5085e3949fe1a.tar.gz pk-99d6d0a93f9c83b63343a00693d5085e3949fe1a.tar.bz2 |
Make performance counters always 64 bits wide (#178)
This prevents the counters from easily overflowing for a 32-bit pk.
-rw-r--r-- | pk/boot.h | 6 | ||||
-rw-r--r-- | pk/pk.c | 6 | ||||
-rw-r--r-- | pk/pk.h | 58 | ||||
-rw-r--r-- | pk/syscall.c | 25 | ||||
-rw-r--r-- | util/snprintf.c | 19 |
5 files changed, 93 insertions, 21 deletions
@@ -20,9 +20,9 @@ typedef struct { size_t brk_max; size_t mmap_max; size_t stack_top; - size_t time0; - size_t cycle0; - size_t instret0; + uint64_t time0; + uint64_t cycle0; + uint64_t instret0; } elf_info; extern elf_info current; @@ -132,9 +132,9 @@ static void run_loaded_program(size_t argc, char** argv, uintptr_t kstack_top) STACK_INIT(uintptr_t); if (current.cycle0) { // start timer if so requested - current.time0 = rdtime(); - current.cycle0 = rdcycle(); - current.instret0 = rdinstret(); + current.time0 = rdtime64(); + current.cycle0 = rdcycle64(); + current.instret0 = rdinstret64(); } trapframe_t tf; @@ -41,6 +41,64 @@ static inline int insn_len(long insn) return (insn & 0x3) < 0x3 ? 2 : 4; } +#if __riscv_xlen == 32 + +static inline uint64_t rdtime64() +{ + uint32_t time; + uint32_t timeh1; + uint32_t timeh2; + + do + { + timeh1 = read_csr(timeh); + time = read_csr(time); + timeh2 = read_csr(timeh); + } while(timeh1 != timeh2); + + return (((uint64_t) timeh1) << 32) | time; +} + +static inline uint64_t rdcycle64() +{ + uint32_t cycle; + uint32_t cycleh1; + uint32_t cycleh2; + + do + { + cycleh1 = read_csr(cycleh); + cycle = read_csr(cycle); + cycleh2 = read_csr(cycleh); + } while(cycleh1 != cycleh2); + + return (((uint64_t) cycleh1) << 32) | cycle; +} + +static inline uint64_t rdinstret64() +{ + uint32_t instret; + uint32_t instreth1; + uint32_t instreth2; + + do + { + instreth1 = read_csr(instreth); + instret = read_csr(instret); + instreth2 = read_csr(instreth); + } while(instreth1 != instreth2); + + return (((uint64_t) instreth1) << 32) | instret; +} + +#else + +#define rdtime64 rdtime +#define rdcycle64 rdcycle +#define rdinstret64 rdinstret + +#endif + #define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0])) #ifdef __cplusplus diff --git a/pk/syscall.c b/pk/syscall.c index 8903ecc..07fa41d 100644 --- a/pk/syscall.c +++ b/pk/syscall.c @@ -16,14 +16,15 @@ typedef long (*syscall_t)(long, long, long, long, long, long, long); void sys_exit(int code) { if (current.cycle0) { - size_t dt = rdtime() - current.time0; - size_t dc = rdcycle() - current.cycle0; - size_t di = rdinstret() - current.instret0; - - printk("%ld ticks\n", dt); - printk("%ld cycles\n", dc); - printk("%ld instructions\n", di); - printk("%d.%d%d CPI\n", dc/di, 10ULL*dc/di % 10, (100ULL*dc + di/2)/di % 10); + uint64_t dt = rdtime64() - current.time0; + uint64_t dc = rdcycle64() - current.cycle0; + uint64_t di = rdinstret64() - current.instret0; + + printk("%lld ticks\n", dt); + printk("%lld cycles\n", dc); + printk("%lld instructions\n", di); + printk("%d.%d%d CPI\n", (int)(dc/di), (int)(10ULL*dc/di % 10), + (int)((100ULL*dc + di/2)/di % 10)); } shutdown(code); } @@ -353,7 +354,7 @@ int sys_rt_sigaction(int sig, const void* act, void* oact, size_t sssz) long sys_time(long* loc) { - uintptr_t t = rdcycle() / CLOCK_FREQ; + uint64_t t = rdcycle64() / CLOCK_FREQ; if (loc) *loc = t; return t; @@ -361,7 +362,7 @@ long sys_time(long* loc) int sys_times(long* loc) { - uintptr_t t = rdcycle(); + uint64_t t = rdcycle64(); kassert(CLOCK_FREQ % 1000000 == 0); loc[0] = t / (CLOCK_FREQ / 1000000); loc[1] = 0; @@ -373,7 +374,7 @@ int sys_times(long* loc) int sys_gettimeofday(long* loc) { - uintptr_t t = rdcycle(); + uint64_t t = rdcycle64(); loc[0] = t / CLOCK_FREQ; loc[1] = (t % CLOCK_FREQ) / (CLOCK_FREQ / 1000000); @@ -382,7 +383,7 @@ int sys_gettimeofday(long* loc) long sys_clock_gettime(int clk_id, long *loc) { - uintptr_t t = rdcycle(); + uint64_t t = rdcycle64(); loc[0] = t / CLOCK_FREQ; loc[1] = (t % CLOCK_FREQ) / (CLOCK_FREQ / 1000000000); diff --git a/util/snprintf.c b/util/snprintf.c index 1544a6c..a11a4f7 100644 --- a/util/snprintf.c +++ b/util/snprintf.c @@ -9,6 +9,7 @@ int vsnprintf(char* out, size_t n, const char* s, va_list vl) { bool format = false; bool longarg = false; + bool longlongarg = false; size_t pos = 0; for( ; *s; s++) { @@ -17,7 +18,12 @@ int vsnprintf(char* out, size_t n, const char* s, va_list vl) switch(*s) { case 'l': - longarg = true; + if (s[1] == 'l') { + longlongarg = true; + s++; + } + else + longarg = true; break; case 'p': longarg = true; @@ -36,13 +42,19 @@ int vsnprintf(char* out, size_t n, const char* s, va_list vl) } case 'd': { - long num = longarg ? va_arg(vl, long) : va_arg(vl, int); + long long num; + if (longarg) + num = va_arg(vl, long); + else if (longlongarg) + num = va_arg(vl, long long); + else + num = va_arg(vl, int); if (num < 0) { num = -num; if (++pos < n) out[pos-1] = '-'; } long digits = 1; - for (long nn = num; nn /= 10; digits++) + for (long long nn = num; nn /= 10; digits++) ; for (int i = digits-1; i >= 0; i--) { if (pos + i + 1 < n) out[pos + i] = '0' + (num % 10); @@ -50,6 +62,7 @@ int vsnprintf(char* out, size_t n, const char* s, va_list vl) } pos += digits; longarg = false; + longlongarg = false; format = false; break; } |