diff --git a/src/qibolab/_core/instruments/rfsoc/constants.py b/src/qibolab/_core/instruments/rfsoc/constants.py new file mode 100644 index 000000000..093774ac0 --- /dev/null +++ b/src/qibolab/_core/instruments/rfsoc/constants.py @@ -0,0 +1,4 @@ +SAMPLING_RATE = 9.8304 +NANO_TO_SECONDS = 1e-9 +HZ_TO_MHZ = 1e-6 +NS_TO_US = 1e-3 diff --git a/src/qibolab/_core/instruments/rfsoc/convert.py b/src/qibolab/_core/instruments/rfsoc/convert.py index 1e036c95c..8e9c2f754 100644 --- a/src/qibolab/_core/instruments/rfsoc/convert.py +++ b/src/qibolab/_core/instruments/rfsoc/convert.py @@ -11,10 +11,9 @@ from qibolab._core.pulses import Pulse from qibolab._core.qubits import Qubit from qibolab._core.sequence import PulseSequence -from qibolab._core.sweeper import BIAS, DURATION, START, Parameter, Sweeper +from qibolab._core.sweeper import Parameter, Sweeper # , BIAS, DURATION, START -HZ_TO_MHZ = 1e-6 -NS_TO_US = 1e-3 +from .constants import HZ_TO_MHZ, NS_TO_US def replace_pulse_shape( @@ -108,11 +107,10 @@ def _( @convert.register -def _( - pulse: Pulse, qubits: dict[int, Qubit], start_delay: float, sampling_rate: float -) -> rfsoc_pulses.Pulse: +def _(pulse: Pulse, start_delay: float, sampling_rate: float) -> rfsoc_pulses.Pulse: """Convert `qibolab.pulses.pulse` to `qibosoq.abstract.Pulse`.""" pulse_type = pulse.type.name.lower() + # remove qubit, use channel instead dac = getattr(qubits[pulse.qubit], pulse_type).port.name adc = qubits[pulse.qubit].feedback.port.name if pulse_type == "readout" else None lo_frequency = pulse_lo_frequency(pulse, qubits) diff --git a/src/qibolab/_core/instruments/rfsoc/driver.py b/src/qibolab/_core/instruments/rfsoc/driver.py index 1cc670801..6107e9300 100644 --- a/src/qibolab/_core/instruments/rfsoc/driver.py +++ b/src/qibolab/_core/instruments/rfsoc/driver.py @@ -22,15 +22,12 @@ from qibolab._core.sequence import PulseSequence from qibolab._core.sweeper import BIAS, ParallelSweepers, Sweeper +from .constants import NS_TO_US, SAMPLING_RATE from .convert import convert, convert_units_sweeper # update docstring __all__ = ["RFSoC"] -SAMPLING_RATE = 9.8304 -NANO_TO_SECONDS = 1e-9 -HZ_TO_MHZ = 1e-6 -NS_TO_US = 1e-3 class RFSoC(Controller): @@ -188,6 +185,9 @@ def _execute_pulse_sequence( Returns: Lists of I and Q value measured """ + + # TODO: pulse conversion + server_commands = { "operation_code": opcode, "cfg": asdict(self.cfg), @@ -257,26 +257,30 @@ def play( A dictionary mapping the readout pulses serial and respective qubits to qibolab results objects """ - if couplers != {}: - raise NotImplementedError( - "The RFSoC driver currently does not support couplers." - ) + # coupler check? + # if couplers != {}: + # raise NotImplementedError( + # "The RFSoC driver currently does not support couplers." + # ) + + # sequence -> sequences + # execution_parameters -> options self.validate_input_command(sequences, options, sweep=(len(sweepers) != 0)) - self.update_cfg(execution_parameters) + self.update_cfg(options) - if execution_parameters.acquisition_type is AcquisitionType.DISCRIMINATION: + if options.acquisition_type is AcquisitionType.DISCRIMINATION: self.cfg.average = False else: - self.cfg.average = ( - execution_parameters.averaging_mode is AveragingMode.CYCLIC - ) + self.cfg.average = options.averaging_mode is AveragingMode.CYCLIC - if execution_parameters.acquisition_type is AcquisitionType.RAW: + if options.acquisition_type is AcquisitionType.RAW: opcode = rfsoc.OperationCode.EXECUTE_PULSE_SEQUENCE_RAW else: opcode = rfsoc.OperationCode.EXECUTE_PULSE_SEQUENCE - toti, totq = self._execute_pulse_sequence(sequence, qubits, opcode) + + # + toti, totq = self._execute_pulse_sequence(sequences, qubits, opcode) results = {} probed_qubits = np.unique([p.qubit for p in sequence.ro_pulses]) @@ -286,28 +290,27 @@ def play( i_pulse = np.array(toti[j][i]) q_pulse = np.array(totq[j][i]) - if ( - execution_parameters.acquisition_type - is AcquisitionType.DISCRIMINATION - ): + if options.acquisition_type is AcquisitionType.DISCRIMINATION: discriminated_shots = self.classify_shots( i_pulse, q_pulse, qubits[ro_pulse.qubit] ) result = self.convert_and_discriminate_samples( - discriminated_shots, execution_parameters + discriminated_shots, options ) else: - result = execution_parameters.results_type(i_pulse + 1j * q_pulse) + result = options.results_type(i_pulse + 1j * q_pulse) results[ro_pulse.qubit] = results[ro_pulse.serial] = result return results - def update_cfg(self, execution_parameters: ExecutionParameters): + ### 1 + # execution_parameters -> options + def update_cfg(self, options: ExecutionParameters): """Update rfsoc.Config object with new parameters.""" - if execution_parameters.nshots is not None: - self.cfg.reps = execution_parameters.nshots - if execution_parameters.relaxation_time is not None: - self.cfg.relaxation_time = execution_parameters.relaxation_time * NS_TO_US + if options.nshots is not None: + self.cfg.reps = options.nshots + if options.relaxation_time is not None: + self.cfg.relaxation_time = options.relaxation_time * NS_TO_US def classify_shots( self, diff --git a/tests/dummy_qrc/rfsoc/calibration.json b/tests/dummy_qrc/rfsoc/calibration.json new file mode 100644 index 000000000..03e6fbb3e --- /dev/null +++ b/tests/dummy_qrc/rfsoc/calibration.json @@ -0,0 +1,24 @@ +{ + "characterization": { + "single_qubit": { + "0": { + "readout_frequency": 7371258599, + "drive_frequency": 5542341844, + "pi_pulse_amplitude": 0.05284168507293318, + "T1": 10441.64173639732, + "T2": 4083.4697338939845, + "threshold": -0.8981346462690887, + "iq_angle": -1.2621946150226666, + "mean_gnd_states": [ + -0.17994037940379404, + -2.4709365853658536 + ], + "mean_exc_states": [ + 0.6854460704607047, + 0.24369105691056914 + ], + "T2_spin_echo": 5425.5448969467925 + } + } + } +} diff --git a/tests/dummy_qrc/rfsoc/parameters.json b/tests/dummy_qrc/rfsoc/parameters.json new file mode 100644 index 000000000..eb5c904dc --- /dev/null +++ b/tests/dummy_qrc/rfsoc/parameters.json @@ -0,0 +1,96 @@ +{ + "settings": { + "nshots": 1024, + "relaxation_time": 100000 + }, + + "configs": { + "tii_rfsoc4x2": { + "kind": "bounds", + "waveforms": 0, + "readout": 0, + "instructions": 0 + }, + "twpa_a": { + "kind": "oscillator", + "frequency": 6200000000, + "power": -1 + }, + "ErasynthLO": { + "kind": "oscillator", + "frequency": 0, + "power": 0 + }, + "0/L3-18_ro": { + "kind": "iq", + "frequency": 7371258599 + }, + "0/L2-RO": { + "kind": "acquisition", + "delay": 0, + "smearing": 0.0, + "threshold": -0.8981346462690887, + "iq_angle": -1.2621946150226666 + }, + "0/L3-18_qd": { + "kind": "iq", + "frequency": 5542341844 + } + }, + + "native_gates": { + "single_qubit": { + "0": { + "RX": [ + [ + "0/L3-18_qd", + { + "kind": "pulse", + "duration": 30, + "amplitude": 0.05284168507293318, + "envelope": { + "kind": "rectangular" + }, + "relative_phase": 0.0 + } + ] + ], + "RX12": [ + [ + "0/L3-18_qd", + { + "kind": "pulse", + "duration": 30, + "amplitude": 0.05284168507293318, + "envelope": { + "kind": "rectangular" + }, + "relative_phase": 0.0 + } + ] + ], + "MZ": [ + [ + "0/L2-RO", + { + "kind": "readout", + "acquisition": { + "kind": "acquisition", + "duration": 600 + }, + "probe": { + "kind": "pulse", + "duration": 600, + "amplitude": 0.03, + "envelope": { + "kind": "rectangular" + }, + "relative_phase": 0.0 + } + } + ] + ] + } + } + } +} diff --git a/tests/dummy_qrc/rfsoc/platform.py b/tests/dummy_qrc/rfsoc/platform.py index a6c793b82..714a04e56 100644 --- a/tests/dummy_qrc/rfsoc/platform.py +++ b/tests/dummy_qrc/rfsoc/platform.py @@ -1,10 +1,10 @@ import pathlib -from qibolab import AcquisitionChannel, DcChannel, IqChannel, Qubit +from qibolab import AcquisitionChannel, DcChannel, IqChannel, Platform, Qubit from qibolab.instruments.era import ERASynth -from qibolab.instruments.rfsoc import RFSoC + +# from qibolab.instruments.rfsoc import RFSoC from qibolab.instruments.rohde_schwarz import SGS100A -from qibolab.platform import Platform FOLDER = pathlib.Path(__file__).parent @@ -15,45 +15,49 @@ def create(): Used in ``test_instruments_rfsoc.py``. """ - qubit = Qubit.default("q0") + qubit = Qubit( + probe="0/L3-18_ro", acquisition="0/L2-RO", drive="0/L3-18_qd", flux="0/L2-22_qf" + ) # offset? channels = {} - # Readout + # Readout (probe) assert qubit.probe is not None channels[qubit.probe] = IqChannel( - device="L3-18_ro", path="0", mixer=None, lo="ErasynthLO" + device="0/L3-18_ro", path="0", mixer=None, lo="ErasynthLO" ) # Acquire (feedback) assert qubit.acquisition is not None channels[qubit.acquisition] = AcquisitionChannel( - device="L2-RO", + device="0/L2-RO", path="0", - probe=qubit.probe, # twpa_pump="twpa_a" ? + probe=qubit.probe, + twpa_pump=None, # "twpa_a" ? ) # Drive assert qubit.drive is not None channels[qubit.drive] = IqChannel( - device="L3-18_qd", + device="0/L3-18_qd", path="1", - mixer=None, # lo="ErasynthLO" ? + mixer=None, + lo=None, # "ErasynthLO" ? ) # Flux assert qubit.flux is not None - channels[qubit.flux] = DcChannel(device="L2-22_qf", path="2") + channels[qubit.flux] = DcChannel(device="0/L2-22_qf", path="2") lo_twpa = SGS100A(address="192.168.0.32") lo_era = ERASynth(address="192.168.0.212", ethernet=True) - controller = RFSoC( - address="0.0.0.0", - channels=channels, - port=0, - ) + controller = lo_era # RFSoC( + # address="0.0.0.0", + # channels=channels, + # port=0, + # ) instruments = {"tii_rfsoc4x2": controller, "twpa_a": lo_twpa, "ErasynthLO": lo_era} - return Platform.load(path=FOLDER, instruments=instruments, qubits={"q0": qubit}) + return Platform.load(path=FOLDER, instruments=instruments, qubits={0: qubit})