I would like to instrument a program to access hardware performance counters.
I have compiled a basic Rocketchip (freechips.rocketchip.system-DefaultConfig
) and am using riscv-pk
to run a binary. I am running a simulation of the core in Verilator, having compiled it all with largely defaults in the UCB Chipyard project.
The C for the binary is as follows:
#include <stdio.h>
#define CACHE_MISS 0x100
int loop(int n, int a) {
int b = 0;
for(int i=0; i<n; i++) {
b = a + b;
}
return b;
}
int main() {
int a = 1;
int n = 200;
int count = 0;
printf("Configuring event monitor ...\n");
/*
// initialize counters here
// should start tracking cache misses with 0x100
__asm__ volatile("csrw mhpmevent3, %0"
:
: "r"(CACHE_MISS)
);
*/
printf("Executing loop ...\n");
loop(n, a);
printf("Reading event counter ...\n");
// read counters here
__asm__ volatile("csrr %0, hpmcounter3"
: "=r"(count)
);
printf("Cache misses: %d\n", count);
return 0;
}
It's a basic code just to see if I can count cache misses. This code gives me an "illegal instruction" error.
z 0000000000000000 ra 00000000000101e0 sp 000000000fee9b00 gp 000000000001e560
tp 0000000000000000 t0 0000000000000000 t1 000000000000000f t2 0000000000000000
s0 000000000fee9b20 s1 0000000000000000 a0 00000000000000c8 a1 0000000000000001
a2 0000000000000000 a3 0000000000000010 a4 00000000000000c8 a5 00000000000000c8
a6 000000000000001f a7 0000000000000000 s2 0000000000000000 s3 0000000000000000
s4 0000000000000000 s5 0000000000000000 s6 0000000000000000 s7 0000000000000000
s8 0000000000000000 s9 0000000000000000 sA 0000000000000000 sB 0000000000000000
t3 0000000000000000 t4 0000000000000000 t5 0000000000000000 t6 0000000000000000
pc 00000000000101e0 va 00000000b03027f3 insn b03027f3 sr 8000000200046020
An illegal instruction was executed!
Originally the line that read from hpmcounter3
was reading from mhpmcounter3
and resulted in the same error.
Speaking with another developer, one possible cause of this is the fact that riscv-pk
runs binaries in U-mode, so the illegal instruction after a call to m*
assembly instructions (which run in Machine, M-mode) is expected. So I changed the binary to comment away the first write to mphmevent3 and just did a bare read from hpmcounter3, but still get the illegal instruction error. The theory for this result was that the mcounteren
and scounteren
registers were not enabled, so I couldn't access the counters. However, looking inside of riscv-pk
's minit.c
, I find:
// Enable user/supervisor use of perf counters
if (supports_extension('S'))
write_csr(scounteren, -1);
if (supports_extension('U'))
write_csr(mcounteren, -1);
I'm not sure, but I feel like this enables the counters.
Any thoughts on how I ought to go about accessing the hardware performance counters?