From 65b4b7bb12d4d3bf7985ee3d0081a816fefd5164 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Sat, 2 May 2015 10:35:21 +0800 Subject: [PATCH] coredevice: rename rtio to ttl, integrated in+out driver, loopback on the same pin in tests --- artiq/coredevice/dds.py | 8 +- artiq/coredevice/runtime.py | 2 +- artiq/coredevice/{rtio.py => ttl.py} | 133 ++++++++++++++++---------- artiq/devices/pdq2/mediator.py | 10 +- artiq/test/full_stack.py | 20 ++-- benchmarks/ddb.pyon | 26 +---- benchmarks/rtio_skew.py | 5 +- doc/manual/core_drivers_reference.rst | 4 +- examples/master/ddb.pyon | 24 ++--- 9 files changed, 121 insertions(+), 111 deletions(-) rename artiq/coredevice/{rtio.py => ttl.py} (58%) diff --git a/artiq/coredevice/dds.py b/artiq/coredevice/dds.py index c0ab079e7..f9af72eb4 100644 --- a/artiq/coredevice/dds.py +++ b/artiq/coredevice/dds.py @@ -1,7 +1,7 @@ from artiq.language.core import * from artiq.language.db import * from artiq.language.units import * -from artiq.coredevice import rtio +from artiq.coredevice import ttl PHASE_MODE_DEFAULT = -1 @@ -14,7 +14,7 @@ class DDS(AutoDB): """Core device Direct Digital Synthesis (DDS) driver. 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. :param dds_sysclk: DDS system frequency, used for computing the frequency @@ -34,7 +34,7 @@ class DDS(AutoDB): self.previous_on = False self.previous_frequency = 0*MHz 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 def frequency_to_ftw(self, frequency): @@ -93,7 +93,7 @@ class DDS(AutoDB): self.set_phase_mode(phase_mode) 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: self.sw.sync() # Channel is already on: diff --git a/artiq/coredevice/runtime.py b/artiq/coredevice/runtime.py index 1136d41eb..ff5e77e56 100644 --- a/artiq/coredevice/runtime.py +++ b/artiq/coredevice/runtime.py @@ -14,7 +14,7 @@ llvm.initialize_all_asmprinters() _syscalls = { "watchdog_set": "i:i", "watchdog_clear": "i:n", - "rtio_set_o": "Iii:n", + "rtio_set_o": "Iib:n", "rtio_set_oe": "Iib:n", "rtio_set_sensitivity": "Iii:n", "rtio_get_counter": "n:I", diff --git a/artiq/coredevice/rtio.py b/artiq/coredevice/ttl.py similarity index 58% rename from artiq/coredevice/rtio.py rename to artiq/coredevice/ttl.py index 8424a524c..05932979f 100644 --- a/artiq/coredevice/rtio.py +++ b/artiq/coredevice/ttl.py @@ -2,26 +2,21 @@ from artiq.language.core import * from artiq.language.db import * -class LLRTIOOut(AutoDB): - """Low-level RTIO output driver. +class LLTTLOut(AutoDB): + """Low-level RTIO TTL output driver. - Allows setting RTIO outputs at arbitrary times, without time unit - conversion. + Allows setting RTIO TTL outputs at arbitrary times, without time + unit conversion. 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: core = Device() 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 def set_o(self, t, value): """Sets the output value of the RTIO channel. @@ -37,7 +32,7 @@ class LLRTIOOut(AutoDB): :param t: timestamp in RTIO cycles (64-bit integer). """ - self.set_o(t, 1) + self.set_o(t, True) @kernel def off(self, t): @@ -45,19 +40,13 @@ class LLRTIOOut(AutoDB): :param t: timestamp in RTIO cycles (64-bit integer). """ - self.set_o(t, 0) + self.set_o(t, False) -class RTIOOut(AutoDB): - """RTIO output driver. +class TTLOut(AutoDB): + """RTIO TTL output driver. - Configures the corresponding RTIO channel as output on the core device and - 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. + This should be used with output-only channels. :param core: core device :param channel: channel number @@ -66,39 +55,31 @@ class RTIOOut(AutoDB): core = Device() channel = Argument() + def build(self): - self.previous_timestamp = int64(0) # in RTIO cycles - self._set_oe() + # in RTIO cycles + self.o_previous_timestamp = int64(0) @kernel - def _set_oe(self): - syscall("rtio_set_oe", time_to_cycles(now()), self.channel, True) - - @kernel - def _set_o(self, value): - syscall("rtio_set_o", time_to_cycles(now()), self.channel, value) - self.previous_timestamp = time_to_cycles(now()) + 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. - - 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: + """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(1) + self._set_o(True) @kernel def off(self): """Sets the output to a logic low state.""" - self._set_o(0) + self._set_o(False) @kernel def pulse(self, duration): @@ -108,12 +89,20 @@ class RTIOOut(AutoDB): self.off() -class RTIOIn(AutoDB): - """RTIO input driver. +class TTLInOut(AutoDB): + """RTIO TTL input/output driver. - Configures the corresponding RTIO channel as input on the core device and - provides functions to analyze the incoming signal, with real-time gating - to prevent overflows. + In output mode, provides functions to set the logic level on the signal. + + 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 channel: channel number @@ -123,17 +112,54 @@ class RTIOIn(AutoDB): channel = Argument() def build(self): - self.previous_timestamp = int64(0) # in RTIO cycles - self._set_oe() + # in RTIO cycles + self.o_previous_timestamp = int64(0) + self.i_previous_timestamp = int64(0) @kernel - def _set_oe(self): - syscall("rtio_set_oe", time_to_cycles(now()), self.channel, False) + def _set_oe(self, oe): + 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 def _set_sensitivity(self, 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 def gate_rising(self, duration): @@ -162,7 +188,8 @@ class RTIOIn(AutoDB): """Poll the RTIO input during all the previously programmed gate openings, and returns the number of registered events.""" 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 return count @@ -174,4 +201,4 @@ class RTIOIn(AutoDB): If the gate is permanently closed, returns a negative value. """ return cycles_to_time(syscall("rtio_get", self.channel, - self.previous_timestamp)) + self.i_previous_timestamp)) diff --git a/artiq/devices/pdq2/mediator.py b/artiq/devices/pdq2/mediator.py index aa4640e77..63d3d7b72 100644 --- a/artiq/devices/pdq2/mediator.py +++ b/artiq/devices/pdq2/mediator.py @@ -1,7 +1,7 @@ from artiq.language.core import * from artiq.language.db import * from artiq.language.units import * -from artiq.coredevice import rtio +from artiq.coredevice import ttl frame_setup = 20*ns @@ -162,13 +162,13 @@ class CompoundPDQ2(AutoDB): def build(self): 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) - self.frame0 = rtio.LLRTIOOut( + self.frame0 = ttl.LLTTLOut( core=self.core, channel=self.rtio_frame[0]) - self.frame1 = rtio.LLRTIOOut( + self.frame1 = ttl.LLTTLOut( core=self.core, channel=self.rtio_frame[1]) - self.frame2 = rtio.LLRTIOOut( + self.frame2 = ttl.LLTTLOut( core=self.core, channel=self.rtio_frame[2]) self.frames = [] diff --git a/artiq/test/full_stack.py b/artiq/test/full_stack.py index ae273c62d..83b287483 100644 --- a/artiq/test/full_stack.py +++ b/artiq/test/full_stack.py @@ -5,7 +5,7 @@ from fractions import Fraction from artiq import * 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 @@ -281,8 +281,7 @@ class ExecutionCase(unittest.TestCase): class _RTIOLoopback(AutoDB): class DBKeys: core = Device() - i = Device() - o = Device() + io = Device() npulses = Argument() def report(self, n): @@ -290,13 +289,15 @@ class _RTIOLoopback(AutoDB): @kernel def run(self): + self.io.output() + delay(1*us) with parallel: + self.io.gate_rising(10*us) with sequential: for i in range(self.npulses): delay(25*ns) - self.o.pulse(25*ns) - self.i.gate_rising(10*us) - self.report(self.i.count()) + self.io.pulse(25*ns) + self.report(self.io.count()) class _RTIOUnderflow(AutoDB): @@ -335,8 +336,7 @@ class RTIOCase(unittest.TestCase): coredev = core.Core(comm=comm) uut = _RTIOLoopback( core=coredev, - i=rtio.RTIOIn(core=coredev, channel=0), - o=rtio.RTIOOut(core=coredev, channel=2), + io=ttl.TTLInOut(core=coredev, channel=0), npulses=npulses ) uut.run() @@ -350,7 +350,7 @@ class RTIOCase(unittest.TestCase): coredev = core.Core(comm=comm) uut = _RTIOUnderflow( core=coredev, - o=rtio.RTIOOut(core=coredev, channel=2) + o=ttl.TTLOut(core=coredev, channel=2) ) with self.assertRaises(runtime_exceptions.RTIOUnderflow): uut.run() @@ -363,7 +363,7 @@ class RTIOCase(unittest.TestCase): coredev = core.Core(comm=comm) uut = _RTIOSequenceError( core=coredev, - o=rtio.RTIOOut(core=coredev, channel=2) + o=ttl.TTLOut(core=coredev, channel=2) ) with self.assertRaises(runtime_exceptions.RTIOSequenceError): uut.run() diff --git a/benchmarks/ddb.pyon b/benchmarks/ddb.pyon index 813c9645d..8dd20362c 100644 --- a/benchmarks/ddb.pyon +++ b/benchmarks/ddb.pyon @@ -14,33 +14,15 @@ "pmt0": { "type": "local", - "module": "artiq.coredevice.rtio", - "class": "RTIOIn", + "module": "artiq.coredevice.ttl", + "class": "TTLInOut", "arguments": {"channel": 0} }, - "pmt1": { - "type": "local", - "module": "artiq.coredevice.rtio", - "class": "RTIOIn", - "arguments": {"channel": 1} - }, "ttl0": { "type": "local", - "module": "artiq.coredevice.rtio", - "class": "RTIOOut", + "module": "artiq.coredevice.ttl", + "class": "TTLOut", "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} - }, } diff --git a/benchmarks/rtio_skew.py b/benchmarks/rtio_skew.py index 04bd6c4e0..a5770864b 100644 --- a/benchmarks/rtio_skew.py +++ b/benchmarks/rtio_skew.py @@ -11,17 +11,18 @@ class RTIOSkew(Experiment, AutoDB): class DBKeys: core = Device() pmt0 = Device() - ttl0 = Device() rtio_skew = Result() @kernel def run(self): + self.pmt0.output() + delay(1*us) with parallel: self.pmt0.gate_rising(10*us) with sequential: delay(5*us) out_t = now() - self.ttl0.pulse(5*us) + self.pmt0.pulse(5*us) in_t = self.pmt0.timestamp() if in_t < 0*s: raise PulseNotReceived diff --git a/doc/manual/core_drivers_reference.rst b/doc/manual/core_drivers_reference.rst index 684c53185..0c9c38301 100644 --- a/doc/manual/core_drivers_reference.rst +++ b/doc/manual/core_drivers_reference.rst @@ -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. -:mod:`artiq.coredevice.rtio` module +:mod:`artiq.coredevice.ttl` module ----------------------------------- -.. automodule:: artiq.coredevice.rtio +.. automodule:: artiq.coredevice.ttl :members: :mod:`artiq.coredevice.dds` module diff --git a/examples/master/ddb.pyon b/examples/master/ddb.pyon index 8ca5e5764..a33fc8bec 100644 --- a/examples/master/ddb.pyon +++ b/examples/master/ddb.pyon @@ -14,39 +14,39 @@ "pmt0": { "type": "local", - "module": "artiq.coredevice.rtio", - "class": "RTIOIn", + "module": "artiq.coredevice.ttl", + "class": "TTLInOut", "arguments": {"channel": 0} }, "pmt1": { "type": "local", - "module": "artiq.coredevice.rtio", - "class": "RTIOIn", + "module": "artiq.coredevice.ttl", + "class": "TTLInOut", "arguments": {"channel": 1} }, "ttl0": { "type": "local", - "module": "artiq.coredevice.rtio", - "class": "RTIOOut", + "module": "artiq.coredevice.ttl", + "class": "TTLOut", "arguments": {"channel": 2} }, "ttl1": { "type": "local", - "module": "artiq.coredevice.rtio", - "class": "RTIOOut", + "module": "artiq.coredevice.ttl", + "class": "TTLOut", "arguments": {"channel": 3} }, "ttl2": { "type": "local", - "module": "artiq.coredevice.rtio", - "class": "RTIOOut", + "module": "artiq.coredevice.ttl", + "class": "TTLOut", "arguments": {"channel": 4} }, "led": { "type": "local", - "module": "artiq.coredevice.rtio", - "class": "RTIOOut", + "module": "artiq.coredevice.ttl", + "class": "TTLOut", "arguments": {"channel": 18} },