ProcessorCI Verification implements NTV, the non-intrusive trace-based verification flow for RISC-V processors. It compares a processor-under-test trace against a reference trace generated by Spike, the RISC-V ISA simulator.
This repository is the verification component of ProcessorCI. It consumes a ProcessorCI-compatible processor wrapper, register-file labels, execution flags, and a RISC-V ELF program, then produces traces and mismatch reports.
exec_trace.py Runs Cocotb simulation and captures fragmented DUT traces
spike_trace.py Runs the Spike fork and captures reference traces
compare_traces.py Builds the final DUT trace and compares it with Spike
config_loader.py Shared JSON/config helpers
elf_reader.py ELF loading helper used by the simulation path
example/ Small tinyriscv example with config, wrapper, and docs
spike_fork/ Forked Spike source used for trace generation
docs/ Maintenance and workflow notes
requirements.txt Python dependencies
git clone https://github.com/LSC-Unicamp/processor_ci_verification.git
cd processor_ci_verification
python3 -m venv env
. env/bin/activate
pip install -r requirements.txtThe full flow also needs a working RTL simulator through Cocotb, a RISC-V
toolchain for ELF programs, and the Spike fork built from spike_fork/.
The verification flow uses:
- A RISC-V ELF program or a directory of ELF programs.
- A processor makefile for Cocotb simulation.
- A register-file JSON file generated or curated for the processor.
- Optional NTV flags JSON for manual trace behavior.
- An output directory for generated traces and comparison results.
The example/ directory contains a small tinyriscv setup that demonstrates all
required files.
Generate the DUT execution trace:
python3 exec_trace.py \
-m example/tinyriscv.mk \
-e example/sanity_check.elf \
-r example/tinyriscv_reg_file.json \
-f example/tinyriscv_manual_ntv_flags.json \
-o output/ \
-vGenerate the Spike reference trace:
python3 spike_trace.py \
-e example/sanity_check.elf \
-o output/Compare the traces:
python3 compare_traces.py \
-s output/sanity_check.spike.json \
-d output/sanity_check.fragmented.json \
-o output/For a guided example, see example/example.md.
exec_trace.pyruns the processor through Cocotb and captures fragmented observations such as fetches, register commits, and memory accesses.spike_trace.pyruns the same program on the Spike fork and produces the reference architectural trace.compare_traces.pyuses the Spike trace to assemble the final expected DUT sequence and reports mismatches.
Fragmented DUT traces look like:
{
"comment": "Trace for sanity_check.elf on tinyriscv",
"fetches": [[0, 5244307]],
"regfile_commits": [[11, 5]],
"memory_accesses": [[60, 5]]
}Keep the Spike fork boundary explicit. Project scripts should live at the root;
forked simulator changes should stay under spike_fork/ and be documented in
docs/README.md.
Use python3 <script>.py --help to check CLI behavior. Add small examples under
example/ when a new trace input or output format is introduced.
Issues and pull requests are welcome. Include a minimal ELF/config example for new verification behavior whenever possible.
See repository license files and the upstream license files inside spike_fork/.