
Simulatore funzionale dell'ISA RISC-V che supporta molteplici estensioni (RV32/64, V, crittografia) con modalità di debug interattivo, integrazione GDB e modellazione a livello di istruzione per lo sviluppo congiunto hardware-software e l'esplorazione dell'architettura.
Spike, il simulatore ISA RISC-V, implementa un modello funzionale di uno o più hart RISC-V. Prende il nome dal chiodo d'oro usato per celebrare il completamento della ferrovia transcontinentale degli Stati Uniti.
Spike supporta le seguenti funzionalità dell'ISA RISC-V:
I progetti sono versionati principalmente per indicare quando l'API è stata estesa o resa incompatibile. In quest'ottica, Spike mira a seguire lo schema di versione SemVer, in cui i numeri di versione major vengono incrementati quando vengono apportate modifiche API non retrocompatibili; i numeri di versione minor vengono incrementati quando vengono aggiunte nuove API; e i numeri di versione patch vengono incrementati quando vengono corretti bug in modo retrocompatibile.
La principale API pubblica di Spike è l'ISA RISC-V. L'interfaccia C++ ai meccanismi interni di Spike non è considerata un'API pubblica al momento, e modifiche non retrocompatibili a questa interfaccia verranno apportate senza incrementare il numero di versione major.
Assumiamo che la variabile d'ambiente RISCV sia impostata sul percorso di installazione degli strumenti 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
Se il sistema utilizza il gestore pacchetti yum, puoi sostituire
yum install dtc per il primo passo.
Installa bash, gmake, dtc, e usa 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
Installa spike (vedi Passaggi di compilazione), riscv-gnu-toolchain, e riscv-pk.
Scrivi un breve programma C e chiamalo hello.c. Quindi, compilalo in un binario ELF RISC-V chiamato hello:
$ riscv64-unknown-elf-gcc -o hello hello.c
Ora puoi simulare il programma sul kernel proxy:
$ spike pk hello
Aggiungere un'istruzione al simulatore richiede due passi:
Descrivi il comportamento funzionale dell'istruzione nel file riscv/insns/<nome_nuova_istruzione>.h. Esamina altre istruzioni in quella directory come punto di partenza.
Aggiungi l'opcode e la maschera opcode a riscv/opcodes.h. In alternativa, aggiungilo al pacchetto riscv-opcodes, e lo farà per te:
$ cd ../riscv-opcodes
$ vi opcodes // aggiungi una riga per la nuova istruzione
$ make install
Aggiungi l'istruzione a riscv/riscv.mk.in. Altrimenti, l'istruzione non sarà inclusa nella build e verrà trattata come istruzione illegale.
Ricostruisci il simulatore.
Per avviare la modalità di debug interattivo, lancia spike con -d:
$ spike -d pk hello
Per vedere il contenuto di un registro intero (0 è per core 0):
: reg 0 a0
Per vedere il contenuto di un registro a virgola mobile:
: fregs 0 ft0
oppure:
: fregd 0 ft0
a seconda che si voglia stampare il registro come singola o doppia precisione.
Per vedere il contenuto di una locazione di memoria (indirizzo fisico in esadecimale):
: mem 2020
Per vedere il contenuto della memoria con un indirizzo virtuale (0 per core 0):
: mem 0 2020
Puoi avanzare di un'istruzione premendo il tasto invio. Puoi anche eseguire fino al raggiungimento di una uguaglianza desiderata:
: until pc 0 2020 (fermati quando pc=2020)
: until reg 0 mie a (fermati quando registro mie=0xa)
: until mem 2020 50a9907311096993 (fermati quando mem[2020]=50a9907311096993)
In alternativa, puoi eseguire finché un'uguaglianza è vera:
: while mem 2020 50a9907311096993
Puoi continuare l'esecuzione indefinitamente con:
: r
In qualsiasi momento durante l'esecuzione (anche senza -d), puoi entrare nella
modalità di debug interattivo con <control>-<c>.
Per terminare la simulazione dal prompt di debug, premi <control>-<c> oppure:
: q
Un'alternativa alla modalità di debug interattivo è collegarsi usando gdb. Poiché spike cerca di essere come hardware reale, hai bisogno anche di OpenOCD per farlo. Useremo il seguente programma di test:
$ 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
Per eseguire il debug di questo programma, prima avvia spike dicendogli di ascoltare per OpenOCD:
$ spike --rbb-port=9824 -m0x10000:0x20000 rot13
Listening for remote bitbang connection on port 9824.
...
In una shell separata esegui OpenOCD con il file di configurazione appropriato:
$ 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
In un'altra shell ancora, avvia la sessione di debug 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)
...
Sul terminale di OpenOCD avrai:
...
decoded text: Instruction sets want to be free!
semihosting: *** application exited with 0 ***
riscv.cpu halted due to breakpoint. Semihosting is active.