forked from M-Labs/artiq
compiler: add lower_units transform
This commit is contained in:
parent
dcc140c5a9
commit
7ea28642e4
|
@ -1,12 +1,11 @@
|
|||
import ast, types
|
||||
|
||||
from artiq.language import units
|
||||
from artiq.compiler.tools import *
|
||||
|
||||
# -1 statement duration could not be pre-determined
|
||||
# 0 statement has no effect on timeline
|
||||
# >0 statement is a static delay that advances the timeline
|
||||
# by the given amount (in seconds)
|
||||
# by the given amount (in microcycles)
|
||||
def _get_duration(stmt):
|
||||
if isinstance(stmt, (ast.Expr, ast.Assign)):
|
||||
return _get_duration(stmt.value)
|
||||
|
@ -21,10 +20,8 @@ def _get_duration(stmt):
|
|||
try:
|
||||
da = eval_constant(stmt.args[0])
|
||||
except NotConstant:
|
||||
return -1
|
||||
if da.unit != units.s_unit:
|
||||
raise units.DimensionError("Delay not expressed in seconds")
|
||||
return da.amount
|
||||
da = -1
|
||||
return da
|
||||
else:
|
||||
return 0
|
||||
else:
|
||||
|
@ -54,14 +51,9 @@ def _interleave_timelines(timelines):
|
|||
stmt.delay -= dt
|
||||
if stmt.delay == 0:
|
||||
ref_stmt = stmt.stmt
|
||||
da_expr = ast.copy_location(
|
||||
ast.Call(func=ast.Name("Quantity", ast.Load()),
|
||||
args=[value_to_ast(dt), ast.Name("s_unit", ast.Load())],
|
||||
keywords=[], starargs=[], kwargs=[]),
|
||||
ref_stmt)
|
||||
delay_stmt = ast.copy_location(
|
||||
ast.Expr(ast.Call(func=ast.Name("delay", ast.Load()),
|
||||
args=[da_expr],
|
||||
args=[value_to_ast(dt)],
|
||||
keywords=[], starargs=[], kwargs=[])),
|
||||
ref_stmt)
|
||||
r.append(delay_stmt)
|
||||
|
|
|
@ -10,16 +10,8 @@ def _insert_int64(node):
|
|||
keywords=[], starargs=[], kwargs=[]), node)
|
||||
|
||||
class _TimeLowerer(ast.NodeTransformer):
|
||||
def __init__(self, ref_period):
|
||||
self.ref_period = ref_period
|
||||
|
||||
def visit_Call(self, node):
|
||||
if isinstance(node.func, ast.Name) \
|
||||
and node.func.id == "Quantity" and node.args[1].id == "s_unit":
|
||||
return ast.copy_location(
|
||||
ast.BinOp(left=node.args[0], op=ast.Div(), right=value_to_ast(self.ref_period.amount)),
|
||||
node)
|
||||
elif isinstance(node.func, ast.Name) and node.func.id == "now":
|
||||
if isinstance(node.func, ast.Name) and node.func.id == "now":
|
||||
return ast.copy_location(ast.Name("now", ast.Load()), node)
|
||||
else:
|
||||
self.generic_visit(node)
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
import ast
|
||||
|
||||
from artiq.compiler.tools import value_to_ast
|
||||
from artiq.language import units
|
||||
|
||||
# TODO:
|
||||
# * track variable and expression dimensions
|
||||
# * raise exception on dimension errors in expressions
|
||||
# * modify RPC map to reintroduce units
|
||||
# * handle core time conversion outside of delay/at,
|
||||
# e.g. foo = now() + 1*us [...] at(foo)
|
||||
|
||||
class _UnitsLowerer(ast.NodeTransformer):
|
||||
def __init__(self, ref_period):
|
||||
self.ref_period = ref_period
|
||||
self.in_core_time = False
|
||||
|
||||
def visit_Call(self, node):
|
||||
fn = node.func.id
|
||||
if fn in ("delay", "at"):
|
||||
old_in_core_time = self.in_core_time
|
||||
self.in_core_time = True
|
||||
self.generic_visit(node)
|
||||
self.in_core_time = old_in_core_time
|
||||
elif fn == "Quantity":
|
||||
if self.in_core_time:
|
||||
if node.args[1].id == "microcycle_units":
|
||||
node = node.args[0]
|
||||
else:
|
||||
node = ast.copy_location(
|
||||
ast.BinOp(left=node.args[0], op=ast.Div(), right=value_to_ast(self.ref_period)),
|
||||
node)
|
||||
else:
|
||||
node = node.args[0]
|
||||
else:
|
||||
self.generic_visit(node)
|
||||
return node
|
||||
|
||||
def lower_units(funcdef, ref_period):
|
||||
if not isinstance(ref_period, units.Quantity) or ref_period.unit is not units.s_unit:
|
||||
raise units.DimensionError("Reference period not expressed in seconds")
|
||||
_UnitsLowerer(ref_period.amount).visit(funcdef)
|
|
@ -1,4 +1,5 @@
|
|||
from artiq.compiler.inline import inline
|
||||
from artiq.compiler.lower_units import lower_units
|
||||
from artiq.compiler.fold_constants import fold_constants
|
||||
from artiq.compiler.unroll_loops import unroll_loops
|
||||
from artiq.compiler.interleave import interleave
|
||||
|
@ -14,6 +15,7 @@ class Core:
|
|||
|
||||
def run(self, k_function, k_args, k_kwargs):
|
||||
funcdef, rpc_map = inline(self, k_function, k_args, k_kwargs)
|
||||
lower_units(funcdef, self.runtime_env.ref_period)
|
||||
fold_constants(funcdef)
|
||||
unroll_loops(funcdef, 50)
|
||||
interleave(funcdef)
|
||||
|
|
Loading…
Reference in New Issue