From 009d3967409fb69e609e2e22f53b7c9d8224cb31 Mon Sep 17 00:00:00 2001 From: whitequark Date: Mon, 21 Nov 2016 04:27:48 +0000 Subject: [PATCH] Move mu_to_seconds, seconds_to_mu to Core. --- artiq/compiler/builtins.py | 6 ----- artiq/compiler/prelude.py | 2 -- .../compiler/transforms/artiq_ir_generator.py | 14 ---------- artiq/compiler/transforms/inferencer.py | 6 ----- artiq/coredevice/ad5360.py | 7 +++-- artiq/coredevice/core.py | 18 +++++++++++++ artiq/coredevice/spi.py | 8 +++--- artiq/devices/pdq2/mediator.py | 6 ++--- artiq/examples/master/idle_kernel.py | 4 +-- .../repository/coredevice_examples/tdr.py | 2 +- artiq/language/core.py | 26 ------------------- artiq/sim/devices.py | 7 +++++ artiq/test/coredevice/test_portability.py | 2 +- artiq/test/coredevice/test_rtio.py | 16 ++++++------ artiq/test/lit/time/conversion.py | 5 ---- doc/manual/compiler.rst | 2 +- doc/manual/rtio.rst | 2 +- 17 files changed, 48 insertions(+), 85 deletions(-) delete mode 100644 artiq/test/lit/time/conversion.py diff --git a/artiq/compiler/builtins.py b/artiq/compiler/builtins.py index ee7306e3c..6ab7ffe15 100644 --- a/artiq/compiler/builtins.py +++ b/artiq/compiler/builtins.py @@ -203,12 +203,6 @@ def fn_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") - def fn_rtio_log(): return types.TBuiltinFunction("rtio_log") diff --git a/artiq/compiler/prelude.py b/artiq/compiler/prelude.py index e19ef6706..b0b8db762 100644 --- a/artiq/compiler/prelude.py +++ b/artiq/compiler/prelude.py @@ -44,8 +44,6 @@ def globals(): "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(), # ARTIQ utility functions "rtio_log": builtins.fn_rtio_log(), diff --git a/artiq/compiler/transforms/artiq_ir_generator.py b/artiq/compiler/transforms/artiq_ir_generator.py index 4575c381c..6ccd74f43 100644 --- a/artiq/compiler/transforms/artiq_ir_generator.py +++ b/artiq/compiler/transforms/artiq_ir_generator.py @@ -1731,20 +1731,6 @@ class ARTIQIRGenerator(algorithm.Visitor): 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.TInt64())) - else: - assert False elif types.is_exn_constructor(typ): return self.alloc_exn(node.type, *[self.visit(arg_node) for arg_node in node.args]) elif types.is_constructor(typ): diff --git a/artiq/compiler/transforms/inferencer.py b/artiq/compiler/transforms/inferencer.py index 920343b44..716f8041b 100644 --- a/artiq/compiler/transforms/inferencer.py +++ b/artiq/compiler/transforms/inferencer.py @@ -899,12 +899,6 @@ class Inferencer(algorithm.Visitor): elif types.is_builtin(typ, "at_mu"): simple_form("at_mu(time_mu:numpy.int64) -> None", [builtins.TInt64()]) - elif types.is_builtin(typ, "mu_to_seconds"): - simple_form("mu_to_seconds(time_mu:numpy.int64) -> float", - [builtins.TInt64()], builtins.TFloat()) - elif types.is_builtin(typ, "seconds_to_mu"): - simple_form("seconds_to_mu(time:float) -> numpy.int64", - [builtins.TFloat()], builtins.TInt64()) elif types.is_builtin(typ, "watchdog"): simple_form("watchdog(time:float) -> [builtin context manager]", [builtins.TFloat()], builtins.TNone()) diff --git a/artiq/coredevice/ad5360.py b/artiq/coredevice/ad5360.py index b2dbe79c6..3338db4ab 100644 --- a/artiq/coredevice/ad5360.py +++ b/artiq/coredevice/ad5360.py @@ -1,5 +1,4 @@ -from artiq.language.core import (kernel, portable, delay_mu, delay, - seconds_to_mu) +from artiq.language.core import (kernel, portable, delay_mu, delay) from artiq.language.units import ns, us from artiq.coredevice import spi @@ -166,10 +165,10 @@ class AD5360: self.bus.write_period_mu + self.bus.ref_period_mu) - 3*self.bus.ref_period_mu - - seconds_to_mu(1.5*us)) + self.core.seconds_to_mu(1.5*us)) for i in range(len(values)): self.write_channel(i, values[i], op) delay_mu(3*self.bus.ref_period_mu + # latency alignment ttl to spi - seconds_to_mu(1.5*us)) # t10 max busy low for one channel + self.core.seconds_to_mu(1.5*us)) # t10 max busy low for one channel self.load() delay_mu(-2*self.bus.ref_period_mu) # load(), t13 diff --git a/artiq/coredevice/core.py b/artiq/coredevice/core.py index 58c2ca7a9..fceb576bc 100644 --- a/artiq/coredevice/core.py +++ b/artiq/coredevice/core.py @@ -1,4 +1,5 @@ import os, sys +import numpy from pythonparser import diagnostic @@ -124,6 +125,23 @@ class Core: return result + @portable + def seconds_to_mu(self, seconds): + """Converts seconds to the corresponding number of machine units + (RTIO cycles). + + :param seconds: time (in seconds) to convert. + """ + return numpy.int64(seconds//self.ref_period) + + @portable + def mu_to_seconds(self, mu): + """Converts machine units (RTIO cycles) to seconds. + + :param mu: cycle count to convert. + """ + return mu*self.ref_period + @kernel def get_rtio_counter_mu(self): return rtio_get_counter() diff --git a/artiq/coredevice/spi.py b/artiq/coredevice/spi.py index e2c551ff5..65943533f 100644 --- a/artiq/coredevice/spi.py +++ b/artiq/coredevice/spi.py @@ -1,7 +1,6 @@ import numpy -from artiq.language.core import (kernel, portable, seconds_to_mu, now_mu, - delay_mu, mu_to_seconds) +from artiq.language.core import (kernel, portable, now_mu, delay_mu) from artiq.language.units import MHz from artiq.coredevice.rtio import rtio_output, rtio_input_data @@ -59,8 +58,7 @@ class SPIMaster: """ def __init__(self, dmgr, channel, core_device="core"): self.core = dmgr.get(core_device) - self.ref_period_mu = seconds_to_mu(self.core.coarse_ref_period, - self.core) + self.ref_period_mu = self.core.seconds_to_mu(self.core.coarse_ref_period) self.channel = channel self.write_period_mu = numpy.int64(0) self.read_period_mu = numpy.int64(0) @@ -68,7 +66,7 @@ class SPIMaster: @portable def frequency_to_div(self, f): - return int(1/(f*mu_to_seconds(self.ref_period_mu))) + 1 + return int(1/(f*self.core.mu_to_seconds(self.ref_period_mu))) + 1 @kernel def set_config(self, flags=0, write_freq=20*MHz, read_freq=20*MHz): diff --git a/artiq/devices/pdq2/mediator.py b/artiq/devices/pdq2/mediator.py index 33fe24314..4b4adb5a6 100644 --- a/artiq/devices/pdq2/mediator.py +++ b/artiq/devices/pdq2/mediator.py @@ -94,7 +94,7 @@ class _Frame: def _arm(self): self.segment_delays = [ - seconds_to_mu(s.duration*delay_margin_factor, self.core) + self.core.seconds_to_mu(s.duration*delay_margin_factor) for s in self.segments] def _invalidate(self): @@ -125,7 +125,7 @@ class _Frame: raise ArmError() call_t = now_mu() - trigger_start_t = call_t - seconds_to_mu(trigger_duration/2) + trigger_start_t = call_t - self.core.seconds_to_mu(trigger_duration/2) if self.pdq.current_frame >= 0: # PDQ is in the middle of a frame. Check it is us. @@ -136,7 +136,7 @@ class _Frame: # to play our first segment. self.pdq.current_frame = self.frame_number self.pdq.next_segment = 0 - at_mu(trigger_start_t - seconds_to_mu(frame_setup)) + at_mu(trigger_start_t - self.core.seconds_to_mu(frame_setup)) self.pdq.frame0.set_o(bool(self.frame_number & 1)) self.pdq.frame1.set_o(bool((self.frame_number & 2) >> 1)) self.pdq.frame2.set_o(bool((self.frame_number & 4) >> 2)) diff --git a/artiq/examples/master/idle_kernel.py b/artiq/examples/master/idle_kernel.py index a1d27a36c..d4d746fd3 100644 --- a/artiq/examples/master/idle_kernel.py +++ b/artiq/examples/master/idle_kernel.py @@ -5,10 +5,10 @@ class IdleKernel(EnvExperiment): def build(self): self.setattr_device("core") self.setattr_device("led") - + @kernel def run(self): - start_time = now_mu() + seconds_to_mu(500*ms) + start_time = now_mu() + self.core.seconds_to_mu(500*ms) while self.core.get_rtio_counter_mu() < start_time: pass self.core.reset() diff --git a/artiq/examples/master/repository/coredevice_examples/tdr.py b/artiq/examples/master/repository/coredevice_examples/tdr.py index 6ec7c0e09..a32015a7b 100644 --- a/artiq/examples/master/repository/coredevice_examples/tdr.py +++ b/artiq/examples/master/repository/coredevice_examples/tdr.py @@ -42,7 +42,7 @@ class TDR(EnvExperiment): pulse = 1e-6 # pulse length, larger than rtt self.t = [0 for i in range(2)] try: - self.many(n, seconds_to_mu(pulse, self.core)) + self.many(n, self.core.seconds_to_mu(pulse)) except PulseNotReceivedError: print("to few edges: cable too long or wiring bad") else: diff --git a/artiq/language/core.py b/artiq/language/core.py index c1c19c802..47c1746f3 100644 --- a/artiq/language/core.py +++ b/artiq/language/core.py @@ -15,7 +15,6 @@ __all__ = ["kernel", "portable", "rpc", "syscall", "host_only", kernel_globals = ( "sequential", "parallel", "interleave", "delay_mu", "now_mu", "at_mu", "delay", - "seconds_to_mu", "mu_to_seconds", "watchdog" ) __all__.extend(kernel_globals) @@ -213,31 +212,6 @@ def delay(duration): _time_manager.take_time(duration) -def seconds_to_mu(seconds, core=None): - """Converts seconds to the corresponding number of machine units - (RTIO cycles). - - :param seconds: time (in seconds) to convert. - :param core: core device for which to perform the conversion. Specify only - when running in the interpreter (not in kernel). - """ - if core is None: - raise ValueError("Core device must be specified for time conversion") - return numpy.int64(seconds//core.ref_period) - - -def mu_to_seconds(mu, core=None): - """Converts machine units (RTIO cycles) to seconds. - - :param mu: cycle count to convert. - :param core: core device for which to perform the conversion. Specify only - when running in the interpreter (not in kernel). - """ - if core is None: - raise ValueError("Core device must be specified for time conversion") - return mu*core.ref_period - - class _DummyWatchdog: def __init__(self, timeout): pass diff --git a/artiq/sim/devices.py b/artiq/sim/devices.py index 95e72f984..ff8e5eb57 100644 --- a/artiq/sim/devices.py +++ b/artiq/sim/devices.py @@ -1,4 +1,5 @@ from random import Random +import numpy from artiq.language.core import delay, at_mu, kernel from artiq.sim import time @@ -18,6 +19,12 @@ class Core: time.manager.timeline.clear() return r + def seconds_to_mu(self, seconds): + return numpy.int64(seconds//self.ref_period) + + def mu_to_seconds(self, mu): + return mu*self.ref_period + class Input: def __init__(self, dmgr, name): diff --git a/artiq/test/coredevice/test_portability.py b/artiq/test/coredevice/test_portability.py index d67aaa287..cd301d29b 100644 --- a/artiq/test/coredevice/test_portability.py +++ b/artiq/test/coredevice/test_portability.py @@ -83,7 +83,7 @@ class _PulseLogger(EnvExperiment): if not hasattr(self.parent_test, "first_timestamp"): self.parent_test.first_timestamp = t origin = self.parent_test.first_timestamp - t_usec = round(mu_to_seconds(t-origin, self.core)*1000000) + t_usec = round(self.core.mu_to_seconds(t-origin)*1000000) self.parent_test.output_list.append((self.name, t_usec, l, f)) def on(self, t, f): diff --git a/artiq/test/coredevice/test_rtio.py b/artiq/test/coredevice/test_rtio.py index 061d5fc3c..c55e44c1f 100644 --- a/artiq/test/coredevice/test_rtio.py +++ b/artiq/test/coredevice/test_rtio.py @@ -38,7 +38,7 @@ class RTT(EnvExperiment): t1 = self.ttl_inout.timestamp_mu() if t1 < 0: raise PulseNotReceived() - self.set_dataset("rtt", mu_to_seconds(t1 - t0)) + self.set_dataset("rtt", self.core.mu_to_seconds(t1 - t0)) class Loopback(EnvExperiment): @@ -62,7 +62,7 @@ class Loopback(EnvExperiment): t1 = self.loop_in.timestamp_mu() if t1 < 0: raise PulseNotReceived() - self.set_dataset("rtt", mu_to_seconds(t1 - t0)) + self.set_dataset("rtt", self.core.mu_to_seconds(t1 - t0)) class ClockGeneratorLoopback(EnvExperiment): @@ -93,7 +93,7 @@ class PulseRate(EnvExperiment): @kernel def run(self): self.core.reset() - dt = seconds_to_mu(300*ns) + dt = self.core.seconds_to_mu(300*ns) while True: for i in range(10000): try: @@ -104,7 +104,7 @@ class PulseRate(EnvExperiment): self.core.break_realtime() break else: - self.set_dataset("pulse_rate", mu_to_seconds(dt)) + self.set_dataset("pulse_rate", self.core.mu_to_seconds(dt)) return @@ -118,7 +118,7 @@ class PulseRateDDS(EnvExperiment): @kernel def run(self): self.core.reset() - dt = seconds_to_mu(5*us) + dt = self.core.seconds_to_mu(5*us) while True: delay(10*ms) for i in range(1250): @@ -132,7 +132,7 @@ class PulseRateDDS(EnvExperiment): self.core.break_realtime() break else: - self.set_dataset("pulse_rate", mu_to_seconds(dt//2)) + self.set_dataset("pulse_rate", self.core.mu_to_seconds(dt//2)) return @@ -403,7 +403,7 @@ class CoredeviceTest(ExperimentCase): self.execute(TimeKeepsRunning) t2 = self.dataset_mgr.get("time_at_start") - dead_time = mu_to_seconds(t2 - t1, self.device_mgr.get("core")) + dead_time = self.core.mu_to_seconds(t2 - t1, self.device_mgr.get("core")) print(dead_time) self.assertGreater(dead_time, 1*ms) self.assertLess(dead_time, 2500*ms) @@ -434,7 +434,7 @@ class RPCTiming(EnvExperiment): t1 = self.core.get_rtio_counter_mu() self.nop() t2 = self.core.get_rtio_counter_mu() - self.ts[i] = mu_to_seconds(t2 - t1) + self.ts[i] = self.core.mu_to_seconds(t2 - t1) def run(self): self.ts = [0. for _ in range(self.repeats)] diff --git a/artiq/test/lit/time/conversion.py b/artiq/test/lit/time/conversion.py deleted file mode 100644 index 6a89034d6..000000000 --- a/artiq/test/lit/time/conversion.py +++ /dev/null @@ -1,5 +0,0 @@ -# RUN: %python -m artiq.compiler.testbench.jit %s -# REQUIRES: time - -assert seconds_to_mu(2.0) == 2000000 -assert mu_to_seconds(1500000) == 1.5 diff --git a/doc/manual/compiler.rst b/doc/manual/compiler.rst index ef26aef8c..95bdd286a 100644 --- a/doc/manual/compiler.rst +++ b/doc/manual/compiler.rst @@ -151,7 +151,7 @@ In the synthetic example above, the compiler will be able to detect that the res @kernel def loop(self): - precomputed_delay_mu = seconds_to_mu(self.worker.interval / 5.0) + precomputed_delay_mu = self.core.seconds_to_mu(self.worker.interval / 5.0) for _ in range(100): delay_mu(precomputed_delay_mu) self.worker.work() diff --git a/doc/manual/rtio.rst b/doc/manual/rtio.rst index 2344a9576..25ad9e0f1 100644 --- a/doc/manual/rtio.rst +++ b/doc/manual/rtio.rst @@ -36,7 +36,7 @@ The wall clock keeps running across experiments. Absolute timestamps can be large numbers. They are represented internally as 64-bit integers with a resolution of typically a nanosecond and a range of hundreds of years. Conversions between such a large integer number and a floating point representation can cause loss of precision through cancellation. -When computing the difference of absolute timestamps, use ``mu_to_seconds(t2-t1)``, not ``mu_to_seconds(t2)-mu_to_seconds(t1)`` (see :meth:`artiq.language.core.mu_to_seconds`). +When computing the difference of absolute timestamps, use ``self.core.mu_to_seconds(t2-t1)``, not ``self.core.mu_to_seconds(t2)-self.core.mu_to_seconds(t1)`` (see :meth:`artiq.coredevice.Core.mu_to_seconds`). When accumulating time, do it in machine units and not in SI units, so that rounding errors do not accumulate. The following basic example shows how to place output events on the timeline.