Whisc-V: A Tiny RISC-V Interpreter

Have you ever felt the need to emulate RISC-V binaries on the most resource-constrained of platforms? Me neither, up until a few months ago. To help with another project, I decided to write a tiny RISC-V interpreter. It was especially timely as I was also taking a hardware design course where we implemented a RISC-V32IM core, so the ISA was fresh in my mind.

Features

The interpreter emulates real RISC-V binaries; it takes a stripped sequence of real RV32I machine code and disassembles, parses, and executes it, illustrating register file state and memory accesses as it runs. The most notable feature is that the main interpreter core is entirely stateless; the wrapper program is charged with storing processor state, which it simply passes to the interpreter, along with a pointer to a struct in which it will store the next execution state.

Therefore, a peculiar and quite useful use case emerges; the wrapper program can hold a circular buffer of execution state, allowing for arbitrary “unwinding” of execution history. In fact, this was the main selling point of the interpreter for the project I built it for; the user could quite literally “rewind time” by spinning a knob, watching the execution history roll backwards in realtime.

The entire thing is written in bare metal, portable C. This results in very efficient performance, a tiny executable size, and the ability to run the interpreter on pretty much any platform known to man. Our team ended up running the interpreter bare-metal on an STM32 microcontroller.

Why?

Why? Excellent question, but sometimes we do things just to say we can. It’s also quite the sight to see an STM32 running RISC-V binaries.

Clone the repository now, and emulate RV32I on all your favorite tiny devices today.