From c55f2222dc1fed45dbeb4c7dfd8e186f1c196407 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20J=C3=B6rdens?= Date: Tue, 22 Sep 2020 17:58:53 +0200 Subject: [PATCH] fastino: documentation and eem pass-through * Repeat information about matching log2_width a few times in the hope that people read it. #1518 * Pass through log2_width in kasli_generic json. close #1481 * Check DAC value range. #1518 --- artiq/coredevice/fastino.py | 22 ++++++++++++---------- artiq/gateware/eem.py | 4 ++-- artiq/gateware/targets/kasli_generic.py | 3 ++- 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/artiq/coredevice/fastino.py b/artiq/coredevice/fastino.py index 200d89018..73fcfdf38 100644 --- a/artiq/coredevice/fastino.py +++ b/artiq/coredevice/fastino.py @@ -19,17 +19,17 @@ class Fastino: bit using :meth:`set_update`. Update is self-clearing. This enables atomic DAC updates synchronized to a frame edge. - The `log2_width=0` RTIO layout uses one DAC channel per RTIO address - and a dense RTIO address space. The RTIO words are narrow. - (32 bit compared to 512) and few-channel updates are efficient. - There is the least amount of DAC state tracking in kernels, - at the cost of more DMA and RTIO data. + The `log2_width=0` RTIO layout uses one DAC channel per RTIO address and a + dense RTIO address space. The RTIO words are narrow. (32 bit) and + few-channel updates are efficient. There is the least amount of DAC state + tracking in kernels, at the cost of more DMA and RTIO data. + The setting here and in the RTIO PHY (gateware) must match. Other `log2_width` (up to `log2_width=5`) settings pack multiple (in powers of two) DAC channels into one group and into one RTIO write. The RTIO data width increases accordingly. The `log2_width` LSBs of the RTIO address for a DAC channel write must be zero and the - address space is sparse. + address space is sparse. For `log2_width=5` the RTIO data is 512 bit wide. If `log2_width` is zero, the :meth:`set_dac`/:meth:`set_dac_mu` interface must be used. If non-zero, the :meth:`set_group`/:meth:`set_group_mu` @@ -37,9 +37,8 @@ class Fastino: :param channel: RTIO channel number :param core_device: Core device name (default: "core") - :param log2_width: Width of DAC channel group (power of two, - see the RTIO PHY for details). Value must match the corresponding value - in the RTIO PHY. + :param log2_width: Width of DAC channel group (logarithm base 2). + Value must match the corresponding value in the RTIO PHY (gateware). """ kernel_invariants = {"core", "channel", "width"} @@ -113,7 +112,10 @@ class Fastino: :param voltage: Voltage in SI Volts. :return: DAC data word in machine units, 16 bit integer. """ - return (int(round((0x8000/10.)*voltage)) + 0x8000) & 0xffff + data = int(round((0x8000/10.)*voltage)) + 0x8000 + if data < 0 or data > 0xffff: + raise ValueError("DAC voltage out of bounds") + return data @portable def voltage_group_to_mu(self, voltage, data): diff --git a/artiq/gateware/eem.py b/artiq/gateware/eem.py index fba2c1b5a..19fbe7ea8 100644 --- a/artiq/gateware/eem.py +++ b/artiq/gateware/eem.py @@ -618,11 +618,11 @@ class Fastino(_EEM): ) for pol in "pn"] @classmethod - def add_std(cls, target, eem, iostandard="LVDS_25"): + def add_std(cls, target, eem, log2_width, iostandard="LVDS_25"): cls.add_extension(target, eem, iostandard=iostandard) phy = fastino.Fastino(target.platform.request("fastino{}_ser_p".format(eem)), target.platform.request("fastino{}_ser_n".format(eem)), - log2_width=0) + log2_width=log2_width) target.submodules += phy target.rtio_channels.append(rtio.Channel.from_phy(phy, ififo_depth=4)) diff --git a/artiq/gateware/targets/kasli_generic.py b/artiq/gateware/targets/kasli_generic.py index 939f60716..2fcd299a1 100755 --- a/artiq/gateware/targets/kasli_generic.py +++ b/artiq/gateware/targets/kasli_generic.py @@ -109,7 +109,8 @@ def peripheral_mirny(module, peripheral): def peripheral_fastino(module, peripheral): if len(peripheral["ports"]) != 1: raise ValueError("wrong number of ports") - eem.Fastino.add_std(module, peripheral["ports"][0]) + eem.Fastino.add_std(module, peripheral["ports"][0], + peripheral.get("log2_width", 0)) peripheral_processors = {