merged developer into feature and solved merge conflicts

This commit is contained in:
Mazzoleni Alice Francesca 2025-04-09 09:39:47 +02:00
commit 9fde62ae30
57 changed files with 1030 additions and 350 deletions

View File

@ -1,4 +1,4 @@
name: CMake name: Native CMake Build
on: [push, pull_request] on: [push, pull_request]
@ -14,7 +14,13 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
name: Configure and build using cmake name: Configure and build using cmake
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: 3.12
cache: 'pip'
- run: pip install pytest numpy
- uses: awalsh128/cache-apt-pkgs-action@latest - uses: awalsh128/cache-apt-pkgs-action@latest
with: with:
packages: libhdf5-dev qtbase5-dev qt5-qmake libqt5svg5-dev libpng-dev libtiff-dev packages: libhdf5-dev qtbase5-dev qt5-qmake libqt5svg5-dev libpng-dev libtiff-dev
@ -27,12 +33,15 @@ jobs:
- name: Build - name: Build
# Build your program with the given configuration # Build your program with the given configuration
run: cmake --build ${{github.workspace}}/build -j2 --config ${{env.BUILD_TYPE}} run: cmake --build ${{github.workspace}}/build -j4 --config ${{env.BUILD_TYPE}}
- name: Test - name: C++ unit tests
working-directory: ${{github.workspace}}/build working-directory: ${{github.workspace}}/build
# Execute tests defined by the CMake configuration.
# See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail
run: ctest -C ${{env.BUILD_TYPE}} -j1 run: ctest -C ${{env.BUILD_TYPE}} -j1
- name: Python unit tests
working-directory: ${{github.workspace}}/build/bin
run: |
python -m pytest ${{github.workspace}}/python/tests

42
.github/workflows/conda_library.yaml vendored Normal file
View File

@ -0,0 +1,42 @@
name: Build slsdetlib
on: [pull_request]
jobs:
build:
strategy:
fail-fast: false
matrix:
platform: [ubuntu-latest, ] # macos-12, windows-2019]
python-version: ["3.12",]
runs-on: ${{ matrix.platform }}
# The setup-miniconda action needs this to activate miniconda
defaults:
run:
shell: "bash -l {0}"
steps:
- uses: actions/checkout@v4
- name: Get conda
uses: conda-incubator/setup-miniconda@v3.0.4
with:
python-version: ${{ matrix.python-version }}
channels: conda-forge
- name: Prepare
run: conda install conda-build conda-verify pytest anaconda-client
- name: Disable upload
run: conda config --set anaconda_upload no
- name: Build
run: conda build conda-recipes/main-library --output-folder build_output
- name: Upload all Conda packages
uses: actions/upload-artifact@v4
with:
name: conda-packages
path: build_output/** # Uploads all packages

42
.github/workflows/conda_python.yaml vendored Normal file
View File

@ -0,0 +1,42 @@
name: slsdet
on: [pull_request]
jobs:
build:
strategy:
fail-fast: false
matrix:
platform: [ubuntu-latest, ] # macos-12, windows-2019]
python-version: ["3.12",]
runs-on: ${{ matrix.platform }}
# The setup-miniconda action needs this to activate miniconda
defaults:
run:
shell: "bash -l {0}"
steps:
- uses: actions/checkout@v4
- name: Get conda
uses: conda-incubator/setup-miniconda@v3.0.4
with:
python-version: ${{ matrix.python-version }}
channels: conda-forge
- name: Prepare
run: conda install conda-build conda-verify pytest anaconda-client
- name: Disable upload
run: conda config --set anaconda_upload no
- name: Build
run: conda build conda-recipes/python-client --output-folder build_output
- name: Upload all Conda packages
uses: actions/upload-artifact@v4
with:
name: conda-packages
path: build_output/** # Uploads all packages

View File

@ -1,6 +1,6 @@
# SPDX-License-Identifier: LGPL-3.0-or-other # SPDX-License-Identifier: LGPL-3.0-or-other
# Copyright (C) 2021 Contributors to the SLS Detector Package # Copyright (C) 2021 Contributors to the SLS Detector Package
cmake_minimum_required(VERSION 3.14) cmake_minimum_required(VERSION 3.15)
project(slsDetectorPackage) project(slsDetectorPackage)
# Read VERSION file into project version # Read VERSION file into project version
@ -29,20 +29,40 @@ include(FetchContent)
option(SLS_FETCH_ZMQ_FROM_GITHUB "Fetch zmq from github" OFF) option(SLS_FETCH_ZMQ_FROM_GITHUB "Fetch zmq from github" OFF)
option(SLS_FETCH_PYBIND11_FROM_GITHUB "Fetch pybind11 from github" OFF) option(SLS_FETCH_PYBIND11_FROM_GITHUB "Fetch pybind11 from github" OFF)
# Allow FetchContent_Populate to be called with a single argument
# otherwise deprecated warning is issued
# Note: From cmake 3.28 we can pass EXCLUDE_FROM_ALL to FetchContent_Declare
# and avoid direct use of Populate
if (${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.30")
cmake_policy(SET CMP0169 OLD)
endif()
# Patch libzmq to set minimum cmake version to 3.15 to avoid warnings
# with newer cmake versions
# Patch is applied in the FetchContent_Declare
set(SLS_LIBZMQ_VERSION "4.3.4")
if(SLS_FETCH_ZMQ_FROM_GITHUB) if(SLS_FETCH_ZMQ_FROM_GITHUB)
# Opt in to pull down a zmq version from github instead of # Opt in to pull down a zmq version from github instead of
# using the bundled verison # using the bundled version
FetchContent_Declare( FetchContent_Declare(
libzmq libzmq
GIT_REPOSITORY https://github.com/zeromq/libzmq.git GIT_REPOSITORY https://github.com/zeromq/libzmq.git
GIT_TAG v4.3.4 GIT_TAG v${SLS_LIBZMQ_VERSION}
PATCH_COMMAND ${CMAKE_COMMAND} -E chdir <SOURCE_DIR> patch -p1 < ${CMAKE_CURRENT_SOURCE_DIR}/libs/libzmq/libzmq_cmake_version.patch
UPDATE_DISCONNECTED 1
) )
else() else()
# Standard behaviour use libzmq included in this repo (libs/libzmq) # Standard behaviour use libzmq included in this repo (libs/libzmq)
FetchContent_Declare( FetchContent_Declare(
libzmq libzmq
URL ${CMAKE_CURRENT_SOURCE_DIR}/libs/libzmq/libzmq-4.3.4.tar.gz URL ${CMAKE_CURRENT_SOURCE_DIR}/libs/libzmq/libzmq-${SLS_LIBZMQ_VERSION}.tar.gz
URL_HASH MD5=cc20b769ac10afa352e5ed2769bb23b3 URL_HASH MD5=cc20b769ac10afa352e5ed2769bb23b3
PATCH_COMMAND ${CMAKE_COMMAND} -E chdir <SOURCE_DIR> patch -p1 < ${CMAKE_CURRENT_SOURCE_DIR}/libs/libzmq/libzmq_cmake_version.patch
UPDATE_DISCONNECTED 1
) )
endif() endif()
@ -54,6 +74,11 @@ set(ENABLE_CPACK OFF CACHE BOOL "")
set(ENABLE_CLANG OFF CACHE BOOL "") set(ENABLE_CLANG OFF CACHE BOOL "")
set(ENABLE_CURVE OFF CACHE BOOL "") set(ENABLE_CURVE OFF CACHE BOOL "")
set(ENABLE_DRAFTS OFF CACHE BOOL "") set(ENABLE_DRAFTS OFF CACHE BOOL "")
set(ENABLE_PRECOMPILED OFF CACHE BOOL "")
set(WITH_DOC OFF CACHE BOOL "")
set(WITH_DOCS OFF CACHE BOOL "")
# Using GetProperties and Populate to be able to exclude zmq # Using GetProperties and Populate to be able to exclude zmq
# from install (not possible with FetchContent_MakeAvailable(libzmq)) # from install (not possible with FetchContent_MakeAvailable(libzmq))
@ -329,9 +354,15 @@ if (SLS_USE_CTBGUI)
add_subdirectory(pyctbgui) add_subdirectory(pyctbgui)
endif(SLS_USE_CTBGUI) endif(SLS_USE_CTBGUI)
# Workaround for file note being copied to build directory
# when issuing a python -m build
# TODO! Proper fix
if(EXISTS ".clang-tidy")
configure_file(.clang-tidy configure_file(.clang-tidy
${CMAKE_BINARY_DIR}/.clang-tidy ${CMAKE_BINARY_DIR}/.clang-tidy
) )
endif()
if (SLS_BUILD_EXAMPLES) if (SLS_BUILD_EXAMPLES)
add_subdirectory(sample) add_subdirectory(sample)

View File

@ -1,11 +0,0 @@
# SPDX-License-Identifier: LGPL-3.0-or-other
# Copyright (C) 2021 Contributors to the SLS Detector Package
echo "|<-------- starting python build"
cd python
# copy VERSION into slsdet for installation
cp ../VERSION slsdet/VERSION
${PYTHON} setup.py install

View File

@ -1,8 +0,0 @@
python:
- 3.8
- 3.9
- 3.10
- 3.11
- 3.12
- 3.13

View File

@ -1,11 +0,0 @@
# SPDX-License-Identifier: LGPL-3.0-or-other
# Copyright (C) 2021 Contributors to the SLS Detector Package
mkdir $PREFIX/lib
mkdir $PREFIX/bin
mkdir $PREFIX/include
cp build/bin/ctbGui $PREFIX/bin/.
cp build/bin/libctbRootLib.so $PREFIX/lib/.

View File

@ -1,125 +0,0 @@
package:
name: sls_detector_software
version: {{ environ.get('GIT_DESCRIBE_TAG', '') }}
source:
path: ..
build:
number: 0
binary_relocation: True
rpaths:
- lib/
requirements:
build:
- {{ compiler('c') }}
- {{compiler('cxx')}}
- cmake
- qt 5.*
- xorg-libx11
- xorg-libice
- xorg-libxext
- xorg-libsm
- xorg-libxau
- xorg-libxrender
- xorg-libxfixes
- {{ cdt('mesa-libgl-devel') }} # [linux]
- {{ cdt('mesa-libegl-devel') }} # [linux]
- {{ cdt('mesa-dri-drivers') }} # [linux]
- {{ cdt('libselinux') }} # [linux]
- {{ cdt('libxdamage') }} # [linux]
- {{ cdt('libxxf86vm') }} # [linux]
- expat
host:
- libstdcxx-ng
- libgcc-ng
- xorg-libx11
- xorg-libice
- xorg-libxext
- xorg-libsm
- xorg-libxau
- xorg-libxrender
- xorg-libxfixes
- expat
run:
- libstdcxx-ng
- libgcc-ng
outputs:
- name: slsdetlib
script: copy_lib.sh
requirements:
build:
- {{ compiler('c') }}
- {{compiler('cxx')}}
- libstdcxx-ng
- libgcc-ng
run:
- libstdcxx-ng
- libgcc-ng
- name: slsdet
script: build_pylib.sh
requirements:
build:
- python
- {{ compiler('c') }}
- {{compiler('cxx')}}
- {{ pin_subpackage('slsdetlib', exact=True) }}
- setuptools
- pybind11=2.13
host:
- python
- {{ pin_subpackage('slsdetlib', exact=True) }}
- setuptools
- pybind11=2.13
run:
- libstdcxx-ng
- libgcc-ng
- python
- numpy
- {{ pin_subpackage('slsdetlib', exact=True) }}
test:
imports:
- slsdet
- name: slsdetgui
script: copy_gui.sh
requirements:
build:
- {{ compiler('c') }}
- {{compiler('cxx')}}
- {{ pin_subpackage('slsdetlib', exact=True) }}
run:
- {{ pin_subpackage('slsdetlib', exact=True) }}
- qt 5.*
- expat
- name: moenchzmq
script: copy_moench.sh
requirements:
build:
- {{ compiler('c') }}
- {{compiler('cxx')}}
- {{ pin_subpackage('slsdetlib', exact=True) }}
run:
- {{ pin_subpackage('slsdetlib', exact=True) }}
- expat

View File

@ -1,3 +0,0 @@
# SPDX-License-Identifier: LGPL-3.0-or-other
# Copyright (C) 2021 Contributors to the SLS Detector Package
ctest -j2

View File

@ -8,7 +8,7 @@ if [ ! -d "install" ]; then
mkdir install mkdir install
fi fi
cd build cd build
cmake .. \ cmake .. -G Ninja \
-DCMAKE_PREFIX_PATH=$CONDA_PREFIX \ -DCMAKE_PREFIX_PATH=$CONDA_PREFIX \
-DCMAKE_INSTALL_PREFIX=install \ -DCMAKE_INSTALL_PREFIX=install \
-DSLS_USE_TEXTCLIENT=ON \ -DSLS_USE_TEXTCLIENT=ON \

View File

@ -0,0 +1,13 @@
c_compiler:
- gcc # [linux]
c_stdlib:
- sysroot # [linux]
cxx_compiler:
- gxx # [linux]
c_stdlib_version: # [linux]
- 2.17 # [linux]

View File

@ -4,7 +4,6 @@
mkdir -p $PREFIX/lib mkdir -p $PREFIX/lib
mkdir -p $PREFIX/bin mkdir -p $PREFIX/bin
mkdir -p $PREFIX/include/sls mkdir -p $PREFIX/include/sls
# mkdir $PREFIX/include/slsDetectorPackage
#Shared and static libraries #Shared and static libraries
cp build/install/lib/* $PREFIX/lib/ cp build/install/lib/* $PREFIX/lib/
@ -15,8 +14,10 @@ cp build/install/bin/sls_detector_acquire_zmq $PREFIX/bin/.
cp build/install/bin/sls_detector_get $PREFIX/bin/. cp build/install/bin/sls_detector_get $PREFIX/bin/.
cp build/install/bin/sls_detector_put $PREFIX/bin/. cp build/install/bin/sls_detector_put $PREFIX/bin/.
cp build/install/bin/sls_detector_help $PREFIX/bin/. cp build/install/bin/sls_detector_help $PREFIX/bin/.
cp build/install/bin/sls_detector $PREFIX/bin/.
cp build/install/bin/slsReceiver $PREFIX/bin/. cp build/install/bin/slsReceiver $PREFIX/bin/.
cp build/install/bin/slsMultiReceiver $PREFIX/bin/. cp build/install/bin/slsMultiReceiver $PREFIX/bin/.
cp build/install/bin/slsFrameSynchronizer $PREFIX/bin/.
cp build/install/include/sls/* $PREFIX/include/sls cp build/install/include/sls/* $PREFIX/include/sls

View File

@ -0,0 +1,79 @@
package:
name: sls_detector_software
version: 2025.3.19
source:
path: ../..
build:
number: 0
binary_relocation: True
rpaths:
- lib/
requirements:
build:
- {{ compiler('c') }}
- {{ stdlib("c") }}
- {{ compiler('cxx') }}
- git
- cmake
- ninja
- qt 5.*
host:
- libstdcxx-ng
- libgcc-ng
- libgl-devel # [linux]
- libtiff
- zlib
run:
- libstdcxx-ng
- libgcc-ng
outputs:
- name: slsdetlib
script: copy_lib.sh
requirements:
build:
- {{ compiler('c') }}
- {{ stdlib("c") }}
- {{ compiler('cxx') }}
run:
- libstdcxx-ng
- libgcc-ng
- name: slsdetgui
script: copy_gui.sh
requirements:
build:
- {{ compiler('c') }}
- {{compiler('cxx')}}
- {{ pin_subpackage('slsdetlib', exact=True) }}
run:
- {{ pin_subpackage('slsdetlib', exact=True) }}
- qt 5.*
- name: moenchzmq
script: copy_moench.sh
requirements:
build:
- {{ compiler('c') }}
- {{compiler('cxx')}}
- {{ pin_subpackage('slsdetlib', exact=True) }}
run:
- {{ pin_subpackage('slsdetlib', exact=True) }}

View File

@ -0,0 +1,16 @@
python:
- 3.11
- 3.12
- 3.13
c_compiler:
- gcc # [linux]
c_stdlib:
- sysroot # [linux]
cxx_compiler:
- gxx # [linux]
c_stdlib_version: # [linux]
- 2.17 # [linux]

View File

@ -0,0 +1,45 @@
package:
name: slsdet
version: 2025.3.19 #TODO! how to not duplicate this?
source:
path: ../..
build:
number: 0
script:
- unset CMAKE_GENERATOR && {{ PYTHON }} -m pip install . -vv # [not win]
requirements:
build:
- python {{python}}
- {{ compiler('c') }}
- {{ stdlib("c") }}
- {{ compiler('cxx') }}
host:
- cmake
- ninja
- python {{python}}
- pip
- scikit-build-core
- pybind11 >=2.13.0
- fmt
- zeromq
- nlohmann_json
- catch2
run:
- python {{python}}
- numpy
test:
imports:
- slsdet
about:
summary: An example project built with pybind11 and scikit-build.
# license_file: LICENSE

View File

@ -40,6 +40,7 @@ set(SPHINX_SOURCE_FILES
src/pydetector.rst src/pydetector.rst
src/pyenums.rst src/pyenums.rst
src/pyexamples.rst src/pyexamples.rst
src/pyPatternGenerator.rst
src/servers.rst src/servers.rst
src/receiver_api.rst src/receiver_api.rst
src/result.rst src/result.rst

View File

@ -36,6 +36,7 @@ Welcome to slsDetectorPackage's documentation!
pydetector pydetector
pyenums pyenums
pyexamples pyexamples
pyPatternGenerator
.. toctree:: .. toctree::
:caption: Command line :caption: Command line

View File

@ -0,0 +1,34 @@
PatternGenerator
=====================================================
Python class to generate patterns for the Chip Test Board.
.. code-block:: python
from slsdet import PatternGenerator
p = PatternGenerator()
p.SB(5)
p.PW()
p.SB(8,9)
p.PW()
p.CB(5)
Created a pattern like this:
.. code-block:: bash
patword 0x0000 0x0000000000000020
patword 0x0001 0x0000000000000320
patword 0x0002 0x0000000000000300
patioctrl 0x0000000000000000
patlimits 0x0000 0x0002
...
.. py:currentmodule:: slsdet
.. autoclass:: PatternGenerator
:members:
:undoc-members:
:show-inheritance:
:inherited-members:

View File

@ -0,0 +1,18 @@
diff --git a/CMakeLists.txt b/CMakeLists.txt
index dd3d8eb9..c0187747 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,11 +1,8 @@
# CMake build script for ZeroMQ
project(ZeroMQ)
-if(${CMAKE_SYSTEM_NAME} STREQUAL Darwin)
- cmake_minimum_required(VERSION 3.0.2)
-else()
- cmake_minimum_required(VERSION 2.8.12)
-endif()
+cmake_minimum_required(VERSION 3.15)
+message(STATUS "Patched cmake version")
include(CheckIncludeFiles)
include(CheckCCompilerFlag)

View File

@ -12,5 +12,6 @@ slsDetectorPackage/8.0.1_rh8 stable cmake/3.15.5 Qt/5.12.10
slsDetectorPackage/8.0.2_rh7 stable cmake/3.15.5 Qt/5.12.10 slsDetectorPackage/8.0.2_rh7 stable cmake/3.15.5 Qt/5.12.10
slsDetectorPackage/8.0.2_rh8 stable cmake/3.15.5 Qt/5.12.10 slsDetectorPackage/8.0.2_rh8 stable cmake/3.15.5 Qt/5.12.10
slsDetectorPackage/9.0.0_rh8 stable cmake/3.15.5 Qt/5.12.10 slsDetectorPackage/9.0.0_rh8 stable cmake/3.15.5 Qt/5.12.10
slsDetectorPackage/9.1.0_rh8 stable cmake/3.15.5 Qt/5.12.10

27
pyproject.toml Normal file
View File

@ -0,0 +1,27 @@
[build-system]
requires = ["scikit-build-core>=0.10", "pybind11", "numpy"]
build-backend = "scikit_build_core.build"
[project]
name = "slsdet"
version = "2025.3.19"
[tool.cibuildwheel]
before-all = "uname -a"
[tool.scikit-build]
build.verbose = true
cmake.build-type = "Release"
install.components = ["python"]
[tool.scikit-build.cmake.define]
#Only build the control software and python ext
SLS_USE_RECEIVER = "OFF"
SLS_USE_RECEIVER_BINARIES = "OFF"
SLS_USE_TEXTCLIENT = "OFF"
SLS_BUILD_SHARED_LIBRARIES = "OFF"
SLS_USE_PYTHON = "ON"
SLS_INSTALL_PYTHONEXT = "ON"

View File

@ -20,13 +20,14 @@ target_link_libraries(_slsdet PUBLIC
set_target_properties(_slsdet PROPERTIES set_target_properties(_slsdet PROPERTIES
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin/slsdet
) )
#Copy Python code #Copy Python code
set( PYTHON_FILES set( PYTHON_FILES
slsdet/__init__.py slsdet/__init__.py
slsdet/adcs.py slsdet/adcs.py
slsdet/bits.py
slsdet/dacs.py slsdet/dacs.py
slsdet/powers.py slsdet/powers.py
slsdet/decorators.py slsdet/decorators.py
@ -38,6 +39,7 @@ set( PYTHON_FILES
slsdet/errors.py slsdet/errors.py
slsdet/gaincaps.py slsdet/gaincaps.py
slsdet/pattern.py slsdet/pattern.py
slsdet/PatternGenerator.py
slsdet/gotthard2.py slsdet/gotthard2.py
slsdet/moench.py slsdet/moench.py
slsdet/proxy.py slsdet/proxy.py
@ -70,9 +72,18 @@ configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/../VERSION
if(SLS_INSTALL_PYTHONEXT) if(SLS_INSTALL_PYTHONEXT)
install(TARGETS _slsdet install(TARGETS _slsdet
EXPORT "${TARGETS_EXPORT_NAME}" EXPORT "${TARGETS_EXPORT_NAME}"
LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}/python LIBRARY DESTINATION slsdet
COMPONENT python
)
install(
FILES ${PYTHON_FILES}
DESTINATION slsdet
COMPONENT python
)
install(
FILES ../VERSION
DESTINATION slsdet
COMPONENT python
) )
install(FILES ${PYTHON_FILES} DESTINATION ${CMAKE_INSTALL_PREFIX}/python/slsdet)
install(FILES ../VERSION DESTINATION ${CMAKE_INSTALL_PREFIX}/python/slsdet)
endif() endif()

View File

@ -1,77 +0,0 @@
# SPDX-License-Identifier: LGPL-3.0-or-other
# Copyright (C) 2021 Contributors to the SLS Detector Package
"""
Setup file for slsdet
Build upon the pybind11 example found here: https://github.com/pybind/python_example
"""
import os
import sys
from setuptools import setup, find_packages
from pybind11.setup_helpers import Pybind11Extension, build_ext
def read_version():
try:
version_file = os.path.join(os.path.dirname(__file__), 'slsdet', 'VERSION')
with open(version_file, "r") as f:
return f.read().strip()
except:
raise RuntimeError("VERSION file not found in slsdet package from setup.py.")
__version__ = read_version()
def get_conda_path():
"""
Keep this a function if we need some fancier logic later
"""
print('Prefix: ', os.environ['CONDA_PREFIX'])
return os.environ['CONDA_PREFIX']
#TODO migrate to CMake build or fetch files from cmake?
ext_modules = [
Pybind11Extension(
'_slsdet',
['src/main.cpp',
'src/enums.cpp',
'src/current.cpp',
'src/detector.cpp',
'src/network.cpp',
'src/pattern.cpp',
'src/scan.cpp',
'src/duration.cpp',
'src/DurationWrapper.cpp',
'src/pedestal.cpp',
]
,
include_dirs=[
os.path.join(get_conda_path(), 'include'),
],
libraries=['SlsDetector', 'SlsSupport', 'SlsReceiver'],
library_dirs=[
os.path.join(get_conda_path(), 'lib'),
],
language='c++'
),
]
setup(
name='slsdet',
version=__version__,
author='Erik Frojdh',
author_email='erik.frojdh@psi.ch',
url='https://github.com/slsdetectorgroup/slsDetectorPackage',
description='Detector API for SLS Detector Group detectors',
long_description='',
packages=find_packages(exclude=['contrib', 'docs', 'tests']),
package_data={
'slsdet': ['VERSION'],
},
ext_modules=ext_modules,
cmdclass={"build_ext": build_ext},
zip_safe=False,
)

View File

@ -0,0 +1,226 @@
from . import Detector, Pattern
from .bits import setbit, clearbit
import textwrap
from pathlib import Path
class PatternGenerator:
"""
Class to generate a pattern for the SLS detector. Intents to as closely as possible
mimic the old pattern generation in the C code.
"""
def __init__(self):
self.pattern = Pattern()
self.iaddr = 0
def SB(self, *bits):
"""
Set one or several bits. Change will take affect with the next PW.
"""
for bit in bits:
self.pattern.word[self.iaddr] = setbit(bit, self.pattern.word[self.iaddr])
return self.pattern.word[self.iaddr]
def CB(self, *bits):
"""
Clear one or several bits. Change will take affect with the next PW.
"""
for bit in bits:
self.pattern.word[self.iaddr] = clearbit(bit, self.pattern.word[self.iaddr])
return self.pattern.word[self.iaddr]
def _pw(self, verbose = False):
if verbose:
print(f'{self.iaddr:#06x} {self.pattern.word[self.iaddr]:#018x}')
#Limits are inclusive so we need to increment the address before writing the next word
self.pattern.limits[1] = self.iaddr
self.iaddr += 1
self.pattern.word[self.iaddr] = self.pattern.word[self.iaddr-1]
def PW(self, x = 1, verbose = False):
for i in range(x):
self._pw(verbose)
# def REPEAT(self, x, verbose = False):
# for i in range(x):
# self._pw(verbose)
# def PW2(self, verbose = 0):
# self.REPEAT(2, verbose)
def CLOCKS(self, bit, times = 1, length = 1, verbose = False):
"""
clocks "bit" n "times", every half clock is long "length"
length is optional, default value is 1
"""
for i in range(0, times):
self.SB(bit); self.PW(length, verbose)
self.CB(bit); self.PW(length, verbose)
def CLOCK(self, bit, length = 1, verbose = 0):
self.CLOCKS(bit, 1, length ,verbose)
def serializer(self, value, serInBit, clkBit, nbits, msbfirst = True, length = 1):
"""serializer(value,serInBit,clkBit,nbits,msbfirst=1,length=1)
Produces the .pat file needed to serialize a word into a shift register.
value: value to be serialized
serInBit: control bit corresponding to serial in
clkBit: control bit corresponding to the clock
nbits: number of bits of the target register to load
msbfirst: if 1 pushes in the MSB first (default),
if 0 pushes in the LSB first
length: length of all the PWs in the pattern
It produces no output because it modifies directly the members of the class pat via SB and CB"""
c = value
self.CB(serInBit, clkBit)
self.PW(length) #generate initial line with clk and serIn to 0
start = 0
stop = nbits
step = 1
if msbfirst:
start = nbits - 1
stop = -1
step =- 1 #reverts loop if msb has to be pushed in first
for i in range(start, stop, step):
if c & (1<<i):
self.SB(serInBit)
self.PW(length)
else:
self.CB(serInBit)
self.PW(length)
self.SB(clkBit)
self.PW(length)
self.CB(clkBit)
self.PW(length)
self.CB(serInBit, clkBit)
self.PW(length) #generate final line with clk and serIn to 0
#NOT IMPLEMENTED YET
#TODO! What should setstop do? Or can we remove it?
#def setstop():
#
def setoutput(self, bit):
self.pattern.ioctrl = setbit(bit, self.pattern.ioctrl)
def setinput(self, bit):
self.pattern.ioctrl= clearbit(bit, self.pattern.ioctrl)
#TODO! What should setclk do? Or can we remove it?
# def setclk(bit):
# self.clkctrl=self.setbit(bit,self.clkctrl)
def setinputs(self, *args):
for i in args:
self.setinput(i)
def setoutputs(self, *args):
for i in args:
self.setoutput(i)
#def setclks(self, *args):
# for i in args:
# self.setclk(i)
def setnloop(self, i, reps):
self.pattern.nloop[i] = reps
def setstartloop(self, i):
"""
Set startloop[i] to the current address.
"""
self.pattern.startloop[i] = self.iaddr
def setstoploop(self, i):
"""
Set stoploop[i] to the current address.
"""
self.pattern.stoploop[i] = self.iaddr
def setstart(self):
"""
Set start of pattern to the current address.
"""
self.pattern.limits[0]=self.iaddr
def setstop(self,l):
"""
Set stop of pattern to the current address.
"""
self.pattern.limits[1] = self.iaddr
def setwaitpoint(self, i):
"""
Set wait[i] to the current address.
"""
self.pattern.wait[i] = self.iaddr
def setwaittime(self, i, t):
"""
Set waittime[i] to t.
"""
self.pattern.waittime[i] = t
def setwait(self, i, t):
"""
Set wait[i] to the current address and waittime[i] to t.
"""
self.setwait(i)
self.setwaittime(i, t)
def __repr__(self):
return textwrap.dedent(f"""\
PatternBuilder:
patlimits: {self.pattern.limits}
startloop: {self.pattern.startloop}
stoploop: {self.pattern.stoploop}
nloop: {self.pattern.nloop}
wait: {self.pattern.wait}
waittime: {self.pattern.waittime}""")
def __str__(self):
return self.pattern.str()
def print(self):
print(self)
def save(self, fname):
"""Save pattern to text file"""
fname = str(fname) #Accept also Path objects, but C++ code needs a string
self.pattern.save(fname)
def load(self, fname):
"""Load pattern from text file"""
fname = str(fname) #Accept also Path objects, but C++ code needs a string
n = self.pattern.load(fname)
#If the firs and only word is 0 we assume an empty pattern
if n == 1 and self.pattern.word[0] == 0:
n = 0
self.iaddr = n
#To make PW work as expected we need to set 1+last word to the last word
if n > 0:
self.pattern.word[n] = self.pattern.word[n-1]
def send_to_detector(self, det):
"""
Load the pattern into the detector.
"""
det.setPattern(self.pattern)

View File

@ -12,8 +12,9 @@ from .gotthard2 import Gotthard2
from .moench import Moench from .moench import Moench
from .pattern import Pattern, patternParameters from .pattern import Pattern, patternParameters
from .gaincaps import Mythen3GainCapsWrapper from .gaincaps import Mythen3GainCapsWrapper
from .PatternGenerator import PatternGenerator
import _slsdet from . import _slsdet
xy = _slsdet.xy xy = _slsdet.xy
defs = _slsdet.slsDetectorDefs defs = _slsdet.slsDetectorDefs
@ -40,3 +41,6 @@ def read_version():
__version__ = read_version() __version__ = read_version()

31
python/slsdet/bits.py Normal file
View File

@ -0,0 +1,31 @@
import numpy as np
def setbit(bit, word):
if isinstance(word, np.generic):
mask = word.dtype.type(1)
mask = mask << bit
else:
mask = 1 << bit
return word | mask
def setbit_arr(bit, arr):
arr |= arr.dtype.type(1 << bit)
def clearbit(bit, word):
"""
Clear the bit at position bit in word.
Two paths to avoid converting the types.
"""
if isinstance(word, np.generic):
mask = word.dtype.type(1)
mask = ~(mask << bit)
else:
mask = ~(1 << bit)
return word & mask
def clearbit_arr(bit, arr):
arr &= arr.dtype.type(~(1 << bit))

View File

@ -4,7 +4,7 @@ from .detector import Detector, freeze
from .utils import element_if_equal from .utils import element_if_equal
from .dacs import DetectorDacs, NamedDacs from .dacs import DetectorDacs, NamedDacs
from .powers import DetectorPowers, NamedPowers from .powers import DetectorPowers, NamedPowers
import _slsdet from . import _slsdet
dacIndex = _slsdet.slsDetectorDefs.dacIndex dacIndex = _slsdet.slsDetectorDefs.dacIndex
from .detector_property import DetectorProperty from .detector_property import DetectorProperty

View File

@ -3,7 +3,7 @@
from .detector_property import DetectorProperty from .detector_property import DetectorProperty
from functools import partial from functools import partial
import numpy as np import numpy as np
import _slsdet from . import _slsdet
from .detector import freeze from .detector import freeze
dacIndex = _slsdet.slsDetectorDefs.dacIndex dacIndex = _slsdet.slsDetectorDefs.dacIndex
class Dac(DetectorProperty): class Dac(DetectorProperty):

View File

@ -1,8 +1,8 @@
# SPDX-License-Identifier: LGPL-3.0-or-other # SPDX-License-Identifier: LGPL-3.0-or-other
# Copyright (C) 2021 Contributors to the SLS Detector Package # Copyright (C) 2021 Contributors to the SLS Detector Package
from _slsdet import CppDetectorApi from ._slsdet import CppDetectorApi
from _slsdet import slsDetectorDefs from ._slsdet import slsDetectorDefs
from _slsdet import IpAddr, MacAddr from ._slsdet import IpAddr, MacAddr
runStatus = slsDetectorDefs.runStatus runStatus = slsDetectorDefs.runStatus
timingMode = slsDetectorDefs.timingMode timingMode = slsDetectorDefs.timingMode
@ -15,7 +15,7 @@ defs = slsDetectorDefs
from .utils import element_if_equal, all_equal, get_set_bits, list_to_bitmask from .utils import element_if_equal, all_equal, get_set_bits, list_to_bitmask
from .utils import Geometry, to_geo, element, reduce_time, is_iterable, hostname_list from .utils import Geometry, to_geo, element, reduce_time, is_iterable, hostname_list
from _slsdet import xy from ._slsdet import xy
from .gaincaps import Mythen3GainCapsWrapper from .gaincaps import Mythen3GainCapsWrapper
from . import utils as ut from . import utils as ut
from .proxy import JsonProxy, SlowAdcProxy, ClkDivProxy, MaxPhaseProxy, ClkFreqProxy, PatLoopProxy, PatNLoopProxy, PatWaitProxy, PatWaitTimeProxy from .proxy import JsonProxy, SlowAdcProxy, ClkDivProxy, MaxPhaseProxy, ClkFreqProxy, PatLoopProxy, PatNLoopProxy, PatWaitProxy, PatWaitTimeProxy

View File

@ -11,7 +11,7 @@ Created on Wed Dec 6 11:51:18 2017
from .detector import Detector from .detector import Detector
from .temperature import Temperature, DetectorTemperature from .temperature import Temperature, DetectorTemperature
from .dacs import DetectorDacs from .dacs import DetectorDacs
import _slsdet from . import _slsdet
dacIndex = _slsdet.slsDetectorDefs.dacIndex dacIndex = _slsdet.slsDetectorDefs.dacIndex
from .detector_property import DetectorProperty from .detector_property import DetectorProperty

View File

@ -15,8 +15,8 @@ if dt === detectorType.EIGER:
""" """
import _slsdet from . import _slsdet
for name, cls in _slsdet.slsDetectorDefs.__dict__.items(): for name, cls in _slsdet.slsDetectorDefs.__dict__.items():
if isinstance(cls, type): if isinstance(cls, type):
exec(f'{name} = {cls.__module__}.{cls.__qualname__}') exec(f'{name} = _slsdet.{cls.__qualname__}')

View File

@ -1,6 +1,6 @@
import _slsdet from . import _slsdet
gc = _slsdet.slsDetectorDefs.M3_GainCaps gc = _slsdet.slsDetectorDefs.M3_GainCaps

View File

@ -11,7 +11,7 @@ from .detector import Detector, freeze
# from .adcs import Adc, DetectorAdcs # from .adcs import Adc, DetectorAdcs
from .dacs import DetectorDacs from .dacs import DetectorDacs
import _slsdet from . import _slsdet
dacIndex = _slsdet.slsDetectorDefs.dacIndex dacIndex = _slsdet.slsDetectorDefs.dacIndex
from .detector_property import DetectorProperty from .detector_property import DetectorProperty

View File

@ -11,7 +11,7 @@ from .detector import Detector, freeze
# from .adcs import Adc, DetectorAdcs # from .adcs import Adc, DetectorAdcs
from .dacs import DetectorDacs from .dacs import DetectorDacs
import _slsdet from . import _slsdet
dacIndex = _slsdet.slsDetectorDefs.dacIndex dacIndex = _slsdet.slsDetectorDefs.dacIndex
from .detector_property import DetectorProperty from .detector_property import DetectorProperty

View File

@ -9,7 +9,7 @@ This file contains the specialization for the Moench detector
from .detector import Detector, freeze from .detector import Detector, freeze
from .dacs import DetectorDacs from .dacs import DetectorDacs
import _slsdet from . import _slsdet
dacIndex = _slsdet.slsDetectorDefs.dacIndex dacIndex = _slsdet.slsDetectorDefs.dacIndex
from .detector_property import DetectorProperty from .detector_property import DetectorProperty

View File

@ -11,7 +11,7 @@ from .detector import Detector, freeze
# from .adcs import Adc, DetectorAdcs # from .adcs import Adc, DetectorAdcs
from .dacs import DetectorDacs from .dacs import DetectorDacs
import _slsdet from . import _slsdet
dacIndex = _slsdet.slsDetectorDefs.dacIndex dacIndex = _slsdet.slsDetectorDefs.dacIndex
gc_enums = _slsdet.slsDetectorDefs.M3_GainCaps gc_enums = _slsdet.slsDetectorDefs.M3_GainCaps
from .detector_property import DetectorProperty from .detector_property import DetectorProperty

View File

@ -1,8 +1,8 @@
# SPDX-License-Identifier: LGPL-3.0-or-other # SPDX-License-Identifier: LGPL-3.0-or-other
# Copyright (C) 2021 Contributors to the SLS Detector Package # Copyright (C) 2021 Contributors to the SLS Detector Package
import _slsdet from . import _slsdet
from _slsdet import Pattern from ._slsdet import Pattern
class patternParameters(_slsdet.patternParameters): class patternParameters(_slsdet.patternParameters):

View File

@ -3,7 +3,7 @@
from .detector_property import DetectorProperty from .detector_property import DetectorProperty
from functools import partial from functools import partial
import numpy as np import numpy as np
import _slsdet from . import _slsdet
from .detector import freeze from .detector import freeze
dacIndex = _slsdet.slsDetectorDefs.dacIndex dacIndex = _slsdet.slsDetectorDefs.dacIndex
class Power(DetectorProperty): class Power(DetectorProperty):

View File

@ -3,7 +3,7 @@
from .utils import element_if_equal from .utils import element_if_equal
from .enums import dacIndex from .enums import dacIndex
from .defines import M3_MAX_PATTERN_LEVELS, MAX_PATTERN_LEVELS from .defines import M3_MAX_PATTERN_LEVELS, MAX_PATTERN_LEVELS
from _slsdet import slsDetectorDefs from ._slsdet import slsDetectorDefs
detectorType = slsDetectorDefs.detectorType detectorType = slsDetectorDefs.detectorType

View File

@ -6,7 +6,7 @@ but not directly used in controlling the detector
""" """
from collections import namedtuple from collections import namedtuple
import _slsdet #C++ lib from . import _slsdet #C++ lib
import functools import functools
import datetime as dt import datetime as dt
import pathlib import pathlib

View File

@ -1,3 +1,4 @@
#include <chrono>
#include "py_headers.h" #include "py_headers.h"
#include "DurationWrapper.h" #include "DurationWrapper.h"
@ -19,4 +20,25 @@ void init_duration(py::module &m) {
<< " count: " << self.count() << ")"; << " count: " << self.count() << ")";
return ss.str(); return ss.str();
}); });
m.def(
"test_return_DurationWrapper",
[]() {
DurationWrapper t(1.3);
return t;
},
R"(
Test function to return a DurationWrapper object. Ensures that the automatic conversion in typecaster.h works.
)");
m.def(
"test_duration_to_ns",
[](const std::chrono::nanoseconds t) {
//Duration wrapper is used to be able to convert from time in python to chrono::nanoseconds
//return count to have something to test
return t.count();
},
R"(
Test function convert DurationWrapper or number to chrono::ns. Ensures that the automatic conversion in typecaster.h works.
)"); // default value to test the default constructor
} }

View File

@ -20,8 +20,10 @@ void init_pattern(py::module &m) {
}); });
py::class_<sls::Pattern> Pattern(m, "Pattern"); py::class_<sls::Pattern> Pattern(m, "Pattern");
Pattern.def(py::init()); Pattern.def(py::init())
Pattern.def("load", &sls::Pattern::load); .def("load", &sls::Pattern::load)
Pattern.def("data", (pat * (sls::Pattern::*)()) & sls::Pattern::data, .def("save", &sls::Pattern::save)
.def("str", &sls::Pattern::str)
.def("data", (pat * (sls::Pattern::*)()) & sls::Pattern::data,
py::return_value_policy::reference); py::return_value_policy::reference);
} }

View File

@ -54,11 +54,16 @@ template <> struct type_caster<std::chrono::nanoseconds> {
value = duration_cast<nanoseconds>(duration<double>(PyFloat_AsDouble(src.ptr()))); value = duration_cast<nanoseconds>(duration<double>(PyFloat_AsDouble(src.ptr())));
return true; return true;
} }
// If invoked with an int we assume it is nanoseconds and convert, same as in chrono.h
if (PyLong_Check(src.ptr())) {
value = duration_cast<nanoseconds>(duration<int64_t>(PyLong_AsLongLong(src.ptr())));
return true;
}
// Lastly if we were actually called with a DurationWrapper object we get // Lastly if we were actually called with a DurationWrapper object we get
// the number of nanoseconds and create a std::chrono::nanoseconds from it // the number of nanoseconds and create a std::chrono::nanoseconds from it
py::object py_cls = py::module::import("_slsdet").attr("DurationWrapper"); py::object py_cls = py::module::import("slsdet._slsdet").attr("DurationWrapper");
if (py::isinstance(src, py_cls)){ if (py::isinstance(src, py_cls)){
sls::DurationWrapper *cls = src.cast<sls::DurationWrapper *>(); sls::DurationWrapper *cls = src.cast<sls::DurationWrapper *>();
value = nanoseconds(cls->count()); value = nanoseconds(cls->count());
@ -77,7 +82,7 @@ template <> struct type_caster<std::chrono::nanoseconds> {
* set the count from chrono::nanoseconds and return * set the count from chrono::nanoseconds and return
*/ */
static handle cast(std::chrono::nanoseconds src, return_value_policy /* policy */, handle /* parent */) { static handle cast(std::chrono::nanoseconds src, return_value_policy /* policy */, handle /* parent */) {
py::object py_cls = py::module::import("_slsdet").attr("DurationWrapper"); py::object py_cls = py::module::import("slsdet._slsdet").attr("DurationWrapper");
py::object* obj = new py::object; py::object* obj = new py::object;
*obj = py_cls(); *obj = py_cls();
sls::DurationWrapper *dur = obj->cast<sls::DurationWrapper *>(); sls::DurationWrapper *dur = obj->cast<sls::DurationWrapper *>();

View File

@ -0,0 +1,58 @@
import pytest
from slsdet import DurationWrapper
#import the compiled extension to use test functions for the automatic conversion
from slsdet import _slsdet
def test_default_construction_of_DurationWrapper():
"""Test default construction of DurationWrapper"""
t = DurationWrapper()
assert t.count() == 0
assert t.total_seconds() == 0
def test_construction_of_DurationWrapper():
"""Test construction of DurationWrapper with total_seconds"""
t = DurationWrapper(5)
assert t.count() == 5e9
assert t.total_seconds() == 5
def test_set_count_on_DurationWrapper():
"""Test set_count on DurationWrapper"""
t = DurationWrapper()
t.set_count(10)
assert t.count() == 10
assert t.total_seconds() == 10e-9
t.set_count(0)
assert t.count() == 0
assert t.total_seconds() == 0
def test_return_a_DurationWrapper_from_cpp():
"""Test returning a DurationWrapper from C++"""
t = _slsdet.test_return_DurationWrapper()
assert t.count() == 1.3e9
assert t.total_seconds() == 1.3
def test_call_a_cpp_function_with_a_duration_wrapper():
"""C++ functions can accept a DurationWrapper"""
t = DurationWrapper(5)
assert _slsdet.test_duration_to_ns(t) == 5e9
def test_call_a_cpp_function_converting_number_to_DurationWrapper():
"""int and float can be converted to std::chrono::nanoseconds"""
assert _slsdet.test_duration_to_ns(0) == 0
assert _slsdet.test_duration_to_ns(3) == 3e9
assert _slsdet.test_duration_to_ns(1.3) == 1.3e9
assert _slsdet.test_duration_to_ns(10e-9) == 10
def test_call_a_cpp_function_with_datetime_timedelta():
"""datetime.timedelta can be converted to std::chrono::nanoseconds"""
import datetime
t = datetime.timedelta(seconds=5)
assert _slsdet.test_duration_to_ns(t) == 5e9
t = datetime.timedelta(seconds=0)
assert _slsdet.test_duration_to_ns(t) == 0
t = datetime.timedelta(seconds=1.3)
assert _slsdet.test_duration_to_ns(t) == 1.3e9

View File

@ -0,0 +1,152 @@
import pytest
from slsdet import PatternGenerator
def apply_detconf(p):
"""
Hacky workaround to apply detConf_mh02 to a pattern
"""
DACMON = 0
cnt_en_3 = 1
pulse_counter_en = 2
cnt_en_1 = 3
par_load = 4
pulse_mux_ctr = 5
reset_cnt = 6
reset_periphery = 7
config_load = 8
cnt_en_0 = 9
tbl = 10
clk_ext = 11
trimbit_load_reg = 12
store = 13
data_in = 14
en_pll_clk = 15
cnt_en_2 = 16
DACINT = 17
data_out_slow = 18 #IN
COMP2_MON = 19 #IN
start_read = 20
dac_store = 21
CNT3_MON = 22 #IN
EN_PIX_DIG_MON = 23
clk_sel = 24
BUSY = 25 #IN
COMP3_MON = 26 #IN
CNT2_MON = 27 #IN
dbit_ena=62 #FIFO LATCH
adc_ena=63 #ADC ENABLE
#FPGA input/ouutputs
p.setoutput(DACMON)
p.setoutput(cnt_en_3)
p.setoutput(pulse_counter_en)
p.setoutput(cnt_en_1)
p.setoutput(par_load)
p.setoutput(pulse_mux_ctr)
p.setoutput(reset_cnt)
p.setoutput(reset_periphery)
p.setoutput(cnt_en_0)
p.setoutput(tbl)
p.setoutput(clk_ext)
p.setoutput(config_load)
p.setoutput(trimbit_load_reg)
p.setoutput(store)
p.setoutput(data_in)
p.setoutput(en_pll_clk)
p.setoutput(cnt_en_2)
p.setoutput(DACINT)
p.setinput(data_out_slow)
p.setinput(COMP2_MON)
p.setoutput(start_read)
p.setoutput(dac_store)
p.setinput(CNT3_MON)
p.setoutput(EN_PIX_DIG_MON)
p.setoutput(clk_sel)
p.setinput(BUSY)
p.setinput(COMP3_MON)
p.setinput(CNT2_MON)
#system signals
p.setoutput(adc_ena)
# FIFO LATCH
p.setoutput(dbit_ena)
return p
def test_first_two_PW():
p = PatternGenerator()
#The pattern is created with a single empty word
assert p.pattern.limits[0] == 0
assert p.pattern.limits[1] == 0
p.SB(8)
p.PW()
#When doing the first PW the empty word is overwritten
assert p.pattern.limits[0] == 0
assert p.pattern.limits[1] == 0
assert p.pattern.word[0] == 256
p.SB(9)
p.PW()
#When doing the second PW we add a new word
assert p.pattern.limits[0] == 0
assert p.pattern.limits[1] == 1
assert p.pattern.word[0] == 256
assert p.pattern.word[1] == 768
def test_simple_pattern():
"""
Using enable pll pattern for MH02
"""
en_pll_clk = 15
p = PatternGenerator()
p = apply_detconf(p)
p.SB(en_pll_clk)
p.PW()
p.PW()
lines = str(p).split("\n")
enable_pll_pattern = [
"patword 0x0000 0x0000000000008000",
"patword 0x0001 0x0000000000008000",
"patioctrl 0xc000000001b3ffff",
"patlimits 0x0000 0x0001",
"patloop 0 0x1fff 0x1fff",
"patnloop 0 0",
"patloop 1 0x1fff 0x1fff",
"patnloop 1 0",
"patloop 2 0x1fff 0x1fff",
"patnloop 2 0",
"patloop 3 0x1fff 0x1fff",
"patnloop 3 0",
"patloop 4 0x1fff 0x1fff",
"patnloop 4 0",
"patloop 5 0x1fff 0x1fff",
"patnloop 5 0",
"patwait 0 0x1fff",
"patwaittime 0 0",
"patwait 1 0x1fff",
"patwaittime 1 0",
"patwait 2 0x1fff",
"patwaittime 2 0",
"patwait 3 0x1fff",
"patwaittime 3 0",
"patwait 4 0x1fff",
"patwaittime 4 0",
"patwait 5 0x1fff",
"patwaittime 5 0",
]
assert len(lines) == len(enable_pll_pattern)
for i, line in enumerate(lines):
assert line == enable_pll_pattern[i]

50
python/tests/test_bits.py Normal file
View File

@ -0,0 +1,50 @@
from slsdet.bits import clearbit, clearbit_arr, setbit, setbit_arr
import numpy as np
def test_clearbit_on_python_int():
val = 5 # 0b101
r = clearbit(0, val)
assert r == 4
assert val == 5
def test_setbit_on_python_int():
val = 5 # 0b101
r = setbit(1, val)
assert r == 7
assert val == 5
def test_setbit_doesnt_change_type():
word = np.int32(5)
ret = setbit(0, word)
assert isinstance(ret, np.int32)
def test_clearbit_doesnt_change_type():
word = np.uint8(5)
ret = clearbit(0, word)
assert isinstance(ret, np.uint8)
def test_setbit_on_array_element():
arr = np.zeros(10, dtype=np.uint64)
arr[5] = setbit(0, arr[5])
arr[5] = setbit(1, arr[5])
arr[5] = setbit(4, arr[5])
assert arr[4] == 0
assert arr[5] == 19 # 0b10011
assert arr[6] == 0
def test_setbit_arr():
arr = np.zeros(10, dtype=np.int32)
setbit_arr(3, arr[3:9])
assert all(arr == np.array((0, 0, 0, 8, 8, 8, 8, 8, 8, 0), dtype=np.int32))
def test_clearbit_arr():
arr = np.array((5, 5, 5), dtype=np.int8)
clearbit_arr(0, arr)
assert all(arr == (4, 4, 4))

View File

@ -5,8 +5,8 @@
#include "sls/sls_detector_defs.h" #include "sls/sls_detector_defs.h"
#define MIN_REQRD_VRSN_T_RD_API 0x171220 #define MIN_REQRD_VRSN_T_RD_API 0x171220
#define REQRD_FRMWRE_VRSN_BOARD2 0x230920 // 1.0 pcb (version = 010) #define REQRD_FRMWRE_VRSN_BOARD2 0x250209 // 1.0 pcb (version = 010)
#define REQRD_FRMWRE_VRSN 0x230921 // 2.0 pcb (version = 011) #define REQRD_FRMWRE_VRSN 0x250208 // 2.0 pcb (version = 011)
#define NUM_HARDWARE_VERSIONS (2) #define NUM_HARDWARE_VERSIONS (2)
#define HARDWARE_VERSION_NUMBERS \ #define HARDWARE_VERSION_NUMBERS \

View File

@ -148,6 +148,8 @@ int main(int argc, char *argv[]) {
strcpy(version, APIMYTHEN3); strcpy(version, APIMYTHEN3);
#elif GOTTHARD2D #elif GOTTHARD2D
strcpy(version, APIGOTTHARD2); strcpy(version, APIGOTTHARD2);
#elif XILINX_CHIPTESTBOARDD
strcpy(version, APIXILINXCTB);
#endif #endif
LOG(logINFO, ("SLS Detector Server Version: %s\n", version)); LOG(logINFO, ("SLS Detector Server Version: %s\n", version));
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);

View File

@ -10891,12 +10891,19 @@ int get_timing_info_decoder(int file_des) {
functionNotImplemented(); functionNotImplemented();
#else #else
// get only // get only
if (isHardwareVersion_1_0()) {
ret = FAIL;
sprintf(mess, "Could not get timing info decoder. Not supported "
"for hardware version 1.0\n");
LOG(logERROR, (mess));
} else {
ret = getTimingInfoDecoder(&retval); ret = getTimingInfoDecoder(&retval);
LOG(logDEBUG1, ("retval timing info decoder: %d\n", retval)); LOG(logDEBUG1, ("retval timing info decoder: %d\n", retval));
if (ret == FAIL) { if (ret == FAIL) {
strcpy(mess, "Could not get timing info decoder\n"); strcpy(mess, "Could not get timing info decoder\n");
LOG(logERROR, (mess)); LOG(logERROR, (mess));
} }
}
#endif #endif
return Server_SendResult(file_des, INT32, &retval, sizeof(retval)); return Server_SendResult(file_des, INT32, &retval, sizeof(retval));
} }

View File

@ -23,6 +23,7 @@ typedef struct __attribute__((packed)) {
#ifdef __cplusplus #ifdef __cplusplus
class Pattern { class Pattern {
patternParameters *pat = new patternParameters{}; patternParameters *pat = new patternParameters{};
std::ostream& stream(std::ostream &os) const;
public: public:
Pattern(); Pattern();
@ -34,7 +35,7 @@ class Pattern {
patternParameters *data() const; patternParameters *data() const;
size_t size() const noexcept { return sizeof(patternParameters); } size_t size() const noexcept { return sizeof(patternParameters); }
void validate() const; void validate() const;
void load(const std::string &fname); size_t load(const std::string &fname);
void save(const std::string &fname); void save(const std::string &fname);
std::string str() const; std::string str() const;
}; };

View File

@ -93,7 +93,8 @@ void Pattern::validate() const {
} }
} }
void Pattern::load(const std::string &fname) { size_t Pattern::load(const std::string &fname) {
size_t numPatWords = 0;
std::ifstream input_file(fname); std::ifstream input_file(fname);
if (!input_file) { if (!input_file) {
throw RuntimeError("Could not open pattern file " + fname + throw RuntimeError("Could not open pattern file " + fname +
@ -125,6 +126,7 @@ void Pattern::load(const std::string &fname) {
throw RuntimeError("Invalid address for " + ToString(args)); throw RuntimeError("Invalid address for " + ToString(args));
} }
pat->word[addr] = StringTo<uint64_t>(args[2]); pat->word[addr] = StringTo<uint64_t>(args[2]);
++numPatWords;
} else if (cmd == "patioctrl") { } else if (cmd == "patioctrl") {
if (nargs != 1) { if (nargs != 1) {
throw RuntimeError("Invalid arguments for " + throw RuntimeError("Invalid arguments for " +
@ -238,6 +240,41 @@ void Pattern::load(const std::string &fname) {
} }
} }
} }
return numPatWords;
}
std::ostream& Pattern::stream(std::ostream &os) const{
for (uint32_t i = pat->limits[0]; i <= pat->limits[1]; ++i) {
os << "patword " << ToStringHex(i, 4) << " "
<< ToStringHex(pat->word[i], 16) << std::endl;
}
// patioctrl
os << "patioctrl " << ToStringHex(pat->ioctrl, 16) << std::endl;
// patlimits
os << "patlimits " << ToStringHex(pat->limits[0], 4) << " "
<< ToStringHex(pat->limits[1], 4) << std::endl;
for (size_t i = 0; i < MAX_PATTERN_LEVELS; ++i) {
// patloop
os << "patloop " << i << " "
<< ToStringHex(pat->startloop[i], 4) << " "
<< ToStringHex(pat->stoploop[i], 4) << std::endl;
// patnloop
os << "patnloop " << i << " " << pat->nloop[i] << std::endl;
}
for (size_t i = 0; i < MAX_PATTERN_LEVELS; ++i) {
// patwait
os << "patwait " << i << " " << ToStringHex(pat->wait[i], 4)
<< std::endl;
// patwaittime
os << "patwaittime " << i << " " << pat->waittime[i];
if (i<MAX_PATTERN_LEVELS-1)
os << std::endl;
}
return os;
} }
void Pattern::save(const std::string &fname) { void Pattern::save(const std::string &fname) {
@ -246,65 +283,12 @@ void Pattern::save(const std::string &fname) {
throw RuntimeError("Could not open pattern file " + fname + throw RuntimeError("Could not open pattern file " + fname +
" for writing"); " for writing");
} }
std::ostringstream os; stream(output_file);
// pattern word
for (uint32_t i = pat->limits[0]; i <= pat->limits[1]; ++i) {
output_file << "patword " << ToStringHex(i, 4) << " "
<< ToStringHex(pat->word[i], 16) << std::endl;
}
// patioctrl
output_file << "patioctrl " << ToStringHex(pat->ioctrl, 16) << std::endl;
// patlimits
output_file << "patlimits " << ToStringHex(pat->limits[0], 4) << " "
<< ToStringHex(pat->limits[1], 4) << std::endl;
for (size_t i = 0; i < MAX_PATTERN_LEVELS; ++i) {
// patloop
output_file << "patloop " << i << " "
<< ToStringHex(pat->startloop[i], 4) << " "
<< ToStringHex(pat->stoploop[i], 4) << std::endl;
// patnloop
output_file << "patnloop " << i << " " << pat->nloop[i] << std::endl;
}
for (size_t i = 0; i < MAX_PATTERN_LEVELS; ++i) {
// patwait
output_file << "patwait " << i << " " << ToStringHex(pat->wait[i], 4)
<< std::endl;
// patwaittime
output_file << "patwaittime " << i << " " << pat->waittime[i]
<< std::endl;
}
} }
std::string Pattern::str() const { std::string Pattern::str() const {
std::ostringstream oss; std::ostringstream oss;
oss << '[' << std::setfill('0') << std::endl; stream(oss);
int addr_width = 4;
int word_width = 16;
for (int i = 0; i < MAX_PATTERN_LENGTH; ++i) {
if (pat->word[i] != 0) {
oss << "patword " << ToStringHex(i, addr_width) << " "
<< ToStringHex(pat->word[i], word_width) << std::endl;
}
}
oss << "patioctrl " << ToStringHex(pat->ioctrl, word_width) << std::endl
<< "patlimits " << ToStringHex(pat->limits[0], addr_width) << " "
<< ToStringHex(pat->limits[1], addr_width) << std::endl;
for (int i = 0; i != MAX_PATTERN_LEVELS; ++i) {
oss << "patloop " << i << ' '
<< ToStringHex(pat->startloop[i], addr_width) << " "
<< ToStringHex(pat->stoploop[i], addr_width) << std::endl
<< "patnloop " << pat->nloop[i] << std::endl
<< "patwait " << i << ' ' << ToStringHex(pat->wait[i], addr_width)
<< std::endl
<< "patwaittime " << i << ' ' << pat->waittime[i] << std::endl;
}
oss << ']';
return oss.str(); return oss.str();
} }

View File

@ -3236,7 +3236,7 @@ TEST_CASE("reg", "[.cmdcall]") {
addr = 0x80; addr = 0x80;
} }
if (det_type == defs::GOTTHARD2) { if (det_type == defs::GOTTHARD2) {
addr = 0x20; addr = 0x298;
} }
std::string saddr = ToStringHex(addr); std::string saddr = ToStringHex(addr);
auto prev_val = det.readRegister(addr); auto prev_val = det.readRegister(addr);
@ -3292,7 +3292,7 @@ TEST_CASE("setbit", "[.cmdcall]") {
addr = 0x80; addr = 0x80;
} }
if (det_type == defs::GOTTHARD2) { if (det_type == defs::GOTTHARD2) {
addr = 0x20; addr = 0x298;
} }
std::string saddr = ToStringHex(addr); std::string saddr = ToStringHex(addr);
auto prev_val = det.readRegister(addr); auto prev_val = det.readRegister(addr);
@ -3322,7 +3322,7 @@ TEST_CASE("clearbit", "[.cmdcall]") {
addr = 0x80; addr = 0x80;
} }
if (det_type == defs::GOTTHARD2) { if (det_type == defs::GOTTHARD2) {
addr = 0x20; addr = 0x298;
} }
std::string saddr = ToStringHex(addr); std::string saddr = ToStringHex(addr);
auto prev_val = det.readRegister(addr); auto prev_val = det.readRegister(addr);
@ -3352,7 +3352,7 @@ TEST_CASE("getbit", "[.cmdcall]") {
addr = 0x80; addr = 0x80;
} }
if (det_type == defs::GOTTHARD2) { if (det_type == defs::GOTTHARD2) {
addr = 0x20; addr = 0x298;
} }
std::string saddr = ToStringHex(addr); std::string saddr = ToStringHex(addr);
auto prev_val = det.readRegister(addr); auto prev_val = det.readRegister(addr);

View File

@ -5,8 +5,8 @@
#define APIRECEIVER "developer 0x241122" #define APIRECEIVER "developer 0x241122"
#define APICTB "developer 0x250310" #define APICTB "developer 0x250310"
#define APIGOTTHARD2 "developer 0x250310" #define APIGOTTHARD2 "developer 0x250310"
#define APIJUNGFRAU "developer 0x250310"
#define APIMYTHEN3 "developer 0x250310" #define APIMYTHEN3 "developer 0x250310"
#define APIMOENCH "developer 0x250310" #define APIMOENCH "developer 0x250310"
#define APIXILINXCTB "developer 0x250310"
#define APIEIGER "developer 0x250310" #define APIEIGER "developer 0x250310"
#define APIXILINXCTB "developer 0x250311"
#define APIJUNGFRAU "developer 0x250318"