测量的mcycle小于Spike中的minstret(The measured mcycle is less than minstret in Spike)

我使用spike在“riscv-tools / riscv-tests / build / benchmarks”中运行测试程序:

$ spike multiply.riscv

输出显示:

mcycle = 24096 minstret = 24103

为什么mcycle不到minstret ?

剂量是否意味着尖峰可以在一个循环中运行多个指令? (我试图追踪尖​​峰代码,但无法找到如何计算mcycle。)

I use spike to run the test program in "riscv-tools/riscv-tests/build/benchmarks":

$ spike multiply.riscv

And the output shows:

mcycle = 24096 minstret = 24103

Why mcycle is less than minstret?

Dose it means that spike can run more than one instructions in one cycle? (I tried to trace spike code but cannot find how mcycle is counted.)

最满意答案

在这种情况下,mcycle和minstret值的打印不是来自Spike,而是来自测试(基准)。 有代码:

https://github.com/ucb-bar/riscv-benchmarks/blob/master/common/syscalls.c

#define NUM_COUNTERS 2 static uintptr_t counters[NUM_COUNTERS]; static char* counter_names[NUM_COUNTERS]; static int handle_stats(int enable) { int i = 0; #define READ_CTR(name) do { \ while (i >= NUM_COUNTERS) ; \ uintptr_t csr = read_csr(name); \ if (!enable) { csr -= counters[i]; counter_names[i] = #name; } \ counters[i++] = csr; \ } while (0) READ_CTR(mcycle); READ_CTR(minstret); #undef READ_CTR return 0; }

阅读mcycle和minstret之间有一些代码。 现在您知道读数之间有多少代码。

在Spike中,mcycle&minstret的定义总是相同的(它们由相同的代码处理): https : //github.com/riscv/riscv-isa-sim/blob/9e012462f53113dc9ed00d7fbb89aeafeb9b89e9/riscv/processor.cc#L347

case CSR_MINSTRET: case CSR_MCYCLE: if (xlen == 32) state.minstret = (state.minstret >> 32 << 32) | (val & 0xffffffffU); else state.minstret = val; break;

syscalls.c从https://github.com/ucb-bar/riscv-benchmarks/blob/master/multiply/bmark.mk链接到multiply.riscv二进制文件 - multiply_riscv_bin = multiply.riscv $(multiply_riscv_bin):.. 。$(patsubst%.c,%。o,... syscalls.c ...)

syscalls.c函数中有_init调用main测试并打印值,使用handle_stats记录在SYS_stats“syscall”上。

void _init(int cid, int nc) { init_tls(); thread_entry(cid, nc); // only single-threaded programs should ever get here. int ret = main(0, 0); char buf[NUM_COUNTERS * 32] __attribute__((aligned(64))); char* pbuf = buf; for (int i = 0; i < NUM_COUNTERS; i++) if (counters[i]) pbuf += sprintf(pbuf, "%s = %d\n", counter_names[i], counters[i]); if (pbuf != buf) printstr(buf); exit(ret); }

The printing of mcycle and minstret values are not from Spike in this case, it is from the test (benchmark). There is the code:

https://github.com/ucb-bar/riscv-benchmarks/blob/master/common/syscalls.c

#define NUM_COUNTERS 2 static uintptr_t counters[NUM_COUNTERS]; static char* counter_names[NUM_COUNTERS]; static int handle_stats(int enable) { int i = 0; #define READ_CTR(name) do { \ while (i >= NUM_COUNTERS) ; \ uintptr_t csr = read_csr(name); \ if (!enable) { csr -= counters[i]; counter_names[i] = #name; } \ counters[i++] = csr; \ } while (0) READ_CTR(mcycle); READ_CTR(minstret); #undef READ_CTR return 0; }

There is some code between reading mcycle & minstret. And now you know how much code is there between readings.

In Spike mcycle & minstret are always equal by definition (they are handled by the same code): https://github.com/riscv/riscv-isa-sim/blob/9e012462f53113dc9ed00d7fbb89aeafeb9b89e9/riscv/processor.cc#L347

case CSR_MINSTRET: case CSR_MCYCLE: if (xlen == 32) state.minstret = (state.minstret >> 32 << 32) | (val & 0xffffffffU); else state.minstret = val; break;

The syscalls.c was linked into multiply.riscv binary from https://github.com/ucb-bar/riscv-benchmarks/blob/master/multiply/bmark.mk - multiply_riscv_bin = multiply.riscv $(multiply_riscv_bin): ... $(patsubst %.c, %.o, ... syscalls.c ... )

There is _init in syscalls.c function which calls main of the test and prints values, recorded on SYS_stats "syscall" with handle_stats.

void _init(int cid, int nc) { init_tls(); thread_entry(cid, nc); // only single-threaded programs should ever get here. int ret = main(0, 0); char buf[NUM_COUNTERS * 32] __attribute__((aligned(64))); char* pbuf = buf; for (int i = 0; i < NUM_COUNTERS; i++) if (counters[i]) pbuf += sprintf(pbuf, "%s = %d\n", counter_names[i], counters[i]); if (pbuf != buf) printstr(buf); exit(ret); }

更多推荐