coredevice: rename rtio to ttl, integrated in+out driver, loopback on the same pin in tests

This commit is contained in:
Sebastien Bourdeauducq 2015-05-02 10:35:21 +08:00
parent 62669f9ff2
commit 65b4b7bb12
9 changed files with 121 additions and 111 deletions

View File

@ -1,7 +1,7 @@
from artiq.language.core import * from artiq.language.core import *
from artiq.language.db import * from artiq.language.db import *
from artiq.language.units import * from artiq.language.units import *
from artiq.coredevice import rtio from artiq.coredevice import ttl
PHASE_MODE_DEFAULT = -1 PHASE_MODE_DEFAULT = -1
@ -14,7 +14,7 @@ class DDS(AutoDB):
"""Core device Direct Digital Synthesis (DDS) driver. """Core device Direct Digital Synthesis (DDS) driver.
Controls DDS devices managed directly by the core device's runtime. It also Controls DDS devices managed directly by the core device's runtime. It also
uses a RTIO channel (through :class:`artiq.coredevice.rtio.RTIOOut`) to uses a RTIO TTL channel (through :class:`artiq.coredevice.ttl.TTLOut`) to
control a RF switch that gates the output of the DDS device. control a RF switch that gates the output of the DDS device.
:param dds_sysclk: DDS system frequency, used for computing the frequency :param dds_sysclk: DDS system frequency, used for computing the frequency
@ -34,7 +34,7 @@ class DDS(AutoDB):
self.previous_on = False self.previous_on = False
self.previous_frequency = 0*MHz self.previous_frequency = 0*MHz
self.set_phase_mode(PHASE_MODE_CONTINUOUS) self.set_phase_mode(PHASE_MODE_CONTINUOUS)
self.sw = rtio.RTIOOut(core=self.core, channel=self.rtio_switch) self.sw = ttl.TTLOut(core=self.core, channel=self.rtio_switch)
@portable @portable
def frequency_to_ftw(self, frequency): def frequency_to_ftw(self, frequency):
@ -93,7 +93,7 @@ class DDS(AutoDB):
self.set_phase_mode(phase_mode) self.set_phase_mode(phase_mode)
if self.previous_frequency != frequency: if self.previous_frequency != frequency:
merge = self.sw.previous_timestamp == time_to_cycles(now()) merge = self.sw.o_previous_timestamp == time_to_cycles(now())
if not merge: if not merge:
self.sw.sync() self.sw.sync()
# Channel is already on: # Channel is already on:

View File

@ -14,7 +14,7 @@ llvm.initialize_all_asmprinters()
_syscalls = { _syscalls = {
"watchdog_set": "i:i", "watchdog_set": "i:i",
"watchdog_clear": "i:n", "watchdog_clear": "i:n",
"rtio_set_o": "Iii:n", "rtio_set_o": "Iib:n",
"rtio_set_oe": "Iib:n", "rtio_set_oe": "Iib:n",
"rtio_set_sensitivity": "Iii:n", "rtio_set_sensitivity": "Iii:n",
"rtio_get_counter": "n:I", "rtio_get_counter": "n:I",

View File

@ -2,26 +2,21 @@ from artiq.language.core import *
from artiq.language.db import * from artiq.language.db import *
class LLRTIOOut(AutoDB): class LLTTLOut(AutoDB):
"""Low-level RTIO output driver. """Low-level RTIO TTL output driver.
Allows setting RTIO outputs at arbitrary times, without time unit Allows setting RTIO TTL outputs at arbitrary times, without time
conversion. unit conversion.
This is meant to be used mostly in drivers; consider using This is meant to be used mostly in drivers; consider using
``RTIOOut`` instead. ``TTLOut`` instead.
This should be used with output-only channels.
""" """
class DBKeys: class DBKeys:
core = Device() core = Device()
channel = Argument() channel = Argument()
def build(self):
self._set_oe()
@kernel
def _set_oe(self):
syscall("rtio_set_oe", time_to_cycles(now()), self.channel, True)
@kernel @kernel
def set_o(self, t, value): def set_o(self, t, value):
"""Sets the output value of the RTIO channel. """Sets the output value of the RTIO channel.
@ -37,7 +32,7 @@ class LLRTIOOut(AutoDB):
:param t: timestamp in RTIO cycles (64-bit integer). :param t: timestamp in RTIO cycles (64-bit integer).
""" """
self.set_o(t, 1) self.set_o(t, True)
@kernel @kernel
def off(self, t): def off(self, t):
@ -45,19 +40,13 @@ class LLRTIOOut(AutoDB):
:param t: timestamp in RTIO cycles (64-bit integer). :param t: timestamp in RTIO cycles (64-bit integer).
""" """
self.set_o(t, 0) self.set_o(t, False)
class RTIOOut(AutoDB): class TTLOut(AutoDB):
"""RTIO output driver. """RTIO TTL output driver.
Configures the corresponding RTIO channel as output on the core device and This should be used with output-only channels.
provides functions to set its level.
This driver supports zero-length transition suppression. For example, if
two pulses are emitted back-to-back with no delay between them, they will
be merged into a single pulse with a duration equal to the sum of the
durations of the original pulses.
:param core: core device :param core: core device
:param channel: channel number :param channel: channel number
@ -66,39 +55,31 @@ class RTIOOut(AutoDB):
core = Device() core = Device()
channel = Argument() channel = Argument()
def build(self): def build(self):
self.previous_timestamp = int64(0) # in RTIO cycles # in RTIO cycles
self._set_oe() self.o_previous_timestamp = int64(0)
@kernel @kernel
def _set_oe(self): def _set_o(self, o):
syscall("rtio_set_oe", time_to_cycles(now()), self.channel, True) syscall("rtio_set_o", time_to_cycles(now()), self.channel, o)
self.o_previous_timestamp = time_to_cycles(now())
@kernel
def _set_o(self, value):
syscall("rtio_set_o", time_to_cycles(now()), self.channel, value)
self.previous_timestamp = time_to_cycles(now())
@kernel @kernel
def sync(self): def sync(self):
"""Busy-waits until all programmed level switches have been effected. """Busy-waits until all programmed level switches have been effected."""
while syscall("rtio_get_counter") < self.o_previous_timestamp:
This function is useful to synchronize CPU-controlled devices (such as
the AD9858 DDS bus) with related RTIO controls (such as RF switches at
the output of the DDS).
"""
while syscall("rtio_get_counter") < self.previous_timestamp:
pass pass
@kernel @kernel
def on(self): def on(self):
"""Sets the output to a logic high state.""" """Sets the output to a logic high state."""
self._set_o(1) self._set_o(True)
@kernel @kernel
def off(self): def off(self):
"""Sets the output to a logic low state.""" """Sets the output to a logic low state."""
self._set_o(0) self._set_o(False)
@kernel @kernel
def pulse(self, duration): def pulse(self, duration):
@ -108,12 +89,20 @@ class RTIOOut(AutoDB):
self.off() self.off()
class RTIOIn(AutoDB): class TTLInOut(AutoDB):
"""RTIO input driver. """RTIO TTL input/output driver.
Configures the corresponding RTIO channel as input on the core device and In output mode, provides functions to set the logic level on the signal.
provides functions to analyze the incoming signal, with real-time gating
to prevent overflows. In input mode, provides functions to analyze the incoming signal, with
real-time gating to prevent overflows.
RTIO TTLs supports zero-length transition suppression. For example, if
two pulses are emitted back-to-back with no delay between them, they will
be merged into a single pulse with a duration equal to the sum of the
durations of the original pulses.
This should be used with bidirectional channels.
:param core: core device :param core: core device
:param channel: channel number :param channel: channel number
@ -123,17 +112,54 @@ class RTIOIn(AutoDB):
channel = Argument() channel = Argument()
def build(self): def build(self):
self.previous_timestamp = int64(0) # in RTIO cycles # in RTIO cycles
self._set_oe() self.o_previous_timestamp = int64(0)
self.i_previous_timestamp = int64(0)
@kernel @kernel
def _set_oe(self): def _set_oe(self, oe):
syscall("rtio_set_oe", time_to_cycles(now()), self.channel, False) syscall("rtio_set_oe", time_to_cycles(now()), self.channel, oe)
@kernel
def output(self):
self._set_oe(True)
@kernel
def input(self):
self._set_oe(False)
@kernel
def _set_o(self, o):
syscall("rtio_set_o", time_to_cycles(now()), self.channel, o)
self.o_previous_timestamp = time_to_cycles(now())
@kernel
def sync(self):
"""Busy-waits until all programmed level switches have been effected."""
while syscall("rtio_get_counter") < self.o_previous_timestamp:
pass
@kernel
def on(self):
"""Sets the output to a logic high state."""
self._set_o(True)
@kernel
def off(self):
"""Sets the output to a logic low state."""
self._set_o(False)
@kernel
def pulse(self, duration):
"""Pulses the output high for the specified duration."""
self.on()
delay(duration)
self.off()
@kernel @kernel
def _set_sensitivity(self, value): def _set_sensitivity(self, value):
syscall("rtio_set_sensitivity", time_to_cycles(now()), self.channel, value) syscall("rtio_set_sensitivity", time_to_cycles(now()), self.channel, value)
self.previous_timestamp = time_to_cycles(now()) self.i_previous_timestamp = time_to_cycles(now())
@kernel @kernel
def gate_rising(self, duration): def gate_rising(self, duration):
@ -162,7 +188,8 @@ class RTIOIn(AutoDB):
"""Poll the RTIO input during all the previously programmed gate """Poll the RTIO input during all the previously programmed gate
openings, and returns the number of registered events.""" openings, and returns the number of registered events."""
count = 0 count = 0
while syscall("rtio_get", self.channel, self.previous_timestamp) >= 0: while syscall("rtio_get", self.channel,
self.i_previous_timestamp) >= 0:
count += 1 count += 1
return count return count
@ -174,4 +201,4 @@ class RTIOIn(AutoDB):
If the gate is permanently closed, returns a negative value. If the gate is permanently closed, returns a negative value.
""" """
return cycles_to_time(syscall("rtio_get", self.channel, return cycles_to_time(syscall("rtio_get", self.channel,
self.previous_timestamp)) self.i_previous_timestamp))

View File

@ -1,7 +1,7 @@
from artiq.language.core import * from artiq.language.core import *
from artiq.language.db import * from artiq.language.db import *
from artiq.language.units import * from artiq.language.units import *
from artiq.coredevice import rtio from artiq.coredevice import ttl
frame_setup = 20*ns frame_setup = 20*ns
@ -162,13 +162,13 @@ class CompoundPDQ2(AutoDB):
def build(self): def build(self):
self.pdq2s = [self.dbh.get_device(d) for d in self.pdq2_devices] self.pdq2s = [self.dbh.get_device(d) for d in self.pdq2_devices]
self.trigger = rtio.LLRTIOOut( self.trigger = ttl.LLTTLOut(
core=self.core, channel=self.rtio_trigger) core=self.core, channel=self.rtio_trigger)
self.frame0 = rtio.LLRTIOOut( self.frame0 = ttl.LLTTLOut(
core=self.core, channel=self.rtio_frame[0]) core=self.core, channel=self.rtio_frame[0])
self.frame1 = rtio.LLRTIOOut( self.frame1 = ttl.LLTTLOut(
core=self.core, channel=self.rtio_frame[1]) core=self.core, channel=self.rtio_frame[1])
self.frame2 = rtio.LLRTIOOut( self.frame2 = ttl.LLTTLOut(
core=self.core, channel=self.rtio_frame[2]) core=self.core, channel=self.rtio_frame[2])
self.frames = [] self.frames = []

View File

@ -5,7 +5,7 @@ from fractions import Fraction
from artiq import * from artiq import *
from artiq.language.units import DimensionError from artiq.language.units import DimensionError
from artiq.coredevice import comm_tcp, core, runtime_exceptions, rtio 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
@ -281,8 +281,7 @@ class ExecutionCase(unittest.TestCase):
class _RTIOLoopback(AutoDB): class _RTIOLoopback(AutoDB):
class DBKeys: class DBKeys:
core = Device() core = Device()
i = Device() io = Device()
o = Device()
npulses = Argument() npulses = Argument()
def report(self, n): def report(self, n):
@ -290,13 +289,15 @@ class _RTIOLoopback(AutoDB):
@kernel @kernel
def run(self): def run(self):
self.io.output()
delay(1*us)
with parallel: with parallel:
self.io.gate_rising(10*us)
with sequential: with sequential:
for i in range(self.npulses): for i in range(self.npulses):
delay(25*ns) delay(25*ns)
self.o.pulse(25*ns) self.io.pulse(25*ns)
self.i.gate_rising(10*us) self.report(self.io.count())
self.report(self.i.count())
class _RTIOUnderflow(AutoDB): class _RTIOUnderflow(AutoDB):
@ -335,8 +336,7 @@ class RTIOCase(unittest.TestCase):
coredev = core.Core(comm=comm) coredev = core.Core(comm=comm)
uut = _RTIOLoopback( uut = _RTIOLoopback(
core=coredev, core=coredev,
i=rtio.RTIOIn(core=coredev, channel=0), io=ttl.TTLInOut(core=coredev, channel=0),
o=rtio.RTIOOut(core=coredev, channel=2),
npulses=npulses npulses=npulses
) )
uut.run() uut.run()
@ -350,7 +350,7 @@ class RTIOCase(unittest.TestCase):
coredev = core.Core(comm=comm) coredev = core.Core(comm=comm)
uut = _RTIOUnderflow( uut = _RTIOUnderflow(
core=coredev, core=coredev,
o=rtio.RTIOOut(core=coredev, channel=2) o=ttl.TTLOut(core=coredev, channel=2)
) )
with self.assertRaises(runtime_exceptions.RTIOUnderflow): with self.assertRaises(runtime_exceptions.RTIOUnderflow):
uut.run() uut.run()
@ -363,7 +363,7 @@ class RTIOCase(unittest.TestCase):
coredev = core.Core(comm=comm) coredev = core.Core(comm=comm)
uut = _RTIOSequenceError( uut = _RTIOSequenceError(
core=coredev, core=coredev,
o=rtio.RTIOOut(core=coredev, channel=2) o=ttl.TTLOut(core=coredev, channel=2)
) )
with self.assertRaises(runtime_exceptions.RTIOSequenceError): with self.assertRaises(runtime_exceptions.RTIOSequenceError):
uut.run() uut.run()

View File

@ -14,33 +14,15 @@
"pmt0": { "pmt0": {
"type": "local", "type": "local",
"module": "artiq.coredevice.rtio", "module": "artiq.coredevice.ttl",
"class": "RTIOIn", "class": "TTLInOut",
"arguments": {"channel": 0} "arguments": {"channel": 0}
}, },
"pmt1": {
"type": "local",
"module": "artiq.coredevice.rtio",
"class": "RTIOIn",
"arguments": {"channel": 1}
},
"ttl0": { "ttl0": {
"type": "local", "type": "local",
"module": "artiq.coredevice.rtio", "module": "artiq.coredevice.ttl",
"class": "RTIOOut", "class": "TTLOut",
"arguments": {"channel": 2} "arguments": {"channel": 2}
}, },
"ttl1": {
"type": "local",
"module": "artiq.coredevice.rtio",
"class": "RTIOOut",
"arguments": {"channel": 3}
},
"ttl2": {
"type": "local",
"module": "artiq.coredevice.rtio",
"class": "RTIOOut",
"arguments": {"channel": 4}
},
} }

View File

@ -11,17 +11,18 @@ class RTIOSkew(Experiment, AutoDB):
class DBKeys: class DBKeys:
core = Device() core = Device()
pmt0 = Device() pmt0 = Device()
ttl0 = Device()
rtio_skew = Result() rtio_skew = Result()
@kernel @kernel
def run(self): def run(self):
self.pmt0.output()
delay(1*us)
with parallel: with parallel:
self.pmt0.gate_rising(10*us) self.pmt0.gate_rising(10*us)
with sequential: with sequential:
delay(5*us) delay(5*us)
out_t = now() out_t = now()
self.ttl0.pulse(5*us) self.pmt0.pulse(5*us)
in_t = self.pmt0.timestamp() in_t = self.pmt0.timestamp()
if in_t < 0*s: if in_t < 0*s:
raise PulseNotReceived raise PulseNotReceived

View File

@ -3,10 +3,10 @@ Core drivers reference
These drivers are for peripherals closely integrated into the core device, which do not use the controller mechanism. These drivers are for peripherals closely integrated into the core device, which do not use the controller mechanism.
:mod:`artiq.coredevice.rtio` module :mod:`artiq.coredevice.ttl` module
----------------------------------- -----------------------------------
.. automodule:: artiq.coredevice.rtio .. automodule:: artiq.coredevice.ttl
:members: :members:
:mod:`artiq.coredevice.dds` module :mod:`artiq.coredevice.dds` module

View File

@ -14,39 +14,39 @@
"pmt0": { "pmt0": {
"type": "local", "type": "local",
"module": "artiq.coredevice.rtio", "module": "artiq.coredevice.ttl",
"class": "RTIOIn", "class": "TTLInOut",
"arguments": {"channel": 0} "arguments": {"channel": 0}
}, },
"pmt1": { "pmt1": {
"type": "local", "type": "local",
"module": "artiq.coredevice.rtio", "module": "artiq.coredevice.ttl",
"class": "RTIOIn", "class": "TTLInOut",
"arguments": {"channel": 1} "arguments": {"channel": 1}
}, },
"ttl0": { "ttl0": {
"type": "local", "type": "local",
"module": "artiq.coredevice.rtio", "module": "artiq.coredevice.ttl",
"class": "RTIOOut", "class": "TTLOut",
"arguments": {"channel": 2} "arguments": {"channel": 2}
}, },
"ttl1": { "ttl1": {
"type": "local", "type": "local",
"module": "artiq.coredevice.rtio", "module": "artiq.coredevice.ttl",
"class": "RTIOOut", "class": "TTLOut",
"arguments": {"channel": 3} "arguments": {"channel": 3}
}, },
"ttl2": { "ttl2": {
"type": "local", "type": "local",
"module": "artiq.coredevice.rtio", "module": "artiq.coredevice.ttl",
"class": "RTIOOut", "class": "TTLOut",
"arguments": {"channel": 4} "arguments": {"channel": 4}
}, },
"led": { "led": {
"type": "local", "type": "local",
"module": "artiq.coredevice.rtio", "module": "artiq.coredevice.ttl",
"class": "RTIOOut", "class": "TTLOut",
"arguments": {"channel": 18} "arguments": {"channel": 18}
}, },