Skip to content
Snippets Groups Projects
Commit 0bf9f1fa authored by Sander Snoo's avatar Sander Snoo
Browse files

Improved waveform partitioning in Qblox compiler to reduce memory usage.

parent dfe50867
No related branches found
No related tags found
No related merge requests found
This diff is collapsed.
...@@ -5,7 +5,6 @@ import numpy as np ...@@ -5,7 +5,6 @@ import numpy as np
import logging import logging
import math import math
from dataclasses import dataclass, field from dataclasses import dataclass, field
from typing import Dict, Optional, List, Union
from numbers import Number from numbers import Number
from packaging.version import Version from packaging.version import Version
...@@ -13,7 +12,6 @@ from pulse_lib.segments.conditional_segment import conditional_segment ...@@ -13,7 +12,6 @@ from pulse_lib.segments.conditional_segment import conditional_segment
from .rendering import SineWaveform, get_modulation from .rendering import SineWaveform, get_modulation
from .pulsar_sequencers import ( from .pulsar_sequencers import (
Voltage1nsSequenceBuilder,
VoltageSequenceBuilder, VoltageSequenceBuilder,
IQSequenceBuilder, IQSequenceBuilder,
AcquisitionSequenceBuilder, AcquisitionSequenceBuilder,
...@@ -43,7 +41,6 @@ def iround(value): ...@@ -43,7 +41,6 @@ def iround(value):
class PulsarUploader: class PulsarUploader:
verbose = False verbose = False
output_dir = None output_dir = None
resolution_1ns = True
def __init__(self, awg_devices, awg_channels, marker_channels, def __init__(self, awg_devices, awg_channels, marker_channels,
IQ_channels, qubit_channels, digitizers, digitizer_channels): IQ_channels, qubit_channels, digitizers, digitizer_channels):
...@@ -404,12 +401,12 @@ class PulsarUploader: ...@@ -404,12 +401,12 @@ class PulsarUploader:
@dataclass @dataclass
class AcqDescription: class AcqDescription:
seq_id: UUID seq_id: UUID
index: List[int] index: list[int]
channels: List[str] channels: list[str]
acq_data_scaling: Dict[str, Union[float, np.ndarray]] acq_data_scaling: dict[str, float | np.ndarray]
n_rep: int n_rep: int
average_repetitions: bool = False average_repetitions: bool = False
triggers: Optional[List[object]] = None triggers: list[object] | None = None
class Job(object): class Job(object):
...@@ -543,7 +540,7 @@ class ChannelInfo: ...@@ -543,7 +540,7 @@ class ChannelInfo:
dc_compensation: bool = False dc_compensation: bool = False
dc_compensation_min: float = 0.0 dc_compensation_min: float = 0.0
dc_compensation_max: float = 0.0 dc_compensation_max: float = 0.0
bias_T_RC_time: Optional[float] = None bias_T_RC_time: float | None = None
# aggregation state # aggregation state
integral: float = 0.0 integral: float = 0.0
...@@ -551,7 +548,7 @@ class ChannelInfo: ...@@ -551,7 +548,7 @@ class ChannelInfo:
@dataclass @dataclass
class JobUploadInfo: class JobUploadInfo:
dc_compensation_duration_ns: float = 0.0 dc_compensation_duration_ns: float = 0.0
dc_compensation_voltages: Dict[str, float] = field(default_factory=dict) dc_compensation_voltages: dict[str, float] = field(default_factory=dict)
@dataclass @dataclass
...@@ -723,30 +720,23 @@ class UploadAggregator: ...@@ -723,30 +720,23 @@ class UploadAggregator:
segments = self.segments segments = self.segments
channel_info = self.channels[channel_name] channel_info = self.channels[channel_name]
t_offset = PulsarConfig.align(self.max_pre_start_ns + channel_info.delay_ns) t_offset = iround(self.max_pre_start_ns + channel_info.delay_ns)
seq = VoltageSequenceBuilder(channel_name, self.program[channel_name],
if PulsarUploader.resolution_1ns: rc_time=channel_info.bias_T_RC_time)
seq = Voltage1nsSequenceBuilder(channel_name, self.program[channel_name],
rc_time=channel_info.bias_T_RC_time)
else:
seq = VoltageSequenceBuilder(channel_name, self.program[channel_name],
rc_time=channel_info.bias_T_RC_time)
seq.set_time_offset(t_offset)
scaling = 1/(channel_info.attenuation * seq.max_output_voltage*1000) scaling = 1/(channel_info.attenuation * seq.max_output_voltage*1000)
markers = self.get_markers_seq(job, channel_name) markers = self.get_markers_seq(job, channel_name)
seq.add_markers(markers) seq.add_markers(markers)
for iseg, (seg, seg_render) in enumerate(zip(job.sequence, segments)): for iseg, (seg, seg_render) in enumerate(zip(job.sequence, segments)):
seg_start = seg_render.t_start seg_start = seg_render.t_start + t_offset
if isinstance(seg, conditional_segment): if isinstance(seg, conditional_segment):
logger.debug(f'conditional for {channel_name}') logger.debug(f'conditional for {channel_name}')
seg_ch = get_conditional_channel(seg, channel_name) seg_ch = get_conditional_channel(seg, channel_name)
else: else:
seg_ch = seg[channel_name] seg_ch = seg[channel_name]
data = seg_ch._get_data_all_at(job.index) data = seg_ch._get_data_all_at(job.index)
if PulsarUploader.resolution_1ns: seq.hres = data._hres
seq.hres = data._hres
# NOTE: break_ramps ensures that there is all ramps are # NOTE: break_ramps ensures that there is all ramps are
# broken at start/end of sine and custom pulses. # broken at start/end of sine and custom pulses.
# Elements are ordered such that the ramps are added as last. # Elements are ordered such that the ramps are added as last.
...@@ -779,7 +769,7 @@ class UploadAggregator: ...@@ -779,7 +769,7 @@ class UploadAggregator:
else: else:
raise Exception(f'Unknown pulse element {type(e)}') raise Exception(f'Unknown pulse element {type(e)}')
t_end = PulsarConfig.ceil(seg_render.t_end) t_end = PulsarConfig.ceil(seg_render.t_end + t_offset)
seq.wait_till(t_end) seq.wait_till(t_end)
compensation_ns = job.upload_info.dc_compensation_duration_ns compensation_ns = job.upload_info.dc_compensation_duration_ns
...@@ -818,7 +808,7 @@ class UploadAggregator: ...@@ -818,7 +808,7 @@ class UploadAggregator:
f'{[[output.awg_channel_name] for output in iq_out_channels]}') f'{[[output.awg_channel_name] for output in iq_out_channels]}')
attenuation = att[0] attenuation = att[0]
t_offset = PulsarConfig.align(self.max_pre_start_ns + delay) t_offset = iround(self.max_pre_start_ns + delay)
lo_freq = iq_channel.LO lo_freq = iq_channel.LO
nco_freq = get_iq_nco_idle_frequency(job, qubit_channel, job.index) nco_freq = get_iq_nco_idle_frequency(job, qubit_channel, job.index)
...@@ -830,17 +820,16 @@ class UploadAggregator: ...@@ -830,17 +820,16 @@ class UploadAggregator:
scaling = 1/(attenuation * seq.max_output_voltage*1000) # @@@@ Multiply with sqrt(2) scaling = 1/(attenuation * seq.max_output_voltage*1000) # @@@@ Multiply with sqrt(2)
seq.set_time_offset(t_offset)
if self.feedback_triggers: if self.feedback_triggers:
for trigger in self.feedback_triggers.values(): for trigger in self.feedback_triggers.values():
seq.add_trigger_counter(trigger) seq.add_trigger_counter(trigger)
seq.add_latch_events(job.latch_events) seq.add_latch_events(job.latch_events, t_offset)
markers = self.get_markers_seq(job, channel_name, delay) markers = self.get_markers_seq(job, channel_name, delay)
seq.add_markers(markers) seq.add_markers(markers)
for iseg, (seg, seg_render) in enumerate(zip(job.sequence, segments)): for iseg, (seg, seg_render) in enumerate(zip(job.sequence, segments)):
seg_start = seg_render.t_start seg_start = seg_render.t_start + t_offset
if not isinstance(seg, conditional_segment): if not isinstance(seg, conditional_segment):
seg_ch = seg[channel_name] seg_ch = seg[channel_name]
self._add_iq_data(job, seg_ch, seg_start, scaling, seq, lo_freq) self._add_iq_data(job, seg_ch, seg_start, scaling, seq, lo_freq)
...@@ -853,7 +842,8 @@ class UploadAggregator: ...@@ -853,7 +842,8 @@ class UploadAggregator:
m = measurements[0] m = measurements[0]
dig_channel = m.acquisition_channel dig_channel = m.acquisition_channel
m_time = job.condition_measurements.get_end_time(m, job.index) m_time = job.condition_measurements.get_end_time(m, job.index)
t_min = m_time+job.condition_measurements.min_feedback_time # NOTE: t_min uses extremes of configured channel delays
t_min = m_time+job.condition_measurements.min_feedback_time + t_offset
with seq.conditional([dig_channel], t_min=t_min, t_max=seg_start) as cond: with seq.conditional([dig_channel], t_min=t_min, t_max=seg_start) as cond:
branches = seg.branches branches = seg.branches
with cond.all_set(): with cond.all_set():
...@@ -863,7 +853,7 @@ class UploadAggregator: ...@@ -863,7 +853,7 @@ class UploadAggregator:
seg_ch = branches[0][channel_name] seg_ch = branches[0][channel_name]
self._add_iq_data(job, seg_ch, seg_start, scaling, seq, lo_freq) self._add_iq_data(job, seg_ch, seg_start, scaling, seq, lo_freq)
t_end = PulsarConfig.ceil(seg_render.t_end) t_end = PulsarConfig.ceil(seg_render.t_end + t_offset)
seq.wait_till(t_end) seq.wait_till(t_end)
# add final markers # add final markers
seq.finalize() seq.finalize()
...@@ -917,12 +907,12 @@ class UploadAggregator: ...@@ -917,12 +907,12 @@ class UploadAggregator:
seq = AcquisitionSequenceBuilder(channel_name, self.program[channel_name], n_rep, seq = AcquisitionSequenceBuilder(channel_name, self.program[channel_name], n_rep,
nco_frequency=nco_freq, nco_frequency=nco_freq,
rf_source=digitizer_channel.rf_source) rf_source=digitizer_channel.rf_source)
seq.set_time_offset(t_offset)
# NCO delay is 4 ns less than delay between output and input # NCO delay is 4 ns less than delay between output and input
seq.nco_delay = digitizer_channel.delay - 4 seq.nco_delay = digitizer_channel.delay - 4
if digitizer_channel.rf_source is not None: if digitizer_channel.rf_source is not None:
seq.offset_rf_ns = PulsarConfig.align(self.max_pre_start_ns + digitizer_channel.rf_source.delay) # relative offset of rf_source w.r.t. digitizer. Align to keep constant relative offset.
seq.offset_rf_ns = PulsarConfig.align(digitizer_channel.rf_source.delay - digitizer_channel.delay)
markers = self.get_markers_seq(job, channel_name) markers = self.get_markers_seq(job, channel_name)
seq.add_markers(markers) seq.add_markers(markers)
...@@ -933,7 +923,7 @@ class UploadAggregator: ...@@ -933,7 +923,7 @@ class UploadAggregator:
acq_threshold_trigger_invert = False acq_threshold_trigger_invert = False
use_feedback = channel_name in self.feedback_triggers use_feedback = channel_name in self.feedback_triggers
for iseg, (seg, seg_render) in enumerate(zip(job.sequence, self.segments)): for iseg, (seg, seg_render) in enumerate(zip(job.sequence, self.segments)):
seg_start = seg_render.t_start seg_start = seg_render.t_start + t_offset
if isinstance(seg, conditional_segment): if isinstance(seg, conditional_segment):
logger.debug(f'conditional for {channel_name}') logger.debug(f'conditional for {channel_name}')
seg_ch = get_conditional_channel(seg, channel_name) seg_ch = get_conditional_channel(seg, channel_name)
...@@ -942,13 +932,14 @@ class UploadAggregator: ...@@ -942,13 +932,14 @@ class UploadAggregator:
acquisition_data = seg_ch._get_data_all_at(job.index).get_data() acquisition_data = seg_ch._get_data_all_at(job.index).get_data()
for acquisition in acquisition_data: for acquisition in acquisition_data:
# TODO align here or in sequencer?
t = PulsarConfig.align(acquisition.start + seg_start) t = PulsarConfig.align(acquisition.start + seg_start)
t_measure = acquisition.t_measure if acquisition.t_measure is not None else acq_conf.t_measure t_measure = acquisition.t_measure if acquisition.t_measure is not None else acq_conf.t_measure
if t_measure is None: if t_measure is None:
raise Exception('measurement time has not been configured') raise Exception('measurement time has not been configured')
# if t_measure = -1, then measure till end of sequence. (time trace feature) # if t_measure = -1, then measure till end of sequence. (time trace feature)
if t_measure < 0: if t_measure < 0:
t_measure = self.segments[-1].t_end - t t_measure = self.segments[-1].t_end + t_offset - t
t_measure = PulsarConfig.floor(t_measure) t_measure = PulsarConfig.floor(t_measure)
if acquisition.n_repeat: if acquisition.n_repeat:
...@@ -976,7 +967,7 @@ class UploadAggregator: ...@@ -976,7 +967,7 @@ class UploadAggregator:
or acq_threshold_trigger_invert != acquisition.zero_on_high): or acq_threshold_trigger_invert != acquisition.zero_on_high):
raise Exception('With feedback all thresholds on a channel must be equal') raise Exception('With feedback all thresholds on a channel must be equal')
t_end = PulsarConfig.ceil(seg_render.t_end) t_end = PulsarConfig.ceil(seg_render.t_end + t_offset)
try: try:
seq.wait_till(t_end) seq.wait_till(t_end)
except Exception: except Exception:
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment