Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: m-labs/artiq
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 649fedd6568b
Choose a base ref
...
head repository: m-labs/artiq
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 2a843ea436c4
Choose a head ref
  • 3 commits
  • 20 files changed
  • 1 contributor

Commits on Dec 2, 2014

  1. Copy the full SHA
    cad5933 View commit details
  2. Copy the full SHA
    83d3b97 View commit details
  3. language: replace AutoContext 'parameter' string with abstract attrib…

    …utes
    
    This allows specifying default values for parameters, and other data.
    sbourdeauducq committed Dec 2, 2014
    Copy the full SHA
    2a843ea View commit details
1 change: 1 addition & 0 deletions artiq/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from artiq.language.core import *
from artiq.language.context import *
from artiq.language.units import ps, ns, us, ms, s
from artiq.language.units import Hz, kHz, MHz, GHz
12 changes: 8 additions & 4 deletions artiq/coredevice/comm_serial.py
Original file line number Diff line number Diff line change
@@ -88,16 +88,20 @@ def set_remote_baud(self, baud):
_write_exactly(self.port, struct.pack(
">lbl", 0x5a5a5a5a, _H2DMsgType.SET_BAUD_RATE.value, baud))
handshake = 0
fails = 0
while handshake < 4:
recv = struct.unpack(
"B", _read_exactly(self.port, 1))
if recv[0] == 0x5a:
(recv, ) = struct.unpack("B", _read_exactly(self.port, 1))
if recv == 0x5a:
handshake += 1
else:
# FIXME: when loading immediately after a board reset,
# we erroneously get some zeros back.
logger.warning("unexpected sync character: {:02x}".format(int(recv[0])))
logger.warning("unexpected sync character: {:02x}".format(int(recv)))
handshake = 0
if recv != 0:
fails += 1
if fails > 3:
raise IOError("Baudrate ack failed")
self.set_baud(baud)
logger.debug("synchronized")

5 changes: 4 additions & 1 deletion artiq/coredevice/dds.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from artiq.language.core import *
from artiq.language.context import *
from artiq.language.units import *
from artiq.coredevice import rtio

@@ -23,7 +24,9 @@ class DDS(AutoContext):
the DDS device.
"""
parameters = "dds_sysclk reg_channel rtio_switch"
dds_sysclk = Parameter()
reg_channel = Parameter()
rtio_switch = Parameter()

def build(self):
self.previous_on = False
3 changes: 2 additions & 1 deletion artiq/coredevice/gpio.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
from artiq.language.core import *
from artiq.language.context import *


class GPIOOut(AutoContext):
parameters = "channel"
channel = Parameter()

@kernel
def on(self):
5 changes: 3 additions & 2 deletions artiq/coredevice/rtio.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from artiq.language.core import *
from artiq.language.context import *


class LLRTIOOut(AutoContext):
@@ -11,7 +12,7 @@ class LLRTIOOut(AutoContext):
``RTIOOut`` instead.
"""
parameters = "channel"
channel = Parameter()

def build(self):
self._set_oe()
@@ -50,7 +51,7 @@ def off(self, t):


class _RTIOBase(AutoContext):
parameters = "channel"
channel = Parameter()

def build(self):
self.previous_timestamp = int64(0) # in RTIO cycles
5 changes: 4 additions & 1 deletion artiq/devices/pdq2/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from artiq.language.core import *
from artiq.language.context import *
from artiq.language.units import *
from artiq.coredevice import rtio

@@ -111,7 +112,9 @@ def _invalidate(self):


class CompoundPDQ2(AutoContext):
parameters = "ids rtio_trigger rtio_frame"
ids = Parameter()
rtio_trigger = Parameter()
rtio_frame = Parameter()

def build(self):
self.trigger = rtio.LLRTIOOut(self, channel=self.rtio_trigger)
138 changes: 138 additions & 0 deletions artiq/language/context.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
"""
Device and parameter attributes.
"""

class _AttributeKind:
pass


class Device(_AttributeKind):
"""Represents a device for ``AutoContext`` to process.
:param type_hint: An optional string giving a hint about the type of the
device.
"""
def __init__(self, type_hint=None):
self.type_hint = type_hint


class NoDefault:
"""Represents the absence of a default value for ``Parameter``.
"""
pass


class Parameter(_AttributeKind):
"""Represents a parameter for ``AutoContext`` to process.
:param default: Default value of the parameter to be used if not found
in database.
"""
def __init__(self, default=NoDefault):
self.default = default


class AutoContext:
"""Base class to automate device and parameter discovery.
Drivers and experiments should in most cases overload this class to
obtain the parameters and devices (including the core device) that they
need.
This class sets all its ``__init__`` keyword arguments as attributes. It
then iterates over each element in the attribute dictionary of the class,
and when they are abtract attributes (e.g. ``Device``, ``Parameter``),
requests them from the ``mvs`` (Missing Value Supplier) object.
A ``AutoContext`` instance can be used as MVS. If the requested parameter
is within its attributes, the value of that attribute is returned.
Otherwise, the request is forwarded to the parent MVS.
All keyword arguments are set as object attributes. This enables setting
parameters of a lower-level ``AutoContext`` object using keyword arguments
without having those explicitly listed in the upper-level ``AutoContext``
parameter list.
At the top-level, it is possible to have a MVS that issues requests to a
database and hardware management system.
:var implicit_core: Automatically adds a ``core`` device to the attributes.
Default: True.
Example:
>>> class SubExperiment(AutoContext):
... foo = Parameter()
... bar = Parameter()
...
... def run(self):
... do_something(self.foo, self.bar)
...
>>> class MainExperiment(AutoContext):
... bar1 = Parameter()
... bar2 = Parameter()
... offset = Parameter()
...
... def build(self):
... self.exp1 = SubExperiment(self, bar=self.bar1)
... self.exp2 = SubExperiment(self, bar=self.bar2)
... self.exp3 = SubExperiment(self, bar=self.bar2 + self.offset)
...
... def run(self):
... self.exp1.run()
... self.exp2.run()
... self.exp3.run()
...
>>> # does not require a database.
>>> a = MainExperiment(foo=1, bar1=2, bar2=3, offset=0)
>>> # "foo" and "offset" are automatically retrieved from the database.
>>> b = MainExperiment(db_mvs, bar1=2, bar2=3)
"""
implicit_core = True

def __init__(self, mvs=None, **kwargs):
if self.implicit_core:
if hasattr(self, "core"):
raise ValueError(
"Set implicit_core to False when"
" core is explicitly specified")
self.core = Device("core")

self.mvs = mvs
for k, v in kwargs.items():
setattr(self, k, v)

for k in dir(self):
v = getattr(self, k)
if isinstance(v, _AttributeKind):
value = self.mvs.get_missing_value(k, v)
setattr(self, k, value)

self.build()

def get_missing_value(self, name, kind):
"""Attempts to retrieve ``parameter`` from the object's attributes.
If not present, forwards the request to the parent MVS.
The presence of this method makes ``AutoContext`` act as a MVS.
"""
try:
return getattr(self, name)
except AttributeError:
return self.mvs.get_missing_value(name, kind)

def build(self):
"""This is called by ``__init__`` after the parameter initialization
is done.
The user may overload this method to complete the object's
initialization with all parameters available.
"""
pass
99 changes: 0 additions & 99 deletions artiq/language/core.py
Original file line number Diff line number Diff line change
@@ -86,105 +86,6 @@ def array(element, count):
return [_copy(element) for i in range(count)]


class AutoContext:
"""Base class to automate device and parameter discovery.
Drivers and experiments should in most cases overload this class to
obtain the parameters and devices (including the core device) that they
need.
This class sets all its ``__init__`` keyword arguments as attributes. It
then iterates over each element in its ``parameters`` attribute and, if
they are not already existing, requests them from ``mvs`` (Missing Value
Supplier).
A ``AutoContext`` instance can be used as MVS. If the requested parameter
is within its attributes, the value of that attribute is returned.
Otherwise, the request is forwarded to the parent MVS.
All keyword arguments are set as object attributes. This enables setting
parameters of a lower-level ``AutoContext`` object using keyword arguments
without having those explicitly listed in the upper-level ``AutoContext``
parameter list.
At the top-level, it is possible to have a MVS that issues requests to a
database and hardware management system.
:var parameters: A string containing the parameters that the object must
have. It must be a space-separated list of valid Python identifiers.
Default: empty.
:var implicit_core: Automatically adds ``core`` to the parameter list.
Default: True.
Example:
>>> class SubExperiment(AutoContext):
... parameters = "foo bar"
...
... def run():
... do_something(self.foo, self.bar)
...
>>> class MainExperiment(AutoContext):
... parameters = "bar1 bar2 offset"
...
... def build(self):
... self.exp1 = SubExperiment(self, bar=self.bar1)
... self.exp2 = SubExperiment(self, bar=self.bar2)
... self.exp3 = SubExperiment(self, bar=self.bar2 + self.offset)
...
... def run():
... self.exp1.run()
... self.exp2.run()
... self.exp3.run()
...
>>> # does not require a database.
>>> a = MainExperiment(foo=1, bar1=2, bar2=3, offset=0)
>>> # "foo" and "offset" are automatically retrieved from the database.
>>> b = MainExperiment(db_mvs, bar1=2, bar2=3)
"""
parameters = ""
implicit_core = True

def __init__(self, mvs=None, **kwargs):
self.mvs = mvs
for k, v in kwargs.items():
setattr(self, k, v)

parameters = self.parameters.split()
if self.implicit_core:
parameters.append("core")
for parameter in parameters:
try:
value = getattr(self, parameter)
except AttributeError:
value = self.mvs.get_missing_value(parameter)
setattr(self, parameter, value)

self.build()

def get_missing_value(self, parameter):
"""Attempts to retrieve ``parameter`` from the object's attributes.
If not present, forwards the request to the parent MVS.
The presence of this method makes ``AutoContext`` act as a MVS.
"""
try:
return getattr(self, parameter)
except AttributeError:
return self.mvs.get_missing_value(parameter)

def build(self):
"""This is called by ``__init__`` after the parameter initialization
is done.
The user may overload this method to complete the object's
initialization with all parameters available.
"""
pass


_KernelFunctionInfo = _namedtuple("_KernelFunctionInfo", "core_name k_function")


9 changes: 5 additions & 4 deletions artiq/sim/devices.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from random import Random

from artiq.language.core import AutoContext, delay
from artiq.language.core import delay
from artiq.language.context import AutoContext, Parameter
from artiq.language import units
from artiq.sim import time

@@ -11,7 +12,7 @@ def run(self, k_function, k_args, k_kwargs):


class Input(AutoContext):
parameters = "name"
name = Parameter()
implicit_core = False

def build(self):
@@ -30,7 +31,7 @@ def count_gate(self, duration):


class WaveOutput(AutoContext):
parameters = "name"
name = Parameter()
implicit_core = False

def pulse(self, frequency, duration):
@@ -39,7 +40,7 @@ def pulse(self, frequency, duration):


class VoltageOutput(AutoContext):
parameters = "name"
name = Parameter()
implicit_core = False

def set(self, value):
3 changes: 2 additions & 1 deletion artiq/transforms/inline.py
Original file line number Diff line number Diff line change
@@ -453,7 +453,8 @@ def get_attr_writeback(attribute_namespace, rpc_mapper, loc_node):
if hasattr(attr_info.obj, attr):
val = getattr(attr_info.obj, attr)
if (not isinstance(val, int)
or isinstance(val, core_language.int64)):
or isinstance(val, core_language.int64)
or isinstance(val, bool)):
continue
#

Loading