forked from M-Labs/artiq
Implement {delay,now,at}{,_mu} and {mu,seconds}_to_{seconds,mu}.
This commit is contained in:
parent
5151adb9a8
commit
501ba912c2
|
@ -138,6 +138,30 @@ def fn_print():
|
||||||
def fn_kernel():
|
def fn_kernel():
|
||||||
return types.TBuiltinFunction("kernel")
|
return types.TBuiltinFunction("kernel")
|
||||||
|
|
||||||
|
def fn_now():
|
||||||
|
return types.TBuiltinFunction("now")
|
||||||
|
|
||||||
|
def fn_delay():
|
||||||
|
return types.TBuiltinFunction("delay")
|
||||||
|
|
||||||
|
def fn_at():
|
||||||
|
return types.TBuiltinFunction("at")
|
||||||
|
|
||||||
|
def fn_now_mu():
|
||||||
|
return types.TBuiltinFunction("now_mu")
|
||||||
|
|
||||||
|
def fn_delay_mu():
|
||||||
|
return types.TBuiltinFunction("delay_mu")
|
||||||
|
|
||||||
|
def fn_at_mu():
|
||||||
|
return types.TBuiltinFunction("at_mu")
|
||||||
|
|
||||||
|
def fn_mu_to_seconds():
|
||||||
|
return types.TBuiltinFunction("mu_to_seconds")
|
||||||
|
|
||||||
|
def fn_seconds_to_mu():
|
||||||
|
return types.TBuiltinFunction("seconds_to_mu")
|
||||||
|
|
||||||
# Accessors
|
# Accessors
|
||||||
|
|
||||||
def is_none(typ):
|
def is_none(typ):
|
||||||
|
|
|
@ -42,7 +42,7 @@ class Source:
|
||||||
return cls(source.Buffer(f.read(), filename, 1), engine=engine)
|
return cls(source.Buffer(f.read(), filename, 1), engine=engine)
|
||||||
|
|
||||||
class Module:
|
class Module:
|
||||||
def __init__(self, src):
|
def __init__(self, src, ref_period=1e-6):
|
||||||
self.engine = src.engine
|
self.engine = src.engine
|
||||||
self.object_map = src.object_map
|
self.object_map = src.object_map
|
||||||
|
|
||||||
|
@ -51,7 +51,8 @@ class Module:
|
||||||
monomorphism_validator = validators.MonomorphismValidator(engine=self.engine)
|
monomorphism_validator = validators.MonomorphismValidator(engine=self.engine)
|
||||||
escape_validator = validators.EscapeValidator(engine=self.engine)
|
escape_validator = validators.EscapeValidator(engine=self.engine)
|
||||||
artiq_ir_generator = transforms.ARTIQIRGenerator(engine=self.engine,
|
artiq_ir_generator = transforms.ARTIQIRGenerator(engine=self.engine,
|
||||||
module_name=src.name)
|
module_name=src.name,
|
||||||
|
ref_period=ref_period)
|
||||||
dead_code_eliminator = transforms.DeadCodeEliminator(engine=self.engine)
|
dead_code_eliminator = transforms.DeadCodeEliminator(engine=self.engine)
|
||||||
local_access_validator = validators.LocalAccessValidator(engine=self.engine)
|
local_access_validator = validators.LocalAccessValidator(engine=self.engine)
|
||||||
|
|
||||||
|
|
|
@ -7,17 +7,34 @@ from . import builtins
|
||||||
|
|
||||||
def globals():
|
def globals():
|
||||||
return {
|
return {
|
||||||
|
# Value constructors
|
||||||
"bool": builtins.fn_bool(),
|
"bool": builtins.fn_bool(),
|
||||||
"int": builtins.fn_int(),
|
"int": builtins.fn_int(),
|
||||||
"float": builtins.fn_float(),
|
"float": builtins.fn_float(),
|
||||||
"list": builtins.fn_list(),
|
"list": builtins.fn_list(),
|
||||||
"range": builtins.fn_range(),
|
"range": builtins.fn_range(),
|
||||||
|
|
||||||
|
# Exception constructors
|
||||||
"Exception": builtins.fn_Exception(),
|
"Exception": builtins.fn_Exception(),
|
||||||
"IndexError": builtins.fn_IndexError(),
|
"IndexError": builtins.fn_IndexError(),
|
||||||
"ValueError": builtins.fn_ValueError(),
|
"ValueError": builtins.fn_ValueError(),
|
||||||
"ZeroDivisionError": builtins.fn_ZeroDivisionError(),
|
"ZeroDivisionError": builtins.fn_ZeroDivisionError(),
|
||||||
|
|
||||||
|
# Built-in Python functions
|
||||||
"len": builtins.fn_len(),
|
"len": builtins.fn_len(),
|
||||||
"round": builtins.fn_round(),
|
"round": builtins.fn_round(),
|
||||||
"print": builtins.fn_print(),
|
"print": builtins.fn_print(),
|
||||||
|
|
||||||
|
# ARTIQ decorators
|
||||||
"kernel": builtins.fn_kernel(),
|
"kernel": builtins.fn_kernel(),
|
||||||
|
|
||||||
|
# ARTIQ time management functions
|
||||||
|
"now": builtins.fn_now(),
|
||||||
|
"delay": builtins.fn_delay(),
|
||||||
|
"at": builtins.fn_at(),
|
||||||
|
"now_mu": builtins.fn_now_mu(),
|
||||||
|
"delay_mu": builtins.fn_delay_mu(),
|
||||||
|
"at_mu": builtins.fn_at_mu(),
|
||||||
|
"mu_to_seconds": builtins.fn_mu_to_seconds(),
|
||||||
|
"seconds_to_mu": builtins.fn_seconds_to_mu(),
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,9 +5,9 @@ from .. import Module, Source
|
||||||
from ..targets import NativeTarget
|
from ..targets import NativeTarget
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
libartiq_personality = os.getenv('LIBARTIQ_PERSONALITY')
|
libartiq_support = os.getenv('LIBARTIQ_SUPPORT')
|
||||||
if libartiq_personality is not None:
|
if libartiq_support is not None:
|
||||||
llvm.load_library_permanently(libartiq_personality)
|
llvm.load_library_permanently(libartiq_support)
|
||||||
|
|
||||||
def process_diagnostic(diag):
|
def process_diagnostic(diag):
|
||||||
print("\n".join(diag.render()))
|
print("\n".join(diag.render()))
|
||||||
|
|
|
@ -67,10 +67,11 @@ class ARTIQIRGenerator(algorithm.Visitor):
|
||||||
|
|
||||||
_size_type = builtins.TInt(types.TValue(32))
|
_size_type = builtins.TInt(types.TValue(32))
|
||||||
|
|
||||||
def __init__(self, module_name, engine):
|
def __init__(self, module_name, engine, ref_period):
|
||||||
self.engine = engine
|
self.engine = engine
|
||||||
self.functions = []
|
self.functions = []
|
||||||
self.name = [module_name] if module_name != "" else []
|
self.name = [module_name] if module_name != "" else []
|
||||||
|
self.ref_period = ir.Constant(ref_period, builtins.TFloat())
|
||||||
self.current_loc = None
|
self.current_loc = None
|
||||||
self.current_function = None
|
self.current_function = None
|
||||||
self.current_class = None
|
self.current_class = None
|
||||||
|
@ -1409,6 +1410,39 @@ class ARTIQIRGenerator(algorithm.Visitor):
|
||||||
self.polymorphic_print([self.visit(arg) for arg in node.args],
|
self.polymorphic_print([self.visit(arg) for arg in node.args],
|
||||||
separator=" ", suffix="\n")
|
separator=" ", suffix="\n")
|
||||||
return ir.Constant(None, builtins.TNone())
|
return ir.Constant(None, builtins.TNone())
|
||||||
|
elif types.is_builtin(typ, "now"):
|
||||||
|
if len(node.args) == 0 and len(node.keywords) == 0:
|
||||||
|
now_mu = self.append(ir.Builtin("now_mu", [], builtins.TInt(types.TValue(64))))
|
||||||
|
now_mu_float = self.append(ir.Coerce(now_mu, builtins.TFloat()))
|
||||||
|
return self.append(ir.Arith(ast.Mult(loc=None), now_mu_float, self.ref_period))
|
||||||
|
else:
|
||||||
|
assert False
|
||||||
|
elif types.is_builtin(typ, "delay") or types.is_builtin(typ, "at"):
|
||||||
|
if len(node.args) == 1 and len(node.keywords) == 0:
|
||||||
|
arg = self.visit(node.args[0])
|
||||||
|
arg_mu_float = self.append(ir.Arith(ast.Div(loc=None), arg, self.ref_period))
|
||||||
|
arg_mu = self.append(ir.Coerce(arg_mu_float, builtins.TInt(types.TValue(64))))
|
||||||
|
self.append(ir.Builtin(typ.name + "_mu", [arg_mu], builtins.TNone()))
|
||||||
|
else:
|
||||||
|
assert False
|
||||||
|
elif types.is_builtin(typ, "now_mu") or types.is_builtin(typ, "delay_mu") \
|
||||||
|
or types.is_builtin(typ, "at_mu"):
|
||||||
|
return self.append(ir.Builtin(typ.name,
|
||||||
|
[self.visit(arg) for arg in node.args], node.type))
|
||||||
|
elif types.is_builtin(typ, "mu_to_seconds"):
|
||||||
|
if len(node.args) == 1 and len(node.keywords) == 0:
|
||||||
|
arg = self.visit(node.args[0])
|
||||||
|
arg_float = self.append(ir.Coerce(arg, builtins.TFloat()))
|
||||||
|
return self.append(ir.Arith(ast.Mult(loc=None), arg_float, self.ref_period))
|
||||||
|
else:
|
||||||
|
assert False
|
||||||
|
elif types.is_builtin(typ, "seconds_to_mu"):
|
||||||
|
if len(node.args) == 1 and len(node.keywords) == 0:
|
||||||
|
arg = self.visit(node.args[0])
|
||||||
|
arg_mu = self.append(ir.Arith(ast.Div(loc=None), arg, self.ref_period))
|
||||||
|
return self.append(ir.Coerce(arg_mu, builtins.TInt(types.TValue(64))))
|
||||||
|
else:
|
||||||
|
assert False
|
||||||
elif types.is_exn_constructor(typ):
|
elif types.is_exn_constructor(typ):
|
||||||
return self.alloc_exn(node.type, *[self.visit(arg_node) for arg_node in node.args])
|
return self.alloc_exn(node.type, *[self.visit(arg_node) for arg_node in node.args])
|
||||||
elif types.is_constructor(typ):
|
elif types.is_constructor(typ):
|
||||||
|
|
|
@ -505,6 +505,17 @@ class Inferencer(algorithm.Visitor):
|
||||||
node.func.loc, notes=valid_forms)
|
node.func.loc, notes=valid_forms)
|
||||||
self.engine.process(diag)
|
self.engine.process(diag)
|
||||||
|
|
||||||
|
def simple_form(info, arg_types=[], return_type=builtins.TNone()):
|
||||||
|
self._unify(node.type, return_type,
|
||||||
|
node.loc, None)
|
||||||
|
|
||||||
|
if len(node.args) == len(arg_types) and len(node.keywords) == 0:
|
||||||
|
for index, arg_type in enumerate(arg_types):
|
||||||
|
self._unify(node.args[index].type, arg_type,
|
||||||
|
node.args[index].loc, None)
|
||||||
|
else:
|
||||||
|
diagnose([ valid_form(info) ])
|
||||||
|
|
||||||
if types.is_exn_constructor(typ):
|
if types.is_exn_constructor(typ):
|
||||||
valid_forms = lambda: [
|
valid_forms = lambda: [
|
||||||
valid_form("{exn}() -> {exn}".format(exn=typ.name)),
|
valid_form("{exn}() -> {exn}".format(exn=typ.name)),
|
||||||
|
@ -730,6 +741,30 @@ class Inferencer(algorithm.Visitor):
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
diagnose(valid_forms())
|
diagnose(valid_forms())
|
||||||
|
elif types.is_builtin(typ, "now"):
|
||||||
|
simple_form("now() -> float",
|
||||||
|
[], builtins.TFloat())
|
||||||
|
elif types.is_builtin(typ, "delay"):
|
||||||
|
simple_form("delay(time:float) -> None",
|
||||||
|
[builtins.TFloat()])
|
||||||
|
elif types.is_builtin(typ, "at"):
|
||||||
|
simple_form("at(time:float) -> None",
|
||||||
|
[builtins.TFloat()])
|
||||||
|
elif types.is_builtin(typ, "now_mu"):
|
||||||
|
simple_form("now_mu() -> int(width=64)",
|
||||||
|
[], builtins.TInt(types.TValue(64)))
|
||||||
|
elif types.is_builtin(typ, "delay_mu"):
|
||||||
|
simple_form("delay_mu(time_mu:int(width=64)) -> None",
|
||||||
|
[builtins.TInt(types.TValue(64))])
|
||||||
|
elif types.is_builtin(typ, "at_mu"):
|
||||||
|
simple_form("at_mu(time_mu:int(width=64)) -> None",
|
||||||
|
[builtins.TInt(types.TValue(64))])
|
||||||
|
elif types.is_builtin(typ, "mu_to_seconds"):
|
||||||
|
simple_form("mu_to_seconds(time_mu:int(width=64)) -> float",
|
||||||
|
[builtins.TInt(types.TValue(64))], builtins.TFloat())
|
||||||
|
elif types.is_builtin(typ, "seconds_to_mu"):
|
||||||
|
simple_form("seconds_to_mu(time:float) -> int(width=64)",
|
||||||
|
[builtins.TFloat()], builtins.TInt(types.TValue(64)))
|
||||||
elif types.is_constructor(typ):
|
elif types.is_constructor(typ):
|
||||||
# An user-defined class.
|
# An user-defined class.
|
||||||
self._unify(node.type, typ.find().instance,
|
self._unify(node.type, typ.find().instance,
|
||||||
|
|
|
@ -14,6 +14,7 @@ llvoid = ll.VoidType()
|
||||||
lli1 = ll.IntType(1)
|
lli1 = ll.IntType(1)
|
||||||
lli8 = ll.IntType(8)
|
lli8 = ll.IntType(8)
|
||||||
lli32 = ll.IntType(32)
|
lli32 = ll.IntType(32)
|
||||||
|
lli64 = ll.IntType(64)
|
||||||
lldouble = ll.DoubleType()
|
lldouble = ll.DoubleType()
|
||||||
llptr = ll.IntType(8).as_pointer()
|
llptr = ll.IntType(8).as_pointer()
|
||||||
llmetadata = ll.MetaData()
|
llmetadata = ll.MetaData()
|
||||||
|
@ -331,9 +332,9 @@ class LLVMIRGenerator:
|
||||||
assert False
|
assert False
|
||||||
|
|
||||||
def llbuiltin(self, name):
|
def llbuiltin(self, name):
|
||||||
llfun = self.llmodule.get_global(name)
|
llglobal = self.llmodule.get_global(name)
|
||||||
if llfun is not None:
|
if llglobal is not None:
|
||||||
return llfun
|
return llglobal
|
||||||
|
|
||||||
if name in "llvm.donothing":
|
if name in "llvm.donothing":
|
||||||
llty = ll.FunctionType(llvoid, [])
|
llty = ll.FunctionType(llvoid, [])
|
||||||
|
@ -366,13 +367,19 @@ class LLVMIRGenerator:
|
||||||
var_arg=True)
|
var_arg=True)
|
||||||
elif name == "recv_rpc":
|
elif name == "recv_rpc":
|
||||||
llty = ll.FunctionType(lli32, [llptr])
|
llty = ll.FunctionType(lli32, [llptr])
|
||||||
|
elif name == "now":
|
||||||
|
llty = lli64
|
||||||
else:
|
else:
|
||||||
assert False
|
assert False
|
||||||
|
|
||||||
llfun = ll.Function(self.llmodule, llty, name)
|
if isinstance(llty, ll.FunctionType):
|
||||||
|
llglobal = ll.Function(self.llmodule, llty, name)
|
||||||
if name in ("__artiq_raise", "__artiq_reraise", "llvm.trap"):
|
if name in ("__artiq_raise", "__artiq_reraise", "llvm.trap"):
|
||||||
llfun.attributes.add("noreturn")
|
llglobal.attributes.add("noreturn")
|
||||||
return llfun
|
else:
|
||||||
|
llglobal = ll.GlobalVariable(self.llmodule, llty, name)
|
||||||
|
|
||||||
|
return llglobal
|
||||||
|
|
||||||
def map(self, value):
|
def map(self, value):
|
||||||
if isinstance(value, (ir.Argument, ir.Instruction, ir.BasicBlock)):
|
if isinstance(value, (ir.Argument, ir.Instruction, ir.BasicBlock)):
|
||||||
|
@ -774,6 +781,17 @@ class LLVMIRGenerator:
|
||||||
elif insn.op == "exncast":
|
elif insn.op == "exncast":
|
||||||
# This is an identity cast at LLVM IR level.
|
# This is an identity cast at LLVM IR level.
|
||||||
return self.map(insn.operands[0])
|
return self.map(insn.operands[0])
|
||||||
|
elif insn.op == "now_mu":
|
||||||
|
return self.llbuilder.load(self.llbuiltin("now"), name=insn.name)
|
||||||
|
elif insn.op == "delay_mu":
|
||||||
|
interval, = insn.operands
|
||||||
|
llnowptr = self.llbuiltin("now")
|
||||||
|
llnow = self.llbuilder.load(llnowptr)
|
||||||
|
lladjusted = self.llbuilder.add(llnow, self.map(interval))
|
||||||
|
return self.llbuilder.store(lladjusted, llnowptr)
|
||||||
|
elif insn.op == "at_mu":
|
||||||
|
time, = insn.operands
|
||||||
|
return self.llbuilder.store(self.map(time), self.llbuiltin("now"))
|
||||||
else:
|
else:
|
||||||
assert False
|
assert False
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,7 @@ class Core:
|
||||||
stitcher.stitch_call(function, args, kwargs)
|
stitcher.stitch_call(function, args, kwargs)
|
||||||
stitcher.finalize()
|
stitcher.finalize()
|
||||||
|
|
||||||
module = Module(stitcher)
|
module = Module(stitcher, ref_period=self.ref_period)
|
||||||
target = OR1KTarget()
|
target = OR1KTarget()
|
||||||
|
|
||||||
library = target.compile_and_link([module])
|
library = target.compile_and_link([module])
|
||||||
|
|
|
@ -1,64 +0,0 @@
|
||||||
"""
|
|
||||||
This transform implements time management functions (delay_mu/now_mu/at_mu)
|
|
||||||
using an accumulator 'now' and simple replacement rules:
|
|
||||||
|
|
||||||
delay_mu(t) -> now += t
|
|
||||||
now_mu() -> now
|
|
||||||
at_mu(t) -> now = t
|
|
||||||
|
|
||||||
The function delay(), that uses seconds, must be lowered to delay_mu() before
|
|
||||||
invoking this transform.
|
|
||||||
The accumulator is initialized to an int64 value at the beginning of the
|
|
||||||
output function.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import ast
|
|
||||||
|
|
||||||
|
|
||||||
class _TimeLowerer(ast.NodeTransformer):
|
|
||||||
def visit_Call(self, node):
|
|
||||||
if node.func.id == "now_mu":
|
|
||||||
return ast.copy_location(ast.Name("now", ast.Load()), node)
|
|
||||||
else:
|
|
||||||
self.generic_visit(node)
|
|
||||||
return node
|
|
||||||
|
|
||||||
def visit_Expr(self, node):
|
|
||||||
r = node
|
|
||||||
if isinstance(node.value, ast.Call):
|
|
||||||
funcname = node.value.func.id
|
|
||||||
if funcname == "delay_mu":
|
|
||||||
r = ast.copy_location(
|
|
||||||
ast.AugAssign(target=ast.Name("now", ast.Store()),
|
|
||||||
op=ast.Add(),
|
|
||||||
value=node.value.args[0]),
|
|
||||||
node)
|
|
||||||
elif funcname == "at_mu":
|
|
||||||
r = ast.copy_location(
|
|
||||||
ast.Assign(targets=[ast.Name("now", ast.Store())],
|
|
||||||
value=node.value.args[0]),
|
|
||||||
node)
|
|
||||||
self.generic_visit(r)
|
|
||||||
return r
|
|
||||||
|
|
||||||
|
|
||||||
def lower_time(func_def):
|
|
||||||
_TimeLowerer().visit(func_def)
|
|
||||||
call_init = ast.Call(
|
|
||||||
func=ast.Name("syscall", ast.Load()),
|
|
||||||
args=[ast.Str("now_init")],
|
|
||||||
keywords=[], starargs=None, kwargs=None)
|
|
||||||
stmt_init = ast.Assign(targets=[ast.Name("now", ast.Store())],
|
|
||||||
value=call_init)
|
|
||||||
call_save = ast.Call(
|
|
||||||
func=ast.Name("syscall", ast.Load()),
|
|
||||||
args=[ast.Str("now_save"), ast.Name("now", ast.Load())],
|
|
||||||
keywords=[], starargs=None, kwargs=None)
|
|
||||||
stmt_save = ast.Expr(call_save)
|
|
||||||
func_def.body = [
|
|
||||||
stmt_init,
|
|
||||||
ast.Try(body=func_def.body,
|
|
||||||
handlers=[],
|
|
||||||
orelse=[],
|
|
||||||
finalbody=[stmt_save])
|
|
||||||
]
|
|
|
@ -1,69 +1,3 @@
|
||||||
"""
|
|
||||||
This transform turns calls to delay() that use non-integer time
|
|
||||||
expressed in seconds into calls to delay_mu() that use int64 time
|
|
||||||
expressed in multiples of ref_period.
|
|
||||||
|
|
||||||
It does so by inserting multiplication/division/rounding operations around
|
|
||||||
those calls.
|
|
||||||
|
|
||||||
The seconds_to_mu and mu_to_seconds core language functions are also
|
|
||||||
implemented here, as well as watchdog to syscall conversion.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import ast
|
|
||||||
|
|
||||||
from artiq.transforms.tools import value_to_ast
|
|
||||||
|
|
||||||
|
|
||||||
def _seconds_to_mu(ref_period, node):
|
|
||||||
divided = ast.copy_location(
|
|
||||||
ast.BinOp(left=node,
|
|
||||||
op=ast.Div(),
|
|
||||||
right=value_to_ast(ref_period)),
|
|
||||||
node)
|
|
||||||
return ast.copy_location(
|
|
||||||
ast.Call(func=ast.Name("round64", ast.Load()),
|
|
||||||
args=[divided],
|
|
||||||
keywords=[], starargs=[], kwargs=[]),
|
|
||||||
divided)
|
|
||||||
|
|
||||||
|
|
||||||
def _mu_to_seconds(ref_period, node):
|
|
||||||
return ast.copy_location(
|
|
||||||
ast.BinOp(left=node,
|
|
||||||
op=ast.Mult(),
|
|
||||||
right=value_to_ast(ref_period)),
|
|
||||||
node)
|
|
||||||
|
|
||||||
|
|
||||||
class _TimeQuantizer(ast.NodeTransformer):
|
|
||||||
def __init__(self, ref_period):
|
|
||||||
self.ref_period = ref_period
|
|
||||||
self.watchdog_id_counter = 0
|
|
||||||
|
|
||||||
def visit_Call(self, node):
|
|
||||||
funcname = node.func.id
|
|
||||||
if funcname == "delay":
|
|
||||||
node.func.id = "delay_mu"
|
|
||||||
if (isinstance(node.args[0], ast.Call)
|
|
||||||
and node.args[0].func.id == "mu_to_seconds"):
|
|
||||||
# optimize:
|
|
||||||
# delay(mu_to_seconds(x)) -> delay_mu(x)
|
|
||||||
node.args[0] = self.visit(node.args[0].args[0])
|
|
||||||
else:
|
|
||||||
node.args[0] = _seconds_to_mu(self.ref_period,
|
|
||||||
self.visit(node.args[0]))
|
|
||||||
return node
|
|
||||||
elif funcname == "seconds_to_mu":
|
|
||||||
return _seconds_to_mu(self.ref_period,
|
|
||||||
self.visit(node.args[0]))
|
|
||||||
elif funcname == "mu_to_seconds":
|
|
||||||
return _mu_to_seconds(self.ref_period,
|
|
||||||
self.visit(node.args[0]))
|
|
||||||
else:
|
|
||||||
self.generic_visit(node)
|
|
||||||
return node
|
|
||||||
|
|
||||||
def visit_With(self, node):
|
def visit_With(self, node):
|
||||||
self.generic_visit(node)
|
self.generic_visit(node)
|
||||||
if (isinstance(node.items[0].context_expr, ast.Call)
|
if (isinstance(node.items[0].context_expr, ast.Call)
|
||||||
|
@ -107,7 +41,3 @@ class _TimeQuantizer(ast.NodeTransformer):
|
||||||
finalbody=[stmt_clear])
|
finalbody=[stmt_clear])
|
||||||
]
|
]
|
||||||
return node
|
return node
|
||||||
|
|
||||||
|
|
||||||
def quantize_time(func_def, ref_period):
|
|
||||||
_TimeQuantizer(ref_period).visit(func_def)
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
CC ?= clang
|
CC ?= clang
|
||||||
|
|
||||||
libartiq_personality.so: ../../soc/runtime/artiq_personality.c artiq_terminate.c
|
libartiq_support.so: ../../soc/runtime/artiq_personality.c artiq_terminate.c artiq_time.c
|
||||||
$(CC) -std=c99 -Wall -Werror -I. -I../../soc/runtime -g -fPIC -shared -o $@ $^
|
$(CC) -std=c99 -Wall -Werror -I. -I../../soc/runtime -g -fPIC -shared -o $@ $^
|
|
@ -0,0 +1,3 @@
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
int64_t now = 0;
|
Binary file not shown.
Binary file not shown.
|
@ -17,11 +17,11 @@ not_ = '{} {}'.format(python_executable, os.path.join(root, 'not.py'))
|
||||||
config.substitutions.append( ('%not', not_) )
|
config.substitutions.append( ('%not', not_) )
|
||||||
|
|
||||||
if os.name == 'posix':
|
if os.name == 'posix':
|
||||||
personality_build = os.path.join(root, 'libartiq_personality')
|
support_build = os.path.join(root, 'libartiq_support')
|
||||||
if subprocess.call(['make', '-sC', personality_build]) != 0:
|
if subprocess.call(['make', '-sC', support_build]) != 0:
|
||||||
lit_config.fatal("Unable to build JIT support library")
|
lit_config.fatal("Unable to build JIT support library")
|
||||||
|
|
||||||
personality_lib = os.path.join(personality_build, 'libartiq_personality.so')
|
support_lib = os.path.join(support_build, 'libartiq_support.so')
|
||||||
config.environment['LIBARTIQ_PERSONALITY'] = personality_lib
|
config.environment['LIBARTIQ_SUPPORT'] = support_lib
|
||||||
|
|
||||||
config.available_features.add('exceptions')
|
config.available_features.add('exceptions')
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
# RUN: %python -m artiq.compiler.testbench.jit %s
|
||||||
|
|
||||||
|
assert now() == 0.0
|
||||||
|
delay(100.0)
|
||||||
|
assert now() == 100.0
|
||||||
|
at(12345.0)
|
||||||
|
assert now() == 12345.0
|
||||||
|
|
||||||
|
assert now_mu() == 12345000000
|
|
@ -0,0 +1,7 @@
|
||||||
|
# RUN: %python -m artiq.compiler.testbench.jit %s
|
||||||
|
|
||||||
|
assert now_mu() == 0
|
||||||
|
delay_mu(100)
|
||||||
|
assert now_mu() == 100
|
||||||
|
at_mu(12345)
|
||||||
|
assert now_mu() == 12345
|
|
@ -0,0 +1,4 @@
|
||||||
|
# RUN: %python -m artiq.compiler.testbench.jit %s
|
||||||
|
|
||||||
|
assert seconds_to_mu(2.0) == 2000000
|
||||||
|
assert mu_to_seconds(1500000) == 1.5
|
|
@ -19,6 +19,8 @@
|
||||||
|
|
||||||
void ksupport_abort(void);
|
void ksupport_abort(void);
|
||||||
|
|
||||||
|
int64_t now;
|
||||||
|
|
||||||
/* compiler-rt symbols */
|
/* compiler-rt symbols */
|
||||||
extern void __divsi3, __modsi3, __ledf2, __gedf2, __unorddf2, __eqdf2, __ltdf2,
|
extern void __divsi3, __modsi3, __ledf2, __gedf2, __unorddf2, __eqdf2, __ltdf2,
|
||||||
__nedf2, __gtdf2, __negsf2, __negdf2, __addsf3, __subsf3, __mulsf3,
|
__nedf2, __gtdf2, __negsf2, __negdf2, __addsf3, __subsf3, __mulsf3,
|
||||||
|
@ -87,8 +89,7 @@ static const struct symbol runtime_exports[] = {
|
||||||
{"abort", &ksupport_abort},
|
{"abort", &ksupport_abort},
|
||||||
|
|
||||||
/* proxified syscalls */
|
/* proxified syscalls */
|
||||||
{"now_init", &now_init},
|
{"now", &now},
|
||||||
{"now_save", &now_save},
|
|
||||||
|
|
||||||
{"watchdog_set", &watchdog_set},
|
{"watchdog_set", &watchdog_set},
|
||||||
{"watchdog_clear", &watchdog_clear},
|
{"watchdog_clear", &watchdog_clear},
|
||||||
|
@ -212,7 +213,10 @@ int main(void)
|
||||||
void (*kernel_init)() = request->library_info->init;
|
void (*kernel_init)() = request->library_info->init;
|
||||||
|
|
||||||
mailbox_send_and_wait(&load_reply);
|
mailbox_send_and_wait(&load_reply);
|
||||||
|
|
||||||
|
now = now_init();
|
||||||
kernel_init();
|
kernel_init();
|
||||||
|
now_save(now);
|
||||||
|
|
||||||
struct msg_base finished_reply;
|
struct msg_base finished_reply;
|
||||||
finished_reply.type = MESSAGE_TYPE_FINISHED;
|
finished_reply.type = MESSAGE_TYPE_FINISHED;
|
||||||
|
|
Loading…
Reference in New Issue