APS2 Instruction Set¶
Abstract Instructions¶
Arbitrary control flow requires three concepts: sequences, loops (repetition) and conditional execution. We add to this set the concept of subroutines because of their value in structured programming and memory re-use.
The BBN APS2 has two memories: a waveform memory and an instruction memory. These memories are accessed via an intermediate caching mechanism to provide low-latency access to nearby sections of memory. In addition, the APS has four other resources available for managing control flow: a repeat counter, an instruction counter, a stack, and a comparison register. The instruction counter points to the current address in instruction memory. The APS2 sequence controller reads and executes operations in instruction memory at the instruction pointer. Unless the instruction specifies otherwise, by default the controller increments the instruction pointer upon executing each instruction. The available abstract instructions are:
We explain each of these instructions below.
SYNC—Halts instruction dispatch until waveform and marker engines have executed all queued instructions. The write flag should be set to broadcast this instruction.
WAIT—Indicates that waveform and marker engines should wait for a trigger before continuing. The write flag should be set to broadcast this instruction.
WAVEFORM—Indicates that the APS should play back length N data points starting at the given waveform memory address. An additional flag marks the waveform as a time-amplitude variant, which outputs data at a fixed address for N counts.
MARKER—Indicates the APS should hold marker channel in state (0 or 1) for N samples.
LOAD_REPEAT—Loads the given value into the repeat counter.
REPEAT—Decrements the repeat counter. If the resulting value is greater than zero, jumps to the given instruction address by updating the instruction counter.
CMP—Compares the value of the comparison register to the mask N with any of these operators: \(=, \neq, >, <\). So, (CMP \(\neq\) 0) would be true if the comparison register contains any value other than zero.
LOAD_CMP—Loads the comparison register with the next value from the message queue (received from the trigger distribution module). If the queue is empty, this instruction will halt execution until a message arrives.
GOTO—Jumps to the given address by updating the instruction counter.
CALL—Pushes the current instruction and repeat counters onto the stack, then jumps to the given address by updating the instruction counter.
MODULATOR—A modulator instruction.
RETURN—Moves (pops) the top values on the stack to the instruction and repeat counters, jumping back to the most recent CALL instruction.
PREFETCH—Prefetches a cache line of instructions starting at address
NOOP—Null or No Operation
These instructions easily facilitate two kinds of looping: iteration and while loops. The former is achieved through use of LOAD_REPEAT to set the value of the repeat counter, followed by the loop body, and terminated by REPEAT to jump back to the beginning of the loop. The latter is achieved by a conditional GOTO followed by the loop body, where the address of the GOTO is set to the end of the loop body.
Subroutines are implemented with the CALL and RETURN instructions. The address of a CALL instruction can indicate the first instruction in instruction memory of a subroutine. The subroutine may have multiple exit points, all of which are marked by a RETURN instruction.
Conditional execution is directly supported by the GOTO, CALL, and RETURN instructions. When these instructions are preceeded by a CMP instruction, their execution depends on the comparison resulted. Consequently, the stated instruction set is sufficient for arbitrary control flow.
Finally, filling the waveform cache is time consuming, requiring several hundred microseconds. Therefore, the PREFETCH instruction allows one to schedule this costly operation during “dead time” in an experiment, e.g. immediately prior to instructions that wait for a trigger.
Concrete Instructions¶
The APS2 uses a 64-bit instruction format, divided into header (bits 63-56), and payload (bits 55-0). The format of the payload depends on instruction op code.
Instruction header (8-bits)¶
Bit(s) | Description |
---|---|
7-4 | op code |
3-2 | engine select (0-3) |
1 | reserved |
0 | write flag |
The op code determines the instruction type. For MARKER instructions, the ‘engine select’ field chooses the output channel of the instruction. The write flag is used to indicate the final instruction in a group of WAVEFORM and MARKER instructions to be sent simultaneously to their respective execution engines.
Instruction op codes¶
Code | instruction |
---|---|
0x0 | WAVEFORM |
0x1 | MARKER |
0x2 | WAIT |
0x3 | LOAD_REPEAT |
0x4 | REPEAT |
0x5 | CMP |
0x6 | GOTO |
0x7 | CALL |
0x8 | RETURN |
0x9 | SYNC |
0xA | MODULATOR |
0xB | LOAD_CMP |
0xC | PREFETCH |
Instruction payload (56-bits)¶
The 56-bit payload formats for the various instruction op codes are described below.
WAVEFORM¶
Bit(s) | Description |
---|---|
47-46 | op code (0 = play waveform, 1 = wait for trig, 2 = wait for sync, 3 = prefetch) |
45 | T/A pair flag |
44-24 | count |
23-0 | address |
The top two bits of the WAVEFORM payload are an op code for the waveform engine. A PLAY_WAVEFORM op code causes the waveform engine to play the waveform starting at address for count quad-samples. When the time/amplitude pair flag is set, the waveform engine will create a constant- amplitude waveform by holding the analog output at the value given at address for count quad-samples. The WAIT_FOR_TRIG and WAIT_FOR_SYNC op codes direct the waveform engine to pause until receipt of an input trigger or a sequence SYNC input, respectively. The PREFETCH op code causes the waveform cache to prefetch 64k samples from addresss into the pending waveform cache bank.
MARKER¶
Bit(s) | Description |
---|---|
47-46 | op code (0 = play marker, 1 = wait for trig, 2 = wait for sync) |
45-37 | reserved |
36-33 | transition word |
32 | state |
31-0 | count (firmwave versions 2.5-2.33 support only 20 bit count) |
The top two bits of the MARKER payload are an op code for the marker engine. A PLAY_MARKER op code causes the marker engine to hold the marker output in value state for count quad-samples. When the count reaches zero, the marker engine will output the 4-bit transition word. One use of this transition word is to achieve single- sample resolution on a low-to-high or high-to-low transition of the marker output. The WAIT_FOR_TRIG and WAIT_FOR_SYNC op codes function identically to the WAVEFORM op codes.
CMP¶
Bit(s) | Description |
---|---|
9-8 | cmp code (0 = equal, 1 = not equal, 2 = greater than, 3 = less than) |
7-0 | mask |
The CMP operation compares the current value of the 8-bit comparison register to mask using the operator given by the cmp code. The result of this comparison effects conditional execution of following GOTO, CALL, and RETURN instructions.
LOAD_CMP¶
Loads the comparison register with the next value from the message queue (received from the trigger distribution module). If the queue is empty, this instruction will halt execution until a message arrives. This instruction ignores all payload data.
GOTO, CALL, and REPEAT¶
Bit(s) | Description |
---|---|
25-0 | address |
Jumps to address. For GOTO and CALL, the jump may be conditional if proceeded by a CMP instruction. For REPEAT, the jump is conditioned on the repeat counter.
LOAD_REPEAT¶
Bit(s) | Description |
---|---|
15-0 | repeat count |
The repeat count gives the number of times a section of code should be repeated, i.e. to execute a sequence N times, one uses a repeat count of N-1.
PREFETCH¶
Bit(s) | Description |
---|---|
25-0 | address |
Prefetches a cache-line (128 instructions) starting at address into the subroutine cache.
WAIT and SYNC¶
Bit(s) | Description |
---|---|
47-46 | op code (0 = play waveform/marker, 1 = wait for trig, 2 = wait for sync) |
The payloads for the WAIT and SYNC instructions must also be valid WAVEFORM and MARKER payloads. Therefore, in addition to indicating WAIT or SYNC in the instruction header, the instruction type must also appear in the payload. The write flag should be set to immediately dispatch this instruction.
RETURN¶
This instruction ignores all payload data.
MODULATOR¶
Bit(s) | Description |
---|---|
47-45 | op code |
44 | reserved |
43-40 | nco select |
39-32 | reserved |
31-0 | payload |
The modulator op codes are enumerate as follows:
- 0x0
- modulate using selected nco for count (payload)
- 0x1
- reset selected nco phase accumulator
- 0x2
- wait for trigger
- 0x3
- set selected nco phase increment (payload)
- 0x4
- wait for sync
- 0x5
- set selected nco phase offset (payload)
- 0x6
- reserved
- 0x7
- update selected nco frame (payload)
The nco select bit field gives one bit to each NCO. In the current firmware
there are two NCO’s. For example, to set the frequency of the second NCO the bit
field would read 0010
or to reset the phase of both NCOs it would read 0011
.
All phase payloads are fixed point integers UQ2.28 representing portions of a circle. The frequency is determined with respect to the 300MHz system clock. For example, setting a phase increment of 1/3 * 2^28 = 0x02aaaaab gives a modulation frequency of 50MHz. Integers greater than 2 give frequencies greater than the Nyquist frequency of 600MHz and will be folded back in as negative frequencies.
Example Sequences¶
Ramsey¶
To give a concrete example of construction of a standard QIP experiment in the APS2 format, consider a Ramsey experiment consisting of two π/2-pulses separated by a variable delay. If the waveform memory has a null-pulse at offset 0x00 and a 16-sample π/2-pulse at offset 0x01, then the Ramsey sequence might in abstract format would look like:
SYNC
WAIT
WAVEFORM 0x01 4
WAVEFORM T/A 0x00 10
WAVEFORM 0x01 4
SYNC
WAIT
WAVEFORM 0x01 4
WAVEFORM T/A 0x00 20
WAVEFORM 0x01 4
SYNC
WAIT
WAVEFORM 0x01 4
WAVEFORM T/A 0x00 30
WAVEFORM 0x01 4
.
.
.
GOTO 0x00
The {SYNC, WAIT} sequences demarcate separate Ramsey delay experiments, where the SYNC command ensures that there is no residual data in any execution engine before continuing, and the WAIT command indicates to wait for a trigger. The GOTO command at the end of the sequence is crucial to ensure that the instruction decoder doesn’t “fall off” into garbage data at the end of instruction memory.
CPMG¶
The Carr-Purcell-Meiboom-Gill pulse sequence uses a repeated delay-π-delay sequence to refocus spins in a fluctuating environment. The π pulse is offset by 90 degrees to the intial π/2 pulse that creates the coherence and even numbers of π pulses are prefered for robustness. We can pull in many elements of arbitrary flow control to compactly describe this sequence. We will use a waveform library with three entries: a null pulse at offset 0x00, a 16-sample π/2-pulse at offset 0x01, and a 16-sample π-pulse at offset 0x05. Note that offsets are also written in terms of quad-samples, so the memory address range of the first π/2 pulse is [0x01,0x04]. The Hahn echo delay-π-delay is considered a subroutine. To ensure even multiples a CPMG subroutine then loops over the Hahn echo twice. The two subroutines are placed at the cache-line aligned address 1024 Then a CPMG sequence with 2, 4, 8, 16 … loops is:
SYNC
WAIT
WAVEFORM 0x01 4 # first 90
LOAD_REPEAT 0
CALL 1024 # call the CPMG subroutine
REPEAT 3
LOAD_REPEAT 1
CALL 1024 # call the CPMG subroutine
REPEAT 6
LOAD_REPEAT 3
CALL 1024 # call the CPMG subroutine
REPEAT 6
LOAD_REPEAT 7
CALL 1024 # call the CPMG subroutine
REPEAT 9
.
.
.
WAVEFORM 0x01 4 # final 90
GOTO 0x00
NOOP
NOOP
NOOP
.
.
.
# pad with NOOP's to address 1024
# start CPMG subroutine
LOAD_REPEAT 1
CALL 1028
REPEAT 1024
RETURN
# start Hahn echo subroutine
WAVEFORM T/A 0x00 25 # delay
WAVEFORM 0x05 4 # π pulse
WAVEFORM T/A 0x00 25 #delay
RETURN
Active Qubit Reset¶
Here we dynamically steer the sequence in response to a qubit measurment in order to actively drive the qubit to the ground state:
GOTO 0x06 # jump over 'Reset' method definition
# start of 'Reset' method
WAIT # wait for qubit measurement data to arrive
CMP = 0 # if the qubit is in the ground state, return
RETURN
# otherwise, do a pi pulse
WAVEFORM 0x05 4
GOTO 0x01 # go back to the beginning of 'Reset'
# end of 'Reset' method
SYNC
CALL 0x01 # call 'Reset'
# qubit is reset, do something...
.
.
.
GOTO 0x00
In this example, we define a ‘Reset’ method for flipping the qubit state if it is not currently in the ground state. The method is defined in instructions 1-5 of the instruction table. We preceed the method definition with a GOTO command to unconditionally jump over the method definition. The structure of the ‘Reset’ method is a while loop: it only exits when the comparison register is equal to zero. We assume that this register’s value is updated to the current qubit state on every input trigger.