FPGA開発日記

カテゴリ別記事インデックス https://msyksphinz.github.io/github_pages , English Version https://fpgadevdiary.hatenadiary.com/

RISC-Vテストパタン riscv-tests を使った命令セットシミュレータの検証 (Vモードのテストパタンの解析)

RISC-V の実装や命令セットシミュレータ (Instruction Set Simulator) を作ったとき、その実装の正当性をチェックするためにriscv-toolsのテストパタンを使用するという方法がある。

riscv-testsにはいくつかの種類があって、

  • rv32ui-p (32-bitモード、整数命令、Physical Addressing モード)
  • rv64uf-v (64-bitモード、浮動小数点命令、Virtual Addressingモード)

で、Virtual Addressingモードのテストパタンの検証なのだけれども結構ややこしいことになっている。 RISC-V の ISSであるSpikeで観測してみた。

spike -l rv64ui-v-add &> rv64ui-v-add.spike.log

sret命令は、割り込み処理から戻るための命令だ。この実装の実体は、ISSの実装から見ることができる。

  • riscv-isa-sim/riscv/insns/sret.h
require_privilege(get_field(STATE.mstatus, MSTATUS_TSR) ? PRV_M : PRV_S);
set_pc_and_serialize(p->get_state()->sepc);
reg_t s = STATE.mstatus;
reg_t prev_prv = get_field(s, MSTATUS_SPP);
s = set_field(s, MSTATUS_SIE, get_field(s, MSTATUS_SPIE));
s = set_field(s, MSTATUS_SPIE, 1);
s = set_field(s, MSTATUS_SPP, PRV_U);
p->set_privilege(prev_prv);
p->set_csr(CSR_MSTATUS, s);

中身を理解するのは少し難しいのだが、mstatusシステムレジスタの中身を理解しなければならないだろう。

f:id:msyksphinz:20180404224215p:plain
図. mstatusレジスタの割り当て。RV32モードとRV64モードで動作が異なる。

MPP / SPP / UPPレジスタは、モード遷移で現在のモードに移動してきた前のモードを保持している。

MPP : M-Mode に遷移してきたとき、一つ前のモード (S-Mode or U-Mode) SPP : S-Mode に遷移してきたとき、一つ前のモード (U-Mode) UPP : U-Modeに遷移してきたとき、一つ前のモード (なし)

実行結果をみてみると、

core   0: 0x00000000800000b4 (0x0f053f03) ld      t5, 240(a0)
core   0: 0x00000000800000b8 (0x0f853f83) ld      t6, 248(a0)
core   0: 0x00000000800000bc (0x05053503) ld      a0, 80(a0)
core   0: 0x00000000800000c0 (0x10200073) sret
core   0: exception trap_instruction_page_fault, epc 0x0000000000002ac8
core   0:           tval 0x0000000000002ac8
core   0: 0xffffffffffe000c4 (0x14011173) csrrw   sp, sscratch, sp
core   0: 0xffffffffffe000c8 (0x00113423) sd      ra, 8(sp)
core   0: 0xffffffffffe000cc (0x00313c23) sd      gp, 24(sp)
core   0: 0xffffffffffe000d0 (0x02413023) sd      tp, 32(sp)

まず、sret命令を実行してsepcからアドレスをPCに設定したのだが、このときにアドレス変換のページテーブル参照に失敗して、例外を発生した。 ところが、medelegレジスタのPage Table Fault には1が設定されており、M-Modeで処理されるはずの例外はS-Modeに移譲され、S-Modeで実行が継続される。

core   0: 0xffffffffffe000b8 (0x0f853f83) ld      t6, 248(a0)
core   0: 0xffffffffffe000bc (0x05053503) ld      a0, 80(a0)
core   0: 0xffffffffffe000c0 (0x10200073) sret
core   0: 0x0000000000002ac8 (0x00000093) li      ra, 0
core   0: 0x0000000000002acc (0x00000113) li      sp, 0
core   0: 0x0000000000002ad0 (0x00208f33) add     t5, ra, sp

つぎにsretで戻ってきたときに例外から戻ってきて、正しくページテーブル変換ができるようになって戻ってくる。