example | ||
src | ||
test | ||
.clang-format | ||
.clangd | ||
.gitignore | ||
CMakeLists.txt | ||
flake.lock | ||
flake.nix | ||
README.md | ||
rve.nix |
A simple RISC-V emulator
This is a toy emulator for RISC-V, made for educational purposes. The goal is to have a base rv32i instruction set (the bare minimum) plus a M-extension for division and multiplication. It is capable of running normal ELF binaries produced by compiling C programs with GCC. It also has support for attaching the GDB debugger to the GDB stub port, so you can debug your programs running in the virtual machine.
The code is small and compact on purpose, to make the implementation easy to understand.
Compiling and running
You'd need nix package manager in order to build the project. This is because installing cross-toolchain to compile an example project is difficult, and I don't know of other ways except nix that make it easy.
If you don't have it, install it like this:
curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix | sh -s -- install
Now, to build the emulator:
nix develop
eval "$configurePhase"
ninja
As a result you should get an executable called rve
Cross-toolchain and an example program in C
There is an example program which you can compile. It requires some custom toolchain so currently not built with CMake. To compile it:
cd example
make
As a result, you'll get an example
binary. To execute it:
./rve ../example/example
The expected output of the example program is 40320
.
Debugging programs under GDB
The virtual machine contains an implementation of GDB stub protocol. To run the program in debug mode, execute:
./rve --debug ../example/example
The program would load, and stop at first instruction. It will then prompt you to connect the debugger.
Then run riscv32-none-elf-gdb
, and in the gdb prompt, type:
target remote :1234
From now on, you can set breakpoints, examine variables, registers and memory as you would expect under GDB.