mirror of
https://github.com/m-labs/artiq.git
synced 2024-12-25 19:28:26 +08:00
compiler: add lower_units transform
This commit is contained in:
parent
dcc140c5a9
commit
7ea28642e4
@ -1,12 +1,11 @@
|
|||||||
import ast, types
|
import ast, types
|
||||||
|
|
||||||
from artiq.language import units
|
|
||||||
from artiq.compiler.tools import *
|
from artiq.compiler.tools import *
|
||||||
|
|
||||||
# -1 statement duration could not be pre-determined
|
# -1 statement duration could not be pre-determined
|
||||||
# 0 statement has no effect on timeline
|
# 0 statement has no effect on timeline
|
||||||
# >0 statement is a static delay that advances the 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):
|
def _get_duration(stmt):
|
||||||
if isinstance(stmt, (ast.Expr, ast.Assign)):
|
if isinstance(stmt, (ast.Expr, ast.Assign)):
|
||||||
return _get_duration(stmt.value)
|
return _get_duration(stmt.value)
|
||||||
@ -21,10 +20,8 @@ def _get_duration(stmt):
|
|||||||
try:
|
try:
|
||||||
da = eval_constant(stmt.args[0])
|
da = eval_constant(stmt.args[0])
|
||||||
except NotConstant:
|
except NotConstant:
|
||||||
return -1
|
da = -1
|
||||||
if da.unit != units.s_unit:
|
return da
|
||||||
raise units.DimensionError("Delay not expressed in seconds")
|
|
||||||
return da.amount
|
|
||||||
else:
|
else:
|
||||||
return 0
|
return 0
|
||||||
else:
|
else:
|
||||||
@ -54,14 +51,9 @@ def _interleave_timelines(timelines):
|
|||||||
stmt.delay -= dt
|
stmt.delay -= dt
|
||||||
if stmt.delay == 0:
|
if stmt.delay == 0:
|
||||||
ref_stmt = stmt.stmt
|
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(
|
delay_stmt = ast.copy_location(
|
||||||
ast.Expr(ast.Call(func=ast.Name("delay", ast.Load()),
|
ast.Expr(ast.Call(func=ast.Name("delay", ast.Load()),
|
||||||
args=[da_expr],
|
args=[value_to_ast(dt)],
|
||||||
keywords=[], starargs=[], kwargs=[])),
|
keywords=[], starargs=[], kwargs=[])),
|
||||||
ref_stmt)
|
ref_stmt)
|
||||||
r.append(delay_stmt)
|
r.append(delay_stmt)
|
||||||
|
@ -10,16 +10,8 @@ def _insert_int64(node):
|
|||||||
keywords=[], starargs=[], kwargs=[]), node)
|
keywords=[], starargs=[], kwargs=[]), node)
|
||||||
|
|
||||||
class _TimeLowerer(ast.NodeTransformer):
|
class _TimeLowerer(ast.NodeTransformer):
|
||||||
def __init__(self, ref_period):
|
|
||||||
self.ref_period = ref_period
|
|
||||||
|
|
||||||
def visit_Call(self, node):
|
def visit_Call(self, node):
|
||||||
if isinstance(node.func, ast.Name) \
|
if isinstance(node.func, ast.Name) and node.func.id == "now":
|
||||||
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":
|
|
||||||
return ast.copy_location(ast.Name("now", ast.Load()), node)
|
return ast.copy_location(ast.Name("now", ast.Load()), node)
|
||||||
else:
|
else:
|
||||||
self.generic_visit(node)
|
self.generic_visit(node)
|
||||||
|
42
artiq/compiler/lower_units.py
Normal file
42
artiq/compiler/lower_units.py
Normal file
@ -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.inline import inline
|
||||||
|
from artiq.compiler.lower_units import lower_units
|
||||||
from artiq.compiler.fold_constants import fold_constants
|
from artiq.compiler.fold_constants import fold_constants
|
||||||
from artiq.compiler.unroll_loops import unroll_loops
|
from artiq.compiler.unroll_loops import unroll_loops
|
||||||
from artiq.compiler.interleave import interleave
|
from artiq.compiler.interleave import interleave
|
||||||
@ -14,6 +15,7 @@ class Core:
|
|||||||
|
|
||||||
def run(self, k_function, k_args, k_kwargs):
|
def run(self, k_function, k_args, k_kwargs):
|
||||||
funcdef, rpc_map = inline(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)
|
fold_constants(funcdef)
|
||||||
unroll_loops(funcdef, 50)
|
unroll_loops(funcdef, 50)
|
||||||
interleave(funcdef)
|
interleave(funcdef)
|
||||||
|
Loading…
Reference in New Issue
Block a user