rvsail
Formal verification of RISC-V processors using the Sail ISA model as an automatic oracle.
One command. Zero hand-written properties. 222 ops verified across 19 RTL targets.
What it does
rvsail checks that a RISC-V RTL implementation matches the official ISA specification — automatically. It uses the Sail ISA model as a golden oracle, so you don't need to write any properties by hand.
$ rvsail verify bridges/crypto_sha256.toml
RVS Bridge: crypto_sha256
RISC-V Crypto SHA256 (Zknh) -- rotation/shift ops
[Yosys] Flattening RTL to SMT2... Done (32ms)
[Z3] Checking 4 operations...
+ sha256sig0 UNSAT 17ms
+ sha256sig1 UNSAT 16ms
+ sha256sum0 UNSAT 16ms
+ sha256sum1 UNSAT 17ms
PASS: crypto_sha256 -- 4/4 UNSAT (68ms)
Install
# macOS
# Ubuntu/Debian
# Arch
Quick start
# Verify a named bridge group (resolves to all manifests for that target)
# Verify individual manifests (still works)
# Run the S-box sweep across multiple RTL targets
# Detect a known bug in Canright AES S-box (expects SAT)
Verified targets
| Target | ISA | Ops | Result |
|---|---|---|---|
| CVA6/Ariane ALU | RV64I | 15 | UNSAT |
| BOOM ALU | RV64I+Zbb | 15 | UNSAT |
| Rocket ALU | RV64I+Zbb | 18 | UNSAT |
| Xiangshan ALU | RV64I+Zba+Zbb+Zbs | 29 | UNSAT |
| IBEX ALU | RV32I | 10 | UNSAT |
| CV32E40P ALU | RV32I | 10 | UNSAT |
| PicoRV32 ALU | RV32I | 10 | UNSAT |
| SERV ALU | RV32I | 10 | UNSAT |
| SweRV ALU | RV32I | 10 | UNSAT |
| riscv-mini ALU | RV32I | 10 | UNSAT |
| Vicuna Vector ALU | RV32V | 44 | UNSAT |
| Vicuna Vector MUL | RV32V | 6 | UNSAT |
| RISC-V Crypto AES32 | RV32Zkn | 16 | UNSAT |
| RISC-V Crypto SHA256 | RV32Zknh | 4 | UNSAT |
| secworks AES S-box | AES | 1 | UNSAT |
| Canright AES S-box | AES | 1 | SAT (bug found) |
Total: 222/223 verified, 1 real bug found (coruus/canright-aes-sboxes#2)
How it works
Verilog RTL ──→ Yosys ──→ SMT2 ──┐
├──→ Z3 ──→ UNSAT (equivalent)
Sail ISA model ──→ Oracle ────────┘ or SAT (bug found)
- Yosys flattens your Verilog/SystemVerilog to an SMT2 model
- The Sail ISA oracle provides the expected behavior (zero manual effort)
- Z3 checks equivalence: UNSAT = your RTL matches the spec
Each verification target is defined by a TOML manifest — add your own core in minutes.
Adding a new target
Create a TOML manifest:
[]
= "my_alu"
= "My custom RISC-V ALU"
[]
= ["path/to/alu.v"]
= "alu"
= "prep -top alu; write_smt2 -wires {output}"
[]
= 60
[[]]
= "add"
= "specs/add_spec.smt2"
= "specs/add_constraints.smt2"
= "(assert (not (= rtl_out spec_out)))"
Then run:
Bug found
rvsail discovered a real bug in the Canright AES S-box — an undriven wire in GF_INV_4 that went unnoticed for 12 years. The bug was confirmed and reported upstream: coruus/canright-aes-sboxes#2.
Experiments (deprecated)
The experiments/ directory contains legacy Python verification scripts that have been consolidated into the Rust CLI. These scripts are preserved for reference but should not be used for new work:
experiments/vicuna_bridge/— uservsail verify --bridge vicunainsteadexperiments/crypto_bridge/— uservsail verify --bridge cryptoinsteadexperiments/crypto_bridge/sweep_sbox.py— uservsail sweepinstead
License
MIT