From 7a727d26a5c84aed35a3fa1c7afe86481e63417b Mon Sep 17 00:00:00 2001 From: Alvaro Orgaz Date: Wed, 17 Jul 2024 10:00:44 +0000 Subject: [PATCH] add support TI dac flux bias --- src/qibosoq/programs/base.py | 8 +-- src/qibosoq/programs/flux.py | 94 ++++++++++++++------------ src/qibosoq/programs/pulse_sequence.py | 5 +- src/qibosoq/programs/sweepers.py | 5 +- src/qibosoq/server.py | 22 ++++-- 5 files changed, 80 insertions(+), 54 deletions(-) diff --git a/src/qibosoq/programs/base.py b/src/qibosoq/programs/base.py index d09f77e..07325f8 100644 --- a/src/qibosoq/programs/base.py +++ b/src/qibosoq/programs/base.py @@ -58,7 +58,7 @@ def __init__( self.relax_delay = self.us2cycles(qpcfg.relaxation_time) self.syncdelay = self.us2cycles(0) - self.wait_initialize = self.us2cycles(2.0) + self.wait_initialize = self.us2cycles(5.0) self.pulses_registered = False self.registered_waveforms: Dict[int, list] = {} @@ -320,16 +320,16 @@ def declare_gen_mux_ro(self): self.declare_gen( ch=ro_ch, nqz=zone, - mixer_freq=0, + # mixer_freq=0, mux_freqs=mux_freqs, mux_gains=mux_gains, - ro_ch=adc_ch_added[0], + # ro_ch=adc_ch_added[0], ) def add_muxed_readout_to_register(self, ro_pulses: List[Rectangular]): """Register multiplexed pulse before firing it.""" # readout amplitude gets divided by len(mask), we are here fixing the values - mask = [0, 1, 2] + mask = [0, 1, 2, 3] pulse = ro_pulses[0] gen_ch = pulse.dac diff --git a/src/qibosoq/programs/flux.py b/src/qibosoq/programs/flux.py index c56d788..9e30e36 100644 --- a/src/qibosoq/programs/flux.py +++ b/src/qibosoq/programs/flux.py @@ -17,6 +17,7 @@ Rectangular, ) from qibosoq.programs.base import BaseProgram +from ..TIDAC80508 import TIDAC80508 logger = logging.getLogger(qibosoq_cfg.MAIN_LOGGER_NAME) @@ -25,10 +26,11 @@ class FluxProgram(BaseProgram): """Abstract class for flux-tunable qubits programs.""" def __init__( - self, soc: QickSoc, qpcfg: Config, sequence: List[Element], qubits: List[Qubit] + self, soc: QickSoc, tidac: TIDAC80508, qpcfg: Config, sequence: List[Element], qubits: List[Qubit] ): """Define an empty dictionary for bias sweepers and call super().__init__.""" self.bias_sweep_registers: Dict[int, Tuple[QickRegister, QickRegister]] = {} + self.tidac = tidac super().__init__(soc, qpcfg, sequence, qubits) def set_bias(self, mode: str = "sweetspot"): @@ -38,46 +40,54 @@ def set_bias(self, mode: str = "sweetspot"): Args: mode (str): can be 'sweetspot' or 'zero' """ - duration = 48 # minimum len - for qubit in self.qubits: - # if bias is zero, just skip the qubit - if qubit.bias is None or qubit.dac is None or qubit.bias == 0: - continue - - flux_ch = qubit.dac - max_gain = int(self.soccfg["gens"][flux_ch]["maxv"]) - - if mode == "sweetspot": - value = max_gain - elif mode == "zero": - value = 0 - else: - raise NotImplementedError(f"Mode {mode} not supported") - - i_wf = np.full(duration, value) - q_wf = np.zeros(len(i_wf)) - self.add_pulse(flux_ch, f"const_{value}_{flux_ch}", i_wf, q_wf) - self.set_pulse_registers( - ch=flux_ch, - waveform=f"const_{value}_{flux_ch}", - style="arb", - outsel="input", - stdysel="last", - freq=0, - phase=0, - gain=np.trunc(max_gain * qubit.bias).astype(int), - ) - - if flux_ch in self.bias_sweep_registers: - swept_reg, non_swept_reg = self.bias_sweep_registers[flux_ch] - if mode == "sweetspot": - non_swept_reg.set_to(swept_reg) - elif mode == "zero": - non_swept_reg.set_to(0) - - self.pulse(ch=flux_ch) - self.sync_all(50) # wait all pulses are fired + 50 clks + # if mode == "sweetspot": + # for qubit in self.qubits: + # self.tidac.set_bias(qubit.dac, bias_value=qubit.bias) + # elif mode == "zero": + # for qubit in self.qubits: + # self.tidac.set_bias(qubit.dac, bias_value=0) + + # duration = 48 # minimum len + # for qubit in self.qubits: + # # if bias is zero, just skip the qubit + # # continue + # if qubit.bias is None or qubit.dac is None or qubit.bias == 0: + # continue + + # flux_ch = qubit.dac + # max_gain = int(self.soccfg["gens"][flux_ch]["maxv"]) + + # if mode == "sweetspot": + # value = max_gain + # elif mode == "zero": + # value = 0 + # else: + # raise NotImplementedError(f"Mode {mode} not supported") + + # i_wf = np.full(duration, value) + # q_wf = np.zeros(len(i_wf)) + # self.add_pulse(flux_ch, f"const_{value}_{flux_ch}", i_wf, q_wf) + # self.set_pulse_registers( + # ch=flux_ch, + # waveform=f"const_{value}_{flux_ch}", + # style="arb", + # outsel="input", + # stdysel="last", + # freq=0, + # phase=0, + # gain=np.trunc(max_gain * qubit.bias).astype(int), + # ) + + # if flux_ch in self.bias_sweep_registers: + # swept_reg, non_swept_reg = self.bias_sweep_registers[flux_ch] + # if mode == "sweetspot": + # non_swept_reg.set_to(swept_reg) + # elif mode == "zero": + # non_swept_reg.set_to(0) + + # self.pulse(ch=flux_ch) + # self.sync_all(50) # wait all pulses are fired + 50 clks def find_qubit_sweetspot(self, pulse: Pulse) -> float: """Return bias of a qubit from flux pulse.""" @@ -149,7 +159,7 @@ def body(self): muxed_pulses_executed = [] muxed_ro_executed_indexes = [] - self.set_bias("sweetspot") + # self.set_bias("sweetspot") for elem in self.sequence: # wait the needed wait time so that the start is timed correctly @@ -172,7 +182,7 @@ def body(self): self.execute_flux_pulse(elem) self.wait_all() - self.set_bias("zero") + # self.set_bias("zero") self.sync_all(self.relax_delay) def declare_zones_and_ro(self, sequence: List[Pulse]): diff --git a/src/qibosoq/programs/pulse_sequence.py b/src/qibosoq/programs/pulse_sequence.py index b791f47..3d681b6 100644 --- a/src/qibosoq/programs/pulse_sequence.py +++ b/src/qibosoq/programs/pulse_sequence.py @@ -9,7 +9,7 @@ from qibosoq.components.base import Config, Qubit from qibosoq.components.pulses import Element from qibosoq.programs.flux import FluxProgram - +from ..TIDAC80508 import TIDAC80508 logger = logging.getLogger(qibosoq_cfg.MAIN_LOGGER_NAME) @@ -19,12 +19,13 @@ class ExecutePulseSequence(FluxProgram, AveragerProgram): def __init__( self, soc: QickSoc, + tidac: TIDAC80508, qpcfg: Config, sequence: List[Element], qubits: List[Qubit], ): """Init function, call super.__init__.""" - super().__init__(soc, qpcfg, sequence, qubits) + super().__init__(soc, tidac, qpcfg, sequence, qubits) self.reps = qpcfg.reps # must be done after AveragerProgram init self.soft_avgs = qpcfg.soft_avgs diff --git a/src/qibosoq/programs/sweepers.py b/src/qibosoq/programs/sweepers.py index fa847fe..b4c9cd0 100644 --- a/src/qibosoq/programs/sweepers.py +++ b/src/qibosoq/programs/sweepers.py @@ -10,7 +10,7 @@ from qibosoq.components.base import Config, Parameter, Qubit, Sweeper from qibosoq.components.pulses import Element from qibosoq.programs.flux import FluxProgram - +from ..TIDAC80508 import TIDAC80508 logger = logging.getLogger(qibosoq_cfg.MAIN_LOGGER_NAME) @@ -30,6 +30,7 @@ class ExecuteSweeps(FluxProgram, NDAveragerProgram): def __init__( self, soc: QickSoc, + tidac: TIDAC80508, qpcfg: Config, sequence: List[Element], qubits: List[Qubit], @@ -37,7 +38,7 @@ def __init__( ): """Init function, sets sweepers parameters before calling super.__init__.""" self.sweepers = reversed_sweepers(sweepers) - super().__init__(soc, qpcfg, sequence, qubits) + super().__init__(soc, tidac, qpcfg, sequence, qubits) self.reps = qpcfg.reps # must be done after NDAveragerProgram init self.soft_avgs = qpcfg.soft_avgs diff --git a/src/qibosoq/server.py b/src/qibosoq/server.py index 2d14969..6cc6dfd 100644 --- a/src/qibosoq/server.py +++ b/src/qibosoq/server.py @@ -20,6 +20,10 @@ logger = logging.getLogger(cfg.MAIN_LOGGER_NAME) qick_logger = logging.getLogger(cfg.PROGRAM_LOGGER_NAME) +# import sys +# sys.path.append('/home/xilinx/jupyter_notebooks/qick/qick_demos/custom/drivers') +from .TIDAC80508 import TIDAC80508 + def load_elements(list_sequence: List[Dict]) -> List[Element]: """Convert a list of elements in dict form to a list of Pulse objects.""" @@ -49,7 +53,7 @@ def load_sweeps(list_sweepers: List[Dict]) -> List[Sweeper]: return sweepers -def execute_program(data: dict, qick_soc: QickSoc) -> dict: +def execute_program(data: dict, qick_soc: QickSoc, tidac: TIDAC80508) -> dict: """Create and execute qick programs. Returns: @@ -70,14 +74,18 @@ def execute_program(data: dict, qick_soc: QickSoc) -> dict: raise NotImplementedError( f"Operation code {data['operation_code']} not supported" ) - + program = programcls( qick_soc, + tidac, Config(**data["cfg"]), load_elements(data["sequence"]), [Qubit(**qubit) for qubit in data["qubits"]], *args, ) + # program.set_bias("sweetspot") + for qubit in program.qubits: + tidac.set_bias(qubit.dac, bias_value=qubit.bias) asm_prog = program.asm() qick_logger.handlers[0].doRollover() # type: ignore @@ -104,10 +112,13 @@ def execute_program(data: dict, qick_soc: QickSoc) -> dict: qick_soc, average=data["cfg"]["average"], ) + # program.set_bias("zero") + for qubit in program.qubits: + tidac.set_bias(qubit.dac, bias_value=0) + # return {"i": (np.array(toti)+0.5).tolist(), "q": (np.array(totq)+0.5).tolist()} # ZCU111? return {"i": toti, "q": totq} - class ConnectionHandler(BaseRequestHandler): """Handle requests to the server.""" @@ -137,7 +148,9 @@ def handle(self): try: data = self.receive_command() - results = execute_program(data, self.server.qick_soc) + + results = execute_program(data, self.server.qick_soc, self.server.tidac) + except Exception: # pylint: disable=W0612,W0718 logger.exception("") logger.error("Faling command: %s", data) @@ -160,5 +173,6 @@ def serve(host, port): TCPServer.allow_reuse_address = True with TCPServer((host, port), ConnectionHandler) as server: server.qick_soc = QickSoc(bitfile=cfg.QICKSOC_LOCATION) + server.tidac = TIDAC80508() log_initial_info() server.serve_forever()