---
title: 'Bitme: RISC-V Machine Code BMC'
url: https://www.emergentmind.com/topics/bitme
type: topic
---

# Bitme: RISC-V Machine Code BMC

Searching arXiv for recent 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 [2507.09539].

## 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 [2507.09539].

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 [2507.09539].

## 2. Execution model and transition-system semantics

Rotor translates a RISC-V integer program into a BTOR2 transition system
$$
R = (S, I, T, B, C),
$$
where $S$ is the machine state, $I \subseteq S$ is the set of initial states, $T : S \to S$ is a purely combinational next-state function over bitvectors and arrays, $B \subseteq S$ is a Boolean condition of bad states, and $C \subseteq S$ is the conjunction of good constraints [2507.09539].

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 [2507.09539].

For bounded model checking up to bound $k$, rotor can unroll the transition relation and emit the formula
$$
I(s_0) \land \bigwedge_{i<k} C(s_i) \land \bigwedge_{i<k}(s_{i+1}=T(s_i)) \land B(s_k).
$$
Bitme reads the original unrolled-on-the-fly BTOR2 model implicitly rather than requiring a separately materialized large formula [2507.09539].

## 3. Decision-diagram representations

Bitme implements two principal tracker families: ADD/ROABVDD and CFLOBDD/CFLOBVDD. In its simplest form, an ADD represents a function
$$
f : \{0,1\}^n \to \mathbb{Z}
$$
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 [2507.09539].

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 $\{0,\ldots,255\}$, 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 [2507.09539].

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 $+$, $\oplus$, $\wedge$, $\vee$, or the ite operator [2507.09539].

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 $O(n^c)$, whereas any OBDD representation would be of size $2^{\Omega(n)}$. 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 [2507.09539]. 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 $v$ at time $i$, bitme maintains a tracker
$$
t_i^v : D_{\mathrm{in}} \to \mathrm{Val}(v),
$$
where $D_{\mathrm{in}}$ is the Cartesian product of all still-unpropagated input byte domains and $\mathrm{Val}(v)$ is the set of bitvector values for $v$ [2507.09539].

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 $v' = op(v_1,\ldots,v_r)$, bitme computes
$$
t_{i+1}^{v'} = \mathrm{TRACKER\_APPLY}(op, t_i^{v_1}, \ldots, t_i^{v_r}).
$$
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 [2507.09539].

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 $M$ nodes, with default $10^6$, 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 [2507.09539].

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 [2507.09539].

## 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 [2507.09539].

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 [2507.09539]. 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 $2^a$. 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 [2507.09539].

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 [2507.09539].

## 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 $X$ bits, and `multizero-X.c`, which reads $X$ bytes and requires all to be 0 [2507.09539].

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 $X$, whereas ROABVDD memory and time grow super-linearly; in absolute time, ROABVDD remains faster by approximately 20% [2507.09539]. 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 [2507.09539].

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 [2507.09539].

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 [2507.09539].

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.

Source: https://www.emergentmind.com/topics/bitme