FPGA開発日記

FPGAというより、コンピュータアーキテクチャかもね! カテゴリ別記事インデックス https://sites.google.com/site/fpgadevelopindex/

RISC-Vの命令セットシミュレータSpikeでRoCCインタフェースを実装する

f:id:msyksphinz:20170201002310j:plain

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.ccrocc_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')