diff --git a/src/qibolab/_core/instruments/qblox/config/__init__.py b/src/qibolab/_core/instruments/qblox/config/__init__.py index 78c5ee40f..5bafc1478 100644 --- a/src/qibolab/_core/instruments/qblox/config/__init__.py +++ b/src/qibolab/_core/instruments/qblox/config/__init__.py @@ -1,3 +1,4 @@ +from .mixer import QbloxIqMixerConfig as QbloxIqMixerConfig from .module import ModuleConfig as ModuleConfig from .port import PortAddress as PortAddress from .sequencer import SequencerConfig as SequencerConfig diff --git a/src/qibolab/_core/instruments/qblox/config/mixer.py b/src/qibolab/_core/instruments/qblox/config/mixer.py new file mode 100644 index 000000000..6efeef6cc --- /dev/null +++ b/src/qibolab/_core/instruments/qblox/config/mixer.py @@ -0,0 +1,32 @@ +from typing import Literal + +from qibolab._core.components.configs import Config + + +class QbloxIqMixerConfig(Config): + """qblox has 6 sequencers per module. + scale_q_*: The relative amplitude scale/factor of the q channel, to account for I-Q + amplitude imbalance. + phase_q_*: The phase offset of the q channel, to account for I-Q phase + imbalance. + """ + + kind: Literal["qblox-iq-mixer"] = "qblox-iq-mixer" + + offset_i: float = 0.0 + """DC offset for the I component.""" + offset_q: float = 0.0 + """DC offset for the Q component.""" + + scale_q_sequencer0: float = 1.0 + phase_q_sequencer0: float = 0.0 + scale_q_sequencer1: float = 1.0 + phase_q_sequencer1: float = 0.0 + scale_q_sequencer2: float = 1.0 + phase_q_sequencer2: float = 0.0 + scale_q_sequencer3: float = 1.0 + phase_q_sequencer3: float = 0.0 + scale_q_sequencer4: float = 1.0 + phase_q_sequencer4: float = 0.0 + scale_q_sequencer5: float = 1.0 + phase_q_sequencer5: float = 0.0 diff --git a/src/qibolab/_core/instruments/qblox/config/module.py b/src/qibolab/_core/instruments/qblox/config/module.py index 14eda8c06..3ced01a3c 100644 --- a/src/qibolab/_core/instruments/qblox/config/module.py +++ b/src/qibolab/_core/instruments/qblox/config/module.py @@ -5,11 +5,12 @@ from qibolab._core.components import Channel, OscillatorConfig from qibolab._core.components.channels import AcquisitionChannel -from qibolab._core.components.configs import Configs, IqMixerConfig +from qibolab._core.components.configs import Configs from qibolab._core.identifier import ChannelId from qibolab._core.serialize import Model from . import port +from .mixer import QbloxIqMixerConfig __all__ = [] @@ -30,10 +31,10 @@ def mixers( all: dict[ChannelId, str], configs: Configs, module_channels: set[ChannelId], -) -> dict[ChannelId, IqMixerConfig]: +) -> dict[ChannelId, QbloxIqMixerConfig]: # TODO: identical to the `.los()` function, deduplicate it please... return { - id_: cast(IqMixerConfig, configs[mixer]) + id_: cast(QbloxIqMixerConfig, configs[mixer]) for id_, mixer in all.items() if id_ in module_channels } @@ -84,7 +85,7 @@ def build( channels: dict[ChannelId, Channel], configs: Configs, los: dict[ChannelId, OscillatorConfig], - mixers: dict[ChannelId, IqMixerConfig], + mixers: dict[ChannelId, QbloxIqMixerConfig], ) -> "ModuleConfig": # generate port configurations as a dictionary def portconfig(*args, **kwargs) -> tuple[str, port.StrDict]: diff --git a/src/qibolab/_core/instruments/qblox/config/port.py b/src/qibolab/_core/instruments/qblox/config/port.py index c2afd659a..b93362b69 100644 --- a/src/qibolab/_core/instruments/qblox/config/port.py +++ b/src/qibolab/_core/instruments/qblox/config/port.py @@ -8,7 +8,6 @@ from qibolab._core.components.configs import ( Config, DcConfig, - IqMixerConfig, OscillatorConfig, ) from qibolab._core.components.filters import ( @@ -18,6 +17,7 @@ from qibolab._core.serialize import Model from ..identifiers import SlotId +from .mixer import QbloxIqMixerConfig __all__ = [] @@ -163,7 +163,7 @@ def build( in_: bool, out: bool, lo: Optional[OscillatorConfig], - mixer: Optional[IqMixerConfig], + mixer: Optional[QbloxIqMixerConfig], ) -> "PortConfig": """Create port configuration for the desired channel. @@ -229,7 +229,7 @@ def lo(self, lo: OscillatorConfig) -> None: def att_(self, lo: OscillatorConfig) -> None: self.att = int(lo.power) - def mixer(self, mixer: IqMixerConfig) -> None: + def mixer(self, mixer: QbloxIqMixerConfig) -> None: self.offset_path0 = mixer.offset_i self.offset_path1 = mixer.offset_q diff --git a/src/qibolab/_core/instruments/qblox/config/sequencer.py b/src/qibolab/_core/instruments/qblox/config/sequencer.py index 188ce37bd..0bce1cad8 100644 --- a/src/qibolab/_core/instruments/qblox/config/sequencer.py +++ b/src/qibolab/_core/instruments/qblox/config/sequencer.py @@ -10,7 +10,6 @@ AcquisitionConfig, Configs, IqConfig, - IqMixerConfig, OscillatorConfig, ) from qibolab._core.execution_parameters import AcquisitionType @@ -19,6 +18,7 @@ from ..q1asm.ast_ import Acquire, Line from ..sequence import Q1Sequence +from .mixer import QbloxIqMixerConfig from .port import PortAddress __all__ = [] @@ -127,9 +127,11 @@ def build( lo_freq = cast(OscillatorConfig, configs[probe_.lo]).frequency cfg.nco_freq = int(freq - lo_freq) assert probe_.mixer is not None - mixer = cast(IqMixerConfig, configs[probe_.mixer]) - cfg.mixer_corr_gain_ratio = mixer.scale_q - cfg.mixer_corr_phase_offset_degree = mixer.phase_q + mixer = cast(QbloxIqMixerConfig, configs[probe_.mixer]) + cfg.mixer_corr_gain_ratio = getattr(mixer, f"scale_q_sequencer{index}") + cfg.mixer_corr_phase_offset_degree = getattr( + mixer, f"phase_q_sequencer{index}" + ) return cfg