qat.purr.backends.qblox.analysis_passes module
- class BindingPass
Bases:
AnalysisPass
Builds binding of variables, instructions, and a view of variables from/to scopes.
Variables are implicitly declared in sweep instructions and are ultimately read from quantum instructions. Thus, every iteration variable is associated to all the scopes it is declared in.
Values of the iteration variable are abstract and don’t mean anything. In this pass, we only extract the bound and associate it to the name variable. Further analysis is required on read sites to make sure their usage is consistent and meaningful.
- static extract_iter_bound(value)
Given a sequence of numbers (typically having been generated from
np.linspace()
), figure out if the numbers are linearly/evenly spaced, in which case returns an IterBound instance holding the start, step, end, and count of the numbers in the array, or else fail.In the future, we might be interested in relaxing this condition and return “interpolated” evenly spaced approximation of the input sequence.
- run(ir, res_mgr, *args, **kwargs)
- Parameters:
ir¶ (
QatIR
) – The list of instructions stored in anInstructionBuilder
.res_mgr¶ (
ResultManager
) – The result manager to save the analysis results.
- class BindingResult(scoping_results=<factory>, rw_results=<factory>, iter_bound_results=<factory>)
Bases:
ResultInfoMixin
-
iter_bound_results:
Dict
[PulseChannel
,Dict
[str
,IterBound
]]
-
rw_results:
Dict
[PulseChannel
,ReadWriteResult
]
-
scoping_results:
Dict
[PulseChannel
,ScopingResult
]
-
iter_bound_results:
- class CFGPass
Bases:
AnalysisPass
- run(ir, res_mgr, *args, **kwargs)
- Parameters:
ir¶ (
QatIR
) – The list of instructions stored in anInstructionBuilder
.res_mgr¶ (
ResultManager
) – The result manager to save the analysis results.
- class CFGResult(cfg=<factory>)
Bases:
ResultInfoMixin
-
cfg:
ControlFlowGraph
-
cfg:
- class IterBound(start=None, step=None, end=None, count=None)
Bases:
object
-
count:
int
= None
-
end:
Union
[int
,float
,complex
] = None
-
start:
Union
[int
,float
,complex
] = None
-
step:
Union
[int
,float
,complex
] = None
-
count:
- class QbloxLegalisationPass
Bases:
AnalysisPass
- amp_as_steps(amp)
The instruction set_awg_offs expects DAC ratio as a (potentially signed) integer operand. However, This function must return an unsigned integer because registers are unsigned 32bit integers.
- Return type:
complex
- static freq_as_steps(freq_hz)
The instruction set_freq expects the frequency as a (potentially signed) integer operand. However, This function must return an unsigned integer because registers are unsigned 32bit integers.
- Return type:
uint32
- static phase_as_steps(phase_rad)
The instruction set_ph_delta expects the phase shift as a (potentially signed) integer operand. However, This function must return an unsigned integer because registers are unsigned 32bit integers.
- Return type:
uint32
- run(ir, res_mgr, *args, **kwargs)
Performs target-dependent legalisation for QBlox.
A repeat instruction with a very high repetition count is illegal because acquisition memory
on a QBlox sequencer is limited. This requires optimal batching of the repeat instruction into maximally supported batches of smaller repeat counts.
This pass does not do any batching. More features and adjustments will follow in future iterations.
Previously processed variables such as frequencies, phases, and amplitudes still need digital conversion
to a representation that’s required by the QBlox ISA.
- NCO’s 1GHz frequency range by 4e9 steps:
[-500, 500] Mhz <=> [-2e9, 2e9] steps
1 Hz <=> 4 steps
- NCO’s 360° phase range by 1e9 steps:
1e9 steps <=> 2*pi rad
125e6 steps <=> pi/4 rad
Time and samples are quantified in nanoseconds
- Amplitude depends on the type of the module:
[-1, 1] <=> [-2.5, 2.5] V (for QCM)
[-1, 1] <=> [-0.5, 0.5] V (for QRM)
- AWG offset:
[-1, 1] <=> [-32 768, 32 767]
The last point is interesting as it requires knowledge of physical configuration of qubits and the modules they are wired to. This knowledge is typically found during execution and involving it early on would upset the rest of the compilation flow. In fact, it complicates this pass in particular, involves allocation concepts that should not be treated here, and promotes a monolithic compilation style. A temporary workaround is to simply assume the legality of amplitudes from the start whereby users are required to convert the desired voltages to the equivalent ratio AOT.
This pass performs target-dependent conversion as described in part (B). More features and adjustments will follow in future iterations.
- class ReadWriteResult(reads=<factory>, writes=<factory>)
Bases:
object
-
reads:
Dict
[str
,List
[Instruction
]]
-
writes:
Dict
[str
,List
[Instruction
]]
-
reads:
- class ScopingResult(scope2symbols=<factory>, symbol2scopes=<factory>)
Bases:
object
-
scope2symbols:
Dict
[Tuple
[Instruction
,Optional
[Instruction
]],Set
[str
]]
-
symbol2scopes:
Dict
[str
,List
[Tuple
[Instruction
,Optional
[Instruction
]]]]
-
scope2symbols:
- class TILegalisationPass
Bases:
AnalysisPass
An instruction is legal if it has a direct equivalent in the programming model implemented by the control stack. The notion of “legal” is highly determined by the hardware features of the control stack as well as its programming model. Control stacks such as Qblox have a direct ISA-level representation for basic RF instructions such as frequency and phase manipulation, arithmetic instructions such as add, and branching instructions such as jump.
This pass performs target-independent legalisation. The goal here is to understand how variables are used and legalise their bounds. Furthermore, analysis in this pass is fundamentally based on QAT semantics and must be kept target-agnostic so that it can be reused among backends.
Particularly in QAT: #. A sweep instruction is illegal because it specifies unclear iteration semantics. #. Device updates/assigns in general are illegal because they are bound to a sweep
instruction via a variable. In fact, a variable (implicitly defined by a Sweep instruction) remains obscure until a “read” (usually on the instruction builder or on the hardware model) (typically from a DeviceUpdate instruction) is encountered where its intent becomes clear. We say that a DeviceUpdate carries meaning for the variable and materialises its intention.
- static decompose_freq(frequency, target)
- run(ir, res_mgr, *args, **kwargs)
- Parameters:
ir¶ (
QatIR
) – The list of instructions stored in anInstructionBuilder
.res_mgr¶ (
ResultManager
) – The result manager to save the analysis results.
- static transform_amp(amp, scale_factor, ignore_scale, target)
- class TriagePass
Bases:
AnalysisPass
Builds a view of instructions per quantum target AOT.
Builds selections of instructions useful for subsequent analysis/transform passes, for code generation, and post-playback steps.
This is equivalent to the
QatFile
and simplifies the duration timeline creation in the legacy code.- run(ir, res_mgr, *args, **kwargs)
- Parameters:
ir¶ (
QatIR
) – The list of instructions stored in anInstructionBuilder
.res_mgr¶ (
ResultManager
) – The result manager to save the analysis results.
- class TriageResult(sweeps=<factory>, returns=<factory>, assigns=<factory>, target_map=<factory>, acquire_map=<factory>, pp_map=<factory>, rp_map=<factory>)
Bases:
ResultInfoMixin
-
acquire_map:
Dict
[PulseChannel
,List
[Acquire
]]
-
pp_map:
Dict
[str
,List
[PostProcessing
]]
-
rp_map:
Dict
[str
,ResultsProcessing
]
-
target_map:
Dict
[PulseChannel
,List
[Instruction
]]
-
acquire_map: