Skip to content

Commit

Permalink
Merge pull request #832 from qiboteam/bounds_settings
Browse files Browse the repository at this point in the history
Unrolling bounds as instrument settings
  • Loading branch information
stavros11 authored Mar 20, 2024
2 parents d42f02b + 4946322 commit aa1d165
Show file tree
Hide file tree
Showing 14 changed files with 82 additions and 67 deletions.
7 changes: 7 additions & 0 deletions src/qibolab/dummy/parameters.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,13 @@
]
},
"instruments": {
"dummy": {
"bounds": {
"waveforms": 0,
"readout": 0,
"instructions": 0
}
},
"twpa_pump": {
"power": 10,
"frequency": 1000000000.0
Expand Down
13 changes: 10 additions & 3 deletions src/qibolab/instruments/abstract.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
27 changes: 7 additions & 20 deletions src/qibolab/instruments/qblox/controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -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


Expand All @@ -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
):
Expand All @@ -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
Expand Down Expand Up @@ -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."""
Expand Down
24 changes: 8 additions & 16 deletions src/qibolab/instruments/qm/controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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}
Expand Down Expand Up @@ -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:
Expand Down
3 changes: 0 additions & 3 deletions src/qibolab/instruments/rfsoc/driver.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
23 changes: 6 additions & 17 deletions src/qibolab/instruments/zhinst.py
Original file line number Diff line number Diff line change
Expand Up @@ -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."""

Expand Down Expand Up @@ -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
):
Expand Down Expand Up @@ -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"

Expand Down Expand Up @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion src/qibolab/platform.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
13 changes: 7 additions & 6 deletions src/qibolab/serialize.py
Original file line number Diff line number Diff line change
Expand Up @@ -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


Expand Down
7 changes: 7 additions & 0 deletions tests/dummy_qrc/qblox/parameters.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,13 @@
]
],
"instruments": {
"qblox_controller": {
"bounds": {
"instructions": 1000000,
"readout": 250,
"waveforms": 40000
}
},
"twpa_pump": {
"frequency": 6535900000,
"power": 4
Expand Down
7 changes: 7 additions & 0 deletions tests/dummy_qrc/qm/parameters.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,13 @@
]
],
"instruments": {
"qm": {
"bounds": {
"waveforms" : 10000,
"readout": 30,
"instructions": 1000000
}
},
"con1": {
"i1": {"gain": 0},
"i2": {"gain": 0}
Expand Down
7 changes: 7 additions & 0 deletions tests/dummy_qrc/qm_octave/parameters.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,13 @@
]
],
"instruments": {
"qm": {
"bounds": {
"waveforms" : 10000,
"readout": 30,
"instructions": 1000000
}
},
"con1": {
"i1": {
"gain": 0
Expand Down
7 changes: 7 additions & 0 deletions tests/dummy_qrc/rfsoc/parameters.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,13 @@
"relaxation_time": 100000
},
"instruments": {
"tii_rfsoc4x2": {
"bounds": {
"waveforms": 0,
"readout": 0,
"instructions": 0
}
},
"twpa_a": {
"frequency": 6200000000,
"power": -1
Expand Down
7 changes: 7 additions & 0 deletions tests/dummy_qrc/zurich/parameters.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,13 @@
"relaxation_time": 300000
},
"instruments": {
"EL_ZURO": {
"bounds": {
"instructions": 1000000,
"readout": 250,
"waveforms": 40000
}
},
"lo_readout": {
"frequency": 5500000000
},
Expand Down
2 changes: 1 addition & 1 deletion tests/test_instruments_zhinst.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit aa1d165

Please sign in to comment.