Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

VM Architecture

XQVM is a stack-based bytecode interpreter. A running VM holds four pieces of mutable state:

StateHoldsNotes
Stacki64 valuesLIFO operand stack, max 8,192 items
Register FileRegVal values256 slots, indexed r0–r255
Loop Stackloop framesone per active RANGE/ITER; see Loops
Calldata / OutputsRegVal valuesread-only inputs (INPUT) and writable output slots (OUTPUT); see Calldata and Outputs

Design Principles

  • Stack-based computation – arithmetic and comparisons operate on an integer stack. This keeps the instruction set simple and compact.
  • Typed register file – registers hold polymorphic RegVal values (integers, vectors, models, samples). Type checking happens at runtime.
  • No heap / no pointers – there is no explicit memory allocation. Vectors and models grow dynamically within registers. Programs cannot address raw memory.
  • Deterministic execution – given the same program, calldata, and configuration, the VM always produces the same output. There are no random instructions or non-deterministic operations.
  • Embeddable – the VM crate supports no_std + alloc, enabling deployment in WASM runtimes and bare-metal environments.

Operand Stack

The operand stack is the primary workspace for computation. It holds i64 signed 64-bit integers and is used by arithmetic, comparison, logical, and bitwise instructions.

Properties

PropertyValue
Element typei64 (signed 64-bit integer)
Maximum depth8,192 items
OrderingLIFO (last in, first out)
Initial stateEmpty

Operations

  • PushPUSH1PUSH8 push constants. LOAD pushes a register’s integer value. COPY duplicates the top element.
  • Pop – most instructions implicitly pop their operands. POP explicitly discards the top element.
  • SwapSWAP exchanges the top two elements.
  • ClearSCLR removes all elements.

Stack Diagrams

Throughout this documentation, stack effects are written as:

$$[\ldots, a, b] \to [\ldots, r]$$

  • \(\ldots\) represents elements below the operands.
  • Rightmost = top of stack.
  • \(b\) is popped first (it was pushed last).
  • \(r\) is the result pushed after the operation.

Errors

  • StackUnderflow – popping from an empty stack or when there are fewer elements than the instruction requires.
  • StackOverflow – pushing when the stack already contains 8,192 items.

Interaction with Registers

The stack holds only i64 integers. Richer types (models, vectors, samples) live exclusively in registers. The bridge between them:

  • LOAD reg – pushes a register’s Int value onto the stack.
  • STOW reg – pops a stack value into a register as Int.

To move non-integer values, use INPUT/OUTPUT with calldata and output slots.

Register File

The register file is a fixed array of 256 slots, indexed r0 through r255. Each slot holds a typed RegVal value.

Properties

PropertyValue
Count256 (r0–r255)
Index typeu8
Value typeRegVal (polymorphic enum)
Default valueUnset for all slots

RegVal Variants

VariantRust TypeDescription
UnsetDefault. No value; a register never written, or reset by DROP.
Int(i64)i64Exchanged with the stack via LOAD/STOW.
VecInt(Vec<i64>)Vec<i64>Integer vector. Created by VEC/VECI.
VecXqmx(Vec<XqmxModel>)Vec<XqmxModel>Vector of models. Created by VECX.
Model(XqmxModel)structQUBO/Ising/integer Hamiltonian. Created by BQMX/SQMX/XQMX.
Sample(XqmxSample)structVariable-assignment vector. Created by BSMX/SSMX/XSMX.

Type Checking

Register access is type-checked at runtime. Instructions that expect a specific variant (e.g. LOAD expects Int, VECPUSH expects VecInt, SETQUAD expects Model, and SETLINE accepts either Model or Sample) will produce a RegisterType error if the register holds a variant the instruction does not accept. The error message includes the expected and actual type names. Reading an Unset register (via LOAD or OUTPUT) is a separate case: it produces an UnsetRegister error rather than RegisterType, since there is no variant to compare against.

XqmxModel Structure

A model represents a QUBO/Ising/integer Hamiltonian:

XqmxModel {
    domain: Domain,                      // Binary | Spin | Integer(k)
    size: usize,                         // number of variables
    linear: BTreeMap<usize, i64>,        // bias terms h_i
    quadratic: BTreeMap<(usize,usize), i64>,  // coupling terms J_{ij}
    rows: usize,                         // grid rows (set by RESIZE)
    cols: usize,                         // grid cols (set by RESIZE)
}

Coefficients are stored sparsely. Missing entries read as 0; setting a coefficient to 0 removes it from the map.

XqmxSample Structure

A sample holds a vector of variable assignments:

XqmxSample {
    domain: Domain,        // must match the model's domain
    values: Vec<i64>,      // one value per variable
    rows: usize,           // grid rows (set by RESIZE; 0 if ungridded)
    cols: usize,           // grid cols (set by RESIZE; 0 if ungridded)
}

Memory Management

There is no garbage collector. Registers hold their values until explicitly overwritten. Use DROP reg to reset a register to Unset, releasing any heap allocation (models, vectors, samples) it held. A register reset this way faults with UnsetRegister on the next LOAD or OUTPUT, until something is written back into it.