とある事情でRISC-Vのベクトル命令の実行回数のみを記録したくて、特殊なシステムレジスタを実装するのも厄介なので、RISC-VのイベントカウンタであるHPMCOUNTERシステムレジスタを使うことにした。
Spikeを使っているのだが、HPMCOUNTERシステムレジスタはどうやら固定値になっているらしくカウントアップデートができない。 そこで、CSRの種類を変更してSpikeを再実装する。
以下の変更では、mhpmcounter
レジスタを定義したうえで、wise_counter_csr_t
で置き換え、カウントアップ機能が使えるようにする。
diff --git a/riscv/processor.cc b/riscv/processor.cc index c61088c9..a44c9752 100644 --- a/riscv/processor.cc +++ b/riscv/processor.cc @@ -264,7 +264,10 @@ void state_t::reset(processor_t* const proc, reg_t max_isa, mmu_t *mmu, uint32_t auto mevent = std::make_shared<const_csr_t>(proc, which_mevent, 0); auto mcounter = std::make_shared<const_csr_t>(proc, which_mcounter, 0); csrmap[which_mevent] = mevent; - csrmap[which_mcounter] = mcounter; + + // csrmap[which_mcounter] = mcounter; + mhpmcounter[i] = std::make_shared<wide_counter_csr_t>(proc, which_counter); + csrmap[which_mcounter] = mhpmcounter[i]; if (proc->extension_enabled_const(EXT_ZICNTR) && proc->extension_enabled_const(EXT_ZIHPM)) { auto counter = std::make_shared<counter_proxy_csr_t>(proc, which_counter, mcounter); diff --git a/riscv/processor.h b/riscv/processor.h index 012b56bc..820df0d6 100644 --- a/riscv/processor.h +++ b/riscv/processor.h @@ -144,6 +144,7 @@ struct state_t csr_t_p mcause; wide_counter_csr_t_p minstret; wide_counter_csr_t_p mcycle; + wide_counter_csr_t_p mhpmcounter[32]; mie_csr_t_p mie; mip_csr_t_p mip; csr_t_p medeleg;
このカウントアップ機能を使うためには、wise_counter_csr_t
のbump()
関数を使う。
// vle8.v and vlseg[2-8]e8.v VI_LD(0, (i * nf + fn), int8, false); P.get_state()->mhpmcounter[10]->bump(1);
これにより、HMPCOUNTER10
がカウントアップされる。あとはこれを観測すればよい。
long long get_vecinst() { long long num; asm volatile ("csrr %0, mhpmcounter10":"=r"(num)); return num; } ... long long start_vecinst = get_vecinst(); ... printf("vecinst = %ld\n", end_vecinst - start_vecinst);
これでベクトル命令のイベントをカウントできるようになった。ログを取るのに便利だ。