mirror of https://github.com/m-labs/artiq.git
Rename 'with parallel' to 'with interleave' (#265).
This commit is contained in:
parent
b0e7fddc32
commit
51a5910002
|
@ -144,8 +144,8 @@ def fn_print():
|
|||
def fn_kernel():
|
||||
return types.TBuiltinFunction("kernel")
|
||||
|
||||
def obj_parallel():
|
||||
return types.TBuiltin("parallel")
|
||||
def obj_interleave():
|
||||
return types.TBuiltin("interleave")
|
||||
|
||||
def obj_sequential():
|
||||
return types.TBuiltin("sequential")
|
||||
|
|
|
@ -1418,7 +1418,7 @@ class Loop(Terminator):
|
|||
def opcode(self):
|
||||
return "loop({} times)".format(self.trip_count)
|
||||
|
||||
class Parallel(Terminator):
|
||||
class Interleave(Terminator):
|
||||
"""
|
||||
An instruction that schedules several threads of execution
|
||||
in parallel.
|
||||
|
@ -1428,7 +1428,7 @@ class Parallel(Terminator):
|
|||
super().__init__(destinations, builtins.TNone(), name)
|
||||
|
||||
def opcode(self):
|
||||
return "parallel"
|
||||
return "interleave"
|
||||
|
||||
def destinations(self):
|
||||
return self.operands
|
||||
|
|
|
@ -30,7 +30,7 @@ def globals():
|
|||
"portable": builtins.fn_kernel(),
|
||||
|
||||
# ARTIQ context managers
|
||||
"parallel": builtins.obj_parallel(),
|
||||
"interleave": builtins.obj_interleave(),
|
||||
"sequential": builtins.obj_sequential(),
|
||||
"watchdog": builtins.fn_watchdog(),
|
||||
|
||||
|
|
|
@ -747,8 +747,8 @@ class ARTIQIRGenerator(algorithm.Visitor):
|
|||
if types.is_builtin(context_expr_node.type, "sequential"):
|
||||
self.visit(node.body)
|
||||
return
|
||||
elif types.is_builtin(context_expr_node.type, "parallel"):
|
||||
parallel = self.append(ir.Parallel([]))
|
||||
elif types.is_builtin(context_expr_node.type, "interleave"):
|
||||
interleave = self.append(ir.Interleave([]))
|
||||
|
||||
heads, tails = [], []
|
||||
for stmt in node.body:
|
||||
|
@ -758,7 +758,7 @@ class ARTIQIRGenerator(algorithm.Visitor):
|
|||
tails.append(self.current_block)
|
||||
|
||||
for head in heads:
|
||||
parallel.add_destination(head)
|
||||
interleave.add_destination(head)
|
||||
|
||||
self.current_block = self.add_block()
|
||||
for tail in tails:
|
||||
|
|
|
@ -993,7 +993,7 @@ class Inferencer(algorithm.Visitor):
|
|||
self.generic_visit(node)
|
||||
|
||||
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
|
||||
types.is_builtin(node.context_expr.func.type, "watchdog"))):
|
||||
# builtin context managers
|
||||
|
@ -1092,7 +1092,7 @@ class Inferencer(algorithm.Visitor):
|
|||
|
||||
for item_node in node.items:
|
||||
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:
|
||||
diag = diagnostic.Diagnostic("error",
|
||||
"the '{kind}' context manager must be the only one in a 'with' statement",
|
||||
|
|
|
@ -66,7 +66,7 @@ class Interleaver:
|
|||
|
||||
postdom_tree = None
|
||||
for insn in func.instructions():
|
||||
if not isinstance(insn, ir.Parallel):
|
||||
if not isinstance(insn, ir.Interleave):
|
||||
continue
|
||||
|
||||
# Lazily compute dominators.
|
||||
|
@ -79,7 +79,7 @@ class Interleaver:
|
|||
source_times = [0 for _ in source_blocks]
|
||||
|
||||
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
|
||||
# it, but below we expect that it would be the first instruction after
|
||||
# the statement itself.
|
||||
|
@ -87,7 +87,7 @@ class Interleaver:
|
|||
continue
|
||||
|
||||
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
|
||||
|
||||
while len(source_blocks) > 0:
|
||||
|
@ -111,7 +111,7 @@ class Interleaver:
|
|||
assert target_time_delta >= 0
|
||||
|
||||
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))
|
||||
elif isinstance(target_terminator, (ir.Delay, ir.Branch)):
|
||||
target_terminator.set_target(source_block)
|
||||
|
@ -119,7 +119,7 @@ class Interleaver:
|
|||
assert False
|
||||
|
||||
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()))
|
||||
elif isinstance(source_terminator, ir.Branch):
|
||||
pass
|
||||
|
@ -149,7 +149,7 @@ class Interleaver:
|
|||
if old_decomp.static_target_function is None:
|
||||
diag = diagnostic.Diagnostic("fatal",
|
||||
"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", {},
|
||||
old_decomp.loc)
|
||||
self.engine.process(diag)
|
||||
|
|
|
@ -219,7 +219,7 @@ class IODelayEstimator(algorithm.Visitor):
|
|||
self.visit(node.items)
|
||||
|
||||
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:
|
||||
delays = []
|
||||
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
|
||||
# inside a `with` statement after all.
|
||||
note = diagnostic.Diagnostic("note",
|
||||
"while interleaving this 'with parallel:' statement", {},
|
||||
"while interleaving this 'with interleave:' statement", {},
|
||||
node.loc)
|
||||
error.cause.notes += [note]
|
||||
self.engine.process(error.cause)
|
||||
|
@ -249,11 +249,11 @@ class IODelayEstimator(algorithm.Visitor):
|
|||
if flow_stmt is not None:
|
||||
note = diagnostic.Diagnostic("note",
|
||||
"this '{kind}' statement transfers control out of "
|
||||
"the 'with parallel:' statement",
|
||||
"the 'with interleave:' statement",
|
||||
{"kind": flow_stmt.keyword_loc.source()},
|
||||
flow_stmt.loc)
|
||||
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])
|
||||
self.engine.process(diag)
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ __all__ = ["host_int", "int", "host_round", "round",
|
|||
|
||||
# global namespace for kernels
|
||||
kernel_globals = (
|
||||
"sequential", "parallel",
|
||||
"sequential", "parallel", "interleave",
|
||||
"delay_mu", "now_mu", "at_mu", "delay",
|
||||
"seconds_to_mu", "mu_to_seconds",
|
||||
"watchdog"
|
||||
|
@ -264,7 +264,7 @@ _time_manager = _DummyTimeManager()
|
|||
def set_time_manager(time_manager):
|
||||
"""Set the time manager used for simulating kernels by running them
|
||||
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.
|
||||
"""
|
||||
global _time_manager
|
||||
|
@ -288,7 +288,7 @@ class _Parallel:
|
|||
|
||||
The execution time of a parallel block is the execution time of its longest
|
||||
statement. A parallel block may contain sequential blocks, which themselves
|
||||
may contain parallel blocks, etc.
|
||||
may contain interleave blocks, etc.
|
||||
"""
|
||||
def __enter__(self):
|
||||
_time_manager.enter_parallel()
|
||||
|
@ -296,7 +296,7 @@ class _Parallel:
|
|||
def __exit__(self, type, value, traceback):
|
||||
_time_manager.exit()
|
||||
parallel = _Parallel()
|
||||
|
||||
interleave = _Parallel() # no difference in semantics on host
|
||||
|
||||
def delay_mu(duration):
|
||||
"""Increases the RTIO time by the given amount (in machine units)."""
|
||||
|
|
|
@ -12,7 +12,7 @@ class CreateTTLPulse(EnvExperiment):
|
|||
def run(self):
|
||||
self.ttl_inout.output()
|
||||
delay_mu(100)
|
||||
with parallel:
|
||||
with interleave:
|
||||
self.ttl_inout.gate_both_mu(1200)
|
||||
with sequential:
|
||||
delay_mu(100)
|
||||
|
|
|
@ -100,7 +100,7 @@ class _Pulses(EnvExperiment):
|
|||
@kernel
|
||||
def run(self):
|
||||
for i in range(3):
|
||||
with parallel:
|
||||
with interleave:
|
||||
with sequential:
|
||||
self.a.pulse(100+i, 20*us)
|
||||
self.b.pulse(200+i, 20*us)
|
||||
|
|
|
@ -16,7 +16,7 @@ class RTT(EnvExperiment):
|
|||
def run(self):
|
||||
self.ttl_inout.output()
|
||||
delay(1*us)
|
||||
with parallel:
|
||||
with interleave:
|
||||
# make sure not to send two commands into the same RTIO
|
||||
# channel with the same timestamp
|
||||
self.ttl_inout.gate_rising(5*us)
|
||||
|
@ -37,7 +37,7 @@ class Loopback(EnvExperiment):
|
|||
def run(self):
|
||||
self.loop_in.input()
|
||||
delay(1*us)
|
||||
with parallel:
|
||||
with interleave:
|
||||
self.loop_in.gate_rising(2*us)
|
||||
with sequential:
|
||||
delay(1*us)
|
||||
|
@ -57,7 +57,7 @@ class ClockGeneratorLoopback(EnvExperiment):
|
|||
self.loop_clock_in.input()
|
||||
self.loop_clock_out.stop()
|
||||
delay(1*us)
|
||||
with parallel:
|
||||
with interleave:
|
||||
self.loop_clock_in.gate_rising(10*us)
|
||||
with sequential:
|
||||
delay(200*ns)
|
||||
|
@ -110,7 +110,7 @@ class LoopbackCount(EnvExperiment):
|
|||
def run(self):
|
||||
self.ttl_inout.output()
|
||||
delay(5*us)
|
||||
with parallel:
|
||||
with interleave:
|
||||
self.ttl_inout.gate_rising(10*us)
|
||||
with sequential:
|
||||
for i in range(self.npulses):
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# RUN: %python -m artiq.compiler.testbench.inferencer +diag %s >%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
|
||||
with parallel, sequential:
|
||||
# CHECK-L: ${LINE:+1}: error: the 'interleave' context manager must be the only one in a 'with' statement
|
||||
with interleave, sequential:
|
||||
pass
|
||||
|
|
|
@ -2,4 +2,4 @@
|
|||
# RUN: OutputCheck %s --file-to-check=%t
|
||||
|
||||
# CHECK-L: as x:NoneType
|
||||
with parallel as x: pass
|
||||
with interleave as x: pass
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
# RUN: OutputCheck %s --file-to-check=%t
|
||||
|
||||
def f():
|
||||
with parallel:
|
||||
with interleave:
|
||||
if True:
|
||||
print(1)
|
||||
else:
|
||||
|
|
|
@ -10,7 +10,7 @@ def g():
|
|||
x = f if True else g
|
||||
|
||||
def h():
|
||||
with parallel:
|
||||
with interleave:
|
||||
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()
|
||||
|
|
|
@ -2,16 +2,16 @@
|
|||
# RUN: OutputCheck %s --file-to-check=%t
|
||||
|
||||
def f():
|
||||
# CHECK-L: ${LINE:+1}: error: cannot interleave this 'with parallel:' statement
|
||||
with parallel:
|
||||
# CHECK-L: ${LINE:+1}: note: this 'return' statement transfers control out of the 'with parallel:' statement
|
||||
# CHECK-L: ${LINE:+1}: error: cannot interleave this 'with interleave:' statement
|
||||
with interleave:
|
||||
# CHECK-L: ${LINE:+1}: note: this 'return' statement transfers control out of the 'with interleave:' statement
|
||||
return
|
||||
delay(1.0)
|
||||
|
||||
def g():
|
||||
while True:
|
||||
# CHECK-L: ${LINE:+1}: error: cannot interleave this 'with parallel:' statement
|
||||
with parallel:
|
||||
# CHECK-L: ${LINE:+1}: note: this 'break' statement transfers control out of the 'with parallel:' statement
|
||||
# CHECK-L: ${LINE:+1}: error: cannot interleave this 'with interleave:' statement
|
||||
with interleave:
|
||||
# CHECK-L: ${LINE:+1}: note: this 'break' statement transfers control out of the 'with interleave:' statement
|
||||
break
|
||||
delay(1.0)
|
||||
|
|
|
@ -5,7 +5,7 @@ def f():
|
|||
delay_mu(2)
|
||||
|
||||
def g():
|
||||
with parallel:
|
||||
with interleave:
|
||||
with sequential:
|
||||
print("A", now_mu())
|
||||
f()
|
||||
|
|
|
@ -5,7 +5,7 @@ def f(n):
|
|||
delay_mu(n)
|
||||
|
||||
def g():
|
||||
with parallel:
|
||||
with interleave:
|
||||
with sequential:
|
||||
print("A", now_mu())
|
||||
f(2)
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
# RUN: OutputCheck %s --file-to-check=%t
|
||||
|
||||
def g():
|
||||
with parallel:
|
||||
with interleave:
|
||||
with sequential:
|
||||
print("A", now_mu())
|
||||
delay_mu(2)
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
# RUN: OutputCheck %s --file-to-check=%t
|
||||
|
||||
def g():
|
||||
with parallel:
|
||||
with interleave:
|
||||
with sequential:
|
||||
print("A", now_mu())
|
||||
delay_mu(3)
|
||||
|
|
|
@ -5,7 +5,7 @@ def f():
|
|||
delay_mu(2)
|
||||
|
||||
def g():
|
||||
with parallel:
|
||||
with interleave:
|
||||
f()
|
||||
delay_mu(2)
|
||||
print(now_mu())
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# RUN: %python -m artiq.compiler.testbench.jit %s >%t
|
||||
# RUN: OutputCheck %s --file-to-check=%t
|
||||
|
||||
with parallel:
|
||||
with interleave:
|
||||
for x in range(10):
|
||||
delay_mu(1)
|
||||
print("a", x)
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
# RUN: OutputCheck %s --file-to-check=%t
|
||||
|
||||
def f():
|
||||
with parallel:
|
||||
with interleave:
|
||||
# CHECK-L: ${LINE:+1}: error: while statement cannot be interleaved
|
||||
while True:
|
||||
delay_mu(1)
|
|
@ -3,13 +3,13 @@
|
|||
|
||||
# CHECK-L: f: (a:int(width=64), b:int(width=64))->NoneType delay(max(a, b) mu)
|
||||
def f(a, b):
|
||||
with parallel:
|
||||
with interleave:
|
||||
delay_mu(a)
|
||||
delay_mu(b)
|
||||
|
||||
# CHECK-L: g: (a:int(width=64))->NoneType delay(max(a, 200) mu)
|
||||
def g(a):
|
||||
with parallel:
|
||||
with interleave:
|
||||
delay_mu(100)
|
||||
delay_mu(200)
|
||||
delay_mu(a)
|
|
@ -1,6 +1,6 @@
|
|||
# RUN: %python -m artiq.compiler.testbench.signature %s >%t
|
||||
|
||||
with parallel:
|
||||
with interleave:
|
||||
delay(1.0)
|
||||
t0 = now_mu()
|
||||
print(t0)
|
||||
|
|
|
@ -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.
|
||||
|
||||
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: ::
|
||||
|
||||
for i in range(1000000):
|
||||
with parallel:
|
||||
with interleave:
|
||||
self.ttl0.pulse(2*us)
|
||||
self.ttl1.pulse(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):
|
||||
with parallel:
|
||||
with interleave:
|
||||
with sequential:
|
||||
self.ttl0.pulse(2*us)
|
||||
delay(1*us)
|
||||
|
@ -181,4 +181,4 @@ Within a parallel block, some statements can be made sequential again using a ``
|
|||
delay(4*us)
|
||||
|
||||
.. 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.
|
||||
|
|
|
@ -117,10 +117,10 @@ dds.pulse(200*MHz, 11*us) # exactly 1 ms after trigger
|
|||
\footnotesize
|
||||
\begin{minted}[frame=leftline]{python}
|
||||
with sequential:
|
||||
with parallel:
|
||||
with interleave:
|
||||
a.pulse(100*MHz, 10*us)
|
||||
b.pulse(200*MHz, 20*us)
|
||||
with parallel:
|
||||
with interleave:
|
||||
c.pulse(300*MHz, 30*us)
|
||||
d.pulse(400*MHz, 20*us)
|
||||
\end{minted}
|
||||
|
@ -128,7 +128,7 @@ with sequential:
|
|||
\begin{itemize}
|
||||
\item Experiments are inherently parallel:
|
||||
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!c! and \verb!d! pulses both start when \verb!a! and \verb!b! are both done
|
||||
(after 20\,µs)
|
||||
|
@ -181,7 +181,7 @@ class Experiment:
|
|||
|
||||
@kernel
|
||||
def run(self):
|
||||
with parallel:
|
||||
with interleave:
|
||||
self.ion1.cool(duration=10*us)
|
||||
self.ion2.cool(frequency=...)
|
||||
self.transporter.move(speed=...)
|
||||
|
@ -222,7 +222,7 @@ class Experiment:
|
|||
\item RPC and exception mappings are generated
|
||||
\item Constants and small kernels are inlined
|
||||
\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 The Python AST is converted to LLVM IR
|
||||
\item The LLVM IR is compiled to OpenRISC machine code
|
||||
|
@ -244,7 +244,7 @@ class Experiment:
|
|||
\item Scheduling of experiments \\
|
||||
e.g.\ calibrations, queue
|
||||
\item Archival of results (HDF5 format)
|
||||
\item Graphical user interface \\
|
||||
\item Graphical user interface \\
|
||||
run with arguments, schedule, real-time plotting
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
|
@ -262,7 +262,7 @@ class Experiment:
|
|||
\item Novatech 409B DDS
|
||||
\item Thorlabs motor controllers
|
||||
\end{itemize}
|
||||
\end{frame}
|
||||
\end{frame}
|
||||
|
||||
\begin{frame}
|
||||
\begin{center}
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
\usepackage{multimedia}
|
||||
\usepackage{tikz}
|
||||
\usetikzlibrary{arrows,shapes,snakes,positioning,backgrounds,decorations,graphs}
|
||||
\definecolor{ethblue}{rgb}{0, 0.2, 0.3568}
|
||||
\definecolor{ethblue}{rgb}{0, 0.2, 0.3568}
|
||||
\usepackage{minted}
|
||||
|
||||
\mode<presentation>
|
||||
|
@ -133,10 +133,10 @@ dds.pulse(200*MHz, 11*us) # exactly 1 ms after trigger
|
|||
\footnotesize
|
||||
\begin{minted}[frame=leftline]{python}
|
||||
with sequential:
|
||||
with parallel:
|
||||
with interleave:
|
||||
a.pulse(100*MHz, 10*us)
|
||||
b.pulse(200*MHz, 20*us)
|
||||
with parallel:
|
||||
with interleave:
|
||||
c.pulse(300*MHz, 30*us)
|
||||
d.pulse(400*MHz, 20*us)
|
||||
\end{minted}
|
||||
|
@ -144,7 +144,7 @@ with sequential:
|
|||
\begin{itemize}
|
||||
\item Experiments are inherently parallel:
|
||||
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!c! and \verb!d! pulses both start when \verb!a! and \verb!b! are both done
|
||||
(after 20\,µs)
|
||||
|
@ -197,7 +197,7 @@ class Experiment:
|
|||
|
||||
@kernel
|
||||
def run(self):
|
||||
with parallel:
|
||||
with interleave:
|
||||
self.ion1.cool(duration=10*us)
|
||||
self.ion2.cool(frequency=...)
|
||||
self.transporter.move(speed=...)
|
||||
|
@ -238,7 +238,7 @@ class Experiment:
|
|||
\item RPC and exception mappings are generated
|
||||
\item Constants and small kernels are inlined
|
||||
\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 The Python AST is converted to LLVM IR
|
||||
\item The LLVM IR is compiled to OpenRISC machine code
|
||||
|
|
|
@ -28,7 +28,7 @@ class PhotonHistogram(EnvExperiment):
|
|||
|
||||
@kernel
|
||||
def cool_detect(self):
|
||||
with parallel:
|
||||
with interleave:
|
||||
self.bd_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_dds.set(self.detect_f)
|
||||
with parallel:
|
||||
with interleave:
|
||||
self.bd_sw.pulse(self.detect_t)
|
||||
self.pmt.gate_rising(self.detect_t)
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ class DDSTest(EnvExperiment):
|
|||
self.led.on()
|
||||
else:
|
||||
self.led.off()
|
||||
with parallel:
|
||||
with interleave:
|
||||
with sequential:
|
||||
self.dds0.set(100*MHz + 4*i*kHz)
|
||||
self.ttl0.pulse(500*us)
|
||||
|
|
|
@ -62,7 +62,7 @@ class TDR(EnvExperiment):
|
|||
@kernel
|
||||
def one(self, t, p):
|
||||
t0 = now_mu()
|
||||
with parallel:
|
||||
with interleave:
|
||||
self.pmt0.gate_both_mu(2*p)
|
||||
self.ttl2.pulse_mu(p)
|
||||
for i in range(len(t)):
|
||||
|
|
|
@ -24,7 +24,7 @@ class AluminumSpectroscopy(EnvExperiment):
|
|||
delay(10*us)
|
||||
self.laser_cooling.pulse(100*MHz, 100*us)
|
||||
delay(5*us)
|
||||
with parallel:
|
||||
with interleave:
|
||||
self.spectroscopy.pulse(self.spectroscopy_freq, 100*us)
|
||||
with sequential:
|
||||
delay(50*us)
|
||||
|
@ -32,7 +32,7 @@ class AluminumSpectroscopy(EnvExperiment):
|
|||
delay(5*us)
|
||||
while True:
|
||||
delay(5*us)
|
||||
with parallel:
|
||||
with interleave:
|
||||
self.state_detection.pulse(100*MHz, 10*us)
|
||||
photon_count = self.pmt.count_gate(10*us)
|
||||
if (photon_count < self.photon_limit_low
|
||||
|
|
|
@ -11,7 +11,7 @@ class SimpleSimulation(EnvExperiment):
|
|||
|
||||
@kernel
|
||||
def run(self):
|
||||
with parallel:
|
||||
with interleave:
|
||||
with sequential:
|
||||
self.a.pulse(100*MHz, 20*us)
|
||||
self.b.pulse(200*MHz, 20*us)
|
||||
|
|
Loading…
Reference in New Issue