Skip to content

Add a method to return values from defcal statements #21

@Swordcat

Description

@Swordcat

With #20 merged to main we can now declare return types in defcal statements. However there isn't a convenient way to return values from defcal statements (as far as I can tell, please correct me if I'm wrong). This capability is demonstrated in the capture instructions of the OpenPulse Grammar specification. I suggest implementing a new method of the opqy.Program class that adds a ReturnStatement ast node to the program

def returns(self, return_var:AstConvertible):
    self._add_statement(ast.ReturnStatement(return_var.to_ast(self)))
    return self

This method just wraps the current workaround I've found to return a value from a defcal statement which requires using the 'private' _add_statement function of opqy.Program, see e.g. the following example

from openpulse import ast

import oqpy

prog = oqpy.Program()  # create a new oqpy program

m0 = oqpy.PortVar("m0")
cap0 = oqpy.PortVar("cap0")
stimulus_frame = oqpy.FrameVar(m0, 5e9, 0, name="stimulus_frame")
caputure_frame = oqpy.FrameVar(cap0, 5e9, 0, name="capture_frame")
dummy_wfm = oqpy.WaveformVar([-1.0, 0.5, 0.25, -0.75], "dummy_wfm")
capture_v2 = oqpy.declare_extern("capture_v2", [("output", ast.FrameType()), ("duration", oqpy.duration)], oqpy.bit)
qubit = oqpy.PhysicalQubits[0]

with oqpy.defcal(prog, qubit, "measure", return_type=oqpy.bit):
    prog.play(stimulus_frame, dummy_wfm)
    prog._add_statement(
        ast.ReturnStatement(capture_v2(caputure_frame, 16000e-9).to_ast(prog))
    )  # Suggestion: replace with prog.returns(result)

prog.measure(qubit, oqpy.BitVar(name="measured_bit"))

print(prog.to_qasm(encal_declarations=True))

Which generates the following OpenQASM code

OPENQASM 3.0;
defcalgrammar "openpulse";
cal {
    extern capture_v2(frame, duration) -> bit;
    port m0;
    port cap0;
    frame stimulus_frame = newframe(m0, 5000000000.0, 0);
    waveform dummy_wfm = {-1.0, 0.5, 0.25, -0.75};
    frame capture_frame = newframe(cap0, 5000000000.0, 0);
}
bit measured_bit;
defcal measure $0 -> bit {
    play(stimulus_frame, dummy_wfm);
    return capture_v2(capture_frame, 16000.0ns);
}
measured_bit = measure $0;

I'm willing to take the lead on implementing this method and any tests that may be required.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions