4db116b Check PMPs with splay-tree-backed range map
~theonlymrcat pushed to ~theonlymrcat/rivet git
Rivet is a toy RISC-V emulator I'm making as an excuse to learn Zig. It currently implements the RV64GC architecture (RV64IMAFDCZicsr_Zifencei), as well as the "Zicntr" and "Zihpm" extensions.
Floating-point support comes from Fabrice Bellard's SoftFP library, used under the MIT licence and modified to support version 2.2 of the RISC-V F/D extension specification. (I had initially tried to use the x86_64 SSE FPU directly, but discovered too late that it's a really hard thing to do, and gave up so as to not burn myself out)
This project is built using Zig 0.13.0. A nix develop
dev shell is provided with this version
of Zig.
Rivet can be built with zig build
. It requires one CLI parameter: an ELF file to load and run.
Additional options are documented in the help text (accessed by running without passing any args).
zig build run -- path/to/executable
Rivet comes with a rudimentary debugger. Passing the --debug
flag on the command line will show
a GDB-like CLI interface where you can control and inspect the state of the emulator. Currently
implemented commands include:
run
: Continue execution until the next breakpoint or watchpointstep
: Step into; one instructionnext
: Step over; one instructionbreak <symbol_or_address>
: Set a breakpoint at the given symbol (as loaded from the ELF) or
address (in hexadecimal)watch <line_no>
: Set a watchpoint at the given line number of a riscof signaturewatch <reg_name>=<value>
: Set a watchpoint for the given register to equal the given valuereg <name>
: Print the current contents of the given registercsr <name>[=<value>]
: Print the current contents of the given CSR (and optionally set it to a
given value)trace <event>
: Enable trace printing for the chosen event, which can be one of the following:
exec
: Prints the program counter and the instruction being executed every steptrap
: Prints the exception code and target privilege whenever an exception or interrupt occursjump
: Prints the previous and next program counter every jump instruction or trapcall
: Prints function symbol names as they are called, and a0
when c.ret
is executedvmem
: Prints the result of every virtual memory translationelf
: Prints information about the loaded ELF filesRivet can be tested against the tests in riscv-tests
, which are included as a submodule in this
repository.
git submodule update --init
# Individually:
make -C riscv-tests/isa rv64ui # For ISA tests
make -C riscv-tests/isa rv64um # For M tests
make -C riscv-tests/isa rv64ua # For A tests
make -C riscv-tests/isa rv64uf # For F tests
make -C riscv-tests/isa rv64ud # For D tests
make -C riscv-tests/isa rv64uc # For C tests
make -C riscv-tests/isa rv64mi # For privilege tests
make -C riscv-tests/isa rv64si # For supervisor tests
# Or just:
make -C riscv-tests/isa # For all tests
The built ELF files can then be run with rivet, which will exit with code 0 if all tests passed, or a code indicating which test failed.
The following find
command can be used to run tests in bulk, printing the exit code of each
test. (Change the -name
parameter to choose different tests to run)
zig build
find riscv-tests/isa -executable -name 'rv64*' -exec sh -c 'zig-out/bin/rivet "{}" 2>/dev/null; printf "{}: %s\n" $?' \;
The nix develop
dev shell has a riscv-test
script which runs the above, but with nicer formatting
riscv-test rv64
RISCOF is an architectural test framework that allows RISC-V targets to be tested against a standard
reference model. More importantly, it provides a more comprehensive set of ISA tests than the old
riscv-tests
repo.
Documentation for running these tests is available in the riscof/ directory of this repository.