Skip to main content
Version: 0.15 (unstable)

Kernel ROM chiplet

The kernel ROM enables executing predefined kernel procedures. These procedures are always executed in the root context and can only be accessed by a SYSCALL operation. The chiplet tracks and enforces correctness of all kernel procedure calls as well as maintaining a list of all the procedures defined for the kernel, whether they are executed or not. More background about Miden VM execution contexts can be found here.

Kernel ROM trace

The kernel ROM table consists of five columns, with exactly one row per declared kernel procedure. The following example table shows the execution trace for three procedures with digests a,b,ca, b, c, called 1, 2, and 0 times respectively.

mmr0r_0r1r_1r2r_2r3r_3
1a0a_0a1a_1a2a_2a3a_3
2b0b_0b1b_1b2b_2b3b_3
0c0c_0c1c_1c2c_2c3c_3

Column meanings:

  • mm is the CALL-label multiplicity — the number of times the procedure was invoked by a SYSCALL. It may be zero for procedures declared in the kernel but never called.
  • r0,,r3r_0, \ldots, r_3 contain the digest of the kernel procedure.

Main-trace constraints

The kernel ROM chiplet has no main-trace shape constraints under the all-LogUp layout. Earlier designs carried a binary "first-row-of-block" selector, a digest-contiguity rule, and an entry-row anchor to shape the trace for a permutation argument. LogUp replaces those with multiset equality under a random challenge α\alpha, so any prover assignment to (m,r0,,r3)(m, r_0, \ldots, r_3) that balances the chiplets bus is sound; no extra shape constraints are required.

Chiplets bus constraints

The kernel ROM chiplet emits two fractions on the chiplets bus bchipb_{chip} per active row, gated by the selector flag fkromf_{krom}. Let

r~=i=03αi+2rivinit=α0+α1KERNEL_PROC_INIT+r~vcall=α0+α1KERNEL_PROC_CALL+r~\begin{aligned} \tilde{r} &= \sum_{i=0}^{3} \alpha_{i+2} \cdot r_i \\ v_{init} &= \alpha_0 + \alpha_1 \cdot \textsf{KERNEL\_PROC\_INIT} + \tilde{r} \\ v_{call} &= \alpha_0 + \alpha_1 \cdot \textsf{KERNEL\_PROC\_CALL} + \tilde{r} \end{aligned}

denote the two encoded bus messages for a row's digest. Here KERNEL_PROC_INIT\textsf{KERNEL\_PROC\_INIT} and KERNEL_PROC_CALL\textsf{KERNEL\_PROC\_CALL} are the unique operation labels, and αi\alpha_i are challenges received from the verifier.

The chiplet contributes to bchipb_{chip} via

fkrom(1vinit+mvcall)f_{krom} \cdot \left( -\frac{1}{v_{init}} + \frac{m}{v_{call}} \right)
  • The INIT term removes exactly one fraction per declared procedure. It is balanced by the public-input boundary term the verifier injects on bchipb_{chip} (one add per kernel procedure digest read from public inputs). This anchors every chiplet row to a declared procedure: a forged row would leave an unmatched INIT remove.
  • The CALL term contributes mm fractions. Each SYSCALL in the decoder emits one matching remove on bchipb_{chip}. Bus balance forces mm to equal the true syscall count for that procedure.

The full set of constraints applied to bchipb_{chip} (including the public-input boundary term for INIT) is described in the chiplets bus constraints.

By using the bus this way, the verifier only learns which procedures can be invoked, not how often they were called — the multiplicity mm is a private witness that only reaches the verifier through the bus balance.