Commit 4f4c7495 authored by Federico Vaga's avatar Federico Vaga

Merge branch 'pytest-improvements' into 'master'

tst: add python requirements

See merge request be-cem-edl/fec/hardware-modules/fmc-tdc-1ns-5cha!25
parents f313382e 0fc85b0f
...@@ -12,7 +12,17 @@ include: ...@@ -12,7 +12,17 @@ include:
ref: master ref: master
file: file:
- 'edl-gitlab-ci.yml' - 'edl-gitlab-ci.yml'
- local: 'hdl/syn/.gitlab-ci.yml'
python-style:
variables:
FF_KUBERNETES_HONOR_ENTRYPOINT: 1 # Make Gitlab K8s executors to respect entrypoint in Acc-Py images, https://cern.service-now.com/service-portal?id=ticket&table=incident&n=INC3570437
stage: analyse
image:
name: gitlab-registry.cern.ch/acc-co/devops/python/distribution-images/acc-py_cc7:pro
before_script:
- pip install pycodestyle
script:
- pycodestyle --ignore=E501 pytest/ software/lib/PyFmcTdc/
cppcheck: cppcheck:
stage: analyse stage: analyse
...@@ -40,3 +50,12 @@ kernel_build_validation: ...@@ -40,3 +50,12 @@ kernel_build_validation:
echo "Checking Dependencies" echo "Checking Dependencies"
if [ "$FMC_BUILDS" != "0" ]; then echo 'FMC did not build successfully. Exiting'; exit 1; fi if [ "$FMC_BUILDS" != "0" ]; then echo 'FMC did not build successfully. Exiting'; exit 1; fi
if [ "$ZIO_BUILDS" != "0" ]; then echo 'ZIO did not build successfully. Exiting'; exit 1; fi if [ "$ZIO_BUILDS" != "0" ]; then echo 'ZIO did not build successfully. Exiting'; exit 1; fi
fpga_synthesis:
extends: .synthesis-ise-14-7
interruptible: true
parallel:
matrix:
- EDL_CI_SYN_SRC_PATH:
- hdl/syn/spec
- hdl/syn/svec
# SPDX-FileCopyrightText: 2022 CERN (home.cern)
#
# SPDX-License-Identifier: LGPL-2.1-or-later
variables:
_FMC_TDC_BITSTREAM_DEST: $CI_PROJECT_DIR/$EDL_CI_EOS_OUTPUT_DIR/bitstreams
.syn_template: &syn_template
interruptible: true
stage: build
needs: []
tags:
- xilinx_ise
- "14.7"
script:
- git submodule init && git submodule update
- cd hdl/syn/"$SYN_NAME"/
- hdlmake
- make
- |
if [[ $(cat *.par | grep -c "All constraints were met") = 0 ]]
then
echo -e "\e[31mTiming errors detected in PAR report. Aborting...\e[0m"
exit 1
fi
- tar -cJf $SYN_NAME.tar.xz *.syr *.par *.twr *.bit *.bin
- mkdir -p $_FMC_TDC_BITSTREAM_DEST
- cp $SYN_NAME.tar.xz $_FMC_TDC_BITSTREAM_DEST
artifacts:
name: "$SYN_NAME-synthesis-$CI_JOB_NAME-$CI_COMMIT_REF_NAME"
paths:
- $_FMC_TDC_BITSTREAM_DEST/*
SPEC synthesis:
variables:
SYN_NAME: "spec"
<<: *syn_template
SVEC synthesis:
variables:
SYN_NAME: "svec"
<<: *syn_template
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
SPDX-License-Identifier: LGPL-2.1-or-later SPDX-License-Identifier: LGPL-2.1-or-later
SPDX-FileCopyrightText: 2020 CERN SPDX-FileCopyrightText: 2020 CERN
""" """
from pathlib import Path
import pytest import pytest
import subprocess import subprocess
import time import time
...@@ -10,6 +10,48 @@ import re ...@@ -10,6 +10,48 @@ import re
import os import os
from PyFmcTdc import FmcTdc from PyFmcTdc import FmcTdc
def valid_slot_type(slot):
if re.search(r"(VME|PCI)\.[0-9]+-FMC\.[0-9]+", slot) is None:
raise ValueError()
return slot
def id_from_slot(slot, name):
carrier, mezzanine = slot.split("-")
carrier_bus, carrier_slot = carrier.split(".")
carrier_slot = int(carrier_slot)
mezzanine_bus, mezzanine_slot = mezzanine.split(".")
mezzanine_slot = int(mezzanine_slot)
if carrier_bus == "PCI":
with open("/run/dynpci") as f:
for line in f.readlines():
dynslot, pciid = line.strip().split(" ")
if int(dynslot) == carrier_slot:
break
pciid = f"0000:{pciid}"
pathfmc = list(Path("/sys/bus/pci/devices").joinpath(pciid)
.glob(f"spec-*/id:*/{name}.*.auto/fmc-slot-*.{mezzanine_slot}"))
elif carrier_bus == "VME":
pathfmc = list(Path("/sys/bus/vme/devices").joinpath(f"slot.{carrier_slot:02d}")
.joinpath(f"vme.{carrier_slot:02d}")
.glob(f"svec-*/svec-*/id:*/{name}.*.auto/fmc-slot-*.{mezzanine_slot}"))
else:
raise ValueError()
assert len(pathfmc) == 1
devname = list(Path(pathfmc[0]).parent.glob("hw-*/*-????/devname"))
assert len(devname) == 1
with open(devname[0]) as f:
fd_id = int(f.read().strip().split("-")[-1], 16)
return fd_id
def pytest_generate_tests(metafunc):
if "fd_tdc_id" in metafunc.fixturenames:
metafunc.parametrize("fd_tdc_id", pytest.fd_tdc_id)
class PulseGenerator(object): class PulseGenerator(object):
def __init__(self, id): def __init__(self, id):
self.id = id self.id = id
...@@ -20,13 +62,14 @@ class PulseGenerator(object): ...@@ -20,13 +62,14 @@ class PulseGenerator(object):
period_ns, count, sync): period_ns, count, sync):
pass pass
class SCPI(PulseGenerator): class SCPI(PulseGenerator):
def __init__(self, scpi_id): def __init__(self, scpi_id):
super(SCPI, self).__init__(scpi_id) super(SCPI, self).__init__(scpi_id)
import pyvisa import pyvisa
self.mgr = pyvisa.ResourceManager() self.mgr = pyvisa.ResourceManager()
self.instr = self.mgr.open_resource(self.id) self.instr = self.mgr.open_resource(self.id)
self.instr.query_delay=0 self.instr.query_delay = 0
self.instr.timeout = 10000 self.instr.timeout = 10000
self.instr.read_termination = '\n' self.instr.read_termination = '\n'
self.instr.write_termination = '\n' self.instr.write_termination = '\n'
...@@ -55,7 +98,7 @@ class SCPI(PulseGenerator): ...@@ -55,7 +98,7 @@ class SCPI(PulseGenerator):
# START Custom Agilent 33600A commands # START Custom Agilent 33600A commands
self.instr.write("TRIGGER:DELAY {:d}e-6".format(rel_time_us)) self.instr.write("TRIGGER:DELAY {:d}e-6".format(rel_time_us))
burst_period_ns = int(count/(1/period_ns)) + 500 burst_period_ns = int(count / (1 / period_ns)) + 500
self.instr.write("SOURCE:BURST:INTERNAL:PERIOD {:d}ns".format(burst_period_ns)) self.instr.write("SOURCE:BURST:INTERNAL:PERIOD {:d}ns".format(burst_period_ns))
self.instr.write("SOURCE:BURST:NCYCLES {:d}".format(count)) self.instr.write("SOURCE:BURST:NCYCLES {:d}".format(count))
self.instr.write("SOURCE:BURST:STATE ON") self.instr.write("SOURCE:BURST:STATE ON")
...@@ -67,6 +110,7 @@ class SCPI(PulseGenerator): ...@@ -67,6 +110,7 @@ class SCPI(PulseGenerator):
if sync: if sync:
self.instr.query_ascii_values("*OPC?") self.instr.query_ascii_values("*OPC?")
class FmcFineDelay(PulseGenerator): class FmcFineDelay(PulseGenerator):
CHANNEL_NUMBER = 4 CHANNEL_NUMBER = 4
...@@ -74,7 +118,7 @@ class FmcFineDelay(PulseGenerator): ...@@ -74,7 +118,7 @@ class FmcFineDelay(PulseGenerator):
super(FmcFineDelay, self).__init__(fd_id) super(FmcFineDelay, self).__init__(fd_id)
def disable(self, ch): def disable(self, ch):
cmd = ["/usr/local/bin/fmc-fdelay-pulse", cmd = ["fmc-fdelay-pulse",
"-d", "0x{:x}".format(self.id), "-d", "0x{:x}".format(self.id),
"-o", str(ch), "-o", str(ch),
"-m", "disable", "-m", "disable",
...@@ -84,13 +128,13 @@ class FmcFineDelay(PulseGenerator): ...@@ -84,13 +128,13 @@ class FmcFineDelay(PulseGenerator):
def generate_pulse(self, ch, rel_time_us, def generate_pulse(self, ch, rel_time_us,
period_ns, count, sync): period_ns, count, sync):
cmd = ["/usr/local/bin/fmc-fdelay-pulse", cmd = ["fmc-fdelay-pulse",
"-d", "0x{:x}".format(self.id), "-d", "0x{:x}".format(self.id),
"-o", str(ch), "-o", str(ch),
"-m", "pulse", "-m", "pulse",
"-r", "{:d}u".format(rel_time_us), "-r", "{:d}u".format(rel_time_us),
"-T", "{:d}n".format(period_ns), "-T", "{:d}n".format(period_ns),
"-w", "{:d}n".format(int(period_ns/2)), "-w", "{:d}n".format(int(period_ns / 2)),
"-c", str(count), "-c", str(count),
"-t" "-t"
] ]
...@@ -99,38 +143,51 @@ class FmcFineDelay(PulseGenerator): ...@@ -99,38 +143,51 @@ class FmcFineDelay(PulseGenerator):
if sync: if sync:
time.sleep(1 + 2 * (period_ns * count) / 1000000000.0) time.sleep(1 + 2 * (period_ns * count) / 1000000000.0)
@pytest.fixture(scope="module")
def fmcfd():
if pytest.fd_id is not None:
gen = FmcFineDelay(pytest.fd_id)
elif pytest.scpi is not None:
gen = SCPI(pytest.scpi)
yield gen
if isinstance(gen, FmcFineDelay):
for ch in range(FmcFineDelay.CHANNEL_NUMBER):
gen.disable(ch + 1)
elif isinstance(gen, SCPI):
gen.disable(0)
@pytest.fixture(scope="function") @pytest.fixture(scope="function")
def fmctdc(): def tdc_and_gen(fd_tdc_id):
tdc = FmcTdc(pytest.tdc_id) fd_id, tdc_id = fd_tdc_id
gen = FmcFineDelay(fd_id)
for ch in range(FmcFineDelay.CHANNEL_NUMBER):
gen.disable(ch + 1)
tdc = FmcTdc(tdc_id)
for ch in tdc.chan: for ch in tdc.chan:
ch.enable = False ch.enable = False
ch.termination = False ch.termination = False
ch.timestamp_mode = "post" ch.timestamp_mode = "post"
ch.flush() ch.flush()
yield (gen, tdc)
for ch in range(FmcFineDelay.CHANNEL_NUMBER):
gen.disable(ch + 1)
for ch in tdc.chan:
ch.enable = False
ch.termination = False
ch.timestamp_mode = "post"
ch.flush()
@pytest.fixture(scope="function")
def fmcfd(tdc_and_gen):
fd, tdc = tdc_and_gen
yield fd
@pytest.fixture(scope="function")
def fmctdc(tdc_and_gen):
fd, tdc = tdc_and_gen
yield tdc yield tdc
def pytest_addoption(parser): def pytest_addoption(parser):
parser.addoption("--tdc-id", type=lambda x : int(x, 16), parser.addoption("--tdc-id", type=lambda x: int(x, 16), action="append",
required=True, help="Fmc TDC Linux Identifier") default=[], help="Fmc TDC Linux Identifier")
parser.addoption("--fd-id", type=lambda x : int(x, 16), default=None, parser.addoption("--slot-tdc", type=valid_slot_type, action='append',
help="Fmc Fine-Delay Linux Identifier") default=[], help="Fmc TDC absolute slot (works only for SPEC and SVEC)")
parser.addoption("--scpi", type=str, default=None, parser.addoption("--fd-id", type=lambda x: int(x, 16), action="append",
help="SCPI Connection String") default=[], help="Fmc Fine-Delay Linux Identifier")
parser.addoption("--slot-fd", type=valid_slot_type, action='append',
default=[], help="Fmc Fine-Delay absolute slot (works only for SPEC and SVEC)")
parser.addoption("--dump-range", type=int, default=10, parser.addoption("--dump-range", type=int, default=10,
help="Timestamps to show before and after an error") help="Timestamps to show before and after an error")
parser.addoption("--channel", type=int, default=[], parser.addoption("--channel", type=int, default=[],
...@@ -141,33 +198,60 @@ def pytest_addoption(parser): ...@@ -141,33 +198,60 @@ def pytest_addoption(parser):
parser.addoption("--usr-acq-period-ns", type=int, default=0, parser.addoption("--usr-acq-period-ns", type=int, default=0,
help="Pulses period (ns) during a acquisition test.") help="Pulses period (ns) during a acquisition test.")
def id_list_get(config, opt_id, opt_slot, devname):
id_list = config.getoption(opt_id)
if len(id_list) == 0:
slot = config.getoption(opt_slot)
if len(slot) == 0:
print(f"Missing argument {opt_id} or {opt_slot}")
raise Exception()
id_list = []
for slot in slot:
id_list.append(id_from_slot(slot, devname))
return id_list
def pytest_configure(config): def pytest_configure(config):
pytest.tdc_id = config.getoption("--tdc-id") pytest.tdc_id = id_list_get(config, "--tdc-id", "--slot-tdc", "fmc-tdc")
pytest.fd_id = config.getoption("--fd-id") pytest.fd_id = id_list_get(config, "--fd-id", "--slot-fd", "fmc-fdelay-tdc")
pytest.scpi = config.getoption("--scpi")
if pytest.scpi is None and pytest.fd_id is None: if len(pytest.tdc_id) != len(pytest.fd_id):
raise Exception("You must set --fd-id or --scpi") print("For each --fd-id there must be a --tdc-id")
raise Exception()
pytest.fd_tdc_id = list(zip(pytest.fd_id, pytest.tdc_id))
pytest.channels = config.getoption("--channel") pytest.channels = config.getoption("--channel")
if len(pytest.channels) == 0: if len(pytest.channels) == 0:
pytest.channels = range(FmcTdc.CHANNEL_NUMBER) pytest.channels = range(FmcTdc.CHANNEL_NUMBER)
if len(pytest.channels) != 1 and pytest.scpi is not None:
raise Exception("With --scpi we can test only the channel connected to the Waveform generator. Set --channel")
pytest.usr_acq = (config.getoption("--usr-acq-period-ns"), pytest.usr_acq = (config.getoption("--usr-acq-period-ns"),
config.getoption("--usr-acq-count")) config.getoption("--usr-acq-count"))
pytest.dump_range = config.getoption("--dump-range") pytest.dump_range = config.getoption("--dump-range")
pytest.transfer_mode = None pytest.transfer_mode = None
with open("/sys/bus/zio/devices/tdc-1n5c-{:04x}/transfer-mode".format(pytest.tdc_id)) as f_mode: modes = []
mode = int(f_mode.read().rstrip()) for tdc_id in pytest.tdc_id:
for k, v in FmcTdc.TRANSFER_MODE.items(): with open(f"/sys/bus/zio/devices/tdc-1n5c-{tdc_id:04x}/transfer-mode") as f_mode:
if mode == v: modes.append(int(f_mode.read().rstrip()))
pytest.transfer_mode = k mode = set(modes)
if len(mode) != 1:
print("Inconsistent transfer mode across devices")
raise Exception()
for k, v in FmcTdc.TRANSFER_MODE.items():
if v in mode:
pytest.transfer_mode = k
pytest.carrier = None pytest.carrier = None
full_path = os.readlink("/sys/bus/zio/devices/tdc-1n5c-{:04x}".format(pytest.tdc_id)) carrs = []
for carr in ["spec", "svec"]: for tdc_id in pytest.tdc_id:
is_carr = re.search(carr, full_path) full_path = os.readlink("/sys/bus/zio/devices/tdc-1n5c-{:04x}".format(tdc_id))
if is_carr is not None: for carr in ["spec", "svec"]:
is_carr = re.search(carr, full_path)
if is_carr is None:
continue
if pytest.carrier is not None and pytest.carrier != carr:
print("Inconsistent installation mix of SPEC and SVEC")
raise Exception()
pytest.carrier = carr pytest.carrier = carr
# SPDX-FileCopyrightText: 2023 CERN (home.cern)
#
# SPDX-License-Identifier: LGPL-2.1-or-later
pytest
...@@ -7,6 +7,7 @@ import pytest ...@@ -7,6 +7,7 @@ import pytest
import random import random
from PyFmcTdc import FmcTdc from PyFmcTdc import FmcTdc
class TestFmctdcGetterSetter(object): class TestFmctdcGetterSetter(object):
@pytest.mark.parametrize("i", range(FmcTdc.CHANNEL_NUMBER)) @pytest.mark.parametrize("i", range(FmcTdc.CHANNEL_NUMBER))
...@@ -16,7 +17,6 @@ class TestFmctdcGetterSetter(object): ...@@ -16,7 +17,6 @@ class TestFmctdcGetterSetter(object):
fmctdc.chan[i].termination = term fmctdc.chan[i].termination = term
assert term == fmctdc.chan[i].termination assert term == fmctdc.chan[i].termination
@pytest.mark.parametrize("i", range(FmcTdc.CHANNEL_NUMBER)) @pytest.mark.parametrize("i", range(FmcTdc.CHANNEL_NUMBER))
@pytest.mark.parametrize("term", [True, False]) @pytest.mark.parametrize("term", [True, False])
def test_termination(self, fmctdc, i, term): def test_termination(self, fmctdc, i, term):
...@@ -53,7 +53,7 @@ class TestFmctdcGetterSetter(object): ...@@ -53,7 +53,7 @@ class TestFmctdcGetterSetter(object):
assert fmctdc.chan[i].enable == (i == ch) assert fmctdc.chan[i].enable == (i == ch)
fmctdc.chan[ch].enable = False fmctdc.chan[ch].enable = False
for i in range(FmcTdc.CHANNEL_NUMBER): for i in range(FmcTdc.CHANNEL_NUMBER):
assert fmctdc.chan[i].enable == False assert fmctdc.chan[i].enable is False
@pytest.mark.parametrize("i", range(FmcTdc.CHANNEL_NUMBER)) @pytest.mark.parametrize("i", range(FmcTdc.CHANNEL_NUMBER))
@pytest.mark.parametrize("buffer_mode", FmcTdc.FmcTdcChannel.BUFFER_MODE.keys()) @pytest.mark.parametrize("buffer_mode", FmcTdc.FmcTdcChannel.BUFFER_MODE.keys())
......
...@@ -4,19 +4,19 @@ SPDX-FileCopyrightText: 2020 CERN ...@@ -4,19 +4,19 @@ SPDX-FileCopyrightText: 2020 CERN
""" """
import pytest import pytest
import random
import select import select
import time import time
import sys
import os import os
from PyFmcTdc import FmcTdc, FmcTdcTime from PyFmcTdc import FmcTdc, FmcTdcTime
TDC_FD_CABLING = [1, 2, 3, 4, 4] TDC_FD_CABLING = [1, 2, 3, 4, 4]
fmctdc_acq_100ns_spec = [(200, 65000), # 5 MHz
(250, 65000), # 4 MHz fmctdc_acq_100ns_spec = [(200, 65000), # 5 MHz
(500, 65000), # 2 MHz (250, 65000), # 4 MHz
(1000, 65000), # 1 Mhz (500, 65000), # 2 MHz
(1000, 65000), # 1 Mhz
(1700, 65000), # 588 kHz (1700, 65000), # 588 kHz
# Let's keep the test within 100ms duration # Let's keep the test within 100ms duration
# vvvvvvvvvvv # vvvvvvvvvvv
...@@ -24,23 +24,26 @@ fmctdc_acq_100ns_spec = [(200, 65000), # 5 MHz ...@@ -24,23 +24,26 @@ fmctdc_acq_100ns_spec = [(200, 65000), # 5 MHz
(2500, 40000), # 400 kHz (2500, 40000), # 400 kHz
(5000, 20000), # 200 khz (5000, 20000), # 200 khz
(10000, 10000), # 100 kHz (10000, 10000), # 100 kHz
(12500, 8000), # 80 kHz (12500, 8000), # 80 kHz
(20000, 5000), # 50 kHz (20000, 5000), # 50 kHz
(100000, 1000), # 10 kHz (100000, 1000), # 10 kHz
(1000000, 100), # 1 kHz (1000000, 100), # 1 kHz
(10000000, 10)] # 100 Hz (10000000, 10)] # 100 Hz
fmctdc_acq_100ns_svec = [(13333, 8000), # 75 kHz
(20000, 5000), # 50 kHz fmctdc_acq_100ns_svec = [(13333, 8000), # 75 kHz
(100000, 1000), # 10 kHz (20000, 5000), # 50 kHz
(1000000, 100), # 1 kHz (100000, 1000), # 10 kHz
(10000000, 10)] # 100 Hz (1000000, 100), # 1 kHz
(10000000, 10)] # 100 Hz
fmctdc_acq_100ns = fmctdc_acq_100ns_svec if pytest.transfer_mode == "fifo" else fmctdc_acq_100ns_spec fmctdc_acq_100ns = fmctdc_acq_100ns_svec if pytest.transfer_mode == "fifo" else fmctdc_acq_100ns_spec
@pytest.fixture(scope="function", params=pytest.channels) @pytest.fixture(scope="function", params=pytest.channels)
def fmctdc_chan(request): def fmctdc_chan(request, fmctdc):
tdc = FmcTdc(pytest.tdc_id) tdc = fmctdc
for ch in tdc.chan: for ch in tdc.chan:
ch.enable = False ch.enable = False
tdc.chan[request.param].termination = False tdc.chan[request.param].termination = False
...@@ -54,6 +57,7 @@ def fmctdc_chan(request): ...@@ -54,6 +57,7 @@ def fmctdc_chan(request):
tdc.chan[request.param].enable = False tdc.chan[request.param].enable = False
del tdc del tdc
class TestFmctdcAcquisition(object): class TestFmctdcAcquisition(object):
def test_acq_single_channel_disable(self, fmctdc_chan, fmcfd): def test_acq_single_channel_disable(self, fmctdc_chan, fmcfd):
...@@ -69,14 +73,13 @@ class TestFmctdcAcquisition(object): ...@@ -69,14 +73,13 @@ class TestFmctdcAcquisition(object):
correctly. Test 100 milli-second acquisition at different correctly. Test 100 milli-second acquisition at different
frequencies""" frequencies"""
stats_before = fmctdc_chan.stats stats_before = fmctdc_chan.stats
fmctdc_chan.buffer_len = max(count + 1, 64) fmctdc_chan.buffer_len = max(count + 1, 64)
fmcfd.generate_pulse(TDC_FD_CABLING[fmctdc_chan.idx], 1000, fmcfd.generate_pulse(TDC_FD_CABLING[fmctdc_chan.idx], 1000,
period_ns, count, True) period_ns, count, True)
stats_after = fmctdc_chan.stats stats_after = fmctdc_chan.stats
assert stats_before[0] + count == stats_after[0] assert stats_before[0] + count == stats_after[0]
@pytest.mark.skipif(pytest.carrier != "spec" or \ @pytest.mark.skipif(pytest.carrier != "spec" or pytest.transfer_mode != "dma",
pytest.transfer_mode != "dma",
reason="Only SPEC with DMA can perform this test") reason="Only SPEC with DMA can perform this test")
@pytest.mark.parametrize("period_ns", [200, 250, 500, 1000]) @pytest.mark.parametrize("period_ns", [200, 250, 500, 1000])
@pytest.mark.repeat(100) @pytest.mark.repeat(100)
...@@ -86,7 +89,7 @@ class TestFmctdcAcquisition(object): ...@@ -86,7 +89,7 @@ class TestFmctdcAcquisition(object):
if we missed a timestamp or not. this is a fine-delay limitation""" if we missed a timestamp or not. this is a fine-delay limitation"""
count = 0xFFFF count = 0xFFFF
stats_before = fmctdc_chan.stats stats_before = fmctdc_chan.stats
fmctdc_chan.buffer_len = count + 1 fmctdc_chan.buffer_len = count + 1
fmcfd.generate_pulse(TDC_FD_CABLING[fmctdc_chan.idx], 1000, fmcfd.generate_pulse(TDC_FD_CABLING[fmctdc_chan.idx], 1000,
period_ns, count, True) period_ns, count, True)
stats_after = fmctdc_chan.stats stats_after = fmctdc_chan.stats
...@@ -98,32 +101,30 @@ class TestFmctdcAcquisition(object): ...@@ -98,32 +101,30 @@ class TestFmctdcAcquisition(object):
metadata is valid. Coars and franc within range, and the sequence metadata is valid. Coars and franc within range, and the sequence
number increases by 1 Test 100 milli-second acquisition at different number increases by 1 Test 100 milli-second acquisition at different
frequencies""" frequencies"""
fmctdc_chan.buffer_len = max(count + 1, 64) fmctdc_chan.buffer_len = max(count + 1, 64)
prev = None prev = None
fmcfd.generate_pulse(TDC_FD_CABLING[fmctdc_chan.idx], 1000, fmcfd.generate_pulse(TDC_FD_CABLING[fmctdc_chan.idx], 1000,
period_ns, count, True) period_ns, count, True)
ts = fmctdc_chan.read(count, os.O_NONBLOCK) ts = fmctdc_chan.read(count, os.O_NONBLOCK)
assert len(ts) == count assert len(ts) == count
for i in range(len(ts)): for i in range(len(ts)):
assert 0 <= ts[i].coarse < 125000000 assert 0 <= ts[i].coarse < 125000000
assert 0 <= ts[i].frac < 4096 assert 0 <= ts[i].frac < 4096
if prev == None: if prev is None:
prev = ts[i] prev = ts[i]
continue continue
assert ts[i].seq_id == (prev.seq_id + 1) & 0xFFFFFFF, \ assert ts[i].seq_id == (prev.seq_id + 1) & 0xFFFFFFF, \
"Missed {:d} timestamps (idx: {:d}, max: {:d}, prev: {{ {:s}, curr: {:s} }}, full dump;\n{:s}".format(ts[i].seq_id - prev.seq_id + 1, "Missed {:d} timestamps (idx: {:d}, max: {:d}, prev: {{ {:s}, curr: {:s} }}, full dump;\n{:s}".format(ts[i].seq_id - prev.seq_id + 1,
i, i,
len(ts), len(ts),
str(prev), str(prev),
str(ts[i]), str(ts[i]),
"\n".join([str(x) for x in ts[max(0, i - pytest.dump_range):min(i + pytest.dump_range, len(ts) -1)]])) "\n".join([str(x) for x in ts[max(0, i - pytest.dump_range):min(i + pytest.dump_range, len(ts) - 1)]]))
prev = ts[i] prev = ts[i]
@pytest.mark.skipif(0 in pytest.usr_acq, @pytest.mark.skipif(0 in pytest.usr_acq,
reason="Missing user acquisition option") reason="Missing user acquisition option")
@pytest.mark.skipif(pytest.carrier == "spec" and \ @pytest.mark.skipif(pytest.carrier == "spec" and pytest.transfer_mode == "fifo" and pytest.usr_acq[0] < 7000,
pytest.transfer_mode == "fifo" and \
pytest.usr_acq[0] < 7000,
reason="On SPEC with FIFO acquisition we can't do more than 100kHz") reason="On SPEC with FIFO acquisition we can't do more than 100kHz")
@pytest.mark.parametrize("period_ns,count", [pytest.usr_acq]) @pytest.mark.parametrize("period_ns,count", [pytest.usr_acq])
def test_acq_timestamp_single_channel(self, capsys, fmctdc_chan, fmcfd, def test_acq_timestamp_single_channel(self, capsys, fmctdc_chan, fmcfd,
...@@ -141,7 +142,7 @@ class TestFmctdcAcquisition(object): ...@@ -141,7 +142,7 @@ class TestFmctdcAcquisition(object):
pending = count pending = count
prev = None prev = None
# be able to buffer for 1 second # be able to buffer for 1 second
fmctdc_chan.buffer_len = int(1/(period_ns/1000000000.0)) + 1 fmctdc_chan.buffer_len = int(1 / (period_ns / 1000000000.0)) + 1
stats_o = fmctdc_chan.stats stats_o = fmctdc_chan.stats
trans_b = stats_o[1] trans_b = stats_o[1]
fmcfd.generate_pulse(TDC_FD_CABLING[fmctdc_chan.idx], 1000, fmcfd.generate_pulse(TDC_FD_CABLING[fmctdc_chan.idx], 1000,
...@@ -157,16 +158,16 @@ class TestFmctdcAcquisition(object): ...@@ -157,16 +158,16 @@ class TestFmctdcAcquisition(object):
ts = fmctdc_chan.read(1000, os.O_NONBLOCK) ts = fmctdc_chan.read(1000, os.O_NONBLOCK)
assert len(ts) <= 1000 assert len(ts) <= 1000
for i in range(len(ts)): for i in range(len(ts)):
if prev == None: if prev is None:
prev = ts[i] prev = ts[i]
continue continue
assert ts[i].seq_id == (prev.seq_id + 1) & 0xFFFFFFF, \ assert ts[i].seq_id == (prev.seq_id + 1) & 0xFFFFFFF, \
"Missed {:d} timestamps (idx: {:d}, max: {:d}, prev: {{ {:s}, curr: {:s} }}, full dump;\n{:s}".format(ts[i].seq_id - prev.seq_id + 1, "Missed {:d} timestamps (idx: {:d}, max: {:d}, prev: {{ {:s}, curr: {:s} }}, full dump;\n{:s}".format(ts[i].seq_id - prev.seq_id + 1,
i, i,
len(ts), len(ts),
str(prev), str(prev),
str(ts[i]), str(ts[i]),
"\n".join([str(x) for x in ts[max(0, i - pytest.dump_range):min(i + pytest.dump_range, len(ts) -1)]])) "\n".join([str(x) for x in ts[max(0, i - pytest.dump_range):min(i + pytest.dump_range, len(ts) - 1)]]))
prev = ts[i] prev = ts[i]
pending -= len(ts) pending -= len(ts)
poll.unregister(fmctdc_chan.fileno) poll.unregister(fmctdc_chan.fileno)
......
...@@ -5,6 +5,7 @@ SPDX-FileCopyrightText: 2020 CERN ...@@ -5,6 +5,7 @@ SPDX-FileCopyrightText: 2020 CERN
import pytest import pytest
class TestFmctdcTemperature(object): class TestFmctdcTemperature(object):
def test_temperature_read(self, fmctdc): def test_temperature_read(self, fmctdc):
......
...@@ -8,14 +8,15 @@ import random ...@@ -8,14 +8,15 @@ import random
import time import time
from PyFmcTdc import FmcTdcTime from PyFmcTdc import FmcTdcTime
class TestFmctdcTime(object): class TestFmctdcTime(object):
def test_whiterabbit_mode(self, fmctdc): def test_whiterabbit_mode(self, fmctdc):
"""It must be possible to toggle the White-Rabbit status""" """It must be possible to toggle the White-Rabbit status"""
fmctdc.whiterabbit_mode = True fmctdc.whiterabbit_mode = True
assert fmctdc.whiterabbit_mode == True assert fmctdc.whiterabbit_mode is True
fmctdc.whiterabbit_mode = False fmctdc.whiterabbit_mode = False
assert fmctdc.whiterabbit_mode == False assert fmctdc.whiterabbit_mode is False
def test_time_set_fail_wr(self, fmctdc): def test_time_set_fail_wr(self, fmctdc):
"""Time can't be changed when White-Rabbit is enabled""" """Time can't be changed when White-Rabbit is enabled"""
......
// SPDX-License-Identifier: GPL-2.0-or-later
/* /*
* ACAM TDC-GPX routines support for fmc-tdc driver. * ACAM TDC-GPX routines support for fmc-tdc driver.
* *
* Copyright (C) 2013 CERN (http://www.cern.ch) * Copyright (C) 2013 CERN (http://www.cern.ch)
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch> * Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>
......
// SPDX-License-Identifier: GPL-2.0-or-later
/* /*
* EEPROM calibration block retreival code for fmc-tdc. * EEPROM calibration block retreival code for fmc-tdc.
* *
* Copyright (C) 2013 CERN (www.cern.ch) * Copyright (C) 2013 CERN (www.cern.ch)
* Author: Tomasz Włostowski <tomasz.wlostowski@cern.ch> * Author: Tomasz Włostowski <tomasz.wlostowski@cern.ch>
* Author: Alessandro Rubini <rubini@gnudd.com> * Author: Alessandro Rubini <rubini@gnudd.com>
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/ */
#include <linux/moduleparam.h> #include <linux/moduleparam.h>
......
// SPDX-License-Identifier: GPL-2.0-or-later
/* /*
* fmc-tdc (a.k.a) FmcTdc1ns5cha main header. * fmc-tdc (a.k.a) FmcTdc1ns5cha main header.
* *
...@@ -5,8 +6,6 @@ ...@@ -5,8 +6,6 @@
* Author: Federico Vaga <federico.vaga@cern.ch> * Author: Federico Vaga <federico.vaga@cern.ch>
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch> * Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* Author: Alessandro Rubini <rubini@gnudd.com> * Author: Alessandro Rubini <rubini@gnudd.com>
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/init.h> #include <linux/init.h>
...@@ -286,63 +285,60 @@ static int ft_zio_block_nr_pages(struct zio_block *block) ...@@ -286,63 +285,60 @@ static int ft_zio_block_nr_pages(struct zio_block *block)
} }
static int sg_alloc_table_from_block(struct device *dev, static int sg_alloc_table_from_block(struct device *dev,
struct sg_table *sgt, struct sg_table *sgt,
struct zio_block *block) struct zio_block *block)
{ {
struct page **pages; struct page **pages;
unsigned int nr_pages; unsigned int nr_pages;
size_t max_segment_size; size_t max_segment_size;
void *data; void *data;
int i; int i;
#if LINUX_VERSION_CODE < KERNEL_VERSION(5,9,0) int err = 0;
int err; #if KERNEL_VERSION(5, 9, 0) <= LINUX_VERSION_CODE
#else struct scatterlist *sg;
struct scatterlist *sg;
#endif #endif
if (!block) if (!block)
return -EINVAL; return -EINVAL;
nr_pages = ft_zio_block_nr_pages(block); nr_pages = ft_zio_block_nr_pages(block);
pages = kcalloc(nr_pages, sizeof(struct page *), GFP_KERNEL); pages = kcalloc(nr_pages, sizeof(struct page *), GFP_KERNEL);
if (!pages) if (!pages)
return -ENOMEM; return -ENOMEM;
data = (void *) block->data; data = (void *) block->data;
if (is_vmalloc_addr(data)) { if (is_vmalloc_addr(data)) {
for (i = 0; i < nr_pages; ++i) { for (i = 0; i < nr_pages; ++i)
pages[i] = vmalloc_to_page(data + PAGE_SIZE * i); pages[i] = vmalloc_to_page(data + PAGE_SIZE * i);
} } else {
} else { for (i = 0; i < nr_pages; ++i)
for (i = 0; i < nr_pages; ++i) pages[i] = virt_to_page(data + PAGE_SIZE * i);
pages[i] = virt_to_page(data + PAGE_SIZE * i); }
}
max_segment_size = dma_get_max_seg_size(dev);
max_segment_size = dma_get_max_seg_size(dev); max_segment_size &= PAGE_MASK; /* to make alloc_table happy */
max_segment_size &= PAGE_MASK; /* to make alloc_table happy */ #if KERNEL_VERSION(5, 9, 0) > LINUX_VERSION_CODE
#if LINUX_VERSION_CODE < KERNEL_VERSION(5,9,0) err = __sg_alloc_table_from_pages(sgt, pages, nr_pages,
err = __sg_alloc_table_from_pages(sgt, pages, nr_pages,
offset_in_page(data), offset_in_page(data),
block->datalen, block->datalen,
max_segment_size, max_segment_size,
GFP_KERNEL); GFP_KERNEL);
if (err)
sg_free_table(sgt);
kfree(pages);
return err;
#else #else
sg = __sg_alloc_table_from_pages(sgt, pages, nr_pages, sg = __sg_alloc_table_from_pages(sgt, pages, nr_pages,
offset_in_page(data), offset_in_page(data),
block->datalen, block->datalen,
max_segment_size, max_segment_size,
NULL, NULL,
0, 0,
GFP_KERNEL); GFP_KERNEL);
if (IS_ERR(sg)) if (IS_ERR(sg))
sg_free_table(sgt); err = PTR_ERR(sg);
kfree(pages);
return PTR_ERR(sg);
#endif #endif
if (err)
sg_free_table(sgt);
kfree(pages);
return err;
} }
static int ft_zio_block_dma_map_sg(struct fmctdc_dev *ft, unsigned int ch, static int ft_zio_block_dma_map_sg(struct fmctdc_dev *ft, unsigned int ch,
......
// SPDX-License-Identifier: GPL-2.0-or-later
/* /*
* Main fmc-tdc driver module. * Main fmc-tdc driver module.
* *
* Copyright (C) 2012-2013 CERN (www.cern.ch) * Copyright (C) 2012-2013 CERN (www.cern.ch)
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch> * Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* Author: Alessandro Rubini <rubini@gnudd.com> * Author: Alessandro Rubini <rubini@gnudd.com>
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>
...@@ -34,7 +33,7 @@ int irq_timeout_ms_default = 10; ...@@ -34,7 +33,7 @@ int irq_timeout_ms_default = 10;
module_param_named(irq_timeout_ms, irq_timeout_ms_default, int, 0444); module_param_named(irq_timeout_ms, irq_timeout_ms_default, int, 0444);
MODULE_PARM_DESC(irq_timeout_ms, "IRQ coalesing timeout (default: 10ms)."); MODULE_PARM_DESC(irq_timeout_ms, "IRQ coalesing timeout (default: 10ms).");
static int test_data_period = 0; static int test_data_period;
module_param_named(test_data_period, test_data_period, int, 0444); module_param_named(test_data_period, test_data_period, int, 0444);
MODULE_PARM_DESC(test_data_period, MODULE_PARM_DESC(test_data_period,
"It sets how many fake timestamps to generate every seconds on the first channel, 0 to disable (default: 0)"); "It sets how many fake timestamps to generate every seconds on the first channel, 0 to disable (default: 0)");
...@@ -209,6 +208,7 @@ static int ft_channels_init(struct fmctdc_dev *ft) ...@@ -209,6 +208,7 @@ static int ft_channels_init(struct fmctdc_dev *ft)
for (i = FT_CH_1; i <= FT_NUM_CHANNELS; i++) { for (i = FT_CH_1; i <= FT_NUM_CHANNELS; i++) {
int ret = ft_init_channel(ft, i); int ret = ft_init_channel(ft, i);
if (ret < 0) if (ret < 0)
return ret; return ret;
/* termination is off by default */ /* termination is off by default */
...@@ -450,7 +450,7 @@ int ft_probe(struct platform_device *pdev) ...@@ -450,7 +450,7 @@ int ft_probe(struct platform_device *pdev)
} }
} }
if(!ft_fmc_slot_is_valid(ft)) if (!ft_fmc_slot_is_valid(ft))
goto out_fmc_err; goto out_fmc_err;
err = sysfs_create_link(&ft->pdev->dev.kobj, &ft->slot->dev.kobj, err = sysfs_create_link(&ft->pdev->dev.kobj, &ft->slot->dev.kobj,
...@@ -461,7 +461,7 @@ int ft_probe(struct platform_device *pdev) ...@@ -461,7 +461,7 @@ int ft_probe(struct platform_device *pdev)
goto err_fmc_link; goto err_fmc_link;
} }
ret = ft_calib_init(ft); ret = ft_calib_init(ft);
if (ret < 0) if (ret < 0)
goto err_calib; goto err_calib;
...@@ -492,9 +492,9 @@ int ft_probe(struct platform_device *pdev) ...@@ -492,9 +492,9 @@ int ft_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, ft); platform_set_drvdata(pdev, ft);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,10,0) #if KERNEL_VERSION(5, 10, 0) <= LINUX_VERSION_CODE
ret = ft_hwmon_init(ft); ret = ft_hwmon_init(ft);
if(ret != 0) if (ret != 0)
dev_err(dev, "Could not create HWMON device: %d", ret); dev_err(dev, "Could not create HWMON device: %d", ret);
#endif #endif
...@@ -546,6 +546,7 @@ int ft_remove(struct platform_device *pdev) ...@@ -546,6 +546,7 @@ int ft_remove(struct platform_device *pdev)
i = ARRAY_SIZE(init_subsystems); i = ARRAY_SIZE(init_subsystems);
while (--i >= 0) { while (--i >= 0) {
struct ft_modlist *m = init_subsystems + i; struct ft_modlist *m = init_subsystems + i;
if (m->exit) if (m->exit)
m->exit(ft); m->exit(ft);
} }
......
// SPDX-License-Identifier: GPL-2.0-or-later
/* /*
* fmc-tdc (a.k.a) FmcTdc1ns5cha main header. * fmc-tdc (a.k.a) FmcTdc1ns5cha main header.
* *
...@@ -5,8 +6,6 @@ ...@@ -5,8 +6,6 @@
* Author: Federico Vaga <federico.vaga@cern.ch> * Author: Federico Vaga <federico.vaga@cern.ch>
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch> * Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* Author: Alessandro Rubini <rubini@gnudd.com> * Author: Alessandro Rubini <rubini@gnudd.com>
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/init.h> #include <linux/init.h>
...@@ -147,7 +146,7 @@ static irqreturn_t ft_irq_handler_ts_fifo(int irq, void *dev_id) ...@@ -147,7 +146,7 @@ static irqreturn_t ft_irq_handler_ts_fifo(int irq, void *dev_id)
redo--; redo--;
} }
} }
} while(irq_stat && redo); } while (irq_stat && redo);
ft_iowrite(ft, irq_stat_orig, ft->ft_irq_base + TDC_EIC_REG_EIC_ISR); ft_iowrite(ft, irq_stat_orig, ft->ft_irq_base + TDC_EIC_REG_EIC_ISR);
return IRQ_HANDLED; return IRQ_HANDLED;
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
#include <linux/hwmon.h> #include <linux/hwmon.h>
#include "fmc-tdc.h" #include "fmc-tdc.h"
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,10,0) #if KERNEL_VERSION(5, 10, 0) <= LINUX_VERSION_CODE
static umode_t ft_hwmon_temp_is_visible(const void *_data, static umode_t ft_hwmon_temp_is_visible(const void *_data,
enum hwmon_sensor_types type, u32 attr, enum hwmon_sensor_types type, u32 attr,
...@@ -25,23 +25,23 @@ static int ft_hwmon_temp_read(struct device *dev, enum hwmon_sensor_types type, ...@@ -25,23 +25,23 @@ static int ft_hwmon_temp_read(struct device *dev, enum hwmon_sensor_types type,
int value, ret; int value, ret;
struct fmctdc_dev *ft = dev_get_drvdata(dev); struct fmctdc_dev *ft = dev_get_drvdata(dev);
switch(attr) { switch (attr) {
case hwmon_temp_min: case hwmon_temp_min:
*val = -25*1000; *val = -25*1000;
return 0; return 0;
case hwmon_temp_max: case hwmon_temp_max:
*val = 60*1000; *val = 60*1000;
return 0; return 0;
case hwmon_temp_crit: case hwmon_temp_crit:
*val = 65*1000; *val = 65*1000;
return 0; return 0;
} }
ret = ft_temperature_get(ft, &value); ret = ft_temperature_get(ft, &value);
if(ret < 0) { if (ret < 0) {
dev_err(dev, "Could not read temperature: %d", ret); dev_err(dev, "Could not read temperature: %d", ret);
return ret; return ret;
} }
...@@ -88,12 +88,12 @@ int ft_hwmon_init(struct fmctdc_dev *ft) ...@@ -88,12 +88,12 @@ int ft_hwmon_init(struct fmctdc_dev *ft)
ft, ft,
&ft_hwmon_temp_chip_info, &ft_hwmon_temp_chip_info,
NULL); NULL);
if(!IS_ERR(ft->hwmon_dev)) { if (!IS_ERR(ft->hwmon_dev)) {
ft->hwmon_temp_sensor_id = devm_kasprintf(ft->hwmon_dev, ft->hwmon_temp_sensor_id = devm_kasprintf(ft->hwmon_dev,
GFP_KERNEL, GFP_KERNEL,
"Temperature [%s]", "Temperature [%s]",
dev_name(&ft->slot->dev)); dev_name(&ft->slot->dev));
if(!ft->hwmon_temp_sensor_id) { if (!ft->hwmon_temp_sensor_id) {
devm_hwmon_device_unregister(dev); devm_hwmon_device_unregister(dev);
return -ENOMEM; return -ENOMEM;
} }
......
// SPDX-License-Identifier: GPL-2.0-or-later
// SPDX-FileCopyrightText: 2023 CERN (home.cern)
/* /*
* Time-related routines for fmc-tdc driver. * Time-related routines for fmc-tdc driver.
* *
* Copyright (C) 2013 CERN (http://www.cern.ch)
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch> * Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>
......
// SPDX-License-Identifier: GPL-2.0-or-later
/* /*
* ZIO interface for the fmc-tdc driver. * ZIO interface for the fmc-tdc driver.
* *
* Copyright (C) 2012-2013 CERN (www.cern.ch) * Copyright (C) 2012-2013 CERN (www.cern.ch)
* Author: Tomasz Włostowski <tomasz.wlostowski@cern.ch> * Author: Tomasz Włostowski <tomasz.wlostowski@cern.ch>
* Author: Alessandro Rubini <rubini@gnudd.com> * Author: Alessandro Rubini <rubini@gnudd.com>
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>
...@@ -138,10 +137,10 @@ int ft_temperature_get(struct fmctdc_dev *ft, int *temp) ...@@ -138,10 +137,10 @@ int ft_temperature_get(struct fmctdc_dev *ft, int *temp)
static int ft_unique_id_get(struct fmctdc_dev *ft, uint64_t *id) static int ft_unique_id_get(struct fmctdc_dev *ft, uint64_t *id)
{ {
int stat = ft_ioread( ft, ft->ft_owregs_base + TDC_OW_REG_CSR); int stat = ft_ioread(ft, ft->ft_owregs_base + TDC_OW_REG_CSR);
uint32_t tmp_l, tmp_h; uint32_t tmp_l, tmp_h;
if( !( stat & TDC_OW_CSR_VALID ) ) if (!(stat & TDC_OW_CSR_VALID))
return -EIO; return -EIO;
tmp_l = ft_ioread(ft, ft->ft_owregs_base + TDC_OW_REG_ID_L); tmp_l = ft_ioread(ft, ft->ft_owregs_base + TDC_OW_REG_ID_L);
...@@ -487,10 +486,10 @@ static struct zio_driver ft_zdrv = { ...@@ -487,10 +486,10 @@ static struct zio_driver ft_zdrv = {
.probe = ft_zio_probe, .probe = ft_zio_probe,
.remove = ft_zio_remove, .remove = ft_zio_remove,
/* Take the version from ZIO git sub-module */ /* Take the version from ZIO git sub-module */
/* Change it if you use new features from a specific patch */
.min_version = ZIO_VERSION(__ZIO_MIN_MAJOR_VERSION, .min_version = ZIO_VERSION(__ZIO_MIN_MAJOR_VERSION,
__ZIO_MIN_MINOR_VERSION, __ZIO_MIN_MINOR_VERSION,
0), /* Change it if you use new features from 0),
a specific patch */
}; };
#define FT_TRIG_POST_DEFAULT 1 #define FT_TRIG_POST_DEFAULT 1
...@@ -590,11 +589,11 @@ static int ft_trig_data_done(struct zio_cset *cset) ...@@ -590,11 +589,11 @@ static int ft_trig_data_done(struct zio_cset *cset)
goto out; goto out;
ts = cset->chan->active_block->data; ts = cset->chan->active_block->data;
for(i = 0; i < cset->ti->nsamples; ++i) { for (i = 0; i < cset->ti->nsamples; ++i) {
dev_dbg(&cset->head.dev, dev_dbg(&cset->head.dev,
"%s TS = {ts-num: %d, ts-num-max: %d, sec: 0x%x, coarse: 0x%x frac: 0x%x, meta: 0x%x}\n", "%s TS = {ts-num: %d, ts-num-max: %d, sec: 0x%x, coarse: 0x%x frac: 0x%x, meta: 0x%x}\n",
__func__, i, cset->ti->nsamples, __func__, i, cset->ti->nsamples,
ts[i].seconds,ts[i].coarse, ts[i].seconds, ts[i].coarse,
ts[i].frac, ts[i].metadata); ts[i].frac, ts[i].metadata);
} }
ft_zio_update_ctrl(cset, &ts[0]); ft_zio_update_ctrl(cset, &ts[0]);
...@@ -678,7 +677,7 @@ int ft_zio_init(struct fmctdc_dev *ft) ...@@ -678,7 +677,7 @@ int ft_zio_init(struct fmctdc_dev *ft)
if (err) if (err)
goto err_dev_reg; goto err_dev_reg;
for(i = 0; i < FT_NUM_CHANNELS; i++) { for (i = 0; i < FT_NUM_CHANNELS; i++) {
ft_raw_mode_set(ft, i, 0); ft_raw_mode_set(ft, i, 0);
ft_update_offsets(ft, i); ft_update_offsets(ft, i);
} }
......
...@@ -6,20 +6,19 @@ SPDX-License-Identifier: LGPL-2.1-or-later ...@@ -6,20 +6,19 @@ SPDX-License-Identifier: LGPL-2.1-or-later
SPDX-FileCopyrightText: 2020 CERN (home.cern) SPDX-FileCopyrightText: 2020 CERN (home.cern)
""" """
import threading
import ctypes import ctypes
import errno import errno
import time import time
import os
class FmcTdcTime(ctypes.Structure): class FmcTdcTime(ctypes.Structure):
_fields_ = [ _fields_ = [
("seconds", ctypes.c_uint64), ("seconds", ctypes.c_uint64),
("coarse", ctypes.c_uint32), ("coarse", ctypes.c_uint32),
("frac", ctypes.c_uint32), ("frac", ctypes.c_uint32),
("seq_id", ctypes.c_uint32), ("seq_id", ctypes.c_uint32),
("debug", ctypes.c_uint32), ("debug", ctypes.c_uint32),
] ]
def __str__(self): def __str__(self):
return "seq: {:d} timestamp: {:f} raw: {:08x}:{:08x}:{:08x}, debug: {:08x}".format(self.seq_id, float(self), self.seconds, self.coarse, self.frac, self.debug) return "seq: {:d} timestamp: {:f} raw: {:08x}:{:08x}:{:08x}, debug: {:08x}".format(self.seq_id, float(self), self.seconds, self.coarse, self.frac, self.debug)
...@@ -31,7 +30,6 @@ class FmcTdcTime(ctypes.Structure): ...@@ -31,7 +30,6 @@ class FmcTdcTime(ctypes.Structure):
return ts return ts
def libfmctdc_create(): def libfmctdc_create():
""" """
Initialize the libfmctdc C library Initialize the libfmctdc C library
...@@ -102,12 +100,12 @@ def libfmctdc_create(): ...@@ -102,12 +100,12 @@ def libfmctdc_create():
libfmctdc.fmctdc_get_time.restype = ctypes.c_int libfmctdc.fmctdc_get_time.restype = ctypes.c_int
libfmctdc.fmctdc_get_time.errcheck = error_check_int libfmctdc.fmctdc_get_time.errcheck = error_check_int
libfmctdc.fmctdc_wr_mode.argtypes =[ctypes.c_void_p, libfmctdc.fmctdc_wr_mode.argtypes = [ctypes.c_void_p,
ctypes.c_int] ctypes.c_int]
libfmctdc.fmctdc_wr_mode.restype = ctypes.c_int libfmctdc.fmctdc_wr_mode.restype = ctypes.c_int
libfmctdc.fmctdc_wr_mode.errcheck = error_check_int libfmctdc.fmctdc_wr_mode.errcheck = error_check_int
libfmctdc.fmctdc_check_wr_mode.argtypes =[ctypes.c_void_p] libfmctdc.fmctdc_check_wr_mode.argtypes = [ctypes.c_void_p]
libfmctdc.fmctdc_check_wr_mode.restype = ctypes.c_int libfmctdc.fmctdc_check_wr_mode.restype = ctypes.c_int
# Channel # Channel
...@@ -230,8 +228,10 @@ def libfmctdc_create(): ...@@ -230,8 +228,10 @@ def libfmctdc_create():
return libfmctdc return libfmctdc
libfmctdc = libfmctdc_create() libfmctdc = libfmctdc_create()
def fmctdc_strerror(err): def fmctdc_strerror(err):
""" """
Return FMC-TDC errors Return FMC-TDC errors
...@@ -241,6 +241,7 @@ def fmctdc_strerror(err): ...@@ -241,6 +241,7 @@ def fmctdc_strerror(err):
""" """
return libfmctdc.fmctdc_strerror(err) return libfmctdc.fmctdc_strerror(err)
class FmcTdc(object): class FmcTdc(object):
""" """
It is a Python class that represent an FMC TDC device It is a Python class that represent an FMC TDC device
...@@ -361,12 +362,12 @@ class FmcTdc(object): ...@@ -361,12 +362,12 @@ class FmcTdc(object):
def read(self, n=1, flags=0): def read(self, n=1, flags=0):
ts = (FmcTdcTime * n)() ts = (FmcTdcTime * n)()
ret = libfmctdc.fmctdc_read(self.tkn, self.idx, ts ,n ,flags) ret = libfmctdc.fmctdc_read(self.tkn, self.idx, ts, n, flags)
return list(ts)[:ret] return list(ts)[:ret]
def fread(self, n=1, flags=0): def fread(self, n=1, flags=0):
ts = (FmcTdcTime * n)() ts = (FmcTdcTime * n)()
libfmctdc.fmctdc_fread(self.tkn, self.idx, ts, n ,flags) libfmctdc.fmctdc_fread(self.tkn, self.idx, ts, n, flags)
return list(ts) return list(ts)
def flush(self): def flush(self):
......
...@@ -17,4 +17,4 @@ setup(name='PyFmcTdc', ...@@ -17,4 +17,4 @@ setup(name='PyFmcTdc',
url='http://www.ohwr.org/projects/fmc-tdc', url='http://www.ohwr.org/projects/fmc-tdc',
packages=['PyFmcTdc'], packages=['PyFmcTdc'],
license='LGPL-2.1-or-later', license='LGPL-2.1-or-later',
) )
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment