diff --git a/.github/workflows/regression-tests.yml b/.github/workflows/regression-tests.yml index 5b1478150..006c1c081 100644 --- a/.github/workflows/regression-tests.yml +++ b/.github/workflows/regression-tests.yml @@ -10,25 +10,18 @@ on: jobs: - lint-flake8: + pre-commit: runs-on: ubuntu-latest - name: flake8 - strategy: - fail-fast: false steps: - - uses: actions/checkout@v6 - - name: Set up Python - uses: actions/setup-python@v6 + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 with: - python-version: 3.11 - - name: flake8 - run: | - pip install flake8 - flake8 --ignore=E501,W503,W504 + python-version: "3.12" + - uses: pre-commit/action@v3.0.1 tests: - name: Python ${{matrix.python-version}} | ${{matrix.sim}} + name: Python ${{matrix.python-version}} | ${{matrix.sim}} runs-on: ubuntu-24.04 env: SIM: ${{matrix.sim}} diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 000000000..32c39dfca --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,17 @@ +repos: + - repo: https://github.com/pycqa/isort + rev: 6.0.1 + hooks: + - id: isort + name: isort (python) + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.14.0 + hooks: + - id: ruff-check + args: [ --fix ] + - id: ruff-format + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v5.0.0 + hooks: + - id: end-of-file-fixer + - id: trailing-whitespace diff --git a/LICENSE.txt b/LICENSE.txt index e726be64d..77f7e54ee 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -2,29 +2,29 @@ Copyright (c) 2011-2018 SiLab, Institute of Physics, University of Bonn All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright notice, + * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - * Neither the name of the copyright holder nor the names of its - contributors may be used to endorse or promote products derived from + * Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from this software without specific prior written permission. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/basil/HL/FEI4AdapterCard.py b/basil/HL/FEI4AdapterCard.py index 0966b6205..91553152b 100644 --- a/basil/HL/FEI4AdapterCard.py +++ b/basil/HL/FEI4AdapterCard.py @@ -6,11 +6,11 @@ # import logging -from struct import pack, unpack_from, calcsize +import string from array import array from collections import OrderedDict from math import log -import string +from struct import calcsize, pack, unpack_from from basil.HL.HardwareLayer import HardwareLayer @@ -18,11 +18,12 @@ class AdcMax1239(HardwareLayer): - '''ADC MAX1238/MAX1239 + """ADC MAX1238/MAX1239 Read current and voltage (AC & QMAC). - ''' - MAX_1239_ADD = 0x6a + """ + + MAX_1239_ADD = 0x6A INT_REF_OFF_EXT_REF_ON = 0x20 INT_REF_ON_OUTPUT_OFF = 0x50 @@ -30,8 +31,8 @@ class AdcMax1239(HardwareLayer): SETUP_DATA = 0x80 NO_RESET = 0x02 EXT_CLK = 0x08 - SETUP_FLAGS = (SETUP_DATA | INT_REF_OFF_EXT_REF_ON | NO_RESET | EXT_CLK) # use external reference - SETUP_FLAGS_BI = (SETUP_DATA | INT_REF_ON_OUTPUT_OFF | NO_RESET | EXT_CLK) # use internal reference + SETUP_FLAGS = SETUP_DATA | INT_REF_OFF_EXT_REF_ON | NO_RESET | EXT_CLK # use external reference + SETUP_FLAGS_BI = SETUP_DATA | INT_REF_ON_OUTPUT_OFF | NO_RESET | EXT_CLK # use internal reference SCAN_OFF = 0x60 SCAN_ON = 0x00 @@ -39,24 +40,22 @@ class AdcMax1239(HardwareLayer): def __init__(self, intf, conf): super(AdcMax1239, self).__init__(intf, conf) - self._base_addr = conf['base_addr'] + self._base_addr = conf["base_addr"] def _setup_adc(self, flags): - '''Initialize ADC - ''' - self._intf.write(self._base_addr + self.MAX_1239_ADD, array('B', pack('B', flags))) + """Initialize ADC""" + self._intf.write(self._base_addr + self.MAX_1239_ADD, array("B", pack("B", flags))) def _get_adc_value(self, channel, average=None): - '''Read ADC - ''' - conf = self.SCAN_OFF | self.SINGLE_ENDED | ((0x1e) & (channel << 1)) - self._intf.write(self._base_addr + self.MAX_1239_ADD, array('B', pack('B', conf))) + """Read ADC""" + conf = self.SCAN_OFF | self.SINGLE_ENDED | ((0x1E) & (channel << 1)) + self._intf.write(self._base_addr + self.MAX_1239_ADD, array("B", pack("B", conf))) def read_data(): ret = self._intf.read(self._base_addr + self.MAX_1239_ADD | 1, size=2) ret.reverse() - ret[1] = ret[1] & 0x0f # 12-bit ADC - return unpack_from('H', ret)[0] + ret[1] = ret[1] & 0x0F # 12-bit ADC + return unpack_from("H", ret)[0] if average: raw = 0 @@ -70,41 +69,43 @@ def read_data(): class DacMax520(HardwareLayer): - '''DAC MAX520 + """DAC MAX520 Write voltage (AC). - ''' + """ + MAX_520_ADD = 0x58 def __init__(self, intf, conf): super(DacMax520, self).__init__(intf, conf) - self._base_addr = conf['base_addr'] + self._base_addr = conf["base_addr"] def _set_dac_value(self, channel, value): - '''Write DAC - ''' - self._intf.write(self._base_addr + self.MAX_520_ADD, array('B', pack('BB', channel, value))) + """Write DAC""" + self._intf.write(self._base_addr + self.MAX_520_ADD, array("B", pack("BB", channel, value))) class Eeprom24Lc128(HardwareLayer): - '''EEPROM 24LC128 + """EEPROM 24LC128 Reading and writing EEPROM (AC & QMAC). - ''' - CAL_EEPROM_ADD = 0xa8 + """ + + CAL_EEPROM_ADD = 0xA8 CAL_EEPROM_PAGE_SIZE = 32 def __init__(self, intf, conf): super(Eeprom24Lc128, self).__init__(intf, conf) - self._base_addr = conf['base_addr'] + self._base_addr = conf["base_addr"] def _read_eeprom(self, address, size): - '''Read EEPROM - ''' - self._intf.write(self._base_addr + self.CAL_EEPROM_ADD, array('B', pack('>H', address & 0x3FFF))) # 14-bit address, 16384 bytes + """Read EEPROM""" + self._intf.write( + self._base_addr + self.CAL_EEPROM_ADD, array("B", pack(">H", address & 0x3FFF)) + ) # 14-bit address, 16384 bytes n_pages, n_bytes = divmod(size, self.CAL_EEPROM_PAGE_SIZE) - data = array('B') + data = array("B") for _ in range(n_pages): data.extend(self._intf.read(self._base_addr + self.CAL_EEPROM_ADD | 1, size=self.CAL_EEPROM_PAGE_SIZE)) @@ -118,14 +119,13 @@ def _write_eeprom(self, address, data): class Fei4Dcs(object): - '''FEI4AdapterCard interface - ''' + """FEI4AdapterCard interface""" # EEPROM HEADER_ADDR = 0 - HEADER_FORMAT = '>H' # Version of EEPROM data + HEADER_FORMAT = ">H" # Version of EEPROM data ID_ADDR = HEADER_ADDR + calcsize(HEADER_FORMAT) - ID_FORMAT = '>H' # Adapter Card ID + ID_FORMAT = ">H" # Adapter Card ID # Channel mappings _ch_map = None @@ -135,66 +135,64 @@ def __init__(self): self._ch_cal = None def set_default(self, channels=None): - '''Setting default voltage - ''' + """Setting default voltage""" if not channels: channels = self._ch_cal.keys() for channel in channels: - self.set_voltage(channel, self._ch_cal[channel]['default'], unit='V') + self.set_voltage(channel, self._ch_cal[channel]["default"], unit="V") - def set_voltage(self, channel, value, unit='V'): - '''Setting voltage - ''' - dac_offset = self._ch_cal[channel]['DACV']['offset'] - dac_gain = self._ch_cal[channel]['DACV']['gain'] + def set_voltage(self, channel, value, unit="V"): + """Setting voltage""" + dac_offset = self._ch_cal[channel]["DACV"]["offset"] + dac_gain = self._ch_cal[channel]["DACV"]["gain"] - if unit == 'raw': + if unit == "raw": value = value - elif unit == 'V': + elif unit == "V": value = int((value - dac_offset) / dac_gain) - elif unit == 'mV': + elif unit == "mV": value = int((value / 1000 - dac_offset) / dac_gain) else: raise TypeError("Invalid unit type.") - self._set_dac_value(value=value, **self._ch_map[channel]['DACV']) + self._set_dac_value(value=value, **self._ch_map[channel]["DACV"]) - def get_voltage(self, channel, unit='V'): - '''Reading voltage - ''' - kwargs = self._ch_map[channel]['ADCV'] + def get_voltage(self, channel, unit="V"): + """Reading voltage""" + kwargs = self._ch_map[channel]["ADCV"] voltage_raw = self._get_adc_value(**kwargs) - voltage = (voltage_raw - self._ch_cal[channel]['ADCV']['offset']) / self._ch_cal[channel]['ADCV']['gain'] + voltage = (voltage_raw - self._ch_cal[channel]["ADCV"]["offset"]) / self._ch_cal[channel]["ADCV"]["gain"] - if unit == 'raw': + if unit == "raw": return voltage_raw - elif unit == 'V': + elif unit == "V": return voltage - elif unit == 'mV': + elif unit == "mV": return voltage * 1000 else: raise TypeError("Invalid unit type.") - def get_current(self, channel, unit='A'): - '''Reading current - ''' - kwargs = self._ch_map[channel]['ADCI'] + def get_current(self, channel, unit="A"): + """Reading current""" + kwargs = self._ch_map[channel]["ADCI"] current_raw = self._get_adc_value(**kwargs) voltage = self.get_voltage(channel) - current_raw_iq = current_raw - (self._ch_cal[channel]['ADCI']['iq_offset'] + self._ch_cal[channel]['ADCI']['iq_gain'] * voltage) # quiescent current (IQ) compensation - current = (current_raw_iq - self._ch_cal[channel]['ADCI']['offset']) / self._ch_cal[channel]['ADCI']['gain'] + current_raw_iq = current_raw - ( + self._ch_cal[channel]["ADCI"]["iq_offset"] + self._ch_cal[channel]["ADCI"]["iq_gain"] * voltage + ) # quiescent current (IQ) compensation + current = (current_raw_iq - self._ch_cal[channel]["ADCI"]["offset"]) / self._ch_cal[channel]["ADCI"]["gain"] - if unit == 'raw': + if unit == "raw": return current_raw - elif unit == 'raw_iq': + elif unit == "raw_iq": return current_raw_iq - elif unit == 'A': + elif unit == "A": return current - elif unit == 'mA': + elif unit == "mA": return current * 1000 - elif unit == 'uA': + elif unit == "uA": return current * 1000000 else: raise TypeError("Invalid unit type.") @@ -218,173 +216,291 @@ def _read_eeprom(self, address, size): class FEI4AdapterCard(AdcMax1239, DacMax520, Eeprom24Lc128, Fei4Dcs): - '''FEI4 Adapter Card interface - ''' + """FEI4 Adapter Card interface""" # EEPROM data V1 - HEADER_V1 = 0xa101 - CAL_DATA_CH_V1_FORMAT = '8sddddddddd' - CAL_DATA_CONST_V1_FORMAT = 'dddddd' + HEADER_V1 = 0xA101 + CAL_DATA_CH_V1_FORMAT = "8sddddddddd" + CAL_DATA_CONST_V1_FORMAT = "dddddd" CAL_DATA_ADDR = Fei4Dcs.ID_ADDR + calcsize(Fei4Dcs.ID_FORMAT) - CAL_DATA_V1_FORMAT = '<' + 4 * CAL_DATA_CH_V1_FORMAT + CAL_DATA_CONST_V1_FORMAT + CAL_DATA_V1_FORMAT = "<" + 4 * CAL_DATA_CH_V1_FORMAT + CAL_DATA_CONST_V1_FORMAT # NTC T_KELVIN_0 = 273.15 - T_KELVIN_25 = (25.0 + T_KELVIN_0) + T_KELVIN_25 = 25.0 + T_KELVIN_0 # Channel mappings _ch_map = { - 'VDDA1': - {'DACV': {'channel': 3}, - 'ADCV': {'channel': 0}, - 'ADCI': {'channel': 1}, - 'NTC1': {'channel': 8}, - 'NTC2': {'channel': 9}, - 'VNTC': {'channel': 10} - }, - 'VDDA2': - {'DACV': {'channel': 0}, - 'ADCV': {'channel': 2}, - 'ADCI': {'channel': 3}, - 'NTC1': {'channel': 8}, - 'NTC2': {'channel': 9}, - 'VNTC': {'channel': 10} - }, - 'VDDD1': - {'DACV': {'channel': 1}, - 'ADCV': {'channel': 4}, - 'ADCI': {'channel': 5}, - 'NTC1': {'channel': 8}, - 'NTC2': {'channel': 9}, - 'VNTC': {'channel': 10} - }, - 'VDDD2': - {'DACV': {'channel': 2}, - 'ADCV': {'channel': 6}, - 'ADCI': {'channel': 7}, - 'NTC1': {'channel': 8}, - 'NTC2': {'channel': 9}, - 'VNTC': {'channel': 10} - } + "VDDA1": { + "DACV": {"channel": 3}, + "ADCV": {"channel": 0}, + "ADCI": {"channel": 1}, + "NTC1": {"channel": 8}, + "NTC2": {"channel": 9}, + "VNTC": {"channel": 10}, + }, + "VDDA2": { + "DACV": {"channel": 0}, + "ADCV": {"channel": 2}, + "ADCI": {"channel": 3}, + "NTC1": {"channel": 8}, + "NTC2": {"channel": 9}, + "VNTC": {"channel": 10}, + }, + "VDDD1": { + "DACV": {"channel": 1}, + "ADCV": {"channel": 4}, + "ADCI": {"channel": 5}, + "NTC1": {"channel": 8}, + "NTC2": {"channel": 9}, + "VNTC": {"channel": 10}, + }, + "VDDD2": { + "DACV": {"channel": 2}, + "ADCV": {"channel": 6}, + "ADCI": {"channel": 7}, + "NTC1": {"channel": 8}, + "NTC2": {"channel": 9}, + "VNTC": {"channel": 10}, + }, } def __init__(self, intf, conf): super(FEI4AdapterCard, self).__init__(intf, conf) # Channel calibrations - self._ch_cal = OrderedDict([ - ('VDDA1', - {'name': '', - 'default': 0.0, - 'DACV': {'offset': 1.558, 'gain': -0.00193}, - 'ADCV': {'offset': 0.0, 'gain': 1638.4}, - 'ADCI': {'offset': 0.0, 'gain': 3296.45, 'iq_offset': 6.0, 'iq_gain': 6.0}, - 'NTC1': {'B_NTC': 3425.0, 'R_NTC_25': 10000.0, 'R1': 3900.0, 'R2': 4700.0, 'R4': 10000.0, 'VREF': 2.5}, - 'NTC2': {'B_NTC': 3425.0, 'R_NTC_25': 10000.0, 'R1': 3900.0, 'R2': 4700.0, 'R4': 10000.0, 'VREF': 2.5}, - 'VNTC': {'B_NTC': 3425.0, 'R_NTC_25': 10000.0, 'R1': 3900.0, 'R2': 4700.0, 'R4': 10000.0, 'VREF': 2.5} - }), - ('VDDA2', - {'name': '', - 'default': 0.0, - 'DACV': {'offset': 1.558, 'gain': -0.00193}, - 'ADCV': {'offset': 0.0, 'gain': 1638.4}, - 'ADCI': {'offset': 0.0, 'gain': 3296.45, 'iq_offset': 6.0, 'iq_gain': 6.0}, - 'NTC1': {'B_NTC': 3425.0, 'R_NTC_25': 10000.0, 'R1': 3900.0, 'R2': 4700.0, 'R4': 10000.0, 'VREF': 2.5}, - 'NTC2': {'B_NTC': 3425.0, 'R_NTC_25': 10000.0, 'R1': 3900.0, 'R2': 4700.0, 'R4': 10000.0, 'VREF': 2.5}, - 'VNTC': {'B_NTC': 3425.0, 'R_NTC_25': 10000.0, 'R1': 3900.0, 'R2': 4700.0, 'R4': 10000.0, 'VREF': 2.5} - }), - ('VDDD1', - {'name': '', - 'default': 0.0, - 'DACV': {'offset': 1.558, 'gain': -0.00193}, - 'ADCV': {'offset': 0.0, 'gain': 1638.4}, - 'ADCI': {'offset': 0.0, 'gain': 3296.45, 'iq_offset': 6.0, 'iq_gain': 6.0}, - 'NTC1': {'B_NTC': 3425.0, 'R_NTC_25': 10000.0, 'R1': 3900.0, 'R2': 4700.0, 'R4': 10000.0, 'VREF': 2.5}, - 'NTC2': {'B_NTC': 3425.0, 'R_NTC_25': 10000.0, 'R1': 3900.0, 'R2': 4700.0, 'R4': 10000.0, 'VREF': 2.5}, - 'VNTC': {'B_NTC': 3425.0, 'R_NTC_25': 10000.0, 'R1': 3900.0, 'R2': 4700.0, 'R4': 10000.0, 'VREF': 2.5} - }), - ('VDDD2', - {'name': '', - 'default': 0.0, - 'DACV': {'offset': 1.558, 'gain': -0.00193}, - 'ADCV': {'offset': 0.0, 'gain': 1638.4}, - 'ADCI': {'offset': 0.0, 'gain': 3296.45, 'iq_offset': 6.0, 'iq_gain': 6.0}, - 'NTC1': {'B_NTC': 3425.0, 'R_NTC_25': 10000.0, 'R1': 3900.0, 'R2': 4700.0, 'R4': 10000.0, 'VREF': 2.5}, - 'NTC2': {'B_NTC': 3425.0, 'R_NTC_25': 10000.0, 'R1': 3900.0, 'R2': 4700.0, 'R4': 10000.0, 'VREF': 2.5}, - 'VNTC': {'B_NTC': 3425.0, 'R_NTC_25': 10000.0, 'R1': 3900.0, 'R2': 4700.0, 'R4': 10000.0, 'VREF': 2.5} - })] + self._ch_cal = OrderedDict( + [ + ( + "VDDA1", + { + "name": "", + "default": 0.0, + "DACV": {"offset": 1.558, "gain": -0.00193}, + "ADCV": {"offset": 0.0, "gain": 1638.4}, + "ADCI": {"offset": 0.0, "gain": 3296.45, "iq_offset": 6.0, "iq_gain": 6.0}, + "NTC1": { + "B_NTC": 3425.0, + "R_NTC_25": 10000.0, + "R1": 3900.0, + "R2": 4700.0, + "R4": 10000.0, + "VREF": 2.5, + }, + "NTC2": { + "B_NTC": 3425.0, + "R_NTC_25": 10000.0, + "R1": 3900.0, + "R2": 4700.0, + "R4": 10000.0, + "VREF": 2.5, + }, + "VNTC": { + "B_NTC": 3425.0, + "R_NTC_25": 10000.0, + "R1": 3900.0, + "R2": 4700.0, + "R4": 10000.0, + "VREF": 2.5, + }, + }, + ), + ( + "VDDA2", + { + "name": "", + "default": 0.0, + "DACV": {"offset": 1.558, "gain": -0.00193}, + "ADCV": {"offset": 0.0, "gain": 1638.4}, + "ADCI": {"offset": 0.0, "gain": 3296.45, "iq_offset": 6.0, "iq_gain": 6.0}, + "NTC1": { + "B_NTC": 3425.0, + "R_NTC_25": 10000.0, + "R1": 3900.0, + "R2": 4700.0, + "R4": 10000.0, + "VREF": 2.5, + }, + "NTC2": { + "B_NTC": 3425.0, + "R_NTC_25": 10000.0, + "R1": 3900.0, + "R2": 4700.0, + "R4": 10000.0, + "VREF": 2.5, + }, + "VNTC": { + "B_NTC": 3425.0, + "R_NTC_25": 10000.0, + "R1": 3900.0, + "R2": 4700.0, + "R4": 10000.0, + "VREF": 2.5, + }, + }, + ), + ( + "VDDD1", + { + "name": "", + "default": 0.0, + "DACV": {"offset": 1.558, "gain": -0.00193}, + "ADCV": {"offset": 0.0, "gain": 1638.4}, + "ADCI": {"offset": 0.0, "gain": 3296.45, "iq_offset": 6.0, "iq_gain": 6.0}, + "NTC1": { + "B_NTC": 3425.0, + "R_NTC_25": 10000.0, + "R1": 3900.0, + "R2": 4700.0, + "R4": 10000.0, + "VREF": 2.5, + }, + "NTC2": { + "B_NTC": 3425.0, + "R_NTC_25": 10000.0, + "R1": 3900.0, + "R2": 4700.0, + "R4": 10000.0, + "VREF": 2.5, + }, + "VNTC": { + "B_NTC": 3425.0, + "R_NTC_25": 10000.0, + "R1": 3900.0, + "R2": 4700.0, + "R4": 10000.0, + "VREF": 2.5, + }, + }, + ), + ( + "VDDD2", + { + "name": "", + "default": 0.0, + "DACV": {"offset": 1.558, "gain": -0.00193}, + "ADCV": {"offset": 0.0, "gain": 1638.4}, + "ADCI": {"offset": 0.0, "gain": 3296.45, "iq_offset": 6.0, "iq_gain": 6.0}, + "NTC1": { + "B_NTC": 3425.0, + "R_NTC_25": 10000.0, + "R1": 3900.0, + "R2": 4700.0, + "R4": 10000.0, + "VREF": 2.5, + }, + "NTC2": { + "B_NTC": 3425.0, + "R_NTC_25": 10000.0, + "R1": 3900.0, + "R2": 4700.0, + "R4": 10000.0, + "VREF": 2.5, + }, + "VNTC": { + "B_NTC": 3425.0, + "R_NTC_25": 10000.0, + "R1": 3900.0, + "R2": 4700.0, + "R4": 10000.0, + "VREF": 2.5, + }, + }, + ), + ] ) def init(self): super(FEI4AdapterCard, self).init() self._setup_adc(self.SETUP_FLAGS) - self._init.setdefault('no_calibration', False) + self._init.setdefault("no_calibration", False) # read calibration - if not self._init['no_calibration']: + if not self._init["no_calibration"]: self.read_eeprom_calibration() - logger.info('Found adapter card: {}'.format('%s with ID %s' % ('FEI4 Single Chip Adapter Card', self.get_id()))) + logger.info( + "Found adapter card: {}".format("%s with ID %s" % ("FEI4 Single Chip Adapter Card", self.get_id())) + ) else: - logger.info('FEI4 Single Chip Adapter Card: skip reading calibration parameters from EEPROM') + logger.info("FEI4 Single Chip Adapter Card: skip reading calibration parameters from EEPROM") - def read_eeprom_calibration(self, temperature=False): # use default values for temperature, EEPROM values are usually not calibrated and random - '''Reading EEPROM calibration for power regulators and temperature - ''' + def read_eeprom_calibration( + self, temperature=False + ): # use default values for temperature, EEPROM values are usually not calibrated and random + """Reading EEPROM calibration for power regulators and temperature""" header = self.get_format() if header == self.HEADER_V1: data = self._read_eeprom(self.CAL_DATA_ADDR, size=calcsize(self.CAL_DATA_V1_FORMAT)) for idx, channel in enumerate(self._ch_cal.keys()): - ch_data = data[idx * calcsize(self.CAL_DATA_CH_V1_FORMAT):(idx + 1) * calcsize(self.CAL_DATA_CH_V1_FORMAT)] + ch_data = data[ + idx * calcsize(self.CAL_DATA_CH_V1_FORMAT) : (idx + 1) * calcsize(self.CAL_DATA_CH_V1_FORMAT) + ] values = unpack_from(self.CAL_DATA_CH_V1_FORMAT, ch_data) - self._ch_cal[channel]['name'] = "".join([c for c in values[0].decode('utf-8', errors='ignore') if (c in string.printable)]) # values[0].strip() - self._ch_cal[channel]['default'] = values[1] - self._ch_cal[channel]['ADCI']['gain'] = values[2] - self._ch_cal[channel]['ADCI']['offset'] = values[3] - self._ch_cal[channel]['ADCI']['iq_gain'] = values[4] - self._ch_cal[channel]['ADCI']['iq_offset'] = values[5] - self._ch_cal[channel]['ADCV']['gain'] = values[6] - self._ch_cal[channel]['ADCV']['offset'] = values[7] - self._ch_cal[channel]['DACV']['gain'] = values[8] - self._ch_cal[channel]['DACV']['offset'] = values[9] - const_data = data[-calcsize(self.CAL_DATA_CONST_V1_FORMAT):] + self._ch_cal[channel]["name"] = "".join( + [c for c in values[0].decode("utf-8", errors="ignore") if (c in string.printable)] + ) # values[0].strip() + self._ch_cal[channel]["default"] = values[1] + self._ch_cal[channel]["ADCI"]["gain"] = values[2] + self._ch_cal[channel]["ADCI"]["offset"] = values[3] + self._ch_cal[channel]["ADCI"]["iq_gain"] = values[4] + self._ch_cal[channel]["ADCI"]["iq_offset"] = values[5] + self._ch_cal[channel]["ADCV"]["gain"] = values[6] + self._ch_cal[channel]["ADCV"]["offset"] = values[7] + self._ch_cal[channel]["DACV"]["gain"] = values[8] + self._ch_cal[channel]["DACV"]["offset"] = values[9] + const_data = data[-calcsize(self.CAL_DATA_CONST_V1_FORMAT) :] values = unpack_from(self.CAL_DATA_CONST_V1_FORMAT, const_data) if temperature: for channel in self._ch_cal.keys(): - self._ch_cal[channel]['VNTC']['B_NTC'] = values[0] - self._ch_cal[channel]['VNTC']['R1'] = values[1] - self._ch_cal[channel]['VNTC']['R2'] = values[2] - self._ch_cal[channel]['VNTC']['R4'] = values[3] - self._ch_cal[channel]['VNTC']['R_NTC_25'] = values[4] - self._ch_cal[channel]['VNTC']['VREF'] = values[5] + self._ch_cal[channel]["VNTC"]["B_NTC"] = values[0] + self._ch_cal[channel]["VNTC"]["R1"] = values[1] + self._ch_cal[channel]["VNTC"]["R2"] = values[2] + self._ch_cal[channel]["VNTC"]["R4"] = values[3] + self._ch_cal[channel]["VNTC"]["R_NTC_25"] = values[4] + self._ch_cal[channel]["VNTC"]["VREF"] = values[5] else: - raise ValueError('EEPROM data format not supported (header: %s)' % header) - - def get_temperature(self, channel, sensor='VNTC'): - '''Reading temperature - ''' -# NTC type SEMITEC 103KT1608 http://www.semitec.co.jp/english/products/pdf/KT_Thermistor.pdf -# -# R_NTC = R_25 * exp(B_NTC * (1/T - 1/T_25)) -# -# R_NTC measured NTC resistance -# R_NTC_25 resistance @ 25C -# B_NTC temperature coefficient -# Temperature current temperature (Kelvin) -# T_25 298,15 K (25C) -# -# B_NTC NTC 'b' coefficient, NTC Semitec 103KT1608-1P -# R_NTC_25 NTC 25C resistance, NTC Semitec 103KT1608-1P -# R1 resistor value for NTC voltage divider -# R2 value of R2 in the reference voltage divider -# R4 value of R4 in the reference voltage divider -# VREF supply voltage of the resistor bridge -# + raise ValueError("EEPROM data format not supported (header: %s)" % header) + + def get_temperature(self, channel, sensor="VNTC"): + """Reading temperature""" + # NTC type SEMITEC 103KT1608 http://www.semitec.co.jp/english/products/pdf/KT_Thermistor.pdf + # + # R_NTC = R_25 * exp(B_NTC * (1/T - 1/T_25)) + # + # R_NTC measured NTC resistance + # R_NTC_25 resistance @ 25C + # B_NTC temperature coefficient + # Temperature current temperature (Kelvin) + # T_25 298,15 K (25C) + # + # B_NTC NTC 'b' coefficient, NTC Semitec 103KT1608-1P + # R_NTC_25 NTC 25C resistance, NTC Semitec 103KT1608-1P + # R1 resistor value for NTC voltage divider + # R2 value of R2 in the reference voltage divider + # R4 value of R4 in the reference voltage divider + # VREF supply voltage of the resistor bridge + # kwargs = self._ch_map[channel][sensor] temp_raw = self._get_adc_value(**kwargs) - v_adc = ((temp_raw - list(self._ch_cal.items())[0][1]['ADCV']['offset']) / list(self._ch_cal.items())[0][1]['ADCV']['gain']) # voltage, VDDA1 - k = self._ch_cal[channel][sensor]['R4'] / (self._ch_cal[channel][sensor]['R2'] + self._ch_cal[channel][sensor]['R4']) # reference voltage divider - r_ntc = self._ch_cal[channel][sensor]['R1'] * (k - v_adc / self._ch_cal[channel][sensor]['VREF']) / (1 - k + v_adc / self._ch_cal[channel][sensor]['VREF']) # NTC resistance - - return (self._ch_cal[channel][sensor]['B_NTC'] / (log(r_ntc) - log(self._ch_cal[channel][sensor]['R_NTC_25']) + self._ch_cal[channel][sensor]['B_NTC'] / self.T_KELVIN_25)) - self.T_KELVIN_0 # NTC temperature + v_adc = (temp_raw - list(self._ch_cal.items())[0][1]["ADCV"]["offset"]) / list(self._ch_cal.items())[0][1][ + "ADCV" + ]["gain"] # voltage, VDDA1 + k = self._ch_cal[channel][sensor]["R4"] / ( + self._ch_cal[channel][sensor]["R2"] + self._ch_cal[channel][sensor]["R4"] + ) # reference voltage divider + r_ntc = ( + self._ch_cal[channel][sensor]["R1"] + * (k - v_adc / self._ch_cal[channel][sensor]["VREF"]) + / (1 - k + v_adc / self._ch_cal[channel][sensor]["VREF"]) + ) # NTC resistance + + return ( + self._ch_cal[channel][sensor]["B_NTC"] + / ( + log(r_ntc) + - log(self._ch_cal[channel][sensor]["R_NTC_25"]) + + self._ch_cal[channel][sensor]["B_NTC"] / self.T_KELVIN_25 + ) + ) - self.T_KELVIN_0 # NTC temperature diff --git a/basil/HL/FEI4QuadModuleAdapterCard.py b/basil/HL/FEI4QuadModuleAdapterCard.py index a1ca1232a..7b0f1ab72 100644 --- a/basil/HL/FEI4QuadModuleAdapterCard.py +++ b/basil/HL/FEI4QuadModuleAdapterCard.py @@ -6,49 +6,49 @@ # import logging -from struct import pack, unpack_from, calcsize +import string from array import array from collections import OrderedDict from math import log -import string +from struct import calcsize, pack, unpack_from -from basil.HL.HardwareLayer import HardwareLayer from basil.HL.FEI4AdapterCard import AdcMax1239, Eeprom24Lc128, Fei4Dcs +from basil.HL.HardwareLayer import HardwareLayer logger = logging.getLogger(__name__) class DacMax5380(HardwareLayer): - '''DAC MAX5380 + """DAC MAX5380 Write current limit (QMAC). - ''' + """ + MAX_5380_ADD = 0x60 def __init__(self, intf, conf): super(DacMax5380, self).__init__(intf, conf) - self._base_addr = conf['base_addr'] + self._base_addr = conf["base_addr"] def _set_dac_value(self, channel, value): - '''Write DAC - ''' - self._intf.write(self._base_addr + self.MAX_5380_ADD, array('B', pack('B', value))) + """Write DAC""" + self._intf.write(self._base_addr + self.MAX_5380_ADD, array("B", pack("B", value))) class DacDs4424(HardwareLayer): - '''DAC DS4424 + """DAC DS4424 Write voltage (QMAC). - ''' + """ + DS_4424_ADD = 0x20 def __init__(self, intf, conf): super(DacDs4424, self).__init__(intf, conf) - self._base_addr = conf['base_addr'] + self._base_addr = conf["base_addr"] def _set_dac_value(self, channel, value): - '''Write DAC - ''' + """Write DAC""" # DAC value cannot be -128 if value == -128: value = -127 @@ -57,92 +57,113 @@ def _set_dac_value(self, channel, value): else: sign = 0 value = (sign << 7) | (0x7F & abs(value)) - self._intf.write(self._base_addr + self.DS_4424_ADD, array('B', pack('BB', channel, value))) + self._intf.write(self._base_addr + self.DS_4424_ADD, array("B", pack("BB", channel, value))) class FEI4QuadModuleAdapterCard(AdcMax1239, DacDs4424, DacMax5380, Eeprom24Lc128, Fei4Dcs): - '''FEI4 Quad Module Adapter Card interface - ''' + """FEI4 Quad Module Adapter Card interface""" # EEPROM data V2 - HEADER_V2 = 0xa102 - CAL_DATA_CH_V2_FORMAT = '8sddddddddddddddd' + HEADER_V2 = 0xA102 + CAL_DATA_CH_V2_FORMAT = "8sddddddddddddddd" CAL_DATA_ADDR = Fei4Dcs.ID_ADDR + calcsize(Fei4Dcs.ID_FORMAT) - CAL_DATA_V2_FORMAT = '<' + 4 * CAL_DATA_CH_V2_FORMAT + CAL_DATA_V2_FORMAT = "<" + 4 * CAL_DATA_CH_V2_FORMAT # NTC T_KELVIN_0 = 273.15 - T_KELVIN_25 = (25.0 + T_KELVIN_0) + T_KELVIN_25 = 25.0 + T_KELVIN_0 # Channel mappings _ch_map = { - 'CH1': - {'DACV': {'channel': 0xf8}, - 'ADCV': {'channel': 0}, - 'ADCI': {'channel': 1}, - 'NTC': {'channel': 8} - }, - 'CH2': - {'DACV': {'channel': 0xf9}, - 'ADCV': {'channel': 2}, - 'ADCI': {'channel': 3}, - 'NTC': {'channel': 9} - }, - 'CH3': - {'DACV': {'channel': 0xfa}, - 'ADCV': {'channel': 4}, - 'ADCI': {'channel': 5}, - 'NTC': {'channel': 10} - }, - 'CH4': - {'DACV': {'channel': 0xfb}, - 'ADCV': {'channel': 6}, - 'ADCI': {'channel': 7}, - 'NTC': {'channel': 11} - } + "CH1": {"DACV": {"channel": 0xF8}, "ADCV": {"channel": 0}, "ADCI": {"channel": 1}, "NTC": {"channel": 8}}, + "CH2": {"DACV": {"channel": 0xF9}, "ADCV": {"channel": 2}, "ADCI": {"channel": 3}, "NTC": {"channel": 9}}, + "CH3": {"DACV": {"channel": 0xFA}, "ADCV": {"channel": 4}, "ADCI": {"channel": 5}, "NTC": {"channel": 10}}, + "CH4": {"DACV": {"channel": 0xFB}, "ADCV": {"channel": 6}, "ADCI": {"channel": 7}, "NTC": {"channel": 11}}, } def __init__(self, intf, conf): super(FEI4QuadModuleAdapterCard, self).__init__(intf, conf) # Channel calibrations - self._ch_cal = OrderedDict([ - ('CH1', - {'name': '', - 'default': 0.0, - 'DACV': {'offset': 1.8, 'gain': 0.00397}, - 'ADCV': {'offset': 0.0, 'gain': 1000.0}, - 'DACI': {'offset': 0.0, 'gain': 0.0078125}, - 'ADCI': {'offset': 0.0, 'gain': 1000.0, 'iq_offset': 1.5, 'iq_gain': 7.0}, - 'NTC': {'B_NTC': 3425.0, 'R_NTC_25': 10000.0, 'R1': 39200.0, 'R2': 4750.0, 'R4': 10000.0, 'VREF': 4.5} - }), - ('CH2', - {'name': '', - 'default': 0.0, - 'DACV': {'offset': 1.8, 'gain': 0.00397}, - 'ADCV': {'offset': 0.0, 'gain': 1000.0}, - 'DACI': {'offset': 0.0, 'gain': 0.0078125}, - 'ADCI': {'offset': 0.0, 'gain': 1000.0, 'iq_offset': 1.5, 'iq_gain': 7.0}, - 'NTC': {'B_NTC': 3425.0, 'R_NTC_25': 10000.0, 'R1': 39200.0, 'R2': 4750.0, 'R4': 10000.0, 'VREF': 4.5} - }), - ('CH3', - {'name': '', - 'default': 0.0, - 'DACV': {'offset': 1.8, 'gain': 0.00397}, - 'ADCV': {'offset': 0.0, 'gain': 1000.0}, - 'DACI': {'offset': 0.0, 'gain': 0.0078125}, - 'ADCI': {'offset': 0.0, 'gain': 1000.0, 'iq_offset': 1.5, 'iq_gain': 7.0}, - 'NTC': {'B_NTC': 3425.0, 'R_NTC_25': 10000.0, 'R1': 39200.0, 'R2': 4750.0, 'R4': 10000.0, 'VREF': 4.5} - }), - ('CH4', - {'name': '', - 'default': 0.0, - 'DACV': {'offset': 1.8, 'gain': 0.00397}, - 'ADCV': {'offset': 0.0, 'gain': 1000.0}, - 'DACI': {'offset': 0.0, 'gain': 0.0078125}, - 'ADCI': {'offset': 0.0, 'gain': 1000.0, 'iq_offset': 1.5, 'iq_gain': 7.0}, - 'NTC': {'B_NTC': 3425.0, 'R_NTC_25': 10000.0, 'R1': 39200.0, 'R2': 4750.0, 'R4': 10000.0, 'VREF': 4.5} - })] + self._ch_cal = OrderedDict( + [ + ( + "CH1", + { + "name": "", + "default": 0.0, + "DACV": {"offset": 1.8, "gain": 0.00397}, + "ADCV": {"offset": 0.0, "gain": 1000.0}, + "DACI": {"offset": 0.0, "gain": 0.0078125}, + "ADCI": {"offset": 0.0, "gain": 1000.0, "iq_offset": 1.5, "iq_gain": 7.0}, + "NTC": { + "B_NTC": 3425.0, + "R_NTC_25": 10000.0, + "R1": 39200.0, + "R2": 4750.0, + "R4": 10000.0, + "VREF": 4.5, + }, + }, + ), + ( + "CH2", + { + "name": "", + "default": 0.0, + "DACV": {"offset": 1.8, "gain": 0.00397}, + "ADCV": {"offset": 0.0, "gain": 1000.0}, + "DACI": {"offset": 0.0, "gain": 0.0078125}, + "ADCI": {"offset": 0.0, "gain": 1000.0, "iq_offset": 1.5, "iq_gain": 7.0}, + "NTC": { + "B_NTC": 3425.0, + "R_NTC_25": 10000.0, + "R1": 39200.0, + "R2": 4750.0, + "R4": 10000.0, + "VREF": 4.5, + }, + }, + ), + ( + "CH3", + { + "name": "", + "default": 0.0, + "DACV": {"offset": 1.8, "gain": 0.00397}, + "ADCV": {"offset": 0.0, "gain": 1000.0}, + "DACI": {"offset": 0.0, "gain": 0.0078125}, + "ADCI": {"offset": 0.0, "gain": 1000.0, "iq_offset": 1.5, "iq_gain": 7.0}, + "NTC": { + "B_NTC": 3425.0, + "R_NTC_25": 10000.0, + "R1": 39200.0, + "R2": 4750.0, + "R4": 10000.0, + "VREF": 4.5, + }, + }, + ), + ( + "CH4", + { + "name": "", + "default": 0.0, + "DACV": {"offset": 1.8, "gain": 0.00397}, + "ADCV": {"offset": 0.0, "gain": 1000.0}, + "DACI": {"offset": 0.0, "gain": 0.0078125}, + "ADCI": {"offset": 0.0, "gain": 1000.0, "iq_offset": 1.5, "iq_gain": 7.0}, + "NTC": { + "B_NTC": 3425.0, + "R_NTC_25": 10000.0, + "R1": 39200.0, + "R2": 4750.0, + "R4": 10000.0, + "VREF": 4.5, + }, + }, + ), + ] ) def init(self): @@ -150,49 +171,52 @@ def init(self): self._setup_adc(self.SETUP_FLAGS_BI) # read calibration - if not self._init['no_calibration']: + if not self._init["no_calibration"]: self.read_eeprom_calibration() - logger.info('Found adapter card: {} with ID {}'.format('FEI4 Quad Module Adapter Card', self.get_id())) + logger.info("Found adapter card: {} with ID {}".format("FEI4 Quad Module Adapter Card", self.get_id())) else: - logger.info('FEI4 Quad Module Adapter Card: skip reading calibration parameters from EEPROM') + logger.info("FEI4 Quad Module Adapter Card: skip reading calibration parameters from EEPROM") # setting up default current limit for ch_name in self._ch_cal.keys(): self.set_current_limit(ch_name, 1.0) - logger.info('Found adapter card: {}'.format('%s with ID %s' % ('Quad Module Adapter Card', self.get_id()))) + logger.info("Found adapter card: {}".format("%s with ID %s" % ("Quad Module Adapter Card", self.get_id()))) - def read_eeprom_calibration(self, temperature=False): # use default values for temperature, EEPROM values are usually not calibrated and random - '''Reading EEPROM calibration for power regulators and temperature - ''' + def read_eeprom_calibration(self, temperature=False): + # use default values for temperature, EEPROM values are usually not calibrated and random + """Reading EEPROM calibration for power regulators and temperature""" header = self.get_format() if header == self.HEADER_V2: data = self._read_eeprom(self.CAL_DATA_ADDR, size=calcsize(self.CAL_DATA_V2_FORMAT)) for idx, channel in enumerate(self._ch_cal.keys()): - ch_data = data[idx * calcsize(self.CAL_DATA_CH_V2_FORMAT):(idx + 1) * calcsize(self.CAL_DATA_CH_V2_FORMAT)] + ch_data = data[ + idx * calcsize(self.CAL_DATA_CH_V2_FORMAT) : (idx + 1) * calcsize(self.CAL_DATA_CH_V2_FORMAT) + ] values = unpack_from(self.CAL_DATA_CH_V2_FORMAT, ch_data) - self._ch_cal[channel]['name'] = "".join([c for c in values[0].decode('utf-8', errors='ignore') if (c in string.printable)]) # values[0].strip() - self._ch_cal[channel]['default'] = values[1] - self._ch_cal[channel]['ADCI']['gain'] = values[2] - self._ch_cal[channel]['ADCI']['offset'] = values[3] - self._ch_cal[channel]['ADCI']['iq_gain'] = values[4] - self._ch_cal[channel]['ADCI']['iq_offset'] = values[5] - self._ch_cal[channel]['ADCV']['gain'] = values[6] - self._ch_cal[channel]['ADCV']['offset'] = values[7] - self._ch_cal[channel]['DACV']['gain'] = values[8] - self._ch_cal[channel]['DACV']['offset'] = values[9] + self._ch_cal[channel]["name"] = "".join( + [c for c in values[0].decode("utf-8", errors="ignore") if (c in string.printable)] + ) # values[0].strip() + self._ch_cal[channel]["default"] = values[1] + self._ch_cal[channel]["ADCI"]["gain"] = values[2] + self._ch_cal[channel]["ADCI"]["offset"] = values[3] + self._ch_cal[channel]["ADCI"]["iq_gain"] = values[4] + self._ch_cal[channel]["ADCI"]["iq_offset"] = values[5] + self._ch_cal[channel]["ADCV"]["gain"] = values[6] + self._ch_cal[channel]["ADCV"]["offset"] = values[7] + self._ch_cal[channel]["DACV"]["gain"] = values[8] + self._ch_cal[channel]["DACV"]["offset"] = values[9] if temperature: - self._ch_cal[channel]['NTC']['B_NTC'] = values[10] - self._ch_cal[channel]['NTC']['R1'] = values[11] - self._ch_cal[channel]['NTC']['R2'] = values[12] - self._ch_cal[channel]['NTC']['R4'] = values[13] - self._ch_cal[channel]['NTC']['R_NTC_25'] = values[14] - self._ch_cal[channel]['NTC']['VREF'] = values[15] + self._ch_cal[channel]["NTC"]["B_NTC"] = values[10] + self._ch_cal[channel]["NTC"]["R1"] = values[11] + self._ch_cal[channel]["NTC"]["R2"] = values[12] + self._ch_cal[channel]["NTC"]["R4"] = values[13] + self._ch_cal[channel]["NTC"]["R_NTC_25"] = values[14] + self._ch_cal[channel]["NTC"]["VREF"] = values[15] else: - raise ValueError('EEPROM data format not supported (header: %s)' % header) + raise ValueError("EEPROM data format not supported (header: %s)" % header) def get_temperature(self, channel): - '''Reading temperature - ''' + """Reading temperature""" # NTC type SEMITEC 103KT1608 http://www.semitec.co.jp/english/products/pdf/KT_Thermistor.pdf # # R_NTC = R_25 * exp(B_NTC * (1/T - 1/T_25)) @@ -214,28 +238,40 @@ def get_temperature(self, channel): # new NTC on FE-I4 # NTC type TDK NTCG163JF103FT1 # - kwargs = self._ch_map[channel]['NTC'] + kwargs = self._ch_map[channel]["NTC"] temp_raw = self._get_adc_value(**kwargs) - v_adc = ((temp_raw - self._ch_cal[channel]['ADCV']['offset']) / self._ch_cal[channel]['ADCV']['gain']) # voltage, VDDA1 - k = self._ch_cal[channel]['NTC']['R4'] / (self._ch_cal[channel]['NTC']['R2'] + self._ch_cal[channel]['NTC']['R4']) # reference voltage divider - r_ntc = self._ch_cal[channel]['NTC']['R1'] * (k - v_adc / self._ch_cal[channel]['NTC']['VREF']) / (1 - k + v_adc / self._ch_cal[channel]['NTC']['VREF']) # NTC resistance + # voltage, VDDA1 + v_adc = (temp_raw - self._ch_cal[channel]["ADCV"]["offset"]) / self._ch_cal[channel]["ADCV"]["gain"] + # reference voltage divider + k = self._ch_cal[channel]["NTC"]["R4"] / ( + self._ch_cal[channel]["NTC"]["R2"] + self._ch_cal[channel]["NTC"]["R4"] + ) + # NTC resistance + r_ntc = ( + self._ch_cal[channel]["NTC"]["R1"] + * (k - v_adc / self._ch_cal[channel]["NTC"]["VREF"]) + / (1 - k + v_adc / self._ch_cal[channel]["NTC"]["VREF"]) + ) - return (self._ch_cal[channel]['NTC']['B_NTC'] * self.T_KELVIN_25) / (self._ch_cal[channel]['NTC']['B_NTC'] + self.T_KELVIN_25 * log(r_ntc / self._ch_cal[channel]['NTC']['R_NTC_25'])) - self.T_KELVIN_0 # NTC temperature + return (self._ch_cal[channel]["NTC"]["B_NTC"] * self.T_KELVIN_25) / ( + self._ch_cal[channel]["NTC"]["B_NTC"] + + self.T_KELVIN_25 * log(r_ntc / self._ch_cal[channel]["NTC"]["R_NTC_25"]) + ) - self.T_KELVIN_0 # NTC temperature - def set_current_limit(self, channel, value, unit='A'): - '''Setting current limit + def set_current_limit(self, channel, value, unit="A"): + """Setting current limit Note: same limit for all channels. - ''' - dac_offset = self._ch_cal[channel]['DACI']['offset'] - dac_gain = self._ch_cal[channel]['DACI']['gain'] + """ + dac_offset = self._ch_cal[channel]["DACI"]["offset"] + dac_gain = self._ch_cal[channel]["DACI"]["gain"] - if unit == 'raw': + if unit == "raw": value = value - elif unit == 'A': + elif unit == "A": value = int((value - dac_offset) / dac_gain) - elif unit == 'mA': + elif unit == "mA": value = int((value / 1000 - dac_offset) / dac_gain) else: raise TypeError("Invalid unit type.") diff --git a/basil/HL/FadcConf.py b/basil/HL/FadcConf.py index 625b852a7..d961da6f0 100644 --- a/basil/HL/FadcConf.py +++ b/basil/HL/FadcConf.py @@ -8,12 +8,10 @@ from basil.HL.RegisterHardwareLayer import HardwareLayer - logger = logging.getLogger(__name__) class FadcConf(HardwareLayer): - def __init__(self, intf, conf): super(FadcConf, self).__init__(intf, conf) @@ -37,12 +35,12 @@ def init(self): pass def enable_pattern(self, pattern): - self._intf.set_data([0x03, 0x80 | ((pattern & 0x3f00) >> 8)]) + self._intf.set_data([0x03, 0x80 | ((pattern & 0x3F00) >> 8)]) self._intf.start() while not self._intf.is_done(): pass - self._intf.set_data([0x04, pattern & 0xff]) + self._intf.set_data([0x04, pattern & 0xFF]) self._intf.start() while not self._intf.is_done(): pass diff --git a/basil/HL/GPAC.py b/basil/HL/GPAC.py index 151a90c2a..f7be9f358 100644 --- a/basil/HL/GPAC.py +++ b/basil/HL/GPAC.py @@ -6,24 +6,24 @@ # import logging -from struct import pack, unpack_from, calcsize +import string from array import array from collections import OrderedDict +from struct import calcsize, pack, unpack_from from time import sleep -import string -from basil.HL.HardwareLayer import HardwareLayer from basil.HL.FEI4AdapterCard import Eeprom24Lc128 - +from basil.HL.HardwareLayer import HardwareLayer logger = logging.getLogger(__name__) class MuxPca9540B(HardwareLayer): - '''PCA 9540B + """PCA 9540B I2C Bus Multiplexer (GPAC). - ''' + """ + PCA9540B_BASE_ADD = 0xE0 # generic slave address PCA9540B_SEL_CH0 = 0x04 # select channel 0 PCA9540B_SEL_CH1 = 0x05 # select channel 1 @@ -31,21 +31,22 @@ class MuxPca9540B(HardwareLayer): def __init__(self, intf, conf): super(MuxPca9540B, self).__init__(intf, conf) - self._base_addr = conf['base_addr'] + self._base_addr = conf["base_addr"] self.PCA9540B_ADD = self.PCA9540B_BASE_ADD def _set_i2c_mux(self, bus): - self._intf.write(self._base_addr + self.PCA9540B_ADD, array('B', pack('B', bus))) + self._intf.write(self._base_addr + self.PCA9540B_ADD, array("B", pack("B", bus))) def _get_i2c_mux(self): - return unpack_from('B', self._intf.read(self._base_addr + self.PCA9540B_ADD | 1, size=1))[0] + return unpack_from("B", self._intf.read(self._base_addr + self.PCA9540B_ADD | 1, size=1))[0] class GpioPca9554(HardwareLayer): - '''PCA 9554 + """PCA 9554 GPIO extension (GPAC). - ''' + """ + PCA9554_BASE_ADD = 0x40 # generic slave address PCA9554_CFG = 0x03 # configuration register: 1 -> input (default), 0 -> output PCA9554_POL = 0x02 # polarity inversion register @@ -54,7 +55,7 @@ class GpioPca9554(HardwareLayer): def __init__(self, intf, conf): super(GpioPca9554, self).__init__(intf, conf) - self._base_addr = conf['base_addr'] + self._base_addr = conf["base_addr"] self.PCA9554_ADD = self.PCA9554_BASE_ADD self.GPIO_CFG = 0x00 @@ -64,18 +65,22 @@ def init(self): self._intf.write(self._base_addr + self.PCA9554_ADD, (self.PCA9554_OUT, 0x00)) def _write_output_port_select(self, value): - self._intf.write(self._base_addr + self.PCA9554_ADD, array('B', pack('BB', self.PCA9554_CFG, value))) # configure output lines + self._intf.write( + self._base_addr + self.PCA9554_ADD, array("B", pack("BB", self.PCA9554_CFG, value)) + ) # configure output lines def _read_input_port(self): - self._intf.write(self._base_addr + self.PCA9554_ADD, array('B', pack('B', self.PCA9554_IN))) # set command byte - return unpack_from('B', self._intf.read(self._base_addr + self.PCA9554_ADD | 1, size=1))[0] # read input lines + self._intf.write(self._base_addr + self.PCA9554_ADD, array("B", pack("B", self.PCA9554_IN))) # set command byte + return unpack_from("B", self._intf.read(self._base_addr + self.PCA9554_ADD | 1, size=1))[0] # read input lines def _write_output_port(self, value): - self._intf.write(self._base_addr + self.PCA9554_ADD, array('B', pack('BB', self.PCA9554_OUT, value))) # write output lines + self._intf.write( + self._base_addr + self.PCA9554_ADD, array("B", pack("BB", self.PCA9554_OUT, value)) + ) # write output lines def _read_output_port(self): - self._intf.write(self._base_addr + self.PCA9554_ADD, array('B', pack('B', self.PCA9554_OUT))) - return unpack_from('B', self._intf.read(self._base_addr + self.PCA9554_ADD | 1, size=1))[0] + self._intf.write(self._base_addr + self.PCA9554_ADD, array("B", pack("B", self.PCA9554_OUT))) + return unpack_from("B", self._intf.read(self._base_addr + self.PCA9554_ADD | 1, size=1))[0] def _set_output_port(self, mask): self._write_output_port(mask | self._read_output_port()) @@ -88,20 +93,20 @@ def _get_input_port(self, mask): class PowerGpio(GpioPca9554): - '''Power GPIO - ''' + """Power GPIO""" + POWER_GPIO_ADD = GpioPca9554.PCA9554_BASE_ADD | 0x02 - POWER_GPIO_CFG = 0xf0 # LSB -> ON, MSB -> OC (over current read back) + POWER_GPIO_CFG = 0xF0 # LSB -> ON, MSB -> OC (over current read back) def __init__(self, intf, conf): super(PowerGpio, self).__init__(intf, conf) self.PCA9554_ADD = self.POWER_GPIO_ADD self.GPIO_CFG = self.POWER_GPIO_CFG - self._init.setdefault('no_power_reset', False) + self._init.setdefault("no_power_reset", False) def init(self): self._intf.write(self._base_addr + self.PCA9554_ADD, (self.PCA9554_CFG, self.GPIO_CFG)) - if self._init['no_power_reset'] is False: + if self._init["no_power_reset"] is False: logger.info("GPAC: power reset") self._intf.write(self._base_addr + self.PCA9554_ADD, (self.PCA9554_OUT, 0x00)) else: @@ -109,8 +114,8 @@ def init(self): class AdcMuxGpio(GpioPca9554): - '''ADC NUX GPIO - ''' + """ADC NUX GPIO""" + ADCMUX_GPIO_ADD = GpioPca9554.PCA9554_BASE_ADD ADCMUX_GPIO_CFG = 0x00 # all outputs @@ -121,8 +126,8 @@ def __init__(self, intf, conf): class CalMuxGpio(GpioPca9554): - '''CAL MUX GPIO - ''' + """CAL MUX GPIO""" + CALMUX_GPIO_ADD = GpioPca9554.PCA9554_BASE_ADD | 0x08 CALMUX_GPIO_CFG = 0x00 # all outputs CALMUX_GPIO_SEL = 0x20 @@ -135,10 +140,11 @@ def __init__(self, intf, conf): class DacDac7578(HardwareLayer): - '''DAC 7578 + """DAC 7578 Set voltage and current (GPAC). - ''' + """ + DAC7578_CMD_WRITE_CH = 0x00 # write DAC input register channel DAC7578_CMD_UPDATE_CH = 0x10 # write DAC input register channel DAC7578_CMD_WRITE_UPDATE_CH = 0x30 # write and update DAC input register channel @@ -147,21 +153,22 @@ class DacDac7578(HardwareLayer): def __init__(self, intf, conf): super(DacDac7578, self).__init__(intf, conf) - self._base_addr = conf['base_addr'] + self._base_addr = conf["base_addr"] def _set_dac_value(self, address, dac_ch, value): - msb = (value >> 4) # MSB first - lsb = (value << 4) & 0xff # LSB left aligned + msb = value >> 4 # MSB first + lsb = (value << 4) & 0xFF # LSB left aligned - data = array('B', pack('BBB', self.DAC7578_CMD_WRITE_UPDATE_CH | dac_ch, msb, lsb)) + data = array("B", pack("BBB", self.DAC7578_CMD_WRITE_UPDATE_CH | dac_ch, msb, lsb)) self._intf.write(self._base_addr + address, data) class AdcMax11644(HardwareLayer): - '''ADC MAX11644 + """ADC MAX11644 Read current and voltage (GPAC). - ''' + """ + MAX11644_ADD = 0x6C # slave address # setup register MAX11644_SETUP = 0x80 # defines setup register access @@ -179,20 +186,21 @@ class AdcMax11644(HardwareLayer): def __init__(self, intf, conf): super(AdcMax11644, self).__init__(intf, conf) - self._base_addr = conf['base_addr'] + self._base_addr = conf["base_addr"] def _setup_adc(self, flags): - '''Initialize ADC - ''' - self._intf.write(self._base_addr + self.MAX11644_ADD, array('B', pack('B', flags | self.MAX11644_SETUP))) + """Initialize ADC""" + self._intf.write(self._base_addr + self.MAX11644_ADD, array("B", pack("B", flags | self.MAX11644_SETUP))) def _get_adc_value(self, average=None): def read_data(): - self._intf.write(self._base_addr + self.MAX11644_ADD, array('B', pack('B', self.ADC_CONF))) # single-ended inputs, conversion of both channels in a scan + self._intf.write( + self._base_addr + self.MAX11644_ADD, array("B", pack("B", self.ADC_CONF)) + ) # single-ended inputs, conversion of both channels in a scan data = self._intf.read(self._base_addr + self.MAX11644_ADD | 1, size=4) - raw = unpack_from('>HH', data) - return raw[0] & 0xfff, raw[1] & 0xfff # ch0, ch1 + raw = unpack_from(">HH", data) + return raw[0] & 0xFFF, raw[1] & 0xFFF # ch0, ch1 if average: raw_ch0 = 0 @@ -216,7 +224,7 @@ class I2cAnalogChannel(AdcMax11644, DacDac7578, MuxPca9540B): def __init__(self, intf, conf): super(I2cAnalogChannel, self).__init__(intf, conf) - self._base_addr = conf['base_addr'] + self._base_addr = conf["base_addr"] self.adc_mux_gpio = AdcMuxGpio(intf, conf) self.power_gpio = PowerGpio(intf, conf) @@ -287,7 +295,7 @@ def _write_eeprom(self, address, data): class GPAC(I2cAnalogChannel, I2cEeprom): - '''GPAC interface + """GPAC interface Note: - Solder 100 Ohm resistor parallel to C55 @@ -295,16 +303,17 @@ class GPAC(I2cAnalogChannel, I2cEeprom): - Close JP2 (2-3, SENSE-GND) - Close JP3 (2-3, REF_2.048V-VREF_1) - Outputs are clamped to potential of PWR0, keep potential of PWR0 close to supply voltage - ''' + """ + # EEPROM data V1 - HEADER_GPAC = 0xa101 + HEADER_GPAC = 0xA101 HEADER_ADDR = 0 - HEADER_FORMAT = '>H' # Version of EEPROM data + HEADER_FORMAT = ">H" # Version of EEPROM data ID_ADDR = HEADER_ADDR + calcsize(HEADER_FORMAT) - ID_FORMAT = '>H' # Adapter Card ID - CAL_DATA_CH_GPAC_FORMAT = '64sdddddddddd' + ID_FORMAT = ">H" # Adapter Card ID + CAL_DATA_CH_GPAC_FORMAT = "64sdddddddddd" CAL_DATA_ADDR = ID_ADDR + calcsize(ID_FORMAT) - CAL_DATA_GPAC_FORMAT = '<' + 22 * CAL_DATA_CH_GPAC_FORMAT + CAL_DATA_GPAC_FORMAT = "<" + 22 * CAL_DATA_CH_GPAC_FORMAT # DAC DAC7578_1_ADD = 0x90 @@ -318,433 +327,503 @@ class GPAC(I2cAnalogChannel, I2cEeprom): # Channel mappings _ch_map = { - 'PWR0': { - 'DAC': {'address': DAC7578_1_ADD, 'dac_ch': 1}, - 'ADCV': {'address': 16, 'adc_ch': 0}, - 'ADCI': {'address': 16, 'adc_ch': 1}, - 'GPIOEN': {'bit': 1}, - 'GPIOOC': {'bit': 16}, + "PWR0": { + "DAC": {"address": DAC7578_1_ADD, "dac_ch": 1}, + "ADCV": {"address": 16, "adc_ch": 0}, + "ADCI": {"address": 16, "adc_ch": 1}, + "GPIOEN": {"bit": 1}, + "GPIOOC": {"bit": 16}, }, - 'PWR1': { - 'DAC': {'address': DAC7578_1_ADD, 'dac_ch': 2}, - 'ADCV': {'address': 17, 'adc_ch': 0}, - 'ADCI': {'address': 17, 'adc_ch': 1}, - 'GPIOEN': {'bit': 2}, - 'GPIOOC': {'bit': 32}, + "PWR1": { + "DAC": {"address": DAC7578_1_ADD, "dac_ch": 2}, + "ADCV": {"address": 17, "adc_ch": 0}, + "ADCI": {"address": 17, "adc_ch": 1}, + "GPIOEN": {"bit": 2}, + "GPIOOC": {"bit": 32}, }, - 'PWR2': { - 'DAC': {'address': DAC7578_1_ADD, 'dac_ch': 3}, - 'ADCV': {'address': 18, 'adc_ch': 0}, - 'ADCI': {'address': 18, 'adc_ch': 1}, - 'GPIOEN': {'bit': 4}, - 'GPIOOC': {'bit': 64}, + "PWR2": { + "DAC": {"address": DAC7578_1_ADD, "dac_ch": 3}, + "ADCV": {"address": 18, "adc_ch": 0}, + "ADCI": {"address": 18, "adc_ch": 1}, + "GPIOEN": {"bit": 4}, + "GPIOOC": {"bit": 64}, }, - 'PWR3': { - 'DAC': {'address': DAC7578_1_ADD, 'dac_ch': 4}, - 'ADCV': {'address': 19, 'adc_ch': 0}, - 'ADCI': {'address': 19, 'adc_ch': 1}, - 'GPIOEN': {'bit': 8}, - 'GPIOOC': {'bit': 128}, + "PWR3": { + "DAC": {"address": DAC7578_1_ADD, "dac_ch": 4}, + "ADCV": {"address": 19, "adc_ch": 0}, + "ADCI": {"address": 19, "adc_ch": 1}, + "GPIOEN": {"bit": 8}, + "GPIOOC": {"bit": 128}, }, - 'VSRC0': { - 'DAC': {'address': DAC7578_3_ADD, 'dac_ch': 1}, - 'ADCV': {'address': 15, 'adc_ch': 0}, - 'ADCI': {'address': 15, 'adc_ch': 1}, + "VSRC0": { + "DAC": {"address": DAC7578_3_ADD, "dac_ch": 1}, + "ADCV": {"address": 15, "adc_ch": 0}, + "ADCI": {"address": 15, "adc_ch": 1}, }, - - 'VSRC1': { - 'DAC': {'address': DAC7578_3_ADD, 'dac_ch': 2}, - 'ADCV': {'address': 14, 'adc_ch': 0}, - 'ADCI': {'address': 14, 'adc_ch': 1}, + "VSRC1": { + "DAC": {"address": DAC7578_3_ADD, "dac_ch": 2}, + "ADCV": {"address": 14, "adc_ch": 0}, + "ADCI": {"address": 14, "adc_ch": 1}, }, - - 'VSRC2': { - 'DAC': {'address': DAC7578_3_ADD, 'dac_ch': 3}, - 'ADCV': {'address': 13, 'adc_ch': 0}, - 'ADCI': {'address': 13, 'adc_ch': 1}, + "VSRC2": { + "DAC": {"address": DAC7578_3_ADD, "dac_ch": 3}, + "ADCV": {"address": 13, "adc_ch": 0}, + "ADCI": {"address": 13, "adc_ch": 1}, }, - - 'VSRC3': { - 'DAC': {'address': DAC7578_3_ADD, 'dac_ch': 4}, - 'ADCV': {'address': 12, 'adc_ch': 0}, - 'ADCI': {'address': 12, 'adc_ch': 1}, + "VSRC3": { + "DAC": {"address": DAC7578_3_ADD, "dac_ch": 4}, + "ADCV": {"address": 12, "adc_ch": 0}, + "ADCI": {"address": 12, "adc_ch": 1}, }, - 'INJ0': { - 'DAC': {'address': DAC7578_3_ADD, 'dac_ch': 5}, + "INJ0": { + "DAC": {"address": DAC7578_3_ADD, "dac_ch": 5}, }, - 'INJ1': { - 'DAC': {'address': DAC7578_3_ADD, 'dac_ch': 6}, + "INJ1": { + "DAC": {"address": DAC7578_3_ADD, "dac_ch": 6}, }, - 'ISRC0': { - 'DAC': {'address': DAC7578_1_ADD, 'dac_ch': 5}, - 'ADCV': {'address': 20, 'adc_ch': 0}, - 'ADCI': {'address': 20, 'adc_ch': 1}, + "ISRC0": { + "DAC": {"address": DAC7578_1_ADD, "dac_ch": 5}, + "ADCV": {"address": 20, "adc_ch": 0}, + "ADCI": {"address": 20, "adc_ch": 1}, }, - 'ISRC1': { - 'DAC': {'address': DAC7578_1_ADD, 'dac_ch': 6}, - 'ADCV': {'address': 21, 'adc_ch': 0}, - 'ADCI': {'address': 21, 'adc_ch': 1}, + "ISRC1": { + "DAC": {"address": DAC7578_1_ADD, "dac_ch": 6}, + "ADCV": {"address": 21, "adc_ch": 0}, + "ADCI": {"address": 21, "adc_ch": 1}, }, - 'ISRC2': { - 'DAC': {'address': DAC7578_1_ADD, 'dac_ch': 7}, - 'ADCV': {'address': 22, 'adc_ch': 0}, - 'ADCI': {'address': 22, 'adc_ch': 1}, + "ISRC2": { + "DAC": {"address": DAC7578_1_ADD, "dac_ch": 7}, + "ADCV": {"address": 22, "adc_ch": 0}, + "ADCI": {"address": 22, "adc_ch": 1}, }, - 'ISRC3': { - 'DAC': {'address': DAC7578_2_ADD, 'dac_ch': 0}, - 'ADCV': {'address': 23, 'adc_ch': 0}, - 'ADCI': {'address': 23, 'adc_ch': 1}, + "ISRC3": { + "DAC": {"address": DAC7578_2_ADD, "dac_ch": 0}, + "ADCV": {"address": 23, "adc_ch": 0}, + "ADCI": {"address": 23, "adc_ch": 1}, }, - 'ISRC4': { - 'DAC': {'address': DAC7578_2_ADD, 'dac_ch': 1}, - 'ADCV': {'address': 24, 'adc_ch': 0}, - 'ADCI': {'address': 24, 'adc_ch': 1}, + "ISRC4": { + "DAC": {"address": DAC7578_2_ADD, "dac_ch": 1}, + "ADCV": {"address": 24, "adc_ch": 0}, + "ADCI": {"address": 24, "adc_ch": 1}, }, - 'ISRC5': { - 'DAC': {'address': DAC7578_2_ADD, 'dac_ch': 2}, - 'ADCV': {'address': 25, 'adc_ch': 0}, - 'ADCI': {'address': 25, 'adc_ch': 1}, + "ISRC5": { + "DAC": {"address": DAC7578_2_ADD, "dac_ch": 2}, + "ADCV": {"address": 25, "adc_ch": 0}, + "ADCI": {"address": 25, "adc_ch": 1}, }, - - 'ISRC6': { - 'DAC': {'address': DAC7578_2_ADD, 'dac_ch': 3}, - 'ADCV': {'address': 26, 'adc_ch': 0}, - 'ADCI': {'address': 26, 'adc_ch': 1}, + "ISRC6": { + "DAC": {"address": DAC7578_2_ADD, "dac_ch": 3}, + "ADCV": {"address": 26, "adc_ch": 0}, + "ADCI": {"address": 26, "adc_ch": 1}, }, - 'ISRC7': { - 'DAC': {'address': DAC7578_2_ADD, 'dac_ch': 4}, - 'ADCV': {'address': 27, 'adc_ch': 0}, - 'ADCI': {'address': 27, 'adc_ch': 1}, + "ISRC7": { + "DAC": {"address": DAC7578_2_ADD, "dac_ch": 4}, + "ADCV": {"address": 27, "adc_ch": 0}, + "ADCI": {"address": 27, "adc_ch": 1}, }, - 'ISRC8': { - 'DAC': {'address': DAC7578_2_ADD, 'dac_ch': 5}, - 'ADCV': {'address': 28, 'adc_ch': 0}, - 'ADCI': {'address': 28, 'adc_ch': 1}, + "ISRC8": { + "DAC": {"address": DAC7578_2_ADD, "dac_ch": 5}, + "ADCV": {"address": 28, "adc_ch": 0}, + "ADCI": {"address": 28, "adc_ch": 1}, }, - 'ISRC9': { - 'DAC': {'address': DAC7578_2_ADD, 'dac_ch': 6}, - 'ADCV': {'address': 29, 'adc_ch': 0}, - 'ADCI': {'address': 29, 'adc_ch': 1}, + "ISRC9": { + "DAC": {"address": DAC7578_2_ADD, "dac_ch": 6}, + "ADCV": {"address": 29, "adc_ch": 0}, + "ADCI": {"address": 29, "adc_ch": 1}, }, - 'ISRC10': { - 'DAC': {'address': DAC7578_2_ADD, 'dac_ch': 7}, - 'ADCV': {'address': 30, 'adc_ch': 0}, - 'ADCI': {'address': 30, 'adc_ch': 1}, + "ISRC10": { + "DAC": {"address": DAC7578_2_ADD, "dac_ch": 7}, + "ADCV": {"address": 30, "adc_ch": 0}, + "ADCI": {"address": 30, "adc_ch": 1}, }, - 'ISRC11': { - 'DAC': {'address': DAC7578_3_ADD, 'dac_ch': 0}, - 'ADCV': {'address': 31, 'adc_ch': 0}, - 'ADCI': {'address': 31, 'adc_ch': 1}, + "ISRC11": { + "DAC": {"address": DAC7578_3_ADD, "dac_ch": 0}, + "ADCV": {"address": 31, "adc_ch": 0}, + "ADCI": {"address": 31, "adc_ch": 1}, }, # reead-only - 'VREF': { - 'ADCV': {'address': 0, 'adc_ch': 0}, + "VREF": { + "ADCV": {"address": 0, "adc_ch": 0}, }, - 'VREF/2': { - 'ADCV': {'address': 1, 'adc_ch': 0}, + "VREF/2": { + "ADCV": {"address": 1, "adc_ch": 0}, }, - 'AUX0': { - 'ADCV': {'address': 11, 'adc_ch': 0}, + "AUX0": { + "ADCV": {"address": 11, "adc_ch": 0}, }, - 'AUX1': { - 'ADCV': {'address': 10, 'adc_ch': 0}, + "AUX1": { + "ADCV": {"address": 10, "adc_ch": 0}, }, - 'AUX2': { - 'ADCV': {'address': 9, 'adc_ch': 0}, + "AUX2": { + "ADCV": {"address": 9, "adc_ch": 0}, }, - 'AUX3': { - 'ADCV': {'address': 8, 'adc_ch': 0}, + "AUX3": { + "ADCV": {"address": 8, "adc_ch": 0}, }, } def __init__(self, intf, conf): super(GPAC, self).__init__(intf, conf) - self._base_addr = conf['base_addr'] + self._base_addr = conf["base_addr"] # Channel calibrations - self._ch_cal = OrderedDict([ - ('PWR0', { - 'name': '', - 'default': 0.0, - 'min': 0.0, - 'max': 1.0, - 'limit': 0.0, # PWR only - 'Vref': float('nan'), - 'DAC': {'offset': 2826.0, 'gain': -0.5}, - 'ADCV': {'offset': 0.0, 'gain': 1.0}, - 'ADCI': {'offset': 0.0, 'gain': 10.0} - }), - ('PWR1', { - 'name': '', - 'default': 0.0, - 'min': 0.0, - 'max': 1.0, - 'limit': 0.0, # PWR only - 'Vref': float('nan'), - 'DAC': {'offset': 2826.0, 'gain': -0.5}, - 'ADCV': {'offset': 0.0, 'gain': 1.0}, - 'ADCI': {'offset': 0.0, 'gain': 10.0} - }), - ('PWR2', { - 'name': '', - 'default': 0.0, - 'min': 0.0, - 'max': 1.0, - 'limit': 0.0, # PWR only - 'Vref': float('nan'), - 'DAC': {'offset': 2826.0, 'gain': -0.5}, - 'ADCV': {'offset': 0.0, 'gain': 1.0}, - 'ADCI': {'offset': 0.0, 'gain': 10.0} - }), - ('PWR3', { - 'name': '', - 'default': 0.0, - 'min': 0.0, - 'max': 1.0, - 'limit': 0.0, # PWR only - 'Vref': float('nan'), - 'DAC': {'offset': 2826.0, 'gain': -0.5}, - 'ADCV': {'offset': 0.0, 'gain': 1.0}, - 'ADCI': {'offset': 0.0, 'gain': 10.0} - }), - ('VSRC0', { - 'name': '', - 'default': 0.0, - 'min': 0.0, - 'max': 1.0, - 'limit': 0.0, # PWR only - 'Vref': float('nan'), - 'DAC': {'offset': 0.0, 'gain': 0.5}, - 'ADCV': {'offset': 0.0, 'gain': 2.0}, - 'ADCI': {'offset': 0.0, 'gain': 2.0} - }), - ('VSRC1', { - 'name': '', - 'default': 0.0, - 'min': 0.0, - 'max': 1.0, - 'limit': 0.0, # PWR only - 'Vref': float('nan'), - 'DAC': {'offset': 0.0, 'gain': 0.5}, - 'ADCV': {'offset': 0.0, 'gain': 2.0}, - 'ADCI': {'offset': 0.0, 'gain': 2.0} - }), - ('VSRC2', { - 'name': '', - 'default': 0.0, - 'min': 0.0, - 'max': 1.0, - 'limit': 0.0, # PWR only - 'Vref': float('nan'), - 'DAC': {'offset': 0.0, 'gain': 0.5}, - 'ADCV': {'offset': 0.0, 'gain': 2.0}, - 'ADCI': {'offset': 0.0, 'gain': 2.0} - }), - ('VSRC3', { - 'name': '', - 'default': 0.0, - 'min': 0.0, - 'max': 1.0, - 'limit': 0.0, # PWR only - 'Vref': float('nan'), - 'DAC': {'offset': 0.0, 'gain': 0.5}, - 'ADCV': {'offset': 0.0, 'gain': 2.0}, - 'ADCI': {'offset': 0.0, 'gain': 2.0} - }), - ('INJ0', { - 'name': '', - 'default': 0.0, - 'min': 0.0, - 'max': 1.0, - 'limit': 0.0, # PWR only - 'Vref': float('nan'), - 'DAC': {'offset': 0.0, 'gain': 0.5}, - 'ADCV': {'offset': 0.0, 'gain': 2.0}, - 'ADCI': {'offset': 0.0, 'gain': 2.0} - }), - ('INJ1', { - 'name': '', - 'default': 0.0, - 'min': 0.0, - 'max': 1.0, - 'limit': 0.0, # PWR only - 'Vref': float('nan'), - 'DAC': {'offset': 0.0, 'gain': 0.5}, - 'ADCV': {'offset': 0.0, 'gain': 2.0}, - 'ADCI': {'offset': 0.0, 'gain': 2.0} - }), - ('ISRC0', { - 'name': '', - 'default': 0.0, - 'min': 0.0, - 'max': 1.0, - 'limit': 0.0, # PWR only - 'Vref': float('nan'), - 'DAC': {'offset': -1024.0, 'gain': 0.5}, - 'ADCV': {'offset': 0.0, 'gain': 2.0}, - 'ADCI': {'offset': 0.0, 'gain': 2.0} - }), - ('ISRC1', { - 'name': '', - 'default': 0.0, - 'min': 0.0, - 'max': 1.0, - 'limit': 0.0, # PWR only - 'Vref': float('nan'), - 'DAC': {'offset': -1024.0, 'gain': 0.5}, - 'ADCV': {'offset': 0.0, 'gain': 2.0}, - 'ADCI': {'offset': 0.0, 'gain': 2.0} - }), - ('ISRC2', { - 'name': '', - 'default': 0.0, - 'min': 0.0, - 'max': 1.0, - 'limit': 0.0, # PWR only - 'Vref': float('nan'), - 'DAC': {'offset': -1024.0, 'gain': 0.5}, - 'ADCV': {'offset': 0.0, 'gain': 2.0}, - 'ADCI': {'offset': 0.0, 'gain': 2.0} - }), - ('ISRC3', { - 'name': '', - 'default': 0.0, - 'min': 0.0, - 'max': 1.0, - 'limit': 0.0, # PWR only - 'Vref': float('nan'), - 'DAC': {'offset': -1024.0, 'gain': 0.5}, - 'ADCV': {'offset': 0.0, 'gain': 2.0}, - 'ADCI': {'offset': 0.0, 'gain': 2.0} - }), - ('ISRC4', { - 'name': '', - 'default': 0.0, - 'min': 0.0, - 'max': 1.0, - 'limit': 0.0, # PWR only - 'Vref': float('nan'), - 'DAC': {'offset': -1024.0, 'gain': 0.5}, - 'ADCV': {'offset': 0.0, 'gain': 2.0}, - 'ADCI': {'offset': 0.0, 'gain': 2.0} - }), - ('ISRC5', { - 'name': '', - 'default': 0.0, - 'min': 0.0, - 'max': 1.0, - 'limit': 0.0, # PWR only - 'Vref': float('nan'), - 'DAC': {'offset': -1024.0, 'gain': 0.5}, - 'ADCV': {'offset': 0.0, 'gain': 2.0}, - 'ADCI': {'offset': 0.0, 'gain': 2.0} - }), - ('ISRC6', { - 'name': '', - 'default': 0.0, - 'min': 0.0, - 'max': 1.0, - 'limit': 0.0, # PWR only - 'Vref': float('nan'), - 'DAC': {'offset': -1024.0, 'gain': 0.5}, - 'ADCV': {'offset': 0.0, 'gain': 2.0}, - 'ADCI': {'offset': 0.0, 'gain': 2.0} - }), - ('ISRC7', { - 'name': '', - 'default': 0.0, - 'min': 0.0, - 'max': 1.0, - 'limit': 0.0, # PWR only - 'Vref': float('nan'), - 'DAC': {'offset': -1024.0, 'gain': 0.5}, - 'ADCV': {'offset': 0.0, 'gain': 2.0}, - 'ADCI': {'offset': 0.0, 'gain': 2.0} - }), - ('ISRC8', { - 'name': '', - 'default': 0.0, - 'min': 0.0, - 'max': 1.0, - 'limit': 0.0, # PWR only - 'Vref': float('nan'), - 'DAC': {'offset': -1024.0, 'gain': 0.5}, - 'ADCV': {'offset': 0.0, 'gain': 2.0}, - 'ADCI': {'offset': 0.0, 'gain': 2.0} - }), - ('ISRC9', { - 'name': '', - 'default': 0.0, - 'min': 0.0, - 'max': 1.0, - 'limit': 0.0, # PWR only - 'Vref': float('nan'), - 'DAC': {'offset': -1024.0, 'gain': 0.5}, - 'ADCV': {'offset': 0.0, 'gain': 2.0}, - 'ADCI': {'offset': 0.0, 'gain': 2.0} - }), - ('ISRC10', { - 'name': '', - 'default': 0.0, - 'min': 0.0, - 'max': 1.0, - 'limit': 0.0, # PWR only - 'Vref': float('nan'), - 'DAC': {'offset': -1024.0, 'gain': 0.5}, - 'ADCV': {'offset': 0.0, 'gain': 2.0}, - 'ADCI': {'offset': 0.0, 'gain': 2.0} - }), - ('ISRC11', { - 'name': '', - 'default': 0.0, - 'min': 0.0, - 'max': 1.0, - 'limit': 0.0, # PWR only - 'Vref': float('nan'), - 'DAC': {'offset': -1024.0, 'gain': 0.5}, - 'ADCV': {'offset': 0.0, 'gain': 2.0}, - 'ADCI': {'offset': 0.0, 'gain': 2.0} - }), - ]) + self._ch_cal = OrderedDict( + [ + ( + "PWR0", + { + "name": "", + "default": 0.0, + "min": 0.0, + "max": 1.0, + "limit": 0.0, # PWR only + "Vref": float("nan"), + "DAC": {"offset": 2826.0, "gain": -0.5}, + "ADCV": {"offset": 0.0, "gain": 1.0}, + "ADCI": {"offset": 0.0, "gain": 10.0}, + }, + ), + ( + "PWR1", + { + "name": "", + "default": 0.0, + "min": 0.0, + "max": 1.0, + "limit": 0.0, # PWR only + "Vref": float("nan"), + "DAC": {"offset": 2826.0, "gain": -0.5}, + "ADCV": {"offset": 0.0, "gain": 1.0}, + "ADCI": {"offset": 0.0, "gain": 10.0}, + }, + ), + ( + "PWR2", + { + "name": "", + "default": 0.0, + "min": 0.0, + "max": 1.0, + "limit": 0.0, # PWR only + "Vref": float("nan"), + "DAC": {"offset": 2826.0, "gain": -0.5}, + "ADCV": {"offset": 0.0, "gain": 1.0}, + "ADCI": {"offset": 0.0, "gain": 10.0}, + }, + ), + ( + "PWR3", + { + "name": "", + "default": 0.0, + "min": 0.0, + "max": 1.0, + "limit": 0.0, # PWR only + "Vref": float("nan"), + "DAC": {"offset": 2826.0, "gain": -0.5}, + "ADCV": {"offset": 0.0, "gain": 1.0}, + "ADCI": {"offset": 0.0, "gain": 10.0}, + }, + ), + ( + "VSRC0", + { + "name": "", + "default": 0.0, + "min": 0.0, + "max": 1.0, + "limit": 0.0, # PWR only + "Vref": float("nan"), + "DAC": {"offset": 0.0, "gain": 0.5}, + "ADCV": {"offset": 0.0, "gain": 2.0}, + "ADCI": {"offset": 0.0, "gain": 2.0}, + }, + ), + ( + "VSRC1", + { + "name": "", + "default": 0.0, + "min": 0.0, + "max": 1.0, + "limit": 0.0, # PWR only + "Vref": float("nan"), + "DAC": {"offset": 0.0, "gain": 0.5}, + "ADCV": {"offset": 0.0, "gain": 2.0}, + "ADCI": {"offset": 0.0, "gain": 2.0}, + }, + ), + ( + "VSRC2", + { + "name": "", + "default": 0.0, + "min": 0.0, + "max": 1.0, + "limit": 0.0, # PWR only + "Vref": float("nan"), + "DAC": {"offset": 0.0, "gain": 0.5}, + "ADCV": {"offset": 0.0, "gain": 2.0}, + "ADCI": {"offset": 0.0, "gain": 2.0}, + }, + ), + ( + "VSRC3", + { + "name": "", + "default": 0.0, + "min": 0.0, + "max": 1.0, + "limit": 0.0, # PWR only + "Vref": float("nan"), + "DAC": {"offset": 0.0, "gain": 0.5}, + "ADCV": {"offset": 0.0, "gain": 2.0}, + "ADCI": {"offset": 0.0, "gain": 2.0}, + }, + ), + ( + "INJ0", + { + "name": "", + "default": 0.0, + "min": 0.0, + "max": 1.0, + "limit": 0.0, # PWR only + "Vref": float("nan"), + "DAC": {"offset": 0.0, "gain": 0.5}, + "ADCV": {"offset": 0.0, "gain": 2.0}, + "ADCI": {"offset": 0.0, "gain": 2.0}, + }, + ), + ( + "INJ1", + { + "name": "", + "default": 0.0, + "min": 0.0, + "max": 1.0, + "limit": 0.0, # PWR only + "Vref": float("nan"), + "DAC": {"offset": 0.0, "gain": 0.5}, + "ADCV": {"offset": 0.0, "gain": 2.0}, + "ADCI": {"offset": 0.0, "gain": 2.0}, + }, + ), + ( + "ISRC0", + { + "name": "", + "default": 0.0, + "min": 0.0, + "max": 1.0, + "limit": 0.0, # PWR only + "Vref": float("nan"), + "DAC": {"offset": -1024.0, "gain": 0.5}, + "ADCV": {"offset": 0.0, "gain": 2.0}, + "ADCI": {"offset": 0.0, "gain": 2.0}, + }, + ), + ( + "ISRC1", + { + "name": "", + "default": 0.0, + "min": 0.0, + "max": 1.0, + "limit": 0.0, # PWR only + "Vref": float("nan"), + "DAC": {"offset": -1024.0, "gain": 0.5}, + "ADCV": {"offset": 0.0, "gain": 2.0}, + "ADCI": {"offset": 0.0, "gain": 2.0}, + }, + ), + ( + "ISRC2", + { + "name": "", + "default": 0.0, + "min": 0.0, + "max": 1.0, + "limit": 0.0, # PWR only + "Vref": float("nan"), + "DAC": {"offset": -1024.0, "gain": 0.5}, + "ADCV": {"offset": 0.0, "gain": 2.0}, + "ADCI": {"offset": 0.0, "gain": 2.0}, + }, + ), + ( + "ISRC3", + { + "name": "", + "default": 0.0, + "min": 0.0, + "max": 1.0, + "limit": 0.0, # PWR only + "Vref": float("nan"), + "DAC": {"offset": -1024.0, "gain": 0.5}, + "ADCV": {"offset": 0.0, "gain": 2.0}, + "ADCI": {"offset": 0.0, "gain": 2.0}, + }, + ), + ( + "ISRC4", + { + "name": "", + "default": 0.0, + "min": 0.0, + "max": 1.0, + "limit": 0.0, # PWR only + "Vref": float("nan"), + "DAC": {"offset": -1024.0, "gain": 0.5}, + "ADCV": {"offset": 0.0, "gain": 2.0}, + "ADCI": {"offset": 0.0, "gain": 2.0}, + }, + ), + ( + "ISRC5", + { + "name": "", + "default": 0.0, + "min": 0.0, + "max": 1.0, + "limit": 0.0, # PWR only + "Vref": float("nan"), + "DAC": {"offset": -1024.0, "gain": 0.5}, + "ADCV": {"offset": 0.0, "gain": 2.0}, + "ADCI": {"offset": 0.0, "gain": 2.0}, + }, + ), + ( + "ISRC6", + { + "name": "", + "default": 0.0, + "min": 0.0, + "max": 1.0, + "limit": 0.0, # PWR only + "Vref": float("nan"), + "DAC": {"offset": -1024.0, "gain": 0.5}, + "ADCV": {"offset": 0.0, "gain": 2.0}, + "ADCI": {"offset": 0.0, "gain": 2.0}, + }, + ), + ( + "ISRC7", + { + "name": "", + "default": 0.0, + "min": 0.0, + "max": 1.0, + "limit": 0.0, # PWR only + "Vref": float("nan"), + "DAC": {"offset": -1024.0, "gain": 0.5}, + "ADCV": {"offset": 0.0, "gain": 2.0}, + "ADCI": {"offset": 0.0, "gain": 2.0}, + }, + ), + ( + "ISRC8", + { + "name": "", + "default": 0.0, + "min": 0.0, + "max": 1.0, + "limit": 0.0, # PWR only + "Vref": float("nan"), + "DAC": {"offset": -1024.0, "gain": 0.5}, + "ADCV": {"offset": 0.0, "gain": 2.0}, + "ADCI": {"offset": 0.0, "gain": 2.0}, + }, + ), + ( + "ISRC9", + { + "name": "", + "default": 0.0, + "min": 0.0, + "max": 1.0, + "limit": 0.0, # PWR only + "Vref": float("nan"), + "DAC": {"offset": -1024.0, "gain": 0.5}, + "ADCV": {"offset": 0.0, "gain": 2.0}, + "ADCI": {"offset": 0.0, "gain": 2.0}, + }, + ), + ( + "ISRC10", + { + "name": "", + "default": 0.0, + "min": 0.0, + "max": 1.0, + "limit": 0.0, # PWR only + "Vref": float("nan"), + "DAC": {"offset": -1024.0, "gain": 0.5}, + "ADCV": {"offset": 0.0, "gain": 2.0}, + "ADCI": {"offset": 0.0, "gain": 2.0}, + }, + ), + ( + "ISRC11", + { + "name": "", + "default": 0.0, + "min": 0.0, + "max": 1.0, + "limit": 0.0, # PWR only + "Vref": float("nan"), + "DAC": {"offset": -1024.0, "gain": 0.5}, + "ADCV": {"offset": 0.0, "gain": 2.0}, + "ADCI": {"offset": 0.0, "gain": 2.0}, + }, + ), + ] + ) def init(self): # init DACs and ADCs super(GPAC, self).init() - self._init.setdefault('no_calibration', False) + self._init.setdefault("no_calibration", False) # read calibration - if not self._init['no_calibration']: + if not self._init["no_calibration"]: self.read_eeprom_calibration() - logger.info('Found adapter card: {} with ID {}'.format('General Purpose Analog Card (GPAC)', self.get_id())) + logger.info("Found adapter card: {} with ID {}".format("General Purpose Analog Card (GPAC)", self.get_id())) else: - logger.info('General Purpose Analog Card (GPAC): skip reading calibration parameters from EEPROM') + logger.info("General Purpose Analog Card (GPAC): skip reading calibration parameters from EEPROM") # setup current limit and current source - self.set_current_limit('PWR0', 0.1) + self.set_current_limit("PWR0", 0.1) for i in range(12): - self.set_current('ISRC' + str(i), 0.0) + self.set_current("ISRC" + str(i), 0.0) - def read_eeprom_calibration(self): # use default values for temperature, EEPROM values are usually not calibrated and random - '''Reading EEPROM calibration for sources and regulators - ''' + def read_eeprom_calibration( + self, + ): + # use default values for temperature, EEPROM values are usually not calibrated and random + """Reading EEPROM calibration for sources and regulators""" header = self.get_format() if header == self.HEADER_GPAC: data = self._read_eeprom(self.CAL_DATA_ADDR, size=calcsize(self.CAL_DATA_GPAC_FORMAT)) for idx, channel in enumerate(self._ch_cal.keys()): - ch_data = data[idx * calcsize(self.CAL_DATA_CH_GPAC_FORMAT):(idx + 1) * calcsize(self.CAL_DATA_CH_GPAC_FORMAT)] + ch_data = data[ + idx * calcsize(self.CAL_DATA_CH_GPAC_FORMAT) : (idx + 1) * calcsize(self.CAL_DATA_CH_GPAC_FORMAT) + ] values = unpack_from(self.CAL_DATA_CH_GPAC_FORMAT, ch_data) - self._ch_cal[channel]['name'] = "".join([c for c in values[0].decode('utf-8', errors='ignore') if (c in string.printable)]) # values[0].strip() - self._ch_cal[channel]['default'] = values[1] - self._ch_cal[channel]['min'] = values[2] - self._ch_cal[channel]['max'] = values[3] - self._ch_cal[channel]['ADCI']['gain'] = -values[4] # fix gain sign - self._ch_cal[channel]['ADCI']['offset'] = values[5] - self._ch_cal[channel]['ADCV']['gain'] = values[6] - self._ch_cal[channel]['ADCV']['offset'] = values[7] - self._ch_cal[channel]['DAC']['gain'] = values[8] - self._ch_cal[channel]['DAC']['offset'] = values[9] - self._ch_cal[channel]['limit'] = values[10] + self._ch_cal[channel]["name"] = "".join( + [c for c in values[0].decode("utf-8", errors="ignore") if (c in string.printable)] + ) # values[0].strip() + self._ch_cal[channel]["default"] = values[1] + self._ch_cal[channel]["min"] = values[2] + self._ch_cal[channel]["max"] = values[3] + self._ch_cal[channel]["ADCI"]["gain"] = -values[4] # fix gain sign + self._ch_cal[channel]["ADCI"]["offset"] = values[5] + self._ch_cal[channel]["ADCV"]["gain"] = values[6] + self._ch_cal[channel]["ADCV"]["offset"] = values[7] + self._ch_cal[channel]["DAC"]["gain"] = values[8] + self._ch_cal[channel]["DAC"]["offset"] = values[9] + self._ch_cal[channel]["limit"] = values[10] else: - raise ValueError('EEPROM data format not supported (header: %s)' % header) + raise ValueError("EEPROM data format not supported (header: %s)" % header) def get_format(self): ret = self._read_eeprom(self.HEADER_ADDR, size=calcsize(self.HEADER_FORMAT)) @@ -754,129 +833,125 @@ def get_id(self): ret = self._read_eeprom(self.ID_ADDR, size=calcsize(self.ID_FORMAT)) return unpack_from(self.ID_FORMAT, ret)[0] - def set_voltage(self, channel, value, unit='V'): - '''Setting voltage - ''' - dac_offset = self._ch_cal[channel]['DAC']['offset'] - dac_gain = self._ch_cal[channel]['DAC']['gain'] + def set_voltage(self, channel, value, unit="V"): + """Setting voltage""" + dac_offset = self._ch_cal[channel]["DAC"]["offset"] + dac_gain = self._ch_cal[channel]["DAC"]["gain"] - if unit == 'raw': + if unit == "raw": value = value - elif unit == 'V': + elif unit == "V": value = int((value * 1000 - dac_offset) / dac_gain) - elif unit == 'mV': + elif unit == "mV": value = int((value - dac_offset) / dac_gain) else: raise TypeError("Invalid unit type.") self._set_dac_value(channel=channel, value=value) - def get_voltage(self, channel, unit='V'): - '''Reading voltage - ''' - adc_ch = self._ch_map[channel]['ADCV']['adc_ch'] - address = self._ch_map[channel]['ADCV']['address'] + def get_voltage(self, channel, unit="V"): + """Reading voltage""" + adc_ch = self._ch_map[channel]["ADCV"]["adc_ch"] + address = self._ch_map[channel]["ADCV"]["address"] raw = self._get_adc_value(address=address)[adc_ch] - dac_offset = self._ch_cal[channel]['ADCV']['offset'] - dac_gain = self._ch_cal[channel]['ADCV']['gain'] + dac_offset = self._ch_cal[channel]["ADCV"]["offset"] + dac_gain = self._ch_cal[channel]["ADCV"]["gain"] - voltage = ((raw - dac_offset) / dac_gain) + voltage = (raw - dac_offset) / dac_gain - if unit == 'raw': + if unit == "raw": return raw - elif unit == 'V': + elif unit == "V": return voltage / 1000 - elif unit == 'mV': + elif unit == "mV": return voltage else: raise TypeError("Invalid unit type.") - def get_current(self, channel, unit='A'): - '''Reading current - ''' - values = self._get_adc_value(address=self._ch_map[channel]['ADCI']['address']) - raw = values[self._ch_map[channel]['ADCI']['adc_ch']] - dac_offset = self._ch_cal[channel]['ADCI']['offset'] - dac_gain = self._ch_cal[channel]['ADCI']['gain'] + def get_current(self, channel, unit="A"): + """Reading current""" + values = self._get_adc_value(address=self._ch_map[channel]["ADCI"]["address"]) + raw = values[self._ch_map[channel]["ADCI"]["adc_ch"]] + dac_offset = self._ch_cal[channel]["ADCI"]["offset"] + dac_gain = self._ch_cal[channel]["ADCI"]["gain"] - if 'PWR' in channel: - current = ((raw - dac_offset) / dac_gain) + if "PWR" in channel: + current = (raw - dac_offset) / dac_gain - if unit == 'raw': + if unit == "raw": return raw - elif unit == 'A': + elif unit == "A": return current / 1000 - elif unit == 'mA': + elif unit == "mA": return current - elif unit == 'uA': + elif unit == "uA": return current * 1000 else: raise TypeError("Invalid unit type.") else: - voltage = values[self._ch_map[channel]['ADCV']['adc_ch']] - current = (((raw - voltage) - dac_offset) / dac_gain) + voltage = values[self._ch_map[channel]["ADCV"]["adc_ch"]] + current = ((raw - voltage) - dac_offset) / dac_gain - if unit == 'raw': + if unit == "raw": return raw - elif unit == 'A': + elif unit == "A": return current / 1000000 - elif unit == 'mA': + elif unit == "mA": return current / 1000 - elif unit == 'uA': + elif unit == "uA": return current else: raise TypeError("Invalid unit type.") def set_enable(self, channel, value): - '''Enable/Disable output of power channel - ''' + """Enable/Disable output of power channel""" try: - bit = self._ch_map[channel]['GPIOEN']['bit'] + bit = self._ch_map[channel]["GPIOEN"]["bit"] except KeyError: - raise ValueError('set_enable() not supported for channel %s' % channel) + raise ValueError("set_enable() not supported for channel %s" % channel) self._set_power_gpio_value(bit=bit, value=value) def get_over_current(self, channel): - '''Reading over current status of power channel - ''' + """Reading over current status of power channel""" try: - bit = self._ch_map[channel]['GPIOOC']['bit'] + bit = self._ch_map[channel]["GPIOOC"]["bit"] except KeyError: - raise ValueError('get_over_current() not supported for channel %s' % channel) + raise ValueError("get_over_current() not supported for channel %s" % channel) return not self._get_power_gpio_value(bit) - def set_current_limit(self, channel, value, unit='A'): - '''Setting current limit + def set_current_limit(self, channel, value, unit="A"): + """Setting current limit Note: same limit for all channels. - ''' + """ # TODO: add units / calibration - if unit == 'raw': + if unit == "raw": value = value - elif unit == 'A': + elif unit == "A": value = int(value * 1000 * self.CURRENT_LIMIT_GAIN) - elif unit == 'mA': + elif unit == "mA": value = int(value * self.CURRENT_LIMIT_GAIN) - elif unit == 'uA': + elif unit == "uA": value = int(value / 1000 * self.CURRENT_LIMIT_GAIN) else: raise TypeError("Invalid unit type.") - I2cAnalogChannel._set_dac_value(self, address=self.CURRENT_LIMIT_DAC_SLAVE_ADD, dac_ch=self.CURRENT_LIMIT_DAC_CH, value=value) + I2cAnalogChannel._set_dac_value( + self, address=self.CURRENT_LIMIT_DAC_SLAVE_ADD, dac_ch=self.CURRENT_LIMIT_DAC_CH, value=value + ) - def set_current(self, channel, value, unit='A'): - '''Setting current of current source - ''' - dac_offset = self._ch_cal[channel]['DAC']['offset'] - dac_gain = self._ch_cal[channel]['DAC']['gain'] - if unit == 'raw': + def set_current(self, channel, value, unit="A"): + """Setting current of current source""" + dac_offset = self._ch_cal[channel]["DAC"]["offset"] + dac_gain = self._ch_cal[channel]["DAC"]["gain"] + if unit == "raw": value = value - elif unit == 'A': + elif unit == "A": value = int((-value * 1000000 - dac_offset) / dac_gain) # fix sign of output - elif unit == 'mA': + elif unit == "mA": value = int((-value * 1000 - dac_offset) / dac_gain) # fix sign of output - elif unit == 'uA': + elif unit == "uA": value = int((-value - dac_offset) / dac_gain) # fix sign of output else: raise TypeError("Invalid unit type.") @@ -894,5 +969,5 @@ def _set_dac_value(self, channel, value): # if value is greater than maximum dac value, set it to maximum and output an error message if value > 4095: value = 4095 - logger.warning('%s DAC value reached maximum value', channel) - I2cAnalogChannel._set_dac_value(self, value=value, **self._ch_map[channel]['DAC']) + logger.warning("%s DAC value reached maximum value", channel) + I2cAnalogChannel._set_dac_value(self, value=value, **self._ch_map[channel]["DAC"]) diff --git a/basil/HL/HardwareLayer.py b/basil/HL/HardwareLayer.py index 1cbc048a6..3e76d3d1a 100644 --- a/basil/HL/HardwareLayer.py +++ b/basil/HL/HardwareLayer.py @@ -11,8 +11,8 @@ class HardwareLayer(Base): - '''Hardware layer (HL) base class. - ''' + """Hardware layer (HL) base class.""" + def __init__(self, intf, conf): super(HardwareLayer, self).__init__(conf) # interface not required for some cases @@ -24,7 +24,7 @@ def is_ready(self): raise NotImplementedError("is_ready() not implemented") def wait_for_ready(self, timeout=None, times=None, delay=None, delay_between=None, abort=None): - '''Determine the ready state of the device and wait until device is ready. + """Determine the ready state of the device and wait until device is ready. Parameters ---------- @@ -42,7 +42,7 @@ def wait_for_ready(self, timeout=None, times=None, delay=None, delay_between=Non Returns ------- True if state is ready, else False. - ''' + """ if delay: try: sleep(delay) @@ -60,7 +60,9 @@ def wait_for_ready(self, timeout=None, times=None, delay=None, delay_between=Non if abort and abort.is_set(): False if timeout is not None and stop <= now: - raise RuntimeError('Time out while waiting for ready in %s, module %s' % (self.name, self.__class__.__module__)) + raise RuntimeError( + "Time out while waiting for ready in %s, module %s" % (self.name, self.__class__.__module__) + ) if times and times > times_checked: False if delay_between: diff --git a/basil/HL/JtagGpio.py b/basil/HL/JtagGpio.py index f67343ac3..9f1e6b0f1 100644 --- a/basil/HL/JtagGpio.py +++ b/basil/HL/JtagGpio.py @@ -10,7 +10,6 @@ from basil.RL.StdRegister import StdRegister from basil.utils.BitLogic import BitLogic - jtag_gpio_yaml = """ name : GPIO type : StdRegister @@ -36,8 +35,7 @@ class JtagGpio(HardwareLayer): - '''GPIO based JTAG interface - ''' + """GPIO based JTAG interface""" def __init__(self, intf, conf): super(JtagGpio, self).__init__(intf, conf) @@ -55,40 +53,40 @@ def init(self): super(JtagGpio, self).init() def reset(self): - self.reg['RESETB'] = 0 + self.reg["RESETB"] = 0 self._write(tck=False) - self.reg['RESETB'] = 1 + self.reg["RESETB"] = 1 self._write(tck=False) self.tms_reset() def tms_reset(self): for _ in range(5): - self.reg['TMS'] = 1 + self.reg["TMS"] = 1 self._write() - self.reg['TMS'] = 0 + self.reg["TMS"] = 0 self._write() # idle def scan_ir(self, data): - self.reg['TMS'] = 1 + self.reg["TMS"] = 1 self._write() - self.reg['TMS'] = 1 + self.reg["TMS"] = 1 self._write() # select ir return self._scan(data) def scan_dr(self, data): - self.reg['TMS'] = 1 + self.reg["TMS"] = 1 self._write() # select dr return self._scan(data) def _scan(self, data): - self.reg['TMS'] = 0 + self.reg["TMS"] = 0 self._write() # capture - self.reg['TMS'] = 0 + self.reg["TMS"] = 0 ret_bit = self._write(tdo=True) ret = [] @@ -98,8 +96,8 @@ def _scan(self, data): size = len(data[dev]) for bit in range(size): if dev == len(data) - 1 and bit == len(data[dev]) - 1: - self.reg['TMS'] = 1 # exit1 - self.reg['TDI'] = data[dev][bit] + self.reg["TMS"] = 1 # exit1 + self.reg["TDI"] = data[dev][bit] dev_ret[bit] = ret_bit if bit == size - 1 and dev == size_dev - 1: # last bit self._write() @@ -107,11 +105,11 @@ def _scan(self, data): ret_bit = self._write(tdo=True) ret.append(dev_ret) - self.reg['TDI'] = 0 - self.reg['TMS'] = 1 + self.reg["TDI"] = 0 + self.reg["TMS"] = 1 self._write() # update - self.reg['TMS'] = 0 + self.reg["TMS"] = 0 self._write() # idle return ret @@ -120,11 +118,11 @@ def _write(self, tck=True, tdo=False): self._intf.set_data(self.reg.tobytes()) if tck: - self.reg['TCK'] = 0 + self.reg["TCK"] = 0 self._intf.set_data(self.reg.tobytes()) - self.reg['TCK'] = 1 + self.reg["TCK"] = 1 self._intf.set_data(self.reg.tobytes()) - self.reg['TCK'] = 0 + self.reg["TCK"] = 0 self._intf.set_data(self.reg.tobytes()) if tdo: diff --git a/basil/HL/JtagMaster.py b/basil/HL/JtagMaster.py index b270f56ae..f1e9c557e 100644 --- a/basil/HL/JtagMaster.py +++ b/basil/HL/JtagMaster.py @@ -5,10 +5,11 @@ # ------------------------------------------------------------ # +import numpy as np +from bitarray import bitarray + from basil.HL.RegisterHardwareLayer import RegisterHardwareLayer from basil.utils.BitLogic import BitLogic -from bitarray import bitarray -import numpy as np class JtagMaster(RegisterHardwareLayer): @@ -188,13 +189,12 @@ def _bytes2bitlogic(self, data, bit_number, original_data): last_data_len = 0 for i in original_data: - rlist.append(BitLogic(binary_string[last_data_len:len(i) + last_data_len])) + rlist.append(BitLogic(binary_string[last_data_len : len(i) + last_data_len])) last_data_len += len(i) return rlist def _raw_data2bytes(self, data): - all_data = "".join(data) # pad with zero if not a multiple of 8 @@ -202,4 +202,4 @@ def _raw_data2bytes(self, data): all_data += "0" * (8 - (len(all_data) % 8)) # convert string to byte - return bytes(int(all_data[i:i + 8], 2) for i in range(0, len(all_data), 8)) + return bytes(int(all_data[i : i + 8], 2) for i in range(0, len(all_data), 8)) diff --git a/basil/HL/MIO_PLL.py b/basil/HL/MIO_PLL.py index c6c4af693..438d4156f 100644 --- a/basil/HL/MIO_PLL.py +++ b/basil/HL/MIO_PLL.py @@ -6,7 +6,7 @@ # # E221 multiple spaces before operator -# flake8: noqa +# flake8: noqa import logging @@ -16,7 +16,7 @@ class MIO_PLL(HardwareLayer): - ''' + """ CY22150 PLL Output frequency range: 80 kHz to 200 MHz @@ -33,58 +33,59 @@ class MIO_PLL(HardwareLayer): base_addr : 0x00000 pll_frequency : 40 # [MHz] - ''' + """ + # slave address - CY22150_BASE_ADDR = 0xD2 + CY22150_BASE_ADDR = 0xD2 # register addresses - CY22150_ADD_CLKOE = 0x09 # clock output enable control - CY22150_ADD_DIV1 = 0x0c # PLL post divider 1 (for LCLK 1-4) - CY22150_ADD_INPDRV = 0x12 # input oscillator drive control - CY22150_ADD_INPCAP = 0x13 # input oscillator load capacitance (for crystal use only) - CY22150_ADD_CHG_PB = 0x40 # charge pump + PLL feedback divider - CY22150_ADD_PB = 0x41 # PLL feedback divider - CY22150_ADD_PO_Q = 0x42 # reference input clock divider - CY22150_ADD_XS1 = 0x44 # output crosspoint switch matrix - CY22150_ADD_XS2 = 0x45 # output crosspoint switch matrix - CY22150_ADD_XS3 = 0x46 # output crosspoint switch matrix - CY22150_ADD_DIV2 = 0x47 # PLL post divider 2 (for CLK 5,6) + CY22150_ADD_CLKOE = 0x09 # clock output enable control + CY22150_ADD_DIV1 = 0x0C # PLL post divider 1 (for LCLK 1-4) + CY22150_ADD_INPDRV = 0x12 # input oscillator drive control + CY22150_ADD_INPCAP = 0x13 # input oscillator load capacitance (for crystal use only) + CY22150_ADD_CHG_PB = 0x40 # charge pump + PLL feedback divider + CY22150_ADD_PB = 0x41 # PLL feedback divider + CY22150_ADD_PO_Q = 0x42 # reference input clock divider + CY22150_ADD_XS1 = 0x44 # output crosspoint switch matrix + CY22150_ADD_XS2 = 0x45 # output crosspoint switch matrix + CY22150_ADD_XS3 = 0x46 # output crosspoint switch matrix + CY22150_ADD_DIV2 = 0x47 # PLL post divider 2 (for CLK 5,6) # bit locations - CY22150_LCLK1_EN = 0x01 # only one output used on MIO board - CY22150_LCLK2_EN = 0x02 - CY22150_LCLK3_EN = 0x04 - CY22150_LCLK4_EN = 0x08 - CY22150_CLK5_EN = 0x10 - CY22150_CLK6_EN = 0x20 + CY22150_LCLK1_EN = 0x01 # only one output used on MIO board + CY22150_LCLK2_EN = 0x02 + CY22150_LCLK3_EN = 0x04 + CY22150_LCLK4_EN = 0x08 + CY22150_CLK5_EN = 0x10 + CY22150_CLK6_EN = 0x20 # constants - CY22150_DEF_INPDRV = 0x28 # input range for 48 MHz reference clock oszillator - CY22150_DEF_INPCAP = 0x00 # no load capacitor - CY22150_FREF_FX = 48.0 # reference clock, from USB controller + CY22150_DEF_INPDRV = 0x28 # input range for 48 MHz reference clock oszillator + CY22150_DEF_INPCAP = 0x00 # no load capacitor + CY22150_FREF_FX = 48.0 # reference clock, from USB controller q_counter = 0 p_counter = 0 - q_total = 0 - p_total = 0 - p_0 = 0 - div = 0 - div1N = 0 - div1SRC = 0 - div2N = 8 - div2SRC = 0 - clk1SRC = 0 - clk2SRC = 0 - clk3SRC = 0 - clk4SRC = 0 - clk5SRC = 0 - clk6SRC = 0 - chg_pump = 0 + q_total = 0 + p_total = 0 + p_0 = 0 + div = 0 + div1N = 0 + div1SRC = 0 + div2N = 8 + div2SRC = 0 + clk1SRC = 0 + clk2SRC = 0 + clk3SRC = 0 + clk4SRC = 0 + clk5SRC = 0 + clk6SRC = 0 + chg_pump = 0 fref = CY22150_FREF_FX pll_frequency = 40 # some default def __init__(self, intf, conf): super(MIO_PLL, self).__init__(intf, conf) - self._base_addr = conf['base_addr'] - self.pll_frequency = conf['pll_frequency'] + self._base_addr = conf["base_addr"] + self.pll_frequency = conf["pll_frequency"] self.CY22150_ADD = self.CY22150_BASE_ADDR def init(self): @@ -100,7 +101,9 @@ def close(self): def setFrequency(self, value): # value in MHz if float(value) < 0.08 or float(value) > 200.0: - raise ValueError('[MIO_PLL ERROR] PLL frequency (' + str(value) + ' MHz) out of range. Allowed range: 80 kHz to 200 MHz') + raise ValueError( + "[MIO_PLL ERROR] PLL frequency (" + str(value) + " MHz) out of range. Allowed range: 80 kHz to 200 MHz" + ) if self._calculateParameters(value): self._updateRegisters() return True @@ -113,7 +116,7 @@ def _set_register_value(self, register, value): def _calculateParameters(self, fout): q_d_f = 0 - ''' + """ fout = fref * (p_total / q_total) * (1 / div) p_total = 2 * ((p_counter + 4) + p_0) [16..1023] @@ -124,7 +127,7 @@ def _calculateParameters(self, fout): f_ref * p_total / q_total = [100..400] MHz f_ref / q_total > 0.25 MHz - ''' + """ for self.q_counter in range(128): self.q_total = self.q_counter + 2 if (self.fref / self.q_total) < 0.25: # PLL constraint @@ -141,7 +144,9 @@ def _calculateParameters(self, fout): break if self.p_total > 1023: break - if ((self.fref * self.p_total / self.q_total) < 100 or (self.fref * self.p_total / self.q_total) > 400): # PLL constraint + if (self.fref * self.p_total / self.q_total) < 100 or ( + self.fref * self.p_total / self.q_total + ) > 400: # PLL constraint break if int(self.p_total) % 2 == 0: self.p_0 = 0 @@ -176,25 +181,25 @@ def _calculateParameters(self, fout): self.chg_pump = 4 ftest = self.fref * self.p_total / self.q_total * 1 / self.div fvco = self.fref * self.p_total / self.q_total - logger.info('PLL frequency set to ' + str(ftest) + ' MHz' + ' (VCO @ ' + str(fvco) + ' MHz)') + logger.info("PLL frequency set to " + str(ftest) + " MHz" + " (VCO @ " + str(fvco) + " MHz)") return True - logger.error('MIO_PLL: Could not find PLL parameters for {}MHz'.format(fout)) + logger.error("MIO_PLL: Could not find PLL parameters for {}MHz".format(fout)) return False def _updateRegisters(self): - temp = (self.div1SRC << 7) | (0x7f & self.div1N) + temp = (self.div1SRC << 7) | (0x7F & self.div1N) self._set_register_value(self.CY22150_ADD_DIV1, temp) # post divider 1 - temp = (self.div2SRC << 7) | (0x7f & self.div2N) + temp = (self.div2SRC << 7) | (0x7F & self.div2N) self._set_register_value(self.CY22150_ADD_DIV2, temp) # post divider 2 temp = 0xC0 | (((0x07 & self.chg_pump) << 2) | ((0x0300 & int(self.p_counter)) >> 8)) self._set_register_value(self.CY22150_ADD_CHG_PB, temp) # charge pump & p divider - temp = (0xff & int(self.p_counter)) + temp = 0xFF & int(self.p_counter) self._set_register_value(self.CY22150_ADD_PB, temp) # p divider - temp = ((0x01 & self.p_0) << 7) | (0x07f & self.q_counter) + temp = ((0x01 & self.p_0) << 7) | (0x07F & self.q_counter) self._set_register_value(self.CY22150_ADD_PO_Q, temp) # p_0 & q divider temp = (self.clk1SRC << 5) | (self.clk2SRC << 2) | ((0x03 & self.clk3SRC) >> 1) @@ -203,5 +208,5 @@ def _updateRegisters(self): temp = (self.clk3SRC << 7) | (self.clk4SRC << 4) | (self.clk5SRC << 1) | ((0x01 & self.clk6SRC) >> 2) self._set_register_value(self.CY22150_ADD_XS2, temp) # clock source - temp = (self.clk6SRC << 6) | 0x3f + temp = (self.clk6SRC << 6) | 0x3F self._set_register_value(self.CY22150_ADD_XS3, temp) # clock source diff --git a/basil/HL/NTCRegister.py b/basil/HL/NTCRegister.py index 5652f2a5e..9360d5202 100644 --- a/basil/HL/NTCRegister.py +++ b/basil/HL/NTCRegister.py @@ -16,7 +16,7 @@ class NTCRegister(HardwareLayer): - """ Register class for NTCRegister + """Register class for NTCRegister hw_drivers: - name : CCPD_Vdda @@ -38,18 +38,44 @@ def init(self): logger.debug("Initializing NTC " + self._conf["NTC_type"] + " on channel " + self._conf["arg_add"]["channel"]) if self._conf["NTC_type"] == "TDK_NTCG16H": - self.R_RATIO = np.array([18.85, 14.429, 11.133, 8.656, 6.779, 5.346, 4.245, 3.393, 2.728, 2.207, 1.796, 1.47, 1.209, 1.0, 0.831, 0.694, 0.583, 0.491, 0.416, 0.354, 0.302, 0.259, 0.223, 0.192, 0.167, 0.145, 0.127, 0.111, 0.0975, 0.086, 0.076, 0.0674, 0.0599, 0.0534]) - self.B_CONST = np.array([3140, 3159, 3176, 3194, 3210, 3226, 3241, 3256, 3270, 3283, 3296, 3308, 3320, 3332, 3343, 3353, 3363, 3373, 3382, 3390, 3399, 3407, 3414, 3422, 3428, 3435, 3441, 3447, 3453, 3458, 3463, 3468, 3473, 3478]) + # fmt: off + self.R_RATIO = np.array( + [ + 18.85, 14.429, 11.133, 8.656, 6.779, 5.346, 4.245, 3.393, 2.728, 2.207, 1.796, 1.47, + 1.209, 1.0, 0.831, 0.694, 0.583, 0.491, 0.416, 0.354, 0.302, 0.259, 0.223, 0.192, + 0.167, 0.145, 0.127, 0.111, 0.0975, 0.086, 0.076, 0.0674, 0.0599, 0.0534, + ] + ) + self.B_CONST = np.array( + [ + 3140, 3159, 3176, 3194, 3210, 3226, 3241, 3256, 3270, 3283, 3296, 3308, + 3320, 3332, 3343, 3353, 3363, 3373, 3382, 3390, 3399, 3407, 3414, 3422, + 3428, 3435, 3441, 3447, 3453, 3458, 3463, 3468, 3473, 3478, + ] + ) + # fmt: on self.TEMP = np.arange(-40 + 273.15, 130 + 273.15, 5) self.R0 = 10000 # R at 25C elif self._conf["NTC_type"] == "130KT1608T": - self.R_RATIO = np.array([221.9, 125.1, 73.38, 44.72, 28.16, 18.25, 12.14, 10.00, 8.283, 5.781, 4.120, 2.996, 2.214, 1.665, 1.451, 1.271, 0.9832, 0.7707, 0.6114, 0.5469]) + # fmt: off + self.R_RATIO = np.array( + [ + 221.9, 125.1, 73.38, 44.72, 28.16, 18.25, 12.14, 10.00, 8.283, 5.781, 4.120, 2.996, + 2.214, 1.665, 1.451, 1.271, 0.9832, 0.7707, 0.6114, 0.5469, + ] + ) self.B_CONST = np.array([3435.0] * len(self.R_RATIO)) - self.TEMP = np.array([233.145, 243.15, 253.15, 263.15, 273.15, 283.15, 293.15, 298.15, 303.15, 313.15, 323.15, 333.15, 343.15, 353.15, 358.15, 363.15, 373.15, 383.15, 393.15, 398.15]) + self.TEMP = np.array( + [ + 233.145, 243.15, 253.15, 263.15, 273.15, 283.15, 293.15, 298.15, 303.15, 313.15, 323.15, 333.15, + 343.15, 353.15, 358.15, 363.15, 373.15, 383.15, 393.15, 398.15, + ] + ) + # fmt: on self.R0 = 1000 # R at 25C self._intf.set_current(self._conf["arg_add"]["channel"], -50, unit="uA") else: - raise ValueError('NTC_type %s is not supported.' % self._conf["NTC_type"]) + raise ValueError("NTC_type %s is not supported." % self._conf["NTC_type"]) def get_voltage(self, unit="V"): return self._intf.get_voltage(self._conf["arg_add"]["channel"], unit=unit) diff --git a/basil/HL/RegisterHardwareLayer.py b/basil/HL/RegisterHardwareLayer.py index 9358ca2ec..a9387ecf7 100644 --- a/basil/HL/RegisterHardwareLayer.py +++ b/basil/HL/RegisterHardwareLayer.py @@ -5,28 +5,29 @@ # ------------------------------------------------------------ # -import logging -from copy import deepcopy -from collections.abc import Iterable import array +import logging from collections import namedtuple +from collections.abc import Iterable +from copy import deepcopy + from six import integer_types -from basil.utils.utils import tobytes -from basil.utils.BitLogic import BitLogic from basil.HL.HardwareLayer import HardwareLayer +from basil.utils.BitLogic import BitLogic +from basil.utils.utils import tobytes logger = logging.getLogger(__name__) # description attributes -read_only = ['read_only', 'read-only', 'readonly', 'ro'] -write_only = ['write_only', 'write-only', 'writeonly', 'wo'] -is_byte_array = ['byte_array', 'byte-array', 'bytearray'] +read_only = ["read_only", "read-only", "readonly", "ro"] +write_only = ["write_only", "write-only", "writeonly", "wo"] +is_byte_array = ["byte_array", "byte-array", "bytearray"] class RegisterHardwareLayer(HardwareLayer): - '''Register Hardware Layer. + """Register Hardware Layer. Implementation of advanced register operations. @@ -39,7 +40,8 @@ class RegisterHardwareLayer(HardwareLayer): 'EN_WRITE_TIMESTAMP': {'descr': {'addr': 1, 'size': 1, 'offset': 3}}, <-- 1-bit register 'EVENT_COUNTER': {'descr': {'addr': 2, 'size': 32, 'properties': ['ro']}} <-- 32-bit register, 'ro' equivalent to 'readonly' _require_version = '==3' <-- or use '<=', '>=', ... accordingly - ''' + """ + _registers = {} _require_version = None @@ -47,8 +49,8 @@ def __init__(self, intf, conf): super(RegisterHardwareLayer, self).__init__(intf, conf) # require interface and base address self._intf = intf - self._base_addr = conf['base_addr'] - rv = namedtuple('_register_values', field_names=iter(self._registers.keys())) + self._base_addr = conf["base_addr"] + rv = namedtuple("_register_values", field_names=iter(self._registers.keys())) self._register_values = rv(*([None] * len(self._registers))) for reg in self._registers.keys(): if not reg.isupper(): @@ -60,26 +62,42 @@ def init(self): # reset during initialization to get default state and to remove any prior settings if "RESET" in self._registers: self.RESET # assign no value, to read back value and write same value or default value - if 'VERSION' in self._registers: + if "VERSION" in self._registers: version = str(self.VERSION) else: version = None - logger.info("Initializing %s (firmware version: %s), module %s, base_addr %s" % (self.name, version if 'VERSION' in self._registers else 'n/a', self.__class__.__module__, hex(self._base_addr))) + logger.info( + "Initializing %s (firmware version: %s), module %s, base_addr %s" + % ( + self.name, + version if "VERSION" in self._registers else "n/a", + self.__class__.__module__, + hex(self._base_addr), + ) + ) if self._require_version and not eval(version + self._require_version): - raise Exception("FPGA module %s does not satisfy version requirements (read: %s, require: %s)" % (self.__class__.__module__, version, self._require_version.strip())) + raise Exception( + "FPGA module %s does not satisfy version requirements (read: %s, require: %s)" + % (self.__class__.__module__, version, self._require_version.strip()) + ) for reg, value in self._registers.items(): if reg in self._init: self[reg] = self._init[reg] - elif 'default' in value and not ('properties' in value['descr'] and [i for i in read_only if i in value['descr']['properties']]): - self[reg] = value['default'] + elif "default" in value and not ( + "properties" in value["descr"] and [i for i in read_only if i in value["descr"]["properties"]] + ): + self[reg] = value["default"] else: # do nothing here, keep existing value pass unknown_regs = set(self._init.keys()).difference(set(self._registers.keys())) if unknown_regs: - raise KeyError("Attempt to write to unknown register(s) in %s, module %s during initialization: %s" % (self.name, self.__class__.__module__, ", ".join(unknown_regs))) + raise KeyError( + "Attempt to write to unknown register(s) in %s, module %s during initialization: %s" + % (self.name, self.__class__.__module__, ", ".join(unknown_regs)) + ) def set_value(self, value, addr, size, offset, **kwargs): - '''Writing a value of any arbitrary size (max. unsigned int 64) and offset to a register + """Writing a value of any arbitrary size (max. unsigned int 64) and offset to a register Parameters ---------- @@ -95,7 +113,7 @@ def set_value(self, value, addr, size, offset, **kwargs): Returns ------- nothing - ''' + """ div_offset, mod_offset = divmod(offset, 8) div_size, mod_size = divmod(size + mod_offset, 8) if mod_size: @@ -106,11 +124,11 @@ def set_value(self, value, addr, size, offset, **kwargs): ret = self._intf.read(self._base_addr + addr + div_offset, size=div_size) reg = BitLogic() reg.frombytes(tobytes(ret)) - reg[size + mod_offset - 1:mod_offset] = value - self._intf.write(self._base_addr + addr + div_offset, data=array.array('B', reg.tobytes())) + reg[size + mod_offset - 1 : mod_offset] = value + self._intf.write(self._base_addr + addr + div_offset, data=array.array("B", reg.tobytes())) def get_value(self, addr, size, offset, **kwargs): - '''Reading a value of any arbitrary size (max. unsigned int 64) and offset from a register + """Reading a value of any arbitrary size (max. unsigned int 64) and offset from a register Parameters ---------- @@ -125,7 +143,7 @@ def get_value(self, addr, size, offset, **kwargs): ------- reg : int Register value. - ''' + """ div_offset, mod_offset = divmod(offset, 8) div_size, mod_size = divmod(size + mod_offset, 8) if mod_size: @@ -133,10 +151,10 @@ def get_value(self, addr, size, offset, **kwargs): ret = self._intf.read(self._base_addr + addr + div_offset, size=div_size) reg = BitLogic() reg.frombytes(tobytes(ret)) - return reg[size + mod_offset - 1:mod_offset].tovalue() + return reg[size + mod_offset - 1 : mod_offset].tovalue() def set_bytes(self, data, addr, **kwargs): - '''Writing bytes of any arbitrary size + """Writing bytes of any arbitrary size Parameters ---------- @@ -148,11 +166,11 @@ def set_bytes(self, data, addr, **kwargs): Returns ------- nothing - ''' - self._intf.write(self._conf['base_addr'] + addr, data) + """ + self._intf.write(self._conf["base_addr"] + addr, data) def get_bytes(self, addr, size, **kwargs): - '''Reading bytes of any arbitrary size + """Reading bytes of any arbitrary size Parameters ----------. @@ -165,8 +183,8 @@ def get_bytes(self, addr, size, **kwargs): ------- data : iterable Byte array. - ''' - return self._intf.read(self._conf['base_addr'] + addr, size) + """ + return self._intf.read(self._conf["base_addr"] + addr, size) def set_configuration(self, conf): if conf: @@ -176,8 +194,10 @@ def set_configuration(self, conf): def get_configuration(self): conf = {} for reg in self._registers.keys(): - descr = self._registers[reg]['descr'] - if not ('properties' in descr and [i for i in write_only if i in descr['properties']]) and not ('properties' in descr and [i for i in read_only if i in descr['properties']]): + descr = self._registers[reg]["descr"] + if not ("properties" in descr and [i for i in write_only if i in descr["properties"]]) and not ( + "properties" in descr and [i for i in read_only if i in descr["properties"]] + ): conf[reg] = self[reg] return conf @@ -201,54 +221,65 @@ def setter(self, value): except Exception as e: logger.error(e) return None + # construct property attribute and add it to the class - setattr(self.__class__, attribute, property(fget=getter, fset=setter, doc=attribute + ' register')) + setattr(self.__class__, attribute, property(fget=getter, fset=setter, doc=attribute + " register")) def set_default(self): for reg, value in self._registers.items(): - if 'default' in value and not ('properties' in value['descr'] and [i for i in read_only if i in self._registers[reg]['descr']['properties']]): - self._set(reg, value['default']) + if "default" in value and not ( + "properties" in value["descr"] + and [i for i in read_only if i in self._registers[reg]["descr"]["properties"]] + ): + self._set(reg, value["default"]) def _get(self, reg): - descr = deepcopy(self._registers[reg]['descr']) - if 'properties' in descr and [i for i in write_only if i in descr['properties']]: + descr = deepcopy(self._registers[reg]["descr"]) + if "properties" in descr and [i for i in write_only if i in descr["properties"]]: # allows a lazy-style of programming - if 'default' in self._registers[reg]: - return self._set(reg, self._registers[reg]['default']) + if "default" in self._registers[reg]: + return self._set(reg, self._registers[reg]["default"]) else: - descr.setdefault('offset', 0) + descr.setdefault("offset", 0) return self._set(reg, self.get_value(**descr)) # raise error when doing read on write-only register -# raise IOError('Register is write-only') - # return None to prevent misuse -# return None + # raise IOError('Register is write-only') + # return None to prevent misuse + # return None else: - if 'properties' in descr and [i for i in is_byte_array if i in descr['properties']]: + if "properties" in descr and [i for i in is_byte_array if i in descr["properties"]]: ret_val = self.get_bytes(**descr) - ret_val = array.array('B', ret_val).tolist() + ret_val = array.array("B", ret_val).tolist() else: - descr.setdefault('offset', 0) + descr.setdefault("offset", 0) curr_val = self._register_values._asdict()[reg] if not self.is_initialized: # this test allows attributes to be set in the __init__ method ret_val = curr_val else: ret_val = self.get_value(**descr) - if curr_val is not None and 'properties' in descr and not [i for i in read_only if i in descr['properties']] and curr_val != ret_val: - raise ValueError('Read value was not expected: read: %s, expected: %s' % (str(ret_val), str(curr_val))) + if ( + curr_val is not None + and "properties" in descr + and not [i for i in read_only if i in descr["properties"]] + and curr_val != ret_val + ): + raise ValueError( + "Read value was not expected: read: %s, expected: %s" % (str(ret_val), str(curr_val)) + ) return ret_val def _set(self, reg, value): - descr = deepcopy(self._registers[reg]['descr']) - if 'properties' in descr and [i for i in read_only if i in descr['properties']]: - raise IOError('Register is read-only') - if 'properties' in descr and [i for i in is_byte_array if i in descr['properties']]: + descr = deepcopy(self._registers[reg]["descr"]) + if "properties" in descr and [i for i in read_only if i in descr["properties"]]: + raise IOError("Register is read-only") + if "properties" in descr and [i for i in is_byte_array if i in descr["properties"]]: if not isinstance(value, Iterable): - raise ValueError('For array byte_register iterable object is needed') - value = array.array('B', value).tolist() + raise ValueError("For array byte_register iterable object is needed") + value = array.array("B", value).tolist() self.set_bytes(value, **descr) self._register_values = self._register_values._replace(**{reg: value}) else: - descr.setdefault('offset', 0) + descr.setdefault("offset", 0) value = value if isinstance(value, integer_types) else int(value, base=2) try: self.set_value(value, **descr) @@ -264,19 +295,19 @@ def __setitem__(self, name, value): return self._set(name, value) def __getattr__(self, name): - '''called only on last resort if there are no attributes in the instance that match the name - ''' + """called only on last resort if there are no attributes in the instance that match the name""" if name.isupper(): _ = self._register_values._asdict()[name] def method(*args, **kwargs): - nsplit = name.split('_', 1) - if len(nsplit) == 2 and nsplit[0] == 'set' and nsplit[1].isupper() and len(args) == 1 and not kwargs: + nsplit = name.split("_", 1) + if len(nsplit) == 2 and nsplit[0] == "set" and nsplit[1].isupper() and len(args) == 1 and not kwargs: self[nsplit[1]] = args[0] # returns None - elif len(nsplit) == 2 and nsplit[0] == 'get' and nsplit[1].isupper() and not args and not kwargs: + elif len(nsplit) == 2 and nsplit[0] == "get" and nsplit[1].isupper() and not args and not kwargs: return self[nsplit[1]] else: raise AttributeError("%r object has no attribute %r" % (self.__class__, name)) + return method def __setattr__(self, name, value): diff --git a/basil/HL/SensirionBridgeDevice.py b/basil/HL/SensirionBridgeDevice.py index cf84121d3..d86623d61 100644 --- a/basil/HL/SensirionBridgeDevice.py +++ b/basil/HL/SensirionBridgeDevice.py @@ -9,10 +9,10 @@ class SensirionBridgeI2CDevice(HardwareLayer): - ''' + """ Driver for I2C devices connected to a Sensirion Sensor Bridge. The device has to be connected to one of the two ports of the Sensirion Sensor Bridge. - ''' + """ def __init__(self, intf, conf): super(SensirionBridgeI2CDevice, self).__init__(intf, conf) @@ -21,15 +21,21 @@ def __init__(self, intf, conf): def init(self, address): super(SensirionBridgeI2CDevice, self).init() - self.port = self._intf.bridge_ports[self._init.get('bridgePort', 'one')] + self.port = self._intf.bridge_ports[self._init.get("bridgePort", "one")] self.address = address self.power_on() def _read(self, command, read_n_bytes=0, timeout_us=100e3): - return self._intf.read_i2c(device=self.device, port=self.port, address=self.address, - command=command, read_n_bytes=read_n_bytes, timeout_us=timeout_us) + return self._intf.read_i2c( + device=self.device, + port=self.port, + address=self.address, + command=command, + read_n_bytes=read_n_bytes, + timeout_us=timeout_us, + ) def _write(self, command): self._intf.write_i2c(device=self.device, port=self.port, address=self.address, command=command) @@ -41,7 +47,7 @@ def power_on(self): self.device = self._intf.setup_i2c_device(bridge_port=self.port, **self._init) def power_off(self): - if hasattr(self, 'device'): + if hasattr(self, "device"): self._intf.disable_i2c_device(self.device, bridge_port=self.port) def __del__(self): diff --git a/basil/HL/SentioProber.py b/basil/HL/SentioProber.py index 752e84471..bb761cd81 100644 --- a/basil/HL/SentioProber.py +++ b/basil/HL/SentioProber.py @@ -9,62 +9,61 @@ class SentioProber(HardwareLayer): - - ''' + """ Implements functions to steer a Sentio probe station. The interface is the same for all Hong Kong Sentio probe stations. - ''' + """ def __init__(self, intf, conf): super(SentioProber, self).__init__(intf, conf) def set_position(self, x, y, speed=None): - ''' Move chuck to absolute position in um''' + """Move chuck to absolute position in um""" return self._intf.query("move_chuck_xy zero,%1.1f,%1.1f" % (x, y)) def move_position(self, dx, dy, speed=None): - ''' Move chuck relative to actual position in um''' + """Move chuck relative to actual position in um""" return self._intf.query("move_chuck_xy relative,%1.1f,%1.1f" % (dx, dy)) def get_position(self): - ''' Read chuck position (x, y, z)''' + """Read chuck position (x, y, z)""" data = self._intf.query("get_chuck_xy 0,zero") - values = data.split(',') + values = data.split(",") x = float(values[2]) y = float(values[3]) - z = float(self._intf.query("get_chuck_z").split(',')[2]) + z = float(self._intf.query("get_chuck_z").split(",")[2]) return [x, y, z] def goto_die(self, index_x, index_y): - ''' Move chuck to wafer map chip index''' + """Move chuck to wafer map chip index""" return self._intf.query("map:step_die %d,%d" % (index_x, index_y)) def goto_next_die(self): - ''' Move chuck to next die from wafer map''' + """Move chuck to next die from wafer map""" return self._intf.query("map:step_next_die") def goto_first_die(self): - ''' Move chuck to first die from wafer map''' + """Move chuck to first die from wafer map""" return self._intf.query("map:step_first_die") def get_die(self): - ''' Get chip index ''' + """Get chip index""" reply = self._intf.query("map:die:get_current_index").strip() - if reply == '0:' or reply == '': + if reply == "0:" or reply == "": reply = self._intf.query("map:die:get_current_index") - values = reply[2:].split(',') + values = reply[2:].split(",") return (int(values[0]), int(values[1])) def contact(self): - ''' Move chuck to contact z position''' + """Move chuck to contact z position""" return self._intf.query("move_chuck_contact") def load(self): - ''' Move chuck to load z position AND contact (!!)''' + """Move chuck to load z position AND contact (!!)""" # return self._intf.query("move_chuck_load") return 0 def separate(self): - ''' Move chuck to separation z position''' + """Move chuck to separation z position""" return self._intf.query("move_chuck_separation") diff --git a/basil/HL/SignatoneProber.py b/basil/HL/SignatoneProber.py index e93b8b02d..f68e82611 100644 --- a/basil/HL/SignatoneProber.py +++ b/basil/HL/SignatoneProber.py @@ -6,57 +6,58 @@ # import re + from basil.HL.RegisterHardwareLayer import HardwareLayer class SignatoneProber(HardwareLayer): - ''' + """ Implements functions to steer a Signatone probe station such as the one of lal in2p3 in Paris. - ''' + """ def __init__(self, intf, conf): super(SignatoneProber, self).__init__(intf, conf) def goto_die(self, index_x, index_y): - ''' Move chuck to wafer map chip index''' + """Move chuck to wafer map chip index""" index_x = abs(index_x) * -1 index_y = abs(index_y) * -1 - self._intf.write('MOVECR %d, %d' % (index_x, index_y)) + self._intf.write("MOVECR %d, %d" % (index_x, index_y)) def goto_next_die(self): - ''' Move chuck to next die from wafer map''' - self._intf.write('NEXT') + """Move chuck to next die from wafer map""" + self._intf.write("NEXT") def goto_first_die(self): - ''' Move chuck to first die from wafer map''' - self._intf.write('TOFIRSTSITE') + """Move chuck to first die from wafer map""" + self._intf.write("TOFIRSTSITE") def get_die(self): - ''' Get chip index ''' - reply = '' + """Get chip index""" + reply = "" for n in range(10): - if reply == '0:' or reply == '': - reply = self._intf.query('GETCR') + if reply == "0:" or reply == "": + reply = self._intf.query("GETCR") else: break - reply = re.sub(r'[a-zA-Z]', r'', reply) - values = reply.split(',') + reply = re.sub(r"[a-zA-Z]", r"", reply) + values = reply.split(",") return (int(values[0]), int(values[1])) def contact(self): - ''' Move chuck to contact z position''' - self._intf.write('ZCHUCKUP') + """Move chuck to contact z position""" + self._intf.write("ZCHUCKUP") def separate(self): - ''' Move chuck to separation z position''' - self._intf.write('ZCHUCKDOWN') + """Move chuck to separation z position""" + self._intf.write("ZCHUCKDOWN") def load(self): - ''' Move chuck to load z position''' - self._intf.write('LOADWAFER') + """Move chuck to load z position""" + self._intf.write("LOADWAFER") def get_id(self): - ''' Get id ''' - return self._intf.query('*IDN?') + """Get id""" + return self._intf.query("*IDN?") diff --git a/basil/HL/SussProber.py b/basil/HL/SussProber.py index f171ef093..5474fff35 100644 --- a/basil/HL/SussProber.py +++ b/basil/HL/SussProber.py @@ -9,62 +9,61 @@ class SussProber(HardwareLayer): - - '''Implements functions to steer a Suss probe station. The interface is the same for all SiLab Suss probe stations. - Dangerous commands like set_position while in contact are ignored by the Suss command server. - ''' + """Implements functions to steer a Suss probe station. The interface is the same for all SiLab Suss probe stations. + Dangerous commands like set_position while in contact are ignored by the Suss command server. + """ def __init__(self, intf, conf): super(SussProber, self).__init__(intf, conf) def set_position(self, x, y, speed=None): - ''' Move chuck to absolute position in um''' + """Move chuck to absolute position in um""" if speed: - self._intf.write('MoveChuckSubsite %1.1f %1.1f R Y %d' % (x, y, speed)) + self._intf.write("MoveChuckSubsite %1.1f %1.1f R Y %d" % (x, y, speed)) else: - self._intf.write('MoveChuckSubsite %1.1f %1.1f R Y' % (x, y)) + self._intf.write("MoveChuckSubsite %1.1f %1.1f R Y" % (x, y)) def move_position(self, dx, dy, speed=None): - ''' Move chuck relative to actual position in um''' + """Move chuck relative to actual position in um""" if speed: - self._intf.write('MoveChuckPosition %1.1f %1.1f R Y %d' % (dx, dy, speed)) + self._intf.write("MoveChuckPosition %1.1f %1.1f R Y %d" % (dx, dy, speed)) else: - self._intf.write('MoveChuckPosition %1.1f %1.1f R Y' % (dx, dy)) + self._intf.write("MoveChuckPosition %1.1f %1.1f R Y" % (dx, dy)) def get_position(self): - ''' Read chuck position (x, y, z)''' - reply = self._intf.query('ReadChuckPosition Y H')[2:] + """Read chuck position (x, y, z)""" + reply = self._intf.query("ReadChuckPosition Y H")[2:] return [float(i) for i in reply.split()] def goto_die(self, index_x, index_y): - ''' Move chuck to wafer map chip index''' - self._intf.write('StepNextDie %d %d' % (index_x, index_y)) + """Move chuck to wafer map chip index""" + self._intf.write("StepNextDie %d %d" % (index_x, index_y)) def goto_next_die(self): - ''' Move chuck to next die from wafer map''' - self._intf.write('StepNextDie') + """Move chuck to next die from wafer map""" + self._intf.write("StepNextDie") def goto_first_die(self): - ''' Move chuck to first die from wafer map''' - self._intf.write('StepFirstDie') + """Move chuck to first die from wafer map""" + self._intf.write("StepFirstDie") def get_die(self): - ''' Get chip index ''' - reply = self._intf.query('ReadMapPosition').strip() - if reply == '0:' or reply == '': - reply = self._intf.query('ReadMapPosition') + """Get chip index""" + reply = self._intf.query("ReadMapPosition").strip() + if reply == "0:" or reply == "": + reply = self._intf.query("ReadMapPosition") - values = reply[2:].split(' ') + values = reply[2:].split(" ") return (int(values[0]), int(values[1])) def contact(self): - ''' Move chuck to contact z position''' - self._intf.write('MoveChuckContact') + """Move chuck to contact z position""" + self._intf.write("MoveChuckContact") def separate(self): - ''' Move chuck to separation z position''' - self._intf.write('MoveChuckSeparation') + """Move chuck to separation z position""" + self._intf.write("MoveChuckSeparation") def load(self): - ''' Move chuck to load z position''' - self._intf.write('MoveChuckLoad') + """Move chuck to load z position""" + self._intf.write("MoveChuckLoad") diff --git a/basil/HL/XPT.py b/basil/HL/XPT.py index 433a1d376..3482a5fd1 100644 --- a/basil/HL/XPT.py +++ b/basil/HL/XPT.py @@ -6,38 +6,41 @@ # -import yaml +import logging from array import array -from basil.HL.HardwareLayer import HardwareLayer from struct import pack, unpack_from -import logging + +import yaml + +from basil.HL.HardwareLayer import HardwareLayer class I2C_INTF(HardwareLayer): - ''' + """ Use basil implementation of i2c. - ''' + """ def __init__(self, intf, conf): super(I2C_INTF, self).__init__(intf, conf) - self._base_addr = conf['base_addr'] + self._base_addr = conf["base_addr"] def init(self): super(I2C_INTF, self).init() def _set_reg(self, addr, val): - self._intf.write(self._base_addr, array('B', pack('BB', addr, val))) + self._intf.write(self._base_addr, array("B", pack("BB", addr, val))) def _get_reg(self, addr): - self._intf.write(self._base_addr, array('B', pack('B', addr))) - return unpack_from('B', self._intf.read(self._base_addr, size=1))[0] + self._intf.write(self._base_addr, array("B", pack("B", addr))) + return unpack_from("B", self._intf.read(self._base_addr, size=1))[0] class MuxPca9540B(HardwareLayer): - '''PCA 9540B + """PCA 9540B I2C Bus Multiplexer (GPAC). - ''' + """ + PCA9540B_BASE_ADD = 0xE0 # generic slave address PCA9540B_SEL_CH0 = 0x04 # select channel 0 PCA9540B_SEL_CH1 = 0x05 # select channel 1 @@ -45,21 +48,22 @@ class MuxPca9540B(HardwareLayer): def __init__(self, intf, conf): super(MuxPca9540B, self).__init__(intf, conf) - self._base_addr = conf['base_addr'] + self._base_addr = conf["base_addr"] self.PCA9540B_ADD = self.PCA9540B_BASE_ADD def _set_i2c_mux(self, bus): - self._intf.write(self._base_addr, array('B', pack('B', bus))) + self._intf.write(self._base_addr, array("B", pack("B", bus))) def _get_i2c_mux(self): - return unpack_from('B', self._intf.read(self._base_addr | 1, size=1))[0] + return unpack_from("B", self._intf.read(self._base_addr | 1, size=1))[0] class GpioPca9554(HardwareLayer): - '''PCA 9554 + """PCA 9554 GPIO extension (GPAC). - ''' + """ + PCA9554_BASE_ADD = 0x40 # generic slave address PCA9554_CFG = 0x03 # configuration register: 1 -> input (default), 0 -> output PCA9554_POL = 0x02 # polarity inversion register @@ -68,7 +72,7 @@ class GpioPca9554(HardwareLayer): def __init__(self, intf, conf): super(GpioPca9554, self).__init__(intf, conf) - self._base_addr = conf['base_addr'] + self._base_addr = conf["base_addr"] self.PCA9554_ADD = self.PCA9554_BASE_ADD self.GPIO_CFG = 0x00 @@ -78,20 +82,22 @@ def init(self): self._intf.write(self._base_addr + self.PCA9554_ADD, (self.PCA9554_OUT, 0x00)) def _write_output_port_select(self, value): - self._intf.write(self._base_addr + self.PCA9554_ADD, - array('B', pack('BB', self.PCA9554_CFG, value))) # configure output lines + self._intf.write( + self._base_addr + self.PCA9554_ADD, array("B", pack("BB", self.PCA9554_CFG, value)) + ) # configure output lines def _read_input_port(self): - self._intf.write(self._base_addr + self.PCA9554_ADD, array('B', pack('B', self.PCA9554_IN))) # set command byte - return unpack_from('B', self._intf.read(self._base_addr + self.PCA9554_ADD | 1, size=1))[0] # read input lines + self._intf.write(self._base_addr + self.PCA9554_ADD, array("B", pack("B", self.PCA9554_IN))) # set command byte + return unpack_from("B", self._intf.read(self._base_addr + self.PCA9554_ADD | 1, size=1))[0] # read input lines def _write_output_port(self, value): - self._intf.write(self._base_addr + self.PCA9554_ADD, - array('B', pack('BB', self.PCA9554_OUT, value))) # write output lines + self._intf.write( + self._base_addr + self.PCA9554_ADD, array("B", pack("BB", self.PCA9554_OUT, value)) + ) # write output lines def _read_output_port(self): - self._intf.write(self._base_addr + self.PCA9554_ADD, array('B', pack('B', self.PCA9554_OUT))) - return unpack_from('B', self._intf.read(self._base_addr + self.PCA9554_ADD | 1, size=1))[0] + self._intf.write(self._base_addr + self.PCA9554_ADD, array("B", pack("B", self.PCA9554_OUT))) + return unpack_from("B", self._intf.read(self._base_addr + self.PCA9554_ADD | 1, size=1))[0] def _set_output_port(self, mask): self._write_output_port(mask | self._read_output_port()) @@ -104,7 +110,7 @@ def _get_input_port(self, mask): class ADN_XPT(I2C_INTF): - ''' + """ XPT Functionality, works for ADN4605 & ADN4604. General procedure: - Reset @@ -113,115 +119,119 @@ class ADN_XPT(I2C_INTF): -Output configuration - Termination if not handled during I/O config - XPT core update - ''' + """ def __init__(self, intf, conf): super().__init__(intf, conf) self.lookup = {} self.map = {} - self.name = conf['name'] - self.addr = conf['base_addr'] + self.name = conf["name"] + self.addr = conf["base_addr"] self.output_channels = [] self.select_table = 0 def init(self, register_map): - ''' + """ Set up helper maps and select an output table if desired - ''' - with open(register_map, 'r') as map_: + """ + with open(register_map, "r") as map_: # register lookup table with register properties (addr, offset, default ...) self.lookup = yaml.safe_load(map_) for key in self.lookup: # set up register dict with everything but output channel assignment - if key != 'Output_Channels': + if key != "Output_Channels": self.map[key] = {} for reg in self.lookup[key]: - self.map[key][reg['name']] = reg + self.map[key][reg["name"]] = reg self.output_channels = [channel for channel in self.lookup["Output_Channels"]] # List of available output channels for given XPT. # self.select_table = self.output_table(write = False) #Query current output table. Upon power up should be 0. def write_register(self, cat, regname, val): - ''' + """ Write register. Register category and name are used to fetch addr, addr offset from register lookup. Write operation only into relevant bits of the register using a mask. Logging of register address, content, write mask, data written and new register content. - ''' + """ addr = self.get_addr(cat, regname) mask = self._calculate_mask(cat, regname) reg_read = self._get_reg(addr) - val = (reg_read & ~mask) | ((val << self.map[cat][regname]['offset']) & mask) - logging.debug('Writing in register %s (address %s). Register content: %s' % (cat + " " + regname, hex(addr), - format(reg_read, '#010b'))) - logging.debug('Use mask: %s. Write data: %s' % (format(mask, '#010b'), format(val, '#010b'))) + val = (reg_read & ~mask) | ((val << self.map[cat][regname]["offset"]) & mask) + logging.debug( + "Writing in register %s (address %s). Register content: %s" + % (cat + " " + regname, hex(addr), format(reg_read, "#010b")) + ) + logging.debug("Use mask: %s. Write data: %s" % (format(mask, "#010b"), format(val, "#010b"))) self._set_reg(addr, val) - logging.debug('Register content after writing: %s' % format(self._get_reg(addr), '#010b')) + logging.debug("Register content after writing: %s" % format(self._get_reg(addr), "#010b")) def read_register(self, cat, regname): - ''' + """ Read register, analog to writing. - ''' + """ addr = self.get_addr(cat, regname) mask = self._calculate_mask(cat, regname) - reg_read = (self._get_reg(addr) & mask) >> self.map[cat][regname]['offset'] - logging.info("Reading register %s (address %s). Masked register content: %s" % ( - cat + " " + regname, hex(addr), format(reg_read, '#010b'))) + reg_read = (self._get_reg(addr) & mask) >> self.map[cat][regname]["offset"] + logging.info( + "Reading register %s (address %s). Masked register content: %s" + % (cat + " " + regname, hex(addr), format(reg_read, "#010b")) + ) return reg_read def _calculate_mask(self, cat, regname): - mask = (pow(2, self.map[cat][regname]['size']) - 1) << self.map[cat][regname]['offset'] + mask = (pow(2, self.map[cat][regname]["size"]) - 1) << self.map[cat][regname]["offset"] return mask def get_addr(self, cat, regname): - return self.map[cat][regname]['address'] + return self.map[cat][regname]["address"] def reset(self): - ''' + """ Global XPT reset to defaults. - ''' - self.write_register('General', 'Reset', 1) + """ + self.write_register("General", "Reset", 1) def xpt_update(self): - ''' + """ Updates XPT core. Needs to be done after changing of channel assignment. - ''' - return self.write_register('General', 'XPT_Update', 1) + """ + return self.write_register("General", "XPT_Update", 1) def output_table(self, write=False, table=0): - ''' + """ Either set an output table (0 or 1), or retrieve the current table. - ''' + """ if not write: - self.select_table = self.read_register('General', 'Table_Select') + self.select_table = self.read_register("General", "Table_Select") return self.select_table elif write: self.select_table = table - self.write_register('General', 'Table_Select', self.select_table) + self.write_register("General", "Table_Select", self.select_table) else: raise Exception def assign_output(self, channel="OUT0", val=0): - ''' + """ Assign an input channel to a given output channel. Input channels are expected as integers. - ''' + """ if isinstance(channel, int): - if self.name == 'ADN4605': + if self.name == "ADN4605": channel = self.output_channels[channel] - elif self.name == 'ADN4604': + elif self.name == "ADN4604": channel = self.output_channels[channel] else: raise NotImplementedError if self.select_table == 0: # Selecting table - self.table = 'XPT_Map0' + self.table = "XPT_Map0" elif self.select_table == 1: - self.table = 'XPT_Map1' + self.table = "XPT_Map1" return self.write_register(self.table, channel, val) - def tx_config(self, register, channel='OUT0', val=0, write=True): - ''' + def tx_config(self, register, channel="OUT0", val=0, write=True): + """ Configure TX channels. Available register blocks: TX_Drive_Control, TX_Sign_Control, TX_Lane_Control. - ''' + """ if isinstance(channel, int): channel = self.output_channels[channel] if channel not in self.map[register].keys(): @@ -232,11 +242,11 @@ def tx_config(self, register, channel='OUT0', val=0, write=True): elif write: return self.write_register(register, channel, val) - def rx_config(self, register, channel='IN0', val=0, write=True): - ''' + def rx_config(self, register, channel="IN0", val=0, write=True): + """ Configure RX channels. Available register blocks: RX_EQ_Control, RX_Sign_Control. Retrieve current config. - ''' + """ if channel not in self.map[register].keys(): logging.info("Invalid %s Register: %s" % (register, channel)) raise ValueError @@ -246,48 +256,48 @@ def rx_config(self, register, channel='IN0', val=0, write=True): return self.write_register(register, channel, val) def set_termination(self): - ''' + """ Set rx and tx termination for XPT. - ''' + """ for key in self.map["TX_Termination_Control"]: self.tx_termination(key, val=0, write=True) if self.name == "ADN4605": # ADN4604 has no RX term for key in self.map["RX_Termination_Control"]: self.rx_termination(key, val=0, write=True) - def tx_termination(self, output='TXA_TERM0', write=False, val=0): - ''' + def tx_termination(self, output="TXA_TERM0", write=False, val=0): + """ Set/get tx termination. 0 is termination active. - ''' + """ if output not in self.map["TX_Termination_Control"].keys(): logging.info("Invalid Tx Termination Control Register") raise ValueError if not write: - return self.read_register('TX_Termination_Control', output) + return self.read_register("TX_Termination_Control", output) elif write: - return self.write_register('TX_Termination_Control', output, val) + return self.write_register("TX_Termination_Control", output, val) - def rx_termination(self, base_addr, output='RXA_TERM0', write=False, val=0): - ''' + def rx_termination(self, base_addr, output="RXA_TERM0", write=False, val=0): + """ Set/get rx termination. 0 is termination active. - ''' - if self.name == 'ADN4604': + """ + if self.name == "ADN4604": pass - elif self.name == 'ADN4605': + elif self.name == "ADN4605": if output not in self.map["RX_Termination_Control"].keys(): logging.info("Invalid Rx Termination Control Register") raise ValueError if not write: - return self.read_register('RX_Termination_Control', output) + return self.read_register("RX_Termination_Control", output) elif write: - return self.write_register('RX_Termination_Control', output, val) + return self.write_register("RX_Termination_Control", output, val) def io_config(self, conf): """Map input pins to the XP outputs according to specifications in the eos_config.yaml. In addition, configure the XP outputs: TX_Lane_Control, TX_Sign_Control and TX_Drive_Control. TX_Lane_Control and TX_Drive_Control offer broadcast.""" - if self.name == 'ADN4605': - for key, value in conf['AURORA_IN'].items(): + if self.name == "ADN4605": + for key, value in conf["AURORA_IN"].items(): if value is not None: self.assign_output(channel=key, val=value) self.tx_config("TX_Lane_Control", key, 0b01001000, True) @@ -300,22 +310,21 @@ def io_config(self, conf): raise NotImplementedError self.input_config() - elif self.name == 'ADN4604': - for key, value in conf['CMD_IN'].items(): - + elif self.name == "ADN4604": + for key, value in conf["CMD_IN"].items(): if not value == "None": # print(key,value) # print(value==True) self.assign_output(channel=key, val=value) - self.tx_config("TX_basic_control", key, 0xff, True) + self.tx_config("TX_basic_control", key, 0xFF, True) self.rx_termination("RX_EQ_Control", key, 1, True) elif value == "None": # But why? pass else: raise NotImplementedError - elif self.name == 'ADN4604_DATA': - for key, value in conf['AURORA_IN'].items(): + elif self.name == "ADN4604_DATA": + for key, value in conf["AURORA_IN"].items(): if value is not None: self.assign_output(channel=key, val=value) self.tx_config("TX_basic_control", key, 0b00110000, True) @@ -326,8 +335,8 @@ def io_config(self, conf): raise NotImplementedError self.input_config() - elif self.name == 'ADN4604_CMD': - for key, value in conf['CMD_IN'].items(): + elif self.name == "ADN4604_CMD": + for key, value in conf["CMD_IN"].items(): if value is not None: self.assign_output(channel=key, val=value) self.tx_config("TX_basic_control", key, 0b00110000, True) @@ -338,8 +347,8 @@ def io_config(self, conf): raise NotImplementedError self.input_config() - elif self.name == 'ADN4604_MOD': - for key, value in conf['MODULE_IN'].items(): + elif self.name == "ADN4604_MOD": + for key, value in conf["MODULE_IN"].items(): if value is not None: self.assign_output(channel=key, val=value) self.tx_config("TX_basic_control", key, 0b00110000, True) @@ -350,13 +359,13 @@ def io_config(self, conf): raise NotImplementedError self.input_config() - def get_output_status(self, channel='OUT0'): - ''' + def get_output_status(self, channel="OUT0"): + """ Query output channel assignment. - ''' + """ if isinstance(channel, int): channel = self.output_channels[channel] - return self.read_register('XPT_Status', channel) + return self.read_register("XPT_Status", channel) def input_config(self): """Configure XP inputs. Available settings are RX_EQ_Control and RX_Sign_Control. @@ -364,14 +373,14 @@ def input_config(self): on an input-by-input basis.""" for key in self.map["RX_EQ_Control"].keys(): if "BC" in key: # Use BCAST - self.rx_config('RX_EQ_Control', key, val=0b00000011, write=True) + self.rx_config("RX_EQ_Control", key, val=0b00000011, write=True) elif "BC" not in key: # Use a different map for input equalizer / inverter. Not implemented - self.rx_config('RX_EQ_Control', key, val=0, write=True) + self.rx_config("RX_EQ_Control", key, val=0, write=True) # if self.name == 'ADN4604_CMD': # need to invert CMD signal for QMS card # for key in self.map["RX_Sign_Control"].keys(): # self.rx_config('RX_Sign_Control', key, val = 0x00, write = True) -if __name__ == '__main__': +if __name__ == "__main__": pass diff --git a/basil/HL/agilent33250a.py b/basil/HL/agilent33250a.py index 3daa032f2..6dde8a66a 100644 --- a/basil/HL/agilent33250a.py +++ b/basil/HL/agilent33250a.py @@ -9,8 +9,7 @@ class agilent33250a(scpi): - '''Interface for Agilent 33250A Function/Arbitrary Waveform Generator implementing additional functionality. - ''' + """Interface for Agilent 33250A Function/Arbitrary Waveform Generator implementing additional functionality.""" def __init__(self, intf, conf): super(agilent33250a, self).__init__(intf, conf) @@ -21,25 +20,25 @@ def set_repeat(self, repeat): def get_repeat(self, repeat): raise NotImplementedError("get_repeat() not implemented") - def set_voltage(self, low, high=0.75, unit='mV'): - if unit == 'raw': + def set_voltage(self, low, high=0.75, unit="mV"): + if unit == "raw": raw_low, raw_high = low, high - elif unit == 'V': + elif unit == "V": raw_low, raw_high = low, high - elif unit == 'mV': + elif unit == "mV": raw_low, raw_high = low * 0.001, high * 0.001 else: raise TypeError("Invalid unit type.") self.set_voltage_high(raw_high) self.set_voltage_low(raw_low) - def get_voltage(self, channel, unit='mV'): + def get_voltage(self, channel, unit="mV"): raw_low, raw_high = float(self.get_voltage_low()), float(self.get_voltage_high()) - if unit == 'raw': + if unit == "raw": return raw_low, raw_high - elif unit == 'V': + elif unit == "V": return raw_low, raw_high - elif unit == 'mV': + elif unit == "mV": return raw_low * 1000, raw_high * 1000 else: raise TypeError("Invalid unit type.") diff --git a/basil/HL/agilent_33250a.yaml b/basil/HL/agilent_33250a.yaml index 169c4ff1c..eedc58ff2 100644 --- a/basil/HL/agilent_33250a.yaml +++ b/basil/HL/agilent_33250a.yaml @@ -1,4 +1,4 @@ -# Device description for the Agilent 33250A Function/Arbitrary Waveform Generator. +# Device description for the Agilent 33250A Function/Arbitrary Waveform Generator. # set_ function expect a parameter, get_ function return a parameter. # Almost all available commands are implemented except arbitrary signals, commands # to save/reset device states, statusregister commands, IEEE 488.2 commands @@ -11,13 +11,13 @@ identifier : Agilent Technologies,33250A ###### # Set function type (frequency, amplitude, offset) ###### -set_sin: APPLy:SINusoid -set_square: APPLy:SQUare -set_ramp: APPLy:RAMP -set_pulse: APPLy:PULSe -set_noise: APPLy:NOISe +set_sin: APPLy:SINusoid +set_square: APPLy:SQUare +set_ramp: APPLy:RAMP +set_pulse: APPLy:PULSe +set_noise: APPLy:NOISe set_DC: APPLy:DC -set_arb: APPLy:USER +set_arb: APPLy:USER get_function: APPLy? ###### @@ -146,9 +146,9 @@ get_trigger_source: TRIGger:SOURce? trigger: TRIG set_trigger_delay: TRIGger:DELay #{Seconds|MINimum|MAXimum} get_trigger_delay: TRIGger:DELay? #[MINimum|MAXimum] -set_trigger_slope: TRIGger:SLOPe #{POSitive|NEGative} +set_trigger_slope: TRIGger:SLOPe #{POSitive|NEGative} get_trigger_slope: TRIGger:SLOPe?BURSt:GATE:POLarity #{NORMal|INVerted} -set_trigger_output_slope: OUTPut:TRIGger:SLOPe #{POSitive|NEGative} +set_trigger_output_slope: OUTPut:TRIGger:SLOPe #{POSitive|NEGative} get_trigger_output_slope: OUTPut:TRIGger:SLOPe? set_trigger_output: OUTPut:TRIGger #{OFF|ON} get_trigger_output: OUTPut:TRIGger? diff --git a/basil/HL/agilent_e3644a.yaml b/basil/HL/agilent_e3644a.yaml index 9682e08be..2c37501b7 100644 --- a/basil/HL/agilent_e3644a.yaml +++ b/basil/HL/agilent_e3644a.yaml @@ -1,4 +1,4 @@ -# Device description for the Agilent Technologies E3644A Power Supply. +# Device description for the Agilent Technologies E3644A Power Supply. # set_ function expect a parameter, get_ function return a parameter. # Just the very basic commands are implemented here. identifier: Agilent Technologies,E3644A diff --git a/basil/HL/arduino_base.py b/basil/HL/arduino_base.py index 5f5f8b296..3f78b2022 100644 --- a/basil/HL/arduino_base.py +++ b/basil/HL/arduino_base.py @@ -1,18 +1,14 @@ from time import sleep + from basil.HL.RegisterHardwareLayer import HardwareLayer class ArduinoBase(HardwareLayer): + CMD_DELIMITER = ":" - CMD_DELIMITER = ':' - - CMDS = { - 'communication_delay': 'D' - } + CMDS = {"communication_delay": "D"} - ERRORS = { - 'error': "An error occured" - } + ERRORS = {"error": "An error occured"} @property def communication_delay(self): @@ -24,7 +20,7 @@ def communication_delay(self): int Communication delay in milliseconds """ - return int(self.query(self.create_command(self.CMDS['communication_delay']))) + return int(self.query(self.create_command(self.CMDS["communication_delay"]))) @communication_delay.setter def communication_delay(self, comm_delay): @@ -36,7 +32,7 @@ def communication_delay(self, comm_delay): comm_delay : int Communication delay in milliseconds """ - self._set_and_retrieve(cmd='communication_delay', val=comm_delay) + self._set_and_retrieve(cmd="communication_delay", val=comm_delay) def __init__(self, intf, conf): super(ArduinoBase, self).__init__(intf, conf) @@ -134,4 +130,4 @@ def create_command(self, *args): str Formatted command string """ - return f'{self.CMD_DELIMITER.join(str(a) for a in args)}{self.CMD_DELIMITER}'.encode() + return f"{self.CMD_DELIMITER.join(str(a) for a in args)}{self.CMD_DELIMITER}".encode() diff --git a/basil/HL/arduino_env_readout.py b/basil/HL/arduino_env_readout.py index 95fd1b675..35d8aede1 100644 --- a/basil/HL/arduino_env_readout.py +++ b/basil/HL/arduino_env_readout.py @@ -1,8 +1,9 @@ import logging -from basil.HL.arduino_ntc_readout import NTCReadout import numpy as np +from basil.HL.arduino_ntc_readout import NTCReadout + logger = logging.getLogger(__name__) @@ -10,43 +11,62 @@ class EnvironmentReadout(NTCReadout): """Class to read from Arduino temperature or humidity/pressure sensor setup""" def __init__(self, intf, conf): - self.CMDS.update({ - 'analog_read': 'A'}) + self.CMDS.update({"analog_read": "A"}) super(EnvironmentReadout, self).__init__(intf, conf) - self.fixed_resistors = self._init.get('resistors', [10000] * 8) + self.fixed_resistors = self._init.get("resistors", [10000] * 8) if not isinstance(self.fixed_resistors, list) and isinstance(self.fixed_resistors, (int, float)): self.fixed_resistors = [float(self.fixed_resistors)] * 8 - self.adc_range = float(self._init.get('adc_range', 1023)) - self.operating_voltage = float(self._init.get('operating_voltage', 5.0)) - - self.humidity_pin = int(self._init.get('humidity_pin', -1)) - self.pressure_pin = int(self._init.get('pressure_pin', -1)) - - self.steinharthart_params = dict(self._init.get('steinharthart_params', { - "A": 0.0, - "B": 0.0, - "C": 0.0, - "D": 0.0, - "R25": 0.0, - })) - - self.humidity_params = dict(self._init.get('humidity_params', { - "slope": 0.0, - "offset": 0.0, - })) - - self.humidity_temp_correction_params = dict(self._init.get('humidity_temp_correction_params', { - "slope": 0.0, - "offset": 0.0, - })) - - self.pressure_params = dict(self._init.get('pressure_params', { - "slope": 0.0, - "offset": 0.0, - })) + self.adc_range = float(self._init.get("adc_range", 1023)) + self.operating_voltage = float(self._init.get("operating_voltage", 5.0)) + + self.humidity_pin = int(self._init.get("humidity_pin", -1)) + self.pressure_pin = int(self._init.get("pressure_pin", -1)) + + self.steinharthart_params = dict( + self._init.get( + "steinharthart_params", + { + "A": 0.0, + "B": 0.0, + "C": 0.0, + "D": 0.0, + "R25": 0.0, + }, + ) + ) + + self.humidity_params = dict( + self._init.get( + "humidity_params", + { + "slope": 0.0, + "offset": 0.0, + }, + ) + ) + + self.humidity_temp_correction_params = dict( + self._init.get( + "humidity_temp_correction_params", + { + "slope": 0.0, + "offset": 0.0, + }, + ) + ) + + self.pressure_params = dict( + self._init.get( + "pressure_params", + { + "slope": 0.0, + "offset": 0.0, + }, + ) + ) def set_fixed_resistance(self, pin, resistance): self.fixed_resistors[pin] = resistance @@ -60,7 +80,12 @@ def get_resistance(self, sensor, adc_range=None): if adc_range is None: adc_range = self.adc_range - return {s: self.fixed_resistors[s] / (adc_range / analog_read[s] - 1.0) if abs(adc_range / analog_read[s] - 1) > 0.01 else None for s in sensor} + return { + s: self.fixed_resistors[s] / (adc_range / analog_read[s] - 1.0) + if abs(adc_range / analog_read[s] - 1) > 0.01 + else None + for s in sensor + } def get_voltage(self, sensor, adc_range=None): analog_read = self.analog_read(sensor) @@ -87,30 +112,36 @@ def temperature(self, sensor, adc_range=None): resistances = self.get_resistance(sensor, adc_range) - return {s: self.steinharthart(resistances[s], **self.steinharthart_params) if resistances[s] is not None else None for s in sensor} + return { + s: self.steinharthart(resistances[s], **self.steinharthart_params) if resistances[s] is not None else None + for s in sensor + } def humidity(self, temperature_correction=None, adc_range=None): if self.humidity_pin < 0: - logger.warning('No humidity pin specified!') + logger.warning("No humidity pin specified!") return voltage = self.get_voltage(self.humidity_pin, adc_range)[self.humidity_pin] - RH = (voltage - self.humidity_params['offset']) / self.humidity_params['slope'] + RH = (voltage - self.humidity_params["offset"]) / self.humidity_params["slope"] if temperature_correction is not None: - RH = RH / (self.humidity_temp_correction_params['slope'] * temperature_correction + self.humidity_temp_correction_params['offset']) + RH = RH / ( + self.humidity_temp_correction_params["slope"] * temperature_correction + + self.humidity_temp_correction_params["offset"] + ) return max(float(RH), 0.0) def pressure(self, adc_range=None): if self.pressure_pin < 0: - logger.warning('No pressure pin specified!') + logger.warning("No pressure pin specified!") return voltage = self.get_voltage(self.pressure_pin, adc_range)[self.pressure_pin] - return self.pressure_params['slope'] * voltage - self.pressure_params['offset'] + return self.pressure_params["slope"] * voltage - self.pressure_params["offset"] def analog_read(self, sensor): - return self._get_measurement(sensor, kind='analog_read') + return self._get_measurement(sensor, kind="analog_read") diff --git a/basil/HL/arduino_grove_4channel_relay.py b/basil/HL/arduino_grove_4channel_relay.py index bd76a0dd5..c6a2f0d2c 100644 --- a/basil/HL/arduino_grove_4channel_relay.py +++ b/basil/HL/arduino_grove_4channel_relay.py @@ -9,49 +9,45 @@ class RelayBoard(ArduinoBase): - ''' + """ Implement functions to control the Arduino digital IO using the Basil Arduino firmware. - ''' + """ - CMDS = { - 'read': 'R', - 'write': 'W', - 'delay': 'D' - } + CMDS = {"read": "R", "write": "W", "delay": "D"} ERRORS = { - 'error': "Serial transmission error" # Custom return code for unsuccesful serial communciation + "error": "Serial transmission error" # Custom return code for unsuccesful serial communciation } def __init__(self, intf, conf): super(RelayBoard, self).__init__(intf, conf) def set_output(self, channel, value): - if value == 'ON': + if value == "ON": value = 1 - elif value == 'OFF': + elif value == "OFF": value = 0 if value != 0 and value != 1: - raise ValueError('The value for the output has to be ON, OFF, 0 or 1') + raise ValueError("The value for the output has to be ON, OFF, 0 or 1") - if channel == 'ALL': + if channel == "ALL": channel = 99 # All channels are internally channel 99 if channel < 1 or (channel > 4 and channel != 99): - raise ValueError('Grove relay only has 4 channels. %d is out of range.' % channel) + raise ValueError("Grove relay only has 4 channels. %d is out of range." % channel) - ret = self.query(self.create_command(self.CMDS['write'], channel, value)) + ret = self.query(self.create_command(self.CMDS["write"], channel, value)) if channel == 99 and int(ret) != value * 1111: error = True - elif channel != 99 and format(int(ret, 2), '04b')[-channel] != str(value): + elif channel != 99 and format(int(ret, 2), "04b")[-channel] != str(value): error = True else: error = False if error: - raise RuntimeError('Got no or wrong response from Arduino!') + raise RuntimeError("Got no or wrong response from Arduino!") def get_state(self): - return self.query(self.create_command(self.CMDS['read'])) + return self.query(self.create_command(self.CMDS["read"])) diff --git a/basil/HL/arduino_ntc_readout.py b/basil/HL/arduino_ntc_readout.py index 9f5d7e4c6..f2f3cd5bf 100644 --- a/basil/HL/arduino_ntc_readout.py +++ b/basil/HL/arduino_ntc_readout.py @@ -1,6 +1,6 @@ import logging -from basil.HL.arduino_base import ArduinoBase +from basil.HL.arduino_base import ArduinoBase logger = logging.getLogger(__name__) @@ -9,76 +9,76 @@ class NTCReadout(ArduinoBase): """Class to read from Arduino temperature sensor setup""" CMDS = { - 'temp': 'T', - 'res': 'Q', - 'samples': 'S', - 'beta': 'B', - 'nominal_res': 'O', - 'nominal_temp': 'C', - 'resistance': 'R', - 'restore': 'X', - 'measure_ntc': 'Y' + "temp": "T", + "res": "Q", + "samples": "S", + "beta": "B", + "nominal_res": "O", + "nominal_temp": "C", + "resistance": "R", + "restore": "X", + "measure_ntc": "Y", } ERRORS = { - '999': "Invalid NTC pin", - 'error': "Serial transmission error" # Custom return code for unsuccesful serial communciation + "999": "Invalid NTC pin", + "error": "Serial transmission error", # Custom return code for unsuccesful serial communciation } @property def n_samples(self): - return int(self.query(self.create_command(self.CMDS['samples']))) + return int(self.query(self.create_command(self.CMDS["samples"]))) @n_samples.setter def n_samples(self, n_samples): - self._set_and_retrieve(cmd='samples', val=int(n_samples)) + self._set_and_retrieve(cmd="samples", val=int(n_samples)) @property def beta_coefficient(self): - return float(self.query(self.create_command(self.CMDS['beta']))) + return float(self.query(self.create_command(self.CMDS["beta"]))) @beta_coefficient.setter def beta_coefficient(self, beta_coefficient): - self._set_and_retrieve(cmd='beta', val=float(beta_coefficient)) + self._set_and_retrieve(cmd="beta", val=float(beta_coefficient)) @property def nominal_resistance(self): - return float(self.query(self.create_command(self.CMDS['nominal_res']))) + return float(self.query(self.create_command(self.CMDS["nominal_res"]))) @nominal_resistance.setter def nominal_resistance(self, nominal_res): - self._set_and_retrieve(cmd='nominal_res', val=float(nominal_res)) + self._set_and_retrieve(cmd="nominal_res", val=float(nominal_res)) @property def nominal_temperature(self): - return float(self.query(self.create_command(self.CMDS['nominal_temp']))) + return float(self.query(self.create_command(self.CMDS["nominal_temp"]))) @nominal_temperature.setter def nominal_temperature(self, nominal_temp): - self._set_and_retrieve(cmd='nominal_temp', val=float(nominal_temp)) + self._set_and_retrieve(cmd="nominal_temp", val=float(nominal_temp)) @property def resistance(self): - return float(self.query(self.create_command(self.CMDS['resistance']))) + return float(self.query(self.create_command(self.CMDS["resistance"]))) @resistance.setter def resistance(self, resistance): - self._set_and_retrieve(cmd='resistance', val=float(resistance)) + self._set_and_retrieve(cmd="resistance", val=float(resistance)) @property def measure_v_drop_over_ntc(self): - return bool(int(self.query(self.create_command(self.CMDS['measure_ntc'])))) + return bool(int(self.query(self.create_command(self.CMDS["measure_ntc"])))) @measure_v_drop_over_ntc.setter def measure_v_drop_over_ntc(self, measure_ntc): - self._set_and_retrieve(cmd='measure_ntc', val=1 if bool(measure_ntc) else 0) + self._set_and_retrieve(cmd="measure_ntc", val=1 if bool(measure_ntc) else 0) def __init__(self, intf, conf): super(NTCReadout, self).__init__(intf, conf) # Store temperature limits of NTC thermistor - self.ntc_limits = tuple(self._init.get('ntc_limits', (-55, 120))) + self.ntc_limits = tuple(self._init.get("ntc_limits", (-55, 120))) - def _get_measurement(self, sensor, kind='temp'): + def _get_measurement(self, sensor, kind="temp"): """Gets measurement of sensor where 0 <= sensor <= 7 is the physical pin number of the sensor on the Arduino analog pin. Can also be a list of ints.""" @@ -95,13 +95,15 @@ def restore_defaults(self): """ Restores default values in the firmware which correspond to this classes properties """ - self._set_and_retrieve(cmd='restore', val=int(111)) # *val* can be any int, just used to test that the command was received + self._set_and_retrieve( + cmd="restore", val=int(111) + ) # *val* can be any int, just used to test that the command was received def get_temp(self, sensor): """Gets temperature of sensor where 0 <= sensor <= 7 is the physical pin number of the sensor on the Arduino analog pin. Can also be a list of ints.""" - result = self._get_measurement(sensor, kind='temp') + result = self._get_measurement(sensor, kind="temp") for sens in result: if not self.ntc_limits[0] <= result[sens] <= self.ntc_limits[1]: @@ -114,4 +116,4 @@ def get_res(self, sensor): """Gets resitance measured on input *sensor* where 0 <= sensor <= 7 is the physical pin number of the sensor on the Arduino analog pin. Can also be a list of ints.""" - return self._get_measurement(sensor, kind='res') + return self._get_measurement(sensor, kind="res") diff --git a/basil/HL/arduino_relay_board.py b/basil/HL/arduino_relay_board.py index 30df66583..d85259cb4 100644 --- a/basil/HL/arduino_relay_board.py +++ b/basil/HL/arduino_relay_board.py @@ -9,39 +9,38 @@ class RelayBoard(ArduinoBase): - ''' + """ Implement functions to control the Arduino digital IO using the Basil Arduino firmware. - ''' + """ - CMDS = { - 'read': 'R', - 'write': 'W', - 'delay': 'D' - } + CMDS = {"read": "R", "write": "W", "delay": "D"} ERRORS = { - 'error': "Serial transmission error" # Custom return code for unsuccesful serial communciation + "error": "Serial transmission error" # Custom return code for unsuccesful serial communciation } def __init__(self, intf, conf): super(RelayBoard, self).__init__(intf, conf) def set_output(self, channel, value): - if value == 'ON': + if value == "ON": value = 1 - elif value == 'OFF': + elif value == "OFF": value = 0 if value != 0 and value != 1: - raise ValueError('The value for the output has to be ON, OFF, 0 or 1') + raise ValueError("The value for the output has to be ON, OFF, 0 or 1") - if channel == 'ALL': + if channel == "ALL": channel = 99 # All channels are internally channel 99 if channel < 2 or (channel > 13 and channel != 99): - raise ValueError('Arduino supports only 14 IOs and pins 0 and 1 are blocked by Serial communication. %d is out of range.' % channel) + raise ValueError( + "Arduino supports only 14 IOs and pins 0 and 1 are blocked by Serial communication. %d is out of range." + % channel + ) - ret = self.query(self.create_command(self.CMDS['write'], channel, value)) + ret = self.query(self.create_command(self.CMDS["write"], channel, value)) error = False if channel == 99 and int(ret) != value * 1111111111: @@ -50,7 +49,7 @@ def set_output(self, channel, value): error = True if error: - raise RuntimeError('Got no or wrong response from Arduino!') + raise RuntimeError("Got no or wrong response from Arduino!") def get_state(self): - return self.query(self.create_command(self.CMDS['read'])) + return self.query(self.create_command(self.CMDS["read"])) diff --git a/basil/HL/arduino_serial_to_i2c.py b/basil/HL/arduino_serial_to_i2c.py index d8c39c870..261f16f7f 100644 --- a/basil/HL/arduino_serial_to_i2c.py +++ b/basil/HL/arduino_serial_to_i2c.py @@ -6,25 +6,19 @@ class I2CTransmissionError(ValueError): class SerialToI2C(ArduinoBase): - - CMDS = { - 'write': 'W', - 'read': 'R', - 'address': 'A', - 'check': 'T' - } + CMDS = {"write": "W", "read": "R", "address": "A", "check": "T"} ERRORS = { - 'error': "Serial transmission error" # Custom return code for unsuccesful serial communciation + "error": "Serial transmission error" # Custom return code for unsuccesful serial communciation } # Check https://www.arduino.cc/en/Reference/WireEndTransmission I2C_RETURN_CODES = { - '0': "Success", - '1': "Data too long to fit in transmit buffer", - '2': "Received NACK on transmit of address", - '3': "Received NACK on transmit of data", - '4': "Other error" + "0": "Success", + "1": "Data too long to fit in transmit buffer", + "2": "Received NACK on transmit of address", + "3": "Received NACK on transmit of data", + "4": "Other error", } @property @@ -37,7 +31,7 @@ def i2c_address(self): int I2C address """ - return int(self.query(self.create_command(self.CMDS['address']))) + return int(self.query(self.create_command(self.CMDS["address"]))) @i2c_address.setter def i2c_address(self, addr): @@ -54,7 +48,7 @@ def i2c_address(self, addr): I2CTransmissionError If the set address on the Arduino does not match with what has been sent """ - self._set_and_retrieve(cmd='address', val=int(addr), exception_=I2CTransmissionError) + self._set_and_retrieve(cmd="address", val=int(addr), exception_=I2CTransmissionError) def __init__(self, intf, conf): super(SerialToI2C, self).__init__(intf, conf) @@ -85,7 +79,7 @@ def query_i2c(self, msg): try: i2c_return_code = self.query(msg) - if i2c_return_code != '0': + if i2c_return_code != "0": if i2c_return_code not in self.I2C_RETURN_CODES: raise NotImplementedError(f"Unknown return code {i2c_return_code}") raise I2CTransmissionError(self.I2C_RETURN_CODES[i2c_return_code]) @@ -109,7 +103,7 @@ def read_register(self, reg): int Data read from *reg* """ - self.query_i2c(self.create_command(self.CMDS['read'], reg)) + self.query_i2c(self.create_command(self.CMDS["read"], reg)) return int(self.read()) def write_register(self, reg, data): @@ -123,10 +117,10 @@ def write_register(self, reg, data): data : int Data to write to register *reg* """ - self.query_i2c(self.create_command(self.CMDS['write'], reg, data)) + self.query_i2c(self.create_command(self.CMDS["write"], reg, data)) def check_i2c_connection(self): """ Checks the i2c connection from arduino to bus device """ - self.query_i2c(self.create_command(self.CMDS['check'])) + self.query_i2c(self.create_command(self.CMDS["check"])) diff --git a/basil/HL/binder_mk53.py b/basil/HL/binder_mk53.py index e82878338..8de102fc7 100644 --- a/basil/HL/binder_mk53.py +++ b/basil/HL/binder_mk53.py @@ -11,11 +11,10 @@ class binderMK53(HardwareLayer): - - '''Driver for the Binder MK 53 climate chamber. + """Driver for the Binder MK 53 climate chamber. A protocoll _similar_ to MODBus via RS 422 serial port is used with 9600 baud rate. Credits to ecree-solarflare with some further information at https://github.com/ecree-solarflare/ovenctl - ''' + """ # MODBus function codes FUNCTION_READN = 0x03 # read n words @@ -23,12 +22,12 @@ class binderMK53(HardwareLayer): FUNCTION_WRITE = 0x06 # write word FUNCTION_WRITEN = 0x10 # write n words - ADDR_CURTEMP = 0x11a9 + ADDR_CURTEMP = 0x11A9 ADDR_DOOROPEN = 0x1007 # does not work, wrong address? ADDR_SETPOINT = 0x1077 ADDR_MANSETPT = 0x1581 - ADDR_BASICSETPT = 0x156f - ADDR_MODE = 0x1a22 + ADDR_BASICSETPT = 0x156F + ADDR_MODE = 0x1A22 # Error codes ERROR_CODES = { @@ -36,7 +35,7 @@ class binderMK53(HardwareLayer): 2: "Invalid parameter address", 3: "Parameter value outside range of values", 4: "Slave not ready", - 5: "Write access to parameter denied" + 5: "Write access to parameter denied", } def __init__(self, intf, conf): @@ -45,9 +44,9 @@ def __init__(self, intf, conf): def init(self): super(binderMK53, self).init() # Operation addresses - self.slave_address = self._init['address'] # set the device address - self.min_temp = self._init['min_temp'] # define the minimum temperature one can set, for safety - self.max_temp = self._init['max_temp'] # define the maximum temperature one can set, for safety + self.slave_address = self._init["address"] # set the device address + self.min_temp = self._init["min_temp"] # define the minimum temperature one can set, for safety + self.max_temp = self._init["max_temp"] # define the maximum temperature one can set, for safety def get_temperature(self, reps=10): ret = -400 @@ -81,10 +80,12 @@ def get_mode(self): def set_temperature(self, temperature): if temperature < self.min_temp: raise RuntimeWarning( - f'Set temperature {temperature} is lower than minimum allowed temperature {self.min_temp}') + f"Set temperature {temperature} is lower than minimum allowed temperature {self.min_temp}" + ) if temperature > self.max_temp: raise RuntimeWarning( - f'Set temperature {temperature} is higher than maximum allowed temperature {self.max_temp}') + f"Set temperature {temperature} is higher than maximum allowed temperature {self.max_temp}" + ) self.write(self.ADDR_MANSETPT, self._encode_float(temperature)) self.write(self.ADDR_BASICSETPT, self._encode_float(temperature)) @@ -96,7 +97,7 @@ def read(self, addr, n_words): # read n words resp = self._intf.read(exp_length) is_err, err_code = self._parse_error_response(resp) if is_err: - raise RuntimeWarning(f'Error code {err_code}: {self.ERROR_CODES[err_code]}') + raise RuntimeWarning(f"Error code {err_code}: {self.ERROR_CODES[err_code]}") data = self._parse_read_response(resp) return data @@ -108,75 +109,75 @@ def write(self, addr, value): # write n words with acknowledge is_err, err_code = self._parse_error_response(resp) if is_err: - raise ValueError(f'Error code {err_code}: {self.ERROR_CODES[err_code]}') + raise ValueError(f"Error code {err_code}: {self.ERROR_CODES[err_code]}") resp_addr, resp_words = self._parse_write_response(resp) if not (resp_addr == addr) and (resp_words == len(value)): - raise ValueError('Write check failed') + raise ValueError("Write check failed") def _parse_read_response(self, msgbytes): if len(msgbytes) < 3: - raise ValueError(f'Read data is too short: {len(msgbytes)}') - _, func, n_bytes = struct.unpack('>BBB', msgbytes[:3]) + raise ValueError(f"Read data is too short: {len(msgbytes)}") + _, func, n_bytes = struct.unpack(">BBB", msgbytes[:3]) if func not in [self.FUNCTION_READN, self.FUNCTION_READN_ALT]: - raise ValueError('Wrong function returned') + raise ValueError("Wrong function returned") if n_bytes & 1: raise ValueError("Odd number of bytes read") if len(msgbytes) < 5 + n_bytes: - raise ValueError(f'Read data is too short: {len(msgbytes)}') - crc = struct.unpack('> 1 words = [] for word in range(n_words): - words.extend(struct.unpack('>H', msgbytes[3 + word * 2:5 + word * 2])) + words.extend(struct.unpack(">H", msgbytes[3 + word * 2 : 5 + word * 2])) return words def _parse_write_response(self, msgbytes): if len(msgbytes) < 8: - raise ValueError(f'Message too short: {len(msgbytes)}') - crc = struct.unpack('BBHH', msgbytes[:6]) + raise ValueError(f"Message too short: {len(msgbytes)}") + crc = struct.unpack("BBHH", msgbytes[:6]) if func != self.FUNCTION_WRITEN: - raise ValueError('Wrong write function returned') + raise ValueError("Wrong write function returned") checkcrc = self._calc_crc16(msgbytes[:6]) if crc != checkcrc: - raise ValueError('Checksum of read after write data wrong') + raise ValueError("Checksum of read after write data wrong") return addr, value def _parse_error_response(self, msgbytes): # string -> (bool, int) if len(msgbytes) < 5: return False, None - crc = struct.unpack('BBB', msgbytes[:3]) + crc = struct.unpack("BBB", msgbytes[:3]) if not func & 0x80: return False, None checkcrc = self._calc_crc16(msgbytes[:3]) if crc != checkcrc: - raise ValueError(f'CRC Error: {str(crc)} - {str(checkcrc)} (bytes: {str(msgbytes)})') + raise ValueError(f"CRC Error: {str(crc)} - {str(checkcrc)} (bytes: {str(msgbytes)})") return True, ecode def _make_write_request(self, addr, words): n_words = len(words) - msg = struct.pack('>BBHHB', self.slave_address, self.FUNCTION_WRITEN, addr, n_words, n_words * 2) + msg = struct.pack(">BBHHB", self.slave_address, self.FUNCTION_WRITEN, addr, n_words, n_words * 2) for word in words: - msg += struct.pack('>H', word) - return msg + struct.pack('H", word) + return msg + struct.pack("BBHH', self.slave_address, self.FUNCTION_READN, addr, n_words) - return msg + struct.pack('BBHH", self.slave_address, self.FUNCTION_READN, addr, n_words) + return msg + struct.pack("HH', struct.pack('>f', value)) + words = struct.unpack(">HH", struct.pack(">f", value)) return words[1], words[0] def _decode_float(self, value): - return struct.unpack('>f', struct.pack('>HH', value[1], value[0]))[0] + return struct.unpack(">f", struct.pack(">HH", value[1], value[0]))[0] def _calc_crc16(self, msg): - crc = 0xffff + crc = 0xFFFF for byte in msg: crc ^= byte for _ in range(8): # loop bits diff --git a/basil/HL/binder_mk56.py b/basil/HL/binder_mk56.py index e656b08ac..589184ece 100644 --- a/basil/HL/binder_mk56.py +++ b/basil/HL/binder_mk56.py @@ -17,8 +17,8 @@ class binderMK56(binderMK53): """ ADDR_CURTEMP = 0x1004 - ADDR_SETPOINT = 0x10b2 - ADDR_MANSETPT = 0x114c + ADDR_SETPOINT = 0x10B2 + ADDR_MANSETPT = 0x114C def get_door_open(self): raise NotImplementedError("Get Door not available for MK56.") @@ -29,10 +29,12 @@ def get_mode(self): def set_temperature(self, temperature, reps=10): if temperature < self.min_temp: raise RuntimeWarning( - f'Set temperature {temperature} is lower than minimum allowed temperature {self.min_temp}') + f"Set temperature {temperature} is lower than minimum allowed temperature {self.min_temp}" + ) if temperature > self.max_temp: raise RuntimeWarning( - f'Set temperature {temperature} is higher than maximum allowed temperature {self.max_temp}') + f"Set temperature {temperature} is higher than maximum allowed temperature {self.max_temp}" + ) for _ in range(reps): try: self.write(self.ADDR_MANSETPT, self._encode_float(temperature)) @@ -42,44 +44,44 @@ def set_temperature(self, temperature, reps=10): def _parse_read_response(self, msgbytes): if len(msgbytes) < 3: - raise ValueError(f'Read data is too short: {len(msgbytes)}') - _, func, n_bytes = struct.unpack('>BBB', msgbytes[:3]) + raise ValueError(f"Read data is too short: {len(msgbytes)}") + _, func, n_bytes = struct.unpack(">BBB", msgbytes[:3]) if func not in [self.FUNCTION_READN, self.FUNCTION_READN_ALT]: - raise ValueError('Wrong function returned') + raise ValueError("Wrong function returned") if n_bytes & 1: raise ValueError("Odd number of bytes read") if len(msgbytes) < 5 + n_bytes: - raise ValueError(f'Read data is too short: {len(msgbytes)}') - crc = struct.unpack('> 1 words = [] for word in range(n_words): - words.extend(struct.unpack('>H', msgbytes[3 + word * 2:5 + word * 2])) + words.extend(struct.unpack(">H", msgbytes[3 + word * 2 : 5 + word * 2])) return words def _parse_write_response(self, msgbytes): if len(msgbytes) < 8: - raise ValueError(f'Message too short: {len(msgbytes)}') - crc = struct.unpack('BBHH', msgbytes[:6]) + raise ValueError(f"Message too short: {len(msgbytes)}") + crc = struct.unpack("BBHH", msgbytes[:6]) if func != self.FUNCTION_WRITEN: - raise ValueError('Wrong write function returned') + raise ValueError("Wrong write function returned") checkcrc = (self._calc_crc16(msgbytes[:6]),) if crc != checkcrc: - raise ValueError('Checksum of read after write data wrong') + raise ValueError("Checksum of read after write data wrong") return addr, value def _parse_error_response(self, msgbytes): # string -> (bool, int) if len(msgbytes) < 5: return False, None - crc = struct.unpack('BBB', msgbytes[:3]) + crc = struct.unpack("BBB", msgbytes[:3]) if not func & 0x80: return False, None checkcrc = (self._calc_crc16(msgbytes[:3]),) if crc != checkcrc: - raise ValueError(f'CRC Error: {str(crc)} - {str(checkcrc)} (bytes: {str(msgbytes)})') + raise ValueError(f"CRC Error: {str(crc)} - {str(checkcrc)} (bytes: {str(msgbytes)})") return True, ecode diff --git a/basil/HL/bram_fifo.py b/basil/HL/bram_fifo.py index c82d60948..f3affc2c7 100644 --- a/basil/HL/bram_fifo.py +++ b/basil/HL/bram_fifo.py @@ -16,15 +16,16 @@ class bram_fifo(RegisterHardwareLayer): - '''BRAM FIFO controller interface for bram_fifo FPGA module. - ''' + """BRAM FIFO controller interface for bram_fifo FPGA module.""" - _registers = {'RESET': {'descr': {'addr': 0, 'size': 8, 'properties': ['writeonly']}}, - 'VERSION': {'descr': {'addr': 0, 'size': 8, 'properties': ['ro']}}, - 'ALMOST_FULL_THRESHOLD': {'descr': {'addr': 1, 'size': 8}}, - 'ALMOST_EMPTY_THRESHOLD': {'descr': {'addr': 2, 'size': 8}}, - 'READ_ERROR_COUNTER': {'descr': {'addr': 3, 'size': 8, 'properties': ['ro']}}, - 'FIFO_SIZE': {'descr': {'addr': 4, 'size': 32, 'properties': ['ro']}}} + _registers = { + "RESET": {"descr": {"addr": 0, "size": 8, "properties": ["writeonly"]}}, + "VERSION": {"descr": {"addr": 0, "size": 8, "properties": ["ro"]}}, + "ALMOST_FULL_THRESHOLD": {"descr": {"addr": 1, "size": 8}}, + "ALMOST_EMPTY_THRESHOLD": {"descr": {"addr": 2, "size": 8}}, + "READ_ERROR_COUNTER": {"descr": {"addr": 3, "size": 8, "properties": ["ro"]}}, + "FIFO_SIZE": {"descr": {"addr": 4, "size": 32, "properties": ["ro"]}}, + } _require_version = "==2" def __init__(self, intf, conf): @@ -36,35 +37,35 @@ def reset(self): @property def FIFO_INT_SIZE(self): - ''' Get FIFO size in units of integers (32 bit). + """Get FIFO size in units of integers (32 bit). Returns ------- fifo_size : int FIFO size in units of integers (32 bit). - ''' + """ fifo_size = self.FIFO_SIZE # sometimes reading of FIFO size happens during writing to BRAM, but we want to have a multiplicity of 32 bits return int((fifo_size - (fifo_size % 4)) / 4) def get_FIFO_INT_SIZE(self): - ''' Get FIFO size in units of integers (32 bit). + """Get FIFO size in units of integers (32 bit). Returns ------- fifo_size : int FIFO size in units of integers (32 bit). - ''' + """ return self.FIFO_INT_SIZE def get_data(self): - ''' Reading data in BRAM. + """Reading data in BRAM. Returns ------- array : numpy.ndarray Array of unsigned integers (32 bit). - ''' + """ fifo_int_size_1 = self.FIFO_INT_SIZE fifo_int_size_2 = self.FIFO_INT_SIZE if fifo_int_size_1 > fifo_int_size_2: @@ -72,4 +73,6 @@ def get_data(self): logger.warning("Reading wrong FIFO size. Expected: %d <= %d" % (fifo_int_size_1, fifo_int_size_2)) else: fifo_int_size = fifo_int_size_1 # use smaller chunk - return np.frombuffer(self._intf.read(self._conf['base_data_addr'], size=4 * fifo_int_size), dtype=np.dtype(' 80 or curr < 0: raise ValueError("Illegal value for tube current (0 - 80 mA)") else: @@ -58,22 +53,19 @@ def set_current(self, curr): logger.info("Set tube current to {:.1f} mA".format(self.get_nominal_current())) def get_nominal_voltage(self): - """Read nominal voltage in kV. - """ + """Read nominal voltage in kV.""" self.write("VN") vol = self.read() - return int(vol) / 1000. + return int(vol) / 1000.0 def get_actual_voltage(self): - """Read actual voltage in kV. - """ + """Read actual voltage in kV.""" self.write("VA") vol = self.read() - return int(vol) / 1000. + return int(vol) / 1000.0 def set_voltage(self, vol): - """Set high voltage in kV - """ + """Set high voltage in kV""" if vol > 60 or vol < 0: raise ValueError("Illegal value for tube voltage (0 - 60 kV)") else: @@ -87,8 +79,7 @@ def set_high_voltage_off(self): self.write("HV:0") def open_shutter(self, shutter=1): - """Open the shutter with given number. Only shuttter=1 supported from hardware currently - """ + """Open the shutter with given number. Only shuttter=1 supported from hardware currently""" if not isinstance(shutter, int): raise TypeError("Invalid type for shutter number") elif shutter > 4 or shutter < 1: @@ -98,8 +89,7 @@ def open_shutter(self, shutter=1): logger.info("Opened shutter number {:1d}".format(shutter)) def close_shutter(self, shutter=1): - """Close the shutter with given number. Only shuttter=1 supported from hardware currently - """ + """Close the shutter with given number. Only shuttter=1 supported from hardware currently""" if not isinstance(shutter, int): raise TypeError("Invalid type for shutter number") elif shutter > 4 or shutter < 1: @@ -109,8 +99,7 @@ def close_shutter(self, shutter=1): logger.info("Closed shutter number {:1d}".format(shutter)) def activate_timer(self, shutter=1): - """Activate the timer for a given shutter number - """ + """Activate the timer for a given shutter number""" if not isinstance(shutter, int): raise TypeError("Invalid type for shutter number") elif shutter > 4 or shutter < 1: @@ -120,8 +109,7 @@ def activate_timer(self, shutter=1): logger.info("Started timer number {:1d}".format(shutter)) def deactivate_timer(self, shutter=1): - """Deactivate the timer for a given shutter number - """ + """Deactivate the timer for a given shutter number""" if not isinstance(shutter, int): raise TypeError("Invalid type for shutter number") elif shutter > 4 or shutter < 1: @@ -131,8 +119,7 @@ def deactivate_timer(self, shutter=1): logger.info("Stopped timer number {:1d}".format(shutter)) def set_timer(self, timer=1, dur=3600): - """Set the timer with the given number (corresponds to shutter number) to the given duration (in s) - """ + """Set the timer with the given number (corresponds to shutter number) to the given duration (in s)""" if not isinstance(timer, int): raise TypeError("Invalid type for timer number") elif not isinstance(dur, int): @@ -145,13 +132,14 @@ def set_timer(self, timer=1, dur=3600): s = (dur % 3600) % 60 self.write("TP:{:1d},{:02d},{:02d},{:02d}".format(timer, h, m, s)) time = self.get_nominal_time(timer) - logger.info("Set timer number {:1d} to {:02d}:{:02d}:{:02d} (HH:MM:SS)".format( - timer, time // 3600, (time % 3600) // 60, (time % 3600) % 60) + logger.info( + "Set timer number {:1d} to {:02d}:{:02d}:{:02d} (HH:MM:SS)".format( + timer, time // 3600, (time % 3600) // 60, (time % 3600) % 60 + ) ) def get_actual_time(self, timer=1): - """Get the actual time of the given timer in s - """ + """Get the actual time of the given timer in s""" if not isinstance(timer, int): raise TypeError("Invalid type for timer number") elif timer > 4 or timer < 1: @@ -162,8 +150,7 @@ def get_actual_time(self, timer=1): return int(time) def get_nominal_time(self, timer=1): - """Get the nominal time of the given timer in s - """ + """Get the nominal time of the given timer in s""" if not isinstance(timer, int): raise TypeError("Invalid type for timer number") elif timer > 4 or timer < 1: @@ -174,16 +161,14 @@ def get_nominal_time(self, timer=1): return int(time) def lock_keyboard(self): - """Locks the hardware keyboard on the device. Only STOP key still works. - """ + """Locks the hardware keyboard on the device. Only STOP key still works.""" self.write("KB:0") def unlock_keyboard(self): self.write("KB:1") def get_status(self, status_word): - """ Get a pre-selected range of status parameters - """ + """Get a pre-selected range of status parameters""" self.write("SR:{:02d}".format(status_word)) response = self.read() status = bin(int(response[7:10]))[2:].zfill(8) # Convert response to 8 char long string of binary values diff --git a/basil/HL/fadc_rx.py b/basil/HL/fadc_rx.py index 8b24f2889..12de23e6f 100644 --- a/basil/HL/fadc_rx.py +++ b/basil/HL/fadc_rx.py @@ -9,20 +9,20 @@ class fadc_rx(RegisterHardwareLayer): - - '''Fast ADC channel receiver - ''' - - _registers = {'RESET': {'descr': {'addr': 0, 'size': 8, 'properties': ['writeonly']}}, - 'VERSION': {'descr': {'addr': 0, 'size': 8, 'properties': ['ro']}}, - 'READY': {'descr': {'addr': 1, 'size': 1, 'properties': ['ro']}}, - 'START': {'descr': {'addr': 1, 'size': 8, 'properties': ['writeonly']}}, - 'ALIGN_TO_SYNC': {'descr': {'addr': 2, 'size': 1}}, - 'EN_TRIGGER': {'descr': {'addr': 2, 'size': 1, 'offset': 1}}, - 'SINGLE_DATA': {'descr': {'addr': 2, 'size': 1, 'offset': 2}}, - 'SAMPLE_DLY': {'descr': {'addr': 7, 'size': 8}}, - 'COUNT': {'descr': {'addr': 3, 'size': 24}}, - 'COUNT_LOST': {'descr': {'addr': 8, 'size': 8, 'properties': ['ro']}}} + """Fast ADC channel receiver""" + + _registers = { + "RESET": {"descr": {"addr": 0, "size": 8, "properties": ["writeonly"]}}, + "VERSION": {"descr": {"addr": 0, "size": 8, "properties": ["ro"]}}, + "READY": {"descr": {"addr": 1, "size": 1, "properties": ["ro"]}}, + "START": {"descr": {"addr": 1, "size": 8, "properties": ["writeonly"]}}, + "ALIGN_TO_SYNC": {"descr": {"addr": 2, "size": 1}}, + "EN_TRIGGER": {"descr": {"addr": 2, "size": 1, "offset": 1}}, + "SINGLE_DATA": {"descr": {"addr": 2, "size": 1, "offset": 2}}, + "SAMPLE_DLY": {"descr": {"addr": 7, "size": 8}}, + "COUNT": {"descr": {"addr": 3, "size": 24}}, + "COUNT_LOST": {"descr": {"addr": 8, "size": 8, "properties": ["ro"]}}, + } _require_version = "==1" @@ -36,14 +36,13 @@ def start(self): self.START = 0 def set_align_to_sync(self, value): - ''' + """ Align data taking to a synchronization signal, reset signal is the synchronization signal (hard coded connection in Verilog source code) - ''' + """ self.ALIGN_TO_SYNC = value def set_single_data(self, value): - ''' - ''' + """ """ self.SINGLE_DATA = value def get_align_to_sync(self): diff --git a/basil/HL/fast_spi_rx.py b/basil/HL/fast_spi_rx.py index cac4eb22c..a41a0a9b1 100644 --- a/basil/HL/fast_spi_rx.py +++ b/basil/HL/fast_spi_rx.py @@ -9,20 +9,21 @@ class fast_spi_rx(RegisterHardwareLayer): - '''Fast SPI interface - ''' - - _registers = {'RESET': {'descr': {'addr': 0, 'size': 8, 'properties': ['writeonly']}}, - 'VERSION': {'descr': {'addr': 0, 'size': 8, 'properties': ['ro']}}, - 'EN': {'descr': {'addr': 2, 'size': 1, 'offset': 0}}, - 'LOST_COUNT': {'descr': {'addr': 3, 'size': 8, 'properties': ['ro']}}} + """Fast SPI interface""" + + _registers = { + "RESET": {"descr": {"addr": 0, "size": 8, "properties": ["writeonly"]}}, + "VERSION": {"descr": {"addr": 0, "size": 8, "properties": ["ro"]}}, + "EN": {"descr": {"addr": 2, "size": 1, "offset": 0}}, + "LOST_COUNT": {"descr": {"addr": 3, "size": 8, "properties": ["ro"]}}, + } _require_version = "==0" def __init__(self, intf, conf): super(fast_spi_rx, self).__init__(intf, conf) def reset(self): - '''Soft reset the module.''' + """Soft reset the module.""" self.RESET = 0 def set_en(self, value): diff --git a/basil/HL/fei4_rx.py b/basil/HL/fei4_rx.py index 19a786f98..19f8e5522 100644 --- a/basil/HL/fei4_rx.py +++ b/basil/HL/fei4_rx.py @@ -10,18 +10,19 @@ class fei4_rx(RegisterHardwareLayer): - '''FEI4 receiver controller interface for fei4_rx FPGA module - ''' - - _registers = {'RESET': {'descr': {'addr': 0, 'size': 8, 'properties': ['writeonly']}}, - 'RX_RESET': {'descr': {'addr': 1, 'size': 8, 'properties': ['writeonly']}}, - 'VERSION': {'descr': {'addr': 0, 'size': 8, 'properties': ['ro']}}, - 'READY': {'descr': {'addr': 2, 'size': 1, 'properties': ['ro']}}, - 'INVERT_RX': {'descr': {'addr': 2, 'size': 1, 'offset': 1}}, - 'ENABLE_RX': {'descr': {'addr': 2, 'size': 1, 'offset': 2}}, - 'FIFO_SIZE': {'default': 0, 'descr': {'addr': 3, 'size': 16, 'properties': ['ro']}}, - 'DECODER_ERROR_COUNTER': {'descr': {'addr': 5, 'size': 8, 'properties': ['ro']}}, - 'LOST_DATA_COUNTER': {'descr': {'addr': 6, 'size': 8, 'properties': ['ro']}}} + """FEI4 receiver controller interface for fei4_rx FPGA module""" + + _registers = { + "RESET": {"descr": {"addr": 0, "size": 8, "properties": ["writeonly"]}}, + "RX_RESET": {"descr": {"addr": 1, "size": 8, "properties": ["writeonly"]}}, + "VERSION": {"descr": {"addr": 0, "size": 8, "properties": ["ro"]}}, + "READY": {"descr": {"addr": 2, "size": 1, "properties": ["ro"]}}, + "INVERT_RX": {"descr": {"addr": 2, "size": 1, "offset": 1}}, + "ENABLE_RX": {"descr": {"addr": 2, "size": 1, "offset": 2}}, + "FIFO_SIZE": {"default": 0, "descr": {"addr": 3, "size": 16, "properties": ["ro"]}}, + "DECODER_ERROR_COUNTER": {"descr": {"addr": 5, "size": 8, "properties": ["ro"]}}, + "LOST_DATA_COUNTER": {"descr": {"addr": 6, "size": 8, "properties": ["ro"]}}, + } _require_version = "==3" def __init__(self, intf, conf): diff --git a/basil/HL/gpio.py b/basil/HL/gpio.py index 553d98493..17222415b 100644 --- a/basil/HL/gpio.py +++ b/basil/HL/gpio.py @@ -9,34 +9,38 @@ class gpio(RegisterHardwareLayer): - '''GPIO interface - ''' + """GPIO interface""" def __init__(self, intf, conf): - - self._registers = {'RESET': {'descr': {'addr': 0, 'size': 8, 'properties': ['writeonly']}}, - 'VERSION': {'descr': {'addr': 0, 'size': 8, 'properties': ['ro']}}} + self._registers = { + "RESET": {"descr": {"addr": 0, "size": 8, "properties": ["writeonly"]}}, + "VERSION": {"descr": {"addr": 0, "size": 8, "properties": ["ro"]}}, + } self._require_version = "==0" self._size = 8 - if 'size' in conf.keys(): - self._size = conf['size'] + if "size" in conf.keys(): + self._size = conf["size"] io_bytes = int(((self._size - 1) / 8) + 1) - self._registers['INPUT'] = {'descr': {'addr': 1, 'size': io_bytes, 'properties': ['ro', 'byte_array']}} - self._registers['OUTPUT'] = {'descr': {'addr': 2 + io_bytes - 1, 'size': io_bytes, 'properties': ['byte_array']}} - self._registers['OUTPUT_EN'] = {'descr': {'addr': 3 + 2 * (io_bytes - 1), 'size': io_bytes, 'properties': ['byte_array']}} + self._registers["INPUT"] = {"descr": {"addr": 1, "size": io_bytes, "properties": ["ro", "byte_array"]}} + self._registers["OUTPUT"] = { + "descr": {"addr": 2 + io_bytes - 1, "size": io_bytes, "properties": ["byte_array"]} + } + self._registers["OUTPUT_EN"] = { + "descr": {"addr": 3 + 2 * (io_bytes - 1), "size": io_bytes, "properties": ["byte_array"]} + } # __init__() after updating register super(gpio, self).__init__(intf, conf) def init(self): super(gpio, self).init() - if 'output_en' in self._init: - self.OUTPUT_EN = self._init['output_en'] + if "output_en" in self._init: + self.OUTPUT_EN = self._init["output_en"] def reset(self): - '''Soft reset the module.''' + """Soft reset the module.""" self.RESET = 0 def set_output_en(self, value): diff --git a/basil/HL/hp4284a.py b/basil/HL/hp4284a.py index 1b8e02d5a..a3d099a92 100644 --- a/basil/HL/hp4284a.py +++ b/basil/HL/hp4284a.py @@ -6,6 +6,7 @@ # import logging + from basil.HL.scpi import scpi @@ -48,10 +49,10 @@ def property_getter(self): self._check_trigger() # Get primary and secondary measurement quantities as well as the measurement status - primary_meas, secondary_meas, meas_status = self.get_value().strip().split(',') + primary_meas, secondary_meas, meas_status = self.get_value().strip().split(",") # Check status - if meas_status != '+0': + if meas_status != "+0": if meas_status not in self.ERROR_STATES: err_msg = f"Unknown measurement status {meas_status} retrieved" else: @@ -71,35 +72,35 @@ class hp4284A(scpi): # Available measurement functions; see manual 8-24, p.264 MEAS_FUNCS = { - 'CPD': "Set function to C_p-D", - 'CPQ': "Set function to C_p-Q", - 'CPG': "Set function to C_p-G", - 'CPRP': "Set function to C_p-R_p", - 'CSD': "Set function to C_s-D", - 'CSQ': "Set function to C_s-Q", - 'CSRS': "Set function to C_s-R_s", - 'LPQ': "Set function to L_p-Q", - 'LPD': "Set function to L_p-D", - 'LPG': "Set function to L_p-G", - 'LPRP': "Set function to L_r-R_p", - 'LSD': "Set function to L_s-D", - 'LSQ': "Set function to L_s-Q", - 'LSRS': "Set function to L_s-R_s", - 'RX': "Set function to R-X", - 'ZTD': "Set function to Z-Theta(deg)", - 'ZTR': "Set function to Z-Theta(rad)", - 'GB': "Set function to G-B", - 'YTD': "Set function to Y-Theta(deg)", - 'YTR': "Set function to Y-Theta(rad)" + "CPD": "Set function to C_p-D", + "CPQ": "Set function to C_p-Q", + "CPG": "Set function to C_p-G", + "CPRP": "Set function to C_p-R_p", + "CSD": "Set function to C_s-D", + "CSQ": "Set function to C_s-Q", + "CSRS": "Set function to C_s-R_s", + "LPQ": "Set function to L_p-Q", + "LPD": "Set function to L_p-D", + "LPG": "Set function to L_p-G", + "LPRP": "Set function to L_r-R_p", + "LSD": "Set function to L_s-D", + "LSQ": "Set function to L_s-Q", + "LSRS": "Set function to L_s-R_s", + "RX": "Set function to R-X", + "ZTD": "Set function to Z-Theta(deg)", + "ZTR": "Set function to Z-Theta(rad)", + "GB": "Set function to G-B", + "YTD": "Set function to Y-Theta(deg)", + "YTR": "Set function to Y-Theta(rad)", } # Measurement error states; see manual 7-8, p.208 ERROR_STATES = { - '-1': "No data (in the data buffer memory)", - '+1': "Analog bridge is unbalanced", - '+2': "A/D converter is not working", - '+3': "Signal source overloaded", - '+4': "ALC unable to regulate" + "-1": "No data (in the data buffer memory)", + "+1": "Analog bridge is unbalanced", + "+2": "A/D converter is not working", + "+3": "Signal source overloaded", + "+4": "ALC unable to regulate", } @property @@ -124,7 +125,7 @@ def ac_voltage(self, ac): ac : float, str AC voltage in V. Allowed string values 'MIN'/'MAX' for min/max values. """ - self.set_ac_voltage(f'{ac}' if self._is_min_max(ac) else f'{ac} V') + self.set_ac_voltage(f"{ac}" if self._is_min_max(ac) else f"{ac} V") @property def frequency(self): @@ -148,7 +149,7 @@ def frequency(self, freq): freq : float, str Frequency in Hz. Allowed string values 'MIN'/'MAX' for min/max values. """ - self.set_frequency(f'{freq}' if self._is_min_max(freq) else f'{freq}HZ') + self.set_frequency(f"{freq}" if self._is_min_max(freq) else f"{freq}HZ") def __init__(self, intf, conf): super(hp4284A, self).__init__(intf, conf) @@ -172,8 +173,8 @@ def __add_meas_func_getters(cls, meas_func, getter_func): setattr(cls, meas_func, property(getter_func)) def _is_min_max(self, val): - return val in ('MIN', 'MAX') + return val in ("MIN", "MAX") def _check_trigger(self): - if self.get_trigger_mode().strip() == 'HOLD': + if self.get_trigger_mode().strip() == "HOLD": self.trigger() diff --git a/basil/HL/hp_4284a.yaml b/basil/HL/hp_4284a.yaml index 80e2f2c37..1bb95a706 100644 --- a/basil/HL/hp_4284a.yaml +++ b/basil/HL/hp_4284a.yaml @@ -1,4 +1,4 @@ -# Device description for the Hewlett Packard LCR meter. +# Device description for the Hewlett Packard LCR meter. # Only GPIB shows working communication with this device! open_correction: CORR:OPEN short_correction: CORR:SHOR diff --git a/basil/HL/hp_81104a.yaml b/basil/HL/hp_81104a.yaml index d8fdae473..a536899b8 100644 --- a/basil/HL/hp_81104a.yaml +++ b/basil/HL/hp_81104a.yaml @@ -1,4 +1,4 @@ -# Device description for the Hewlett Packard Pulse-/ Pattern Generator. +# Device description for the Hewlett Packard Pulse-/ Pattern Generator. # Only GPIB shows working communication with this device! identifier : HEWLETT-PACKARD,HP81104A @@ -9,7 +9,7 @@ channel 1: channel 2: on : OUTP2:NORM:STAT ON off : OUTP2:NORM:STAT OFF - + on : OUTP1:NORM:STAT ON off : OUTP1:NORM:STAT OFF diff --git a/basil/HL/i2c.py b/basil/HL/i2c.py index 6dca732e4..ea2c5b9e8 100644 --- a/basil/HL/i2c.py +++ b/basil/HL/i2c.py @@ -9,18 +9,18 @@ class i2c(RegisterHardwareLayer): - '''Implement master i2c programming interface driver. - ''' - - _registers = {'RESET': {'descr': {'addr': 0, 'size': 8, 'properties': ['writeonly']}}, - 'VERSION': {'descr': {'addr': 0, 'size': 8, 'properties': ['ro']}}, - 'START': {'descr': {'addr': 1, 'size': 8, 'properties': ['writeonly']}}, - 'READY': {'descr': {'addr': 1, 'size': 1, 'properties': ['ro']}}, - 'NO_ACK': {'descr': {'addr': 1, 'size': 1, 'offset': 1, 'properties': ['ro']}}, - 'SIZE': {'descr': {'addr': 3, 'size': 16}}, - 'ADDR': {'descr': {'addr': 2, 'size': 8}}, - 'MEM_BYTES': {'descr': {'addr': 6, 'size': 16}}, - } + """Implement master i2c programming interface driver.""" + + _registers = { + "RESET": {"descr": {"addr": 0, "size": 8, "properties": ["writeonly"]}}, + "VERSION": {"descr": {"addr": 0, "size": 8, "properties": ["ro"]}}, + "START": {"descr": {"addr": 1, "size": 8, "properties": ["writeonly"]}}, + "READY": {"descr": {"addr": 1, "size": 1, "properties": ["ro"]}}, + "NO_ACK": {"descr": {"addr": 1, "size": 1, "offset": 1, "properties": ["ro"]}}, + "SIZE": {"descr": {"addr": 3, "size": 16}}, + "ADDR": {"descr": {"addr": 2, "size": 8}}, + "MEM_BYTES": {"descr": {"addr": 6, "size": 16}}, + } _require_version = "==1" @@ -55,7 +55,7 @@ def get_address(self): def set_size(self, value): if self._mem_size < value: - raise ValueError('Size of data (%d bytes) is too big for memory (%d bytes)' % (value, self._mem_size)) + raise ValueError("Size of data (%d bytes) is too big for memory (%d bytes)" % (value, self._mem_size)) self.SIZE = value def get_size(self): @@ -66,11 +66,11 @@ def is_done(self): @property def is_ready(self): - ''' + """ :raises IOError: Transfer not acknowledged. - ''' + """ if self.NO_ACK: - raise IOError('i2c:Transfer not acknowledged') + raise IOError("i2c:Transfer not acknowledged") return self.READY def get_done(self): @@ -78,19 +78,19 @@ def get_done(self): def set_data(self, data, addr=0): if self._mem_size < len(data): - raise ValueError('Size of data (%d bytes) is too big for memory (%d bytes)' % (len(data), self._mem_size)) - self._intf.write(self._conf['base_addr'] + self._seq_mem_offset + addr, data) + raise ValueError("Size of data (%d bytes) is too big for memory (%d bytes)" % (len(data), self._mem_size)) + self._intf.write(self._conf["base_addr"] + self._seq_mem_offset + addr, data) def get_data(self, size=None, addr=0): if size and self._mem_size < size: - raise ValueError('Size is too big') + raise ValueError("Size is too big") if not size: - return self._intf.read(self._conf['base_addr'] + self._seq_mem_offset + addr, self._mem_size) + return self._intf.read(self._conf["base_addr"] + self._seq_mem_offset + addr, self._mem_size) else: - return self._intf.read(self._conf['base_addr'] + self._seq_mem_offset + addr, size) + return self._intf.read(self._conf["base_addr"] + self._seq_mem_offset + addr, size) def write(self, addr, data): - '''Write access. + """Write access. :param addr: i2c slave address :type addr: char @@ -98,8 +98,8 @@ def write(self, addr, data): :type data: iterable :rtype: None - ''' - self.set_addr(addr & 0xfe) + """ + self.set_addr(addr & 0xFE) self.set_data(data) self.set_size(len(data)) self.start() @@ -107,7 +107,7 @@ def write(self, addr, data): pass def read(self, addr, size): - '''Read access. + """Read access. :param addr: i2c slave address :type addr: char @@ -116,7 +116,7 @@ def read(self, addr, size): :returns: data byte array :rtype: array.array('B') - ''' + """ self.set_addr(addr | 0x01) self.set_size(size) self.start() diff --git a/basil/HL/iseg_hv.py b/basil/HL/iseg_hv.py index 3b5c0470f..ed8284e96 100644 --- a/basil/HL/iseg_hv.py +++ b/basil/HL/iseg_hv.py @@ -105,9 +105,7 @@ def init(self): self.answer_delay = 1 # ms # # Add error response for attempting to set voltage too high - self.ERRORS[f"? UMAX={self.get_voltage_limit}"] = ( - "Set voltage exceeds voltage limit" - ) + self.ERRORS[f"? UMAX={self.get_voltage_limit}"] = "Set voltage exceeds voltage limit" self.set_autostart(self._autostart) @@ -142,28 +140,20 @@ def get_voltage(self): def set_voltage(self, voltage): # Check hardware voltage limit if abs(voltage) > abs(self.voltage_limit): - raise ValueError( - f"Voltage of {voltage}V too high! Maximum voltage is {self.voltage_limit} V" - ) + raise ValueError(f"Voltage of {voltage}V too high! Maximum voltage is {self.voltage_limit} V") # Get module status for checks ms = self.get_module_status() # Issue warning if PSU is in different polarity as value if ms[5] == "1" and voltage < 0: - raise ValueError( - f"Power supply polarity is set to positive but target voltage of {voltage}V is negative!" - ) + raise ValueError(f"Power supply polarity is set to positive but target voltage of {voltage}V is negative!") elif ms[5] == "0" and voltage > 0: - raise ValueError( - f"Power supply polarity is set to negative but target voltage of {voltage}V is positive!" - ) + raise ValueError(f"Power supply polarity is set to negative but target voltage of {voltage}V is positive!") # Check software voltage limit if self._voltage_limit is not None: - if (ms[5] == "1" and voltage > self._voltage_limit) or ( - ms[5] == "0" and voltage < self._voltage_limit - ): + if (ms[5] == "1" and voltage > self._voltage_limit) or (ms[5] == "0" and voltage < self._voltage_limit): raise ValueError( f"Voltage of {voltage}V too high! Increase *v_lim={self._v_lim}V* to enable higher voltage!" ) @@ -171,9 +161,7 @@ def set_voltage(self, voltage): # Issue warning if PSU is in manual mode # Then voltage can only be changed manually, at the device if ms[6] == "1": - logging.warning( - "Power supply in manual mode; voltage changes have no effect!" - ) + logging.warning("Power supply in manual mode; voltage changes have no effect!") self._get_set_property(prop="set_voltage", value=abs(voltage)) @@ -199,11 +187,7 @@ def get_hardware_voltage_limit(self): Voltage limit in V """ # Property get_v_lim returns voltage limit as percentage of max voltage - return ( - int(self._get_set_property(prop="get_voltage_limit")) - / 100.0 - * float(self.V_MAX[:-1]) - ) + return int(self._get_set_property(prop="get_voltage_limit")) / 100.0 * float(self.V_MAX[:-1]) def get_voltage_limit(self): """ @@ -217,9 +201,7 @@ def get_voltage_limit(self): return self._voltage_limit def set_voltage_limit(self, voltage_limit): - self._voltage_limit = ( - voltage_limit if voltage_limit is None else float(voltage_limit) - ) + self._voltage_limit = voltage_limit if voltage_limit is None else float(voltage_limit) def get_current_limit(self): """ @@ -231,9 +213,7 @@ def get_current_limit(self): Current limit in A """ # Property get_i_lim returns voltage limit as percentage of max current - return ( - int(self._get_set_property(prop="get_current_limit")) / 100.0 * float(self.I_MAX[:-2]) - ) + return int(self._get_set_property(prop="get_current_limit")) / 100.0 * float(self.I_MAX[:-2]) def get_current_trip(self, resolution="mA"): """ @@ -408,7 +388,6 @@ def module_msg(bit, prefix, t_msg, f_msg=""): return module_description def _get_set_property(self, prop, value=None): - if "{channel}" in self.CMDS[prop] and "{value}" in self.CMDS[prop]: cmd = self.CMDS[prop].format(channel=self.channel, value=value) elif "{channel}" in self.CMDS[prop]: @@ -468,18 +447,14 @@ def query(self, msg): # RECV -> actual data // recv the actual data echo = str(self._intf.query(msg)).strip() if echo != msg: - raise RuntimeError( - f"Issued command ({msg}) and echoed command ({echo}) differ." - ) + raise RuntimeError(f"Issued command ({msg}) and echoed command ({echo}) differ.") return self.read() def on(self): try: self.set_voltage(float(self.high_voltage)) except TypeError: - raise ValueError( - "High voltage is not set. Set *high_voltage* attribute to numerical value" - ) + raise ValueError("High voltage is not set. Set *high_voltage* attribute to numerical value") def off(self): self.set_voltage(0) diff --git a/basil/HL/julabo1000F.py b/basil/HL/julabo1000F.py index c43889b0e..fefab7083 100644 --- a/basil/HL/julabo1000F.py +++ b/basil/HL/julabo1000F.py @@ -14,30 +14,30 @@ from basil.HL.HardwareLayer import HardwareLayer - logger = logging.getLogger(__name__) class julabo1000F(HardwareLayer): - ''' Driver for the Julabo Magio MS-1000F chiller. + """Driver for the Julabo Magio MS-1000F chiller. A simple protocol via crossed null modem serial port is used with baud rate of 9600. All commands were taken from Julabo Magio MS-1000F manual. - ''' - - CMDS = {'get_temp': 'in_sp_00', - 'set_temp': 'out_sp_00', - 'get_curr_temp': 'in_pv_00', - 'get_fluid_level': 'in_pv_16', - 'get_version': 'version', - 'get_status': 'status', - 'start': 'out_mode_05 1', - 'stop': 'out_mode_05 0', - 'set_power': 'out_sp_10', - 'get_power': 'in_sp_10', - 'get_curr_power': 'in_pv_01', - 'get_actuator_source': 'in_mode_11', - 'set_actuator_source': 'out_mode_11' - } + """ + + CMDS = { + "get_temp": "in_sp_00", + "set_temp": "out_sp_00", + "get_curr_temp": "in_pv_00", + "get_fluid_level": "in_pv_16", + "get_version": "version", + "get_status": "status", + "start": "out_mode_05 1", + "stop": "out_mode_05 0", + "set_power": "out_sp_10", + "get_power": "in_sp_10", + "get_curr_power": "in_pv_01", + "get_actuator_source": "in_mode_11", + "set_actuator_source": "out_mode_11", + } def __init__(self, intf, conf): super(julabo1000F, self).__init__(intf, conf) @@ -59,26 +59,22 @@ def write(self, cmd): self.pre_time = time.time() def get_version(self): - ''' Read identifier - ''' - self.write(self.CMDS['get_version']) + """Read identifier""" + self.write(self.CMDS["get_version"]) ret = self.read() return ret def start_chiller(self): - ''' Start chiller - ''' - self.write(self.CMDS['start']) + """Start chiller""" + self.write(self.CMDS["start"]) def stop_chiller(self): - ''' Stop chiller - ''' - self.write(self.CMDS['stop']) + """Stop chiller""" + self.write(self.CMDS["stop"]) def get_status(self): - ''' Get status - ''' - self.write(self.CMDS['get_status']) + """Get status""" + self.write(self.CMDS["get_status"]) ret = self.read() logger.debug("status:{:s}".format(ret)) try: @@ -92,51 +88,43 @@ def get_status(self): return status, status_str def get_set_temp(self): - '''get the set temperature - ''' - self.write(self.CMDS['get_temp']) + """get the set temperature""" + self.write(self.CMDS["get_temp"]) ret = self.read() return float(ret) def set_temp(self, temp): - '''set the temperature - ''' + """set the temperature""" self.write(f"{self.CMDS['set_temp']} {temp}") def get_temp(self): - '''get the current temperature in chiller - ''' - self.write(self.CMDS['get_curr_temp']) + """get the current temperature in chiller""" + self.write(self.CMDS["get_curr_temp"]) ret = self.read() return float(ret) def set_power(self, variable): - '''Set the power for heater/cooler via serial interface (positive value for heating, negative value for cooling) - ''' + """Set the power for heater/cooler via serial interface (positive value for heating, negative value for cooling)""" self.write(f"{self.CMDS['set_power']} {variable}") def get_power(self): - '''get the current power for heater/cooler - ''' - self.write(self.CMDS['get_curr_power']) + """get the current power for heater/cooler""" + self.write(self.CMDS["get_curr_power"]) ret = self.read() return float(ret) def get_set_power(self): - '''get the power for heater/cooler set via serial interface - ''' - self.write(self.CMDS['get_power']) + """get the power for heater/cooler set via serial interface""" + self.write(self.CMDS["get_power"]) ret = self.read() return float(ret) def get_mode(self): - '''get the source for the actuating variable. 0=Thermostat, 1=Serial, 2=Analog (EPROG) - ''' - self.write(self.CMDS['get_actuator_source']) + """get the source for the actuating variable. 0=Thermostat, 1=Serial, 2=Analog (EPROG)""" + self.write(self.CMDS["get_actuator_source"]) ret = self.read() return int(ret) def set_mode(self, variable): - '''Set the source for the actuating variable. 0=Thermostat, 1=Serial, 2=Analog (EPROG) - ''' + """Set the source for the actuating variable. 0=Thermostat, 1=Serial, 2=Analog (EPROG)""" self.write(f"{self.CMDS['set_actuator_source']} {variable}") diff --git a/basil/HL/julaboF32HD.py b/basil/HL/julaboF32HD.py index 944111fa0..b48cea9ec 100644 --- a/basil/HL/julaboF32HD.py +++ b/basil/HL/julaboF32HD.py @@ -10,14 +10,13 @@ from basil.HL.RegisterHardwareLayer import HardwareLayer - logger = logging.getLogger(__name__) class julaboF32HD(HardwareLayer): - ''' Driver for the Julabo F32-HD chiller. + """Driver for the Julabo F32-HD chiller. A simple protocol via RS 232 serial port is used with 4800 baud rate. - ''' + """ def __init__(self, intf, conf): super(julaboF32HD, self).__init__(intf, conf) @@ -39,28 +38,24 @@ def write(self, cmd): self.pre_time = time.time() def get_identifier(self): - ''' Read identifier - ''' + """Read identifier""" self.write("version") ret = self.read() return ret def start_thermostat(self, start=True): - ''' Start chiller - ''' + """Start chiller""" if start is True: self.write("out_mode_05 1") else: self.write("out_mode_05 0") def stop_thermostat(self): - ''' Stop chiller - ''' + """Stop chiller""" self.start_thermostat(False) def get_status(self): - ''' Get status - ''' + """Get status""" self.write("status") ret = self.read() logger.debug("status:{:s}".format(ret)) diff --git a/basil/HL/julaboFP50.py b/basil/HL/julaboFP50.py index c8d152aac..43e30d7e6 100644 --- a/basil/HL/julaboFP50.py +++ b/basil/HL/julaboFP50.py @@ -14,25 +14,25 @@ from basil.HL.HardwareLayer import HardwareLayer - logger = logging.getLogger(__name__) class julaboFP50(HardwareLayer): - ''' Driver for the Julabo FP50 chiller. + """Driver for the Julabo FP50 chiller. A simple protocol via crossed null modem serial port is used with baud rate of 9600. All commands were taken from JulaboFP50 manual. - ''' - - CMDS = {'get_temp': 'in_sp_00', - 'set_temp': 'out_sp_00', - 'get_curr_temp': 'in_pv_00', - 'get_version': 'version', - 'get_status': 'status', - 'start': 'out_mode_05 1', - 'stop': 'out_mode_05 0', - 'set_power': 'out_sp_06' - } + """ + + CMDS = { + "get_temp": "in_sp_00", + "set_temp": "out_sp_00", + "get_curr_temp": "in_pv_00", + "get_version": "version", + "get_status": "status", + "start": "out_mode_05 1", + "stop": "out_mode_05 0", + "set_power": "out_sp_06", + } def __init__(self, intf, conf): super(julaboFP50, self).__init__(intf, conf) @@ -54,26 +54,22 @@ def write(self, cmd): self.pre_time = time.time() def get_version(self): - ''' Read identifier - ''' - self.write(self.CMDS['get_version']) + """Read identifier""" + self.write(self.CMDS["get_version"]) ret = self.read() return ret def start_chiller(self): - ''' Start chiller - ''' - self.write(self.CMDS['start']) + """Start chiller""" + self.write(self.CMDS["start"]) def stop_chiller(self): - ''' Stop chiller - ''' - self.write(self.CMDS['stop']) + """Stop chiller""" + self.write(self.CMDS["stop"]) def get_status(self): - ''' Get status - ''' - self.write(self.CMDS['get_status']) + """Get status""" + self.write(self.CMDS["get_status"]) ret = self.read() logger.debug("status:{:s}".format(ret)) try: @@ -87,25 +83,21 @@ def get_status(self): return status, status_str def get_set_temp(self): - '''get the set temperature - ''' - self.write(self.CMDS['get_temp']) + """get the set temperature""" + self.write(self.CMDS["get_temp"]) ret = self.read() return float(ret) def set_temp(self, temp): - '''set the temperature - ''' + """set the temperature""" self.write(f"{self.CMDS['set_temp']}={temp}") def get_temp(self): - '''get the current temperature in chiller - ''' - self.write(self.CMDS['get_curr_temp']) + """get the current temperature in chiller""" + self.write(self.CMDS["get_curr_temp"]) ret = self.read() return float(ret) def set_power(self, variable): - '''Set the power for heater/cooler via serial interface (positive value for heating, negative value for cooling) - ''' + """Set the power for heater/cooler via serial interface (positive value for heating, negative value for cooling)""" self.write(f"{self.CMDS['set_power']}={variable}") diff --git a/basil/HL/keithley6517a.py b/basil/HL/keithley6517a.py index 6660413af..6632fa608 100644 --- a/basil/HL/keithley6517a.py +++ b/basil/HL/keithley6517a.py @@ -5,10 +5,10 @@ # ------------------------------------------------------------ # import logging -from types import MethodType from time import sleep -from basil.HL.scpi import scpi +from types import MethodType +from basil.HL.scpi import scpi logger = logging.getLogger(__name__) @@ -42,14 +42,14 @@ def init(self): # Overwrite TL write to add a delay after each write; Keithley 6517A needs this because otherwise errors occur self._intf.write = MethodType(_write_with_delay(self._intf.write), self._intf) - def setup_current_measurement(self, current_range=None, limit_current=True, voltage_range=None, filter=('REP', 10)): + def setup_current_measurement(self, current_range=None, limit_current=True, voltage_range=None, filter=("REP", 10)): # See manual p.2-23 ff. # Enable zero check before switching functions self.zero_check_on() # Select current measurement function self.select_current() # Set lowest range (20 pA) to do zero correction, works by scaling - self.set_current_range('MIN') + self.set_current_range("MIN") # Zero correct self.zero_correct_on() if current_range is None: @@ -80,5 +80,5 @@ def setup_current_measurement(self, current_range=None, limit_current=True, volt def get_current(self): if not self._setup_for_current_measurement: self.setup_current_measurement() - res = self.get_read().split(',')[0][:-4] + res = self.get_read().split(",")[0][:-4] return float(res) diff --git a/basil/HL/keithley_2000.yaml b/basil/HL/keithley_2000.yaml index 44b450a92..2b98d27c1 100644 --- a/basil/HL/keithley_2000.yaml +++ b/basil/HL/keithley_2000.yaml @@ -1,4 +1,4 @@ -# Device description for the Keithley 2000 Multimeter. +# Device description for the Keithley 2000 Multimeter. # Do not expect the Keithley 2000 to work over serial! # Only GPIB shows working communication with this device! identifier : KEITHLEY INSTRUMENTS INC.,MODEL 2000 diff --git a/basil/HL/keithley_2001.yaml b/basil/HL/keithley_2001.yaml index 5dab1133f..cff189cae 100644 --- a/basil/HL/keithley_2001.yaml +++ b/basil/HL/keithley_2001.yaml @@ -1,4 +1,4 @@ -# Device description for the Keithley 2001 Multimeter. +# Device description for the Keithley 2001 Multimeter. # Only GPIB is possible with this device! identifier : KEITHLEY INSTRUMENTS INC.,MODEL 2001 get_current : MEAS:CURR? diff --git a/basil/HL/keithley_2400.yaml b/basil/HL/keithley_2400.yaml index dd24d887d..e3ded96c9 100644 --- a/basil/HL/keithley_2400.yaml +++ b/basil/HL/keithley_2400.yaml @@ -1,4 +1,4 @@ -# Device description for the Keithley 2400 Sourcemeter. +# Device description for the Keithley 2400 Sourcemeter. # set_ function expect a parameter, get_ function return a parameter. # Just the very basic commands are implemented here. identifier : KEITHLEY INSTRUMENTS INC.,MODEL 2400 @@ -14,7 +14,7 @@ set_voltage : SOUR:VOLT get_voltage : SENSE:FUNC 'VOLT';:READ? set_current_limit : SENS:CURR:PROT get_current_limit : SENS:CURR:PROT? -set_voltage_limit : SENS:VOLT:PROT +set_voltage_limit : SENS:VOLT:PROT get_voltage_limit : SENS:VOLT:PROT? source_volt : SOUR:FUNC VOLT source_current : SOUR:FUNC CURR diff --git a/basil/HL/keithley_2410.yaml b/basil/HL/keithley_2410.yaml index d6c50458a..c167e850f 100644 --- a/basil/HL/keithley_2410.yaml +++ b/basil/HL/keithley_2410.yaml @@ -1,4 +1,4 @@ -# Device description for the Keithley 2410 Sourcemeter. +# Device description for the Keithley 2410 Sourcemeter. # set_ function expect a parameter, get_ function return a parameter. # Just the very basic commands are implemented here. identifier : KEITHLEY INSTRUMENTS INC.,MODEL 2410 diff --git a/basil/HL/keithley_2450.yaml b/basil/HL/keithley_2450.yaml index a2e84b5cb..469a6f001 100644 --- a/basil/HL/keithley_2450.yaml +++ b/basil/HL/keithley_2450.yaml @@ -1,4 +1,4 @@ -# Device description for the Keithley 2450 Sourcemeter. +# Device description for the Keithley 2450 Sourcemeter. # set_ function expect a parameter, get_ function return a parameter. # Just the very basic commands are implemented here. identifier : KEITHLEY INSTRUMENTS,MODEL 2450 @@ -11,7 +11,7 @@ set_voltage : SOUR:VOLT get_voltage : SENSE:FUNC 'VOLT';:READ? set_current_limit : SENS:CURR:PROT get_current_limit : SENS:CURR:PROT? -set_voltage_limit : SENS:VOLT:PROT +set_voltage_limit : SENS:VOLT:PROT get_voltage_limit : SENS:VOLT:PROT? source_volt : SOUR:FUNC VOLT source_current : SOUR:FUNC CURR diff --git a/basil/HL/keithley_2602a.yaml b/basil/HL/keithley_2602a.yaml index 1621d6937..ef84da461 100644 --- a/basil/HL/keithley_2602a.yaml +++ b/basil/HL/keithley_2602a.yaml @@ -1,4 +1,4 @@ -# Device description for the Keithley 2602A Sourcemeter. +# Device description for the Keithley 2602A Sourcemeter. # set_ function expect a parameter, get_ function return a parameter. # Just the very basic commands are implemented here. identifier : Keithley Instruments Inc., Model 2602A @@ -9,10 +9,10 @@ channel 1: off : smua.source.output = 0 source_current : smua.source.func = smua.OUTPUT_DCAMPS source_volt : smua.source.func = smua.OUTPUT_DCVOLTS - set_voltage_limit : smua.source.limitv = + set_voltage_limit : smua.source.limitv = set_current_limit : smua.source.limiti = - set_voltage_range : smua.source.rangev = - set_current_range : smua.source.rangei = + set_voltage_range : smua.source.rangev = + set_current_range : smua.source.rangei = set_current : smua.source.leveli = get_current : print(smua.measure.i()) set_voltage : smua.source.levelv = @@ -28,17 +28,17 @@ channel 2: source_current : smub.source.func = smub.OUTPUT_DCAMPS source_volt : smub.source.func = smub.OUTPUT_DCVOLTS set_voltage_range : smub.source.rangev = - set_current_range : smub.source.rangei = - set_voltage_limit : smub.source.limitv = + set_current_range : smub.source.rangei = + set_voltage_limit : smub.source.limitv = set_current_limit : smub.source.limiti = - set_current : smub.source.leveli = + set_current : smub.source.leveli = get_current : print(smub.measure.i()) set_voltage : smub.source.levelv = get_voltage : print(smub.measure.v()) set_mode_measure_current : display.smub.measure.func = display.MEASURE_DCAMPS four_wire_on : smub.sense = smub.SENSE_REMOTE four_wire_off : smub.sense = smub.SENSE_LOCAL - + #on : smua.source.output = 1 #off : smua.source.output = 0 #get_current : print(smua.measure.i()) diff --git a/basil/HL/keithley_2634b.yaml b/basil/HL/keithley_2634b.yaml index 5bceb1849..df4b45cf9 100644 --- a/basil/HL/keithley_2634b.yaml +++ b/basil/HL/keithley_2634b.yaml @@ -1,4 +1,4 @@ -# Device description for the Keithley 2634b Sourcemeter. +# Device description for the Keithley 2634b Sourcemeter. # set_ function expect a parameter, get_ function return a parameter. # Just the very basic commands are implemented here. identifier : Keithley Instruments Inc., Model 2634B @@ -69,7 +69,7 @@ channel 2: get_voltage_sense_range: print(smub.measure.rangev) set_mode_measure_current : display.smub.measure.func = display.MEASURE_DCAMPS - + on : smua.source.output = 1 off : smua.source.output = 0 get_on : print(smua.source.output) @@ -101,4 +101,3 @@ get_current_sense_range: print(smua.measure.rangei) set_voltage_sense_range: smua.measure.rangev = get_voltage_sense_range: print(smua.measure.rangev) set_mode_measure_current : display.smua.measure.func = display.MEASURE_DCAMPS - diff --git a/basil/HL/keithley_6517a.yaml b/basil/HL/keithley_6517a.yaml index 21872edf0..6b2b79de0 100644 --- a/basil/HL/keithley_6517a.yaml +++ b/basil/HL/keithley_6517a.yaml @@ -1,5 +1,5 @@ ######################################################## -# Device description for the Keithley 6517A Electrometer +# Device description for the Keithley 6517A Electrometer # Last Modified: Do 02 Jun 2022 11:22:30 CEST # Note: # A delay is required between most of the commands. @@ -59,7 +59,7 @@ current_filter_off: SENS:CURR:AVER OFF voltage_filter_off: SENS:CURR:AVER OFF # Status get_current_filter: SENS:CURR:AVER:STAT? -get_voltage_filter: SENS:VOLT:AVER:STAT? +get_voltage_filter: SENS:VOLT:AVER:STAT? # System get_config : CONF? get_error : SYST:ERR? diff --git a/basil/HL/m26_rx.py b/basil/HL/m26_rx.py index 84440b045..46105e86c 100644 --- a/basil/HL/m26_rx.py +++ b/basil/HL/m26_rx.py @@ -9,22 +9,23 @@ class m26_rx(RegisterHardwareLayer): - '''Mimosa 26 RX interface - ''' - - _registers = {'RESET': {'descr': {'addr': 0, 'size': 8, 'properties': ['writeonly']}}, - 'VERSION': {'descr': {'addr': 0, 'size': 8, 'properties': ['ro']}}, - 'EN': {'descr': {'addr': 1, 'size': 1, 'offset': 0}}, - 'TIMESTAMP_HEADER': {'descr': {'addr': 1, 'size': 1, 'offset': 1}}, - 'LOST_COUNT': {'descr': {'addr': 2, 'size': 8, 'properties': ['ro']}}, - 'INVALID_DATA_COUNT': {'descr': {'addr': 3, 'size': 8, 'properties': ['ro']}}} + """Mimosa 26 RX interface""" + + _registers = { + "RESET": {"descr": {"addr": 0, "size": 8, "properties": ["writeonly"]}}, + "VERSION": {"descr": {"addr": 0, "size": 8, "properties": ["ro"]}}, + "EN": {"descr": {"addr": 1, "size": 1, "offset": 0}}, + "TIMESTAMP_HEADER": {"descr": {"addr": 1, "size": 1, "offset": 1}}, + "LOST_COUNT": {"descr": {"addr": 2, "size": 8, "properties": ["ro"]}}, + "INVALID_DATA_COUNT": {"descr": {"addr": 3, "size": 8, "properties": ["ro"]}}, + } _require_version = "==2" def __init__(self, intf, conf): super(m26_rx, self).__init__(intf, conf) def reset(self): - '''Soft reset the module.''' + """Soft reset the module.""" self.RESET = 0 def set_en(self, value): diff --git a/basil/HL/mercury.py b/basil/HL/mercury.py index 814ea05fa..63b53be27 100644 --- a/basil/HL/mercury.py +++ b/basil/HL/mercury.py @@ -4,16 +4,17 @@ # SiLab, Institute of Physics, University of Bonn # ------------------------------------------------------------ # -from basil.HL.RegisterHardwareLayer import HardwareLayer import logging import time +from basil.HL.RegisterHardwareLayer import HardwareLayer + logger = logging.getLogger(__name__) # logger.setLevel(logging.DEBUG) class Mercury(HardwareLayer): - '''Driver for the Physiks Instruments Mercury Controller. + """Driver for the Physiks Instruments Mercury Controller. A protocoll via RS 232 serial port is used with 9600/19200/38400/115200 baud rate. The baud rate can be set with dip switches, as well as a hardware address to distinguish several devices on one line. Keep in mind that the address that is set via the DIP switches corresponds @@ -26,7 +27,7 @@ class Mercury(HardwareLayer): https://twiki.cern.ch/twiki/pub/ILCBDSColl/Phase2Preparations/MercuryNativeCommands_MS176E101.pdf The overall manual: https://www.le.infn.it/~chiodini/allow_listing/pi/Manuals/C-863_Benutzerhandbuch_Kurzversion_MS205Dqu200.pdf - ''' + """ def __init__(self, intf, conf): super(Mercury, self).__init__(intf, conf) @@ -40,7 +41,7 @@ def init(self): self._board_numbers.append(board_n) def write(self, value): - msg = value + '\r'.encode() # msg has CR at the end + msg = value + "\r".encode() # msg has CR at the end self._intf.write(msg) def read(self): @@ -88,7 +89,11 @@ def set_position(self, value, precision=100, board_number=None, wait=False): if abs(pos - value) <= precision: logger.debug("At position {pos}, Target at {target}".format(pos=pos, target=value)) else: - logger.warning("Target not reached! Target: {target}, actual position: {pos}, precision: {pre}".format(target=value, pos=pos, pre=precision)) + logger.warning( + "Target not reached! Target: {target}, actual position: {pos}, precision: {pre}".format( + target=value, pos=pos, pre=precision + ) + ) def move_relative(self, value, precision=100, board_number=None, wait=False): target = self.get_position(board_number) + value @@ -98,7 +103,11 @@ def move_relative(self, value, precision=100, board_number=None, wait=False): if abs(pos - target) <= precision: logger.debug("At position {pos}, Target at {target}".format(pos=pos, target=target)) else: - logger.warning("Target not reached! Target: {target}, actual position: {pos}, precision: {pre}".format(target=target, pos=pos, pre=precision)) + logger.warning( + "Target not reached! Target: {target}, actual position: {pos}, precision: {pre}".format( + target=target, pos=pos, pre=precision + ) + ) def abort(self, board_number=None): self._write_command("AB", board_number) diff --git a/basil/HL/pulse_gen.py b/basil/HL/pulse_gen.py index a275e8c19..7ef0035d4 100644 --- a/basil/HL/pulse_gen.py +++ b/basil/HL/pulse_gen.py @@ -9,54 +9,54 @@ class pulse_gen(RegisterHardwareLayer): - '''Pulser generator - ''' - - _registers = {'RESET': {'descr': {'addr': 0, 'size': 8, 'properties': ['writeonly']}}, - 'VERSION': {'descr': {'addr': 0, 'size': 8, 'properties': ['ro']}}, - 'READY': {'descr': {'addr': 1, 'size': 1, 'properties': ['ro']}}, - 'START': {'descr': {'addr': 1, 'size': 8, 'properties': ['writeonly']}}, - 'EN': {'descr': {'addr': 2, 'size': 1}}, - 'DELAY': {'descr': {'addr': 3, 'size': 32}}, - 'WIDTH': {'descr': {'addr': 7, 'size': 32}}, - 'REPEAT': {'descr': {'addr': 11, 'size': 32}} - } + """Pulser generator""" + + _registers = { + "RESET": {"descr": {"addr": 0, "size": 8, "properties": ["writeonly"]}}, + "VERSION": {"descr": {"addr": 0, "size": 8, "properties": ["ro"]}}, + "READY": {"descr": {"addr": 1, "size": 1, "properties": ["ro"]}}, + "START": {"descr": {"addr": 1, "size": 8, "properties": ["writeonly"]}}, + "EN": {"descr": {"addr": 2, "size": 1}}, + "DELAY": {"descr": {"addr": 3, "size": 32}}, + "WIDTH": {"descr": {"addr": 7, "size": 32}}, + "REPEAT": {"descr": {"addr": 11, "size": 32}}, + } _require_version = "==3" def __init__(self, intf, conf): super(pulse_gen, self).__init__(intf, conf) def start(self): - ''' + """ Software start of pulse at random time - ''' + """ self.START = 0 def reset(self): self.RESET = 0 def set_delay(self, value): - ''' + """ Pulse delay w.r.t. shift register finish signal [in clock cycles(?)] - ''' + """ self.DELAY = value def get_delay(self): return self.DELAY def set_width(self, value): - ''' + """ Pulse width in terms of clock cycles - ''' + """ self.WIDTH = value def get_width(self): return self.WIDTH def set_repeat(self, value): - ''' + """ Pulse repetition in range of 0-255 - ''' + """ self.REPEAT = value def get_repeat(self): @@ -70,14 +70,14 @@ def is_ready(self): return self.READY def set_en(self, value): - ''' + """ If true: The pulse comes with a fixed delay with respect to the external trigger (EXT_START). If false: The pulse comes only at software start. - ''' + """ self.EN = value def get_en(self): - ''' + """ Return info if pulse starts with a fixed delay w.r.t. shift register finish signal (true) or if it only starts with .start() (false) - ''' + """ return self.EN diff --git a/basil/HL/rs_hmp4040.py b/basil/HL/rs_hmp4040.py index 3bb1408af..fd954a79a 100644 --- a/basil/HL/rs_hmp4040.py +++ b/basil/HL/rs_hmp4040.py @@ -3,15 +3,14 @@ from basil.HL.RegisterHardwareLayer import HardwareLayer - logger = logging.getLogger(__name__) class rs_HMP4040(HardwareLayer): - ''' + """ HL for the RS HMP4040 !! Analog to tti ql355tp for compatibility with bdaq53 - ''' + """ def __init__(self, intf, conf): super(rs_HMP4040, self).__init__(intf, conf) @@ -36,7 +35,7 @@ def read(self): return ret def set_channel(self, channel): - """ channel: 1=OP1, 2=OP2, 3=OP3, 4=OP4""" + """channel: 1=OP1, 2=OP2, 3=OP3, 4=OP4""" cmd = "INST:NSEL %d" % channel self.write(cmd) @@ -45,7 +44,7 @@ def get_channel(self): return ret def set_enable(self, on, channel=1): - """ channel: 1=OP1, 2=OP2, 3=OP3, 4=OP4, ALL=all channels""" + """channel: 1=OP1, 2=OP2, 3=OP3, 4=OP4, ALL=all channels""" if channel == "ALL": for i in [1, 2, 3, 4]: self.set_enable(on, channel=i) @@ -64,41 +63,41 @@ def get_name(self): return self.ask("*IDN?") def get_current(self, channel): - """ channel: 1=OP1, 2=OP2, 3=OP3, 4=OP4""" + """channel: 1=OP1, 2=OP2, 3=OP3, 4=OP4""" self.set_channel(channel) ret = self.ask("MEAS:CURR?") return float(ret) def get_voltage(self, channel): - """ channel: 1=OP1, 2=OP2, 3=OP3, 4=OP4""" + """channel: 1=OP1, 2=OP2, 3=OP3, 4=OP4""" self.set_channel(channel) ret = self.ask("MEAS:VOLT?") return float(ret) def get_set_voltage(self, channel): - """ channel: 1=OP1, 2=OP2, 3=OP3, 4=OP4""" + """channel: 1=OP1, 2=OP2, 3=OP3, 4=OP4""" self.set_channel(channel) ret = self.ask("VOLT?") return float(ret) def get_current_limit(self, channel): - """ channel: 1=OP1, 2=OP2, 3=OP3, 4=OP4""" + """channel: 1=OP1, 2=OP2, 3=OP3, 4=OP4""" self.set_channel(channel) ret = self.ask("CURR?") return float(ret) def set_voltage(self, value, channel=1): - """ channel: 1=OP1, 2=OP2, 3=OP3, 4=OP4""" + """channel: 1=OP1, 2=OP2, 3=OP3, 4=OP4""" self.set_channel(channel) cmd = "VOLT %f" % value self.write(cmd) def set_current_limit(self, value, channel=1): - """ channel: 1=OP1, 2=OP2, 3=OP3, 4=OP4""" + """channel: 1=OP1, 2=OP2, 3=OP3, 4=OP4""" self.set_channel(channel) cmd = "CURR %f" % value self.write(cmd) diff --git a/basil/HL/rs_hmp4040.yaml b/basil/HL/rs_hmp4040.yaml index 34072dcbd..8127227c7 100644 --- a/basil/HL/rs_hmp4040.yaml +++ b/basil/HL/rs_hmp4040.yaml @@ -14,4 +14,3 @@ get_target_voltage: VOLT? get_target_current: CURR? set_ovp: VOLT:PROT get_ovp: VOLT:PROT? - diff --git a/basil/HL/scpi.py b/basil/HL/scpi.py index 83ce0e040..08974c491 100644 --- a/basil/HL/scpi.py +++ b/basil/HL/scpi.py @@ -7,27 +7,20 @@ import os -from yaml import load, BaseLoader, scanner +from yaml import BaseLoader, load, scanner from basil.HL.RegisterHardwareLayer import HardwareLayer - # SCPI command mandatory by IEEE 488.2 -_scpi_ieee_488_2 = { - 'clear': '*CLS', - 'reset': '*RST', - 'trigger': '*TRG', - 'get_name': '*IDN?' -} +_scpi_ieee_488_2 = {"clear": "*CLS", "reset": "*RST", "trigger": "*TRG", "get_name": "*IDN?"} class scpi(HardwareLayer): + """Implement Standard Commands for Programmable Instruments (SCPI).""" - '''Implement Standard Commands for Programmable Instruments (SCPI). - ''' @property def has_formatting(self): - '''Whether or not device has SCPI query formatting specified in device description''' + """Whether or not device has SCPI query formatting specified in device description""" return self._scpi_query_fmt is not None @has_formatting.setter @@ -36,7 +29,7 @@ def has_formatting(self, val): @property def formatting_enabled(self): - '''Whether or not device has SCPI query formatting is enabled''' + """Whether or not device has SCPI query formatting is enabled""" return self._formatting_enabled @formatting_enabled.setter @@ -51,54 +44,71 @@ def init(self): self._scpi_commands = _scpi_ieee_488_2.copy() self._scpi_query_fmt = None self._formatting_enabled = False - device_desciption = os.path.join(os.path.dirname(__file__), self._init['device'].lower().replace(" ", "_") + '.yaml') + device_desciption = os.path.join( + os.path.dirname(__file__), self._init["device"].lower().replace(" ", "_") + ".yaml" + ) try: - with open(device_desciption, 'r') as in_file: + with open(device_desciption, "r") as in_file: self._scpi_commands.update(load(in_file, Loader=BaseLoader)) except scanner.ScannerError: - raise RuntimeError('Parsing error for ' + self._init['device'] + ' device description in file ' + device_desciption) + raise RuntimeError( + "Parsing error for " + self._init["device"] + " device description in file " + device_desciption + ) except IOError: - raise RuntimeError('Cannot find a device description for ' + self._init['device'] + '. Consider adding it!') - if 'identifier' in self._scpi_commands and self._scpi_commands['identifier']: + raise RuntimeError("Cannot find a device description for " + self._init["device"] + ". Consider adding it!") + if "identifier" in self._scpi_commands and self._scpi_commands["identifier"]: name = self.get_name() - if self._scpi_commands['identifier'] not in name: - raise RuntimeError('Wrong device description (' + self._init['device'] + ') loaded for ' + name) + if self._scpi_commands["identifier"] not in name: + raise RuntimeError("Wrong device description (" + self._init["device"] + ") loaded for " + name) # Device specific query return value formatting - if '__scpi_query_fmt' in self._scpi_commands: - self._scpi_query_fmt = self._scpi_commands.pop('__scpi_query_fmt') + if "__scpi_query_fmt" in self._scpi_commands: + self._scpi_query_fmt = self._scpi_commands.pop("__scpi_query_fmt") # Check if we want to enable formatting from the init - if 'enable_formatting' in self._init and self._init['enable_formatting']: + if "enable_formatting" in self._init and self._init["enable_formatting"]: self.enable_formatting() def __getattr__(self, name): - '''dynamically adding device specific commands - ''' + """dynamically adding device specific commands""" + def method(*args, **kwargs): - channel = kwargs.pop('channel', None) + channel = kwargs.pop("channel", None) try: - command = self._scpi_commands['channel %s' % channel][name] if channel is not None else self._scpi_commands[name] + command = ( + self._scpi_commands["channel %s" % channel][name] + if channel is not None + else self._scpi_commands[name] + ) except Exception: - raise ValueError('SCPI command %s is not defined for device %s' % (name, self.name)) + raise ValueError("SCPI command %s is not defined for device %s" % (name, self.name)) - name_split = name.split('_', 1) - if len(name_split) == 2 and name_split[0] == 'set' and len(args) == 1 and not kwargs: - self._intf.write(command + ' ' + str(args[0])) - elif len(name_split) == 2 and name_split[0] == 'get' and not args and not kwargs: + name_split = name.split("_", 1) + if len(name_split) == 2 and name_split[0] == "set" and len(args) == 1 and not kwargs: + self._intf.write(command + " " + str(args[0])) + elif len(name_split) == 2 and name_split[0] == "get" and not args and not kwargs: res = self._intf.query(command) - if self.has_formatting and self._formatting_enabled and name in self._scpi_query_fmt['fmt_method']: - res = self._scpi_query_fmt['fmt_method'][name].format(*res.strip().split(self._scpi_query_fmt['fmt_sep'])) + if self.has_formatting and self._formatting_enabled and name in self._scpi_query_fmt["fmt_method"]: + res = self._scpi_query_fmt["fmt_method"][name].format( + *res.strip().split(self._scpi_query_fmt["fmt_sep"]) + ) return res elif len(name_split) >= 1 and not args and not kwargs: self._intf.write(command) else: - raise ValueError('Invalid SCPI command %s for device %s with args=%s and kwargs=%s' % (name, self.name, str(args), str(kwargs))) + raise ValueError( + "Invalid SCPI command %s for device %s with args=%s and kwargs=%s" + % (name, self.name, str(args), str(kwargs)) + ) return method def enable_formatting(self): - '''Enables formatting if specified in device description''' + """Enables formatting if specified in device description""" if not self.has_formatting: - raise AttributeError("No formatting specified for {}! Specify formatting by adding '__scpi_query_fmt' in the device description yaml".format(self._init['device'])) + raise AttributeError( + "No formatting specified for {}! Specify formatting by adding '__scpi_query_fmt' in the device description yaml".format( + self._init["device"] + ) + ) self._formatting_enabled = True def disable_formatting(self): diff --git a/basil/HL/sensirion_ekh4.py b/basil/HL/sensirion_ekh4.py index f96d57489..6a7f129b7 100644 --- a/basil/HL/sensirion_ekh4.py +++ b/basil/HL/sensirion_ekh4.py @@ -5,19 +5,19 @@ # ------------------------------------------------------------ # -import time import binascii import codecs +import time from basil.HL.RegisterHardwareLayer import HardwareLayer class sensirionEKH4(HardwareLayer): - '''Driver for the Sensirion EK-H4 multiplexer box. Can be used to read up to 4 channels of sensirion sensors for humidity and temperature + """Driver for the Sensirion EK-H4 multiplexer box. Can be used to read up to 4 channels of sensirion sensors for humidity and temperature (http://www.sensirion.com/en/products/humidity-temperature/evaluation-kits/ek-h4/). A TLV protocoll via serial port is used with 115200 baud rate. The type byte definitions cannot be found online... The data returned by the device is often too long. Different cases are handled and not reconsturctable channels are set to None. - ''' + """ def __init__(self, intf, conf): super(sensirionEKH4, self).__init__(intf, conf) @@ -31,15 +31,15 @@ def _write(self, command): self._intf.write(binascii.a2b_hex(command)) def _read(self): - word = '' + word = "" data_flg = 0 for _ in range(1024): - b = codecs.encode(self._intf.read(size=1), 'hex_codec').decode('utf-8') + b = codecs.encode(self._intf.read(size=1), "hex_codec").decode("utf-8") - if b == '7e': # delimiter - if data_flg == 0: # data word comes next + if b == "7e": # delimiter + if data_flg == 0: # data word comes next data_flg = 1 - else: # data word finished + else: # data word finished break elif data_flg == 1: word += b @@ -52,9 +52,9 @@ def _query(self, command): return self._read() def _calc_value(self, value): - ''' - Calculate two's complement of signed binary, if applicable. - ''' + """ + Calculate two's complement of signed binary, if applicable. + """ bits = 16 value = int(value, 16) if (value & (1 << (bits - 1))) != 0: # if sign bit is set, e.g., 8bit: 128-255 @@ -62,33 +62,33 @@ def _calc_value(self, value): return float(value) / 100.0 def _get_values(self, cmd): - ''' - Retrieve raw values via self._query and do error correction if possible - First 4 characters of data word are unknown ("4608", "4708" or "4808"). - Last two characters seem to be some kind of checksum? - In between there should be 16 characters, 4 per channel. Sometimes it's more. - Two cases can be distinguished here: - 1. Some kind of common error code "7d31" plus an additional byte. - In this case, the affected channel is set to None, - the extra byte is removed and the other channels are interpreted as usual. - 2. Varying amount of extra bytes with no recognizable error code. - In this case, nothing can be reconstructed and all channels are set to None. - - Case 1 is reproducable for temperatures between about 43.53C and 46.1C...? - ''' + """ + Retrieve raw values via self._query and do error correction if possible + First 4 characters of data word are unknown ("4608", "4708" or "4808"). + Last two characters seem to be some kind of checksum? + In between there should be 16 characters, 4 per channel. Sometimes it's more. + Two cases can be distinguished here: + 1. Some kind of common error code "7d31" plus an additional byte. + In this case, the affected channel is set to None, + the extra byte is removed and the other channels are interpreted as usual. + 2. Varying amount of extra bytes with no recognizable error code. + In this case, nothing can be reconstructed and all channels are set to None. + + Case 1 is reproducable for temperatures between about 43.53C and 46.1C...? + """ ret = self._query(cmd)[4:-2] # Cut off extra bytes in case of error for i in range(0, 16, 4): - if ret[i:i + 4] == '7d31': - ret = ret[:i + 4] + ret[i + 6:] + if ret[i : i + 4] == "7d31": + ret = ret[: i + 4] + ret[i + 6 :] if len(ret) != 16: # wrong number of bytes despite attempted error correction values = [None, None, None, None] else: values = [] - data = [ret[j:j + 4] for j in range(0, len(ret), 4)] + data = [ret[j : j + 4] for j in range(0, len(ret), 4)] for i, d in enumerate(data): - if d == '7d31' or d == '7fff': # Error or no sensor connected + if d == "7d31" or d == "7fff": # Error or no sensor connected values.append(None) else: values.append(self._calc_value(d)) diff --git a/basil/HL/sensirion_sht85.py b/basil/HL/sensirion_sht85.py index 3ca12754d..ad68e3dfc 100644 --- a/basil/HL/sensirion_sht85.py +++ b/basil/HL/sensirion_sht85.py @@ -4,10 +4,11 @@ # ------------------------------------------------------------ # -import numpy as np import logging import struct +import numpy as np + from basil.HL.SensirionBridgeDevice import SensirionBridgeI2CDevice logger = logging.getLogger(__name__) @@ -15,7 +16,7 @@ class sensirionSHT85(SensirionBridgeI2CDevice): - ''' + """ Driver for the Sensirion SHT85 temperature and humidity sensor. Measurements can be performed in three repeatability modes: low (0.15°C 0.21%RH) (default), medium (0.08°C 0.15%RH), high (0.04°C 0.08%RH) @@ -26,7 +27,7 @@ class sensirionSHT85(SensirionBridgeI2CDevice): A non-blocking call to the asynchrounous read function may return None if no data is available. In ART mode the humidity response is accelerated. A heater may be turned on for debugging purposes. - ''' + """ def __init__(self, intf, conf): super(sensirionSHT85, self).__init__(intf, conf) @@ -36,26 +37,27 @@ def init(self): try: import crcmod + self.crc_func = crcmod.mkCrcFun(0x131, initCrc=0xFF, rev=False, xorOut=0x00) except ImportError: logger.warning("You have to install the package 'crcmod'! Transmission errors will not be caught.") self.crc_func = lambda x: 0 - self.repeatability = self._init.get('repeatability', 'low') + self.repeatability = self._init.get("repeatability", "low") def _read(self, command, read_n_words=0, timeout_us=20e3, n_tries=10): for _ in range(n_tries): rx_data = super(sensirionSHT85, self)._read(command, read_n_words * 3, timeout_us) data = [0] * read_n_words for i in range(read_n_words): - if self.crc_func(rx_data[i * 3:(i + 1) * 3]): + if self.crc_func(rx_data[i * 3 : (i + 1) * 3]): break else: - data[i] = struct.unpack('>H', rx_data[i * 3: i * 3 + 2])[0] + data[i] = struct.unpack(">H", rx_data[i * 3 : i * 3 + 2])[0] else: return data continue - raise Exception('Checksum repeatedly ({0}x) wrong'.format(n_tries), rx_data) + raise Exception("Checksum repeatedly ({0}x) wrong".format(n_tries), rx_data) def _write(self, command): super(sensirionSHT85, self)._write(command) @@ -109,7 +111,7 @@ def start_asynchronous_read(self, measurments_per_second=1, ART=False): 2: [0x22, 0x36], 4: [0x23, 0x34], 10: [0x27, 0x37], - }[measurments_per_second] + }[measurments_per_second], }[self.repeatability] self._write(cmd) @@ -137,6 +139,7 @@ def read(self_a): def read_synchronous(self_a, timeout_us=100e3): return self.read_asynchronous(timeout_us) + return Asynchronous() def _get_status(self): @@ -162,10 +165,10 @@ def _to_humidity(self, data): return 100 * (float(data[1]) / (2**16 - 1)) def to_dew_point(self, T, RH): - ''' returns the dew point using an approximation - approximation specified by Sensirion: - http://irtfweb.ifa.hawaii.edu/~tcs3/tcs3/Misc/Dewpoint_Calculation_Humidity_Sensor_E.pdf - ''' + """returns the dew point using an approximation + approximation specified by Sensirion: + http://irtfweb.ifa.hawaii.edu/~tcs3/tcs3/Misc/Dewpoint_Calculation_Humidity_Sensor_E.pdf + """ if RH == 0: RH = self._to_humidity((0, 1)) # lowest non-zero rel. humidity H = (np.log10(RH) - 2) / 0.4343 + (17.62 * T) / (243.12 + T) diff --git a/basil/HL/seq_gen.py b/basil/HL/seq_gen.py index 33e6025f8..33860ef1b 100644 --- a/basil/HL/seq_gen.py +++ b/basil/HL/seq_gen.py @@ -9,24 +9,24 @@ class seq_gen(RegisterHardwareLayer): - '''Sequencer generator controller interface for seq_gen FPGA module. - ''' - - _registers = {'RESET': {'descr': {'addr': 0, 'size': 8, 'properties': ['writeonly']}}, - 'VERSION': {'descr': {'addr': 0, 'size': 8, 'properties': ['ro']}}, - 'READY': {'descr': {'addr': 1, 'size': 1, 'properties': ['ro']}}, - 'START': {'descr': {'addr': 1, 'size': 8, 'properties': ['writeonly']}}, - 'EN_EXT_START': {'descr': {'addr': 2, 'size': 1}}, - 'CLK_DIV': {'descr': {'addr': 3, 'size': 8}}, - 'SIZE': {'descr': {'addr': 4, 'size': 32}}, - 'WAIT': {'descr': {'addr': 8, 'size': 32}}, - 'REPEAT': {'descr': {'addr': 12, 'size': 32}}, - 'REPEAT_START': {'descr': {'addr': 16, 'size': 32}}, - 'NESTED_START': {'descr': {'addr': 20, 'size': 32}}, - 'NESTED_STOP': {'descr': {'addr': 24, 'size': 32}}, - 'NESTED_REPEAT': {'descr': {'addr': 28, 'size': 32}}, - 'MEM_BYTES': {'descr': {'addr': 32, 'size': 32, 'properties': ['ro']}}, - } + """Sequencer generator controller interface for seq_gen FPGA module.""" + + _registers = { + "RESET": {"descr": {"addr": 0, "size": 8, "properties": ["writeonly"]}}, + "VERSION": {"descr": {"addr": 0, "size": 8, "properties": ["ro"]}}, + "READY": {"descr": {"addr": 1, "size": 1, "properties": ["ro"]}}, + "START": {"descr": {"addr": 1, "size": 8, "properties": ["writeonly"]}}, + "EN_EXT_START": {"descr": {"addr": 2, "size": 1}}, + "CLK_DIV": {"descr": {"addr": 3, "size": 8}}, + "SIZE": {"descr": {"addr": 4, "size": 32}}, + "WAIT": {"descr": {"addr": 8, "size": 32}}, + "REPEAT": {"descr": {"addr": 12, "size": 32}}, + "REPEAT_START": {"descr": {"addr": 16, "size": 32}}, + "NESTED_START": {"descr": {"addr": 20, "size": 32}}, + "NESTED_STOP": {"descr": {"addr": 24, "size": 32}}, + "NESTED_REPEAT": {"descr": {"addr": 28, "size": 32}}, + "MEM_BYTES": {"descr": {"addr": 32, "size": 32, "properties": ["ro"]}}, + } _require_version = "==3" def __init__(self, intf, conf): @@ -112,13 +112,15 @@ def get_mem_size(self): def set_data(self, data, addr=0): if self._seq_mem_size < len(data): - raise ValueError('Size of data (%d bytes) is too big for memory (%d bytes)' % (len(data), self._seq_mem_size)) - self._intf.write(self._conf['base_addr'] + self._seq_mem_offset + addr, data) + raise ValueError( + "Size of data (%d bytes) is too big for memory (%d bytes)" % (len(data), self._seq_mem_size) + ) + self._intf.write(self._conf["base_addr"] + self._seq_mem_offset + addr, data) def get_data(self, size=None, addr=0): if size and self._seq_mem_size < size: - raise ValueError('Size is too big') + raise ValueError("Size is too big") if not size: - return self._intf.read(self._conf['base_addr'] + self._seq_mem_offset + addr, self._seq_mem_size) + return self._intf.read(self._conf["base_addr"] + self._seq_mem_offset + addr, self._seq_mem_size) else: - return self._intf.read(self._conf['base_addr'] + self._seq_mem_offset + addr, size) + return self._intf.read(self._conf["base_addr"] + self._seq_mem_offset + addr, size) diff --git a/basil/HL/seq_rec.py b/basil/HL/seq_rec.py index c990e0802..5075047e3 100644 --- a/basil/HL/seq_rec.py +++ b/basil/HL/seq_rec.py @@ -9,17 +9,17 @@ class seq_rec(RegisterHardwareLayer): - '''Sequencer receiver controller interface for seq_rec FPGA module. - ''' - - _registers = {'RESET': {'descr': {'addr': 0, 'size': 8, 'properties': ['writeonly']}}, - 'VERSION': {'descr': {'addr': 0, 'size': 8, 'properties': ['ro']}}, - 'READY': {'descr': {'addr': 1, 'size': 1, 'properties': ['ro']}}, - 'START': {'descr': {'addr': 1, 'size': 8, 'properties': ['writeonly']}}, - 'EN_EXT_START': {'descr': {'addr': 2, 'size': 8}}, - 'SIZE': {'descr': {'addr': 4, 'size': 32}}, - 'MEM_BYTES': {'descr': {'addr': 8, 'size': 32, 'properties': ['ro']}}, - } + """Sequencer receiver controller interface for seq_rec FPGA module.""" + + _registers = { + "RESET": {"descr": {"addr": 0, "size": 8, "properties": ["writeonly"]}}, + "VERSION": {"descr": {"addr": 0, "size": 8, "properties": ["ro"]}}, + "READY": {"descr": {"addr": 1, "size": 1, "properties": ["ro"]}}, + "START": {"descr": {"addr": 1, "size": 8, "properties": ["writeonly"]}}, + "EN_EXT_START": {"descr": {"addr": 2, "size": 8}}, + "SIZE": {"descr": {"addr": 4, "size": 32}}, + "MEM_BYTES": {"descr": {"addr": 8, "size": 32, "properties": ["ro"]}}, + } _require_version = "==1" def __init__(self, intf, conf): @@ -66,8 +66,8 @@ def get_done(self): def get_data(self, size=None, addr=0): if size and self._seq_mem_size < size: - raise ValueError('Size is too big memory=%d requested_size=%d' % (self._seq_mem_size, size)) + raise ValueError("Size is too big memory=%d requested_size=%d" % (self._seq_mem_size, size)) if not size: - return self._intf.read(self._conf['base_addr'] + self._seq_mem_offset + addr, self._seq_mem_size) + return self._intf.read(self._conf["base_addr"] + self._seq_mem_offset + addr, self._seq_mem_size) else: - return self._intf.read(self._conf['base_addr'] + self._seq_mem_offset + addr, size) + return self._intf.read(self._conf["base_addr"] + self._seq_mem_offset + addr, size) diff --git a/basil/HL/si570.py b/basil/HL/si570.py index 210dc9a74..c7a118f67 100644 --- a/basil/HL/si570.py +++ b/basil/HL/si570.py @@ -10,7 +10,6 @@ from basil.HL.HardwareLayer import HardwareLayer from basil.RL.StdRegister import StdRegister - logger = logging.getLogger(__name__) @@ -48,7 +47,7 @@ def frequency_change(self, freq): # freq in MHz HS_DIV, N1, RFREQ = self.read_registers() - fxtal = float(f0 * HS_DIV * N1) / (float(RFREQ) / 2 ** 28) + fxtal = float(f0 * HS_DIV * N1) / (float(RFREQ) / 2**28) new_fdco = freq * HS_DIV * N1 @@ -61,9 +60,7 @@ def frequency_change(self, freq): # freq in MHz for hs in HS_DIV_avaiable: for n in N1_avaiable: fdco = freq * 1e6 * hs * n - if (fdco >= 4.85e9) & ( - fdco <= 5.67e9 - ): # fdco range defined by manufacturer + if (fdco >= 4.85e9) & (fdco <= 5.67e9): # fdco range defined by manufacturer HS_DIV = hs N1 = n found_new_values = True @@ -74,12 +71,10 @@ def frequency_change(self, freq): # freq in MHz new_fdco = freq * HS_DIV * N1 new_RFREQ_freq = new_fdco / fxtal - new_RFREQ = int(new_RFREQ_freq * 2 ** 28) + new_RFREQ = int(new_RFREQ_freq * 2**28) self.modify_register(HS_DIV, N1, new_RFREQ) - logger.info( - "Changed Si570 reference frequency to %s MHz", new_fdco / (HS_DIV * N1) - ) + logger.info("Changed Si570 reference frequency to %s MHz", new_fdco / (HS_DIV * N1)) def modify_register(self, HS_DIV, N1, RFREQ): # Preparation of the array that needs to be send @@ -112,12 +107,6 @@ def read_registers(self): N1 = ((reg_val[0] & 0x1F) << 2) | ((reg_val[1] & 0xC0) >> 6) N1 += 1 - RFREQ = ( - ((reg_val[1] & 0x3F) << 32) - | reg_val[2] << 24 - | reg_val[3] << 16 - | reg_val[4] << 8 - | reg_val[5] - ) + RFREQ = ((reg_val[1] & 0x3F) << 32) | reg_val[2] << 24 | reg_val[3] << 16 | reg_val[4] << 8 | reg_val[5] return HS_DIV, N1, RFREQ diff --git a/basil/HL/sitcp_fifo.py b/basil/HL/sitcp_fifo.py index f7e72d820..2a417f3bf 100644 --- a/basil/HL/sitcp_fifo.py +++ b/basil/HL/sitcp_fifo.py @@ -4,8 +4,8 @@ # SiLab, Institute of Physics, University of Bonn # ------------------------------------------------------------ # -import struct import array +import struct import numpy as np @@ -13,19 +13,20 @@ class sitcp_fifo(HardwareLayer): - ''' SiTCP driver that mimics the RegisterHardwareLayer BRAM and SRAM FIFO interfaces. + """SiTCP driver that mimics the RegisterHardwareLayer BRAM and SRAM FIFO interfaces. No firmware module is available for this driver. This is just a driver that replaces BRAM and SRAM FIFO when the SiTCP transfer layer is used. - ''' + """ + _version = 0 def __getitem__(self, name): if name == "RESET": self._intf.reset() # returns None - elif name == 'VERSION': + elif name == "VERSION": return self._version - elif name == 'FIFO_SIZE': + elif name == "FIFO_SIZE": return self._intf._get_tcp_data_size() else: super(sitcp_fifo, self).__getitem__(name) @@ -37,19 +38,20 @@ def __setitem__(self, name, value): super(sitcp_fifo, self).__setitem__(name, value) def __getattr__(self, name): - '''called only on last resort if there are no attributes in the instance that match the name - ''' + """called only on last resort if there are no attributes in the instance that match the name""" if name.isupper(): return self[name] else: + def method(*args, **kwargs): - nsplit = name.split('_', 1) - if len(nsplit) == 2 and nsplit[0] == 'set' and nsplit[1].isupper() and len(args) == 1 and not kwargs: + nsplit = name.split("_", 1) + if len(nsplit) == 2 and nsplit[0] == "set" and nsplit[1].isupper() and len(args) == 1 and not kwargs: self[nsplit[1]] = args[0] # returns None - elif len(nsplit) == 2 and nsplit[0] == 'get' and nsplit[1].isupper() and not args and not kwargs: + elif len(nsplit) == 2 and nsplit[0] == "get" and nsplit[1].isupper() and not args and not kwargs: return self[nsplit[1]] else: raise AttributeError("%r object has no attribute %r" % (self.__class__, name)) + return method def __setattr__(self, name, value): @@ -59,25 +61,25 @@ def __setattr__(self, name, value): super(sitcp_fifo, self).__setattr__(name, value) def get_data(self): - ''' Reading data from SiTCP FIFO (via TCP). + """Reading data from SiTCP FIFO (via TCP). Returns ------- array : numpy.ndarray Array of unsigned integers (32 bit). - ''' + """ fifo_size = self._intf._get_tcp_data_size() fifo_int_size = int((fifo_size - (fifo_size % 4)) / 4) data = self._intf._get_tcp_data(fifo_int_size * 4) - return np.frombuffer(data, dtype=np.dtype(' repeat forever) - ''' + """ return self.REPEAT def set_en(self, value): - ''' + """ Enable start on external EXT_START signal (inside FPGA) - ''' + """ self.EN = value def get_en(self): - ''' + """ Gets state of enable. - ''' + """ return self.EN def is_done(self): - ''' + """ Get the status of transfer/sequence. - ''' + """ return self.is_ready @property @@ -105,26 +106,26 @@ def get_mem_size(self): return self.MEM_BYTES def set_data(self, data, addr=0): - ''' + """ Sets data for outgoing stream - ''' + """ if self._mem_bytes < len(data): - raise ValueError('Size of data (%d bytes) is too big for memory (%d bytes)' % (len(data), self._mem_bytes)) - self._intf.write(self._conf['base_addr'] + self._spi_mem_offset + addr, data) + raise ValueError("Size of data (%d bytes) is too big for memory (%d bytes)" % (len(data), self._mem_bytes)) + self._intf.write(self._conf["base_addr"] + self._spi_mem_offset + addr, data) # This needs to be changed to return written value def get_data(self, size=None, addr=None): - ''' + """ Gets data for incoming stream - ''' + """ # readback memory offset if addr is None: addr = self._mem_bytes if size and self._mem_bytes < size: - raise ValueError('Size is too big') + raise ValueError("Size is too big") if size is None: - return self._intf.read(self._conf['base_addr'] + self._spi_mem_offset + addr, self._mem_bytes) + return self._intf.read(self._conf["base_addr"] + self._spi_mem_offset + addr, self._mem_bytes) else: - return self._intf.read(self._conf['base_addr'] + self._spi_mem_offset + addr, size) + return self._intf.read(self._conf["base_addr"] + self._spi_mem_offset + addr, size) diff --git a/basil/HL/sram_fifo.py b/basil/HL/sram_fifo.py index 46da31b29..19413ae8b 100644 --- a/basil/HL/sram_fifo.py +++ b/basil/HL/sram_fifo.py @@ -16,15 +16,16 @@ class sram_fifo(RegisterHardwareLayer): - '''SRAM FIFO controller interface for sram_fifo FPGA module. - ''' - - _registers = {'RESET': {'descr': {'addr': 0, 'size': 8, 'properties': ['writeonly']}}, - 'VERSION': {'descr': {'addr': 0, 'size': 8, 'properties': ['ro']}}, - 'ALMOST_FULL_THRESHOLD': {'descr': {'addr': 1, 'size': 8}}, - 'ALMOST_EMPTY_THRESHOLD': {'descr': {'addr': 2, 'size': 8}}, - 'READ_ERROR_COUNTER': {'descr': {'addr': 3, 'size': 8, 'properties': ['ro']}}, - 'FIFO_SIZE': {'descr': {'addr': 4, 'size': 32, 'properties': ['ro']}}} + """SRAM FIFO controller interface for sram_fifo FPGA module.""" + + _registers = { + "RESET": {"descr": {"addr": 0, "size": 8, "properties": ["writeonly"]}}, + "VERSION": {"descr": {"addr": 0, "size": 8, "properties": ["ro"]}}, + "ALMOST_FULL_THRESHOLD": {"descr": {"addr": 1, "size": 8}}, + "ALMOST_EMPTY_THRESHOLD": {"descr": {"addr": 2, "size": 8}}, + "READ_ERROR_COUNTER": {"descr": {"addr": 3, "size": 8, "properties": ["ro"]}}, + "FIFO_SIZE": {"descr": {"addr": 4, "size": 32, "properties": ["ro"]}}, + } _require_version = "==2" def __init__(self, intf, conf): @@ -41,69 +42,69 @@ def set_almost_empty_threshold(self, value): self.ALMOST_EMPTY_THRESHOLD = value # no get function possible def get_fifo_size(self): - ''' *Deprecated* Get FIFO size in units of bytes (8 bit). + """*Deprecated* Get FIFO size in units of bytes (8 bit). Returns ------- fifo_size : int FIFO size in units of bytes (8 bit). - ''' + """ logger.warning("Deprecated: Use get_FIFO_SIZE()") return self.FIFO_SIZE @property def FIFO_INT_SIZE(self): - ''' Get FIFO size in units of integers (32 bit). + """Get FIFO size in units of integers (32 bit). Returns ------- fifo_size : int FIFO size in units of integers (32 bit). - ''' + """ fifo_size = self.FIFO_SIZE # sometimes reading of FIFO size happens during writing to SRAM, but we want to have a multiplicity of 32 bits return int((fifo_size - (fifo_size % 4)) / 4) def get_fifo_int_size(self): - ''' *Deprecated* Get FIFO size in units of integers (32 bit). + """*Deprecated* Get FIFO size in units of integers (32 bit). Returns ------- fifo_size : int FIFO size in units of integers (32 bit). - ''' + """ logger.warning("Deprecated: Use get_FIFO_INT_SIZE()") return self.FIFO_INT_SIZE def get_FIFO_INT_SIZE(self): - ''' Get FIFO size in units of integers (32 bit). + """Get FIFO size in units of integers (32 bit). Returns ------- fifo_size : int FIFO size in units of integers (32 bit). - ''' + """ return self.FIFO_INT_SIZE def get_read_error_counter(self): - ''' *Deprecated* Get read error counter. + """*Deprecated* Get read error counter. Returns ------- fifo_size : int Read error counter (read attempts when SRAM is empty). - ''' + """ logger.warning("Deprecated: Use get_READ_ERROR_COUNTER()") return self.READ_ERROR_COUNTER def get_data(self): - ''' Reading data in SRAM. + """Reading data in SRAM. Returns ------- array : numpy.ndarray Array of unsigned integers (32 bit). - ''' + """ fifo_int_size_1 = self.FIFO_INT_SIZE fifo_int_size_2 = self.FIFO_INT_SIZE if fifo_int_size_1 > fifo_int_size_2: @@ -111,10 +112,11 @@ def get_data(self): logger.warning("Reading wrong FIFO size. Expected: %d <= %d" % (fifo_int_size_1, fifo_int_size_2)) else: fifo_int_size = fifo_int_size_1 # use smaller chunk - return np.frombuffer(self._intf.read(self._conf['base_data_addr'], size=4 * fifo_int_size), dtype=np.dtype('> 9) & 0x0FFFF) + (((word >> 7) & 0x3)) + return self.CLK_DIV * ((word >> 9) & 0x0FFFF) + ((word >> 7) & 0x3) def get_word_type(self, word): - return (word >> (32 - 7) & 0b111) + return word >> (32 - 7) & 0b111 def is_calib_word(self, word): return self.get_word_type(word) == 4 def is_time_word(self, word): if isinstance(word, np.ndarray): - return [(self.word_type_codes[t] in ['TRIGGERED', 'RISING', 'FALLING']) for t in self.get_word_type(word)] + return [(self.word_type_codes[t] in ["TRIGGERED", "RISING", "FALLING"]) for t in self.get_word_type(word)] else: - return self.word_type_codes[self.get_word_type(word)] in ['TRIGGERED', 'RISING', 'FALLING'] + return self.word_type_codes[self.get_word_type(word)] in ["TRIGGERED", "RISING", "FALLING"] def get_raw_tdl_values(self, word): return word & 0b1111111 @@ -75,13 +71,14 @@ def set_calib_values(self, calib_values): data_sort, value_counts = np.unique(calib_values % 128, return_counts=True) self.calib_vector = np.zeros(100) for i, zero in enumerate(self.calib_vector): - bins_lt_i = (data_sort <= i) + bins_lt_i = data_sort <= i self.calib_vector[i] = np.sum(value_counts[bins_lt_i]) self.calib_sum = np.sum(value_counts) self.calib_vector = self.calib_vector / self.calib_sum def plot_calib_values(self, data): import matplotlib.pyplot as plt + # This if is a safeguard: If data with a large range of values is given to the below # the code takes forever to return. if max(data) - min(data) < 1000: @@ -97,14 +94,14 @@ def plot_calib_values(self, data): def tdc_word_to_time(self, word): if isinstance(word, dict): - word = word['raw_word'] + word = word["raw_word"] if isinstance(word, np.ndarray): if not all(self.is_time_word(word)): - raise ValueError('can not convert tdc word of given types to time') + raise ValueError("can not convert tdc word of given types to time") else: - if (not self.is_time_word(word)): + if not self.is_time_word(word): word_type = self.word_type_codes[self.get_word_type(word)] - raise ValueError('can not convert tdc word of type %s to time' % word_type) + raise ValueError("can not convert tdc word of type %s to time" % word_type) tdc_value = self.get_tdc_value(word) tdc_time = 1 / self.GHZ_S_FREQ * tdc_value return tdc_time - self.tdl_to_time(self.get_raw_tdl_values(word)) @@ -112,21 +109,23 @@ def tdc_word_to_time(self, word): def disassemble_tdc_word(self, word): # Shift away the 32 - 7 data bits and grab 3 bit word type word_type = self.word_type_codes[self.get_word_type(word)] - if word_type in ['CALIB', 'TRIGGERED', 'RISING', 'FALLING']: - return {'source_id': (word >> (32 - 4)), - 'word_type': word_type, - 'tdl_value': word & 0b1111111, - 'fine_clk_value': self.get_tdc_value(word), - 'raw_word': word} - elif word_type in ['TIMESTAMP', 'RST']: - return {'source_id': (word >> (32 - 4)), - 'word_type': word_type, - 'timestamp': (word >> 9) & 0xFFFF, - 'raw_word': word} + if word_type in ["CALIB", "TRIGGERED", "RISING", "FALLING"]: + return { + "source_id": (word >> (32 - 4)), + "word_type": word_type, + "tdl_value": word & 0b1111111, + "fine_clk_value": self.get_tdc_value(word), + "raw_word": word, + } + elif word_type in ["TIMESTAMP", "RST"]: + return { + "source_id": (word >> (32 - 4)), + "word_type": word_type, + "timestamp": (word >> 9) & 0xFFFF, + "raw_word": word, + } else: - return {'source_id': (word >> (32 - 4)), - 'word_type': word_type, - 'raw_word': word} + return {"source_id": (word >> (32 - 4)), "word_type": word_type, "raw_word": word} def reset(self): self.RESET = 0 diff --git a/basil/HL/tektronix_oscilloscope.py b/basil/HL/tektronix_oscilloscope.py index 729fab9ec..597926856 100644 --- a/basil/HL/tektronix_oscilloscope.py +++ b/basil/HL/tektronix_oscilloscope.py @@ -5,11 +5,13 @@ # ------------------------------------------------------------ # -from basil.HL.scpi import scpi from collections import namedtuple from enum import Enum + from pyvisa.errors import VisaIOError +from basil.HL.scpi import scpi + Identity = namedtuple("Identity", "company, model, serial, config") XScale = namedtuple("XScale", "slope, offset, unit") YScale = namedtuple("YScale", "top, bottom") @@ -64,7 +66,7 @@ def _make_jobs(self, channel=1): } results = {} - sources = ['CH' + str(channel)] + sources = ["CH" + str(channel)] for source in sources: if source.split("_")[0] not in results: # Determine the type of waveform and set key interface parameters @@ -76,9 +78,7 @@ def _make_jobs(self, channel=1): rec_len = int(self._intf.query("horizontal:recordlength?").strip()) # Keep track of each super channel and math source that has been handled - results[source.split("_")[0]] = JobParameters( - wave_type, channel, encoding, bit_nr, datatype, rec_len - ) + results[source.split("_")[0]] = JobParameters(wave_type, channel, encoding, bit_nr, datatype, rec_len) return results def _classify_waveform(self, source): @@ -114,8 +114,8 @@ def _get_xscale(self): return result def _get_yscale(self, channel=1): - scale = float(self._intf.query("{}:SCALE?".format('CH' + str(channel)))) - position = float(self._intf.query("{}:POSITION?".format('CH' + str(channel)))) + scale = float(self._intf.query("{}:SCALE?".format("CH" + str(channel)))) + position = float(self._intf.query("{}:POSITION?".format("CH" + str(channel)))) top = scale * (5 - position) bottom = scale * (-5 - position) return YScale(top=top, bottom=bottom) @@ -133,11 +133,11 @@ def _setup_curve_query(self, parameters, channel=1): """Setup the instrument for the curve query operation""" # extract the job parameters - wave_type, channel, encoding, bit_nr, datatype, rec_len = parameters['CH' + str(channel)] + wave_type, channel, encoding, bit_nr, datatype, rec_len = parameters["CH" + str(channel)] # Switch to the source and setup the data encoding - self._intf.write("data:source {}".format('CH' + channel)) - self.set_data_encoding('ascii') + self._intf.write("data:source {}".format("CH" + channel)) + self.set_data_encoding("ascii") self._intf.write("WFMOUTPRE:BIT_NR {}".format(bit_nr)) # Set the start and stop point of the record @@ -173,7 +173,7 @@ def get_waveform(self, channel=1): x_scale = self._get_xscale() ret_val = None if x_scale is not None: - source_data = [int(i) for i in self.get_data(channel=channel).replace('\n', '').split(',')] + source_data = [int(i) for i in self.get_data(channel=channel).replace("\n", "").split(",")] if wave_type is WaveType.ANALOG: ret_val = self._post_process_analog(source_data, x_scale, channel=channel) else: diff --git a/basil/HL/tektronix_tds3034b.py b/basil/HL/tektronix_tds3034b.py index af09f63c7..1262a5462 100644 --- a/basil/HL/tektronix_tds3034b.py +++ b/basil/HL/tektronix_tds3034b.py @@ -6,11 +6,13 @@ # -from basil.HL.scpi import scpi from collections import namedtuple from enum import Enum + from pyvisa.errors import VisaIOError +from basil.HL.scpi import scpi + Identity = namedtuple("Identity", "company, model, serial, config") XScale = namedtuple("XScale", "slope, offset, unit") YScale = namedtuple("YScale", "scale, top, bottom, unit") @@ -65,7 +67,7 @@ def _make_jobs(self, channel=1): } results = {} - sources = ['CH' + str(channel)] + sources = ["CH" + str(channel)] for source in sources: if source.split("_")[0] not in results: # Determine the type of waveform and set key interface parameters @@ -74,11 +76,9 @@ def _make_jobs(self, channel=1): encoding, bit_nr, datatype = encoding_table[wave_type] # Set the start and stop point of the record - rec_len = int(self._intf.query("horizontal:recordlength?").split(' ')[1].strip()) + rec_len = int(self._intf.query("horizontal:recordlength?").split(" ")[1].strip()) # Keep track of each super channel and math source that has been handled - results[source.split("_")[0]] = JobParameters( - wave_type, channel, encoding, bit_nr, datatype, rec_len - ) + results[source.split("_")[0]] = JobParameters(wave_type, channel, encoding, bit_nr, datatype, rec_len) return results def _classify_waveform(self, source): @@ -97,14 +97,14 @@ def _get_xscale(self): # available and the channel is enabled. result = None try: - xincr = self._intf.query("WFMPre:XINCR?").split(' ')[1].strip() + xincr = self._intf.query("WFMPre:XINCR?").split(" ")[1].strip() except VisaIOError: pass else: # collect more horizontal data - pt_off = self._intf.query("WFMPre:PT_OFF?").split(' ')[1].strip() - xzero = self._intf.query("WFMPre:XZERO?").split(' ')[1].strip() - xunit = self._intf.query("WFMPre:XUNIT?").split(' ')[1].strip() + pt_off = self._intf.query("WFMPre:PT_OFF?").split(" ")[1].strip() + xzero = self._intf.query("WFMPre:XZERO?").split(" ")[1].strip() + xunit = self._intf.query("WFMPre:XUNIT?").split(" ")[1].strip() # calculate horizontal scale slope = float(xincr) offset = float(pt_off) * -slope + float(xzero) @@ -113,11 +113,11 @@ def _get_xscale(self): return result def _get_yscale(self, channel=1): - scale = float(self._intf.query("{}:SCALE?".format('CH' + str(channel))).split(' ')[1]) - position = float(self._intf.query("{}:POSITION?".format('CH' + str(channel))).split(' ')[1]) + scale = float(self._intf.query("{}:SCALE?".format("CH" + str(channel))).split(" ")[1]) + position = float(self._intf.query("{}:POSITION?".format("CH" + str(channel))).split(" ")[1]) top = scale * (5 - position) bottom = scale * (-5 - position) - yunit = self._intf.query("WFMPre:YUNIT?").split(' ')[1].strip() + yunit = self._intf.query("WFMPre:YUNIT?").split(" ")[1].strip() return YScale(scale=scale, top=top, bottom=bottom, unit=yunit) def _has_data_available(self, source): @@ -133,15 +133,15 @@ def _setup_curve_query(self, parameters, channel=1): """Setup the instrument for the curve query operation""" # extract the job parameters - wave_type, channel, encoding, bit_nr, datatype, rec_len = parameters['CH' + str(channel)] + wave_type, channel, encoding, bit_nr, datatype, rec_len = parameters["CH" + str(channel)] # Switch to the source and setup the data encoding - self._intf.write("data:source {}".format('CH' + channel)) - self.set_data_encoding('ascii') + self._intf.write("data:source {}".format("CH" + channel)) + self.set_data_encoding("ascii") self._intf.write("WFMOUTPRE:BIT_NR {}".format(bit_nr)) # Set the start and stop point of the record - rec_len = self._intf.query("horizontal:recordlength?").split(' ')[1] + rec_len = self._intf.query("horizontal:recordlength?").split(" ")[1] self._intf.write("data:start 1") self._intf.write("data:stop {}".format(rec_len)) return wave_type @@ -149,8 +149,8 @@ def _setup_curve_query(self, parameters, channel=1): def _post_process_analog(self, source_data, x_scale, channel=1): """Post processes analog channel data""" # Normal analog channels must have the vertical scale and offset applied - offset = float(self._intf.query("WFMPre:YZEro?").split(' ')[1]) - scale = float(self._intf.query("WFMPre:YMUlt?").split(' ')[1]) + offset = float(self._intf.query("WFMPre:YZEro?").split(" ")[1]) + scale = float(self._intf.query("WFMPre:YMUlt?").split(" ")[1]) source_data = [scale * i + offset for i in source_data] # Include y-scale information with analog channel waveforms @@ -168,7 +168,7 @@ def get_waveform(self, channel=1, continue_meas=True): x_scale = self._get_xscale() ret_val = None if x_scale is not None: - source_data = [int(i) for i in self.get_data(channel=channel).split(' ')[1].replace('\n', '').split(',')] + source_data = [int(i) for i in self.get_data(channel=channel).split(" ")[1].replace("\n", "").split(",")] if wave_type is WaveType.ANALOG: ret_val = self._post_process_analog(source_data, x_scale, channel=channel) else: @@ -179,6 +179,6 @@ def get_waveform(self, channel=1, continue_meas=True): return ret_val def get_y_info(self, channel=1): - scale = float(self._intf.query("{}:SCALE?".format('CH' + str(channel))).split(' ')[1]) - position = float(self._intf.query("{}:POSITION?".format('CH' + str(channel))).split(' ')[1]) + scale = float(self._intf.query("{}:SCALE?".format("CH" + str(channel))).split(" ")[1]) + position = float(self._intf.query("{}:POSITION?".format("CH" + str(channel))).split(" ")[1]) return scale, position diff --git a/basil/HL/timestamp.py b/basil/HL/timestamp.py index 40d34cbe2..a988ee06d 100644 --- a/basil/HL/timestamp.py +++ b/basil/HL/timestamp.py @@ -9,17 +9,17 @@ class timestamp(RegisterHardwareLayer): - '''Implement timestamp driver. - ''' + """Implement timestamp driver.""" def __init__(self, intf, conf): - self._registers = {'RESET': {'descr': {'addr': 0, 'size': 8, 'properties': ['writeonly']}}, - 'VERSION': {'descr': {'addr': 0, 'size': 8, 'properties': ['ro']}}, - 'ENABLE': {'descr': {'addr': 2, 'size': 1, 'offset': 0}}, - 'EXT_TIMESTAMP': {'descr': {'addr': 2, 'size': 1, 'offset': 1}}, - 'ENABLE_EXTERN': {'descr': {'addr': 2, 'size': 1, 'offset': 2}}, - 'LOST_COUNT': {'descr': {'addr': 3, 'size': 8}}, - } + self._registers = { + "RESET": {"descr": {"addr": 0, "size": 8, "properties": ["writeonly"]}}, + "VERSION": {"descr": {"addr": 0, "size": 8, "properties": ["ro"]}}, + "ENABLE": {"descr": {"addr": 2, "size": 1, "offset": 0}}, + "EXT_TIMESTAMP": {"descr": {"addr": 2, "size": 1, "offset": 1}}, + "ENABLE_EXTERN": {"descr": {"addr": 2, "size": 1, "offset": 2}}, + "LOST_COUNT": {"descr": {"addr": 3, "size": 8}}, + } self._require_version = "==2" super(timestamp, self).__init__(intf, conf) @@ -28,5 +28,5 @@ def init(self): super(timestamp, self).init() def reset(self): - '''Soft reset the module.''' + """Soft reset the module.""" self.RESET = 0 diff --git a/basil/HL/tlu.py b/basil/HL/tlu.py index 090a88c4f..287ff7772 100644 --- a/basil/HL/tlu.py +++ b/basil/HL/tlu.py @@ -7,50 +7,50 @@ from basil.HL.RegisterHardwareLayer import RegisterHardwareLayer - trigger_modes = { - 'EXTERNAL': 0, # external trigger - 'NO_HANDSHAKE': 1, # TLU no handshake - 'SIMPLE_HANDSHALKE': 2, # TLU simple handshake - 'DATA_HANDSHAKE': 3 # TLU trigger data handshake + "EXTERNAL": 0, # external trigger + "NO_HANDSHAKE": 1, # TLU no handshake + "SIMPLE_HANDSHALKE": 2, # TLU simple handshake + "DATA_HANDSHAKE": 3, # TLU trigger data handshake } trigger_data_format = { - 'TRIGGER_COUNTER': 0, # trigger number according to TRIGGER_MODE - 'TIMESTAMP': 1, # time stamp only - 'COMBINED': 2, # combined, 15bit time stamp + 16bit trigger number + "TRIGGER_COUNTER": 0, # trigger number according to TRIGGER_MODE + "TIMESTAMP": 1, # time stamp only + "COMBINED": 2, # combined, 15bit time stamp + 16bit trigger number } class tlu(RegisterHardwareLayer): - '''TLU controller interface - ''' - - _registers = {'RESET': {'descr': {'addr': 0, 'size': 8, 'properties': ['writeonly']}}, - 'VERSION': {'descr': {'addr': 0, 'size': 8, 'properties': ['ro']}}, - 'TRIGGER_MODE': {'descr': {'addr': 1, 'size': 2, 'offset': 0}}, - 'TRIGGER_DATA_MSB_FIRST': {'descr': {'addr': 1, 'size': 1, 'offset': 2}}, - 'TRIGGER_ENABLE': {'descr': {'addr': 1, 'size': 1, 'offset': 3}}, - 'USE_EXT_TIMESTAMP': {'descr': {'addr': 1, 'size': 1, 'offset': 4}}, - 'DATA_FORMAT': {'descr': {'addr': 2, 'size': 2, 'offset': 0}}, - 'EN_TLU_RESET_TIMESTAMP': {'descr': {'addr': 2, 'size': 1, 'offset': 5}}, - 'EN_TLU_VETO': {'descr': {'addr': 2, 'size': 1, 'offset': 6}}, - 'TRIGGER_LOW_TIMEOUT': {'descr': {'addr': 3, 'size': 8}}, - 'CURRENT_TLU_TRIGGER_NUMBER': {'descr': {'addr': 4, 'size': 32, 'properties': ['ro']}}, - 'TRIGGER_COUNTER': {'descr': {'addr': 8, 'size': 32}}, - 'LOST_DATA_COUNTER': {'descr': {'addr': 12, 'size': 8, 'properties': ['ro']}}, - 'TRIGGER_SELECT': {'descr': {'addr': 13, 'size': 32}}, - 'TRIGGER_VETO_SELECT': {'descr': {'addr': 17, 'size': 32}}, - 'TRIGGER_INVERT': {'descr': {'addr': 21, 'size': 32}}, - 'MAX_TRIGGERS': {'descr': {'addr': 25, 'size': 32}}, - 'TRIGGER_HANDSHAKE_ACCEPT_WAIT_CYCLES': {'descr': {'addr': 29, 'size': 8}}, - 'HANDSHAKE_BUSY_VETO_WAIT_CYCLES': {'descr': {'addr': 30, 'size': 8}}, - 'TRIGGER_LOW_TIMEOUT_ERROR_COUNTER': {'descr': {'addr': 31, 'size': 8, 'properties': ['ro']}}, - 'TLU_TRIGGER_ACCEPT_ERROR_COUNTER': {'descr': {'addr': 32, 'size': 8, 'properties': ['ro']}}, - 'TRIGGER_THRESHOLD': {'descr': {'addr': 33, 'size': 8}}, - 'SOFT_TRIGGER': {'descr': {'addr': 34, 'size': 8, 'properties': ['writeonly']}}, - 'TRIGGER_DATA_DELAY': {'descr': {'addr': 35, 'size': 8}}} + """TLU controller interface""" + + _registers = { + "RESET": {"descr": {"addr": 0, "size": 8, "properties": ["writeonly"]}}, + "VERSION": {"descr": {"addr": 0, "size": 8, "properties": ["ro"]}}, + "TRIGGER_MODE": {"descr": {"addr": 1, "size": 2, "offset": 0}}, + "TRIGGER_DATA_MSB_FIRST": {"descr": {"addr": 1, "size": 1, "offset": 2}}, + "TRIGGER_ENABLE": {"descr": {"addr": 1, "size": 1, "offset": 3}}, + "USE_EXT_TIMESTAMP": {"descr": {"addr": 1, "size": 1, "offset": 4}}, + "DATA_FORMAT": {"descr": {"addr": 2, "size": 2, "offset": 0}}, + "EN_TLU_RESET_TIMESTAMP": {"descr": {"addr": 2, "size": 1, "offset": 5}}, + "EN_TLU_VETO": {"descr": {"addr": 2, "size": 1, "offset": 6}}, + "TRIGGER_LOW_TIMEOUT": {"descr": {"addr": 3, "size": 8}}, + "CURRENT_TLU_TRIGGER_NUMBER": {"descr": {"addr": 4, "size": 32, "properties": ["ro"]}}, + "TRIGGER_COUNTER": {"descr": {"addr": 8, "size": 32}}, + "LOST_DATA_COUNTER": {"descr": {"addr": 12, "size": 8, "properties": ["ro"]}}, + "TRIGGER_SELECT": {"descr": {"addr": 13, "size": 32}}, + "TRIGGER_VETO_SELECT": {"descr": {"addr": 17, "size": 32}}, + "TRIGGER_INVERT": {"descr": {"addr": 21, "size": 32}}, + "MAX_TRIGGERS": {"descr": {"addr": 25, "size": 32}}, + "TRIGGER_HANDSHAKE_ACCEPT_WAIT_CYCLES": {"descr": {"addr": 29, "size": 8}}, + "HANDSHAKE_BUSY_VETO_WAIT_CYCLES": {"descr": {"addr": 30, "size": 8}}, + "TRIGGER_LOW_TIMEOUT_ERROR_COUNTER": {"descr": {"addr": 31, "size": 8, "properties": ["ro"]}}, + "TLU_TRIGGER_ACCEPT_ERROR_COUNTER": {"descr": {"addr": 32, "size": 8, "properties": ["ro"]}}, + "TRIGGER_THRESHOLD": {"descr": {"addr": 33, "size": 8}}, + "SOFT_TRIGGER": {"descr": {"addr": 34, "size": 8, "properties": ["writeonly"]}}, + "TRIGGER_DATA_DELAY": {"descr": {"addr": 35, "size": 8}}, + } _require_version = "==11" def __init__(self, intf, conf): diff --git a/basil/HL/tti_ql355tp.py b/basil/HL/tti_ql355tp.py index bf85dbb40..491ac5ab7 100644 --- a/basil/HL/tti_ql355tp.py +++ b/basil/HL/tti_ql355tp.py @@ -10,13 +10,11 @@ from basil.HL.RegisterHardwareLayer import HardwareLayer - logger = logging.getLogger(__name__) class ttiQl355tp(HardwareLayer): - ''' HL for the TTi QL355TP. - ''' + """HL for the TTi QL355TP.""" def __init__(self, intf, conf): super(ttiQl355tp, self).__init__(intf, conf) @@ -42,7 +40,7 @@ def read(self): return ret[:-2] def set_enable(self, on, channel=1): - """ channel: 1=OP1, 2=OP2, 3=AUX, ALL=all channels""" + """channel: 1=OP1, 2=OP2, 3=AUX, ALL=all channels""" if isinstance(channel, str): cmd = "OPALL %d" % int(on) elif isinstance(channel, int): @@ -53,7 +51,7 @@ def get_name(self): return self.ask("*IDN?") def get_current(self, channel): - """ channel: 1=OP1, 2=OP2, AUX is not supported""" + """channel: 1=OP1, 2=OP2, AUX is not supported""" ret = self.ask("I%dO?" % channel) if ret[-1] != "A": logger.warning("ttiQl355tp.get_current() format error: %s" % ret) @@ -61,7 +59,7 @@ def get_current(self, channel): return float(ret[:-1]) def get_voltage(self, channel): - """ channel: 1=OP1, 2=OP2, AUX is not supported""" + """channel: 1=OP1, 2=OP2, AUX is not supported""" ret = self.ask("V%dO?" % channel) if ret[-1] != "V": logger.warning("ttiQl355tp.get_voltage() format error: %s" % ret) @@ -69,7 +67,7 @@ def get_voltage(self, channel): return float(ret[:-1]) def get_set_voltage(self, channel): - """ channel: 1=OP1, 2=OP2, AUX is not supported""" + """channel: 1=OP1, 2=OP2, AUX is not supported""" ret = self.ask("V%d?" % channel) if ret[:3] != "V%d " % channel: logger.warning("ttiQl355tp.get_voltage() format error: %s" % ret) @@ -77,7 +75,7 @@ def get_set_voltage(self, channel): return float(ret[3:]) def get_current_limit(self, channel): - """ channel: 1=OP1, 2=OP2, AUX is not supported""" + """channel: 1=OP1, 2=OP2, AUX is not supported""" ret = self.ask("I%d?" % channel) if ret[:3] != "I%d " % channel: logger.warning("ttiQl355tp.get_current_limit() format error: %s" % ret) @@ -85,12 +83,12 @@ def get_current_limit(self, channel): return float(ret[3:]) def set_voltage(self, value, channel=1): - """ channel: 1=OP1, 2=OP2, AUX is not supported""" + """channel: 1=OP1, 2=OP2, AUX is not supported""" cmd = "V%d %f" % (channel, value) self.write(cmd) def set_current_limit(self, value, channel=1): - """ channel: 1=OP1, 2=OP2, AUX is not supported""" + """channel: 1=OP1, 2=OP2, AUX is not supported""" cmd = "I%d %f" % (channel, value) self.write(cmd) diff --git a/basil/HL/weiss_labevent.py b/basil/HL/weiss_labevent.py index 7e7049586..11690490a 100644 --- a/basil/HL/weiss_labevent.py +++ b/basil/HL/weiss_labevent.py @@ -13,12 +13,12 @@ class weissLabEvent(HardwareLayer): - ''' - Driver for Weiss LabEvent T/210/70/5 climate chamber. Commands extracted from - https://github.com/IzaakWN/ClimateChamberMonitor/blob/master/chamber_commands.py - ''' + """ + Driver for Weiss LabEvent T/210/70/5 climate chamber. Commands extracted from + https://github.com/IzaakWN/ClimateChamberMonitor/blob/master/chamber_commands.py + """ - CHAMBER_TYPE = 'LabEvent T/210/70/5' + CHAMBER_TYPE = "LabEvent T/210/70/5" RETURN_CODES = { 1: "Command is accepted and executed.", @@ -27,12 +27,7 @@ class weissLabEvent(HardwareLayer): -8: "Data could not be read!", } - STATUS_CODES = { - 1: 'Test not running (Idle)', - 3: 'Test running', - 4: 'Warnings present', - 8: 'Alarms present' - } + STATUS_CODES = {1: "Test not running (Idle)", 3: "Test running", 4: "Warnings present", 8: "Alarms present"} def __init__(self, intf, conf): super(weissLabEvent, self).__init__(intf, conf) @@ -42,88 +37,95 @@ def init(self): info = self.get_info() if info != self.CHAMBER_TYPE: - raise ValueError("Not the expected climatechamber! Expected '{0}', chamber reported '{1}'.".format(self.CHAMBER_TYPE, info)) + raise ValueError( + "Not the expected climatechamber! Expected '{0}', chamber reported '{1}'.".format( + self.CHAMBER_TYPE, info + ) + ) def query(self, cmd): ret = self._intf.query(cmd, buffer_size=512)[0] - dat = [d.decode('ascii') for d in ret.split(b'\xb6')] + dat = [d.decode("ascii") for d in ret.split(b"\xb6")] code = int(dat[0]) try: data = dat[1] except IndexError: data = None - logger.debug('Return code {0}: {1}'.format(code, self.RETURN_CODES[code])) + logger.debug("Return code {0}: {1}".format(code, self.RETURN_CODES[code])) if code != 1: - logger.error('Return code {0}: {1}'.format(code, self.RETURN_CODES[code])) + logger.error("Return code {0}: {1}".format(code, self.RETURN_CODES[code])) return code, data def _get_feature_status(self, id): - ''' - Installed features: - 1 - Condensation protection - 2 - Not installed - 3 - Not installed - 4 - Compressed air / N2 - 5 - Air Dryer - 6 - Not installed - ''' + """ + Installed features: + 1 - Condensation protection + 2 - Not installed + 3 - Not installed + 4 - Compressed air / N2 + 5 - Air Dryer + 6 - Not installed + """ if id not in range(1, 7): - raise ValueError('Invalid feature id!') + raise ValueError("Invalid feature id!") - feature_name = self.query(b'14010\xb61\xb6' + str(id).encode('ascii'))[1] - feature_status = self.query(b'14003\xb61\xb6' + str(id + 1).encode('ascii'))[1] # For get and set status, id = id + 1 - logger.debug('Feature {0} has status {1}'.format(feature_name, feature_status)) + feature_name = self.query(b"14010\xb61\xb6" + str(id).encode("ascii"))[1] + # For get and set status, id = id + 1 + feature_status = self.query(b"14003\xb61\xb6" + str(id + 1).encode("ascii"))[1] + logger.debug("Feature {0} has status {1}".format(feature_name, feature_status)) return bool(int(feature_status)) def _set_feature_status(self, id, value): - return self.query(b'14001\xb61\xb6' + str(id + 1).encode('ascii') + b'\xb6' + str(int(value)).encode('ascii')) # For get and set status, id = id + 1 + return self.query( + b"14001\xb61\xb6" + str(id + 1).encode("ascii") + b"\xb6" + str(int(value)).encode("ascii") + ) # For get and set status, id = id + 1 def get_info(self): - return self.query(b'99997\xb61\xb61')[1] + return self.query(b"99997\xb61\xb61")[1] def get_status(self): - status_code = int(self.query(b'10012\xb61\xb61')[1]) - status = '{0}: {1}'.format(status_code, self.STATUS_CODES[status_code]) + status_code = int(self.query(b"10012\xb61\xb61")[1]) + status = "{0}: {1}".format(status_code, self.STATUS_CODES[status_code]) return status def start_manual_mode(self): - if not self.query(b'14001\xb61\xb61\xb61')[0] == 1: - logger.error('Could not start manual mode!') + if not self.query(b"14001\xb61\xb61\xb61")[0] == 1: + logger.error("Could not start manual mode!") def stop_manual_mode(self): - if not self.query(b'14001\xb61\xb61\xb60')[0] == 1: - logger.error('Could not stop manual mode!') + if not self.query(b"14001\xb61\xb61\xb60")[0] == 1: + logger.error("Could not stop manual mode!") def get_temperature(self): - return float(self.query(b'11004\xb61\xb61')[1]) + return float(self.query(b"11004\xb61\xb61")[1]) def set_temperature(self, target): - if not self.query(b'11001\xb61\xb61\xb6' + str(target).encode('ascii'))[0] == 1: - logger.error('Could not set temperature!') + if not self.query(b"11001\xb61\xb61\xb6" + str(target).encode("ascii"))[0] == 1: + logger.error("Could not set temperature!") def get_temperature_setpoint(self): - return float(self.query(b'11002\xb61\xb61')[1]) + return float(self.query(b"11002\xb61\xb61")[1]) def get_condensation_protection(self): return self._get_feature_status(1) def set_condensation_protection(self, value): if not self._set_feature_status(1, value)[0] == 1: - logger.error('Could not set condensation protection!') + logger.error("Could not set condensation protection!") def get_compressed_air(self): return self._get_feature_status(4) def set_compressed_air(self, value): if not self._set_feature_status(4, value)[0] == 1: - logger.error('Could not set compressed air / N2!') + logger.error("Could not set compressed air / N2!") def get_air_dryer(self): return self._get_feature_status(5) def set_air_dryer(self, value): if not self._set_feature_status(5, value)[0] == 1: - logger.error('Could not set air dryer!') + logger.error("Could not set air dryer!") diff --git a/basil/HL/weiss_sb22.py b/basil/HL/weiss_sb22.py index 868b820b2..db13c3042 100644 --- a/basil/HL/weiss_sb22.py +++ b/basil/HL/weiss_sb22.py @@ -9,11 +9,10 @@ class weissSB22(HardwareLayer): - - '''Driver for the Weiss SB 22 climate chamber. + """Driver for the Weiss SB 22 climate chamber. A simple protocoll via RS 232 serial port is used with 9600/19200 baud rate and 256 modulo complement check sum. Between the different command a delay of 5 seconds should be set according to the manual, but it works at faster rates. - ''' + """ _ERROR_CODES = { 1: "Power cut", @@ -34,7 +33,7 @@ class weissSB22(HardwareLayer): 16: "Humidity too low", 17: "Humidity water heater", 18: "Test room heater", - 19: "No program memory" + 19: "No program memory", } def __init__(self, intf, conf): @@ -42,76 +41,88 @@ def __init__(self, intf, conf): def init(self): super(weissSB22, self).init() - self.slave_address = self._init['address'] # set the device address - self.min_temp = self._init['min_temp'] # define the minimum temperature one can set, for safety - self.max_temp = self._init['max_temp'] # define the maximum temperature one can set, for safety - self.min_humidity = self._init['min_humidity'] # define the minimum humidity one can set, for safety - self.max_humidity = self._init['max_humidity'] # define the maximum humidity one can set, for safety - self._temperature = self.get_temperature() # tmp variable to store last value set, needed since always temp and humidity has to be set - self._humidity = self.get_humidity() # tmp variable to store last value set, needed since always temp and humidity has to be set + self.slave_address = self._init["address"] # set the device address + self.min_temp = self._init["min_temp"] # define the minimum temperature one can set, for safety + self.max_temp = self._init["max_temp"] # define the maximum temperature one can set, for safety + self.min_humidity = self._init["min_humidity"] # define the minimum humidity one can set, for safety + self.max_humidity = self._init["max_humidity"] # define the maximum humidity one can set, for safety + # tmp variable to store last value set, needed since always temp and humidity has to be set + self._temperature = self.get_temperature() + # tmp variable to store last value set, needed since always temp and humidity has to be set + self._humidity = self.get_humidity() self._digital_ch = self.get_digital_ch() # the digital channels define the functions (humiditiy control, dew protection, ..., in binary coding, 1000000000000000 is temperature control only) def get_temperature(self): - self.write('%d?' % self.slave_address) + self.write("%d?" % self.slave_address) answer = self.read() return float(answer[3:8]) def get_temperature_target(self): - self.write('%d?' % self.slave_address) + self.write("%d?" % self.slave_address) answer = self.read() return float(answer[23:28]) def get_humidity(self): - self.write('%d?' % self.slave_address) + self.write("%d?" % self.slave_address) answer = self.read() return int(answer[9:11]) def get_humidity_target(self): - self.write('%d?' % self.slave_address) + self.write("%d?" % self.slave_address) answer = self.read() return int(answer[29:31]) def get_digital_ch(self): - self.write('%d?' % self.slave_address) + self.write("%d?" % self.slave_address) answer = self.read() return answer[32:48] - def set_digital_ch(self, channel, value=1): # Set channel to 0 or 1, functionality acording to manual, Channel is a normal decimal int starting from 1 + def set_digital_ch( + self, channel, value=1 + ): # Set channel to 0 or 1, functionality acording to manual, Channel is a normal decimal int starting from 1 actual_channels = list(self.get_digital_ch()) if value > 0: - actual_channels[channel - 1] = '1' + actual_channels[channel - 1] = "1" else: - actual_channels[channel - 1] = '0' + actual_channels[channel - 1] = "0" actual_channels = "".join(actual_channels) self._digital_ch = actual_channels - msg = '%dT%05.1fF%02dR%s' % (self.slave_address, self._temperature, self._humidity, self._digital_ch) + msg = "%dT%05.1fF%02dR%s" % (self.slave_address, self._temperature, self._humidity, self._digital_ch) self.write(msg) self.check_for_errors(self.read()) def set_temperature(self, temperature): if temperature < self.min_temp: - raise RuntimeWarning('Set temperature %f is lower than minimum allowed temperature %f' % (temperature, self.min_temp)) + raise RuntimeWarning( + "Set temperature %f is lower than minimum allowed temperature %f" % (temperature, self.min_temp) + ) if temperature > self.max_temp: - raise RuntimeWarning('Set temperature %f is higher than maximum allowed temperature %f' % (temperature, self.max_temp)) + raise RuntimeWarning( + "Set temperature %f is higher than maximum allowed temperature %f" % (temperature, self.max_temp) + ) self._temperature = temperature - msg = '%dT%05.1fF%02dR%s' % (self.slave_address, self._temperature, self._humidity, self._digital_ch) + msg = "%dT%05.1fF%02dR%s" % (self.slave_address, self._temperature, self._humidity, self._digital_ch) self.write(msg) self.check_for_errors(self.read()) def set_humidity(self, humidity): if humidity < self.min_humidity: - raise RuntimeWarning('Set humidity %f is lower than minimum allowed humidity %f' % (humidity, self.min_humidity)) + raise RuntimeWarning( + "Set humidity %f is lower than minimum allowed humidity %f" % (humidity, self.min_humidity) + ) if humidity > self.max_humidity: - raise RuntimeWarning('Set humidity %f is higher than maximum allowed humidity %f' % (humidity, self.max_humidity)) + raise RuntimeWarning( + "Set humidity %f is higher than maximum allowed humidity %f" % (humidity, self.max_humidity) + ) self._humidity = humidity - msg = '%dT%05.1fF%02dR%s' % (self.slave_address, self._temperature, self._humidity, self._digital_ch) + msg = "%dT%05.1fF%02dR%s" % (self.slave_address, self._temperature, self._humidity, self._digital_ch) self.write(msg) self.check_for_errors(self.read()) def write(self, value): - msg = '\x02' + value # msg has STX at the beginning + msg = "\x02" + value # msg has STX at the beginning msg += self._calc_crc(msg) # CRC for all characters including STX - msg += '\x03' # msg has ETX at the end + msg += "\x03" # msg has ETX at the end self._intf.write(str(msg)) def read(self): @@ -120,18 +131,18 @@ def read(self): def check_for_errors(self, answer): if len(answer) > 6: # error codes are not in the ackowledge strings - error_code = int(answer[20:22]) if answer[20:22] != '--' else 0 + error_code = int(answer[20:22]) if answer[20:22] != "--" else 0 if error_code > 0: - raise RuntimeError('Climate chamber error %d: %s' % (error_code, self._ERROR_CODES[error_code])) + raise RuntimeError("Climate chamber error %d: %s" % (error_code, self._ERROR_CODES[error_code])) else: # ack answer - if answer[2] != '\x06': - raise RuntimeError('Data transmission not ackowledged') + if answer[2] != "\x06": + raise RuntimeError("Data transmission not ackowledged") if int(answer[1]) != self.slave_address: - raise RuntimeError('Climate chamber address %s instead of %d' % (answer[1], self.slave_address)) + raise RuntimeError("Climate chamber address %s instead of %d" % (answer[1], self.slave_address)) def _calc_crc(self, msg): ASCII = "0123456789ABCDEF" - mod_256 = (-(sum(i for i in msg) % 256) & 0xFF) + mod_256 = -(sum(i for i in msg) % 256) & 0xFF lword = (mod_256 & 0xF0) >> 4 hword = mod_256 & 0x0F return ASCII[lword] + ASCII[hword] diff --git a/basil/RL/FunctionalRegister.py b/basil/RL/FunctionalRegister.py index 89e413040..75769c313 100644 --- a/basil/RL/FunctionalRegister.py +++ b/basil/RL/FunctionalRegister.py @@ -9,6 +9,5 @@ class FunctionalRegister(RegisterLayer): - def __init__(self, driver, conf): RegisterLayer.__init__(self, driver, conf) diff --git a/basil/RL/RegisterLayer.py b/basil/RL/RegisterLayer.py index a51ae2e53..b1c67157f 100644 --- a/basil/RL/RegisterLayer.py +++ b/basil/RL/RegisterLayer.py @@ -33,15 +33,15 @@ def __getattr__(self, name): def method(*args, **kargs): arg = () - if 'arg_names' in self._conf: + if "arg_names" in self._conf: for i in range(len(args)): - kargs[self._conf['arg_names'][i]] = args[i] + kargs[self._conf["arg_names"][i]] = args[i] else: arg = args - if 'arg_add' in self._conf: - for argn in self._conf['arg_add']: - kargs[argn] = self._conf['arg_add'][argn] + if "arg_add" in self._conf: + for argn in self._conf["arg_add"]: + kargs[argn] = self._conf["arg_add"][argn] return attr(*arg, **kargs) diff --git a/basil/RL/StdRegister.py b/basil/RL/StdRegister.py index e053d13e0..f669f4f67 100644 --- a/basil/RL/StdRegister.py +++ b/basil/RL/StdRegister.py @@ -7,41 +7,47 @@ import array +from six import integer_types + from basil.RL.RegisterLayer import RegisterLayer -from basil.utils.BitLogic import BitLogic from basil.utils import utils -from six import integer_types +from basil.utils.BitLogic import BitLogic class StdRegister(RegisterLayer): def __init__(self, driver, conf): super(StdRegister, self).__init__(driver, conf) - self._size = conf['size'] + self._size = conf["size"] self._fields = dict() self._bv = None self._fields_conf = dict() - if 'fields' in self._conf: - for field in self._conf['fields']: - - if field['offset'] + 1 < field['size']: - raise ValueError("Register " + self._conf['name'] + ":" + field['name'] + ": Invalid offset value. Specify MSB position.") - - if 'repeat' in field: + if "fields" in self._conf: + for field in self._conf["fields"]: + if field["offset"] + 1 < field["size"]: + raise ValueError( + "Register " + + self._conf["name"] + + ":" + + field["name"] + + ": Invalid offset value. Specify MSB position." + ) + + if "repeat" in field: reg_list = [] - for _ in range(field['repeat']): + for _ in range(field["repeat"]): reg = StdRegister(None, field) reg_list.append(reg) - self._fields[field['name']] = reg_list + self._fields[field["name"]] = reg_list else: - bv = BitLogic(field['size']) - self._fields[field['name']] = bv + bv = BitLogic(field["size"]) + self._fields[field["name"]] = bv - self._fields_conf[field['name']] = field + self._fields_conf[field["name"]] = field # set default if "default" in field: - self[field['name']] = field['default'] - self._bv = BitLogic(self._conf['size']) + self[field["name"]] = field["default"] + self._bv = BitLogic(self._conf["size"]) def init(self): super(StdRegister, self).init() @@ -59,13 +65,13 @@ def __getitem__(self, items): def __setitem__(self, key, value): if isinstance(key, slice): reg = self._construct_reg() - reg[key.start:key.stop] = value + reg[key.start : key.stop] = value self._deconstruct_reg(reg) elif isinstance(key, str): - self._fields[key][len(self._fields[key]) - 1:0] = value - if 'bit_order' in self._get_field_config(key): + self._fields[key][len(self._fields[key]) - 1 : 0] = value + if "bit_order" in self._get_field_config(key): new_val = BitLogic(len(self._fields[key])) - for i, bit in enumerate(self._get_field_config(key)['bit_order']): + for i, bit in enumerate(self._get_field_config(key)["bit_order"]): new_val[len(self._fields[key]) - 1 - i] = self._fields[key][bit] self._fields[key] = new_val elif isinstance(key, integer_types): @@ -76,21 +82,21 @@ def __setitem__(self, key, value): raise TypeError("Invalid argument type.") def __len__(self): - return self._conf['size'] + return self._conf["size"] def __str__(self): fields = dict() full = dict() reg = self._construct_reg() - full[self._conf['name']] = str(len(reg)) + 'b' + str(reg[:]) + full[self._conf["name"]] = str(len(reg)) + "b" + str(reg[:]) for field in self._fields: - if 'repeat' in self._get_field_config(field): + if "repeat" in self._get_field_config(field): for i, sub_reg in enumerate(self._fields[field]): - fields[str(field) + '[' + str(i) + ']'] = str(sub_reg) + fields[str(field) + "[" + str(i) + "]"] = str(sub_reg) else: - fields[field] = str(len(self._fields[field])) + 'b' + str(self._fields[field][:]) + fields[field] = str(len(self._fields[field])) + "b" + str(self._fields[field][:]) if self._fields: return str([full, fields]) @@ -124,36 +130,34 @@ def read(self): raise NotImplementedError("read() not implemented") def _construct_reg(self): - for field in self._fields: - offs = self._fields_conf[field]['offset'] + offs = self._fields_conf[field]["offset"] - if 'repeat' in self._fields_conf[field]: + if "repeat" in self._fields_conf[field]: for i, sub_field in enumerate(self._fields[field]): - bvstart = offs - i * self._get_field_config(field)['size'] + bvstart = offs - i * self._get_field_config(field)["size"] bvstop = bvstart - len(sub_field._construct_reg()) + 1 -# self._bv[bvstart:bvstop] = sub_field._construct_reg() + # self._bv[bvstart:bvstop] = sub_field._construct_reg() self._bv.set_slice_ba(bvstart, bvstop, sub_field._construct_reg()) else: - bvsize = len(self._fields[field]) bvstart = offs bvstop = offs - bvsize + 1 -# self._bv[bvstart:bvstop] = self._fields[field] + # self._bv[bvstart:bvstop] = self._fields[field] self._bv.set_slice_ba(bvstart, bvstop, self._fields[field]) return self._bv def _deconstruct_reg(self, reg): for field in self._fields: - offs = self._get_field_config(field)['offset'] - bvsize = self._get_field_config(field)['size'] + offs = self._get_field_config(field)["offset"] + bvsize = self._get_field_config(field)["size"] bvstart = offs bvstop = offs - bvsize + 1 - if 'repeat' in self._get_field_config(field): - size = self._get_field_config(field)['size'] + if "repeat" in self._get_field_config(field): + size = self._get_field_config(field)["size"] for i, ifield in enumerate(self._fields[field]): - ifield.set(reg[bvstart - size * i:bvstop - size * i]) + ifield.set(reg[bvstart - size * i : bvstop - size * i]) else: self._fields[field] = reg[bvstart:bvstop] @@ -171,8 +175,8 @@ def setall(self, value): def frombytes(self, value): bl_value = BitLogic() - bl_value.frombytes(utils.tobytes(array.array('B', value)[::-1])) - self._deconstruct_reg(bl_value[self._conf['size']:]) + bl_value.frombytes(utils.tobytes(array.array("B", value)[::-1])) + self._deconstruct_reg(bl_value[self._conf["size"] :]) def get_configuration(self): fields = dict() @@ -180,7 +184,7 @@ def get_configuration(self): reg = self._construct_reg() for field in self._fields: - if 'repeat' in self._get_field_config(field): + if "repeat" in self._get_field_config(field): rep_field = [] for sub_reg in self._fields[field]: rep_field.append(sub_reg.get_configuration()) @@ -197,7 +201,7 @@ def get_configuration(self): def set_configuration(self, conf): for name, value in conf.items(): if name in self._fields: - if 'repeat' in self._fields_conf[name]: + if "repeat" in self._fields_conf[name]: for i, rep_val_dict in enumerate(value): for rep_name, rep_value in rep_val_dict.items(): self[name][i][rep_name] = rep_value diff --git a/basil/RL/TrackRegister.py b/basil/RL/TrackRegister.py index ed38e90bf..1f5679088 100644 --- a/basil/RL/TrackRegister.py +++ b/basil/RL/TrackRegister.py @@ -6,37 +6,35 @@ # from bitarray import bitarray +from six.moves import range -from basil.utils import utils from basil.RL.RegisterLayer import RegisterLayer - -from six.moves import range +from basil.utils import utils class TrackRegister(RegisterLayer): - '''Tracking register - ''' + """Tracking register""" def __init__(self, driver, conf): RegisterLayer.__init__(self, driver, conf) self._tracks = dict() - for track in self._conf['tracks']: + for track in self._conf["tracks"]: bv = bitarray(self._conf["seq_size"]) bv.setall(False) - self._tracks[track['name']] = bv + self._tracks[track["name"]] = bv def __getitem__(self, items): if items in self._tracks: return self._tracks[items] else: - raise ValueError('Item does not exist') + raise ValueError("Item does not exist") def __setitem__(self, key, value): self._tracks[key] = value def clear(self): - 'Clear tracks in memory - all zero' + "Clear tracks in memory - all zero" for track in self._tracks: self._tracks[track].setall(False) @@ -46,18 +44,18 @@ def write(self, size=-1): bv = bitarray(self._conf["seq_width"] * size) for i in range(size): - for track in self._conf['tracks']: + for track in self._conf["tracks"]: bit = 0 if self._conf["seq_width"] >= 8: - bit = i * self._conf["seq_width"] + self._conf["seq_width"] - 1 - track['position'] + bit = i * self._conf["seq_width"] + self._conf["seq_width"] - 1 - track["position"] elif self._conf["seq_width"] == 4: if i % 2 == 0: - bit = (i + 1) * self._conf["seq_width"] + self._conf["seq_width"] - 1 - track['position'] + bit = (i + 1) * self._conf["seq_width"] + self._conf["seq_width"] - 1 - track["position"] else: - bit = (i - 1) * self._conf["seq_width"] + self._conf["seq_width"] - 1 - track['position'] + bit = (i - 1) * self._conf["seq_width"] + self._conf["seq_width"] - 1 - track["position"] else: raise NotImplementedError("To be implemented.") - bv[bit] = self._tracks[track['name']][i] + bv[bit] = self._tracks[track["name"]][i] ba = utils.bitarray_to_byte_array(bv) ba = ba[::-1] diff --git a/basil/TL/Dummy.py b/basil/TL/Dummy.py index 390b2000e..ff0367961 100644 --- a/basil/TL/Dummy.py +++ b/basil/TL/Dummy.py @@ -5,8 +5,8 @@ # ------------------------------------------------------------ # -import logging import array +import logging from basil.TL.SiTransferLayer import SiTransferLayer @@ -14,8 +14,7 @@ class Dummy(SiTransferLayer): - '''Dummy device - ''' + """Dummy device""" def __init__(self, conf): self.mem = {} # dummy memory dict, keys are addresses, values are of type int @@ -23,18 +22,17 @@ def __init__(self, conf): def init(self): super(Dummy, self).init() - logger.debug( - "Dummy SiTransferLayer.init configuration: %s" % str(self._conf)) - if 'mem' in self._init: - if isinstance(self._init['mem'], dict): - self.mem = self._init['mem'] + logger.debug("Dummy SiTransferLayer.init configuration: %s" % str(self._conf)) + if "mem" in self._init: + if isinstance(self._init["mem"], dict): + self.mem = self._init["mem"] else: - self.mem = {i: j for i, j in enumerate(self._init['mem'])} + self.mem = {i: j for i, j in enumerate(self._init["mem"])} else: self.mem = {} def write(self, addr, data): - '''Write to dummy memory + """Write to dummy memory Parameters ---------- @@ -46,14 +44,13 @@ def write(self, addr, data): Returns ------- nothing - ''' - logger.debug( - "Dummy SiTransferLayer.write addr: %s data: %s" % (hex(addr), data)) + """ + logger.debug("Dummy SiTransferLayer.write addr: %s data: %s" % (hex(addr), data)) for curr_addr, d in enumerate(data, start=addr): - self.mem[curr_addr] = array.array('B', [d])[0] # write int + self.mem[curr_addr] = array.array("B", [d])[0] # write int def read(self, addr, size): - ''' + """ Parameters ---------- addr : int @@ -65,6 +62,8 @@ def read(self, addr, size): ------- array : array Data (byte array) read from memory. Returns 0 for each byte if it hasn't been written to. - ''' + """ logger.debug("Dummy SiTransferLayer.read addr: %s size: %s" % (hex(addr), size)) - return array.array('B', [self.mem[curr_addr] if curr_addr in self.mem else 0 for curr_addr in range(addr, addr + size)]) + return array.array( + "B", [self.mem[curr_addr] if curr_addr in self.mem else 0 for curr_addr in range(addr, addr + size)] + ) diff --git a/basil/TL/SensirionSensorBridge.py b/basil/TL/SensirionSensorBridge.py index da82a3a0c..15d8ea5b9 100644 --- a/basil/TL/SensirionSensorBridge.py +++ b/basil/TL/SensirionSensorBridge.py @@ -7,11 +7,12 @@ import logging -from basil.TL.TransferLayer import TransferLayer - -from sensirion_shdlc_driver import ShdlcSerialPort, ShdlcConnection +from sensirion_shdlc_driver import ShdlcConnection, ShdlcSerialPort from sensirion_shdlc_sensorbridge import SensorBridgePort, SensorBridgeShdlcDevice from sensirion_shdlc_sensorbridge.device_errors import SensorBridgeI2cTimeoutError + +from basil.TL.TransferLayer import TransferLayer + TimeoutError = SensorBridgeI2cTimeoutError # Requires 'sensirion_shdlc_sensorbridge' @@ -19,10 +20,10 @@ class SensirionSensorBridge(TransferLayer): - ''' + """ Driver for Sensirion Sensor Bridge using the official SHDLC drivers of Sensirion. The Sensirion Sensor Bridge is connected via USB and allows communication to two I2C ports. - ''' + """ bridge_ports = { "one": SensorBridgePort.ONE, @@ -36,8 +37,8 @@ def __init__(self, conf): def init(self): super(SensirionSensorBridge, self).init() - self.port = self._init['port'] - self.baudrate = self._init.get('baudrate', 460800) + self.port = self._init["port"] + self.baudrate = self._init.get("baudrate", 460800) self.ser = ShdlcSerialPort(port=self.port, baudrate=self.baudrate) @@ -49,7 +50,7 @@ def setup_i2c_device(self, bridge_port=SensorBridgePort.ONE, voltage=3.3, freque return device def disable_i2c_device(self, device, bridge_port=SensorBridgePort.ONE): - if hasattr(self, 'device'): + if hasattr(self, "device"): device.switch_supply_off(bridge_port) def print_i2c_device_information(self, device): @@ -59,18 +60,18 @@ def print_i2c_device_information(self, device): logger.info("Version: {}".format(device.get_version())) def read_i2c(self, device, port, address, command, read_n_bytes=0, timeout_us=100e3): - rx_data = device.transceive_i2c(port, address=address, tx_data=command, - rx_length=read_n_bytes, timeout_us=timeout_us) + rx_data = device.transceive_i2c( + port, address=address, tx_data=command, rx_length=read_n_bytes, timeout_us=timeout_us + ) return rx_data def write_i2c(self, device, port, address, command): - device.transceive_i2c(port, address=address, - rx_length=0, tx_data=command, timeout_us=0) + device.transceive_i2c(port, address=address, rx_length=0, tx_data=command, timeout_us=0) def __del__(self): self.close() def close(self): super(SensirionSensorBridge, self).close() - if hasattr(self, 'ser'): + if hasattr(self, "ser"): self.ser.close() diff --git a/basil/TL/Serial.py b/basil/TL/Serial.py index 9eba61057..8b42058cf 100644 --- a/basil/TL/Serial.py +++ b/basil/TL/Serial.py @@ -14,34 +14,35 @@ class Serial(TransferLayer): - '''Transfer layer of serial device using the pySerial module. - ''' + """Transfer layer of serial device using the pySerial module.""" def __init__(self, conf): super(Serial, self).__init__(conf) self._port = None def init(self): - ''' + """ Initialize serial device. Parameters of serial.Serial: http://pyserial.sourceforge.net/pyserial_api.html Plus termination string parameter eol - ''' + """ super(Serial, self).init() - self.read_termination = self._init.get('read_termination', None) - self.write_termination = self._init.get('write_termination', self.read_termination) + self.read_termination = self._init.get("read_termination", None) + self.write_termination = self._init.get("write_termination", self.read_termination) try: - self.read_termination = bytes(self.read_termination, 'utf-8') - self.write_termination = bytes(self.write_termination, 'utf-8') + self.read_termination = bytes(self.read_termination, "utf-8") + self.write_termination = bytes(self.write_termination, "utf-8") except TypeError as e: logger.debug(e) - self.timeout = self._init.get('timeout', None) # timeout of 0 returns immediately + self.timeout = self._init.get("timeout", None) # timeout of 0 returns immediately # make interface compatible with other transfer layes (visa) if "baud_rate" in self._init.keys(): self._init["baudrate"] = self._init.pop("baud_rate") - self._port = serial.Serial(**{key: value for key, value in self._init.items() if key not in ("read_termination", "write_termination")}) + self._port = serial.Serial( + **{key: value for key, value in self._init.items() if key not in ("read_termination", "write_termination")} + ) def close(self): super(Serial, self).close() @@ -50,12 +51,12 @@ def close(self): def write(self, data): if self.write_termination is None: try: - self._port.write(bytes(data, 'utf-8')) + self._port.write(bytes(data, "utf-8")) except TypeError: # Python 2.7 self._port.write(bytes(data)) else: try: - self._port.write(bytes(data, 'utf-8') + self.write_termination) + self._port.write(bytes(data, "utf-8") + self.write_termination) except TypeError: # Python 2.7 self._port.write(bytes(data + self.write_termination)) @@ -66,7 +67,10 @@ def read(self, size=None): def query(self, data): if self._port.inWaiting(): - logger.warning("Found %d bytes in the input buffer of interface %s which will be flushed" % (self._port.inWaiting(), self.name)) + logger.warning( + "Found %d bytes in the input buffer of interface %s which will be flushed" + % (self._port.inWaiting(), self.name) + ) self._port.flushInput() self.write(data) return self._readline() @@ -77,7 +81,9 @@ def _readline(self): # http://stackoverflow.com/questions/16470903/pyserial-2-6 # 2. termination of "" will return immediately # 3. timeout of None will never return if not self.read_termination and self.timeout is None: - raise RuntimeError('Requested serial read will not terminate due to missing termination string and missing timeout') + raise RuntimeError( + "Requested serial read will not terminate due to missing termination string and missing timeout" + ) data = bytearray() count = len(self.read_termination) if self.read_termination else 0 @@ -86,4 +92,4 @@ def _readline(self): # http://stackoverflow.com/questions/16470903/pyserial-2-6 data += character if not character: break - return data.decode('utf-8', errors='ignore') + return data.decode("utf-8", errors="ignore") diff --git a/basil/TL/SiSim.py b/basil/TL/SiSim.py index 0964115a3..3f24b2e42 100644 --- a/basil/TL/SiSim.py +++ b/basil/TL/SiSim.py @@ -9,20 +9,24 @@ # Verilog testbenches in Python. # -import socket import array -import time import logging +import socket +import time from threading import Lock from basil.TL.SiTransferLayer import SiTransferLayer -from basil.utils.sim.Protocol import WriteRequest, ReadRequest, ReadResponse, PickleInterface +from basil.utils.sim.Protocol import ( + PickleInterface, + ReadRequest, + ReadResponse, + WriteRequest, +) logger = logging.getLogger(__name__) class SiSim(SiTransferLayer): - def __init__(self, conf): super(SiSim, self).__init__(conf) self._sock = None @@ -31,18 +35,18 @@ def init(self): super(SiSim, self).init() self._sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - host = 'localhost' - if 'host' in self._init.keys(): - host = self._init['host'] + host = "localhost" + if "host" in self._init.keys(): + host = self._init["host"] port = 12345 - if 'port' in self._init.keys(): - port = self._init['port'] + if "port" in self._init.keys(): + port = self._init["port"] # try few times for simulator to setup try_cnt = 120 - if 'timeout' in self._init.keys(): - try_cnt = self._init['timeout'] + if "timeout" in self._init.keys(): + try_cnt = self._init["timeout"] while self._sock.connect_ex((host, port)) != 0: logger.debug("Trying to connect to simulator.") @@ -56,7 +60,7 @@ def init(self): self._lock = Lock() def write(self, addr, data): - ad = array.array('B', data) + ad = array.array("B", data) req = WriteRequest(addr, ad) with self._lock: @@ -71,7 +75,7 @@ def read(self, addr, size): if not isinstance(resp, ReadResponse): raise ValueError("Communication error with Simulation: got %s" % repr(resp)) - return array.array('B', resp.data) + return array.array("B", resp.data) def close(self): super(SiSim, self).close() diff --git a/basil/TL/SiTcp.py b/basil/TL/SiTcp.py index 71f909079..41712633e 100644 --- a/basil/TL/SiTcp.py +++ b/basil/TL/SiTcp.py @@ -8,27 +8,26 @@ # import logging -import socket +import re import select +import socket import struct -import re from array import array -from threading import Thread from threading import RLock as Lock +from threading import Thread from time import time -from basil.TL.SiTransferLayer import SiTransferLayer from basil.HL.sram_fifo import sram_fifo - +from basil.TL.SiTransferLayer import SiTransferLayer # Fake SRAM version to ensure compatibility with the simulation -sram_fifo_version = int(re.findall(r'\d+', sram_fifo._require_version)[-1]) +sram_fifo_version = int(re.findall(r"\d+", sram_fifo._require_version)[-1]) logger = logging.getLogger(__name__) class SiTcp(SiTransferLayer): - '''SiTcp transport layer.transport + """SiTcp transport layer.transport UDP (RBCP) Header+Data @@ -120,9 +119,10 @@ class SiTcp(SiTransferLayer): TCP to BUS reset sequence (in case of status invalid): 65535 * 0xff + 6 * 0x00 - ''' + """ + # UDP(RBCP) interface - RBCP_VER = 0xff + RBCP_VER = 0xFF RBCP_CMD_WR = 0x80 RBCP_CMD_RD = 0xC0 RBCP_MAX_SIZE = 255 # bytes @@ -146,7 +146,7 @@ def __init__(self, conf): def reset(self): with self._tcp_lock: - self._tcp_read_buff = array('B') + self._tcp_read_buff = array("B") def reset_fifo(self): with self._tcp_lock: @@ -158,33 +158,34 @@ def reset_fifo(self): def init(self): super(SiTcp, self).init() self.reset() - if 'ip' not in self._init: # check for IP address - raise ValueError('Parameter \'ip\' missing.') - if 'udp_port' not in self._init: # check for UDP port - raise ValueError('Parameter \'udp_port\' missing.') - connect_timeout = float(self._init.get('connect_timeout', 5.0)) # in seconds + if "ip" not in self._init: # check for IP address + raise ValueError("Parameter 'ip' missing.") + if "udp_port" not in self._init: # check for UDP port + raise ValueError("Parameter 'udp_port' missing.") + connect_timeout = float(self._init.get("connect_timeout", 5.0)) # in seconds self._sock_udp = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) self._sock_udp.settimeout(connect_timeout) - self._sock_udp.connect((self._init['ip'], self._init['udp_port'])) + self._sock_udp.connect((self._init["ip"], self._init["udp_port"])) self._sock_udp.settimeout(None) # https://stackoverflow.com/questions/3432102/python-socket-connection-timeout # using select to monitor socket status, therefore the socket is set to blocking (default) self._sock_udp.setblocking(0) # start readout thread if TCP connection is set - if 'tcp_connection' in self._init and self._init['tcp_connection']: - if 'tcp_port' not in self._init: - raise ValueError('Parameter \'tcp_port\' missing.') + if "tcp_connection" in self._init and self._init["tcp_connection"]: + if "tcp_port" not in self._init: + raise ValueError("Parameter 'tcp_port' missing.") self._sock_tcp = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self._sock_tcp.settimeout(connect_timeout) - self._sock_tcp.connect((self._init['ip'], self._init['tcp_port'])) - self._sock_tcp.settimeout(None) # https://stackoverflow.com/questions/3432102/python-socket-connection-timeout + self._sock_tcp.connect((self._init["ip"], self._init["tcp_port"])) + # https://stackoverflow.com/questions/3432102/python-socket-connection-timeout + self._sock_tcp.settimeout(None) # using select to monitor socket status, therefore the socket is set to blocking (default) self._sock_tcp.setblocking(0) - self._tcp_readout_thread = Thread(target=self._tcp_readout, name='TcpReadoutThread', kwargs={}) + self._tcp_readout_thread = Thread(target=self._tcp_readout, name="TcpReadoutThread", kwargs={}) self._tcp_readout_thread.daemon = True # exiting program even when thread is alive self._stop = False self._tcp_readout_thread.start() - if 'tcp_to_bus' in self._init and self._init['tcp_to_bus']: + if "tcp_to_bus" in self._init and self._init["tcp_to_bus"]: self._reset_tcp_to_bus() else: self._sock_tcp = None @@ -196,7 +197,7 @@ def _write_single(self, addr, data): self.RBCP_ID = 0 else: self.RBCP_ID += 1 - request = array('B', struct.pack('>BBBBI', self.RBCP_VER, self.RBCP_CMD_WR, self.RBCP_ID, len(data), addr)) + request = array("B", struct.pack(">BBBBI", self.RBCP_VER, self.RBCP_CMD_WR, self.RBCP_ID, len(data), addr)) request += data while True: rlist, _, _ = select.select([self._sock_udp], [], [], 0.0) @@ -205,65 +206,79 @@ def _write_single(self, addr, data): # remaining meassge data is lost. rbcp_recv_pending = self._sock_udp.recv(3) if len(rbcp_recv_pending) == 3: - rbcp_pending_status = array('B', rbcp_recv_pending) - logger.warning('SiTcp:_write_single - Pending RBCP data before send - RBCP message ID: current: %d, read: %d' % (self.RBCP_ID, rbcp_pending_status[2])) + rbcp_pending_status = array("B", rbcp_recv_pending) + logger.warning( + "SiTcp:_write_single - Pending RBCP data before send - RBCP message ID: current: %d, read: %d" + % (self.RBCP_ID, rbcp_pending_status[2]) + ) else: - logger.warning('SiTcp:_write_single - Pending data before send') + logger.warning("SiTcp:_write_single - Pending data before send") else: break retry_write_cnt += 1 _, wlist, _ = select.select([], [self._sock_udp], [], self.UDP_TIMEOUT) if not wlist and retry_write_cnt <= self.UDP_RETRANSMIT_CNT: - logger.warning('SiTcp:_write_single - Write timeout - Retry...') + logger.warning("SiTcp:_write_single - Write timeout - Retry...") continue elif not wlist: - raise IOError('SiTcp:_write_single - Write timeout') + raise IOError("SiTcp:_write_single - Write timeout") else: total_sent = self._sock_udp.send(request) if total_sent != len(request): - raise IOError('SiTcp:_write_single - Socket broken') + raise IOError("SiTcp:_write_single - Socket broken") retry_read_cnt = 0 while True: retry_read_cnt += 1 rlist, _, _ = select.select([self._sock_udp], [], [], self.UDP_TIMEOUT) if not rlist: if retry_read_cnt <= self.UDP_RETRANSMIT_CNT: - logger.warning('SiTcp:_write_single - Read timeout - Retry...') + logger.warning("SiTcp:_write_single - Read timeout - Retry...") continue elif retry_write_cnt <= self.UDP_RETRANSMIT_CNT: - logger.warning('SiTcp:_write_single - Read timeout - Retry write...') + logger.warning("SiTcp:_write_single - Read timeout - Retry write...") break else: - raise IOError('SiTcp:_write_single - Read timeout') + raise IOError("SiTcp:_write_single - Read timeout") else: # Recv buffer needs to be longer than message size, # otherwise remaining message data is not read out and is lost. rbcp_recv = self._sock_udp.recv(1024) if len(rbcp_recv) < 8: - raise IOError('SiTcp:_write_single - Invalid RBCP message') - rbcp_status = array('B', rbcp_recv[:8]) + raise IOError("SiTcp:_write_single - Invalid RBCP message") + rbcp_status = array("B", rbcp_recv[:8]) if rbcp_status[2] != self.RBCP_ID: if retry_read_cnt <= self.UDP_RETRANSMIT_CNT: - logger.warning('SiTcp:_write_single - Wrong RBCP message ID - Retry...') + logger.warning("SiTcp:_write_single - Wrong RBCP message ID - Retry...") continue elif retry_write_cnt <= self.UDP_RETRANSMIT_CNT: - logger.warning('SiTcp:_write_single - Wrong RBCP message ID - Retry write...') + logger.warning("SiTcp:_write_single - Wrong RBCP message ID - Retry write...") break else: - raise IOError('SiTcp:_write_single - Wrong RBCP message ID') + raise IOError("SiTcp:_write_single - Wrong RBCP message ID") if rbcp_status[0] != self.RBCP_VER: - raise IOError('SiTcp:_write_single - Invalid RBCP version') - if (0x0f & rbcp_status[1]) != 0x8: - raise IOError('SiTcp:_write_single - RBCP bus error') + raise IOError("SiTcp:_write_single - Invalid RBCP version") + if (0x0F & rbcp_status[1]) != 0x8: + raise IOError("SiTcp:_write_single - RBCP bus error") if rbcp_status[3] != request[3]: - raise IOError('SiTcp:_write_single - RBCP size mismatch - expected: %d, read: %d' % (request[3], rbcp_status[3])) + raise IOError( + "SiTcp:_write_single - RBCP size mismatch - expected: %d, read: %d" + % (request[3], rbcp_status[3]) + ) if rbcp_status[4:8] != request[4:8]: - raise IOError('SiTcp:_write_single - RBCP address mismatch - expected: %d, read: %d' % (request[4:8], rbcp_status[4:8])) + raise IOError( + "SiTcp:_write_single - RBCP address mismatch - expected: %d, read: %d" + % (request[4:8], rbcp_status[4:8]) + ) if len(rbcp_recv) != len(request): - raise IOError('SiTcp:_write_single - Invalid RBCP message byte size - expected bytes: %d, received bytes: %d' % (len(request), len(rbcp_recv))) - rbcp_data = array('B', rbcp_recv[8:]) + raise IOError( + "SiTcp:_write_single - Invalid RBCP message byte size - expected bytes: %d, received bytes: %d" + % (len(request), len(rbcp_recv)) + ) + rbcp_data = array("B", rbcp_recv[8:]) if rbcp_data != data: - raise IOError('SiTcp:_write_single - RBCP data mismatch - expected: %s, read: %s' % (data, rbcp_data)) + raise IOError( + "SiTcp:_write_single - RBCP data mismatch - expected: %s, read: %s" % (data, rbcp_data) + ) while True: rlist, _, _ = select.select([self._sock_udp], [], [], 0.0) if rlist: @@ -271,23 +286,26 @@ def _write_single(self, addr, data): # remaining meassge data is lost. rbcp_recv_pending = self._sock_udp.recv(3) if len(rbcp_recv_pending) == 3: - rbcp_pending_status = array('B', rbcp_recv_pending) - logger.warning('SiTcp:_write_single - Pending RBCP data after recv - RBCP message ID: current: %d, read: %d' % (self.RBCP_ID, rbcp_pending_status[2])) + rbcp_pending_status = array("B", rbcp_recv_pending) + logger.warning( + "SiTcp:_write_single - Pending RBCP data after recv - RBCP message ID: current: %d, read: %d" + % (self.RBCP_ID, rbcp_pending_status[2]) + ) else: - logger.warning('SiTcp:_write_single - Pending data after recv') + logger.warning("SiTcp:_write_single - Pending data after recv") else: break return def write(self, addr, data): if addr < self.BASE_DATA_TCP: - if self._sock_tcp is not None and 'tcp_to_bus' in self._init and self._init['tcp_to_bus']: - arr = array('B', struct.pack('BBBBI', self.RBCP_VER, self.RBCP_CMD_RD, self.RBCP_ID, size, addr)) + request = array("B", struct.pack(">BBBBI", self.RBCP_VER, self.RBCP_CMD_RD, self.RBCP_ID, size, addr)) while True: rlist, _, _ = select.select([self._sock_udp], [], [], 0.0) if rlist: @@ -319,63 +337,75 @@ def _read_single(self, addr, size): # remaining meassge data is lost. rbcp_recv_pending = self._sock_udp.recv(3) if len(rbcp_recv_pending) == 3: - rbcp_pending_status = array('B', rbcp_recv_pending) - logger.warning('SiTcp:_read_single - Pending RBCP data before send - RBCP message ID: current: %d, read: %d' % (self.RBCP_ID, rbcp_pending_status[2])) + rbcp_pending_status = array("B", rbcp_recv_pending) + logger.warning( + "SiTcp:_read_single - Pending RBCP data before send - RBCP message ID: current: %d, read: %d" + % (self.RBCP_ID, rbcp_pending_status[2]) + ) else: - logger.warning('SiTcp:_read_single - Pending data before send') + logger.warning("SiTcp:_read_single - Pending data before send") else: break retry_write_cnt += 1 _, wlist, _ = select.select([], [self._sock_udp], [], self.UDP_TIMEOUT) if not wlist and retry_write_cnt <= self.UDP_RETRANSMIT_CNT: - logger.warning('SiTcp:_read_single - Write timeout - Retry...') + logger.warning("SiTcp:_read_single - Write timeout - Retry...") continue elif not wlist: - raise IOError('SiTcp:_read_single - Write timeout') + raise IOError("SiTcp:_read_single - Write timeout") else: total_sent = self._sock_udp.send(request) if total_sent != len(request): - raise IOError('SiTcp:_read_single - Socket broken') + raise IOError("SiTcp:_read_single - Socket broken") retry_read_cnt = 0 while True: retry_read_cnt += 1 rlist, _, _ = select.select([self._sock_udp], [], [], self.UDP_TIMEOUT) if not rlist: if retry_read_cnt <= self.UDP_RETRANSMIT_CNT: - logger.warning('SiTcp:_read_single - Read timeout - Retry...') + logger.warning("SiTcp:_read_single - Read timeout - Retry...") continue elif retry_write_cnt <= self.UDP_RETRANSMIT_CNT: - logger.warning('SiTcp:_read_single - Read timeout - Retry write...') + logger.warning("SiTcp:_read_single - Read timeout - Retry write...") break else: - raise IOError('SiTcp:_read_single - Read timeout') + raise IOError("SiTcp:_read_single - Read timeout") else: # Recv buffer needs to be longer than message size, # otherwise remaining message data is not read out and is lost. rbcp_recv = self._sock_udp.recv(1024) if len(rbcp_recv) < 8: - raise IOError('SiTcp:_read_single - Invalid RBCP message') - rbcp_status = array('B', rbcp_recv[:8]) + raise IOError("SiTcp:_read_single - Invalid RBCP message") + rbcp_status = array("B", rbcp_recv[:8]) if rbcp_status[2] != self.RBCP_ID: if retry_read_cnt <= self.UDP_RETRANSMIT_CNT: - logger.warning('SiTcp:_read_single - Wrong RBCP message ID - Retry...') + logger.warning("SiTcp:_read_single - Wrong RBCP message ID - Retry...") continue elif retry_write_cnt <= self.UDP_RETRANSMIT_CNT: - logger.warning('SiTcp:_read_single - Wrong RBCP message ID - Retry write...') + logger.warning("SiTcp:_read_single - Wrong RBCP message ID - Retry write...") break else: - raise IOError('SiTcp:_read_single - Wrong RBCP message ID') + raise IOError("SiTcp:_read_single - Wrong RBCP message ID") if rbcp_status[0] != self.RBCP_VER: - raise IOError('SiTcp:_read_single - Invalid RBCP version') - if (0x0f & rbcp_status[1]) != 0x8: - raise IOError('SiTcp:_read_single - RBCP bus error') + raise IOError("SiTcp:_read_single - Invalid RBCP version") + if (0x0F & rbcp_status[1]) != 0x8: + raise IOError("SiTcp:_read_single - RBCP bus error") if rbcp_status[3] != request[3]: - raise IOError('SiTcp:_read_single - RBCP size mismatch - expected: %d, read: %d' % (request[3], rbcp_status[3])) + raise IOError( + "SiTcp:_read_single - RBCP size mismatch - expected: %d, read: %d" + % (request[3], rbcp_status[3]) + ) if rbcp_status[4:8] != request[4:8]: - raise IOError('SiTcp:_read_single - RBCP address mismatch - expected: %d, read: %d' % (request[4:8], rbcp_status[4:8])) + raise IOError( + "SiTcp:_read_single - RBCP address mismatch - expected: %d, read: %d" + % (request[4:8], rbcp_status[4:8]) + ) if len(rbcp_recv) != size + 8: - raise IOError('SiTcp:_read_single - Invalid RBCP message byte size - expected bytes: %d, received bytes: %d' % (size + 8, len(rbcp_recv))) - rbcp_data = array('B', rbcp_recv[8:]) + raise IOError( + "SiTcp:_read_single - Invalid RBCP message byte size - expected bytes: %d, received bytes: %d" + % (size + 8, len(rbcp_recv)) + ) + rbcp_data = array("B", rbcp_recv[8:]) while True: rlist, _, _ = select.select([self._sock_udp], [], [], 0.0) if rlist: @@ -383,17 +413,20 @@ def _read_single(self, addr, size): # remaining meassge data is lost. rbcp_recv_pending = self._sock_udp.recv(3) if len(rbcp_recv_pending) == 3: - rbcp_pending_status = array('B', rbcp_recv_pending) - logger.warning('SiTcp:_read_single - Pending RBCP data after recv - RBCP message ID: current: %d, read: %d' % (self.RBCP_ID, rbcp_pending_status[2])) + rbcp_pending_status = array("B", rbcp_recv_pending) + logger.warning( + "SiTcp:_read_single - Pending RBCP data after recv - RBCP message ID: current: %d, read: %d" + % (self.RBCP_ID, rbcp_pending_status[2]) + ) else: - logger.warning('SiTcp:_read_single - Pending data after recv') + logger.warning("SiTcp:_read_single - Pending data after recv") else: break return rbcp_data def read(self, addr, size): if addr < self.BASE_DATA_TCP: - ret = array('B') + ret = array("B") with self._udp_lock: if size > self.RBCP_MAX_SIZE: new_addr = addr @@ -409,24 +442,27 @@ def read(self, addr, size): elif addr < self.BASE_FAKE_FIFO_TCP: return self._get_tcp_data(size) elif addr == self.BASE_FAKE_FIFO_TCP: - return array('B', chr(sram_fifo_version)) + return array("B", chr(sram_fifo_version)) else: # this is to fake a HL fifo. Is there better way? Definitely... if size == 4: - return array('B', struct.pack('I', self._get_tcp_data_size())) + return array("B", struct.pack("I", self._get_tcp_data_size())) else: - return array('B', '\x00' * size) # FIXME: workaround for SRAM module registers -# logger.warning("SiTcp:read - Invalid address %s" % hex(addr)) + return array("B", "\x00" * size) # FIXME: workaround for SRAM module registers + + # logger.warning("SiTcp:read - Invalid address %s" % hex(addr)) def _tcp_readout(self): time_read = time() while not self._stop: try: # this is in case close() was not called and the thread was forcibly stopped - rlist, _, _ = select.select([self._sock_tcp], [], [], max(0.0, self._tcp_readout_interval + time_read - time())) + rlist, _, _ = select.select( + [self._sock_tcp], [], [], max(0.0, self._tcp_readout_interval + time_read - time()) + ) time_read = time() if rlist: with self._tcp_lock: data = self._sock_tcp.recv(1024 * 8) - self._tcp_read_buff.extend(array('B', data)) + self._tcp_read_buff.extend(array("B", data)) except AttributeError: pass @@ -438,7 +474,7 @@ def _get_tcp_data_size(self): def _get_tcp_data(self, size): with self._tcp_lock: ret_size = min((size, self._get_tcp_data_size())) - ret_size = (ret_size - (ret_size % 4)) # modulo 4 bytes + ret_size = ret_size - (ret_size % 4) # modulo 4 bytes ret = self._tcp_read_buff[:ret_size] self._tcp_read_buff = self._tcp_read_buff[ret_size:] return ret @@ -450,14 +486,14 @@ def _send_tcp_data(self, data): if wlist: sent = self._sock_tcp.send(data[total_sent:]) if sent == 0: - raise IOError('SiTcp:_send_tcp_data - Socket broken') + raise IOError("SiTcp:_send_tcp_data - Socket broken") total_sent += sent if total_sent == len(data): break def _reset_tcp_to_bus(self): - self._send_tcp_data(array('B', [255] * 65535)) - self._send_tcp_data(array('B', [0] * 6)) + self._send_tcp_data(array("B", [255] * 65535)) + self._send_tcp_data(array("B", [0] * 6)) def close(self): super(SiTcp, self).close() @@ -465,12 +501,12 @@ def close(self): self._tcp_readout_thread.join() self._tcp_readout_thread = None self._sock_udp.close() - if self._init['tcp_connection']: + if self._init["tcp_connection"]: self._sock_tcp.close() def chunks(array, max_len): index = 0 while index < len(array): - yield array[index: index + max_len] + yield array[index : index + max_len] index += max_len diff --git a/basil/TL/SiTransferLayer.py b/basil/TL/SiTransferLayer.py index 71b6a001f..6fce916d1 100644 --- a/basil/TL/SiTransferLayer.py +++ b/basil/TL/SiTransferLayer.py @@ -9,21 +9,20 @@ class SiTransferLayer(TransferLayer): - '''Multiplexing Transfer Layer implements abstract methods to access + """Multiplexing Transfer Layer implements abstract methods to access hardware with multiple endpoints. On error ``raise IOError``. - ''' + """ def __init__(self, conf): super(SiTransferLayer, self).__init__(conf) def init(self): - '''Initialize and connect to hardware. - ''' + """Initialize and connect to hardware.""" super(SiTransferLayer, self).init() def read(self, addr, size): - '''Read access. + """Read access. :param addr: start transfer address :type addr: int @@ -32,11 +31,11 @@ def read(self, addr, size): :returns: data byte array :rtype: array.array('B') - ''' + """ pass def write(self, addr, data): - '''Write access. + """Write access. :param addr: start transfer address :type addr: int @@ -44,5 +43,5 @@ def write(self, addr, data): :type data: iterable :rtype: None - ''' + """ pass diff --git a/basil/TL/SiUart.py b/basil/TL/SiUart.py index c691e2ed3..43b3435ac 100644 --- a/basil/TL/SiUart.py +++ b/basil/TL/SiUart.py @@ -5,8 +5,8 @@ # ------------------------------------------------------------ # -import logging import array +import logging from struct import pack from time import sleep @@ -25,48 +25,48 @@ def __init__(self, conf): def init(self): super(SiUart, self).init() - self._init.setdefault('board_id', None) - self._init.setdefault('avoid_download', False) - if self._init['board_id'] and int(self._init['board_id']) >= 0: + self._init.setdefault("board_id", None) + self._init.setdefault("avoid_download", False) + if self._init["board_id"] and int(self._init["board_id"]) >= 0: self._ser = serial.Serial() - if 'port' in self._init.keys(): - self._ser.setPort(self._init['port']) - if 'baudrate' in self._init.keys(): - self._ser.setBaudrate(self._init['baudrate']) - if 'parity' in self._init.keys() and self._init["parity"] == 0: + if "port" in self._init.keys(): + self._ser.setPort(self._init["port"]) + if "baudrate" in self._init.keys(): + self._ser.setBaudrate(self._init["baudrate"]) + if "parity" in self._init.keys() and self._init["parity"] == 0: self._ser.setParity(serial.PARITY_NONE) - if 'stopbits' in self._init.keys(): - self._ser.setStopbits(self._init['stopbits']) - if 'bytesize' in self._init.keys(): - self._ser.setByteSize(self._init['bytesize']) - if 'timeout' in self._init.keys(): - self._ser.setTimeout(self._init['timeout']) + if "stopbits" in self._init.keys(): + self._ser.setStopbits(self._init["stopbits"]) + if "bytesize" in self._init.keys(): + self._ser.setByteSize(self._init["bytesize"]) + if "timeout" in self._init.keys(): + self._ser.setTimeout(self._init["timeout"]) self._ser.open() if not self._ser.isOpen(): raise IOError("Port at %s not open" % self._ser.port) else: - logger.info('Found board') + logger.info("Found board") def __del__(self): self._ser.close() def write(self, addr, data): logger.debug("------------ writing ------------") - logger.debug('Addr: %s \tdata: %s', addr, data) + logger.debug("Addr: %s \tdata: %s", addr, data) done = False - a = array.array('B', 'a') + array.array('B', pack(" 0: logger.debug("writing ...") @@ -80,26 +80,26 @@ def write(self, addr, data): def read(self, addr, size): logger.debug("------------ reading ------------") - logger.debug('Addr: %s \tSize: %s', addr, size) + logger.debug("Addr: %s \tSize: %s", addr, size) - a = array.array('B', 'a') + array.array('B', pack(" 0: logger.info("reading ...") sleep(0.3) if "OK" in self._ser.read(): - a = array.array('B', dataOut) + a = array.array("B", dataOut) logger.debug("Reading finished") return a raise Exception("Read serial port failed") diff --git a/basil/TL/SiUsb.py b/basil/TL/SiUsb.py index 6d9778a32..20c62d061 100644 --- a/basil/TL/SiUsb.py +++ b/basil/TL/SiUsb.py @@ -9,16 +9,16 @@ import os from SiLibUSB import GetUSBBoards, SiUSBDevice +from six.moves import filter from basil.TL.SiTransferLayer import SiTransferLayer -from six.moves import filter logger = logging.getLogger(__name__) class SiUsb(SiTransferLayer): - '''SiLab USB device - ''' + """SiLab USB device""" + BASE_ADDRESS_I2C = 0x00000 HIGH_ADDRESS_I2C = BASE_ADDRESS_I2C + 256 @@ -26,7 +26,7 @@ class SiUsb(SiTransferLayer): HIGH_ADDRESS_EXTERNAL = BASE_ADDRESS_EXTERNAL + 0x10000 BASE_ADDRESS_BLOCK = 0x0001000000000000 - HIGH_ADDRESS_BLOCK = 0xffffffffffffffff + HIGH_ADDRESS_BLOCK = 0xFFFFFFFFFFFFFFFF def __init__(self, conf): super(SiUsb, self).__init__(conf) @@ -34,22 +34,40 @@ def __init__(self, conf): def init(self): super(SiUsb, self).init() - self._init.setdefault('board_id', None) - self._init.setdefault('avoid_download', False) - if self._init['board_id'] and int(self._init['board_id']) >= 0: - self._sidev = SiUSBDevice.from_board_id(self._init['board_id']) + self._init.setdefault("board_id", None) + self._init.setdefault("avoid_download", False) + if self._init["board_id"] and int(self._init["board_id"]) >= 0: + self._sidev = SiUSBDevice.from_board_id(self._init["board_id"]) else: # search for any available device devices = GetUSBBoards() if not devices: - raise IOError('Can\'t find USB board. Connect or reset USB board!') + raise IOError("Can't find USB board. Connect or reset USB board!") else: - logger.info('Found USB board(s): {}'.format(', '.join(('%s with ID %s (FW %s)' % (device.board_name, "".join(filter(str.isdigit, device.board_id)), "".join(filter(str.isdigit, device.fw_version)))) for device in devices))) + logger.info( + "Found USB board(s): {}".format( + ", ".join( + ( + "%s with ID %s (FW %s)" + % ( + device.board_name, + "".join(filter(str.isdigit, device.board_id)), + "".join(filter(str.isdigit, device.fw_version)), + ) + ) + for device in devices + ) + ) + ) if len(devices) > 1: - raise ValueError('Please specify ID of USB board') + raise ValueError("Please specify ID of USB board") self._sidev = devices[0] - if 'bit_file' in self._init.keys(): - if 'avoid_download' in self._init.keys() and self._init['avoid_download'] is True and self._sidev.XilinxAlreadyLoaded(): + if "bit_file" in self._init.keys(): + if ( + "avoid_download" in self._init.keys() + and self._init["avoid_download"] is True + and self._sidev.XilinxAlreadyLoaded() + ): logger.info("FPGA already programmed, skipping download") else: # invert polarity of the interface clock (IFCONFIG.4) -> IFCLK & UCLK are in-phase @@ -57,41 +75,41 @@ def init(self): ifconfig = ifconfig & ~0x10 self._sidev._Write8051(0xE601, [ifconfig]) - if os.path.exists(self._init['bit_file']): - bit_file = self._init['bit_file'] - elif os.path.exists(os.path.join(os.path.dirname(self.parent.conf_path), self._init['bit_file'])): - bit_file = os.path.join(os.path.dirname(self.parent.conf_path), self._init['bit_file']) + if os.path.exists(self._init["bit_file"]): + bit_file = self._init["bit_file"] + elif os.path.exists(os.path.join(os.path.dirname(self.parent.conf_path), self._init["bit_file"])): + bit_file = os.path.join(os.path.dirname(self.parent.conf_path), self._init["bit_file"]) else: - raise ValueError('No such bit file: %s' % self._init['bit_file']) - logger.info("Programming FPGA: %s..." % (self._init['bit_file'])) + raise ValueError("No such bit file: %s" % self._init["bit_file"]) + logger.info("Programming FPGA: %s..." % (self._init["bit_file"])) status = self._sidev.DownloadXilinx(bit_file) - logger.log(logging.INFO if status else logging.ERROR, 'Success!' if status else 'Failed!') + logger.log(logging.INFO if status else logging.ERROR, "Success!" if status else "Failed!") else: if not self._sidev.XilinxAlreadyLoaded(): - raise ValueError('FPGA not initialized, bit_file not specified') + raise ValueError("FPGA not initialized, bit_file not specified") else: logger.info("Programming FPGA: bit_file not specified") def write(self, addr, data): - if (addr >= self.BASE_ADDRESS_I2C and addr < self.HIGH_ADDRESS_I2C): + if addr >= self.BASE_ADDRESS_I2C and addr < self.HIGH_ADDRESS_I2C: self._sidev.WriteI2C(addr - self.BASE_ADDRESS_I2C, data) - elif (addr >= self.BASE_ADDRESS_EXTERNAL and addr < self.HIGH_ADDRESS_EXTERNAL): + elif addr >= self.BASE_ADDRESS_EXTERNAL and addr < self.HIGH_ADDRESS_EXTERNAL: self._sidev.WriteExternal(addr - self.BASE_ADDRESS_EXTERNAL, data) - elif (addr >= self.BASE_ADDRESS_BLOCK and addr < self.HIGH_ADDRESS_BLOCK): + elif addr >= self.BASE_ADDRESS_BLOCK and addr < self.HIGH_ADDRESS_BLOCK: self._sidev.FastBlockWrite(data) def read(self, addr, size): - if (addr >= self.BASE_ADDRESS_I2C and addr < self.HIGH_ADDRESS_I2C): + if addr >= self.BASE_ADDRESS_I2C and addr < self.HIGH_ADDRESS_I2C: return self._sidev.ReadI2C(addr - self.BASE_ADDRESS_I2C, size) - elif (addr >= self.BASE_ADDRESS_EXTERNAL and addr < self.HIGH_ADDRESS_EXTERNAL): + elif addr >= self.BASE_ADDRESS_EXTERNAL and addr < self.HIGH_ADDRESS_EXTERNAL: data = self._sidev.ReadExternal(addr - self.BASE_ADDRESS_EXTERNAL, size) return data - elif (addr >= self.BASE_ADDRESS_BLOCK and addr < self.HIGH_ADDRESS_BLOCK): + elif addr >= self.BASE_ADDRESS_BLOCK and addr < self.HIGH_ADDRESS_BLOCK: return self._sidev.FastBlockRead(size) def get_configuration(self): conf = dict(self._init) - conf['board_id'] = self._sidev.board_id + conf["board_id"] = self._sidev.board_id return conf def close(self): diff --git a/basil/TL/SiUsb3.py b/basil/TL/SiUsb3.py index c55eaf8b9..34968442d 100644 --- a/basil/TL/SiUsb3.py +++ b/basil/TL/SiUsb3.py @@ -6,19 +6,21 @@ # import logging -# import os from SiLibUSB import GetUSBBoards, SiUSBDevice +from six.moves import filter from basil.TL.SiTransferLayer import SiTransferLayer -from six.moves import filter + +# import os + logger = logging.getLogger(__name__) class SiUsb3(SiTransferLayer): - '''SiLab USB3 device - ''' + """SiLab USB3 device""" + BASE_ADDRESS_I2C = 0x00000 HIGH_ADDRESS_I2C = BASE_ADDRESS_I2C + 256 @@ -26,7 +28,7 @@ class SiUsb3(SiTransferLayer): HIGH_ADDRESS_EXTERNAL = BASE_ADDRESS_EXTERNAL + 0x10000 BASE_ADDRESS_BLOCK = 0x0001000000000000 - HIGH_ADDRESS_BLOCK = 0xffffffffffffffff + HIGH_ADDRESS_BLOCK = 0xFFFFFFFFFFFFFFFF def __init__(self, conf): super(SiUsb3, self).__init__(conf) @@ -34,59 +36,74 @@ def __init__(self, conf): def init(self): super(SiUsb3, self).init() - self._init.setdefault('board_id', None) - self._init.setdefault('avoid_download', False) - if self._init['board_id'] and int(self._init['board_id']) >= 0: - self._sidev = SiUSBDevice.from_board_id(self._init['board_id']) + self._init.setdefault("board_id", None) + self._init.setdefault("avoid_download", False) + if self._init["board_id"] and int(self._init["board_id"]) >= 0: + self._sidev = SiUSBDevice.from_board_id(self._init["board_id"]) else: # search for any available device devices = GetUSBBoards() if not devices: - raise IOError('Can\'t find USB board. Connect or reset USB board!') + raise IOError("Can't find USB board. Connect or reset USB board!") else: - logger.info('Found USB board(s): {}'.format(', '.join(('%s with ID %s (FW %s)' % (device.board_name, "".join(filter(type(device.board_id).isdigit, device.board_id)), "".join(filter(type(device.fw_version).isdigit, device.fw_version)))) for device in devices))) + logger.info( + "Found USB board(s): {}".format( + ", ".join( + ( + "%s with ID %s (FW %s)" + % ( + device.board_name, + "".join(filter(type(device.board_id).isdigit, device.board_id)), + "".join(filter(type(device.fw_version).isdigit, device.fw_version)), + ) + ) + for device in devices + ) + ) + ) if len(devices) > 1: - raise ValueError('Please specify ID of USB board') + raise ValueError("Please specify ID of USB board") self._sidev = devices[0] -# TODO: Firmware upload TBD -# if 'bit_file' in self._init.keys(): -# if 'avoid_download' in self._init.keys() and self._init['avoid_download'] is True and self._sidev.XilinxAlreadyLoaded(): -# logger.info("FPGA already programmed, skipping download") -# else: -# if os.path.exists(self._init['bit_file']): -# bit_file = self._init['bit_file'] -# elif os.path.exists(os.path.join(os.path.dirname(self.parent.conf_path), self._init['bit_file'])): -# bit_file = os.path.join(os.path.dirname(self.parent.conf_path), self._init['bit_file']) -# else: -# raise ValueError('No such bit file: %s' % self._init['bit_file']) -# logger.info("Programming FPGA: %s..." % (self._init['bit_file'])) -# status = self._sidev.DownloadXilinx(bit_file) -# logger.log(logging.INFO if status else logging.ERROR, 'Success!' if status else 'Failed!') -# else: -# if not self._sidev.XilinxAlreadyLoaded(): -# raise ValueError('FPGA not initialized, bit_file not specified') -# else: -# logger.info("Programming FPGA: bit_file not specified") + + # TODO: Firmware upload TBD + # if 'bit_file' in self._init.keys(): + # if 'avoid_download' in self._init.keys() and self._init['avoid_download'] is True and self._sidev.XilinxAlreadyLoaded(): + # logger.info("FPGA already programmed, skipping download") + # else: + # if os.path.exists(self._init['bit_file']): + # bit_file = self._init['bit_file'] + # elif os.path.exists(os.path.join(os.path.dirname(self.parent.conf_path), self._init['bit_file'])): + # bit_file = os.path.join(os.path.dirname(self.parent.conf_path), self._init['bit_file']) + # else: + # raise ValueError('No such bit file: %s' % self._init['bit_file']) + # logger.info("Programming FPGA: %s..." % (self._init['bit_file'])) + # status = self._sidev.DownloadXilinx(bit_file) + # logger.log(logging.INFO if status else logging.ERROR, 'Success!' if status else 'Failed!') + # else: + # if not self._sidev.XilinxAlreadyLoaded(): + # raise ValueError('FPGA not initialized, bit_file not specified') + # else: + # logger.info("Programming FPGA: bit_file not specified") def write(self, addr, data): - if (addr >= self.BASE_ADDRESS_I2C and addr < self.HIGH_ADDRESS_I2C): + if addr >= self.BASE_ADDRESS_I2C and addr < self.HIGH_ADDRESS_I2C: self._sidev.WriteI2C(addr - self.BASE_ADDRESS_I2C, data) - elif (addr >= self.BASE_ADDRESS_EXTERNAL and addr < self.HIGH_ADDRESS_EXTERNAL): + elif addr >= self.BASE_ADDRESS_EXTERNAL and addr < self.HIGH_ADDRESS_EXTERNAL: self._sidev.WriteExternal(addr - self.BASE_ADDRESS_EXTERNAL, data) - elif (addr >= self.BASE_ADDRESS_BLOCK and addr < self.HIGH_ADDRESS_BLOCK): + elif addr >= self.BASE_ADDRESS_BLOCK and addr < self.HIGH_ADDRESS_BLOCK: self._sidev.WriteExternal(addr - self.BASE_ADDRESS_BLOCK, data) def read(self, addr, size): - if (addr >= self.BASE_ADDRESS_I2C and addr < self.HIGH_ADDRESS_I2C): + if addr >= self.BASE_ADDRESS_I2C and addr < self.HIGH_ADDRESS_I2C: return self._sidev.ReadI2C(addr - self.BASE_ADDRESS_I2C, size) - elif (addr >= self.BASE_ADDRESS_EXTERNAL and addr < self.HIGH_ADDRESS_EXTERNAL): + elif addr >= self.BASE_ADDRESS_EXTERNAL and addr < self.HIGH_ADDRESS_EXTERNAL: return self._sidev.ReadExternal(addr - self.BASE_ADDRESS_EXTERNAL, size) - elif (addr >= self.BASE_ADDRESS_BLOCK and addr < self.HIGH_ADDRESS_BLOCK): + elif addr >= self.BASE_ADDRESS_BLOCK and addr < self.HIGH_ADDRESS_BLOCK: return self._sidev.ReadExternal(addr - self.BASE_ADDRESS_BLOCK, size) def get_configuration(self): conf = dict(self._init) - conf['board_id'] = self._sidev.board_id + conf["board_id"] = self._sidev.board_id return conf def close(self): diff --git a/basil/TL/Socket.py b/basil/TL/Socket.py index e2585877c..3772584e5 100644 --- a/basil/TL/Socket.py +++ b/basil/TL/Socket.py @@ -5,30 +5,32 @@ class Socket(TransferLayer): - ''' - General direct socket TL implementation. - Used for TCP/IP based direct communication with devices. - Commands are handled including encoding, read and write termination. - ''' + """ + General direct socket TL implementation. + Used for TCP/IP based direct communication with devices. + Commands are handled including encoding, read and write termination. + """ def __init__(self, conf): super(Socket, self).__init__(conf) def init(self): - ''' - Create socket object and connect to specified ip address and port. - ''' + """ + Create socket object and connect to specified ip address and port. + """ super(Socket, self).init() self._sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - self.encoding = self._init.get('encoding', 'utf-8') - self.write_termination = self._init.get('write_termination', '').encode(self.encoding).decode('unicode_escape') - self.read_termination = self._init.get('read_termination', self.write_termination).encode(self.encoding).decode('unicode_escape') - self.query_delay = self._init.get('query_delay', 0) - self.handle_as_byte = self._init.get('handle_as_byte', False) + self.encoding = self._init.get("encoding", "utf-8") + self.write_termination = self._init.get("write_termination", "").encode(self.encoding).decode("unicode_escape") + self.read_termination = ( + self._init.get("read_termination", self.write_termination).encode(self.encoding).decode("unicode_escape") + ) + self.query_delay = self._init.get("query_delay", 0) + self.handle_as_byte = self._init.get("handle_as_byte", False) - address = self._init.get('address') - port = self._init.get('port') + address = self._init.get("address") + port = self._init.get("port") self._sock.connect((address, port)) @@ -43,7 +45,7 @@ def write(self, data): cmd = data.encode(self.encoding) cmd += self.write_termination.encode(self.encoding) if not self.handle_as_byte: - cmd.decode('unicode_escape') + cmd.decode("unicode_escape") self._sock.send(cmd) def read(self, buffer_size=1): diff --git a/basil/TL/TransferLayer.py b/basil/TL/TransferLayer.py index 5baaf9946..6eb0d75ff 100644 --- a/basil/TL/TransferLayer.py +++ b/basil/TL/TransferLayer.py @@ -9,31 +9,30 @@ class TransferLayer(Base): - '''Transfer Layer implements minimum API needed access to hardware. + """Transfer Layer implements minimum API needed access to hardware. On error ``raise IOError``. - ''' + """ def __init__(self, conf): super(TransferLayer, self).__init__(conf) def init(self): - '''Initialize and connect to hardware. - ''' + """Initialize and connect to hardware.""" super(TransferLayer, self).init() def read(self): - '''Read access. + """Read access. :rtype: None - ''' + """ raise NotImplementedError("read() not implemented") def write(self, data): - '''Write access. + """Write access. :param data: array/list of bytes :type data: iterable :rtype: None - ''' + """ raise NotImplementedError("write() not implemented") diff --git a/basil/TL/Visa.py b/basil/TL/Visa.py index 0365f80a8..17ffc1f42 100644 --- a/basil/TL/Visa.py +++ b/basil/TL/Visa.py @@ -4,45 +4,50 @@ # SiLab, Institute of Physics, University of Bonn # ------------------------------------------------------------ # -import pyvisa as visa import logging import time -from basil.TL.TransferLayer import TransferLayer +import pyvisa as visa from pyvisa.errors import VisaIOError +from basil.TL.TransferLayer import TransferLayer + logger = logging.getLogger(__name__) class Visa(TransferLayer): - '''Transfer layer for a Virtual Instrument Software Architecture (VISA) provided by pyVisa. + """Transfer layer for a Virtual Instrument Software Architecture (VISA) provided by pyVisa. Several interfaces are available (GPIB, RS232, USB, Ethernet). To be able to use pyVisa without the proprietary NI-VISA driver a pyVisa backend pyVisa-py can be used. GPIB under linux is not supported via pyVisa-py right now. - ''' + """ def __init__(self, conf): super(Visa, self).__init__(conf) self._resource = None def init(self): - ''' + """ Initialize the device. Parameters of visa.ResourceManager().open_resource() - ''' + """ super(Visa, self).init() - backend = self._init.get('backend', '') # Empty string means std. backend (NI VISA) + backend = self._init.get("backend", "") # Empty string means std. backend (NI VISA) rm = visa.ResourceManager(backend) try: - logger.info('BASIL VISA TL with %s backend found the following devices: %s', backend, ", ".join(rm.list_resources())) + logger.info( + "BASIL VISA TL with %s backend found the following devices: %s", backend, ", ".join(rm.list_resources()) + ) except NotImplementedError: # some backends do not always implement the list_resources function - logger.info('BASIL VISA TL with %s backend', backend) + logger.info("BASIL VISA TL with %s backend", backend) # make interface compatible with other transfer layers (serial) if "baudrate" in self._init.keys(): self._init["baud_rate"] = self._init.pop("baudrate") - self._resource = rm.open_resource(**{key: value for key, value in self._init.items() if key not in ("backend",)}) + self._resource = rm.open_resource( + **{key: value for key, value in self._init.items() if key not in ("backend",)} + ) def close(self): super(Visa, self).close() diff --git a/basil/__init__.py b/basil/__init__.py index bd551f2ac..97e8fda00 100644 --- a/basil/__init__.py +++ b/basil/__init__.py @@ -1,4 +1,5 @@ import collections + import yaml __version__ = "3.3.0" diff --git a/basil/dut.py b/basil/dut.py index 3f4ecb4d9..e118629f5 100644 --- a/basil/dut.py +++ b/basil/dut.py @@ -4,21 +4,24 @@ # SiLab, Institute of Physics, University of Bonn # ------------------------------------------------------------ # -import os -from importlib import import_module -from inspect import getmembers, isclass -from yaml import safe_load -import warnings -from collections import OrderedDict -from six import string_types - # FIXME: Bad practice # Logger settings should not be defined in a module, but once by the # application developer. Thus outside of basil. Otherwise multiple calls to # the basic config are possible. This is left here at the moment for backward # compatibility and since our logging format is the same everywhere (?). import logging -logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(name)s - [%(levelname)-8s] (%(threadName)-10s) %(message)s") +import os +import warnings +from collections import OrderedDict +from importlib import import_module +from inspect import getmembers, isclass + +from six import string_types +from yaml import safe_load + +logging.basicConfig( + level=logging.INFO, format="%(asctime)s - %(name)s - [%(levelname)-8s] (%(threadName)-10s) %(message)s" +) class Base(object): @@ -29,27 +32,27 @@ def __init__(self, conf): self.parent = None self._init = {} self._conf = self._open_conf(conf) - if 'name' in self._conf: - self.name = self._conf['name'] - if 'version' in self._conf: - self.version = self._conf['version'] - if 'conf_path' in self._conf: - self.conf_path = self._conf['conf_path'] - if 'parent' in self._conf: - self.parent = self._conf['parent'] - if 'init' in self._conf: - self._update_init(self._conf['init']) + if "name" in self._conf: + self.name = self._conf["name"] + if "version" in self._conf: + self.version = self._conf["version"] + if "conf_path" in self._conf: + self.conf_path = self._conf["conf_path"] + if "parent" in self._conf: + self.parent = self._conf["parent"] + if "init" in self._conf: + self._update_init(self._conf["init"]) def _open_conf(self, conf): def isFile(f): - return hasattr(f, 'read') + return hasattr(f, "read") conf_dict = {} if not conf: pass elif isinstance(conf, string_types): # parse the first YAML document in a stream if os.path.isfile(conf): - with open(conf, 'r') as f: + with open(conf, "r") as f: conf_dict.update(safe_load(f)) conf_dict.update(conf_path=f.name) else: # YAML string @@ -91,8 +94,8 @@ def get_configuration(self): class Dut(Base): - '''Device - ''' + """Device""" + def __init__(self, conf): super(Dut, self).__init__(conf) self._transfer_layer = None @@ -147,7 +150,7 @@ def set_configuration(self, conf): conf = self._open_conf(conf) if conf: for item, item_conf in conf.items(): - if item != 'conf_path': + if item != "conf_path": try: self[item].set_configuration(item_conf) except NotImplementedError: @@ -180,73 +183,73 @@ def load_hw_configuration(self, conf, extend_config=False): self._conf = conf if not extend_config: - if 'name' in self._conf: - self.name = self._conf['name'] + if "name" in self._conf: + self.name = self._conf["name"] else: self.name = None - if 'version' in self._conf: - self.version = self._conf['version'] + if "version" in self._conf: + self.version = self._conf["version"] else: self.version = None self._transfer_layer = OrderedDict() self._hardware_layer = OrderedDict() self._registers = OrderedDict() - if 'transfer_layer' in conf: - for intf in conf['transfer_layer']: - intf['parent'] = self + if "transfer_layer" in conf: + for intf in conf["transfer_layer"]: + intf["parent"] = self kargs = {} - kargs['conf'] = intf - self._transfer_layer[intf['name']] = self._factory('basil.TL.' + intf['type'], *(), **kargs) + kargs["conf"] = intf + self._transfer_layer[intf["name"]] = self._factory("basil.TL." + intf["type"], *(), **kargs) - if 'hw_drivers' in conf: - if conf['hw_drivers']: - for hwdrv in conf['hw_drivers']: - hwdrv['parent'] = self + if "hw_drivers" in conf: + if conf["hw_drivers"]: + for hwdrv in conf["hw_drivers"]: + hwdrv["parent"] = self kargs = {} - if 'interface' in hwdrv: - if hwdrv['interface'].lower() == 'none': - kargs['intf'] = None + if "interface" in hwdrv: + if hwdrv["interface"].lower() == "none": + kargs["intf"] = None else: - kargs['intf'] = self._transfer_layer[hwdrv['interface']] - elif 'hw_driver' in hwdrv: - kargs['intf'] = self._hardware_layer[hwdrv['hw_driver']] + kargs["intf"] = self._transfer_layer[hwdrv["interface"]] + elif "hw_driver" in hwdrv: + kargs["intf"] = self._hardware_layer[hwdrv["hw_driver"]] else: - kargs['intf'] = None - kargs['conf'] = hwdrv - self._hardware_layer[hwdrv['name']] = self._factory('basil.HL.' + hwdrv['type'], *(), **kargs) + kargs["intf"] = None + kargs["conf"] = hwdrv + self._hardware_layer[hwdrv["name"]] = self._factory("basil.HL." + hwdrv["type"], *(), **kargs) - if 'user_drivers' in conf: + if "user_drivers" in conf: warnings.warn("Deprecated: user_drivers move modules to hw_drivers", DeprecationWarning) - if conf['user_drivers']: - for userdrv in conf['user_drivers']: - userdrv['parent'] = self + if conf["user_drivers"]: + for userdrv in conf["user_drivers"]: + userdrv["parent"] = self kargs = {} - kargs['intf'] = self._hardware_layer[userdrv['hw_driver']] - kargs['conf'] = userdrv - self._hardware_layer[userdrv['name']] = self._factory('basil.HL.' + userdrv['type'], *(), **kargs) - - if 'registers' in conf: - if conf['registers']: - for reg in conf['registers']: - reg['parent'] = self + kargs["intf"] = self._hardware_layer[userdrv["hw_driver"]] + kargs["conf"] = userdrv + self._hardware_layer[userdrv["name"]] = self._factory("basil.HL." + userdrv["type"], *(), **kargs) + + if "registers" in conf: + if conf["registers"]: + for reg in conf["registers"]: + reg["parent"] = self kargs = {} - if 'driver' in reg: - if not reg['driver'] or reg['driver'].lower() == 'none': - kargs['driver'] = None + if "driver" in reg: + if not reg["driver"] or reg["driver"].lower() == "none": + kargs["driver"] = None else: - kargs['driver'] = self._hardware_layer[reg['driver']] - kargs['conf'] = reg - self._registers[reg['name']] = self._factory('basil.RL.' + reg['type'], *(), **kargs) - elif 'hw_driver' in reg: - kargs['driver'] = self._hardware_layer[reg['hw_driver']] - kargs['conf'] = reg - self._registers[reg['name']] = self._factory('basil.RL.' + reg['type'], *(), **kargs) + kargs["driver"] = self._hardware_layer[reg["driver"]] + kargs["conf"] = reg + self._registers[reg["name"]] = self._factory("basil.RL." + reg["type"], *(), **kargs) + elif "hw_driver" in reg: + kargs["driver"] = self._hardware_layer[reg["hw_driver"]] + kargs["conf"] = reg + self._registers[reg["name"]] = self._factory("basil.RL." + reg["type"], *(), **kargs) else: - raise ValueError('No driver specified for register: %s' % (reg['name'],)) + raise ValueError("No driver specified for register: %s" % (reg["name"],)) def _factory(self, importname, *args, **kargs): - splitted_import_name = importname.split('.') + splitted_import_name = importname.split(".") def is_basil_base_class(item): return isclass(item) and issubclass(item, Base) and item.__module__ == importname @@ -254,15 +257,15 @@ def is_basil_base_class(item): try: mod = import_module(importname) except ImportError: # give it another try - if len(splitted_import_name) > 2 and splitted_import_name[0] == 'basil': - importname = '.'.join(splitted_import_name[2:]) # remove "basil.RL." etc. + if len(splitted_import_name) > 2 and splitted_import_name[0] == "basil": + importname = ".".join(splitted_import_name[2:]) # remove "basil.RL." etc. mod = import_module(importname) else: # raise initial exception raise basil_base_classes = getmembers(mod, is_basil_base_class) cls = None if not basil_base_classes: # found no base class - raise ValueError('Found no matching class in %s.' % importname) + raise ValueError("Found no matching class in %s." % importname) elif len(basil_base_classes) > 1: # found more than 1 base class mod_name = splitted_import_name[-1] for basil_base_class in basil_base_classes: @@ -270,7 +273,7 @@ def is_basil_base_class(item): cls = basil_base_class[1] break if cls is None: - raise ValueError('Found more than one matching class in %s.' % importname) + raise ValueError("Found more than one matching class in %s." % importname) else: # found single class cls = basil_base_classes[0][1] return cls(*args, **kargs) @@ -282,10 +285,10 @@ def __getitem__(self, item): return self._hardware_layer[item] elif item in self._transfer_layer: return self._transfer_layer[item] - raise KeyError('Item not existing: %s' % (item,)) + raise KeyError("Item not existing: %s" % (item,)) def get_modules(self, type_name): - '''Getting modules by type name. + """Getting modules by type name. Parameters ---------- @@ -295,7 +298,7 @@ def get_modules(self, type_name): Returns ------- List of modules of given type name else empty list. - ''' + """ modules = [] for module in self: if module.__class__.__name__ == type_name: diff --git a/basil/firmware/arduino/EnvironmentReadout/EnvironmentReadout.ino b/basil/firmware/arduino/EnvironmentReadout/EnvironmentReadout.ino index 80f9fc435..5bfae6e19 100644 --- a/basil/firmware/arduino/EnvironmentReadout/EnvironmentReadout.ino +++ b/basil/firmware/arduino/EnvironmentReadout/EnvironmentReadout.ino @@ -56,7 +56,7 @@ bool oneLastProcess; // Define vars potentially coming in from serial int nSamples; -uint16_t serialDelayMillis; +uint16_t serialDelayMillis; float ntcNominalRes; float resistorRes; float tempNominalDegreeC; @@ -80,7 +80,7 @@ void restoreDefaults(){ float steinhartHartNTC(float res){ /* - Steinhart-Hart equation for NTC: 1/T = 1/T_0 + 1/B * ln(R/R_0) + Steinhart-Hart equation for NTC: 1/T = 1/T_0 + 1/B * ln(R/R_0) */ // Do calculation @@ -88,7 +88,7 @@ float steinhartHartNTC(float res){ // To Kelvin temperature -= KELVIN; - + return temperature; } @@ -120,7 +120,7 @@ float getRes(int ntc){ // Voltage divider is measured over the fixed RESISTOR_RES else { - resistance = resistorRes * resistance; + resistance = resistorRes * resistance; } return resistance; @@ -142,7 +142,7 @@ float getAnalogRead(int ntc){ // Do the average val /= nSamples; - + return val; } @@ -179,9 +179,9 @@ void printNTCMeasurements(int kind){ /* Read the input buffer, read pins to read and print the respective temp or resistance to serial */ - + while (processIncoming()){ - + ntcPin = atoi(serialBuffer); // We only have 8 analog pins diff --git a/basil/firmware/arduino/Grove4ChannelRelay/Grove4ChannelRelay.ino b/basil/firmware/arduino/Grove4ChannelRelay/Grove4ChannelRelay.ino index d04e9df2a..1312a9c1e 100644 --- a/basil/firmware/arduino/Grove4ChannelRelay/Grove4ChannelRelay.ino +++ b/basil/firmware/arduino/Grove4ChannelRelay/Grove4ChannelRelay.ino @@ -93,14 +93,14 @@ void loop() { varPin = atoi(serialBuffer); processIncoming(); varState = atoi(serialBuffer); - + if (varState == 0) { if (varPin == 99) { relay.channelCtrl(0); } else { relay.turn_off_channel(varPin); - } + } } if (varState == 1) { if (varPin == 99) { diff --git a/basil/firmware/arduino/NTCReadout/NTCReadout.ino b/basil/firmware/arduino/NTCReadout/NTCReadout.ino index 07cfa848c..987a1232a 100644 --- a/basil/firmware/arduino/NTCReadout/NTCReadout.ino +++ b/basil/firmware/arduino/NTCReadout/NTCReadout.ino @@ -54,7 +54,7 @@ bool oneLastProcess; // Define vars potentially coming in from serial int nSamples; -uint16_t serialDelayMillis; +uint16_t serialDelayMillis; float ntcNominalRes; float resistorRes; float tempNominalDegreeC; @@ -78,7 +78,7 @@ void restoreDefaults(){ float steinhartHartNTC(float res){ /* - Steinhart-Hart equation for NTC: 1/T = 1/T_0 + 1/B * ln(R/R_0) + Steinhart-Hart equation for NTC: 1/T = 1/T_0 + 1/B * ln(R/R_0) */ // Do calculation @@ -86,7 +86,7 @@ float steinhartHartNTC(float res){ // To Kelvin temperature -= KELVIN; - + return temperature; } @@ -118,7 +118,7 @@ float getRes(int ntc){ // Voltage divider is measured over the fixed RESISTOR_RES else { - resistance = resistorRes * resistance; + resistance = resistorRes * resistance; } return resistance; @@ -157,9 +157,9 @@ void printNTCMeasurements(int kind){ /* Read the input buffer, read pins to read and print the respective temp or resistance to serial */ - + while (processIncoming()){ - + ntcPin = atoi(serialBuffer); // We only have 8 analog pins diff --git a/basil/firmware/arduino/RelayBoard/RelayBoard.ino b/basil/firmware/arduino/RelayBoard/RelayBoard.ino index b1a5c4ece..fd82e1a74 100644 --- a/basil/firmware/arduino/RelayBoard/RelayBoard.ino +++ b/basil/firmware/arduino/RelayBoard/RelayBoard.ino @@ -65,7 +65,7 @@ void setup() { void loop() { - + if (Serial.available()) { processIncoming(); @@ -100,7 +100,7 @@ void loop() { varPin = atoi(serialBuffer); processIncoming(); varState = atoi(serialBuffer); - + if (varPin == 99) { for (int x = 2; x <= 11; x++){ digitalWrite(x, varState); diff --git a/basil/firmware/arduino/SerialToI2C/SerialToI2C.ino b/basil/firmware/arduino/SerialToI2C/SerialToI2C.ino index b2e296a9a..310646dfc 100644 --- a/basil/firmware/arduino/SerialToI2C/SerialToI2C.ino +++ b/basil/firmware/arduino/SerialToI2C/SerialToI2C.ino @@ -87,7 +87,7 @@ uint8_t checkWire(){ * 1:data too long to fit in transmit buffer * 2:received NACK on transmit of address * 3:received NACK on transmit of data - * 4:other error + * 4:other error */ Wire.beginTransmission(i2cAddress); return Wire.endTransmission(); @@ -143,7 +143,7 @@ void loop(){ // Lowercase means we want to set some value and print back that value on the serial bus if (isLowerCase(serialBuffer[0])){ - + // Set I2C address if (toupper(serialBuffer[0]) == ADDR_CMD){ processIncoming(); @@ -157,7 +157,7 @@ void loop(){ serialDelayMillis = atoi(serialBuffer); Serial.println(serialDelayMillis); } - + } // Here we want to read something or interact with the I2C bus @@ -187,7 +187,7 @@ void loop(){ Serial.println(readCurrentReg()); } - + // Write if (serialBuffer[0] == WRITE_CMD){ processIncoming(); diff --git a/basil/firmware/modules/README.rst b/basil/firmware/modules/README.rst index 492a3b927..d8fab7bad 100644 --- a/basil/firmware/modules/README.rst +++ b/basil/firmware/modules/README.rst @@ -48,4 +48,4 @@ The following parameters, pins, and registers are common to all bus-connected mo | RESET | 0 | wo | Soft reset on write to address | +------------+----------------+-------+----------------------------------------+ | VERSION | 0 | ro | Module version | -+------------+----------------+-------+----------------------------------------+ \ No newline at end of file ++------------+----------------+-------+----------------------------------------+ diff --git a/basil/firmware/modules/cmd_seq/README.rst b/basil/firmware/modules/cmd_seq/README.rst index 947b11656..f694b9dd7 100644 --- a/basil/firmware/modules/cmd_seq/README.rst +++ b/basil/firmware/modules/cmd_seq/README.rst @@ -3,5 +3,4 @@ **cmd_seq** - Command generator (FE-I4) ========================================= -Generate arbitrary single bit data stream and clock (mainly to generate FE-I4 commands). Supports hardware loops and Manchester data encoding. - +Generate arbitrary single bit data stream and clock (mainly to generate FE-I4 commands). Supports hardware loops and Manchester data encoding. diff --git a/basil/firmware/modules/fast_spi_rx/README.rst b/basil/firmware/modules/fast_spi_rx/README.rst index 1816c3560..160ec45e5 100644 --- a/basil/firmware/modules/fast_spi_rx/README.rst +++ b/basil/firmware/modules/fast_spi_rx/README.rst @@ -3,4 +3,4 @@ **fast_spi_rx** - Fast SPI receiver ===================================== -Allows continuous serial data receive. Received data are propagated to FIFO data interface. +Allows continuous serial data receive. Received data are propagated to FIFO data interface. diff --git a/basil/firmware/modules/fei4_rx/README.rst b/basil/firmware/modules/fei4_rx/README.rst index 12d8140a2..8704c7223 100644 --- a/basil/firmware/modules/fei4_rx/README.rst +++ b/basil/firmware/modules/fei4_rx/README.rst @@ -3,5 +3,5 @@ **fei4_rx** - FE-I4 data receiver ===================================== -Allows continuous data recording from FE-I4. Received data are propagated to FIFO data interface. +Allows continuous data recording from FE-I4. Received data are propagated to FIFO data interface. Implements auto synchronization and data error monitoring. diff --git a/basil/firmware/modules/gpac_adc_rx/README.rst b/basil/firmware/modules/gpac_adc_rx/README.rst index db2f23028..0c1ffb2a4 100644 --- a/basil/firmware/modules/gpac_adc_rx/README.rst +++ b/basil/firmware/modules/gpac_adc_rx/README.rst @@ -3,4 +3,4 @@ **gpac_adc_rx** - ADC receiver (GPAC) ===================================== -Received data are propagated to FIFO data interface. +Received data are propagated to FIFO data interface. diff --git a/basil/firmware/modules/gpio/README.rst b/basil/firmware/modules/gpio/README.rst index 20e2cab61..0a6092118 100644 --- a/basil/firmware/modules/gpio/README.rst +++ b/basil/firmware/modules/gpio/README.rst @@ -3,41 +3,41 @@ **gpio** - General purpose IO ============================= -General purpose input output (gpio) is a generic pins whose behavior, including whether it is an input or output pin, can be controlled by the user at run time. +General purpose input output (gpio) is a generic pins whose behavior, including whether it is an input or output pin, can be controlled by the user at run time. -**Unit test/Example:** -`test_SimGpio.v `_ +**Unit test/Example:** +`test_SimGpio.v `_ `test_SimGpio.py `_ **Parameters:** - +--------------+---------------------+-----------------------------------------------------------------+ - | Name | Default | Description | - +==============+=====================+=================================================================+ - | IO_WIDTH | 8 | Defines io width in bits | - +--------------+---------------------+-----------------------------------------------------------------+ + +--------------+---------------------+-----------------------------------------------------------------+ + | Name | Default | Description | + +==============+=====================+=================================================================+ + | IO_WIDTH | 8 | Defines io width in bits | + +--------------+---------------------+-----------------------------------------------------------------+ | IO_DIRECTION | 0 | Defines direction for every pin separate, 0 - input, 1 - output | - +--------------+---------------------+-----------------------------------------------------------------+ + +--------------+---------------------+-----------------------------------------------------------------+ | IO_TRI | 0 | instantiate tri-state buffer for given pin | - +--------------+---------------------+-----------------------------------------------------------------+ + +--------------+---------------------+-----------------------------------------------------------------+ **Pins:** - +--------------+---------------------+-----------------------+-----------------------------------------+ - | Name | Size | Direction | Description | - +==============+=====================+=================================================================+ - | IO | IO_WIDTH | IO_DIRECTION/IO_TRI | General purpose pins | - +--------------+---------------------+-----------------------------------------------------------------+ + +--------------+---------------------+-----------------------+-----------------------------------------+ + | Name | Size | Direction | Description | + +==============+=====================+=================================================================+ + | IO | IO_WIDTH | IO_DIRECTION/IO_TRI | General purpose pins | + +--------------+---------------------+-----------------------------------------------------------------+ **Registers:** - +------------+---------------------+----------------------------------------+ - | Name | Address | Description | - +============+=====================+========================================+ - | RESET | 0 | Soft reset active on write to address | - +------------+---------------------+----------------------------------------+ + +------------+---------------------+----------------------------------------+ + | Name | Address | Description | + +============+=====================+========================================+ + | RESET | 0 | Soft reset active on write to address | + +------------+---------------------+----------------------------------------+ | INPUT | 1 to BYTE | Readback of state of pin | - +------------+---------------------+----------------------------------------+ + +------------+---------------------+----------------------------------------+ | OUTPUT | 1+BYTE to 2*BYTE | Set output state on pin | - +------------+---------------------+----------------------------------------+ - | DIRECTION | 1+2*BYTE to 3*BYTE | Tri-state pin (if enabled) | + +------------+---------------------+----------------------------------------+ + | DIRECTION | 1+2*BYTE to 3*BYTE | Tri-state pin (if enabled) | +------------+---------------------+----------------------------------------+ Where: BYTE = IO_WIDTH/8+1 diff --git a/basil/firmware/modules/gpio/gpio_core.v b/basil/firmware/modules/gpio/gpio_core.v index 44e800ae4..47a36905c 100644 --- a/basil/firmware/modules/gpio/gpio_core.v +++ b/basil/firmware/modules/gpio/gpio_core.v @@ -4,7 +4,7 @@ * SiLab, Institute of Physics, University of Bonn * ------------------------------------------------------------ */ - + module gpio_core #( parameter ABUSWIDTH = 16, parameter IO_WIDTH = 8, diff --git a/basil/firmware/modules/jtag_master/README.rst b/basil/firmware/modules/jtag_master/README.rst index 143743b91..63343c0a7 100644 --- a/basil/firmware/modules/jtag_master/README.rst +++ b/basil/firmware/modules/jtag_master/README.rst @@ -5,55 +5,55 @@ Module implements master jtag peripheral interface. Supports simple internal loops. -**Unit test/Example:** -`test_SimJtagMaster.v `_ +**Unit test/Example:** +`test_SimJtagMaster.v `_ `test_SimJtagMaster.py `_ **Parameters:** - +--------------+---------------------+-------------------------------------------------------------------------+ - | Name | Default | Description | - +==============+=====================+=========================================================================+ - | MEM_BYTES | 16 | Amount of meemory allocated for data (maximum single transfer in bytes) | - +--------------+---------------------+-------------------------------------------------------------------------+ + +--------------+---------------------+-------------------------------------------------------------------------+ + | Name | Default | Description | + +==============+=====================+=========================================================================+ + | MEM_BYTES | 16 | Amount of meemory allocated for data (maximum single transfer in bytes) | + +--------------+---------------------+-------------------------------------------------------------------------+ **Pins:** - +--------------+---------------------+-----------------------+------------------------------------------------------+ - | Name | Size | Direction | Description | - +==============+=====================+=======================+======================================================+ - | JTAG_CLK | 1 | input | clock used for SPI transfers | - +--------------+---------------------+-----------------------+------------------------------------------------------+ - | TCK | 1 | output | external clock (active only during transfers) | - +--------------+---------------------+-----------------------+------------------------------------------------------+ - | TDO | 1 | input | incoming data | - +--------------+---------------------+-----------------------+------------------------------------------------------+ - | TDI | 1 | output | outgoing data | - +--------------+---------------------+-----------------------+------------------------------------------------------+ - | TMS | 1 | output | jtag machine state control pin | - +--------------+---------------------+-----------------------+------------------------------------------------------+ - | SEN | 1 | output | active high during transfer | - +--------------+---------------------+-----------------------+------------------------------------------------------+ - | SLD | 1 | output | active high strobe indicating end of transfer | - +--------------+---------------------+-----------------------+------------------------------------------------------+ - + +--------------+---------------------+-----------------------+------------------------------------------------------+ + | Name | Size | Direction | Description | + +==============+=====================+=======================+======================================================+ + | JTAG_CLK | 1 | input | clock used for SPI transfers | + +--------------+---------------------+-----------------------+------------------------------------------------------+ + | TCK | 1 | output | external clock (active only during transfers) | + +--------------+---------------------+-----------------------+------------------------------------------------------+ + | TDO | 1 | input | incoming data | + +--------------+---------------------+-----------------------+------------------------------------------------------+ + | TDI | 1 | output | outgoing data | + +--------------+---------------------+-----------------------+------------------------------------------------------+ + | TMS | 1 | output | jtag machine state control pin | + +--------------+---------------------+-----------------------+------------------------------------------------------+ + | SEN | 1 | output | active high during transfer | + +--------------+---------------------+-----------------------+------------------------------------------------------+ + | SLD | 1 | output | active high strobe indicating end of transfer | + +--------------+---------------------+-----------------------+------------------------------------------------------+ + **Registers:** - +--------------+-----------------------------------+--------+-------+-------------+---------------------------------------------------------+ - | Name | Address | Bits | r/w | Default | Description | - +==============+===================================+========+=======+=============+=========================================================+ - | START | 1 | | wo | | start transfer on write to address | - +--------------+-----------------------------------+--------+-------+-------------+---------------------------------------------------------+ - | DONE | 1 | [0] | ro | 0 | indicate transfer finish | - +--------------+-----------------------------------+--------+-------+-------------+---------------------------------------------------------+ - | BIT_OUT | 4 - 3 | [15:0] | r/w | MEM_BYTES*8 | set the size of transfer in bits | - +--------------+-----------------------------------+--------+-------+-------------+---------------------------------------------------------+ - | WAIT | 8 - 5 | [31:0] | r/w | 4 | waits after every transfer if REPEAT != 0 | - +--------------+-----------------------------------+--------+-------+-------------+---------------------------------------------------------+ - | WORD_COUNT | 10 - 9 | [15:0] | r/w | 1 | number of word to be sent (1 word = BIT_OUT bit long) | - +--------------+-----------------------------------+--------+-------+-------------+---------------------------------------------------------+ - | JTAG COMMAND | 12 - 11 | [15:0] | r/w | 0 | JTAG command 0 = SCAN_IR, 1 = SCAN_DR | - +--------------+-----------------------------------+--------+-------+-------------+---------------------------------------------------------+ - | MEM_BYTES | 15 - 14 | [15:0] | ro | MEM_BYTES | byte size of memory | - +--------------+-----------------------------------+--------+-------+-------------+---------------------------------------------------------+ - | DATA_OUT | 16 to 16+MEM_BYTES-1 | | r/w | unknown | memory for outgoing data | - +--------------+-----------------------------------+--------+-------+-------------+---------------------------------------------------------+ - | DATA_IN | 16+MEM_BYTES to 16+2*MEM_BYTES-1 | | r/w | unknown | memory for incoming data | - +--------------+-----------------------------------+--------+-------+-------------+---------------------------------------------------------+ \ No newline at end of file + +--------------+-----------------------------------+--------+-------+-------------+---------------------------------------------------------+ + | Name | Address | Bits | r/w | Default | Description | + +==============+===================================+========+=======+=============+=========================================================+ + | START | 1 | | wo | | start transfer on write to address | + +--------------+-----------------------------------+--------+-------+-------------+---------------------------------------------------------+ + | DONE | 1 | [0] | ro | 0 | indicate transfer finish | + +--------------+-----------------------------------+--------+-------+-------------+---------------------------------------------------------+ + | BIT_OUT | 4 - 3 | [15:0] | r/w | MEM_BYTES*8 | set the size of transfer in bits | + +--------------+-----------------------------------+--------+-------+-------------+---------------------------------------------------------+ + | WAIT | 8 - 5 | [31:0] | r/w | 4 | waits after every transfer if REPEAT != 0 | + +--------------+-----------------------------------+--------+-------+-------------+---------------------------------------------------------+ + | WORD_COUNT | 10 - 9 | [15:0] | r/w | 1 | number of word to be sent (1 word = BIT_OUT bit long) | + +--------------+-----------------------------------+--------+-------+-------------+---------------------------------------------------------+ + | JTAG COMMAND | 12 - 11 | [15:0] | r/w | 0 | JTAG command 0 = SCAN_IR, 1 = SCAN_DR | + +--------------+-----------------------------------+--------+-------+-------------+---------------------------------------------------------+ + | MEM_BYTES | 15 - 14 | [15:0] | ro | MEM_BYTES | byte size of memory | + +--------------+-----------------------------------+--------+-------+-------------+---------------------------------------------------------+ + | DATA_OUT | 16 to 16+MEM_BYTES-1 | | r/w | unknown | memory for outgoing data | + +--------------+-----------------------------------+--------+-------+-------------+---------------------------------------------------------+ + | DATA_IN | 16+MEM_BYTES to 16+2*MEM_BYTES-1 | | r/w | unknown | memory for incoming data | + +--------------+-----------------------------------+--------+-------+-------------+---------------------------------------------------------+ diff --git a/basil/firmware/modules/jtag_master/jtag_master_core.v b/basil/firmware/modules/jtag_master/jtag_master_core.v index 5cc3f90fd..418769896 100644 --- a/basil/firmware/modules/jtag_master/jtag_master_core.v +++ b/basil/firmware/modules/jtag_master/jtag_master_core.v @@ -172,15 +172,15 @@ assign memout_addrb = (out_word_cnt * CONF_BIT_OUT) + CONF_BIT_OUT - 1 - out_bit ramb_8_to_n #(.SIZE(MEM_BYTES), .WIDTH(1)) memout ( -.clkA(BUS_CLK), -.clkB(JTAG_CLK), -.weA(BUS_WR && BUS_ADD >= 16 && BUS_ADD < 16+MEM_BYTES), -.weB(1'b0), -.addrA(memout_addra), -.addrB(memout_addrb), -.diA(BUS_DATA_IN_IB), -.doA(BUS_IN_MEM_IB), -.diB(), +.clkA(BUS_CLK), +.clkB(JTAG_CLK), +.weA(BUS_WR && BUS_ADD >= 16 && BUS_ADD < 16+MEM_BYTES), +.weB(1'b0), +.addrA(memout_addra), +.addrB(memout_addrb), +.diA(BUS_DATA_IN_IB), +.doA(BUS_IN_MEM_IB), +.diB(), .doB(SDI_MEM) ); @@ -191,15 +191,15 @@ assign ADDRB_MIN = (out_word_cnt * CONF_BIT_OUT) + CONF_BIT_OUT - out_bit_cnt; reg SEN_INT; ramb_8_to_n #(.SIZE(MEM_BYTES), .WIDTH(1)) memin ( - .clkA(BUS_CLK), - .clkB(JTAG_CLK), - .weA(1'b0), - .weB(SEN_INT && (state == SHIFT_DR || state == SHIFT_IR)), - .addrA(ADDRA_MIN), - .addrB(ADDRB_MIN), - .diA(BUS_DATA_IN_IB), - .doA(BUS_OUT_MEM_IB), - .diB(TDO), + .clkA(BUS_CLK), + .clkB(JTAG_CLK), + .weA(1'b0), + .weB(SEN_INT && (state == SHIFT_DR || state == SHIFT_IR)), + .addrA(ADDRA_MIN), + .addrB(ADDRB_MIN), + .diA(BUS_DATA_IN_IB), + .doA(BUS_OUT_MEM_IB), + .diB(TDO), .doB() ); diff --git a/basil/firmware/modules/m26_rx/README.rst b/basil/firmware/modules/m26_rx/README.rst index 473b3f6b5..021df9fac 100644 --- a/basil/firmware/modules/m26_rx/README.rst +++ b/basil/firmware/modules/m26_rx/README.rst @@ -3,5 +3,5 @@ **m26_rx** - MIMOSA26 data receiver ===================================== -Allows continuous data recording from MIMOSA26. Received data are propagated to FIFO data interface. +Allows continuous data recording from MIMOSA26. Received data are propagated to FIFO data interface. Implements error monitoring. diff --git a/basil/firmware/modules/pulse_gen/README.rst b/basil/firmware/modules/pulse_gen/README.rst index 370c2a50f..0c7c3b112 100644 --- a/basil/firmware/modules/pulse_gen/README.rst +++ b/basil/firmware/modules/pulse_gen/README.rst @@ -5,35 +5,34 @@ Simple pulse generator with configurable delay and width. -**Unit test/Example:** -`test_SimSeq.v `_ +**Unit test/Example:** +`test_SimSeq.v `_ `test_SimSeq.py `_ **Pins:** - +---------------+---------------------+-----------------------+------------------------------------------------------+ - | Name | Size | Direction | Description | - +===============+=====================+=======================+======================================================+ - | EXT_START | 1 | input | active high start signal (synchronous to PULSE_CLK) | - +---------------+---------------------+-----------------------+------------------------------------------------------+ - | PULSE_CLK | 1 | input | module clock | - +---------------+---------------------+-----------------------+------------------------------------------------------+ - | PULSE | 1 | output | output pulse | - +---------------+---------------------+-----------------------+------------------------------------------------------+ - + +---------------+---------------------+-----------------------+------------------------------------------------------+ + | Name | Size | Direction | Description | + +===============+=====================+=======================+======================================================+ + | EXT_START | 1 | input | active high start signal (synchronous to PULSE_CLK) | + +---------------+---------------------+-----------------------+------------------------------------------------------+ + | PULSE_CLK | 1 | input | module clock | + +---------------+---------------------+-----------------------+------------------------------------------------------+ + | PULSE | 1 | output | output pulse | + +---------------+---------------------+-----------------------+------------------------------------------------------+ + **Registers:** - +---------------+----------------------------------+--------+-------+-------------+--------------------------------------------------------------------------------------------+ - | Name | Address | Bits | r/w | Default | Description | - +===============+==================================+========+=======+=============+============================================================================================+ - | START | 1 | | wo | | software start on write to address | - +---------------+----------------------------------+--------+-------+-------------+--------------------------------------------------------------------------------------------+ - | READY | 1 | [0] | ro | 0 | indicate finish | - +---------------+----------------------------------+--------+-------+-------------+--------------------------------------------------------------------------------------------+ - | EN | 2 | [0] | r/w | 0 | enable external start | - +---------------+----------------------------------+--------+-------+-------------+--------------------------------------------------------------------------------------------+ - | DELAY | 6 - 3 | [31:0] | r/w | 0 | pulse delay from start | - +---------------+----------------------------------+--------+-------+-------------+--------------------------------------------------------------------------------------------+ - | WIDTH | 10 - 7 | [31:0] | r/w | 0 | pulse width | - +---------------+----------------------------------+--------+-------+-------------+--------------------------------------------------------------------------------------------+ - | REPEAT | 11 - 14 | [31:0] | r/w | 1 | repeat count (0 ->forever) | - +---------------+----------------------------------+--------+-------+-------------+--------------------------------------------------------------------------------------------+ - + +---------------+----------------------------------+--------+-------+-------------+--------------------------------------------------------------------------------------------+ + | Name | Address | Bits | r/w | Default | Description | + +===============+==================================+========+=======+=============+============================================================================================+ + | START | 1 | | wo | | software start on write to address | + +---------------+----------------------------------+--------+-------+-------------+--------------------------------------------------------------------------------------------+ + | READY | 1 | [0] | ro | 0 | indicate finish | + +---------------+----------------------------------+--------+-------+-------------+--------------------------------------------------------------------------------------------+ + | EN | 2 | [0] | r/w | 0 | enable external start | + +---------------+----------------------------------+--------+-------+-------------+--------------------------------------------------------------------------------------------+ + | DELAY | 6 - 3 | [31:0] | r/w | 0 | pulse delay from start | + +---------------+----------------------------------+--------+-------+-------------+--------------------------------------------------------------------------------------------+ + | WIDTH | 10 - 7 | [31:0] | r/w | 0 | pulse width | + +---------------+----------------------------------+--------+-------+-------------+--------------------------------------------------------------------------------------------+ + | REPEAT | 11 - 14 | [31:0] | r/w | 1 | repeat count (0 ->forever) | + +---------------+----------------------------------+--------+-------+-------------+--------------------------------------------------------------------------------------------+ diff --git a/basil/firmware/modules/rrp_arbiter/README.rst b/basil/firmware/modules/rrp_arbiter/README.rst index 2524bf673..180722cfb 100644 --- a/basil/firmware/modules/rrp_arbiter/README.rst +++ b/basil/firmware/modules/rrp_arbiter/README.rst @@ -6,28 +6,27 @@ Round-robin arbiter for data (32 bit) streams with priority. Data streams multiplexer. **Parameters:** - +--------------+---------------------+-------------------------------------------------------------------------+ - | Name | Default | Description | - +==============+=====================+=========================================================================+ - | WIDTH | 4 | Number of incoming data streams | - +--------------+---------------------+-------------------------------------------------------------------------+ + +--------------+---------------------+-------------------------------------------------------------------------+ + | Name | Default | Description | + +==============+=====================+=========================================================================+ + | WIDTH | 4 | Number of incoming data streams | + +--------------+---------------------+-------------------------------------------------------------------------+ **Pins:** - +--------------+---------------------+-----------------------+------------------------------------------------------+ - | Name | Size | Direction | Description | - +==============+=====================+=======================+======================================================+ - | WRITE_REQ | WIDTH | input | indicate will of writing data | - +--------------+---------------------+-----------------------+------------------------------------------------------+ - | HOLD_REQ | WIDTH | input | wait for writing for given stream (priority) | - +--------------+---------------------+-----------------------+------------------------------------------------------+ - | DATA_IN | WIDTH*32 | input | incoming data for arbitration | - +--------------+---------------------+-----------------------+------------------------------------------------------+ - | READ_GRANT | WIDTH | output | indicate to stream that data has been accepted | - +--------------+---------------------+-----------------------+------------------------------------------------------+ - | READY_OUT | 1 | input | indicate ready for outgoing stream | - +--------------+---------------------+-----------------------+------------------------------------------------------+ - | WRITE_OUT | 1 | output | indicate will of write to outgoing stream | - +--------------+---------------------+-----------------------+------------------------------------------------------+ - | DATA_OUT | 32 | output | outgoing data stream | - +--------------+---------------------+-----------------------+------------------------------------------------------+ - \ No newline at end of file + +--------------+---------------------+-----------------------+------------------------------------------------------+ + | Name | Size | Direction | Description | + +==============+=====================+=======================+======================================================+ + | WRITE_REQ | WIDTH | input | indicate will of writing data | + +--------------+---------------------+-----------------------+------------------------------------------------------+ + | HOLD_REQ | WIDTH | input | wait for writing for given stream (priority) | + +--------------+---------------------+-----------------------+------------------------------------------------------+ + | DATA_IN | WIDTH*32 | input | incoming data for arbitration | + +--------------+---------------------+-----------------------+------------------------------------------------------+ + | READ_GRANT | WIDTH | output | indicate to stream that data has been accepted | + +--------------+---------------------+-----------------------+------------------------------------------------------+ + | READY_OUT | 1 | input | indicate ready for outgoing stream | + +--------------+---------------------+-----------------------+------------------------------------------------------+ + | WRITE_OUT | 1 | output | indicate will of write to outgoing stream | + +--------------+---------------------+-----------------------+------------------------------------------------------+ + | DATA_OUT | 32 | output | outgoing data stream | + +--------------+---------------------+-----------------------+------------------------------------------------------+ diff --git a/basil/firmware/modules/seq_gen/README.rst b/basil/firmware/modules/seq_gen/README.rst index a6e757375..1a0497f30 100644 --- a/basil/firmware/modules/seq_gen/README.rst +++ b/basil/firmware/modules/seq_gen/README.rst @@ -6,30 +6,30 @@ Module implements a simple sequencer/pattern generator base on block ram. Supports 2 levels of internal loops and external start. For OUT_BITS != 8 user need to provide block memory module (seq_gen_blk_mem) with proper size. -**Unit test/Example:** -`test_SimSeq.v `_ +**Unit test/Example:** +`test_SimSeq.v `_ `test_SimSeq.py `_ **Parameters:** - +--------------+---------------------+-------------------------------------------------------------------------+ - | Name | Default | Description | - +==============+=====================+=========================================================================+ - | MEM_BYTES | 16384 | Amount of memory allocated for data (in bytes) | - +--------------+---------------------+-------------------------------------------------------------------------+ - | OUT_BITS | 8 | Size (bit) for output pattern - word size | - +--------------+---------------------+-------------------------------------------------------------------------+ - + +--------------+---------------------+-------------------------------------------------------------------------+ + | Name | Default | Description | + +==============+=====================+=========================================================================+ + | MEM_BYTES | 16384 | Amount of memory allocated for data (in bytes) | + +--------------+---------------------+-------------------------------------------------------------------------+ + | OUT_BITS | 8 | Size (bit) for output pattern - word size | + +--------------+---------------------+-------------------------------------------------------------------------+ + **Pins:** - +---------------+---------------------+-----------------------+------------------------------------------------------+ - | Name | Size | Direction | Description | - +===============+=====================+=======================+======================================================+ - | SEQ_EXT_START | 1 | input | external start signal (synchronous to SEQ_CLK) | - +---------------+---------------------+-----------------------+------------------------------------------------------+ - | SEQ_CLK | 1 | input | external clock used for friving sequence | - +---------------+---------------------+-----------------------+------------------------------------------------------+ - | SEQ_OUT | OUT_BITS | output | sequencer output | - +---------------+---------------------+-----------------------+------------------------------------------------------+ - + +---------------+---------------------+-----------------------+------------------------------------------------------+ + | Name | Size | Direction | Description | + +===============+=====================+=======================+======================================================+ + | SEQ_EXT_START | 1 | input | external start signal (synchronous to SEQ_CLK) | + +---------------+---------------------+-----------------------+------------------------------------------------------+ + | SEQ_CLK | 1 | input | external clock used for friving sequence | + +---------------+---------------------+-----------------------+------------------------------------------------------+ + | SEQ_OUT | OUT_BITS | output | sequencer output | + +---------------+---------------------+-----------------------+------------------------------------------------------+ + **Registers:** +---------------+----------------------------------+--------+-------+-------------+--------------------------------------------------------------------------------------------+ | Name | Address | Bits | r/w | Default | Description | @@ -60,4 +60,3 @@ For OUT_BITS != 8 user need to provide block memory module (seq_gen_blk_mem) wit +---------------+----------------------------------+--------+-------+-------------+--------------------------------------------------------------------------------------------+ | DATA | 64 to 64+MEM_BYTES-1 | | r/w | unknown | memory for pattern | +---------------+----------------------------------+--------+-------+-------------+--------------------------------------------------------------------------------------------+ - diff --git a/basil/firmware/modules/seq_gen/seq_gen_core.v b/basil/firmware/modules/seq_gen/seq_gen_core.v index 3d39836fe..c81a69542 100644 --- a/basil/firmware/modules/seq_gen/seq_gen_core.v +++ b/basil/firmware/modules/seq_gen/seq_gen_core.v @@ -193,14 +193,14 @@ wire WEA; assign WEA = BUS_WR && BUS_ADD >=MEM_OFFSET && BUS_ADD < MEM_OFFSET+MEM_BYTES; ramb_8_to_n #(.SIZE(MEM_BYTES), .WIDTH(OUT_BITS)) mem ( - .clkA(BUS_CLK), - .clkB(SEQ_CLK), - .weA(WEA), - .weB(1'b0), - .addrA(memout_addra), - .addrB(memout_addrb), - .diA(BUS_DATA_IN), - .doA(BUS_IN_MEM), + .clkA(BUS_CLK), + .clkB(SEQ_CLK), + .weA(WEA), + .weB(1'b0), + .addrA(memout_addra), + .addrB(memout_addrb), + .diA(BUS_DATA_IN), + .doA(BUS_IN_MEM), .diB({OUT_BITS{1'b0}}), .doB(SEQ_OUT_MEM) ); diff --git a/basil/firmware/modules/seq_rec/README.rst b/basil/firmware/modules/seq_rec/README.rst index dbb355097..4560bcb8a 100644 --- a/basil/firmware/modules/seq_rec/README.rst +++ b/basil/firmware/modules/seq_rec/README.rst @@ -5,6 +5,6 @@ Simple module that allow recording arbitrary data vector. -**Unit test/Example:** -`test_SimSeq.v `_ +**Unit test/Example:** +`test_SimSeq.v `_ `test_SimSeq.py `_ diff --git a/basil/firmware/modules/seq_rec/seq_rec_core.v b/basil/firmware/modules/seq_rec/seq_rec_core.v index 1facd724b..f5e8f35b2 100644 --- a/basil/firmware/modules/seq_rec/seq_rec_core.v +++ b/basil/firmware/modules/seq_rec/seq_rec_core.v @@ -155,14 +155,14 @@ wire WEA, WEB; assign WEA = BUS_WR && BUS_ADD >=16 && BUS_ADD < 16 + MEM_BYTES && !WEB; ramb_8_to_n #(.SIZE(MEM_BYTES), .WIDTH(IN_BITS)) mem ( - .clkA(BUS_CLK), - .clkB(SEQ_CLK), - .weA(WEA), - .weB(WEB), - .addrA(memout_addra), - .addrB(memout_addrb), - .diA(BUS_DATA_IN), - .doA(BUS_IN_MEM), + .clkA(BUS_CLK), + .clkB(SEQ_CLK), + .weA(WEA), + .weB(WEB), + .addrA(memout_addra), + .addrB(memout_addrb), + .diA(BUS_DATA_IN), + .doA(BUS_IN_MEM), .diB(SEQ_IN), .doB() ); diff --git a/basil/firmware/modules/spi/README.rst b/basil/firmware/modules/spi/README.rst index b11fd5d83..e8f888be3 100644 --- a/basil/firmware/modules/spi/README.rst +++ b/basil/firmware/modules/spi/README.rst @@ -5,8 +5,8 @@ Module implements master serial peripheral interface. Supports simple internal loops. -**Unit test/Example:** -`test_SimSpi.v `_ +**Unit test/Example:** +`test_SimSpi.v `_ `test_SimSpi.py `_ **Parameters:** @@ -17,43 +17,43 @@ Module implements master serial peripheral interface. Supports simple internal l +--------------+---------------------+------------------------------------------------------------------------+ **Pins:** - +--------------+---------------------+-----------------------+------------------------------------------------------+ - | Name | Size | Direction | Description | - +==============+=====================+=======================+======================================================+ - | SPI_CLK | 1 | input | clock used for SPI transfers | - +--------------+---------------------+-----------------------+------------------------------------------------------+ - | SCLK | 1 | output | external clock (active only during transfers) | - +--------------+---------------------+-----------------------+------------------------------------------------------+ - | SDO | 1 | input | incoming data | - +--------------+---------------------+-----------------------+------------------------------------------------------+ - | SDI | 1 | output | outgoing data | - +--------------+---------------------+-----------------------+------------------------------------------------------+ - | SEN | 1 | output | active high during transfer | - +--------------+---------------------+-----------------------+------------------------------------------------------+ - | SLD | 1 | output | active high strobe indicating end of transfer | - +--------------+---------------------+-----------------------+------------------------------------------------------+ - | EXT_START | 1 | input | active high start signal (synchronous to SPI_CLK) | - +--------------+---------------------+-----------------------+------------------------------------------------------+ - + +--------------+---------------------+-----------------------+------------------------------------------------------+ + | Name | Size | Direction | Description | + +==============+=====================+=======================+======================================================+ + | SPI_CLK | 1 | input | clock used for SPI transfers | + +--------------+---------------------+-----------------------+------------------------------------------------------+ + | SCLK | 1 | output | external clock (active only during transfers) | + +--------------+---------------------+-----------------------+------------------------------------------------------+ + | SDO | 1 | input | incoming data | + +--------------+---------------------+-----------------------+------------------------------------------------------+ + | SDI | 1 | output | outgoing data | + +--------------+---------------------+-----------------------+------------------------------------------------------+ + | SEN | 1 | output | active high during transfer | + +--------------+---------------------+-----------------------+------------------------------------------------------+ + | SLD | 1 | output | active high strobe indicating end of transfer | + +--------------+---------------------+-----------------------+------------------------------------------------------+ + | EXT_START | 1 | input | active high start signal (synchronous to SPI_CLK) | + +--------------+---------------------+-----------------------+------------------------------------------------------+ + **Registers:** - +--------------+----------------------------------+--------+-------+-------------+---------------------------------------------+ - | Name | Address | Bits | r/w | Default | Description | - +==============+==================================+========+=======+=============+=============================================+ - | START | 1 | | wo | | start transfer on write to address | - +--------------+----------------------------------+--------+-------+-------------+---------------------------------------------+ - | DONE | 1 | [0] | ro | 0 | indicate transfer finish | - +--------------+----------------------------------+--------+-------+-------------+---------------------------------------------+ - | BIT_OUT | 4 - 3 | [15:0] | r/w | MEM_BYTES*8 | set the size of transfer in bits | - +--------------+----------------------------------+--------+-------+-------------+---------------------------------------------+ - | WAIT | 8 - 5 | [31:0] | r/w | 4 | waits after every transfer if REPEAT != 0 | - +--------------+----------------------------------+--------+-------+-------------+---------------------------------------------+ - | REPEAT | 12 - 9 | [31:0] | r/w | 1 | repeat transfer count (0 -> forever) | - +--------------+----------------------------------+--------+-------+-------------+---------------------------------------------+ - | CONF_EN | 13 | [0] | r/w | 0 | enable external start (0-> soft start only) | - +--------------+----------------------------------+--------+-------+-------------+---------------------------------------------+ - | MEM_BYTES | 15 - 14 | [15:0] | ro | MEM_BYTES | byte size of memory | - +--------------+----------------------------------+--------+-------+-------------+---------------------------------------------+ - | DATA_OUT | 16 to 16+MEM_BYTES-1 | | r/w | unknown | memory for outgoing data | - +--------------+----------------------------------+--------+-------+-------------+---------------------------------------------+ - | DATA_IN | 16+MEM_BYTES to 16+2*MEM_BYTES-1 | | r/w | unknown | memory for incoming data | - +--------------+----------------------------------+--------+-------+-------------+---------------------------------------------+ + +--------------+----------------------------------+--------+-------+-------------+---------------------------------------------+ + | Name | Address | Bits | r/w | Default | Description | + +==============+==================================+========+=======+=============+=============================================+ + | START | 1 | | wo | | start transfer on write to address | + +--------------+----------------------------------+--------+-------+-------------+---------------------------------------------+ + | DONE | 1 | [0] | ro | 0 | indicate transfer finish | + +--------------+----------------------------------+--------+-------+-------------+---------------------------------------------+ + | BIT_OUT | 4 - 3 | [15:0] | r/w | MEM_BYTES*8 | set the size of transfer in bits | + +--------------+----------------------------------+--------+-------+-------------+---------------------------------------------+ + | WAIT | 8 - 5 | [31:0] | r/w | 4 | waits after every transfer if REPEAT != 0 | + +--------------+----------------------------------+--------+-------+-------------+---------------------------------------------+ + | REPEAT | 12 - 9 | [31:0] | r/w | 1 | repeat transfer count (0 -> forever) | + +--------------+----------------------------------+--------+-------+-------------+---------------------------------------------+ + | CONF_EN | 13 | [0] | r/w | 0 | enable external start (0-> soft start only) | + +--------------+----------------------------------+--------+-------+-------------+---------------------------------------------+ + | MEM_BYTES | 15 - 14 | [15:0] | ro | MEM_BYTES | byte size of memory | + +--------------+----------------------------------+--------+-------+-------------+---------------------------------------------+ + | DATA_OUT | 16 to 16+MEM_BYTES-1 | | r/w | unknown | memory for outgoing data | + +--------------+----------------------------------+--------+-------+-------------+---------------------------------------------+ + | DATA_IN | 16+MEM_BYTES to 16+2*MEM_BYTES-1 | | r/w | unknown | memory for incoming data | + +--------------+----------------------------------+--------+-------+-------------+---------------------------------------------+ diff --git a/basil/firmware/modules/spi/blk_mem_gen_8_to_1_2k.v b/basil/firmware/modules/spi/blk_mem_gen_8_to_1_2k.v index 2be1581bb..a14a4eff9 100644 --- a/basil/firmware/modules/spi/blk_mem_gen_8_to_1_2k.v +++ b/basil/firmware/modules/spi/blk_mem_gen_8_to_1_2k.v @@ -1,12 +1,12 @@ /** * ------------------------------------------------------------ - * Copyright (c) All rights reserved + * Copyright (c) All rights reserved * SiLab, Institute of Physics, University of Bonn * ------------------------------------------------------------ */ `timescale 1ps/1ps `default_nettype none - + module blk_mem_gen_8_to_1_2k ( CLKA, CLKB, DOUTA, DOUTB, WEA, WEB, ADDRA, ADDRB, DINA, DINB ); diff --git a/basil/firmware/modules/tb/silbusb.sv b/basil/firmware/modules/tb/silbusb.sv index d6c7bc71a..985521ea8 100644 --- a/basil/firmware/modules/tb/silbusb.sv +++ b/basil/firmware/modules/tb/silbusb.sv @@ -1,26 +1,26 @@ /** * ------------------------------------------------------------ - * Copyright (c) SILAB , Physics Institute of Bonn University + * Copyright (c) SILAB , Physics Institute of Bonn University * ------------------------------------------------------------ * * SVN revision information: * $Rev:: $: - * $Author:: $: + * $Author:: $: * $Date:: $: */ - + interface SiLibUSB (input FCLK); logic RD_B; logic WR_B; tri [7:0] DATA; logic [15:0] ADD; - + logic FREAD; logic FSTROBE; logic FMODE; tri [7:0] FD; - + logic [7:0] DATA_T; assign DATA = ~WR_B ? DATA_T : 8'bzzzz_zzzz; initial begin @@ -30,9 +30,9 @@ interface SiLibUSB (input FCLK); FREAD = 0; FSTROBE = 0; FMODE = 0; - - end - + + end + task ReadExternal; input [15:0] ADDIN; output [7:0] DATAOUT; @@ -82,7 +82,7 @@ interface SiLibUSB (input FCLK); @(posedge FCLK); WR_B = 1; ADD = 16'hxxxx; - DATA_T = 16'hxxxx; + DATA_T = 16'hxxxx; repeat (5) @(posedge FCLK); @@ -99,8 +99,6 @@ interface SiLibUSB (input FCLK); #1 FREAD <= 0; FSTROBE = 0; @(posedge FCLK); end - endtask - + endtask + endinterface - - \ No newline at end of file diff --git a/basil/firmware/modules/tdl_tdc/Readme.rst b/basil/firmware/modules/tdl_tdc/Readme.rst index e80af62c7..72028042e 100644 --- a/basil/firmware/modules/tdl_tdc/Readme.rst +++ b/basil/firmware/modules/tdl_tdc/Readme.rst @@ -31,11 +31,11 @@ Before every experiment, the Tdc should be calibrated, ideally after it had time chip['TDL_TDC'].EN_CALIBRATION_MOD = 0 - + This will cause the Tdc to write many ``CALIB`` words to the fifo. Subsequently any required configuration bits for the particular experiment may be set. During analysis the recorded calibration stream is easily incorporated:: - + calib_data_indices = chip['TDL_TDC'].is_calib_word(collected_data) if any(calib_data_indices) : @@ -48,7 +48,7 @@ Optionally, you can view a histogram of the calibration using ``chip['TDL_TDC']. If measurements are made over a longer time span, recalibration might be necessary, however note that the above example lumps all the calibration(s) in ``collected_data`` together. The calibrated basil module can then be used the following way:: - + time_word_indices = chip['TDL_TDC'].is_time_word(collected_data) time_data = collected_data[time_word_indices] if any(calib_data_indices) : @@ -60,7 +60,7 @@ The calibrated basil module can then be used the following way:: Test module ---------------- -Under ``examples/tdc_bdaq`` you can find an example implementation of the module along side a sequence generator to generate test signals. The TDC uses the external Si570 oscillator while the signal generator uses the external Si550. The script generates pulses of varying trigger distance and creates a plot of the difference of measured and expected time values, alongside errorbars of the standard deviation. +Under ``examples/tdc_bdaq`` you can find an example implementation of the module along side a sequence generator to generate test signals. The TDC uses the external Si570 oscillator while the signal generator uses the external Si550. The script generates pulses of varying trigger distance and creates a plot of the difference of measured and expected time values, alongside errorbars of the standard deviation. **Unit test/Example:** `test_SimTdl_Tlu.v `_ @@ -147,7 +147,7 @@ The Tdc module uses a state machine to send various types of 32 bit data words, +-------------------------+-------------------+---------------------------------------------------------+ The three bit codes for the individual word types can be found in `word_broker.v `_, but the basil driver can decode these without manual effort. The words containing the tdc information are in the following order:: - + [TRIGGERED] -> RISING -> FALLING -> [TIMESTAMP] ``TRIGGERED`` is only sent if ``EN_TRIGGER_DIST``, and ``TIMESTAMP`` only if ``EN_WRITE_TIMESTAMP`` is set. Note however, that this sequence can be interrupted and appear incomplete, for example if the module is reset during a measurement. @@ -192,7 +192,7 @@ If the Tdc is set for self-calibration using ``EN_CALIBRATION_MODE``, it will re RESET ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ If a reset is issued to the Tdc, either as a global bus reset or through basil, this word is sent. It might be useful for resetting a state machine -decoding the words on the receiving end. The Timestamp included is sampled as soon as +decoding the words on the receiving end. The Timestamp included is sampled as soon as the reset signal has passed the clock domain crossing circuitry. +-------------------------------------------------------------------+-----------------------------------+ @@ -212,5 +212,3 @@ In order to sample the delay elements at a high enough rate while still being ab The most distinct design choice in this implementation is that it uses only a single delay line for measuring rising and falling edges of two inputs. As rising and falling edges propagate delay elements differently it makes sense to treat with distinct calibrations or even separate delay lines. To circumvent this additional space requirement and complexity, we use a multiplexer co-ordinating which input, in which polarity, gets seen by the delay elements. This induces a lower bound on width of pulses we can measure as this input multiplexer needs some time to switch between signals. To drive the multiplexer we use a simple state machine, which also drives the word output generation in the ``word_broker`` module. .. image:: architecture.png - - diff --git a/basil/firmware/modules/tdl_tdc/controller.v b/basil/firmware/modules/tdl_tdc/controller.v index 0158b9481..3575f2fef 100644 --- a/basil/firmware/modules/tdl_tdc/controller.v +++ b/basil/firmware/modules/tdl_tdc/controller.v @@ -1,5 +1,5 @@ // Main state machine of the tdc. Contains the logic for switching the -// multiplexer, controling the corse counter, arming, calibration +// multiplexer, controling the corse counter, arming, calibration // states and the trigger distance mode. Furthermore counts successful events // and tdl misses. module controller #( @@ -104,7 +104,7 @@ always @(state, en_write_trigger_distance) begin FAL_EDGE: begin if (en_write_trigger_distance) mux_addr <= TRIG_IN; - else + else mux_addr <= SIG_IN; counter_reset <= 1; counter_count <= 0; @@ -148,7 +148,7 @@ always @(posedge CLK) begin event_cnt <= event_cnt + 1; // This is really a multicycle path: Only every 4 cycles can this occur. end MISSED: - miss_cnt <= miss_cnt + 1; + miss_cnt <= miss_cnt + 1; endcase end @@ -175,7 +175,7 @@ always @(posedge CLK) begin state <= CALIB; end else if (en_write_trigger_distance) begin state <= IDLE_TRIG; - end else if (armed) begin + end else if (armed) begin if (hit) state <= RIS_EDGE; end else begin @@ -187,7 +187,7 @@ always @(posedge CLK) begin state <= CALIB; end else if (~en_write_trigger_distance) begin state <= IDLE; - end else if (armed) begin + end else if (armed) begin if (hit) state <= TRIGGERED; end else begin diff --git a/basil/firmware/modules/tdl_tdc/counter/slimfast_multioption_counter.ucf b/basil/firmware/modules/tdl_tdc/counter/slimfast_multioption_counter.ucf index 638d347a9..ef0694b00 100644 --- a/basil/firmware/modules/tdl_tdc/counter/slimfast_multioption_counter.ucf +++ b/basil/firmware/modules/tdl_tdc/counter/slimfast_multioption_counter.ucf @@ -23,7 +23,7 @@ ##-- -- ##--------------------------------------------------------------------- -TIMEGRP "SFCounter" = ffs("*/SFC_*"); +TIMEGRP "SFCounter" = ffs("*/SFC_*"); TIMESPEC TS_SlimFastCounter = FROM "SFCounter" TO "SFCounter" 40 ns; #set_multicycle_path -setup 15 -from [get_cells -hier *SFC_*] -to [get_cells -hier *SFC_* ] #set_multicycle_path -hold 2 -from [get_cells -hier *SFC_*] -to [get_cells -hier *SFC_* ] diff --git a/basil/firmware/modules/tdl_tdc/counter/slimfast_multioption_counter.v b/basil/firmware/modules/tdl_tdc/counter/slimfast_multioption_counter.v index e97d77193..fd8746a3d 100644 --- a/basil/firmware/modules/tdl_tdc/counter/slimfast_multioption_counter.v +++ b/basil/firmware/modules/tdl_tdc/counter/slimfast_multioption_counter.v @@ -89,7 +89,7 @@ input wire count; input wire reset; input wire [size-3:0] highbits_next; -output wire [size-3:0] highbits_this; +output wire [size-3:0] highbits_this; output wire [outputwidth-1:0] countout; @@ -99,7 +99,7 @@ wire final_reset; reg [2:0] fast_counts = 3'b0; (* KEEP = "true" *) reg [size-3:0] SFC_slow_counts = 'b0; //SFC_ prefix to make this name unique -wire [size-3:0] slow_counts_next; +wire [size-3:0] slow_counts_next; @@ -123,7 +123,7 @@ generate assign final_count = clipped_count; end else begin // I added this, so that one could switch from "clipped" to "not clipped" without changing the number of flip flop stages reg piped_count; - always@(posedge countClock) + always@(posedge countClock) begin piped_count <= count; end @@ -144,7 +144,7 @@ generate if (final_reset == 1'b1) begin - fast_counts <= 0; + fast_counts <= 0; SFC_slow_counts <= 0; end else begin @@ -155,13 +155,13 @@ generate end //-- uses final_count as CE - if (final_count == 1'b1) fast_counts <= fast_counts + 1'b1; + if (final_count == 1'b1) fast_counts <= fast_counts + 1'b1; end end -endgenerate +endgenerate assign countout[outputwidth-1] = SFC_slow_counts[size-3]; assign countout[outputwidth-2:0] = {SFC_slow_counts[size-4:0],fast_counts}; diff --git a/basil/firmware/modules/tdl_tdc/counter/slimfast_multioption_counter.xdc b/basil/firmware/modules/tdl_tdc/counter/slimfast_multioption_counter.xdc index 2423e6333..32aad2d43 100644 --- a/basil/firmware/modules/tdl_tdc/counter/slimfast_multioption_counter.xdc +++ b/basil/firmware/modules/tdl_tdc/counter/slimfast_multioption_counter.xdc @@ -28,4 +28,3 @@ # We should have up to 8 cycles to do this computation, as the fast count has 3 bits set_multicycle_path -setup -from [get_pins -hier *SFC_*/C] -to [get_pins -hier *SFC_*/D] 8; set_multicycle_path -hold -end -from [get_pins -hier *SFC_*/C] -to [get_pins -hier *SFC_*/D] 7; - diff --git a/basil/firmware/modules/tdl_tdc/delayline/carrysampler_spartan6_20ps.v b/basil/firmware/modules/tdl_tdc/delayline/carrysampler_spartan6_20ps.v index 192bd17ab..c8c8c5650 100644 --- a/basil/firmware/modules/tdl_tdc/delayline/carrysampler_spartan6_20ps.v +++ b/basil/firmware/modules/tdl_tdc/delayline/carrysampler_spartan6_20ps.v @@ -30,8 +30,8 @@ module CHAIN_CELL (CINIT, CI, CO, DO, CLK); output wire CO; input wire CI; input wire CLK; - input wire CINIT; - + input wire CINIT; + wire [3:0] carry_out; CARRY4 CARRY4_inst ( @@ -43,7 +43,7 @@ module CHAIN_CELL (CINIT, CI, CO, DO, CLK); .S(4'b1111) // 4-bit carry-MUX select input ); assign CO = carry_out[3]; - + (* BEL = "FFD" *) FDCE #(.INIT(1'b0)) TDL_FF_D (.D(carry_out[3]), .Q(DO[3]), .C(CLK), .CE(1'b1), .CLR(1'b0)); (* BEL = "FFC" *) FDCE #(.INIT(1'b0)) TDL_FF_C (.D(carry_out[2]), .Q(DO[2]), .C(CLK), .CE(1'b1), .CLR(1'b0)); (* BEL = "FFB" *) FDCE #(.INIT(1'b0)) TDL_FF_B (.D(carry_out[1]), .Q(DO[1]), .C(CLK), .CE(1'b1), .CLR(1'b0)); @@ -57,7 +57,7 @@ module carry_sampler_spartan6 (d, q, CLK); parameter bits = 74; parameter resolution = 1; - + input wire d; input wire CLK; output wire [bits-1:0] q; @@ -65,32 +65,32 @@ module carry_sampler_spartan6 (d, q, CLK); `ifndef SIMULATION wire [(bits*resolution/4)-1:0] connect; wire [bits*resolution-1:0] register_out; - + genvar i,j; generate - + CHAIN_CELL FirstCell( .DO({register_out[2],register_out[3],register_out[0],register_out[1]}), .CINIT(d), .CI(1'b0), .CO(connect[0]), .CLK(CLK) - ); - - for (i=1; i < bits*resolution/4; i=i+1) begin : carry_chain + ); + + for (i=1; i < bits*resolution/4; i=i+1) begin : carry_chain CHAIN_CELL MoreCells( .DO({register_out[4*i+2],register_out[4*i+3],register_out[4*i+0],register_out[4*i+1]}), //swapped to avoid empty bins .CINIT(1'b0), .CI(connect[i-1]), .CO(connect[i]), .CLK(CLK) - ); - end + ); + end - for (j=0; j < bits; j=j+1) begin : carry_sampler + for (j=0; j < bits; j=j+1) begin : carry_sampler assign q[j] = register_out[j*resolution]; end - + endgenerate `else reg sim_buffer; @@ -108,5 +108,5 @@ module carry_sampler_spartan6 (d, q, CLK); end assign q = sim_out; `endif - + endmodule diff --git a/basil/firmware/modules/tdl_tdc/delayline/sample_deser.v b/basil/firmware/modules/tdl_tdc/delayline/sample_deser.v index 1392f6965..c98039893 100644 --- a/basil/firmware/modules/tdl_tdc/delayline/sample_deser.v +++ b/basil/firmware/modules/tdl_tdc/delayline/sample_deser.v @@ -47,7 +47,7 @@ assign b = ~internally_rising; // line samples by comparing their respective first and last bits. wire [clk_ratio-1:0] hit_flags; genvar k; -generate +generate for(k=0; k`_ +**Unit test/Example:** +`test_Timestamp.v `_ `test_Timestamp.py `_ **Pins:** - +---------------+---------------------+-----------------------+------------------------------------------------------+ - | Name | Size | Direction | Description | - +===============+=====================+=======================+======================================================+ - | EXT_ENABLE | 1 | input | active high accept DI signal (synchronous to CLK) | - +---------------+---------------------+-----------------------+------------------------------------------------------+ - | CLK | 1 | input | module clock | - +---------------+---------------------+-----------------------+------------------------------------------------------+ - | DI | 1 | input | input signal | - +---------------+---------------------+-----------------------+------------------------------------------------------+ - | EXT_TIMESTAMP | 64 | input | external timestamp timestamp pulse | - +---------------+---------------------+-----------------------+------------------------------------------------------+ - | TIMESTAMP_OUT | 64 | output | | - +---------------+---------------------+-----------------------+------------------------------------------------------+ + +---------------+---------------------+-----------------------+------------------------------------------------------+ + | Name | Size | Direction | Description | + +===============+=====================+=======================+======================================================+ + | EXT_ENABLE | 1 | input | active high accept DI signal (synchronous to CLK) | + +---------------+---------------------+-----------------------+------------------------------------------------------+ + | CLK | 1 | input | module clock | + +---------------+---------------------+-----------------------+------------------------------------------------------+ + | DI | 1 | input | input signal | + +---------------+---------------------+-----------------------+------------------------------------------------------+ + | EXT_TIMESTAMP | 64 | input | external timestamp timestamp pulse | + +---------------+---------------------+-----------------------+------------------------------------------------------+ + | TIMESTAMP_OUT | 64 | output | | + +---------------+---------------------+-----------------------+------------------------------------------------------+ **Registers:** - +---------------+----------------------------------+--------+-------+-------------+----------------------------------------------+ - | Name | Address | Bits | r/w | Default | Description | - +===============+==================================+========+=======+=============+==============================================+ - | EN | 2 | [0] | r/w | | enable module | - +---------------+----------------------------------+--------+-------+-------------+----------------------------------------------+ - | EXT_TIMESTMP | 2 | [1] | r/w | 0 | use external timestamp | - +---------------+----------------------------------+--------+-------+-------------+----------------------------------------------+ - | EXT_ENABLE | 2 | [2] | r/w | 0 | enable external start | - +---------------+----------------------------------+--------+-------+-------------+----------------------------------------------+ + +---------------+----------------------------------+--------+-------+-------------+----------------------------------------------+ + | Name | Address | Bits | r/w | Default | Description | + +===============+==================================+========+=======+=============+==============================================+ + | EN | 2 | [0] | r/w | | enable module | + +---------------+----------------------------------+--------+-------+-------------+----------------------------------------------+ + | EXT_TIMESTMP | 2 | [1] | r/w | 0 | use external timestamp | + +---------------+----------------------------------+--------+-------+-------------+----------------------------------------------+ + | EXT_ENABLE | 2 | [2] | r/w | 0 | enable external start | + +---------------+----------------------------------+--------+-------+-------------+----------------------------------------------+ diff --git a/basil/firmware/modules/tlu/README.rst b/basil/firmware/modules/tlu/README.rst index 9627edae5..73dc74cf1 100644 --- a/basil/firmware/modules/tlu/README.rst +++ b/basil/firmware/modules/tlu/README.rst @@ -135,4 +135,3 @@ DATA_FORMAT[1:0]: +----------------------------------------+----------------------------------+--------+-------+-------------+-------------------------------------------------------+ | TRIGGER_DATA_DELAY | 35 | [7:0] | r/w | 0 | additional TLU data delay for longer cables | +----------------------------------------+----------------------------------+--------+-------+-------------+-------------------------------------------------------+ - diff --git a/basil/firmware/modules/utils/BUFG_sim.v b/basil/firmware/modules/utils/BUFG_sim.v index 26c4c342d..e42bb0e7e 100644 --- a/basil/firmware/modules/utils/BUFG_sim.v +++ b/basil/firmware/modules/utils/BUFG_sim.v @@ -1,6 +1,6 @@ /** * ------------------------------------------------------------ - * Copyright (c) All rights reserved + * Copyright (c) All rights reserved * SiLab, Institute of Physics, University of Bonn * ------------------------------------------------------------ */ @@ -8,7 +8,7 @@ `default_nettype none -module BUFG ( +module BUFG ( input wire I, output wire O ); diff --git a/basil/firmware/modules/utils/IDDR_s3.v b/basil/firmware/modules/utils/IDDR_s3.v index 691052959..1746699c0 100644 --- a/basil/firmware/modules/utils/IDDR_s3.v +++ b/basil/firmware/modules/utils/IDDR_s3.v @@ -1,6 +1,6 @@ /** * ------------------------------------------------------------ - * Copyright (c) All rights reserved + * Copyright (c) All rights reserved * SiLab, Institute of Physics, University of Bonn * ------------------------------------------------------------ */ @@ -9,18 +9,18 @@ module IDDR ( - output wire Q1, Q2, + output wire Q1, Q2, input wire C, CE, D, R, S ); IFDDRRSE IFDDRRSE_inst ( - .Q0(Q1), - .Q1(Q2), - .C0(C), - .C1(~C), - .CE(CE), - .D(D), - .R(R), + .Q0(Q1), + .Q1(Q2), + .C0(C), + .C1(~C), + .CE(CE), + .D(D), + .R(R), .S(S) ); diff --git a/basil/firmware/modules/utils/IDDR_s3_noibuf.v b/basil/firmware/modules/utils/IDDR_s3_noibuf.v index 9e95718c0..b96a51f3c 100644 --- a/basil/firmware/modules/utils/IDDR_s3_noibuf.v +++ b/basil/firmware/modules/utils/IDDR_s3_noibuf.v @@ -1,6 +1,6 @@ /** * ------------------------------------------------------------ - * Copyright (c) All rights reserved + * Copyright (c) All rights reserved * SiLab, Institute of Physics, University of Bonn * ------------------------------------------------------------ */ @@ -9,10 +9,10 @@ module IDDR ( - output wire Q1, Q2, + output wire Q1, Q2, input wire C, CE, D, R, S ); - + FDRSE F0 ( .C(C), .CE(CE), diff --git a/basil/firmware/modules/utils/IDDR_s6.v b/basil/firmware/modules/utils/IDDR_s6.v index 2eaadcf9d..335c03e1c 100644 --- a/basil/firmware/modules/utils/IDDR_s6.v +++ b/basil/firmware/modules/utils/IDDR_s6.v @@ -1,6 +1,6 @@ /** * ------------------------------------------------------------ - * Copyright (c) All rights reserved + * Copyright (c) All rights reserved * SiLab, Institute of Physics, University of Bonn * ------------------------------------------------------------ */ @@ -9,19 +9,19 @@ module IDDR ( - output wire Q1, Q2, + output wire Q1, Q2, input wire C, CE, D, R, S ); IDDR2 IDDR2_inst ( - .Q0(Q1), - .Q1(Q2), - .C0(C), - .C1(~C), - .CE(CE), - .D(D), - .R(R), - .S(S) + .Q0(Q1), + .Q1(Q2), + .C0(C), + .C1(~C), + .CE(CE), + .D(D), + .R(R), + .S(S) ); endmodule diff --git a/basil/firmware/modules/utils/ODDR_s3.v b/basil/firmware/modules/utils/ODDR_s3.v index 68a42def3..c823d2205 100644 --- a/basil/firmware/modules/utils/ODDR_s3.v +++ b/basil/firmware/modules/utils/ODDR_s3.v @@ -1,6 +1,6 @@ /** * ------------------------------------------------------------ - * Copyright (c) All rights reserved + * Copyright (c) All rights reserved * SiLab, Institute of Physics, University of Bonn * ------------------------------------------------------------ */ @@ -9,13 +9,13 @@ module ODDR ( - input wire D1, D2, + input wire D1, D2, input wire C, CE, R, S, output wire Q ); OFDDRRSE OFDDRRSE_INST ( - .CE(CE), + .CE(CE), .C0(C), .C1(~C), .D0(D1), diff --git a/basil/firmware/modules/utils/ODDR_s6.v b/basil/firmware/modules/utils/ODDR_s6.v index 94d433a4c..1245c4d7b 100644 --- a/basil/firmware/modules/utils/ODDR_s6.v +++ b/basil/firmware/modules/utils/ODDR_s6.v @@ -1,6 +1,6 @@ /** * ------------------------------------------------------------ - * Copyright (c) All rights reserved + * Copyright (c) All rights reserved * SiLab, Institute of Physics, University of Bonn * ------------------------------------------------------------ */ @@ -9,19 +9,19 @@ module ODDR ( - input wire D1, D2, + input wire D1, D2, input wire C, CE, R, S, output wire Q ); ODDR2 ODDR2_inst ( - .Q(Q), - .C0(C), - .C1(~C), - .CE(CE), - .D0(D1), - .D1(D2), - .R(R), + .Q(Q), + .C0(C), + .C1(~C), + .CE(CE), + .D0(D1), + .D1(D2), + .R(R), .S(S) ); diff --git a/basil/firmware/modules/utils/RAMB16_S1_S2_sim.v b/basil/firmware/modules/utils/RAMB16_S1_S2_sim.v index 90c4aab82..508dd1640 100644 --- a/basil/firmware/modules/utils/RAMB16_S1_S2_sim.v +++ b/basil/firmware/modules/utils/RAMB16_S1_S2_sim.v @@ -68,4 +68,3 @@ end endgenerate endmodule - diff --git a/basil/firmware/modules/utils/README.rst b/basil/firmware/modules/utils/README.rst index 479ffdaec..2f463fc93 100644 --- a/basil/firmware/modules/utils/README.rst +++ b/basil/firmware/modules/utils/README.rst @@ -27,4 +27,4 @@ Various Verilog modules used by basil. - rbcp_to_bus - reset_gen - simple_arbiter -- three_stage_synchronizer_ce \ No newline at end of file +- three_stage_synchronizer_ce diff --git a/basil/firmware/modules/utils/generic_fifo.v b/basil/firmware/modules/utils/generic_fifo.v index 2de6aee9d..115ef80c7 100644 --- a/basil/firmware/modules/utils/generic_fifo.v +++ b/basil/firmware/modules/utils/generic_fifo.v @@ -12,7 +12,7 @@ module generic_fifo #( parameter DATA_SIZE = 32, parameter DEPTH = 8, parameter POINTER_SIZE = 16 // maximum in Xilinx 7-series -)( +)( clk, reset, write, diff --git a/basil/firmware/modules/utils/ramb_8_to_n.v b/basil/firmware/modules/utils/ramb_8_to_n.v index 27e75487b..d86d69082 100644 --- a/basil/firmware/modules/utils/ramb_8_to_n.v +++ b/basil/firmware/modules/utils/ramb_8_to_n.v @@ -15,7 +15,7 @@ module ramb_8_to_n (clkA, doA, diB, doB); - + parameter SIZE = 1024; parameter WIDTH = 8; @@ -74,7 +74,7 @@ generate end end endgenerate - + generate if (WIDTH < 8) begin always @(posedge clkB) @@ -84,11 +84,11 @@ generate doB <= RAM[addrB]; end - + always @(posedge clkA) begin : portA integer i; reg [log2RATIO-1:0] lsbaddr ; - + for (i = 0; i< RATIO; i = i + 1) begin lsbaddr = i; if (weA) @@ -110,7 +110,7 @@ generate doA <= RAM[addrA]; end - + always @(posedge clkB) begin : portA integer i; reg [log2RATIO-1:0] lsbaddr ; @@ -124,6 +124,6 @@ generate end end endgenerate - - + + endmodule diff --git a/basil/firmware/modules/utils/simple_arbiter.v b/basil/firmware/modules/utils/simple_arbiter.v index 63bf53188..e35818b01 100644 --- a/basil/firmware/modules/utils/simple_arbiter.v +++ b/basil/firmware/modules/utils/simple_arbiter.v @@ -1,6 +1,6 @@ /** * ------------------------------------------------------------ - * Copyright (c) All rights reserved + * Copyright (c) All rights reserved * SiLab, Institute of Physics, University of Bonn * ------------------------------------------------------------ */ @@ -10,7 +10,7 @@ // 'base' is a one hot signal indicating the first request // that should be considered for a grant. Followed by higher // indexed requests, then wrapping around. -// NOTE: Ff there is more than one request at time, +// NOTE: Ff there is more than one request at time, // this arbiter will finish all requests by the first request, // and then go on with higher indexed request request. diff --git a/basil/utils/BitLogic.py b/basil/utils/BitLogic.py index ac760768c..c54fb8364 100644 --- a/basil/utils/BitLogic.py +++ b/basil/utils/BitLogic.py @@ -13,9 +13,8 @@ class BitLogic(bitarray): def __new__(cls, *args, **kwargs): - '''Initialize BitLogic with size (int) or bit string - ''' - endian = kwargs.pop('endian', 'little') + """Initialize BitLogic with size (int) or bit string""" + endian = kwargs.pop("endian", "little") try: _ = int(args[0], base=2) except (TypeError, IndexError): @@ -29,44 +28,44 @@ def __new__(cls, *args, **kwargs): return ba @classmethod - def from_value(cls, value, size=None, fmt='Q', **kwargs): - ''' + def from_value(cls, value, size=None, fmt="Q", **kwargs): + """ Factory method For format characters see: https://docs.python.org/2/library/struct.html - ''' + """ bl = cls(**kwargs) # size is 0 by default bl.fromvalue(value=value, size=size, fmt=fmt) return bl - def fromvalue(self, value, size=None, fmt='Q'): - ''' + def fromvalue(self, value, size=None, fmt="Q"): + """ Append from a int/long number. - ''' + """ if size and value.bit_length() > size: - raise TypeError('Value is too big for given size') + raise TypeError("Value is too big for given size") self.frombytes(struct.pack(fmt, value)) if size: if not isinstance(size, integer_types) or not size > 0: - raise TypeError('Size must be greater than zero') + raise TypeError("Size must be greater than zero") if size > len(self): bitarray.extend(self, (size - len(self)) * [0]) else: bitarray.__delitem__(self, slice(size, len(self))) # or use __delslice__() (deprecated) - def tovalue(self, fmt='Q'): - ''' + def tovalue(self, fmt="Q"): + """ Convert bitstring to a int/long number. - ''' + """ format_size = struct.calcsize(fmt) if len(self) > format_size * 8: - raise TypeError('Cannot convert to number') + raise TypeError("Cannot convert to number") ba = self.copy() ba.extend((format_size * 8 - len(self)) * [0]) return struct.unpack_from(fmt, ba.tobytes())[0] def __str__(self): - if self.endian == 'little': + if self.endian == "little": return self.to01()[::-1] else: return self.to01() @@ -77,10 +76,10 @@ def __getitem__(self, key): return bitarray.__getitem__(self, slc) def __setitem__(self, key, item): - '''Indexing and slicing + """Indexing and slicing Note: the length must not be changed - ''' + """ length = len(self) try: # item is bit string @@ -95,20 +94,20 @@ def __setitem__(self, key, item): else: # item is bitarray, list, tuple, bool # make slice if item is no bool, otherwise assignment will be casted to bool, and is most likely True - slc = self._swap_slice_indices(key, make_slice=True if (type(item) not in (bool, )) else False) + slc = self._swap_slice_indices(key, make_slice=True if (type(item) not in (bool,)) else False) bitarray.__setitem__(self, slc, item) else: slc = self._swap_slice_indices(key, make_slice=True) bl = BitLogic(item) bitarray.__setitem__(self, slc, bl) if len(self) != length: - raise ValueError('Unexpected length for slice assignment') + raise ValueError("Unexpected length for slice assignment") def _swap_slice_indices(self, slc, make_slice=False): - '''Swap slice indices + """Swap slice indices Change slice indices from Verilog slicing (e.g. IEEE 1800-2012) to Python slicing. - ''' + """ try: start = slc.start stop = slc.stop diff --git a/basil/utils/DataManipulation.py b/basil/utils/DataManipulation.py index b1ce0c4ae..d7c3a3fa3 100644 --- a/basil/utils/DataManipulation.py +++ b/basil/utils/DataManipulation.py @@ -9,7 +9,7 @@ def convert_data_array(arr, filter_func=None, converter_func=None): - '''Filter and convert any given data array of any dtype. + """Filter and convert any given data array of any dtype. Parameters ---------- @@ -23,15 +23,15 @@ def convert_data_array(arr, filter_func=None, converter_func=None): Returns ------- array of specified dimension (converter_func) and content (filter_func) - ''' -# if filter_func != None: -# if not hasattr(filter_func, '__call__'): -# raise ValueError('Filter is not callable') + """ + # if filter_func != None: + # if not hasattr(filter_func, '__call__'): + # raise ValueError('Filter is not callable') if filter_func: array = arr[filter_func(arr)] # Indexing with Boolean Arrays -# if converter_func != None: -# if not hasattr(converter_func, '__call__'): -# raise ValueError('Converter is not callable') + # if converter_func != None: + # if not hasattr(converter_func, '__call__'): + # raise ValueError('Converter is not callable') if converter_func: arr = converter_func(arr) return array @@ -41,8 +41,9 @@ def convert_data_array(arr, filter_func=None, converter_func=None): # Filter functions + def logical_and(f1, f2): # function factory - '''Logical and from functions. + """Logical and from functions. Parameters ---------- @@ -57,15 +58,17 @@ def logical_and(f1, f2): # function factory -------- filter_func=logical_and(is_data_record, is_data_from_channel(4)) # new filter function filter_func(array) # array that has Data Records from channel 4 - ''' + """ + def f_and(arr): return np.logical_and(f1(arr), f2(arr)) + f_and.__name__ = f1.__name__ + "_and_" + f2.__name__ return f_and def logical_or(f1, f2): # function factory - '''Logical or from functions. + """Logical or from functions. Parameters ---------- @@ -75,15 +78,17 @@ def logical_or(f1, f2): # function factory Returns ------- Function - ''' + """ + def f_or(arr): return np.logical_or(f1(arr), f2(arr)) + f_or.__name__ = f1.__name__ + "_or_" + f2.__name__ return f_or def logical_not(f): # function factory - '''Logical not from functions. + """Logical not from functions. Parameters ---------- @@ -93,15 +98,17 @@ def logical_not(f): # function factory Returns ------- Function - ''' + """ + def f_not(arr): return np.logical_not(f(arr)) + f_not.__name__ = "not_" + f.__name__ return f_not def logical_xor(f1, f2): # function factory - '''Logical xor from functions. + """Logical xor from functions. Parameters ---------- @@ -111,15 +118,17 @@ def logical_xor(f1, f2): # function factory Returns ------- Function - ''' + """ + def f_xor(arr): return np.logical_xor(f1(arr), f2(arr)) + f_xor.__name__ = f1.__name__ + "_xor_" + f2.__name__ return f_xor def arr_select(value): # function factory - '''Selecting array elements by bitwise and comparison to a given value. + """Selecting array elements by bitwise and comparison to a given value. Parameters: value : int @@ -127,17 +136,20 @@ def arr_select(value): # function factory Returns: array : np.array - ''' + """ + def f_eq(arr): return np.equal(np.bitwise_and(arr, value), value) + f_eq.__name__ = "arr_bitwise_and_" + str(value) # or use inspect module: inspect.stack()[0][3] return f_eq # Converter functions + def arr_astype(arr_type): # function factory - '''Change dtype of array. + """Change dtype of array. Parameters: arr_type : str, np.dtype @@ -145,8 +157,10 @@ def arr_astype(arr_type): # function factory Returns: array : np.array - ''' + """ + def f_astype(arr): return arr.astype(arr_type) + f_astype.__name__ = "arr_astype_" + str(arr_type) # or use inspect module: inspect.stack()[0][3] return f_astype diff --git a/basil/utils/USBBinds.py b/basil/utils/USBBinds.py index 7a42e7997..ec15f2dd4 100644 --- a/basil/utils/USBBinds.py +++ b/basil/utils/USBBinds.py @@ -1,12 +1,9 @@ import os - from pathlib import Path -from six import string_types - import pyvisa - import ruamel.yaml +from six import string_types def query_identification(rm, resource, baud_rate, read_termination=None, write_termination=None, timeout=1000 * 5): @@ -39,12 +36,7 @@ def query_identification(rm, resource, baud_rate, read_termination=None, write_t return reply -def find_usb_binds(rm, log, - instruments, - binds_to_skip=[], - memorized_binds={}, - timeout=1000 * 4 - ): +def find_usb_binds(rm, log, instruments, binds_to_skip=[], memorized_binds={}, timeout=1000 * 4): """ Finds the USB bind for each instrument in the given list of instruments. @@ -68,9 +60,7 @@ def find_usb_binds(rm, log, dict: A dictionary mapping the identification strings of the instruments to their corresponding USB binds. """ - skip_binds = binds_to_skip + [ - str(Path(f"/dev/{bind}").resolve()) for bind in binds_to_skip - ] + skip_binds = binds_to_skip + [str(Path(f"/dev/{bind}").resolve()) for bind in binds_to_skip] results = {} @@ -82,8 +72,8 @@ def find_usb_binds(rm, log, if "port" in instrument.keys(): port = instrument.get("port") - if 'ASRL' not in port: - port = f'ASRL{port}::INSTR' + if "ASRL" not in port: + port = f"ASRL{port}::INSTR" if port in resources: resources = (port,) + resources @@ -105,7 +95,14 @@ def find_usb_binds(rm, log, log.debug(f"Found memorized bind {res}") result = memorized_binds[res] else: - result = query_identification(rm, res, instrument['baud_rate'], instrument['read_termination'], instrument['write_termination'], timeout=timeout) + result = query_identification( + rm, + res, + instrument["baud_rate"], + instrument["read_termination"], + instrument["write_termination"], + timeout=timeout, + ) memorized_binds[res] = result log.debug(f"Found {result.strip()}") @@ -173,7 +170,7 @@ def load_yaml_with_comments(conf): elif isinstance(conf, string_types): # parse the first YAML document in a stream yaml = ruamel.yaml.YAML() if os.path.isfile(conf): - with open(conf, 'r') as f: + with open(conf, "r") as f: yaml = ruamel.yaml.YAML() conf_dict.update(yaml.load(f)) else: # YAML string @@ -181,7 +178,7 @@ def load_yaml_with_comments(conf): conf_dict.update(yaml.load(conf)) except ValueError: # invalid path/filename raise IOError("File not found: %s" % conf) - elif hasattr(conf, 'read'): # parse the first YAML document in a stream + elif hasattr(conf, "read"): # parse the first YAML document in a stream yaml = ruamel.yaml.YAML() conf_dict.update(yaml.load(conf)) conf.close() @@ -232,13 +229,15 @@ def modify_basil_config(conf, log, skip_binds=[], save_modified=None): else: port = None - instruments.append({ - "identification": instrument, - "baud_rate": baud_rate, - "read_termination": read_termination, - "write_termination": write_termination, - "port": port, - }) + instruments.append( + { + "identification": instrument, + "baud_rate": baud_rate, + "read_termination": read_termination, + "write_termination": write_termination, + "port": port, + } + ) insts_idx_map[instrument.lower().strip()] = i @@ -255,8 +254,8 @@ def modify_basil_config(conf, log, skip_binds=[], save_modified=None): if save_modified is not None: yaml = ruamel.yaml.YAML() - log.info(f'Saving modified periphery file: {save_modified}') - with open(save_modified, 'w') as f: + log.info(f"Saving modified periphery file: {save_modified}") + with open(save_modified, "w") as f: yaml.dump(conf, f) for inst in found_binds.keys(): diff --git a/basil/utils/sim/BasilBusDriver.py b/basil/utils/sim/BasilBusDriver.py index fee5929fa..342aec5ca 100644 --- a/basil/utils/sim/BasilBusDriver.py +++ b/basil/utils/sim/BasilBusDriver.py @@ -10,8 +10,8 @@ # pylint: disable=pointless-statement, expression-not-assigned -from cocotb.types import LogicArray from cocotb.triggers import RisingEdge, Timer +from cocotb.types import LogicArray from cocotb_bus.drivers import BusDriver @@ -100,7 +100,6 @@ async def read(self, address, size): return result async def write(self, address, data): - self.bus.BUS_ADD.value = self._x self.bus.BUS_DATA.value = self._high_impedance self.bus.BUS_WR.value = 0 diff --git a/basil/utils/sim/BasilSbusDriver.py b/basil/utils/sim/BasilSbusDriver.py index 64aa84def..c9e045efb 100644 --- a/basil/utils/sim/BasilSbusDriver.py +++ b/basil/utils/sim/BasilSbusDriver.py @@ -8,8 +8,8 @@ # pylint: disable=pointless-statement, expression-not-assigned +from cocotb.triggers import ReadOnly, RisingEdge from cocotb.types import LogicArray -from cocotb.triggers import RisingEdge, ReadOnly from cocotb_bus.drivers import BusDriver @@ -68,7 +68,6 @@ async def read(self, address, size): byte = 0 while byte < size: - await RisingEdge(self.clock) if self._has_byte_acces and self.bus.BUS_BYTE_ACCESS.value == 0: @@ -102,7 +101,6 @@ async def read(self, address, size): return result async def write(self, address, data): - await RisingEdge(self.clock) for index, byte in enumerate(data): diff --git a/basil/utils/sim/Protocol.py b/basil/utils/sim/Protocol.py index dccaebc37..eb2d1216a 100644 --- a/basil/utils/sim/Protocol.py +++ b/basil/utils/sim/Protocol.py @@ -11,9 +11,10 @@ These classes are pickled and sent over a socket to communicate with the sim Protocol is very simple, simply prefix the pickled data with a 4-byte length """ + import pickle -import struct import socket +import struct class ProtocolBase(object): diff --git a/basil/utils/sim/SiLibUsb.py b/basil/utils/sim/SiLibUsb.py index 1515423c6..8bcb95858 100644 --- a/basil/utils/sim/SiLibUsb.py +++ b/basil/utils/sim/SiLibUsb.py @@ -17,17 +17,20 @@ """ - -import socket import array +import socket -from basil.utils.sim.Protocol import WriteRequest, ReadRequest, ReadResponse, PickleInterface +from basil.utils.sim.Protocol import ( + PickleInterface, + ReadRequest, + ReadResponse, + WriteRequest, +) __version__ = "0.0.3" class SiUSBDevice(object): - """Simulation library to emulate SiUSBDevices""" BASE_ADDRESS_I2C = 0x00000 diff --git a/basil/utils/sim/SiLibUsbBusDriver.py b/basil/utils/sim/SiLibUsbBusDriver.py index 20eabc23e..9f0aa1dd3 100644 --- a/basil/utils/sim/SiLibUsbBusDriver.py +++ b/basil/utils/sim/SiLibUsbBusDriver.py @@ -12,13 +12,13 @@ """ Abastract away interactions with the control bus """ + +from cocotb.triggers import ReadOnly, RisingEdge, Timer from cocotb.types import LogicArray -from cocotb.triggers import RisingEdge, ReadOnly, Timer from cocotb_bus.drivers import BusDriver class SiLibUsbBusDriver(BusDriver): - _signals = ["FCLK_IN", "BUS_DATA", "ADD", "RD_B", "WR_B", "FD", "FREAD", "FSTROBE", "FMODE"] BASE_ADDRESS_I2C = 0x00000 diff --git a/basil/utils/sim/Test.py b/basil/utils/sim/Test.py index 75ce4e5f6..07c1d2d05 100644 --- a/basil/utils/sim/Test.py +++ b/basil/utils/sim/Test.py @@ -11,13 +11,18 @@ import logging import os import socket -import yaml import cocotb -from cocotb.triggers import Timer +import yaml from cocotb.clock import Clock +from cocotb.triggers import Timer -from basil.utils.sim.Protocol import WriteRequest, ReadRequest, ReadResponse, PickleInterface +from basil.utils.sim.Protocol import ( + PickleInterface, + ReadRequest, + ReadResponse, + WriteRequest, +) def get_bus(): diff --git a/basil/utils/sim/utils.py b/basil/utils/sim/utils.py index 23f639289..4ddcad025 100644 --- a/basil/utils/sim/utils.py +++ b/basil/utils/sim/utils.py @@ -5,18 +5,30 @@ # ------------------------------------------------------------ # +import os import subprocess + import basil -import os def get_basil_dir(): return str(os.path.dirname(basil.__file__)) -def cocotb_makefile(sim_files, top_level='tb', test_module='basil.utils.sim.Test', sim_host='localhost', sim_port=12345, sim_bus='basil.utils.sim.BasilBusDriver', - end_on_disconnect=True, include_dirs=(), extra_defines=(), compile_args=(), build_args=(), extra=''): - +def cocotb_makefile( + sim_files, + top_level="tb", + test_module="basil.utils.sim.Test", + sim_host="localhost", + sim_port=12345, + sim_bus="basil.utils.sim.BasilBusDriver", + end_on_disconnect=True, + include_dirs=(), + extra_defines=(), + compile_args=(), + build_args=(), + extra="", +): basil_dir = get_basil_dir() include_dirs += (basil_dir + "/firmware/modules", basil_dir + "/firmware/modules/includes") @@ -31,21 +43,27 @@ def cocotb_makefile(sim_files, top_level='tb', test_module='basil.utils.sim.Test mkfile += "TOPLEVEL = %s\nMODULE = %s\n\n" % (top_level, test_module) - mkfile += "ICARUS_INCLUDE_DIRS = %s\n" % (" ".join('-I' + str(e) for e in include_dirs)) - mkfile += "ICARUS_DEFINES += %s\n\n" % (" ".join('-D' + str(e) for e in extra_defines)) + mkfile += "ICARUS_INCLUDE_DIRS = %s\n" % (" ".join("-I" + str(e) for e in include_dirs)) + mkfile += "ICARUS_DEFINES += %s\n\n" % (" ".join("-D" + str(e) for e in extra_defines)) - mkfile += "NOT_ICARUS_DEFINES = %s\n" % (" ".join('+define+' + str(e) for e in extra_defines)) - mkfile += "NOT_ICARUS_INCLUDE_DIRS=+incdir+./ %s\n" % (" ".join('+incdir+' + str(e) for e in include_dirs)) # this is for modelsim better full path? + mkfile += "NOT_ICARUS_DEFINES = %s\n" % (" ".join("+define+" + str(e) for e in extra_defines)) + mkfile += "NOT_ICARUS_INCLUDE_DIRS=+incdir+./ %s\n" % ( + " ".join("+incdir+" + str(e) for e in include_dirs) + ) # this is for modelsim better full path? - mkfile += "COMPILE_ARGS_DEFINES = %s\n" % (" ".join(str(e) for e in compile_args)) # extra compiler args, e.g., for adding Xilinx's glbl.v to Icarus use "-s glbl" - mkfile += "BUILD_ARGS_DEFINES = %s\n" % (" ".join(str(e) for e in build_args)) # extra build args passed to build stage in supported simulators + mkfile += "COMPILE_ARGS_DEFINES = %s\n" % ( + " ".join(str(e) for e in compile_args) + ) # extra compiler args, e.g., for adding Xilinx's glbl.v to Icarus use "-s glbl" + mkfile += "BUILD_ARGS_DEFINES = %s\n" % ( + " ".join(str(e) for e in build_args) + ) # extra build args passed to build stage in supported simulators mkfile += "\n" mkfile += extra mkfile += "\n" try: - if os.environ['SIM'] == 'verilator': + if os.environ["SIM"] == "verilator": mkfile += "EXTRA_ARGS += -DVERILATOR_SIM\n" mkfile += "EXTRA_ARGS += -Wno-WIDTH -Wno-TIMESCALEMOD -Wwarn-ASSIGNDLY\n" except KeyError: @@ -91,11 +109,11 @@ def cocotb_makefile(sim_files, top_level='tb', test_module='basil.utils.sim.Test def cocotb_compile_and_run(*args, **kw): # run simulator in background - with open('Makefile', 'w') as f: + with open("Makefile", "w") as f: f.write(cocotb_makefile(*args, **kw)) - subprocess.Popen(['make']) + subprocess.Popen(["make"]) def cocotb_compile_clean(): - subprocess.call('make clean', shell=True) - subprocess.call('rm -f Makefile', shell=True) + subprocess.call("make clean", shell=True) + subprocess.call("rm -f Makefile", shell=True) diff --git a/basil/utils/utils.py b/basil/utils/utils.py index b970e700c..6b6d4b07e 100644 --- a/basil/utils/utils.py +++ b/basil/utils/utils.py @@ -5,22 +5,24 @@ # ------------------------------------------------------------ # +import fileinput +import os.path from array import array + +import git import numpy as np from bitarray import bitarray -import os.path -import git -import fileinput def logging(fn): def wrapped(*args, **kargs): - print('loging: {}'.format(locals())) -# if args: -# print("loging: arguments: " + str(args)) -# if kargs: -# print("loging: kargs: " + str(kargs)) + print("loging: {}".format(locals())) + # if args: + # print("loging: arguments: " + str(args)) + # if kargs: + # print("loging: kargs: " + str(kargs)) return fn(*args, **kargs) + return wrapped @@ -31,11 +33,11 @@ def lsbits(b): def bitvector_to_byte_array(bitvector): bsize = len(bitvector) size_bytes = int(((bsize - 1) / 8) + 1) - bs = tobytes(array('B', bitvector.vector))[0:size_bytes] - bitstream_swap = '' + bs = tobytes(array("B", bitvector.vector))[0:size_bytes] + bitstream_swap = "" for b in bs: bitstream_swap += chr(lsbits(b)) - return array('B', bitstream_swap) + return array("B", bitstream_swap) def bitarray_to_byte_array(bitarr): @@ -43,60 +45,67 @@ def bitarray_to_byte_array(bitarr): ba.reverse() # this flip the byte order and the bit order of each byte bs = np.frombuffer(ba.tobytes(), dtype=np.uint8) # byte padding happens here, bitarray.tobytes() bs = (bs * np.uint64(0x0202020202) & 0x010884422010) % 1023 - return array('B', bs.astype(np.uint8)) + return array("B", bs.astype(np.uint8)) -def get_si_tcp(rel_path=''): - ''' Download SiTCP/SiTCP10G sources from the official github repo and apply patches - ''' +def get_si_tcp(rel_path=""): + """Download SiTCP/SiTCP10G sources from the official github repo and apply patches""" - sitcp_repo = r'https://github.com/BeeBeansTechnologies/SiTCP_Netlist_for_Kintex7' - sitcp_10G_repo = r'https://github.com/BeeBeansTechnologies/SiTCPXG_Netlist_for_Kintex7' + sitcp_repo = r"https://github.com/BeeBeansTechnologies/SiTCP_Netlist_for_Kintex7" + sitcp_10G_repo = r"https://github.com/BeeBeansTechnologies/SiTCPXG_Netlist_for_Kintex7" def line_prepender(filename, line): - with open(filename, 'rb+') as f: + with open(filename, "rb+") as f: content = f.read() f.seek(0, 0) add = bytearray() add.extend(map(ord, line)) - add.extend(map(ord, '\n')) + add.extend(map(ord, "\n")) f.write(add + content) - sitcp_folder = os.path.join(os.path.os.getcwd(), rel_path, 'SiTCP/') + sitcp_folder = os.path.join(os.path.os.getcwd(), rel_path, "SiTCP/") # Only download if the SiTCP git repository is not present - if not os.path.isdir(os.path.join(sitcp_folder, '.git')): - print('Downloading SiTCP') + if not os.path.isdir(os.path.join(sitcp_folder, ".git")): + print("Downloading SiTCP") # Has to be moved to be allowed to use existing folder for git checkout - git.Repo.clone_from(url=sitcp_repo, - to_path=sitcp_folder, branch='master') + git.Repo.clone_from(url=sitcp_repo, to_path=sitcp_folder, branch="master") # Patch sources, see README of bdaq53 - line_prepender(filename=sitcp_folder + 'TIMER.v', line=r'`default_nettype wire') - line_prepender(filename=sitcp_folder + 'WRAP_SiTCP_GMII_XC7K_32K.V', line=r'`default_nettype wire') - for line in fileinput.input([sitcp_folder + 'WRAP_SiTCP_GMII_XC7K_32K.V'], inplace=True): - print(line.replace("assign\tMY_IP_ADDR[31:0]\t= (~FORCE_DEFAULTn | (EXT_IP_ADDR[31:0]==32'd0) \t? DEFAULT_IP_ADDR[31:0]\t\t: EXT_IP_ADDR[31:0]\t\t);", - 'assign\tMY_IP_ADDR[31:0]\t= EXT_IP_ADDR[31:0];'), end='') + line_prepender(filename=sitcp_folder + "TIMER.v", line=r"`default_nettype wire") + line_prepender(filename=sitcp_folder + "WRAP_SiTCP_GMII_XC7K_32K.V", line=r"`default_nettype wire") + for line in fileinput.input([sitcp_folder + "WRAP_SiTCP_GMII_XC7K_32K.V"], inplace=True): + print( + line.replace( + "assign\tMY_IP_ADDR[31:0]\t= (~FORCE_DEFAULTn | (EXT_IP_ADDR[31:0]==32'd0) \t? DEFAULT_IP_ADDR[31:0]\t\t: EXT_IP_ADDR[31:0]\t\t);", + "assign\tMY_IP_ADDR[31:0]\t= EXT_IP_ADDR[31:0];", + ), + end="", + ) else: # update if existing - print('SiTCP already present. Checking for updates') + print("SiTCP already present. Checking for updates") g = git.cmd.Git(sitcp_folder) g.pull() - sitcp_10G_folder = os.path.join(os.path.os.getcwd(), rel_path, 'SiTCP10G/') + sitcp_10G_folder = os.path.join(os.path.os.getcwd(), rel_path, "SiTCP10G/") # Only download if the SiTCP10G git repository is not present - if not os.path.isdir(os.path.join(sitcp_10G_folder, '.git')): - print('Downloading SiTCP10G') + if not os.path.isdir(os.path.join(sitcp_10G_folder, ".git")): + print("Downloading SiTCP10G") # Has to be moved to be allowed to use existing folder for git checkout - git.Repo.clone_from(url=sitcp_10G_repo, - to_path=sitcp_10G_folder, branch='master') + git.Repo.clone_from(url=sitcp_10G_repo, to_path=sitcp_10G_folder, branch="master") # Patch sources, see README of bdaq53 - for line in fileinput.input([sitcp_10G_folder + 'WRAP_SiTCPXG_XC7K_128K.v'], inplace=True): - print(line.replace("\t\t.MY_IP_ADDR \t\t\t\t\t(MY_IP_ADDR[31:0] \t\t\t),\t// in\t: My IP address[31:0]", - "\t\t.MY_IP_ADDR \t\t\t\t\t({8'd192, 8'd168, 8'd100, 8'd12}),\t// in\t: My IP address[31:0]"), end='') + for line in fileinput.input([sitcp_10G_folder + "WRAP_SiTCPXG_XC7K_128K.v"], inplace=True): + print( + line.replace( + "\t\t.MY_IP_ADDR \t\t\t\t\t(MY_IP_ADDR[31:0] \t\t\t),\t// in\t: My IP address[31:0]", + "\t\t.MY_IP_ADDR \t\t\t\t\t({8'd192, 8'd168, 8'd100, 8'd12}),\t// in\t: My IP address[31:0]", + ), + end="", + ) else: # update if existing - print('SiTCP10G already present. Checking for updates') + print("SiTCP10G already present. Checking for updates") g = git.cmd.Git(sitcp_10G_folder) g.pull() @@ -107,8 +116,10 @@ def line_prepender(filename, line): try: array.tobytes except AttributeError: # Python 2 + def tobytes(v): return v.tostring() else: # Python 3 + def tobytes(v): return v.tobytes() diff --git a/docs/conf.py b/docs/conf.py index 540e22385..ab096052a 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -12,14 +12,13 @@ # All configuration values have a default; values that are commented out # serve to show the default. -import sys import os - +import sys # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. -sys.path.insert(0, os.path.abspath('../basil')) +sys.path.insert(0, os.path.abspath("../basil")) # -- General configuration ------------------------------------------------ @@ -31,29 +30,29 @@ # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ - 'sphinx.ext.autodoc', - 'sphinx.ext.doctest', - 'sphinx.ext.todo', - 'sphinx.ext.ifconfig', - 'sphinx.ext.viewcode', - 'sphinx.ext.graphviz', + "sphinx.ext.autodoc", + "sphinx.ext.doctest", + "sphinx.ext.todo", + "sphinx.ext.ifconfig", + "sphinx.ext.viewcode", + "sphinx.ext.graphviz", ] # Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] +templates_path = ["_templates"] # The suffix of source filenames. -source_suffix = '.rst' +source_suffix = ".rst" # The encoding of source files. # source_encoding = 'utf-8-sig' # The master toctree document. -master_doc = 'index' +master_doc = "index" # General information about the project. -project = 'basil' -copyright = '2013-2026' +project = "basil" +copyright = "2013-2026" author = 'SiLab, Institute of Physics, University of Bonn' # The version info for the project you're documenting, acts as replacement for @@ -62,6 +61,7 @@ # try: from importlib.metadata import version as get_version + basil_version = get_version("basil_daq") except Exception: basil_version = "dev" @@ -83,7 +83,7 @@ # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. -exclude_patterns = ['_build'] +exclude_patterns = ["_build"] # The reST default role (used for this markup: `text`) to use for all # documents. @@ -101,7 +101,7 @@ # show_authors = False # The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' +pygments_style = "sphinx" # A list of ignored prefixes for module index sorting. # modindex_common_prefix = [] @@ -134,7 +134,7 @@ # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] +html_static_path = ["_static"] def setup(app): @@ -192,7 +192,7 @@ def setup(app): # Output file base name for HTML help builder. -htmlhelp_basename = 'basildoc' +htmlhelp_basename = "basildoc" # -- Options for LaTeX output --------------------------------------------- @@ -200,10 +200,8 @@ def setup(app): latex_elements = { # The paper size ('letterpaper' or 'a4paper'). # 'papersize': 'letterpaper', - # The font size ('10pt', '11pt' or '12pt'). # 'pointsize': '10pt', - # Additional stuff for the LaTeX preamble. # 'preamble': '', } @@ -212,8 +210,7 @@ def setup(app): # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ - ('index', 'basil.tex', 'basil Documentation', - 'SiLab, University of Bonn', 'manual'), + ("index", "basil.tex", "basil Documentation", "SiLab, University of Bonn", "manual"), ] # The name of an image file (relative to this directory) to place at the top of @@ -241,10 +238,7 @@ def setup(app): # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). -man_pages = [ - ('index', 'basil', 'basil Documentation', - ['SiLab, University of Bonn'], 1) -] +man_pages = [("index", "basil", "basil Documentation", ["SiLab, University of Bonn"], 1)] # If true, show URL addresses after external links. # man_show_urls = False @@ -256,9 +250,15 @@ def setup(app): # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ - ('index', 'basil', 'basil Documentation', - 'SiLab, University of Bonn', 'basil', 'Modular DAQ framework for pixel detectors.', - 'Miscellaneous'), + ( + "index", + "basil", + "basil Documentation", + "SiLab, University of Bonn", + "basil", + "Modular DAQ framework for pixel detectors.", + "Miscellaneous", + ), ] # Documents to append as an appendix to all manuals. @@ -273,5 +273,5 @@ def setup(app): # If true, do not generate a @detailmenu in the "Top" node's menu. # texinfo_no_detailmenu = False -sys.path.append('./') -sys.path.append('../') +sys.path.append("./") +sys.path.append("../") diff --git a/docs/examples.rst b/docs/examples.rst index 86ff5d729..471884ce0 100644 --- a/docs/examples.rst +++ b/docs/examples.rst @@ -17,14 +17,14 @@ Instantiate a verilog spi module in the firmware verilog code. .. code-block:: verilog - localparam SPI_BASEADDR = 32'h1000; - localparam SPI_HIGHADDR = 32'h1FFF; + localparam SPI_BASEADDR = 32'h1000; + localparam SPI_HIGHADDR = 32'h1FFF; - spi - #( - .BASEADDR(SPI_BASEADDR), + spi + #( + .BASEADDR(SPI_BASEADDR), .HIGHADDR(SPI_HIGHADDR), - .MEM_BYTES(4) + .MEM_BYTES(4) ) i_spi ( .BUS_CLK(BUS_CLK), @@ -96,5 +96,3 @@ gpio ------- TBD. - - diff --git a/docs/modules.rst b/docs/modules.rst index 86c66217f..1bc6cb423 100644 --- a/docs/modules.rst +++ b/docs/modules.rst @@ -5,7 +5,7 @@ Modules .. include:: ../basil/firmware/modules/README.rst :start-after: begin-include -.. !!!!!!!!!!!!! +.. !!!!!!!!!!!!! .. !GPIO! .. !!!!!!!!!!!!! @@ -44,7 +44,7 @@ Modules .. autoclass:: seq_gen :members: - + .. !!!!!!!!!!!!! .. !PULSE_GEN! .. !!!!!!!!!!!!! @@ -184,8 +184,8 @@ No Python driver — this module operates autonomously in the FPGA fabric. .. autoclass:: i2c :members: - - + + .. !!!!!!!!!!!!! .. !UART! .. !!!!!!!!!!!!! diff --git a/examples/MIO/ise/.gitignore b/examples/MIO/ise/.gitignore index a66111ac2..3b87f548c 100644 --- a/examples/MIO/ise/.gitignore +++ b/examples/MIO/ise/.gitignore @@ -2,4 +2,3 @@ !.gitignore !*.xise - diff --git a/examples/MIO/src/mio.ucf b/examples/MIO/src/mio.ucf index 28c991a06..6e0fec321 100644 --- a/examples/MIO/src/mio.ucf +++ b/examples/MIO/src/mio.ucf @@ -1,15 +1,15 @@ # # ------------------------------------------------------------ -# Copyright (c) SILAB , Physics Institute of Bonn University +# Copyright (c) SILAB , Physics Institute of Bonn University # ------------------------------------------------------------ # # SVN revision information: # $Rev:: $: -# $Author:: $: +# $Author:: $: # $Date:: $: # #-------------------------------------------------------------- - + #............................................................................... # Constraints File - Xilinx UCF format @@ -57,7 +57,7 @@ TIMESPEC TS_FCLK_IN = PERIOD "TNM_FCLK_IN" 20 ns HIGH 50 %; NET "FCLK_IN" IOSTANDARD = LVCMOS33; NET "FCLK_IN" LOC = N10; -#NET "LCK1" LOC = "P9" | IOSTANDARD = LVCMOS33; +#NET "LCK1" LOC = "P9" | IOSTANDARD = LVCMOS33; #NET "UCLK_IN" LOC = "P10" | IOSTANDARD = LVCMOS33; # NET "BUSY_CONF" LOC=V10; @@ -431,4 +431,3 @@ NET "SCL" LOC = D14; #NET "DOUT13" LOC = B6; #DOUT13 #NET "DOUT14" LOC = A4; #DOUT14 #NET "DOUT15" LOC = C8; #DOUT15 - diff --git a/examples/MIO/tb/example.py b/examples/MIO/tb/example.py index e736d5e90..8ce1d23e6 100644 --- a/examples/MIO/tb/example.py +++ b/examples/MIO/tb/example.py @@ -5,12 +5,13 @@ # import time + from basil.dut import Dut chip = Dut("example.yaml") chip.init() for i in range(5): - chip['GPIO_LED']['LED'] = 0x01 << i - chip['GPIO_LED'].write() + chip["GPIO_LED"]["LED"] = 0x01 << i + chip["GPIO_LED"].write() time.sleep(1) diff --git a/examples/MIO/tb/example.yaml b/examples/MIO/tb/example.yaml index 7fcbaa145..304404349 100644 --- a/examples/MIO/tb/example.yaml +++ b/examples/MIO/tb/example.yaml @@ -11,7 +11,7 @@ transfer_layer: init: avoid_download : True bit_file : ../ise/example.bit - + hw_drivers: - name : GPIO_DRV type : gpio diff --git a/examples/MIO/tb/test_SimExample.py b/examples/MIO/tb/test_SimExample.py index 222770af9..e8b245a22 100644 --- a/examples/MIO/tb/test_SimExample.py +++ b/examples/MIO/tb/test_SimExample.py @@ -4,57 +4,64 @@ # ------------------------------------------------------------ # -import unittest import os +import unittest + import yaml from basil.dut import Dut -from basil.utils.sim.utils import cocotb_compile_and_run, cocotb_compile_clean, get_basil_dir +from basil.utils.sim.utils import ( + cocotb_compile_and_run, + cocotb_compile_clean, + get_basil_dir, +) class TestExampleMIO(unittest.TestCase): def setUp(self): - fw_path = os.path.join(get_basil_dir(), 'firmware/modules') - cocotb_compile_and_run([ - os.path.join(fw_path, 'gpio/gpio.v'), - os.path.join(fw_path, 'gpio/gpio_core.v'), - os.path.join(fw_path, 'utils/reset_gen.v'), - os.path.join(fw_path, 'utils/bus_to_ip.v'), - os.path.join(fw_path, 'utils/fx2_to_bus.v'), - os.path.join(os.path.dirname(__file__), '../src/example.v')], - top_level='example', - sim_bus='basil.utils.sim.SiLibUsbBusDriver' + fw_path = os.path.join(get_basil_dir(), "firmware/modules") + cocotb_compile_and_run( + [ + os.path.join(fw_path, "gpio/gpio.v"), + os.path.join(fw_path, "gpio/gpio_core.v"), + os.path.join(fw_path, "utils/reset_gen.v"), + os.path.join(fw_path, "utils/bus_to_ip.v"), + os.path.join(fw_path, "utils/fx2_to_bus.v"), + os.path.join(os.path.dirname(__file__), "../src/example.v"), + ], + top_level="example", + sim_bus="basil.utils.sim.SiLibUsbBusDriver", ) - with open(os.path.join(os.path.dirname(__file__), 'example.yaml'), 'r') as f: + with open(os.path.join(os.path.dirname(__file__), "example.yaml"), "r") as f: cnfg = yaml.safe_load(f) # change to simulation interface - cnfg['transfer_layer'][0]['type'] = 'SiSim' + cnfg["transfer_layer"][0]["type"] = "SiSim" self.chip = Dut(cnfg) self.chip.init() def test_gpio(self): - ret = self.chip['GPIO_LED'].get_data() + ret = self.chip["GPIO_LED"].get_data() self.assertEqual([0], ret) - self.chip['GPIO_LED']['LED'] = 0x01 - self.chip['GPIO_LED'].write() + self.chip["GPIO_LED"]["LED"] = 0x01 + self.chip["GPIO_LED"].write() - ret = self.chip['GPIO_LED'].get_data() + ret = self.chip["GPIO_LED"].get_data() self.assertEqual([0x21], ret) - self.chip['GPIO_LED']['LED'] = 0x02 - self.chip['GPIO_LED'].write() + self.chip["GPIO_LED"]["LED"] = 0x02 + self.chip["GPIO_LED"].write() - ret = self.chip['GPIO_LED'].get_data() + ret = self.chip["GPIO_LED"].get_data() self.assertEqual([0x42], ret) - self.chip['GPIO_LED']['LED'] = 0x03 - self.chip['GPIO_LED'].write() + self.chip["GPIO_LED"]["LED"] = 0x03 + self.chip["GPIO_LED"].write() - ret = self.chip['GPIO_LED'].get_data() + ret = self.chip["GPIO_LED"].get_data() self.assertEqual([0x63], ret) def tearDown(self): @@ -62,5 +69,5 @@ def tearDown(self): cocotb_compile_clean() -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/examples/MMC3/mmc3.srcs/sources_1/mmc3_constants.v b/examples/MMC3/mmc3.srcs/sources_1/mmc3_constants.v index 40fb9cdd5..2664ba277 100644 --- a/examples/MMC3/mmc3.srcs/sources_1/mmc3_constants.v +++ b/examples/MMC3/mmc3.srcs/sources_1/mmc3_constants.v @@ -1,24 +1,24 @@ // ------- MODULE ADREESSES ------- // - + parameter CMD_BASEADDR = 32'h0000; parameter CMD_HIGHADDR = 32'h0800-1; - + parameter LED_GPIO_BASE = 32'h1000; - + parameter FIFO_BASEADDR = 32'h8100; parameter FIFO_HIGHADDR = 32'h8200-1; parameter RX4_BASEADDR = 32'h8300; parameter RX4_HIGHADDR = 32'h8400-1; - + parameter RX3_BASEADDR = 32'h8400; parameter RX3_HIGHADDR = 32'h8500-1; - + parameter RX2_BASEADDR = 32'h8500; parameter RX2_HIGHADDR = 32'h8600-1; - + parameter RX1_BASEADDR = 32'h8600; parameter RX1_HIGHADDR = 32'h8700-1; - + parameter FIFO_BASEADDR_DATA = 32'h8000_0000; - parameter FIFO_HIGHADDR_DATA = 32'h9000_0000; \ No newline at end of file + parameter FIFO_HIGHADDR_DATA = 32'h9000_0000; diff --git a/examples/bdaq/.gitignore b/examples/bdaq/.gitignore index 1899ec62f..566071db7 100644 --- a/examples/bdaq/.gitignore +++ b/examples/bdaq/.gitignore @@ -6,4 +6,4 @@ firmware/vivado/reports firmware/SiTCP *.log -*.history \ No newline at end of file +*.history diff --git a/examples/bdaq/Readme.md b/examples/bdaq/Readme.md index 2ae43212b..383042733 100644 --- a/examples/bdaq/Readme.md +++ b/examples/bdaq/Readme.md @@ -4,9 +4,9 @@ This example shows how to control a GPIO module and how to receive data via the 2. FPGA starts to send data from a 32 bit counter through a BRAM FIFO. 3. The Python script checks the received data and counts the transferred bytes during a given time period. 4. At the end, the average data rate is printed and the FPGA data source is stopped by clearing bit [0]. - + ## Build script -To build this example firmware, navigate to `firmware/vivado` and start the process using the Makefile +To build this example firmware, navigate to `firmware/vivado` and start the process using the Makefile ```terminal cd firmware/vivado make @@ -20,4 +20,4 @@ You can find further build instructions in the *Firmware section* of the ([bdaq5 [url2]: https://gitlab.cern.ch/silab/bdaq53#firmware ## Test -A test for CocoTB is available under `test` \ No newline at end of file +A test for CocoTB is available under `test` diff --git a/examples/bdaq/bdaq53_eth.py b/examples/bdaq/bdaq53_eth.py index 340ec901b..da0f0c4c4 100644 --- a/examples/bdaq/bdaq53_eth.py +++ b/examples/bdaq/bdaq53_eth.py @@ -13,33 +13,32 @@ from basil.dut import Dut - chip = Dut("bdaq53_eth.yaml") chip.init() -chip['CONTROL']['EN'] = 0 -chip['CONTROL'].write() +chip["CONTROL"]["EN"] = 0 +chip["CONTROL"].write() logging.info("Starting data test ...") -chip['CONTROL']['EN'] = 1 -chip['CONTROL'].write() +chip["CONTROL"]["EN"] = 1 +chip["CONTROL"].write() start = 0 for i in range(10): time.sleep(1) - fifo_data = chip['FIFO'].get_data() + fifo_data = chip["FIFO"].get_data() data_size = len(fifo_data) data_gen = np.linspace(start, data_size - 1 + start, data_size, dtype=np.int32) - comp = (fifo_data == data_gen) + comp = fifo_data == data_gen logging.info("%s: %.2f Mbits checked. OK?: %s" % (i, float(32 * data_size) / pow(10, 6), comp.all())) start += data_size -chip['CONTROL']['EN'] = 0 # stop data source -chip['CONTROL'].write() +chip["CONTROL"]["EN"] = 0 # stop data source +chip["CONTROL"].write() logging.info("Starting speed test ...") @@ -49,11 +48,11 @@ tick_old = 0 start_time = time.time() -chip['CONTROL']['EN'] = 1 -chip['CONTROL'].write() +chip["CONTROL"]["EN"] = 1 +chip["CONTROL"].write() while time.time() - start_time < testduration: - data = chip['FIFO'].get_data() + data = chip["FIFO"].get_data() total_len += len(data) * 4 * 8 time.sleep(0.01) tick = int(time.time() - start_time) @@ -61,7 +60,9 @@ logging.info("Time: %f s" % (time.time() - start_time)) tick_old = tick -chip['CONTROL']['EN'] = 0x0 # stop data source -chip['CONTROL'].write() +chip["CONTROL"]["EN"] = 0x0 # stop data source +chip["CONTROL"].write() -logging.info("Bytes received: %s, average data rate: %s Mbit/s" % (total_len, round((total_len / 1e6 / testduration), 2))) +logging.info( + "Bytes received: %s, average data rate: %s Mbit/s" % (total_len, round((total_len / 1e6 / testduration), 2)) +) diff --git a/examples/bdaq/firmware/src/SiTCP.xdc b/examples/bdaq/firmware/src/SiTCP.xdc index d4af81a58..3f8e73e2a 100644 --- a/examples/bdaq/firmware/src/SiTCP.xdc +++ b/examples/bdaq/firmware/src/SiTCP.xdc @@ -1,27 +1,27 @@ #######SiTCP####### set SiPDMIN [expr [get_property -min PERIOD [get_clocks -of_objects [get_pins -hier -filter {name =~ */GMII/*}]]] - 1.5] -set_max_delay $SiPDMIN -datapath_only -from [get_pins -hier -filter {name =~ */GMII_RXBUF/cmpWrAddr*/C}] -to [get_pins -hier -filter {name =~ */GMII_RXBUF/smpWrStatusAddr*/D}] -set_max_delay $SiPDMIN -datapath_only -from [get_pins -hier -filter {name =~ */GMII_TXBUF/orRdAct*/C}] -to [get_pins -hier -filter {name =~ */GMII_TXBUF/irRdAct*/D}] -set_max_delay $SiPDMIN -datapath_only -from [get_pins -hier -filter {name =~ */GMII_TXBUF/muxEndTgl/C}] -to [get_pins -hier -filter {name =~ */GMII_TXBUF/rsmpMuxTrnsEnd*/D}] +set_max_delay $SiPDMIN -datapath_only -from [get_pins -hier -filter {name =~ */GMII_RXBUF/cmpWrAddr*/C}] -to [get_pins -hier -filter {name =~ */GMII_RXBUF/smpWrStatusAddr*/D}] +set_max_delay $SiPDMIN -datapath_only -from [get_pins -hier -filter {name =~ */GMII_TXBUF/orRdAct*/C}] -to [get_pins -hier -filter {name =~ */GMII_TXBUF/irRdAct*/D}] +set_max_delay $SiPDMIN -datapath_only -from [get_pins -hier -filter {name =~ */GMII_TXBUF/muxEndTgl/C}] -to [get_pins -hier -filter {name =~ */GMII_TXBUF/rsmpMuxTrnsEnd*/D}] -set_max_delay $SiPDMIN -datapath_only -from [get_pins -hier -filter {name =~ */SiTCP_INT_REG/regX10Data*/C}] -to [get_pins -hier -filter {name =~ */GMII_RXCNT/irMacFlowEnb/D}] -set_max_delay $SiPDMIN -datapath_only -from [get_pins -hier -filter {name =~ */SiTCP_INT_REG/regX12Data*/C}] -to [get_pins -hier -filter {name =~ */GMII_RXCNT/muxMyMac*/D}] -set_max_delay $SiPDMIN -datapath_only -from [get_pins -hier -filter {name =~ */SiTCP_INT_REG/regX13Data*/C}] -to [get_pins -hier -filter {name =~ */GMII_RXCNT/muxMyMac*/D}] -set_max_delay $SiPDMIN -datapath_only -from [get_pins -hier -filter {name =~ */SiTCP_INT_REG/regX14Data*/C}] -to [get_pins -hier -filter {name =~ */GMII_RXCNT/muxMyMac*/D}] -set_max_delay $SiPDMIN -datapath_only -from [get_pins -hier -filter {name =~ */SiTCP_INT_REG/regX15Data*/C}] -to [get_pins -hier -filter {name =~ */GMII_RXCNT/muxMyMac*/D}] -set_max_delay $SiPDMIN -datapath_only -from [get_pins -hier -filter {name =~ */SiTCP_INT_REG/regX16Data*/C}] -to [get_pins -hier -filter {name =~ */GMII_RXCNT/muxMyMac*/D}] -set_max_delay $SiPDMIN -datapath_only -from [get_pins -hier -filter {name =~ */SiTCP_INT_REG/regX17Data*/C}] -to [get_pins -hier -filter {name =~ */GMII_RXCNT/muxMyMac*/D}] -set_max_delay $SiPDMIN -datapath_only -from [get_pins -hier -filter {name =~ */SiTCP_INT_REG/regX18Data*/C}] -to [get_pins -hier -filter {name =~ */GMII_RXCNT/muxMyIp*/D}] -set_max_delay $SiPDMIN -datapath_only -from [get_pins -hier -filter {name =~ */SiTCP_INT_REG/regX19Data*/C}] -to [get_pins -hier -filter {name =~ */GMII_RXCNT/muxMyIp*/D}] -set_max_delay $SiPDMIN -datapath_only -from [get_pins -hier -filter {name =~ */SiTCP_INT_REG/regX1AData*/C}] -to [get_pins -hier -filter {name =~ */GMII_RXCNT/muxMyIp*/D}] -set_max_delay $SiPDMIN -datapath_only -from [get_pins -hier -filter {name =~ */SiTCP_INT_REG/regX1BData*/C}] -to [get_pins -hier -filter {name =~ */GMII_RXCNT/muxMyIp*/D}] +set_max_delay $SiPDMIN -datapath_only -from [get_pins -hier -filter {name =~ */SiTCP_INT_REG/regX10Data*/C}] -to [get_pins -hier -filter {name =~ */GMII_RXCNT/irMacFlowEnb/D}] +set_max_delay $SiPDMIN -datapath_only -from [get_pins -hier -filter {name =~ */SiTCP_INT_REG/regX12Data*/C}] -to [get_pins -hier -filter {name =~ */GMII_RXCNT/muxMyMac*/D}] +set_max_delay $SiPDMIN -datapath_only -from [get_pins -hier -filter {name =~ */SiTCP_INT_REG/regX13Data*/C}] -to [get_pins -hier -filter {name =~ */GMII_RXCNT/muxMyMac*/D}] +set_max_delay $SiPDMIN -datapath_only -from [get_pins -hier -filter {name =~ */SiTCP_INT_REG/regX14Data*/C}] -to [get_pins -hier -filter {name =~ */GMII_RXCNT/muxMyMac*/D}] +set_max_delay $SiPDMIN -datapath_only -from [get_pins -hier -filter {name =~ */SiTCP_INT_REG/regX15Data*/C}] -to [get_pins -hier -filter {name =~ */GMII_RXCNT/muxMyMac*/D}] +set_max_delay $SiPDMIN -datapath_only -from [get_pins -hier -filter {name =~ */SiTCP_INT_REG/regX16Data*/C}] -to [get_pins -hier -filter {name =~ */GMII_RXCNT/muxMyMac*/D}] +set_max_delay $SiPDMIN -datapath_only -from [get_pins -hier -filter {name =~ */SiTCP_INT_REG/regX17Data*/C}] -to [get_pins -hier -filter {name =~ */GMII_RXCNT/muxMyMac*/D}] +set_max_delay $SiPDMIN -datapath_only -from [get_pins -hier -filter {name =~ */SiTCP_INT_REG/regX18Data*/C}] -to [get_pins -hier -filter {name =~ */GMII_RXCNT/muxMyIp*/D}] +set_max_delay $SiPDMIN -datapath_only -from [get_pins -hier -filter {name =~ */SiTCP_INT_REG/regX19Data*/C}] -to [get_pins -hier -filter {name =~ */GMII_RXCNT/muxMyIp*/D}] +set_max_delay $SiPDMIN -datapath_only -from [get_pins -hier -filter {name =~ */SiTCP_INT_REG/regX1AData*/C}] -to [get_pins -hier -filter {name =~ */GMII_RXCNT/muxMyIp*/D}] +set_max_delay $SiPDMIN -datapath_only -from [get_pins -hier -filter {name =~ */SiTCP_INT_REG/regX1BData*/C}] -to [get_pins -hier -filter {name =~ */GMII_RXCNT/muxMyIp*/D}] -set_max_delay $SiPDMIN -datapath_only -from [get_pins -hier -filter {name =~ */GMII_TXBUF/dlyBank0LastWrAddr*/C}] -to [get_pins -hier -filter {name =~ */GMII_TXBUF/rsmpBank0LastWrAddr*/D}] -set_max_delay $SiPDMIN -datapath_only -from [get_pins -hier -filter {name =~ */GMII_TXBUF/dlyBank1LastWrAddr*/C}] -to [get_pins -hier -filter {name =~ */GMII_TXBUF/rsmpBank1LastWrAddr*/D}] -set_max_delay $SiPDMIN -datapath_only -from [get_pins -hier -filter {name =~ */GMII_TXBUF/memRdReq*/C}] -to [get_pins -hier -filter {name =~ */GMII_TXBUF/irMemRdReq*/D}] +set_max_delay $SiPDMIN -datapath_only -from [get_pins -hier -filter {name =~ */GMII_TXBUF/dlyBank0LastWrAddr*/C}] -to [get_pins -hier -filter {name =~ */GMII_TXBUF/rsmpBank0LastWrAddr*/D}] +set_max_delay $SiPDMIN -datapath_only -from [get_pins -hier -filter {name =~ */GMII_TXBUF/dlyBank1LastWrAddr*/C}] -to [get_pins -hier -filter {name =~ */GMII_TXBUF/rsmpBank1LastWrAddr*/D}] +set_max_delay $SiPDMIN -datapath_only -from [get_pins -hier -filter {name =~ */GMII_TXBUF/memRdReq*/C}] -to [get_pins -hier -filter {name =~ */GMII_TXBUF/irMemRdReq*/D}] -set_max_delay $SiPDMIN -datapath_only -from [get_pins -hier -filter {name =~ */GMII_RXCNT/orMacTim*/C}] -to [get_pins -hier -filter {name =~ */GMII_TXCNT/irMacPauseTime*/D}] +set_max_delay $SiPDMIN -datapath_only -from [get_pins -hier -filter {name =~ */GMII_RXCNT/orMacTim*/C}] -to [get_pins -hier -filter {name =~ */GMII_TXCNT/irMacPauseTime*/D}] set_max_delay $SiPDMIN -datapath_only -from [get_pins -hier -filter {name =~ */GMII_RXCNT/orMacPause/C}] -to [get_pins -hier -filter {name =~ */GMII_TXCNT/irMacPauseExe_0/D}] set_false_path -from [get_pins -hier -filter {name =~ */SiTCP_INT/SiTCP_RESET_OUT/C}] diff --git a/examples/bdaq/firmware/src/bdaq53_eth_core.v b/examples/bdaq/firmware/src/bdaq53_eth_core.v index 920137f8f..e3e07d070 100644 --- a/examples/bdaq/firmware/src/bdaq53_eth_core.v +++ b/examples/bdaq/firmware/src/bdaq53_eth_core.v @@ -53,7 +53,7 @@ module bdaq53_eth_core( assign EN = GPIO[0]; reg [31:0] FIFO_DATA_REG = 0; - + always @(posedge BUS_CLK) if(EN) begin if(FIFO_READY) begin diff --git a/examples/bdaq/test/test_bdaq53_eth.py b/examples/bdaq/test/test_bdaq53_eth.py index e7252f1ac..632060ea7 100644 --- a/examples/bdaq/test/test_bdaq53_eth.py +++ b/examples/bdaq/test/test_bdaq53_eth.py @@ -9,13 +9,13 @@ import os import sys import time -import yaml import unittest +import yaml + from basil.dut import Dut from basil.utils.sim.utils import cocotb_compile_and_run, cocotb_compile_clean - doprint = True IntsToReceive = 1000 @@ -26,21 +26,29 @@ def setUp(self): proj_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) cocotb_compile_and_run( - sim_files=[proj_dir + '/test/bdaq53_eth_tb.v'], - top_level='tb', - include_dirs=(proj_dir, proj_dir + '/firmware/src') + sim_files=[proj_dir + "/test/bdaq53_eth_tb.v"], + top_level="tb", + include_dirs=(proj_dir, proj_dir + "/firmware/src"), ) - with open(proj_dir + '/bdaq53_eth.yaml') as conf_file: + with open(proj_dir + "/bdaq53_eth.yaml") as conf_file: try: conf = yaml.safe_load(conf_file) except yaml.YAMLError as exception: print(exception) - conf['transfer_layer'][0]['type'] = 'SiSim' - conf['transfer_layer'][0]['tcp_connection'] = 'False' - - conf['hw_drivers'].append({'name': 'FIFO', 'type': 'sram_fifo', 'interface': 'intf', 'base_addr': 0x8000, 'base_data_addr': 0x80000000}) + conf["transfer_layer"][0]["type"] = "SiSim" + conf["transfer_layer"][0]["tcp_connection"] = "False" + + conf["hw_drivers"].append( + { + "name": "FIFO", + "type": "sram_fifo", + "interface": "intf", + "base_addr": 0x8000, + "base_data_addr": 0x80000000, + } + ) self.chip = Dut(conf) self.chip.init() @@ -52,11 +60,11 @@ def test(self): tick_old = 0 start_time = time.time() - self.chip['CONTROL']['EN'] = 0x01 # start data source - self.chip['CONTROL'].write() + self.chip["CONTROL"]["EN"] = 0x01 # start data source + self.chip["CONTROL"].write() while time.time() - start_time < testduration: - data = self.chip['FIFO'].get_data() + data = self.chip["FIFO"].get_data() total_len += len(data) time.sleep(0.01) tick = int(time.time() - start_time) @@ -75,15 +83,19 @@ def test(self): break total_len_bits = total_len * 32 # 32-bit ints to bits - print('Bits received: {}; Data rate: {}Mbit/s'.format(total_len_bits, round((total_len_bits / 1e6 / testduration), 2))) + print( + "Bits received: {}; Data rate: {}Mbit/s".format( + total_len_bits, round((total_len_bits / 1e6 / testduration), 2) + ) + ) - self.chip['CONTROL']['EN'] = 0x00 # stop data source - self.chip['CONTROL'].write() + self.chip["CONTROL"]["EN"] = 0x00 # stop data source + self.chip["CONTROL"].write() def tearDown(self): self.chip.close() # let it close connection and stop simulator cocotb_compile_clean() -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/examples/lab_devices/MotorStage.py b/examples/lab_devices/MotorStage.py index c02832dd1..7cd85ebe1 100644 --- a/examples/lab_devices/MotorStage.py +++ b/examples/lab_devices/MotorStage.py @@ -5,13 +5,13 @@ # ------------------------------------------------------------ # -''' This script shows how to use a Motor Stage -''' +"""This script shows how to use a Motor Stage""" import time + from basil.dut import Dut -dut = Dut('mercury_pyserial.yaml') +dut = Dut("mercury_pyserial.yaml") dut.init() # setup (for c-862) diff --git a/examples/lab_devices/ProbeStation.py b/examples/lab_devices/ProbeStation.py index 747411396..7fc6b173f 100644 --- a/examples/lab_devices/ProbeStation.py +++ b/examples/lab_devices/ProbeStation.py @@ -5,7 +5,7 @@ # ------------------------------------------------------------ # -''' This script shows how to use a Suss or Signatone Probe station. +"""This script shows how to use a Suss or Signatone Probe station. BTW: For the PA-200 it is not forseen to be able to communicate with the prober bench software @@ -16,17 +16,16 @@ comport has to be created connecting the real comport (that is set in the RS232 Interface application, pbrs232.exe) to a virtual one. This virtual one is then used to steer the probe station within BASIL. -''' - +""" from basil.dut import Dut -dut = Dut('suss_pa_200.yaml') +dut = Dut("suss_pa_200.yaml") dut.init() -print(dut['SussProber'].get_position()) -print(dut['SussProber'].get_die()) +print(dut["SussProber"].get_position()) +print(dut["SussProber"].get_die()) -dut2 = Dut('SignatoneProber.yaml') +dut2 = Dut("SignatoneProber.yaml") dut2.init() -print(dut2['SignatoneProber'].get_position()) -print(dut2['SignatoneProber'].get_die()) +print(dut2["SignatoneProber"].get_position()) +print(dut2["SignatoneProber"].get_die()) diff --git a/examples/lab_devices/SentioProber.py b/examples/lab_devices/SentioProber.py index 28d42128d..bb97f93b7 100644 --- a/examples/lab_devices/SentioProber.py +++ b/examples/lab_devices/SentioProber.py @@ -1,14 +1,15 @@ -from basil.dut import Dut import os import sys +from basil.dut import Dut + print(os.path.dirname(sys.executable)) # Sentio Prober Control -dut = Dut('SentioProber_config.yaml') +dut = Dut("SentioProber_config.yaml") dut.init() # print(dut['Prober'].separate()) -print(dut['Prober'].set_position(160000, -40000)) +print(dut["Prober"].set_position(160000, -40000)) # print(dut['Prober'].move_position(100,-50)) # print(dut['Prober'].get_position()) # print(dut['Prober'].goto_next_die()) diff --git a/examples/lab_devices/SentioProber_config.yaml b/examples/lab_devices/SentioProber_config.yaml index f46ae7ea5..f4643ff60 100644 --- a/examples/lab_devices/SentioProber_config.yaml +++ b/examples/lab_devices/SentioProber_config.yaml @@ -12,4 +12,4 @@ transfer_layer: hw_drivers: - name : Prober type : SentioProber - interface : ProberSocket \ No newline at end of file + interface : ProberSocket diff --git a/examples/lab_devices/WeissLabEvent_socket.yaml b/examples/lab_devices/WeissLabEvent_socket.yaml index 7f80d83a0..b4ce8072b 100644 --- a/examples/lab_devices/WeissLabEvent_socket.yaml +++ b/examples/lab_devices/WeissLabEvent_socket.yaml @@ -14,4 +14,3 @@ hw_drivers: - name : Climatechamber type : weiss_labevent interface : Socket - diff --git a/examples/lab_devices/arduino_ntc_readout.py b/examples/lab_devices/arduino_ntc_readout.py index 15f82755e..2be1029b2 100644 --- a/examples/lab_devices/arduino_ntc_readout.py +++ b/examples/lab_devices/arduino_ntc_readout.py @@ -5,45 +5,44 @@ # ------------------------------------------------------------ # -''' Example how to use the Arduino as NTC readout. -''' +"""Example how to use the Arduino as NTC readout.""" import time from basil.dut import Dut -dut = Dut('arduino_ntc_readout.yaml') +dut = Dut("arduino_ntc_readout.yaml") dut.init() time.sleep(2) print(f"Communication delay after command to Arduino is {dut['NTCReadout'].communication_delay} ms") -dut['NTCReadout'].communication_delay = 5 # Set delay between two commands to 5 milli seconds +dut["NTCReadout"].communication_delay = 5 # Set delay between two commands to 5 milli seconds print(f"Communication delay after command to Arduino is {dut['NTCReadout'].communication_delay} ms") print(f"Number of samples to average NTC measurement is {dut['NTCReadout'].n_samples}") -dut['NTCReadout'].n_samples = 10 # Set amount of NTC measurements to average +dut["NTCReadout"].n_samples = 10 # Set amount of NTC measurements to average print(f"Number of samples to average NTC measurement is {dut['NTCReadout'].n_samples}") print(f"Beta coefficient is {dut['NTCReadout'].beta_coefficient} Kelvin") -dut['NTCReadout'].beta_coefficient = 3450 # Set beta in K +dut["NTCReadout"].beta_coefficient = 3450 # Set beta in K print(f"Beta coefficient is {dut['NTCReadout'].beta_coefficient} Kelvin") print(f"Nominal NTC resistance is {dut['NTCReadout'].nominal_resistance} Ohm") -dut['NTCReadout'].nominal_resistance = 20e3 # Set nom. res. in Ohm +dut["NTCReadout"].nominal_resistance = 20e3 # Set nom. res. in Ohm print(f"Nominal NTC resistance is {dut['NTCReadout'].nominal_resistance} Ohm") print(f"Nominal NTC temperature is {dut['NTCReadout'].nominal_temperature} °C") -dut['NTCReadout'].nominal_temperature = 30 # Set nom. res. in Ohm +dut["NTCReadout"].nominal_temperature = 30 # Set nom. res. in Ohm print(f"Nominal NTC temperature is {dut['NTCReadout'].nominal_temperature} °C") print(f"Resistor value is {dut['NTCReadout'].resistance} Ohm") -dut['NTCReadout'].resistance = 15e3 # Set res. in Ohm +dut["NTCReadout"].resistance = 15e3 # Set res. in Ohm print(f"Resistor value is {dut['NTCReadout'].resistance} Ohm") print("Restore defaults") -dut['NTCReadout'].restore_defaults() +dut["NTCReadout"].restore_defaults() print(f"Communication delay after command to Arduino is {dut['NTCReadout'].communication_delay} ms") print(f"Number of samples to average NTC measurement is {dut['NTCReadout'].n_samples}") @@ -53,11 +52,11 @@ print(f"Resistor value is {dut['NTCReadout'].resistance} Ohm") # Read temperature in degree C and resistanc ein Ohm for the first 4 inputs -print(dut['NTCReadout'].get_temp(list(range(4)))) -print(dut['NTCReadout'].get_res(list(range(4)))) +print(dut["NTCReadout"].get_temp(list(range(4)))) +print(dut["NTCReadout"].get_res(list(range(4)))) print(f"Voltage is measured over NTC in divider config: {dut['NTCReadout'].measure_v_drop_over_ntc}") print(f"Resistance is: {dut['NTCReadout'].get_res(1)}") -dut['NTCReadout'].measure_v_drop_over_ntc = True +dut["NTCReadout"].measure_v_drop_over_ntc = True print(f"Voltage is measured over NTC in divider config: {dut['NTCReadout'].measure_v_drop_over_ntc}") print(f"Resistance is: {dut['NTCReadout'].get_res(1)}") diff --git a/examples/lab_devices/arduino_relay_board.py b/examples/lab_devices/arduino_relay_board.py index 3113ed150..42af5b92e 100644 --- a/examples/lab_devices/arduino_relay_board.py +++ b/examples/lab_devices/arduino_relay_board.py @@ -5,29 +5,28 @@ # ------------------------------------------------------------ # -''' Example how to use the digital IO of the Arduino board. -''' +"""Example how to use the digital IO of the Arduino board.""" import time from basil.dut import Dut -dut = Dut('arduino_relay_board.yaml') +dut = Dut("arduino_relay_board.yaml") dut.init() time.sleep(2) # Wait for Arduino to reset print(f"Communication delay after command to Arduino is {dut['RelayBoard'].communication_delay} ms") -dut['RelayBoard'].communication_delay = 5 # Set delay between two commands to 5 milli seconds +dut["RelayBoard"].communication_delay = 5 # Set delay between two commands to 5 milli seconds print(f"Communication delay after command to Arduino is {dut['RelayBoard'].communication_delay} ms") print(f"State of RelayBoard is: {dut['RelayBoard'].get_state()}") for i in range(2, 12): print(f"Switching on channel {i}") - dut['RelayBoard'].set_output(channel=i, value='ON') + dut["RelayBoard"].set_output(channel=i, value="ON") print(f"State of RelayBoard is: {dut['RelayBoard'].get_state()}") print("Switching off all channels") -dut['RelayBoard'].set_output(channel='ALL', value='OFF') +dut["RelayBoard"].set_output(channel="ALL", value="OFF") print(f"State of RelayBoard is: {dut['RelayBoard'].get_state()}") diff --git a/examples/lab_devices/arduino_serial_to_i2c.py b/examples/lab_devices/arduino_serial_to_i2c.py index 221da4809..d4dd3eb17 100644 --- a/examples/lab_devices/arduino_serial_to_i2c.py +++ b/examples/lab_devices/arduino_serial_to_i2c.py @@ -5,26 +5,27 @@ # ------------------------------------------------------------ # -''' Example how to use the SerialToI2C Arduino interface. -''' +"""Example how to use the SerialToI2C Arduino interface.""" import time from basil.dut import Dut -dut = Dut('arduino_serial_to_i2c.yaml') +dut = Dut("arduino_serial_to_i2c.yaml") dut.init() time.sleep(2) # Allow tranfer layer to initialize / arduino to boot print(f"Communication delay after command to Arduino is {dut['SerialToI2C'].communication_delay} ms") -dut['SerialToI2C'].communication_delay = 5 # Set delay between two commands to 5 milli seconds +dut["SerialToI2C"].communication_delay = 5 # Set delay between two commands to 5 milli seconds print(f"Communication delay after command to Arduino is {dut['SerialToI2C'].communication_delay} ms") print(f"I2C bus address to write to is {dut['SerialToI2C'].i2c_address}") -dut['SerialToI2C'].i2c_address = 0x20 # Set I2C address +dut["SerialToI2C"].i2c_address = 0x20 # Set I2C address print(f"I2C bus address to write to is {dut['SerialToI2C'].i2c_address}") -dut['SerialToI2C'].check_i2c_connection() # Check if connection is established on I2C bus with given address -dut['SerialToI2C'].read_register(reg=0x00) # Read register 0x00 at adress dut['SerialToI2C'].i2c_address -dut['SerialToI2C'].write_register(reg=0x00, data=0x00) # Write 0 to register 0x00 at adress dut['SerialToI2C'].i2c_address +dut["SerialToI2C"].check_i2c_connection() # Check if connection is established on I2C bus with given address +dut["SerialToI2C"].read_register(reg=0x00) # Read register 0x00 at adress dut['SerialToI2C'].i2c_address +dut["SerialToI2C"].write_register( + reg=0x00, data=0x00 +) # Write 0 to register 0x00 at adress dut['SerialToI2C'].i2c_address diff --git a/examples/lab_devices/bronkhorsteflow.py b/examples/lab_devices/bronkhorsteflow.py index e48a326ea..73c3aca87 100644 --- a/examples/lab_devices/bronkhorsteflow.py +++ b/examples/lab_devices/bronkhorsteflow.py @@ -5,12 +5,11 @@ # ------------------------------------------------------------ # -''' This script shows how to use EFLOW -''' +"""This script shows how to use EFLOW""" from basil.dut import Dut -dut = Dut('bronkhorstELFLOW_pyserial.yaml') +dut = Dut("bronkhorstELFLOW_pyserial.yaml") dut.init() # setting set point diff --git a/examples/lab_devices/hp_4284a_pyvisa.yaml b/examples/lab_devices/hp_4284a_pyvisa.yaml index 2ffd5faa2..97514460e 100644 --- a/examples/lab_devices/hp_4284a_pyvisa.yaml +++ b/examples/lab_devices/hp_4284a_pyvisa.yaml @@ -3,7 +3,7 @@ transfer_layer: type : Visa init : resource_name : GPIB0::17::INSTR - + hw_drivers: - name : LCRMeter type : hp4284a diff --git a/examples/lab_devices/hp_81104a_pyvisa.yaml b/examples/lab_devices/hp_81104a_pyvisa.yaml index 24b148e7d..a3ed31815 100644 --- a/examples/lab_devices/hp_81104a_pyvisa.yaml +++ b/examples/lab_devices/hp_81104a_pyvisa.yaml @@ -3,7 +3,7 @@ transfer_layer: type : Visa init : resource_name : GPIB0::1::INSTR - + hw_drivers: - name : ClockGenerator type : scpi diff --git a/examples/lab_devices/iseg_shq.py b/examples/lab_devices/iseg_shq.py index 43f8f8070..41a57dd84 100644 --- a/examples/lab_devices/iseg_shq.py +++ b/examples/lab_devices/iseg_shq.py @@ -5,62 +5,61 @@ # ------------------------------------------------------------ # -''' Example how to use the Arduino as NTC readout. -''' +"""Example how to use the Arduino as NTC readout.""" from basil.dut import Dut -dut = Dut('iseg_shq.yaml') +dut = Dut("iseg_shq.yaml") dut.init() # Set PSU channel -dut['SHQ'].set_current_channel(1) +dut["SHQ"].set_current_channel(1) # Set voltage ramp speed in V/s -dut['SHQ'].set_ramp_speed(2) +dut["SHQ"].set_ramp_speed(2) # Set autostart to True in order to automatically start voltage change when new voltage is set -dut['SHQ'].set_autostart(True) +dut["SHQ"].set_autostart(True) # Set voltage to +-30 volts; requires hardware polarity change -polarity = dut['SHQ'].get_polarity() +polarity = dut["SHQ"].get_polarity() -dut['SHQ'].set_high_voltage(15 * polarity) # Set high voltage; hv_on() / hv_off() -dut['SHQ'].set_voltage_limit(20 * polarity) # Set software-side voltage limit -dut['SHQ'].set_voltage(10 * polarity) # Set voltage +dut["SHQ"].set_high_voltage(15 * polarity) # Set high voltage; hv_on() / hv_off() +dut["SHQ"].set_voltage_limit(20 * polarity) # Set software-side voltage limit +dut["SHQ"].set_voltage(10 * polarity) # Set voltage -dut['SHQ'].set_current_trip(10) # Set current trip in mA -dut['SHQ'].set_current_trip(10000, resolution="muA") # Set current trip in µA +dut["SHQ"].set_current_trip(10) # Set current trip in mA +dut["SHQ"].set_current_trip(10000, resolution="muA") # Set current trip in µA # Disable autostart -dut['SHQ'].set_autostart(False) +dut["SHQ"].set_autostart(False) # Read back the voltage that is measured at the output -print(dut['SHQ'].get_voltage()) +print(dut["SHQ"].get_voltage()) # Read back the current that is measured at the output -print(dut['SHQ'].get_current()) +print(dut["SHQ"].get_current()) # Read back the software-side voltage limit -print(dut['SHQ'].get_voltage_limit()) +print(dut["SHQ"].get_voltage_limit()) # Read back the hardware-side voltage-limit -print(dut['SHQ'].get_hardware_voltage_limit()) +print(dut["SHQ"].get_hardware_voltage_limit()) # Read back the voltage that is set to be the output -print(dut['SHQ'].get_source_voltage()) +print(dut["SHQ"].get_source_voltage()) # Read back the current trip (default is mA range) -print(dut['SHQ'].get_current_trip()) +print(dut["SHQ"].get_current_trip()) # Read back the current trip in mA -print(dut['SHQ'].get_current_trip(resolution="mA")) +print(dut["SHQ"].get_current_trip(resolution="mA")) # Read back the current trip in µA -print(dut['SHQ'].get_current_trip("muA")) +print(dut["SHQ"].get_current_trip("muA")) # Print the module description -print(dut['SHQ'].get_module_description()) +print(dut["SHQ"].get_module_description()) # Print the module description -print(dut['SHQ'].get_identifier()) +print(dut["SHQ"].get_identifier()) diff --git a/examples/lab_devices/iseg_shq.yaml b/examples/lab_devices/iseg_shq.yaml index 724781338..8eaa90fd9 100644 --- a/examples/lab_devices/iseg_shq.yaml +++ b/examples/lab_devices/iseg_shq.yaml @@ -15,6 +15,6 @@ hw_drivers: init : # high_voltage : 15 # Set HV to be 15 V # v_lim : 100 # Set software-side voltage limit to be 100 V - n_channel : 1 # Set number of channels the ISEG HV PS has + n_channel : 1 # Set number of channels the ISEG HV PS has channel : 1 # Set channel number autostart : True # Set autostart to True in order to automatically start voltage change when new voltage is set diff --git a/examples/lab_devices/julaboF32HD.py b/examples/lab_devices/julaboF32HD.py index ba5e51f72..9fcebc73e 100644 --- a/examples/lab_devices/julaboF32HD.py +++ b/examples/lab_devices/julaboF32HD.py @@ -5,12 +5,11 @@ # ------------------------------------------------------------ # -''' Example how to use the chiller. -''' +"""Example how to use the chiller.""" from basil.dut import Dut -dut = Dut('julaboF32HD.yaml') +dut = Dut("julaboF32HD.yaml") dut.init() print("ID: {}".format(dut["chiller"].get_identifier())) print("Status: {}".format(dut["chiller"].get_status())) diff --git a/examples/lab_devices/julaboFP50.py b/examples/lab_devices/julaboFP50.py index 29034468f..da499631a 100644 --- a/examples/lab_devices/julaboFP50.py +++ b/examples/lab_devices/julaboFP50.py @@ -1,6 +1,6 @@ from basil.dut import Dut -dut = Dut('julaboFP50_pyserial.yaml') +dut = Dut("julaboFP50_pyserial.yaml") dut.init() diff --git a/examples/lab_devices/keithley2634b.yaml b/examples/lab_devices/keithley2634b.yaml index e85219f9a..bbc9ae909 100644 --- a/examples/lab_devices/keithley2634b.yaml +++ b/examples/lab_devices/keithley2634b.yaml @@ -12,4 +12,4 @@ hw_drivers: type: scpi interface: Serial init: - device: Keithley 2634B \ No newline at end of file + device: Keithley 2634B diff --git a/examples/lab_devices/keithley6517a.py b/examples/lab_devices/keithley6517a.py index 7455eb628..02a3c055f 100644 --- a/examples/lab_devices/keithley6517a.py +++ b/examples/lab_devices/keithley6517a.py @@ -6,13 +6,14 @@ # Manual https://download.tek.com/manual/6517A_900_01C.pdf import time + from basil.dut import Dut ################## # Initialisation # ################## -dut = Dut('keithley6517a_pyvisa.yaml') +dut = Dut("keithley6517a_pyvisa.yaml") dut.init() ######################### @@ -24,29 +25,31 @@ def current_measurement(): # Use electrometer to measure current with configuration of fig 2-9, p.2-11 of manual # Connect the internal meter to the voltage source as shwon in fig 2-9 - dut['EMeter'].connect_meter() + dut["EMeter"].connect_meter() # Setup the electrometer for current measurement - dut['EMeter'].setup_current_measurement(current_range=2e-10, # Also 'MIN'/'MAX' e.g. 20e-12/12e-3 A or any number in between or None for autorange - voltage_range='MIN', # Also 'MIN'/'MAX' e.g. 100/1000 V or any number in between - current_limit=1e-10, # Current limit for protection DUT - filter=('REP', 5)) # Average filter to apply e.g. REPeat measurement 5 times andy yield average + dut["EMeter"].setup_current_measurement( + current_range=2e-10, # Also 'MIN'/'MAX' e.g. 20e-12/12e-3 A or any number in between or None for autorange + voltage_range="MIN", # Also 'MIN'/'MAX' e.g. 100/1000 V or any number in between + current_limit=1e-10, # Current limit for protection DUT + filter=("REP", 5), + ) # Average filter to apply e.g. REPeat measurement 5 times andy yield average # Turn the output on - dut['EMeter'].on() + dut["EMeter"].on() # Loop over voltages for i in range(5): - dut['Emeter'].set_voltage(i) + dut["Emeter"].set_voltage(i) time.sleep(1) # Bias voltage needs time to settle for precise measurement -> maybe needs to be increased print(f"{dut['EMeter'].get_current()} A @ {i} V") # Ramp down for j in range(4, -1, -1): - dut['Emeter'].set_voltage(j) + dut["Emeter"].set_voltage(j) # Turn the output off - dut['EMeter'].off() + dut["EMeter"].off() -if __name__ == '__main__': +if __name__ == "__main__": current_measurement() diff --git a/examples/lab_devices/keithley6517a_pyvisa.yaml b/examples/lab_devices/keithley6517a_pyvisa.yaml index e408fb557..0cf67ab9b 100644 --- a/examples/lab_devices/keithley6517a_pyvisa.yaml +++ b/examples/lab_devices/keithley6517a_pyvisa.yaml @@ -9,7 +9,7 @@ transfer_layer: init: # using serial-USB adapter # resource_name: ASRLCOM6 # example for windows system - resource_name: ASRL/dev/ttyUSB0 # example for linux system + resource_name: ASRL/dev/ttyUSB0 # example for linux system timeout : 2000 # Needed because of sleeps in between write in subclass of keithley6517a TL read_termination: "\n" baud_rate: 19200 diff --git a/examples/lab_devices/rs_hmp4040.yaml b/examples/lab_devices/rs_hmp4040.yaml index af20f42e0..ecd4c3a54 100644 --- a/examples/lab_devices/rs_hmp4040.yaml +++ b/examples/lab_devices/rs_hmp4040.yaml @@ -12,4 +12,4 @@ hw_drivers: type: rs_hmp4040 interface: Visa init: - device : rs_hmp4040 \ No newline at end of file + device : rs_hmp4040 diff --git a/examples/lab_devices/rs_hmp4040_pyvisa.yaml b/examples/lab_devices/rs_hmp4040_pyvisa.yaml index 1d1ccf6a3..9d6835b1b 100644 --- a/examples/lab_devices/rs_hmp4040_pyvisa.yaml +++ b/examples/lab_devices/rs_hmp4040_pyvisa.yaml @@ -11,4 +11,4 @@ hw_drivers: type : scpi interface : Visa init : - device : rs_hmp4040 \ No newline at end of file + device : rs_hmp4040 diff --git a/examples/lab_devices/scpi_devices.py b/examples/lab_devices/scpi_devices.py index 46d6c37ba..79f318997 100644 --- a/examples/lab_devices/scpi_devices.py +++ b/examples/lab_devices/scpi_devices.py @@ -5,52 +5,51 @@ # ------------------------------------------------------------ # -''' Example how to use different laboratory devices (Sourcemeter, pulsers, etc.) that understand SCPI. - The language (SCPI) is independent of the interface (TCP, RS232, GPIB, USB, etc.). The interfaces - can be choosen by an appropriate transportation layer (TL). This can be a VISA TL and - a Serial TL at the moment. VISA TL is recommendet since it gives you access to almost - all laboratory devices (> 90%) over TCP, RS232, USB, GPIB (Windows only so far). - ''' - +"""Example how to use different laboratory devices (Sourcemeter, pulsers, etc.) that understand SCPI. +The language (SCPI) is independent of the interface (TCP, RS232, GPIB, USB, etc.). The interfaces +can be choosen by an appropriate transportation layer (TL). This can be a VISA TL and +a Serial TL at the moment. VISA TL is recommendet since it gives you access to almost +all laboratory devices (> 90%) over TCP, RS232, USB, GPIB (Windows only so far). +""" from basil.dut import Dut # Talk to a Keithley device via serial port using pySerial -dut = Dut('keithley2400_pyserial.yaml') +dut = Dut("keithley2400_pyserial.yaml") dut.init() -print(dut['Sourcemeter'].get_name()) +print(dut["Sourcemeter"].get_name()) # Talk to a Keithley device via serial port using VISA with Serial interface -dut = Dut('keithley2400_pyvisa.yaml') +dut = Dut("keithley2400_pyvisa.yaml") dut.init() -print(dut['Sourcemeter'].get_name()) +print(dut["Sourcemeter"].get_name()) # Some additional implemented methods for this device -print(dut['Sourcemeter'].get_voltage()) -dut['Sourcemeter'].off() -dut['Sourcemeter'].set_voltage(3.14159) -dut['Sourcemeter'].set_current_limit(.9265) +print(dut["Sourcemeter"].get_voltage()) +dut["Sourcemeter"].off() +dut["Sourcemeter"].set_voltage(3.14159) +dut["Sourcemeter"].set_current_limit(0.9265) # Example of a SCPI device implementing more specialized functions (e.g. unit conversion) via extra class definitions -dut = Dut('agilent33250a_pyserial.yaml') +dut = Dut("agilent33250a_pyserial.yaml") dut.init() -print(dut['Pulser'].get_info()) +print(dut["Pulser"].get_info()) # Some additional implemented methods for this device -dut['Pulser'].set_voltage(0., 1., unit='V') -print("{}{}".format(dut['Pulser'].get_voltage(0, unit='mV'), 'mV')) +dut["Pulser"].set_voltage(0.0, 1.0, unit="V") +print("{}{}".format(dut["Pulser"].get_voltage(0, unit="mV"), "mV")) # Example for device with multiple channels -dut = Dut('ttiql355tp.yaml') +dut = Dut("ttiql355tp.yaml") dut.init() -print(dut['PowerSupply'].get_name()) -print(dut['PowerSupply'].get_voltage(channel=1)) +print(dut["PowerSupply"].get_name()) +print(dut["PowerSupply"].get_voltage(channel=1)) # Talk to a Keithley device via GPIB using NI VISA -dut = Dut('keithley2000_pyvisa.yaml') +dut = Dut("keithley2000_pyvisa.yaml") dut.init() -print(dut['Multimeter'].get_name()) +print(dut["Multimeter"].get_name()) # Talk to a Tektronix mixed signal oscilloscope via TCPIP, USB -dut = Dut('tektronixMSO4104B_pyvisa.yaml') +dut = Dut("tektronixMSO4104B_pyvisa.yaml") dut.init() -print(dut['Oscilloscope'].get_name()) -print(dut['Oscilloscope'].get_data(channel=1)) +print(dut["Oscilloscope"].get_name()) +print(dut["Oscilloscope"].get_data(channel=1)) diff --git a/examples/lab_devices/tektronix_oscilloscope_tds3034b.py b/examples/lab_devices/tektronix_oscilloscope_tds3034b.py index cc012ee5d..d9b9683ac 100644 --- a/examples/lab_devices/tektronix_oscilloscope_tds3034b.py +++ b/examples/lab_devices/tektronix_oscilloscope_tds3034b.py @@ -11,23 +11,24 @@ # If such an error occures, reboot the oscilloscope # -from basil.dut import Dut -import numpy as np import matplotlib.pyplot as plt +import numpy as np + +from basil.dut import Dut -dut = Dut('tektronix_tds_3034b.yaml') +dut = Dut("tektronix_tds_3034b.yaml") dut.init() # Control settings of the oscilloscope -dut['Oscilloscope'].set_vertical_scale('5.0E-2', channel=1) -dut['Oscilloscope'].set_vertical_position('0', channel=1) -dut['Oscilloscope'].set_vertical_offset('0.0E0', channel=1) -dut['Oscilloscope'].set_trigger_source(channel=1) -dut['Oscilloscope'].set_trigger_level(1e-2) -dut['Oscilloscope'].set_trigger_mode('AUTO') +dut["Oscilloscope"].set_vertical_scale("5.0E-2", channel=1) +dut["Oscilloscope"].set_vertical_position("0", channel=1) +dut["Oscilloscope"].set_vertical_offset("0.0E0", channel=1) +dut["Oscilloscope"].set_trigger_source(channel=1) +dut["Oscilloscope"].set_trigger_level(1e-2) +dut["Oscilloscope"].set_trigger_mode("AUTO") # Taking a measurement -meas_waveform = dut['Oscilloscope'].get_waveform(channel=1) +meas_waveform = dut["Oscilloscope"].get_waveform(channel=1) CH_id = meas_waveform[0] CH_data = meas_waveform[1] CH_xscale = meas_waveform[2] @@ -36,10 +37,10 @@ # Plot the data plt.figure(figsize=(16, 9)) -plt.scatter(CH_time, CH_data, label='CH' + str(CH_id)) +plt.scatter(CH_time, CH_data, label="CH" + str(CH_id)) plt.ylim(-4 * CH_yscale[0], 4 * CH_yscale[0]) -plt.xlabel('Time $t$ / s') -plt.ylabel('Voltage U / V') +plt.xlabel("Time $t$ / s") +plt.ylabel("Voltage U / V") plt.grid() plt.legend() plt.show() diff --git a/examples/lab_devices/tektronix_tds_3034b.yaml b/examples/lab_devices/tektronix_tds_3034b.yaml index e43276ed1..fe3d38e99 100644 --- a/examples/lab_devices/tektronix_tds_3034b.yaml +++ b/examples/lab_devices/tektronix_tds_3034b.yaml @@ -12,4 +12,4 @@ hw_drivers: type : tektronix_tds3034b interface : Visa init : - device : tektronix oscilloscope \ No newline at end of file + device : tektronix oscilloscope diff --git a/examples/lab_devices/temperature_control.py b/examples/lab_devices/temperature_control.py index 67d94755e..a8b7580c3 100644 --- a/examples/lab_devices/temperature_control.py +++ b/examples/lab_devices/temperature_control.py @@ -5,28 +5,27 @@ # ------------------------------------------------------------ # -''' - This script shows how to set temperature using a Binder MK 53 climate chamber. - For the communication with the Binder MK 53 also a serial TL has to be used (http://www.binder-world.com). - The newer Weiss Labevent climatechamber uses a direct TCP/IP connection. -''' - +""" +This script shows how to set temperature using a Binder MK 53 climate chamber. +For the communication with the Binder MK 53 also a serial TL has to be used (http://www.binder-world.com). +The newer Weiss Labevent climatechamber uses a direct TCP/IP connection. +""" from basil.dut import Dut # Binder MK 53 control -dut = Dut('binderMK53_pyserial.yaml') +dut = Dut("binderMK53_pyserial.yaml") dut.init() -print(dut['Climatechamber'].get_temperature()) -print(dut['Climatechamber'].get_door_open()) -print(dut['Climatechamber'].get_mode()) -temperature_target = dut['Climatechamber'].get_temperature_target() -dut['Climatechamber'].set_temperature(temperature_target) +print(dut["Climatechamber"].get_temperature()) +print(dut["Climatechamber"].get_door_open()) +print(dut["Climatechamber"].get_mode()) +temperature_target = dut["Climatechamber"].get_temperature_target() +dut["Climatechamber"].set_temperature(temperature_target) # New Weiss Labevent control -dut = Dut('WeissLabEvent_socket.yaml') +dut = Dut("WeissLabEvent_socket.yaml") dut.init() -dut['Climatechamber'].start_manual_mode() -dut['Climatechamber'].set_temperature(20) -dut['Climatechamber'].set_air_dryer(True) # Make sure the air dryer is turned on -print(dut['Climatechamber'].get_temperature()) +dut["Climatechamber"].start_manual_mode() +dut["Climatechamber"].set_temperature(20) +dut["Climatechamber"].set_air_dryer(True) # Make sure the air dryer is turned on +print(dut["Climatechamber"].get_temperature()) diff --git a/examples/lab_devices/temperature_sensors.py b/examples/lab_devices/temperature_sensors.py index 9e7e0fac2..5b5ad0520 100644 --- a/examples/lab_devices/temperature_sensors.py +++ b/examples/lab_devices/temperature_sensors.py @@ -5,28 +5,28 @@ # ------------------------------------------------------------ # -''' - This script shows how to read temperature/humidity with Sensirion sensors. - Some Sensirion sensors are read using the Sensirion EK-H4 multiplexer box from the evaluation kit. A serial TL has to be used - (http://www.sensirion.com/fileadmin/user_upload/customers/sensirion/Dokumente/Humidity/Sensirion_Humidity_EK-H4_Datasheet_V3.pdf). - The Sensirion SHT85 sensor is read using the Sensirion Sensor Bridge. -''' - +""" +This script shows how to read temperature/humidity with Sensirion sensors. +Some Sensirion sensors are read using the Sensirion EK-H4 multiplexer box from the evaluation kit. A serial TL has to be used +(http://www.sensirion.com/fileadmin/user_upload/customers/sensirion/Dokumente/Humidity/Sensirion_Humidity_EK-H4_Datasheet_V3.pdf). +The Sensirion SHT85 sensor is read using the Sensirion Sensor Bridge. +""" import time + from basil.dut import Dut # Sensirion EK-H4 sensor readout -dut = Dut('sensirionEKH4_pyserial.yaml') +dut = Dut("sensirionEKH4_pyserial.yaml") dut.init() -print(dut['Thermohygrometer'].get_temperature()) -print(dut['Thermohygrometer'].get_humidity()) -print(dut['Thermohygrometer'].get_dew_point()) +print(dut["Thermohygrometer"].get_temperature()) +print(dut["Thermohygrometer"].get_humidity()) +print(dut["Thermohygrometer"].get_dew_point()) # Sensirion SHT85 sensor readout -dut = Dut('sensirionSHT85.yaml') +dut = Dut("sensirionSHT85.yaml") dut.init() -sensor = dut['Thermohygrometer'] +sensor = dut["Thermohygrometer"] sensor.printInformation() for action in sensor.enable_heater, sensor.disable_heater: action() @@ -35,7 +35,7 @@ print(sensor.get_temperature_and_humidity(), sensor.get_dew_point()) with sensor.asynchronous(measurments_per_second=1) as a: for _ in range(10): - time.sleep(.8) + time.sleep(0.8) T, RH = a.read() if T is not None: print(T, RH, sensor.to_dew_point(T, RH)) diff --git a/examples/lab_devices/xray_tube.py b/examples/lab_devices/xray_tube.py index 28d8d5042..2757d84f1 100644 --- a/examples/lab_devices/xray_tube.py +++ b/examples/lab_devices/xray_tube.py @@ -1,8 +1,9 @@ import time + from basil.dut import Dut # Initialize x-ray tube -devices = Dut('xray_tube_pyserial.yaml') +devices = Dut("xray_tube_pyserial.yaml") devices.init() # Set high voltage and current diff --git a/examples/lx9/device/src/top.ucf b/examples/lx9/device/src/top.ucf index 7d46dd9f3..6c07c6fbe 100644 --- a/examples/lx9/device/src/top.ucf +++ b/examples/lx9/device/src/top.ucf @@ -44,4 +44,3 @@ TIMESPEC TS_ETH_RX_CLK = PERIOD ETH_RX_CLK_TMN 25000 kHz; NET ETH_TX_CLK TNM_NET = ETH_TX_CLK_TMN; TIMESPEC TS_ETH_TX_CLK = PERIOD ETH_TX_CLK_TMN 25000 kHz; - diff --git a/examples/lx9/host/lx9.py b/examples/lx9/host/lx9.py index eb63ac265..eb9e615dc 100644 --- a/examples/lx9/host/lx9.py +++ b/examples/lx9/host/lx9.py @@ -6,10 +6,10 @@ # -import yaml import time import numpy as np +import yaml from bitarray import bitarray from basil.dut import Dut @@ -33,11 +33,11 @@ def program_global_reg(self): self._clear_strobes() - gr_size = len(self['GLOBAL_REG'][:]) # get the size - self['SEQ']['SHIFT_IN'][0:gr_size] = self['GLOBAL_REG'][:] # this will be shifted out - self['SEQ']['GLOBAL_SHIFT_EN'][0:gr_size] = bitarray(gr_size * '1') # this is to enable clock - self['SEQ']['GLOBAL_CTR_LD'][gr_size + 1:gr_size + 2] = bitarray("1") # load signals - self['SEQ']['GLOBAL_DAC_LD'][gr_size + 1:gr_size + 2] = bitarray("1") + gr_size = len(self["GLOBAL_REG"][:]) # get the size + self["SEQ"]["SHIFT_IN"][0:gr_size] = self["GLOBAL_REG"][:] # this will be shifted out + self["SEQ"]["GLOBAL_SHIFT_EN"][0:gr_size] = bitarray(gr_size * "1") # this is to enable clock + self["SEQ"]["GLOBAL_CTR_LD"][gr_size + 1 : gr_size + 2] = bitarray("1") # load signals + self["SEQ"]["GLOBAL_DAC_LD"][gr_size + 1 : gr_size + 2] = bitarray("1") # Execute the program (write bits to output pins) # + 1 extra 0 bit so that everything ends on LOW instead of HIGH @@ -59,13 +59,13 @@ def program_pixel_reg(self, enable_receiver=True): self._clear_strobes() # enable receiver it work only if pixel register is enabled/clocked - self['PIXEL_RX'].set_en(enable_receiver) + self["PIXEL_RX"].set_en(enable_receiver) - px_size = len(self['PIXEL_REG'][:]) # get the size - self['SEQ']['SHIFT_IN'][0:px_size] = self['PIXEL_REG'][:] # this will be shifted out - self['SEQ']['PIXEL_SHIFT_EN'][0:px_size] = bitarray(px_size * '1') # this is to enable clock + px_size = len(self["PIXEL_REG"][:]) # get the size + self["SEQ"]["SHIFT_IN"][0:px_size] = self["PIXEL_REG"][:] # this will be shifted out + self["SEQ"]["PIXEL_SHIFT_EN"][0:px_size] = bitarray(px_size * "1") # this is to enable clock - print('px_size = {}'.format(px_size)) + print("px_size = {}".format(px_size)) self._run_seq(px_size + 1) # add 1 bit more so there is 0 at the end other way will stay high @@ -76,14 +76,14 @@ def _run_seq(self, size): """ # Write the sequence to the sequence generator (hw driver) - self['SEQ'].write(size) # write pattern to memory + self["SEQ"].write(size) # write pattern to memory - self['SEQ'].set_size(size) # set size - self['SEQ'].set_repeat(1) # set repeat + self["SEQ"].set_size(size) # set size + self["SEQ"].set_repeat(1) # set repeat for _ in range(1): - self['SEQ'].start() # start + self["SEQ"].start() # start - while not self['SEQ'].get_done(): + while not self["SEQ"].get_done(): # time.sleep(0.1) print("Wait for done...") @@ -93,52 +93,52 @@ def _clear_strobes(self): """ # reset some stuff - self['SEQ']['GLOBAL_SHIFT_EN'].setall(False) - self['SEQ']['GLOBAL_CTR_LD'].setall(False) - self['SEQ']['GLOBAL_DAC_LD'].setall(False) - self['SEQ']['PIXEL_SHIFT_EN'].setall(False) - self['SEQ']['INJECTION'].setall(False) + self["SEQ"]["GLOBAL_SHIFT_EN"].setall(False) + self["SEQ"]["GLOBAL_CTR_LD"].setall(False) + self["SEQ"]["GLOBAL_DAC_LD"].setall(False) + self["SEQ"]["PIXEL_SHIFT_EN"].setall(False) + self["SEQ"]["INJECTION"].setall(False) print("Start") -stream = open("lx9.yaml", 'r') +stream = open("lx9.yaml", "r") cnfg = yaml.safe_load(stream) chip = Pixel(cnfg) chip.init() -chip['GPIO']['LED1'] = 1 -chip['GPIO']['LED2'] = 0 -chip['GPIO']['LED3'] = 0 -chip['GPIO']['LED4'] = 0 -chip['GPIO'].write() +chip["GPIO"]["LED1"] = 1 +chip["GPIO"]["LED2"] = 0 +chip["GPIO"]["LED3"] = 0 +chip["GPIO"]["LED4"] = 0 +chip["GPIO"].write() # settings for global register (to input into global SR) # can be an integer representing the binary number desired, # or a bitarray (of the form bitarray("10101100")). -chip['GLOBAL_REG']['global_readout_enable'] = 0 # size = 1 bit -chip['GLOBAL_REG']['SRDO_load'] = 0 # size = 1 bit -chip['GLOBAL_REG']['NCout2'] = 0 # size = 1 bit -chip['GLOBAL_REG']['count_hits_not'] = 0 # size = 1 -chip['GLOBAL_REG']['count_enable'] = 0 # size = 1 -chip['GLOBAL_REG']['count_clear_not'] = 0 # size = 1 -chip['GLOBAL_REG']['S0'] = 0 # size = 1 -chip['GLOBAL_REG']['S1'] = 0 # size = 1 -chip['GLOBAL_REG']['config_mode'] = 3 # size = 2 -chip['GLOBAL_REG']['LD_IN0_7'] = 0 # size = 8 -chip['GLOBAL_REG']['LDENABLE_SEL'] = 0 # size = 1 -chip['GLOBAL_REG']['SRCLR_SEL'] = 0 # size = 1 -chip['GLOBAL_REG']['HITLD_IN'] = 0 # size = 1 -chip['GLOBAL_REG']['NCout21_25'] = 0 # size = 5 -chip['GLOBAL_REG']['column_address'] = 0 # size = 6 -chip['GLOBAL_REG']['DisVbn'] = 0 # size = 8 -chip['GLOBAL_REG']['VbpThStep'] = 0 # size = 8 -chip['GLOBAL_REG']['PrmpVbp'] = 0 # size = 8 -chip['GLOBAL_REG']['PrmpVbnFol'] = 0 # size = 8 -chip['GLOBAL_REG']['vth'] = 0 # size = 8 -chip['GLOBAL_REG']['PrmpVbf'] = 0 # size = 8 +chip["GLOBAL_REG"]["global_readout_enable"] = 0 # size = 1 bit +chip["GLOBAL_REG"]["SRDO_load"] = 0 # size = 1 bit +chip["GLOBAL_REG"]["NCout2"] = 0 # size = 1 bit +chip["GLOBAL_REG"]["count_hits_not"] = 0 # size = 1 +chip["GLOBAL_REG"]["count_enable"] = 0 # size = 1 +chip["GLOBAL_REG"]["count_clear_not"] = 0 # size = 1 +chip["GLOBAL_REG"]["S0"] = 0 # size = 1 +chip["GLOBAL_REG"]["S1"] = 0 # size = 1 +chip["GLOBAL_REG"]["config_mode"] = 3 # size = 2 +chip["GLOBAL_REG"]["LD_IN0_7"] = 0 # size = 8 +chip["GLOBAL_REG"]["LDENABLE_SEL"] = 0 # size = 1 +chip["GLOBAL_REG"]["SRCLR_SEL"] = 0 # size = 1 +chip["GLOBAL_REG"]["HITLD_IN"] = 0 # size = 1 +chip["GLOBAL_REG"]["NCout21_25"] = 0 # size = 5 +chip["GLOBAL_REG"]["column_address"] = 0 # size = 6 +chip["GLOBAL_REG"]["DisVbn"] = 0 # size = 8 +chip["GLOBAL_REG"]["VbpThStep"] = 0 # size = 8 +chip["GLOBAL_REG"]["PrmpVbp"] = 0 # size = 8 +chip["GLOBAL_REG"]["PrmpVbnFol"] = 0 # size = 8 +chip["GLOBAL_REG"]["vth"] = 0 # size = 8 +chip["GLOBAL_REG"]["PrmpVbf"] = 0 # size = 8 print("program global register...") chip.program_global_reg() @@ -147,8 +147,8 @@ def _clear_strobes(self): # can be an integer representing the binary number desired, # or a bitarray (of the form bitarray("10101100")). -chip['PIXEL_REG'][:] = bitarray('1111111010001100' * 8) -print(chip['PIXEL_REG']) +chip["PIXEL_REG"][:] = bitarray("1111111010001100" * 8) +print(chip["PIXEL_REG"]) # chip['PIXEL_REG'][0] = 0 print("program pixel register...") @@ -156,14 +156,15 @@ def _clear_strobes(self): time.sleep(0.5) # Get output size in bytes -print("chip['DATA'].get_FIFO_SIZE() = {}".format(chip['DATA'].get_FIFO_SIZE())) +print("chip['DATA'].get_FIFO_SIZE() = {}".format(chip["DATA"].get_FIFO_SIZE())) -rxd = chip['DATA'].get_data() # get data from sram fifo +rxd = chip["DATA"].get_data() # get data from sram fifo print(rxd) data0 = rxd.astype(np.uint8) # Change type to unsigned int 8 bits and take from rxd only the last 8 bits data1 = np.right_shift(rxd, 8).astype(np.uint8) # Rightshift rxd 8 bits and take again last 8 bits -data = np.reshape(np.vstack((data1, data0)), -1, order='F') # data is now a 1 dimensional array of all bytes read from the FIFO +# data is now a 1 dimensional array of all bytes read from the FIFO +data = np.reshape(np.vstack((data1, data0)), -1, order="F") bdata = np.unpackbits(data) print("data = {}".format(data)) diff --git a/examples/lx9/host/lx9.yaml b/examples/lx9/host/lx9.yaml index c1a1882ac..8a63539ec 100644 --- a/examples/lx9/host/lx9.yaml +++ b/examples/lx9/host/lx9.yaml @@ -5,42 +5,42 @@ # ------------------------------------------------------------ # -name : ExampleLx9Design +name : ExampleLx9Design version : 0.01 transfer_layer: - name : inf type : SiTcp - init: + init: ip : "192.168.10.16" udp_port : 4660 tcp_port : 24 tcp_connection : True - -hw_drivers: + +hw_drivers: - name : gpio type : gpio interface : inf base_addr : 0x0 size : 8 - + - name : SEQ_GEN type : seq_gen interface : inf mem_size : 8192 base_addr : 0x1000 - + - name : PIXEL_RX type : fast_spi_rx interface : inf base_addr : 0x0100 - + - name : DATA type : sram_fifo interface : inf base_addr : 0x200000000 base_data_addr: 0x100000000 - + registers: - name : GPIO type : StdRegister @@ -67,15 +67,15 @@ registers: type : StdRegister driver : None size : 144 - fields : - - name : global_readout_enable - size : 1 + fields : + - name : global_readout_enable + size : 1 offset : 143 - - name : SRDO_load - size : 1 + - name : SRDO_load + size : 1 offset : 142 - - name : NCout2 - size : 1 + - name : NCout2 + size : 1 offset : 141 - name : count_hits_not size : 1 @@ -148,11 +148,11 @@ registers: hw_driver : SEQ_GEN seq_width : 8 seq_size : 8192 - tracks : + tracks : - name : SHIFT_IN position : 0 - name : GLOBAL_SHIFT_EN - position : 1 + position : 1 - name : GLOBAL_CTR_LD position : 2 - name : GLOBAL_DAC_LD @@ -164,4 +164,4 @@ registers: - name : NOT_USED_0 position : 6 - name : NOT_USED_1 - position : 7 \ No newline at end of file + position : 7 diff --git a/examples/mio3_eth_gpac/README.md b/examples/mio3_eth_gpac/README.md index 14b8ed005..fb8246483 100644 --- a/examples/mio3_eth_gpac/README.md +++ b/examples/mio3_eth_gpac/README.md @@ -7,4 +7,3 @@ The firmware makes use of the free SiTcp Ethernet module ([general website][url1 [url1]: https://translate.google.de/translate?hl=de&sl=ja&tl=en&u=http%3A%2F%2Fresearch.kek.jp%2Fpeople%2Fuchida%2Ftechnologies%2FSiTCP%2F [url2]: https://sitcp.bbtech.co.jp/ - diff --git a/examples/mio3_eth_gpac/mio3_eth_gpac.py b/examples/mio3_eth_gpac/mio3_eth_gpac.py index bad859a2e..bd961b2a3 100644 --- a/examples/mio3_eth_gpac/mio3_eth_gpac.py +++ b/examples/mio3_eth_gpac/mio3_eth_gpac.py @@ -9,10 +9,10 @@ chip = Dut("mio3_eth_gpac.yaml") chip.init() -chip['VDD'].set_current_limit(80, unit='mA') -chip['VDD'].set_voltage(1.3, unit='V') -chip['VDD'].set_enable(True) +chip["VDD"].set_current_limit(80, unit="mA") +chip["VDD"].set_voltage(1.3, unit="V") +chip["VDD"].set_enable(True) -chip['CONTROL']['LED'] = 0xa5 +chip["CONTROL"]["LED"] = 0xA5 -chip['CONTROL'].write() +chip["CONTROL"].write() diff --git a/examples/mio_pixel/firmware/ise/.gitignore b/examples/mio_pixel/firmware/ise/.gitignore index a66111ac2..3b87f548c 100644 --- a/examples/mio_pixel/firmware/ise/.gitignore +++ b/examples/mio_pixel/firmware/ise/.gitignore @@ -2,4 +2,3 @@ !.gitignore !*.xise - diff --git a/examples/mio_pixel/firmware/src/pixel.ucf b/examples/mio_pixel/firmware/src/pixel.ucf index 654393110..4a19773f0 100644 --- a/examples/mio_pixel/firmware/src/pixel.ucf +++ b/examples/mio_pixel/firmware/src/pixel.ucf @@ -56,7 +56,7 @@ TIMESPEC TS_FALSE_BUS_ADC_ENC = FROM "tn_BUS_CLK" TO "tn_SPI_CLK" TIG; NET "FCLK_IN" IOSTANDARD = LVCMOS33; NET "FCLK_IN" LOC = N10; -#NET "LCK1" LOC = "P9" | IOSTANDARD = LVCMOS33; +#NET "LCK1" LOC = "P9" | IOSTANDARD = LVCMOS33; #NET "UCLK_IN" LOC = "P10" | IOSTANDARD = LVCMOS33; # NET "BUSY_CONF" LOC=V10; diff --git a/examples/mio_pixel/pixel.py b/examples/mio_pixel/pixel.py index 49c5f7c71..0a938144e 100644 --- a/examples/mio_pixel/pixel.py +++ b/examples/mio_pixel/pixel.py @@ -32,11 +32,11 @@ def program_global_reg(self): self._clear_strobes() - gr_size = len(self['GLOBAL_REG'][:]) # get the size - self['SEQ']['SHIFT_IN'][0:gr_size] = self['GLOBAL_REG'][:] # this will be shifted out - self['SEQ']['GLOBAL_SHIFT_EN'][0:gr_size] = bitarray(gr_size * '1') # this is to enable clock - self['SEQ']['GLOBAL_CTR_LD'][gr_size + 1:gr_size + 2] = bitarray("1") # load signals - self['SEQ']['GLOBAL_DAC_LD'][gr_size + 1:gr_size + 2] = bitarray("1") + gr_size = len(self["GLOBAL_REG"][:]) # get the size + self["SEQ"]["SHIFT_IN"][0:gr_size] = self["GLOBAL_REG"][:] # this will be shifted out + self["SEQ"]["GLOBAL_SHIFT_EN"][0:gr_size] = bitarray(gr_size * "1") # this is to enable clock + self["SEQ"]["GLOBAL_CTR_LD"][gr_size + 1 : gr_size + 2] = bitarray("1") # load signals + self["SEQ"]["GLOBAL_DAC_LD"][gr_size + 1 : gr_size + 2] = bitarray("1") # Execute the program (write bits to output pins) # + 1 extra 0 bit so that everything ends on LOW instead of HIGH @@ -58,11 +58,11 @@ def program_pixel_reg(self, enable_receiver=True): self._clear_strobes() # enable receiver it work only if pixel register is enabled/clocked - self['PIXEL_RX'].set_en(enable_receiver) + self["PIXEL_RX"].set_en(enable_receiver) - px_size = len(self['PIXEL_REG'][:]) # get the size - self['SEQ']['SHIFT_IN'][0:px_size] = self['PIXEL_REG'][:] # this will be shifted out - self['SEQ']['PIXEL_SHIFT_EN'][0:px_size] = bitarray(px_size * '1') # this is to enable clock + px_size = len(self["PIXEL_REG"][:]) # get the size + self["SEQ"]["SHIFT_IN"][0:px_size] = self["PIXEL_REG"][:] # this will be shifted out + self["SEQ"]["PIXEL_SHIFT_EN"][0:px_size] = bitarray(px_size * "1") # this is to enable clock self._run_seq(px_size + 1) # add 1 bit more so there is 0 at the end other way will stay high @@ -73,13 +73,13 @@ def _run_seq(self, size): """ # Write the sequence to the sequence generator (hw driver) - self['SEQ'].write(size) # write pattern to memory + self["SEQ"].write(size) # write pattern to memory - self['SEQ'].set_size(size) # set size - self['SEQ'].set_repeat(1) # set repeat - self['SEQ'].start() # start + self["SEQ"].set_size(size) # set size + self["SEQ"].set_repeat(1) # set repeat + self["SEQ"].start() # start - while not self['SEQ'].get_done(): + while not self["SEQ"].get_done(): time.sleep(0.01) def _clear_strobes(self): @@ -88,54 +88,53 @@ def _clear_strobes(self): """ # reset some stuff - self['SEQ']['GLOBAL_SHIFT_EN'].setall(False) - self['SEQ']['GLOBAL_CTR_LD'].setall(False) - self['SEQ']['GLOBAL_DAC_LD'].setall(False) - self['SEQ']['PIXEL_SHIFT_EN'].setall(False) - self['SEQ']['INJECTION'].setall(False) + self["SEQ"]["GLOBAL_SHIFT_EN"].setall(False) + self["SEQ"]["GLOBAL_CTR_LD"].setall(False) + self["SEQ"]["GLOBAL_DAC_LD"].setall(False) + self["SEQ"]["PIXEL_SHIFT_EN"].setall(False) + self["SEQ"]["INJECTION"].setall(False) if __name__ == "__main__": - # Create the Pixel object chip = Pixel("pixel.yaml") chip.init() # turn on the adapter card's power - chip['PWR']['EN_VD1'] = 1 - chip['PWR']['EN_VD2'] = 1 - chip['PWR']['EN_VA1'] = 1 - chip['PWR']['EN_VA2'] = 1 - chip['PWR'].write() + chip["PWR"]["EN_VD1"] = 1 + chip["PWR"]["EN_VD2"] = 1 + chip["PWR"]["EN_VA1"] = 1 + chip["PWR"]["EN_VA2"] = 1 + chip["PWR"].write() # Set the output voltage on the pins - chip['PWRAC'].set_voltage("VDDD1", 1.2) - print("VDDD1 = {}V/{}A".format(chip['PWRAC'].get_voltage("VDDD1"), chip['PWRAC'].get_current("VDDD1"))) + chip["PWRAC"].set_voltage("VDDD1", 1.2) + print("VDDD1 = {}V/{}A".format(chip["PWRAC"].get_voltage("VDDD1"), chip["PWRAC"].get_current("VDDD1"))) # settings for global register (to input into global SR) # can be an integer representing the binary number desired, # or a bitarray (of the form bitarray("10101100")). - chip['GLOBAL_REG']['global_readout_enable'] = 0 # size = 1 bit - chip['GLOBAL_REG']['SRDO_load'] = 0 # size = 1 bit - chip['GLOBAL_REG']['NCout2'] = 0 # size = 1 bit - chip['GLOBAL_REG']['count_hits_not'] = 0 # size = 1 - chip['GLOBAL_REG']['count_enable'] = 0 # size = 1 - chip['GLOBAL_REG']['count_clear_not'] = 0 # size = 1 - chip['GLOBAL_REG']['S0'] = 0 # size = 1 - chip['GLOBAL_REG']['S1'] = 0 # size = 1 - chip['GLOBAL_REG']['config_mode'] = 3 # size = 2 - chip['GLOBAL_REG']['LD_IN0_7'] = 0 # size = 8 - chip['GLOBAL_REG']['LDENABLE_SEL'] = 0 # size = 1 - chip['GLOBAL_REG']['SRCLR_SEL'] = 0 # size = 1 - chip['GLOBAL_REG']['HITLD_IN'] = 0 # size = 1 - chip['GLOBAL_REG']['NCout21_25'] = 0 # size = 5 - chip['GLOBAL_REG']['column_address'] = 0 # size = 6 - chip['GLOBAL_REG']['DisVbn'] = 0 # size = 8 - chip['GLOBAL_REG']['VbpThStep'] = 0 # size = 8 - chip['GLOBAL_REG']['PrmpVbp'] = 0 # size = 8 - chip['GLOBAL_REG']['PrmpVbnFol'] = 0 # size = 8 - chip['GLOBAL_REG']['vth'] = 0 # size = 8 - chip['GLOBAL_REG']['PrmpVbf'] = 0 # size = 8 + chip["GLOBAL_REG"]["global_readout_enable"] = 0 # size = 1 bit + chip["GLOBAL_REG"]["SRDO_load"] = 0 # size = 1 bit + chip["GLOBAL_REG"]["NCout2"] = 0 # size = 1 bit + chip["GLOBAL_REG"]["count_hits_not"] = 0 # size = 1 + chip["GLOBAL_REG"]["count_enable"] = 0 # size = 1 + chip["GLOBAL_REG"]["count_clear_not"] = 0 # size = 1 + chip["GLOBAL_REG"]["S0"] = 0 # size = 1 + chip["GLOBAL_REG"]["S1"] = 0 # size = 1 + chip["GLOBAL_REG"]["config_mode"] = 3 # size = 2 + chip["GLOBAL_REG"]["LD_IN0_7"] = 0 # size = 8 + chip["GLOBAL_REG"]["LDENABLE_SEL"] = 0 # size = 1 + chip["GLOBAL_REG"]["SRCLR_SEL"] = 0 # size = 1 + chip["GLOBAL_REG"]["HITLD_IN"] = 0 # size = 1 + chip["GLOBAL_REG"]["NCout21_25"] = 0 # size = 5 + chip["GLOBAL_REG"]["column_address"] = 0 # size = 6 + chip["GLOBAL_REG"]["DisVbn"] = 0 # size = 8 + chip["GLOBAL_REG"]["VbpThStep"] = 0 # size = 8 + chip["GLOBAL_REG"]["PrmpVbp"] = 0 # size = 8 + chip["GLOBAL_REG"]["PrmpVbnFol"] = 0 # size = 8 + chip["GLOBAL_REG"]["vth"] = 0 # size = 8 + chip["GLOBAL_REG"]["PrmpVbf"] = 0 # size = 8 print("program global register...") chip.program_global_reg() @@ -144,22 +143,23 @@ def _clear_strobes(self): # can be an integer representing the binary number desired, # or a bitarray (of the form bitarray("10101100")). - chip['PIXEL_REG'][:] = bitarray('10' * 64) - chip['PIXEL_REG'][0] = 0 + chip["PIXEL_REG"][:] = bitarray("10" * 64) + chip["PIXEL_REG"][0] = 0 print("program pixel register...") chip.program_pixel_reg() # Get output size in bytes - print("chip['DATA'].get_FIFO_SIZE() = {}".format(chip['DATA'].get_FIFO_SIZE())) + print("chip['DATA'].get_FIFO_SIZE() = {}".format(chip["DATA"].get_FIFO_SIZE())) # Get output in bytes print("chip['DATA'].get_data()") - rxd = chip['DATA'].get_data() # get data from sram fifo + rxd = chip["DATA"].get_data() # get data from sram fifo data0 = rxd.astype(np.uint8) # Change type to unsigned int 8 bits and take from rxd only the last 8 bits data1 = np.right_shift(rxd, 8).astype(np.uint8) # Rightshift rxd 8 bits and take again last 8 bits - data = np.reshape(np.vstack((data1, data0)), -1, order='F') # data is now a 1 dimensional array of all bytes read from the FIFO + # data is now a 1 dimensional array of all bytes read from the FIFO + data = np.reshape(np.vstack((data1, data0)), -1, order="F") bdata = np.unpackbits(data) print("data = {}".format(data)) diff --git a/examples/mio_pixel/pixel.yaml b/examples/mio_pixel/pixel.yaml index ec7575627..7cdc89545 100644 --- a/examples/mio_pixel/pixel.yaml +++ b/examples/mio_pixel/pixel.yaml @@ -5,21 +5,21 @@ # ------------------------------------------------------------ # --- -name : ExamplePixelDut +name : ExamplePixelDut version : 0.01 transfer_layer: - name : usb type : SiUsb # or SimSiUsb to run as simulation - init: + init: bit_file : "./firmware/ise/pixel.bit" avoid_download : False - -hw_drivers: + +hw_drivers: - name : DATA type : sram_fifo interface : usb - base_addr : 0x10020 + base_addr : 0x10020 base_data_addr: 0x0001000000000000 - name : SEQ_GEN @@ -37,7 +37,7 @@ hw_drivers: type : fast_spi_rx interface : usb base_addr : 0x10100 - + - name : gpio type : gpio interface : usb @@ -57,15 +57,15 @@ registers: type : StdRegister driver : None size : 144 - fields : - - name : global_readout_enable - size : 1 + fields : + - name : global_readout_enable + size : 1 offset : 143 - - name : SRDO_load - size : 1 + - name : SRDO_load + size : 1 offset : 142 - - name : NCout2 - size : 1 + - name : NCout2 + size : 1 offset : 141 - name : count_hits_not size : 1 @@ -138,11 +138,11 @@ registers: hw_driver : SEQ_GEN seq_width : 8 seq_size : 8192 - tracks : + tracks : - name : SHIFT_IN position : 0 - name : GLOBAL_SHIFT_EN - position : 1 + position : 1 - name : GLOBAL_CTR_LD position : 2 - name : GLOBAL_DAC_LD diff --git a/examples/mio_pixel/tests/tb.v b/examples/mio_pixel/tests/tb.v index 43e30734d..34f9ab3c1 100644 --- a/examples/mio_pixel/tests/tb.v +++ b/examples/mio_pixel/tests/tb.v @@ -97,4 +97,3 @@ module tb ( end endmodule - diff --git a/examples/mio_pixel/tests/test_Sim_mio_pixel.py b/examples/mio_pixel/tests/test_Sim_mio_pixel.py index d099711ef..edb898607 100644 --- a/examples/mio_pixel/tests/test_Sim_mio_pixel.py +++ b/examples/mio_pixel/tests/test_Sim_mio_pixel.py @@ -4,79 +4,85 @@ # ------------------------------------------------------------ # +import os import sys import unittest -import os -import yaml import numpy as np +import yaml from bitarray import bitarray -from basil.utils.sim.utils import cocotb_compile_and_run, cocotb_compile_clean, get_basil_dir +from basil.utils.sim.utils import ( + cocotb_compile_and_run, + cocotb_compile_clean, + get_basil_dir, +) + sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) -import pixel # noqa E402 +import pixel # noqa E402 class TestPixel(unittest.TestCase): def setUp(self): - - fw_path = os.path.join(get_basil_dir(), 'firmware/modules') - cocotb_compile_and_run([ - os.path.join(fw_path, 'gpio/gpio.v'), - os.path.join(fw_path, 'gpio/gpio_core.v'), - os.path.join(fw_path, 'utils/reset_gen.v'), - os.path.join(fw_path, 'utils/bus_to_ip.v'), - os.path.join(fw_path, 'rrp_arbiter/rrp_arbiter.v'), - os.path.join(fw_path, 'utils/ODDR_sim.v'), - os.path.join(fw_path, 'utils/generic_fifo.v'), - os.path.join(fw_path, 'utils/cdc_pulse_sync.v'), - os.path.join(fw_path, 'utils/fx2_to_bus.v'), - os.path.join(fw_path, 'utils/BUFG_sim.v'), - os.path.join(fw_path, 'utils/cdc_syncfifo.v'), - os.path.join(fw_path, 'utils/ddr_des.v'), - os.path.join(fw_path, 'utils/IDDR_sim.v'), - os.path.join(fw_path, 'utils/DCM_sim.v'), - os.path.join(fw_path, 'utils/clock_divider.v'), - os.path.join(fw_path, 'utils/clock_multiplier.v'), - os.path.join(fw_path, 'utils/flag_domain_crossing.v'), - os.path.join(fw_path, 'utils/3_stage_synchronizer.v'), - os.path.join(fw_path, 'fast_spi_rx/fast_spi_rx.v'), - os.path.join(fw_path, 'fast_spi_rx/fast_spi_rx_core.v'), - os.path.join(fw_path, 'seq_gen/seq_gen.v'), - os.path.join(fw_path, 'seq_gen/seq_gen_core.v'), - os.path.join(fw_path, 'utils/ramb_8_to_n.v'), - os.path.join(fw_path, 'tdc_s3/tdc_s3.v'), - os.path.join(fw_path, 'tdc_s3/tdc_s3_core.v'), - os.path.join(fw_path, 'sram_fifo/sram_fifo_core.v'), - os.path.join(fw_path, 'sram_fifo/sram_fifo.v'), - os.path.join(os.path.dirname(__file__), '../firmware/src/clk_gen.v'), - os.path.join(os.path.dirname(__file__), '../firmware/src/pixel.v'), - os.path.join(os.path.dirname(__file__), '../tests/tb.v')], - top_level='tb', - sim_bus='basil.utils.sim.SiLibUsbBusDriver' + fw_path = os.path.join(get_basil_dir(), "firmware/modules") + cocotb_compile_and_run( + [ + os.path.join(fw_path, "gpio/gpio.v"), + os.path.join(fw_path, "gpio/gpio_core.v"), + os.path.join(fw_path, "utils/reset_gen.v"), + os.path.join(fw_path, "utils/bus_to_ip.v"), + os.path.join(fw_path, "rrp_arbiter/rrp_arbiter.v"), + os.path.join(fw_path, "utils/ODDR_sim.v"), + os.path.join(fw_path, "utils/generic_fifo.v"), + os.path.join(fw_path, "utils/cdc_pulse_sync.v"), + os.path.join(fw_path, "utils/fx2_to_bus.v"), + os.path.join(fw_path, "utils/BUFG_sim.v"), + os.path.join(fw_path, "utils/cdc_syncfifo.v"), + os.path.join(fw_path, "utils/ddr_des.v"), + os.path.join(fw_path, "utils/IDDR_sim.v"), + os.path.join(fw_path, "utils/DCM_sim.v"), + os.path.join(fw_path, "utils/clock_divider.v"), + os.path.join(fw_path, "utils/clock_multiplier.v"), + os.path.join(fw_path, "utils/flag_domain_crossing.v"), + os.path.join(fw_path, "utils/3_stage_synchronizer.v"), + os.path.join(fw_path, "fast_spi_rx/fast_spi_rx.v"), + os.path.join(fw_path, "fast_spi_rx/fast_spi_rx_core.v"), + os.path.join(fw_path, "seq_gen/seq_gen.v"), + os.path.join(fw_path, "seq_gen/seq_gen_core.v"), + os.path.join(fw_path, "utils/ramb_8_to_n.v"), + os.path.join(fw_path, "tdc_s3/tdc_s3.v"), + os.path.join(fw_path, "tdc_s3/tdc_s3_core.v"), + os.path.join(fw_path, "sram_fifo/sram_fifo_core.v"), + os.path.join(fw_path, "sram_fifo/sram_fifo.v"), + os.path.join(os.path.dirname(__file__), "../firmware/src/clk_gen.v"), + os.path.join(os.path.dirname(__file__), "../firmware/src/pixel.v"), + os.path.join(os.path.dirname(__file__), "../tests/tb.v"), + ], + top_level="tb", + sim_bus="basil.utils.sim.SiLibUsbBusDriver", ) - with open(os.path.join(os.path.dirname(__file__), '../pixel.yaml'), 'r') as f: + with open(os.path.join(os.path.dirname(__file__), "../pixel.yaml"), "r") as f: cnfg = yaml.safe_load(f) # change to simulation interface - cnfg['transfer_layer'][0]['type'] = 'SiSim' + cnfg["transfer_layer"][0]["type"] = "SiSim" self.chip = pixel.Pixel(cnfg) self.chip.init() def test_simple(self): - input_arr = bitarray('10' * 64) + input_arr = bitarray("10" * 64) - self.chip['PIXEL_REG'][:] = input_arr - self.chip['PIXEL_REG'][0] = 0 + self.chip["PIXEL_REG"][:] = input_arr + self.chip["PIXEL_REG"][0] = 0 self.chip.program_pixel_reg() - ret = self.chip['DATA'].get_data() + ret = self.chip["DATA"].get_data() data0 = ret.astype(np.uint8) data1 = np.right_shift(ret, 8).astype(np.uint8) - data = np.reshape(np.vstack((data1, data0)), -1, order='F') + data = np.reshape(np.vstack((data1, data0)), -1, order="F") bdata = np.unpackbits(data) input_arr[0] = 0 @@ -88,5 +94,5 @@ def tearDown(self): cocotb_compile_clean() -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/examples/mio_sram_test/firmware/ise/.gitignore b/examples/mio_sram_test/firmware/ise/.gitignore index a66111ac2..3b87f548c 100644 --- a/examples/mio_sram_test/firmware/ise/.gitignore +++ b/examples/mio_sram_test/firmware/ise/.gitignore @@ -2,4 +2,3 @@ !.gitignore !*.xise - diff --git a/examples/mio_sram_test/firmware/src/mio.ucf b/examples/mio_sram_test/firmware/src/mio.ucf index be30ce652..bc74e547b 100644 --- a/examples/mio_sram_test/firmware/src/mio.ucf +++ b/examples/mio_sram_test/firmware/src/mio.ucf @@ -1,6 +1,6 @@ # # ------------------------------------------------------------ -# Copyright (c) SILAB , Physics Institute of Bonn University +# Copyright (c) SILAB , Physics Institute of Bonn University # ------------------------------------------------------------ # @@ -33,7 +33,7 @@ TIMESPEC TS_FCLK_IN = PERIOD "TNM_FCLK_IN" 20 ns HIGH 50 %; NET "FCLK_IN" IOSTANDARD = LVCMOS33; NET "FCLK_IN" LOC = N10; -#NET "LCK1" LOC = "P9" | IOSTANDARD = LVCMOS33; +#NET "LCK1" LOC = "P9" | IOSTANDARD = LVCMOS33; #NET "UCLK_IN" LOC = "P10" | IOSTANDARD = LVCMOS33; # NET "BUSY_CONF" LOC=V10; @@ -362,4 +362,3 @@ NET "SRAM_IO[0]" LOC = D17; NET "SDA" LOC = D10; NET "SCL" LOC = D14; - diff --git a/examples/mio_sram_test/sram_test.py b/examples/mio_sram_test/sram_test.py index ec7cd6b46..527864633 100644 --- a/examples/mio_sram_test/sram_test.py +++ b/examples/mio_sram_test/sram_test.py @@ -9,7 +9,6 @@ from basil.dut import Dut - chip = Dut("sram_test.yaml") chip.init() @@ -19,17 +18,16 @@ def test_sram(count=10000): error = 0 for k in range(count): - # chip['CONTROL']['COUNTER_EN'] = 1 # chip['CONTROL'].write() # chip['CONTROL']['COUNTER_EN'] = 0 # chip['CONTROL'].write() - chip['PULSE'].set_DELAY(1) - chip['PULSE'].set_WIDTH((k + 1) % 3000) - chip['PULSE'].START + chip["PULSE"].set_DELAY(1) + chip["PULSE"].set_WIDTH((k + 1) % 3000) + chip["PULSE"].START - ret = chip['FIFO'].get_data() + ret = chip["FIFO"].get_data() x = np.arange(i * 4, (i + ret.shape[0]) * 4, dtype=np.uint8) x.dtype = np.uint32 @@ -49,14 +47,13 @@ def test_direct(count=10000): error = 0 for k in range(count): - - chip['CONTROL']['COUNTER_DIRECT'] = 1 - chip['CONTROL'].write() + chip["CONTROL"]["COUNTER_DIRECT"] = 1 + chip["CONTROL"].write() size = (k + 1) % 5000 - base_data_addr = chip['FIFO']._conf['base_data_addr'] + base_data_addr = chip["FIFO"]._conf["base_data_addr"] - ret = chip['USB'].read(base_data_addr, size=size) + ret = chip["USB"].read(base_data_addr, size=size) x = np.arange(i, i + size, dtype=np.uint8) i += size @@ -69,8 +66,8 @@ def test_direct(count=10000): if not ok: error += 1 - chip['CONTROL']['COUNTER_DIRECT'] = 0 - chip['CONTROL'].write() + chip["CONTROL"]["COUNTER_DIRECT"] = 0 + chip["CONTROL"].write() return error @@ -78,8 +75,8 @@ def test_register(count=10000): error = 0 for i in range(count): data = np.array([(i * 4 + 3) % 255, (i * 4 + 2) % 255, (i * 4 + 1) % 255, (i * 4) % 255]) - chip['GPIO_PATTERN_DRV'].set_data(data) - ret = chip['GPIO_PATTERN_DRV'].get_data() + chip["GPIO_PATTERN_DRV"].set_data(data) + ret = chip["GPIO_PATTERN_DRV"].get_data() ok = np.alltrue(data == ret) @@ -90,6 +87,6 @@ def test_register(count=10000): if __name__ == "__main__": - print('test_register ... errors: {}'.format(test_register())) - print('test_direct ... errors: {}'.format(test_direct())) - print('test_sram ... errors: {}'.format(test_sram())) + print("test_register ... errors: {}".format(test_register())) + print("test_direct ... errors: {}".format(test_direct())) + print("test_sram ... errors: {}".format(test_sram())) diff --git a/examples/mio_sram_test/sram_test.yaml b/examples/mio_sram_test/sram_test.yaml index 9e35b6529..5faa16c0b 100644 --- a/examples/mio_sram_test/sram_test.yaml +++ b/examples/mio_sram_test/sram_test.yaml @@ -11,14 +11,14 @@ transfer_layer: init: #avoid_download : True bit_file : ./firmware/ise/sram_test.bit - + hw_drivers: - name : GPIO_CONTROL_DRV type : gpio interface : USB base_addr : 0x10000 size : 8 - + - name : GPIO_PATTERN_DRV type : gpio interface : USB @@ -30,12 +30,12 @@ hw_drivers: interface : USB base_addr : 0x10020 base_data_addr: 0x0001000000000000 - + - name : PULSE type : pulse_gen interface : USB base_addr : 0x10030 - + registers: - name : CONTROL type : StdRegister @@ -50,7 +50,7 @@ registers: offset : 1 - name : COUNTER_DIRECT size : 1 - offset : 2 + offset : 2 - name : PATTERN type : StdRegister diff --git a/examples/mio_sram_test/tests/test_Sim.py b/examples/mio_sram_test/tests/test_Sim.py index 6f0cc2f5f..4faf303da 100644 --- a/examples/mio_sram_test/tests/test_Sim.py +++ b/examples/mio_sram_test/tests/test_Sim.py @@ -4,88 +4,93 @@ # ------------------------------------------------------------ # -import unittest import os -import yaml +import unittest import numpy as np +import yaml from basil.dut import Dut -from basil.utils.sim.utils import cocotb_compile_and_run, cocotb_compile_clean, get_basil_dir +from basil.utils.sim.utils import ( + cocotb_compile_and_run, + cocotb_compile_clean, + get_basil_dir, +) class TestSram(unittest.TestCase): def setUp(self): - - fw_path = os.path.join(get_basil_dir(), 'firmware/modules') - cocotb_compile_and_run([ - os.path.join(fw_path, 'gpio/gpio.v'), - os.path.join(fw_path, 'gpio/gpio_core.v'), - os.path.join(fw_path, 'utils/reset_gen.v'), - os.path.join(fw_path, 'utils/bus_to_ip.v'), - os.path.join(fw_path, 'rrp_arbiter/rrp_arbiter.v'), - os.path.join(fw_path, 'utils/ODDR_sim.v'), - os.path.join(fw_path, 'utils/generic_fifo.v'), - os.path.join(fw_path, 'utils/cdc_pulse_sync.v'), - os.path.join(fw_path, 'utils/3_stage_synchronizer.v'), - os.path.join(fw_path, 'utils/fx2_to_bus.v'), - os.path.join(fw_path, 'pulse_gen/pulse_gen.v'), - os.path.join(fw_path, 'pulse_gen/pulse_gen_core.v'), - os.path.join(fw_path, 'sram_fifo/sram_fifo_core.v'), - os.path.join(fw_path, 'sram_fifo/sram_fifo.v'), - os.path.join(os.path.dirname(__file__), '../firmware/src/sram_test.v'), - os.path.join(os.path.dirname(__file__), '../tests/tb.v')], - top_level='tb', - sim_bus='basil.utils.sim.SiLibUsbBusDriver' + fw_path = os.path.join(get_basil_dir(), "firmware/modules") + cocotb_compile_and_run( + [ + os.path.join(fw_path, "gpio/gpio.v"), + os.path.join(fw_path, "gpio/gpio_core.v"), + os.path.join(fw_path, "utils/reset_gen.v"), + os.path.join(fw_path, "utils/bus_to_ip.v"), + os.path.join(fw_path, "rrp_arbiter/rrp_arbiter.v"), + os.path.join(fw_path, "utils/ODDR_sim.v"), + os.path.join(fw_path, "utils/generic_fifo.v"), + os.path.join(fw_path, "utils/cdc_pulse_sync.v"), + os.path.join(fw_path, "utils/3_stage_synchronizer.v"), + os.path.join(fw_path, "utils/fx2_to_bus.v"), + os.path.join(fw_path, "pulse_gen/pulse_gen.v"), + os.path.join(fw_path, "pulse_gen/pulse_gen_core.v"), + os.path.join(fw_path, "sram_fifo/sram_fifo_core.v"), + os.path.join(fw_path, "sram_fifo/sram_fifo.v"), + os.path.join(os.path.dirname(__file__), "../firmware/src/sram_test.v"), + os.path.join(os.path.dirname(__file__), "../tests/tb.v"), + ], + top_level="tb", + sim_bus="basil.utils.sim.SiLibUsbBusDriver", ) - with open(os.path.join(os.path.dirname(__file__), '../sram_test.yaml'), 'r') as f: + with open(os.path.join(os.path.dirname(__file__), "../sram_test.yaml"), "r") as f: cnfg = yaml.safe_load(f) # change to simulation interface - cnfg['transfer_layer'][0]['type'] = 'SiSim' + cnfg["transfer_layer"][0]["type"] = "SiSim" self.chip = Dut(cnfg) self.chip.init() def test_simple(self): - self.chip['CONTROL']['COUNTER_EN'] = 1 - self.chip['CONTROL'].write() - self.chip['CONTROL'].write() - self.chip['CONTROL']['COUNTER_EN'] = 0 - self.chip['CONTROL'].write() + self.chip["CONTROL"]["COUNTER_EN"] = 1 + self.chip["CONTROL"].write() + self.chip["CONTROL"].write() + self.chip["CONTROL"]["COUNTER_EN"] = 0 + self.chip["CONTROL"].write() for _ in range(10): - self.chip['CONTROL'].write() + self.chip["CONTROL"].write() - ret = self.chip['FIFO'].get_data() + ret = self.chip["FIFO"].get_data() - self.chip['CONTROL']['COUNTER_EN'] = 1 - self.chip['CONTROL'].write() - self.chip['CONTROL'].write() - self.chip['CONTROL'].write() - self.chip['CONTROL']['COUNTER_EN'] = 0 + self.chip["CONTROL"]["COUNTER_EN"] = 1 + self.chip["CONTROL"].write() + self.chip["CONTROL"].write() + self.chip["CONTROL"].write() + self.chip["CONTROL"]["COUNTER_EN"] = 0 for _ in range(10): - self.chip['CONTROL'].write() + self.chip["CONTROL"].write() - ret = np.hstack((ret, self.chip['FIFO'].get_data())) + ret = np.hstack((ret, self.chip["FIFO"].get_data())) x = np.arange(170 * 4, dtype=np.uint8) x.dtype = np.uint32 np.testing.assert_array_equal(ret, x) - self.chip['FIFO'].reset() + self.chip["FIFO"].reset() - self.chip['CONTROL']['COUNTER_EN'] = 1 - self.chip['CONTROL'].write() - self.chip['CONTROL'].write() + self.chip["CONTROL"]["COUNTER_EN"] = 1 + self.chip["CONTROL"].write() + self.chip["CONTROL"].write() - self.chip['CONTROL']['COUNTER_EN'] = 0 - self.chip['CONTROL'].write() - self.chip['CONTROL'].write() - self.chip['CONTROL'].write() + self.chip["CONTROL"]["COUNTER_EN"] = 0 + self.chip["CONTROL"].write() + self.chip["CONTROL"].write() + self.chip["CONTROL"].write() - ret = np.hstack((ret, self.chip['FIFO'].get_data())) + ret = np.hstack((ret, self.chip["FIFO"].get_data())) x = np.arange(238 * 4, dtype=np.uint8) x.dtype = np.uint32 @@ -93,23 +98,23 @@ def test_simple(self): np.testing.assert_array_equal(ret, x) def test_full(self): - self.chip['CONTROL']['COUNTER_EN'] = 1 - self.chip['CONTROL'].write() + self.chip["CONTROL"]["COUNTER_EN"] = 1 + self.chip["CONTROL"].write() for _ in range(2): - self.chip['FIFO'].get_FIFO_SIZE() + self.chip["FIFO"].get_FIFO_SIZE() - self.chip['CONTROL']['COUNTER_EN'] = 0 - self.chip['CONTROL'].write() + self.chip["CONTROL"]["COUNTER_EN"] = 0 + self.chip["CONTROL"].write() for _ in range(10): - self.chip['CONTROL'].write() + self.chip["CONTROL"].write() - size = self.chip['FIFO'].get_FIFO_SIZE() + size = self.chip["FIFO"].get_FIFO_SIZE() self.assertEqual(size, 512) - ret = self.chip['FIFO'].get_data() - ret = np.hstack((ret, self.chip['FIFO'].get_data())) + ret = self.chip["FIFO"].get_data() + ret = np.hstack((ret, self.chip["FIFO"].get_data())) x = np.arange(200 * 4, dtype=np.uint8) x.dtype = np.uint32 @@ -117,85 +122,84 @@ def test_full(self): np.testing.assert_array_equal(ret, x) def test_overflow(self): - self.chip['CONTROL']['COUNTER_EN'] = 1 - self.chip['CONTROL'].write() + self.chip["CONTROL"]["COUNTER_EN"] = 1 + self.chip["CONTROL"].write() for _ in range(20): - self.chip['FIFO'].get_FIFO_SIZE() + self.chip["FIFO"].get_FIFO_SIZE() - self.chip['CONTROL']['COUNTER_EN'] = 0 - self.chip['CONTROL'].write() + self.chip["CONTROL"]["COUNTER_EN"] = 0 + self.chip["CONTROL"].write() for _ in range(10): - self.chip['CONTROL'].write() + self.chip["CONTROL"].write() - ret = self.chip['FIFO'].get_data() - while self.chip['FIFO'].get_FIFO_SIZE(): - ret = np.hstack((ret, self.chip['FIFO'].get_data())) + ret = self.chip["FIFO"].get_data() + while self.chip["FIFO"].get_FIFO_SIZE(): + ret = np.hstack((ret, self.chip["FIFO"].get_data())) x = np.arange((128 + 1023) * 4, dtype=np.uint8) x.dtype = np.uint32 np.testing.assert_array_equal(ret, x) - self.chip['PULSE'].set_DELAY(1) - self.chip['PULSE'].set_WIDTH(1) - self.chip['PULSE'].start() + self.chip["PULSE"].set_DELAY(1) + self.chip["PULSE"].set_WIDTH(1) + self.chip["PULSE"].start() - ret = self.chip['FIFO'].get_data() + ret = self.chip["FIFO"].get_data() x = np.arange((128 + 1023) * 4, (128 + 1023 + 1) * 4).astype(np.uint8) x.dtype = np.uint32 np.testing.assert_array_equal(ret, x) def test_single(self): + self.chip["PULSE"].set_DELAY(1) + self.chip["PULSE"].set_WIDTH(1) + self.chip["PULSE"].start() - self.chip['PULSE'].set_DELAY(1) - self.chip['PULSE'].set_WIDTH(1) - self.chip['PULSE'].start() - - self.assertEqual(self.chip['FIFO'].get_data().tolist(), [0x03020100]) + self.assertEqual(self.chip["FIFO"].get_data().tolist(), [0x03020100]) - self.chip['PULSE'].start() + self.chip["PULSE"].start() - self.assertEqual(self.chip['FIFO'].get_data().tolist(), [0x07060504]) + self.assertEqual(self.chip["FIFO"].get_data().tolist(), [0x07060504]) def test_pattern(self): - self.chip['PATTERN'] = 0xaa5555aa - self.chip['PATTERN'].write() + self.chip["PATTERN"] = 0xAA5555AA + self.chip["PATTERN"].write() - self.chip['CONTROL']['PATTERN_EN'] = 1 - self.chip['CONTROL'].write() - self.chip['CONTROL']['PATTERN_EN'] = 0 - self.chip['CONTROL'].write() + self.chip["CONTROL"]["PATTERN_EN"] = 1 + self.chip["CONTROL"].write() + self.chip["CONTROL"]["PATTERN_EN"] = 0 + self.chip["CONTROL"].write() for _ in range(5): - self.chip['CONTROL'].write() + self.chip["CONTROL"].write() - self.assertEqual(self.chip['FIFO'].get_data().tolist(), [0xaa5555aa] * 34) + self.assertEqual(self.chip["FIFO"].get_data().tolist(), [0xAA5555AA] * 34) def test_direct(self): - self.chip['CONTROL']['COUNTER_DIRECT'] = 1 - self.chip['CONTROL'].write() + self.chip["CONTROL"]["COUNTER_DIRECT"] = 1 + self.chip["CONTROL"].write() size = 648 - base_data_addr = self.chip['FIFO']._conf['base_data_addr'] + base_data_addr = self.chip["FIFO"]._conf["base_data_addr"] - ret = self.chip['USB'].read(base_data_addr, size=size) - ret = np.hstack((ret, self.chip['USB'].read(base_data_addr, size=size))) + ret = self.chip["USB"].read(base_data_addr, size=size) + ret = np.hstack((ret, self.chip["USB"].read(base_data_addr, size=size))) x = np.arange(size * 2, dtype=np.uint8) self.assertEqual(ret.tolist(), x.tolist()) def test_continouse(self): - self.chip['PULSE'].set_DELAY(35) - self.chip['PULSE'].set_WIDTH(3) - self.chip['PULSE'].set_repeat(0) - self.chip['PULSE'].start() + self.chip["PULSE"].set_DELAY(35) + self.chip["PULSE"].set_WIDTH(3) + self.chip["PULSE"].set_repeat(0) + self.chip["PULSE"].start() i = 0 error = False for _ in range(100): - ret = self.chip['FIFO'].get_data() + ret = self.chip["FIFO"].get_data() x = np.arange(i * 4, (i + ret.shape[0]) * 4).astype(np.uint8) x.dtype = np.uint32 @@ -215,5 +219,5 @@ def tearDown(self): cocotb_compile_clean() -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/examples/mmc3_eth/firmware/src/mmc3.xdc b/examples/mmc3_eth/firmware/src/mmc3.xdc index 863de0bf5..433413dcd 100644 --- a/examples/mmc3_eth/firmware/src/mmc3.xdc +++ b/examples/mmc3_eth/firmware/src/mmc3.xdc @@ -73,4 +73,3 @@ set_property PACKAGE_PIN L25 [get_ports {LED[6]}] set_property PACKAGE_PIN P23 [get_ports {LED[7]}] set_property IOSTANDARD LVCMOS33 [get_ports LED*] set_property SLEW SLOW [get_ports LED*] - diff --git a/examples/mmc3_eth/mmc3_eth.py b/examples/mmc3_eth/mmc3_eth.py index 86c781684..32ed82345 100644 --- a/examples/mmc3_eth/mmc3_eth.py +++ b/examples/mmc3_eth/mmc3_eth.py @@ -13,33 +13,31 @@ from basil.dut import Dut - chip = Dut("mmc3_eth.yaml") chip.init() -chip['CONTROL']['EN'] = 0 -chip['CONTROL'].write() +chip["CONTROL"]["EN"] = 0 +chip["CONTROL"].write() logging.info("Starting data test ...") -chip['CONTROL']['EN'] = 1 -chip['CONTROL'].write() +chip["CONTROL"]["EN"] = 1 +chip["CONTROL"].write() start = 0 for i in range(10): - time.sleep(1) - fifo_data = chip['FIFO'].get_data() + fifo_data = chip["FIFO"].get_data() data_size = len(fifo_data) data_gen = np.linspace(start, data_size - 1 + start, data_size, dtype=np.int32) - comp = (fifo_data == data_gen) + comp = fifo_data == data_gen logging.info(str((i, " OK?:", comp.all(), float(32 * data_size) / pow(10, 6), "Mbit"))) start += data_size -chip['CONTROL']['EN'] = 0 # stop data source -chip['CONTROL'].write() +chip["CONTROL"]["EN"] = 0 # stop data source +chip["CONTROL"].write() logging.info("Starting speed test ...") @@ -49,11 +47,11 @@ tick_old = 0 start_time = time.time() -chip['CONTROL']['EN'] = 1 -chip['CONTROL'].write() +chip["CONTROL"]["EN"] = 1 +chip["CONTROL"].write() while time.time() - start_time < testduration: - data = chip['FIFO'].get_data() + data = chip["FIFO"].get_data() total_len += len(data) * 4 * 8 time.sleep(0.01) tick = int(time.time() - start_time) @@ -61,7 +59,9 @@ logging.info("Time: %f s" % (time.time() - start_time)) tick_old = tick -chip['CONTROL']['EN'] = 0x0 # stop data source -chip['CONTROL'].write() +chip["CONTROL"]["EN"] = 0x0 # stop data source +chip["CONTROL"].write() -logging.info(str(('Bytes received:', total_len, ' data rate:', round((total_len / 1e6 / testduration), 2), ' Mbits/s'))) +logging.info( + str(("Bytes received:", total_len, " data rate:", round((total_len / 1e6 / testduration), 2), " Mbits/s")) +) diff --git a/examples/mmc3_eth/test/test_mmc3_eth.py b/examples/mmc3_eth/test/test_mmc3_eth.py index 96a80fa85..bc455d3f9 100644 --- a/examples/mmc3_eth/test/test_mmc3_eth.py +++ b/examples/mmc3_eth/test/test_mmc3_eth.py @@ -15,7 +15,6 @@ from basil.dut import Dut from basil.utils.sim.utils import cocotb_compile_and_run, cocotb_compile_clean - doprint = True IntsToReceive = 1000 @@ -59,12 +58,10 @@ def setUp(self): proj_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) cocotb_compile_and_run( - sim_files=[proj_dir + '/test/mmc3_eth_tb.v'], - top_level='tb', - include_dirs=(proj_dir, proj_dir + '/src') + sim_files=[proj_dir + "/test/mmc3_eth_tb.v"], top_level="tb", include_dirs=(proj_dir, proj_dir + "/src") ) - ''' + """ with open("test_mmc3_eth.yaml") as conf_file: try: conf = yaml.safe_load(conf_file) @@ -75,7 +72,7 @@ def setUp(self): self.chip = Dut(conf) self.chip.init() - ''' + """ self.chip = Dut(cnfg_yaml) self.chip.init() @@ -87,11 +84,11 @@ def test(self): tick_old = 0 start_time = time.time() - self.chip['GPIO_LED']['LED'] = 0x01 # start data source - self.chip['GPIO_LED'].write() + self.chip["GPIO_LED"]["LED"] = 0x01 # start data source + self.chip["GPIO_LED"].write() while time.time() - start_time < testduration: - data = self.chip['FIFO'].get_data() + data = self.chip["FIFO"].get_data() total_len += len(data) time.sleep(0.01) tick = int(time.time() - start_time) @@ -110,15 +107,19 @@ def test(self): break total_len_bits = total_len * 32 # 32-bit ints to bits - print('Bits received: {}; Data rate: {}Mbit/s'.format(total_len_bits, round((total_len_bits / 1e6 / testduration), 2))) + print( + "Bits received: {}; Data rate: {}Mbit/s".format( + total_len_bits, round((total_len_bits / 1e6 / testduration), 2) + ) + ) - self.chip['GPIO_LED']['LED'] = 0x00 # stop data source - self.chip['GPIO_LED'].write() + self.chip["GPIO_LED"]["LED"] = 0x00 # stop data source + self.chip["GPIO_LED"].write() def tearDown(self): self.chip.close() # let it close connection and stop simulator cocotb_compile_clean() -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/examples/register_example/simple_register_example.py b/examples/register_example/simple_register_example.py index b8080f957..74c929d10 100644 --- a/examples/register_example/simple_register_example.py +++ b/examples/register_example/simple_register_example.py @@ -9,23 +9,23 @@ chip = Dut("simple_register_example.yaml") -print(chip['TEST']) -print(chip['REG']) +print(chip["TEST"]) +print(chip["REG"]) # chip['REG'][0] = 1 -chip['REG']['VPULSE'][5] = 1 +chip["REG"]["VPULSE"][5] = 1 # chip['REG']['VPULSE'] = 1 # chip['REG']['COLUMN'][0] = 1 # does not work yet # chip['REG'][0] = 1 # does not work yet -chip['REG']['COLUMN'][0]['EnR'] = 1 -chip['REG']['COLUMN'][0]['DACR'] = 3 +chip["REG"]["COLUMN"][0]["EnR"] = 1 +chip["REG"]["COLUMN"][0]["DACR"] = 3 -chip['REG']['VINJECT'] = 3 -print(chip['REG']) +chip["REG"]["VINJECT"] = 3 +print(chip["REG"]) -chip['REG']['VINJECT'][0] = 1 -print(chip['REG']) +chip["REG"]["VINJECT"][0] = 1 +print(chip["REG"]) -print('VINJECT {}'.format(str(chip['REG']['VINJECT']))) +print("VINJECT {}".format(str(chip["REG"]["VINJECT"]))) diff --git a/examples/register_example/simple_register_example.yaml b/examples/register_example/simple_register_example.yaml index 318857c80..a6e64bad0 100644 --- a/examples/register_example/simple_register_example.yaml +++ b/examples/register_example/simple_register_example.yaml @@ -1,40 +1,40 @@ # # ------------------------------------------------------------ -# Copyright (c) SILAB , Physics Institute of Bonn University +# Copyright (c) SILAB , Physics Institute of Bonn University # ------------------------------------------------------------ # # SVN revision information: # $Rev:: 36 $: -# $Author:: themperek $: +# $Author:: themperek $: # $Date:: 2013-09-12 12:16:59 #$: # --- -name : SimpleExample +name : SimpleExample version : 0.01 transfer_layer: - name : usb type : Dummy board_id : -1 - + hw_drivers: - name : spi_module type : spi interface : usb base_addr : 0x10000 mem_bytes : 2 - -registers: + +registers: - name : TEST type : StdRegister hw_driver : spi_module size : 3 - + - name : REG type : StdRegister hw_driver : spi_module size : 20 - fields : + fields : - name : VINJECT size : 6 offset : 19 @@ -49,7 +49,7 @@ registers: offset : 5 size : 3 repeat : 2 - fields : + fields : - name : EnR size : 1 offset : 2 diff --git a/examples/tdc_bdaq/firmware/src/SiTCP.xdc b/examples/tdc_bdaq/firmware/src/SiTCP.xdc index 6c5df838b..d712787c8 100644 --- a/examples/tdc_bdaq/firmware/src/SiTCP.xdc +++ b/examples/tdc_bdaq/firmware/src/SiTCP.xdc @@ -24,9 +24,3 @@ set_max_delay -datapath_only -from [get_pins -hier -filter {name =~ */GMII_RXCNT set_max_delay -datapath_only -from [get_pins -hier -filter {name =~ */GMII_RXCNT/orMacPause/C}] -to [get_pins -hier -filter {name =~ */GMII_TXCNT/irMacPauseExe_0/D}] 5.500 set_false_path -from [get_pins -hier -filter {name =~ */SiTCP_INT/SiTCP_RESET_OUT/C}] - - - - - - diff --git a/examples/tdc_bdaq/firmware/src/tdc_bdaq.v b/examples/tdc_bdaq/firmware/src/tdc_bdaq.v index 97f1906fb..4fa6e5dbc 100644 --- a/examples/tdc_bdaq/firmware/src/tdc_bdaq.v +++ b/examples/tdc_bdaq/firmware/src/tdc_bdaq.v @@ -69,7 +69,7 @@ wire CLK_156M250; IBUFDS_GTE2 IBUFDS_GTE2_inst_156 ( .O(CLK_156M250_in), // Buffer output .ODIV2(), - .CEB(1'b0), + .CEB(1'b0), .I(Si511_P), // Diff_p buffer input (connect directly to top-level port) .IB(Si511_N) // Diff_n buffer input (connect directly to top-level port) ); @@ -84,7 +84,7 @@ wire CLK_160; IBUFDS_GTE2 IBUFDS_GTE2_inst_160 ( .O(CLK_160_in), // Buffer output .ODIV2(), - .CEB(1'b0), + .CEB(1'b0), .I(Si570_P), // Diff_p buffer input (connect directly to top-level port) .IB(Si570_N) // Diff_n buffer input (connect directly to top-level port) ); @@ -150,27 +150,27 @@ PLLE2_BASE_BUS ( // .CLKFBOUT_MULT(16), // Multiply value for all CLKOUT, (2-64) // .CLKFBOUT_PHASE(0.0), // Phase offset in degrees of CLKFB, (-360.000-360.000). // .CLKIN1_PERIOD(10.000), // Input clock period in ns to ps resolution (i.e. 33.333 is 30 MHz). -// +// // .CLKOUT0_DIVIDE(10), // Divide amount for CLKOUT0 (1-128) // .CLKOUT0_DUTY_CYCLE(0.5), // Duty cycle for CLKOUT0 (0.001-0.999). // .CLKOUT0_PHASE(90.0), // Phase offset for CLKOUT0 (-360.000-360.000). -// +// // .CLKOUT1_DIVIDE(10), // Divide amount for CLKOUT0 (1-128) // .CLKOUT1_DUTY_CYCLE(0.5), // Duty cycle for CLKOUT0 (0.001-0.999). // .CLKOUT1_PHASE(0.0), // Phase offset for CLKOUT0 (-360.000-360.000). -// +// // .CLKOUT2_DIVIDE(40), // Divide amount for CLKOUT0 (1-128) // .CLKOUT2_DUTY_CYCLE(0.5), // Duty cycle for CLKOUT0 (0.001-0.999). // .CLKOUT2_PHASE(0.0), // Phase offset for CLKOUT0 (-360.000-360.000). -// +// // .CLKOUT3_DIVIDE(8), // Divide amount for CLKOUT0 (1-128) // .CLKOUT3_DUTY_CYCLE(0.5), // Duty cycle for CLKOUT0 (0.001-0.999). // .CLKOUT3_PHASE(90.0), // Phase offset for CLKOUT0 (-360.000-360.000). -// +// // .CLKOUT4_DIVIDE(8), // Divide amount for CLKOUT0 (1-128) // .CLKOUT4_DUTY_CYCLE(0.5), // Duty cycle for CLKOUT0 (0.001-0.999). // .CLKOUT4_PHASE(-5.625), // Phase offset for CLKOUT0 (-360.000-360.000). -// +// // .DIVCLK_DIVIDE(1), // Master division value, (1-56) // .REF_JITTER1(0.0), // Reference input jitter in UI, (0.000-0.999). // .STARTUP_WAIT("FALSE") // Delay DONE until PLL Locks, ("TRUE"/"FALSE") @@ -574,9 +574,9 @@ always @(posedge BUS_CLK) begin ETH_START_SENDING_temp <= ETH_START_SENDING; // RX FIFO word counter - if (TCP_RX_WR) + if (TCP_RX_WR) TCP_RX_WC_11B <= TCP_RX_WC_11B + 1; - else + else TCP_RX_WC_11B <= 11'd0; @@ -587,7 +587,7 @@ always @(posedge BUS_CLK) begin FIFO_NEXT <= 1'b0; // stop, if connection is closed by host - if (TCP_CLOSE_REQ || !EN) + if (TCP_CLOSE_REQ || !EN) ETH_START_SENDING_LOCK <= 0; end diff --git a/examples/tdc_bdaq/firmware/src/tdc_bdaq.xdc b/examples/tdc_bdaq/firmware/src/tdc_bdaq.xdc index 5371ff165..e6be952d4 100644 --- a/examples/tdc_bdaq/firmware/src/tdc_bdaq.xdc +++ b/examples/tdc_bdaq/firmware/src/tdc_bdaq.xdc @@ -18,5 +18,3 @@ set_property MARK_DEBUG true [get_nets {i_tdc/i_tdc_core/tdc_state_delayed[2]}] set_property MARK_DEBUG true [get_nets {i_tdc/i_tdc_core/tdc_state_delayed[3]}] set_property MARK_DEBUG true [get_nets {i_tdc/i_tdc_core/fine_time_delayed[0]}] set_property MARK_DEBUG true [get_nets {i_tdc/i_tdc_core/fine_time_delayed[1]}] - - diff --git a/examples/tdc_bdaq/tdc_bdaq.py b/examples/tdc_bdaq/tdc_bdaq.py index 6d183f99f..11c13b485 100644 --- a/examples/tdc_bdaq/tdc_bdaq.py +++ b/examples/tdc_bdaq/tdc_bdaq.py @@ -8,106 +8,116 @@ # import logging import time -from tqdm import tqdm +import matplotlib.pyplot as plt import numpy as np from scipy import stats -import matplotlib.pyplot as plt +from tqdm import tqdm from basil.dut import Dut from basil.HL import si570 def disassemble_tdc_word(word): - word_type_codes = {0: 'TRIGGERED', - 1: 'RISING', - 2: 'FALLING', - 3: 'TIMESTAMP', - 4: 'OVFLOW', - 5: 'CALIB', - 6: 'MISS', - 7: 'RST'} + word_type_codes = { + 0: "TRIGGERED", + 1: "RISING", + 2: "FALLING", + 3: "TIMESTAMP", + 4: "OVFLOW", + 5: "CALIB", + 6: "MISS", + 7: "RST", + } # Shift away the 32 - 7 data bits and grab 3 bit word type - return {'source_id': (word >> (32 - 4)), - 'word_type': word_type_codes[(word >> (32 - 7)) & 0b111], - 'tdl_value': word & 0b1111111, - 'fine_value': (word >> 7) & 0b11, - 'corse_value': (word >> 9) & 0xFFFF} + return { + "source_id": (word >> (32 - 4)), + "word_type": word_type_codes[(word >> (32 - 7)) & 0b111], + "tdl_value": word & 0b1111111, + "fine_value": (word >> 7) & 0b11, + "corse_value": (word >> 9) & 0xFFFF, + } chip = Dut("tdc_bdaq.yaml") chip.init() -si570_conf = {'name': 'si570', 'type': 'bdaq53.si570', 'interface': 'intf', 'base_addr': 0xba, 'init': {'frequency': 160}} -si570_clk = si570.si570(chip['i2c'], si570_conf) +si570_conf = { + "name": "si570", + "type": "bdaq53.si570", + "interface": "intf", + "base_addr": 0xBA, + "init": {"frequency": 160}, +} +si570_clk = si570.si570(chip["i2c"], si570_conf) time.sleep(0.1) si570_clk.init() time.sleep(0.1) -chip['TDL_TDC'].reset() +chip["TDL_TDC"].reset() -chip['CONTROL']['EN'] = 0 -chip['CONTROL'].write() +chip["CONTROL"]["EN"] = 0 +chip["CONTROL"].write() logging.info("Starting TDC...") -chip['CONTROL']['EN'] = 1 -chip['CONTROL'].write() +chip["CONTROL"]["EN"] = 1 +chip["CONTROL"].write() -chip['TDL_TDC'].RESET = 1 +chip["TDL_TDC"].RESET = 1 -chip['TDL_TDC'].EN_TRIGGER_DIST = 0 -chip['TDL_TDC'].ENABLE = 1 -chip['TDL_TDC'].RESET = 0 -chip['TDL_TDC'].EN_TRIGGER_DIST = 1 +chip["TDL_TDC"].EN_TRIGGER_DIST = 0 +chip["TDL_TDC"].ENABLE = 1 +chip["TDL_TDC"].RESET = 0 +chip["TDL_TDC"].EN_TRIGGER_DIST = 1 collected_data = np.empty(0, dtype=np.uint32) calib_duration = 3 start_time = time.time() -chip['TDL_TDC'].EN_CALIBRATION_MODE = 1 +chip["TDL_TDC"].EN_CALIBRATION_MODE = 1 while time.time() - start_time < calib_duration: - time.sleep(.01) + time.sleep(0.01) - fifo_data = chip['FIFO'].get_data() + fifo_data = chip["FIFO"].get_data() data_size = len(fifo_data) collected_data = np.concatenate((collected_data, fifo_data), dtype=np.uint32) -chip['TDL_TDC'].EN_CALIBRATION_MODE = 0 +chip["TDL_TDC"].EN_CALIBRATION_MODE = 0 -chip['TDL_TDC'].RESET = 1 -chip['FIFO'].get_data() +chip["TDL_TDC"].RESET = 1 +chip["FIFO"].get_data() -chip['CONTROL']['EN'] = 0 # stop data source -chip['CONTROL'].write() +chip["CONTROL"]["EN"] = 0 # stop data source +chip["CONTROL"].write() -calib_data_indices = chip['TDL_TDC'].is_calib_word(collected_data) +calib_data_indices = chip["TDL_TDC"].is_calib_word(collected_data) print(calib_data_indices) if any(calib_data_indices): - calib_values = chip['TDL_TDC'].get_raw_tdl_values(np.array(collected_data[calib_data_indices])) + calib_values = chip["TDL_TDC"].get_raw_tdl_values(np.array(collected_data[calib_data_indices])) print(calib_values[-20:]) - chip['TDL_TDC'].set_calib_values(calib_values) + chip["TDL_TDC"].set_calib_values(calib_values) # chip['TDL_TDC'].plot_calib_values(calib_values) logging.info("Calibration set using %s samples" % len(calib_values)) collected_rising = [] collected_falling = [] -chip['CONTROL']['EN'] = 1 # start data source -chip['CONTROL'].write() -chip['FIFO'].get_data() +chip["CONTROL"]["EN"] = 1 # start data source +chip["CONTROL"].write() +chip["FIFO"].get_data() -chip['TDL_TDC'].RESET = 1 +chip["TDL_TDC"].RESET = 1 time.sleep(0.1) -chip['FIFO'].get_data() +chip["FIFO"].get_data() logging.info("Ready for measurements") -chip['TDL_TDC'].EN_TRIGGER_DIST = 1 -chip['TDL_TDC'].EN_WRITE_TIMESTAMP = 0 +chip["TDL_TDC"].EN_TRIGGER_DIST = 1 +chip["TDL_TDC"].EN_WRITE_TIMESTAMP = 0 delta_t = 0 @@ -128,24 +138,24 @@ def load_and_start_trig_seq(trig_dis_cycles): trig_total = remain_trig_cycles + need_kilo_cycles * 1000 - chip['SEQ'].reset() - while not chip['SEQ'].is_ready: + chip["SEQ"].reset() + while not chip["SEQ"].is_ready: pass - chip['SEQ'].SIZE = sig_cycles + trig_total + 1 - chip['SEQ']['TDC_IN'][:] = False - chip['SEQ']['TDC_IN'][trig_total:sig_cycles + trig_total] = True - chip['SEQ']['TDC_TRIGGER_IN'][0:20] = True - chip['SEQ'].write(sig_cycles + trig_total + 1) + chip["SEQ"].SIZE = sig_cycles + trig_total + 1 + chip["SEQ"]["TDC_IN"][:] = False + chip["SEQ"]["TDC_IN"][trig_total : sig_cycles + trig_total] = True + chip["SEQ"]["TDC_TRIGGER_IN"][0:20] = True + chip["SEQ"].write(sig_cycles + trig_total + 1) - chip['SEQ'].REPEAT = 1 + chip["SEQ"].REPEAT = 1 # This repeat window isn't optimal as the trigger signal is repeated. # However, once first registered, the repeated trigger signal will # be ignored by the TDC implementation. - chip['SEQ'].NESTED_START = 0 - chip['SEQ'].NESTED_STOP = 1000 - chip['SEQ'].NESTED_REPEAT = kilo_trig_cycles + chip["SEQ"].NESTED_START = 0 + chip["SEQ"].NESTED_STOP = 1000 + chip["SEQ"].NESTED_REPEAT = kilo_trig_cycles - chip['SEQ'].START + chip["SEQ"].START seq_clk_GHZ = 0.15625 @@ -156,23 +166,25 @@ def load_and_start_trig_seq(trig_dis_cycles): actual = [] for i in tqdm(range(10, 4000, 100)): for j in range(N_measure): - load_and_start_trig_seq(i) - while not chip['SEQ'].is_ready: + while not chip["SEQ"].is_ready: time.sleep(0.0001) pass - fifo_size = chip['FIFO']._intf._get_tcp_data_size() + fifo_size = chip["FIFO"]._intf._get_tcp_data_size() fifo_int_size = int((fifo_size - (fifo_size % 4)) / 4) while fifo_int_size < 2: time.sleep(0.0001) - fifo_size = chip['FIFO']._intf._get_tcp_data_size() + fifo_size = chip["FIFO"]._intf._get_tcp_data_size() fifo_int_size = int((fifo_size - (fifo_size % 4)) / 4) - fifo_data = chip['FIFO'].get_data() - times = chip['TDL_TDC'].tdc_word_to_time(fifo_data) + fifo_data = chip["FIFO"].get_data() + times = chip["TDL_TDC"].tdc_word_to_time(fifo_data) current_measurements[j] = times[1] - times[0] actual.append(i / seq_clk_GHZ) std = np.std(current_measurements) - print('Actual time: %5.3f Measured time: %5.3f Difference: %.3f Std %.3f' % (i / seq_clk_GHZ, times[1] - times[0], times[1] - times[0] - i / seq_clk_GHZ, std)) + print( + "Actual time: %5.3f Measured time: %5.3f Difference: %.3f Std %.3f" + % (i / seq_clk_GHZ, times[1] - times[0], times[1] - times[0] - i / seq_clk_GHZ, std) + ) measured.append(np.mean(current_measurements)) stds.append(std) print() @@ -181,10 +193,10 @@ def load_and_start_trig_seq(trig_dis_cycles): stds = np.asarray(stds) res = stats.linregress(actual, measured - actual) print(f"R-squared: {res.rvalue**2:.6f}") -print('Intercept: %f' % (res.intercept)) -print('Slope: %.6e' % (res.slope)) +print("Intercept: %f" % (res.intercept)) +print("Slope: %.6e" % (res.slope)) plt.errorbar(actual, measured - actual, yerr=stds) -plt.plot(actual, res.intercept + res.slope * actual, 'r') +plt.plot(actual, res.intercept + res.slope * actual, "r") plt.show() plt.plot(actual, stds) diff --git a/examples/tdc_bdaq/tdc_bdaq.yaml b/examples/tdc_bdaq/tdc_bdaq.yaml index f6e80053f..6e29a2aa5 100644 --- a/examples/tdc_bdaq/tdc_bdaq.yaml +++ b/examples/tdc_bdaq/tdc_bdaq.yaml @@ -47,7 +47,7 @@ registers: type : TrackRegister hw_driver : SEQ_GEN seq_width : 8 - seq_size : 65535 + seq_size : 65535 tracks: - name : TDC_TRIGGER_IN position : 0 diff --git a/examples/test_eth/test_eth.py b/examples/test_eth/test_eth.py index c66b77457..266881871 100644 --- a/examples/test_eth/test_eth.py +++ b/examples/test_eth/test_eth.py @@ -1,18 +1,19 @@ +import datetime import logging import signal +import struct import time -import datetime -# import random -from threading import Thread, Event # , Lock, Condition from array import array -import struct + +# import random +from threading import Event, Thread # , Lock, Condition import numpy as np from basil.dut import Dut from basil.HL.RegisterHardwareLayer import RegisterHardwareLayer -conf = ''' +conf = """ name : test_eth version : 1.0 @@ -36,26 +37,27 @@ interface : ETH base_addr : 0x0 -''' +""" stop_thread = False class test_eth(RegisterHardwareLayer): - '''Register Hardware Layer. + """Register Hardware Layer. Implementation of advanced register operations. - ''' + """ + _registers = { - 'RESET': {'descr': {'addr': 0, 'size': 8, 'properties': ['writeonly']}}, - 'VERSION': {'descr': {'addr': 0, 'size': 8, 'properties': ['readonly']}}, - 'SETUP': {'default': 0, 'descr': {'addr': 1, 'size': 8, 'offset': 0}}, - 'TEST_DATA': {'descr': {'addr': 2, 'size': 64, 'offset': 0}}, - 'BUS_WRITE_CNT': {'descr': {'addr': 10, 'size': 32, 'offset': 0}}, - 'TCP_WRITE_DLY': {'default': 0, 'descr': {'addr': 14, 'size': 16, 'offset': 0}}, - 'TCP_WRITE_CNT': {'descr': {'addr': 16, 'size': 64, 'offset': 0, 'properties': ['readonly']}}, - 'TCP_FAILED_WRITE_CNT': {'descr': {'addr': 24, 'size': 64, 'offset': 0, 'properties': ['readonly']}}, - 'TCP_RECV_WRITE_CNT': {'descr': {'addr': 32, 'size': 64, 'offset': 0, 'properties': ['readonly']}} + "RESET": {"descr": {"addr": 0, "size": 8, "properties": ["writeonly"]}}, + "VERSION": {"descr": {"addr": 0, "size": 8, "properties": ["readonly"]}}, + "SETUP": {"default": 0, "descr": {"addr": 1, "size": 8, "offset": 0}}, + "TEST_DATA": {"descr": {"addr": 2, "size": 64, "offset": 0}}, + "BUS_WRITE_CNT": {"descr": {"addr": 10, "size": 32, "offset": 0}}, + "TCP_WRITE_DLY": {"default": 0, "descr": {"addr": 14, "size": 16, "offset": 0}}, + "TCP_WRITE_CNT": {"descr": {"addr": 16, "size": 64, "offset": 0, "properties": ["readonly"]}}, + "TCP_FAILED_WRITE_CNT": {"descr": {"addr": 24, "size": 64, "offset": 0, "properties": ["readonly"]}}, + "TCP_RECV_WRITE_CNT": {"descr": {"addr": 32, "size": 64, "offset": 0, "properties": ["readonly"]}}, } @@ -64,17 +66,17 @@ def __init__(self): self.dut = Dut(conf) self.dut.init() # fw_version = dut['ETH'].read(0x0000, 1)[0] - logging.info("Firmware version: %s" % self.dut['REGISTERS'].VERSION) + logging.info("Firmware version: %s" % self.dut["REGISTERS"].VERSION) signal.signal(signal.SIGINT, self.signal_handler) - logging.info('Press Ctrl-C to stop') + logging.info("Press Ctrl-C to stop") self.stop_thread = Event() self.total_tcp_err_cnt = 0 def signal_handler(self, signum, frame): - logging.info('Pressed Ctrl-C...') - self.dut['REGISTERS'].TCP_WRITE_DLY = 0 # no TCP data + logging.info("Pressed Ctrl-C...") + self.dut["REGISTERS"].TCP_WRITE_DLY = 0 # no TCP data self.time_stop = time.time() self.stop_thread.set() signal.signal(signal.SIGINT, signal.SIG_DFL) # setting default handler @@ -85,13 +87,13 @@ def start(self, test_tcp=True, test_bus=True, tcp_write_delay=6, monitor_interva self.test_tcp = test_tcp self.test_bus = test_bus # reset registers - self.dut['REGISTERS'].RESET + self.dut["REGISTERS"].RESET # setup register values # Monitor self.monitor_delay = monitor_interval # Speed of displaying netowrk speed # TCP self.tcp_readout_delay = 0.1 # Delay between reading TCP buffer - self.dut['REGISTERS'].TCP_WRITE_DLY = 0 # no TCP data + self.dut["REGISTERS"].TCP_WRITE_DLY = 0 # no TCP data self.time_start = time.time() self.total_tcp_err_cnt = 0 self.total_tcp_data_words_read = 0 @@ -105,19 +107,21 @@ def start(self, test_tcp=True, test_bus=True, tcp_write_delay=6, monitor_interva self.bus_read_write_speeds = None # initializing threads self.stop_thread.clear() - self.mon_t = Thread(target=self.monitor, name='Monitor thread', kwargs={}) + self.mon_t = Thread(target=self.monitor, name="Monitor thread", kwargs={}) self.mon_t.daemon = True self.mon_t.start() if test_tcp: - self.tcp_t = Thread(target=self.tcp_read, name='TCP thread', kwargs={}) + self.tcp_t = Thread(target=self.tcp_read, name="TCP thread", kwargs={}) self.tcp_t.daemon = True self.tcp_t.start() if test_bus: - self.bus_t = Thread(target=self.bus_read_write, name='BUS thread', kwargs={}) + self.bus_t = Thread(target=self.bus_read_write, name="BUS thread", kwargs={}) self.bus_t.daemon = True self.bus_t.start() if test_tcp: - self.dut['REGISTERS'].TCP_WRITE_DLY = tcp_write_delay # set TCP write delay: 1 equivalent to write data every clock cycle (1/133MHz=0.0075us=7.5ns) + self.dut[ + "REGISTERS" + ].TCP_WRITE_DLY = tcp_write_delay # set TCP write delay: 1 equivalent to write data every clock cycle (1/133MHz=0.0075us=7.5ns) self.time_start = time.time() self.time_stop = self.time_start + 1.0 # while loop for signal handler @@ -142,30 +146,57 @@ def start(self, test_tcp=True, test_bus=True, tcp_write_delay=6, monitor_interva logging.info("=== TCP transfer statistics ===") logging.info("TCP data error counter: %d" % self.total_tcp_err_cnt) logging.info("TCP exception counter: %d" % self.tcp_exception_cnt) - logging.info("TCP write busy counter: %d" % self.dut['REGISTERS'].TCP_FAILED_WRITE_CNT) - logging.info("TCP data words: read: %d, expected: %d" % (self.dut['REGISTERS'].TCP_WRITE_CNT * 4 + self.dut['REGISTERS'].TCP_RECV_WRITE_CNT, self.total_tcp_data_words_read * 4)) + logging.info("TCP write busy counter: %d" % self.dut["REGISTERS"].TCP_FAILED_WRITE_CNT) + logging.info( + "TCP data words: read: %d, expected: %d" + % ( + self.dut["REGISTERS"].TCP_WRITE_CNT * 4 + self.dut["REGISTERS"].TCP_RECV_WRITE_CNT, + self.total_tcp_data_words_read * 4, + ) + ) if self.total_tcp_data_words_read * 4 / 10.0**6 > 1000000: logging.info("Total amount transmitted: %.2f TB" % (self.total_tcp_data_words_read * 4 / 10.0**12)) elif self.total_tcp_data_words_read * 4 / 10.0**6 > 1000: logging.info("Total amount transmitted: %.2f GB" % (self.total_tcp_data_words_read * 4 / 10.0**9)) else: logging.info("Total amount transmitted: %.2f MB" % (self.total_tcp_data_words_read * 4 / 10.0**6)) - total_tcp_avg_read_speed = self.total_tcp_data_words_read * 32 / (self.time_stop - self.time_start) / 10.0**6 + total_tcp_avg_read_speed = ( + self.total_tcp_data_words_read * 32 / (self.time_stop - self.time_start) / 10.0**6 + ) if total_tcp_avg_read_speed < 1.0: logging.info("Total average TCP read speed: %.2f kbit/s" % (total_tcp_avg_read_speed * 10**3)) else: logging.info("Total average TCP read speed: %.2f Mbit/s" % (total_tcp_avg_read_speed)) if self.tcp_read_speeds: if np.average(self.tcp_read_speeds) < 1.0: - logging.info("TCP read speed (min/median/average/max): %.2f/%.2f/%.2f/%.2f kbit/s" % (np.min(self.tcp_read_speeds) * 10**3, np.median(self.tcp_read_speeds) * 10**3, np.average(self.tcp_read_speeds) * 10**3, np.max(self.tcp_read_speeds) * 10**3)) + logging.info( + "TCP read speed (min/median/average/max): %.2f/%.2f/%.2f/%.2f kbit/s" + % ( + np.min(self.tcp_read_speeds) * 10**3, + np.median(self.tcp_read_speeds) * 10**3, + np.average(self.tcp_read_speeds) * 10**3, + np.max(self.tcp_read_speeds) * 10**3, + ) + ) else: - logging.info("TCP read speed (min/median/average/max): %.2f/%.2f/%.2f/%.2f Mbit/s" % (np.min(self.tcp_read_speeds), np.median(self.tcp_read_speeds), np.average(self.tcp_read_speeds), np.max(self.tcp_read_speeds))) + logging.info( + "TCP read speed (min/median/average/max): %.2f/%.2f/%.2f/%.2f Mbit/s" + % ( + np.min(self.tcp_read_speeds), + np.median(self.tcp_read_speeds), + np.average(self.tcp_read_speeds), + np.max(self.tcp_read_speeds), + ) + ) if test_bus: logging.info("=== BUS transfer statistics ===") logging.info("BUS data error counter: %d" % self.total_bus_err_cnt) logging.info("BUS exception counter: %d" % self.bus_exception_cnt) - logging.info("BUS read/write counter: read: %d, expected: %d" % (self.dut['REGISTERS'].BUS_WRITE_CNT, self.total_bus_read_write_cnt * 8)) + logging.info( + "BUS read/write counter: read: %d, expected: %d" + % (self.dut["REGISTERS"].BUS_WRITE_CNT, self.total_bus_read_write_cnt * 8) + ) if self.total_bus_read_write_cnt * 8 / 10.0**6 > 1000000: logging.info("Total amount transmitted: %.2f TB" % (self.total_bus_read_write_cnt * 8 / 10.0**12)) elif self.total_bus_read_write_cnt * 8 / 10.0**6 > 1000: @@ -179,9 +210,25 @@ def start(self, test_tcp=True, test_bus=True, tcp_write_delay=6, monitor_interva logging.info("Total average BUS read/write speed: %.2f Mbit/s" % (total_bus_avg_read_speed)) if self.bus_read_write_speeds: if np.average(self.bus_read_write_speeds) < 1.0: - logging.info("BUS read/write speed (min/median/average/max): %.2f/%.2f/%.2f/%.2f kbit/s" % (np.min(self.bus_read_write_speeds) * 10**3, np.median(self.bus_read_write_speeds) * 10**3, np.average(self.bus_read_write_speeds) * 10**3, np.max(self.bus_read_write_speeds) * 10**3)) + logging.info( + "BUS read/write speed (min/median/average/max): %.2f/%.2f/%.2f/%.2f kbit/s" + % ( + np.min(self.bus_read_write_speeds) * 10**3, + np.median(self.bus_read_write_speeds) * 10**3, + np.average(self.bus_read_write_speeds) * 10**3, + np.max(self.bus_read_write_speeds) * 10**3, + ) + ) else: - logging.info("BUS read/write speed (min/median/average/max): %.2f/%.2f/%.2f/%.2f Mbit/s" % (np.min(self.bus_read_write_speeds), np.median(self.bus_read_write_speeds), np.average(self.bus_read_write_speeds), np.max(self.bus_read_write_speeds))) + logging.info( + "BUS read/write speed (min/median/average/max): %.2f/%.2f/%.2f/%.2f Mbit/s" + % ( + np.min(self.bus_read_write_speeds), + np.median(self.bus_read_write_speeds), + np.average(self.bus_read_write_speeds), + np.max(self.bus_read_write_speeds), + ) + ) # close DUT self.dut.close() @@ -196,7 +243,12 @@ def monitor(self): tmp_total_tcp_data_words_read = self.total_tcp_data_words_read tmp_total_bus_read_write_cnt = self.total_bus_read_write_cnt if self.test_tcp: - tcp_read_speed = (tmp_total_tcp_data_words_read - last_total_tcp_data_words_read) * 32 / (tmp_time_read - time_read) / 10**6 + tcp_read_speed = ( + (tmp_total_tcp_data_words_read - last_total_tcp_data_words_read) + * 32 + / (tmp_time_read - time_read) + / 10**6 + ) if self.tcp_read_speeds is None: # add on second iteration self.tcp_read_speeds = [] else: @@ -206,7 +258,12 @@ def monitor(self): else: logging.info("TCP read speed: %0.2f Mbit/s" % tcp_read_speed) if self.test_bus: - bus_read_write_speed = (tmp_total_bus_read_write_cnt - last_total_bus_read_write_cnt) * 64 / (tmp_time_read - time_read) / 10**6 + bus_read_write_speed = ( + (tmp_total_bus_read_write_cnt - last_total_bus_read_write_cnt) + * 64 + / (tmp_time_read - time_read) + / 10**6 + ) if self.bus_read_write_speeds is None: # add on second iteration self.bus_read_write_speeds = [] else: @@ -228,10 +285,12 @@ def tcp_read(self): fifo_data_last_value = -1 fifo_was_empty = 0 time_read = time.time() - while not self.stop_thread.wait(max(0.0, self.tcp_readout_delay - time_read + time.time())) or fifo_was_empty < 1: + while ( + not self.stop_thread.wait(max(0.0, self.tcp_readout_delay - time_read + time.time())) or fifo_was_empty < 1 + ): time_read = time.time() try: - fifo_data = self.dut['SITCP_FIFO'].get_data() + fifo_data = self.dut["SITCP_FIFO"].get_data() except Exception as e: logging.error(e) self.tcp_exception_cnt += 1 @@ -259,32 +318,58 @@ def bus_read_write(self): time_read = time.time() write_value = int(np.random.randint(2**64, size=None, dtype=np.uint64)) # random.randint(0, 2**64 - 1) try: - self.dut['REGISTERS'].TEST_DATA = write_value + self.dut["REGISTERS"].TEST_DATA = write_value except Exception as e: logging.error(e) self.bus_exception_cnt += 1 else: try: - read_value = self.dut['REGISTERS'].TEST_DATA + read_value = self.dut["REGISTERS"].TEST_DATA except Exception as e: logging.error(e) self.bus_exception_cnt += 1 else: self.total_bus_read_write_cnt += 1 if read_value != write_value: - logging.warning("BUS data not correct: read: %s, expected: %s" % (array('B', struct.unpack("BBBBBBBB", struct.pack("Q", read_value))), array('B', struct.unpack("BBBBBBBB", struct.pack("Q", write_value))))) + logging.warning( + "BUS data not correct: read: %s, expected: %s" + % ( + array("B", struct.unpack("BBBBBBBB", struct.pack("Q", read_value))), + array("B", struct.unpack("BBBBBBBB", struct.pack("Q", write_value))), + ) + ) self.total_bus_err_cnt += 1 logging.info("Stopping BUS thread...") if __name__ == "__main__": import argparse - parser = argparse.ArgumentParser(description='Testing MMC3 Ethernet Interface %s\nExample: python test_eth.py -t 1.0 -d 6 --no-bus', formatter_class=argparse.RawTextHelpFormatter) - parser.add_argument('-w', '--deadline', type=float, metavar='', action='store', help='timeout in seconds before application exits') - parser.add_argument('-i', '--interval', type=float, metavar='', action='store', help='time interval in seconds for the monitor') - parser.add_argument('-d', '--delay', type=int, metavar='', action='store', help='clock cycles between TCP writes') - parser.add_argument('--no-bus', dest='no_bus', action='store_true', help='disable BUS tests') - parser.add_argument('--no-tcp', dest='no_tcp', action='store_true', help='disable TCP downstream tests') + + parser = argparse.ArgumentParser( + description="Testing MMC3 Ethernet Interface %s\nExample: python test_eth.py -t 1.0 -d 6 --no-bus", + formatter_class=argparse.RawTextHelpFormatter, + ) + parser.add_argument( + "-w", + "--deadline", + type=float, + metavar="", + action="store", + help="timeout in seconds before application exits", + ) + parser.add_argument( + "-i", + "--interval", + type=float, + metavar="", + action="store", + help="time interval in seconds for the monitor", + ) + parser.add_argument( + "-d", "--delay", type=int, metavar="", action="store", help="clock cycles between TCP writes" + ) + parser.add_argument("--no-bus", dest="no_bus", action="store_true", help="disable BUS tests") + parser.add_argument("--no-tcp", dest="no_tcp", action="store_true", help="disable TCP downstream tests") parser.set_defaults(no_m26_jtag_configuration=False) args = parser.parse_args() diff --git a/pyproject.toml b/pyproject.toml index 00912be67..a95631034 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -42,9 +42,12 @@ include-package-data = true [tool.setuptools.dynamic] version = {attr = "basil.__version__"} -[tool.flake8] -ignore = ["E501", "E902", "W503", "W605", "W504"] -# max-line-length = 160 - [tool.pytest.ini_options] markers = ["verilator: Verilog tests."] + +[tool.isort] +profile = "black" + +[tool.ruff] +# Set the maximum line length to 180. +line-length = 120 diff --git a/tests/test_BitLogic.py b/tests/test_BitLogic.py index 32e0b67a0..7be3ed1d7 100644 --- a/tests/test_BitLogic.py +++ b/tests/test_BitLogic.py @@ -5,9 +5,10 @@ # ------------------------------------------------------------ # +import struct import unittest + from bitarray import bitarray -import struct from basil.utils.BitLogic import BitLogic @@ -17,42 +18,42 @@ def setUp(self): pass def test_from_value_format(self): - bl = BitLogic.from_value(2232744712, fmt='I') - self.assertEqual(bl, bitarray('10000101000101001111101100001000'[::-1])) + bl = BitLogic.from_value(2232744712, fmt="I") + self.assertEqual(bl, bitarray("10000101000101001111101100001000"[::-1])) def test_from_bit_str(self): - bl = BitLogic('10000101000101001111101100001000', endian='big') # 2232744712 - self.assertEqual(bl, bitarray('10000101000101001111101100001000'[::-1])) + bl = BitLogic("10000101000101001111101100001000", endian="big") # 2232744712 + self.assertEqual(bl, bitarray("10000101000101001111101100001000"[::-1])) def test_from_value_long_long(self): if struct.calcsize("P") == 4: # 32-bit - self.assertRaises(struct.error, BitLogic.from_value, 57857885568556688222588556, fmt='Q') + self.assertRaises(struct.error, BitLogic.from_value, 57857885568556688222588556, fmt="Q") else: - bl = BitLogic.from_value(4772894553230993930 * 2, fmt='Q') - self.assertEqual(bl, bitarray('1000010001111001011101001001110111010111011101011101010000010100'[::-1])) + bl = BitLogic.from_value(4772894553230993930 * 2, fmt="Q") + self.assertEqual(bl, bitarray("1000010001111001011101001001110111010111011101011101010000010100"[::-1])) def test_from_value_with_size_bigger(self): - bl = BitLogic.from_value(2232744712, size=70, fmt='Q') - self.assertEqual(bl, bitarray('10000101000101001111101100001000'[::-1] + '0' * 38)) + bl = BitLogic.from_value(2232744712, size=70, fmt="Q") + self.assertEqual(bl, bitarray("10000101000101001111101100001000"[::-1] + "0" * 38)) def test_from_value_with_int_bigger_than_size(self): - self.assertRaises(TypeError, BitLogic.from_value, 8, size=3, fmt='Q') + self.assertRaises(TypeError, BitLogic.from_value, 8, size=3, fmt="Q") def test_from_value_with_funny_size(self): - self.assertRaises(TypeError, BitLogic.from_value, 8, size='123', fmt='Q') + self.assertRaises(TypeError, BitLogic.from_value, 8, size="123", fmt="Q") def test_from_value_with_size_smaller(self): - bl = BitLogic.from_value(259, size=9, fmt='Q') - self.assertEqual(bl, bitarray('100000011'[::-1])) + bl = BitLogic.from_value(259, size=9, fmt="Q") + self.assertEqual(bl, bitarray("100000011"[::-1])) def test_to_value(self): value = 12 - bl = BitLogic.from_value(value, size=16, fmt='I') + bl = BitLogic.from_value(value, size=16, fmt="I") ret_val = bl.tovalue() self.assertEqual(ret_val, value) def test_get_item(self): - bl = BitLogic.from_value(259, size=9, fmt='Q') + bl = BitLogic.from_value(259, size=9, fmt="Q") self.assertEqual(bl[0], True) self.assertEqual(bl[1], True) self.assertEqual(bl[2], False) @@ -64,32 +65,30 @@ def test_get_item(self): self.assertEqual(bl[8], True) def test_endianness_of_string_assignment(self): - '''test indexing - ''' - bl_1 = BitLogic('11001000') + """test indexing""" + bl_1 = BitLogic("11001000") bl_2 = BitLogic(8) - bl_2[:] = '11001000' + bl_2[:] = "11001000" self.assertEqual(bl_1, bl_2) def test_wrong_size_of_string_assignment(self): - '''test assignment of wrong length bit string - ''' + """test assignment of wrong length bit string""" bl_2 = BitLogic(8) def assign_fails_slice_all(): - bl_2[:] = '110010000' + bl_2[:] = "110010000" def assign_fails_slice_part_1(): - bl_2[3:] = '11110' + bl_2[3:] = "11110" def assign_fails_slice_part_2(): - bl_2[:4] = '11110' + bl_2[:4] = "11110" def assign_fails_slice_part_3(): - bl_2[4:2] = '11110' + bl_2[4:2] = "11110" def assign_fails_slice_part_4(): - bl_2[4:2] = '1' + bl_2[4:2] = "1" self.assertRaises(ValueError, assign_fails_slice_all) self.assertRaises(ValueError, assign_fails_slice_part_1) @@ -98,19 +97,17 @@ def assign_fails_slice_part_4(): self.assertRaises(ValueError, assign_fails_slice_part_4) def test_indexing(self): - '''test indexing - ''' - bl = BitLogic.from_value(128, size=8, fmt='Q', endian='little') + """test indexing""" + bl = BitLogic.from_value(128, size=8, fmt="Q", endian="little") self.assertEqual(bl[7], True) - self.assertEqual(bl[7:7], bitarray('1')) + self.assertEqual(bl[7:7], bitarray("1")) self.assertEqual(bl[-1], True) self.assertEqual(bl[0], False) - self.assertEqual(bl[0:0], bitarray('0')) + self.assertEqual(bl[0:0], bitarray("0")) def test_endianness(self): - '''changing the bit order of each byte - ''' - bl = BitLogic.from_value(259, size=9, fmt='Q', endian='big') + """changing the bit order of each byte""" + bl = BitLogic.from_value(259, size=9, fmt="Q", endian="big") self.assertEqual(bl[0], False) self.assertEqual(bl[1], False) self.assertEqual(bl[2], False) @@ -121,15 +118,15 @@ def test_endianness(self): self.assertEqual(bl[8], False) def test_get_item_with_slice(self): - bl = BitLogic.from_value(12, size=9, fmt='Q') - self.assertEqual(bl[3:1], bitarray('011')) - self.assertEqual(bl[:], bitarray('001100000')) - self.assertEqual(bl[len(bl):], bitarray('001100000')) - self.assertEqual(bl[len(bl):], bitarray('001100000')) - self.assertEqual(bl[len(bl):0], bitarray('001100000')) + bl = BitLogic.from_value(12, size=9, fmt="Q") + self.assertEqual(bl[3:1], bitarray("011")) + self.assertEqual(bl[:], bitarray("001100000")) + self.assertEqual(bl[len(bl) :], bitarray("001100000")) + self.assertEqual(bl[len(bl) :], bitarray("001100000")) + self.assertEqual(bl[len(bl) : 0], bitarray("001100000")) def test_set_item(self): - bl = BitLogic.from_value(8, size=9, fmt='Q') + bl = BitLogic.from_value(8, size=9, fmt="Q") self.assertEqual(bl[3], True) self.assertEqual(bl[2], False) self.assertEqual(bl[4], False) @@ -157,54 +154,54 @@ def assign_slice(value): self.assertRaises(TypeError, lambda val: assign_slice(val), [True, False]) def test_set_item_with_slice(self): - ba = bitarray('001100000') - ba[1:3] = bitarray('11') - self.assertEqual(ba[:], bitarray('011100000')) - bl = BitLogic.from_value(12, size=9, fmt='Q') - self.assertEqual(bl[:], bitarray('001100000')) - bl[2:1] = bitarray('10') - self.assertEqual(bl[:], bitarray('010100000')) - bl[2:1] = bitarray('01') - self.assertEqual(bl[:], bitarray('001100000')) + ba = bitarray("001100000") + ba[1:3] = bitarray("11") + self.assertEqual(ba[:], bitarray("011100000")) + bl = BitLogic.from_value(12, size=9, fmt="Q") + self.assertEqual(bl[:], bitarray("001100000")) + bl[2:1] = bitarray("10") + self.assertEqual(bl[:], bitarray("010100000")) + bl[2:1] = bitarray("01") + self.assertEqual(bl[:], bitarray("001100000")) bl[:] = 5 - self.assertEqual(bl[:], bitarray('101000000')) + self.assertEqual(bl[:], bitarray("101000000")) bl[5:3] = 7 - self.assertEqual(bl[:], bitarray('101111000')) + self.assertEqual(bl[:], bitarray("101111000")) bl[5:3] = 0 - self.assertEqual(bl[:], bitarray('101000000')) - bl[4:4] = bitarray('1') - self.assertEqual(bl[:], bitarray('101010000')) + self.assertEqual(bl[:], bitarray("101000000")) + bl[4:4] = bitarray("1") + self.assertEqual(bl[:], bitarray("101010000")) bl[4:4] = 0 - self.assertEqual(bl[:], bitarray('101000000')) + self.assertEqual(bl[:], bitarray("101000000")) bl[8:8] = 1 - self.assertEqual(bl[:], bitarray('101000001')) + self.assertEqual(bl[:], bitarray("101000001")) bl[0:0] = 0 - self.assertEqual(bl[:], bitarray('001000001')) - bl[3:] = '1111' - self.assertEqual(bl[:], bitarray('111100001')) - bl[:4] = '11111' - self.assertEqual(bl[:], bitarray('111111111')) - bl[2:1] = '00' - self.assertEqual(bl[:], bitarray('100111111')) + self.assertEqual(bl[:], bitarray("001000001")) + bl[3:] = "1111" + self.assertEqual(bl[:], bitarray("111100001")) + bl[:4] = "11111" + self.assertEqual(bl[:], bitarray("111111111")) + bl[2:1] = "00" + self.assertEqual(bl[:], bitarray("100111111")) bl[4:] = 0x0 - self.assertEqual(bl[:], bitarray('000001111')) - bl[:] = 2 ** 8 - self.assertEqual(bl[:], bitarray('000000001')) + self.assertEqual(bl[:], bitarray("000001111")) + bl[:] = 2**8 + self.assertEqual(bl[:], bitarray("000000001")) bl[7] = True - self.assertEqual(bl[:], bitarray('000000011')) + self.assertEqual(bl[:], bitarray("000000011")) bl[8] = False - self.assertEqual(bl[:], bitarray('000000010')) + self.assertEqual(bl[:], bitarray("000000010")) bl[8:8] = True - self.assertEqual(bl[:], bitarray('000000011')) + self.assertEqual(bl[:], bitarray("000000011")) bl[0:0] = True - self.assertEqual(bl[:], bitarray('100000011')) + self.assertEqual(bl[:], bitarray("100000011")) def test_init_to_zero(self): bl = BitLogic(55) - self.assertEqual(bl, bitarray(55 * '0')) + self.assertEqual(bl, bitarray(55 * "0")) def test_get_type_slicing_and_indexing(self): - bl = BitLogic('01000000') + bl = BitLogic("01000000") self.assertIsInstance(bl[3:], bitarray) self.assertIsInstance(bl[:3], bitarray) self.assertIsInstance(bl[:], bitarray) @@ -215,7 +212,7 @@ def test_get_type_slicing_and_indexing(self): self.assertIsInstance(bl[2], int) def test_get_slicing_and_indexing(self): - bl = BitLogic('10000110') + bl = BitLogic("10000110") self.assertFalse(bl[0]) self.assertTrue(bl[1]) self.assertTrue(bl[2]) @@ -224,184 +221,184 @@ def test_get_slicing_and_indexing(self): self.assertFalse(bl[5]) self.assertFalse(bl[6]) self.assertTrue(bl[7]) - self.assertEqual(bl[3:0], bitarray('0110')) - self.assertEqual(bl[3:0], bitarray('0110')) - self.assertEqual(bl[3:], bitarray('0110')) - self.assertEqual(bl[:3], bitarray('00001')) - self.assertEqual(bl[:], bitarray('01100001')) + self.assertEqual(bl[3:0], bitarray("0110")) + self.assertEqual(bl[3:0], bitarray("0110")) + self.assertEqual(bl[3:], bitarray("0110")) + self.assertEqual(bl[:3], bitarray("00001")) + self.assertEqual(bl[:], bitarray("01100001")) def test_set_slicing_and_indexing(self): - bl = BitLogic('00000000') + bl = BitLogic("00000000") bl[3:1] = True # same as 1 - self.assertEqual(bl, bitarray('01000000')) - bl = BitLogic('00000000') + self.assertEqual(bl, bitarray("01000000")) + bl = BitLogic("00000000") bl[3:1] = 0b111 - self.assertEqual(bl, bitarray('01110000')) - bl = BitLogic('11111111') + self.assertEqual(bl, bitarray("01110000")) + bl = BitLogic("11111111") bl[3:1] = False # same as 0 - self.assertEqual(bl, bitarray('10001111')) - bl = BitLogic('00000000') + self.assertEqual(bl, bitarray("10001111")) + bl = BitLogic("00000000") bl[3:1] = 1 - self.assertEqual(bl, bitarray('01000000')) - bl = BitLogic('11111111') + self.assertEqual(bl, bitarray("01000000")) + bl = BitLogic("11111111") bl[3:1] = 0 - self.assertEqual(bl, bitarray('10001111')) + self.assertEqual(bl, bitarray("10001111")) - bl = BitLogic('00000000') + bl = BitLogic("00000000") def assign_slice(value): bl[3:1] = value - self.assertRaises(ValueError, lambda val: assign_slice(val), '1') - self.assertRaises(ValueError, lambda val: assign_slice(val), bitarray('1')) + self.assertRaises(ValueError, lambda val: assign_slice(val), "1") + self.assertRaises(ValueError, lambda val: assign_slice(val), bitarray("1")) # this has to fail -# bl = BitLogic('00000000') -# bl[3:1] = '1' -# self.assertEqual(bl, bitarray('01000000')) -# bl = BitLogic('11111111') -# bl[3:1] = '0' -# self.assertEqual(bl, bitarray('00000000')) -# bl = BitLogic('00000000') -# bl[3:1] = bitarray('1') -# self.assertEqual(bl, bitarray('01000000')) -# bl = BitLogic('11111111') -# bl[3:1] = bitarray('0') -# self.assertEqual(bl, bitarray('00000000')) - - bl = BitLogic('00000000') + # bl = BitLogic('00000000') + # bl[3:1] = '1' + # self.assertEqual(bl, bitarray('01000000')) + # bl = BitLogic('11111111') + # bl[3:1] = '0' + # self.assertEqual(bl, bitarray('00000000')) + # bl = BitLogic('00000000') + # bl[3:1] = bitarray('1') + # self.assertEqual(bl, bitarray('01000000')) + # bl = BitLogic('11111111') + # bl[3:1] = bitarray('0') + # self.assertEqual(bl, bitarray('00000000')) + + bl = BitLogic("00000000") bl[1] = True - self.assertEqual(bl, bitarray('01000000')) - bl = BitLogic('11111111') + self.assertEqual(bl, bitarray("01000000")) + bl = BitLogic("11111111") bl[1] = False - self.assertEqual(bl, bitarray('10111111')) - bl = BitLogic('00000000') + self.assertEqual(bl, bitarray("10111111")) + bl = BitLogic("00000000") bl[1] = 1 - self.assertEqual(bl, bitarray('01000000')) - bl = BitLogic('11111111') + self.assertEqual(bl, bitarray("01000000")) + bl = BitLogic("11111111") bl[1] = 0 - self.assertEqual(bl, bitarray('10111111')) - bl = BitLogic('00000000') - bl[1] = '1' - self.assertEqual(bl, bitarray('01000000')) - bl = BitLogic('11111111') - bl[1] = '0' - self.assertEqual(bl, bitarray('10111111')) - bl = BitLogic('00000000') - bl[1] = bitarray('1') - self.assertEqual(bl, bitarray('01000000')) - bl = BitLogic('11111111') - bl[1] = bitarray('0') - self.assertEqual(bl, bitarray('10111111')) - - bl = BitLogic('00000000') + self.assertEqual(bl, bitarray("10111111")) + bl = BitLogic("00000000") + bl[1] = "1" + self.assertEqual(bl, bitarray("01000000")) + bl = BitLogic("11111111") + bl[1] = "0" + self.assertEqual(bl, bitarray("10111111")) + bl = BitLogic("00000000") + bl[1] = bitarray("1") + self.assertEqual(bl, bitarray("01000000")) + bl = BitLogic("11111111") + bl[1] = bitarray("0") + self.assertEqual(bl, bitarray("10111111")) + + bl = BitLogic("00000000") bl[1:1] = True - self.assertEqual(bl, bitarray('01000000')) - bl = BitLogic('11111111') + self.assertEqual(bl, bitarray("01000000")) + bl = BitLogic("11111111") bl[1:1] = False - self.assertEqual(bl, bitarray('10111111')) - bl = BitLogic('00000000') + self.assertEqual(bl, bitarray("10111111")) + bl = BitLogic("00000000") bl[1:1] = 1 - self.assertEqual(bl, bitarray('01000000')) - bl = BitLogic('11111111') + self.assertEqual(bl, bitarray("01000000")) + bl = BitLogic("11111111") bl[1:1] = 0 - self.assertEqual(bl, bitarray('10111111')) - bl = BitLogic('00000000') - bl[1:1] = '1' - self.assertEqual(bl, bitarray('01000000')) - bl = BitLogic('11111111') - bl[1:1] = '0' - self.assertEqual(bl, bitarray('10111111')) - bl = BitLogic('00000000') - bl[1:1] = bitarray('1') - self.assertEqual(bl, bitarray('01000000')) - bl = BitLogic('11111111') - bl[1:1] = bitarray('0') - self.assertEqual(bl, bitarray('10111111')) + self.assertEqual(bl, bitarray("10111111")) + bl = BitLogic("00000000") + bl[1:1] = "1" + self.assertEqual(bl, bitarray("01000000")) + bl = BitLogic("11111111") + bl[1:1] = "0" + self.assertEqual(bl, bitarray("10111111")) + bl = BitLogic("00000000") + bl[1:1] = bitarray("1") + self.assertEqual(bl, bitarray("01000000")) + bl = BitLogic("11111111") + bl[1:1] = bitarray("0") + self.assertEqual(bl, bitarray("10111111")) def test_set_item_negative(self): - bl = BitLogic('00000000') + bl = BitLogic("00000000") bl[-3] = True - self.assertEqual(bl, bitarray('00000100')) + self.assertEqual(bl, bitarray("00000100")) bl[-3] = False - self.assertEqual(bl, bitarray('00000000')) + self.assertEqual(bl, bitarray("00000000")) bl[-3:-3] = True - self.assertEqual(bl, bitarray('00000100')) + self.assertEqual(bl, bitarray("00000100")) bl[-3:-3] = False - self.assertEqual(bl, bitarray('00000000')) + self.assertEqual(bl, bitarray("00000000")) bl[-3] = 1 - self.assertEqual(bl, bitarray('00000100')) + self.assertEqual(bl, bitarray("00000100")) bl[-3] = 0 - self.assertEqual(bl, bitarray('00000000')) + self.assertEqual(bl, bitarray("00000000")) bl[-3:-3] = 1 - self.assertEqual(bl, bitarray('00000100')) + self.assertEqual(bl, bitarray("00000100")) bl[-3:-3] = 0 - self.assertEqual(bl, bitarray('00000000')) - bl[-3] = '1' - self.assertEqual(bl, bitarray('00000100')) - bl[-3] = '0' - self.assertEqual(bl, bitarray('00000000')) - bl[-3:-3] = '1' - self.assertEqual(bl, bitarray('00000100')) - bl[-3:-3] = '0' - self.assertEqual(bl, bitarray('00000000')) + self.assertEqual(bl, bitarray("00000000")) + bl[-3] = "1" + self.assertEqual(bl, bitarray("00000100")) + bl[-3] = "0" + self.assertEqual(bl, bitarray("00000000")) + bl[-3:-3] = "1" + self.assertEqual(bl, bitarray("00000100")) + bl[-3:-3] = "0" + self.assertEqual(bl, bitarray("00000000")) bl[-1] = True - self.assertEqual(bl, bitarray('00000001')) + self.assertEqual(bl, bitarray("00000001")) bl[-1] = False - self.assertEqual(bl, bitarray('00000000')) + self.assertEqual(bl, bitarray("00000000")) bl[-1:-1] = True - self.assertEqual(bl, bitarray('00000001')) + self.assertEqual(bl, bitarray("00000001")) bl[-1:-1] = False - self.assertEqual(bl, bitarray('00000000')) + self.assertEqual(bl, bitarray("00000000")) bl[-1] = 1 - self.assertEqual(bl, bitarray('00000001')) + self.assertEqual(bl, bitarray("00000001")) bl[-1] = 0 - self.assertEqual(bl, bitarray('00000000')) + self.assertEqual(bl, bitarray("00000000")) bl[-1:-1] = 1 - self.assertEqual(bl, bitarray('00000001')) + self.assertEqual(bl, bitarray("00000001")) bl[-1:-1] = 0 - self.assertEqual(bl, bitarray('00000000')) - bl[-1] = '1' - self.assertEqual(bl, bitarray('00000001')) - bl[-1] = '0' - self.assertEqual(bl, bitarray('00000000')) - bl[-1:-1] = '1' - self.assertEqual(bl, bitarray('00000001')) - bl[-1:-1] = '0' - self.assertEqual(bl, bitarray('00000000')) + self.assertEqual(bl, bitarray("00000000")) + bl[-1] = "1" + self.assertEqual(bl, bitarray("00000001")) + bl[-1] = "0" + self.assertEqual(bl, bitarray("00000000")) + bl[-1:-1] = "1" + self.assertEqual(bl, bitarray("00000001")) + bl[-1:-1] = "0" + self.assertEqual(bl, bitarray("00000000")) bl[-8] = True - self.assertEqual(bl, bitarray('10000000')) + self.assertEqual(bl, bitarray("10000000")) bl[-8] = False - self.assertEqual(bl, bitarray('00000000')) + self.assertEqual(bl, bitarray("00000000")) bl[-8:-8] = True - self.assertEqual(bl, bitarray('10000000')) + self.assertEqual(bl, bitarray("10000000")) bl[-8:-8] = False - self.assertEqual(bl, bitarray('00000000')) + self.assertEqual(bl, bitarray("00000000")) bl[-8] = 1 - self.assertEqual(bl, bitarray('10000000')) + self.assertEqual(bl, bitarray("10000000")) bl[-8] = 0 - self.assertEqual(bl, bitarray('00000000')) + self.assertEqual(bl, bitarray("00000000")) bl[-8:-8] = 1 - self.assertEqual(bl, bitarray('10000000')) + self.assertEqual(bl, bitarray("10000000")) bl[-8:-8] = 0 - self.assertEqual(bl, bitarray('00000000')) - bl[-8] = '1' - self.assertEqual(bl, bitarray('10000000')) - bl[-8] = '0' - self.assertEqual(bl, bitarray('00000000')) - bl[-8:-8] = '1' - self.assertEqual(bl, bitarray('10000000')) - bl[-8:-8] = '0' - self.assertEqual(bl, bitarray('00000000')) + self.assertEqual(bl, bitarray("00000000")) + bl[-8] = "1" + self.assertEqual(bl, bitarray("10000000")) + bl[-8] = "0" + self.assertEqual(bl, bitarray("00000000")) + bl[-8:-8] = "1" + self.assertEqual(bl, bitarray("10000000")) + bl[-8:-8] = "0" + self.assertEqual(bl, bitarray("00000000")) bl[-7:-8] = 2 - self.assertEqual(bl, bitarray('01000000')) + self.assertEqual(bl, bitarray("01000000")) bl[-2:-3] = 2 - self.assertEqual(bl, bitarray('01000010')) + self.assertEqual(bl, bitarray("01000010")) bl[-1:-2] = 2 - self.assertEqual(bl, bitarray('01000001')) + self.assertEqual(bl, bitarray("01000001")) -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/tests/test_RegisterHardwareLayer.py b/tests/test_RegisterHardwareLayer.py index 6df555353..1b11ad433 100644 --- a/tests/test_RegisterHardwareLayer.py +++ b/tests/test_RegisterHardwareLayer.py @@ -5,38 +5,35 @@ # ------------------------------------------------------------ # +import os import unittest from basil.dut import Dut from basil.HL.RegisterHardwareLayer import RegisterHardwareLayer -import os -_test_init = { - 'REG_TEST_INIT': 15, - 'REG1': 120, - 'REG_BYTE_ARRAY': [4, 3, 2, 1] -} +_test_init = {"REG_TEST_INIT": 15, "REG1": 120, "REG_BYTE_ARRAY": [4, 3, 2, 1]} class test_RegisterHardwareLayer(RegisterHardwareLayer): - '''Register Hardware Layer. + """Register Hardware Layer. Implementation of advanced register operations. - ''' + """ + _registers = { - 'REG1': {'default': 12, 'descr': {'addr': 0, 'size': 15, 'offset': 0}}, - 'REG2': {'default': 1, 'descr': {'addr': 1, 'size': 1, 'offset': 7}}, - 'REG3': {'default': 2 ** 16 - 1, 'descr': {'addr': 2, 'size': 16, 'offset': 0}}, - 'REG4_RO': {'default': 0, 'descr': {'addr': 4, 'size': 8, 'properties': ['readonly']}}, - 'REG5_WO': {'default': 0, 'descr': {'addr': 5, 'size': 8, 'properties': ['writeonly']}}, - 'REG_TEST_INIT': {'descr': {'addr': 6, 'size': 8}}, - 'REG_BYTE_ARRAY': {'default': [1, 2, 3, 4], 'descr': {'addr': 16, 'size': 4, 'properties': ['bytearray']}} + "REG1": {"default": 12, "descr": {"addr": 0, "size": 15, "offset": 0}}, + "REG2": {"default": 1, "descr": {"addr": 1, "size": 1, "offset": 7}}, + "REG3": {"default": 2**16 - 1, "descr": {"addr": 2, "size": 16, "offset": 0}}, + "REG4_RO": {"default": 0, "descr": {"addr": 4, "size": 8, "properties": ["readonly"]}}, + "REG5_WO": {"default": 0, "descr": {"addr": 5, "size": 8, "properties": ["writeonly"]}}, + "REG_TEST_INIT": {"descr": {"addr": 6, "size": 8}}, + "REG_BYTE_ARRAY": {"default": [1, 2, 3, 4], "descr": {"addr": 16, "size": 4, "properties": ["bytearray"]}}, } class TestRegisterHardwareLayer(unittest.TestCase): def setUp(self): - self.dut = Dut(os.path.join(os.path.dirname(__file__), 'test_RegisterHardwareLayer.yaml')) + self.dut = Dut(os.path.join(os.path.dirname(__file__), "test_RegisterHardwareLayer.yaml")) self.dut.init() def test_init_non_existing(self): @@ -44,157 +41,205 @@ def test_init_non_existing(self): self.dut.init({"test_register": {"NON_EXISTING": 1}}) def test_lazy_programming(self): - self.dut['test_register'].set_default() - self.assertDictEqual({0: 12, 1: 128, 2: 255, 3: 255, 5: 0, 16: 1, 17: 2, 18: 3, 19: 4}, self.dut['dummy_tl'].mem) - self.dut['test_register'].REG5_WO = 255 - self.assertDictEqual({0: 12, 1: 128, 2: 255, 3: 255, 5: 255, 16: 1, 17: 2, 18: 3, 19: 4}, self.dut['dummy_tl'].mem) - self.dut['test_register'].REG5_WO # get value from write-only register, but this will write zero instead - self.assertDictEqual({0: 12, 1: 128, 2: 255, 3: 255, 5: 0, 16: 1, 17: 2, 18: 3, 19: 4}, self.dut['dummy_tl'].mem) + self.dut["test_register"].set_default() + self.assertDictEqual( + {0: 12, 1: 128, 2: 255, 3: 255, 5: 0, 16: 1, 17: 2, 18: 3, 19: 4}, self.dut["dummy_tl"].mem + ) + self.dut["test_register"].REG5_WO = 255 + self.assertDictEqual( + {0: 12, 1: 128, 2: 255, 3: 255, 5: 255, 16: 1, 17: 2, 18: 3, 19: 4}, self.dut["dummy_tl"].mem + ) + self.dut["test_register"].REG5_WO # get value from write-only register, but this will write zero instead + self.assertDictEqual( + {0: 12, 1: 128, 2: 255, 3: 255, 5: 0, 16: 1, 17: 2, 18: 3, 19: 4}, self.dut["dummy_tl"].mem + ) def test_get_configuration(self): - self.dut.set_configuration(os.path.join(os.path.dirname(__file__), 'test_RegisterHardwareLayer_configuration.yaml')) - conf = self.dut['test_register'].get_configuration() - self.assertDictEqual({'REG1': 257, 'REG2': 1, 'REG3': 2, 'REG_TEST_INIT': 0, 'REG_BYTE_ARRAY': [1, 2, 3, 4]}, conf) + self.dut.set_configuration( + os.path.join(os.path.dirname(__file__), "test_RegisterHardwareLayer_configuration.yaml") + ) + conf = self.dut["test_register"].get_configuration() + self.assertDictEqual( + {"REG1": 257, "REG2": 1, "REG3": 2, "REG_TEST_INIT": 0, "REG_BYTE_ARRAY": [1, 2, 3, 4]}, conf + ) def test_set_configuration(self): - self.dut.set_configuration(os.path.join(os.path.dirname(__file__), 'test_RegisterHardwareLayer_configuration.yaml')) - self.assertDictEqual({0: 1, 1: 129, 2: 2, 3: 0, 5: 5, 16: 1, 17: 2, 18: 3, 19: 4}, self.dut['dummy_tl'].mem) + self.dut.set_configuration( + os.path.join(os.path.dirname(__file__), "test_RegisterHardwareLayer_configuration.yaml") + ) + self.assertDictEqual({0: 1, 1: 129, 2: 2, 3: 0, 5: 5, 16: 1, 17: 2, 18: 3, 19: 4}, self.dut["dummy_tl"].mem) def test_set_configuration_non_existing(self): with self.assertRaises(KeyError): self.dut.set_configuration({"test_register": {"NON_EXISTING": 1}}) def test_read_only(self): - self.assertRaises(IOError, self.dut['test_register']._set, 'REG4_RO', value=0) + self.assertRaises(IOError, self.dut["test_register"]._set, "REG4_RO", value=0) -# def test_write_only(self): -# self.assertRaises(IOError, self.dut['test_register']._get, 'REG5_WO') + # def test_write_only(self): + # self.assertRaises(IOError, self.dut['test_register']._get, 'REG5_WO') def test_write_only_lazy_programming(self): - self.dut['test_register'].set_default() - self.assertDictEqual({0: 12, 1: 128, 2: 255, 3: 255, 5: 0, 16: 1, 17: 2, 18: 3, 19: 4}, self.dut['dummy_tl'].mem) - self.dut['test_register'].REG5_WO = 20 - self.assertDictEqual({0: 12, 1: 128, 2: 255, 3: 255, 5: 20, 16: 1, 17: 2, 18: 3, 19: 4}, self.dut['dummy_tl'].mem) - self.dut['test_register'].REG5_WO - self.assertDictEqual({0: 12, 1: 128, 2: 255, 3: 255, 5: 0, 16: 1, 17: 2, 18: 3, 19: 4}, self.dut['dummy_tl'].mem) - self.assertIs(None, self.dut['test_register']._get('REG5_WO')) + self.dut["test_register"].set_default() + self.assertDictEqual( + {0: 12, 1: 128, 2: 255, 3: 255, 5: 0, 16: 1, 17: 2, 18: 3, 19: 4}, self.dut["dummy_tl"].mem + ) + self.dut["test_register"].REG5_WO = 20 + self.assertDictEqual( + {0: 12, 1: 128, 2: 255, 3: 255, 5: 20, 16: 1, 17: 2, 18: 3, 19: 4}, self.dut["dummy_tl"].mem + ) + self.dut["test_register"].REG5_WO + self.assertDictEqual( + {0: 12, 1: 128, 2: 255, 3: 255, 5: 0, 16: 1, 17: 2, 18: 3, 19: 4}, self.dut["dummy_tl"].mem + ) + self.assertIs(None, self.dut["test_register"]._get("REG5_WO")) def test_set_default(self): - self.dut['test_register'].set_default() - self.assertDictEqual({0: 12, 1: 128, 2: 255, 3: 255, 5: 0, 16: 1, 17: 2, 18: 3, 19: 4}, self.dut['dummy_tl'].mem) + self.dut["test_register"].set_default() + self.assertDictEqual( + {0: 12, 1: 128, 2: 255, 3: 255, 5: 0, 16: 1, 17: 2, 18: 3, 19: 4}, self.dut["dummy_tl"].mem + ) def test_set_attribute_add(self): - val = self.dut['test_register']._registers['REG1']['default'] - self.dut['test_register'].REG1 = val # 12 - mem = self.dut['dummy_tl'].mem.copy() - self.dut['test_register'].REG1 += 1 # 13 + val = self.dut["test_register"]._registers["REG1"]["default"] + self.dut["test_register"].REG1 = val # 12 + mem = self.dut["dummy_tl"].mem.copy() + self.dut["test_register"].REG1 += 1 # 13 mem[0] = 13 - self.assertDictEqual(mem, self.dut['dummy_tl'].mem) + self.assertDictEqual(mem, self.dut["dummy_tl"].mem) def test_write_read_reg(self): - for reg in ['REG1', 'REG2', 'REG3']: - val = self.dut['test_register']._registers[reg]['default'] - self.dut['test_register']._set(reg, val) - ret_val = self.dut['test_register']._get(reg) + for reg in ["REG1", "REG2", "REG3"]: + val = self.dut["test_register"]._registers[reg]["default"] + self.dut["test_register"]._set(reg, val) + ret_val = self.dut["test_register"]._get(reg) self.assertEqual(ret_val, val) - self.assertDictEqual({0: 12, 1: 128, 2: 255, 3: 255, 5: 0, 16: 1, 17: 2, 18: 3, 19: 4}, self.dut['dummy_tl'].mem) + self.assertDictEqual( + {0: 12, 1: 128, 2: 255, 3: 255, 5: 0, 16: 1, 17: 2, 18: 3, 19: 4}, self.dut["dummy_tl"].mem + ) def test_set_attribute_by_value(self): - self.dut['test_register'].set_default() - self.assertDictEqual({0: 12, 1: 128, 2: 255, 3: 255, 5: 0, 16: 1, 17: 2, 18: 3, 19: 4}, self.dut['dummy_tl'].mem) - self.dut['test_register'].REG2 = 0 - mem = self.dut['dummy_tl'].mem.copy() + self.dut["test_register"].set_default() + self.assertDictEqual( + {0: 12, 1: 128, 2: 255, 3: 255, 5: 0, 16: 1, 17: 2, 18: 3, 19: 4}, self.dut["dummy_tl"].mem + ) + self.dut["test_register"].REG2 = 0 + mem = self.dut["dummy_tl"].mem.copy() mem[1] = 0 - self.assertDictEqual(mem, self.dut['dummy_tl'].mem) + self.assertDictEqual(mem, self.dut["dummy_tl"].mem) def test_set_attribute_by_string(self): - mem = self.dut['dummy_tl'].mem.copy() - self.dut['test_register'].REG3 = '1010101010101010' # dfghfghdfghgfdghf + mem = self.dut["dummy_tl"].mem.copy() + self.dut["test_register"].REG3 = "1010101010101010" # dfghfghdfghgfdghf mem[2] = 170 mem[3] = 170 - self.assertDictEqual(mem, self.dut['dummy_tl'].mem) + self.assertDictEqual(mem, self.dut["dummy_tl"].mem) def test_get_attribute_by_string(self): - self.dut['test_register'].REG3 = '1010101010101010' # 43690 - self.assertEqual(43690, self.dut['test_register'].REG3) + self.dut["test_register"].REG3 = "1010101010101010" # 43690 + self.assertEqual(43690, self.dut["test_register"].REG3) def test_set_attribute_too_long_string(self): - val = '11010101010101010' # 17 bit - self.assertRaises(TypeError, self.dut['test_register']._set, 'REG3', value=val) + val = "11010101010101010" # 17 bit + self.assertRaises(TypeError, self.dut["test_register"]._set, "REG3", value=val) def test_set_attribute_dict_access(self): - self.dut['test_register']['REG1'] = 27306 # 27306 - self.assertEqual(27306, self.dut['test_register']['REG1']) + self.dut["test_register"]["REG1"] = 27306 # 27306 + self.assertEqual(27306, self.dut["test_register"]["REG1"]) def test_set_attribute_too_big_val(self): - val = 2 ** 16 # max 2 ** 16 - 1 - self.assertRaises(TypeError, self.dut['test_register']._set, 'REG3', value=val) + val = 2**16 # max 2 ** 16 - 1 + self.assertRaises(TypeError, self.dut["test_register"]._set, "REG3", value=val) def test_set_by_function(self): - self.dut['test_register'].set_REG1(27308) - self.assertEqual(27308, self.dut['test_register']['REG1']) + self.dut["test_register"].set_REG1(27308) + self.assertEqual(27308, self.dut["test_register"]["REG1"]) def test_get_by_function(self): - self.dut['test_register']['REG1'] = 27305 # 27306 - ret = self.dut['test_register'].get_REG1() - self.assertEqual(ret, self.dut['test_register']['REG1']) + self.dut["test_register"]["REG1"] = 27305 # 27306 + ret = self.dut["test_register"].get_REG1() + self.assertEqual(ret, self.dut["test_register"]["REG1"]) def test_init_with_dict(self): - self.dut['test_register'].set_default() - self.dut.init({'test_register': _test_init}) + self.dut["test_register"].set_default() + self.dut.init({"test_register": _test_init}) conf = self.dut.get_configuration() - self.assertDictEqual({'test_register': {'REG1': 120, 'REG2': 1, 'REG3': 65535, 'REG_TEST_INIT': 15, 'REG_BYTE_ARRAY': [4, 3, 2, 1]}, 'dummy_tl': {}}, conf) + self.assertDictEqual( + { + "test_register": { + "REG1": 120, + "REG2": 1, + "REG3": 65535, + "REG_TEST_INIT": 15, + "REG_BYTE_ARRAY": [4, 3, 2, 1], + }, + "dummy_tl": {}, + }, + conf, + ) def test_get_dut_configuration(self): - self.dut['test_register'].set_default() + self.dut["test_register"].set_default() conf = self.dut.get_configuration() - self.assertDictEqual({'test_register': {'REG1': 12, 'REG2': 1, 'REG3': 65535, 'REG_TEST_INIT': 0, 'REG_BYTE_ARRAY': [1, 2, 3, 4]}, 'dummy_tl': {}}, conf) + self.assertDictEqual( + { + "test_register": { + "REG1": 12, + "REG2": 1, + "REG3": 65535, + "REG_TEST_INIT": 0, + "REG_BYTE_ARRAY": [1, 2, 3, 4], + }, + "dummy_tl": {}, + }, + conf, + ) def test_get_set_value(self): for val in range(256): - self.dut['test_register'].set_value(val, 0, size=8, offset=0) - ret_val = self.dut['test_register'].get_value(0, size=8, offset=0) + self.dut["test_register"].set_value(val, 0, size=8, offset=0) + ret_val = self.dut["test_register"].get_value(0, size=8, offset=0) self.assertEqual(ret_val, val) def test_write_read_reg_with_bit_str(self): - val = '00110110' # 54 - self.dut['test_register'].set_value(val, 0, size=8, offset=0) - ret_val = self.dut['test_register'].get_value(0, size=8, offset=0) + val = "00110110" # 54 + self.dut["test_register"].set_value(val, 0, size=8, offset=0) + ret_val = self.dut["test_register"].get_value(0, size=8, offset=0) self.assertEqual(ret_val, int(val, base=2)) def test_write_read_reg_with_offset(self): for offset in range(32): val = 131 - self.dut['test_register'].set_value(val, 0, size=8, offset=offset) - ret_val = self.dut['test_register'].get_value(0, size=8, offset=offset) + self.dut["test_register"].set_value(val, 0, size=8, offset=offset) + ret_val = self.dut["test_register"].get_value(0, size=8, offset=offset) self.assertEqual(ret_val, val) def test_write_read_reg_with_size(self): for size in range(8, 33): val = 131 - self.dut['test_register'].set_value(val, 0, size=size, offset=7) - ret_val = self.dut['test_register'].get_value(0, size=size, offset=7) + self.dut["test_register"].set_value(val, 0, size=size, offset=7) + ret_val = self.dut["test_register"].get_value(0, size=size, offset=7) self.assertEqual(ret_val, val) def test_read_non_existing(self): with self.assertRaises(KeyError): - self.dut['test_register'].NON_EXISTING + self.dut["test_register"].NON_EXISTING with self.assertRaises(KeyError): - self.dut['test_register']['NON_EXISTING'] + self.dut["test_register"]["NON_EXISTING"] with self.assertRaises(KeyError): - self.dut['test_register'].get_NON_EXISTING() + self.dut["test_register"].get_NON_EXISTING() def test_write_non_existing(self): with self.assertRaises(KeyError): - self.dut['test_register'].NON_EXISTING = 42 + self.dut["test_register"].NON_EXISTING = 42 with self.assertRaises(KeyError): - self.dut['test_register']['NON_EXISTING'] = 42 + self.dut["test_register"]["NON_EXISTING"] = 42 with self.assertRaises(KeyError): - self.dut['test_register'].set_NON_EXISTING(42) + self.dut["test_register"].set_NON_EXISTING(42) def test_wrong_size(self): - self.assertRaises(TypeError, self.dut['test_register'].set_value, 131, addr=0, size=7, offset=7) + self.assertRaises(TypeError, self.dut["test_register"].set_value, 131, addr=0, size=7, offset=7) -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/tests/test_RegisterHardwareLayer.yaml b/tests/test_RegisterHardwareLayer.yaml index ee6f0bd09..1cd0c6836 100644 --- a/tests/test_RegisterHardwareLayer.yaml +++ b/tests/test_RegisterHardwareLayer.yaml @@ -5,13 +5,13 @@ # ------------------------------------------------------------ # -name : RegisterHardwareLayer +name : RegisterHardwareLayer version : 0.01 transfer_layer: - name : dummy_tl type : Dummy - + hw_drivers: - name : test_register type : test_RegisterHardwareLayer diff --git a/tests/test_SimAdcRx.py b/tests/test_SimAdcRx.py index 2492e848e..1c70a2f92 100644 --- a/tests/test_SimAdcRx.py +++ b/tests/test_SimAdcRx.py @@ -5,8 +5,8 @@ # ------------------------------------------------------------ # -import unittest import os +import unittest from basil.dut import Dut from basil.utils.sim.utils import cocotb_compile_and_run, cocotb_compile_clean @@ -54,77 +54,77 @@ class TestSimAdcRx(unittest.TestCase): def setUp(self): - cocotb_compile_and_run([os.path.join(os.path.dirname(__file__), 'test_SimAdcRx.v')]) + cocotb_compile_and_run([os.path.join(os.path.dirname(__file__), "test_SimAdcRx.v")]) self.chip = Dut(cnfg_yaml) self.chip.init() def test_io(self): pattern = [0, 1, 1, 1, 2, 1, 3, 1, 4, 1, 5, 1, 6, 1, 7, 1] - self.chip['SEQ_GEN'].set_data(pattern) + self.chip["SEQ_GEN"].set_data(pattern) - self.chip['PULSE_GEN'].set_DELAY(1) - self.chip['PULSE_GEN'].set_WIDTH(1) + self.chip["PULSE_GEN"].set_DELAY(1) + self.chip["PULSE_GEN"].set_WIDTH(1) - self.chip['SEQ_GEN'].set_en_ext_start(True) - self.chip['SEQ_GEN'].set_SIZE(8) - self.chip['SEQ_GEN'].set_REPEAT(1) + self.chip["SEQ_GEN"].set_en_ext_start(True) + self.chip["SEQ_GEN"].set_SIZE(8) + self.chip["SEQ_GEN"].set_REPEAT(1) # this is to have something in memory and not X - self.chip['PULSE_GEN'].start() - self.chip['SEQ_GEN'].is_ready - self.chip['SEQ_GEN'].is_ready + self.chip["PULSE_GEN"].start() + self.chip["SEQ_GEN"].is_ready + self.chip["SEQ_GEN"].is_ready - while not self.chip['SEQ_GEN'].is_ready: + while not self.chip["SEQ_GEN"].is_ready: pass # take some data - self.chip['FADC'].set_align_to_sync(True) - self.chip['FADC'].set_data_count(16) - self.chip['FADC'].set_single_data(True) - self.chip['FADC'].start() + self.chip["FADC"].set_align_to_sync(True) + self.chip["FADC"].set_data_count(16) + self.chip["FADC"].set_single_data(True) + self.chip["FADC"].start() - self.chip['PULSE_GEN'].start() - self.chip['SEQ_GEN'].is_ready - self.chip['SEQ_GEN'].is_ready + self.chip["PULSE_GEN"].start() + self.chip["SEQ_GEN"].is_ready + self.chip["SEQ_GEN"].is_ready - while not self.chip['FADC'].is_ready: + while not self.chip["FADC"].is_ready: pass - ret = self.chip['FIFO'].get_data() + ret = self.chip["FIFO"].get_data() self.assertEqual(len(ret), 16) - self.assertEqual(ret[2:2 + 8].tolist(), [0x0100, 0x0101, 0x0102, 0x0103, 0x0104, 0x0105, 0x0106, 0x0107]) + self.assertEqual(ret[2 : 2 + 8].tolist(), [0x0100, 0x0101, 0x0102, 0x0103, 0x0104, 0x0105, 0x0106, 0x0107]) # 2times - self.chip['FADC'].start() + self.chip["FADC"].start() - self.chip['PULSE_GEN'].start() - self.chip['SEQ_GEN'].is_ready + self.chip["PULSE_GEN"].start() + self.chip["SEQ_GEN"].is_ready - while not self.chip['FADC'].is_ready: + while not self.chip["FADC"].is_ready: pass - self.chip['FADC'].start() + self.chip["FADC"].start() - self.chip['PULSE_GEN'].start() - self.chip['SEQ_GEN'].is_ready + self.chip["PULSE_GEN"].start() + self.chip["SEQ_GEN"].is_ready - while not self.chip['FADC'].is_ready: + while not self.chip["FADC"].is_ready: pass - ret = self.chip['FIFO'].get_data() + ret = self.chip["FIFO"].get_data() self.assertEqual(len(ret), 32) - self.assertEqual(ret[2:2 + 8].tolist(), [0x0100, 0x0101, 0x0102, 0x0103, 0x0104, 0x0105, 0x0106, 0x0107]) + self.assertEqual(ret[2 : 2 + 8].tolist(), [0x0100, 0x0101, 0x0102, 0x0103, 0x0104, 0x0105, 0x0106, 0x0107]) - self.chip['FADC'].set_align_to_sync(False) - self.chip['FADC'].start() - self.chip['FADC'].start() + self.chip["FADC"].set_align_to_sync(False) + self.chip["FADC"].start() + self.chip["FADC"].start() - while not self.chip['FADC'].is_ready: + while not self.chip["FADC"].is_ready: pass - ret = self.chip['FIFO'].get_data() + ret = self.chip["FIFO"].get_data() self.assertEqual(len(ret), 16) def tearDown(self): @@ -132,5 +132,5 @@ def tearDown(self): cocotb_compile_clean() -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/tests/test_SimCmdSeq.py b/tests/test_SimCmdSeq.py index aed171323..32d48c8ed 100644 --- a/tests/test_SimCmdSeq.py +++ b/tests/test_SimCmdSeq.py @@ -5,8 +5,8 @@ # ------------------------------------------------------------ # -import unittest import os +import unittest import numpy as np @@ -47,19 +47,19 @@ class TestSimSeq(unittest.TestCase): def setUp(self): - cocotb_compile_and_run([os.path.join(os.path.dirname(__file__), 'test_SimCmdSeq.v')]) + cocotb_compile_and_run([os.path.join(os.path.dirname(__file__), "test_SimCmdSeq.v")]) self.chip = Dut(cnfg_yaml) self.chip.init() @unittest.skip("saving CPU time") def test_basic_io(self): - self.chip['CMD_SEQ']['OUTPUT_MODE'] = 0 - self.chip['CMD_SEQ']['OUTPUT_ENABLE'] = 0x01 - self.chip['SEQ_REC']['EN_EXT_START'] = 1 - self.chip['CMD_SEQ']['EN_EXT_TRIGGER'] = 1 - self.chip['PULSE_GEN']['DELAY'] = 1 - self.chip['PULSE_GEN']['WIDTH'] = 1 + self.chip["CMD_SEQ"]["OUTPUT_MODE"] = 0 + self.chip["CMD_SEQ"]["OUTPUT_ENABLE"] = 0x01 + self.chip["SEQ_REC"]["EN_EXT_START"] = 1 + self.chip["CMD_SEQ"]["EN_EXT_TRIGGER"] = 1 + self.chip["PULSE_GEN"]["DELAY"] = 1 + self.chip["PULSE_GEN"]["WIDTH"] = 1 for cmd_pattern in [0x00, np.random.randint(1, 255), 0xFF]: for cmd_size in [0, 1, 2, np.random.randint(3, max_cmd_size - 1), max_cmd_size - 1, max_cmd_size]: @@ -67,25 +67,25 @@ def test_basic_io(self): if isinstance(cmd_pattern, list): write_cmd_pattern = list(cmd_pattern) # copy write_cmd_pattern.extend(np.random.randint(0, 256, size=max_cmd_byte_size - len(write_cmd_pattern))) - self.chip['CMD_SEQ'].set_data(data=write_cmd_pattern, addr=0) + self.chip["CMD_SEQ"].set_data(data=write_cmd_pattern, addr=0) else: write_cmd_pattern = [cmd_pattern] * max_cmd_byte_size - self.chip['CMD_SEQ'].set_data(data=write_cmd_pattern, addr=0) - ret = self.chip['CMD_SEQ'].get_data(size=max_cmd_byte_size) + self.chip["CMD_SEQ"].set_data(data=write_cmd_pattern, addr=0) + ret = self.chip["CMD_SEQ"].get_data(size=max_cmd_byte_size) np.testing.assert_array_equal(ret, write_cmd_pattern) # self.assertListEqual(ret.tolist(), write_cmd_pattern) - self.chip['CMD_SEQ']['CMD_SIZE'] = cmd_size + self.chip["CMD_SEQ"]["CMD_SIZE"] = cmd_size rec_size = cmd_size + rec_add_size - self.chip['SEQ_REC']['SIZE'] = rec_size - self.chip['PULSE_GEN']['START'] + self.chip["SEQ_REC"]["SIZE"] = rec_size + self.chip["PULSE_GEN"]["START"] - while not self.chip['CMD_SEQ']['READY']: + while not self.chip["CMD_SEQ"]["READY"]: pass - while not self.chip['SEQ_REC']['READY']: + while not self.chip["SEQ_REC"]["READY"]: pass - ret = self.chip['SEQ_REC'].get_data(size=rec_size) + ret = self.chip["SEQ_REC"].get_data(size=rec_size) expected_arr = np.array(write_cmd_pattern, dtype=np.uint8) expected_bits = np.unpackbits(expected_arr).flatten()[:cmd_size] expected_bits = np.r_[expected_bits, [0] * (rec_size - len(expected_bits))] @@ -94,38 +94,47 @@ def test_basic_io(self): @unittest.skip("saving CPU time") def test_repeat(self): - self.chip['CMD_SEQ']['OUTPUT_MODE'] = 0 - self.chip['CMD_SEQ']['OUTPUT_ENABLE'] = 0x01 - self.chip['SEQ_REC']['EN_EXT_START'] = 1 - self.chip['CMD_SEQ']['EN_EXT_TRIGGER'] = 1 - self.chip['PULSE_GEN']['DELAY'] = 1 - self.chip['PULSE_GEN']['WIDTH'] = 1 + self.chip["CMD_SEQ"]["OUTPUT_MODE"] = 0 + self.chip["CMD_SEQ"]["OUTPUT_ENABLE"] = 0x01 + self.chip["SEQ_REC"]["EN_EXT_START"] = 1 + self.chip["CMD_SEQ"]["EN_EXT_TRIGGER"] = 1 + self.chip["PULSE_GEN"]["DELAY"] = 1 + self.chip["PULSE_GEN"]["WIDTH"] = 1 for cmd_pattern in [0x00, np.random.randint(0, 256, size=max_cmd_byte_size).tolist(), 0xFF]: - for cmd_size in [0, 1, 2, np.random.randint(3, max_cmd_size - 1), max_cmd_size - 1, max_cmd_size]: # 0 will prevent writing command + for cmd_size in [ + 0, + 1, + 2, + np.random.randint(3, max_cmd_size - 1), + max_cmd_size - 1, + max_cmd_size, + ]: # 0 will prevent writing command # cmd_size of 0 will not start cmd_seq for cmd_repeat in [1, 2, 3]: # when cmd_repeat is 0 -> infinite loop if isinstance(cmd_pattern, list): write_cmd_pattern = list(cmd_pattern) # copy - write_cmd_pattern.extend(np.random.randint(0, 256, size=max_cmd_byte_size - len(write_cmd_pattern))) - self.chip['CMD_SEQ'].set_data(data=write_cmd_pattern, addr=0) + write_cmd_pattern.extend( + np.random.randint(0, 256, size=max_cmd_byte_size - len(write_cmd_pattern)) + ) + self.chip["CMD_SEQ"].set_data(data=write_cmd_pattern, addr=0) else: write_cmd_pattern = [cmd_pattern] * max_cmd_byte_size - self.chip['CMD_SEQ'].set_data(data=write_cmd_pattern, addr=0) - self.chip['CMD_SEQ']['CMD_SIZE'] = cmd_size - self.chip['CMD_SEQ']['CMD_REPEAT'] = cmd_repeat + self.chip["CMD_SEQ"].set_data(data=write_cmd_pattern, addr=0) + self.chip["CMD_SEQ"]["CMD_SIZE"] = cmd_size + self.chip["CMD_SEQ"]["CMD_REPEAT"] = cmd_repeat rec_size = cmd_size * cmd_repeat + rec_add_size - self.chip['SEQ_REC']['SIZE'] = rec_size - self.chip['PULSE_GEN']['START'] + self.chip["SEQ_REC"]["SIZE"] = rec_size + self.chip["PULSE_GEN"]["START"] - while not self.chip['CMD_SEQ']['READY']: + while not self.chip["CMD_SEQ"]["READY"]: pass - while not self.chip['SEQ_REC']['READY']: + while not self.chip["SEQ_REC"]["READY"]: pass - ret = self.chip['SEQ_REC'].get_data(size=rec_size) + ret = self.chip["SEQ_REC"].get_data(size=rec_size) expected_arr = np.array(write_cmd_pattern, dtype=np.uint8) expected_bits = np.unpackbits(expected_arr).flatten()[:cmd_size] expected_bits = np.tile(expected_bits, cmd_repeat) @@ -139,46 +148,57 @@ def test_start_sequnce(self): if isinstance(cmd_pattern, list): write_cmd_pattern = list(cmd_pattern) # copy write_cmd_pattern.extend(np.random.randint(0, 256, size=max_cmd_byte_size - len(write_cmd_pattern))) - self.chip['CMD_SEQ'].set_data(data=write_cmd_pattern, addr=0) + self.chip["CMD_SEQ"].set_data(data=write_cmd_pattern, addr=0) else: write_cmd_pattern = [cmd_pattern] * max_cmd_byte_size - self.chip['CMD_SEQ'].set_data(data=write_cmd_pattern, addr=0) + self.chip["CMD_SEQ"].set_data(data=write_cmd_pattern, addr=0) - self.chip['CMD_SEQ']['OUTPUT_MODE'] = 0 - self.chip['CMD_SEQ']['OUTPUT_ENABLE'] = 0x01 - self.chip['SEQ_REC']['EN_EXT_START'] = 1 - self.chip['CMD_SEQ']['EN_EXT_TRIGGER'] = 1 - self.chip['PULSE_GEN']['DELAY'] = 1 - self.chip['PULSE_GEN']['WIDTH'] = 1 + self.chip["CMD_SEQ"]["OUTPUT_MODE"] = 0 + self.chip["CMD_SEQ"]["OUTPUT_ENABLE"] = 0x01 + self.chip["SEQ_REC"]["EN_EXT_START"] = 1 + self.chip["CMD_SEQ"]["EN_EXT_TRIGGER"] = 1 + self.chip["PULSE_GEN"]["DELAY"] = 1 + self.chip["PULSE_GEN"]["WIDTH"] = 1 for cmd_size in [1, 2, np.random.randint(3, max_cmd_size - 1), max_cmd_size - 1, max_cmd_size]: # cmd_size of 0 will not start cmd_seq for cmd_repeat in [1, 2, 3]: # when cmd_repeat is 0 -> infinite loop - for cmd_start_sequnce_length in [0, 1, np.random.randint(1, cmd_size + 2), cmd_size - 1, cmd_size, cmd_size + 1]: + for cmd_start_sequnce_length in [ + 0, + 1, + np.random.randint(1, cmd_size + 2), + cmd_size - 1, + cmd_size, + cmd_size + 1, + ]: # if cmd_start_sequnce_length > cmd_size, cmd_seq will not start - self.chip['CMD_SEQ']['CMD_SIZE'] = cmd_size - self.chip['CMD_SEQ']['CMD_REPEAT'] = cmd_repeat - self.chip['CMD_SEQ']['START_SEQUENCE_LENGTH'] = cmd_start_sequnce_length - self.chip['CMD_SEQ']['STOP_SEQUENCE_LENGTH'] = 0 + self.chip["CMD_SEQ"]["CMD_SIZE"] = cmd_size + self.chip["CMD_SEQ"]["CMD_REPEAT"] = cmd_repeat + self.chip["CMD_SEQ"]["START_SEQUENCE_LENGTH"] = cmd_start_sequnce_length + self.chip["CMD_SEQ"]["STOP_SEQUENCE_LENGTH"] = 0 if cmd_start_sequnce_length <= cmd_size: - rec_size = cmd_start_sequnce_length + (cmd_size - cmd_start_sequnce_length) * cmd_repeat + rec_add_size + rec_size = ( + cmd_start_sequnce_length + (cmd_size - cmd_start_sequnce_length) * cmd_repeat + rec_add_size + ) else: rec_size = rec_add_size - self.chip['SEQ_REC']['SIZE'] = rec_size - self.chip['PULSE_GEN']['START'] + self.chip["SEQ_REC"]["SIZE"] = rec_size + self.chip["PULSE_GEN"]["START"] - while not self.chip['CMD_SEQ']['READY']: + while not self.chip["CMD_SEQ"]["READY"]: pass - while not self.chip['SEQ_REC']['READY']: + while not self.chip["SEQ_REC"]["READY"]: pass - ret = self.chip['SEQ_REC'].get_data(size=rec_size) + ret = self.chip["SEQ_REC"].get_data(size=rec_size) expected_arr = np.array(write_cmd_pattern, dtype=np.uint8) expected_bits = np.unpackbits(expected_arr).flatten()[:cmd_size] if cmd_start_sequnce_length <= cmd_size: - expected_bits = np.r_[expected_bits, np.tile(expected_bits[cmd_start_sequnce_length:], cmd_repeat - 1)] + expected_bits = np.r_[ + expected_bits, np.tile(expected_bits[cmd_start_sequnce_length:], cmd_repeat - 1) + ] else: expected_bits = np.tile(expected_bits, 0) expected_bits = np.r_[expected_bits, [0] * (rec_size - len(expected_bits))] @@ -191,46 +211,65 @@ def test_stop_sequence(self): if isinstance(cmd_pattern, list): write_cmd_pattern = list(cmd_pattern) # copy write_cmd_pattern.extend(np.random.randint(0, 256, size=max_cmd_byte_size - len(write_cmd_pattern))) - self.chip['CMD_SEQ'].set_data(data=write_cmd_pattern, addr=0) + self.chip["CMD_SEQ"].set_data(data=write_cmd_pattern, addr=0) else: write_cmd_pattern = [cmd_pattern] * max_cmd_byte_size - self.chip['CMD_SEQ'].set_data(data=write_cmd_pattern, addr=0) + self.chip["CMD_SEQ"].set_data(data=write_cmd_pattern, addr=0) - self.chip['CMD_SEQ']['OUTPUT_MODE'] = 0 - self.chip['CMD_SEQ']['OUTPUT_ENABLE'] = 0x01 - self.chip['SEQ_REC']['EN_EXT_START'] = 1 - self.chip['CMD_SEQ']['EN_EXT_TRIGGER'] = 1 - self.chip['PULSE_GEN']['DELAY'] = 1 - self.chip['PULSE_GEN']['WIDTH'] = 1 + self.chip["CMD_SEQ"]["OUTPUT_MODE"] = 0 + self.chip["CMD_SEQ"]["OUTPUT_ENABLE"] = 0x01 + self.chip["SEQ_REC"]["EN_EXT_START"] = 1 + self.chip["CMD_SEQ"]["EN_EXT_TRIGGER"] = 1 + self.chip["PULSE_GEN"]["DELAY"] = 1 + self.chip["PULSE_GEN"]["WIDTH"] = 1 for cmd_size in [1, 2, np.random.randint(3, max_cmd_size - 1), max_cmd_size - 1, max_cmd_size]: # cmd_size of 0 will not start cmd_seq for cmd_repeat in [1, 2, 3]: # when cmd_repeat is 0 -> infinite loop - for cmd_stop_sequnce_length in [0, 1, np.random.randint(1, cmd_size + 2), cmd_size - 1, cmd_size, cmd_size + 1]: + for cmd_stop_sequnce_length in [ + 0, + 1, + np.random.randint(1, cmd_size + 2), + cmd_size - 1, + cmd_size, + cmd_size + 1, + ]: # if cmd_stop_sequnce_length > cmd_size, cmd_seq will not start - self.chip['CMD_SEQ']['CMD_SIZE'] = cmd_size - self.chip['CMD_SEQ']['CMD_REPEAT'] = cmd_repeat - self.chip['CMD_SEQ']['START_SEQUENCE_LENGTH'] = 0 - self.chip['CMD_SEQ']['STOP_SEQUENCE_LENGTH'] = cmd_stop_sequnce_length + self.chip["CMD_SEQ"]["CMD_SIZE"] = cmd_size + self.chip["CMD_SEQ"]["CMD_REPEAT"] = cmd_repeat + self.chip["CMD_SEQ"]["START_SEQUENCE_LENGTH"] = 0 + self.chip["CMD_SEQ"]["STOP_SEQUENCE_LENGTH"] = cmd_stop_sequnce_length if cmd_stop_sequnce_length <= cmd_size: - rec_size = (cmd_size - cmd_stop_sequnce_length) * cmd_repeat + cmd_stop_sequnce_length * (cmd_repeat if cmd_stop_sequnce_length == 0 else 1) + rec_add_size + rec_size = ( + (cmd_size - cmd_stop_sequnce_length) * cmd_repeat + + cmd_stop_sequnce_length * (cmd_repeat if cmd_stop_sequnce_length == 0 else 1) + + rec_add_size + ) else: rec_size = rec_add_size - self.chip['SEQ_REC']['SIZE'] = rec_size - self.chip['PULSE_GEN']['START'] + self.chip["SEQ_REC"]["SIZE"] = rec_size + self.chip["PULSE_GEN"]["START"] - while not self.chip['CMD_SEQ']['READY']: + while not self.chip["CMD_SEQ"]["READY"]: pass - while not self.chip['SEQ_REC']['READY']: + while not self.chip["SEQ_REC"]["READY"]: pass - ret = self.chip['SEQ_REC'].get_data(size=rec_size) + ret = self.chip["SEQ_REC"].get_data(size=rec_size) expected_arr = np.array(write_cmd_pattern, dtype=np.uint8) expected_bits = np.unpackbits(expected_arr).flatten()[:cmd_size] if cmd_stop_sequnce_length <= cmd_size: - expected_bits = np.r_[np.tile(expected_bits[:cmd_size if (cmd_stop_sequnce_length == 0) else -cmd_stop_sequnce_length], cmd_repeat), expected_bits[cmd_size if (cmd_stop_sequnce_length == 0) else -cmd_stop_sequnce_length:]] + expected_bits = np.r_[ + np.tile( + expected_bits[ + : cmd_size if (cmd_stop_sequnce_length == 0) else -cmd_stop_sequnce_length + ], + cmd_repeat, + ), + expected_bits[cmd_size if (cmd_stop_sequnce_length == 0) else -cmd_stop_sequnce_length :], + ] else: expected_bits = np.tile(expected_bits, 0) expected_bits = np.r_[expected_bits, [0] * (rec_size - len(expected_bits))] @@ -243,17 +282,17 @@ def test_start_and_stop_sequence(self): if isinstance(cmd_pattern, list): write_cmd_pattern = list(cmd_pattern) # copy write_cmd_pattern.extend(np.random.randint(0, 256, size=max_cmd_byte_size - len(write_cmd_pattern))) - self.chip['CMD_SEQ'].set_data(data=write_cmd_pattern, addr=0) + self.chip["CMD_SEQ"].set_data(data=write_cmd_pattern, addr=0) else: write_cmd_pattern = [cmd_pattern] * max_cmd_byte_size - self.chip['CMD_SEQ'].set_data(data=write_cmd_pattern, addr=0) + self.chip["CMD_SEQ"].set_data(data=write_cmd_pattern, addr=0) - self.chip['CMD_SEQ']['OUTPUT_MODE'] = 0 - self.chip['CMD_SEQ']['OUTPUT_ENABLE'] = 0x01 - self.chip['SEQ_REC']['EN_EXT_START'] = 1 - self.chip['CMD_SEQ']['EN_EXT_TRIGGER'] = 1 - self.chip['PULSE_GEN']['DELAY'] = 1 - self.chip['PULSE_GEN']['WIDTH'] = 1 + self.chip["CMD_SEQ"]["OUTPUT_MODE"] = 0 + self.chip["CMD_SEQ"]["OUTPUT_ENABLE"] = 0x01 + self.chip["SEQ_REC"]["EN_EXT_START"] = 1 + self.chip["CMD_SEQ"]["EN_EXT_TRIGGER"] = 1 + self.chip["PULSE_GEN"]["DELAY"] = 1 + self.chip["PULSE_GEN"]["WIDTH"] = 1 cmd_size = 1 # cmd_size of 0 will not start cmd_seq @@ -262,21 +301,21 @@ def test_start_and_stop_sequence(self): cmd_start_sequnce_length = 1 cmd_stop_sequnce_length = 0 # if cmd_start_sequnce_length + cmd_stop_sequnce_length > cmd_size, cmd_seq will not start - self.chip['CMD_SEQ']['CMD_SIZE'] = cmd_size - self.chip['CMD_SEQ']['CMD_REPEAT'] = cmd_repeat - self.chip['CMD_SEQ']['START_SEQUENCE_LENGTH'] = cmd_start_sequnce_length - self.chip['CMD_SEQ']['STOP_SEQUENCE_LENGTH'] = cmd_stop_sequnce_length + self.chip["CMD_SEQ"]["CMD_SIZE"] = cmd_size + self.chip["CMD_SEQ"]["CMD_REPEAT"] = cmd_repeat + self.chip["CMD_SEQ"]["START_SEQUENCE_LENGTH"] = cmd_start_sequnce_length + self.chip["CMD_SEQ"]["STOP_SEQUENCE_LENGTH"] = cmd_stop_sequnce_length rec_size = 1 + rec_add_size - self.chip['SEQ_REC']['SIZE'] = rec_size - self.chip['PULSE_GEN']['START'] + self.chip["SEQ_REC"]["SIZE"] = rec_size + self.chip["PULSE_GEN"]["START"] - while not self.chip['CMD_SEQ']['READY']: + while not self.chip["CMD_SEQ"]["READY"]: pass - while not self.chip['SEQ_REC']['READY']: + while not self.chip["SEQ_REC"]["READY"]: pass - ret = self.chip['SEQ_REC'].get_data(size=rec_size) + ret = self.chip["SEQ_REC"].get_data(size=rec_size) expected_arr = np.array(write_cmd_pattern, dtype=np.uint8) expected_bits = np.unpackbits(expected_arr).flatten()[:cmd_size] expected_bits = np.r_[expected_bits, [0] * (rec_size - len(expected_bits))] @@ -285,17 +324,17 @@ def test_start_and_stop_sequence(self): cmd_start_sequnce_length = 0 cmd_stop_sequnce_length = 1 - self.chip['CMD_SEQ']['START_SEQUENCE_LENGTH'] = cmd_start_sequnce_length - self.chip['CMD_SEQ']['STOP_SEQUENCE_LENGTH'] = cmd_stop_sequnce_length + self.chip["CMD_SEQ"]["START_SEQUENCE_LENGTH"] = cmd_start_sequnce_length + self.chip["CMD_SEQ"]["STOP_SEQUENCE_LENGTH"] = cmd_stop_sequnce_length - self.chip['PULSE_GEN']['START'] + self.chip["PULSE_GEN"]["START"] - while not self.chip['CMD_SEQ']['READY']: + while not self.chip["CMD_SEQ"]["READY"]: pass - while not self.chip['SEQ_REC']['READY']: + while not self.chip["SEQ_REC"]["READY"]: pass - ret = self.chip['SEQ_REC'].get_data(size=rec_size) + ret = self.chip["SEQ_REC"].get_data(size=rec_size) expected_arr = np.array(write_cmd_pattern, dtype=np.uint8) expected_bits = np.unpackbits(expected_arr).flatten()[:cmd_size] expected_bits = np.r_[expected_bits, [0] * (rec_size - len(expected_bits))] @@ -304,17 +343,17 @@ def test_start_and_stop_sequence(self): cmd_start_sequnce_length = 1 cmd_stop_sequnce_length = 1 - self.chip['CMD_SEQ']['START_SEQUENCE_LENGTH'] = cmd_start_sequnce_length - self.chip['CMD_SEQ']['STOP_SEQUENCE_LENGTH'] = cmd_stop_sequnce_length + self.chip["CMD_SEQ"]["START_SEQUENCE_LENGTH"] = cmd_start_sequnce_length + self.chip["CMD_SEQ"]["STOP_SEQUENCE_LENGTH"] = cmd_stop_sequnce_length - self.chip['PULSE_GEN']['START'] + self.chip["PULSE_GEN"]["START"] - while not self.chip['CMD_SEQ']['READY']: + while not self.chip["CMD_SEQ"]["READY"]: pass - while not self.chip['SEQ_REC']['READY']: + while not self.chip["SEQ_REC"]["READY"]: pass - ret = self.chip['SEQ_REC'].get_data(size=rec_size) + ret = self.chip["SEQ_REC"].get_data(size=rec_size) expected_arr = np.array(write_cmd_pattern, dtype=np.uint8) expected_bits = np.unpackbits(expected_arr).flatten()[:0] expected_bits = np.r_[expected_bits, [0] * (rec_size - len(expected_bits))] @@ -324,18 +363,18 @@ def test_start_and_stop_sequence(self): cmd_repeat = 2 cmd_start_sequnce_length = 1 cmd_stop_sequnce_length = 0 - self.chip['CMD_SEQ']['CMD_REPEAT'] = cmd_repeat - self.chip['CMD_SEQ']['START_SEQUENCE_LENGTH'] = cmd_start_sequnce_length - self.chip['CMD_SEQ']['STOP_SEQUENCE_LENGTH'] = cmd_stop_sequnce_length + self.chip["CMD_SEQ"]["CMD_REPEAT"] = cmd_repeat + self.chip["CMD_SEQ"]["START_SEQUENCE_LENGTH"] = cmd_start_sequnce_length + self.chip["CMD_SEQ"]["STOP_SEQUENCE_LENGTH"] = cmd_stop_sequnce_length - self.chip['PULSE_GEN']['START'] + self.chip["PULSE_GEN"]["START"] - while not self.chip['CMD_SEQ']['READY']: + while not self.chip["CMD_SEQ"]["READY"]: pass - while not self.chip['SEQ_REC']['READY']: + while not self.chip["SEQ_REC"]["READY"]: pass - ret = self.chip['SEQ_REC'].get_data(size=rec_size) + ret = self.chip["SEQ_REC"].get_data(size=rec_size) expected_arr = np.array(write_cmd_pattern, dtype=np.uint8) expected_bits = np.unpackbits(expected_arr).flatten()[:cmd_size] expected_bits = np.r_[expected_bits, [0] * (rec_size - len(expected_bits))] @@ -344,17 +383,17 @@ def test_start_and_stop_sequence(self): cmd_start_sequnce_length = 0 cmd_stop_sequnce_length = 1 - self.chip['CMD_SEQ']['START_SEQUENCE_LENGTH'] = cmd_start_sequnce_length - self.chip['CMD_SEQ']['STOP_SEQUENCE_LENGTH'] = cmd_stop_sequnce_length + self.chip["CMD_SEQ"]["START_SEQUENCE_LENGTH"] = cmd_start_sequnce_length + self.chip["CMD_SEQ"]["STOP_SEQUENCE_LENGTH"] = cmd_stop_sequnce_length - self.chip['PULSE_GEN']['START'] + self.chip["PULSE_GEN"]["START"] - while not self.chip['CMD_SEQ']['READY']: + while not self.chip["CMD_SEQ"]["READY"]: pass - while not self.chip['SEQ_REC']['READY']: + while not self.chip["SEQ_REC"]["READY"]: pass - ret = self.chip['SEQ_REC'].get_data(size=rec_size) + ret = self.chip["SEQ_REC"].get_data(size=rec_size) expected_arr = np.array(write_cmd_pattern, dtype=np.uint8) expected_bits = np.unpackbits(expected_arr).flatten()[:cmd_size] expected_bits = np.r_[expected_bits, [0] * (rec_size - len(expected_bits))] @@ -363,17 +402,17 @@ def test_start_and_stop_sequence(self): cmd_start_sequnce_length = 1 cmd_stop_sequnce_length = 1 - self.chip['CMD_SEQ']['START_SEQUENCE_LENGTH'] = cmd_start_sequnce_length - self.chip['CMD_SEQ']['STOP_SEQUENCE_LENGTH'] = cmd_stop_sequnce_length + self.chip["CMD_SEQ"]["START_SEQUENCE_LENGTH"] = cmd_start_sequnce_length + self.chip["CMD_SEQ"]["STOP_SEQUENCE_LENGTH"] = cmd_stop_sequnce_length - self.chip['PULSE_GEN']['START'] + self.chip["PULSE_GEN"]["START"] - while not self.chip['CMD_SEQ']['READY']: + while not self.chip["CMD_SEQ"]["READY"]: pass - while not self.chip['SEQ_REC']['READY']: + while not self.chip["SEQ_REC"]["READY"]: pass - ret = self.chip['SEQ_REC'].get_data(size=rec_size) + ret = self.chip["SEQ_REC"].get_data(size=rec_size) expected_arr = np.array(write_cmd_pattern, dtype=np.uint8) expected_bits = np.unpackbits(expected_arr).flatten()[:0] expected_bits = np.r_[expected_bits, [0] * (rec_size - len(expected_bits))] @@ -384,21 +423,21 @@ def test_start_and_stop_sequence(self): cmd_repeat = 1 cmd_start_sequnce_length = 1 cmd_stop_sequnce_length = 0 - self.chip['CMD_SEQ']['CMD_SIZE'] = cmd_size - self.chip['CMD_SEQ']['CMD_REPEAT'] = cmd_repeat - self.chip['CMD_SEQ']['START_SEQUENCE_LENGTH'] = cmd_start_sequnce_length - self.chip['CMD_SEQ']['STOP_SEQUENCE_LENGTH'] = cmd_stop_sequnce_length + self.chip["CMD_SEQ"]["CMD_SIZE"] = cmd_size + self.chip["CMD_SEQ"]["CMD_REPEAT"] = cmd_repeat + self.chip["CMD_SEQ"]["START_SEQUENCE_LENGTH"] = cmd_start_sequnce_length + self.chip["CMD_SEQ"]["STOP_SEQUENCE_LENGTH"] = cmd_stop_sequnce_length rec_size = 2 + rec_add_size - self.chip['SEQ_REC']['SIZE'] = rec_size - self.chip['PULSE_GEN']['START'] + self.chip["SEQ_REC"]["SIZE"] = rec_size + self.chip["PULSE_GEN"]["START"] - while not self.chip['CMD_SEQ']['READY']: + while not self.chip["CMD_SEQ"]["READY"]: pass - while not self.chip['SEQ_REC']['READY']: + while not self.chip["SEQ_REC"]["READY"]: pass - ret = self.chip['SEQ_REC'].get_data(size=rec_size) + ret = self.chip["SEQ_REC"].get_data(size=rec_size) expected_arr = np.array(write_cmd_pattern, dtype=np.uint8) expected_bits = np.unpackbits(expected_arr).flatten()[:cmd_size] expected_bits = np.r_[expected_bits, [0] * (rec_size - len(expected_bits))] @@ -407,17 +446,17 @@ def test_start_and_stop_sequence(self): cmd_start_sequnce_length = 0 cmd_stop_sequnce_length = 1 - self.chip['CMD_SEQ']['START_SEQUENCE_LENGTH'] = cmd_start_sequnce_length - self.chip['CMD_SEQ']['STOP_SEQUENCE_LENGTH'] = cmd_stop_sequnce_length + self.chip["CMD_SEQ"]["START_SEQUENCE_LENGTH"] = cmd_start_sequnce_length + self.chip["CMD_SEQ"]["STOP_SEQUENCE_LENGTH"] = cmd_stop_sequnce_length - self.chip['PULSE_GEN']['START'] + self.chip["PULSE_GEN"]["START"] - while not self.chip['CMD_SEQ']['READY']: + while not self.chip["CMD_SEQ"]["READY"]: pass - while not self.chip['SEQ_REC']['READY']: + while not self.chip["SEQ_REC"]["READY"]: pass - ret = self.chip['SEQ_REC'].get_data(size=rec_size) + ret = self.chip["SEQ_REC"].get_data(size=rec_size) expected_arr = np.array(write_cmd_pattern, dtype=np.uint8) expected_bits = np.unpackbits(expected_arr).flatten()[:cmd_size] expected_bits = np.r_[expected_bits, [0] * (rec_size - len(expected_bits))] @@ -426,17 +465,17 @@ def test_start_and_stop_sequence(self): cmd_start_sequnce_length = 1 cmd_stop_sequnce_length = 1 - self.chip['CMD_SEQ']['START_SEQUENCE_LENGTH'] = cmd_start_sequnce_length - self.chip['CMD_SEQ']['STOP_SEQUENCE_LENGTH'] = cmd_stop_sequnce_length + self.chip["CMD_SEQ"]["START_SEQUENCE_LENGTH"] = cmd_start_sequnce_length + self.chip["CMD_SEQ"]["STOP_SEQUENCE_LENGTH"] = cmd_stop_sequnce_length - self.chip['PULSE_GEN']['START'] + self.chip["PULSE_GEN"]["START"] - while not self.chip['CMD_SEQ']['READY']: + while not self.chip["CMD_SEQ"]["READY"]: pass - while not self.chip['SEQ_REC']['READY']: + while not self.chip["SEQ_REC"]["READY"]: pass - ret = self.chip['SEQ_REC'].get_data(size=rec_size) + ret = self.chip["SEQ_REC"].get_data(size=rec_size) expected_arr = np.array(write_cmd_pattern, dtype=np.uint8) expected_bits = np.unpackbits(expected_arr).flatten()[:cmd_size] expected_bits = np.r_[expected_bits, [0] * (rec_size - len(expected_bits))] @@ -445,17 +484,17 @@ def test_start_and_stop_sequence(self): cmd_start_sequnce_length = 2 cmd_stop_sequnce_length = 0 - self.chip['CMD_SEQ']['START_SEQUENCE_LENGTH'] = cmd_start_sequnce_length - self.chip['CMD_SEQ']['STOP_SEQUENCE_LENGTH'] = cmd_stop_sequnce_length + self.chip["CMD_SEQ"]["START_SEQUENCE_LENGTH"] = cmd_start_sequnce_length + self.chip["CMD_SEQ"]["STOP_SEQUENCE_LENGTH"] = cmd_stop_sequnce_length - self.chip['PULSE_GEN']['START'] + self.chip["PULSE_GEN"]["START"] - while not self.chip['CMD_SEQ']['READY']: + while not self.chip["CMD_SEQ"]["READY"]: pass - while not self.chip['SEQ_REC']['READY']: + while not self.chip["SEQ_REC"]["READY"]: pass - ret = self.chip['SEQ_REC'].get_data(size=rec_size) + ret = self.chip["SEQ_REC"].get_data(size=rec_size) expected_arr = np.array(write_cmd_pattern, dtype=np.uint8) expected_bits = np.unpackbits(expected_arr).flatten()[:cmd_size] expected_bits = np.r_[expected_bits, [0] * (rec_size - len(expected_bits))] @@ -464,17 +503,17 @@ def test_start_and_stop_sequence(self): cmd_start_sequnce_length = 0 cmd_stop_sequnce_length = 2 - self.chip['CMD_SEQ']['START_SEQUENCE_LENGTH'] = cmd_start_sequnce_length - self.chip['CMD_SEQ']['STOP_SEQUENCE_LENGTH'] = cmd_stop_sequnce_length + self.chip["CMD_SEQ"]["START_SEQUENCE_LENGTH"] = cmd_start_sequnce_length + self.chip["CMD_SEQ"]["STOP_SEQUENCE_LENGTH"] = cmd_stop_sequnce_length - self.chip['PULSE_GEN']['START'] + self.chip["PULSE_GEN"]["START"] - while not self.chip['CMD_SEQ']['READY']: + while not self.chip["CMD_SEQ"]["READY"]: pass - while not self.chip['SEQ_REC']['READY']: + while not self.chip["SEQ_REC"]["READY"]: pass - ret = self.chip['SEQ_REC'].get_data(size=rec_size) + ret = self.chip["SEQ_REC"].get_data(size=rec_size) expected_arr = np.array(write_cmd_pattern, dtype=np.uint8) expected_bits = np.unpackbits(expected_arr).flatten()[:cmd_size] expected_bits = np.r_[expected_bits, [0] * (rec_size - len(expected_bits))] @@ -483,17 +522,17 @@ def test_start_and_stop_sequence(self): cmd_start_sequnce_length = 2 cmd_stop_sequnce_length = 1 - self.chip['CMD_SEQ']['START_SEQUENCE_LENGTH'] = cmd_start_sequnce_length - self.chip['CMD_SEQ']['STOP_SEQUENCE_LENGTH'] = cmd_stop_sequnce_length + self.chip["CMD_SEQ"]["START_SEQUENCE_LENGTH"] = cmd_start_sequnce_length + self.chip["CMD_SEQ"]["STOP_SEQUENCE_LENGTH"] = cmd_stop_sequnce_length - self.chip['PULSE_GEN']['START'] + self.chip["PULSE_GEN"]["START"] - while not self.chip['CMD_SEQ']['READY']: + while not self.chip["CMD_SEQ"]["READY"]: pass - while not self.chip['SEQ_REC']['READY']: + while not self.chip["SEQ_REC"]["READY"]: pass - ret = self.chip['SEQ_REC'].get_data(size=rec_size) + ret = self.chip["SEQ_REC"].get_data(size=rec_size) expected_arr = np.array(write_cmd_pattern, dtype=np.uint8) expected_bits = np.unpackbits(expected_arr).flatten()[:0] expected_bits = np.r_[expected_bits, [0] * (rec_size - len(expected_bits))] @@ -502,17 +541,17 @@ def test_start_and_stop_sequence(self): cmd_start_sequnce_length = 1 cmd_stop_sequnce_length = 2 - self.chip['CMD_SEQ']['START_SEQUENCE_LENGTH'] = cmd_start_sequnce_length - self.chip['CMD_SEQ']['STOP_SEQUENCE_LENGTH'] = cmd_stop_sequnce_length + self.chip["CMD_SEQ"]["START_SEQUENCE_LENGTH"] = cmd_start_sequnce_length + self.chip["CMD_SEQ"]["STOP_SEQUENCE_LENGTH"] = cmd_stop_sequnce_length - self.chip['PULSE_GEN']['START'] + self.chip["PULSE_GEN"]["START"] - while not self.chip['CMD_SEQ']['READY']: + while not self.chip["CMD_SEQ"]["READY"]: pass - while not self.chip['SEQ_REC']['READY']: + while not self.chip["SEQ_REC"]["READY"]: pass - ret = self.chip['SEQ_REC'].get_data(size=rec_size) + ret = self.chip["SEQ_REC"].get_data(size=rec_size) expected_arr = np.array(write_cmd_pattern, dtype=np.uint8) expected_bits = np.unpackbits(expected_arr).flatten()[:0] expected_bits = np.r_[expected_bits, [0] * (rec_size - len(expected_bits))] @@ -526,26 +565,43 @@ def test_start_and_stop_sequence(self): # when cmd_repeat is 0 -> infinite loop cmd_start_sequnce_length = np.random.randint(0, cmd_size + 1) cmd_stop_sequnce_length = np.random.randint(0, cmd_size - cmd_start_sequnce_length + 1) - self.chip['CMD_SEQ']['CMD_SIZE'] = cmd_size - self.chip['CMD_SEQ']['CMD_REPEAT'] = cmd_repeat - self.chip['CMD_SEQ']['START_SEQUENCE_LENGTH'] = cmd_start_sequnce_length - self.chip['CMD_SEQ']['STOP_SEQUENCE_LENGTH'] = cmd_stop_sequnce_length - - rec_size = cmd_start_sequnce_length + (cmd_size - cmd_stop_sequnce_length - cmd_start_sequnce_length) * cmd_repeat + cmd_stop_sequnce_length + rec_add_size - self.chip['SEQ_REC']['SIZE'] = rec_size - self.chip['PULSE_GEN']['START'] - - while not self.chip['CMD_SEQ']['READY']: + self.chip["CMD_SEQ"]["CMD_SIZE"] = cmd_size + self.chip["CMD_SEQ"]["CMD_REPEAT"] = cmd_repeat + self.chip["CMD_SEQ"]["START_SEQUENCE_LENGTH"] = cmd_start_sequnce_length + self.chip["CMD_SEQ"]["STOP_SEQUENCE_LENGTH"] = cmd_stop_sequnce_length + + rec_size = ( + cmd_start_sequnce_length + + (cmd_size - cmd_stop_sequnce_length - cmd_start_sequnce_length) * cmd_repeat + + cmd_stop_sequnce_length + + rec_add_size + ) + self.chip["SEQ_REC"]["SIZE"] = rec_size + self.chip["PULSE_GEN"]["START"] + + while not self.chip["CMD_SEQ"]["READY"]: pass - while not self.chip['SEQ_REC']['READY']: + while not self.chip["SEQ_REC"]["READY"]: pass - ret = self.chip['SEQ_REC'].get_data(size=rec_size) + ret = self.chip["SEQ_REC"].get_data(size=rec_size) expected_arr = np.array(write_cmd_pattern, dtype=np.uint8) cmd_bits = np.unpackbits(expected_arr).flatten()[:cmd_size] expected_bits = np.r_[cmd_bits[:cmd_start_sequnce_length]] - expected_bits = np.r_[expected_bits, np.tile(cmd_bits[cmd_start_sequnce_length:cmd_size if (cmd_stop_sequnce_length == 0) else -cmd_stop_sequnce_length], cmd_repeat)] - expected_bits = np.r_[expected_bits, cmd_bits[cmd_size if (cmd_stop_sequnce_length == 0) else -cmd_stop_sequnce_length:]] + expected_bits = np.r_[ + expected_bits, + np.tile( + cmd_bits[ + cmd_start_sequnce_length : cmd_size + if (cmd_stop_sequnce_length == 0) + else -cmd_stop_sequnce_length + ], + cmd_repeat, + ), + ] + expected_bits = np.r_[ + expected_bits, cmd_bits[cmd_size if (cmd_stop_sequnce_length == 0) else -cmd_stop_sequnce_length :] + ] expected_bits = np.r_[expected_bits, [0] * (rec_size - len(expected_bits))] np.testing.assert_array_equal(ret, expected_bits) # self.assertListEqual(ret.tolist(), expected_bits.tolist()) @@ -555,5 +611,5 @@ def tearDown(self): cocotb_compile_clean() -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/tests/test_SimFifo8to32.py b/tests/test_SimFifo8to32.py index 5cc04c255..7164c10b2 100644 --- a/tests/test_SimFifo8to32.py +++ b/tests/test_SimFifo8to32.py @@ -5,14 +5,14 @@ # ------------------------------------------------------------ # +import os import unittest + import pytest -import os from basil.dut import Dut from basil.utils.sim.utils import cocotb_compile_and_run, cocotb_compile_clean - cnfg_yaml = """ transfer_layer: - name : INTF @@ -31,26 +31,30 @@ class TestSimFifo8to32(unittest.TestCase): - def __init__(self, testname, tb='test_SimFifo8to32.v', bus_drv='basil.utils.sim.BasilBusDriver', bus_split=False): + def __init__(self, testname, tb="test_SimFifo8to32.v", bus_drv="basil.utils.sim.BasilBusDriver", bus_split=False): super(TestSimFifo8to32, self).__init__(testname) self._test_tb = tb self._sim_bus = bus_drv self._bus_split_def = () if bus_split is not False: - if bus_split == 'sbus': + if bus_split == "sbus": self._bus_split_def = ("BASIL_SBUS",) - elif bus_split == 'top': + elif bus_split == "top": self._bus_split_def = ("BASIL_TOPSBUS",) def setUp(self): - cocotb_compile_and_run(sim_files=[os.path.join(os.path.dirname(__file__), self._test_tb)], sim_bus=self._sim_bus, extra_defines=self._bus_split_def) + cocotb_compile_and_run( + sim_files=[os.path.join(os.path.dirname(__file__), self._test_tb)], + sim_bus=self._sim_bus, + extra_defines=self._bus_split_def, + ) self.chip = Dut(cnfg_yaml) self.chip.init() def test_io(self): for i in range(4): - self.chip['INTF'].write(0x1000, [i]) + self.chip["INTF"].write(0x1000, [i]) data = [] iterations = 1000 @@ -58,11 +62,11 @@ def test_io(self): while not len(data) == 1: if i >= iterations: break - data.extend(self.chip['FIFO'].get_data()) + data.extend(self.chip["FIFO"].get_data()) i += 1 assert data[0] == 50462976 - self.chip['INTF'].write(0x1000, [4, 5, 6, 7]) + self.chip["INTF"].write(0x1000, [4, 5, 6, 7]) data = [] iterations = 1000 @@ -70,11 +74,11 @@ def test_io(self): while not len(data) == 1: if i >= iterations: break - data.extend(self.chip['FIFO'].get_data()) + data.extend(self.chip["FIFO"].get_data()) i += 1 assert data[0] == 117835012 - self.chip['INTF'].write(0x1000, range(8)) + self.chip["INTF"].write(0x1000, range(8)) data = [] iterations = 1000 @@ -82,7 +86,7 @@ def test_io(self): while not len(data) == 2: if i >= iterations: break - data.extend(self.chip['FIFO'].get_data()) + data.extend(self.chip["FIFO"].get_data()) i += 1 assert data[0] == 50462976 assert data[1] == 117835012 @@ -102,8 +106,10 @@ def tearDown(self): @pytest.mark.verilator class TestSimFifo8to32SbusTop(TestSimFifo8to32): def __init__(self, testname): - super(TestSimFifo8to32SbusTop, self).__init__(testname=testname, tb='test_SimFifo8to32.v', bus_drv='basil.utils.sim.BasilSbusDriver', bus_split='top') + super(TestSimFifo8to32SbusTop, self).__init__( + testname=testname, tb="test_SimFifo8to32.v", bus_drv="basil.utils.sim.BasilSbusDriver", bus_split="top" + ) -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/tests/test_SimGpio.py b/tests/test_SimGpio.py index 4137ff150..c794f6a55 100644 --- a/tests/test_SimGpio.py +++ b/tests/test_SimGpio.py @@ -5,14 +5,14 @@ # ------------------------------------------------------------ # +import os import unittest + import pytest -import os from basil.dut import Dut from basil.utils.sim.utils import cocotb_compile_and_run, cocotb_compile_clean - cnfg_yaml = """ transfer_layer: - name : INTF @@ -56,45 +56,48 @@ class TestSimGpio(unittest.TestCase): - def __init__(self, testname, tb='test_SimGpio.v', bus_drv='basil.utils.sim.BasilBusDriver', bus_split=False): + def __init__(self, testname, tb="test_SimGpio.v", bus_drv="basil.utils.sim.BasilBusDriver", bus_split=False): super(TestSimGpio, self).__init__(testname) self._test_tb = tb self._sim_bus = bus_drv self._bus_split_def = () if bus_split is not False: - if bus_split == 'sbus': + if bus_split == "sbus": self._bus_split_def = ("BASIL_SBUS",) - elif bus_split == 'top': + elif bus_split == "top": self._bus_split_def = ("BASIL_TOPSBUS",) def setUp(self): - cocotb_compile_and_run(sim_files=[os.path.join(os.path.dirname(__file__), self._test_tb)], sim_bus=self._sim_bus, extra_defines=self._bus_split_def) + cocotb_compile_and_run( + sim_files=[os.path.join(os.path.dirname(__file__), self._test_tb)], + sim_bus=self._sim_bus, + extra_defines=self._bus_split_def, + ) self.chip = Dut(cnfg_yaml) self.chip.init() def test_io(self): - self.chip['GPIO'].set_output_en([0xff, 0, 0]) # to remove 'z in simulation + self.chip["GPIO"].set_output_en([0xFF, 0, 0]) # to remove 'z in simulation - ret = self.chip['GPIO'].get_data() + ret = self.chip["GPIO"].get_data() self.assertEqual([0, 0, 0], ret) - self.chip['GPIO'].set_output_en([0x0f, 0, 0]) - self.chip['GPIO'].set_data([0xe3, 0xfa, 0x5a]) - ret = self.chip['GPIO'].get_data() - self.assertEqual([0x33, 0x5a, 0x5a], ret) - ret = self.chip['GPIO2'].get_data() - self.assertEqual([0xa5, 0xcd], ret) + self.chip["GPIO"].set_output_en([0x0F, 0, 0]) + self.chip["GPIO"].set_data([0xE3, 0xFA, 0x5A]) + ret = self.chip["GPIO"].get_data() + self.assertEqual([0x33, 0x5A, 0x5A], ret) + ret = self.chip["GPIO2"].get_data() + self.assertEqual([0xA5, 0xCD], ret) def test_io_register(self): + self.chip["GPIO"].set_output_en([0xFF, 0, 0]) # to remove 'z in simulation - self.chip['GPIO'].set_output_en([0xff, 0, 0]) # to remove 'z in simulation - - self.chip['GPIO']['OUT'] = 0xa5 + self.chip["GPIO"]["OUT"] = 0xA5 - self.chip['GPIO'].write() - ret = self.chip['GPIO'].get_data() - self.assertEqual([0, 0xa5, 0xa5], ret) + self.chip["GPIO"].write() + ret = self.chip["GPIO"].get_data() + self.assertEqual([0, 0xA5, 0xA5], ret) # TODO: Add register readback and comparison def tearDown(self): @@ -105,14 +108,18 @@ def tearDown(self): @pytest.mark.verilator class TestSimGpioSbus(TestSimGpio): def __init__(self, testname): - super(TestSimGpioSbus, self).__init__(testname=testname, tb='test_SimGpio.v', bus_drv='basil.utils.sim.BasilSbusDriver', bus_split='sbus') + super(TestSimGpioSbus, self).__init__( + testname=testname, tb="test_SimGpio.v", bus_drv="basil.utils.sim.BasilSbusDriver", bus_split="sbus" + ) @pytest.mark.verilator class TestSimGpioSbusTop(TestSimGpio): def __init__(self, testname): - super(TestSimGpioSbusTop, self).__init__(testname=testname, tb='test_SimGpio.v', bus_drv='basil.utils.sim.BasilSbusDriver', bus_split='top') + super(TestSimGpioSbusTop, self).__init__( + testname=testname, tb="test_SimGpio.v", bus_drv="basil.utils.sim.BasilSbusDriver", bus_split="top" + ) -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/tests/test_SimI2c.py b/tests/test_SimI2c.py index c93cbccff..6ae0b723a 100644 --- a/tests/test_SimI2c.py +++ b/tests/test_SimI2c.py @@ -5,8 +5,8 @@ # ------------------------------------------------------------ # -import unittest import os +import unittest from basil.dut import Dut from basil.utils.sim.utils import cocotb_compile_and_run, cocotb_compile_clean @@ -41,34 +41,34 @@ class TestSimS2C(unittest.TestCase): def setUp(self): - cocotb_compile_and_run([os.path.join(os.path.dirname(__file__), 'test_SimI2c.v')]) + cocotb_compile_and_run([os.path.join(os.path.dirname(__file__), "test_SimI2c.v")]) self.chip = Dut(cnfg_yaml) self.chip.init() def test_i2c(self): - data = [0x85, 0x81, 0xa5, 0x91] - self.chip['i2c'].write(0x92, data) + data = [0x85, 0x81, 0xA5, 0x91] + self.chip["i2c"].write(0x92, data) - ret = self.chip['i2c'].get_data(4) + ret = self.chip["i2c"].get_data(4) self.assertEqual(ret.tolist(), data) - self.chip['i2c'].write(0x92, data[0:1]) + self.chip["i2c"].write(0x92, data[0:1]) - self.chip['i2c'].set_data([0, 1, 2, 3]) + self.chip["i2c"].set_data([0, 1, 2, 3]) - ret = self.chip['i2c'].read(0x92, 3) + ret = self.chip["i2c"].read(0x92, 3) self.assertEqual(ret.tolist(), data[1:]) - self.chip['i2c'].write(0x92, range(16)) - self.chip['i2c'].write(0x92, [0]) - ret = self.chip['i2c'].read(0x92, 15) + self.chip["i2c"].write(0x92, range(16)) + self.chip["i2c"].write(0x92, [0]) + ret = self.chip["i2c"].read(0x92, 15) self.assertEqual(ret.tolist(), list(range(16))[1:]) # no ack/no such device exept = False try: - self.chip['i2c'].write(0x55, data) + self.chip["i2c"].write(0x55, data) except IOError: exept = True @@ -79,5 +79,5 @@ def tearDown(self): cocotb_compile_clean() -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/tests/test_SimJtagGpio.py b/tests/test_SimJtagGpio.py index 0b0043005..3b54f2ae7 100644 --- a/tests/test_SimJtagGpio.py +++ b/tests/test_SimJtagGpio.py @@ -5,14 +5,15 @@ # ------------------------------------------------------------ # -import unittest import os +import unittest + import yaml from basil.dut import Dut -from basil.utils.sim.utils import cocotb_compile_and_run, cocotb_compile_clean -from basil.utils.BitLogic import BitLogic from basil.RL.StdRegister import StdRegister +from basil.utils.BitLogic import BitLogic +from basil.utils.sim.utils import cocotb_compile_and_run, cocotb_compile_clean cnfg_yaml = """ transfer_layer: @@ -158,115 +159,116 @@ class TestSimJtagGpio(unittest.TestCase): def setUp(self): - cocotb_compile_and_run([ - os.path.join(os.path.dirname(__file__), 'jtag_tap.v'), - os.path.join(os.path.dirname(__file__), 'test_SimJtagGpio.v')] + cocotb_compile_and_run( + [ + os.path.join(os.path.dirname(__file__), "jtag_tap.v"), + os.path.join(os.path.dirname(__file__), "test_SimJtagGpio.v"), + ] ) self.chip = Dut(cnfg_yaml) self.chip.init(init_yaml) def test_gpio(self): + ID_CODE = BitLogic("0010") + BYPASS = BitLogic("1111") + DEBUG = BitLogic("1000") - ID_CODE = BitLogic('0010') - BYPASS = BitLogic('1111') - DEBUG = BitLogic('1000') - - ret_ir = BitLogic('0101') + ret_ir = BitLogic("0101") # TEST REG INIT dev1ret = StdRegister(driver=None, conf=yaml.safe_load(gpio_yaml)) dev1ret.init() - dev1ret['F1'] = 0x1 - dev1ret['F2'] = 0x2f - dev1ret['F3'] = 0x2 - dev1ret['F4'] = 0x17cf4 - self.assertEqual(dev1ret[:], self.chip['DEV1'][:]) + dev1ret["F1"] = 0x1 + dev1ret["F2"] = 0x2F + dev1ret["F3"] = 0x2 + dev1ret["F4"] = 0x17CF4 + self.assertEqual(dev1ret[:], self.chip["DEV1"][:]) - self.chip['DEV1']['F2'] = 0 - self.assertFalse(dev1ret[:] == self.chip['DEV1'][:]) + self.chip["DEV1"]["F2"] = 0 + self.assertFalse(dev1ret[:] == self.chip["DEV1"][:]) self.chip.set_configuration(init_yaml) - self.assertEqual(dev1ret[:], self.chip['DEV1'][:]) + self.assertEqual(dev1ret[:], self.chip["DEV1"][:]) - self.chip['JTAG'].reset() + self.chip["JTAG"].reset() # IR CODE - ret = self.chip['JTAG'].scan_ir([ID_CODE] * 2) + ret = self.chip["JTAG"].scan_ir([ID_CODE] * 2) self.assertEqual(ret, [ret_ir] * 2) # ID CODE - id_code = BitLogic.from_value(0x149B51C3, fmt='I') - ret = self.chip['JTAG'].scan_dr(['0' * 32] * 2) + id_code = BitLogic.from_value(0x149B51C3, fmt="I") + ret = self.chip["JTAG"].scan_dr(["0" * 32] * 2) self.assertEqual(ret, [id_code] * 2) # BYPASS + ID CODE - bypass_code = BitLogic('0') - ret = self.chip['JTAG'].scan_ir([ID_CODE, BYPASS]) + bypass_code = BitLogic("0") + ret = self.chip["JTAG"].scan_ir([ID_CODE, BYPASS]) self.assertEqual(ret, [ret_ir] * 2) - ret = self.chip['JTAG'].scan_dr(['0' * 32, '1']) + ret = self.chip["JTAG"].scan_dr(["0" * 32, "1"]) self.assertEqual(ret, [id_code, bypass_code]) - ret = self.chip['JTAG'].scan_ir([BYPASS, ID_CODE]) + ret = self.chip["JTAG"].scan_ir([BYPASS, ID_CODE]) self.assertEqual(ret, [ret_ir] * 2) - ret = self.chip['JTAG'].scan_dr(['1', '0' * 32]) + ret = self.chip["JTAG"].scan_dr(["1", "0" * 32]) self.assertEqual(ret, [bypass_code, id_code]) # DEBUG - ret = self.chip['JTAG'].scan_ir([DEBUG, DEBUG]) + ret = self.chip["JTAG"].scan_ir([DEBUG, DEBUG]) self.assertEqual(ret, [ret_ir] * 2) - self.chip['JTAG'].scan_dr(['1' * 32, '0' * 1 + '1' * 30 + '0' * 1]) - ret = self.chip['JTAG'].scan_dr(['0' * 32, '1' * 32]) - self.assertEqual(ret, [BitLogic('1' * 32), BitLogic('0' * 1 + '1' * 30 + '0' * 1)]) - ret = self.chip['JTAG'].scan_dr(['0' * 32, '0' * 32]) - self.assertEqual(ret, [BitLogic('0' * 32), BitLogic('1' * 32)]) + self.chip["JTAG"].scan_dr(["1" * 32, "0" * 1 + "1" * 30 + "0" * 1]) + ret = self.chip["JTAG"].scan_dr(["0" * 32, "1" * 32]) + self.assertEqual(ret, [BitLogic("1" * 32), BitLogic("0" * 1 + "1" * 30 + "0" * 1)]) + ret = self.chip["JTAG"].scan_dr(["0" * 32, "0" * 32]) + self.assertEqual(ret, [BitLogic("0" * 32), BitLogic("1" * 32)]) # SHIT IN DEV REG/DEBUG - self.chip['JTAG'].scan_dr([self.chip['DEV1'][:], self.chip['DEV2'][:]]) + self.chip["JTAG"].scan_dr([self.chip["DEV1"][:], self.chip["DEV2"][:]]) # GPIO RETURN - dev1ret.frombytes(self.chip['GPIO_DEV1'].get_data()) - self.assertEqual(dev1ret[:], self.chip['DEV1'][:]) + dev1ret.frombytes(self.chip["GPIO_DEV1"].get_data()) + self.assertEqual(dev1ret[:], self.chip["DEV1"][:]) - self.assertFalse(dev1ret[:] == self.chip['DEV2'][:]) - dev1ret.frombytes(self.chip['GPIO_DEV2'].get_data()) - self.assertEqual(dev1ret[:], self.chip['DEV2'][:]) + self.assertFalse(dev1ret[:] == self.chip["DEV2"][:]) + dev1ret.frombytes(self.chip["GPIO_DEV2"].get_data()) + self.assertEqual(dev1ret[:], self.chip["DEV2"][:]) # JTAG RETURN - ret = self.chip['JTAG'].scan_dr(['0' * 32, '0' * 32]) + ret = self.chip["JTAG"].scan_dr(["0" * 32, "0" * 32]) dev1ret.set(ret[0]) - self.assertEqual(dev1ret[:], self.chip['DEV1'][:]) + self.assertEqual(dev1ret[:], self.chip["DEV1"][:]) dev1ret.set(ret[1]) - self.assertEqual(dev1ret[:], self.chip['DEV2'][:]) + self.assertEqual(dev1ret[:], self.chip["DEV2"][:]) # REPEATING REGISTER - self.chip['JTAG'].scan_dr([self.chip['DEV'][:]]) - ret1 = self.chip['JTAG'].scan_dr([self.chip['DEV'][:]]) - self.chip['JTAG'].scan_dr([self.chip['DEV1'][:], self.chip['DEV2'][:]]) - ret2 = self.chip['JTAG'].scan_dr([self.chip['DEV1'][:] + self.chip['DEV2'][:]]) - ret3 = self.chip['JTAG'].scan_dr([self.chip['DEV1'][:] + self.chip['DEV2'][:]]) + self.chip["JTAG"].scan_dr([self.chip["DEV"][:]]) + ret1 = self.chip["JTAG"].scan_dr([self.chip["DEV"][:]]) + self.chip["JTAG"].scan_dr([self.chip["DEV1"][:], self.chip["DEV2"][:]]) + ret2 = self.chip["JTAG"].scan_dr([self.chip["DEV1"][:] + self.chip["DEV2"][:]]) + ret3 = self.chip["JTAG"].scan_dr([self.chip["DEV1"][:] + self.chip["DEV2"][:]]) self.assertEqual(ret1[:], ret2[:]) self.assertEqual(ret2[:], ret3[:]) # REPEATING SETTING - self.chip['JTAG'].scan_dr(['1' * 32 + '0' * 32]) - ret = self.chip['JTAG'].scan_dr(['0' * 32 + '0' * 32]) + self.chip["JTAG"].scan_dr(["1" * 32 + "0" * 32]) + ret = self.chip["JTAG"].scan_dr(["0" * 32 + "0" * 32]) - self.chip['DEV'].set(ret[0]) - self.assertEqual(self.chip['DEV'][:], BitLogic('0' * 32 + '1' * 32)) + self.chip["DEV"].set(ret[0]) + self.assertEqual(self.chip["DEV"][:], BitLogic("0" * 32 + "1" * 32)) - self.chip['JTAG'].scan_dr([self.chip['DEV1'][:] + self.chip['DEV2'][:]]) - ret = self.chip['JTAG'].scan_dr([self.chip['DEV1'][:] + self.chip['DEV2'][:]]) + self.chip["JTAG"].scan_dr([self.chip["DEV1"][:] + self.chip["DEV2"][:]]) + ret = self.chip["JTAG"].scan_dr([self.chip["DEV1"][:] + self.chip["DEV2"][:]]) - self.chip['DEV'].set(ret[0]) - self.assertEqual(self.chip['DEV'][:], self.chip['DEV1'][:] + self.chip['DEV2'][:]) + self.chip["DEV"].set(ret[0]) + self.assertEqual(self.chip["DEV"][:], self.chip["DEV1"][:] + self.chip["DEV2"][:]) def tearDown(self): self.chip.close() # let it close connection and stop simulator cocotb_compile_clean() -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/tests/test_SimJtagMaster.py b/tests/test_SimJtagMaster.py index 2b75a0264..ae7773e42 100644 --- a/tests/test_SimJtagMaster.py +++ b/tests/test_SimJtagMaster.py @@ -5,15 +5,16 @@ # ------------------------------------------------------------ # -import unittest import os -import yaml +import unittest + import numpy as np +import yaml from basil.dut import Dut -from basil.utils.sim.utils import cocotb_compile_and_run, cocotb_compile_clean -from basil.utils.BitLogic import BitLogic from basil.RL.StdRegister import StdRegister +from basil.utils.BitLogic import BitLogic +from basil.utils.sim.utils import cocotb_compile_and_run, cocotb_compile_clean cnfg_yaml = """ transfer_layer: @@ -228,7 +229,6 @@ def jtag_master_FSM_tests(self): pass def jtag_tests(self): - ID_CODE_STR = "0010" ID_CODE = BitLogic(ID_CODE_STR) BYPASS = BitLogic("1111") diff --git a/tests/test_SimM26.py b/tests/test_SimM26.py index 9b5297b14..bf0068403 100644 --- a/tests/test_SimM26.py +++ b/tests/test_SimM26.py @@ -5,15 +5,14 @@ # ------------------------------------------------------------ # -import unittest import os +import unittest import numpy as np from basil.dut import Dut -from basil.utils.sim.utils import cocotb_compile_and_run, cocotb_compile_clean from basil.utils.BitLogic import BitLogic - +from basil.utils.sim.utils import cocotb_compile_and_run, cocotb_compile_clean cnfg_yaml = """ transfer_layer: @@ -60,89 +59,88 @@ class TestSimM26(unittest.TestCase): def setUp(self): - cocotb_compile_and_run([os.path.join(os.path.dirname(__file__), 'test_SimM26.v')]) + cocotb_compile_and_run([os.path.join(os.path.dirname(__file__), "test_SimM26.v")]) self.chip = Dut(cnfg_yaml) self.chip.init() def test_io(self): - # no data taking when marker for digital data (MKD) is not set - self.chip['SEQ']['MKD'][0] = 0 - self.chip['SEQ']['MKD'][1] = 0 - self.chip['SEQ']['MKD'][2] = 0 - self.chip['SEQ']['MKD'][3] = 0 + self.chip["SEQ"]["MKD"][0] = 0 + self.chip["SEQ"]["MKD"][1] = 0 + self.chip["SEQ"]["MKD"][2] = 0 + self.chip["SEQ"]["MKD"][3] = 0 header0 = BitLogic(16) header1 = BitLogic(16) header0[:] = 0x5555 header1[:] = 0xDAAA - self.chip['SEQ']['DATA0'][0:16] = header0[:] - self.chip['SEQ']['DATA1'][0:16] = header1[:] + self.chip["SEQ"]["DATA0"][0:16] = header0[:] + self.chip["SEQ"]["DATA1"][0:16] = header1[:] fcnt0 = BitLogic(16) fcnt1 = BitLogic(16) - fcnt0[:] = 0xffaa - fcnt1[:] = 0xaa55 + fcnt0[:] = 0xFFAA + fcnt1[:] = 0xAA55 - self.chip['SEQ']['DATA0'][16:32] = fcnt0[:] - self.chip['SEQ']['DATA1'][16:32] = fcnt1[:] + self.chip["SEQ"]["DATA0"][16:32] = fcnt0[:] + self.chip["SEQ"]["DATA1"][16:32] = fcnt1[:] datalen0 = BitLogic(16) datalen1 = BitLogic(16) datalen0[:] = 0x0003 datalen1[:] = 0x0003 - self.chip['SEQ']['DATA0'][32:48] = datalen0[:] - self.chip['SEQ']['DATA1'][32:48] = datalen1[:] + self.chip["SEQ"]["DATA0"][32:48] = datalen0[:] + self.chip["SEQ"]["DATA1"][32:48] = datalen1[:] for i in range(4): data0 = BitLogic(16) data1 = BitLogic(16) data0[:] = i * 2 data1[:] = i * 2 + 1 - self.chip['SEQ']['DATA0'][48 + i * 16:48 + 16 + i * 16] = data0[:] - self.chip['SEQ']['DATA1'][48 + i * 16:48 + 16 + i * 16] = data1[:] + self.chip["SEQ"]["DATA0"][48 + i * 16 : 48 + 16 + i * 16] = data0[:] + self.chip["SEQ"]["DATA1"][48 + i * 16 : 48 + 16 + i * 16] = data1[:] - self.chip['SEQ'].write(16 * (4 + 4)) - self.chip['SEQ'].set_REPEAT(4) - self.chip['SEQ'].set_SIZE(16 * (4 + 12)) + self.chip["SEQ"].write(16 * (4 + 4)) + self.chip["SEQ"].set_REPEAT(4) + self.chip["SEQ"].set_SIZE(16 * (4 + 12)) - self.chip['M26_RX']['TIMESTAMP_HEADER'] = False - self.chip['M26_RX']['EN'] = True + self.chip["M26_RX"]["TIMESTAMP_HEADER"] = False + self.chip["M26_RX"]["EN"] = True - self.chip['SEQ'].start() + self.chip["SEQ"].start() - while not self.chip['SEQ'].is_ready: + while not self.chip["SEQ"].is_ready: pass - ret = self.chip['FIFO'].get_FIFO_SIZE() + ret = self.chip["FIFO"].get_FIFO_SIZE() self.assertEqual(ret, 0) # set marker for digital data (MKD) - self.chip['SEQ']['MKD'][0] = 1 - self.chip['SEQ']['MKD'][1] = 1 - self.chip['SEQ']['MKD'][2] = 1 - self.chip['SEQ']['MKD'][3] = 1 + self.chip["SEQ"]["MKD"][0] = 1 + self.chip["SEQ"]["MKD"][1] = 1 + self.chip["SEQ"]["MKD"][2] = 1 + self.chip["SEQ"]["MKD"][3] = 1 - self.chip['SEQ'].write(16 * (4 + 4)) + self.chip["SEQ"].write(16 * (4 + 4)) - self.chip['SEQ'].start() + self.chip["SEQ"].start() - while not self.chip['SEQ'].is_ready: + while not self.chip["SEQ"].is_ready: pass - ret = self.chip['FIFO'].get_FIFO_SIZE() + ret = self.chip["FIFO"].get_FIFO_SIZE() self.assertEqual(ret, 14 * 4 * 4) - ret = self.chip['FIFO'].get_data() + ret = self.chip["FIFO"].get_data() exps = np.zeros((14,), dtype=np.uint32) exps[0] = 0x00010000 | 0x5555 exps[1] = 0xDAAA - exps[2] = 0xffaa - exps[3] = 0xaa55 + exps[2] = 0xFFAA + exps[3] = 0xAA55 exps[4] = 0x0003 exps[5] = 0x0003 for i in range(4): @@ -154,20 +152,20 @@ def test_io(self): np.testing.assert_array_equal(exp, ret) # testing internal timestamp replaces M26 header - self.chip['M26_RX'].reset() - self.chip['M26_RX']['TIMESTAMP_HEADER'] = True # default - self.chip['M26_RX']['EN'] = True - self.chip['SEQ'].start() + self.chip["M26_RX"].reset() + self.chip["M26_RX"]["TIMESTAMP_HEADER"] = True # default + self.chip["M26_RX"]["EN"] = True + self.chip["SEQ"].start() exps[0] = 0x00010000 | 0xBB44 exps[1] = 0xAA55 exp = np.tile(exps, 4) - while not self.chip['SEQ'].is_ready: + while not self.chip["SEQ"].is_ready: pass - ret = self.chip['FIFO'].get_data() + ret = self.chip["FIFO"].get_data() np.testing.assert_array_equal(exp, ret) @@ -178,25 +176,25 @@ def test_io(self): datalen0[:] = 0x023B datalen1[:] = 0x023B - self.chip['SEQ']['DATA0'][32:48] = datalen0[:] - self.chip['SEQ']['DATA1'][32:48] = datalen1[:] + self.chip["SEQ"]["DATA0"][32:48] = datalen0[:] + self.chip["SEQ"]["DATA1"][32:48] = datalen1[:] - self.chip['SEQ'].write(16 * (4 + 4)) + self.chip["SEQ"].write(16 * (4 + 4)) - self.chip['M26_RX'].reset() - self.chip['M26_RX']['TIMESTAMP_HEADER'] = True # default - self.chip['M26_RX']['EN'] = True - self.chip['SEQ'].start() + self.chip["M26_RX"].reset() + self.chip["M26_RX"]["TIMESTAMP_HEADER"] = True # default + self.chip["M26_RX"]["EN"] = True + self.chip["SEQ"].start() - while not self.chip['SEQ'].is_ready: + while not self.chip["SEQ"].is_ready: pass - self.assertEqual(self.chip['M26_RX']['INVALID_DATA_COUNT'], 4) + self.assertEqual(self.chip["M26_RX"]["INVALID_DATA_COUNT"], 4) - ret = self.chip['FIFO'].get_FIFO_SIZE() + ret = self.chip["FIFO"].get_FIFO_SIZE() self.assertEqual(ret, 6 * 4 * 4) - ret = self.chip['FIFO'].get_data() + ret = self.chip["FIFO"].get_data() exps[4] = 0x023B exps[5] = 0x023B @@ -211,20 +209,20 @@ def test_io(self): datalen0[:] = 0x0003 datalen1[:] = 0x0003 - self.chip['SEQ']['DATA0'][32:48] = datalen0[:] - self.chip['SEQ']['DATA1'][32:48] = datalen1[:] + self.chip["SEQ"]["DATA0"][32:48] = datalen0[:] + self.chip["SEQ"]["DATA1"][32:48] = datalen1[:] - self.chip['SEQ'].write(16 * (4 + 4)) + self.chip["SEQ"].write(16 * (4 + 4)) - self.chip['SEQ'].start() + self.chip["SEQ"].start() - while not self.chip['SEQ'].is_ready: + while not self.chip["SEQ"].is_ready: pass - ret = self.chip['FIFO'].get_FIFO_SIZE() + ret = self.chip["FIFO"].get_FIFO_SIZE() self.assertEqual(ret, 14 * 4 * 4) - ret = self.chip['FIFO'].get_data() + ret = self.chip["FIFO"].get_data() exps[4] = 0x0003 exps[5] = 0x0003 @@ -238,5 +236,5 @@ def tearDown(self): cocotb_compile_clean() -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/tests/test_SimSCPIFormatting.py b/tests/test_SimSCPIFormatting.py index 6f9fefbc2..c7d25bfe0 100644 --- a/tests/test_SimSCPIFormatting.py +++ b/tests/test_SimSCPIFormatting.py @@ -1,6 +1,8 @@ +import os import unittest + import yaml -import os + from basil.dut import Dut k2410def_yaml = os.path.join(os.path.dirname(__file__), "formatting.yaml") @@ -26,35 +28,34 @@ class TestSimScpi(unittest.TestCase): - def setUp(self): self.cfg = yaml.safe_load(cnfg_yaml) self.device = Dut(self.cfg) self.device.init() # Check that formatting is present - self.assertTrue(self.device['Sourcemeter'].has_formatting) + self.assertTrue(self.device["Sourcemeter"].has_formatting) # Check that formatting is enabled after init - self.assertTrue(self.device['Sourcemeter'].formatting_enabled) + self.assertTrue(self.device["Sourcemeter"].formatting_enabled) def tearDown(self): self.device.close() def test_read_voltage(self): - voltage = self.device['Sourcemeter'].get_voltage() - self.assertEqual(voltage, '-5.124E-05') + voltage = self.device["Sourcemeter"].get_voltage() + self.assertEqual(voltage, "-5.124E-05") def test_read_voltage_unformatted(self): # Check that formatting is enabled - self.assertTrue(self.device['Sourcemeter'].formatting_enabled) + self.assertTrue(self.device["Sourcemeter"].formatting_enabled) # Disable formatting - self.device['Sourcemeter'].disable_formatting() - voltage = self.device['Sourcemeter'].get_voltage().split(',')[0] - self.assertEqual(voltage, '-5.124E-05') + self.device["Sourcemeter"].disable_formatting() + voltage = self.device["Sourcemeter"].get_voltage().split(",")[0] + self.assertEqual(voltage, "-5.124E-05") # Check that formatting is disabled - self.assertFalse(self.device['Sourcemeter'].formatting_enabled) + self.assertFalse(self.device["Sourcemeter"].formatting_enabled) # Enable formatting - self.device['Sourcemeter'].enable_formatting() + self.device["Sourcemeter"].enable_formatting() -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/tests/test_SimScpi.py b/tests/test_SimScpi.py index 14675ed64..8c366a1ec 100644 --- a/tests/test_SimScpi.py +++ b/tests/test_SimScpi.py @@ -6,11 +6,12 @@ # import unittest + import yaml from basil.dut import Dut -cnfg_yaml = ''' +cnfg_yaml = """ transfer_layer: - name : Visa type : Visa @@ -26,11 +27,10 @@ interface : Visa init : device : scpi sim device -''' +""" class TestSimScpi(unittest.TestCase): - def setUp(self): self.cfg = yaml.safe_load(cnfg_yaml) self.device = Dut(self.cfg) @@ -40,20 +40,20 @@ def tearDown(self): self.device.close() def test_read(self): - self.assertEqual(self.device['Pulser'].get_frequency(), '100.00') + self.assertEqual(self.device["Pulser"].get_frequency(), "100.00") def test_write(self): - self.device['Pulser'].set_on(1) - self.assertEqual(self.device['Pulser'].get_on(), 'OK') + self.device["Pulser"].set_on(1) + self.assertEqual(self.device["Pulser"].get_on(), "OK") def test_invalid_parameter(self): with self.assertRaises(ValueError): - self.device['Pulser'].set_on(1, 2) + self.device["Pulser"].set_on(1, 2) def test_exception(self): with self.assertRaises(ValueError): - self.device['Pulser'].unknown_function() + self.device["Pulser"].unknown_function() -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/tests/test_SimSeq.py b/tests/test_SimSeq.py index 5a075dd47..97df70b51 100644 --- a/tests/test_SimSeq.py +++ b/tests/test_SimSeq.py @@ -5,8 +5,8 @@ # ------------------------------------------------------------ # -import unittest import os +import unittest from basil.dut import Dut from basil.utils.sim.utils import cocotb_compile_and_run, cocotb_compile_clean @@ -65,7 +65,7 @@ class TestSimSeq(unittest.TestCase): def setUp(self): - cocotb_compile_and_run([os.path.join(os.path.dirname(__file__), 'test_SimSeq.v')]) + cocotb_compile_and_run([os.path.join(os.path.dirname(__file__), "test_SimSeq.v")]) self.chip = Dut(cnfg_yaml) self.chip.init() @@ -73,105 +73,109 @@ def setUp(self): def test_io(self): MEM_KB = 1 - self.assertEqual(self.chip['SEQ_GEN'].get_mem_size(), MEM_KB * 1024) - self.assertEqual(self.chip['SEQ_REC'].get_mem_size(), MEM_KB * 1024) + self.assertEqual(self.chip["SEQ_GEN"].get_mem_size(), MEM_KB * 1024) + self.assertEqual(self.chip["SEQ_REC"].get_mem_size(), MEM_KB * 1024) mem_in = (list(range(256)) * 4) * MEM_KB self.chip["SEQ_GEN"].set_data(mem_in) - ret = self.chip['SEQ_GEN'].get_data() + ret = self.chip["SEQ_GEN"].get_data() self.assertEqual(ret.tolist(), mem_in) - self.chip['SEQ_GEN'].set_EN_EXT_START(True) - self.chip['SEQ_REC'].set_EN_EXT_START(True) + self.chip["SEQ_GEN"].set_EN_EXT_START(True) + self.chip["SEQ_REC"].set_EN_EXT_START(True) - self.chip['PULSE_GEN'].set_DELAY(1) - self.chip['PULSE_GEN'].set_WIDTH(1) - self.chip['PULSE_GEN'].START + self.chip["PULSE_GEN"].set_DELAY(1) + self.chip["PULSE_GEN"].set_WIDTH(1) + self.chip["PULSE_GEN"].START - while not self.chip['SEQ_GEN'].is_ready: + while not self.chip["SEQ_GEN"].is_ready: pass # 2nd time - self.chip['PULSE_GEN'].START + self.chip["PULSE_GEN"].START - while not self.chip['SEQ_GEN'].is_ready: + while not self.chip["SEQ_GEN"].is_ready: pass - ret = self.chip['SEQ_REC'].get_data() + ret = self.chip["SEQ_REC"].get_data() self.assertEqual(ret.tolist()[2:], mem_in[:-2]) - self.chip['SEQ']['S0'][0] = 1 - self.chip['SEQ']['S1'][1] = 1 - self.chip['SEQ']['S2'][2] = 1 - self.chip['SEQ']['S3'][3] = 1 + self.chip["SEQ"]["S0"][0] = 1 + self.chip["SEQ"]["S1"][1] = 1 + self.chip["SEQ"]["S2"][2] = 1 + self.chip["SEQ"]["S3"][3] = 1 - self.chip['SEQ']['S4'][12] = 1 - self.chip['SEQ']['S5'][13] = 1 - self.chip['SEQ']['S6'][14] = 1 - self.chip['SEQ']['S7'][15] = 1 + self.chip["SEQ"]["S4"][12] = 1 + self.chip["SEQ"]["S5"][13] = 1 + self.chip["SEQ"]["S6"][14] = 1 + self.chip["SEQ"]["S7"][15] = 1 pattern = [0x01, 0x02, 0x04, 0x08, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0x20, 0x40, 0x80] - self.chip['SEQ'].write(16) + self.chip["SEQ"].write(16) - ret = self.chip['SEQ'].get_data(size=16) + ret = self.chip["SEQ"].get_data(size=16) self.assertEqual(ret.tolist(), pattern) rec_size = 16 * 4 + 8 - self.chip['SEQ_REC'].set_EN_EXT_START(True) - self.chip['SEQ_REC'].set_size(rec_size) + self.chip["SEQ_REC"].set_EN_EXT_START(True) + self.chip["SEQ_REC"].set_size(rec_size) - self.chip['PULSE_GEN'].set_DELAY(1) - self.chip['PULSE_GEN'].set_WIDTH(1) + self.chip["PULSE_GEN"].set_DELAY(1) + self.chip["PULSE_GEN"].set_WIDTH(1) - self.assertEqual(self.chip['PULSE_GEN'].get_DELAY(), 1) - self.assertEqual(self.chip['PULSE_GEN'].get_WIDTH(), 1) + self.assertEqual(self.chip["PULSE_GEN"].get_DELAY(), 1) + self.assertEqual(self.chip["PULSE_GEN"].get_WIDTH(), 1) - self.chip['SEQ'].set_REPEAT(4) - self.chip['SEQ'].set_EN_EXT_START(True) - self.chip['SEQ'].set_size(16) + self.chip["SEQ"].set_REPEAT(4) + self.chip["SEQ"].set_EN_EXT_START(True) + self.chip["SEQ"].set_size(16) # self.chip['SEQ'].START - self.chip['PULSE_GEN'].START + self.chip["PULSE_GEN"].START - while not self.chip['SEQ'].is_ready: + while not self.chip["SEQ"].is_ready: pass - ret = self.chip['SEQ_REC'].get_data(size=rec_size) + ret = self.chip["SEQ_REC"].get_data(size=rec_size) self.assertEqual(ret.tolist()[2:], pattern * 4 + [0x80] * 6) # 2 clk delay + pattern x4 + 6 x last pattern # - self.chip['SEQ'].set_REPEAT_START(12) - self.chip['PULSE_GEN'].START + self.chip["SEQ"].set_REPEAT_START(12) + self.chip["PULSE_GEN"].START - while not self.chip['SEQ'].is_ready: + while not self.chip["SEQ"].is_ready: pass - ret = self.chip['SEQ_REC'].get_data(size=rec_size) - self.assertEqual(ret.tolist(), [0x80] * 2 + pattern + pattern[12:] * 3 + [0x80] * 3 * 12 + [0x80] * 6) # 2 clk delay 0x80 > from last pattern + ... + ret = self.chip["SEQ_REC"].get_data(size=rec_size) + self.assertEqual( + ret.tolist(), [0x80] * 2 + pattern + pattern[12:] * 3 + [0x80] * 3 * 12 + [0x80] * 6 + ) # 2 clk delay 0x80 > from last pattern + ... - self.chip['SEQ'].set_wait(4) - self.chip['PULSE_GEN'].START + self.chip["SEQ"].set_wait(4) + self.chip["PULSE_GEN"].START - while not self.chip['SEQ'].is_ready: + while not self.chip["SEQ"].is_ready: pass - ret = self.chip['SEQ_REC'].get_data(size=rec_size) + ret = self.chip["SEQ_REC"].get_data(size=rec_size) lpat = pattern[12:] + [0x80] * 4 - self.assertEqual(ret.tolist(), [0x80] * 2 + pattern + [0x80] * 4 + lpat * 3 + [0x80] * (3 * 12 - 4 * 4) + [0x80] * 6) + self.assertEqual( + ret.tolist(), [0x80] * 2 + pattern + [0x80] * 4 + lpat * 3 + [0x80] * (3 * 12 - 4 * 4) + [0x80] * 6 + ) # rec_size = rec_size * 3 - self.chip['SEQ_REC'].set_size(rec_size) - self.chip['SEQ'].set_clk_divide(3) - self.chip['SEQ'].set_wait(3) - self.chip['PULSE_GEN'].START + self.chip["SEQ_REC"].set_size(rec_size) + self.chip["SEQ"].set_clk_divide(3) + self.chip["SEQ"].set_wait(3) + self.chip["PULSE_GEN"].START - while not self.chip['SEQ'].is_ready: + while not self.chip["SEQ"].is_ready: pass - ret = self.chip['SEQ_REC'].get_data(size=rec_size) + ret = self.chip["SEQ_REC"].get_data(size=rec_size) lpat = pattern[12:] + [0x80] * 3 mu_pat = pattern + [0x80] * 3 + lpat * 3 fm = [] @@ -180,13 +184,13 @@ def test_io(self): self.assertEqual(ret.tolist(), [0x80] * 2 + fm + [0x80] * 94) # - self.chip['SEQ'].set_wait(0) - self.chip['PULSE_GEN'].START + self.chip["SEQ"].set_wait(0) + self.chip["PULSE_GEN"].START - while not self.chip['SEQ'].is_ready: + while not self.chip["SEQ"].is_ready: pass - ret = self.chip['SEQ_REC'].get_data(size=rec_size) + ret = self.chip["SEQ_REC"].get_data(size=rec_size) lpat = pattern[12:] mu_pat = pattern + lpat * 3 fm = [] @@ -196,16 +200,16 @@ def test_io(self): # nested loop test pattern = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16] - self.chip['SEQ'].set_data(pattern) - self.chip['SEQ'].set_REPEAT(4) - self.chip['SEQ'].set_REPEAT_START(2) - self.chip['SEQ'].set_NESTED_START(8) - self.chip['SEQ'].set_NESTED_STOP(12) - self.chip['SEQ'].set_NESTED_REPEAT(3) - self.chip['SEQ'].set_CLK_DIV(1) - self.chip['PULSE_GEN'].START - - while not self.chip['SEQ'].is_ready: + self.chip["SEQ"].set_data(pattern) + self.chip["SEQ"].set_REPEAT(4) + self.chip["SEQ"].set_REPEAT_START(2) + self.chip["SEQ"].set_NESTED_START(8) + self.chip["SEQ"].set_NESTED_STOP(12) + self.chip["SEQ"].set_NESTED_REPEAT(3) + self.chip["SEQ"].set_CLK_DIV(1) + self.chip["PULSE_GEN"].START + + while not self.chip["SEQ"].is_ready: pass exp_pattern = [0x10, 0x10] @@ -216,7 +220,7 @@ def test_io(self): exp_pattern += rep * 4 exp_pattern += [16] * 124 - ret = self.chip['SEQ_REC'].get_data(size=rec_size) + ret = self.chip["SEQ_REC"].get_data(size=rec_size) self.assertEqual(ret.tolist(), exp_pattern) def tearDown(self): @@ -226,7 +230,7 @@ def tearDown(self): class TestSimSeq4bit(unittest.TestCase): def setUp(self): - cocotb_compile_and_run([os.path.join(os.path.dirname(__file__), 'test_SimSeq.v')], extra_defines=["BITS=4"]) + cocotb_compile_and_run([os.path.join(os.path.dirname(__file__), "test_SimSeq.v")], extra_defines=["BITS=4"]) self.chip = Dut(cnfg_yaml) self.chip.init() @@ -237,20 +241,20 @@ def test_seq_4bit(self): mem_in = (list(range(256)) * 4) * MEM_KB self.chip["SEQ_GEN"].set_data(mem_in) - ret = self.chip['SEQ_GEN'].get_data() + ret = self.chip["SEQ_GEN"].get_data() self.assertEqual(ret.tolist(), mem_in) - self.chip['SEQ_GEN'].set_EN_EXT_START(True) - self.chip['SEQ_REC'].set_EN_EXT_START(True) + self.chip["SEQ_GEN"].set_EN_EXT_START(True) + self.chip["SEQ_REC"].set_EN_EXT_START(True) - self.chip['PULSE_GEN'].set_DELAY(1) - self.chip['PULSE_GEN'].set_WIDTH(1) - self.chip['PULSE_GEN'].START + self.chip["PULSE_GEN"].set_DELAY(1) + self.chip["PULSE_GEN"].set_WIDTH(1) + self.chip["PULSE_GEN"].START - while not self.chip['SEQ_GEN'].is_ready: + while not self.chip["SEQ_GEN"].is_ready: pass - ret = self.chip['SEQ_REC'].get_data() + ret = self.chip["SEQ_REC"].get_data() self.assertEqual(ret.tolist()[1:], mem_in[:-1]) def tearDown(self): @@ -260,7 +264,7 @@ def tearDown(self): class TestSimSeq16bit(unittest.TestCase): def setUp(self): - cocotb_compile_and_run([os.path.join(os.path.dirname(__file__), 'test_SimSeq.v')], extra_defines=["BITS=16"]) + cocotb_compile_and_run([os.path.join(os.path.dirname(__file__), "test_SimSeq.v")], extra_defines=["BITS=16"]) self.chip = Dut(cnfg_yaml) self.chip.init() @@ -271,20 +275,20 @@ def test_seq_16bit(self): mem_in = (list(range(256)) * 4) * MEM_KB self.chip["SEQ_GEN"].set_data(mem_in) - ret = self.chip['SEQ_GEN'].get_data() + ret = self.chip["SEQ_GEN"].get_data() self.assertEqual(ret.tolist(), mem_in) - self.chip['SEQ_GEN'].set_EN_EXT_START(True) - self.chip['SEQ_REC'].set_EN_EXT_START(True) + self.chip["SEQ_GEN"].set_EN_EXT_START(True) + self.chip["SEQ_REC"].set_EN_EXT_START(True) - self.chip['PULSE_GEN'].set_DELAY(1) - self.chip['PULSE_GEN'].set_WIDTH(1) - self.chip['PULSE_GEN'].START + self.chip["PULSE_GEN"].set_DELAY(1) + self.chip["PULSE_GEN"].set_WIDTH(1) + self.chip["PULSE_GEN"].START - while not self.chip['SEQ_GEN'].is_ready: + while not self.chip["SEQ_GEN"].is_ready: pass - ret = self.chip['SEQ_REC'].get_data() + ret = self.chip["SEQ_REC"].get_data() self.assertEqual(ret.tolist()[4:], mem_in[:-4]) def tearDown(self): @@ -292,5 +296,5 @@ def tearDown(self): cocotb_compile_clean() -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/tests/test_SimSpi.py b/tests/test_SimSpi.py index 3d5992b89..2431465f6 100644 --- a/tests/test_SimSpi.py +++ b/tests/test_SimSpi.py @@ -5,17 +5,16 @@ # ------------------------------------------------------------ # -import unittest -import pytest import os -import yaml +import unittest import numpy as np +import pytest +import yaml from basil.dut import Dut from basil.utils.sim.utils import cocotb_compile_and_run, cocotb_compile_clean - cnfg_yaml = """ transfer_layer: - name : INTF @@ -65,97 +64,101 @@ class TestSimSpi(unittest.TestCase): - def __init__(self, testname, tb='test_SimSpi.v', bus_drv='basil.utils.sim.BasilBusDriver', bus_split=False): + def __init__(self, testname, tb="test_SimSpi.v", bus_drv="basil.utils.sim.BasilBusDriver", bus_split=False): super(TestSimSpi, self).__init__(testname) self._test_tb = tb self._sim_bus = bus_drv self._bus_split_def = () if bus_split is not False: - if bus_split == 'sbus': + if bus_split == "sbus": self._bus_split_def = ("BASIL_SBUS",) - elif bus_split == 'top': + elif bus_split == "top": self._bus_split_def = ("BASIL_TOPSBUS",) def setUp(self): - cocotb_compile_and_run(sim_files=[os.path.join(os.path.dirname(__file__), self._test_tb)], sim_bus=self._sim_bus, extra_defines=self._bus_split_def) + cocotb_compile_and_run( + sim_files=[os.path.join(os.path.dirname(__file__), self._test_tb)], + sim_bus=self._sim_bus, + extra_defines=self._bus_split_def, + ) self.chip = Dut(cnfg_yaml) self.chip.init() def test_io(self): - size = self.chip['SPI'].get_SIZE() - self.chip['GPIO'].reset() + size = self.chip["SPI"].get_SIZE() + self.chip["GPIO"].reset() self.assertEqual(size, 16 * 8) - self.chip['SPI'].set_data(range(16)) - ret = self.chip['SPI'].get_data(size=16, addr=0) # to read back what was written + self.chip["SPI"].set_data(range(16)) + ret = self.chip["SPI"].get_data(size=16, addr=0) # to read back what was written self.assertEqual(ret.tolist(), list(range(16))) - self.chip['SPI'].set_data(range(16)) - ret = self.chip['SPI'].get_data(addr=0) # to read back what was written + self.chip["SPI"].set_data(range(16)) + ret = self.chip["SPI"].get_data(addr=0) # to read back what was written self.assertEqual(ret.tolist(), list(range(16))) - self.chip['SPI'].start() - while not self.chip['SPI'].is_ready: + self.chip["SPI"].start() + while not self.chip["SPI"].is_ready: pass - ret = self.chip['SPI'].get_data() # read back what was received (looped) + ret = self.chip["SPI"].get_data() # read back what was received (looped) self.assertEqual(ret.tolist(), list(range(16))) # ext_start - self.chip['SPI'].set_en(1) - self.assertEqual(self.chip['SPI'].get_en(), 1) - - self.chip['PULSE_GEN'].set_DELAY(1) - self.chip['PULSE_GEN'].set_WIDTH(1 + size) - self.chip['PULSE_GEN'].set_REPEAT(1) - self.assertEqual(self.chip['PULSE_GEN'].get_DELAY(), 1) - self.assertEqual(self.chip['PULSE_GEN'].get_WIDTH(), 1 + size) - self.assertEqual(self.chip['PULSE_GEN'].get_REPEAT(), 1) - - self.chip['PULSE_GEN'].start() - while not self.chip['PULSE_GEN'].is_ready: + self.chip["SPI"].set_en(1) + self.assertEqual(self.chip["SPI"].get_en(), 1) + + self.chip["PULSE_GEN"].set_DELAY(1) + self.chip["PULSE_GEN"].set_WIDTH(1 + size) + self.chip["PULSE_GEN"].set_REPEAT(1) + self.assertEqual(self.chip["PULSE_GEN"].get_DELAY(), 1) + self.assertEqual(self.chip["PULSE_GEN"].get_WIDTH(), 1 + size) + self.assertEqual(self.chip["PULSE_GEN"].get_REPEAT(), 1) + + self.chip["PULSE_GEN"].start() + while not self.chip["PULSE_GEN"].is_ready: pass - ret = self.chip['SPI'].get_data() # read back what was received (looped) + ret = self.chip["SPI"].get_data() # read back what was received (looped) self.assertEqual(ret.tolist(), list(range(16))) # SPI_RX - ret = self.chip['SPI_RX'].get_en() + ret = self.chip["SPI_RX"].get_en() self.assertEqual(ret, False) - self.chip['SPI_RX'].set_en(True) - ret = self.chip['SPI_RX'].get_en() + self.chip["SPI_RX"].set_en(True) + ret = self.chip["SPI_RX"].get_en() self.assertEqual(ret, True) - self.chip['SPI'].start() - while not self.chip['SPI'].is_ready: + self.chip["SPI"].start() + while not self.chip["SPI"].is_ready: pass - ret = self.chip['FIFO'].get_FIFO_SIZE() + ret = self.chip["FIFO"].get_FIFO_SIZE() self.assertEqual(ret, 32) - ret = self.chip['FIFO'].get_data() + ret = self.chip["FIFO"].get_data() data0 = ret.astype(np.uint8) data1 = np.right_shift(ret, 8).astype(np.uint8) - data = np.reshape(np.vstack((data1, data0)), -1, order='F') + data = np.reshape(np.vstack((data1, data0)), -1, order="F") self.assertEqual(data.tolist(), list(range(16))) def test_dut_iter(self): conf = yaml.safe_load(cnfg_yaml) def iter_conf(): - for item in conf['registers']: + for item in conf["registers"]: yield item - for item in conf['hw_drivers']: + for item in conf["hw_drivers"]: yield item - for item in conf['transfer_layer']: + for item in conf["transfer_layer"]: yield item for mod, mcnf in zip(self.chip, iter_conf()): - self.assertEqual(mod.name, mcnf['name']) - self.assertEqual(mod.__class__.__name__, mcnf['type']) + self.assertEqual(mod.name, mcnf["name"]) + self.assertEqual(mod.__class__.__name__, mcnf["type"]) def tearDown(self): self.chip.close() # let it close connection and stop simulator @@ -172,8 +175,10 @@ def tearDown(self): @pytest.mark.verilator class TestSimSpiSbusTop(TestSimSpi): def __init__(self, testname): - super(TestSimSpiSbusTop, self).__init__(testname=testname, tb='test_SimSpi.v', bus_drv='basil.utils.sim.BasilSbusDriver', bus_split='top') + super(TestSimSpiSbusTop, self).__init__( + testname=testname, tb="test_SimSpi.v", bus_drv="basil.utils.sim.BasilSbusDriver", bus_split="top" + ) -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/tests/test_SimTdc.py b/tests/test_SimTdc.py index 77b7e0b7c..eff4caf5c 100644 --- a/tests/test_SimTdc.py +++ b/tests/test_SimTdc.py @@ -5,8 +5,8 @@ # ------------------------------------------------------------ # -import unittest import os +import unittest from basil.dut import Dut from basil.utils.sim.utils import cocotb_compile_and_run, cocotb_compile_clean @@ -86,73 +86,73 @@ class TestSimTdc(unittest.TestCase): def setUp(self): - cocotb_compile_and_run([os.path.join(os.path.dirname(__file__), 'test_SimTdc.v')]) + cocotb_compile_and_run([os.path.join(os.path.dirname(__file__), "test_SimTdc.v")]) self.chip = Dut(cnfg_yaml) self.chip.init() def test_tdc(self): - self.chip['TDC0'].ENABLE = 1 - self.chip['SEQ'].REPEAT = 1 + self.chip["TDC0"].ENABLE = 1 + self.chip["SEQ"].REPEAT = 1 for index, i in enumerate(range(0, 10)): length = i + 1 - self.chip['SEQ'].SIZE = length + 1 - self.chip['SEQ']['TDC_IN'][0:length] = True - self.chip['SEQ'].write(length) - self.chip['SEQ'].START - while not self.chip['SEQ'].is_ready: + self.chip["SEQ"].SIZE = length + 1 + self.chip["SEQ"]["TDC_IN"][0:length] = True + self.chip["SEQ"].write(length) + self.chip["SEQ"].START + while not self.chip["SEQ"].is_ready: pass - self.assertEqual(self.chip['FIFO0'].get_FIFO_INT_SIZE(), 1) + self.assertEqual(self.chip["FIFO0"].get_FIFO_INT_SIZE(), 1) - data = self.chip['FIFO0'].get_data() + data = self.chip["FIFO0"].get_data() self.assertEqual(data[0], (index << 12) + length) def test_tdc_overflow(self): - self.chip['TDC0'].ENABLE = 1 - self.chip['SEQ'].REPEAT = 1 + self.chip["TDC0"].ENABLE = 1 + self.chip["SEQ"].REPEAT = 1 for index, i in enumerate(range(4094, 4097)): length = i + 1 - self.chip['SEQ_GEN'].SIZE = length + 1 - self.chip['SEQ']['TDC_IN'][0:length] = True - self.chip['SEQ'].write(length) - self.chip['SEQ'].START - while not self.chip['SEQ_GEN'].is_ready: + self.chip["SEQ_GEN"].SIZE = length + 1 + self.chip["SEQ"]["TDC_IN"][0:length] = True + self.chip["SEQ"].write(length) + self.chip["SEQ"].START + while not self.chip["SEQ_GEN"].is_ready: pass - self.assertEqual(self.chip['FIFO0'].get_FIFO_INT_SIZE(), 1) + self.assertEqual(self.chip["FIFO0"].get_FIFO_INT_SIZE(), 1) - data = self.chip['FIFO0'].get_data() + data = self.chip["FIFO0"].get_data() self.assertEqual(data[0], (index << 12) + min(length, 4095)) # overflow 12bit def test_broadcasting(self): - self.chip['TDC0'].ENABLE = 1 - self.chip['TDC1'].ENABLE = 1 - self.chip['TDC2'].ENABLE = 1 - self.chip['TDC0'].EN_TRIGGER_DIST = 1 - self.chip['TDC1'].EN_TRIGGER_DIST = 1 - self.chip['TDC2'].EN_TRIGGER_DIST = 1 - self.chip['SEQ'].REPEAT = 1 + self.chip["TDC0"].ENABLE = 1 + self.chip["TDC1"].ENABLE = 1 + self.chip["TDC2"].ENABLE = 1 + self.chip["TDC0"].EN_TRIGGER_DIST = 1 + self.chip["TDC1"].EN_TRIGGER_DIST = 1 + self.chip["TDC2"].EN_TRIGGER_DIST = 1 + self.chip["SEQ"].REPEAT = 1 TDC_TRIG_DIST_MASK = 0x0FF00000 TDC_VALUE_MASK = 0x00000FFF for _, i in enumerate([1045, 1046, 1047]): - offset = 50 # trigger distance + offset = 50 # trigger distance length = i + 1 + offset - self.chip['SEQ_GEN'].SIZE = length + 1 - self.chip['SEQ']['TDC_IN'][offset:length + offset] = True - self.chip['SEQ']['TDC_TRIGGER_IN'][0:10] = True - self.chip['SEQ'].write(length) - self.chip['SEQ'].START - while not self.chip['SEQ_GEN'].is_ready: + self.chip["SEQ_GEN"].SIZE = length + 1 + self.chip["SEQ"]["TDC_IN"][offset : length + offset] = True + self.chip["SEQ"]["TDC_TRIGGER_IN"][0:10] = True + self.chip["SEQ"].write(length) + self.chip["SEQ"].START + while not self.chip["SEQ_GEN"].is_ready: pass - self.assertEqual(self.chip['FIFO0'].get_FIFO_INT_SIZE(), 1) - self.assertEqual(self.chip['FIFO1'].get_FIFO_INT_SIZE(), 1) - self.assertEqual(self.chip['FIFO2'].get_FIFO_INT_SIZE(), 1) + self.assertEqual(self.chip["FIFO0"].get_FIFO_INT_SIZE(), 1) + self.assertEqual(self.chip["FIFO1"].get_FIFO_INT_SIZE(), 1) + self.assertEqual(self.chip["FIFO2"].get_FIFO_INT_SIZE(), 1) - data0 = self.chip['FIFO0'].get_data() - data1 = self.chip['FIFO1'].get_data() - data2 = self.chip['FIFO2'].get_data() + data0 = self.chip["FIFO0"].get_data() + data1 = self.chip["FIFO1"].get_data() + data2 = self.chip["FIFO2"].get_data() # Check data from first TDC module self.assertEqual(data0[0] & TDC_VALUE_MASK, i + 1) # TDC value @@ -161,22 +161,22 @@ def test_broadcasting(self): self.assertEqual(data0[0], data1[0]) # Compare TDC0 with TDC1 self.assertEqual(data0[0], data2[0]) # Compare TDC0 with TDC2 -# def test_tdc_delay(self): -# pass -# -# def test_tdc_delay_overflow(self): -# pass -# -# def test_tdc_delay_late_trigger(self): -# pass -# -# def test_tdc_arm(self): -# pass + # def test_tdc_delay(self): + # pass + # + # def test_tdc_delay_overflow(self): + # pass + # + # def test_tdc_delay_late_trigger(self): + # pass + # + # def test_tdc_arm(self): + # pass def tearDown(self): self.chip.close() # let it close connection and stop simulator cocotb_compile_clean() -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/tests/test_SimTdl_Tdc.py b/tests/test_SimTdl_Tdc.py index 4fa1a32b1..d2c5b9b1d 100644 --- a/tests/test_SimTdl_Tdc.py +++ b/tests/test_SimTdl_Tdc.py @@ -5,8 +5,8 @@ # ------------------------------------------------------------ # -import unittest import os +import unittest from basil.dut import Dut from basil.utils.sim.utils import cocotb_compile_and_run, cocotb_compile_clean @@ -86,70 +86,70 @@ class TestSimTdlTdc(unittest.TestCase): def setUp(self): - cocotb_compile_and_run([os.path.join(os.path.dirname(__file__), 'test_SimTdl_Tdc.v')]) + cocotb_compile_and_run([os.path.join(os.path.dirname(__file__), "test_SimTdl_Tdc.v")]) self.chip = Dut(cnfg_yaml) self.chip.init() @unittest.skip("Currently not compatible with Icarus Verilog") def test_tdc(self): - self.chip['TDC0'].ENABLE = 1 - self.chip['TDC0'].EN_TRIGGER_DIST = 1 - self.chip['SEQ'].REPEAT = 1 + self.chip["TDC0"].ENABLE = 1 + self.chip["TDC0"].EN_TRIGGER_DIST = 1 + self.chip["SEQ"].REPEAT = 1 for write_timestamp in range(0, 1): for index, i in enumerate(range(1045, 1047)): trigger_dis = 50 length = i + 1 + trigger_dis - self.chip['SEQ'].SIZE = length + 1 - self.chip['SEQ']['TDC_IN'][trigger_dis:length + trigger_dis] = True - self.chip['SEQ']['TDC_TRIGGER_IN'][0:10] = True - self.chip['SEQ'].write(length) - self.chip['SEQ'].START - while not self.chip['SEQ'].is_ready: + self.chip["SEQ"].SIZE = length + 1 + self.chip["SEQ"]["TDC_IN"][trigger_dis : length + trigger_dis] = True + self.chip["SEQ"]["TDC_TRIGGER_IN"][0:10] = True + self.chip["SEQ"].write(length) + self.chip["SEQ"].START + while not self.chip["SEQ"].is_ready: pass - self.assertEqual(self.chip['FIFO0'].get_FIFO_INT_SIZE(), 3 + write_timestamp) - - data = self.chip['FIFO0'].get_data() - data = [self.chip['TDC0'].disassemble_tdc_word(w) for w in data] - self.assertEqual(data[0]['word_type'], 'TRIGGERED') - self.assertEqual(data[1]['word_type'], 'RISING') - self.assertEqual(data[1]['tdc_value'], trigger_dis) - self.assertEqual(data[2]['word_type'], 'FALLING') - self.assertEqual(data[2]['tdc_value'], trigger_dis + i + 1) + self.assertEqual(self.chip["FIFO0"].get_FIFO_INT_SIZE(), 3 + write_timestamp) + + data = self.chip["FIFO0"].get_data() + data = [self.chip["TDC0"].disassemble_tdc_word(w) for w in data] + self.assertEqual(data[0]["word_type"], "TRIGGERED") + self.assertEqual(data[1]["word_type"], "RISING") + self.assertEqual(data[1]["tdc_value"], trigger_dis) + self.assertEqual(data[2]["word_type"], "FALLING") + self.assertEqual(data[2]["tdc_value"], trigger_dis + i + 1) if write_timestamp: - self.assertEqual(data[3]['word_type'], 'TIMESTAMP') - self.asserEqual(data[3]['timestamp'], 42) + self.assertEqual(data[3]["word_type"], "TIMESTAMP") + self.asserEqual(data[3]["timestamp"], 42) @unittest.skip("Currently not compatible with Icarus Verilog") def test_broadcasting(self): - self.chip['TDC0'].ENABLE = 1 - self.chip['TDC1'].ENABLE = 1 - self.chip['TDC2'].ENABLE = 1 - self.chip['TDC0'].EN_TRIGGER_DIST = 1 - self.chip['TDC1'].EN_TRIGGER_DIST = 1 - self.chip['TDC2'].EN_TRIGGER_DIST = 1 - self.chip['SEQ'].REPEAT = 1 + self.chip["TDC0"].ENABLE = 1 + self.chip["TDC1"].ENABLE = 1 + self.chip["TDC2"].ENABLE = 1 + self.chip["TDC0"].EN_TRIGGER_DIST = 1 + self.chip["TDC1"].EN_TRIGGER_DIST = 1 + self.chip["TDC2"].EN_TRIGGER_DIST = 1 + self.chip["SEQ"].REPEAT = 1 TDC_TRIG_DIST_MASK = 0x0FF00000 TDC_VALUE_MASK = 0x00000FFF for _, i in enumerate([1045, 1046, 1047]): - offset = 50 # trigger distance + offset = 50 # trigger distance length = i + 1 + offset - self.chip['SEQ_GEN'].SIZE = length + 1 - self.chip['SEQ']['TDC_IN'][offset:length + offset] = True - self.chip['SEQ']['TDC_TRIGGER_IN'][0:10] = True - self.chip['SEQ'].write(length) - self.chip['SEQ'].START - while not self.chip['SEQ_GEN'].is_ready: + self.chip["SEQ_GEN"].SIZE = length + 1 + self.chip["SEQ"]["TDC_IN"][offset : length + offset] = True + self.chip["SEQ"]["TDC_TRIGGER_IN"][0:10] = True + self.chip["SEQ"].write(length) + self.chip["SEQ"].START + while not self.chip["SEQ_GEN"].is_ready: pass - self.assertEqual(self.chip['FIFO0'].get_FIFO_INT_SIZE(), 1) - self.assertEqual(self.chip['FIFO1'].get_FIFO_INT_SIZE(), 1) - self.assertEqual(self.chip['FIFO2'].get_FIFO_INT_SIZE(), 1) + self.assertEqual(self.chip["FIFO0"].get_FIFO_INT_SIZE(), 1) + self.assertEqual(self.chip["FIFO1"].get_FIFO_INT_SIZE(), 1) + self.assertEqual(self.chip["FIFO2"].get_FIFO_INT_SIZE(), 1) - data0 = self.chip['FIFO0'].get_data() - data1 = self.chip['FIFO1'].get_data() - data2 = self.chip['FIFO2'].get_data() + data0 = self.chip["FIFO0"].get_data() + data1 = self.chip["FIFO1"].get_data() + data2 = self.chip["FIFO2"].get_data() # Check data from first TDC module self.assertEqual(data0[0] & TDC_VALUE_MASK, i + 1) # TDC value @@ -175,5 +175,5 @@ def tearDown(self): cocotb_compile_clean() -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/tests/test_SimTimestamp.py b/tests/test_SimTimestamp.py index 9b3d2254d..c06c1f1ed 100644 --- a/tests/test_SimTimestamp.py +++ b/tests/test_SimTimestamp.py @@ -5,13 +5,12 @@ # ------------------------------------------------------------ # -import unittest import os +import unittest from basil.dut import Dut from basil.utils.sim.utils import cocotb_compile_and_run, cocotb_compile_clean - cnfg_yaml = """ transfer_layer: - name : intf @@ -64,51 +63,49 @@ class TestSimTimestamp(unittest.TestCase): def setUp(self): - cocotb_compile_and_run([os.path.join(os.path.dirname(__file__), 'test_SimTimestamp.v')]) + cocotb_compile_and_run([os.path.join(os.path.dirname(__file__), "test_SimTimestamp.v")]) self.chip = Dut(cnfg_yaml) self.chip.init() def test_io(self): - self.chip['timestamp'].reset() - self.chip['timestamp']["ENABLE"] = 1 - self.chip['gpio'].reset() + self.chip["timestamp"].reset() + self.chip["timestamp"]["ENABLE"] = 1 + self.chip["gpio"].reset() - self.chip['fifo'].reset() - ret = self.chip['fifo'].get_fifo_size() + self.chip["fifo"].reset() + ret = self.chip["fifo"].get_fifo_size() self.assertEqual(ret, 0) # trigger timestamp - self.chip['PULSE_GEN'].set_delay(0x105) - self.chip['PULSE_GEN'].set_width(10) - self.chip['PULSE_GEN'].set_repeat(1) - self.assertEqual(self.chip['PULSE_GEN'].get_delay(), 0x105) - self.assertEqual(self.chip['PULSE_GEN'].get_width(), 10) - self.assertEqual(self.chip['PULSE_GEN'].get_repeat(), 1) - - self.chip['PULSE_GEN'].start() - while not self.chip['PULSE_GEN'].is_done(): + self.chip["PULSE_GEN"].set_delay(0x105) + self.chip["PULSE_GEN"].set_width(10) + self.chip["PULSE_GEN"].set_repeat(1) + self.assertEqual(self.chip["PULSE_GEN"].get_delay(), 0x105) + self.assertEqual(self.chip["PULSE_GEN"].get_width(), 10) + self.assertEqual(self.chip["PULSE_GEN"].get_repeat(), 1) + + self.chip["PULSE_GEN"].start() + while not self.chip["PULSE_GEN"].is_done(): pass # get data from fifo - ret = self.chip['fifo'].get_fifo_size() + ret = self.chip["fifo"].get_fifo_size() self.assertEqual(ret, 3 * 4) - ret = self.chip['fifo'].get_data() + ret = self.chip["fifo"].get_data() self.assertEqual(len(ret), 3) # check with gpio - ret2 = self.chip['gpio'].get_data() + ret2 = self.chip["gpio"].get_data() self.assertEqual(len(ret2), 8) for i, r in enumerate(ret): self.assertEqual(r & 0xF0000000, 0x50000000) self.assertEqual(r & 0xF000000, 0x1000000 * (3 - i)) - self.assertEqual(ret[2] & 0xFFFFFF, 0x10000 * - ret2[5] + 0x100 * ret2[6] + ret2[7]) - self.assertEqual(ret[1] & 0xFFFFFF, 0x10000 * - ret2[2] + 0x100 * ret2[3] + ret2[4]) + self.assertEqual(ret[2] & 0xFFFFFF, 0x10000 * ret2[5] + 0x100 * ret2[6] + ret2[7]) + self.assertEqual(ret[1] & 0xFFFFFF, 0x10000 * ret2[2] + 0x100 * ret2[3] + ret2[4]) self.assertEqual(ret[1] & 0xFFFFFF, 0x100 * ret2[0] + ret2[1]) def tearDown(self): @@ -116,5 +113,5 @@ def tearDown(self): cocotb_compile_clean() -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/tests/test_SimTlu.py b/tests/test_SimTlu.py index d91b011ff..4af69303d 100644 --- a/tests/test_SimTlu.py +++ b/tests/test_SimTlu.py @@ -5,8 +5,8 @@ # ------------------------------------------------------------ # -import unittest import os +import unittest from basil.dut import Dut from basil.utils.sim.utils import cocotb_compile_and_run, cocotb_compile_clean @@ -51,221 +51,220 @@ class TestSimTlu(unittest.TestCase): def setUp(self): - cocotb_compile_and_run( - [os.path.join(os.path.dirname(__file__), 'test_SimTlu.v')]) + cocotb_compile_and_run([os.path.join(os.path.dirname(__file__), "test_SimTlu.v")]) self.chip = Dut(cnfg_yaml) self.chip.init() def test_simple_trigger_veto(self): - self.chip['TLU'].TRIGGER_COUNTER = 0 - self.chip['TLU'].TRIGGER_MODE = 0 - self.chip['TLU'].TRIGGER_SELECT = 2 - self.chip['TLU'].TRIGGER_VETO_SELECT = 2 - self.chip['TLU'].TRIGGER_ENABLE = True + self.chip["TLU"].TRIGGER_COUNTER = 0 + self.chip["TLU"].TRIGGER_MODE = 0 + self.chip["TLU"].TRIGGER_SELECT = 2 + self.chip["TLU"].TRIGGER_VETO_SELECT = 2 + self.chip["TLU"].TRIGGER_ENABLE = True - self.chip['GPIO'].set_data([0x06]) # assert trigger and veto signal - self.chip['GPIO'].set_data([0x00]) # de-assert trigger and veto signal + self.chip["GPIO"].set_data([0x06]) # assert trigger and veto signal + self.chip["GPIO"].set_data([0x00]) # de-assert trigger and veto signal - self.chip['GPIO'].set_data([0x02]) # assert trigger signal - self.chip['GPIO'].set_data([0x00]) # de-assert trigger signal + self.chip["GPIO"].set_data([0x02]) # assert trigger signal + self.chip["GPIO"].set_data([0x00]) # de-assert trigger signal - self.chip['TLU'].TRIGGER_ENABLE = False + self.chip["TLU"].TRIGGER_ENABLE = False - self.assertEqual(self.chip['FIFO'].get_FIFO_INT_SIZE(), 1) - self.assertEqual(self.chip['TLU'].TRIGGER_COUNTER, 1) + self.assertEqual(self.chip["FIFO"].get_FIFO_INT_SIZE(), 1) + self.assertEqual(self.chip["TLU"].TRIGGER_COUNTER, 1) - data = self.chip['FIFO'].get_data() + data = self.chip["FIFO"].get_data() self.assertEqual(data[0], 0x80000000 + 0) def test_simple_trigger_veto_disabled(self): - self.chip['TLU'].TRIGGER_COUNTER = 0 - self.chip['TLU'].TRIGGER_MODE = 0 - self.chip['TLU'].TRIGGER_SELECT = 2 - self.chip['TLU'].TRIGGER_VETO_SELECT = 252 - self.chip['TLU'].TRIGGER_ENABLE = True + self.chip["TLU"].TRIGGER_COUNTER = 0 + self.chip["TLU"].TRIGGER_MODE = 0 + self.chip["TLU"].TRIGGER_SELECT = 2 + self.chip["TLU"].TRIGGER_VETO_SELECT = 252 + self.chip["TLU"].TRIGGER_ENABLE = True - self.chip['GPIO'].set_data([0x06]) # assert trigger and veto signal - self.chip['GPIO'].set_data([0x00]) # de-assert trigger and veto signal + self.chip["GPIO"].set_data([0x06]) # assert trigger and veto signal + self.chip["GPIO"].set_data([0x00]) # de-assert trigger and veto signal - self.chip['GPIO'].set_data([0x02]) # assert trigger signal - self.chip['GPIO'].set_data([0x00]) # de-assert trigger signal + self.chip["GPIO"].set_data([0x02]) # assert trigger signal + self.chip["GPIO"].set_data([0x00]) # de-assert trigger signal - self.chip['TLU'].TRIGGER_ENABLE = False + self.chip["TLU"].TRIGGER_ENABLE = False - self.assertEqual(self.chip['FIFO'].get_FIFO_INT_SIZE(), 2) - self.assertEqual(self.chip['TLU'].TRIGGER_COUNTER, 2) + self.assertEqual(self.chip["FIFO"].get_FIFO_INT_SIZE(), 2) + self.assertEqual(self.chip["TLU"].TRIGGER_COUNTER, 2) - data = self.chip['FIFO'].get_data() + data = self.chip["FIFO"].get_data() self.assertEqual(data[0], 0x80000000 + 0) self.assertEqual(data[1], 0x80000000 + 1) def test_simple_trigger_threshold(self): - self.chip['TLU'].TRIGGER_COUNTER = 0 - self.chip['TLU'].TRIGGER_MODE = 0 + self.chip["TLU"].TRIGGER_COUNTER = 0 + self.chip["TLU"].TRIGGER_MODE = 0 # select short trigger (one clock cycle) - self.chip['TLU'].TRIGGER_SELECT = 4 - self.chip['TLU'].TRIGGER_THRESHOLD = 1 # at least one clock cycle - self.chip['TLU'].TRIGGER_ENABLE = True + self.chip["TLU"].TRIGGER_SELECT = 4 + self.chip["TLU"].TRIGGER_THRESHOLD = 1 # at least one clock cycle + self.chip["TLU"].TRIGGER_ENABLE = True - self.chip['GPIO'].set_data([0x02]) # assert trigger signal - self.chip['GPIO'].set_data([0x00]) # de-assert trigger signal + self.chip["GPIO"].set_data([0x02]) # assert trigger signal + self.chip["GPIO"].set_data([0x00]) # de-assert trigger signal - self.chip['GPIO'].set_data([0x02]) # assert trigger signal - self.chip['GPIO'].set_data([0x00]) # de-assert trigger signal + self.chip["GPIO"].set_data([0x02]) # assert trigger signal + self.chip["GPIO"].set_data([0x00]) # de-assert trigger signal - self.chip['TLU'].TRIGGER_ENABLE = False + self.chip["TLU"].TRIGGER_ENABLE = False - self.assertEqual(self.chip['FIFO'].get_FIFO_INT_SIZE(), 2) - self.assertEqual(self.chip['TLU'].TRIGGER_COUNTER, 2) + self.assertEqual(self.chip["FIFO"].get_FIFO_INT_SIZE(), 2) + self.assertEqual(self.chip["TLU"].TRIGGER_COUNTER, 2) - data = self.chip['FIFO'].get_data() + data = self.chip["FIFO"].get_data() self.assertEqual(data[0], 0x80000000 + 0) self.assertEqual(data[1], 0x80000000 + 1) - self.chip['TLU'].TRIGGER_COUNTER = 0 - self.chip['TLU'].TRIGGER_THRESHOLD = 2 # at least two clock cycles - self.chip['TLU'].TRIGGER_ENABLE = True + self.chip["TLU"].TRIGGER_COUNTER = 0 + self.chip["TLU"].TRIGGER_THRESHOLD = 2 # at least two clock cycles + self.chip["TLU"].TRIGGER_ENABLE = True - self.chip['GPIO'].set_data([0x02]) # assert trigger signal - self.chip['GPIO'].set_data([0x00]) # de-assert trigger signal + self.chip["GPIO"].set_data([0x02]) # assert trigger signal + self.chip["GPIO"].set_data([0x00]) # de-assert trigger signal - self.chip['GPIO'].set_data([0x02]) # assert trigger signal - self.chip['GPIO'].set_data([0x00]) # de-assert trigger signal + self.chip["GPIO"].set_data([0x02]) # assert trigger signal + self.chip["GPIO"].set_data([0x00]) # de-assert trigger signal - self.chip['TLU'].TRIGGER_ENABLE = False + self.chip["TLU"].TRIGGER_ENABLE = False - self.assertEqual(self.chip['FIFO'].get_FIFO_INT_SIZE(), 0) - self.assertEqual(self.chip['TLU'].TRIGGER_COUNTER, 0) + self.assertEqual(self.chip["FIFO"].get_FIFO_INT_SIZE(), 0) + self.assertEqual(self.chip["TLU"].TRIGGER_COUNTER, 0) def test_simple_trigger_max_triggers(self): - self.chip['TLU'].TRIGGER_COUNTER = 0 - self.chip['TLU'].MAX_TRIGGERS = 2 # max. 2 triggers - self.chip['TLU'].TRIGGER_MODE = 0 - self.chip['TLU'].TRIGGER_SELECT = 2 - self.chip['TLU'].TRIGGER_VETO_SELECT = 252 - self.chip['TLU'].TRIGGER_ENABLE = True + self.chip["TLU"].TRIGGER_COUNTER = 0 + self.chip["TLU"].MAX_TRIGGERS = 2 # max. 2 triggers + self.chip["TLU"].TRIGGER_MODE = 0 + self.chip["TLU"].TRIGGER_SELECT = 2 + self.chip["TLU"].TRIGGER_VETO_SELECT = 252 + self.chip["TLU"].TRIGGER_ENABLE = True - self.chip['GPIO'].set_data([0x02]) # assert trigger signal - self.chip['GPIO'].set_data([0x00]) # de-assert trigger signal + self.chip["GPIO"].set_data([0x02]) # assert trigger signal + self.chip["GPIO"].set_data([0x00]) # de-assert trigger signal - self.chip['GPIO'].set_data([0x02]) # assert trigger signal - self.chip['GPIO'].set_data([0x00]) # de-assert trigger signal + self.chip["GPIO"].set_data([0x02]) # assert trigger signal + self.chip["GPIO"].set_data([0x00]) # de-assert trigger signal - self.chip['GPIO'].set_data([0x02]) # assert trigger signal - self.chip['GPIO'].set_data([0x00]) # de-assert trigger signal + self.chip["GPIO"].set_data([0x02]) # assert trigger signal + self.chip["GPIO"].set_data([0x00]) # de-assert trigger signal - self.chip['GPIO'].set_data([0x02]) # assert trigger signal - self.chip['GPIO'].set_data([0x00]) # de-assert trigger signal + self.chip["GPIO"].set_data([0x02]) # assert trigger signal + self.chip["GPIO"].set_data([0x00]) # de-assert trigger signal - self.chip['TLU'].TRIGGER_ENABLE = False + self.chip["TLU"].TRIGGER_ENABLE = False - self.assertEqual(self.chip['FIFO'].get_FIFO_INT_SIZE(), 2) - self.assertEqual(self.chip['TLU'].TRIGGER_COUNTER, 2) + self.assertEqual(self.chip["FIFO"].get_FIFO_INT_SIZE(), 2) + self.assertEqual(self.chip["TLU"].TRIGGER_COUNTER, 2) - data = self.chip['FIFO'].get_data() + data = self.chip["FIFO"].get_data() self.assertEqual(data[0], 0x80000000 + 0) self.assertEqual(data[1], 0x80000000 + 1) def test_simple_trigger(self): - self.chip['TLU'].TRIGGER_COUNTER = 10 - self.chip['TLU'].TRIGGER_MODE = 0 - self.chip['TLU'].TRIGGER_SELECT = 1 - self.chip['TLU'].TRIGGER_VETO_SELECT = 0 - self.chip['TLU'].TRIGGER_ENABLE = True - self.chip['GPIO'].set_data([0x01]) # enable trigger/TLU FSM + self.chip["TLU"].TRIGGER_COUNTER = 10 + self.chip["TLU"].TRIGGER_MODE = 0 + self.chip["TLU"].TRIGGER_SELECT = 1 + self.chip["TLU"].TRIGGER_VETO_SELECT = 0 + self.chip["TLU"].TRIGGER_ENABLE = True + self.chip["GPIO"].set_data([0x01]) # enable trigger/TLU FSM readings = 0 - while (self.chip['FIFO'].get_FIFO_INT_SIZE() < 4 and readings < 10000): + while self.chip["FIFO"].get_FIFO_INT_SIZE() < 4 and readings < 10000: readings += 1 - self.chip['GPIO'].set_data([0x00]) # disable trigger/TLU FSM - self.chip['TLU'].TRIGGER_ENABLE = False + self.chip["GPIO"].set_data([0x00]) # disable trigger/TLU FSM + self.chip["TLU"].TRIGGER_ENABLE = False - self.assertGreaterEqual(self.chip['FIFO'].get_FIFO_INT_SIZE(), 4) - self.assertGreaterEqual(self.chip['TLU'].TRIGGER_COUNTER, 14) + self.assertGreaterEqual(self.chip["FIFO"].get_FIFO_INT_SIZE(), 4) + self.assertGreaterEqual(self.chip["TLU"].TRIGGER_COUNTER, 14) - data = self.chip['FIFO'].get_data() + data = self.chip["FIFO"].get_data() self.assertEqual(data[0], 0x80000000 + 10) self.assertEqual(data[1], 0x80000000 + 11) self.assertEqual(data[2], 0x80000000 + 12) self.assertEqual(data[3], 0x80000000 + 13) def test_manual_soft_trigger(self): - self.chip['TLU'].TRIGGER_COUNTER = 10 - self.chip['TLU'].TRIGGER_MODE = 0 - self.chip['TLU'].TRIGGER_SELECT = 0 - self.chip['TLU'].TRIGGER_VETO_SELECT = 0 - self.chip['TLU'].TRIGGER_ENABLE = True + self.chip["TLU"].TRIGGER_COUNTER = 10 + self.chip["TLU"].TRIGGER_MODE = 0 + self.chip["TLU"].TRIGGER_SELECT = 0 + self.chip["TLU"].TRIGGER_VETO_SELECT = 0 + self.chip["TLU"].TRIGGER_ENABLE = True for i in range(4): - self.chip['TLU'].SOFT_TRIGGER = 1 + self.chip["TLU"].SOFT_TRIGGER = 1 readings = 0 - while (self.chip['FIFO'].get_FIFO_INT_SIZE() <= i and readings < 10000): + while self.chip["FIFO"].get_FIFO_INT_SIZE() <= i and readings < 10000: readings += 1 - self.chip['TLU'].TRIGGER_ENABLE = False - self.assertGreaterEqual(self.chip['FIFO'].get_FIFO_INT_SIZE(), 4) - self.assertGreaterEqual(self.chip['TLU'].TRIGGER_COUNTER, 14) + self.chip["TLU"].TRIGGER_ENABLE = False + self.assertGreaterEqual(self.chip["FIFO"].get_FIFO_INT_SIZE(), 4) + self.assertGreaterEqual(self.chip["TLU"].TRIGGER_COUNTER, 14) - data = self.chip['FIFO'].get_data() + data = self.chip["FIFO"].get_data() self.assertEqual(data[0], 0x80000000 + 10) self.assertEqual(data[1], 0x80000000 + 11) self.assertEqual(data[2], 0x80000000 + 12) self.assertEqual(data[3], 0x80000000 + 13) def test_tlu_trigger_handshake(self): - self.chip['TLU'].TRIGGER_COUNTER = 0 - self.chip['TLU'].TRIGGER_MODE = 3 + self.chip["TLU"].TRIGGER_COUNTER = 0 + self.chip["TLU"].TRIGGER_MODE = 3 # not used when EN_TLU_VETO is False - self.chip['TLU'].TRIGGER_VETO_SELECT = 255 - self.chip['TLU'].EN_TLU_VETO = 0 -# self.chip['TLU'].DATA_FORMAT = 2 -# self.chip['TLU'].TRIGGER_LOW_TIMEOUT = 5 -# self.chip['TLU'].TRIGGER_HANDSHAKE_ACCEPT_WAIT_CYCLES = 0 -# self.chip['TLU'].HANDSHAKE_BUSY_VETO_WAIT_CYCLES = 0 - self.chip['TLU'].TRIGGER_ENABLE = True - self.chip['GPIO'].set_data([0x01]) + self.chip["TLU"].TRIGGER_VETO_SELECT = 255 + self.chip["TLU"].EN_TLU_VETO = 0 + # self.chip['TLU'].DATA_FORMAT = 2 + # self.chip['TLU'].TRIGGER_LOW_TIMEOUT = 5 + # self.chip['TLU'].TRIGGER_HANDSHAKE_ACCEPT_WAIT_CYCLES = 0 + # self.chip['TLU'].HANDSHAKE_BUSY_VETO_WAIT_CYCLES = 0 + self.chip["TLU"].TRIGGER_ENABLE = True + self.chip["GPIO"].set_data([0x01]) readings = 0 - while (self.chip['FIFO'].get_FIFO_INT_SIZE() < 4 and readings < 1000): + while self.chip["FIFO"].get_FIFO_INT_SIZE() < 4 and readings < 1000: readings += 1 - self.chip['GPIO'].set_data([0x00]) # disable trigger/TLU FSM - self.chip['TLU'].TRIGGER_ENABLE = False + self.chip["GPIO"].set_data([0x00]) # disable trigger/TLU FSM + self.chip["TLU"].TRIGGER_ENABLE = False - self.assertGreaterEqual(self.chip['FIFO'].get_FIFO_INT_SIZE(), 4) - self.assertGreaterEqual(self.chip['TLU'].TRIGGER_COUNTER, 4) - self.assertGreaterEqual(self.chip['TLU'].CURRENT_TLU_TRIGGER_NUMBER, 3) + self.assertGreaterEqual(self.chip["FIFO"].get_FIFO_INT_SIZE(), 4) + self.assertGreaterEqual(self.chip["TLU"].TRIGGER_COUNTER, 4) + self.assertGreaterEqual(self.chip["TLU"].CURRENT_TLU_TRIGGER_NUMBER, 3) - data = self.chip['FIFO'].get_data() + data = self.chip["FIFO"].get_data() self.assertEqual(data[0], 0x80000000) self.assertEqual(data[1], 0x80000001) self.assertEqual(data[2], 0x80000002) self.assertEqual(data[3], 0x80000003) def test_tlu_trigger_handshake_veto(self): - self.chip['TLU'].TRIGGER_COUNTER = 0 - self.chip['TLU'].TRIGGER_MODE = 3 + self.chip["TLU"].TRIGGER_COUNTER = 0 + self.chip["TLU"].TRIGGER_MODE = 3 # used when EN_TLU_VETO is True - self.chip['TLU'].TRIGGER_VETO_SELECT = 255 - self.chip['TLU'].EN_TLU_VETO = 1 - self.chip['TLU'].TRIGGER_ENABLE = True - self.chip['GPIO'].set_data([0x01]) # enable trigger/TLU FSM + self.chip["TLU"].TRIGGER_VETO_SELECT = 255 + self.chip["TLU"].EN_TLU_VETO = 1 + self.chip["TLU"].TRIGGER_ENABLE = True + self.chip["GPIO"].set_data([0x01]) # enable trigger/TLU FSM readings = 0 - while (self.chip['FIFO'].get_FIFO_INT_SIZE() == 0 and readings < 1000): + while self.chip["FIFO"].get_FIFO_INT_SIZE() == 0 and readings < 1000: readings += 1 - self.assertEqual(self.chip['FIFO'].get_FIFO_INT_SIZE(), 0) - self.assertEqual(self.chip['TLU'].TRIGGER_COUNTER, 0) - self.assertEqual(self.chip['TLU'].CURRENT_TLU_TRIGGER_NUMBER, 0) + self.assertEqual(self.chip["FIFO"].get_FIFO_INT_SIZE(), 0) + self.assertEqual(self.chip["TLU"].TRIGGER_COUNTER, 0) + self.assertEqual(self.chip["TLU"].CURRENT_TLU_TRIGGER_NUMBER, 0) def tearDown(self): self.chip.close() # let it close connection and stop simulator cocotb_compile_clean() -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/tests/test_StdRegister.py b/tests/test_StdRegister.py index d443a0deb..e4ec1535e 100644 --- a/tests/test_StdRegister.py +++ b/tests/test_StdRegister.py @@ -6,13 +6,12 @@ # import unittest -import yaml +import yaml from bitarray import bitarray from basil.dut import Dut - cnfg_yaml = """ transfer_layer: - name : dummy_tl @@ -63,204 +62,203 @@ class TestClass(unittest.TestCase): - @classmethod def setUpClass(cls): cls.cnfg = yaml.safe_load(cnfg_yaml) cls.dut = Dut(cls.cnfg) - cls.dut['spi_module']._require_version = "==2" + cls.dut["spi_module"]._require_version = "==2" cls.dut.init() - cls.dut['spi_module']._mem_bytes = 4 + cls.dut["spi_module"]._mem_bytes = 4 def test_mem_bytes(self): self.dut.init() - self.dut['spi_module']._mem_bytes = 4 - self.assertEqual(4, self.dut['spi_module'].MEM_BYTES) - self.assertRaises(ValueError, self.dut['spi_module'].set_data, [1, 2, 3, 4, 5]) + self.dut["spi_module"]._mem_bytes = 4 + self.assertEqual(4, self.dut["spi_module"].MEM_BYTES) + self.assertRaises(ValueError, self.dut["spi_module"].set_data, [1, 2, 3, 4, 5]) def test_init_simple(self): - self.dut['TEST1'].write() + self.dut["TEST1"].write() mem = dict() -# mem[0] = 0 # reset -# mem[0] = 1 + # mem[0] = 0 # reset + # mem[0] = 1 mem[16] = 0 # has an offset of 16 bytes mem[17] = 0 mem[18] = 0 mem[19] = 0 - self.assertDictEqual(mem, self.dut['dummy_tl'].mem) + self.assertDictEqual(mem, self.dut["dummy_tl"].mem) - self.dut['TEST1'][0] = 1 - self.dut['TEST1'].write() + self.dut["TEST1"][0] = 1 + self.dut["TEST1"].write() mem[19] = 1 - self.assertDictEqual(mem, self.dut['dummy_tl'].mem) + self.assertDictEqual(mem, self.dut["dummy_tl"].mem) - self.dut['TEST1'][31] = 1 - self.dut['TEST1'].write() + self.dut["TEST1"][31] = 1 + self.dut["TEST1"].write() mem[16] = 0x80 - self.assertDictEqual(mem, self.dut['dummy_tl'].mem) + self.assertDictEqual(mem, self.dut["dummy_tl"].mem) - self.dut['TEST1'] = 0 - self.dut['TEST1'].write() + self.dut["TEST1"] = 0 + self.dut["TEST1"].write() mem[16] = 0 mem[19] = 0 - self.assertDictEqual(mem, self.dut['dummy_tl'].mem) + self.assertDictEqual(mem, self.dut["dummy_tl"].mem) - self.dut['TEST1'] = 0xa55a8001 - self.dut['TEST1'].write() - mem[16] = 0xa5 - mem[17] = 0x5a + self.dut["TEST1"] = 0xA55A8001 + self.dut["TEST1"].write() + mem[16] = 0xA5 + mem[17] = 0x5A mem[18] = 0x80 mem[19] = 0x01 - self.assertDictEqual(mem, self.dut['dummy_tl'].mem) + self.assertDictEqual(mem, self.dut["dummy_tl"].mem) - self.dut['TEST1'] = 0 - self.dut['TEST1'][11:4] = 0xff - self.dut['TEST1'].write() + self.dut["TEST1"] = 0 + self.dut["TEST1"][11:4] = 0xFF + self.dut["TEST1"].write() mem[16] = 0x0 mem[17] = 0x0 - mem[18] = 0x0f - mem[19] = 0xf0 - self.assertDictEqual(mem, self.dut['dummy_tl'].mem) + mem[18] = 0x0F + mem[19] = 0xF0 + self.assertDictEqual(mem, self.dut["dummy_tl"].mem) - self.dut['TEST1'] = 0 - self.dut['TEST1'][11:4] = '10000001' - self.dut['TEST1'].write() + self.dut["TEST1"] = 0 + self.dut["TEST1"][11:4] = "10000001" + self.dut["TEST1"].write() mem[16] = 0x0 mem[17] = 0x0 mem[18] = 0x08 mem[19] = 0x10 - self.assertDictEqual(mem, self.dut['dummy_tl'].mem) + self.assertDictEqual(mem, self.dut["dummy_tl"].mem) - self.dut['TEST1'] = 0 - self.dut['TEST1'][11:4] = bitarray('00011000') - self.dut['TEST1'].write() + self.dut["TEST1"] = 0 + self.dut["TEST1"][11:4] = bitarray("00011000") + self.dut["TEST1"].write() mem[16] = 0x0 mem[17] = 0x0 mem[18] = 0x01 mem[19] = 0x80 - self.assertDictEqual(mem, self.dut['dummy_tl'].mem) + self.assertDictEqual(mem, self.dut["dummy_tl"].mem) def test_bit_order(self): - self.dut['TEST2'].write() + self.dut["TEST2"].write() mem = dict() -# mem[0] = 0 # reset + # mem[0] = 0 # reset mem[0] = 2 mem[14] = 4 mem[16] = 0 mem[17] = 0 mem[18] = 0 - self.assertDictEqual(mem, self.dut['dummy_tl'].mem) + self.assertDictEqual(mem, self.dut["dummy_tl"].mem) - self.dut['TEST2']['VINJECT'] = 0x01 - self.dut['TEST2'].write() + self.dut["TEST2"]["VINJECT"] = 0x01 + self.dut["TEST2"].write() mem[16] = 0x08 - self.assertDictEqual(mem, self.dut['dummy_tl'].mem) + self.assertDictEqual(mem, self.dut["dummy_tl"].mem) - self.dut['TEST2']['VINJECT'] = 0x02 - self.dut['TEST2'].write() + self.dut["TEST2"]["VINJECT"] = 0x02 + self.dut["TEST2"].write() mem[16] = 0x10 - self.assertDictEqual(mem, self.dut['dummy_tl'].mem) + self.assertDictEqual(mem, self.dut["dummy_tl"].mem) - self.dut['TEST2']['VINJECT'] = 0x04 - self.dut['TEST2'].write() + self.dut["TEST2"]["VINJECT"] = 0x04 + self.dut["TEST2"].write() mem[16] = 0x04 - self.assertDictEqual(mem, self.dut['dummy_tl'].mem) + self.assertDictEqual(mem, self.dut["dummy_tl"].mem) - self.dut['TEST2']['VINJECT'] = 0x08 - self.dut['TEST2'].write() + self.dut["TEST2"]["VINJECT"] = 0x08 + self.dut["TEST2"].write() mem[16] = 0x20 - self.assertDictEqual(mem, self.dut['dummy_tl'].mem) + self.assertDictEqual(mem, self.dut["dummy_tl"].mem) - self.dut['TEST2']['VINJECT'] = 0 - self.dut['TEST2']['VINJECT'][0] = 1 - self.dut['TEST2'].write() + self.dut["TEST2"]["VINJECT"] = 0 + self.dut["TEST2"]["VINJECT"][0] = 1 + self.dut["TEST2"].write() mem[16] = 0x04 - self.assertDictEqual(mem, self.dut['dummy_tl'].mem) + self.assertDictEqual(mem, self.dut["dummy_tl"].mem) def test_repeat(self): - self.dut['dummy_tl'].mem = dict() -# self.dut['TEST2'] = 0 - self.dut['TEST2']['VINJECT'] = 0 - self.dut['TEST2']['VPULSE'] = 0 - self.dut['TEST2'].write() + self.dut["dummy_tl"].mem = dict() + # self.dut['TEST2'] = 0 + self.dut["TEST2"]["VINJECT"] = 0 + self.dut["TEST2"]["VPULSE"] = 0 + self.dut["TEST2"].write() mem = dict() -# mem[0] = 1 + # mem[0] = 1 mem[16] = 0 mem[17] = 0 mem[18] = 0 - self.assertDictEqual(mem, self.dut['dummy_tl'].mem) + self.assertDictEqual(mem, self.dut["dummy_tl"].mem) - self.dut['TEST2']['COLUMN'][0]['EnR'] = 1 - self.dut['TEST2'].write() + self.dut["TEST2"]["COLUMN"][0]["EnR"] = 1 + self.dut["TEST2"].write() mem[17] = 0x02 - self.assertDictEqual(mem, self.dut['dummy_tl'].mem) + self.assertDictEqual(mem, self.dut["dummy_tl"].mem) - self.dut['TEST2']['COLUMN'][1]['DACR'] = 1 - self.dut['TEST2'].write() + self.dut["TEST2"]["COLUMN"][1]["DACR"] = 1 + self.dut["TEST2"].write() mem[18] = 0x10 - self.assertDictEqual(mem, self.dut['dummy_tl'].mem) + self.assertDictEqual(mem, self.dut["dummy_tl"].mem) def test_default(self): - self.cnfg['registers'][1]['fields'][0]['default'] = 0x01 # VINJECT + self.cnfg["registers"][1]["fields"][0]["default"] = 0x01 # VINJECT self.dut = Dut(self.cnfg) - self.dut['spi_module']._require_version = "==2" + self.dut["spi_module"]._require_version = "==2" self.dut.init() - self.dut['spi_module']._mem_bytes = 32 + self.dut["spi_module"]._mem_bytes = 32 mem = dict() -# mem[0] = 0 # reset + # mem[0] = 0 # reset mem[0] = 2 mem[14] = 4 mem[16] = 0x08 mem[17] = 0 mem[18] = 0 - self.dut['TEST2'].write() - self.assertDictEqual(mem, self.dut['dummy_tl'].mem) + self.dut["TEST2"].write() + self.assertDictEqual(mem, self.dut["dummy_tl"].mem) def test_fields(self): - self.dut['dummy_tl'].mem = dict() - self.dut['TEST2']['VINJECT'] = 0 - self.dut['TEST2']['VPULSE'] = 0 - self.dut['TEST2'].write() + self.dut["dummy_tl"].mem = dict() + self.dut["TEST2"]["VINJECT"] = 0 + self.dut["TEST2"]["VPULSE"] = 0 + self.dut["TEST2"].write() mem = dict() -# mem[0] = 1 + # mem[0] = 1 mem[16] = 0 mem[17] = 0 mem[18] = 0 - self.assertDictEqual(mem, self.dut['dummy_tl'].mem) + self.assertDictEqual(mem, self.dut["dummy_tl"].mem) - self.dut['TEST2']['VPULSE'] = 0x5 - self.dut['TEST2'].write() + self.dut["TEST2"]["VPULSE"] = 0x5 + self.dut["TEST2"].write() mem = dict() mem[16] = 0 mem[17] = 0x50 mem[18] = 0 - self.assertDictEqual(mem, self.dut['dummy_tl'].mem) + self.assertDictEqual(mem, self.dut["dummy_tl"].mem) - self.dut['TEST2']['VPULSE'] = bitarray('100001') - self.dut['TEST2'].write() + self.dut["TEST2"]["VPULSE"] = bitarray("100001") + self.dut["TEST2"].write() mem = dict() mem[16] = 0x02 mem[17] = 0x10 mem[18] = 0 - self.assertDictEqual(mem, self.dut['dummy_tl'].mem) + self.assertDictEqual(mem, self.dut["dummy_tl"].mem) - self.dut['TEST2']['VPULSE'] = '100001' - self.dut['TEST2'].write() + self.dut["TEST2"]["VPULSE"] = "100001" + self.dut["TEST2"].write() mem = dict() mem[16] = 0x02 mem[17] = 0x10 mem[18] = 0 - self.assertDictEqual(mem, self.dut['dummy_tl'].mem) + self.assertDictEqual(mem, self.dut["dummy_tl"].mem) - self.dut['TEST2']['VPULSE'] = 0b100011 - self.dut['TEST2'].write() + self.dut["TEST2"]["VPULSE"] = 0b100011 + self.dut["TEST2"].write() mem = dict() mem[16] = 0x02 mem[17] = 0x30 mem[18] = 0 - self.assertDictEqual(mem, self.dut['dummy_tl'].mem) + self.assertDictEqual(mem, self.dut["dummy_tl"].mem) -if __name__ == '__main__': +if __name__ == "__main__": suite = unittest.TestLoader().loadTestsFromTestCase(TestClass) unittest.TextTestRunner(verbosity=2).run(suite)