qat.experimental.conversion.pulse_to_q1.passes module
Pass and pipeline definitions for the Pulse-to-Q1 conversion.
- class AcquireAnalysisStack(for_op_number_repeats, for_op_indexes)
Bases:
objectMutable stack state tracked while walking the enclosing loop nest.
Both lists behave as stacks that are pushed on entry to an
scf.forand popped on exit, so at any acquire they describe exactly the loops surrounding it.- Variables:
for_op_number_repeats – A stack tracking the number of repetitions of each enclosing
scf.forloop.for_op_indexes – Induction-variable SSA values of the currently enclosing
scf.forloops, aligned withfor_op_number_repeats.
-
for_op_indexes:
list[SSAValue[IndexType]]
-
for_op_number_repeats:
list[int]
- class BoundDeadFrameEliminationPass
Bases:
OrderedPass,ModulePassErase frame metadata after binding and lowering have consumed it.
This deliberately runs after
PulseToQ1LoweringPassrather than markingpulse.create_frameglobally pure. Frames identify physical channels during outlining and binding, including channels with no timed instructions, so generic Pulse canonicalization must preserve them until that information has been captured.- apply(ctx, op)
- Return type:
None
- name: ClassVar[str] = 'bound-dead-frame-elimination'
- required_predecessors()
Pass classes that must be present in the same pipeline and run before this pass.
- Return type:
frozenset[type[ModulePass]]
- class PulseToQ1LoweringPass(target_data=QbloxTargetData(max_acquisitions=10000, default_shots=1000, QUBIT_DATA=QubitDescription(sample_time=1e-09, samples_per_clock_cycle=1, instruction_memory_size=50000, waveform_memory_size=1500, pulse_duration_min=6.4e-08, pulse_duration_max=0.001, pulse_channel_lo_freq_min=1000000, pulse_channel_lo_freq_max=10000000000, pulse_channel_if_freq_min=0, pulse_channel_if_freq_max=10000000000, passive_reset_time=0.001), RESONATOR_DATA=ResonatorDescription(sample_time=1e-09, samples_per_clock_cycle=1, instruction_memory_size=50000, waveform_memory_size=1500, pulse_duration_min=6.4e-08, pulse_duration_max=0.001, pulse_channel_lo_freq_min=1000000, pulse_channel_lo_freq_max=10000000000, pulse_channel_if_freq_min=0, pulse_channel_if_freq_max=10000000000), driver_version=SemanticVersion(major=1, minor=3, patch=1, prerelease=None, build=None), fw_version=SemanticVersion(major=0, minor=13, patch=0, prerelease=None, build=None), Q1ASM_DATA=Q1asmDescription(min_gain=-32768, max_gain=32767, min_offset=-32768, max_offset=32767, max_wait_time=65532, register_size=4294967295, loop_unroll_threshold=4), CONTROL_SEQUENCER_DATA=ControlSequencerDescription(grid_time=4, nco_min_freq=-500000000.0, nco_max_freq=500000000.0, nco_max_phase_steps=1000000000, nco_phase_steps_per_deg=2777777.777777778, nco_freq_steps_per_hz=4, nco_freq_limit_steps=2000000000.0, number_of_registers=64, min_acq_integration_length=4, max_acq_integration_length=16777212, min_acq_threshold=-16777212, max_acq_threshold=16777212, max_sample_size_waveforms=16384, max_num_instructions=16384, sample_rate=1000000000.0), READOUT_SEQUENCER_DATA=ReadoutSequencerDescription(grid_time=4, nco_min_freq=-500000000.0, nco_max_freq=500000000.0, nco_max_phase_steps=1000000000, nco_phase_steps_per_deg=2777777.777777778, nco_freq_steps_per_hz=4, nco_freq_limit_steps=2000000000.0, number_of_registers=64, min_acq_integration_length=4, max_acq_integration_length=16777212, min_acq_threshold=-16777212, max_acq_threshold=16777212, max_sample_size_waveforms=16384, max_num_instructions=12288, sample_rate=1000000000.0), QCM_DATA=QcmDescription(number_of_sequencers=6, min_qcm_offset_v=-2.5, max_qcm_offset_v=2.5, output_connections={0: [0, 1, 2, 3, 4, 5], 1: [0, 1, 2, 3, 4, 5], 2: [0, 1, 2, 3, 4, 5], 3: [0, 1, 2, 3, 4, 5]}), QCM_RF_DATA=QcmRfDescription(number_of_sequencers=6, min_qcm_rf_offset_mv=-84, max_qcm_rf_offset_mv=73, min_out_att_db=0, max_out_att_db=60, output_connections={0: [0, 1, 2, 3, 4, 5], 1: [0, 1, 2, 3, 4, 5]}), QRM_DATA=QrmDescription(number_of_sequencers=6, min_sample_size_scope_acquisitions=4, max_sample_size_scope_acquisitions=16384, max_binned_acquisitions=3000000, min_qrm_offset_v=-0.09, max_qrm_offset_v=0.09, output_connections={0: [0, 1, 2, 3, 4, 5], 1: [0, 1, 2, 3, 4, 5]}, input_connections={0: [0, 1, 2, 3, 4, 5], 1: [0, 1, 2, 3, 4, 5]}), QRM_RF_DATA=QrmRfDescription(number_of_sequencers=6, min_sample_size_scope_acquisitions=4, max_sample_size_scope_acquisitions=16384, max_binned_acquisitions=3000000, min_qrm_rf_offset_v=-0.09, max_qrm_rf_offset_v=0.09, min_out_att_db=0, max_out_att_db=60, min_in_att_db=0, max_in_att_db=30, output_connections={0: [0, 1, 2, 3, 4, 5]}, input_connections={0: [0, 1, 2, 3, 4, 5]}), QRC_DATA=QrcDescription(number_of_sequencers=12, min_sample_size_scope_acquisitions=4, max_sample_size_scope_acquisitions=16384, max_binned_acquisitions=7000000, number_of_readout_sequencers=8, number_of_control_sequencers=4, min_out_att_db=0.0, max_out_att_db=31.5, min_in_att_db=0.0, max_in_att_db=31.5, output_connections={0: [0, 1, 2, 3, 4, 5, 6, 7], 1: [0, 1, 2, 3, 4, 5, 6, 7], 2: [0, 4, 8, 9, 10, 11], 3: [1, 5, 8, 9, 10, 11], 4: [2, 6, 8, 9, 10, 11], 5: [3, 7, 8, 9, 10, 11]}, input_connections={0: [0, 1, 2, 3, 4, 5, 6, 7], 1: [0, 1, 2, 3, 4, 5, 6, 7]})))
Bases:
OrderedPass,ModulePassApply the Pulse-to-Q1 rewrite stage inside outlined sequences.
Q1OutliningPassfirst isolates one logical sequence envelope for each frame partition. This pass then traverses those envelopes and applies the per-operation rewrite set that converts Pulse-level instructions into the flat Q1 instruction dialect.- apply(ctx, op)
- Return type:
None
- name: ClassVar[str] = 'pulse-to-q1-lowering'
- required_predecessors()
Pass classes that must be present in the same pipeline and run before this pass.
- Return type:
frozenset[type[ModulePass]]
- runs_before()
Pass classes that, if present in the same pipeline, must run after this pass.
- Return type:
frozenset[type[ModulePass]]
-
target_data:
QbloxTargetData= QbloxTargetData(max_acquisitions=10000, default_shots=1000, QUBIT_DATA=QubitDescription(sample_time=1e-09, samples_per_clock_cycle=1, instruction_memory_size=50000, waveform_memory_size=1500, pulse_duration_min=6.4e-08, pulse_duration_max=0.001, pulse_channel_lo_freq_min=1000000, pulse_channel_lo_freq_max=10000000000, pulse_channel_if_freq_min=0, pulse_channel_if_freq_max=10000000000, passive_reset_time=0.001), RESONATOR_DATA=ResonatorDescription(sample_time=1e-09, samples_per_clock_cycle=1, instruction_memory_size=50000, waveform_memory_size=1500, pulse_duration_min=6.4e-08, pulse_duration_max=0.001, pulse_channel_lo_freq_min=1000000, pulse_channel_lo_freq_max=10000000000, pulse_channel_if_freq_min=0, pulse_channel_if_freq_max=10000000000), driver_version=SemanticVersion(major=1, minor=3, patch=1, prerelease=None, build=None), fw_version=SemanticVersion(major=0, minor=13, patch=0, prerelease=None, build=None), Q1ASM_DATA=Q1asmDescription(min_gain=-32768, max_gain=32767, min_offset=-32768, max_offset=32767, max_wait_time=65532, register_size=4294967295, loop_unroll_threshold=4), CONTROL_SEQUENCER_DATA=ControlSequencerDescription(grid_time=4, nco_min_freq=-500000000.0, nco_max_freq=500000000.0, nco_max_phase_steps=1000000000, nco_phase_steps_per_deg=2777777.777777778, nco_freq_steps_per_hz=4, nco_freq_limit_steps=2000000000.0, number_of_registers=64, min_acq_integration_length=4, max_acq_integration_length=16777212, min_acq_threshold=-16777212, max_acq_threshold=16777212, max_sample_size_waveforms=16384, max_num_instructions=16384, sample_rate=1000000000.0), READOUT_SEQUENCER_DATA=ReadoutSequencerDescription(grid_time=4, nco_min_freq=-500000000.0, nco_max_freq=500000000.0, nco_max_phase_steps=1000000000, nco_phase_steps_per_deg=2777777.777777778, nco_freq_steps_per_hz=4, nco_freq_limit_steps=2000000000.0, number_of_registers=64, min_acq_integration_length=4, max_acq_integration_length=16777212, min_acq_threshold=-16777212, max_acq_threshold=16777212, max_sample_size_waveforms=16384, max_num_instructions=12288, sample_rate=1000000000.0), QCM_DATA=QcmDescription(number_of_sequencers=6, min_qcm_offset_v=-2.5, max_qcm_offset_v=2.5, output_connections={0: [0, 1, 2, 3, 4, 5], 1: [0, 1, 2, 3, 4, 5], 2: [0, 1, 2, 3, 4, 5], 3: [0, 1, 2, 3, 4, 5]}), QCM_RF_DATA=QcmRfDescription(number_of_sequencers=6, min_qcm_rf_offset_mv=-84, max_qcm_rf_offset_mv=73, min_out_att_db=0, max_out_att_db=60, output_connections={0: [0, 1, 2, 3, 4, 5], 1: [0, 1, 2, 3, 4, 5]}), QRM_DATA=QrmDescription(number_of_sequencers=6, min_sample_size_scope_acquisitions=4, max_sample_size_scope_acquisitions=16384, max_binned_acquisitions=3000000, min_qrm_offset_v=-0.09, max_qrm_offset_v=0.09, output_connections={0: [0, 1, 2, 3, 4, 5], 1: [0, 1, 2, 3, 4, 5]}, input_connections={0: [0, 1, 2, 3, 4, 5], 1: [0, 1, 2, 3, 4, 5]}), QRM_RF_DATA=QrmRfDescription(number_of_sequencers=6, min_sample_size_scope_acquisitions=4, max_sample_size_scope_acquisitions=16384, max_binned_acquisitions=3000000, min_qrm_rf_offset_v=-0.09, max_qrm_rf_offset_v=0.09, min_out_att_db=0, max_out_att_db=60, min_in_att_db=0, max_in_att_db=30, output_connections={0: [0, 1, 2, 3, 4, 5]}, input_connections={0: [0, 1, 2, 3, 4, 5]}), QRC_DATA=QrcDescription(number_of_sequencers=12, min_sample_size_scope_acquisitions=4, max_sample_size_scope_acquisitions=16384, max_binned_acquisitions=7000000, number_of_readout_sequencers=8, number_of_control_sequencers=4, min_out_att_db=0.0, max_out_att_db=31.5, min_in_att_db=0.0, max_in_att_db=31.5, output_connections={0: [0, 1, 2, 3, 4, 5, 6, 7], 1: [0, 1, 2, 3, 4, 5, 6, 7], 2: [0, 4, 8, 9, 10, 11], 3: [1, 5, 8, 9, 10, 11], 4: [2, 6, 8, 9, 10, 11], 5: [3, 7, 8, 9, 10, 11]}, input_connections={0: [0, 1, 2, 3, 4, 5, 6, 7], 1: [0, 1, 2, 3, 4, 5, 6, 7]}))
- class Q1PreAcquireTransformationPass
Bases:
OrderedPass,ModulePassLower
pulse.acquiretoPreQ1AcquireOpwith QBlox acquisition context.QBlox acquires need a result store index (bin) and a repetition count, neither of which is expressed by
pulse.acquireitself. This pass walks the module, tracking the enclosingscf.fornest, and for eachpulse.acquirecomputes:a
store_idxfrom the loop induction variables, so each iteration writes to a distinct bin, andnumber_runsfrom the product of the enclosing loop trip counts.
It then replaces the
pulse.acquirewith an equivalentPreQ1AcquireOpcarrying that context, ready for the context-free lowering inRewritePreQ1AcquireOp.Assumes there are no
scf.whileloops and that allscf.forbounds are constant.- apply(ctx, op)
Run the transformation over
opin place.
- name: ClassVar[str] = 'acquire-pre-q1-transformation'
- required_predecessors()
Pass classes that must be present in the same pipeline and run before this pass.
- Return type:
frozenset[type[ModulePass]]
- runs_before()
Pass classes that, if present in the same pipeline, must run after this pass.
- Return type:
frozenset[type[ModulePass]]
- class Q1PulseLegalisationPass
Bases:
OrderedPass,ModulePassApply Pulse phase legalisation before Pulse-to-Q1 lowering.
This stage applies the legalisation pattern set to Pulse-level operands after validation. The pattern set is expected to grow over time as more Pulse operations acquire legalisation support.
- apply(ctx, op)
- Return type:
None
- name: ClassVar[str] = 'q1-pulse-legalisation'
- required_predecessors()
Pass classes that must be present in the same pipeline and run before this pass.
- Return type:
frozenset[type[ModulePass]]
- runs_before()
Pass classes that, if present in the same pipeline, must run after this pass.
- Return type:
frozenset[type[ModulePass]]
- class Q1PulseValidationPass
Bases:
OrderedPass,ModulePassValidate QBlox-specific pre-conditions on constant Pulse operands.
Enforces hardware constraints that cannot be expressed as Pulse dialect invariants, ahead of legalisation and lowering. Dynamic waits, frame frequencies, continuous amplitudes, and phase operands are rejected because no Q1 lowering exists for them: Q1 phase instructions only accept an immediate, so a dynamic phase would require a real radians-to-NCO-steps runtime conversion that does not exist.
The following constraints are enforced:
pulse.waitconstant duration: finite, non-negative, and an integer number of nanoseconds.pulse.create_frameconstant frequency: finite.pulse.phase_setandpulse.phase_shiftconstant phase: finite.
- apply(ctx, op)
- Return type:
None
- name: ClassVar[str] = 'q1-pulse-validation'
- required_predecessors()
Pass classes that must be present in the same pipeline and run before this pass.
- Return type:
frozenset[type[ModulePass]]
- runs_before()
Pass classes that, if present in the same pipeline, must run after this pass.
- Return type:
frozenset[type[ModulePass]]
- create_qblox_configured_q1_pipeline(canonical_data, target_data=QbloxTargetData(max_acquisitions=10000, default_shots=1000, QUBIT_DATA=QubitDescription(sample_time=1e-09, samples_per_clock_cycle=1, instruction_memory_size=50000, waveform_memory_size=1500, pulse_duration_min=6.4e-08, pulse_duration_max=0.001, pulse_channel_lo_freq_min=1000000, pulse_channel_lo_freq_max=10000000000, pulse_channel_if_freq_min=0, pulse_channel_if_freq_max=10000000000, passive_reset_time=0.001), RESONATOR_DATA=ResonatorDescription(sample_time=1e-09, samples_per_clock_cycle=1, instruction_memory_size=50000, waveform_memory_size=1500, pulse_duration_min=6.4e-08, pulse_duration_max=0.001, pulse_channel_lo_freq_min=1000000, pulse_channel_lo_freq_max=10000000000, pulse_channel_if_freq_min=0, pulse_channel_if_freq_max=10000000000), driver_version=SemanticVersion(major=1, minor=3, patch=1, prerelease=None, build=None), fw_version=SemanticVersion(major=0, minor=13, patch=0, prerelease=None, build=None), Q1ASM_DATA=Q1asmDescription(min_gain=-32768, max_gain=32767, min_offset=-32768, max_offset=32767, max_wait_time=65532, register_size=4294967295, loop_unroll_threshold=4), CONTROL_SEQUENCER_DATA=ControlSequencerDescription(grid_time=4, nco_min_freq=-500000000.0, nco_max_freq=500000000.0, nco_max_phase_steps=1000000000, nco_phase_steps_per_deg=2777777.777777778, nco_freq_steps_per_hz=4, nco_freq_limit_steps=2000000000.0, number_of_registers=64, min_acq_integration_length=4, max_acq_integration_length=16777212, min_acq_threshold=-16777212, max_acq_threshold=16777212, max_sample_size_waveforms=16384, max_num_instructions=16384, sample_rate=1000000000.0), READOUT_SEQUENCER_DATA=ReadoutSequencerDescription(grid_time=4, nco_min_freq=-500000000.0, nco_max_freq=500000000.0, nco_max_phase_steps=1000000000, nco_phase_steps_per_deg=2777777.777777778, nco_freq_steps_per_hz=4, nco_freq_limit_steps=2000000000.0, number_of_registers=64, min_acq_integration_length=4, max_acq_integration_length=16777212, min_acq_threshold=-16777212, max_acq_threshold=16777212, max_sample_size_waveforms=16384, max_num_instructions=12288, sample_rate=1000000000.0), QCM_DATA=QcmDescription(number_of_sequencers=6, min_qcm_offset_v=-2.5, max_qcm_offset_v=2.5, output_connections={0: [0, 1, 2, 3, 4, 5], 1: [0, 1, 2, 3, 4, 5], 2: [0, 1, 2, 3, 4, 5], 3: [0, 1, 2, 3, 4, 5]}), QCM_RF_DATA=QcmRfDescription(number_of_sequencers=6, min_qcm_rf_offset_mv=-84, max_qcm_rf_offset_mv=73, min_out_att_db=0, max_out_att_db=60, output_connections={0: [0, 1, 2, 3, 4, 5], 1: [0, 1, 2, 3, 4, 5]}), QRM_DATA=QrmDescription(number_of_sequencers=6, min_sample_size_scope_acquisitions=4, max_sample_size_scope_acquisitions=16384, max_binned_acquisitions=3000000, min_qrm_offset_v=-0.09, max_qrm_offset_v=0.09, output_connections={0: [0, 1, 2, 3, 4, 5], 1: [0, 1, 2, 3, 4, 5]}, input_connections={0: [0, 1, 2, 3, 4, 5], 1: [0, 1, 2, 3, 4, 5]}), QRM_RF_DATA=QrmRfDescription(number_of_sequencers=6, min_sample_size_scope_acquisitions=4, max_sample_size_scope_acquisitions=16384, max_binned_acquisitions=3000000, min_qrm_rf_offset_v=-0.09, max_qrm_rf_offset_v=0.09, min_out_att_db=0, max_out_att_db=60, min_in_att_db=0, max_in_att_db=30, output_connections={0: [0, 1, 2, 3, 4, 5]}, input_connections={0: [0, 1, 2, 3, 4, 5]}), QRC_DATA=QrcDescription(number_of_sequencers=12, min_sample_size_scope_acquisitions=4, max_sample_size_scope_acquisitions=16384, max_binned_acquisitions=7000000, number_of_readout_sequencers=8, number_of_control_sequencers=4, min_out_att_db=0.0, max_out_att_db=31.5, min_in_att_db=0.0, max_in_att_db=31.5, output_connections={0: [0, 1, 2, 3, 4, 5, 6, 7], 1: [0, 1, 2, 3, 4, 5, 6, 7], 2: [0, 4, 8, 9, 10, 11], 3: [1, 5, 8, 9, 10, 11], 4: [2, 6, 8, 9, 10, 11], 5: [3, 7, 8, 9, 10, 11]}, input_connections={0: [0, 1, 2, 3, 4, 5, 6, 7], 1: [0, 1, 2, 3, 4, 5, 6, 7]})))
Create the Pulse-to-emission-ready configured Qblox Q1 conversion pipeline.
This is a Q1 conversion/configuration pipeline only: it assumes the input module has already been through Pulse-level preprocessing (see
build_default_pipeline()). The experimental middleend runs Pulse preprocessing before the backend applies this pipeline.Binding runs after Pulse validation, legalisation, and acquisition preparation while
pulse.create_framestill carries generator-selection metadata.ReconcileUnrealizedCastsPassruns after all lowering (including the arith integer constant toq1.ir.moverewrite applied byPulseToQ1LoweringPass) has substituted the values that made the index-to-Q1-register bridging casts identity casts, and before register allocation, which requires the module to be free ofbuiltin.unrealized_conversion_cast.- Parameters:
canonical_data¶ (
CanonicalSystemData) – Canonical hardware data used for physical binding.target_data¶ (
QbloxTargetData) – Qblox limits used by Q1 lowering and final verification.
- Return type:
PassPipeline- Returns:
Ordered pipeline ending in strict Qblox pre-emission verification.