Migrating from tProc v1
Note
Content originally contributed by Jay Chien
(PR #412), adapted here
for the current docs structure and verified against qick.asm_v2.
tProc v2 keeps the same basic role as tProc v1 — sequencing pulses, triggers, readout windows, and feedback — but reorganizes both the firmware interface and the Python programming model. This page is a short migration guide for users who already know tProc v1 and want to understand the most important changes before writing tProc v2 programs. For the full picture, see How to play pulses with QICK, Timing with tProcessor v2, and Time units.
Hardware sweeps
In tProc v1 programs, hardware sweeps often required an update() method
with explicit register math. For example, a gain sweep might update the
generator’s gain register with mathi() after each shot:
class Program(RAveragerProgram):
def initialize(self):
self.q_rp = self.ch_page(self.cfg["qubit_ch"])
self.r_gain = self.sreg(self.cfg["qubit_ch"], "gain")
def body(self):
...
def update(self):
self.mathi(self.q_rp, self.r_gain, self.r_gain, "+", self.cfg["step"])
gain_list, avgi, avgq = prog.acquire(soc)
tProc v2 provides higher-level sweep helpers. A program declares a loop with
add_loop(), attaches a swept parameter to that loop with
QickSweep1D(), and later queries the compiled program for the actual
sweep points:
class Program(AveragerProgramV2):
def _initialize(self, cfg):
self.add_loop("gainloop", cfg["steps"])
self.add_pulse(
ch=cfg["qubit_ch"],
name="qubit_pulse",
style="const",
freq=cfg["freq"],
phase=0,
gain=QickSweep1D("gainloop", cfg["gain_start"], cfg["gain_stop"]),
length=cfg["length"],
)
def _body(self, cfg):
self.pulse(ch=cfg["qubit_ch"], name="qubit_pulse", t=0)
iq_list = prog.acquire(soc, rounds=avg, progress=False)
gains = prog.get_pulse_param("qubit_pulse", "gain", as_array=True)
Common swept parameters include frequency, length, time, and gain. For
frequency, length, and gain sweeps, use get_pulse_param() to query the
compiled sweep points:
freqs = prog.get_pulse_param("qubit_pulse", "freq", as_array=True)
lengths = prog.get_pulse_param("qubit_pulse", "length", as_array=True)
gains = prog.get_pulse_param("qubit_pulse", "gain", as_array=True)
For timing sweeps, tag the timed instruction (delay, delay_auto, …)
and use get_time_param():
times = prog.get_time_param("time_tag", "t", as_array=True)
Timing
In tProc v2, pulse and trigger times are written in user-facing units, usually microseconds. The Python API converts these values to tProc timing-clock cycles when the program is compiled. See Timing with tProcessor v2 for the underlying clock model.
Some tProc v1 timing calls have renamed equivalents in QickProgramV2:
tProc v1 |
tProc v2 |
Notes |
|---|---|---|
|
|
Advances the reference time to the end of the last pulse/readout, plus an optional margin. |
|
|
Advances the reference time by a fixed amount, independent of pulse/readout end times. |
(no direct v1 equivalent) |
|
Pauses execution without moving the reference time; see Timing with tProcessor v2. |
Playing pulses
In tProc v1, pulse parameters were typically loaded into generator registers
right before playing a pulse. In tProc v2, pulse settings are stored as
waveforms in waveform memory ahead of time: a pulse can bundle one or more
waveforms, and pulse() just tells the generator which waveform-memory entry
to play. This makes it easy to define several pulses during initialization and
choose which one to play in the program body. See How to play pulses with QICK for the
full workflow.
A typical tProc v2 program:
Declares the generator and readout channels (
declare_gen(),declare_readout()).Adds pulse definitions in
_initialize()(add_envelope(),add_pulse()).Plays those pulses in
_body()withpulse().Uses
trigger()andacquire()/acquire_decimated()when readout data is needed.
Units
tProc v2 APIs generally use natural units instead of raw register values:
Times and pulse lengths are in microseconds.
Frequencies are in MHz.
Phases are in degrees.
Gains are normalized values, usually from
-1to1.
The compiler rounds these values to the nearest supported hardware
representation. To inspect the rounded values actually used by a compiled
program, use get_pulse_param() and get_time_param(). See Time units
for the full reference.