forked from M-Labs/artiq
simplify unit system and use floats by default
This commit is contained in:
parent
e6a4c2fb36
commit
c71fe29792
|
@ -1,6 +1,4 @@
|
||||||
from artiq.language.core import *
|
from artiq.language.core import *
|
||||||
from artiq.language.experiment import Experiment
|
from artiq.language.experiment import Experiment
|
||||||
from artiq.language.db import *
|
from artiq.language.db import *
|
||||||
from artiq.language.units import check_unit
|
from artiq.language.units import *
|
||||||
from artiq.language.units import ps, ns, us, ms, s
|
|
||||||
from artiq.language.units import Hz, kHz, MHz, GHz
|
|
||||||
|
|
|
@ -5,7 +5,6 @@ from artiq.language.db import *
|
||||||
from artiq.language.units import ns
|
from artiq.language.units import ns
|
||||||
|
|
||||||
from artiq.transforms.inline import inline
|
from artiq.transforms.inline import inline
|
||||||
from artiq.transforms.lower_units import lower_units
|
|
||||||
from artiq.transforms.quantize_time import quantize_time
|
from artiq.transforms.quantize_time import quantize_time
|
||||||
from artiq.transforms.remove_inter_assigns import remove_inter_assigns
|
from artiq.transforms.remove_inter_assigns import remove_inter_assigns
|
||||||
from artiq.transforms.fold_constants import fold_constants
|
from artiq.transforms.fold_constants import fold_constants
|
||||||
|
@ -61,13 +60,10 @@ class Core(AutoDB):
|
||||||
|
|
||||||
def transform_stack(self, func_def, rpc_map, exception_map,
|
def transform_stack(self, func_def, rpc_map, exception_map,
|
||||||
debug_unparse=_no_debug_unparse):
|
debug_unparse=_no_debug_unparse):
|
||||||
lower_units(func_def, rpc_map)
|
|
||||||
debug_unparse("lower_units", func_def)
|
|
||||||
|
|
||||||
remove_inter_assigns(func_def)
|
remove_inter_assigns(func_def)
|
||||||
debug_unparse("remove_inter_assigns_1", func_def)
|
debug_unparse("remove_inter_assigns_1", func_def)
|
||||||
|
|
||||||
quantize_time(func_def, self.ref_period.amount)
|
quantize_time(func_def, self.ref_period)
|
||||||
debug_unparse("quantize_time", func_def)
|
debug_unparse("quantize_time", func_def)
|
||||||
|
|
||||||
fold_constants(func_def)
|
fold_constants(func_def)
|
||||||
|
|
|
@ -2,7 +2,7 @@ import logging
|
||||||
import ctypes
|
import ctypes
|
||||||
import struct
|
import struct
|
||||||
|
|
||||||
from artiq.language.units import dB, check_unit, Quantity
|
from artiq.language.units import dB
|
||||||
|
|
||||||
|
|
||||||
logger = logging.getLogger("lda")
|
logger = logging.getLogger("lda")
|
||||||
|
@ -47,14 +47,7 @@ class Ldasim:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
step = self.get_att_step_size()
|
step = self.get_att_step_size()
|
||||||
|
att = round(attenuation/step)*step
|
||||||
if isinstance(attenuation, Quantity):
|
|
||||||
check_unit(attenuation, "dB")
|
|
||||||
att = attenuation
|
|
||||||
else:
|
|
||||||
att = attenuation*dB
|
|
||||||
|
|
||||||
att = round(att/step)*step
|
|
||||||
|
|
||||||
if att > self.get_att_max():
|
if att > self.get_att_max():
|
||||||
raise ValueError("Cannot set attenuation {} > {}"
|
raise ValueError("Cannot set attenuation {} > {}"
|
||||||
|
@ -62,7 +55,7 @@ class Ldasim:
|
||||||
elif att < 0*dB:
|
elif att < 0*dB:
|
||||||
raise ValueError("Cannot set attenuation {} < 0".format(att))
|
raise ValueError("Cannot set attenuation {} < 0".format(att))
|
||||||
else:
|
else:
|
||||||
att = round(att.amount*4)/4. * dB
|
att = round(att*4)/4. * dB
|
||||||
self._attenuation = att
|
self._attenuation = att
|
||||||
|
|
||||||
def ping(self):
|
def ping(self):
|
||||||
|
@ -218,14 +211,7 @@ class Lda:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
step = self.get_att_step_size()
|
step = self.get_att_step_size()
|
||||||
|
att = round(attenuation/step)*step
|
||||||
if isinstance(attenuation, Quantity):
|
|
||||||
check_unit(attenuation, "dB")
|
|
||||||
att = attenuation
|
|
||||||
else:
|
|
||||||
att = attenuation*dB
|
|
||||||
|
|
||||||
att = round(att/step)*step
|
|
||||||
|
|
||||||
if att > self.get_att_max():
|
if att > self.get_att_max():
|
||||||
raise ValueError("Cannot set attenuation {} > {}"
|
raise ValueError("Cannot set attenuation {} > {}"
|
||||||
|
@ -233,7 +219,7 @@ class Lda:
|
||||||
elif att < 0*dB:
|
elif att < 0*dB:
|
||||||
raise ValueError("Cannot set attenuation {} < 0".format(att))
|
raise ValueError("Cannot set attenuation {} < 0".format(att))
|
||||||
else:
|
else:
|
||||||
self.set(0x8d, bytes([int(round(att.amount*4))]))
|
self.set(0x8d, bytes([int(round(att*4))]))
|
||||||
|
|
||||||
def ping(self):
|
def ping(self):
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -4,7 +4,7 @@ import struct as st
|
||||||
|
|
||||||
import serial
|
import serial
|
||||||
|
|
||||||
from artiq.language.units import V, strip_unit
|
from artiq.language.units import V
|
||||||
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
@ -302,7 +302,7 @@ class Tcube:
|
||||||
class Tpz(Tcube):
|
class Tpz(Tcube):
|
||||||
def __init__(self, serial_dev):
|
def __init__(self, serial_dev):
|
||||||
Tcube.__init__(self, serial_dev)
|
Tcube.__init__(self, serial_dev)
|
||||||
self.voltage_limit = self.get_tpz_io_settings()[0].amount
|
self.voltage_limit = self.get_tpz_io_settings()[0]
|
||||||
|
|
||||||
def handle_message(self, msg):
|
def handle_message(self, msg):
|
||||||
msg_id = msg.id
|
msg_id = msg.id
|
||||||
|
@ -372,8 +372,6 @@ class Tpz(Tcube):
|
||||||
between the three values 75 V, 100 V and 150 V.
|
between the three values 75 V, 100 V and 150 V.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
voltage = strip_unit(voltage, "V")
|
|
||||||
|
|
||||||
if voltage < 0 or voltage > self.voltage_limit:
|
if voltage < 0 or voltage > self.voltage_limit:
|
||||||
raise ValueError("Voltage must be in range [0;{}]"
|
raise ValueError("Voltage must be in range [0;{}]"
|
||||||
.format(self.voltage_limit))
|
.format(self.voltage_limit))
|
||||||
|
@ -390,7 +388,7 @@ class Tpz(Tcube):
|
||||||
|
|
||||||
get_msg = self.send_request(MGMSG.PZ_REQ_OUTPUTVOLTS,
|
get_msg = self.send_request(MGMSG.PZ_REQ_OUTPUTVOLTS,
|
||||||
[MGMSG.PZ_GET_OUTPUTVOLTS], 1)
|
[MGMSG.PZ_GET_OUTPUTVOLTS], 1)
|
||||||
return st.unpack("<H", get_msg.data[2:])[0]*self.voltage_limit*V/32767
|
return st.unpack("<H", get_msg.data[2:])[0]*self.voltage_limit/32767
|
||||||
|
|
||||||
def set_output_position(self, position_sw):
|
def set_output_position(self, position_sw):
|
||||||
"""Set output position of the piezo actuator.
|
"""Set output position of the piezo actuator.
|
||||||
|
@ -532,7 +530,6 @@ class Tpz(Tcube):
|
||||||
<artiq.devices.thorlabs.driver.Tpz.set_tpz_io_settings>` method.
|
<artiq.devices.thorlabs.driver.Tpz.set_tpz_io_settings>` method.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
output = strip_unit(output, "V")
|
|
||||||
volt = round(output*32767/self.voltage_limit)
|
volt = round(output*32767/self.voltage_limit)
|
||||||
payload = st.pack("<HHH", 1, lut_index, volt)
|
payload = st.pack("<HHH", 1, lut_index, volt)
|
||||||
self.send(Message(MGMSG.PZ_SET_OUTPUTLUT, data=payload))
|
self.send(Message(MGMSG.PZ_SET_OUTPUTLUT, data=payload))
|
||||||
|
@ -548,7 +545,7 @@ class Tpz(Tcube):
|
||||||
get_msg = self.send_request(MGMSG.PZ_REQ_OUTPUTLUT,
|
get_msg = self.send_request(MGMSG.PZ_REQ_OUTPUTLUT,
|
||||||
[MGMSG.PZ_GET_OUTPUTLUT], 1)
|
[MGMSG.PZ_GET_OUTPUTLUT], 1)
|
||||||
(index, output) = st.unpack("<Hh", get_msg.data[2:])
|
(index, output) = st.unpack("<Hh", get_msg.data[2:])
|
||||||
return index, output*self.voltage_limit*V/32767
|
return index, output*self.voltage_limit/32767
|
||||||
|
|
||||||
def set_output_lut_parameters(self, mode, cycle_length, num_cycles,
|
def set_output_lut_parameters(self, mode, cycle_length, num_cycles,
|
||||||
delay_time, precycle_rest, postcycle_rest):
|
delay_time, precycle_rest, postcycle_rest):
|
||||||
|
@ -684,9 +681,6 @@ class Tpz(Tcube):
|
||||||
100 V limit.
|
100 V limit.
|
||||||
|
|
||||||
150 V limit.
|
150 V limit.
|
||||||
|
|
||||||
You can either provide this parameter as an integer or as a
|
|
||||||
:class:`artiq.language.units` Volt quantity (e.g. 75*V).
|
|
||||||
:param hub_analog_input: When the T-Cube piezo driver unit is used in
|
:param hub_analog_input: When the T-Cube piezo driver unit is used in
|
||||||
conjunction with the T-Cube Strain Gauge Reader (TSG001) on the
|
conjunction with the T-Cube Strain Gauge Reader (TSG001) on the
|
||||||
T-Cube Controller Hub (TCH001), a feedback signal can be passed
|
T-Cube Controller Hub (TCH001), a feedback signal can be passed
|
||||||
|
@ -706,7 +700,7 @@ class Tpz(Tcube):
|
||||||
connectors.
|
connectors.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self.voltage_limit = strip_unit(voltage_limit, "V")
|
self.voltage_limit = voltage_limit
|
||||||
|
|
||||||
if self.voltage_limit == 75:
|
if self.voltage_limit == 75:
|
||||||
voltage_limit = 1
|
voltage_limit = 1
|
||||||
|
@ -727,21 +721,21 @@ class Tpz(Tcube):
|
||||||
Hub analog input. Refer to :py:meth:`set_tpz_io_settings()
|
Hub analog input. Refer to :py:meth:`set_tpz_io_settings()
|
||||||
<artiq.devices.thorlabs.driver.Tpz.set_tpz_io_settings>` for the
|
<artiq.devices.thorlabs.driver.Tpz.set_tpz_io_settings>` for the
|
||||||
meaning of those parameters.
|
meaning of those parameters.
|
||||||
:rtype: a 2 elements tuple (Quantity, int)
|
:rtype: a 2 elements tuple (int, int)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
get_msg = self.send_request(MGMSG.PZ_REQ_TPZ_IOSETTINGS,
|
get_msg = self.send_request(MGMSG.PZ_REQ_TPZ_IOSETTINGS,
|
||||||
[MGMSG.PZ_GET_TPZ_IOSETTINGS], 1)
|
[MGMSG.PZ_GET_TPZ_IOSETTINGS], 1)
|
||||||
voltage_limit, hub_analog_input = st.unpack("<HH", get_msg.data[2:6])
|
voltage_limit, hub_analog_input = st.unpack("<HH", get_msg.data[2:6])
|
||||||
if voltage_limit == 1:
|
if voltage_limit == 1:
|
||||||
voltage_limit = 75*V
|
voltage_limit = 75
|
||||||
elif voltage_limit == 2:
|
elif voltage_limit == 2:
|
||||||
voltage_limit = 100*V
|
voltage_limit = 100
|
||||||
elif voltage_limit == 3:
|
elif voltage_limit == 3:
|
||||||
voltage_limit = 150*V
|
voltage_limit = 150
|
||||||
else:
|
else:
|
||||||
raise ValueError("Voltage limit should be in range [1; 3]")
|
raise ValueError("Voltage limit should be in range [1; 3]")
|
||||||
self.voltage_limit = voltage_limit.amount
|
self.voltage_limit = voltage_limit
|
||||||
return voltage_limit, hub_analog_input
|
return voltage_limit, hub_analog_input
|
||||||
|
|
||||||
|
|
||||||
|
@ -1398,14 +1392,13 @@ class TpzSim:
|
||||||
return self.intensity
|
return self.intensity
|
||||||
|
|
||||||
def set_tpz_io_settings(self, voltage_limit, hub_analog_input):
|
def set_tpz_io_settings(self, voltage_limit, hub_analog_input):
|
||||||
self.voltage_limit = strip_unit(voltage_limit, "V")
|
if voltage_limit not in [75, 100, 150]:
|
||||||
|
|
||||||
if self.voltage_limit not in [75, 100, 150]:
|
|
||||||
raise ValueError("voltage_limit must be 75 V, 100 V or 150 V")
|
raise ValueError("voltage_limit must be 75 V, 100 V or 150 V")
|
||||||
|
self.voltage_limit = voltage_limit
|
||||||
self.hub_analog_input = hub_analog_input
|
self.hub_analog_input = hub_analog_input
|
||||||
|
|
||||||
def get_tpz_io_settings(self):
|
def get_tpz_io_settings(self):
|
||||||
return self.voltage_limit*V, self.hub_analog_input
|
return self.voltage_limit, self.hub_analog_input
|
||||||
|
|
||||||
|
|
||||||
class TdcSim:
|
class TdcSim:
|
||||||
|
|
|
@ -9,7 +9,6 @@ from pyqtgraph import dockarea
|
||||||
|
|
||||||
from artiq.tools import TaskObject
|
from artiq.tools import TaskObject
|
||||||
from artiq.protocols.sync_struct import Subscriber
|
from artiq.protocols.sync_struct import Subscriber
|
||||||
from artiq.language.units import strip_unit
|
|
||||||
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
@ -170,7 +169,7 @@ class _DeviceManager:
|
||||||
if (v["module"] == "artiq.coredevice.dds"
|
if (v["module"] == "artiq.coredevice.dds"
|
||||||
and v["class"] == "DDS"):
|
and v["class"] == "DDS"):
|
||||||
channel = v["arguments"]["channel"]
|
channel = v["arguments"]["channel"]
|
||||||
sysclk = strip_unit(v["arguments"]["sysclk"], "Hz")
|
sysclk = v["arguments"]["sysclk"]
|
||||||
self.dds_widgets[channel] = _DDSWidget(
|
self.dds_widgets[channel] = _DDSWidget(
|
||||||
self.send_to_device, channel, sysclk, k)
|
self.send_to_device, channel, sysclk, k)
|
||||||
self.dds_cb()
|
self.dds_cb()
|
||||||
|
|
|
@ -231,7 +231,7 @@ def time_to_cycles(time, core=None):
|
||||||
"""
|
"""
|
||||||
if core is None:
|
if core is None:
|
||||||
raise ValueError("Core device must be specified for time conversion")
|
raise ValueError("Core device must be specified for time conversion")
|
||||||
return round64(time.amount//core.ref_period)
|
return round64(time//core.ref_period)
|
||||||
|
|
||||||
|
|
||||||
def cycles_to_time(cycles, core=None):
|
def cycles_to_time(cycles, core=None):
|
||||||
|
|
|
@ -1,266 +1,17 @@
|
||||||
"""
|
|
||||||
Definition and management of physical units.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
from fractions import Fraction as _Fraction
|
|
||||||
|
|
||||||
|
|
||||||
class DimensionError(Exception):
|
|
||||||
"""Raised when attempting an operation with incompatible units.
|
|
||||||
|
|
||||||
When targeting the core device, all units are statically managed at
|
|
||||||
compilation time. Thus, when raised by functions in this module, this
|
|
||||||
exception cannot be caught in the kernel as it is raised by the compiler
|
|
||||||
instead.
|
|
||||||
|
|
||||||
"""
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def mul_dimension(l, r):
|
|
||||||
"""Returns the unit obtained by multiplying unit ``l`` with unit ``r``.
|
|
||||||
|
|
||||||
Raises ``DimensionError`` if the resulting unit is not implemented.
|
|
||||||
|
|
||||||
"""
|
|
||||||
if l is None:
|
|
||||||
return r
|
|
||||||
if r is None:
|
|
||||||
return l
|
|
||||||
if {l, r} == {"Hz", "s"}:
|
|
||||||
return None
|
|
||||||
raise DimensionError
|
|
||||||
|
|
||||||
|
|
||||||
def _rmul_dimension(l, r):
|
|
||||||
return mul_dimension(r, l)
|
|
||||||
|
|
||||||
|
|
||||||
def div_dimension(l, r):
|
|
||||||
"""Returns the unit obtained by dividing unit ``l`` with unit ``r``.
|
|
||||||
|
|
||||||
Raises ``DimensionError`` if the resulting unit is not implemented.
|
|
||||||
|
|
||||||
"""
|
|
||||||
if l == r:
|
|
||||||
return None
|
|
||||||
if r is None:
|
|
||||||
return l
|
|
||||||
if l is None:
|
|
||||||
if r == "s":
|
|
||||||
return "Hz"
|
|
||||||
if r == "Hz":
|
|
||||||
return "s"
|
|
||||||
raise DimensionError
|
|
||||||
|
|
||||||
|
|
||||||
def _rdiv_dimension(l, r):
|
|
||||||
return div_dimension(r, l)
|
|
||||||
|
|
||||||
|
|
||||||
def addsub_dimension(x, y):
|
|
||||||
"""Returns the unit obtained by adding or subtracting unit ``l`` with
|
|
||||||
unit ``r``.
|
|
||||||
|
|
||||||
Raises ``DimensionError`` if ``l`` and ``r`` are different.
|
|
||||||
|
|
||||||
"""
|
|
||||||
if x == y:
|
|
||||||
return x
|
|
||||||
else:
|
|
||||||
raise DimensionError
|
|
||||||
|
|
||||||
|
|
||||||
_prefixes_str = "pnum_kMG"
|
_prefixes_str = "pnum_kMG"
|
||||||
_smallest_prefix = _Fraction(1, 10**12)
|
_smallest_prefix_exp = -12
|
||||||
|
|
||||||
|
|
||||||
def _format(amount, unit):
|
|
||||||
if amount is NotImplemented:
|
|
||||||
return NotImplemented
|
|
||||||
if unit is None:
|
|
||||||
return amount
|
|
||||||
else:
|
|
||||||
return Quantity(amount, unit)
|
|
||||||
|
|
||||||
|
|
||||||
class Quantity:
|
|
||||||
"""Represents an amount in a given fundamental unit (identified by a
|
|
||||||
string).
|
|
||||||
|
|
||||||
The amount can be of any Python numerical type (integer, float,
|
|
||||||
Fraction, ...).
|
|
||||||
Arithmetic operations and comparisons are directly delegated to the
|
|
||||||
underlying numerical types.
|
|
||||||
|
|
||||||
"""
|
|
||||||
def __init__(self, amount, unit):
|
|
||||||
self.amount = amount
|
|
||||||
self.unit = unit
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
r_amount = self.amount
|
|
||||||
if isinstance(r_amount, int) or isinstance(r_amount, _Fraction):
|
|
||||||
r_prefix = 0
|
|
||||||
r_amount = r_amount/_smallest_prefix
|
|
||||||
if r_amount:
|
|
||||||
numerator = r_amount.numerator
|
|
||||||
while numerator % 1000 == 0 and r_prefix < len(_prefixes_str):
|
|
||||||
numerator /= 1000
|
|
||||||
r_amount /= 1000
|
|
||||||
r_prefix += 1
|
|
||||||
prefix_str = _prefixes_str[r_prefix]
|
|
||||||
if prefix_str == "_":
|
|
||||||
prefix_str = ""
|
|
||||||
return str(r_amount) + " " + prefix_str + self.unit
|
|
||||||
else:
|
|
||||||
return str(r_amount) + " " + self.unit
|
|
||||||
|
|
||||||
def __float__(self):
|
|
||||||
return float(self.amount)
|
|
||||||
|
|
||||||
# mul/div
|
|
||||||
def _binop(self, other, opf_name, dim_function):
|
|
||||||
opf = getattr(self.amount, opf_name)
|
|
||||||
if isinstance(other, Quantity):
|
|
||||||
amount = opf(other.amount)
|
|
||||||
unit = dim_function(self.unit, other.unit)
|
|
||||||
else:
|
|
||||||
amount = opf(other)
|
|
||||||
unit = dim_function(self.unit, None)
|
|
||||||
return _format(amount, unit)
|
|
||||||
|
|
||||||
def __mul__(self, other):
|
|
||||||
return self._binop(other, "__mul__", mul_dimension)
|
|
||||||
|
|
||||||
def __rmul__(self, other):
|
|
||||||
return self._binop(other, "__rmul__", _rmul_dimension)
|
|
||||||
|
|
||||||
def __truediv__(self, other):
|
|
||||||
return self._binop(other, "__truediv__", div_dimension)
|
|
||||||
|
|
||||||
def __rtruediv__(self, other):
|
|
||||||
return self._binop(other, "__rtruediv__", _rdiv_dimension)
|
|
||||||
|
|
||||||
def __floordiv__(self, other):
|
|
||||||
return self._binop(other, "__floordiv__", div_dimension)
|
|
||||||
|
|
||||||
def __rfloordiv__(self, other):
|
|
||||||
return self._binop(other, "__rfloordiv__", _rdiv_dimension)
|
|
||||||
|
|
||||||
# unary ops
|
|
||||||
def __neg__(self):
|
|
||||||
return Quantity(self.amount.__neg__(), self.unit)
|
|
||||||
|
|
||||||
def __pos__(self):
|
|
||||||
return Quantity(self.amount.__pos__(), self.unit)
|
|
||||||
|
|
||||||
def __abs__(self):
|
|
||||||
return Quantity(abs(self.amount), self.unit)
|
|
||||||
|
|
||||||
# add/sub
|
|
||||||
def __add__(self, other):
|
|
||||||
return self._binop(other, "__add__", addsub_dimension)
|
|
||||||
|
|
||||||
def __radd__(self, other):
|
|
||||||
return self._binop(other, "__radd__", addsub_dimension)
|
|
||||||
|
|
||||||
def __sub__(self, other):
|
|
||||||
return self._binop(other, "__sub__", addsub_dimension)
|
|
||||||
|
|
||||||
def __rsub__(self, other):
|
|
||||||
return self._binop(other, "__rsub__", addsub_dimension)
|
|
||||||
|
|
||||||
def __mod__(self, other):
|
|
||||||
return self._binop(other, "__mod__", addsub_dimension)
|
|
||||||
|
|
||||||
def __rmod__(self, other):
|
|
||||||
return self._binop(other, "__rmod__", addsub_dimension)
|
|
||||||
|
|
||||||
# comparisons
|
|
||||||
def _cmp(self, other, opf_name):
|
|
||||||
if not isinstance(other, Quantity) or other.unit != self.unit:
|
|
||||||
raise DimensionError
|
|
||||||
return getattr(self.amount, opf_name)(other.amount)
|
|
||||||
|
|
||||||
def __lt__(self, other):
|
|
||||||
return self._cmp(other, "__lt__")
|
|
||||||
|
|
||||||
def __le__(self, other):
|
|
||||||
return self._cmp(other, "__le__")
|
|
||||||
|
|
||||||
def __eq__(self, other):
|
|
||||||
return self._cmp(other, "__eq__")
|
|
||||||
|
|
||||||
def __ne__(self, other):
|
|
||||||
return self._cmp(other, "__ne__")
|
|
||||||
|
|
||||||
def __gt__(self, other):
|
|
||||||
return self._cmp(other, "__gt__")
|
|
||||||
|
|
||||||
def __ge__(self, other):
|
|
||||||
return self._cmp(other, "__ge__")
|
|
||||||
|
|
||||||
|
|
||||||
def _register_unit(unit, prefixes):
|
def _register_unit(unit, prefixes):
|
||||||
amount = _smallest_prefix
|
exponent = _smallest_prefix_exp
|
||||||
for prefix in _prefixes_str:
|
for prefix in _prefixes_str:
|
||||||
if prefix in prefixes:
|
if prefix in prefixes:
|
||||||
quantity = Quantity(amount, unit)
|
|
||||||
full_name = prefix + unit if prefix != "_" else unit
|
full_name = prefix + unit if prefix != "_" else unit
|
||||||
globals()[full_name] = quantity
|
globals()[full_name] = 10.**exponent
|
||||||
amount *= 1000
|
exponent += 3
|
||||||
|
|
||||||
|
|
||||||
_register_unit("s", "pnum_")
|
_register_unit("s", "pnum_")
|
||||||
_register_unit("Hz", "_kMG")
|
_register_unit("Hz", "_kMG")
|
||||||
_register_unit("dB", "_")
|
_register_unit("dB", "_")
|
||||||
_register_unit("V", "um_k")
|
_register_unit("V", "um_k")
|
||||||
|
|
||||||
|
|
||||||
def check_unit(value, unit):
|
|
||||||
"""Checks that the value has the specified unit. Unit specification is
|
|
||||||
a string representing the unit without any prefix (e.g. ``s``, ``Hz``).
|
|
||||||
Checking for a dimensionless value (not a ``Quantity`` instance) is done
|
|
||||||
by setting ``unit`` to ``None``.
|
|
||||||
|
|
||||||
If the units do not match, ``DimensionError`` is raised.
|
|
||||||
|
|
||||||
This function can be used in kernels and is executed at compilation time.
|
|
||||||
|
|
||||||
There is already unit checking built into the arithmetic, so you typically
|
|
||||||
need to use this function only when using the ``amount`` property of
|
|
||||||
``Quantity``.
|
|
||||||
|
|
||||||
"""
|
|
||||||
if unit is None:
|
|
||||||
if isinstance(value, Quantity):
|
|
||||||
raise DimensionError
|
|
||||||
else:
|
|
||||||
if not isinstance(value, Quantity) or value.unit != unit:
|
|
||||||
raise DimensionError
|
|
||||||
|
|
||||||
def strip_unit(value, unit):
|
|
||||||
"""Check that the value has the specified unit and returns its amount.
|
|
||||||
Raises ``DimensionError`` if the units does not match.
|
|
||||||
|
|
||||||
If the passed value is not a ``Quantity``, it is assumed to be in the
|
|
||||||
specified unit and is returned unchanged.
|
|
||||||
|
|
||||||
If ``unit`` is ``None``, passing a ``Quantity`` as value raises
|
|
||||||
``DimensionError``.
|
|
||||||
|
|
||||||
"""
|
|
||||||
if unit is None:
|
|
||||||
if isinstance(value, Quantity):
|
|
||||||
raise DimensionError
|
|
||||||
else:
|
|
||||||
return value
|
|
||||||
else:
|
|
||||||
if isinstance(value, Quantity):
|
|
||||||
if value.unit != unit:
|
|
||||||
raise DimensionError
|
|
||||||
else:
|
|
||||||
return value.amount
|
|
||||||
else:
|
|
||||||
return value
|
|
||||||
|
|
|
@ -6,7 +6,6 @@ import traceback
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from artiq.protocols import pyon
|
from artiq.protocols import pyon
|
||||||
from artiq.language.units import strip_unit
|
|
||||||
from artiq.tools import (asyncio_process_wait_timeout, asyncio_process_wait,
|
from artiq.tools import (asyncio_process_wait_timeout, asyncio_process_wait,
|
||||||
asyncio_wait_or_cancel)
|
asyncio_wait_or_cancel)
|
||||||
|
|
||||||
|
@ -50,7 +49,7 @@ class Worker:
|
||||||
avail = set(range(n_user_watchdogs + 1)) \
|
avail = set(range(n_user_watchdogs + 1)) \
|
||||||
- set(self.watchdogs.keys())
|
- set(self.watchdogs.keys())
|
||||||
wid = next(iter(avail))
|
wid = next(iter(avail))
|
||||||
self.watchdogs[wid] = time.monotonic() + strip_unit(t, "s")
|
self.watchdogs[wid] = time.monotonic() + t
|
||||||
return wid
|
return wid
|
||||||
|
|
||||||
def delete_watchdog(self, wid):
|
def delete_watchdog(self, wid):
|
||||||
|
|
|
@ -14,7 +14,6 @@ The main rationale for this new custom serializer (instead of using JSON) is
|
||||||
that JSON does not support Numpy and more generally cannot be extended with
|
that JSON does not support Numpy and more generally cannot be extended with
|
||||||
other data types while keeping a concise syntax. Here we can use the Python
|
other data types while keeping a concise syntax. Here we can use the Python
|
||||||
function call syntax to mark special data types.
|
function call syntax to mark special data types.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
@ -25,8 +24,6 @@ import tempfile
|
||||||
|
|
||||||
import numpy
|
import numpy
|
||||||
|
|
||||||
from artiq.language.units import Quantity
|
|
||||||
|
|
||||||
|
|
||||||
_encode_map = {
|
_encode_map = {
|
||||||
type(None): "none",
|
type(None): "none",
|
||||||
|
@ -39,7 +36,6 @@ _encode_map = {
|
||||||
list: "list",
|
list: "list",
|
||||||
dict: "dict",
|
dict: "dict",
|
||||||
Fraction: "fraction",
|
Fraction: "fraction",
|
||||||
Quantity: "quantity",
|
|
||||||
numpy.ndarray: "nparray"
|
numpy.ndarray: "nparray"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,10 +106,6 @@ class _Encoder:
|
||||||
return "Fraction({}, {})".format(encode(x.numerator),
|
return "Fraction({}, {})".format(encode(x.numerator),
|
||||||
encode(x.denominator))
|
encode(x.denominator))
|
||||||
|
|
||||||
def encode_quantity(self, x):
|
|
||||||
return "Quantity({}, {})".format(encode(x.amount),
|
|
||||||
encode(x.unit))
|
|
||||||
|
|
||||||
def encode_nparray(self, x):
|
def encode_nparray(self, x):
|
||||||
r = "nparray("
|
r = "nparray("
|
||||||
r += encode(x.shape) + ", "
|
r += encode(x.shape) + ", "
|
||||||
|
@ -147,7 +139,6 @@ _eval_dict = {
|
||||||
"true": True,
|
"true": True,
|
||||||
|
|
||||||
"Fraction": Fraction,
|
"Fraction": Fraction,
|
||||||
"Quantity": Quantity,
|
|
||||||
"nparray": _nparray
|
"nparray": _nparray
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,6 @@ import os
|
||||||
from fractions import Fraction
|
from fractions import Fraction
|
||||||
|
|
||||||
from artiq import *
|
from artiq import *
|
||||||
from artiq.language.units import DimensionError
|
|
||||||
from artiq.coredevice import comm_tcp, core, runtime_exceptions, ttl
|
from artiq.coredevice import comm_tcp, core, runtime_exceptions, ttl
|
||||||
from artiq.sim import devices as sim_devices
|
from artiq.sim import devices as sim_devices
|
||||||
|
|
||||||
|
@ -51,7 +50,6 @@ class _Primes(AutoDB):
|
||||||
class _Misc(AutoDB):
|
class _Misc(AutoDB):
|
||||||
def build(self):
|
def build(self):
|
||||||
self.input = 84
|
self.input = 84
|
||||||
self.inhomogeneous_units = []
|
|
||||||
self.al = [1, 2, 3, 4, 5]
|
self.al = [1, 2, 3, 4, 5]
|
||||||
self.list_copy_in = [2*Hz, 10*MHz]
|
self.list_copy_in = [2*Hz, 10*MHz]
|
||||||
|
|
||||||
|
@ -59,29 +57,10 @@ class _Misc(AutoDB):
|
||||||
def run(self):
|
def run(self):
|
||||||
self.half_input = self.input//2
|
self.half_input = self.input//2
|
||||||
self.decimal_fraction = Fraction("1.2")
|
self.decimal_fraction = Fraction("1.2")
|
||||||
self.inhomogeneous_units.append(1000*Hz)
|
|
||||||
self.inhomogeneous_units.append(10*s)
|
|
||||||
self.acc = 0
|
self.acc = 0
|
||||||
for i in range(len(self.al)):
|
for i in range(len(self.al)):
|
||||||
self.acc += self.al[i]
|
self.acc += self.al[i]
|
||||||
self.list_copy_out = self.list_copy_in
|
self.list_copy_out = self.list_copy_in
|
||||||
self.unit_comp = [1*MHz for _ in range(3)]
|
|
||||||
|
|
||||||
@kernel
|
|
||||||
def dimension_error1(self):
|
|
||||||
print(1*Hz + 1*s)
|
|
||||||
|
|
||||||
@kernel
|
|
||||||
def dimension_error2(self):
|
|
||||||
print(1*Hz < 1*s)
|
|
||||||
|
|
||||||
@kernel
|
|
||||||
def dimension_error3(self):
|
|
||||||
check_unit(1*Hz, "s")
|
|
||||||
|
|
||||||
@kernel
|
|
||||||
def dimension_error4(self):
|
|
||||||
delay(10*Hz)
|
|
||||||
|
|
||||||
|
|
||||||
class _PulseLogger(AutoDB):
|
class _PulseLogger(AutoDB):
|
||||||
|
@ -103,9 +82,9 @@ class _PulseLogger(AutoDB):
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def pulse(self, f, duration):
|
def pulse(self, f, duration):
|
||||||
self.on(int(now().amount*1000000000), f)
|
self.on(int(now()*1000000000), f)
|
||||||
delay(duration)
|
delay(duration)
|
||||||
self.off(int(now().amount*1000000000))
|
self.off(int(now()*1000000000))
|
||||||
|
|
||||||
|
|
||||||
class _Pulses(AutoDB):
|
class _Pulses(AutoDB):
|
||||||
|
@ -229,18 +208,8 @@ class ExecutionCase(unittest.TestCase):
|
||||||
uut.run()
|
uut.run()
|
||||||
self.assertEqual(uut.half_input, 42)
|
self.assertEqual(uut.half_input, 42)
|
||||||
self.assertEqual(uut.decimal_fraction, Fraction("1.2"))
|
self.assertEqual(uut.decimal_fraction, Fraction("1.2"))
|
||||||
self.assertEqual(uut.inhomogeneous_units, [1000*Hz, 10*s])
|
|
||||||
self.assertEqual(uut.acc, sum(uut.al))
|
self.assertEqual(uut.acc, sum(uut.al))
|
||||||
self.assertEqual(uut.list_copy_in, uut.list_copy_out)
|
self.assertEqual(uut.list_copy_in, uut.list_copy_out)
|
||||||
self.assertEqual(uut.unit_comp, [1*MHz for _ in range(3)])
|
|
||||||
with self.assertRaises(DimensionError):
|
|
||||||
uut.dimension_error1()
|
|
||||||
with self.assertRaises(DimensionError):
|
|
||||||
uut.dimension_error2()
|
|
||||||
with self.assertRaises(DimensionError):
|
|
||||||
uut.dimension_error3()
|
|
||||||
with self.assertRaises(DimensionError):
|
|
||||||
uut.dimension_error4()
|
|
||||||
finally:
|
finally:
|
||||||
comm.close()
|
comm.close()
|
||||||
|
|
||||||
|
|
|
@ -10,9 +10,9 @@ lda_serial = os.getenv("ARTIQ_LDA_SERIAL")
|
||||||
|
|
||||||
class GenericLdaTest:
|
class GenericLdaTest:
|
||||||
def test_attenuation(self):
|
def test_attenuation(self):
|
||||||
step = self.cont.get_att_step_size().amount
|
step = self.cont.get_att_step_size()
|
||||||
max = self.cont.get_att_max().amount
|
attmax = self.cont.get_att_max()
|
||||||
test_vector = [i*step*dB for i in range(0, int(max*int(1/step)+1))]
|
test_vector = [i*step*dB for i in range(0, int(attmax*int(1/step)+1))]
|
||||||
for i in test_vector:
|
for i in test_vector:
|
||||||
with self.subTest(i=i):
|
with self.subTest(i=i):
|
||||||
self.cont.set_attenuation(i)
|
self.cont.set_attenuation(i)
|
||||||
|
|
|
@ -88,7 +88,7 @@ class GenericTpzTest:
|
||||||
|
|
||||||
def test_ouput_volts(self):
|
def test_ouput_volts(self):
|
||||||
for voltage in 5*V, 10*V, 15*V, \
|
for voltage in 5*V, 10*V, 15*V, \
|
||||||
round(self.cont.get_tpz_io_settings()[0].amount)*V:
|
round(self.cont.get_tpz_io_settings()[0])*V:
|
||||||
with self.subTest(voltage=voltage):
|
with self.subTest(voltage=voltage):
|
||||||
test_vector = voltage
|
test_vector = voltage
|
||||||
self.cont.set_output_volts(test_vector)
|
self.cont.set_output_volts(test_vector)
|
||||||
|
|
|
@ -6,21 +6,13 @@ from artiq.coredevice import comm_dummy, core
|
||||||
from artiq.transforms.unparse import unparse
|
from artiq.transforms.unparse import unparse
|
||||||
|
|
||||||
|
|
||||||
# Original code before inline:
|
|
||||||
#
|
|
||||||
# n = time_to_cycles(1.2345*ns)
|
|
||||||
# ftw = self.dds.frequency_to_ftw(345*MHz)
|
|
||||||
# f = self.dds.ftw_to_frequency(ftw)
|
|
||||||
# phi = 1000*cycles_to_time(n)*f
|
|
||||||
# do_someting(int(phi))
|
|
||||||
#
|
|
||||||
optimize_in = """
|
optimize_in = """
|
||||||
|
|
||||||
def run():
|
def run():
|
||||||
dds_sysclk = Quantity(Fraction(1000000000, 1), 'Hz')
|
dds_sysclk = Fraction(1000000000, 1)
|
||||||
n = time_to_cycles((1.2345 * Quantity(Fraction(1, 1000000000), 's')))
|
n = time_to_cycles((1.2345 * Fraction(1, 1000000000)))
|
||||||
with sequential:
|
with sequential:
|
||||||
frequency = (345 * Quantity(Fraction(1000000, 1), 'Hz'))
|
frequency = 345 * Fraction(1000000, 1)
|
||||||
frequency_to_ftw_return = int((((2 ** 32) * frequency) / dds_sysclk))
|
frequency_to_ftw_return = int((((2 ** 32) * frequency) / dds_sysclk))
|
||||||
ftw = frequency_to_ftw_return
|
ftw = frequency_to_ftw_return
|
||||||
with sequential:
|
with sequential:
|
||||||
|
|
|
@ -1,190 +0,0 @@
|
||||||
import ast
|
|
||||||
from collections import defaultdict
|
|
||||||
from copy import copy
|
|
||||||
|
|
||||||
from artiq.language import units
|
|
||||||
from artiq.transforms.tools import embeddable_func_names
|
|
||||||
|
|
||||||
|
|
||||||
def _add_units(f, unit_list):
|
|
||||||
def wrapper(*args):
|
|
||||||
new_args = []
|
|
||||||
for arg, unit in zip(args, unit_list):
|
|
||||||
if unit is None:
|
|
||||||
new_args.append(arg)
|
|
||||||
else:
|
|
||||||
if isinstance(arg, list):
|
|
||||||
new_args.append([units.Quantity(x, unit) for x in arg])
|
|
||||||
else:
|
|
||||||
new_args.append(units.Quantity(arg, unit))
|
|
||||||
return f(*new_args)
|
|
||||||
return wrapper
|
|
||||||
|
|
||||||
|
|
||||||
class _UnitsLowerer(ast.NodeTransformer):
|
|
||||||
def __init__(self, rpc_map):
|
|
||||||
self.rpc_map = rpc_map
|
|
||||||
# (original rpc number, (unit list)) -> new rpc number
|
|
||||||
self.rpc_remap = defaultdict(lambda: len(self.rpc_remap))
|
|
||||||
self.variable_units = dict()
|
|
||||||
|
|
||||||
def visit_Name(self, node):
|
|
||||||
try:
|
|
||||||
unit = self.variable_units[node.id]
|
|
||||||
except KeyError:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
if unit is not None:
|
|
||||||
node.unit = unit
|
|
||||||
return node
|
|
||||||
|
|
||||||
def visit_BoolOp(self, node):
|
|
||||||
self.generic_visit(node)
|
|
||||||
us = [getattr(value, "unit", None) for value in node.values]
|
|
||||||
if not all(u == us[0] for u in us[1:]):
|
|
||||||
raise units.DimensionError
|
|
||||||
return node
|
|
||||||
|
|
||||||
def visit_Compare(self, node):
|
|
||||||
self.generic_visit(node)
|
|
||||||
u0 = getattr(node.left, "unit", None)
|
|
||||||
us = [getattr(comparator, "unit", None)
|
|
||||||
for comparator in node.comparators]
|
|
||||||
if not all(u == u0 for u in us):
|
|
||||||
raise units.DimensionError
|
|
||||||
return node
|
|
||||||
|
|
||||||
def visit_UnaryOp(self, node):
|
|
||||||
self.generic_visit(node)
|
|
||||||
if hasattr(node.operand, "unit"):
|
|
||||||
node.unit = node.operand.unit
|
|
||||||
return node
|
|
||||||
|
|
||||||
def visit_BinOp(self, node):
|
|
||||||
self.generic_visit(node)
|
|
||||||
op = type(node.op)
|
|
||||||
left_unit = getattr(node.left, "unit", None)
|
|
||||||
right_unit = getattr(node.right, "unit", None)
|
|
||||||
if op in (ast.Add, ast.Sub, ast.Mod):
|
|
||||||
unit = units.addsub_dimension(left_unit, right_unit)
|
|
||||||
elif op == ast.Mult:
|
|
||||||
unit = units.mul_dimension(left_unit, right_unit)
|
|
||||||
elif op in (ast.Div, ast.FloorDiv):
|
|
||||||
unit = units.div_dimension(left_unit, right_unit)
|
|
||||||
else:
|
|
||||||
if left_unit is not None or right_unit is not None:
|
|
||||||
raise units.DimensionError
|
|
||||||
unit = None
|
|
||||||
if unit is not None:
|
|
||||||
node.unit = unit
|
|
||||||
return node
|
|
||||||
|
|
||||||
def visit_Attribute(self, node):
|
|
||||||
self.generic_visit(node)
|
|
||||||
if node.attr == "amount" and hasattr(node.value, "unit"):
|
|
||||||
del node.value.unit
|
|
||||||
return node.value
|
|
||||||
else:
|
|
||||||
return node
|
|
||||||
|
|
||||||
def visit_List(self, node):
|
|
||||||
self.generic_visit(node)
|
|
||||||
if node.elts:
|
|
||||||
us = [getattr(elt, "unit", None) for elt in node.elts]
|
|
||||||
if not all(u == us[0] for u in us[1:]):
|
|
||||||
raise units.DimensionError
|
|
||||||
node.unit = us[0]
|
|
||||||
return node
|
|
||||||
|
|
||||||
def visit_ListComp(self, node):
|
|
||||||
self.generic_visit(node)
|
|
||||||
if hasattr(node.elt, "unit"):
|
|
||||||
node.unit = node.elt.unit
|
|
||||||
return node
|
|
||||||
|
|
||||||
def visit_Call(self, node):
|
|
||||||
self.generic_visit(node)
|
|
||||||
if node.func.id == "Quantity":
|
|
||||||
amount, unit = node.args
|
|
||||||
amount.unit = unit.s
|
|
||||||
return amount
|
|
||||||
elif node.func.id in ("now", "cycles_to_time"):
|
|
||||||
node.unit = "s"
|
|
||||||
elif node.func.id == "syscall":
|
|
||||||
# only RPCs can have units
|
|
||||||
if node.args[0].s == "rpc":
|
|
||||||
unit_list = tuple(getattr(arg, "unit", None)
|
|
||||||
for arg in node.args[2:])
|
|
||||||
rpc_n = node.args[1].n
|
|
||||||
node.args[1].n = self.rpc_remap[(rpc_n, (unit_list))]
|
|
||||||
else:
|
|
||||||
if any(hasattr(arg, "unit") for arg in node.args):
|
|
||||||
raise units.DimensionError
|
|
||||||
elif node.func.id in ("delay", "at", "time_to_cycles", "watchdog"):
|
|
||||||
if getattr(node.args[0], "unit", None) != "s":
|
|
||||||
raise units.DimensionError
|
|
||||||
elif node.func.id == "check_unit":
|
|
||||||
self.generic_visit(node)
|
|
||||||
elif node.func.id in embeddable_func_names:
|
|
||||||
# must be last (some embeddable funcs may have units)
|
|
||||||
if any(hasattr(arg, "unit") for arg in node.args):
|
|
||||||
raise units.DimensionError
|
|
||||||
return node
|
|
||||||
|
|
||||||
def visit_Expr(self, node):
|
|
||||||
self.generic_visit(node)
|
|
||||||
if (isinstance(node.value, ast.Call)
|
|
||||||
and node.value.func.id == "check_unit"):
|
|
||||||
call = node.value
|
|
||||||
if (isinstance(call.args[1], ast.NameConstant)
|
|
||||||
and call.args[1].value is None):
|
|
||||||
if hasattr(call.value.args[0], "unit"):
|
|
||||||
raise units.DimensionError
|
|
||||||
elif isinstance(call.args[1], ast.Str):
|
|
||||||
if getattr(call.args[0], "unit", None) != call.args[1].s:
|
|
||||||
raise units.DimensionError
|
|
||||||
else:
|
|
||||||
raise NotImplementedError
|
|
||||||
return None
|
|
||||||
else:
|
|
||||||
return node
|
|
||||||
|
|
||||||
def _update_target(self, target, unit):
|
|
||||||
if isinstance(target, ast.Name):
|
|
||||||
if target.id in self.variable_units:
|
|
||||||
if self.variable_units[target.id] != unit:
|
|
||||||
raise TypeError(
|
|
||||||
"Inconsistent units for variable '{}': '{}' and '{}'"
|
|
||||||
.format(target.id,
|
|
||||||
self.variable_units[target.id],
|
|
||||||
unit))
|
|
||||||
else:
|
|
||||||
self.variable_units[target.id] = unit
|
|
||||||
|
|
||||||
def visit_Assign(self, node):
|
|
||||||
node.value = self.visit(node.value)
|
|
||||||
unit = getattr(node.value, "unit", None)
|
|
||||||
for target in node.targets:
|
|
||||||
self._update_target(target, unit)
|
|
||||||
return node
|
|
||||||
|
|
||||||
def visit_AugAssign(self, node):
|
|
||||||
value = self.visit_BinOp(ast.BinOp(
|
|
||||||
op=node.op, left=node.target, right=node.value))
|
|
||||||
unit = getattr(value, "unit", None)
|
|
||||||
self._update_target(node.target, unit)
|
|
||||||
return node
|
|
||||||
|
|
||||||
# Only dimensionless iterators are supported
|
|
||||||
def visit_For(self, node):
|
|
||||||
self.generic_visit(node)
|
|
||||||
self._update_target(node.target, None)
|
|
||||||
return node
|
|
||||||
|
|
||||||
|
|
||||||
def lower_units(func_def, rpc_map):
|
|
||||||
ul = _UnitsLowerer(rpc_map)
|
|
||||||
ul.visit(func_def)
|
|
||||||
original_map = copy(rpc_map)
|
|
||||||
for (original_rpcn, unit_list), new_rpcn in ul.rpc_remap.items():
|
|
||||||
rpc_map[new_rpcn] = _add_units(original_map[original_rpcn], unit_list)
|
|
|
@ -11,7 +11,7 @@ embeddable_funcs = (
|
||||||
core_language.syscall, core_language.watchdog,
|
core_language.syscall, core_language.watchdog,
|
||||||
range, bool, int, float, round, len,
|
range, bool, int, float, round, len,
|
||||||
core_language.int64, core_language.round64,
|
core_language.int64, core_language.round64,
|
||||||
Fraction, units.Quantity, units.check_unit, core_language.EncodedException
|
Fraction, core_language.EncodedException
|
||||||
)
|
)
|
||||||
embeddable_func_names = {func.__name__ for func in embeddable_funcs}
|
embeddable_func_names = {func.__name__ for func in embeddable_funcs}
|
||||||
|
|
||||||
|
@ -61,11 +61,6 @@ def value_to_ast(value):
|
||||||
for kg in core_language.kernel_globals:
|
for kg in core_language.kernel_globals:
|
||||||
if value is getattr(core_language, kg):
|
if value is getattr(core_language, kg):
|
||||||
return ast.Name(kg, ast.Load())
|
return ast.Name(kg, ast.Load())
|
||||||
if isinstance(value, units.Quantity):
|
|
||||||
return ast.Call(
|
|
||||||
func=ast.Name("Quantity", ast.Load()),
|
|
||||||
args=[value_to_ast(value.amount), ast.Str(value.unit)],
|
|
||||||
keywords=[], starargs=None, kwargs=None)
|
|
||||||
raise NotASTRepresentable(str(value))
|
raise NotASTRepresentable(str(value))
|
||||||
|
|
||||||
|
|
||||||
|
@ -88,14 +83,6 @@ def eval_constant(node):
|
||||||
numerator = eval_constant(node.args[0])
|
numerator = eval_constant(node.args[0])
|
||||||
denominator = eval_constant(node.args[1])
|
denominator = eval_constant(node.args[1])
|
||||||
return Fraction(numerator, denominator)
|
return Fraction(numerator, denominator)
|
||||||
elif funcname == "Quantity":
|
|
||||||
amount, unit = node.args
|
|
||||||
amount = eval_constant(amount)
|
|
||||||
try:
|
|
||||||
unit = getattr(units, unit.id)
|
|
||||||
except:
|
|
||||||
raise NotConstant
|
|
||||||
return units.Quantity(amount, unit)
|
|
||||||
else:
|
else:
|
||||||
raise NotConstant
|
raise NotConstant
|
||||||
else:
|
else:
|
||||||
|
@ -105,8 +92,7 @@ def eval_constant(node):
|
||||||
_replaceable_funcs = {
|
_replaceable_funcs = {
|
||||||
"bool", "int", "float", "round",
|
"bool", "int", "float", "round",
|
||||||
"int64", "round64", "Fraction",
|
"int64", "round64", "Fraction",
|
||||||
"time_to_cycles", "cycles_to_time",
|
"time_to_cycles", "cycles_to_time"
|
||||||
"Quantity"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@ class RPCTiming(Experiment, AutoDB):
|
||||||
t1 = self.core.get_rtio_time()
|
t1 = self.core.get_rtio_time()
|
||||||
self.nop(10)
|
self.nop(10)
|
||||||
t2 = self.core.get_rtio_time()
|
t2 = self.core.get_rtio_time()
|
||||||
self.ts[i] = float(t2.amount - t1.amount)
|
self.ts[i] = t2 - t1
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
self.bench()
|
self.bench()
|
||||||
|
|
|
@ -60,22 +60,19 @@
|
||||||
"type": "local",
|
"type": "local",
|
||||||
"module": "artiq.coredevice.dds",
|
"module": "artiq.coredevice.dds",
|
||||||
"class": "DDS",
|
"class": "DDS",
|
||||||
"arguments": {"sysclk": Quantity(Fraction(1000000000, 1), "Hz"),
|
"arguments": {"sysclk": 1e9, "channel": 0}
|
||||||
"channel": 0}
|
|
||||||
},
|
},
|
||||||
"dds1": {
|
"dds1": {
|
||||||
"type": "local",
|
"type": "local",
|
||||||
"module": "artiq.coredevice.dds",
|
"module": "artiq.coredevice.dds",
|
||||||
"class": "DDS",
|
"class": "DDS",
|
||||||
"arguments": {"sysclk": Quantity(Fraction(1000000000, 1), "Hz"),
|
"arguments": {"sysclk": 1e9, "channel": 1}
|
||||||
"channel": 1}
|
|
||||||
},
|
},
|
||||||
"dds2": {
|
"dds2": {
|
||||||
"type": "local",
|
"type": "local",
|
||||||
"module": "artiq.coredevice.dds",
|
"module": "artiq.coredevice.dds",
|
||||||
"class": "DDS",
|
"class": "DDS",
|
||||||
"arguments": {"sysclk": Quantity(Fraction(1000000000, 1), "Hz"),
|
"arguments": {"sysclk": 1e9, "channel": 2}
|
||||||
"channel": 2}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
"qc_q1_0": {
|
"qc_q1_0": {
|
||||||
|
|
Loading…
Reference in New Issue