Config-driven build and test tooling for bare-metal RISC-V or virtual
hardware simulation: the same compiled test runs either against real
hardware over JTAG or against cocotb/GHDL simulation; results
can be verified against Spike-generated or checked-in golden references.
Organized as one module per responsibility, each with its own
__config__.py of defaults; a consuming project supplies its own
config.yaml, which overrides these defaults. See
docs/configuration.md for the full reference.
| Module | Responsibility | Doc |
|---|---|---|
compiler |
.c/.S -> .elf/.bin, header parsing (RV32_EXT/RV32_TEST_KIND/RV32_TIMEOUT_S) |
docs/modules/compiler.md |
bin_to_image |
.bin -> .mif/.hex (memory-image formats, no compiler involved) | docs/modules/bin_to_image.md |
c_to_asm |
.c -> human-readable RISC-V assembly (gcc -S), for inspecting codegen |
docs/modules/c_to_asm.md |
boot_rom |
Builds the fixed, shared bootloader, once, reused across every test | docs/modules/boot_rom.md |
jtag |
Live JTAG cable detection, generic .tcl runner |
docs/modules/jtag.md |
mem_edit |
Generic In-System Memory Content Editor primitives (read/write word, write-full, dump) | docs/modules/mem_edit.md |
rom_writer |
JTAG-write a ROM image without reprogramming | docs/modules/rom_writer.md |
ram_zero |
JTAG-zero the whole RAM without reprogramming | docs/modules/ram_zero.md |
ram_dump |
JTAG-dump the whole RAM to a .mif |
docs/modules/ram_dump.md |
mailbox |
PASS/FAIL mailbox read + restart "go flag" pulse | docs/modules/mailbox.md |
quartus_program |
Full recompile + quartus_pgm (the slow "base" path) |
docs/modules/quartus_program.md |
mem_validator |
Compare a RAM dump against a golden JSON | docs/modules/mem_validator.md |
golden_generator |
Generate a golden JSON dynamically by running an ELF under Spike | docs/modules/golden_generator.md |
orchestrator |
Composes the above into a full real-hardware test-suite run, or a clock frequency sweep to find Fmax | docs/modules/orchestrator.md |
sim_runner |
Drives cocotb/GHDL simulation: the sim-side counterpart to orchestrator (needs the sim extra) |
docs/modules/sim_runner.md |
certify |
Builds and runs the ACT4 architectural certification suite under cocotb/GHDL | docs/modules/certify.md |
vhdl_sort |
Topologically sort VHDL sources by entity/package dependency, for GHDL -a |
docs/modules/vhdl_sort.md |
freq_sweep |
Rewrite a PLL source's clock frequency/phase offsets: the mechanism orchestrator's frequency sweep edits with |
docs/modules/freq_sweep.md |
run_log |
Rotates and tees a run's full console output into a persistent per-kind log history | docs/modules/run_log.md |
Every module in the table above owns exactly one job. When adding or changing code:
- New functionality that doesn't fit an existing module's responsibility gets its own new module; don't bolt it onto the nearest unrelated one just because it's convenient to import from there.
- Logic needed by two or more modules gets factored into its own module (or a small private helper shared via an explicit import), not copy-pasted into each caller. Duplication between modules is how a fix applied to one copy silently leaves the other one broken, with nothing at either call site hinting that a second copy even exists.
- If you're unsure whether something is a new responsibility or fits an existing one, prefer the smaller, more specific module: merging two modules later is easy; un-tangling a module that grew several unrelated jobs is not.
| Path | Points at | Why |
|---|---|---|
vendor/riscv-gnu-toolchain |
riscv-collab/riscv-gnu-toolchain | The GCC cross-toolchain compiler builds test programs with |
vendor/riscv-isa-sim |
riscv-software-src/riscv-isa-sim (Spike, RISC-V International's reference simulator) | Golden-reference source for golden_generator (docs) |
Neither needs to be checked out for normal use. On an org workstation set
up per insper-riscv/Infra's
SPIKE_SETUP.md, a prebuilt GCC toolchain and a prebuilt Spike already
live in a shared cache (/opt/riscv-foundation), so neither submodule
needs building there at all. Off that kind of workstation, compiler
still just expects a prebuilt GCC toolchain on PATH from somewhere
(building vendor/riscv-gnu-toolchain from source takes tens of minutes),
and golden_generator can point RISCV_ISA_SIM_DIR at any already-built
Spike instead of building vendor/riscv-isa-sim locally (see
docs/generating-a-golden.md). Only
initialize one of these submodules if you actually want to build it from
source:
git submodule update --init vendor/riscv-gnu-toolchain
git submodule update --init vendor/riscv-isa-sim- Configuration reference
- Creating a test in C
- Creating a test in ASM
- Generating a golden JSON via Spike
- Finding Fmax (clock frequency sweep)
- Creating a GitHub Actions workflow per task
uv sync
uv run riscv-tools --config /path/to/project/config.yaml compile --emit mif
uv run riscv-tools --config /path/to/project/config.yaml compile --emit asm
uv run riscv-tools --config /path/to/project/config.yaml run
uv run riscv-tools --config /path/to/project/config.yaml generate-golden \
build/real/some_test.elf --march rv32im --start 0x10 --end 0x20 --out golden/some_test.json
# Simulation (needs the "sim" extra: cocotb + cocotb-tools, and GHDL on PATH)
uv sync --extra sim
uv run riscv-tools --config /path/to/project/config.yaml compile --emit hex
uv run riscv-tools --config /path/to/project/config.yaml simSee riscv-tools --help for the full subcommand list (write-rom,
zero-ram, dump-ram, program, mailbox read|pulse, generate-header,
generate-golden, run, sim, vhdl-sort, freq-sweep).
# vhdl-sort needs no --config; pure file-content analysis, e.g. wired
# into a Makefile's own VHDL-syntax-check target:
uv run riscv-tools vhdl-sort src/**/*.vhd
# freq-sweep: find Fmax by editing the PLL and doing a full
# recompile+reprogram+RAM-compare at each candidate frequency. See
# docs/finding-fmax.md.
uv run riscv-tools --config /path/to/project/config.yaml freq-sweep \
build/real/full.mif --golden golden/full.json --start 1 --stop 30 --step 2
uv run riscv-tools --config /path/to/project/config.yaml freq-sweep \
build/real/full.mif --golden golden/full.json --binary --low 1 --high 50uv sync --group dev
uv run pytestCopyright 2026 Insper. Licensed under the Apache License, Version 2.0.