The visualizer puts the program, the datapath, all 32 registers and memory side by side and steps them together, one data transfer at a time. Shrinking that into a phone would mean hiding most of it, which would defeat the point.
It needs at least 1024 × 560 logical pixels — a landscape tablet, a laptop, or a desktop.
On a tablet, turning it to landscape is usually enough. Otherwise open this page on a laptop or a desktop.
Read what it does instead →An RV32IM machine you can step one data transfer at a time. Everything on screen is architectural: what the instruction is defined to do, which component holds which value, and how the bits change on the way through. Nothing here describes a particular implementation — no pipeline, no cache, no arithmetization.
The name marks the scope, not the content: RV32IM with a read-only program region and no system instructions is the machine a zero-knowledge VM actually implements, which is why the omissions below are what they are. What the tool says about each instruction is plain RISC-V.
The machine implements RV32I plus the M extension — the 32-bit base integer instructions and multiply/divide, 45 opcodes in all, every one of which the sample program executes at least once.
| Not implemented | Why |
|---|---|
| RV64I widths | This is a 32-bit machine; the *W family exists only to keep 32-bit arithmetic exact on a 64-bit one. |
| A — atomics | One hart, no interrupts, no preemption: every atomicity and ordering guarantee is already satisfied by executing in order. |
| C — compressed | Every instruction here is four bytes wide, which keeps the address arithmetic and the ROM layout uniform. |
ecall, ebreak, fence, CSRs | These are the boundary with an execution environment and privileged software, and there is neither here. There is no console: results are written into RAM, where you read them. |
Byte-addressed and little-endian, split into three regions:
0x00000000–0x000007FF — instruction memory plus read-only data. Instructions are fetched from it and constants can be loaded out of it; a store into it raises a store access fault.0x00010000–0x000103FF — ordinary read-write memory.0x00020000–0x000203FF — the same kind of memory, shown separately because sp is what makes call frames legible. It starts at 0x00020400 and grows downward.Alignment is enforced: a halfword access must be even and a word access a multiple of four. The base ISA leaves misaligned access to the execution environment, and this one declines it and reports load/store address misaligned — the same choice most real implementations make.
One Step button, and a selector beside it that decides how far one step goes. One transfer is the fine grain: a single value moving between two components. The sender lights teal, the receiver amber, the wire animates, and the value rides across on it. A component computing on what it already holds lights steel. An instruction is eight to thirteen transfers. Whole instruction finishes whatever is in flight and lands on the last transfer. Run uses the same setting, at anything from ten steps a second down to one every four seconds.
An ALU is not one circuit but a bundle of them — an adder, a logic array, a shifter, a comparator —
so the execute box stays labelled ALU and adds which part is engaged:
ALU · ADDER, ALU · LOGIC, ALU · SHIFTER,
ALU · COMPARE, ALU · BRANCH (the condition), ALU · TARGET
(a jump destination), ALU · ADDRESS (an effective address), and ALU · PASS
for LUI, which does no arithmetic at all. Multiply and divide are the M extension and get
their own unit in essentially every implementation, so those two read MUL UNIT and
DIV UNIT — no ALU involved.
The program listing is disassembly of what is actually in ROM — every row is a real
RV32IM instruction, decoded from its own encoded word. Assembler shorthand never appears, because it is
not part of the machine: li is not an opcode (a 32-bit constant is lui then
addi), mv is addi rd, rs, 0, ret is
jalr x0, 0(ra), and j is jal x0, offset. Branch and jump targets
are shown as labels only because an address is easier to follow with a name on it; the encoded
immediate is the offset.
Every box keeps what it was given until the next instruction overwrites it, so the diagram accumulates the state of the instruction as you walk it. The side panels stay honest about time: the highlighted line in the program does not advance, a register write shows dashed and still holding its old value, and a stored word stays unchanged, until the transfer that actually does it goes through.
addi a7, a6, 1 on 0x7FFFFFFF — wraps to the most negative integer with no exception. RISC-V has no overflow trap and no flags.sll t2, t0, t1 with t1 = 0x54 — the shift is by 20, because only the low five bits of the amount are ever used.lb and lbu on the same address — identical bytes, different widening.sb and one sh into one word — memory is byte-addressable, so each touches only its own bytes.div t6, a0, zero — division by zero is defined in RISC-V, not trapped.ret — just jalr x0, 0(ra), and JALR always clears bit 0 of its target.RISC-V Opcodes Under the Prover — an opcode-by-opcode treatment of this same instruction set, and of what it costs to prove each family inside a zkVM. The subset implemented here is the subset that piece is about.