See also
A Jupyter notebook version of this tutorial can be downloaded here.
LINQ Routing Configuration#
Every piece of data sent via LINQ-based feedback is tagged with an 8-bit id that controls which sequencers receive it. There are three routing modes, which differ primarily in latency. For a full overview of latencies per data type and routing mode, see the LINQ-based feedback documentation.
IDs 1–15 are reserved for self-cast and require no routing configuration. IDs 16–255 must be explicitly configured using one of the routing commands below before the sequencers are armed:
Command |
Description |
|---|---|
|
Reset all routing to factory defaults. |
|
Intra-cast: route |
|
Multi-cast: route |
|
Broadcast: route |
ID 0 is reserved to disable sharing of a specific data type.
This tutorial demonstrates all three routing modes using Q1 register / immediate transfers, which are supported on every module variant.
Hardware Requirements#
A Qblox Cluster with one module containing at least two sequencers.
Setup#
[1]:
from __future__ import annotations
from qcodes.instrument import find_or_create_instrument
from qblox_instruments import Cluster, ClusterType
Scan For Clusters#
We scan for the available devices connected via ethernet using the Plug & Play functionality of the Qblox Instruments package (see Plug & Play for more info).
!qblox-pnp list
[2]:
cluster_ip = "10.10.200.42"
cluster_name = "cluster0"
Connect to Cluster#
We now make a connection with the Cluster.
[3]:
cluster: Cluster = find_or_create_instrument(
Cluster,
recreate=True,
name=cluster_name,
identifier=cluster_ip,
dummy_cfg=(
{
2: ClusterType.CLUSTER_QCM,
4: ClusterType.CLUSTER_QRM,
6: ClusterType.CLUSTER_QCM_RF,
8: ClusterType.CLUSTER_QRM_RF,
10: ClusterType.CLUSTER_QTM,
12: ClusterType.CLUSTER_QRC,
16: ClusterType.CLUSTER_QSM,
}
if cluster_ip is None
else None
),
)
cluster.reset()
print(cluster.get_system_status())
Status: ERROR, Flags: FEEDBACK_NETWORK_CALIBRATION_FAILED, Slot flags: NONE
Get connected modules#
[4]:
# QRC modules
modules = cluster.get_connected_modules(lambda mod: mod.is_qrc_type)
# This uses the module of the correct type with the lowest slot index
module = list(modules.values())[0]
Self-Cast#
IDs 1–15 are reserved for self-cast — no routing configuration is needed. Data sent with these IDs is delivered only to the feedback queue of the originating sequencer.
Experiment Parameters#
[5]:
SELF_CAST_ID = 5 # Any value 1–15
VALUE = 42
Define Q1ASM Program#
[6]:
prog_self_cast = f"""
fb_com_data {SELF_CAST_ID}, {VALUE}, 4 # Self-cast {VALUE} with ID {SELF_CAST_ID}
wait 60 # Wait for self-cast latency
fb_pop_data {SELF_CAST_ID}, R0 # Pop message into R0
stop
"""
Upload and Run#
[7]:
module.sequencer0.sequence(
{
"waveforms": {},
"program": prog_self_cast,
"acquisitions": {},
"weights": {},
}
)
module.arm_sequencer(0)
module.start_sequencer()
print("Sequencer 0 status:", module.get_sequencer_status(0))
Sequencer 0 status: Status: OKAY, State: STOPPED, Exit Code: 0, Info Flags: NONE, Warning Flags: NONE, Error Flags: NONE, Log: []
Verify Result#
[8]:
self_cast_result = module.sequencer0.get_register("R0")
print(f"Sent : {VALUE}")
print(f"Received: {self_cast_result}")
print(
"✓ PASS"
if self_cast_result == VALUE
else "✗ FAIL — check that the ID is in the self-cast range (1–15)"
)
Sent : 42
Received: 42
✓ PASS
Intra-Cast#
module.set_local_route(id) routes data with the given id to all sequencers within the module. To restrict delivery to a subset, pass an explicit list of sequencers:
module.set_local_route(id, [module.sequencer1, module.sequencer3])
Experiment Parameters#
[9]:
INTRA_ID = 16
VALUE = 99
Configure Routing#
[10]:
cluster.clear_router()
module.set_local_route(INTRA_ID) # All sequencers in module receive ID 16
Configure Sequencers#
[11]:
module.sequencer0.sync_en(True)
module.sequencer1.sync_en(True)
Define Q1ASM Programs#
[12]:
prog_intra_sender = f"""
wait_sync 4 # Synchronize with receiver
fb_com_data {INTRA_ID}, {VALUE}, 4 # Intra-cast {VALUE} with ID {INTRA_ID}
stop
"""
prog_intra_receiver = f"""
wait_sync 4 # Synchronize with sender
wait 150 # Wait for intra-cast latency (~150 ns)
fb_pop_data {INTRA_ID}, R0 # Pop message with ID {INTRA_ID} into R0
stop
"""
Upload and Run#
[13]:
module.sequencer0.sequence(
{
"waveforms": {},
"program": prog_intra_sender,
"acquisitions": {},
"weights": {},
}
)
module.sequencer1.sequence(
{
"waveforms": {},
"program": prog_intra_receiver,
"acquisitions": {},
"weights": {},
}
)
module.arm_sequencer(0)
module.arm_sequencer(1)
module.start_sequencer()
print("Sequencer 0 status:", module.get_sequencer_status(0))
print("Sequencer 1 status:", module.get_sequencer_status(1))
Sequencer 0 status: Status: OKAY, State: STOPPED, Exit Code: 0, Info Flags: NONE, Warning Flags: NONE, Error Flags: NONE, Log: []
Sequencer 1 status: Status: OKAY, State: STOPPED, Exit Code: 0, Info Flags: NONE, Warning Flags: NONE, Error Flags: NONE, Log: []
Verify Result#
[14]:
intra_result = module.sequencer1.get_register("R0")
print(f"Sent : {VALUE}")
print(f"Received: {intra_result}")
print(
"✓ PASS"
if intra_result == VALUE
else "✗ FAIL — check that set_local_route was called before arming"
)
Sent : 99
Received: 99
✓ PASS
Multi-Cast and Broadcast#
cluster.set_cmm_route(id, targets) routes data via the CMM to specific modules or sequencers. cluster.set_broadcast(id) delivers to every sequencer in the cluster, including the sender.
Here we configure two IDs simultaneously: ID 32 is targeted to sequencer 1 only (multi-cast), while ID 64 is broadcast to all sequencers. Sequencer 0 sends both in one program, and sequencer 1 pops both.
Experiment Parameters#
[15]:
MULTI_ID = 32
BROADCAST_ID = 64
VALUE_MULTI = 2025
VALUE_BCAST = 12345
Configure Routing#
[16]:
cluster.clear_router()
cluster.set_cmm_route(MULTI_ID, [module.sequencer1]) # ID 32 → sequencer 1 only
cluster.set_broadcast(BROADCAST_ID) # ID 64 → all sequencers
Configure Sequencers#
[17]:
module.sequencer0.sync_en(True)
module.sequencer1.sync_en(True)
Define Q1ASM Programs#
[18]:
prog_multi_sender = f"""
wait_sync 4
fb_com_data {MULTI_ID}, {VALUE_MULTI}, 4 # Multi-cast to sequencer 1
fb_com_data {BROADCAST_ID}, {VALUE_BCAST}, 4 # Broadcast to all sequencers
stop
"""
prog_multi_receiver = f"""
wait_sync 4
wait 500 # Wait conservatively for multi-cast latency
fb_pop_data {MULTI_ID}, R0 # Pop multi-cast value into R0
fb_pop_data {BROADCAST_ID}, R1 # Pop broadcast value into R1
stop
"""
Upload and Run#
[19]:
module.sequencer0.sequence(
{
"waveforms": {},
"program": prog_multi_sender,
"acquisitions": {},
"weights": {},
}
)
module.sequencer1.sequence(
{
"waveforms": {},
"program": prog_multi_receiver,
"acquisitions": {},
"weights": {},
}
)
module.arm_sequencer(0)
module.arm_sequencer(1)
module.start_sequencer()
print("Sequencer 0 status:", module.get_sequencer_status(0))
print("Sequencer 1 status:", module.get_sequencer_status(1))
Sequencer 0 status: Status: OKAY, State: STOPPED, Exit Code: 0, Info Flags: NONE, Warning Flags: NONE, Error Flags: NONE, Log: []
Sequencer 1 status: Status: OKAY, State: STOPPED, Exit Code: 0, Info Flags: NONE, Warning Flags: NONE, Error Flags: NONE, Log: []
Verify Result#
[20]:
multi_result = module.sequencer1.get_register("R0")
bcast_result = module.sequencer1.get_register("R1")
print(f"Multi-cast — sent: {VALUE_MULTI}, received: {multi_result}")
print(f"Broadcast — sent: {VALUE_BCAST}, received: {bcast_result}")
print(
"✓ PASS"
if multi_result == VALUE_MULTI and bcast_result == VALUE_BCAST
else "✗ FAIL — check CMM route and broadcast configuration"
)
Multi-cast — sent: 2025, received: 2025
Broadcast — sent: 12345, received: 12345
✓ PASS
Stop#
Finally, let’s stop the sequencers if they haven’t already and close the instrument connection. One can also display a detailed snapshot containing the instrument parameters before closing the connection by uncommenting the corresponding lines.
[21]:
# Stop all sequencers.
module.stop_sequencer()
# Print status of sequencers 0 and 1 (should now say it is stopped).
print(module.get_sequencer_status(0))
print(module.get_sequencer_status(1))
print()
Status: OKAY, State: STOPPED, Exit Code: 0, Info Flags: FORCED_STOP, Warning Flags: NONE, Error Flags: NONE, Log: []
Status: OKAY, State: STOPPED, Exit Code: 0, Info Flags: FORCED_STOP, Warning Flags: NONE, Error Flags: NONE, Log: []