FPGA開発日記

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

自作RISC-V OoOコアでDhrystoneが完走した

ちまちまと自作RISC-Vコアを実装している。riscv-testsがかなり通っているので、Dhrystoneを実行することにした。

実はDhrystoneは少し前に動かしていたのだけれども、L1Dキャッシュのデータリプレースの部分になかなか難しいバグがあり、難しくなっていた部分を一気に書き換えてバグを全面的に潰した。 その結果、Dhrystoneが完走できるようになった。

riscv-testsにはすでにDhrystoneなどのベンチマークが備わっているが、現在の実装では上手く動かすことが出来ない。 いくつかの原因があって、

  • FPUをサポートしていないので、GCCコンパイルオプションを変更する必要がある
  • tohost / fromhostを正しく実装していないので、printf()の実装をいくつか変更する必要がある

まずはriscv-tests/benchmarks/の中で、FPUが必須のベンチマークプログラムを外して、コンパイルオプションを変更する。

diff --git a/benchmarks/Makefile b/benchmarks/Makefile
index c9469e2..44316be 100644
--- a/benchmarks/Makefile
+++ b/benchmarks/Makefile
@@ -24,20 +24,21 @@ bmarks = \
        towers \
        vvadd \
        multiply \
-       mm \
        dhrystone \
-       spmv \
-       mt-vvadd \
-       mt-matmul \
        pmp \

+#      mm \
+#      spmv \
+#      mt-vvadd \
+#      mt-matmul \
+
 #--------------------------------------------------------------------
 # Build rules
 #--------------------------------------------------------------------

 RISCV_PREFIX ?= riscv$(XLEN)-unknown-elf-
 RISCV_GCC ?= $(RISCV_PREFIX)gcc
-RISCV_GCC_OPTS ?= -DPREALLOCATE=1 -mcmodel=medany -static -std=gnu99 -O2 -ffast-math -fno-common -fno-builtin-printf -fno-tree-loop-distribute-patterns
+RISCV_GCC_OPTS ?= -march=rv$(XLEN)imc -mabi=lp$(XLEN) -DPREALLOCATE=1 -mcmodel=medany -static -std=gnu99 -O2 -ffast-math -fno-common -fno-builtin-printf -fno-tree-loop-distribute-patterns
 RISCV_LINK ?= $(RISCV_GCC) -T $(src_dir)/common/test.ld $(incs)
 RISCV_LINK_OPTS ?= -static -nostdlib -nostartfiles -lm -lgcc -T $(src_dir)/common/test.ld
 RISCV_OBJDUMP ?= $(RISCV_PREFIX)objdump --disassemble-all --disassemble-zeroes --section=.text --section=.text.startup --section=.text.init --section=.data

次に、syscalls.cを変更してputchar()を実行した後にfromhostの状態変更を待たずにすぐに戻るように変更する。

diff --git a/benchmarks/common/syscalls.c b/benchmarks/common/syscalls.c
index 39547b3..f3f8836 100644
--- a/benchmarks/common/syscalls.c
+++ b/benchmarks/common/syscalls.c
@@ -25,8 +25,8 @@ static uintptr_t syscall(uintptr_t which, uint64_t arg0, uint64_t arg1, uint64_t
   __sync_synchronize();

   tohost = (uintptr_t)magic_mem;
-  while (fromhost == 0)
-    ;
+  // while (fromhost == 0)
+  //   ;
   fromhost = 0;

   __sync_synchronize();

この変更したことで、Dhrystoneが完走できた。

1906722 : 201307 : PC=[000000008000264e] (20,02) 0017e793 ori     a5, a5, 1
GPR[15](178) <= 0000000000000001
1906722 : 201308 : PC=[0000000080002652] (20,04) fffff717 auipc   a4, 0xfffff
GPR[14](60) <= 0000000080001652
1906722 : 201309 : PC=[0000000080002656] (20,08) 9af73723 sd      a5, -1618(a4)
MW8(0x0000000080001000)=>0000000000000001
1906722 : 201310 : PC=[000000008000265a] (20,10) 0000a001 c.j     pc + 0
GPR[00](0) <= 0000000000000000
1906738 : L1D Stq Store : 80001000(00) : ______________________________________________________00000000_00000001
===============================
SIMULATION FINISH : PASS
===============================
f:id:msyksphinz:20210921235632p:plain

ただし分岐予測が全く実装できていないため、性能については全くダメ... これは今後の実装課題だな。