UCBの開発しているシミュレータSpikeは、RISC-Vの命令セットをシミュレーションすることのできるISSで、サイクル精度を出すことはできないが最初のアプリケーションのデバッグに有用なツールだ。
そして、RISC-Vにはカスタム命令 (custom0 - custom3)が用意されており、Rocket Chipの場合にはこの命令フィールドを用いてRoCCインタフェース上にアクセラレータを搭載することが出来る。
どうせ元はChiselなのだから、この辺をうまくマージすることが出来ないだろうかといろいろ調査していたのだが、どうやらRoCCインタフェースをSpikeシミュレータではシミュレーションすることが出来るようだ。
まず、サンプルプログラムとして dummy_rocc/
ディレクトリにサンプルが存在している。
dummy_rocc/
├── dummy_rocc.ac
├── dummy_rocc.cc
├── dummy_rocc.mk.in
└── dummy_rocc_test.c
0 directories, 4 files
この実装 dummy_rocc.cc
は rocc_t
を継承する形で実装されている。
https://github.com/riscv/riscv-isa-sim/blob/master/dummy_rocc/dummy_rocc.cc
class dummy_rocc_t : public rocc_t
{
public:
const char* name() { return "dummy_rocc"; }
reg_t custom0(rocc_insn_t insn, reg_t xs1, reg_t xs2)
{
reg_t prev_acc = acc[insn.rs2];
if (insn.rs2 >= num_acc)
...
これを拡張して memtotal_rocc.cc
を作成してビルドを行ってみる。そのために memtotal_rocc/
ディレクトリを作成する。
$ tree memtotal_rocc/ -L 2
memtotal_rocc/
├── memtotal_rocc.ac
├── memtotal_rocc.cc
├── memtotal_rocc.mk.in
└── memtotal_rocc_test.c
0 directories, 4 files
class memtotal_rocc_t : public rocc_t
{
public:
const char* name() { return "memtotal_rocc"; }
...
reg_t custom0(rocc_insn_t insn, reg_t xs1, reg_t xs2)
{
switch (insn.funct)
{
case 0:
c0_reg_lengthM = xs1;
break;
case 1:
c0_reg_lengthK = xs1;
break;
case 2:
reg_t total = 0;
for (reg_t i = 0; i < c0_reg_lengthK; i++) {
total += p->get_mmu()->load_int32(xs1) * p->get_mmu()->load_int32(xs2);
xs1 += sizeof(int32_t);
xs2 += c0_reg_lengthK * sizeof(int32_t);
}
break;
}
return 0;
}
ここで custom0 ()
の実装で、メモリアクセスを p->get_mmu()->load_int32(xs1) * p->get_mmu()->load_int32(xs2)
としている。
さらにこの memtotal_rocc をコンパイルするようにサブモジュールとして登録する。
riscv-isa-sim/configure.ac
diff --git a/configure.ac b/configure.ac
index e361877..64759fa 100644
--- a/configure.ac
+++ b/configure.ac
@@ -86,7 +86,7 @@ AC_SUBST([CXXFLAGS],["-Wall -Wno-unused -g -O2 -std=c++11"])
# The '*' suffix indicates an optional subproject. The '**' suffix
# indicates an optional subproject which is also the name of a group.
-MCPPBS_SUBPROJECTS([ riscv, dummy_rocc, softfloat, spike_main ])
+MCPPBS_SUBPROJECTS([ riscv, dummy_rocc, memtotal_rocc, softfloat, spike_main ])
#-------------------------------------------------------------------------
# MCPPBS subproject groups
これでビルドするとlibmemtotal.so
が作成される。
build$ ls -1 *.so
libdummy_rocc.so
libmemtotal_rocc.so
libriscv.so
libsoftfloat.so
libspike_main.so
これをオプションとして指定することで、extensionとして使用できるようになる。が、--extension=memtotal_rocc
で何故か認識されなかった。要解析。
$ ./spike --extension=dummy_rocc
usage: spike [host options] <target program> [target options]
Host Options:
-p<n> Simulate <n> processors [default 1]
-m<n> Provide <n> MiB of target memory [default 2048]
-m<a:m,b:n,...> Provide memory regions of size m and n bytes
at base addresses a and b (with 4 KiB alignment)
-d Interactive debug mode
-g Track histogram of PCs
-l Generate a log of execution
-h Print this help message
-H Start halted, allowing a debugger to connect
--isa=<name> RISC-V ISA string [default rv32ima]
--pc=<address> Override ELF entry point
--ic=<S>:<W>:<B> Instantiate a cache model with S sets,
--dc=<S>:<W>:<B> W ways, and B-byte blocks (with S and
--l2=<S>:<W>:<B> B both powers of 2).
--extension=<name> Specify RoCC Extension
--extlib=<name> Shared library to load
--rbb-port=<port> Listen on <port> for remote bitbang connection
--dump-dts Print device tree string and exit
$ ./spike --extension=memtotal_rocc
couldn't find extension 'memtotal_rocc' (or library 'libmemtotal_rocc.so')