Bloqade Lanes
Bloqade Lanes is a component of QuEra's Neutral Atom SDK. It compiles quantum circuits down to physical atom movement instructions for neutral atom quantum processors.
What's in this book
- Architecture Specification — the
ArchSpecJSON format that defines device topology, transport buses, zones, and AOD paths - Instruction Quick Reference — compact summary of all 24 instructions with opcodes and stack effects
- Instruction Set — the fixed-width instruction encoding, opcode layout, and per-instruction reference
- CLI Reference — the
bloqade-bytecodeCLI tool for assembling, disassembling, and validating bytecode programs
Crate documentation
The Rust API documentation is generated separately via cargo doc:
bloqade-lanes-bytecode-core— pure Rust: bytecode format, arch spec, validationbloqade-lanes-bytecode-cli— CLI tool and C library
Repository
Source code: github.com/QuEraComputing/bloqade-lanes
ArchSpec — Architecture Specification
The ArchSpec defines the physical topology and transport capabilities of a Bloqade quantum device. It is the input that the bytecode compiler and validator use to determine which instructions are legal for a given hardware configuration.
The formal JSON Schema is available at archspec-schema.json.
Top-Level Structure
{
"version": "2.0",
"words": [...],
"zones": [...],
"zone_buses": [...],
"modes": [...],
"paths": [...], // optional
"feed_forward": false, // optional, default false
"atom_reloading": false, // optional, default false
"blockade_radius": 2.0 // optional
}
| Field | Type | Description |
|---|---|---|
version | string | Format version as "major.minor" (e.g. "2.0"). |
words | Word[] | Word definitions. A word's ID is its index in this array. |
zones | Zone[] | Logical zones, each owning a coordinate grid and intra-zone buses. |
zone_buses | InterZoneBus[] | Inter-zone word buses. |
modes | Mode[] | Named operational modes (zone subsets + measurement bitstring ordering). |
paths | TransportPath[] | (optional) AOD transport paths for lanes. |
feed_forward | bool | (optional, default false) Whether the device supports mid-circuit measurement with classical feedback. |
atom_reloading | bool | (optional, default false) Whether the device supports reloading atoms after initial fill. |
blockade_radius | float | (optional) Rydberg blockade radius in micrometers — metadata for interpreting entangling pairs. |
Words
A word is an independent register of atom trapping sites. It is the fundamental unit of the device topology. A word's ID is its index in the top-level words array (e.g., the first word is word 0).
"words": [
{ "sites": [[0, 0], [1, 0], [2, 0], [3, 0], [4, 0]] }
]
| Field | Type | Description |
|---|---|---|
sites | [x_idx, y_idx][] | Site positions as index pairs into the owning zone grid's x and y coordinate arrays. |
All words must have the same number of sites (sites_per_word is derived as the site count of the first word), and every site's [x, y] indices must lie within the zone grid.
Zones
A zone is a logical region owning a coordinate grid and the transport buses that operate within it. A zone's ID is its index in the zones array (e.g., the first zone is zone 0).
"zones": [
{
"name": "entangling",
"grid": {
"x_start": 1.0,
"y_start": 2.5,
"x_spacing": [2.0, 2.0, 2.0, 2.0],
"y_spacing": [2.5]
},
"site_buses": [
{ "src": [0, 1], "dst": [3, 4] }
],
"word_buses": [
{ "src": [0], "dst": [1] }
],
"words_with_site_buses": [0, 1],
"sites_with_word_buses": [0],
"entangling_pairs": [[0, 1]]
}
]
| Field | Type | Description |
|---|---|---|
name | string | (optional, default "") Human-readable zone name. |
grid | Grid | Coordinate grid for all words in this zone. |
site_buses | Bus[] | Site buses moving atoms between sites within words of this zone. |
word_buses | Bus[] | Word buses moving atoms between words within this zone. |
words_with_site_buses | integer[] | Word IDs with site-bus transport capability in this zone. |
sites_with_word_buses | integer[] | Site indices serving as landing pads for word-bus moves. |
entangling_pairs | [w_a, w_b][] | (optional, default []) Word pairs at blockade radius for CZ gates. |
Grid
A grid defines the physical coordinate axes for a zone using a start position and spacing values. Positions are typically in micrometers (µm).
| Field | Type | Description |
|---|---|---|
x_start | float | X-coordinate of the first grid point. |
y_start | float | Y-coordinate of the first grid point. |
x_spacing | float[] | Spacing between consecutive x-coordinates. The number of x grid points is len(x_spacing) + 1. |
y_spacing | float[] | Spacing between consecutive y-coordinates. The number of y grid points is len(y_spacing) + 1. |
The x-coordinates are computed as [x_start, x_start + x_spacing[0], x_start + x_spacing[0] + x_spacing[1], ...] (cumulative sum of spacings from the start). Same for y. Sites reference grid positions by index: site [2, 1] is located at the 3rd x-coordinate and 2nd y-coordinate. Spacings must be non-negative.
All zones must have the same grid dimensions — i.e., the same number of x and y grid points (same x_spacing and y_spacing lengths). The actual coordinate values differ (zones are at different physical locations), and zone bounding boxes must not overlap in physical space.
Entangling Pairs
Each zone's entangling_pairs lists which word pairs within it can perform CZ (entangling) gates. Within a pair, sites at matching indices in w_a and w_b are within blockade radius. A zone with no entangling pairs is a storage/low-connectivity zone.
Buses
Buses are the physical transport channels that move atoms. Each bus defines a paired mapping via parallel arrays: the atom at src[i] moves to dst[i], and all pairs of one bus execute simultaneously as one AOD operation. There are three kinds:
Site Bus
A site bus moves atoms between sites within the same word. Entries are site indices. A site bus's ID is its index in the owning zone's site_buses array.
{ "src": [0, 1, 2, 3, 4], "dst": [5, 6, 7, 8, 9] }
This means the atom at site 0 moves to site 5, the atom at site 1 moves to site 6, and so on — all in a single transport operation. Only words listed in the zone's words_with_site_buses can execute site-bus moves.
Word Bus
A word bus moves atoms between different words within a zone. The src and dst arrays contain word IDs (not site indices). A word bus's ID is its index in the owning zone's word_buses array.
{ "src": [0], "dst": [1] }
The specific sites involved in inter-word transport are those listed in the zone's sites_with_word_buses — the "landing pad" positions within each word.
Zone Bus
A zone bus (top-level zone_buses) moves words across zone boundaries. Entries are zone-qualified word references, and every (src[i], dst[i]) pair must have different zone_ids.
{
"src": [{ "zone_id": 0, "word_id": 0 }],
"dst": [{ "zone_id": 1, "word_id": 0 }]
}
Bus Well-Formedness
For every bus kind, the src→dst relation must be well-formed: src entries unique, dst entries unique, and acyclic (no rotations, including self-loops) — a bus is a set of explicit transports, never a permutation. Overlapping-but-acyclic relations (conveyor chains such as 0→1, 1→2) are legal. See Validation Rules.
Modes
A mode is a named operational configuration: a subset of zones plus the bitstring ordering used for measurement results.
"modes": [
{ "name": "full", "zones": [0, 1], "bitstring_order": [] }
]
| Field | Type | Description |
|---|---|---|
name | string | Human-readable mode name. |
zones | integer[] | Zone IDs active in this mode. |
bitstring_order | integer[] | Bit-to-location mapping for measurement results. Each entry is a LocationAddr encoded as a packed integer (layout [zone_id:8][word_id:16][site_id:16][pad:24], most-significant first). |
Paths (Optional)
AOD (Acousto-Optic Deflector) transport paths. Each path identifies a transport lane and provides a sequence of [x, y] waypoints defining the physical trajectory atoms follow during transport.
The lane is identified by its encoded LaneAddr, serialized as a hex string. See Address Encoding for the LaneAddr bit layout.
"paths": [
{
"lane": "0x2000000000000000", // encoded LaneAddr (hex, 16-digit)
"waypoints": [[0.0, 0.0], [0.0, 5.0], [2.0, 5.0]] // physical trajectory
}
]
Each TransportPath entry has:
| Field | Type | Description |
|---|---|---|
lane | string | Encoded LaneAddr as a "0x..." hex string. |
waypoints | [x, y][] | Sequence of physical coordinate waypoints (at least 2, all finite). |
To decode the lane hex string, parse it as a 64-bit unsigned integer. The low 32 bits (data0) contain [word_id:16][site_id:16] and the high 32 bits (data1) contain [dir:1][mt:2][zone_id:8][pad:5][bus_id:16]. For example, "0x2000000000000000" has data1 = 0x20000000: direction=Forward (bit 31 clear), move_type=WordBus (bits 30–29 = 01), zone=0, word=0, site=0, bus=0. In the lane address convention, word_id always encodes the forward-direction source word for that lane, so a Backward lane with the same address fields moves the atom from the bus destination back to that source.
This field is omitted from the JSON when not needed.
Capability Flags (Optional)
Two boolean flags describe device capabilities that affect bytecode validation:
| Field | Default | Description |
|---|---|---|
feed_forward | false | Mid-circuit measurement with classical feedback. When false, at most one measure instruction is allowed per program. |
atom_reloading | false | Atom reloading after initial fill. When false, no fill instruction is allowed (only initial_fill). |
Both fields are optional in the JSON — existing arch spec files that omit them default to false, which is the most restrictive setting.
{
"feed_forward": true,
"atom_reloading": false
}
Validation Rules
The ArchSpec::validate() method checks all structural rules in a single pass, collecting every error rather than failing fast. Errors are grouped into coarse ArchSpecError categories, each carrying a descriptive message; the Error column below names the category (Rust enum variant). Through the Python bindings the categories map onto exception classes:
ArchSpecError variant | Python exception |
|---|---|
Structure | ArchSpecGeometryError |
ZoneBus, InterZoneBus, CyclicBus | ArchSpecBusError |
EntanglingPair, Mode | ArchSpecZoneError |
Path | ArchSpecPathError |
Structural Rules
| Rule | Error |
|---|---|
| At least one zone and at least one word must exist | Structure |
| All grid spacings must be non-negative | Structure |
| All zones must have the same grid dimensions (same number of x and y positions) | Structure |
| All words must have the same number of sites | Structure |
Every word site's [x, y] indices must lie within the zone grid | Structure |
| No two zones may have overlapping bounding boxes in physical (x, y) space | Structure |
Per-Zone Bus Rules
| Rule | Error |
|---|---|
Every ID in words_with_site_buses must be a valid word ID | ZoneBus |
Every index in sites_with_word_buses must be < sites_per_word | ZoneBus |
Site bus src and dst must have equal length | ZoneBus |
All site bus indices in src and dst must be < sites_per_word | ZoneBus |
Word bus src and dst must have equal length | ZoneBus |
All word bus IDs in src and dst must be valid word IDs | ZoneBus |
Inter-Zone Bus Rules
| Rule | Error |
|---|---|
Zone bus src and dst must have equal length | InterZoneBus |
All zone bus zone_id / word_id entries must be in range | InterZoneBus |
Every (src[i], dst[i]) pair must cross a zone boundary | InterZoneBus |
Bus Well-Formedness Rules (all bus kinds)
A bus is a set of explicit edge transports executed simultaneously as one AOD operation — never a permutation. These rules apply to site buses, word buses, and zone buses alike:
| Rule | Error |
|---|---|
src entries must be unique (endpoint resolution is positional first-match, so a duplicated source silently shadows later pairs) | ZoneBus / InterZoneBus |
dst entries must be unique (two simultaneous transports into one site cannot both complete) | ZoneBus / InterZoneBus |
The src→dst relation must be acyclic, including self-loops — a cycle would rotate a fully-occupied set of atoms with no empty site, which AOD hardware cannot do. Overlapping-but-acyclic relations (conveyor chains such as 0→1, 1→2) are legal. | CyclicBus |
Entangling Pair Rules
| Rule | Error |
|---|---|
Both word IDs in every entangling_pairs entry must be valid word IDs | EntanglingPair |
| A word must not be paired with itself | EntanglingPair |
No duplicate pairs (order-insensitive: [a, b] duplicates [b, a]) | EntanglingPair |
Mode Rules
| Rule | Error |
|---|---|
| Every zone ID in a mode must reference a defined zone | Mode |
Every bitstring_order entry's zone_id, word_id, and site_id must be in range | Mode |
Path Rules
| Rule | Error |
|---|---|
| Waypoint coordinates must be finite (no NaN or Inf) | Path |
Every path's lane must have a valid zone_id | Path |
| Every path must have at least 2 waypoints | Path |
Capability Rules (Bytecode Validation)
These rules are checked during bytecode validation (ValidationError, not ArchSpecError) when an ArchSpec is provided:
| Rule | Error |
|---|---|
If feed_forward = false, control flow and multiple measure instructions are rejected | ControlFlowRequiresFeedForward, MultipleMeasuresRequireFeedForward |
If atom_reloading = false, no fill instruction is allowed (initial_fill is a separate instruction and is always permitted) | FillRequiresAtomReloading |
Address Encoding
At the bytecode level, locations and lanes are encoded as bit-packed integers with 16-bit address fields. Each address type is packed into instruction data words (u32):
| Type | Width | Layout | Description |
|---|---|---|---|
LocationAddr | 64 bits | [zone_id:8][word_id:16][site_id:16][pad:24] (most-significant first) | Identifies a specific site within a word of a zone. |
LaneAddr | 64 bits (2 × u32) | data0 (low): [word_id:16][site_id:16], data1 (high): [dir:1][mt:2][zone_id:8][pad:5][bus_id:16] | Identifies a transport lane (direction + move type + zone + word/site + bus). |
ZoneAddr | 32 bits (1 × u32) | [pad:24][zone_id:8] | Identifies a zone. |
These packed addresses are used in 16-byte bytecode instructions (opcode + 3 data words) and are validated against the arch spec during program validation. In JSON, LaneAddr is represented as a 16-digit hex string (data0 | data1 << 32) and LocationAddr as a plain integer; in Python both are u64 values.
Examples
Minimal spec with one word, one zone, and one site bus (this is examples/arch/simple.json):
{
"version": "2.0",
"words": [
{ "sites": [[0, 0], [1, 0], [2, 0], [3, 0], [4, 0]] }
],
"zones": [
{
"grid": {
"x_start": 1.0,
"y_start": 2.0,
"x_spacing": [2.0, 2.0, 2.0, 2.0],
"y_spacing": []
},
"site_buses": [
{ "src": [0, 1], "dst": [3, 4] }
],
"word_buses": [],
"words_with_site_buses": [0],
"sites_with_word_buses": []
}
],
"zone_buses": [],
"modes": [
{ "name": "default", "zones": [0], "bitstring_order": [] }
]
}
A fuller example with multiple words, CZ pairs, and word buses is available at examples/arch/full.json.
Zone-Centric Architecture — Visual Guide
This guide explains the zone-centric ArchSpec model using diagrams and examples. The audience is hardware engineers and architects validating that the spec correctly models the physical device. For the formal specification, see Architecture Specification.
Zones — The Primary Unit
The processor is organized into zones — physically distinct regions of the trap array. Each zone owns its own coordinate grid of trap sites. Zones differ in purpose and connectivity:
- Gate zones — contain entangling word pairs; high internal connectivity (many site and word buses)
- Memory zones — atom storage; no entangling pairs; lower connectivity
Zone 0 (Gate) Zone 1 (Memory)
┌──────────────────────┐ ┌──────────────────────┐
│ ●──● ●──● │ │ ● ● ● ● │
│ ╠══╣ ╠══╣ dense │ │ loose │
│ ●──● ●──● │ │ ● ● ● ● │
│ │ │ │
│ entangling_pairs: │ │ entangling_pairs: │
│ word 0 ↔ word 1 │ │ (none) │
│ word 2 ↔ word 3 │ │ │
└──────────────────────┘ └──────────────────────┘
◄──── zone buses ────►
All zones share the same global word definitions and have the same grid
dimensions (uniform zone dimension constraint). What differs is the
physical spacing and the connectivity. This uniformity is what makes uniform
addressing work — (zone, word, site) addresses the same logical position in
any zone.
Words — The Shared Template
A word groups grid sites into a logical register. Words are a global template — the same slicing pattern applied identically across every zone. A word references index pairs into the parent zone's grid; the physical coordinates come from the zone.
Word template (global):
Word 0 = sites (0,0), (1,0) ┌──────────┐
Word 1 = sites (2,0), (3,0) │ w0 w1 │ ← row 0
Word 2 = sites (0,1), (1,1) │ w2 w3 │ ← row 1
Word 3 = sites (2,1), (3,1) └──────────┘
Applied to each zone:
Zone 0 (Gate) Zone 1 (Memory)
┌─────────┐ ┌─────────┐
│ w0 │ w1 │ │ w0 │ w1 │ same word IDs
│────┼────│ │────┼────│ same site IDs
│ w2 │ w3 │ │ w2 │ w3 │ different physical positions
└─────────┘ └─────────┘
A zone bus moving an atom from (zone:0, word:0) to (zone:1, word:0) moves
it from the gate zone's Word 0 to the memory zone's Word 0. The uniform
template means the same word ID refers to the same logical slot across zones —
this is what makes cross-zone transport well-defined.
Entangling Word Pairs
Each zone declares its own entangling_pairs — pairs of word IDs within that
zone whose sites are physically close enough for CZ gates. A gate zone has
entangling pairs; a memory zone has none.
Zone 0 (Gate) — entangling pairs: [0,1] and [2,3]
Word 0 Word 1
┌────┐ CZ ↔ ┌────┐
│ s0 │────────│ s0 │ site 0 ↔ site 0
│ s1 │────────│ s1 │ site 1 ↔ site 1
└────┘ └────┘
Word 2 Word 3
┌────┐ CZ ↔ ┌────┐
│ s0 │────────│ s0 │
│ s1 │────────│ s1 │
└────┘ └────┘
CZ partner of (zone=0, word=0, site=1)
is (zone=0, word=1, site=1)
— always same zone, same site ID
Zone 1 (Memory) has entangling_pairs: [] — no CZ capability. The presence
of pairs is the signal; there is no separate flag. A zone with entangling
pairs is a gate zone; a zone without is a storage zone.
Transport — How Atoms Move
Atoms move via AOD transport buses at three scopes. Gate zones have more buses (high connectivity); memory zones have fewer (lower connectivity).
Within a word — Site Buses
Zone-owned buses that move atoms between sites within words. A site bus
applies simultaneously to all words listed in words_with_site_buses
(lockstep, reflecting AOD beam physics).
Site bus: move atoms between sites within a word
Word 0: s0 ──► s1
Word 1: s0 ──► s1 all words in words_with_site_buses
Word 2: s0 ──► s1 move in lockstep (AOD beam)
Word 3: s0 ──► s1
Within a zone — Word Buses
Zone-owned buses that move atoms between different words in the same zone.
Only sites listed in sites_with_word_buses participate as landing pads.
Word bus: move atoms between words within a zone
Zone 0:
Word 0 ●───●
│ ╲
│ ╲ atom moves Word 0 → Word 2
│ ▼
Word 2 ●───●
Across zones — Zone Buses
ArchSpec-owned buses that move atoms between words in different zones. Every entry must cross a zone boundary.
Zone bus: move atoms between zones
Zone 0 (Gate) Zone 1 (Memory)
┌────────────┐ ┌──────────────┐
│ Word 0 ●●──│────────────►│──►●● Word 0 │
│ Word 1 ●● │ │ ●● Word 1 │
└────────────┘ └──────────────┘
Rectangle Constraint
For all bus types, the source and destination positions must each form a complete rectangular grid (Cartesian product of x and y values), and both rectangles must have the same dimensions. This reflects the AOD hardware — beams move entire rows or columns, so every move operates on a rectangle.
Summary
┌────────────┬──────────────┬───────────┐
│ Bus Type │ Scope │ Owned By │
├────────────┼──────────────┼───────────┤
│ Site bus │ Within word │ Zone │
│ Word bus │ Within zone │ Zone │
│ Zone bus │ Across zones │ ArchSpec │
└────────────┴──────────────┴───────────┘
Measurement Modes
A Mode names a subset of zones and provides an explicit bit-position-to-site mapping for measurement results.
Mode "all_zones": zones = [0, 1] all sites, explicit ordering
Mode "subset": zones = [0] gate zone sites only
Each mode's bitstring_order maps bit positions to (zone, word, site)
addresses — no implicit conventions or special zone IDs. The mode names and
zone subsets are user-defined; the examples above are illustrative, not
canonical.
Old Model vs. New Model
The zone-centric redesign shifts structural ownership from words to zones:
OLD MODEL NEW MODEL
───────── ─────────
ArchSpec ArchSpec
├── geometry ├── version: 2.0
│ └── words[] ├── words[] ◄── global template
│ ├── positions: Grid ◄─ each │ └── sites: [(x_idx, y_idx)]
│ │ word owns a grid │
│ ├── site_indices ├── zones[] ◄── primary unit
│ └── has_cz ◄─ CZ per word │ ├── grid ◄── zone owns grid
│ │ ├── site_buses
├── buses ◄── global flat lists │ ├── word_buses
│ ├── site_buses[] │ ├── words_with_site_buses
│ └── word_buses[] │ ├── sites_with_word_buses
│ │ └── entangling_pairs ◄── per-zone
├── zones[] ◄── afterthought │
│ └── words: [0, 1, 2, 3] ├── zone_buses[] ◄── inter-zone
│ │
├── entangling_zones ├── modes[] ◄── replaces
└── measurement_mode_zones │ ├── name measurement_mode
│ ├── zones _zones
│ └── bitstring_order
│
├── feed_forward
└── atom_reloading
| Aspect | Old | New |
|---|---|---|
| Grid ownership | Each word owns a Grid | Each zone owns a Grid |
| Bus ownership | Global flat lists | Per-zone (site + word) + ArchSpec (zone) |
| CZ declaration | Word.has_cz (intra-word) | Zone.entangling_pairs (intra-zone word pairs) |
| Measurement | measurement_mode_zones: [int] | modes: [{ name, zones, bitstring_order }] |
| Zone role | Grouping of word IDs | Primary structural unit |
Key Invariants (Quick Reference)
┌─────────────────────────────────────────────────────────────────┐
│ 1. UNIFORM DIMENSIONS │
│ All zones share the same global word definitions and │
│ have the same grid dimensions. │
│ │
│ 2. RECTANGLE CONSTRAINT │
│ Every bus's src and dst positions form complete │
│ rectangular grids with matching dimensions. │
│ │
│ 3. ZONE BUS CROSSING │
│ Every zone bus entry must cross a zone boundary. │
│ │
│ 4. ENTANGLING = INTRA-ZONE WORD PAIRS │
│ Each zone declares its own entangling_pairs (word pairs). │
│ CZ partner is always in the same zone, same site_id. │
│ │
│ 5. WORDS ARE TEMPLATES │
│ Words define a slicing pattern, not physical positions. │
│ Physical positions come from the parent zone's grid. │
└─────────────────────────────────────────────────────────────────┘
Full Data Model (Optional Reading)
Complete ArchSpec field tree for reference. Sites are addressed as
(zone_id, word_id, site_id), encoded into 64-bit addresses for bytecode —
see Architecture Specification for encoding details.
ArchSpec
│
├── version: Version
│
├── words: [Word] global template
│ └── sites: [(x_idx, y_idx)] index pairs into parent zone's grid
│
├── zones: [Zone] primary structural unit
│ ├── grid: Grid zone's coordinate system
│ │ ├── x_start, y_start origin
│ │ ├── x_spacing: [f64] cumulative spacing
│ │ └── y_spacing: [f64]
│ ├── site_buses: [Bus<SiteRef>] intra-word transport
│ ├── word_buses: [Bus<WordRef>] intra-zone transport
│ ├── words_with_site_buses: [u32] which words participate in site buses
│ ├── sites_with_word_buses: [u32] which sites are word-bus landing pads
│ └── entangling_pairs: [[u32; 2]] word pairs for CZ gates (empty = storage zone)
│
├── zone_buses: [Bus<ZonedWordRef>] inter-zone transport
│ └── Bus { src: [ZonedWordRef], dst: [ZonedWordRef] }
│ └── ZonedWordRef { zone_id: u8, word_id: u16 }
│
├── modes: [Mode] measurement configurations
│ ├── name: String
│ ├── zones: [u32] which zones are imaged
│ └── bitstring_order: [LocationAddr] bit-to-site mapping
│
├── paths: Option<[TransportPath]> optional AOD transport paths
│ └── TransportPath { lane: u64, waypoints: [[f64; 2]] }
│
├── feed_forward: bool mid-circuit measurement + classical feedback
└── atom_reloading: bool atom reload after initial fill
Instruction Quick Reference
A compact summary of all 24 bytecode instructions. See the Instruction Set for full encoding details.
Cpu (0x00)
Stack manipulation, constants, and control flow (FLAIR-aligned).
| Instruction | Opcode | Stack Effect | Description |
|---|---|---|---|
const_int | 0x0200 | ( -- int) | Push 64-bit integer constant |
const_float | 0x0300 | ( -- float) | Push 64-bit float constant |
dup | 0x0400 | (a -- a a) | Duplicate top of stack |
pop | 0x0500 | (a -- ) | Discard top of stack |
swap | 0x0600 | (a b -- b a) | Swap top two elements |
return | 0x6400 | ( -- ) | Return from program |
halt | 0xFF00 | ( -- ) | Halt execution |
LaneConstants (0x0F)
Address constant instructions.
| Instruction | Opcode | Stack Effect | Description |
|---|---|---|---|
const_loc | 0x000F | ( -- loc) | Push location address |
const_lane | 0x010F | ( -- lane) | Push lane address |
const_zone | 0x020F | ( -- zone) | Push zone address |
AtomArrangement (0x10)
Atom filling and transport.
| Instruction | Opcode | Stack Effect | Description |
|---|---|---|---|
initial_fill | 0x0010 | (loc₁..locₙ -- ) | Initial atom loading |
fill | 0x0110 | (loc₁..locₙ -- ) | Atom refill |
move | 0x0210 | (lane₁..laneₙ -- ) | Atom transport along lanes |
QuantumGate (0x11)
Single- and multi-qubit gate operations.
| Instruction | Opcode | Stack Effect | Description |
|---|---|---|---|
local_r | 0x0011 | (loc₁..locₙ θ φ -- ) | Local R rotation |
local_rz | 0x0111 | (loc₁..locₙ θ -- ) | Local Rz rotation |
global_r | 0x0211 | (θ φ -- ) | Global R rotation |
global_rz | 0x0311 | (θ -- ) | Global Rz rotation |
cz | 0x0411 | (zone -- ) | Controlled-Z gate on zone |
Measurement (0x12)
Qubit measurement.
| Instruction | Opcode | Stack Effect | Description |
|---|---|---|---|
measure | 0x0012 | (zone₁..zoneₙ -- future₁..futureₙ) | Initiate measurement |
await_measure | 0x0112 | (future -- array_ref) | Wait for measurement result |
Array (0x13)
Array construction and indexing.
| Instruction | Opcode | Stack Effect | Description |
|---|---|---|---|
new_array | 0x0013 | (elem₁..elemₙ -- array_ref) | Construct array from stack |
get_item | 0x0113 | (array_ref idx₁..idxₙ -- value) | Index into array |
DetectorObservable (0x14)
Detector and observable setup.
| Instruction | Opcode | Stack Effect | Description |
|---|---|---|---|
set_detector | 0x0014 | (array_ref -- detector_ref) | Set detector |
set_observable | 0x0114 | (array_ref -- observable_ref) | Set observable |
Bloqade Lanes Bytecode Instruction Specification
This document specifies the bytecode instruction set used by Bloqade Lanes to describe atom shuttling programs for neutral atom quantum processors. A bytecode program is a sequence of fixed-width instructions that drive the full lifecycle of a computation: loading atoms into an optical lattice, shuttling them between sites using AOD (Acousto-Optic Deflector) transport, applying quantum gates, and reading out measurement results.
The instruction set is organized around the physical structure of the hardware. Atoms occupy sites within words (rows of trapping positions in the lattice). Buses define the AOD transport channels that move atoms between sites (site buses) or between words (word buses). A lane is a single atom trajectory along a bus — one source site to one destination site. A zone groups words that share a global entangling interaction (e.g. a Rydberg pulse) or define locations where atoms are measured. These concepts map directly to the address types used in the bytecode: LocationAddr (word, site), LaneAddr (word, site, bus, direction), and ZoneAddr (zone).
Programs execute on a stack machine. Address constants and numeric parameters are pushed onto the stack, then consumed by operation instructions (fills, moves, gates, measurements). The bytecode is designed to be validated offline against an architecture specification (ArchSpec) that captures the geometry, bus topology, and zone layout of a specific device.
Instruction Format
Every instruction is a fixed 16 bytes: a 32-bit opcode word followed by three 32-bit data words, all little-endian.
┌──────────────┬──────────────┬──────────────┬──────────────┐
│ opcode (u32) │ data0 (u32) │ data1 (u32) │ data2 (u32) │
├──────────────┼──────────────┼──────────────┼──────────────┤
│ bytes 0–3 │ bytes 4–7 │ bytes 8–11 │ bytes 12–15 │
└──────────────┴──────────────┴──────────────┴──────────────┘
Instructions that take no operands ignore the data words (should be zero). Instructions with operands encode them in the data words as described per-instruction below.
Opcode Packing
The opcode word is packed as a 1-byte instruction code and a 1-byte device code in the low 16 bits of the u32. The upper 16 bits are unused (must be zero). The device code occupies the least significant byte.
┌──────────────┬──────────────────┬──────────────────┐
│ unused │ instruction code │ device code │
│ (16 bits) │ (8 bits) │ (8 bits) │
└──────────────┴──────────────────┴──────────────────┘
bits 31–16 bits 15–8 bits 7–0
Full opcode = (instruction_code << 8) | device_code.
In little-endian memory layout:
byte[0] = device_code (bits 7–0)
byte[1] = instruction_code (bits 15–8)
byte[2] = 0x00 (unused)
byte[3] = 0x00 (unused)
Instruction codes can overlap across different devices — the device code byte disambiguates.
Device Codes
| Device Code | Name | Description |
|---|---|---|
0x00 | Cpu | Stack manipulation, constants, control flow (FLAIR-aligned) |
0x0F | LaneConstants | Lane-specific constant instructions |
0x10 | AtomArrangement | Atom filling and movement |
0x11 | QuantumGate | Single- and multi-qubit gate operations |
0x12 | Measurement | Qubit measurement |
0x13 | Array | Array construction and indexing |
0x14 | DetectorObservable | Detector and observable setup |
Device codes 0x01–0x0E are reserved for future FLAIR device types.
Address Encoding
All address field components are 16-bit, packed into the data words.
LocationAddr
Packed in a single data word (data0):
data0: [word_id:16][site_id:16]
bits 31–16 bits 15–0
Total: 32 bits (u32).
LaneAddr
Packed across two data words (data0 + data1):
data0: [word_id:16][site_id:16]
bits 31–16 bits 15–0
data1: [dir:1][mt:1][pad:14][bus_id:16]
bit 31 bit 30 29–16 bits 15–0
dir— direction: 0 = Forward, 1 = Backwardmt— move type: 0 = SiteBus, 1 = WordBus
Total: 64 bits across two u32 words. Note that data0 shares the same layout as LocationAddr.
Lane address convention
The word_id and site_id fields in a LaneAddr always encode the forward-direction source — the position where the atom starts in a forward move. The direction field does not change which position is encoded; it only controls which endpoint is treated as source vs destination when the lane is resolved.
Endpoint resolution always starts by resolving the forward direction:
- Look up the bus (site bus or word bus, selected by
move_typeandbus_id) - Find the index
iwherebus.src[i]matches the encodedsite_id(for site buses) orword_id(for word buses) - The forward source is
(word_id, site_id)as encoded; the forward destination is(word_id, bus.dst[i])for site buses or(bus.dst[i], site_id)for word buses - If
direction = Forward: return(fwd_source, fwd_destination) - If
direction = Backward: return(fwd_destination, fwd_source)— the endpoints are swapped
Example: Given a site bus with src=[0,1,2,3,4] dst=[5,6,7,8,9]:
| Lane | Encoded | Resolved src → dst |
|---|---|---|
site_id=0, dir=Forward | Forward source is site 0 | Site 0 → Site 5 |
site_id=0, dir=Backward | Forward source is still site 0 | Site 5 → Site 0 |
site_id=2, dir=Backward | Forward source is site 2 | Site 7 → Site 2 |
Note that a backward lane with site_id=0 means the atom moves from site 5 to site 0 — not that site 0 is the destination of a forward move.
Lane validation rules
The validator (check_lane) checks the following for each LaneAddr:
| Rule | Error condition |
|---|---|
| Bus must exist | bus_id out of range for the given move_type |
word_id in range | word_id >= num_words |
site_id in range | site_id >= sites_per_word |
| Bus membership | For site buses: word_id must be in words_with_site_buses. For word buses: site_id must be in sites_with_word_buses. |
| Valid forward source | For site buses: bus.resolve_forward(site_id) must succeed (i.e. site_id is in bus.src). For word buses: bus.resolve_forward(word_id) must succeed (i.e. word_id is in bus.src). |
Validation is always performed against the forward-direction source, regardless of the direction field.
ZoneAddr
Packed in a single data word (data0):
data0: [pad:16][zone_id:16]
bits 31–16 bits 15–0
Total: 32 bits (u32).
Instructions
Cpu (0x00) — FLAIR-aligned shared opcodes
These instruction codes are shared with the FLAIR VM/IR spec and use identical values.
const_int — Push integer constant
| Field | Value |
|---|---|
| Device Code | 0x00 |
| Instruction Code | 0x02 |
| Full Opcode | 0x0200 |
| data0 | i64 LE low 32 bits |
| data1 | i64 LE high 32 bits |
| data2 | unused |
| Stack | ( -- int) |
Pushes a signed 64-bit integer onto the stack. The value is stored as a little-endian i64 across data0 (low) and data1 (high).
const_float — Push float constant
| Field | Value |
|---|---|
| Device Code | 0x00 |
| Instruction Code | 0x03 |
| Full Opcode | 0x0300 |
| data0 | f64 LE low 32 bits |
| data1 | f64 LE high 32 bits |
| data2 | unused |
| Stack | ( -- float) |
Pushes a 64-bit float onto the stack. The value is stored as a little-endian f64 across data0 (low) and data1 (high).
dup — Duplicate top of stack
| Field | Value |
|---|---|
| Device Code | 0x00 |
| Instruction Code | 0x04 |
| Full Opcode | 0x0400 |
| data0–2 | unused |
| Stack | (a -- a a) |
pop — Discard top of stack
| Field | Value |
|---|---|
| Device Code | 0x00 |
| Instruction Code | 0x05 |
| Full Opcode | 0x0500 |
| data0–2 | unused |
| Stack | (a -- ) |
swap — Swap top two stack elements
| Field | Value |
|---|---|
| Device Code | 0x00 |
| Instruction Code | 0x06 |
| Full Opcode | 0x0600 |
| data0–2 | unused |
| Stack | (a b -- b a) |
return — Return from program
| Field | Value |
|---|---|
| Device Code | 0x00 |
| Instruction Code | 0x64 |
| Full Opcode | 0x6400 |
| data0–2 | unused |
| Stack | ( -- ) |
halt — Halt execution
| Field | Value |
|---|---|
| Device Code | 0x00 |
| Instruction Code | 0xFF |
| Full Opcode | 0xFF00 |
| data0–2 | unused |
| Stack | ( -- ) |
LaneConstants (0x0F)
const_loc — Push location address
| Field | Value |
|---|---|
| Device Code | 0x0F |
| Instruction Code | 0x00 |
| Full Opcode | 0x000F |
| data0 | LocationAddr — [word_id:16][site_id:16] |
| data1 | unused |
| data2 | unused |
| Stack | ( -- loc) |
const_lane — Push lane address
| Field | Value |
|---|---|
| Device Code | 0x0F |
| Instruction Code | 0x01 |
| Full Opcode | 0x010F |
| data0 | [word_id:16][site_id:16] |
| data1 | [dir:1][mt:1][pad:14][bus_id:16] |
| data2 | unused |
| Stack | ( -- lane) |
const_zone — Push zone address
| Field | Value |
|---|---|
| Device Code | 0x0F |
| Instruction Code | 0x02 |
| Full Opcode | 0x020F |
| data0 | ZoneAddr — [pad:16][zone_id:16] |
| data1 | unused |
| data2 | unused |
| Stack | ( -- zone) |
AtomArrangement (0x10)
initial_fill — Initial atom loading
| Field | Value |
|---|---|
| Device Code | 0x10 |
| Instruction Code | 0x00 |
| Full Opcode | 0x0010 |
| data0 | u32 LE arity |
| data1 | unused |
| data2 | unused |
| Stack | (loc₁ loc₂ … locₙ -- ) |
Pops n location addresses and performs the initial atom fill at those sites.
fill — Atom refill
| Field | Value |
|---|---|
| Device Code | 0x10 |
| Instruction Code | 0x01 |
| Full Opcode | 0x0110 |
| data0 | u32 LE arity |
| data1 | unused |
| data2 | unused |
| Stack | (loc₁ loc₂ … locₙ -- ) |
Pops n location addresses and refills atoms at those sites.
move — Atom transport
| Field | Value |
|---|---|
| Device Code | 0x10 |
| Instruction Code | 0x02 |
| Full Opcode | 0x0210 |
| data0 | u32 LE arity |
| data1 | unused |
| data2 | unused |
| Stack | (lane₁ lane₂ … laneₙ -- ) |
Pops n lane addresses and performs atom moves along those lanes. All lanes in a single move instruction are executed simultaneously as one AOD transport operation: every endpoint is resolved against the pre-move atom state, so the result is independent of lane order, and a multi-hop route (x→y then y→z for the same atom) must be split across separate move instructions.
A lane whose source holds no atom is a no-op (AOD rectangle filler), but the trap site still arrives at its destination — so an occupied destination is only legal when its occupant is itself moved by another lane in the same instruction (conveyor chains such as x→y, y→z executed as one shot). A destination occupied by an atom that does not move in the group makes the group not executable.
This executability rule is state-dependent, so it is not checked by the static program validator below (which has no atom-occupancy state). It is enforced by AtomStateData::validate_moves, which reports it as MoveValidationError::DestinationOccupiedByStationaryAtom. An implementation that applies an unvalidated group (AtomStateData::apply_moves) instead models a mover landing on a stationary atom as a collision: both atoms are removed from the location maps and recorded in the state's collision field.
Lane group validation
When an ArchSpec is provided, the validator checks the group of lanes as a whole — not just each lane individually. These constraints reflect the physical limitations of a single AOD (Acousto-Optic Deflector). Each move instruction corresponds to one AOD operation:
Consistency — all lanes in the group must share the same move_type, bus_id, and direction. A single AOD operation cannot mix site-bus and word-bus moves, use different buses, or move atoms in different directions simultaneously.
Bus membership — for site-bus moves, every lane's word_id must be in words_with_site_buses. For word-bus moves, every lane's site_id must be in sites_with_word_buses.
Grid constraint — the physical positions of the lane sources must form a complete grid (Cartesian product of unique X and Y coordinates). An AOD addresses rows and columns independently, so it cannot select an arbitrary subset of positions — it must address every intersection of the selected rows and columns.
For example, if a move group contains lanes at positions (0,0), (0,1), (1,0), and (1,1), this is a valid 2x2 grid. But (0,0), (0,1), (1,0) alone is invalid — the AOD would also address (1,1), so the group must include it.
| Check | Error |
|---|---|
All lanes share move_type, bus_id, direction | Inconsistent |
Site-bus lane word_id in words_with_site_buses | WordNotInSiteBusList |
Word-bus lane site_id in sites_with_word_buses | SiteNotInWordBusList |
| Lane positions form a complete grid | AODConstraintViolation |
QuantumGate (0x11)
local_r — Local R rotation
| Field | Value |
|---|---|
| Device Code | 0x11 |
| Instruction Code | 0x00 |
| Full Opcode | 0x0011 |
| data0 | u32 LE arity |
| data1 | unused |
| data2 | unused |
| Stack | (loc₁ loc₂ … locₙ θ φ -- ) |
Pops 2 float parameters (φ = axis angle, θ = rotation angle) then n location addresses, and applies a local R rotation. The call convention matches the SSA IR: local_r(%φ, %θ, %loc₁, …) — first argument (φ) is pushed last and popped first.
local_rz — Local Rz rotation
| Field | Value |
|---|---|
| Device Code | 0x11 |
| Instruction Code | 0x01 |
| Full Opcode | 0x0111 |
| data0 | u32 LE arity |
| data1 | unused |
| data2 | unused |
| Stack | (loc₁ loc₂ … locₙ θ -- ) |
Pops 1 float parameter (θ = rotation angle) then n location addresses, and applies a local Rz rotation. The call convention matches the SSA IR: local_rz(%θ, %loc₁, …).
global_r — Global R rotation
| Field | Value |
|---|---|
| Device Code | 0x11 |
| Instruction Code | 0x02 |
| Full Opcode | 0x0211 |
| data0–2 | unused |
| Stack | (θ φ -- ) |
Pops 2 float parameters (φ = axis angle, θ = rotation angle), applies a global R rotation. The call convention matches the SSA IR: global_r(%φ, %θ).
global_rz — Global Rz rotation
| Field | Value |
|---|---|
| Device Code | 0x11 |
| Instruction Code | 0x03 |
| Full Opcode | 0x0311 |
| data0–2 | unused |
| Stack | (θ -- ) |
Pops 1 float parameter (θ = rotation angle), applies a global Rz rotation. Since there is only one parameter, it is both pushed last and popped first.
cz — Controlled-Z gate
| Field | Value |
|---|---|
| Device Code | 0x11 |
| Instruction Code | 0x04 |
| Full Opcode | 0x0411 |
| data0–2 | unused |
| Stack | (zone -- ) |
Pops a zone address and applies a CZ gate across the zone.
Measurement (0x12)
measure — Initiate measurement
| Field | Value |
|---|---|
| Device Code | 0x12 |
| Instruction Code | 0x00 |
| Full Opcode | 0x0012 |
| data0 | u32 LE arity |
| data1 | unused |
| data2 | unused |
| Stack | (zone₁ zone₂ … zoneₙ -- future₁ future₂ … futureₙ) |
Pops n zone addresses and pushes n measure futures.
await_measure — Wait for measurement result
| Field | Value |
|---|---|
| Device Code | 0x12 |
| Instruction Code | 0x01 |
| Full Opcode | 0x0112 |
| data0–2 | unused |
| Stack | (future -- array_ref) |
Pops a measure future and pushes an array reference containing the measurement results.
Array (0x13)
new_array — Construct array from stack
| Field | Value |
|---|---|
| Device Code | 0x13 |
| Instruction Code | 0x00 |
| Full Opcode | 0x0013 |
| data0 | [type_tag:8][pad:8][dim0:16] |
| data1 | [pad:16][dim1:16] |
| data2 | unused |
| Stack | (elem₁ elem₂ … elemₙ -- array_ref) |
Constructs an array of dim0 × dim1 elements with element type type_tag. If dim1 is 0, the array is 1-dimensional with dim0 elements.
get_item — Index into array
| Field | Value |
|---|---|
| Device Code | 0x13 |
| Instruction Code | 0x01 |
| Full Opcode | 0x0113 |
| data0 | u16 LE ndims (upper 16 bits unused) |
| data1 | unused |
| data2 | unused |
| Stack | (array_ref idx₁ … idxₙ -- value) |
Pops ndims index values then the array reference, and pushes the indexed element.
DetectorObservable (0x14)
set_detector — Set detector
| Field | Value |
|---|---|
| Device Code | 0x14 |
| Instruction Code | 0x00 |
| Full Opcode | 0x0014 |
| data0–2 | unused |
| Stack | (array_ref -- detector_ref) |
Pops an array reference and pushes a detector reference.
set_observable — Set observable
| Field | Value |
|---|---|
| Device Code | 0x14 |
| Instruction Code | 0x01 |
| Full Opcode | 0x0114 |
| data0–2 | unused |
| Stack | (array_ref -- observable_ref) |
Pops an array reference and pushes an observable reference.
Reserved Opcode Ranges
| Range | Owner |
|---|---|
Device 0x00, inst codes 0x00–0x8F | Reserved for FLAIR. This project uses only 0x02–0x06, 0x64, 0xFF. |
Device codes 0x01–0x0E | Reserved for future FLAIR device types |
Device codes 0x0F–0xFF | Project-specific (currently 0x0F–0x14 allocated) |
Known FLAIR allocations (device 0x00)
| Instruction Code | Purpose |
|---|---|
0x01 | const.bool |
0x10–0x17 | Arithmetic (arith.add_int, arith.add_float, etc.) |
0x20–0x23 | Comparison (cmp.gt_int, cmp.eq_float, etc.) |
0x28–0x2A | Boolean (bool.not, bool.and, bool.or) |
0x30–0x33 | Waveform (waveform.poly4, waveform.delay, etc.) |
0x40–0x43 | Channel (channel.emit, channel.play, etc.) |
0x50–0x52 | Peer messaging |
0x60–0x63 | Control flow (cf.jump, cf.branch, cf.call) |
0x80 | debug.trace |
CLI Reference
The bloqade-bytecode CLI assembles, disassembles, and validates lane-move bytecode programs.
bloqade-bytecode <COMMAND>
Installation
Via the Python package (recommended)
The CLI is bundled in the bloqade-lanes Python wheel and placed on your PATH automatically:
pip install bloqade-lanes
After installation, bloqade-bytecode is available as a command.
Note: The CLI is only included in pre-built platform wheels, not in the source distribution (sdist). If no wheel is available for your platform, use the cargo install method instead.
From source (cargo)
Install the CLI directly from the repository using cargo:
cargo install --path crates/bloqade-lanes-bytecode-cli
This compiles the binary and places it in ~/.cargo/bin/, which is typically on your PATH. No Python installation is required.
Alternatively, build without installing:
just build-cli # Output: target/release/bloqade-bytecode
The binary can be run in place (./target/release/bloqade-bytecode) or copied to a directory on your PATH.
Development install
For local development, this builds the CLI, stages it into the Python package, and installs everything:
just develop
Testing
just test-rust # Run Rust tests (core + CLI crates)
just cli-smoke-test # CLI bytecode validation tests
Commands
assemble
Assemble a text program (.sst) into binary format (.bin).
bloqade-bytecode assemble <INPUT> -o <OUTPUT>
| Argument | Description |
|---|---|
<INPUT> | Input text file (.sst) |
-o, --output <OUTPUT> | Output binary file (required) |
Example:
bloqade-bytecode assemble prog.sst -o prog.bin
# assembled 12 instructions -> prog.bin
disassemble
Disassemble a binary program (.bin) into human-readable text format.
bloqade-bytecode disassemble <INPUT> [-o <OUTPUT>]
| Argument | Description |
|---|---|
<INPUT> | Input binary file (.bin) |
-o, --output <OUTPUT> | Output text file (omit to print to stdout) |
Examples:
# Print to stdout
bloqade-bytecode disassemble prog.bin
# Write to file
bloqade-bytecode disassemble prog.bin -o prog.sst
# disassembled 12 instructions -> prog.sst
The conversion is semantically lossless: assembling and then disassembling a program preserves its instructions, and the disassembler's canonical text output round-trips through text → binary → text.
validate
Validate a program for correctness. Accepts both text (.sst) and binary formats — the format is auto-detected from the file extension.
bloqade-bytecode validate <INPUT> [--arch <ARCH>] [--simulate-stack]
| Argument | Description |
|---|---|
<INPUT> | Input file (.sst = text, otherwise binary) |
--arch <ARCH> | ArchSpec JSON file for address validation |
--simulate-stack | Run stack type simulation (implied by --arch) |
Validation levels:
| Level | When | What it checks |
|---|---|---|
| Structural | Always | Arity bounds, initial_fill ordering |
| Address | --arch provided | Location, lane, zone, and bus validity against the architecture |
| Stack simulation | --simulate-stack or --arch provided | Type safety, stack balance, and (with an arch) the lane/location group checks — consistency, bus membership, AOD grid geometry |
Examples:
# Structural validation only
bloqade-bytecode validate prog.sst
# valid (12 instructions)
# Full validation with architecture and stack simulation
bloqade-bytecode validate prog.sst --arch gemini-logical.json --simulate-stack
# valid (12 instructions)
# Validation failure
bloqade-bytecode validate bad.sst --arch gemini-logical.json
# [0] initial_fill: invalid location address ...
# error: 1 validation error(s)
arch
Pretty-print an architecture specification.
bloqade-bytecode arch <INPUT>
| Argument | Description |
|---|---|
<INPUT> | ArchSpec JSON file |
Example output:
ArchSpec v2.0
Words: 1 word(s), 5 sites/word
Word 0: sites=[(0,0) (1,0) (2,0) (3,0) (4,0)]
Zones: 1 zone(s)
Zone 0: 5x1 grid, 1 site bus(es), 0 word bus(es)
Site bus 0: src=[SiteRef(0), SiteRef(1)] dst=[SiteRef(3), SiteRef(4)]
words_with_site_buses: [0]
modes: 1 mode(s)
default: zones=[0]
Capabilities:
feed_forward: false
atom_reloading: false
The Paths section is only shown when the ArchSpec includes path data. Each path is identified by its 64-bit encoded lane address (in hex) and lists the AOD waypoints (physical coordinates) that define the transport trajectory.
arch validate
Validate an ArchSpec JSON file for internal consistency.
bloqade-bytecode arch validate <INPUT>
| Argument | Description |
|---|---|
<INPUT> | ArchSpec JSON file |
Example:
bloqade-bytecode arch validate gemini-logical.json
# arch spec is valid: gemini-logical.json
File Formats
| Extension | Format | Description |
|---|---|---|
.sst | Text | Human-readable bytecode (one instruction per line, ; comments) |
.bin | Binary | Compact binary encoding (BLQD magic header, 16 bytes per instruction) |
.json | JSON | Architecture specification |
See also the Instruction Quick Reference for a compact summary of all 24 instructions, or the full Instruction Set for encoding details.