Bitme: RISC-V Machine Code BMC
- Bitme is a bounded-model checking engine for RISC-V that translates integer programs into BTOR2 models and interleaves decision-diagram propagation with SMT solving.
- It employs specialized decision-diagram trackers, namely ROABVDD and CFLOBVDD, to pre-propagate symbolic input domains and improve performance compared to SMT-only approaches.
- Empirical results on microbenchmarks show up to 16/18 successful verifications, indicating a significant efficiency boost over traditional pure SMT methods.
Searching arXiv for papers on Bitme, rotor, and CFLOBDDs. Bitme is a bounded-model-checking engine for the BTOR2 models that rotor produces from RISC-V integer machine code. It is designed to push bit-precise symbolic execution down to unmodified RISC-V machine code and to exploit decision-diagram technology—specifically Algebraic Decision Diagrams (ADDs) and Context-Free-Language Ordered Binary Decision Diagrams (CFLOBDDs)—to pre-propagate as much of the input space as possible before invoking an SMT solver. In the formulation reported for bitme, the tool unrolls the BTOR2 transition relation breadth-first, tracks symbolic input bytes through machine state with a tracker data structure, and falls back to Z3 or Bitwuzla only when domain propagation can no longer make progress (Bolotina et al., 13 Jul 2025).
1. Definition and scope
Bitme operates on BTOR2 transition systems produced by rotor from RISC-V integer programs. Its stated focus is machine-code-level reasoning rather than reasoning at source-code or intermediate-representation level. The modeling target is RISC-V restricted to integer arithmetic, motivated by the observation that RISC-V integer semantics is essentially equivalent to established SMT semantics over bitvectors and arrays of bitvectors (Bolotina et al., 13 Jul 2025).
The tool’s purpose is bounded model checking. In this setting, symbolic execution is coupled to explicit model generation, and state exploration is controlled by bounded unrolling of the transition relation. The central design choice is not merely to encode the whole problem directly for SMT solving, but to interleave domain propagation in decision diagrams with residual SMT reasoning. This suggests a workflow in which symbolic input is simplified aggressively before solver invocation, thereby reducing the effective burden of state explosion (Bolotina et al., 13 Jul 2025).
2. Execution model and transition-system semantics
Rotor translates a RISC-V integer program into a BTOR2 transition system
where is the machine state, is the set of initial states, is a purely combinational next-state function over bitvectors and arrays, is a Boolean condition of bad states, and is the conjunction of good constraints (Bolotina et al., 13 Jul 2025).
The machine state is specified as consisting of the PC, 32 GPRs, four memory segments—code, data, heap, stack—each as an array of bitvectors, plus some kernel counters for syscalls. Initial states may be constant-initialized or left symbolic if flagged as uninitialized by rotor. The transition function implements fetch–decode–execute–syscall. Bad states include conditions such as division-by-zero, invalid instruction, and nonzero exit code, while good constraints include conditions such as no segfault up to that point (Bolotina et al., 13 Jul 2025).
For bounded model checking up to bound , rotor can unroll the transition relation and emit the formula
Bitme reads the original unrolled-on-the-fly BTOR2 model implicitly rather than requiring a separately materialized large formula (Bolotina et al., 13 Jul 2025).
3. Decision-diagram representations
Bitme implements two principal tracker families: ADD/ROABVDD and CFLOBDD/CFLOBVDD. In its simplest form, an ADD represents a function
by a rooted directed acyclic graph with Boolean-variable tests at non-terminal nodes and integer labels or weights associated with edges and terminals. The value of the function is obtained by traversing the path induced by an input assignment and multiplying and summing edge weights until reaching a terminal (Bolotina et al., 13 Jul 2025).
Bitme generalizes this scheme to byte-granularity inputs in a Reduced Ordered Algebraic Bitvector Decision Diagram (ROABVDD). Each input byte is treated as a single variable with domain , and internally subsets of the byte domain are represented by 256-bit masks so that unions and intersections of pre-images become bitwise operations in constant machine-word cost. The reported motivation is that many arithmetic expressions over bitvectors collapse to small diagrams, although ROABVDDs may still blow up under poor input ordering or genuinely exponential structure (Bolotina et al., 13 Jul 2025).
CFLOBDDs are presented as a representation capable of capturing classes of functions with nested, repetition-friendly structure that are exponentially large for OBDDs but polynomial for grammatically structured diagrams. Rather than a flat variable ordering, a CFLOBDD imposes a hierarchy of decompositions guided by a small context-free grammar. In bitme, the byte-granularity variant is CFLOBVDD, in which each terminal carries a bitvector of width up to 64 bits, each non-terminal consumes 1, 2, 4, or 8 input bytes at a time, and the combinator is either 0, 1, 2, 3, or the ite operator (Bolotina et al., 13 Jul 2025).
A key theorem cited in the bitme work is from Zhi and Sistla’s “Polynomial CFLOBDDs,” which is described as showing that for a wide class of regularly structured functions, CFLOBDDs can be of size 4, whereas any OBDD representation would be of size 5. In the reported implementation, CFLOBVDDs are up to an order of magnitude more compact than ROABVDDs on bit-reversal and multi-input tests, with a small constant in combination overhead (Bolotina et al., 13 Jul 2025). A plausible implication is that bitme treats decision-diagram choice not as a purely theoretical matter, but as a practical tuning parameter that trades raw speed against memory scaling.
4. Domain propagation and SMT fallback
The central operational mechanism in bitme is domain propagation via trackers. For each state bitvector 6 at time 7, bitme maintains a tracker
8
where 9 is the Cartesian product of all still-unpropagated input byte domains and 0 is the set of bitvector values for 1 (Bolotina et al., 13 Jul 2025).
Initialization sets each input-byte tracker to the identity on its domain and each constant-initialized state variable to a constant-valued tracker. On each unrolling step, if a next-state definition has the form 2, bitme computes
3
If the operation can be performed entirely in the BDD algebra, the new tracker is recorded and the SMT solver is not touched. If the operation is outside the tractable domain—for example, an array read with a large index domain, or a case in which the resulting BDD would blow up—bitme stops propagation for the relevant variables, introduces fresh symbolic BTOR2 variables, emits corresponding residual constraints, and continues in SMT (Bolotina et al., 13 Jul 2025).
The solver heuristic is correspondingly direct. Bitme first attempts propagation in the BDD algebra. If applying TRACKER_APPLY would cause a BDD with more than 4 nodes, with default 5, or if the operation is an array read or write on an unflattened array, then it concretizes all input bytes involved in that operation, emits the pending BTOR2 expressions as a single SMT query, and invokes Z3 or Bitwuzla on the residual assertions in the QF_BV+Arrays fragment (Bolotina et al., 13 Jul 2025).
The description characterizes this process as generalizing constant propagation to domain propagation. Residual constraints passed to the SMT solver are therefore smaller, and many safety-property checks are reduced to lookups in a decision diagram rather than large SAT queries. This suggests that bitme’s novelty lies less in replacing SMT outright than in changing the point at which SMT becomes necessary (Bolotina et al., 13 Jul 2025).
5. Empirical behavior and scalability
The reported experiments use an 18-program microbenchmark suite. Each sample reads at most 6 input bytes, implements a simple safety check such as division-by-zero or out-of-bounds read, and is bounded to 2048 instructions. Experiments were run on a 16-core Ryzen 9 with 96 GB RAM under Linux, using Z3 4.12.1 and Bitwuzla 3.9.0, with a 900 s timeout (Bolotina et al., 13 Jul 2025).
The main empirical comparison concerns completion counts under different propagation regimes.
| Method | Completed |
|---|---|
| SMT alone (–propagate 0) | 2/18 |
| constant propagation only | 2/18 |
| ROABVDD domain propagation | 16/18 |
| CFLOBVDD domain propagation | 16/18 |
The associated runtime distribution is summarized as showing that SMT and constant propagation stall at 2 programs, while BDD propagation solves 5 in under 10 s, 12 in under 50 s, and 16 in under 200 s (Bolotina et al., 13 Jul 2025). Within the reported benchmark envelope, this indicates that domain propagation materially alters the tractable portion of the workload.
Array unfolding is identified as another important variable. Because array reads are not yet propagated in BDD form, the effect of the --array parameter was measured by flattening arrays up to size 6. Without unfolding, neither ROABVDD nor CFLOBVDD completed more than the trivial two programs; with --array 8, both completed 16/18. The report states that this demonstrates flattening small arrays is essential for domain propagation but can hurt pure SMT solving (Bolotina et al., 13 Jul 2025).
Model complexity was also varied by comparing full RISC-V ISA models against the RISC-U subset via --riscuonly. SMT runtimes doubled on full-ISA models, while ROABVDD and CFLOBVDD runtimes rose by only 30%. This suggests that propagation scales more gently than pure SMT as model complexity increases (Bolotina et al., 13 Jul 2025).
6. ROABVDD versus CFLOBVDD
To study the effect of structured reuse, two parametric benchmark families were introduced: bitreversal-X.c, which reads one byte and bit-reverses its top 7 bits, and multizero-X.c, which reads 8 bytes and requires all to be 0 (Bolotina et al., 13 Jul 2025).
For bitreversal-X, the reported runtime and memory figures are:
| X | ROABVDD time / mem | CFLOBVDD time / mem |
|---|---|---|
| 2 | 15.4 s / 995 MiB | 20.8 s / 600 MiB |
| 3 | 45.0 s / 2182 MiB | 50.8 s / 809 MiB |
| 4 | 71.1 s / 3404 MiB | 80.2 s / 1050 MiB |
| 5 | 104.5 s / 4797 MiB | 115.5 s / 1338 MiB |
| 6 | 118.7 s / 5469 MiB | 136.7 s / 1593 MiB |
For multizero-X, the corresponding figures are:
| X | ROABVDD time / mem | CFLOBVDD time / mem |
|---|---|---|
| 2 | 16.0 s / 1056 MiB | 22.2 s / 613 MiB |
| 3 | 22.5 s / 1344 MiB | 31.7 s / 692 MiB |
| 4 | 28.0 s / 1551 MiB | 38.5 s / 753 MiB |
| 5 | 51.1 s / 2619 MiB | 61.3 s / 897 MiB |
| 6 | 76.4 s / 3749 MiB | 86.6 s / 1044 MiB |
The accompanying interpretation in the source is that CFLOBVDD uses roughly 40% less memory and scales linearly in 9, whereas ROABVDD memory and time grow super-linearly; in absolute time, ROABVDD remains faster by approximately 20% (Bolotina et al., 13 Jul 2025). This establishes a practical asymmetry between the two tracker families: ROABVDD provides the best raw speed, while CFLOBVDD offers superior memory behavior on highly regular or deeply nested input structures.
7. Significance, limitations, and research direction
Bitme is presented as evidence that bounded model checking of bit-precise RISC-V machine code can be extended substantially by interleaving BDD-based domain propagation with SMT solving. The reported conclusion is that this approach pushes bounded model checking an order of magnitude beyond what Z3 or Bitwuzla alone can achieve on the studied microbenchmarks (Bolotina et al., 13 Jul 2025).
The design also has clearly stated practical constraints. Array reads are not yet propagated in BDD form, making array unfolding essential in the reported experiments. Solver fallback remains necessary whenever a BDD would exceed the node cap or the operation lies outside the tractable bitvector-algebra fragment. The current modeling target is RISC-V restricted to integer arithmetic, and future work is stated as extending domain propagation to arrays, supporting floating-point operations, and inlining CFLOBDD reuse into compositional symbolic execution (Bolotina et al., 13 Jul 2025).
A common misconception would be to interpret bitme as a replacement for SMT. The reported architecture does not support that reading: SMT solvers remain integral, but they are invoked after substantial reduction of the symbolic search space. Another misconception would be to equate all decision-diagram choices. The reported experiments distinguish a speed-oriented ROABVDD regime from a memory-oriented CFLOBVDD regime, and the theory cited for CFLOBDDs suggests that this distinction is structural rather than incidental (Bolotina et al., 13 Jul 2025).
In that sense, bitme occupies a specific position in formal verification research: it is a machine-code-level bounded-model-checking engine whose contribution lies in changing the boundary between symbolic propagation and solver-based reasoning.