The hardware language

A programme is a list of statements over one device. Each statement is one instruction and one machine cycle: it says what moves where, or which ions a gate, a measurement or a cooling touches. It says nothing about cost. The replay computes the cost, the duration and the heating of every cycle from the device's own primitive tables, and the rules judge each cycle as a whole. The same text runs in the studio's Write pane and, unchanged, in Python through qccd.api.

Syntax

programme  ::=  { statement NEWLINE }
statement  ::=  "p." verb "(" [ arguments ] ")"
verb       ::=  "init" | "fill" | "move" | "shuttle" | "simd" | "rotate"
             |  "gate" | "cool" | "measure" | "reset" | "barrier" | "claim"
arguments  ::=  argument { "," argument }
argument   ::=  literal | name "=" literal            (keywords after positionals)
literal    ::=  string | number | "True" | "False" | "None"
             |  "[" [ literal { "," literal } ] "]"
             |  "{" [ string ":" literal { "," string ":" literal } ] "}"

Statements are Python calls on a programme p; the literals are Python's. A statement may span lines while a bracket is open, which is Python's own rule and the only line-joining rule there is. Positional arguments come first, keywords after.

Semantics

The machine state is a map from ions to sites, a motional excitation n̄ per ion, and a clock. init and fill create the map; every other statement is a transition of it. Transport statements move ions along segments and through junctions; each crossing is priced from the device's curves and adds to n̄. Gates leave positions alone and read n̄ to evaluate their error. Cooling lowers n̄. Instructions execute in order, each atomically; the next starts when the previous ends. Every cycle is then judged by the rules, which is where a programme is refused.

Statements

p.init({ion: site, ...}, quanta=None)

Places the named ions on the named sites. The first statement of every programme: a device starts empty.

state
position := placement; n̄(ion) := 0, or the quanta given. Nothing moves.
cost
0 hops, 0 µs.
rules
R1, R2
IR
init
passes

p.init({"d0": "S1", "d1": "A0"})
no rule failscost 0 · steps 0 · 0 µs · peak n̄ 0.00
open the page, with its Report pane

p.fill(loop=None, prefix="d")

Places one ion on every slot of a loop, d0 on its first site and so on: the packed ring in one line.

state
position := every site of the loop, in order. Nothing moves.
cost
0 hops, 0 µs.
rules
R1
IR
init
passes

p.fill()
no rule failscost 0 · steps 0 · 0 µs · peak n̄ 0.00
open the page, with its Report pane

p.move(ion, src, dst, via=None, cls="shuttle")

One ion, one hop, in its own cycle: the shortest form of a transport instruction.

state
position(ion) := dst; the segment between src and dst, or the segments in via, is crossed once; n̄ grows by the primitives crossed.
cost
the segment's hop, plus a junction_cross priced by the degree of any junction transited; duration from the device's curves.
rules
R1, R2, R3, R4, R8
IR
simd with one participant
passes

p.init({"d0": "S1"})
p.move("d0", "S1", "S2")
no rule failscost 1 · steps 1 · 5 µs · peak n̄ 0.10
open the page, with its Report pane

p.shuttle(ion, [site, site, ...], cls="shuttle")

Walks one ion along a path of site ids, one trap-to-trap step per cycle. Junctions on the way are transited, never rested on.

state
one cycle per step of the path; after each, position(ion) is the next site.
cost
the sum of the hops; here 1 for the plain segment and 3 across the degree-3 junction at S0.
rules
R1, R2, R3, R4, R8, R18
IR
one simd per step
passes

p.init({"d0": "S1"})
p.shuttle("d0", ["S1", "S0", "A0"])
no rule failscost 3 · steps 2 · 105 µs · peak n̄ 3.21
open the page, with its Report pane

p.simd(cls, [[ion, from, to], [ion, from, to, via], ...], mode="inter")

Several ions in one cycle, driven together under one movement class. The rules judge the cycle as a whole: one waveform, one direction per loop, no exchanges.

state
every listed ion moves at once; position := the listed destinations.
cost
cost sums over the participants; depth and duration take the maximum, because the cycle waits for its slowest ion.
rules
R1, R2, R3, R4, R4d, R5, R8, R11
IR
simd
passes

p.init({"d0": "S1", "d1": "S4"})
p.simd("shuttle", [["d0", "S1", "S2"], ["d1", "S4", "S5"]])
no rule failscost 2 · steps 1 · 5 µs · peak n̄ 0.10
open the page, with its Report pane

p.rotate(delta, loop=None)

Turns a closed loop: every ion on it moves delta slots forward (negative: back). One instruction, one movement template driven |delta| times.

state
position(ion) := slot + delta (mod the loop) for every ion on the loop.
cost
|delta| unit cycles, each the full loop's hops summed and the deepest edge as its depth.
rules
R4, R11
IR
simd with a loop_shift template
passes

p.fill()
p.rotate(2)
no rule failscost 16 · steps 2 · 200 µs · peak n̄ 3.21
open the page, with its Report pane

p.gate(name, [[control, target], ...], sites=None)

A gate cycle. Two-qubit: every pair sits in one site whose zone allows gates, control first. Single-qubit: an empty pair list and the site named.

state
positions unchanged; the gate's error is evaluated from each ion's n̄ at gate time.
cost
0 hops; the gate's duration from the primitive table.
rules
R6, R6b, R7, R7c, R12, R13, R16
IR
gate
passes

p.init({"d0": "A0", "d1": "A0"})
p.cool()
p.gate("CX", [["d0", "d1"]])
no rule failscost 0 · steps 2 · 325 µs · peak n̄ 0.02
open the page, with its Report pane

p.cool(ions=None)

Cools ions back toward the motional ground state: all of them when no list is given (a broadcast), else the listed ones.

state
n̄(ion) := what the cooling primitive leaves, for the cooled ions.
cost
the cooling primitive's duration; one op for every ion under broadcast.
rules
R6, R7, R7c
IR
cool
passes

p.init({"d0": "S1"})
p.shuttle("d0", ["S1", "S0", "A0"])
p.cool()
no rule failscost 3 · steps 3 · 405 µs · peak n̄ 3.22
open the page, with its Report pane

p.measure([ion, ...])

Reads the listed ions out. Each must sit in a zone with SPAM (state preparation and measurement).

state
positions unchanged.
cost
the measure primitive's duration.
rules
R6
IR
measure
passes

p.init({"d0": "A0"})
p.measure(["d0"])
no rule failscost 0 · steps 1 · 120 µs · peak n̄ 0.01
open the page, with its Report pane

p.reset([ion, ...])

Puts the listed ions back to |0>. The same zone requirement as measuring.

state
positions unchanged.
cost
the reset primitive's duration.
rules
R6
IR
reset
passes

p.init({"d0": "A0"})
p.reset(["d0"])
no rule failscost 0 · steps 1 · 50 µs · peak n̄ 0.00
open the page, with its Report pane

p.barrier()

A cycle in which nothing happens: an explicit synchronisation point, a marker between phases of a programme.

state
unchanged.
cost
0 hops, 0 µs.
rules
IR
barrier
passes

p.init({"d0": "S1"})
p.move("d0", "S1", "S2")
p.barrier()
p.move("d0", "S2", "S3")
no rule failscost 3 · steps 2 · 105 µs · peak n̄ 3.21
open the page, with its Report pane

p.claim(total_cost=..., total_steps=..., ...)

Annotates the programme with the totals its author claims. Claims are not content: the replay recomputes everything and R9 rejects any claim it cannot reproduce.

state
unchanged; the claim is recorded on the programme.
cost
none.
rules
R9
IR
the programme's metrics
passes

p.init({"d0": "S1"})
p.move("d0", "S1", "S2")
p.claim(total_cost=1, total_steps=1)
no rule failscost 1 · steps 1 · 5 µs · peak n̄ 0.10
open the page, with its Report pane

Beneath the text: the IR

Every statement becomes one instruction of the control IR, the JSON the compiler emits and the verifier replays. The Write pane and the compiler meet there.

statementinstruction typecarries
initinitplacement, quanta
fillinitplacement over a loop
move / shuttle / simdsimdclass, mode, participants (ion, from, to, via)
rotatesimdclass, a loop_shift template, holds
gategategate, pairs, sites
coolcoolbroadcast or ions
measure / resetmeasure / resetions
barrierbarriernothing
claimmetricsclaimed totals, checked by R9

The IR reference is docs/tsir; the device language the programmes run on is docs/adl.