
Simulador funcional del ISA RISC-V que admite múltiples extensiones (RV32/64, V, criptografía) con modo de depuración interactiva, integración con GDB y modelado a nivel de instrucción para el codesarrollo de hardware-software y la exploración de arquitecturas.
Spike, el simulador de ISA RISC-V, implementa un modelo funcional de uno o más harts RISC-V. Recibe su nombre del clavo de oro (golden spike) utilizado para celebrar la finalización del ferrocarril transcontinental de EE. UU.
Spike soporta las siguientes características de la ISA RISC-V:
Los proyectos se versionan principalmente para indicar cuándo la API se ha ampliado o se ha vuelto incompatible. En ese espíritu, Spike pretende seguir el esquema de versionado SemVer, en el cual los números de versión mayor se incrementan cuando se realizan cambios incompatibles hacia atrás en la API; los números de versión menor se incrementan cuando se añaden nuevas APIs; y los números de versión de parche se incrementan cuando se corrigen errores de manera compatible hacia atrás.
La API pública principal de Spike es la ISA RISC-V. La interfaz C++ de los internos de Spike no se considera una API pública en este momento, y se realizarán cambios incompatibles hacia atrás en esta interfaz sin incrementar el número de versión mayor.
Asumimos que la variable de entorno RISCV está configurada con la ruta de instalación de las herramientas 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
Si su sistema usa el gestor de paquetes yum, puede sustituir yum install dtc por el primer paso.
Instale bash, gmake, dtc y use 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
Instale spike (consulte Pasos de compilación), riscv-gnu-toolchain y riscv-pk.
Escriba un programa C corto y asígnele el nombre hello.c. Luego, compílelo en un binario ELF RISC-V llamado hello:
$ riscv64-unknown-elf-gcc -o hello hello.c
Ahora puede simular el programa sobre el kernel proxy:
$ spike pk hello
Agregar una instrucción al simulador requiere dos pasos:
Describa el comportamiento funcional de la instrucción en el archivo riscv/insns/<nombre_de_la_nueva_instrucción>.h. Examine otras instrucciones en ese directorio como punto de partida.
Agregue el código de operación y la máscara de código de operación a riscv/opcodes.h. Alternativamente, agréguelo al paquete riscv-opcodes, y lo hará por usted:
$ cd ../riscv-opcodes
$ vi opcodes // añada una línea para la nueva instrucción
$ make install
Agregue la instrucción a riscv/riscv.mk.in. De lo contrario, la instrucción no se incluirá en la compilación y se tratará como una instrucción ilegal.
Vuelva a compilar el simulador.
Para invocar el modo de depuración interactiva, lance spike con -d:
$ spike -d pk hello
Para ver el contenido de un registro entero (0 es para el núcleo 0):
: reg 0 a0
Para ver el contenido de un registro de punto flotante:
: fregs 0 ft0
o:
: fregd 0 ft0
dependiendo de si desea imprimir el registro como precisión simple o doble.
Para ver el contenido de una ubicación de memoria (dirección física en hexadecimal):
: mem 2020
Para ver el contenido de la memoria con una dirección virtual (0 para el núcleo 0):
: mem 0 2020
Puede avanzar una instrucción presionando la tecla Enter. También puede ejecutar hasta alcanzar una igualdad deseada:
: until pc 0 2020 (detenerse cuando pc=2020)
: until reg 0 mie a (detenerse cuando el registro mie=0xa)
: until mem 2020 50a9907311096993 (detenerse cuando mem[2020]=50a9907311096993)
Alternativamente, puede ejecutar mientras una igualdad sea verdadera:
: while mem 2020 50a9907311096993
Puede continuar la ejecución indefinidamente mediante:
: r
En cualquier punto durante la ejecución (incluso sin -d), puede ingresar al
modo de depuración interactiva con <control>-<c>.
Para finalizar la simulación desde el símbolo del sistema de depuración, presione <control>-<c> o:
: q
Una alternativa al modo de depuración interactiva es conectarse usando gdb. Debido a que spike intenta ser como hardware real, también necesita OpenOCD para hacerlo. Usaremos el siguiente programa de prueba:
$ 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
Para depurar este programa, primero ejecute spike indicándole que escuche a OpenOCD:
$ spike --rbb-port=9824 -m0x10000:0x20000 rot13
Listening for remote bitbang connection on port 9824.
...
En una terminal separada ejecute OpenOCD con el archivo de configuración apropiado:
$ 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
En otra terminal más, inicie su sesión de depuración con 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)
...
En la terminal de OpenOCD tendrá:
...
decoded text: Instruction sets want to be free!
semihosting: *** application exited with 0 ***
riscv.cpu halted due to breakpoint. Semihosting is active.