Allow generic subschedule in conditional playback
Explanation of changes
Example 1
body = Schedule()
body.add(Square_Pulse(duration=50e-9, port=A, clock=B, ...))
body.add(SSBIntegrationComplex(duration=100e-9, port=A, clock=B))
Will compile to q1asm of the form:
set_awg_gain 10000
play 1,0,4
wait 46
acquire 0,0,100
This has a total duration of 150 ns and has 3 real-time instructions.
passing the body to a conditional:
schedule.add(ConditionalOperation(body, "q0"))
will compile it to the following q1asm:
set_cond 1,1,0,4 # set_enable=1, mask=0, operator=OR, else_duration=4
set_awg_gain 10000
play 1,0,4 # real-time instruction
wait 46 # real-time instruction
acquire 0,0,100 # real-time instruction
set_cond 1,1,1,4 # set_enable=1, mask=0, operator=NOR, else_duration=4
wait 142 # 150 - 3*4 + 4
set_cond 0,0,0,0 # set_enable=0
If the condition is met (unmet), the first set_cond block will have a duration of 150 ns (12 ns), while the second set_cond block will have a duration of 4 ns (142 ns). In both branches the total duration is 154 ns. (adding an additional 4 ns the second set_cond wait time to make both branches the same duration)
Example 2
body = Schedule()
body.add(SquarePulse(duration=50e-9, port=A, clock=B, ...))
body.add(DragPulse(duration=40e-9, port=A, clock=B, ...))
Will compile to q1asm of the form:
set_awg_gain 10000
play 1,0,4 # real-time instruction
wait 46 # real-time instruction
set_awg_gain 10000
play 1,0,4 # real-time instruction
wait 36 # real-time instruction
This has a total duration of 90 ns and has 4 real-time instructions.
passing the body to a conditional:
schedule.add(ConditionalOperation(body, "q0"))
will compile it to the following q1asm:
set_cond 1,1,0,4 # set_enable=1, mask=0, operator=OR, else_duration=4
set_awg_gain 10000
play 1,0,4 # real-time instruction
wait 46 # real-time instruction
set_awg_gain 10000
play 1,0,4 # real-time instruction
wait 36 # real-time instruction
set_cond 1,1,1,4 # set_enable=1, mask=0, operator=NOR, else_duration=4
wait 78 # 90 - 4*4 + 4
set_cond 0,0,0,0 # set_enable=0
If the condition is met (unmet), the first set_cond block will have a duration of 90 ns (16 ns), while the second set_cond block will have a duration of 4 ns (78 ns). In both branches the total duration is 94 ns. (adding an additional 4 ns the second set_cond wait time to make both branches the same duration)
This implementation will ensure that:
- any subschedule that is passed to conditional playback will run without raising errors.
- at the expense of an additional 4 ns.
- with a limitation that the duration of the body needs to be less than 65528 ns + 4 ns *number_of_real_time_instructions
explanation
The else_duration
is the wait time per real time instruction in the
conditional block. If a trigger happened, the first block runs normally for
50 ns, the second block runs for 4 ns. If there is no trigger, the first
block runs for 3*4 = 12 ns, second block for 42 ns. So the duration in
both cases is 42 ns. Note that set_cond
itself has zero duration.
todos:
-
fix circular import error -
add tests -
raise error when duration > 65528 ns + 4 ns *number_of_real_time_instructions -
update conditional playback documentation
Merge checklist
See also merge request guidelines
-
Merge request has been reviewed (in-depth by a knowledgeable contributor), and is approved by a project maintainer. -
New code is covered by unit tests (or N/A). -
New code is documented and docstrings use numpydoc format (or N/A). -
New functionality: considered making private instead of extending public API (or N/A). -
Public API changed: added @deprecated
and entry in deprecated code suggestions (or N/A). -
Newly added/adjusted documentation and docstrings render properly (or N/A). -
Pipeline fix or dependency update: post in #software-for-developers
channel to mergemain
back in or update local packages (or N/A). -
Tested on hardware (or N/A). -
CHANGELOG.md
for breaking changes andAUTHORS.md
have been updated (or N/A). -
Update Hardware backends documentation if backend interface change or N/A -
Check whether performance is significantly affected by looking at the Performance metrics results. -
Windows tests in CI pipeline pass (manually triggered by maintainers before merging). - Maintainers do not hit Auto-merge, we need to actively check as manual tests do not block pipeline
For reference, the issues workflow is described in the contribution guidelines.
Summary by CodeRabbit
-
New Features
- Introduced
ConditionalOperation
for executing operations based on conditional logic. - Enhanced
conditional
method inQASMProgram
for improved instruction timing.
- Introduced
-
Bug Fixes
- Improved error handling in various tests related to conditional operations and pulse compensation.
-
Tests
- Added comprehensive unit tests for conditional operations and control flow.
- Expanded existing tests to cover edge cases and improve validation accuracy.
-
Documentation
- Enhanced docstrings and comments for better clarity on functionality and usage.