mirror of
https://github.com/m-labs/artiq.git
synced 2024-12-29 13:13:34 +08:00
Move mu_to_seconds, seconds_to_mu to Core.
This commit is contained in:
parent
06ea76336d
commit
009d396740
@ -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")
|
||||
|
||||
|
@ -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(),
|
||||
|
@ -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):
|
||||
|
@ -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())
|
||||
|
@ -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
|
||||
|
@ -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()
|
||||
|
@ -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):
|
||||
|
@ -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))
|
||||
|
@ -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()
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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):
|
||||
|
@ -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):
|
||||
|
@ -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)]
|
||||
|
@ -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
|
@ -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()
|
||||
|
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user