~theonlymrcat/rivet

Toy RV64I emulator written in Zig

78f617a Deduplicate virtqueue handling into dedicated struct

11 days ago

c1c643a Reduce the number of PMP checks in instruction fetch

26 days ago

#rivet

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)

#Building and running

This project is built using Zig 0.13.0. It also requires a recent version of dtc (Device Tree Compiler) at build-time. A nix develop dev shell is provided with all the required dependencies.

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

#riscv-tests

Rivet 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

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.

#dqib_riscv64-virt

My final goal is to be able to run some sort of Linux system on rivet, so I'm testing against images generated by the Debian Quick Image Baker.

The following steps assume you have built OpenSBI with a U-Boot payload and that $OPENSBI_UBOOT points to the output folder containing fw_payload.elf. The nix develop shell provides this, but it can otherwise be made by installing the u-boot-qemu package (Debian), and compiling OpenSBI with the PLATFORM=generic FW_PAYLOAD_PATH=/usr/lib/u-boot/qemu-riscv64_smode/uboot.elf make flags. (I haven't tested this though, sorry. Nix is a lot more convenient)

  1. Download a riscv64-virt image, and extract it into this repo at dqib_riscv64-virt/.

  2. Convert the QCow2 image into a raw image using qemu-img:

    qemu-img convert -f qcow2 -O raw dqib_riscv64-virt/image.qcow2 dqib_riscv64-virt/image.img
    
  3. Run Rivet on the converted image:

    zig build run -Doptimize=ReleaseSafe -- $OPENSBI_UBOOT/fw_payload.elf --blk0 dqib_riscv64-virt/image.img