diff --git a/src/qibolab/dummy/parameters.json b/src/qibolab/dummy/parameters.json index 4da772817..3199bd943 100644 --- a/src/qibolab/dummy/parameters.json +++ b/src/qibolab/dummy/parameters.json @@ -36,6 +36,13 @@ ] }, "instruments": { + "dummy": { + "bounds": { + "waveforms": 0, + "readout": 0, + "instructions": 0 + } + }, "twpa_pump": { "power": 10, "frequency": 1000000000.0 diff --git a/src/qibolab/instruments/abstract.py b/src/qibolab/instruments/abstract.py index e034cda67..bdd44e66c 100644 --- a/src/qibolab/instruments/abstract.py +++ b/src/qibolab/instruments/abstract.py @@ -58,12 +58,19 @@ class Controller(Instrument): PortType = Port """Class used by the instrument to instantiate ports.""" - BOUNDS: Bounds = Bounds(0, 0, 0) - """Estimated limitations of the device memory.""" - def __init__(self, name, address): super().__init__(name, address) self._ports = {} + self.bounds: Bounds = Bounds(0, 0, 0) + """Estimated limitations of the device memory.""" + + def setup(self, bounds): + """Set unrolling batch bounds.""" + self.bounds = Bounds(**bounds) + + def dump(self): + """Dump unrolling batch bounds.""" + return {"bounds": asdict(self.bounds)} @property @abstractmethod diff --git a/src/qibolab/instruments/qblox/controller.py b/src/qibolab/instruments/qblox/controller.py index 65d0df2f2..f657756c0 100644 --- a/src/qibolab/instruments/qblox/controller.py +++ b/src/qibolab/instruments/qblox/controller.py @@ -16,13 +16,6 @@ from qibolab.sweeper import Parameter, Sweeper, SweeperType from qibolab.unrolling import Bounds -MAX_DURATION = int(4e4) # Translate SEQUENCER_MEMORY = 2**17 into pulse duration -"""Maximum duration of the control pulses [1q 40ns] [Rough estimate].""" -MAX_READOUT = int(1e6) -"""Maximum number of readout pulses [Not estimated].""" -MAX_INSTRUCTIONS = int(1e6) -"""Maximum instructions size [Not estimated].""" - SEQUENCER_MEMORY = 2**17 @@ -34,12 +27,6 @@ class QbloxController(Controller): modules (dict): A dictionay with the qblox modules connected to the experiment. """ - BOUNDS = Bounds( - waveforms=MAX_DURATION, - readout=MAX_READOUT, - instructions=MAX_READOUT, - ) - def __init__( self, name, address: str, modules, internal_reference_clock: bool = True ): @@ -49,6 +36,13 @@ def __init__( self.cluster: QbloxCluster = None self.modules: dict = modules self._reference_clock = "internal" if internal_reference_clock else "external" + self.bounds = Bounds( + waveforms=int( + 4e4 + ), # Translate SEQUENCER_MEMORY = 2**17 into pulse duration + readout=int(1e6), + instructions=int(1e6), + ) signal.signal(signal.SIGTERM, self._termination_handler) @property @@ -84,13 +78,6 @@ def disconnect(self): self.cluster.close() self.is_connected = False - def setup(self): - """Empty method to comply with Instrument interface. - - Setup of the modules happens in the platform ``create`` method - using :meth:`qibolab.serialize.load_instrument_settings`. - """ - def _termination_handler(self, signum, frame): """Calls all modules to stop if the program receives a termination signal.""" diff --git a/src/qibolab/instruments/qm/controller.py b/src/qibolab/instruments/qm/controller.py index 2fdf0d0e4..4f07be423 100644 --- a/src/qibolab/instruments/qm/controller.py +++ b/src/qibolab/instruments/qm/controller.py @@ -24,13 +24,6 @@ """Offset to be added to Octave addresses, because they must be 11xxx, where xxx are the last three digits of the Octave IP address.""" -MAX_DURATION = int(4e4) -"""Maximum duration of the control pulses [1q 40ns] [Rough estimate].""" -MAX_READOUT = int(30) -"""Maximum number of readout pulses [Not estimated].""" -MAX_INSTRUCTIONS = int(1e6) -"""Maximum instructions size [Not estimated].""" - def declare_octaves(octaves, host, calibration_path=None): """Initiate Octave configuration and add octaves info. @@ -126,16 +119,12 @@ class QMController(Controller): """Dictionary containing the :class:`qibolab.instruments.qm.devices.Octave` instruments being used.""" - BOUNDS = Bounds( - waveforms=MAX_DURATION, - readout=MAX_READOUT, - instructions=MAX_INSTRUCTIONS, - ) - time_of_flight: int = 0 """Time of flight used for hardware signal integration.""" smearing: int = 0 """Smearing used for hardware signal integration.""" + bounds: Bounds = Bounds(0, 0, 0) + """Maximum bounds used for batching in sequence unrolling.""" calibration_path: Optional[str] = None """Path to the JSON file that contains the mixer calibration.""" script_file_name: Optional[str] = None @@ -170,6 +159,12 @@ class QMController(Controller): def __post_init__(self): super().__init__(self.name, self.address) + # redefine bounds because abstract instrument overwrites them + self.bounds = Bounds( + waveforms=int(4e4), + readout=30, + instructions=int(1e6), + ) # convert lists to dicts if not isinstance(self.opxs, dict): self.opxs = {instr.name: instr for instr in self.opxs} @@ -223,9 +218,6 @@ def connect(self): ) self.is_connected = True - def setup(self): - """Deprecated method.""" - def disconnect(self): """Disconnect from QM manager.""" if self.manager is not None: diff --git a/src/qibolab/instruments/rfsoc/driver.py b/src/qibolab/instruments/rfsoc/driver.py index 934318067..46172c37c 100644 --- a/src/qibolab/instruments/rfsoc/driver.py +++ b/src/qibolab/instruments/rfsoc/driver.py @@ -69,9 +69,6 @@ def connect(self): def disconnect(self): """Empty method to comply with Instrument interface.""" - def setup(self): - """Empty deprecated method.""" - def _execute_pulse_sequence( self, sequence: PulseSequence, diff --git a/src/qibolab/instruments/zhinst.py b/src/qibolab/instruments/zhinst.py index 3d177364a..ef7e5e22e 100644 --- a/src/qibolab/instruments/zhinst.py +++ b/src/qibolab/instruments/zhinst.py @@ -55,14 +55,6 @@ SWEEPER_START = {"start"} -MAX_DURATION = int(4e4) -"""Maximum duration of the control pulses [1q 40ns] [Rough estimate].""" -MAX_READOUT = 250 -"""Maximum number of readout pulses [Not estimated].""" -MAX_INSTRUCTIONS = int(1e6) -"""Maximum instructions size [Not estimated].""" - - def select_pulse(pulse, pulse_type): """Pulse translation.""" @@ -298,12 +290,6 @@ class Zurich(Controller): PortType = ZhPort - BOUNDS = Bounds( - waveforms=MAX_DURATION, - readout=MAX_READOUT, - instructions=MAX_INSTRUCTIONS, - ) - def __init__( self, name, device_setup, use_emulation=False, time_of_flight=0.0, smearing=0.0 ): @@ -337,6 +323,12 @@ def __init__( self.results = None "Zurich experiment definitions" + self.bounds = Bounds( + waveforms=int(4e4), + readout=250, + instructions=int(1e6), + ) + self.acquisition_type = None "To store if the AcquisitionType.SPECTROSCOPY needs to be enabled by parsing the sequence" @@ -371,9 +363,6 @@ def disconnect(self): self.device = self.session.disconnect() self.is_connected = False - def setup(self, *args, **kwargs): - """Empty method to comply with Instrument interface.""" - def calibration_step(self, qubits, couplers, options): """Zurich general pre experiment calibration definitions. diff --git a/src/qibolab/platform.py b/src/qibolab/platform.py index c14d69120..e32d1fdc9 100644 --- a/src/qibolab/platform.py +++ b/src/qibolab/platform.py @@ -240,7 +240,7 @@ def execute_pulse_sequences( } results = defaultdict(list) - bounds = kwargs.get("bounds", self._controller.BOUNDS) + bounds = kwargs.get("bounds", self._controller.bounds) for b in batch(sequences, bounds): sequence, readouts = unroll_sequences(b, options.relaxation_time) result = self._execute(sequence, options, **kwargs) diff --git a/src/qibolab/serialize.py b/src/qibolab/serialize.py index 098a6e7ce..30507c2a7 100644 --- a/src/qibolab/serialize.py +++ b/src/qibolab/serialize.py @@ -177,18 +177,19 @@ def dump_instruments(instruments: InstrumentMap) -> dict: data = {} for name, instrument in instruments.items(): try: + # TODO: Migrate all instruments to this approach + # (I think it is also useful for qblox) + settings = instrument.dump() + if len(settings) > 0: + data[name] = settings + except AttributeError: settings = instrument.settings if settings is not None: if isinstance(settings, dict): data[name] = settings else: data[name] = settings.dump() - except AttributeError: - # TODO: Migrate all instruments to this approach - # (I think it is also useful for qblox) - settings = instrument.dump() - if len(settings) > 0: - data[name] = settings + return data diff --git a/tests/dummy_qrc/qblox/parameters.json b/tests/dummy_qrc/qblox/parameters.json index 41cf5bee7..624f8866c 100644 --- a/tests/dummy_qrc/qblox/parameters.json +++ b/tests/dummy_qrc/qblox/parameters.json @@ -30,6 +30,13 @@ ] ], "instruments": { + "qblox_controller": { + "bounds": { + "instructions": 1000000, + "readout": 250, + "waveforms": 40000 + } + }, "twpa_pump": { "frequency": 6535900000, "power": 4 diff --git a/tests/dummy_qrc/qm/parameters.json b/tests/dummy_qrc/qm/parameters.json index 5f2d43a0b..ac63fa311 100644 --- a/tests/dummy_qrc/qm/parameters.json +++ b/tests/dummy_qrc/qm/parameters.json @@ -30,6 +30,13 @@ ] ], "instruments": { + "qm": { + "bounds": { + "waveforms" : 10000, + "readout": 30, + "instructions": 1000000 + } + }, "con1": { "i1": {"gain": 0}, "i2": {"gain": 0} diff --git a/tests/dummy_qrc/qm_octave/parameters.json b/tests/dummy_qrc/qm_octave/parameters.json index c56861589..44e1dbd98 100644 --- a/tests/dummy_qrc/qm_octave/parameters.json +++ b/tests/dummy_qrc/qm_octave/parameters.json @@ -30,6 +30,13 @@ ] ], "instruments": { + "qm": { + "bounds": { + "waveforms" : 10000, + "readout": 30, + "instructions": 1000000 + } + }, "con1": { "i1": { "gain": 0 diff --git a/tests/dummy_qrc/rfsoc/parameters.json b/tests/dummy_qrc/rfsoc/parameters.json index 5e6883262..0fbecb8ec 100644 --- a/tests/dummy_qrc/rfsoc/parameters.json +++ b/tests/dummy_qrc/rfsoc/parameters.json @@ -9,6 +9,13 @@ "relaxation_time": 100000 }, "instruments": { + "tii_rfsoc4x2": { + "bounds": { + "waveforms": 0, + "readout": 0, + "instructions": 0 + } + }, "twpa_a": { "frequency": 6200000000, "power": -1 diff --git a/tests/dummy_qrc/zurich/parameters.json b/tests/dummy_qrc/zurich/parameters.json index df0dc9a10..98af9d1eb 100644 --- a/tests/dummy_qrc/zurich/parameters.json +++ b/tests/dummy_qrc/zurich/parameters.json @@ -36,6 +36,13 @@ "relaxation_time": 300000 }, "instruments": { + "EL_ZURO": { + "bounds": { + "instructions": 1000000, + "readout": 250, + "waveforms": 40000 + } + }, "lo_readout": { "frequency": 5500000000 }, diff --git a/tests/test_instruments_zhinst.py b/tests/test_instruments_zhinst.py index 22e35bfc4..c94fe8135 100644 --- a/tests/test_instruments_zhinst.py +++ b/tests/test_instruments_zhinst.py @@ -735,7 +735,7 @@ def test_batching(dummy_qrc): sequence.add(platform.create_MZ_pulse(0, start=measurement_start)) sequence.add(platform.create_MZ_pulse(1, start=measurement_start)) - batches = list(batch(600 * [sequence], instrument.BOUNDS)) + batches = list(batch(600 * [sequence], instrument.bounds)) # These sequences get limited by the number of measuraments (600/250/2) assert len(batches) == 5 assert len(batches[0]) == 125