
Функциональный симулятор ISA RISC-V, поддерживающий множество расширений (RV32/64, V, криптография) с интерактивным режимом отладки, интеграцией GDB и моделированием на уровне инструкций для совместной разработки аппаратного и программного обеспечения и исследования архитектуры.
Spike, симулятор архитектуры RISC-V ISA, реализует функциональную модель одного или нескольких ядер RISC-V. Он назван в честь золотого костыля, ознаменовавшего завершение строительства трансконтинентальной железной дороги США.
Spike поддерживает следующие возможности архитектуры RISC-V:
Проекты версионируются в первую очередь для указания того, когда API был расширен или стал несовместимым. В этом духе Spike стремится следовать схеме версионирования SemVer, в которой номера основных версий увеличиваются, когда вносятся обратно несовместимые изменения API; номера минорных версий увеличиваются, когда добавляются новые API; номера патч-версий увеличиваются, когда исправляются ошибки обратно-совместимым образом.
Основной публичный API Spike — это архитектура RISC-V ISA. Интерфейс C++ к внутренностям Spike в настоящее время не считается публичным 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
Добавление инструкции в симулятор состоит из двух шагов:
Опишите функциональное поведение инструкции в файле riscv/insns/<new_instruction_name>.h. Изучите другие инструкции в этом каталоге в качестве отправной точки.
Добавьте код операции и маску кода операции в riscv/opcodes.h. В качестве альтернативы добавьте их в пакет riscv-opcodes, и он сделает это за вас:
$ cd ../riscv-opcodes
$ vi opcodes // добавьте строку для новой инструкции
$ make install
Добавьте инструкцию в riscv/riscv.mk.in. В противном случае инструкция не будет включена в сборку и будет рассматриваться как недопустимая.
Пересоберите симулятор.
Чтобы вызвать интерактивный режим отладки, запустите spike с флагом -d:
$ spike -d pk hello
Чтобы просмотреть содержимое целочисленного регистра (0 — для ядра 0):
: reg 0 a0
Чтобы просмотреть содержимое регистра с плавающей запятой:
: fregs 0 ft0
или:
: fregd 0 ft0
в зависимости от того, хотите ли вы вывести регистр как одинарной или двойной точности.
Чтобы просмотреть содержимое ячейки памяти (физический адрес в шестнадцатеричном формате):
: mem 2020
Чтобы просмотреть содержимое памяти с виртуальным адресом (0 — для ядра 0):
: mem 0 2020
Вы можете продвинуться на одну инструкцию, нажав клавишу Enter. Вы также можете выполнять инструкции до достижения желаемого равенства:
: 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.