feat: add automatic RF switching as a qblox backend compiler pass
(asked AI to generate a feature description, and can confirm that what it wrote is correct)
Auto RF Switch Dressing — Feature Description
What it does
When auto_rf_switch: True is set in QbloxCompilerOptions, the compilation pass auto_rf_switch_dressing automatically inserts RFSwitchToggle operations around microwave pulses. This gates the RF switch open only when needed, rather than leaving it always on.
RF Switch window placement
- Each MW pulse gets an RF switch window that starts ramp_buffer before the pulse and ends ramp_buffer after it (default ramp_buffer = 20 ns).
- If the pulse starts at t=0 (no room before), the window starts at t=0 and only the post-buffer is added.
- The t0 offset on a pulse is accounted for when calculating the window boundaries.
- ramp_buffer is configurable via auto_rf_switch_ramp_buffer in compiler options.
Window merging
- Adjacent RF switch windows are merged into a single RFSwitchToggle when the gap between consecutive pulses is ≤ 2 * ramp_buffer.
- If the gap is > 2 * ramp_buffer, two separate RFSwitchToggle operations are created.
- The merge boundary is inclusive (gap == 2 * ramp_buffer → merged; gap == 2 * ramp_buffer + ε → separate).
Supported pulse types on MW ports
- Regular MW pulses (e.g. SquarePulse on a :mw port): detected and windowed directly.
- Stitched pulses via VoltageOffset: a non-zero VoltageOffset followed by a zero VoltageOffset on a :mw port is treated as a pulse window from the first event to the second. These windows participate in the same merging logic as regular pulses.
Sub-schedule support
- MW pulses inside nested sub-schedules are discovered recursively, with their absolute times computed relative to the global (root) schedule timeline.
- All RFSwitchToggle operations are inserted on the root schedule only — never inside a sub-schedule. This prevents the sub-schedule's duration from being extended, which would cause timing problems.
- Cross-sub-schedule merging works: if a pulse at the end of one sub-schedule and a pulse at the start of the next sub-schedule are within 2 * ramp_buffer of each other globally, their windows are merged into a single RF switch.
What is NOT supported / explicitly excluded
- Non-MW ports (e.g. flux ports like q0:fl): SquarePulse or VoltageOffset on flux/baseband ports are completely ignored — no RF switch is inserted.
- Unclosed VoltageOffset windows: a non-zero VoltageOffset with no subsequent zero VoltageOffset on the same port is silently ignored (no RF switch generated).
- VoltageOffset-only zero events: a zero-valued VoltageOffset with no preceding non-zero event produces no RF switch.
- RFSwitchToggle operations themselves: already-existing RF switch toggles are not re-processed or double-counted when collecting pulses.
- Disabled by default: the pass is a no-op unless auto_rf_switch: True is explicitly set. If compiler_options is absent from the hardware config, the pass is also skipped entirely.
Merge checklist
See also merge request guidelines
- Merge request has been reviewed (in-depth by a knowledgeable contributor), and is approved by a project maintainer.
- New code is covered by unit tests (or N/A).
- New code is documented and docstrings use numpydoc format (or N/A).
- New functionality: considered making private instead of extending public API (or N/A).
-
Public API changed: added
@deprecatedand entry in deprecated code suggestions (or N/A). - Newly added/adjusted documentation and docstrings render properly (or N/A).
-
Pipeline fix or dependency update: post in
#software-for-developerschannel to mergemainback in or update local packages (or N/A). - Tested on hardware (or N/A).
-
CHANGELOG.mdfor breaking changes andAUTHORS.mdhave been updated (or N/A). - Update Hardware backends documentation if backend interface change or N/A
- Check whether performance is significantly affected by looking at the Performance metrics results.
-
Windows tests in CI pipeline pass (manually triggered by maintainers before merging).
- Maintainers do not hit Auto-merge, we need to actively check as manual tests do not block pipeline
For reference, the issues workflow is described in the contribution guidelines.
Edited by Robert Sokolewicz