Source code for semi_cr.core.station.chip

"""
This module declares a Chip class representing a quantum chip and its associated devices. For now,
it's deserializable from the QCoDes YAML format, but in the future it should hold more chip-related information.

Example of a chip configuration in YAML format:

.. code-block:: yaml

    instruments:
      X002001C1:
        type: semi_cr.core.lab.instrument.chip.Chip
        init:
          devices:
            D1:
              type: semi_cr.core.lab.devices.multiplexer.Multiplexer
              pins:
                T2:
                  type: Gate
                  pads:
                    - QboardII[8]
                T4:
                  type: Gate
                  pads:
                    - QboardII[17]
                B1:
                  type: Gate
                  pads:
                    - QboardII[38]
                B4:
                  type: Gate
                  pads:
                    - QboardII[32]
                RF_In:
                  type: RFInput
                  pads:
                    - QboardII[RF1]
                RF_Out_1:
                  type: RFOutput
                  pads:
                    - QboardII[RF4]
                RF_Out_2:
                  type: RFOutput
                  pads:
                    - QboardII[RF8]
                RF_Out_3:
                  type: RFOutput
                  pads:
                    - QboardII[RF10]
                RF_Out_4:
                  type: RFOutput
                  pads:
                    - QboardII[RF12]

"""

from __future__ import annotations

from dataclasses import dataclass, field
from typing import TYPE_CHECKING

from semi_cr.core.station.device import QuantumDevice
from semi_cr.core.station.graph import GraphEdge, GraphNode

if TYPE_CHECKING:
    from collections.abc import Iterable

    from quam_builder.architecture.quantum_dots import BaseQuamQD

    from semi_cr.core.station.instruments.qcodes_proxy import QCoDeSInstrumentSpec
    from semi_cr.core.station.station import NQCPStation


[docs] @dataclass class Chip: chip_id: str parent_ref: NQCPStation = field(repr=False, compare=False) devices: list[QuantumDevice] = field(default_factory=list, compare=False, repr=False) def __rich__(self): # noqa: PLW3201 yield ("Chip ID", self.chip_id)
[docs] def device(self, device_id: str) -> QuantumDevice: """Gets a device by name. :returns: The device matching ``device_id``. :raises KeyError: If no matching device exists. """ for device in self.devices: if device.device_id == device_id: return device raise KeyError(f"Device not found: {device_id}")
[docs] @classmethod def from_instrument_spec(cls, spec: QCoDeSInstrumentSpec, parent_ref: NQCPStation) -> Chip: """Given the parsed yaml of a chip, return a Chip object. Recursively creates QuantumDevice objects. `spec` is a tuple: - First element is the identifier of the Chip - Second element is the QCoDes compatible YAML structure underneath it """ chip_id = spec[0] aux_data = spec[1] # Just a quick sanity check... if aux_data["type"] != "semi_cr.core.lab.instrument.chip.Chip": raise ValueError("Chip type not supported") # Instantiate QuantumDevice objects from the chip's manifest device_configs = aux_data["init"]["devices"].items() # device_configs are now tuples of key -> dict pairs chip = cls( chip_id=chip_id, parent_ref=parent_ref, ) chip.devices = [QuantumDevice.from_instrument_spec(device_config, chip) for device_config in device_configs] return chip
[docs] def graph_nodes(self) -> Iterable[GraphNode]: """Iterates over all devices to return the graph nodes for this chip.""" for device in self.devices: yield from device.graph_nodes()
[docs] def graph_edges(self) -> Iterable[GraphEdge]: """Iterates over all devices to return any graph edges for this chip.""" for device in self.devices: yield from device.graph_edges()
[docs] def to_quam(self) -> BaseQuamQD: """Exports a representation of the current chip for use with quam-builder, such as the gate tuning web app Torbjørn presented. At the meeting on 2026-09-28 we decided that it should live on our Chip representation, not device or station. :returns: A :class:`BaseQuamQD` representation of the current chip.""" # We start by making some QM-related imports. We don't want to do that globally because it carries side # effects and takes forever. Disabling PLC0415 momentarily lets us do that. from quam_builder.architecture.quantum_dots import BaseQuamQD # noqa: PLC0415 state = BaseQuamQD() # TODO: Write a test suite for this integration WHILE WE DESIGN IT to make sure the API stays user-centric # TODO: Look at the builders `build_quam.py` (is in quam_builder/builder/quantum_dots on release/nightly) raise NotImplementedError() return state