Rename 'with parallel' to 'with interleave' (#265).

This commit is contained in:
whitequark 2016-02-22 13:24:43 +00:00
parent b0e7fddc32
commit 51a5910002
33 changed files with 79 additions and 79 deletions

View File

@ -144,8 +144,8 @@ def fn_print():
def fn_kernel(): def fn_kernel():
return types.TBuiltinFunction("kernel") return types.TBuiltinFunction("kernel")
def obj_parallel(): def obj_interleave():
return types.TBuiltin("parallel") return types.TBuiltin("interleave")
def obj_sequential(): def obj_sequential():
return types.TBuiltin("sequential") return types.TBuiltin("sequential")

View File

@ -1418,7 +1418,7 @@ class Loop(Terminator):
def opcode(self): def opcode(self):
return "loop({} times)".format(self.trip_count) return "loop({} times)".format(self.trip_count)
class Parallel(Terminator): class Interleave(Terminator):
""" """
An instruction that schedules several threads of execution An instruction that schedules several threads of execution
in parallel. in parallel.
@ -1428,7 +1428,7 @@ class Parallel(Terminator):
super().__init__(destinations, builtins.TNone(), name) super().__init__(destinations, builtins.TNone(), name)
def opcode(self): def opcode(self):
return "parallel" return "interleave"
def destinations(self): def destinations(self):
return self.operands return self.operands

View File

@ -30,7 +30,7 @@ def globals():
"portable": builtins.fn_kernel(), "portable": builtins.fn_kernel(),
# ARTIQ context managers # ARTIQ context managers
"parallel": builtins.obj_parallel(), "interleave": builtins.obj_interleave(),
"sequential": builtins.obj_sequential(), "sequential": builtins.obj_sequential(),
"watchdog": builtins.fn_watchdog(), "watchdog": builtins.fn_watchdog(),

View File

@ -747,8 +747,8 @@ class ARTIQIRGenerator(algorithm.Visitor):
if types.is_builtin(context_expr_node.type, "sequential"): if types.is_builtin(context_expr_node.type, "sequential"):
self.visit(node.body) self.visit(node.body)
return return
elif types.is_builtin(context_expr_node.type, "parallel"): elif types.is_builtin(context_expr_node.type, "interleave"):
parallel = self.append(ir.Parallel([])) interleave = self.append(ir.Interleave([]))
heads, tails = [], [] heads, tails = [], []
for stmt in node.body: for stmt in node.body:
@ -758,7 +758,7 @@ class ARTIQIRGenerator(algorithm.Visitor):
tails.append(self.current_block) tails.append(self.current_block)
for head in heads: for head in heads:
parallel.add_destination(head) interleave.add_destination(head)
self.current_block = self.add_block() self.current_block = self.add_block()
for tail in tails: for tail in tails:

View File

@ -993,7 +993,7 @@ class Inferencer(algorithm.Visitor):
self.generic_visit(node) self.generic_visit(node)
typ = node.context_expr.type typ = node.context_expr.type
if (types.is_builtin(typ, "parallel") or types.is_builtin(typ, "sequential") or if (types.is_builtin(typ, "interleave") or types.is_builtin(typ, "sequential") or
(isinstance(node.context_expr, asttyped.CallT) and (isinstance(node.context_expr, asttyped.CallT) and
types.is_builtin(node.context_expr.func.type, "watchdog"))): types.is_builtin(node.context_expr.func.type, "watchdog"))):
# builtin context managers # builtin context managers
@ -1092,7 +1092,7 @@ class Inferencer(algorithm.Visitor):
for item_node in node.items: for item_node in node.items:
typ = item_node.context_expr.type.find() typ = item_node.context_expr.type.find()
if (types.is_builtin(typ, "parallel") or types.is_builtin(typ, "sequential")) and \ if (types.is_builtin(typ, "interleave") or types.is_builtin(typ, "sequential")) and \
len(node.items) != 1: len(node.items) != 1:
diag = diagnostic.Diagnostic("error", diag = diagnostic.Diagnostic("error",
"the '{kind}' context manager must be the only one in a 'with' statement", "the '{kind}' context manager must be the only one in a 'with' statement",

View File

@ -66,7 +66,7 @@ class Interleaver:
postdom_tree = None postdom_tree = None
for insn in func.instructions(): for insn in func.instructions():
if not isinstance(insn, ir.Parallel): if not isinstance(insn, ir.Interleave):
continue continue
# Lazily compute dominators. # Lazily compute dominators.
@ -79,7 +79,7 @@ class Interleaver:
source_times = [0 for _ in source_blocks] source_times = [0 for _ in source_blocks]
if len(source_blocks) == 1: if len(source_blocks) == 1:
# Immediate dominator for a parallel instruction with one successor # Immediate dominator for a interleave instruction with one successor
# is the first instruction in the body of the statement which created # is the first instruction in the body of the statement which created
# it, but below we expect that it would be the first instruction after # it, but below we expect that it would be the first instruction after
# the statement itself. # the statement itself.
@ -87,7 +87,7 @@ class Interleaver:
continue continue
interleave_until = postdom_tree.immediate_dominator(insn.basic_block) interleave_until = postdom_tree.immediate_dominator(insn.basic_block)
assert interleave_until is not None # no nonlocal flow in `with parallel` assert interleave_until is not None # no nonlocal flow in `with interleave`
assert interleave_until not in source_blocks assert interleave_until not in source_blocks
while len(source_blocks) > 0: while len(source_blocks) > 0:
@ -111,7 +111,7 @@ class Interleaver:
assert target_time_delta >= 0 assert target_time_delta >= 0
target_terminator = target_block.terminator() target_terminator = target_block.terminator()
if isinstance(target_terminator, ir.Parallel): if isinstance(target_terminator, ir.Interleave):
target_terminator.replace_with(ir.Branch(source_block)) target_terminator.replace_with(ir.Branch(source_block))
elif isinstance(target_terminator, (ir.Delay, ir.Branch)): elif isinstance(target_terminator, (ir.Delay, ir.Branch)):
target_terminator.set_target(source_block) target_terminator.set_target(source_block)
@ -119,7 +119,7 @@ class Interleaver:
assert False assert False
source_terminator = source_block.terminator() source_terminator = source_block.terminator()
if isinstance(source_terminator, ir.Parallel): if isinstance(source_terminator, ir.Interleave):
source_terminator.replace_with(ir.Branch(source_terminator.target())) source_terminator.replace_with(ir.Branch(source_terminator.target()))
elif isinstance(source_terminator, ir.Branch): elif isinstance(source_terminator, ir.Branch):
pass pass
@ -149,7 +149,7 @@ class Interleaver:
if old_decomp.static_target_function is None: if old_decomp.static_target_function is None:
diag = diagnostic.Diagnostic("fatal", diag = diagnostic.Diagnostic("fatal",
"it is not possible to interleave this function call within " "it is not possible to interleave this function call within "
"a 'with parallel:' statement because the compiler could not " "a 'with interleave:' statement because the compiler could not "
"prove that the same function would always be called", {}, "prove that the same function would always be called", {},
old_decomp.loc) old_decomp.loc)
self.engine.process(diag) self.engine.process(diag)

View File

@ -219,7 +219,7 @@ class IODelayEstimator(algorithm.Visitor):
self.visit(node.items) self.visit(node.items)
context_expr = node.items[0].context_expr context_expr = node.items[0].context_expr
if len(node.items) == 1 and types.is_builtin(context_expr.type, "parallel"): if len(node.items) == 1 and types.is_builtin(context_expr.type, "interleave"):
try: try:
delays = [] delays = []
for stmt in node.body: for stmt in node.body:
@ -235,7 +235,7 @@ class IODelayEstimator(algorithm.Visitor):
# since there's no chance that the code will never actually execute # since there's no chance that the code will never actually execute
# inside a `with` statement after all. # inside a `with` statement after all.
note = diagnostic.Diagnostic("note", note = diagnostic.Diagnostic("note",
"while interleaving this 'with parallel:' statement", {}, "while interleaving this 'with interleave:' statement", {},
node.loc) node.loc)
error.cause.notes += [note] error.cause.notes += [note]
self.engine.process(error.cause) self.engine.process(error.cause)
@ -249,11 +249,11 @@ class IODelayEstimator(algorithm.Visitor):
if flow_stmt is not None: if flow_stmt is not None:
note = diagnostic.Diagnostic("note", note = diagnostic.Diagnostic("note",
"this '{kind}' statement transfers control out of " "this '{kind}' statement transfers control out of "
"the 'with parallel:' statement", "the 'with interleave:' statement",
{"kind": flow_stmt.keyword_loc.source()}, {"kind": flow_stmt.keyword_loc.source()},
flow_stmt.loc) flow_stmt.loc)
diag = diagnostic.Diagnostic("error", diag = diagnostic.Diagnostic("error",
"cannot interleave this 'with parallel:' statement", {}, "cannot interleave this 'with interleave:' statement", {},
node.keyword_loc.join(node.colon_loc), notes=[note]) node.keyword_loc.join(node.colon_loc), notes=[note])
self.engine.process(diag) self.engine.process(diag)

View File

@ -13,7 +13,7 @@ __all__ = ["host_int", "int", "host_round", "round",
# global namespace for kernels # global namespace for kernels
kernel_globals = ( kernel_globals = (
"sequential", "parallel", "sequential", "parallel", "interleave",
"delay_mu", "now_mu", "at_mu", "delay", "delay_mu", "now_mu", "at_mu", "delay",
"seconds_to_mu", "mu_to_seconds", "seconds_to_mu", "mu_to_seconds",
"watchdog" "watchdog"
@ -264,7 +264,7 @@ _time_manager = _DummyTimeManager()
def set_time_manager(time_manager): def set_time_manager(time_manager):
"""Set the time manager used for simulating kernels by running them """Set the time manager used for simulating kernels by running them
directly inside the Python interpreter. The time manager responds to the directly inside the Python interpreter. The time manager responds to the
entering and leaving of parallel/sequential blocks, delays, etc. and entering and leaving of interleave/parallel/sequential blocks, delays, etc. and
provides a time-stamped logging facility for events. provides a time-stamped logging facility for events.
""" """
global _time_manager global _time_manager
@ -288,7 +288,7 @@ class _Parallel:
The execution time of a parallel block is the execution time of its longest The execution time of a parallel block is the execution time of its longest
statement. A parallel block may contain sequential blocks, which themselves statement. A parallel block may contain sequential blocks, which themselves
may contain parallel blocks, etc. may contain interleave blocks, etc.
""" """
def __enter__(self): def __enter__(self):
_time_manager.enter_parallel() _time_manager.enter_parallel()
@ -296,7 +296,7 @@ class _Parallel:
def __exit__(self, type, value, traceback): def __exit__(self, type, value, traceback):
_time_manager.exit() _time_manager.exit()
parallel = _Parallel() parallel = _Parallel()
interleave = _Parallel() # no difference in semantics on host
def delay_mu(duration): def delay_mu(duration):
"""Increases the RTIO time by the given amount (in machine units).""" """Increases the RTIO time by the given amount (in machine units)."""

View File

@ -12,7 +12,7 @@ class CreateTTLPulse(EnvExperiment):
def run(self): def run(self):
self.ttl_inout.output() self.ttl_inout.output()
delay_mu(100) delay_mu(100)
with parallel: with interleave:
self.ttl_inout.gate_both_mu(1200) self.ttl_inout.gate_both_mu(1200)
with sequential: with sequential:
delay_mu(100) delay_mu(100)

View File

@ -100,7 +100,7 @@ class _Pulses(EnvExperiment):
@kernel @kernel
def run(self): def run(self):
for i in range(3): for i in range(3):
with parallel: with interleave:
with sequential: with sequential:
self.a.pulse(100+i, 20*us) self.a.pulse(100+i, 20*us)
self.b.pulse(200+i, 20*us) self.b.pulse(200+i, 20*us)

View File

@ -16,7 +16,7 @@ class RTT(EnvExperiment):
def run(self): def run(self):
self.ttl_inout.output() self.ttl_inout.output()
delay(1*us) delay(1*us)
with parallel: with interleave:
# make sure not to send two commands into the same RTIO # make sure not to send two commands into the same RTIO
# channel with the same timestamp # channel with the same timestamp
self.ttl_inout.gate_rising(5*us) self.ttl_inout.gate_rising(5*us)
@ -37,7 +37,7 @@ class Loopback(EnvExperiment):
def run(self): def run(self):
self.loop_in.input() self.loop_in.input()
delay(1*us) delay(1*us)
with parallel: with interleave:
self.loop_in.gate_rising(2*us) self.loop_in.gate_rising(2*us)
with sequential: with sequential:
delay(1*us) delay(1*us)
@ -57,7 +57,7 @@ class ClockGeneratorLoopback(EnvExperiment):
self.loop_clock_in.input() self.loop_clock_in.input()
self.loop_clock_out.stop() self.loop_clock_out.stop()
delay(1*us) delay(1*us)
with parallel: with interleave:
self.loop_clock_in.gate_rising(10*us) self.loop_clock_in.gate_rising(10*us)
with sequential: with sequential:
delay(200*ns) delay(200*ns)
@ -110,7 +110,7 @@ class LoopbackCount(EnvExperiment):
def run(self): def run(self):
self.ttl_inout.output() self.ttl_inout.output()
delay(5*us) delay(5*us)
with parallel: with interleave:
self.ttl_inout.gate_rising(10*us) self.ttl_inout.gate_rising(10*us)
with sequential: with sequential:
for i in range(self.npulses): for i in range(self.npulses):

View File

@ -1,6 +1,6 @@
# RUN: %python -m artiq.compiler.testbench.inferencer +diag %s >%t # RUN: %python -m artiq.compiler.testbench.inferencer +diag %s >%t
# RUN: OutputCheck %s --file-to-check=%t # RUN: OutputCheck %s --file-to-check=%t
# CHECK-L: ${LINE:+1}: error: the 'parallel' context manager must be the only one in a 'with' statement # CHECK-L: ${LINE:+1}: error: the 'interleave' context manager must be the only one in a 'with' statement
with parallel, sequential: with interleave, sequential:
pass pass

View File

@ -2,4 +2,4 @@
# RUN: OutputCheck %s --file-to-check=%t # RUN: OutputCheck %s --file-to-check=%t
# CHECK-L: as x:NoneType # CHECK-L: as x:NoneType
with parallel as x: pass with interleave as x: pass

View File

@ -2,7 +2,7 @@
# RUN: OutputCheck %s --file-to-check=%t # RUN: OutputCheck %s --file-to-check=%t
def f(): def f():
with parallel: with interleave:
if True: if True:
print(1) print(1)
else: else:

View File

@ -10,7 +10,7 @@ def g():
x = f if True else g x = f if True else g
def h(): def h():
with parallel: with interleave:
f() f()
# CHECK-L: ${LINE:+1}: fatal: it is not possible to interleave this function call within a 'with parallel:' statement because the compiler could not prove that the same function would always be called # CHECK-L: ${LINE:+1}: fatal: it is not possible to interleave this function call within a 'with interleave:' statement because the compiler could not prove that the same function would always be called
x() x()

View File

@ -2,16 +2,16 @@
# RUN: OutputCheck %s --file-to-check=%t # RUN: OutputCheck %s --file-to-check=%t
def f(): def f():
# CHECK-L: ${LINE:+1}: error: cannot interleave this 'with parallel:' statement # CHECK-L: ${LINE:+1}: error: cannot interleave this 'with interleave:' statement
with parallel: with interleave:
# CHECK-L: ${LINE:+1}: note: this 'return' statement transfers control out of the 'with parallel:' statement # CHECK-L: ${LINE:+1}: note: this 'return' statement transfers control out of the 'with interleave:' statement
return return
delay(1.0) delay(1.0)
def g(): def g():
while True: while True:
# CHECK-L: ${LINE:+1}: error: cannot interleave this 'with parallel:' statement # CHECK-L: ${LINE:+1}: error: cannot interleave this 'with interleave:' statement
with parallel: with interleave:
# CHECK-L: ${LINE:+1}: note: this 'break' statement transfers control out of the 'with parallel:' statement # CHECK-L: ${LINE:+1}: note: this 'break' statement transfers control out of the 'with interleave:' statement
break break
delay(1.0) delay(1.0)

View File

@ -5,7 +5,7 @@ def f():
delay_mu(2) delay_mu(2)
def g(): def g():
with parallel: with interleave:
with sequential: with sequential:
print("A", now_mu()) print("A", now_mu())
f() f()

View File

@ -5,7 +5,7 @@ def f(n):
delay_mu(n) delay_mu(n)
def g(): def g():
with parallel: with interleave:
with sequential: with sequential:
print("A", now_mu()) print("A", now_mu())
f(2) f(2)

View File

@ -2,7 +2,7 @@
# RUN: OutputCheck %s --file-to-check=%t # RUN: OutputCheck %s --file-to-check=%t
def g(): def g():
with parallel: with interleave:
with sequential: with sequential:
print("A", now_mu()) print("A", now_mu())
delay_mu(2) delay_mu(2)

View File

@ -2,7 +2,7 @@
# RUN: OutputCheck %s --file-to-check=%t # RUN: OutputCheck %s --file-to-check=%t
def g(): def g():
with parallel: with interleave:
with sequential: with sequential:
print("A", now_mu()) print("A", now_mu())
delay_mu(3) delay_mu(3)

View File

@ -5,7 +5,7 @@ def f():
delay_mu(2) delay_mu(2)
def g(): def g():
with parallel: with interleave:
f() f()
delay_mu(2) delay_mu(2)
print(now_mu()) print(now_mu())

View File

@ -1,7 +1,7 @@
# RUN: %python -m artiq.compiler.testbench.jit %s >%t # RUN: %python -m artiq.compiler.testbench.jit %s >%t
# RUN: OutputCheck %s --file-to-check=%t # RUN: OutputCheck %s --file-to-check=%t
with parallel: with interleave:
for x in range(10): for x in range(10):
delay_mu(1) delay_mu(1)
print("a", x) print("a", x)

View File

@ -2,7 +2,7 @@
# RUN: OutputCheck %s --file-to-check=%t # RUN: OutputCheck %s --file-to-check=%t
def f(): def f():
with parallel: with interleave:
# CHECK-L: ${LINE:+1}: error: while statement cannot be interleaved # CHECK-L: ${LINE:+1}: error: while statement cannot be interleaved
while True: while True:
delay_mu(1) delay_mu(1)

View File

@ -3,13 +3,13 @@
# CHECK-L: f: (a:int(width=64), b:int(width=64))->NoneType delay(max(a, b) mu) # CHECK-L: f: (a:int(width=64), b:int(width=64))->NoneType delay(max(a, b) mu)
def f(a, b): def f(a, b):
with parallel: with interleave:
delay_mu(a) delay_mu(a)
delay_mu(b) delay_mu(b)
# CHECK-L: g: (a:int(width=64))->NoneType delay(max(a, 200) mu) # CHECK-L: g: (a:int(width=64))->NoneType delay(max(a, 200) mu)
def g(a): def g(a):
with parallel: with interleave:
delay_mu(100) delay_mu(100)
delay_mu(200) delay_mu(200)
delay_mu(a) delay_mu(a)

View File

@ -1,6 +1,6 @@
# RUN: %python -m artiq.compiler.testbench.signature %s >%t # RUN: %python -m artiq.compiler.testbench.signature %s >%t
with parallel: with interleave:
delay(1.0) delay(1.0)
t0 = now_mu() t0 = now_mu()
print(t0) print(t0)

View File

@ -156,23 +156,23 @@ The core device records the real-time IO waveforms into a circular buffer. It is
Afterwards, the recorded data can be extracted and written to a VCD file using ``artiq_coreanalyzer -w rtio.vcd`` (see: :ref:`core-device-rtio-analyzer-tool`). VCD files can be viewed using third-party tools such as GtkWave. Afterwards, the recorded data can be extracted and written to a VCD file using ``artiq_coreanalyzer -w rtio.vcd`` (see: :ref:`core-device-rtio-analyzer-tool`). VCD files can be viewed using third-party tools such as GtkWave.
Parallel and sequential blocks Interleave and sequential blocks
------------------------------ --------------------------------
It is often necessary that several pulses overlap one another. This can be expressed through the use of ``with parallel`` constructs, in which all statements execute at the same time. The execution time of the ``parallel`` block is the execution time of its longest statement. It is often necessary that several pulses overlap one another. This can be expressed through the use of ``with interleave`` constructs, in which all statements execute at the same time. The execution time of the ``interleave`` block is the execution time of its longest statement.
Try the following code and observe the generated pulses on a 2-channel oscilloscope or logic analyzer: :: Try the following code and observe the generated pulses on a 2-channel oscilloscope or logic analyzer: ::
for i in range(1000000): for i in range(1000000):
with parallel: with interleave:
self.ttl0.pulse(2*us) self.ttl0.pulse(2*us)
self.ttl1.pulse(4*us) self.ttl1.pulse(4*us)
delay(4*us) delay(4*us)
Within a parallel block, some statements can be made sequential again using a ``with sequential`` construct. Observe the pulses generated by this code: :: Within a interleave block, some statements can be made sequential again using a ``with sequential`` construct. Observe the pulses generated by this code: ::
for i in range(1000000): for i in range(1000000):
with parallel: with interleave:
with sequential: with sequential:
self.ttl0.pulse(2*us) self.ttl0.pulse(2*us)
delay(1*us) delay(1*us)
@ -181,4 +181,4 @@ Within a parallel block, some statements can be made sequential again using a ``
delay(4*us) delay(4*us)
.. warning:: .. warning::
In its current implementation, ARTIQ only supports those pulse sequences that can be interleaved at compile time into a sequential series of on/off events. Combinations of ``parallel``/``sequential`` blocks that require multithreading (due to the parallel execution of long loops, complex algorithms, or algorithms that depend on external input) will cause the compiler to return an error. In its current implementation, ARTIQ only supports those pulse sequences that can be interleaved at compile time into a sequential series of on/off events. Combinations of ``interleave``/``sequential`` blocks that require multithreading (due to the parallel execution of long loops, complex algorithms, or algorithms that depend on external input) will cause the compiler to return an error.

View File

@ -117,10 +117,10 @@ dds.pulse(200*MHz, 11*us) # exactly 1 ms after trigger
\footnotesize \footnotesize
\begin{minted}[frame=leftline]{python} \begin{minted}[frame=leftline]{python}
with sequential: with sequential:
with parallel: with interleave:
a.pulse(100*MHz, 10*us) a.pulse(100*MHz, 10*us)
b.pulse(200*MHz, 20*us) b.pulse(200*MHz, 20*us)
with parallel: with interleave:
c.pulse(300*MHz, 30*us) c.pulse(300*MHz, 30*us)
d.pulse(400*MHz, 20*us) d.pulse(400*MHz, 20*us)
\end{minted} \end{minted}
@ -128,7 +128,7 @@ with sequential:
\begin{itemize} \begin{itemize}
\item Experiments are inherently parallel: \item Experiments are inherently parallel:
simultaneous laser pulses, parallel cooling of ions in different trap zones simultaneous laser pulses, parallel cooling of ions in different trap zones
\item \verb!parallel! and \verb!sequential! contexts with arbitrary nesting \item \verb!interleave! and \verb!sequential! contexts with arbitrary nesting
\item \verb!a! and \verb!b! pulses both start at the same time \item \verb!a! and \verb!b! pulses both start at the same time
\item \verb!c! and \verb!d! pulses both start when \verb!a! and \verb!b! are both done \item \verb!c! and \verb!d! pulses both start when \verb!a! and \verb!b! are both done
(after 20\,µs) (after 20\,µs)
@ -181,7 +181,7 @@ class Experiment:
@kernel @kernel
def run(self): def run(self):
with parallel: with interleave:
self.ion1.cool(duration=10*us) self.ion1.cool(duration=10*us)
self.ion2.cool(frequency=...) self.ion2.cool(frequency=...)
self.transporter.move(speed=...) self.transporter.move(speed=...)
@ -222,7 +222,7 @@ class Experiment:
\item RPC and exception mappings are generated \item RPC and exception mappings are generated
\item Constants and small kernels are inlined \item Constants and small kernels are inlined
\item Small loops are unrolled \item Small loops are unrolled
\item Statements in parallel blocks are interleaved \item Statements in interleave blocks are interleaved
\item Time is converted to RTIO clock cycles \item Time is converted to RTIO clock cycles
\item The Python AST is converted to LLVM IR \item The Python AST is converted to LLVM IR
\item The LLVM IR is compiled to OpenRISC machine code \item The LLVM IR is compiled to OpenRISC machine code

View File

@ -133,10 +133,10 @@ dds.pulse(200*MHz, 11*us) # exactly 1 ms after trigger
\footnotesize \footnotesize
\begin{minted}[frame=leftline]{python} \begin{minted}[frame=leftline]{python}
with sequential: with sequential:
with parallel: with interleave:
a.pulse(100*MHz, 10*us) a.pulse(100*MHz, 10*us)
b.pulse(200*MHz, 20*us) b.pulse(200*MHz, 20*us)
with parallel: with interleave:
c.pulse(300*MHz, 30*us) c.pulse(300*MHz, 30*us)
d.pulse(400*MHz, 20*us) d.pulse(400*MHz, 20*us)
\end{minted} \end{minted}
@ -144,7 +144,7 @@ with sequential:
\begin{itemize} \begin{itemize}
\item Experiments are inherently parallel: \item Experiments are inherently parallel:
simultaneous laser pulses, parallel cooling of ions in different trap zones simultaneous laser pulses, parallel cooling of ions in different trap zones
\item \verb!parallel! and \verb!sequential! contexts with arbitrary nesting \item \verb!interleave! and \verb!sequential! contexts with arbitrary nesting
\item \verb!a! and \verb!b! pulses both start at the same time \item \verb!a! and \verb!b! pulses both start at the same time
\item \verb!c! and \verb!d! pulses both start when \verb!a! and \verb!b! are both done \item \verb!c! and \verb!d! pulses both start when \verb!a! and \verb!b! are both done
(after 20\,µs) (after 20\,µs)
@ -197,7 +197,7 @@ class Experiment:
@kernel @kernel
def run(self): def run(self):
with parallel: with interleave:
self.ion1.cool(duration=10*us) self.ion1.cool(duration=10*us)
self.ion2.cool(frequency=...) self.ion2.cool(frequency=...)
self.transporter.move(speed=...) self.transporter.move(speed=...)
@ -238,7 +238,7 @@ class Experiment:
\item RPC and exception mappings are generated \item RPC and exception mappings are generated
\item Constants and small kernels are inlined \item Constants and small kernels are inlined
\item Small loops are unrolled \item Small loops are unrolled
\item Statements in parallel blocks are interleaved \item Statements in interleave blocks are interleaved
\item Time is converted to RTIO clock cycles \item Time is converted to RTIO clock cycles
\item The Python AST is converted to LLVM IR \item The Python AST is converted to LLVM IR
\item The LLVM IR is compiled to OpenRISC machine code \item The LLVM IR is compiled to OpenRISC machine code

View File

@ -28,7 +28,7 @@ class PhotonHistogram(EnvExperiment):
@kernel @kernel
def cool_detect(self): def cool_detect(self):
with parallel: with interleave:
self.bd_sw.pulse(1*ms) self.bd_sw.pulse(1*ms)
self.bdd_sw.pulse(1*ms) self.bdd_sw.pulse(1*ms)
@ -36,7 +36,7 @@ class PhotonHistogram(EnvExperiment):
self.bd_sw.pulse(100*us) self.bd_sw.pulse(100*us)
self.bd_dds.set(self.detect_f) self.bd_dds.set(self.detect_f)
with parallel: with interleave:
self.bd_sw.pulse(self.detect_t) self.bd_sw.pulse(self.detect_t)
self.pmt.gate_rising(self.detect_t) self.pmt.gate_rising(self.detect_t)

View File

@ -27,7 +27,7 @@ class DDSTest(EnvExperiment):
self.led.on() self.led.on()
else: else:
self.led.off() self.led.off()
with parallel: with interleave:
with sequential: with sequential:
self.dds0.set(100*MHz + 4*i*kHz) self.dds0.set(100*MHz + 4*i*kHz)
self.ttl0.pulse(500*us) self.ttl0.pulse(500*us)

View File

@ -62,7 +62,7 @@ class TDR(EnvExperiment):
@kernel @kernel
def one(self, t, p): def one(self, t, p):
t0 = now_mu() t0 = now_mu()
with parallel: with interleave:
self.pmt0.gate_both_mu(2*p) self.pmt0.gate_both_mu(2*p)
self.ttl2.pulse_mu(p) self.ttl2.pulse_mu(p)
for i in range(len(t)): for i in range(len(t)):

View File

@ -24,7 +24,7 @@ class AluminumSpectroscopy(EnvExperiment):
delay(10*us) delay(10*us)
self.laser_cooling.pulse(100*MHz, 100*us) self.laser_cooling.pulse(100*MHz, 100*us)
delay(5*us) delay(5*us)
with parallel: with interleave:
self.spectroscopy.pulse(self.spectroscopy_freq, 100*us) self.spectroscopy.pulse(self.spectroscopy_freq, 100*us)
with sequential: with sequential:
delay(50*us) delay(50*us)
@ -32,7 +32,7 @@ class AluminumSpectroscopy(EnvExperiment):
delay(5*us) delay(5*us)
while True: while True:
delay(5*us) delay(5*us)
with parallel: with interleave:
self.state_detection.pulse(100*MHz, 10*us) self.state_detection.pulse(100*MHz, 10*us)
photon_count = self.pmt.count_gate(10*us) photon_count = self.pmt.count_gate(10*us)
if (photon_count < self.photon_limit_low if (photon_count < self.photon_limit_low

View File

@ -11,7 +11,7 @@ class SimpleSimulation(EnvExperiment):
@kernel @kernel
def run(self): def run(self):
with parallel: with interleave:
with sequential: with sequential:
self.a.pulse(100*MHz, 20*us) self.a.pulse(100*MHz, 20*us)
self.b.pulse(200*MHz, 20*us) self.b.pulse(200*MHz, 20*us)