qblox_backend ============= .. py:module:: quantify_scheduler.backends.qblox_backend .. autoapi-nested-parse:: Compiler backend for Qblox hardware. Module Contents --------------- Classes ~~~~~~~ .. autoapisummary:: quantify_scheduler.backends.qblox_backend.OperationTimingInfo quantify_scheduler.backends.qblox_backend.QbloxHardwareCompilationConfig Functions ~~~~~~~~~ .. autoapisummary:: quantify_scheduler.backends.qblox_backend._get_square_pulses_to_replace quantify_scheduler.backends.qblox_backend._replace_long_square_pulses quantify_scheduler.backends.qblox_backend.compile_conditional_playback quantify_scheduler.backends.qblox_backend.compile_long_square_pulses_to_awg_offsets quantify_scheduler.backends.qblox_backend.hardware_compile quantify_scheduler.backends.qblox_backend.find_qblox_instruments quantify_scheduler.backends.qblox_backend.validate_non_overlapping_stitched_pulse quantify_scheduler.backends.qblox_backend._exists_pulse_starting_before_current_end quantify_scheduler.backends.qblox_backend._raise_if_pulses_overlap_on_same_port_clock quantify_scheduler.backends.qblox_backend._get_pulse_start_ends quantify_scheduler.backends.qblox_backend._has_voltage_offset quantify_scheduler.backends.qblox_backend._has_pulse quantify_scheduler.backends.qblox_backend._operation_end .. py:function:: _get_square_pulses_to_replace(schedule: quantify_scheduler.schedules.schedule.Schedule) -> dict[str, list[int]] Generate a dict referring to long square pulses to replace in the schedule. This function generates a mapping (dict) from the keys in the :meth:`~quantify_scheduler.schedules.schedule.ScheduleBase.operations` dict to a list of indices, which refer to entries in the `"pulse_info"` list that describe a square pulse. :param schedule: A :class:`~quantify_scheduler.schedules.schedule.Schedule`, possibly containing long square pulses. :type schedule: Schedule :returns: **square_pulse_idx_map** -- The mapping from ``operation_id`` to ``"pulse_info"`` indices to be replaced. :rtype: dict[str, list[int]] .. py:function:: _replace_long_square_pulses(schedule: quantify_scheduler.schedules.schedule.Schedule, pulse_idx_map: dict[str, list[int]]) -> quantify_scheduler.schedules.schedule.Schedule Replace any square pulses indicated by pulse_idx_map by a ``long_square_pulse``. :param schedule: A :class:`~quantify_scheduler.schedules.schedule.Schedule`, possibly containing long square pulses. :type schedule: Schedule :param pulse_idx_map: A mapping from the keys in the :meth:`~quantify_scheduler.schedules.schedule.ScheduleBase.operations` dict to a list of indices, which refer to entries in the `"pulse_info"` list that describe a square pulse. :type pulse_idx_map: dict[str, list[int]] :returns: The schedule with square pulses longer than :class:`~quantify_scheduler.backends.qblox.constants.PULSE_STITCHING_DURATION` replaced by :func:`~quantify_scheduler.backends.qblox.operations.pulse_factories.long_square_pulse`. If no replacements were done, this is the original unmodified schedule. :rtype: Schedule .. py:class:: OperationTimingInfo Timing information for an Operation. .. py:attribute:: start :type: float start time of the operation. .. py:attribute:: end :type: float end time of the operation. .. py:method:: from_operation_and_schedulable(operation: quantify_scheduler.operations.operation.Operation, schedulable: quantify_scheduler.schedules.schedule.Schedulable) -> OperationTimingInfo :classmethod: Create an ``OperationTimingInfo`` from an operation and a schedulable. .. py:method:: overlaps_with(operation_timing_info: OperationTimingInfo) -> bool Check if this operation timing info overlaps with another. .. py:function:: compile_conditional_playback(schedule: quantify_scheduler.schedules.schedule.Schedule, **_: Any) -> quantify_scheduler.schedules.schedule.Schedule Compiles conditional playback. This compiler pass will determine the mapping between trigger labels and trigger addresses that the hardware will use. The feedback trigger address is stored under the key ``feedback_trigger_address`` in ``pulse_info`` and in ``acquisition_info`` of the corresponding operation. A valid conditional playback consists of two parts: (1) a conditional acquisition or measure, and (2) a conditional control flow. The first should always be followed by the second, else an error is raised. A conditional acquisition sends a trigger after the acquisition ends and if the acquisition crosses a certain threshold. Each sequencer that is subscribed to this trigger will increase their *latch* counters by one. To ensure the latch counters contain either 0 or 1 trigger counts, a :class:`~quantify_scheduler.backends.qblox.operations.pulse_library.LatchReset` operation is inserted right after the start of a conditional acquisition, on all sequencers. If this is not possible (e.g. due to concurring operations), a :class:`RuntimeError` is raised. :param schedule: The schedule to compile. :returns: The returned schedule is a reference to the original ``schedule``, but updated. :rtype: Schedule :raises RuntimeError: - If a conditional acquisitions/measures is not followed by a conditional control flow. - If a conditional control flow is not preceded by a conditional acquisition/measure. - If the compilation pass is unable to insert :class:`~quantify_scheduler.backends.qblox.operations.pulse_library.LatchReset` on all sequencers. .. py:function:: compile_long_square_pulses_to_awg_offsets(schedule: quantify_scheduler.schedules.schedule.Schedule, **_: Any) -> quantify_scheduler.schedules.schedule.Schedule Replace square pulses in the schedule with long square pulses. Introspects operations in the schedule to find square pulses with a duration longer than :class:`~quantify_scheduler.backends.qblox.constants.PULSE_STITCHING_DURATION`. Any of these square pulses are converted to :func:`~quantify_scheduler.backends.qblox.operations.pulse_factories.long_square_pulse`, which consist of AWG voltage offsets. If any operations are to be replaced, a deepcopy will be made of the schedule, which is returned by this function. Otherwise the original unmodified schedule will be returned. :param schedule: A :class:`~quantify_scheduler.schedules.schedule.Schedule`, possibly containing long square pulses. :type schedule: Schedule :returns: **schedule** -- The schedule with square pulses longer than :class:`~quantify_scheduler.backends.qblox.constants.PULSE_STITCHING_DURATION` replaced by :func:`~quantify_scheduler.backends.qblox.operations.pulse_factories.long_square_pulse`. If no replacements were done, this is the original unmodified schedule. :rtype: Schedule .. py:function:: hardware_compile(schedule: quantify_scheduler.schedules.schedule.Schedule, config: quantify_scheduler.backends.graph_compilation.CompilationConfig | dict[str, Any] | None = None, *, hardware_cfg: Optional[dict[str, Any]] = None) -> quantify_scheduler.schedules.schedule.CompiledSchedule Generate qblox hardware instructions for executing the schedule. The principle behind the overall compilation is as follows: For every instrument in the hardware configuration, we instantiate a compiler object. Then we assign all the pulses/acquisitions that need to be played by that instrument to the compiler, which then compiles for each instrument individually. This function then returns all the compiled programs bundled together in a dictionary with the QCoDeS name of the instrument as key. :param schedule: The schedule to compile. It is assumed the pulse and acquisition info is already added to the operation. Otherwise an exception is raised. :param config: Compilation config for :class:`~quantify_scheduler.backends.graph_compilation.QuantifyCompiler`. :param hardware_cfg: (deprecated) The hardware configuration of the setup. Pass a full compilation config instead using ``config`` argument. :returns: The compiled schedule. :raises ValueError: When both ``config`` and ``hardware_cfg`` are supplied. .. py:function:: find_qblox_instruments(hardware_config: Dict[str, Any], instrument_type: str) -> Dict[str, Any] Find all inner dictionaries representing a qblox instrument of the given type. .. py:class:: QbloxHardwareCompilationConfig(/, **data: Any) Bases: :py:obj:`quantify_scheduler.backends.types.common.HardwareCompilationConfig` Datastructure containing the information needed to compile to the Qblox backend. This information is structured in the same way as in the generic :class:`~quantify_scheduler.backends.types.common.HardwareCompilationConfig`, but contains fields for hardware-specific settings. .. py:attribute:: config_type :type: Type[QbloxHardwareCompilationConfig] A reference to the :class:`~quantify_scheduler.backends.types.common.HardwareCompilationConfig` DataStructure for the Qblox backend. .. py:attribute:: hardware_description :type: Dict[str, Union[quantify_scheduler.backends.types.qblox.QbloxHardwareDescription, quantify_scheduler.backends.types.common.HardwareDescription]] Description of the instruments in the physical setup. .. py:attribute:: hardware_options :type: quantify_scheduler.backends.types.qblox.QbloxHardwareOptions Options that are used in compiling the instructions for the hardware, such as :class:`~quantify_scheduler.backends.types.common.LatencyCorrection` or :class:`~quantify_scheduler.backends.types.qblox.SequencerOptions`. .. py:attribute:: compilation_passes :type: List[quantify_scheduler.backends.graph_compilation.SimpleNodeConfig] The list of compilation nodes that should be called in succession to compile a schedule to instructions for the Qblox hardware. .. py:method:: _validate_connectivity_channel_names() -> QbloxHardwareCompilationConfig .. py:method:: from_old_style_hardware_config(data: Any) -> Any :classmethod: Convert old style hardware config dict to new style before validation. .. py:function:: validate_non_overlapping_stitched_pulse(schedule: quantify_scheduler.schedules.schedule.Schedule, **_: Any) -> None Raise an error when pulses overlap, if at least one contains a voltage offset. Since voltage offsets are sometimes used to construct pulses (see e.g. :func:`.long_square_pulse`), overlapping these with regular pulses in time on the same port-clock can lead to undefined behaviour. Note that for each schedulable, all pulse info entries with the same port and clock count as one pulse for that port and clock. This is because schedulables, starting before another schedulable has finished, could affect the waveforms or offsets in the remaining time of that other schedulable. :param schedule: A :class:`~quantify_scheduler.schedules.schedule.Schedule`, possibly containing long square pulses. :type schedule: Schedule :returns: **schedule** -- A :class:`~quantify_scheduler.schedules.schedule.Schedule`, possibly containing long square pulses. :rtype: Schedule :raises RuntimeError: If the schedule contains overlapping pulses (containing voltage offsets) on the same port and clock. .. py:function:: _exists_pulse_starting_before_current_end(sorted_schedulables: list[quantify_scheduler.schedules.schedule.Schedulable], current_idx: int, schedule: quantify_scheduler.schedules.schedule.Schedule) -> quantify_scheduler.schedules.schedule.Schedulable | Literal[False] .. py:function:: _raise_if_pulses_overlap_on_same_port_clock(schble_a: quantify_scheduler.schedules.schedule.Schedulable, schble_b: quantify_scheduler.schedules.schedule.Schedulable, schedule: quantify_scheduler.schedules.schedule.Schedule) -> None Raise an error if any pulse operations overlap on the same port-clock. A pulse here means a waveform or a voltage offset. .. py:function:: _get_pulse_start_ends(schedulable: quantify_scheduler.schedules.schedule.Schedulable, schedule: quantify_scheduler.schedules.schedule.Schedule) -> dict[str, tuple[float, float]] .. py:function:: _has_voltage_offset(schedulable: quantify_scheduler.schedules.schedule.Schedulable, schedule: quantify_scheduler.schedules.schedule.Schedule) -> bool .. py:function:: _has_pulse(schedulable: quantify_scheduler.schedules.schedule.Schedulable, schedule: quantify_scheduler.schedules.schedule.Schedule) -> bool .. py:function:: _operation_end(schedulable: quantify_scheduler.schedules.schedule.Schedulable, schedule: quantify_scheduler.schedules.schedule.Schedule) -> float