
機能的なRISC-V ISAシミュレータで、複数の拡張機能(RV32/64、V、暗号)をサポートし、インタラクティブデバッグモード、GDB統合、命令レベルのモデリングを備え、ハードウェア・ソフトウェアの共同開発やアーキテクチャ探索に利用できます。
SpikeはRISC-V ISAシミュレータであり、1つ以上のRISC-Vハートの機能モデルを実装しています。その名前は、アメリカ大陸横断鉄道の完成を祝うために打ち込まれた黄金の釘に由来しています。
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
$ apt-get install libboost-regex-dev libboost-system-dev
$ mkdir build
$ cd build
$ ../configure --prefix=$RISCV
$ make
$ [sudo] make install
システムがyumパッケージマネージャを使用している場合、最初のステップをyum install dtcに置き換えることができます。
対話型デバッグモードでソケット経由のコマンドI/Oを使用する必要がない場合は、2番目のステップをスキップできます。
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と名付けます。次に、それをhelloという名前のRISC-V ELFバイナリにコンパイルします:
$ 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 // add a line for the new instruction
$ 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 (stop when pc=2020)
: until reg 0 mie a (stop when register mie=0xa)
: until mem 2020 50a9907311096993 (stop when 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
このプログラムをデバッグするには、まずOpenOCDを待ち受けるようにspikeを実行します:
$ 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.