cnlohr/mini-rv32ima logo

cnlohr/mini-rv32ima

Free

A tiny C header-only risc-v emulator.

FreeFree tier
Type
Open Source

About cnlohr/mini-rv32ima

mini-rv32ima is a single-file-header RISC-V emulator (rv32ima) written in C, in the STB style. It implements the rv32ima instruction set with Zifencei and Zicsr extensions, partial supervisor mode, CLINT, and MMIO. The core emulator is about 400 lines of code with no dependencies (not even libc), making it trivially embeddable. It is performant, achieving ~450 CoreMark on a laptop (about half the speed of QEMU), and compiles to an ~18kB executable when paired with the included demo wrapper. The demo wrapper adds CLI, SYSCON, UART, DTB, and kernel image loading in about 250 lines of code. Designed to run Linux on RV32-NOMMU systems, it also supports running bare-metal programs and applications like Doom. The emulator is human-readable, extensible, and intentionally incomplete—it omits parts of the RISC-V spec not used by Linux to keep the code small and simple.

Key Features

Single-file-header (mini-rv32ima.h) in STB style, ~400 lines of actual code
No dependencies: does not rely on libc or any external libraries
Extensible: easy to add CSRs, instructions, MMIO, etc.
Performant: ~450 CoreMark on laptop, approximately half QEMU speed
Human-readable and written in basic C code
Demo wrapper (~250 lines) implements CLI, SYSCON, UART, DTB, and kernel image loading
Compiles to ~18kB executable when combined with demo wrapper
Can run Linux, applications, and bare-metal code (e.g., Doom)
Supports RV32-NOMMU and runs on Windows, Linux, and potentially pixel shaders

Pros & Cons

Pros
  • Extremely small and self-contained (single header, no dependencies)
  • Fast enough for practical use (half QEMU speed)
  • Easy to understand, modify, and extend due to simple C code
  • Cross-platform: runs on Windows, Linux, and can be embedded anywhere
  • Free and open source under a permissive license
  • Active development with community support
Cons
  • Incomplete implementation: omits many parts of the RISC-V spec not used by Linux
  • Zifencei and RV32A are stubbed, limiting multiprocessor support
  • No MMU (Memory Management Unit), so not suitable for full RISC-V environments
  • Only supports 32-bit RISC-V (rv32), not rv64
  • Not intended for production use; focused on simplicity and educational purposes

Best For

Embedded Linux development on RV32-NOMMU systems (e.g., ESP32-C3)Learning about RISC-V architecture and emulator designPorting the emulator to unconventional platforms (e.g., pixel shaders)Education in assembly language and low-level system conceptsRunning bare-metal RISC-V programs and games like DoomDeveloping and testing RISC-V kernel images without hardware

FAQ

Why not rv64?
Because the author wants to eventually run the emulator in a pixel shader, which is easier with 32-bit.