Program, configuration and trace reference#
The simulator accepts ELF or raw machine code and JSON configuration files. Run files, serialized profiles and traces use schema version 1.
Program input#
ELF programs must be little-endian ELF32 RISC-V executables with valid,
nonoverlapping PT_LOAD segments and an aligned executable entry address.
Compressed-instruction flags are rejected. Loading enforces segment permissions
and zero-fills BSS.
Raw programs require --raw-base and a nonempty file whose size is a multiple
of four bytes. The simulator reads machine code, not assembly text.
Memory accesses are little-endian. Misaligned halfword, word and instruction accesses raise typed faults. Unmapped bytes within configured RAM can hold data, but instruction fetches require executable mappings.
The ISA is RV32I with codeword, timing and measurement-register instructions.
Registers and addresses are 32 bits. ECALL with a7 = 93
ends the program; a0 retains its 32-bit program exit status. A nonzero status
is a program outcome and does not raise an architectural fault. Other ECALLs
and EBREAK raise distinct traps. FENCE is supported; FENCE.I, privileged instructions and unselected extensions raise
IllegalInstruction.
CPU selection#
rv32 is the default CPU model. vliw accepts the same instructions and adds
32-bit words containing two cw operations.
qsbit-sim --program program.elf --cpu-model rv32
qsbit-sim --program program.elf --cpu-model vliw
In a run file, set "cpu_model": "vliw". Assemble paired operations with
cw.bundle; selecting the CPU model does not rewrite the program.
rv32 rejects bundle instructions with IllegalInstruction.
Quantum instruction encoding#
Scalar control instructions use opcode 0x0b in the RISC-V custom-0 space.
31 25 24 20 19 15 14 12 11 7 6 0
funct7 rs2 rs1 funct3 rd opcode
funct3 |
Instruction |
Fields |
|---|---|---|
0 |
|
|
0 |
|
|
0 |
|
|
0 |
|
|
1 |
|
rs1 selects a GPR; funct7, rs2 and rd are zero. |
2 |
|
Bits 31–15 hold an unsigned 17-bit interval; rd is zero. |
3 |
|
rs1 holds a 5-bit qubit index; funct7 and rs2 are zero. |
6 |
|
Bits 31–15 hold an unsigned 17-bit controller address; rd is zero. |
funct3 values 4, 5 and 7 are reserved. Invalid fixed fields raise
IllegalInstruction. sync schedules a synchronization event with a connected
neighbor; an unconnected target raises UnsupportedSynchronization.
send and recv are unsupported.
The port operand selects a source port in the codeword map;
its events may use different output ports.
Dual-codeword encoding#
cw.bundle uses opcode 0x2b in the RISC-V custom-1 space and requires
the vliw CPU model.
Word bits |
Field |
|---|---|
31 |
Zero; a set bit raises |
30–19 |
Operation 1. |
18–7 |
Operation 0. |
6–0 |
Opcode |
Each operation occupies 12 bits:
Operation bits |
Field |
|---|---|
11 |
One for an immediate codeword; zero for a register operand. |
10 |
One for an immediate port; zero for a register operand. |
9–5 |
Codeword immediate or register index. |
4–0 |
Port immediate or register index. |
The GNU assembler macro accepts four operands and two optional modes:
cw.bundle port0, codeword0, port1, codeword1, mode0=3, mode1=3
Port and codeword arguments are integers from 0 to 31. Register operands use register numbers; their resolved values retain all 32 bits. Each mode defaults to 3:
Mode |
Port operand |
Codeword operand |
|---|---|---|
0 |
Register |
Register |
1 |
Immediate |
Register |
2 |
Register |
Immediate |
3 |
Immediate |
Immediate |
cw.bundle 0, 1, 1, 2
li x5, 1
li x6, 2
wait.i 1
cw.bundle 0, 1, 5, 6, 3, 0
Both bundles prepare codeword 1 on source port 0 and codeword 2 on source port 1.
The two operations in each bundle use the current time point.
wait advances that time point in a separate instruction. A bundle writes
no GPR and retires once, advancing the PC by four bytes.
Instruction effects#
cw prepares the mapped events at the current time point without writing
a GPR. A measurement increments the target qubit’s pending count.
A positive wait enqueues the pending time point and its events, waits for
acknowledgment, then advances the time point in TCU cycles.
wait.i 0 and wait.r x0 enqueue the current time point with permission to
wait for subsequent work. The instruction completes on enqueue acknowledgment.
After that point triggers, an empty timing queue pauses the TCU logical timer;
physical time continues. See pause and deadline rules
for admission, resumption and restoration of strict deadlines.
fmr enqueues pending events and waits for all accepted measurements of the
selected qubit to complete. It copies the latest result into rd without
changing the measurement register. Further cw instructions require a
wait after the submitted point, or a preceding wait 0 that left the
current point open for subsequent codewords.
The exit ECALL enqueues pending events and halts the CPU after acknowledgment. Simulation completion follows the drain conditions.
quantum.inc provides GNU assembler macros.
sim_exit expands to li a0, 0; li a7, 93; ecall.
Instruction and control operation names#
Instruction |
Command payload |
|---|---|
|
|
|
|
|
|
Exit ECALL |
|
|
|
CLI and profile#
Start a run with --config FILE or --program FILE. Run qsbit-sim --help
for the executable’s option list.
Option |
Meaning |
|---|---|
|
Read a schema-1 JSON run file. Paths inside it are relative to that file. |
|
Load an ELF program, or raw input when |
|
Select |
|
Select a backend; default is mock. Accepts registered names and |
|
List discovered backends and missing dependencies. |
|
Print the selected backend’s descriptor and configuration schema. |
|
Export an editor schema for backend options. |
|
Print a run configuration template for the selected backend. |
|
Load and validate the run without executing instructions or writing outputs. |
|
Overlay a strict JSON profile on the current settings. |
|
Write the complete default profile and exit. |
|
Override the seed and TCU startup offset, respectively. |
|
Load raw machine words at this address. |
|
Select simulated RAM. |
|
Write JSONL events and JSON final state. |
|
Include a final 32-bit memory word; repeatable. |
|
Write all RAM bytes starting at memory base. |
|
Set mock bits by measurement ID, starting at one; omitted IDs return zero. |
|
Schedule a session reset; repeated ticks must be sorted and unique. |
|
Reverse process registration for diagnostic runs. |
|
Add a module directory for the selected Python adapter. |
Options are applied from left to right. Later values override earlier ones,
including values loaded by a run file. Within a run file, profile_file is
applied before inline profile. Unknown options and JSON keys are errors.
Exit status |
Meaning |
|---|---|
0 |
The run completed, or |
1 |
A fault occurred during simulation. |
2 |
Input, configuration or construction failed. |
An in-simulation fault writes a partial trace and failed summary when the output paths are usable.
Run file#
A run file combines the program, backend, profile and output paths:
{
"schema": 1,
"program": "program.elf",
"backend": "mock",
"outcomes": [true],
"inspect": [4096],
"trace": "results/feedback.jsonl",
"summary": "results/feedback.json"
}
The program must exist at the path shown, relative to this file. Output parent directories are created as needed.
Field |
Type and meaning |
|---|---|
|
Required integer |
|
Program path. |
|
Per-core IDs, ELF programs, profiles, CPU models and synchronization capacities. Replaces |
|
Neighbor addresses, directional delays in TCU cycles and signal capacities. |
|
|
|
Built-in name, registered adapter name or |
|
Backend-owned options; see backend configuration. |
|
Optional repeated-simulation strategy. |
|
Include |
|
Batch settings shared by all backends: |
|
Optional decoder configuration: MMIO address, bounded transport queues, algorithms and timing. |
|
Optional editor schema URI; runtime validates through the selected adapter. |
|
Path to a separate profile overlay. |
|
Inline profile overlay. |
|
Output paths. |
|
Optional adapter module directory. |
|
RAM addresses and size and optional raw load address. |
|
Array of integer reset ticks. |
|
Array of 32-bit addresses to inspect. |
|
Array of booleans indexed by measurement ID, starting at one; omitted IDs return zero. |
|
Boolean diagnostic option. |
Simulation profile#
A simulation profile sets clocks, capacities, communication delays and
codeword mappings. Supply it with --profile, or in a run file’s profile
and profile_file fields.
Use --dump-default-profile for a complete machine-readable profile.
An overlay changes only the supplied fields.
Fields |
Units or role |
|---|---|
|
Clock objects with integer |
|
Initial TCU start tick, reused as an offset on reset; global simulation watchdog deadline. |
|
CPU periods from memory acceptance to service completion. |
|
Mailbox communication latency in receiver edges for time-point requests and enqueue replies. |
|
Receiver edges for the independent result paths. |
|
Timing entries, entries per port and staged events. |
|
Maximum outstanding measurements on each delivery path. |
|
Port count, qubit count (1–32) and maximum events per port per time point. |
|
Random seed and fast-path enable flag. |
|
Source port and codeword entries and their event lists. |
|
Shared gate definitions with two required output endpoints. |
The serialized profile uses schema: 1. Each mapping has port, codeword and
a nonempty actions array.
Codeword mappings#
A mapping is looked up by source port and codeword. Each selected event
has its own core-local output port; neither port is necessarily a qubit index.
Simulator adds a per-core offset when sending events to the shared device,
which uses globally remapped ports.
An event selects kind, output port, operation, targets and resources.
It also supplies delay and duration. Gates accept amplitude; pulses accept
amplitude and axis; acquisitions accept discriminator_delay and separate_arm.
Fields belonging to another event kind are rejected. For gates and pulses, execution_flag selects
always (default), last_one, last_zero or equal. Measurement-dependent conditions
require a single-qubit gate or pulse and enabled fast feedback. A resource has a numeric
id and an exclusive boolean. Two overlapping events sharing that resource
conflict if either reservation is exclusive. The same configured core-local
output port cannot host overlapping events, even when their resource declarations
differ. Equal local port numbers on different cores map to distinct device ports.
A two-qubit gate can reserve both target resources. Its two configured outputs
share that reservation when their physical intervals coincide. Other events on
the same target may overlap only when both are pulses or one is a discriminator arm.
A measurement sample and an ideal gate starting on the same target at the
same tick also conflict.
Periods and event durations are positive. Discriminator delay may be zero. Pulse amplitude uses radians/ns; a rotation gate uses radians. Backend support is checked when an event is requested, so a profile may contain entries unused by the chosen backend.
Two-port gate outputs#
The default CX requires codeword 6 on port 0 and codeword 10 on port 1 at the same physical start tick. Both instructions can come from one core. Distributed programs can place one output on each core.
two_qubit_gates defines each gate’s unique name, backend operation, ordered
pair of targets, positive duration in ns, optional resources and exactly two
inputs. Each input names core, local port and codeword. The two inputs must
use distinct output ports; an input cannot belong to more than one gate definition.
The single-program core ID is 0. All cores share the same gate definitions.
Each input maps to one unconditional gate_output action whose gate names the
definition. It uses the mapping’s port and inherits the gate duration. delay
sets its output latency in ns. Targets and resources come from the shared gate,
not from the output action. An explicit duration must equal the gate duration.
This profile fragment replaces the codeword and two-qubit gate tables:
{
"two_qubit_gates": [{
"name": "cx01", "operation": "cx", "targets": [0, 1], "duration": 20,
"inputs": [
{"core": 0, "port": 0, "codeword": 6},
{"core": 0, "port": 1, "codeword": 10}
],
"resources": [{"id": 0}, {"id": 1}]
}],
"mappings": [
{"port": 0, "codeword": 6, "actions": [{"kind": "gate_output", "gate": "cx01"}]},
{"port": 1, "codeword": 10, "actions": [{"kind": "gate_output", "gate": "cx01"}]}
]
}
The shared device collects all starts at fire_tick + delay, validates both
outputs and applies the ideal gate once at that tick. Missing or misaligned
inputs raise GateInputMismatch before the backend changes state at that
boundary. Duplicate outputs on one port raise ResourceConflict. The device
does not wait for a late input. Reset discards both active and pending outputs.
Set two_qubit_gates to an empty array when replacing the default mappings with
a profile that has no paired gate outputs. Explicit kind: "gate" mappings
apply backend gates directly. Neither mode integrates a physical two-qubit pulse
sequence or estimates fidelity loss from waveform misalignment.
JSONL trace#
CodewordQueued records codeword preparation; TimingPointSubmitted,
TimingPointEnqueued and EnqueueAcknowledged record the enqueue request, insertion
and acknowledgment of a time point and its events. TimingPointTriggered records the
event trigger.
Each line is a JSON object with schema: 1. Ticks are nondecreasing and use
nanoseconds. The common fields are tick, epoch, kind, id, label,
cycle, port, codeword, operation, targets, detail and value.
CPU records also use pc, word, rd, next_pc and registers.
Unused scalars are zero; unused strings and arrays are empty. Interpret a field
according to kind rather than treating zero as a missing value.
Event kind |
Meaning and significant fields |
|---|---|
|
|
|
Instruction ID, CPU cycle, PC, word, destination, next PC, result and all registers. |
|
CPU cycle and |
|
Held instruction and reason, or younger instructions discarded on a branch or exit, respectively. |
|
Instruction ID, accumulated positive wait intervals in |
|
Label and accumulated positive wait intervals in |
|
Label, current TCU cycle and post-enqueue timing occupancy in |
|
Enqueue label acknowledged to the CPU. |
|
Label and TCU cycle. |
|
Requesting |
|
Receiving |
|
Requesting |
|
|
|
TCU logical |
|
Suppressed event ID and label. |
|
Event ID, label, resolved port, codeword, operation and targets. |
|
Event identity and duration in |
|
Event ID, label, port, operation and targets. |
|
One paired gate application; |
|
Measurement ID, target and bit. |
|
Measurement ID, target and bit delivered before the CPU step; FMR can read it on this edge. |
|
Measurement ID, target and bit used to update execution flags after the triggering decision. |
|
Reading instruction ID, target qubit and returned bit. |
|
Request identity, requesting |
|
Decoder processing and result lifetime; decoder ID in |
|
Last enqueued label when the TCU receives closure. |
|
New epoch and aborted event IDs where applicable. |
|
An old-epoch completion was ignored. |
|
Typed error name in |
|
Successful full-drain stop tick. |
Instruction, label, physical-event and measurement IDs occupy separate
namespaces. Correlate records by event kind, epoch and the appropriate ID.
The cycle field is a dimensionless index, not nanoseconds:
Trace kind |
|
Selected other fields |
|---|---|---|
|
CPU edge index relative to CPU phase |
Retirement |
|
Accumulated positive wait intervals; excludes the TCU’s one-cycle spacing for zero-interval points |
|
|
Current logical TCU cycle in this epoch |
|
|
Current logical TCU cycle in this epoch |
|
Other kinds |
Interpret only where explicitly defined; otherwise zero |
|
CPU pipeline snapshots#
CpuPipelineUpdated.pipeline contains fetch, fetched, decode, execute
and halted. The snapshot records state after the CPU has processed responses,
retirement, pipeline movement and any new fetch request on that edge.
Each occupied slot contains an instruction id, pc, word and discarded.
An empty slot is null. fetch is the outstanding memory request, so its
word is null; fetched holds a returned instruction waiting to enter decode.
discarded: true marks a fetch whose response will be ignored after a branch
or halt. Decode and execute slots contain instruction words.
The snapshot is emitted on the first CPU edge after reset and whenever slot
contents or halted change. Unchanged snapshots are omitted. CpuStalled
identifies a blocked instruction in execute. Retirement commits within execute;
it does not occupy a separate pipeline slot.
Identity scopes#
Identity |
Allocation and scope |
Reset behavior |
|---|---|---|
Epoch |
Simulator session identity |
Incremented; global time continues |
Instruction ID |
CPU instruction identity within an epoch |
CPU instruction sequence restarts |
Control-event ID |
Timing control-generated event identity within an epoch |
Sequence restarts |
Label |
Timing control-generated time point identity within an epoch |
Sequence restarts; zero marks an empty stream |
Measurement ID |
MeasurementRegisters measurement sequence within an epoch |
Sequence restarts |
Fetch generation |
CPU identity for pending instruction fetches |
Updated when old fetch work is invalidated |
A measurement reference contains its epoch, measurement ID and target qubit. Match trace records using their kind, epoch and documented identity.
Independent events at the same tick may be compared as a set; ordering required on one target still applies. A consumer must reject unknown schema versions.
Summary file#
The JSON summary contains success status, stop tick, cpu_model, backend,
resolved backend options and execution settings, complete profile, fingerprint, final CPU registers
and PC, program exit_code, requested memory words, measurement
registers and statevector entries as [real, imaginary] pairs.
measurement_registers is indexed by qubit. Each entry contains value,
pending and valid; valid is true when pending is zero.
Backends without statevector inspection return an empty array. A backend may
instead supply density_matrix as rows of [real, imaginary] entries.
On successful completion, the quantum state includes evolution through stop_tick.
exit_code is the value of a0 after an acknowledged exit ECALL, or null
when the CPU has not halted. success describes simulator completion without
a fault; consumers classify program success separately using the exit status.
For multicore runs, each entry in cores contains id, cpu_model,
configuration (the resolved core profile), registers, pc, exit_code,
measurement_registers and drained. These per-core fields replace the
single-core fields at the top level; configuration_hash is omitted.
sync_connections records the synchronization links. Quantum state and
stop_tick remain shared top-level fields.