From f39208c95af3593e31ca4114d236e64e5d1217fa Mon Sep 17 00:00:00 2001 From: Robert Jordens Date: Tue, 8 Mar 2016 22:10:47 +0100 Subject: [PATCH 1/5] pipistrello: try with fewer leds/pmod ttl --- artiq/gateware/targets/pipistrello.py | 7 +++---- doc/manual/core_device.rst | 16 ++++------------ 2 files changed, 7 insertions(+), 16 deletions(-) diff --git a/artiq/gateware/targets/pipistrello.py b/artiq/gateware/targets/pipistrello.py index d9dcb3bcc..e75d9804b 100755 --- a/artiq/gateware/targets/pipistrello.py +++ b/artiq/gateware/targets/pipistrello.py @@ -196,15 +196,14 @@ trce -v 12 -fastpaths -tsi {build_name}.tsi -o {build_name}.twr {build_name}.ncd self.submodules += phy rtio_channels.append(rtio.Channel.from_phy(phy, ofifo_depth=4)) - for led_number in range(4): + for led_number in range(2): phy = ttl_simple.Output(platform.request("user_led", led_number)) self.submodules += phy rtio_channels.append(rtio.Channel.from_phy(phy, ofifo_depth=4)) spi_pins = self.platform.request("pmod_extended_spi", 0) - for i, p in enumerate((spi_pins.int, spi_pins.rst, - spi_pins.d0, spi_pins.d1)): + for i, p in enumerate((spi_pins.int, spi_pins.rst)): phy = ttl_simple.Inout(p) self.submodules += phy rtio_channels.append(rtio.Channel.from_phy(phy, ififo_depth=4, @@ -220,7 +219,7 @@ trce -v 12 -fastpaths -tsi {build_name}.tsi -o {build_name}.twr {build_name}.ncd self.submodules += phy self.config["RTIO_FIRST_SPI_CHANNEL"] = len(rtio_channels) rtio_channels.append(rtio.Channel.from_phy( - phy, ofifo_depth=64, ififo_depth=64)) + phy, ofifo_depth=256, ififo_depth=256)) self.config["RTIO_DDS_CHANNEL"] = len(rtio_channels) self.config["DDS_CHANNEL_COUNT"] = 8 diff --git a/doc/manual/core_device.rst b/doc/manual/core_device.rst index 8a947dab6..fe3ef2640 100644 --- a/doc/manual/core_device.rst +++ b/doc/manual/core_device.rst @@ -128,19 +128,11 @@ When plugged to an adapter, the NIST QC1 hardware can be used. The TTL lines are +--------------+------------+--------------+ | 19 | USER_LED_2 | Output | +--------------+------------+--------------+ -| 20 | USER_LED_3 | Output | +| 20 | PMOD_4 | Input+Output | +--------------+------------+--------------+ -| 21 | USER_LED_4 | Output | +| 21 | PMOD_5 | Input+Output | +--------------+------------+--------------+ -| 22 | PMOD_4 | Input+Output | -+--------------+------------+--------------+ -| 23 | PMOD_5 | Input+Output | -+--------------+------------+--------------+ -| 24 | PMOD_6 | Input+Output | -+--------------+------------+--------------+ -| 25 | PMOD_7 | Input+Output | -+--------------+------------+--------------+ -| 26 | TTL15 | Clock | +| 22 | TTL15 | Clock | +--------------+------------+--------------+ The input only limitation on channels 0 and 1 comes from the QC-DAQ adapter. When the adapter is not used (and physically unplugged from the Pipistrello board), the corresponding pins on the Pipistrello can be used as outputs. Do not configure these channels as outputs when the adapter is plugged, as this would cause electrical contention. @@ -153,5 +145,5 @@ Interface Type 2 (SPI) and 2A (expanded SPI): +--------------+--------+--------+--------+--------+ | RTIO channel | CS_N | MOSI | MISO | CLK | +==============+========+========+========+========+ -| 27 | PMOD_0 | PMOD_1 | PMOD_2 | PMOD_3 | +| 23 | PMOD_0 | PMOD_1 | PMOD_2 | PMOD_3 | +--------------+--------+--------+--------+--------+ From f33baf339f4bfc891ca4e780580a81bfc5086b70 Mon Sep 17 00:00:00 2001 From: Robert Jordens Date: Tue, 8 Mar 2016 23:34:51 +0100 Subject: [PATCH 2/5] pipistrello: drop ttls on pmod, add leds back in --- artiq/gateware/targets/pipistrello.py | 8 +------- doc/manual/core_device.rst | 4 ++-- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/artiq/gateware/targets/pipistrello.py b/artiq/gateware/targets/pipistrello.py index e75d9804b..620810b60 100755 --- a/artiq/gateware/targets/pipistrello.py +++ b/artiq/gateware/targets/pipistrello.py @@ -196,19 +196,13 @@ trce -v 12 -fastpaths -tsi {build_name}.tsi -o {build_name}.twr {build_name}.ncd self.submodules += phy rtio_channels.append(rtio.Channel.from_phy(phy, ofifo_depth=4)) - for led_number in range(2): + for led_number in range(4): phy = ttl_simple.Output(platform.request("user_led", led_number)) self.submodules += phy rtio_channels.append(rtio.Channel.from_phy(phy, ofifo_depth=4)) spi_pins = self.platform.request("pmod_extended_spi", 0) - for i, p in enumerate((spi_pins.int, spi_pins.rst)): - phy = ttl_simple.Inout(p) - self.submodules += phy - rtio_channels.append(rtio.Channel.from_phy(phy, ififo_depth=4, - ofifo_depth=4)) - self.config["RTIO_REGULAR_TTL_COUNT"] = len(rtio_channels) phy = ttl_simple.ClockGen(platform.request("ttl", 15)) diff --git a/doc/manual/core_device.rst b/doc/manual/core_device.rst index fe3ef2640..484f69358 100644 --- a/doc/manual/core_device.rst +++ b/doc/manual/core_device.rst @@ -128,9 +128,9 @@ When plugged to an adapter, the NIST QC1 hardware can be used. The TTL lines are +--------------+------------+--------------+ | 19 | USER_LED_2 | Output | +--------------+------------+--------------+ -| 20 | PMOD_4 | Input+Output | +| 20 | USER_LED_3 | Output | +--------------+------------+--------------+ -| 21 | PMOD_5 | Input+Output | +| 21 | USER_LED_4 | Output | +--------------+------------+--------------+ | 22 | TTL15 | Clock | +--------------+------------+--------------+ From 80e1cf5d7823675da9de7156ccff3d7c0f32efc7 Mon Sep 17 00:00:00 2001 From: whitequark Date: Wed, 9 Mar 2016 02:34:22 +0000 Subject: [PATCH 3/5] Monkey-patch asyncio create_server (fixes #253). --- artiq/tools.py | 108 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) diff --git a/artiq/tools.py b/artiq/tools.py index ef666cabf..8d2424cdc 100644 --- a/artiq/tools.py +++ b/artiq/tools.py @@ -7,6 +7,8 @@ import asyncio import time import collections import os +import socket +import itertools import atexit import string @@ -243,3 +245,109 @@ def get_windows_drives(): drives.append(letter) bitmask >>= 1 return drives + +if sys.version_info[:3] == (3, 5, 1): + # See https://github.com/m-labs/artiq/issues/253 + @asyncio.coroutines.coroutine + def create_server(self, protocol_factory, host=None, port=None, + *, + family=socket.AF_UNSPEC, + flags=socket.AI_PASSIVE, + sock=None, + backlog=100, + ssl=None, + reuse_address=None, + reuse_port=None): + """Create a TCP server. + The host parameter can be a string, in that case the TCP server is bound + to host and port. + The host parameter can also be a sequence of strings and in that case + the TCP server is bound to all hosts of the sequence. If a host + appears multiple times (possibly indirectly e.g. when hostnames + resolve to the same IP address), the server is only bound once to that + host. + Return a Server object which can be used to stop the service. + This method is a coroutine. + """ + if isinstance(ssl, bool): + raise TypeError('ssl argument must be an SSLContext or None') + if host is not None or port is not None: + if sock is not None: + raise ValueError( + 'host/port and sock can not be specified at the same time') + + AF_INET6 = getattr(socket, 'AF_INET6', 0) + if reuse_address is None: + reuse_address = os.name == 'posix' and sys.platform != 'cygwin' + sockets = [] + if host == '': + hosts = [None] + elif (isinstance(host, str) or + not isinstance(host, collections.Iterable)): + hosts = [host] + else: + hosts = host + + fs = [self._create_server_getaddrinfo(host, port, family=family, + flags=flags) + for host in hosts] + infos = yield from asyncio.tasks.gather(*fs, loop=self) + infos = set(itertools.chain.from_iterable(infos)) + + completed = False + try: + for res in infos: + af, socktype, proto, canonname, sa = res + try: + sock = socket.socket(af, socktype, proto) + except socket.error: + # Assume it's a bad family/type/protocol combination. + if self._debug: + asyncio.log.logger.warning('create_server() failed to create ' + 'socket.socket(%r, %r, %r)', + af, socktype, proto, exc_info=True) + continue + sockets.append(sock) + if reuse_address: + sock.setsockopt( + socket.SOL_SOCKET, socket.SO_REUSEADDR, True) + if reuse_port: + if not hasattr(socket, 'SO_REUSEPORT'): + raise ValueError( + 'reuse_port not supported by socket module') + else: + sock.setsockopt( + socket.SOL_SOCKET, socket.SO_REUSEPORT, True) + # Disable IPv4/IPv6 dual stack support (enabled by + # default on Linux) which makes a single socket + # listen on both address families. + if af == AF_INET6 and hasattr(socket, 'IPPROTO_IPV6'): + sock.setsockopt(socket.IPPROTO_IPV6, + socket.IPV6_V6ONLY, + True) + try: + sock.bind(sa) + except OSError as err: + raise OSError(err.errno, 'error while attempting ' + 'to bind on address %r: %s' + % (sa, err.strerror.lower())) + completed = True + finally: + if not completed: + for sock in sockets: + sock.close() + else: + if sock is None: + raise ValueError('Neither host/port nor sock were specified') + sockets = [sock] + + server = asyncio.base_events.Server(self, sockets) + for sock in sockets: + sock.listen(backlog) + sock.setblocking(False) + self._start_serving(protocol_factory, sock, ssl, server) + if self._debug: + asyncio.log.logger.info("%r is serving", server) + return server + + asyncio.base_events.BaseEventLoop.create_server = create_server From 2e4e251877c966fa5e5da8768f5a372ed793ff27 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Wed, 9 Mar 2016 10:34:58 +0800 Subject: [PATCH 4/5] examples/device_db: remove --no-localhost-bind --- examples/master/device_db.pyon | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/master/device_db.pyon b/examples/master/device_db.pyon index ee475911a..f10b1e6b2 100644 --- a/examples/master/device_db.pyon +++ b/examples/master/device_db.pyon @@ -154,25 +154,25 @@ # that it always resolves to a network-visible IP address (see documentation). "host": "::1", "port": 4000, - "command": "pdq2_controller --no-localhost-bind -p {port} --bind {bind} --simulation --dump qc_q1_0.bin" + "command": "pdq2_controller -p {port} --bind {bind} --simulation --dump qc_q1_0.bin" }, "qc_q1_1": { "type": "controller", "host": "::1", "port": 4001, - "command": "pdq2_controller --no-localhost-bind -p {port} --bind {bind} --simulation --dump qc_q1_1.bin" + "command": "pdq2_controller -p {port} --bind {bind} --simulation --dump qc_q1_1.bin" }, "qc_q1_2": { "type": "controller", "host": "::1", "port": 4002, - "command": "pdq2_controller --no-localhost-bind -p {port} --bind {bind} --simulation --dump qc_q1_2.bin" + "command": "pdq2_controller -p {port} --bind {bind} --simulation --dump qc_q1_2.bin" }, "qc_q1_3": { "type": "controller", "host": "::1", "port": 4003, - "command": "pdq2_controller --no-localhost-bind -p {port} --bind {bind} --simulation --dump qc_q1_3.bin" + "command": "pdq2_controller -p {port} --bind {bind} --simulation --dump qc_q1_3.bin" }, "electrodes": { "type": "local", From 9d1903a4e2276b69ba3a8ec058f1a716496f7c7f Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Wed, 9 Mar 2016 13:01:34 +0800 Subject: [PATCH 5/5] coredevice/i2c,ttl,spi: consistent device get --- artiq/coredevice/i2c.py | 8 ++++---- artiq/coredevice/spi.py | 4 ++-- artiq/coredevice/ttl.py | 12 ++++++------ 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/artiq/coredevice/i2c.py b/artiq/coredevice/i2c.py index e9de36161..55148402a 100644 --- a/artiq/coredevice/i2c.py +++ b/artiq/coredevice/i2c.py @@ -34,8 +34,8 @@ class PCA9548: On the KC705, this chip is used for selecting the I2C buses on the two FMC connectors. HPC=1, LPC=2. """ - def __init__(self, dmgr, busno=0, address=0xe8): - self.core = dmgr.get("core") + def __init__(self, dmgr, busno=0, address=0xe8, core_device="core"): + self.core = dmgr.get(core_device) self.busno = busno self.address = address @@ -77,8 +77,8 @@ class TCA6424A: On the NIST QC2 hardware, this chip is used for switching the directions of TTL buffers.""" - def __init__(self, dmgr, busno=0, address=0x44): - self.core = dmgr.get("core") + def __init__(self, dmgr, busno=0, address=0x44, core_device="core"): + self.core = dmgr.get(core_device) self.busno = busno self.address = address diff --git a/artiq/coredevice/spi.py b/artiq/coredevice/spi.py index 6221c8f53..20095a8ff 100644 --- a/artiq/coredevice/spi.py +++ b/artiq/coredevice/spi.py @@ -40,8 +40,8 @@ class SPIMaster: :param channel: RTIO channel number of the SPI bus to control. """ - def __init__(self, dmgr, channel): - self.core = dmgr.get("core") + 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.channel = channel diff --git a/artiq/coredevice/ttl.py b/artiq/coredevice/ttl.py index 9ac12ca48..ef855d6b2 100644 --- a/artiq/coredevice/ttl.py +++ b/artiq/coredevice/ttl.py @@ -10,8 +10,8 @@ class TTLOut: :param channel: channel number """ - def __init__(self, dmgr, channel): - self.core = dmgr.get("core") + def __init__(self, dmgr, channel, core_device="core"): + self.core = dmgr.get(core_device) self.channel = channel # in RTIO cycles @@ -82,8 +82,8 @@ class TTLInOut: :param channel: channel number """ - def __init__(self, dmgr, channel): - self.core = dmgr.get("core") + def __init__(self, dmgr, channel, core_device="core"): + self.core = dmgr.get(core_device) self.channel = channel # in RTIO cycles @@ -232,8 +232,8 @@ class TTLClockGen: :param channel: channel number """ - def __init__(self, dmgr, channel): - self.core = dmgr.get("core") + def __init__(self, dmgr, channel, core_device="core"): + self.core = dmgr.get(core_device) self.channel = channel # in RTIO cycles