From ae9affbd0bbefd06abcf25a6241fb039cd289907 Mon Sep 17 00:00:00 2001 From: "jordi.valls@qilimanjaro.tech" Date: Wed, 4 Sep 2024 16:13:13 +0000 Subject: [PATCH 01/15] Implemented delay qblox qprogram --- .../instruments/awg_analog_digital_converter.py | 16 ++++++++++++++++ .../awg_settings/awg_adc_sequencer.py | 1 + .../instruments/awg_settings/awg_sequencer.py | 1 + src/qililab/platform/platform.py | 8 ++++++++ src/qililab/qprogram/qblox_compiler.py | 15 +++++++++++++++ 5 files changed, 41 insertions(+) diff --git a/src/qililab/instruments/awg_analog_digital_converter.py b/src/qililab/instruments/awg_analog_digital_converter.py index bd92ead96..a6595d1ec 100644 --- a/src/qililab/instruments/awg_analog_digital_converter.py +++ b/src/qililab/instruments/awg_analog_digital_converter.py @@ -95,6 +95,9 @@ def setup(self, parameter: Parameter, value: float | str | bool, channel_id: int if parameter == Parameter.TIME_OF_FLIGHT: self._set_time_of_flight(value=value, sequencer_id=channel_id) return + if parameter == Parameter.DELAY: + self._set_delay(value=value, sequencer_id=channel_id) + return raise ParameterNotFound(f"Invalid Parameter: {parameter.value}") @@ -344,6 +347,19 @@ def _set_time_of_flight(self, value: int | float | str | bool, sequencer_id: int """ cast(AWGADCSequencer, self.get_sequencer(sequencer_id)).time_of_flight = int(value) + @Instrument.CheckParameterValueFloatOrInt + def _set_delay(self, value: int | float | str | bool, sequencer_id: int): + """set delay + + Args: + value (int | float | str | bool): value to update + sequencer_id (int): sequencer to update the value + + Raises: + ValueError: when value type is not bool + """ + cast(AWGADCSequencer, self.get_sequencer(sequencer_id)).delay = int(value) + @property def acquisition_delay_time(self): """AWG 'delay_before_readout' property. diff --git a/src/qililab/instruments/awg_settings/awg_adc_sequencer.py b/src/qililab/instruments/awg_settings/awg_adc_sequencer.py index 9056b08b8..5e9f8c5ae 100644 --- a/src/qililab/instruments/awg_settings/awg_adc_sequencer.py +++ b/src/qililab/instruments/awg_settings/awg_adc_sequencer.py @@ -49,6 +49,7 @@ class AWGADCSequencer(AWGSequencer): # pylint: disable=too-many-instance-attrib threshold: float threshold_rotation: float time_of_flight: int # nanoseconds + delay: int # nanoseconds def __post_init__(self): """Cast all enum attributes to its corresponding Enum class.""" diff --git a/src/qililab/instruments/awg_settings/awg_sequencer.py b/src/qililab/instruments/awg_settings/awg_sequencer.py index d8e576e7a..5d9886105 100644 --- a/src/qililab/instruments/awg_settings/awg_sequencer.py +++ b/src/qililab/instruments/awg_settings/awg_sequencer.py @@ -51,6 +51,7 @@ class AWGSequencer: # pylint: disable=too-many-instance-attributes gain_q: float offset_i: float offset_q: float + delay: int def to_dict(self): """Return a dict representation of an AWG Sequencer.""" diff --git a/src/qililab/platform/platform.py b/src/qililab/platform/platform.py index 8cce58758..73660e299 100644 --- a/src/qililab/platform/platform.py +++ b/src/qililab/platform/platform.py @@ -725,6 +725,11 @@ def execute_qprogram( # pylint: disable=too-many-locals for bus in buses if isinstance(bus.system_control, ReadoutSystemControl) } + delays = { + bus.alias: int(bus.get_parameter(Parameter.DELAY)) + for bus in buses + if isinstance(bus.system_control, ReadoutSystemControl) + } # Determine what should be the initial value of the markers for each bus. # This depends on the model of the associated Qblox module and the `output` setting of the associated sequencer. markers = {} @@ -745,6 +750,7 @@ def execute_qprogram( # pylint: disable=too-many-locals return self._execute_qprogram_with_qblox( qprogram=qprogram, times_of_flight=times_of_flight, + delays=delays, markers=markers, bus_mapping=bus_mapping, calibration=calibration, @@ -782,6 +788,7 @@ def _execute_qprogram_with_qblox( # pylint: disable=too-many-locals self, qprogram: QProgram, times_of_flight: dict[str, int], + delays: dict[str, int], markers: dict[str, str], bus_mapping: dict[str, str] | None = None, calibration: Calibration | None = None, @@ -794,6 +801,7 @@ def _execute_qprogram_with_qblox( # pylint: disable=too-many-locals bus_mapping=bus_mapping, calibration=calibration, times_of_flight=times_of_flight, + delays=delays, markers=markers, ) buses = {bus_alias: self._get_bus_by_alias(alias=bus_alias) for bus_alias in sequences} diff --git a/src/qililab/qprogram/qblox_compiler.py b/src/qililab/qprogram/qblox_compiler.py index 07dcf6e9e..ec72392db 100644 --- a/src/qililab/qprogram/qblox_compiler.py +++ b/src/qililab/qprogram/qblox_compiler.py @@ -99,6 +99,9 @@ def __init__(self) -> None: # Time of flight. Defaults to minimum_wait_duration and is updated if times_of_flight parameter is provided during compilation. self.time_of_flight = QbloxCompiler.minimum_wait_duration + # Delay. Defaults 0 delay and is updated if delays parameter is provided within the runcard. + self.delay = 0 + class QbloxCompiler: # pylint: disable=too-few-public-methods """A class for compiling QProgram to QBlox hardware.""" @@ -136,6 +139,7 @@ def compile( bus_mapping: dict[str, str] | None = None, calibration: Calibration | None = None, times_of_flight: dict[str, int] | None = None, + delays: dict[str, int] | None = None, markers: dict[str, str] | None = None, ) -> tuple[Sequences, Acquisitions]: """Compile QProgram to qpysequence.Sequence @@ -150,9 +154,15 @@ def compile( """ def traverse(block: Block): + delay_implemented = False for bus in self._buses: self._buses[bus].qprogram_block_stack.append(block) for element in block.elements: + if isinstance(element, Play) and not delay_implemented: + for bus in self._buses: + if self._buses[bus].delay != 0: + self._handle_wait(element=Wait(bus=bus, duration=self._buses[bus].delay)) + delay_implemented = True handler = self._handlers.get(type(element)) if not handler: raise NotImplementedError(f"{element.__class__} is currently not supported in QBlox.") @@ -187,6 +197,11 @@ def traverse(block: Block): for bus in self._buses.keys() & times_of_flight.keys(): self._buses[bus].time_of_flight = times_of_flight[bus] + # Pre-processing: Update delay + if delays is not None: + for bus in self._buses.keys() & delays.keys(): + self._buses[bus].delay = delays[bus] + # Pre-processing: Set markers ON/OFF for bus in self._buses: mask = markers[bus] if markers is not None and bus in markers else "0000" From e7ac08cb5d3ecc6e948d44f221ba156c77ed7417 Mon Sep 17 00:00:00 2001 From: "jordi.valls@qilimanjaro.tech" Date: Thu, 5 Sep 2024 13:30:54 +0000 Subject: [PATCH 02/15] REMOVED READOUT CONDITION DELAY --- src/qililab/platform/platform.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/qililab/platform/platform.py b/src/qililab/platform/platform.py index 73660e299..7d9819c58 100644 --- a/src/qililab/platform/platform.py +++ b/src/qililab/platform/platform.py @@ -728,7 +728,6 @@ def execute_qprogram( # pylint: disable=too-many-locals delays = { bus.alias: int(bus.get_parameter(Parameter.DELAY)) for bus in buses - if isinstance(bus.system_control, ReadoutSystemControl) } # Determine what should be the initial value of the markers for each bus. # This depends on the model of the associated Qblox module and the `output` setting of the associated sequencer. From b769a5808d443eb782c3840a5d96cf17a17ecf4a Mon Sep 17 00:00:00 2001 From: jvallsq Date: Fri, 6 Sep 2024 09:40:38 +0200 Subject: [PATCH 03/15] Modified sync to take de,ay into account --- src/qililab/qprogram/qblox_compiler.py | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/src/qililab/qprogram/qblox_compiler.py b/src/qililab/qprogram/qblox_compiler.py index ec72392db..0751d6776 100644 --- a/src/qililab/qprogram/qblox_compiler.py +++ b/src/qililab/qprogram/qblox_compiler.py @@ -161,7 +161,7 @@ def traverse(block: Block): if isinstance(element, Play) and not delay_implemented: for bus in self._buses: if self._buses[bus].delay != 0: - self._handle_wait(element=Wait(bus=bus, duration=self._buses[bus].delay)) + self._handle_wait(element=Wait(bus=bus, duration=self._buses[bus].delay), delay = True) delay_implemented = True handler = self._handlers.get(type(element)) if not handler: @@ -172,7 +172,7 @@ def traverse(block: Block): if not self._qprogram.qblox.disable_autosync and isinstance( element, (ForLoop, Parallel, Loop, Average) ): - self._handle_sync(element=Sync(buses=None)) + self._handle_sync(element=Sync(buses=None), delay = True) if appended: for bus in self._buses: self._buses[bus].qpy_block_stack.pop() @@ -404,7 +404,7 @@ def _handle_set_markers(self, element: SetMarkers): component=QPyInstructions.SetMrk(marker_outputs=marker_outputs) ) - def _handle_wait(self, element: Wait): + def _handle_wait(self, element: Wait, delay:bool = False): duration: QPyProgram.Register | int if isinstance(element.duration, Variable): duration = self._buses[element.bus].variable_to_register[element.duration] @@ -415,7 +415,8 @@ def _handle_wait(self, element: Wait): else: convert = QbloxCompiler._convert_value(element) duration = convert(element.duration) - self._buses[element.bus].static_duration += duration + if not delay: + self._buses[element.bus].static_duration += duration # loop over wait instructions if static duration is longer than allowed qblox max wait time of 2**16 -4 self._handle_add_waits(bus=element.bus, duration=duration) @@ -438,7 +439,7 @@ def _handle_add_waits(self, bus: str, duration: int): component=QPyInstructions.Wait(wait_time=duration % INST_MAX_WAIT) ) - def _handle_sync(self, element: Sync): + def _handle_sync(self, element: Sync, delay:bool = False): # Get the buses involved in the sync operation. buses = set(element.buses or self._buses) @@ -457,16 +458,22 @@ def _handle_sync(self, element: Sync): self.__handle_dynamic_sync(buses=buses) else: # If no, calculating the difference is trivial. - self.__handle_static_sync(buses=buses) + self.__handle_static_sync(buses=buses, delay=delay) # In any case, mark al buses as synced. for bus in buses: self._buses[bus].marked_for_sync = False - def __handle_static_sync(self, buses: set[str]): + def __handle_static_sync(self, buses: set[str], delay:bool = False): max_duration = max(self._buses[bus].static_duration for bus in buses) + if delay: + max_delay = max(self._buses[bus].delay for bus in buses) for bus in buses: - duration_diff = max_duration - self._buses[bus].static_duration + if delay: + delay_diff = max_delay - self._buses[bus].delay + duration_diff = max_duration - self._buses[bus].static_duration + delay_diff + else: + duration_diff = max_duration - self._buses[bus].static_duration if duration_diff > 0: # loop over wait instructions if static duration is longer than allowed qblox max wait time of 2**16 -4 self._handle_add_waits(bus=bus, duration=duration_diff) From 9b9312e9e7e677c21e21e7bd7c05987e80e4d99d Mon Sep 17 00:00:00 2001 From: jvallsq Date: Fri, 6 Sep 2024 10:05:20 +0200 Subject: [PATCH 04/15] removed mandatory delay from awg_sequencers --- .../instruments/awg_analog_digital_converter.py | 16 ---------------- .../awg_settings/awg_adc_sequencer.py | 1 - .../instruments/awg_settings/awg_sequencer.py | 1 - 3 files changed, 18 deletions(-) diff --git a/src/qililab/instruments/awg_analog_digital_converter.py b/src/qililab/instruments/awg_analog_digital_converter.py index a6595d1ec..bd92ead96 100644 --- a/src/qililab/instruments/awg_analog_digital_converter.py +++ b/src/qililab/instruments/awg_analog_digital_converter.py @@ -95,9 +95,6 @@ def setup(self, parameter: Parameter, value: float | str | bool, channel_id: int if parameter == Parameter.TIME_OF_FLIGHT: self._set_time_of_flight(value=value, sequencer_id=channel_id) return - if parameter == Parameter.DELAY: - self._set_delay(value=value, sequencer_id=channel_id) - return raise ParameterNotFound(f"Invalid Parameter: {parameter.value}") @@ -347,19 +344,6 @@ def _set_time_of_flight(self, value: int | float | str | bool, sequencer_id: int """ cast(AWGADCSequencer, self.get_sequencer(sequencer_id)).time_of_flight = int(value) - @Instrument.CheckParameterValueFloatOrInt - def _set_delay(self, value: int | float | str | bool, sequencer_id: int): - """set delay - - Args: - value (int | float | str | bool): value to update - sequencer_id (int): sequencer to update the value - - Raises: - ValueError: when value type is not bool - """ - cast(AWGADCSequencer, self.get_sequencer(sequencer_id)).delay = int(value) - @property def acquisition_delay_time(self): """AWG 'delay_before_readout' property. diff --git a/src/qililab/instruments/awg_settings/awg_adc_sequencer.py b/src/qililab/instruments/awg_settings/awg_adc_sequencer.py index 5e9f8c5ae..9056b08b8 100644 --- a/src/qililab/instruments/awg_settings/awg_adc_sequencer.py +++ b/src/qililab/instruments/awg_settings/awg_adc_sequencer.py @@ -49,7 +49,6 @@ class AWGADCSequencer(AWGSequencer): # pylint: disable=too-many-instance-attrib threshold: float threshold_rotation: float time_of_flight: int # nanoseconds - delay: int # nanoseconds def __post_init__(self): """Cast all enum attributes to its corresponding Enum class.""" diff --git a/src/qililab/instruments/awg_settings/awg_sequencer.py b/src/qililab/instruments/awg_settings/awg_sequencer.py index 5d9886105..d8e576e7a 100644 --- a/src/qililab/instruments/awg_settings/awg_sequencer.py +++ b/src/qililab/instruments/awg_settings/awg_sequencer.py @@ -51,7 +51,6 @@ class AWGSequencer: # pylint: disable=too-many-instance-attributes gain_q: float offset_i: float offset_q: float - delay: int def to_dict(self): """Return a dict representation of an AWG Sequencer.""" From a5a714b921e996be7126d898d1598d78bc404b36 Mon Sep 17 00:00:00 2001 From: "jordi.valls@qilimanjaro.tech" Date: Fri, 6 Sep 2024 09:47:47 +0000 Subject: [PATCH 05/15] Black --- src/qililab/platform/platform.py | 5 +---- src/qililab/qprogram/qblox_compiler.py | 10 +++++----- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/src/qililab/platform/platform.py b/src/qililab/platform/platform.py index 7d9819c58..7dfafa732 100644 --- a/src/qililab/platform/platform.py +++ b/src/qililab/platform/platform.py @@ -725,10 +725,7 @@ def execute_qprogram( # pylint: disable=too-many-locals for bus in buses if isinstance(bus.system_control, ReadoutSystemControl) } - delays = { - bus.alias: int(bus.get_parameter(Parameter.DELAY)) - for bus in buses - } + delays = {bus.alias: int(bus.get_parameter(Parameter.DELAY)) for bus in buses} # Determine what should be the initial value of the markers for each bus. # This depends on the model of the associated Qblox module and the `output` setting of the associated sequencer. markers = {} diff --git a/src/qililab/qprogram/qblox_compiler.py b/src/qililab/qprogram/qblox_compiler.py index 0751d6776..5c40a4709 100644 --- a/src/qililab/qprogram/qblox_compiler.py +++ b/src/qililab/qprogram/qblox_compiler.py @@ -161,7 +161,7 @@ def traverse(block: Block): if isinstance(element, Play) and not delay_implemented: for bus in self._buses: if self._buses[bus].delay != 0: - self._handle_wait(element=Wait(bus=bus, duration=self._buses[bus].delay), delay = True) + self._handle_wait(element=Wait(bus=bus, duration=self._buses[bus].delay), delay=True) delay_implemented = True handler = self._handlers.get(type(element)) if not handler: @@ -172,7 +172,7 @@ def traverse(block: Block): if not self._qprogram.qblox.disable_autosync and isinstance( element, (ForLoop, Parallel, Loop, Average) ): - self._handle_sync(element=Sync(buses=None), delay = True) + self._handle_sync(element=Sync(buses=None), delay=True) if appended: for bus in self._buses: self._buses[bus].qpy_block_stack.pop() @@ -404,7 +404,7 @@ def _handle_set_markers(self, element: SetMarkers): component=QPyInstructions.SetMrk(marker_outputs=marker_outputs) ) - def _handle_wait(self, element: Wait, delay:bool = False): + def _handle_wait(self, element: Wait, delay: bool = False): duration: QPyProgram.Register | int if isinstance(element.duration, Variable): duration = self._buses[element.bus].variable_to_register[element.duration] @@ -439,7 +439,7 @@ def _handle_add_waits(self, bus: str, duration: int): component=QPyInstructions.Wait(wait_time=duration % INST_MAX_WAIT) ) - def _handle_sync(self, element: Sync, delay:bool = False): + def _handle_sync(self, element: Sync, delay: bool = False): # Get the buses involved in the sync operation. buses = set(element.buses or self._buses) @@ -464,7 +464,7 @@ def _handle_sync(self, element: Sync, delay:bool = False): for bus in buses: self._buses[bus].marked_for_sync = False - def __handle_static_sync(self, buses: set[str], delay:bool = False): + def __handle_static_sync(self, buses: set[str], delay: bool = False): max_duration = max(self._buses[bus].static_duration for bus in buses) if delay: max_delay = max(self._buses[bus].delay for bus in buses) From d62481d524524114fbf8bf5705a29eb9e321cc9c Mon Sep 17 00:00:00 2001 From: "jordi.valls@qilimanjaro.tech" Date: Fri, 6 Sep 2024 10:25:24 +0000 Subject: [PATCH 06/15] added missing tests --- tests/qprogram/test_qblox_compiler.py | 58 +++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/tests/qprogram/test_qblox_compiler.py b/tests/qprogram/test_qblox_compiler.py index 7201cf14c..19fcb2b39 100644 --- a/tests/qprogram/test_qblox_compiler.py +++ b/tests/qprogram/test_qblox_compiler.py @@ -1191,6 +1191,64 @@ def test_multiple_play_operations_with_no_Q_waveform(self, multiple_play_operati "start,stop,step,expected_result", [(0, 10, 1, 11), (10, 0, -1, 11), (1, 2.05, 0.1, 11)], ) + def test_delay(self, average_with_for_loop_nshots: QProgram): + compiler = QbloxCompiler() + sequences, _ = compiler.compile(qprogram=average_with_for_loop_nshots, delays={"drive": 20}) + + assert len(sequences) == 2 + assert "drive" in sequences + assert "readout" in sequences + + drive_str = """ + setup: + wait_sync 4 + set_mrk 0 + upd_param 4 + + main: + move 1000, R0 + avg_0: + move 3, R1 + move 0, R2 + loop_0: + wait 20 + play 0, 1, 40 + wait 2940 + add R2, 1, R2 + loop R1, @loop_0 + loop R0, @avg_0 + set_mrk 0 + upd_param 4 + stop + """ + readout_str = """ + setup: + wait_sync 4 + set_mrk 0 + upd_param 4 + + main: + move 1000, R0 + avg_0: + move 1, R1 + move 0, R2 + move 0, R3 + move 3, R4 + move 0, R5 + loop_0: + play 0, 1, 1000 + acquire_weighed 0, R3, R2, R1, 2000 + add R3, 1, R3 + add R5, 1, R5 + loop R4, @loop_0 + loop R0, @avg_0 + set_mrk 0 + upd_param 4 + stop + """ + assert is_q1asm_equal(sequences["drive"], drive_str) + assert is_q1asm_equal(sequences["readout"], readout_str) + def test_calculate_iterations(self, start, stop, step, expected_result): result = QbloxCompiler._calculate_iterations(start, stop, step) assert result == expected_result From b15c047d9dc56e39deb0780477be5d2fe4ec5d48 Mon Sep 17 00:00:00 2001 From: "jordi.valls@qilimanjaro.tech" Date: Fri, 6 Sep 2024 12:35:40 +0000 Subject: [PATCH 07/15] test fix --- src/qililab/qprogram/qblox_compiler.py | 2 +- tests/qprogram/test_qblox_compiler.py | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/qililab/qprogram/qblox_compiler.py b/src/qililab/qprogram/qblox_compiler.py index 5c40a4709..a60d6e15c 100644 --- a/src/qililab/qprogram/qblox_compiler.py +++ b/src/qililab/qprogram/qblox_compiler.py @@ -133,7 +133,7 @@ def __init__(self) -> None: self._buses: dict[str, BusCompilationInfo] self._sync_counter: int - def compile( + def compile( # noqa: C901 self, qprogram: QProgram, bus_mapping: dict[str, str] | None = None, diff --git a/tests/qprogram/test_qblox_compiler.py b/tests/qprogram/test_qblox_compiler.py index 19fcb2b39..3526a6130 100644 --- a/tests/qprogram/test_qblox_compiler.py +++ b/tests/qprogram/test_qblox_compiler.py @@ -1187,10 +1187,6 @@ def test_multiple_play_operations_with_no_Q_waveform(self, multiple_play_operati """ assert is_q1asm_equal(sequences["drive"], drive_str) - @pytest.mark.parametrize( - "start,stop,step,expected_result", - [(0, 10, 1, 11), (10, 0, -1, 11), (1, 2.05, 0.1, 11)], - ) def test_delay(self, average_with_for_loop_nshots: QProgram): compiler = QbloxCompiler() sequences, _ = compiler.compile(qprogram=average_with_for_loop_nshots, delays={"drive": 20}) From 68b0223cf2b9fcbdcadfb4fff022a097d3cb2689 Mon Sep 17 00:00:00 2001 From: "jordi.valls@qilimanjaro.tech" Date: Fri, 6 Sep 2024 12:53:48 +0000 Subject: [PATCH 08/15] fixed tests --- tests/qprogram/test_qblox_compiler.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/qprogram/test_qblox_compiler.py b/tests/qprogram/test_qblox_compiler.py index 8d50c09b9..85e5af276 100644 --- a/tests/qprogram/test_qblox_compiler.py +++ b/tests/qprogram/test_qblox_compiler.py @@ -1209,7 +1209,7 @@ def test_delay(self, average_with_for_loop_nshots: QProgram): loop_0: wait 20 play 0, 1, 40 - wait 2940 + wait 2960 add R2, 1, R2 loop R1, @loop_0 loop R0, @avg_0 @@ -1235,6 +1235,7 @@ def test_delay(self, average_with_for_loop_nshots: QProgram): play 0, 1, 1000 acquire_weighed 0, R3, R2, R1, 2000 add R3, 1, R3 + wait 20 add R5, 1, R5 loop R4, @loop_0 loop R0, @avg_0 From d642a28ba1394e6b65f38b8f1eb1d12de76966f4 Mon Sep 17 00:00:00 2001 From: "jordi.valls@qilimanjaro.tech" Date: Fri, 6 Sep 2024 13:16:19 +0000 Subject: [PATCH 09/15] tests --- tests/qprogram/test_qblox_compiler.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/qprogram/test_qblox_compiler.py b/tests/qprogram/test_qblox_compiler.py index 85e5af276..885d9e148 100644 --- a/tests/qprogram/test_qblox_compiler.py +++ b/tests/qprogram/test_qblox_compiler.py @@ -1246,6 +1246,10 @@ def test_delay(self, average_with_for_loop_nshots: QProgram): assert is_q1asm_equal(sequences["drive"], drive_str) assert is_q1asm_equal(sequences["readout"], readout_str) + @pytest.mark.parametrize( + "start,stop,step,expected_result", + [(0, 10, 1, 11), (10, 0, -1, 11), (1, 2.05, 0.1, 11)], + ) def test_calculate_iterations(self, start, stop, step, expected_result): result = QbloxCompiler._calculate_iterations(start, stop, step) assert result == expected_result From 9c3f131b71440788ff9b0492574608af437fb129 Mon Sep 17 00:00:00 2001 From: "jordi.valls@qilimanjaro.tech" Date: Fri, 6 Sep 2024 13:39:24 +0000 Subject: [PATCH 10/15] aDDED NEGATIVE DELAYS --- src/qililab/qprogram/qblox_compiler.py | 8 +++- tests/qprogram/test_qblox_compiler.py | 58 ++++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 1 deletion(-) diff --git a/src/qililab/qprogram/qblox_compiler.py b/src/qililab/qprogram/qblox_compiler.py index a60d6e15c..a6f9859db 100644 --- a/src/qililab/qprogram/qblox_compiler.py +++ b/src/qililab/qprogram/qblox_compiler.py @@ -160,8 +160,14 @@ def traverse(block: Block): for element in block.elements: if isinstance(element, Play) and not delay_implemented: for bus in self._buses: - if self._buses[bus].delay != 0: + if self._buses[bus].delay > 0: self._handle_wait(element=Wait(bus=bus, duration=self._buses[bus].delay), delay=True) + elif self._buses[bus].delay < 0: + for other_buses in self._buses: + if other_buses != bus: + self._handle_wait( + element=Wait(bus=other_buses, duration=-self._buses[bus].delay), delay=True + ) delay_implemented = True handler = self._handlers.get(type(element)) if not handler: diff --git a/tests/qprogram/test_qblox_compiler.py b/tests/qprogram/test_qblox_compiler.py index 885d9e148..767fa4251 100644 --- a/tests/qprogram/test_qblox_compiler.py +++ b/tests/qprogram/test_qblox_compiler.py @@ -1246,6 +1246,64 @@ def test_delay(self, average_with_for_loop_nshots: QProgram): assert is_q1asm_equal(sequences["drive"], drive_str) assert is_q1asm_equal(sequences["readout"], readout_str) + def test_negative_delay(self, average_with_for_loop_nshots: QProgram): + compiler = QbloxCompiler() + sequences, _ = compiler.compile(qprogram=average_with_for_loop_nshots, delays={"drive": -20}) + + assert len(sequences) == 2 + assert "drive" in sequences + assert "readout" in sequences + + drive_str = """ + setup: + wait_sync 4 + set_mrk 0 + upd_param 4 + + main: + move 1000, R0 + avg_0: + move 3, R1 + move 0, R2 + loop_0: + play 0, 1, 40 + wait 2980 + add R2, 1, R2 + loop R1, @loop_0 + loop R0, @avg_0 + set_mrk 0 + upd_param 4 + stop + """ + readout_str = """ + setup: + wait_sync 4 + set_mrk 0 + upd_param 4 + + main: + move 1000, R0 + avg_0: + move 1, R1 + move 0, R2 + move 0, R3 + move 3, R4 + move 0, R5 + loop_0: + wait 20 + play 0, 1, 1000 + acquire_weighed 0, R3, R2, R1, 2000 + add R3, 1, R3 + add R5, 1, R5 + loop R4, @loop_0 + loop R0, @avg_0 + set_mrk 0 + upd_param 4 + stop + """ + assert is_q1asm_equal(sequences["drive"], drive_str) + assert is_q1asm_equal(sequences["readout"], readout_str) + @pytest.mark.parametrize( "start,stop,step,expected_result", [(0, 10, 1, 11), (10, 0, -1, 11), (1, 2.05, 0.1, 11)], From d0d24ba40035f858f54e8bd3b366891719185c5a Mon Sep 17 00:00:00 2001 From: "jordi.valls@qilimanjaro.tech" Date: Fri, 6 Sep 2024 14:29:32 +0000 Subject: [PATCH 11/15] pylint --- src/qililab/qprogram/qblox_compiler.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qililab/qprogram/qblox_compiler.py b/src/qililab/qprogram/qblox_compiler.py index a6f9859db..36f84cd7e 100644 --- a/src/qililab/qprogram/qblox_compiler.py +++ b/src/qililab/qprogram/qblox_compiler.py @@ -153,7 +153,7 @@ def compile( # noqa: C901 dict[str, QPy.Sequence]: A dictionary with the buses participating in the QProgram as keys and the corresponding Sequence as values. """ - def traverse(block: Block): + def traverse(block: Block): # pylint: disable=too-many-nested-blocks delay_implemented = False for bus in self._buses: self._buses[bus].qprogram_block_stack.append(block) From 0b788f6d319da2ea9389b7dcf909ef954e05dab0 Mon Sep 17 00:00:00 2001 From: "jordi.valls@qilimanjaro.tech" Date: Fri, 6 Sep 2024 14:43:03 +0000 Subject: [PATCH 12/15] pylint --- src/qililab/qprogram/qblox_compiler.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/qililab/qprogram/qblox_compiler.py b/src/qililab/qprogram/qblox_compiler.py index 36f84cd7e..babc72d84 100644 --- a/src/qililab/qprogram/qblox_compiler.py +++ b/src/qililab/qprogram/qblox_compiler.py @@ -153,11 +153,11 @@ def compile( # noqa: C901 dict[str, QPy.Sequence]: A dictionary with the buses participating in the QProgram as keys and the corresponding Sequence as values. """ - def traverse(block: Block): # pylint: disable=too-many-nested-blocks + def traverse(block: Block): delay_implemented = False for bus in self._buses: self._buses[bus].qprogram_block_stack.append(block) - for element in block.elements: + for element in block.elements: # pylint: disable=too-many-nested-blocks if isinstance(element, Play) and not delay_implemented: for bus in self._buses: if self._buses[bus].delay > 0: From 96a760d9151bcba591a417184468ab5e9a357f0a Mon Sep 17 00:00:00 2001 From: jordivallsq <151619025+jordivallsq@users.noreply.github.com> Date: Mon, 9 Sep 2024 10:38:04 +0200 Subject: [PATCH 13/15] Update qblox_compiler.py --- src/qililab/qprogram/qblox_compiler.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qililab/qprogram/qblox_compiler.py b/src/qililab/qprogram/qblox_compiler.py index babc72d84..37e4b97f0 100644 --- a/src/qililab/qprogram/qblox_compiler.py +++ b/src/qililab/qprogram/qblox_compiler.py @@ -133,7 +133,7 @@ def __init__(self) -> None: self._buses: dict[str, BusCompilationInfo] self._sync_counter: int - def compile( # noqa: C901 + def compile( # noqa: max-complexity=5 self, qprogram: QProgram, bus_mapping: dict[str, str] | None = None, From c8b535afe7a5fd12aedb28c13d69c3ac5d36c4cd Mon Sep 17 00:00:00 2001 From: jordivallsq <151619025+jordivallsq@users.noreply.github.com> Date: Mon, 9 Sep 2024 10:41:55 +0200 Subject: [PATCH 14/15] Update qblox_compiler.py --- src/qililab/qprogram/qblox_compiler.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qililab/qprogram/qblox_compiler.py b/src/qililab/qprogram/qblox_compiler.py index 37e4b97f0..654d83c52 100644 --- a/src/qililab/qprogram/qblox_compiler.py +++ b/src/qililab/qprogram/qblox_compiler.py @@ -133,7 +133,7 @@ def __init__(self) -> None: self._buses: dict[str, BusCompilationInfo] self._sync_counter: int - def compile( # noqa: max-complexity=5 + def compile( self, qprogram: QProgram, bus_mapping: dict[str, str] | None = None, From 6b9389d9f4760cc7c73bdcc23db54ecaf0f58e7f Mon Sep 17 00:00:00 2001 From: jordivallsq <151619025+jordivallsq@users.noreply.github.com> Date: Mon, 9 Sep 2024 10:45:17 +0200 Subject: [PATCH 15/15] Update qblox_compiler.py --- src/qililab/qprogram/qblox_compiler.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qililab/qprogram/qblox_compiler.py b/src/qililab/qprogram/qblox_compiler.py index 654d83c52..0d535d07a 100644 --- a/src/qililab/qprogram/qblox_compiler.py +++ b/src/qililab/qprogram/qblox_compiler.py @@ -133,7 +133,7 @@ def __init__(self) -> None: self._buses: dict[str, BusCompilationInfo] self._sync_counter: int - def compile( + def compile( # noqa: max-complexity=25 self, qprogram: QProgram, bus_mapping: dict[str, str] | None = None,