Skip to content

Commit 405e1dd

Browse files
committed
Fix bugs in scheduling sequences with multiple logicals per physical.
NOTE: These changes haven't been tested with hardware. I merely found several examples where the code would not terminate because of how various indices were being tracked. So, these changes are sufficient to get the code to terminate.
1 parent 0d9efa3 commit 405e1dd

File tree

1 file changed

+40
-16
lines changed

1 file changed

+40
-16
lines changed

src/APS2.jl

Lines changed: 40 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ function create_wf_instrs!(instr_lib, wfs, pulses)
141141
# TODO: better handle Id so we don't generate useless long wfs and have repeated TAZ offsets
142142
idx = 0
143143
for p in pulses
144-
wf = p.amp * QGL.waveform(p, DAC_CLOCK)
144+
wf = p.amp .* QGL.waveform(p, DAC_CLOCK)
145145
if !USE_PHASE_OFFSET_INSTRUCTION
146146
wf *= exp(1im * 2π * p.phase)
147147
end
@@ -173,21 +173,37 @@ function create_marker_instrs!(instr_lib, pulses, marker_chan)
173173
end
174174
end
175175

176+
"""
177+
find_next_analog_entry!(entry, chan, wf_lib, analog_timestamps, id_ch, Z_chs_id)
178+
179+
Finds the next sequential entry in a sequence for channels that have multiple logical
180+
channels sharing a physical channel.
176181
177-
function find_next_analog_entry!(entry, chan, wf_lib, analog_timestamps, id_ch, Z_chs_id)
178-
if any([id_ch[ct] > length(entry.pulses[chan[ct]]) for ct in 1:length(chan)])
182+
`analog_timestamps` tracks the time from the start of the PulseBlock for each logical channel
183+
`ch_idx` tracks the index into the PulseBlock of each logical channel
184+
`Z_chs_ids` carries the logical channel index of the previous Z pulses
185+
"""
186+
function find_next_analog_entry!(entry, chan, wf_lib, analog_timestamps, ch_idx, Z_chs_id)
187+
if all([ch_idx[ct] > length(entry.pulses[chan[ct]]) for ct in 1:length(chan)])
179188
return
180189
end
190+
# get all logical channel indices that could have the next pulse
181191
sim_chs_id = findall(x-> x == minimum(analog_timestamps), analog_timestamps)
182192
filter!(x->!(x in Z_chs_id), sim_chs_id)
193+
if length(sim_chs_id) == 0
194+
# must be done...
195+
return
196+
end
183197
pulses = []
184198
for ct in sim_chs_id
185-
pulse = entry.pulses[chan[ct]][id_ch[ct]]
199+
pulse = entry.pulses[chan[ct]][ch_idx[ct]]
186200
if typeof(pulse) == QGL.ZPulse
187201
if length(sim_chs_id) > 1 #if simultaneous logical channels, remove the Z pulses one by one
188202
push!(Z_chs_id, ct)
203+
else
204+
Z_chs_id = Int[]
189205
end
190-
id_ch[ct]+=1
206+
ch_idx[ct] += 1
191207
return pulse, Z_chs_id
192208
end
193209
push!(pulses, pulse)
@@ -202,15 +218,17 @@ function find_next_analog_entry!(entry, chan, wf_lib, analog_timestamps, id_ch,
202218
elseif length(nonid_ids) == 1
203219
chan_select = sim_chs_id[nonid_ids[1]]
204220
else #select the channel with the shortest Id
205-
chan_select = sim_chs_id[indmin([pulse.length for pulse in pulses])]
221+
chan_select = sim_chs_id[argmin([pulse.length for pulse in pulses])]
206222
end
207223
end
208-
next_entry = entry.pulses[chan[chan_select]][id_ch[chan_select]]
209-
for ct in sim_chs_id
210-
analog_timestamps[ct] += wf_lib[entry.pulses[chan[ct]][id_ch[ct]]].count + 1
211-
id_ch[ct]+=1
212-
end
213-
Z_chs_id = []
224+
next_entry = entry.pulses[chan[chan_select]][ch_idx[chan_select]]
225+
analog_timestamps[chan_select] += wf_lib[entry.pulses[chan[chan_select]][ch_idx[chan_select]]].count + 1
226+
ch_idx[chan_select] += 1
227+
# for ct in sim_chs_id
228+
# analog_timestamps[ct] += wf_lib[entry.pulses[chan[ct]][ch_idx[ct]]].count + 1
229+
# ch_idx[ct] += 1
230+
# end
231+
Z_chs_id = Int[]
214232
return next_entry, Z_chs_id
215233
end
216234

@@ -247,9 +265,11 @@ function create_instrs(seqs, wf_lib, chans, chan_freqs)
247265
all_done[ct] = num_entries[ct] == 0
248266
end
249267

268+
# analog_timestamps will track time delay from the start of the PulseBlock
250269
analog_timestamps = zeros(Int, length(chan_freqs))
251270
analog_idx = ones(Int, length(chan_freqs))
252-
Z_chs_id = []
271+
num_analog_entries = [length(entry.pulses[chan]) for chan in keys(chan_freqs)]
272+
Z_chs_id = Int[]
253273
# serialize pulses from the PulseBlock
254274
# round-robin through the channels until all are exhausted
255275
while !all(all_done)
@@ -258,9 +278,9 @@ function create_instrs(seqs, wf_lib, chans, chan_freqs)
258278
for (ct, chan) in enumerate(chans)
259279
if (!all_done[ct]) && (time_stamp[ct] <= next_instr_time)
260280

261-
if length(chan)>1 # multiple logical channels per analog channel
281+
if length(chan) > 1 # multiple logical channels per analog channel
262282
next_entry_info = find_next_analog_entry!(entry, chan, wf_lib, analog_timestamps, analog_idx, Z_chs_id)
263-
if typeof(next_entry_info) === nothing
283+
if next_entry_info === nothing
264284
all_done[ct] = true
265285
break
266286
end
@@ -277,7 +297,11 @@ function create_instrs(seqs, wf_lib, chans, chan_freqs)
277297
push!(instrs, modulation_instr(MODULATE, nco_select[next_entry.channel], wf.count))
278298
end
279299
push!(instrs, wf.instruction)
280-
time_stamp[ct] += wf.count+1
300+
if length(chan) > 1
301+
time_stamp[ct] = minimum(analog_timestamps)
302+
else
303+
time_stamp[ct] += wf.count+1
304+
end
281305
elseif typeof(next_entry) == QGL.ZPulse
282306
# round phase to 28 bit integer
283307
fixed_pt_phase = round(Int32, mod(-next_entry.angle, 1) * 2^28 )

0 commit comments

Comments
 (0)