
機能的なRISC-V ISAシミュレータで、複数の拡張機能(RV32/64、V、暗号)をサポートし、インタラクティブデバッグモード、GDB統合、命令レベルのモデリングを備え、ハードウェア・ソフトウェアの共同開発やアーキテクチャ探索に利用できます。
Spikeは、RISC-V ISAシミュレーターであり、1つ以上のRISC-Vハートの機能モデルを実装しています。その名前は、アメリカ大陸横断鉄道の完成を祝うために使用された金色のスパイク(spike)に由来します。
Spikeは以下のRISC-V ISA機能をサポートしています:
プロジェクトは主に、APIが拡張されたり互換性がなくなったことを示すためにバージョン管理されます。その精神に基づき、SpikeはSemVerバージョニングスキームに従うことを目指しています。このスキームでは、後方互換性のないAPI変更が行われた場合にメジャーバージョン番号が増分され、新しいAPIが追加された場合にマイナーバージョン番号が増分され、バグが後方互換性のある方法で修正された場合にパッチバージョン番号が増分されます。
Spikeの主要な公開APIはRISC-V ISAです。現時点では、Spikeの内部へのC++インターフェースは公開APIとは見なされません。このインターフェースに対する後方互換性のない変更は、メジャーバージョン番号を増分せずに行われます。
RISCV環境変数がRISC-Vツールのインストールパスに設定されていることを前提とします。
$ apt-get install device-tree-compiler libboost-regex-dev libboost-system-dev
$ mkdir build
$ cd build
$ ../configure --prefix=$RISCV
$ make
$ [sudo] make install
システムがyumパッケージマネージャを使用している場合は、最初のステップをyum install dtcに置き換えることができます。
bash、gmake、dtcをインストールし、clangを使用します。
$ pkg_add bash gmake dtc
$ exec bash
$ export CC=cc; export CXX=c++
$ mkdir build
$ cd build
$ ../configure --prefix=$RISCV
$ gmake
$ [doas] make install
spike(ビルド手順を参照)、riscv-gnu-toolchain、riscv-pkをインストールします。
短いCプログラムを作成し、hello.cという名前を付けます。次に、それをRISC-V ELFバイナリhelloにコンパイルします:
$ riscv64-unknown-elf-gcc -o hello hello.c
これで、プロキシカーネル上でプログラムをシミュレートできます:
$ spike pk hello
シミュレーターに命令を追加するには、2つのステップが必要です:
ファイル riscv/insns/<new_instruction_name>.h に、その命令の機能的な動作を記述します。そのディレクトリ内の他の命令を出発点として調べてください。
オペコードとオペコードマスクを riscv/opcodes.h に追加します。または、riscv-opcodes パッケージに追加すると、自動的に行われます:
$ cd ../riscv-opcodes
$ vi opcodes // 新しい命令の行を追加
$ make install
命令を riscv/riscv.mk.in に追加します。そうしないと、ビルドに含まれず、不正命令として扱われます。
シミュレーターを再ビルドします。
対話型デバッグモードを起動するには、-dオプションを付けてspikeを起動します:
$ spike -d pk hello
整数レジスタの内容を表示するには(0はコア0を示します):
: reg 0 a0
浮動小数点レジスタの内容を表示するには:
: fregs 0 ft0
または:
: fregd 0 ft0
レジスタを単精度または倍精度で表示するかによって異なります。
メモリ位置の内容を表示するには(物理アドレスを16進数で):
: mem 2020
仮想アドレスでメモリの内容を表示するには(0はコア0):
: mem 0 2020
Enterキーを押すことで1命令ずつ進めることができます。また、特定の等号条件に達するまで実行することもできます:
: until pc 0 2020 (pc=2020になったら停止)
: until reg 0 mie a (レジスタmie=0xaになったら停止)
: until mem 2020 50a9907311096993 (mem[2020]=50a9907311096993になったら停止)
または、等号条件が真の間実行し続けることもできます:
: while mem 2020 50a9907311096993
次のようにして無限に実行を続けることができます:
: r
実行中いつでも(-dなしでも)、<control>-<c>で対話型デバッグモードに入ることができます。
デバッグプロンプトからシミュレーションを終了するには、<control>-<c>を押すか、次のようにします:
: q
対話型デバッグモードの代替として、gdbを使用してアタッチする方法があります。Spikeは実際のハードウェアのように振る舞おうとするため、それにはOpenOCDも必要です。次のテストプログラムを使用します:
$ cat rot13.c
#include <stdio.h>
char text[] = "Vafgehpgvba frgf jnag gb or serr!";
// Don't use the stack, because sp isn't set up.
volatile int wait = 1;
int main()
{
int i = 0;
while (text[i]) {
char lower = text[i] | 32;
if (lower >= 'a' && lower <= 'm')
text[i] += 13;
else if (lower > 'm' && lower <= 'z')
text[i] -= 13;
i++;
}
done:
printf("decoded text: %s\n", text);
}
$ riscv64-unknown-elf-gcc -g -Og --specs=semihost.specs -o rot13 rot13.c
このプログラムをデバッグするには、まずspikeを起動してOpenOCDを待ち受けるように指示します:
$ spike --rbb-port=9824 -m0x10000:0x20000 rot13
Listening for remote bitbang connection on port 9824.
...
別のシェルで、適切な設定ファイルを指定してOpenOCDを実行します:
$ cat spike.cfg
adapter driver remote_bitbang
remote_bitbang host localhost
remote_bitbang port 9824
set _CHIPNAME riscv
jtag newtap $_CHIPNAME cpu -irlen 5 -expected-id 0xdeadbeef
set _TARGETNAME $_CHIPNAME.cpu
target create $_TARGETNAME riscv -chain-position $_TARGETNAME
gdb report_data_abort enable
init
arm semihosting enable
halt
$ openocd -f spike.cfg
Open On-Chip Debugger 0.12.0
...
Info : starting gdb server for riscv.cpu on 3333
Info : Listening on port 3333 for gdb connections
riscv.cpu halted due to debug-request. Semihosting is active.
...
riscv.cpu: target state: halted
さらに別のシェルで、gdbデバッグセッションを開始します:
$ riscv64-unknown-elf-gdb rot13
...
Reading symbols from rot13...
(gdb) target extended-remote localhost:3333
...
(gdb) load
...
(gdb) set $sp=0x2fff0
(gdb) b main
Breakpoint 1 at 0x10202: file rot13.c, line 5.
(gdb) c
Continuing.
Disabling abstract command writes to CSRs.
Breakpoint 1, main () at rot13.c:5
5 {
(gdb) print text
$1 = "Vafgehpgvba frgf jnag gb or serr!"
(gdb) until done
[riscv.cpu] Found 4 triggers
main () at rot13.c:16
16 printf("decoded text: %s\n", text);
(gdb) c
Continuing.
Program received signal SIGTRAP, Trace/breakpoint trap.
0x00019ff8 in _exit ()
(gdb)
...
OpenOCDのターミナルには次のように表示されます:
...
decoded text: Instruction sets want to be free!
semihosting: *** application exited with 0 ***
riscv.cpu halted due to breakpoint. Semihosting is active.