Compare commits

...

84 Commits

Author SHA1 Message Date
41a73e0c73 fix a ctbConfig test
All checks were successful
Build on RHEL9 / build (push) Successful in 3m20s
Build on RHEL8 / build (push) Successful in 4m53s
2025-12-15 15:56:21 +01:00
caa3b3087c Allowed concatenation with other RegisterValue, made them all constexpr 2025-12-15 15:47:33 +01:00
ea9508da9f Removing implicit conversions:
RegisterAddresss and RegisterValue: Removed the implicit conversions.
RegisterAddress: Changed member name from address_ to value_ and method as well to value().
RegisterValue: Also added | operator to be able to concatenate with uint32_t. Same in python bindings (but could not find the tests to modify
2025-12-15 15:19:27 +01:00
ea561e2422 got rid of setbitposition and setaddress, instead overloaded constructor to take in strings so that the conversion from string to bit address members, takes place within the class for easy maintainance in case type changes 2025-12-15 14:29:55 +01:00
5f287ea092 changed bitPosition from int to uint32_t 2025-12-15 13:41:56 +01:00
199f5f113f added marker for 8 cmd tests connected to define, changed macro to static constexpr 2025-12-15 12:14:29 +01:00
224f202e05 naming refactoring (getRegisterDefnition to retunr name and address specifically
All checks were successful
Build on RHEL9 / build (push) Successful in 3m21s
Build on RHEL8 / build (push) Successful in 4m34s
2025-12-13 02:26:07 +01:00
ad642c07a4 refactor from github comments
All checks were successful
Build on RHEL9 / build (push) Successful in 3m23s
Build on RHEL8 / build (push) Successful in 5m21s
2025-12-12 17:26:34 +01:00
5ae1021de9 allow string for register and bit names in c++ api 2025-12-12 17:08:26 +01:00
e3c1191088 Merge remote-tracking branch 'origin/dev/define_cmd' into dev/define_cmd
All checks were successful
Build on RHEL9 / build (push) Successful in 3m20s
Build on RHEL8 / build (push) Successful in 5m12s
2025-12-12 15:22:42 +01:00
497c890b28 split define into 2 commands define_reg and define_bit, definelist into 2: definelist_reg and definelist_bit 2025-12-12 15:21:35 +01:00
froejdh_e
c34eec033a added example using bits 2025-12-12 09:47:45 +01:00
Erik Fröjdh
5295e148da Merge branch 'developer' into dev/define_cmd 2025-12-12 08:36:55 +01:00
Erik Fröjdh
f150eed74b Using define reg/bit from python (#1344)
* define_bit, define_addr in python. 
* setBit/clearBit takes int or addr
2025-12-12 08:35:31 +01:00
654c16b52b changed BitPosition to BitAddress
All checks were successful
Build on RHEL9 / build (push) Successful in 3m44s
Build on RHEL8 / build (push) Successful in 5m17s
2025-12-11 13:04:13 +01:00
ee3222e56b removed bit names in reg 2025-12-11 12:45:45 +01:00
a503881353 fixing so all tests pass 2025-12-11 11:44:04 +01:00
497b3ed00e Merge pull request #1343 from slsdetectorgroup/dev/update_release_notes
All checks were successful
Build on local RHEL9 / build (push) Successful in 1m23s
Build on local RHEL8 / build (push) Successful in 3m26s
Build on RHEL9 / build (push) Successful in 3m35s
Build on RHEL8 / build (push) Successful in 5m10s
updated release notes
2025-12-11 09:52:56 +01:00
300a296c20 updated release notes 2025-12-10 16:21:00 +01:00
ecf1ec553d removed duplicates
Some checks failed
Build on RHEL8 / build (push) Failing after 1m14s
Build on RHEL9 / build (push) Successful in 3m52s
2025-12-08 15:18:27 +01:00
0ca667bd52 Merge branch 'developer' into dev/define_cmd
Some checks failed
Build on RHEL8 / build (push) Failing after 1m14s
Build on RHEL9 / build (push) Successful in 4m17s
2025-12-08 09:55:08 +01:00
01e392b112 Merge pull request #1342 from slsdetectorgroup/dev/dbitorder
All checks were successful
Build on local RHEL9 / build (push) Successful in 1m22s
Build on local RHEL8 / build (push) Successful in 3m26s
Build on RHEL9 / build (push) Successful in 3m49s
Build on RHEL8 / build (push) Successful in 4m31s
Preserve order in receiver dbit list
2025-12-04 16:03:48 +01:00
5409cec73e adapted test to test no reorder behavior
All checks were successful
Build on RHEL9 / build (push) Successful in 4m12s
Build on RHEL8 / build (push) Successful in 4m30s
2025-12-04 10:58:37 +01:00
Erik Fröjdh
1c31a85a43 added function to remove duplicates, preserve order of dbit 2025-12-03 12:14:35 +01:00
134137ead0 build RH8 in conda env
All checks were successful
Build on local RHEL8 / build (push) Successful in 3m24s
Build on RHEL9 / build (push) Successful in 3m24s
Build on local RHEL9 / build (push) Successful in 1m21s
Build on RHEL8 / build (push) Successful in 5m25s
2025-11-27 16:28:21 +01:00
6d3922f487 typo
All checks were successful
Build on RHEL9 / build (push) Successful in 3m24s
Build on RHEL8 / build (push) Successful in 5m14s
Build on local RHEL9 / build (push) Successful in 1m22s
Build on local RHEL8 / build (push) Successful in 3m23s
2025-11-27 15:27:17 +01:00
f14cfb0b31 deploy python ui
Some checks failed
Build on local RHEL9 / build (push) Successful in 1m23s
Build on local RHEL8 / build (push) Successful in 3m23s
Build on RHEL9 / build (push) Successful in 4m26s
Build on RHEL8 / build (push) Has been cancelled
2025-11-27 15:21:34 +01:00
cf4e6b65c1 Merge branch 'dev/NFS_testing' into developer 2025-11-27 11:00:29 +01:00
0da80cd898 local runners only for developer
All checks were successful
Build on RHEL9 / build (push) Successful in 3m53s
Build on RHEL8 / build (push) Successful in 5m30s
2025-11-27 10:43:51 +01:00
8e7921ae45 Merge pull request #1339 from slsdetectorgroup/dev/python_cmd_for_ROI
All checks were successful
Build on RHEL9 / build (push) Successful in 4m30s
Build on RHEL8 / build (push) Successful in 5m46s
Dev/python cmd for roi
2025-11-26 15:29:40 +01:00
b90851a855 clang-format 12 2025-11-26 14:15:04 +01:00
683accd914 fix unsuccesful merge in RELEASE.txt 2025-11-26 14:04:55 +01:00
30e82e4740 removed tests for eiger 2025-11-26 13:51:38 +01:00
08486b9812 rx_roi also accepts sequence of 2 ints 2025-11-26 13:51:22 +01:00
a5c661ce22 another bug for xilinx in test script 2025-11-26 13:51:08 +01:00
50448cefb4 Code Review 2025-11-26 13:50:45 +01:00
c1e5cfa101 fixed virtual detector test scripts 2025-11-26 12:25:25 +01:00
ae8c9175bf disable user id and port test 2025-11-26 12:24:48 +01:00
e7f5a2aa11 added colorama in github workflows 2025-11-26 12:24:27 +01:00
cad44943c3 wrapped virtual detector setup in a test fixture 2025-11-26 12:24:07 +01:00
d4f8049623 added tests 2025-11-26 12:23:40 +01:00
925cd55b1c API also allows single sequence for single ROI 2025-11-26 12:23:22 +01:00
ec11ba5a54 added typecaster for slsdefs::ROI and added setter and getter for ROI 2025-11-26 12:23:04 +01:00
eea4dca449 remove branch restrictions
All checks were successful
Build on local RHEL9 / build (push) Successful in 1m44s
Build on local RHEL8 / build (push) Successful in 4m34s
Build on RHEL9 / build (push) Successful in 4m31s
Build on RHEL8 / build (push) Successful in 5m47s
2025-11-26 09:11:55 +01:00
3285221e8a added RH9 workflow
All checks were successful
Build on local RHEL8 / build (push) Successful in 4m37s
Build on RHEL8 / build (push) Successful in 5m18s
Build on RHEL9 / build (push) Successful in 5m26s
Build on local RHEL9 / build (push) Successful in 1m54s
2025-11-25 17:56:20 +01:00
Erik Fröjdh
56de3c17ea Merge branch 'developer' into dev/define_cmd
Some checks failed
Build on RHEL8 / build (push) Failing after 1m28s
Build on RHEL9 / build (push) Successful in 5m36s
2025-11-25 16:53:49 +01:00
Erik Fröjdh
f32fcf1e88 Using system libzmq in conda builds (#1327)
All checks were successful
Build on RHEL8 / build (push) Successful in 5m18s
Build on RHEL9 / build (push) Successful in 5m21s
* system (conda) libzmq
* added python 3.14 and bumped cibuildwheel version
2025-11-25 16:53:20 +01:00
3ff199822d change path to RH8
All checks were successful
Build on local RHEL8 / build (push) Successful in 4m37s
Build on RHEL8 / build (push) Successful in 5m13s
Build on RHEL9 / build (push) Successful in 6m0s
2025-11-25 16:37:42 +01:00
0ba9a269a1 New this build bin path script (#1335)
All checks were successful
Build on RHEL8 / build (push) Successful in 5m34s
Build on RHEL9 / build (push) Successful in 5m54s
* better this_build_bin_path script
* Put new values first in PATH and PYTHONPATH. Remove LD_LIBRARY_PATH
2025-11-25 16:29:48 +01:00
afc51c9771 testing NFS deploy 2025-11-25 16:14:33 +01:00
1ad2628311 added tests for python
Some checks failed
Build on RHEL8 / build (push) Failing after 1m18s
Build on RHEL9 / build (push) Failing after 3m30s
2025-11-20 12:22:43 +01:00
1cf9dc21ab Merge pull request #1326 from slsdetectorgroup/doc/exptime
All checks were successful
Build on RHEL9 / build (push) Successful in 4m24s
Build on RHEL8 / build (push) Successful in 5m23s
added example to time conversion
2025-11-19 16:16:34 +01:00
f4c1395319 python compiles
Some checks failed
Build on RHEL8 / build (push) Failing after 1m19s
Build on RHEL9 / build (push) Failing after 4m7s
2025-11-19 15:32:02 +01:00
3b92ffb902 Merge branch 'developer' into doc/exptime
All checks were successful
Build on RHEL9 / build (push) Successful in 3m27s
Build on RHEL8 / build (push) Successful in 5m31s
2025-11-19 09:58:21 +01:00
Martin Mueller
0490c0ef23 Merge pull request #1332 from slsdetectorgroup/MH02_debug
All checks were successful
Build on RHEL9 / build (push) Successful in 3m43s
Build on RHEL8 / build (push) Successful in 5m18s
MH02 change clock switching method during periphery reset
2025-11-17 13:40:43 +01:00
f0bd9dd0b3 wip for pybindings
Some checks failed
Build on RHEL8 / build (push) Failing after 1m26s
Build on RHEL9 / build (push) Failing after 2m53s
2025-11-13 13:59:53 +01:00
161cd5508d Dev/define cmd tie bit to reg (#1328)
Some checks failed
Build on RHEL8 / build (push) Failing after 1m8s
Build on RHEL9 / build (push) Failing after 2m22s
* strong type wip

* moved everythign to bit_utils class

* wip, still on testing in ctb reg

* passed tests for define
2025-11-10 16:27:03 +01:00
af2c6eca0c MH02 change clock switching method during periphery reset 2025-11-10 10:35:20 +01:00
Erik Fröjdh
d3dc92b18b Using find_package(Threads REQUIRED) instead of linking pthread directly (#1324)
All checks were successful
Build on RHEL9 / build (push) Successful in 4m30s
Build on RHEL8 / build (push) Successful in 4m42s
* Linking to Threads::Threads instead of pthread directly 
* moved rt linking to slsSupportObject and only enable for linux
2025-10-27 16:30:40 +01:00
froejdh_e
e243af045d added example to time conversion 2025-10-27 16:28:36 +01:00
b4a0c69897 removed std::vector<std::pair<string,int> to std::map<string, int> for defiitions list
Some checks failed
Build on RHEL9 / build (push) Failing after 3m5s
Build on RHEL8 / build (push) Failing after 5m8s
2025-10-13 17:21:53 +02:00
c80dc9bdf3 converting char array+int in runtimeerror compiles but throws at runtime.Fixed.Tested for it. Also check if string or int before using getregisterdefinitonbyvalue to see if it threw to call the other function. because both of it can throw and we should differentiate the issues for both 2025-10-13 16:39:17 +02:00
98c72efd31 refactor
Some checks failed
Build on RHEL9 / build (push) Failing after 3m7s
Build on RHEL8 / build (push) Failing after 5m19s
2025-10-13 12:33:18 +02:00
a4d5e38130 refactor define cmdline 2025-10-13 12:23:22 +02:00
6551d22c7e refactor 2025-10-13 11:54:03 +02:00
049aeaf52a refactor 2025-10-13 11:37:25 +02:00
55aa5db630 updating help 2025-10-13 11:13:00 +02:00
d6f8ff09d0 definelist has no put 2025-10-13 11:04:02 +02:00
98ecbe954d validate autocomplete 2025-10-13 10:59:51 +02:00
4fb66865fd improved autocomplete for getbit,setbit, clearbit 2025-10-13 10:55:46 +02:00
137365642d formatting
Some checks failed
Build on RHEL9 / build (push) Failing after 3m0s
Build on RHEL8 / build (push) Failing after 5m14s
2025-10-10 17:22:15 +02:00
5d4a0055e1 works 2025-10-10 17:21:56 +02:00
3fdef9dac6 done with tests 2025-10-10 16:29:05 +02:00
a382705e50 wip, works for read and write reg with pipes
Some checks failed
Build on RHEL9 / build (push) Failing after 3m20s
Build on RHEL8 / build (push) Failing after 5m1s
2025-10-04 04:39:14 +02:00
c43a3207e8 wip, reg define 2025-10-04 02:33:41 +02:00
d32c034fcf refactor test, wip
Some checks failed
Build on RHEL9 / build (push) Failing after 3m31s
Build on RHEL8 / build (push) Failing after 5m13s
2025-09-30 17:41:20 +02:00
b55bc8d89e tests for define and definelist pass. yet to implement using them for reg, setbit, clearbit and getbit 2025-09-30 17:13:51 +02:00
c2141cf60f Merge branch 'developer' into dev/define_cmd 2025-09-30 16:49:21 +02:00
7e13ccf632 wip 2025-09-30 16:32:01 +02:00
2c2d046ce0 wip
Some checks failed
Build on RHEL9 / build (push) Failing after 47s
Build on RHEL8 / build (push) Failing after 49s
2025-09-30 14:45:49 +02:00
08b282a330 wip 2025-09-30 14:45:11 +02:00
8178a5c16e wip
Some checks failed
Build on RHEL9 / build (push) Failing after 45s
Build on RHEL8 / build (push) Failing after 48s
2025-09-29 17:35:00 +02:00
89be26dfe0 basic ctb config api for register and bit names
Some checks failed
Build on RHEL9 / build (push) Failing after 3m29s
Build on RHEL8 / build (push) Failing after 5m14s
2025-09-19 13:58:34 +02:00
96804ab7cd wip 2025-09-17 17:34:00 +02:00
87 changed files with 3637 additions and 1044 deletions

View File

@@ -0,0 +1,33 @@
name: Build on local RHEL8
on:
push:
branches:
- developer
workflow_dispatch:
permissions:
contents: read
jobs:
build:
runs-on: "detectors-software-RH8"
steps:
- uses: actions/checkout@v4
- name: Build library
run: |
source /home/gitea_runner/.bashrc
conda activate det
mkdir build && cd build
conda activate det
cmake .. -DSLS_USE_PYTHON=ON
make -j 2
cd ../pyctbgui
make
- name: Deploy to NFS update server
if: gitea.ref == 'refs/heads/developer'
run: |
sftp -r gitea_runner@mpc2935:/slsDetectorSoftware/RH8 <<< $'put build/bin'
sftp -r gitea_runner@mpc2935:/slsDetectorSoftware/RH8 <<< $'put pyctbgui'

View File

@@ -21,9 +21,9 @@ jobs:
- name: Build library
run: |
mkdir build && cd build
cmake .. -DSLS_USE_PYTHON=ON -DSLS_USE_TESTS=ON
cmake .. -DSLS_USE_PYTHON=ON -DSLS_USE_TESTS=ON -DSLS_USE_SIMULATOR=ON
make -j 2
- name: C++ unit tests
working-directory: ${{gitea.workspace}}/build
run: ctest
run: ctest -j1 --rerun-failed --output-on-failure

View File

@@ -0,0 +1,30 @@
name: Build on local RHEL9
on:
push:
branches:
- developer
workflow_dispatch:
permissions:
contents: read
jobs:
build:
runs-on: "detectors-software-RH9"
steps:
- uses: actions/checkout@v4
- name: Build library
run: |
mkdir build && cd build
cmake -DSLS_USE_PYTHON=ON -DPython_EXECUTABLE=/usr/bin/python3.13 -DPython_INCLUDE_DIR=/usr/include/python3.13 -DPython_LIBRARY=/usr/lib64/libpython3.13.so ..
make -j 2
cd ../pyctbgui
make
- name: Deploy to NFS update server
if: gitea.ref == 'refs/heads/developer'
run: |
sftp -r gitea_runner@mpc2935:/slsDetectorSoftware/RH9 <<< $'put build/bin'
sftp -r gitea_runner@mpc2935:/slsDetectorSoftware/RH9 <<< $'put pyctbgui'

View File

@@ -19,9 +19,9 @@ jobs:
- name: Build library
run: |
mkdir build && cd build
cmake .. -DSLS_USE_PYTHON=ON -DSLS_USE_TESTS=ON
cmake .. -DSLS_USE_PYTHON=ON -DSLS_USE_TESTS=ON -DSLS_USE_SIMULATOR=ON
make -j 2
- name: C++ unit tests
working-directory: ${{gitea.workspace}}/build
run: ctest
run: ctest -j1 --rerun-failed --output-on-failure

View File

@@ -23,7 +23,7 @@ jobs:
- uses: actions/checkout@v4
- name: Build wheels
run: pipx run cibuildwheel==2.23.0
run: pipx run cibuildwheel==3.2.1
- uses: actions/upload-artifact@v4
with:

View File

@@ -19,7 +19,7 @@ jobs:
with:
python-version: 3.12
cache: 'pip'
- run: pip install pytest numpy
- run: pip install pytest numpy colorama
- uses: awalsh128/cache-apt-pkgs-action@latest
with:
@@ -37,7 +37,7 @@ jobs:
- name: C++ unit tests
working-directory: ${{github.workspace}}/build
run: ctest -C ${{env.BUILD_TYPE}} -j1
run: ctest -C ${{env.BUILD_TYPE}} -j1 --rerun-failed --output-on-failure
- name: Python unit tests
working-directory: ${{github.workspace}}/build/bin

View File

@@ -24,6 +24,15 @@ include(cmake/SlsAddFlag.cmake)
include(cmake/helpers.cmake)
find_package(Threads REQUIRED)
# POSIX threads are required for the moment but we use CMake to find them
# Once migrated to std::thread this can be removed
if(NOT CMAKE_USE_PTHREADS_INIT)
message(FATAL_ERROR "A POSIX threads (pthread) implementation is required, but was not found.")
endif()
option(SLS_USE_SYSTEM_ZMQ "Use system installed libzmq" OFF)
# Using FetchContent to get libzmq
@@ -332,6 +341,9 @@ if (NOT TARGET slsProjectCSettings)
-Wno-format-truncation
)
sls_disable_c_warning("-Wstringop-truncation")
target_link_libraries(slsProjectCSettings INTERFACE
Threads::Threads
)
endif()

View File

@@ -1,7 +1,7 @@
SLS Detector Package Major Release x.x.x released on xx.xx.202x
===============================================================
This document describes the differences between vx.x.x and vx.0.2
This document describes the differences between vx.x.x and v10.0.0
@@ -35,6 +35,8 @@ instead of the one included in our repo.
Experimental support for building the detector client (including python bindings) on macOS
``rx_dbitlist`` keeps the order of the passed bit list
2 On-board Detector Server Compatibility
==========================================

View File

@@ -19,6 +19,7 @@ cmake .. -G Ninja \
-DSLS_USE_PYTHON=OFF \
-DCMAKE_BUILD_TYPE=Release \
-DSLS_USE_HDF5=OFF \
-DSLS_USE_SYSTEM_ZMQ=ON \
NCORES=$(getconf _NPROCESSORS_ONLN)
echo "Building using: ${NCORES} cores"

View File

@@ -29,6 +29,7 @@ requirements:
- libtiff
- zlib
- expat
- zeromq
run:
- libstdcxx-ng

View File

@@ -2,6 +2,8 @@ python:
- 3.11
- 3.12
- 3.13
- 3.14
c_compiler:
- gcc # [linux]
@@ -13,4 +15,4 @@ cxx_compiler:
- gxx # [linux]
c_stdlib_version: # [linux]
- 2.17 # [linux]
- 2.17 # [linux]

View File

@@ -9,11 +9,11 @@ package:
build:
number: 0
script:
- unset CMAKE_GENERATOR && {{ PYTHON }} -m pip install . -vv # [not win]
- unset CMAKE_GENERATOR && {{ PYTHON }} -m pip install . -vv --config-settings=cmake.define.SLS_USE_SYSTEM_ZMQ=ON # [not win]
requirements:
build:
- python {{python}}
- python
- {{ compiler('c') }}
- {{ stdlib("c") }}
- {{ compiler('cxx') }}
@@ -21,7 +21,7 @@ requirements:
host:
- cmake
- ninja
- python {{python}}
- python
- pip
- scikit-build-core
- pybind11 >=2.13.0
@@ -31,7 +31,7 @@ requirements:
- catch2
run:
- python {{python}}
- python
- numpy

View File

@@ -11,7 +11,8 @@ add_executable(gendoc src/gendoc.cpp)
# This is a bit hacky, but better than exposing stuff?
target_include_directories(gendoc PRIVATE ${PROJECT_SOURCE_DIR}/slsDetectorSoftware/src)
target_link_libraries(gendoc PRIVATE
slsDetectorShared
slsDetectorStatic
)
set_target_properties(gendoc PROPERTIES
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin

View File

@@ -50,6 +50,12 @@ datetime.timedelta, DurationWrapper or by setting the time in seconds.
>>> d.getExptime()
[sls::DurationWrapper(total_seconds: 181.23 count: 181230000000)]
# In C++ it is possible to use chrono literals to set time more easily
# d.setExptime(7ms). However, this is not possible due to pythons syntax.
# instead we can create a unit that we use for conversion.
>>> ms = dt.timedelta(milliseconds = 1)
>>> d.exptime = 7.5*ms
------------------------------------

View File

@@ -17,7 +17,7 @@ dependencies = [
[tool.cibuildwheel]
before-all = "uname -a"
build = "cp{311,312,313}-manylinux_x86_64"
build = "cp{311,312,313,314}-manylinux_x86_64"
[tool.scikit-build.build]
verbose = true

View File

@@ -12,6 +12,7 @@ pybind11_add_module(_slsdet
src/duration.cpp
src/DurationWrapper.cpp
src/pedestal.cpp
src/bit.cpp
)
target_link_libraries(_slsdet PUBLIC

View File

@@ -27,6 +27,9 @@ from .defines import *
IpAddr = _slsdet.IpAddr
MacAddr = _slsdet.MacAddr
RegisterAddress = _slsdet.RegisterAddress
BitAddress = _slsdet.BitAddress
RegisterValue = _slsdet.RegisterValue
scanParameters = _slsdet.scanParameters
currentSrcParameters = _slsdet.currentSrcParameters
DurationWrapper = _slsdet.DurationWrapper

View File

@@ -3,6 +3,7 @@
from ._slsdet import CppDetectorApi
from ._slsdet import slsDetectorDefs
from ._slsdet import IpAddr, MacAddr
from ._slsdet import RegisterAddress, RegisterValue, BitAddress
runStatus = slsDetectorDefs.runStatus
timingMode = slsDetectorDefs.timingMode
@@ -24,6 +25,7 @@ import datetime as dt
from functools import wraps
from collections import namedtuple
from collections.abc import Sequence
import socket
import numpy as np
@@ -301,6 +303,46 @@ class Detector(CppDetectorApi):
def rx_arping(self, value):
ut.set_using_dict(self.setRxArping, value)
@property
def rx_roi(self):
"""Gets the list of ROIs configured in the receiver.
Note
-----
Each ROI is represented as a tuple of (x_start, y_start, x_end, y_end). \n
If no ROIs are configured, returns [[-1,-1,-1,-1]].
"""
return self.getRxROI() #vector of Roi structs how represented?
@rx_roi.setter
def rx_roi(self, rois):
"""
Sets the list of ROIs in the receiver.
Can only set multiple ROIs at multi module level without gap pixels. If more than 1 ROI per
UDP port, it will throw. Setting number of udp interfaces will clear the
roi. Cannot be set for CTB or Xilinx CTB.
Note
-----
Each ROI should be represented as a sequence of 4 ints (x_start, y_start, x_end, y_end). \n
For mythen3 or gotthard2 pass a sequence of 2 ints (x_start, x_end) \n
For multiple ROI's pass a sequence of sequence \n
Example: [[0, 100, 50, 100], [260, 270, 50,100]] \n
"""
# TODO: maybe better to accept py::object in setRxROI and handle there?
if not isinstance(rois, Sequence):
raise TypeError(
"setRxROI failed: expected a tuple/list of ints x_min, x_max, y_min, y_max "
"or a sequence of such."
)
if(not isinstance(rois[0], Sequence)):
self.setRxROI([rois])
else:
self.setRxROI(rois)
def rx_clearroi(self):
"""Clears all the ROIs configured in the receiver."""
self.clearRxROI()
@property
@element
@@ -1772,6 +1814,109 @@ class Detector(CppDetectorApi):
[Eiger] Address is +0x100 for only left, +0x200 for only right.
"""
return self._register
def define_reg(self, name, addr):
"""
[Ctb] Define a name for a register to be used later with reg.
Example
--------
d.define_reg('myreg',addr=0x6)
"""
addr = RegisterAddress(addr)
self.setRegisterDefinition(name, addr)
def define_bit(self, name, addr, bit):
"""
[Ctb] Define a name for a bit in a register to be used later with setBit/clearBit/getBit
Example
--------
d.define_bit('mybit',addr=0x6, bit=7)
"""
addr = RegisterAddress(addr)
bit = BitAddress(addr, bit)
self.setBitDefinition(name, bit)
def setBit(self, bit_or_addr, number=None):
"""
Set a bit in a register
[Ctb] Can use a named bit address
Example
--------
d.setBit(0x5, 3)
#Ctb
d.setBit('mybit')
myreg = RegisterAddress(0x5)
mybit = BitAddress(myreg, 5)
d.setBit(mybit)
"""
#Old usage passing two ints
if isinstance(bit_or_addr, int):
return super().setBit(bit_or_addr, number)
#New usage with str or BitAddress
if isinstance(bit_or_addr, str):
bit_or_addr = self.getBitDefinition(bit_or_addr)
return super().setBit(bit_or_addr)
def clearBit(self, bit_or_addr, number=None):
"""
Clear a bit in a register
[Ctb] Can use a named bit address
Example
--------
d.clearBit(0x5, 3)
#Ctb
d.clearBit('mybit')
myreg = RegisterAddress(0x5)
mybit = BitAddress(myreg, 5)
d.clearBit(mybit)
"""
#Old usage passing two ints
if isinstance(bit_or_addr, int):
return super().clearBit(bit_or_addr, number)
#New usage with str or BitAddress
if isinstance(bit_or_addr, str):
bit_or_addr = self.getBitDefinition(bit_or_addr)
return super().clearBit(bit_or_addr)
@element
def getBit(self, bit_or_addr, number=None):
"""
Get a bit from a register
[Ctb] Can use a named bit address
Example
--------
d.getBit(0x5, 3)
#Ctb
d.getBit('mybit')
myreg = RegisterAddress(0x5)
mybit = BitAddress(myreg, 5)
d.getBit(mybit)
"""
#Old usage passing two ints
if isinstance(bit_or_addr, int):
return super().getBit(bit_or_addr, number)
#New usage with str or BitAddress
if isinstance(bit_or_addr, str):
bit_or_addr = self.getBitDefinition(bit_or_addr)
return super().getBit(bit_or_addr)
@property
def slowadc(self):

View File

@@ -1,13 +1,28 @@
# SPDX-License-Identifier: LGPL-3.0-or-other
# Copyright (C) 2021 Contributors to the SLS Detector Package
from ._slsdet import RegisterValue, RegisterAddress
from .utils import element
class Register:
def __init__(self, detector):
self._detector = detector
@element
def __getitem__(self, key):
if isinstance(key, str):
key = self._detector.getRegisterDefinition(key)
return self._detector.readRegister(key)
def __setitem__(self, key, value):
if isinstance(key, str):
key = self._detector.getRegisterDefinition(key)
elif isinstance(key, int):
key = RegisterAddress(key)
if isinstance(value, int):
value = RegisterValue(value)
self._detector.writeRegister(key, value, False)
class Adc_register:

View File

@@ -141,21 +141,38 @@ def make_ip(arg):
def make_mac(arg):
return _make(arg, _slsdet.MacAddr)
def make_register_address(arg):
return _make(arg, _slsdet.RegisterAddress)
def make_bit_address(arg):
return _make(arg, _slsdet.BitAddress)
def make_register_value(arg):
return _make(arg, _slsdet.RegisterValue)
def make_path(arg):
return _make(arg, Path)
def _make(arg, transform):
"""Helper function for make_mac and make_ip special cases for
"""Helper function for make_mac, make_ip and other special cases for
dict, list and tuple. Otherwise just calls transform"""
if isinstance(arg, dict):
return {key: transform(value) for key, value in arg.items()}
return {key: _make(value, transform) for key, value in arg.items()}
elif isinstance(arg, list):
return [transform(a) for a in arg]
return [_make(a, transform) for a in arg]
elif isinstance(arg, tuple):
return tuple(transform(a) for a in arg)
# special case for BitAddress
if transform is _slsdet.BitAddress:
addr, bit = arg
if isinstance(addr, int):
addr = _slsdet.RegisterAddress(addr)
return transform(addr, bit)
else:
# general case: recursively transform each element
return tuple(_make(a, transform) for a in arg)
else:
# single element
return transform(arg)

60
python/src/bit.cpp Normal file
View File

@@ -0,0 +1,60 @@
// SPDX-License-Identifier: LGPL-3.0-or-other
// Copyright (C) 2021 Contributors to the SLS Detector Package
/*
This file contains Python bindings for the RegisterAddr, BitAddress and
RegisterValue classes.
*/
#include "py_headers.h"
#include "sls/bit_utils.h"
namespace py = pybind11;
using sls::BitAddress;
using sls::RegisterAddress;
using sls::RegisterValue;
void init_bit(py::module &m) {
py::class_<RegisterAddress>(m, "RegisterAddress")
.def(py::init())
.def(py::init<const std::string &>())
.def(py::init<uint32_t>())
.def(py::init<const RegisterAddress &>())
.def("__repr__", &RegisterAddress::str)
.def("str", &RegisterAddress::str)
.def("value", &RegisterAddress::value)
.def(py::self == py::self)
.def(py::self != py::self);
py::class_<BitAddress>(m, "BitAddress")
.def(py::init())
.def(py::init<RegisterAddress, uint32_t>())
.def(py::init<std::string, std::string>())
.def("__repr__", &BitAddress::str)
.def("str", &BitAddress::str)
.def("address", &BitAddress::address)
.def("bitPosition", &BitAddress::bitPosition)
.def(py::self == py::self)
.def(py::self != py::self);
py::class_<RegisterValue>(m, "RegisterValue")
.def(py::init<>())
.def(py::init<const std::string &>())
.def(py::init<uint32_t>())
.def(py::init<const RegisterValue &>())
.def("__repr__", &RegisterValue::str)
.def("str", &RegisterValue::str)
.def("value", &RegisterValue::value)
.def(py::self == py::self)
.def(py::self != py::self)
.def("__or__", [](const RegisterValue &lhs, const RegisterValue &rhs) {
return lhs | rhs;
})
.def("__or__", [](const RegisterValue& lhs, uint32_t rhs) {
return lhs | rhs;
})
.def("__ior__", [](RegisterValue &lhs, uint32_t rhs) -> RegisterValue& {
lhs |= rhs;
return lhs;
}, py::return_value_policy::reference_internal);
}

View File

@@ -8,6 +8,7 @@
#include "sls/Detector.h"
#include "sls/TimeHelper.h"
#include "sls/ToString.h"
#include "sls/bit_utils.h"
#include "sls/network_utils.h"
#include "sls/sls_detector_defs.h"
@@ -15,10 +16,13 @@
#include <chrono>
namespace py = pybind11;
void init_det(py::module &m) {
using sls::BitAddress;
using sls::defs;
using sls::Detector;
using sls::ns;
using sls::Positions;
using sls::RegisterAddress;
using sls::RegisterValue;
using sls::Result;
m.def("freeSharedMemory",
@@ -1795,6 +1799,78 @@ void init_det(py::module &m) {
(std::string(Detector::*)(const defs::dacIndex) const) &
Detector::getSlowADCName,
py::arg());
CppDetectorApi.def("getRegisterDefinitionsCount",
(int (Detector::*)() const) &
Detector::getRegisterDefinitionsCount);
CppDetectorApi.def(
"setRegisterDefinition",
(void (Detector::*)(const std::string &, sls::RegisterAddress)) &
Detector::setRegisterDefinition,
py::arg(), py::arg());
CppDetectorApi.def("hasRegisterDefinition",
(bool (Detector::*)(const std::string &) const) &
Detector::hasRegisterDefinition,
py::arg());
CppDetectorApi.def("hasRegisterDefinition",
(bool (Detector::*)(sls::RegisterAddress) const) &
Detector::hasRegisterDefinition,
py::arg());
CppDetectorApi.def(
"getRegisterDefinitionAddress",
(sls::RegisterAddress(Detector::*)(const std::string &) const) &
Detector::getRegisterDefinitionAddress,
py::arg());
CppDetectorApi.def("getRegisterDefinitionName",
(std::string(Detector::*)(sls::RegisterAddress) const) &
Detector::getRegisterDefinitionName,
py::arg());
CppDetectorApi.def("clearRegisterDefinitions",
(void (Detector::*)()) &
Detector::clearRegisterDefinitions);
CppDetectorApi.def(
"setRegisterDefinitions",
(void (Detector::*)(const std::map<std::string, RegisterAddress> &)) &
Detector::setRegisterDefinitions,
py::arg());
CppDetectorApi.def(
"getRegisterDefinitions",
(std::map<std::string, RegisterAddress>(Detector::*)() const) &
Detector::getRegisterDefinitions);
CppDetectorApi.def("getBitDefinitionsCount",
(int (Detector::*)() const) &
Detector::getBitDefinitionsCount);
CppDetectorApi.def(
"setBitDefinition",
(void (Detector::*)(const std::string &, sls::BitAddress)) &
Detector::setBitDefinition,
py::arg(), py::arg());
CppDetectorApi.def("hasBitDefinition",
(bool (Detector::*)(const std::string &) const) &
Detector::hasBitDefinition,
py::arg());
CppDetectorApi.def("hasBitDefinition",
(bool (Detector::*)(sls::BitAddress) const) &
Detector::hasBitDefinition,
py::arg());
CppDetectorApi.def(
"getBitDefinitionAddress",
(sls::BitAddress(Detector::*)(const std::string &) const) &
Detector::getBitDefinitionAddress,
py::arg());
CppDetectorApi.def("getBitDefinitionName",
(std::string(Detector::*)(sls::BitAddress) const) &
Detector::getBitDefinitionName,
py::arg());
CppDetectorApi.def("clearBitDefinitions",
(void (Detector::*)()) & Detector::clearBitDefinitions);
CppDetectorApi.def(
"setBitDefinitions",
(void (Detector::*)(const std::map<std::string, BitAddress> &)) &
Detector::setBitDefinitions,
py::arg());
CppDetectorApi.def("getBitDefinitions", (std::map<std::string, BitAddress>(
Detector::*)() const) &
Detector::getBitDefinitions);
CppDetectorApi.def("configureTransceiver",
(void (Detector::*)(sls::Positions)) &
Detector::configureTransceiver,
@@ -1968,6 +2044,58 @@ void init_det(py::module &m) {
(void (Detector::*)(const bool, sls::Positions)) &
Detector::setUpdateMode,
py::arg(), py::arg() = Positions{});
CppDetectorApi.def("readRegister",
(Result<sls::RegisterValue>(Detector::*)(
sls::RegisterAddress, sls::Positions) const) &
Detector::readRegister,
py::arg(), py::arg() = Positions{});
CppDetectorApi.def(
"writeRegister",
(void (Detector::*)(sls::RegisterAddress, sls::RegisterValue, bool,
sls::Positions)) &
Detector::writeRegister,
py::arg(), py::arg(), py::arg() = false, py::arg() = Positions{});
CppDetectorApi.def(
"setBit",
(void (Detector::*)(sls::BitAddress, bool, sls::Positions)) &
Detector::setBit,
py::arg(), py::arg() = false, py::arg() = Positions{});
CppDetectorApi.def(
"clearBit",
(void (Detector::*)(sls::BitAddress, bool, sls::Positions)) &
Detector::clearBit,
py::arg(), py::arg() = false, py::arg() = Positions{});
CppDetectorApi.def(
"getBit",
(Result<int>(Detector::*)(sls::BitAddress, sls::Positions) const) &
Detector::getBit,
py::arg(), py::arg() = Positions{});
CppDetectorApi.def("readRegister",
(Result<sls::RegisterValue>(Detector::*)(
const std::string &, sls::Positions) const) &
Detector::readRegister,
py::arg(), py::arg() = Positions{});
CppDetectorApi.def(
"writeRegister",
(void (Detector::*)(const std::string &, sls::RegisterValue, bool,
sls::Positions)) &
Detector::writeRegister,
py::arg(), py::arg(), py::arg() = false, py::arg() = Positions{});
CppDetectorApi.def(
"setBit",
(void (Detector::*)(const std::string &, bool, sls::Positions)) &
Detector::setBit,
py::arg(), py::arg() = false, py::arg() = Positions{});
CppDetectorApi.def(
"clearBit",
(void (Detector::*)(const std::string &, bool, sls::Positions)) &
Detector::clearBit,
py::arg(), py::arg() = false, py::arg() = Positions{});
CppDetectorApi.def(
"getBit",
(Result<int>(Detector::*)(const std::string &, sls::Positions) const) &
Detector::getBit,
py::arg(), py::arg() = Positions{});
CppDetectorApi.def(
"readRegister",
(Result<uint32_t>(Detector::*)(uint32_t, sls::Positions) const) &
@@ -1990,7 +2118,7 @@ void init_det(py::module &m) {
py::arg(), py::arg(), py::arg() = false, py::arg() = Positions{});
CppDetectorApi.def(
"getBit",
(Result<int>(Detector::*)(uint32_t, int, sls::Positions)) &
(Result<int>(Detector::*)(uint32_t, int, sls::Positions) const) &
Detector::getBit,
py::arg(), py::arg(), py::arg() = Positions{});
CppDetectorApi.def("executeFirmwareTest",

View File

@@ -7,15 +7,19 @@
#include "sls/network_utils.h"
#include "sls/sls_detector_defs.h"
#include "sls/TimeHelper.h"
#include "sls/bit_utils.h"
#include <array>
#include <chrono>
namespace py = pybind11;
void init_det(py::module &m) {
using sls::BitAddress;
using sls::defs;
using sls::Detector;
using sls::ns;
using sls::Positions;
using sls::RegisterAddress;
using sls::RegisterValue;
using sls::Result;
m.def("freeSharedMemory", (void (*)(const int, const int)) &sls::freeSharedMemory, py::arg() = 0, py::arg() = -1);

View File

@@ -20,6 +20,7 @@ void init_scan(py::module &);
void init_source(py::module &);
void init_duration(py::module &);
void init_pedestal(py::module &);
void init_bit(py::module &);
PYBIND11_MODULE(_slsdet, m) {
m.doc() = R"pbdoc(
@@ -40,6 +41,7 @@ PYBIND11_MODULE(_slsdet, m) {
init_source(m);
init_duration(m);
init_pedestal(m);
init_bit(m);
// init_experimental(m);
py::module io = m.def_submodule("io", "Submodule for io");

View File

@@ -1,11 +1,12 @@
// SPDX-License-Identifier: LGPL-3.0-or-other
// Copyright (C) 2021 Contributors to the SLS Detector Package
#pragma once
#include <pybind11/pybind11.h>
#include <datetime.h>
#include <pybind11/pybind11.h>
#include "sls/Result.h"
#include "DurationWrapper.h"
#include "sls/Result.h"
#include "sls/sls_detector_defs.h"
namespace py = pybind11;
namespace pybind11 {
@@ -14,84 +15,130 @@ template <typename Type, typename Alloc>
struct type_caster<sls::Result<Type, Alloc>>
: list_caster<sls::Result<Type, Alloc>, Type> {};
// Based on the typecaster in pybind11/chrono.h
template <> struct type_caster<std::chrono::nanoseconds> {
public:
PYBIND11_TYPE_CASTER(std::chrono::nanoseconds, const_name("DurationWrapper"));
public:
PYBIND11_TYPE_CASTER(std::chrono::nanoseconds,
const_name("DurationWrapper"));
// signed 25 bits required by the standard.
using days = std::chrono::duration<int_least32_t, std::ratio<86400>>;
// signed 25 bits required by the standard.
using days = std::chrono::duration<int_least32_t, std::ratio<86400>>;
/**
* Conversion part 1 (Python->C++): convert a PyObject into std::chrono::nanoseconds
* try datetime.timedelta, floats and our DurationWrapper wrapper
*/
/**
* Conversion part 1 (Python->C++): convert a PyObject into
* std::chrono::nanoseconds try datetime.timedelta, floats and our
* DurationWrapper wrapper
*/
bool load(handle src, bool) {
using namespace std::chrono;
bool load(handle src, bool) {
using namespace std::chrono;
// Lazy initialise the PyDateTime import
if (!PyDateTimeAPI) {
PyDateTime_IMPORT;
}
// Lazy initialise the PyDateTime import
if (!PyDateTimeAPI) {
PyDateTime_IMPORT;
}
if (!src) {
if (!src) {
return false;
}
// If invoked with datetime.delta object, same as in chrono.h
if (PyDelta_Check(src.ptr())) {
value = duration_cast<nanoseconds>(
days(PyDateTime_DELTA_GET_DAYS(src.ptr())) +
seconds(PyDateTime_DELTA_GET_SECONDS(src.ptr())) +
microseconds(PyDateTime_DELTA_GET_MICROSECONDS(src.ptr()))
);
return true;
}
// If invoked with a float we assume it is seconds and convert, same as
// in chrono.h
if (PyFloat_Check(src.ptr())) {
value = duration_cast<nanoseconds>(
duration<double>(PyFloat_AsDouble(src.ptr())));
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 the number of nanoseconds and create a std::chrono::nanoseconds
// from it
py::object py_cls =
py::module::import("slsdet._slsdet").attr("DurationWrapper");
if (py::isinstance(src, py_cls)) {
sls::DurationWrapper *cls = src.cast<sls::DurationWrapper *>();
value = nanoseconds(cls->count());
return true;
}
return false;
}
/**
* Conversion part 2 (C++ -> Python)
* import the module to get a handle to the wrapped class
* Default construct an object of (wrapped) DurationWrapper
* set the count from chrono::nanoseconds and return
*/
static handle cast(std::chrono::nanoseconds src,
return_value_policy /* policy */, handle /* parent */) {
py::object py_cls =
py::module::import("slsdet._slsdet").attr("DurationWrapper");
py::object *obj = new py::object;
*obj = py_cls();
sls::DurationWrapper *dur = obj->cast<sls::DurationWrapper *>();
dur->set_count(src.count());
return *obj;
}
};
// Type caster for sls::defs::ROI from tuple
template <> struct type_caster<sls::defs::ROI> {
PYBIND11_TYPE_CASTER(sls::defs::ROI, _("Sequence[int, int, int, int] or "
"Sequence[int, int]"));
// convert c++ ROI to python tuple
static handle cast(const sls::defs::ROI &roi, return_value_policy, handle) {
return py::make_tuple(roi.xmin, roi.xmax, roi.ymin, roi.ymax).release();
}
// convert from python to c++ ROI
bool load(handle roi, bool /*allow implicit conversion*/) {
// accept tuple, list, numpy array any sequence
py::sequence seq;
try {
seq = py::reinterpret_borrow<py::sequence>(roi);
} catch (...) {
return false;
}
if (seq.size() != 4 && seq.size() != 2)
return false;
// Check if each element is an int
for (auto item : seq) {
if (!py::isinstance<py::int_>(item)) {
return false;
}
// If invoked with datetime.delta object, same as in chrono.h
if (PyDelta_Check(src.ptr())) {
value = duration_cast<nanoseconds>(
days(PyDateTime_DELTA_GET_DAYS(src.ptr())) +
seconds(PyDateTime_DELTA_GET_SECONDS(src.ptr())) +
microseconds(PyDateTime_DELTA_GET_MICROSECONDS(src.ptr()))
);
return true;
}
// If invoked with a float we assume it is seconds and convert, same as in chrono.h
if (PyFloat_Check(src.ptr())) {
value = duration_cast<nanoseconds>(duration<double>(PyFloat_AsDouble(src.ptr())));
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
// the number of nanoseconds and create a std::chrono::nanoseconds from it
py::object py_cls = py::module::import("slsdet._slsdet").attr("DurationWrapper");
if (py::isinstance(src, py_cls)){
sls::DurationWrapper *cls = src.cast<sls::DurationWrapper *>();
value = nanoseconds(cls->count());
return true;
}
return false;
}
/**
* Conversion part 2 (C++ -> Python)
* import the module to get a handle to the wrapped class
* Default construct an object of (wrapped) DurationWrapper
* set the count from chrono::nanoseconds and return
*/
static handle cast(std::chrono::nanoseconds src, return_value_policy /* policy */, handle /* parent */) {
py::object py_cls = py::module::import("slsdet._slsdet").attr("DurationWrapper");
py::object* obj = new py::object;
*obj = py_cls();
sls::DurationWrapper *dur = obj->cast<sls::DurationWrapper *>();
dur->set_count(src.count());
return *obj;
value.xmin = seq[0].cast<int>();
value.xmax = seq[1].cast<int>();
if (seq.size() == 4) {
value.ymin = seq[2].cast<int>();
value.ymax = seq[3].cast<int>();
}
};
return true;
}
};
} // namespace detail
} // namespace pybind11

85
python/tests/conftest.py Normal file
View File

@@ -0,0 +1,85 @@
import pytest
import sys
import traceback
from pathlib import Path
current_dir = Path(__file__).resolve().parents[2]
scripts_dir = current_dir / "tests" / "scripts"
sys.path.append(str(scripts_dir))
print(sys.path)
from utils_for_test import (
Log,
LogLevel,
cleanup,
startReceiver,
startDetectorVirtualServer,
loadConfig,
loadBasicSettings,
)
def pytest_addoption(parser):
parser.addoption(
"--with-detector-simulators", action="store_true", default=False, help="Run tests that require detector simulators"
)
def pytest_configure(config):
config.addinivalue_line("markers", "withdetectorsimulators: mark test as needing detector simulators to run")
def pytest_collection_modifyitems(config, items):
if config.getoption("--with-detector-simulators"):
return
skip = pytest.mark.skip(reason="need --with-detector-simulators option to run")
for item in items:
if "withdetectorsimulators" in item.keywords:
item.add_marker(skip)
#helper fixture for servers
@pytest.fixture
def servers(request):
try:
return request.param # comes from @pytest.mark.parametrize(..., indirect=True)
except AttributeError:
# fallback default if the test did not parametrize
return ['eiger', 'jungfrau', 'mythen3', 'gotthard2', 'ctb', 'moench', 'xilinx_ctb']
return request.param
@pytest.fixture
def test_with_simulators(servers):
""" Fixture to automatically setup virtual detector servers for testing. """
LOG_PREFIX_FNAME = '/tmp/slsDetectorPackage_virtual_PythonAPI_test'
MAIN_LOG_FNAME = LOG_PREFIX_FNAME + '_log.txt'
with open(MAIN_LOG_FNAME, 'w') as fp:
try:
nmods = 2
for server in servers:
for ninterfaces in range(1,2):
if ninterfaces == 2 and server != 'jungfrau' and server != 'moench':
continue
msg = f'Starting Python API Tests for {server}'
if server == 'jungfrau' or server == 'moench':
msg += f' with {ninterfaces} interfaces'
Log(LogLevel.INFOBLUE, msg, fp)
cleanup(fp)
startDetectorVirtualServer(server, nmods, fp)
startReceiver(nmods, fp)
d = loadConfig(name=server, log_file_fp=fp, num_mods=nmods, num_frames=1, num_interfaces=ninterfaces)
loadBasicSettings(name=server, d=d, fp=fp)
yield # run test
cleanup(fp) # teardown
except Exception as e:
with open(MAIN_LOG_FNAME, 'a') as fp_error:
traceback.print_exc(file=fp_error)
Log(LogLevel.ERROR, f'Tests Failed.', fp)
cleanup(fp)

View File

@@ -0,0 +1,48 @@
import pytest
import sys
from conftest import test_with_simulators
from slsdet import Detector
@pytest.mark.withdetectorsimulators
@pytest.mark.parametrize("servers", [["moench"]], indirect=True)
def test_rx_ROI_moench(test_with_simulators, servers):
""" Test setting and getting rx_ROI property of Detector class for moench. """
d = Detector()
d.rx_roi = (0, 10, 10, 20)
roi = d.rx_roi
assert roi == [(0, 10, 10, 20)]
d.rx_roi = [5,15,15,25]
assert d.rx_roi == [(5,15,15,25)]
d.rx_roi = [[0,10,0,20], [5,20,410,420]]
roi = d.rx_roi
assert roi == [(0,10,0,20), (5,20,410,420)]
d.rx_clearroi()
roi = d.rx_roi
assert roi == [(-1,-1,-1,-1)]
@pytest.mark.withdetectorsimulators
@pytest.mark.parametrize("servers", [["mythen3"]], indirect=True)
def test_rx_ROI_mythen(test_with_simulators, servers):
""" Test setting and getting rx_ROI property of Detector class for mythen. """
d = Detector()
d.rx_roi = (0, 10)
roi = d.rx_roi
assert roi == [(0, 10, -1, -1)]
#d.rx_roi = [[5,15, 0, 1]] # not allowed for mythen3
d.rx_roi = [0,10, -1, -1]
assert d.rx_roi == [(0,10,-1,-1)]

View File

@@ -8,7 +8,7 @@ Testing functions from utils.py
import pytest
from slsdet.utils import *
from slsdet import IpAddr, MacAddr, DurationWrapper
from slsdet import IpAddr, MacAddr, DurationWrapper, RegisterAddress, RegisterValue, BitAddress
import datetime as dt
import pathlib
from pathlib import Path
@@ -199,6 +199,7 @@ def test_make_mac_from_tuple():
MacAddr("84:a9:3e:24:32:aa"))
def test_make_path_from_str():
assert make_path("/") == Path("/")
assert make_path("/home") == Path("/home")

View File

@@ -3,15 +3,21 @@
add_executable(using_logger using_logger.cpp)
target_link_libraries(using_logger
slsSupportShared
pthread
rt
)
set_target_properties(using_logger PROPERTIES
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin
)
add_executable(using_registers using_registers.cpp)
target_link_libraries(using_registers
slsDetectorShared
)
set_target_properties(using_registers PROPERTIES
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin
)
# add_executable(result useResult.cpp)
# target_link_libraries(result
# slsDetectorShared

View File

@@ -3,15 +3,23 @@
#include "sls/logger.h"
#include <iostream>
#include <chrono>
using sls::logINFO;
using sls::logINFORED;
using sls::logINFOBLUE;
using sls::logINFOGREEN;
using sls::logERROR;
using sls::logWARNING;
int main() {
//compare old and new
std::cout << "Compare output between old and new:\n";
LOG(logINFO) << "Some info message";
LOG(logERROR) << "This is an error";
LOG(logWARNING) << "While this is only a warning"; prefix="/afs/psi.ch/project/sls_det_software/dhanya_softwareDevelopment/mySoft/slsDetectorPackage/"
p=${file#"$prefix"}
LOG(logWARNING) << "While this is only a warning";
//Logging level can be configure at runtime
std::cout << "\n\n";
std::cout << "The default macro controlled level is: "

View File

@@ -0,0 +1,49 @@
// SPDX-License-Identifier: LGPL-3.0-or-other
// Copyright (C) 2021 Contributors to the SLS Detector Package
/* This example assumes that you have a ctb configured or using the virtual ctb detector server*/
#include "sls/Detector.h"
#include "sls/bit_utils.h"
#include <iostream>
void somefunc(uint32_t addr){
std::cout << "somefunc called with: " << addr << std::endl;
}
int main(){
// Config file has the following defines
// define addr somereg 0x5
// define bit mybit somereg 7
sls::Detector d;
auto somereg = d.getRegisterDefinition("somereg");
d.writeRegister(somereg, sls::RegisterValue(0));
auto val = d.readRegister(somereg);
std::cout << "somereg has the address: " << somereg << " and value " << val.squash() << std::endl;
auto mybit = d.getBitDefinition("mybit");
std::cout << "mybit refers to register: " << mybit.address() << " bit nr: " << mybit.bitPosition() << std::endl;
d.setBit(mybit);
val = d.readRegister(somereg);
std::cout << "somereg has the address: " << somereg << " and value " << val.squash() << std::endl;
std::cout << "mybit: " << d.getBit(mybit) << std::endl;
//Let's define a bit
sls::BitAddress newbit(sls::RegisterAddress(0x6), 4);
d.setBitDefinition("newbit", newbit);
//This can now be usef from command line "g getbit newbit"
uint32_t addr = somereg; //I'm not sure this should compile
somefunc(somereg); //This should also not compile
}

View File

@@ -76,11 +76,8 @@ foreach(exe ${JUNGFRAU_EXECUTABLES})
target_link_libraries(${exe}
PUBLIC
slsSupportStatic
pthread
tiffio
fmt::fmt
#-L/usr/lib64/
#-lm -lstdc++ -lrt
PRIVATE
slsProjectWarnings

View File

@@ -69,7 +69,6 @@ foreach(exe ${MOENCH_EXECUTABLES})
PUBLIC
slsSupportStatic
${ZeroMQ_LIBRARIES}
pthread
tiffio
PRIVATE

View File

@@ -37,7 +37,9 @@ target_compile_definitions(ctbDetectorServer_virtual
)
target_link_libraries(ctbDetectorServer_virtual
PUBLIC pthread rt m slsProjectCSettings
PUBLIC
m
slsProjectCSettings
)
set_target_properties(ctbDetectorServer_virtual PROPERTIES

View File

@@ -30,7 +30,8 @@ target_compile_definitions(eigerDetectorServer_virtual
)
target_link_libraries(eigerDetectorServer_virtual
PUBLIC pthread rt slsProjectCSettings
PUBLIC
slsProjectCSettings
)
set_target_properties(eigerDetectorServer_virtual PROPERTIES

View File

@@ -31,7 +31,8 @@ target_compile_definitions(gotthard2DetectorServer_virtual
)
target_link_libraries(gotthard2DetectorServer_virtual
PUBLIC pthread rt slsProjectCSettings
PUBLIC
slsProjectCSettings
)
set_target_properties(gotthard2DetectorServer_virtual PROPERTIES

View File

@@ -29,7 +29,8 @@ target_compile_definitions(jungfrauDetectorServer_virtual
)
target_link_libraries(jungfrauDetectorServer_virtual
PUBLIC pthread rt slsProjectCSettings
PUBLIC
slsProjectCSettings
)
set_target_properties(jungfrauDetectorServer_virtual PROPERTIES

View File

@@ -29,7 +29,8 @@ target_compile_definitions(moenchDetectorServer_virtual
)
target_link_libraries(moenchDetectorServer_virtual
PUBLIC pthread rt slsProjectCSettings
PUBLIC
slsProjectCSettings
)
set_target_properties(moenchDetectorServer_virtual PROPERTIES

View File

@@ -33,7 +33,8 @@ target_compile_definitions(mythen3DetectorServer_virtual
)
target_link_libraries(mythen3DetectorServer_virtual
PUBLIC pthread rt slsProjectCSettings
PUBLIC
slsProjectCSettings
)
set_target_properties(mythen3DetectorServer_virtual PROPERTIES

View File

@@ -31,7 +31,9 @@ target_compile_definitions(xilinx_ctbDetectorServer_virtual
)
target_link_libraries(xilinx_ctbDetectorServer_virtual
PUBLIC pthread rt m slsProjectCSettings
PUBLIC
m
slsProjectCSettings
)
set_target_properties(xilinx_ctbDetectorServer_virtual PROPERTIES

View File

@@ -1,5 +1,5 @@
# Prepare MH02 configuration
reg 0xC00C 0x00000041
reg 0xC00C 0x00040041
reg 0xC010 0x01200004
# configure Matterhorn SPI
@@ -14,7 +14,7 @@ reg 0xC120 0x1
reg 0xC120 0x0
# set MSB LSB inversions and polarity for transceiver
reg 0xC120 0x61e0
reg 0xC120 0x1e0
# Enable MH02 PLL clock
pattern enable_clock_pattern.pyat

View File

@@ -1,7 +1,7 @@
# turn off clock
setbit 0xC00C 16
setbit 0xC014 0
clearbit 0xB018 15
setbit 0xB010 15
sleep 1
# reset Matterhorn periphery
@@ -9,8 +9,7 @@ setbit 0xC014 1
sleep 1
# turn on clock
clearbit 0xC00C 16
setbit 0xC014 0
clearbit 0xB010 15
sleep 1
# reset rx transceiver datapath

View File

@@ -28,11 +28,11 @@ target_link_libraries(slsDetectorObject
PUBLIC
slsProjectOptions
slsSupportStatic
pthread
PRIVATE
slsProjectWarnings
)
set(DETECTOR_LIBRARY_TARGETS slsDetectorObject)
@@ -97,8 +97,7 @@ if(SLS_USE_TEXTCLIENT)
add_executable(${val1} src/CmdApp.cpp)
target_link_libraries(${val1}
slsDetectorStatic
pthread
slsDetectorStatic
)
SET_SOURCE_FILES_PROPERTIES( src/Caller.cpp PROPERTIES COMPILE_FLAGS "-Wno-unused-variable -Wno-unused-but-set-variable")

View File

@@ -74,6 +74,11 @@ class Caller {
static void EmptyDataCallBack(detectorData *data, uint64_t frameIndex,
uint32_t subFrameIndex, void *this_pointer);
std::string bitoperations(int action);
RegisterAddress parseAddress(const std::string &saddr) const;
bool parseValidate();
BitAddress parseBitAddress() const;
FunctionMap functions{
{"list", &Caller::list},

View File

@@ -80,7 +80,7 @@ _sd() {
local IS_PATH=0
local SLS_COMMANDS=" acquire activate adcclk adcenable adcenable10g adcindex adcinvert adclist adcname adcphase adcpipeline adcreg adcvpp apulse asamples autocompdisable badchannels blockingtrigger burstmode burstperiod bursts burstsl bustest cdsgain chipversion clearbit clearbusy clientversion clkdiv clkfreq clkphase collectionmode column compdisabletime confadc config configtransceiver counters currentsource dac dacindex daclist dacname dacvalues datastream dbitclk dbitphase dbitpipeline defaultdac defaultpattern delay delayl detectorserverversion detsize diodelay dpulse dr drlist dsamples execcommand exptime exptime1 exptime2 exptime3 extrastoragecells extsampling extsamplingsrc extsig fformat filtercells filterresistor findex firmwaretest firmwareversion fliprows flowcontrol10g fmaster fname foverwrite fpath framecounter frames framesl frametime free fwrite gaincaps gainmode gappixels gatedelay gatedelay1 gatedelay2 gatedelay3 gates getbit hardwareversion highvoltage hostname im_a im_b im_c im_d im_io imagetest initialchecks inj_ch interpolation interruptsubframe kernelversion lastclient led lock master maxadcphaseshift maxclkphaseshift maxdbitphaseshift measuredperiod measuredsubperiod moduleid nextframenumber nmod numinterfaces overflow packageversion parallel parameters partialreset patfname patioctrl patlimits patloop patloop0 patloop1 patloop2 patmask patnloop patnloop0 patnloop1 patnloop2 patsetbit pattern patternstart patwait patwait0 patwait1 patwait2 patwaittime patwaittime0 patwaittime1 patwaittime2 patword pedestalmode period periodl polarity port powerchip powerindex powerlist powername powervalues programfpga pulse pulsechip pulsenmove pumpprobe quad ratecorr readnrows readout readoutspeed readoutspeedlist rebootcontroller reg resetdacs resetfpga romode row runclk runtime rx_arping rx_clearroi rx_dbitlist rx_dbitoffset rx_dbitreorder rx_discardpolicy rx_fifodepth rx_frameindex rx_framescaught rx_framesperfile rx_hostname rx_jsonaddheader rx_jsonpara rx_lastclient rx_lock rx_missingpackets rx_padding rx_printconfig rx_realudpsocksize rx_roi rx_silent rx_start rx_status rx_stop rx_tcpport rx_threads rx_udpsocksize rx_version rx_zmqfreq rx_zmqhwm rx_zmqip rx_zmqport rx_zmqstartfnum rx_zmqstream samples savepattern scan scanerrmsg selinterface serialnumber setbit settings settingslist settingspath signalindex signallist signalname sleep slowadc slowadcindex slowadclist slowadcname slowadcvalues start status stop stopport storagecell_delay storagecell_start subdeadtime subexptime sync syncclk temp_10ge temp_adc temp_control temp_dcdc temp_event temp_fpga temp_fpgaext temp_fpgafl temp_fpgafr temp_slowadc temp_sodl temp_sodr temp_threshold templist tempvalues tengiga threshold thresholdnotb timing timing_info_decoder timinglist timingsource top transceiverenable trigger triggers triggersl trimbits trimen trimval tsamples txdelay txdelay_frame txdelay_left txdelay_right type udp_cleardst udp_dstip udp_dstip2 udp_dstlist udp_dstmac udp_dstmac2 udp_dstport udp_dstport2 udp_firstdst udp_numdst udp_reconfigure udp_srcip udp_srcip2 udp_srcmac udp_srcmac2 udp_validate update updatedetectorserver updatekernel updatemode user v_a v_b v_c v_chip v_d v_io v_limit vchip_comp_adc vchip_comp_fe vchip_cs vchip_opa_1st vchip_opa_fd vchip_ref_comp_fe versions veto vetoalg vetofile vetophoton vetoref vetostream virtual vm_a vm_b vm_c vm_d vm_io zmqhwm zmqip zmqport "
local SLS_COMMANDS=" acquire activate adcclk adcenable adcenable10g adcindex adcinvert adclist adcname adcphase adcpipeline adcreg adcvpp apulse asamples autocompdisable badchannels blockingtrigger burstmode burstperiod bursts burstsl bustest cdsgain chipversion clearbit clearbusy clientversion clkdiv clkfreq clkphase collectionmode column compdisabletime confadc config configtransceiver counters currentsource dac dacindex daclist dacname dacvalues datastream dbitclk dbitphase dbitpipeline defaultdac defaultpattern define_bit define_reg definelist_bit definelist_reg delay delayl detectorserverversion detsize diodelay dpulse dr drlist dsamples execcommand exptime exptime1 exptime2 exptime3 extrastoragecells extsampling extsamplingsrc extsig fformat filtercells filterresistor findex firmwaretest firmwareversion fliprows flowcontrol10g fmaster fname foverwrite fpath framecounter frames framesl frametime free fwrite gaincaps gainmode gappixels gatedelay gatedelay1 gatedelay2 gatedelay3 gates getbit hardwareversion highvoltage hostname im_a im_b im_c im_d im_io imagetest initialchecks inj_ch interpolation interruptsubframe kernelversion lastclient led lock master maxadcphaseshift maxclkphaseshift maxdbitphaseshift measuredperiod measuredsubperiod moduleid nextframenumber nmod numinterfaces overflow packageversion parallel parameters partialreset patfname patioctrl patlimits patloop patloop0 patloop1 patloop2 patmask patnloop patnloop0 patnloop1 patnloop2 patsetbit pattern patternstart patwait patwait0 patwait1 patwait2 patwaittime patwaittime0 patwaittime1 patwaittime2 patword pedestalmode period periodl polarity port powerchip powerindex powerlist powername powervalues programfpga pulse pulsechip pulsenmove pumpprobe quad ratecorr readnrows readout readoutspeed readoutspeedlist rebootcontroller reg resetdacs resetfpga romode row runclk runtime rx_arping rx_clearroi rx_dbitlist rx_dbitoffset rx_dbitreorder rx_discardpolicy rx_fifodepth rx_frameindex rx_framescaught rx_framesperfile rx_hostname rx_jsonaddheader rx_jsonpara rx_lastclient rx_lock rx_missingpackets rx_padding rx_printconfig rx_realudpsocksize rx_roi rx_silent rx_start rx_status rx_stop rx_tcpport rx_threads rx_udpsocksize rx_version rx_zmqfreq rx_zmqhwm rx_zmqip rx_zmqport rx_zmqstartfnum rx_zmqstream samples savepattern scan scanerrmsg selinterface serialnumber setbit settings settingslist settingspath signalindex signallist signalname sleep slowadc slowadcindex slowadclist slowadcname slowadcvalues start status stop stopport storagecell_delay storagecell_start subdeadtime subexptime sync syncclk temp_10ge temp_adc temp_control temp_dcdc temp_event temp_fpga temp_fpgaext temp_fpgafl temp_fpgafr temp_slowadc temp_sodl temp_sodr temp_threshold templist tempvalues tengiga threshold thresholdnotb timing timing_info_decoder timinglist timingsource top transceiverenable trigger triggers triggersl trimbits trimen trimval tsamples txdelay txdelay_frame txdelay_left txdelay_right type udp_cleardst udp_dstip udp_dstip2 udp_dstlist udp_dstmac udp_dstmac2 udp_dstport udp_dstport2 udp_firstdst udp_numdst udp_reconfigure udp_srcip udp_srcip2 udp_srcmac udp_srcmac2 udp_validate update updatedetectorserver updatekernel updatemode user v_a v_b v_c v_chip v_d v_io v_limit vchip_comp_adc vchip_comp_fe vchip_cs vchip_opa_1st vchip_opa_fd vchip_ref_comp_fe versions veto vetoalg vetofile vetophoton vetoref vetostream virtual vm_a vm_b vm_c vm_d vm_io zmqhwm zmqip zmqport "
__acquire() {
FCN_RETURN=""
return 0
@@ -682,6 +682,54 @@ fi
fi
return 0
}
__define_bit() {
FCN_RETURN=""
if [[ ${IS_GET} -eq 1 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN=""
fi
if [[ "${cword}" == "3" ]]; then
FCN_RETURN=""
fi
fi
if [[ ${IS_GET} -eq 0 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN=""
fi
if [[ "${cword}" == "3" ]]; then
FCN_RETURN=""
fi
if [[ "${cword}" == "4" ]]; then
FCN_RETURN=""
fi
fi
return 0
}
__define_reg() {
FCN_RETURN=""
if [[ ${IS_GET} -eq 1 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN=""
fi
fi
if [[ ${IS_GET} -eq 0 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN=""
fi
if [[ "${cword}" == "3" ]]; then
FCN_RETURN=""
fi
fi
return 0
}
__definelist_bit() {
FCN_RETURN=""
return 0
}
__definelist_reg() {
FCN_RETURN=""
return 0
}
__delay() {
FCN_RETURN=""
if [[ ${IS_GET} -eq 1 ]]; then

View File

@@ -4,7 +4,7 @@
_sd() {
local SLS_COMMANDS=" acquire activate adcclk adcenable adcenable10g adcindex adcinvert adclist adcname adcphase adcpipeline adcreg adcvpp apulse asamples autocompdisable badchannels blockingtrigger burstmode burstperiod bursts burstsl bustest cdsgain chipversion clearbit clearbusy clientversion clkdiv clkfreq clkphase collectionmode column compdisabletime confadc config configtransceiver counters currentsource dac dacindex daclist dacname dacvalues datastream dbitclk dbitphase dbitpipeline defaultdac defaultpattern delay delayl detectorserverversion detsize diodelay dpulse dr drlist dsamples execcommand exptime exptime1 exptime2 exptime3 extrastoragecells extsampling extsamplingsrc extsig fformat filtercells filterresistor findex firmwaretest firmwareversion fliprows flowcontrol10g fmaster fname foverwrite fpath framecounter frames framesl frametime free fwrite gaincaps gainmode gappixels gatedelay gatedelay1 gatedelay2 gatedelay3 gates getbit hardwareversion highvoltage hostname im_a im_b im_c im_d im_io imagetest initialchecks inj_ch interpolation interruptsubframe kernelversion lastclient led lock master maxadcphaseshift maxclkphaseshift maxdbitphaseshift measuredperiod measuredsubperiod moduleid nextframenumber nmod numinterfaces overflow packageversion parallel parameters partialreset patfname patioctrl patlimits patloop patloop0 patloop1 patloop2 patmask patnloop patnloop0 patnloop1 patnloop2 patsetbit pattern patternstart patwait patwait0 patwait1 patwait2 patwaittime patwaittime0 patwaittime1 patwaittime2 patword pedestalmode period periodl polarity port powerchip powerindex powerlist powername powervalues programfpga pulse pulsechip pulsenmove pumpprobe quad ratecorr readnrows readout readoutspeed readoutspeedlist rebootcontroller reg resetdacs resetfpga romode row runclk runtime rx_arping rx_clearroi rx_dbitlist rx_dbitoffset rx_dbitreorder rx_discardpolicy rx_fifodepth rx_frameindex rx_framescaught rx_framesperfile rx_hostname rx_jsonaddheader rx_jsonpara rx_lastclient rx_lock rx_missingpackets rx_padding rx_printconfig rx_realudpsocksize rx_roi rx_silent rx_start rx_status rx_stop rx_tcpport rx_threads rx_udpsocksize rx_version rx_zmqfreq rx_zmqhwm rx_zmqip rx_zmqport rx_zmqstartfnum rx_zmqstream samples savepattern scan scanerrmsg selinterface serialnumber setbit settings settingslist settingspath signalindex signallist signalname sleep slowadc slowadcindex slowadclist slowadcname slowadcvalues start status stop stopport storagecell_delay storagecell_start subdeadtime subexptime sync syncclk temp_10ge temp_adc temp_control temp_dcdc temp_event temp_fpga temp_fpgaext temp_fpgafl temp_fpgafr temp_slowadc temp_sodl temp_sodr temp_threshold templist tempvalues tengiga threshold thresholdnotb timing timing_info_decoder timinglist timingsource top transceiverenable trigger triggers triggersl trimbits trimen trimval tsamples txdelay txdelay_frame txdelay_left txdelay_right type udp_cleardst udp_dstip udp_dstip2 udp_dstlist udp_dstmac udp_dstmac2 udp_dstport udp_dstport2 udp_firstdst udp_numdst udp_reconfigure udp_srcip udp_srcip2 udp_srcmac udp_srcmac2 udp_validate update updatedetectorserver updatekernel updatemode user v_a v_b v_c v_chip v_d v_io v_limit vchip_comp_adc vchip_comp_fe vchip_cs vchip_opa_1st vchip_opa_fd vchip_ref_comp_fe versions veto vetoalg vetofile vetophoton vetoref vetostream virtual vm_a vm_b vm_c vm_d vm_io zmqhwm zmqip zmqport "
local SLS_COMMANDS=" acquire activate adcclk adcenable adcenable10g adcindex adcinvert adclist adcname adcphase adcpipeline adcreg adcvpp apulse asamples autocompdisable badchannels blockingtrigger burstmode burstperiod bursts burstsl bustest cdsgain chipversion clearbit clearbusy clientversion clkdiv clkfreq clkphase collectionmode column compdisabletime confadc config configtransceiver counters currentsource dac dacindex daclist dacname dacvalues datastream dbitclk dbitphase dbitpipeline defaultdac defaultpattern define_bit define_reg definelist_bit definelist_reg delay delayl detectorserverversion detsize diodelay dpulse dr drlist dsamples execcommand exptime exptime1 exptime2 exptime3 extrastoragecells extsampling extsamplingsrc extsig fformat filtercells filterresistor findex firmwaretest firmwareversion fliprows flowcontrol10g fmaster fname foverwrite fpath framecounter frames framesl frametime free fwrite gaincaps gainmode gappixels gatedelay gatedelay1 gatedelay2 gatedelay3 gates getbit hardwareversion highvoltage hostname im_a im_b im_c im_d im_io imagetest initialchecks inj_ch interpolation interruptsubframe kernelversion lastclient led lock master maxadcphaseshift maxclkphaseshift maxdbitphaseshift measuredperiod measuredsubperiod moduleid nextframenumber nmod numinterfaces overflow packageversion parallel parameters partialreset patfname patioctrl patlimits patloop patloop0 patloop1 patloop2 patmask patnloop patnloop0 patnloop1 patnloop2 patsetbit pattern patternstart patwait patwait0 patwait1 patwait2 patwaittime patwaittime0 patwaittime1 patwaittime2 patword pedestalmode period periodl polarity port powerchip powerindex powerlist powername powervalues programfpga pulse pulsechip pulsenmove pumpprobe quad ratecorr readnrows readout readoutspeed readoutspeedlist rebootcontroller reg resetdacs resetfpga romode row runclk runtime rx_arping rx_clearroi rx_dbitlist rx_dbitoffset rx_dbitreorder rx_discardpolicy rx_fifodepth rx_frameindex rx_framescaught rx_framesperfile rx_hostname rx_jsonaddheader rx_jsonpara rx_lastclient rx_lock rx_missingpackets rx_padding rx_printconfig rx_realudpsocksize rx_roi rx_silent rx_start rx_status rx_stop rx_tcpport rx_threads rx_udpsocksize rx_version rx_zmqfreq rx_zmqhwm rx_zmqip rx_zmqport rx_zmqstartfnum rx_zmqstream samples savepattern scan scanerrmsg selinterface serialnumber setbit settings settingslist settingspath signalindex signallist signalname sleep slowadc slowadcindex slowadclist slowadcname slowadcvalues start status stop stopport storagecell_delay storagecell_start subdeadtime subexptime sync syncclk temp_10ge temp_adc temp_control temp_dcdc temp_event temp_fpga temp_fpgaext temp_fpgafl temp_fpgafr temp_slowadc temp_sodl temp_sodr temp_threshold templist tempvalues tengiga threshold thresholdnotb timing timing_info_decoder timinglist timingsource top transceiverenable trigger triggers triggersl trimbits trimen trimval tsamples txdelay txdelay_frame txdelay_left txdelay_right type udp_cleardst udp_dstip udp_dstip2 udp_dstlist udp_dstmac udp_dstmac2 udp_dstport udp_dstport2 udp_firstdst udp_numdst udp_reconfigure udp_srcip udp_srcip2 udp_srcmac udp_srcmac2 udp_validate update updatedetectorserver updatekernel updatemode user v_a v_b v_c v_chip v_d v_io v_limit vchip_comp_adc vchip_comp_fe vchip_cs vchip_opa_1st vchip_opa_fd vchip_ref_comp_fe versions veto vetoalg vetofile vetophoton vetoref vetostream virtual vm_a vm_b vm_c vm_d vm_io zmqhwm zmqip zmqport "
__acquire() {
FCN_RETURN=""
return 0
@@ -606,6 +606,54 @@ fi
fi
return 0
}
__define_bit() {
FCN_RETURN=""
if [[ ${IS_GET} -eq 1 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN=""
fi
if [[ "${cword}" == "3" ]]; then
FCN_RETURN=""
fi
fi
if [[ ${IS_GET} -eq 0 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN=""
fi
if [[ "${cword}" == "3" ]]; then
FCN_RETURN=""
fi
if [[ "${cword}" == "4" ]]; then
FCN_RETURN=""
fi
fi
return 0
}
__define_reg() {
FCN_RETURN=""
if [[ ${IS_GET} -eq 1 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN=""
fi
fi
if [[ ${IS_GET} -eq 0 ]]; then
if [[ "${cword}" == "2" ]]; then
FCN_RETURN=""
fi
if [[ "${cword}" == "3" ]]; then
FCN_RETURN=""
fi
fi
return 0
}
__definelist_bit() {
FCN_RETURN=""
return 0
}
__definelist_reg() {
FCN_RETURN=""
return 0
}
__delay() {
FCN_RETURN=""
if [[ ${IS_GET} -eq 1 ]]; then

View File

@@ -2761,6 +2761,90 @@ sleep:
- argc: 2
arg_types: [ int, special::time_unit ]
define_reg:
is_description: true
actions:
GET:
argc: 1
arg_types: [ std::string ]
PUT:
argc: 2
arg_types: [ std::string, int ]
define_bit:
is_description: true
actions:
GET:
args:
- argc: 1
arg_types: [ std::string ]
- argc: 2
arg_types: [ std::string, int ]
PUT:
argc: 3
arg_types: [ std::string, std::string, int ]
definelist_reg:
is_description: true
actions:
GET:
argc: 0
definelist_bit:
is_description: true
actions:
GET:
argc: 0
reg:
is_description: true
actions:
GET:
argc: 1
arg_types: [ std::string]
PUT:
args:
- argc: 2
arg_types: [ uint32_t, uint32_t ]
- argc: 3
arg_types: [ uint32_t, uint32_t, special::validate ]
getbit:
is_description: true
actions:
GET:
args:
- argc: 1
arg_types: [ std::string ]
- argc: 2
arg_types: [ std::string, std::string ]
setbit:
is_description: true
actions:
PUT:
args:
- argc: 1
arg_types: [ std::string ]
- argc: 2
arg_types: [ std::string, std::string ]
- argc: 3
arg_types: [ std::string, std::string, special::validate ]
clearbit:
is_description: true
actions:
PUT:
args:
- argc: 1
arg_types: [ std::string ]
- argc: 2
arg_types: [ std::string, std::string ]
- argc: 3
arg_types: [ std::string, std::string, special::validate ]
################# special commands ##########################
@@ -4172,36 +4256,6 @@ update:
input_types: [ std::string, std::string ]
output: [ '"successful"' ]
reg:
help: "[address] [32 bit value][(optional)--validate]\n\t[Mythen3][Gotthard2] Reads/writes to a 32 bit register in hex. Advanced Function!\n\tGoes to stop server. Hence, can be called while calling blocking acquire().\n\t\t Use --validate to force validation when writing to it.\n\t[Eiger] +0x100 for only left, +0x200 for only right."
actions:
GET:
argc: 1
require_det_id: true
function: readRegister
input: [ 'args[0]' ]
input_types: [ uint32_t ]
cast_input: [ true ]
output: [ OutStringHex(t) ]
PUT:
require_det_id: true
function: writeRegister
output: [ '"["', 'args[0]', '", "', 'args[1]', '"]"' ]
args:
- argc: 2
input: [ 'args[0]', 'args[1]', '"0"' ]
input_types: [ uint32_t, uint32_t, bool ]
arg_types: [ uint32_t, uint32_t ]
cast_input: [ true, true, true ]
- argc: 3
arg_types: [ uint32_t, uint32_t, special::validate ]
exceptions:
- condition: 'args[2] != "--validate"'
message: '"Could not scan third argument. Did you mean --validate?"'
input: [ 'args[0]', 'args[1]', '"1"' ]
input_types: [ uint32_t, uint32_t, bool ]
cast_input: [ true, true, true ]
adcreg:
help: "[address] [value]\n\t[Jungfrau][Moench][Ctb] Writes to an adc register in hex. Advanced user Function!"
actions:
@@ -4214,62 +4268,7 @@ adcreg:
cast_input: [ true, true ]
output: [ ToString(args) ]
getbit:
help: "[reg address in hex] [bit index]\n\tGets bit in address."
actions:
GET:
argc: 2
exceptions:
- condition: 'StringTo<int>(args[1]) < 0 || StringTo<int>(args[1]) > 31'
message: '"Bit number out of range: " + args[1]'
require_det_id: true
function: getBit
input: [ 'args[0]', 'args[1]' ]
input_types: [ uint32_t, int ]
cast_input: [ true, true ]
output: [ OutString(t) ]
Setbit:
template: true
actions:
PUT:
require_det_id: true
function: setBit
output: [ '"["', 'args[0]', '", "', 'args[1]', '"]"' ]
args:
- argc: 2
exceptions:
- condition: 'StringTo<int>(args[1]) < 0 || StringTo<int>(args[1]) > 31'
message: '"Bit number out of range: " + args[1]'
input: [ 'args[0]', 'args[1]', '"0"' ]
input_types: [ uint32_t, int, bool ]
arg_types: [ uint32_t, int ]
cast_input: [ true, true, true ]
- argc: 3
arg_types: [ uint32_t, int, special::validate ]
exceptions:
- condition: 'StringTo<int>(args[1]) < 0 || StringTo<int>(args[1]) > 31'
message: '"Bit number out of range: " + args[1]'
- condition: 'args[2] != "--validate"'
message: '"Could not scan third argument. Did you mean --validate?"'
input: [ 'args[0]', 'args[1]', '"1"' ]
input_types: [ uint32_t, int, bool ]
cast_input: [ true, true, true ]
setbit:
inherit_actions: Setbit
help: "[reg address in hex] [bit index]\n\tSets bit in address.\n\tUse --validate to force validation."
actions:
PUT:
function: setBit
clearbit:
inherit_actions: Setbit
help: "[reg address in hex] [bit index]\n\tClears bit in address.\n\tUse --validate to force validation."
actions:
PUT:
function: clearBit
initialchecks:
help: "[0, 1]\n\t[Mythen3][Gotthard2] Enable or disable intial compatibility and other checks at detector start up. It is enabled by default. Must come before 'hostname' command to take effect. Can be used to reprogram fpga when current firmware is incompatible.\n\tAdvanced User function!"

View File

@@ -1096,74 +1096,49 @@ clearbit:
PUT:
args:
- arg_types:
- uint32_t
- int
argc: 2
cast_input:
- true
- true
- true
- std::string
argc: 1
cast_input: []
check_det_id: false
convert_det_id: true
exceptions:
- condition: StringTo<int>(args[1]) < 0 || StringTo<int>(args[1]) > 31
message: '"Bit number out of range: " + args[1]'
function: clearBit
input:
- args[0]
- args[1]
- '"0"'
input_types:
- uint32_t
- int
- bool
output:
- '"["'
- args[0]
- '", "'
- args[1]
- '"]"'
require_det_id: true
function: ''
input: []
input_types: []
output: []
require_det_id: false
store_result_in_t: false
- arg_types:
- uint32_t
- int
- special::validate
argc: 3
cast_input:
- true
- true
- true
- std::string
- std::string
argc: 2
cast_input: []
check_det_id: false
convert_det_id: true
exceptions:
- condition: StringTo<int>(args[1]) < 0 || StringTo<int>(args[1]) > 31
message: '"Bit number out of range: " + args[1]'
- condition: args[2] != "--validate"
message: '"Could not scan third argument. Did you mean --validate?"'
function: clearBit
input:
- args[0]
- args[1]
- '"1"'
input_types:
- uint32_t
- int
- bool
output:
- '"["'
- args[0]
- '", "'
- args[1]
- '"]"'
require_det_id: true
function: ''
input: []
input_types: []
output: []
require_det_id: false
store_result_in_t: false
- arg_types:
- std::string
- std::string
- special::validate
argc: 3
cast_input: []
check_det_id: false
convert_det_id: true
function: ''
input: []
input_types: []
output: []
require_det_id: false
store_result_in_t: false
command_name: clearbit
function_alias: clearbit
help: "[reg address in hex] [bit index]\n\tClears bit in address.\n\tUse --validate\
\ to force validation."
help: ''
infer_action: true
template: true
is_description: true
clearbusy:
actions:
PUT:
@@ -2500,6 +2475,132 @@ defaultpattern:
\ to go back to initial settings."
infer_action: true
template: true
define_bit:
actions:
GET:
args:
- arg_types:
- std::string
argc: 1
cast_input: []
check_det_id: false
convert_det_id: true
function: ''
input: []
input_types: []
output: []
require_det_id: false
store_result_in_t: true
- arg_types:
- std::string
- int
argc: 2
cast_input: []
check_det_id: false
convert_det_id: true
function: ''
input: []
input_types: []
output: []
require_det_id: false
store_result_in_t: true
PUT:
args:
- arg_types:
- std::string
- std::string
- int
argc: 3
cast_input: []
check_det_id: false
convert_det_id: true
function: ''
input: []
input_types: []
output: []
require_det_id: false
store_result_in_t: false
command_name: define_bit
function_alias: define_bit
help: ''
infer_action: true
is_description: true
define_reg:
actions:
GET:
args:
- arg_types:
- std::string
argc: 1
cast_input: []
check_det_id: false
convert_det_id: true
function: ''
input: []
input_types: []
output: []
require_det_id: false
store_result_in_t: true
PUT:
args:
- arg_types:
- std::string
- int
argc: 2
cast_input: []
check_det_id: false
convert_det_id: true
function: ''
input: []
input_types: []
output: []
require_det_id: false
store_result_in_t: false
command_name: define_reg
function_alias: define_reg
help: ''
infer_action: true
is_description: true
definelist_bit:
actions:
GET:
args:
- arg_types: []
argc: 0
cast_input: []
check_det_id: false
convert_det_id: true
function: ''
input: []
input_types: []
output: []
require_det_id: false
store_result_in_t: true
command_name: definelist_bit
function_alias: definelist_bit
help: ''
infer_action: true
is_description: true
definelist_reg:
actions:
GET:
args:
- arg_types: []
argc: 0
cast_input: []
check_det_id: false
convert_det_id: true
function: ''
input: []
input_types: []
output: []
require_det_id: false
store_result_in_t: true
command_name: definelist_reg
function_alias: definelist_reg
help: ''
infer_action: true
is_description: true
delay:
actions:
GET:
@@ -4706,32 +4807,35 @@ getbit:
GET:
args:
- arg_types:
- uint32_t
- int
argc: 2
cast_input:
- true
- true
- std::string
argc: 1
cast_input: []
check_det_id: false
convert_det_id: true
exceptions:
- condition: StringTo<int>(args[1]) < 0 || StringTo<int>(args[1]) > 31
message: '"Bit number out of range: " + args[1]'
function: getBit
input:
- args[0]
- args[1]
input_types:
- uint32_t
- int
output:
- OutString(t)
require_det_id: true
function: ''
input: []
input_types: []
output: []
require_det_id: false
store_result_in_t: true
- arg_types:
- std::string
- std::string
argc: 2
cast_input: []
check_det_id: false
convert_det_id: true
function: ''
input: []
input_types: []
output: []
require_det_id: false
store_result_in_t: true
command_name: getbit
function_alias: getbit
help: "[reg address in hex] [bit index]\n\tGets bit in address."
help: ''
infer_action: true
is_description: true
hardwareversion:
actions:
GET:
@@ -7870,20 +7974,16 @@ reg:
GET:
args:
- arg_types:
- uint32_t
- std::string
argc: 1
cast_input:
- true
cast_input: []
check_det_id: false
convert_det_id: true
function: readRegister
input:
- args[0]
input_types:
- uint32_t
output:
- OutStringHex(t)
require_det_id: true
function: ''
input: []
input_types: []
output: []
require_det_id: false
store_result_in_t: true
PUT:
args:
@@ -7891,68 +7991,34 @@ reg:
- uint32_t
- uint32_t
argc: 2
cast_input:
- true
- true
- true
cast_input: []
check_det_id: false
convert_det_id: true
function: writeRegister
input:
- args[0]
- args[1]
- '"0"'
input_types:
- uint32_t
- uint32_t
- bool
output:
- '"["'
- args[0]
- '", "'
- args[1]
- '"]"'
require_det_id: true
function: ''
input: []
input_types: []
output: []
require_det_id: false
store_result_in_t: false
- arg_types:
- uint32_t
- uint32_t
- special::validate
argc: 3
cast_input:
- true
- true
- true
cast_input: []
check_det_id: false
convert_det_id: true
exceptions:
- condition: args[2] != "--validate"
message: '"Could not scan third argument. Did you mean --validate?"'
function: writeRegister
input:
- args[0]
- args[1]
- '"1"'
input_types:
- uint32_t
- uint32_t
- bool
output:
- '"["'
- args[0]
- '", "'
- args[1]
- '"]"'
require_det_id: true
function: ''
input: []
input_types: []
output: []
require_det_id: false
store_result_in_t: false
command_name: reg
function_alias: reg
help: "[address] [32 bit value][(optional)--validate]\n\t[Mythen3][Gotthard2] Reads/writes\
\ to a 32 bit register in hex. Advanced Function!\n\tGoes to stop server. Hence,\
\ can be called while calling blocking acquire().\n\t\t Use --validate to force\
\ validation when writing to it.\n\t[Eiger] +0x100 for only left, +0x200 for only\
\ right."
help: ''
infer_action: true
is_description: true
resetdacs:
actions:
PUT:
@@ -9577,74 +9643,49 @@ setbit:
PUT:
args:
- arg_types:
- uint32_t
- int
argc: 2
cast_input:
- true
- true
- true
- std::string
argc: 1
cast_input: []
check_det_id: false
convert_det_id: true
exceptions:
- condition: StringTo<int>(args[1]) < 0 || StringTo<int>(args[1]) > 31
message: '"Bit number out of range: " + args[1]'
function: setBit
input:
- args[0]
- args[1]
- '"0"'
input_types:
- uint32_t
- int
- bool
output:
- '"["'
- args[0]
- '", "'
- args[1]
- '"]"'
require_det_id: true
function: ''
input: []
input_types: []
output: []
require_det_id: false
store_result_in_t: false
- arg_types:
- uint32_t
- int
- special::validate
argc: 3
cast_input:
- true
- true
- true
- std::string
- std::string
argc: 2
cast_input: []
check_det_id: false
convert_det_id: true
exceptions:
- condition: StringTo<int>(args[1]) < 0 || StringTo<int>(args[1]) > 31
message: '"Bit number out of range: " + args[1]'
- condition: args[2] != "--validate"
message: '"Could not scan third argument. Did you mean --validate?"'
function: setBit
input:
- args[0]
- args[1]
- '"1"'
input_types:
- uint32_t
- int
- bool
output:
- '"["'
- args[0]
- '", "'
- args[1]
- '"]"'
require_det_id: true
function: ''
input: []
input_types: []
output: []
require_det_id: false
store_result_in_t: false
- arg_types:
- std::string
- std::string
- special::validate
argc: 3
cast_input: []
check_det_id: false
convert_det_id: true
function: ''
input: []
input_types: []
output: []
require_det_id: false
store_result_in_t: false
command_name: setbit
function_alias: setbit
help: "[reg address in hex] [bit index]\n\tSets bit in address.\n\tUse --validate\
\ to force validation."
help: ''
infer_action: true
template: true
is_description: true
settings:
actions:
GET:

View File

@@ -3,6 +3,7 @@
#pragma once
#include "sls/Pattern.h"
#include "sls/Result.h"
#include "sls/bit_utils.h"
#include "sls/network_utils.h"
#include "sls/sls_detector_defs.h"
#include <chrono>
@@ -1837,6 +1838,61 @@ class Detector {
/** [CTB][Xilinx CTB] */
std::string getSlowADCName(const defs::dacIndex i) const;
/** [CTB][Xilinx CTB] */
int getRegisterDefinitionsCount() const;
/** [CTB][Xilinx CTB] */
void setRegisterDefinition(const std::string &name, RegisterAddress addr);
/** [CTB][Xilinx CTB] */
bool hasRegisterDefinition(const std::string &name) const;
/** [CTB][Xilinx CTB] */
bool hasRegisterDefinition(RegisterAddress addr) const;
/** [CTB][Xilinx CTB] */
RegisterAddress getRegisterDefinitionAddress(const std::string &name) const;
/** [CTB][Xilinx CTB] */
std::string getRegisterDefinitionName(RegisterAddress addr) const;
/** [CTB][Xilinx CTB] */
void clearRegisterDefinitions();
/** [CTB][Xilinx CTB] */
void
setRegisterDefinitions(const std::map<std::string, RegisterAddress> &list);
/** [CTB][Xilinx CTB] */
std::map<std::string, RegisterAddress> getRegisterDefinitions() const;
/** [CTB][Xilinx CTB] */
int getBitDefinitionsCount() const;
/** [CTB][Xilinx CTB] */
void setBitDefinition(const std::string &name, BitAddress addr);
/** [CTB][Xilinx CTB] */
bool hasBitDefinition(const std::string &name) const;
/** [CTB][Xilinx CTB] */
bool hasBitDefinition(BitAddress addr) const;
/** [CTB][Xilinx CTB] returns bit position and address */
BitAddress getBitDefinitionAddress(const std::string &name) const;
/** [CTB][Xilinx CTB] */
std::string getBitDefinitionName(BitAddress addr) const;
/** [CTB][Xilinx CTB] */
void clearBitDefinitions();
/** [CTB][Xilinx CTB] */
void setBitDefinitions(const std::map<std::string, BitAddress> &list);
/** [CTB][Xilinx CTB] */
std::map<std::string, BitAddress> getBitDefinitions() const;
///@}
/** @name Xilinx CTB Specific */
@@ -2045,26 +2101,71 @@ class Detector {
/** Advanced user Function! \n
* Goes to stop server. Hence, can be called while calling blocking
* acquire(). \n [Eiger] Address is +0x100 for only left, +0x200 for only
* right. */
Result<uint32_t> readRegister(uint32_t addr, Positions pos = {}) const;
* right.*/
Result<RegisterValue> readRegister(RegisterAddress addr,
Positions pos = {}) const;
/** Advanced user Function! \n
* Goes to stop server. Hence, can be called while calling blocking
* acquire(). \n [Eiger] Address is +0x100 for only left, +0x200 for only
* right. */
void writeRegister(uint32_t addr, uint32_t val, bool validate = false,
Positions pos = {});
* right.*/
void writeRegister(RegisterAddress addr, RegisterValue val,
bool validate = false, Positions pos = {});
/** Advanced user Function! */
void setBit(uint32_t addr, int bitnr, bool validate = false,
/** Advanced user Function! */
void setBit(BitAddress addr, bool validate = false, Positions pos = {});
/** Advanced user Function!*/
void clearBit(BitAddress addr, bool validate = false, Positions pos = {});
/** Advanced user Function! */
Result<int> getBit(BitAddress addr, Positions pos = {}) const;
/** [CTB][Xilinx CTB] Advanced user Function! */
Result<RegisterValue> readRegister(const std::string &reg_name,
Positions pos = {}) const;
/** [CTB][Xilinx CTB] Advanced user Function! */
void writeRegister(const std::string &reg_name, RegisterValue val,
bool validate = false, Positions pos = {});
/** [CTB][Xilinx CTB] Advanced user Function! */
void setBit(const std::string &bit_name, bool validate = false,
Positions pos = {});
/** Advanced user Function! */
void clearBit(uint32_t addr, int bitnr, bool validate = false,
/** [CTB][Xilinx CTB] Advanced user Function! */
void clearBit(const std::string &bit_name, bool validate = false,
Positions pos = {});
/** Advanced user Function! */
Result<int> getBit(uint32_t addr, int bitnr, Positions pos = {});
/** [CTB][Xilinx CTB] Advanced user Function! */
Result<int> getBit(const std::string &bit_name, Positions pos = {}) const;
/** Deprecated Advanced user Function! */
[[deprecated("Use the overload taking RegisterAddress instead of "
"uint32_t")]] Result<uint32_t>
readRegister(uint32_t addr, Positions pos = {}) const;
/** Deprecated Advanced user Function! */
[[deprecated("Use the overload taking RegisterAddress and RegisterValue "
"instead of uint32_t")]] void
writeRegister(uint32_t addr, uint32_t val, bool validate = false,
Positions pos = {});
/** Deprecated Advanced user Function! */
[[deprecated("Use the overload taking BitAddress instead of uint32_t and "
"int")]] void
setBit(uint32_t addr, int bitnr, bool validate = false, Positions pos = {});
/** Deprecated Advanced user Function! */
[[deprecated("Use the overload taking BitAddress instead of uint32_t and "
"int")]] void
clearBit(uint32_t addr, int bitnr, bool validate = false,
Positions pos = {});
/** Deprecated Advanced user Function! */
[[deprecated("Use the overload taking BitAddress instead of uint32_t and "
"int")]] Result<int>
getBit(uint32_t addr, int bitnr, Positions pos = {}) const;
/** [Jungfrau][Moench][Mythen3][Gotthard2][CTB] Advanced user
* Function! */

View File

@@ -1453,100 +1453,6 @@ std::string Caller::chipversion(int action) {
return os.str();
}
std::string Caller::clearbit(int action) {
std::ostringstream os;
// print help
if (action == slsDetectorDefs::HELP_ACTION) {
os << R"V0G0N([reg address in hex] [bit index]
Clears bit in address.
Use --validate to force validation. )V0G0N"
<< std::endl;
return os.str();
}
// check if action and arguments are valid
if (action == slsDetectorDefs::PUT_ACTION) {
if (1 && args.size() != 2 && args.size() != 3) {
throw RuntimeError("Wrong number of arguments for action PUT");
}
if (args.size() == 2) {
try {
StringTo<uint32_t>(args[0]);
} catch (...) {
throw RuntimeError("Could not convert argument 0 to uint32_t");
}
try {
StringTo<int>(args[1]);
} catch (...) {
throw RuntimeError("Could not convert argument 1 to int");
}
try {
StringTo<bool>("0");
} catch (...) {
throw RuntimeError("Could not convert argument 2 to bool");
}
}
if (args.size() == 3) {
try {
StringTo<uint32_t>(args[0]);
} catch (...) {
throw RuntimeError("Could not convert argument 0 to uint32_t");
}
try {
StringTo<int>(args[1]);
} catch (...) {
throw RuntimeError("Could not convert argument 1 to int");
}
try {
StringTo<bool>("1");
} catch (...) {
throw RuntimeError("Could not convert argument 2 to bool");
}
}
}
else {
throw RuntimeError(
"INTERNAL ERROR: Invalid action: supported actions are ['PUT']");
}
// generate code for each action
if (action == slsDetectorDefs::PUT_ACTION) {
if (args.size() == 2) {
if (StringTo<int>(args[1]) < 0 || StringTo<int>(args[1]) > 31) {
throw RuntimeError("Bit number out of range: " + args[1]);
}
auto arg0 = StringTo<uint32_t>(args[0]);
auto arg1 = StringTo<int>(args[1]);
auto arg2 = StringTo<bool>("0");
det->clearBit(arg0, arg1, arg2, std::vector<int>{det_id});
os << "[" << args[0] << ", " << args[1] << "]" << '\n';
}
if (args.size() == 3) {
if (StringTo<int>(args[1]) < 0 || StringTo<int>(args[1]) > 31) {
throw RuntimeError("Bit number out of range: " + args[1]);
}
if (args[2] != "--validate") {
throw RuntimeError(
"Could not scan third argument. Did you mean --validate?");
}
auto arg0 = StringTo<uint32_t>(args[0]);
auto arg1 = StringTo<int>(args[1]);
auto arg2 = StringTo<bool>("1");
det->clearBit(arg0, arg1, arg2, std::vector<int>{det_id});
os << "[" << args[0] << ", " << args[1] << "]" << '\n';
}
}
return os.str();
}
std::string Caller::clearbusy(int action) {
std::ostringstream os;
@@ -5955,60 +5861,6 @@ std::string Caller::gates(int action) {
return os.str();
}
std::string Caller::getbit(int action) {
std::ostringstream os;
// print help
if (action == slsDetectorDefs::HELP_ACTION) {
os << R"V0G0N([reg address in hex] [bit index]
Gets bit in address. )V0G0N"
<< std::endl;
return os.str();
}
// check if action and arguments are valid
if (action == slsDetectorDefs::GET_ACTION) {
if (1 && args.size() != 2) {
throw RuntimeError("Wrong number of arguments for action GET");
}
if (args.size() == 2) {
try {
StringTo<uint32_t>(args[0]);
} catch (...) {
throw RuntimeError("Could not convert argument 0 to uint32_t");
}
try {
StringTo<int>(args[1]);
} catch (...) {
throw RuntimeError("Could not convert argument 1 to int");
}
}
}
else {
throw RuntimeError(
"INTERNAL ERROR: Invalid action: supported actions are ['GET']");
}
// generate code for each action
if (action == slsDetectorDefs::GET_ACTION) {
if (args.size() == 2) {
if (StringTo<int>(args[1]) < 0 || StringTo<int>(args[1]) > 31) {
throw RuntimeError("Bit number out of range: " + args[1]);
}
auto arg0 = StringTo<uint32_t>(args[0]);
auto arg1 = StringTo<int>(args[1]);
auto t = det->getBit(arg0, arg1, std::vector<int>{det_id});
os << OutString(t) << '\n';
}
}
return os.str();
}
std::string Caller::hardwareversion(int action) {
std::ostringstream os;
@@ -8454,7 +8306,7 @@ std::string Caller::patternstart(int action) {
// print help
if (action == slsDetectorDefs::HELP_ACTION) {
os << R"V0G0N(
[Mythen3][Xilinx Ctb] Starts Pattern )V0G0N"
[Mythen3][Ctb][Xilinx Ctb] Starts Pattern )V0G0N"
<< std::endl;
return os.str();
}
@@ -10096,119 +9948,6 @@ std::string Caller::rebootcontroller(int action) {
return os.str();
}
std::string Caller::reg(int action) {
std::ostringstream os;
// print help
if (action == slsDetectorDefs::HELP_ACTION) {
os << R"V0G0N([address] [32 bit value][(optional)--validate]
[Mythen3][Gotthard2] Reads/writes to a 32 bit register in hex. Advanced Function!
Goes to stop server. Hence, can be called while calling blocking acquire().
Use --validate to force validation when writing to it.
[Eiger] +0x100 for only left, +0x200 for only right. )V0G0N"
<< std::endl;
return os.str();
}
// check if action and arguments are valid
if (action == slsDetectorDefs::GET_ACTION) {
if (1 && args.size() != 1) {
throw RuntimeError("Wrong number of arguments for action GET");
}
if (args.size() == 1) {
try {
StringTo<uint32_t>(args[0]);
} catch (...) {
throw RuntimeError("Could not convert argument 0 to uint32_t");
}
}
}
else if (action == slsDetectorDefs::PUT_ACTION) {
if (1 && args.size() != 2 && args.size() != 3) {
throw RuntimeError("Wrong number of arguments for action PUT");
}
if (args.size() == 2) {
try {
StringTo<uint32_t>(args[0]);
} catch (...) {
throw RuntimeError("Could not convert argument 0 to uint32_t");
}
try {
StringTo<uint32_t>(args[1]);
} catch (...) {
throw RuntimeError("Could not convert argument 1 to uint32_t");
}
try {
StringTo<bool>("0");
} catch (...) {
throw RuntimeError("Could not convert argument 2 to bool");
}
}
if (args.size() == 3) {
try {
StringTo<uint32_t>(args[0]);
} catch (...) {
throw RuntimeError("Could not convert argument 0 to uint32_t");
}
try {
StringTo<uint32_t>(args[1]);
} catch (...) {
throw RuntimeError("Could not convert argument 1 to uint32_t");
}
try {
StringTo<bool>("1");
} catch (...) {
throw RuntimeError("Could not convert argument 2 to bool");
}
}
}
else {
throw RuntimeError("INTERNAL ERROR: Invalid action: supported actions "
"are ['GET', 'PUT']");
}
// generate code for each action
if (action == slsDetectorDefs::GET_ACTION) {
if (args.size() == 1) {
auto arg0 = StringTo<uint32_t>(args[0]);
auto t = det->readRegister(arg0, std::vector<int>{det_id});
os << OutStringHex(t) << '\n';
}
}
if (action == slsDetectorDefs::PUT_ACTION) {
if (args.size() == 2) {
auto arg0 = StringTo<uint32_t>(args[0]);
auto arg1 = StringTo<uint32_t>(args[1]);
auto arg2 = StringTo<bool>("0");
det->writeRegister(arg0, arg1, arg2, std::vector<int>{det_id});
os << "[" << args[0] << ", " << args[1] << "]" << '\n';
}
if (args.size() == 3) {
if (args[2] != "--validate") {
throw RuntimeError(
"Could not scan third argument. Did you mean --validate?");
}
auto arg0 = StringTo<uint32_t>(args[0]);
auto arg1 = StringTo<uint32_t>(args[1]);
auto arg2 = StringTo<bool>("1");
det->writeRegister(arg0, arg1, arg2, std::vector<int>{det_id});
os << "[" << args[0] << ", " << args[1] << "]" << '\n';
}
}
return os.str();
}
std::string Caller::resetdacs(int action) {
std::ostringstream os;
@@ -12384,100 +12123,6 @@ std::string Caller::serialnumber(int action) {
return os.str();
}
std::string Caller::setbit(int action) {
std::ostringstream os;
// print help
if (action == slsDetectorDefs::HELP_ACTION) {
os << R"V0G0N([reg address in hex] [bit index]
Sets bit in address.
Use --validate to force validation. )V0G0N"
<< std::endl;
return os.str();
}
// check if action and arguments are valid
if (action == slsDetectorDefs::PUT_ACTION) {
if (1 && args.size() != 2 && args.size() != 3) {
throw RuntimeError("Wrong number of arguments for action PUT");
}
if (args.size() == 2) {
try {
StringTo<uint32_t>(args[0]);
} catch (...) {
throw RuntimeError("Could not convert argument 0 to uint32_t");
}
try {
StringTo<int>(args[1]);
} catch (...) {
throw RuntimeError("Could not convert argument 1 to int");
}
try {
StringTo<bool>("0");
} catch (...) {
throw RuntimeError("Could not convert argument 2 to bool");
}
}
if (args.size() == 3) {
try {
StringTo<uint32_t>(args[0]);
} catch (...) {
throw RuntimeError("Could not convert argument 0 to uint32_t");
}
try {
StringTo<int>(args[1]);
} catch (...) {
throw RuntimeError("Could not convert argument 1 to int");
}
try {
StringTo<bool>("1");
} catch (...) {
throw RuntimeError("Could not convert argument 2 to bool");
}
}
}
else {
throw RuntimeError(
"INTERNAL ERROR: Invalid action: supported actions are ['PUT']");
}
// generate code for each action
if (action == slsDetectorDefs::PUT_ACTION) {
if (args.size() == 2) {
if (StringTo<int>(args[1]) < 0 || StringTo<int>(args[1]) > 31) {
throw RuntimeError("Bit number out of range: " + args[1]);
}
auto arg0 = StringTo<uint32_t>(args[0]);
auto arg1 = StringTo<int>(args[1]);
auto arg2 = StringTo<bool>("0");
det->setBit(arg0, arg1, arg2, std::vector<int>{det_id});
os << "[" << args[0] << ", " << args[1] << "]" << '\n';
}
if (args.size() == 3) {
if (StringTo<int>(args[1]) < 0 || StringTo<int>(args[1]) > 31) {
throw RuntimeError("Bit number out of range: " + args[1]);
}
if (args[2] != "--validate") {
throw RuntimeError(
"Could not scan third argument. Did you mean --validate?");
}
auto arg0 = StringTo<uint32_t>(args[0]);
auto arg1 = StringTo<int>(args[1]);
auto arg2 = StringTo<bool>("1");
det->setBit(arg0, arg1, arg2, std::vector<int>{det_id});
os << "[" << args[0] << ", " << args[1] << "]" << '\n';
}
}
return os.str();
}
std::string Caller::settings(int action) {
std::ostringstream os;

View File

@@ -3,7 +3,7 @@
#include "CmdParser.h"
#include "HelpDacs.h"
#include "sls/Detector.h"
#include "sls/bit_utils.h"
#include <iostream>
#include <string>
#include <vector>
@@ -107,6 +107,10 @@ class Caller {
std::string dbitpipeline(int action);
std::string defaultdac(int action);
std::string defaultpattern(int action);
std::string define_bit(int action);
std::string define_reg(int action);
std::string definelist_bit(int action);
std::string definelist_reg(int action);
std::string delay(int action);
std::string delayl(int action);
std::string detectorserverversion(int action);
@@ -398,6 +402,11 @@ class Caller {
static void EmptyDataCallBack(detectorData *data, uint64_t frameIndex,
uint32_t subFrameIndex, void *this_pointer);
std::string bitoperations(int action);
RegisterAddress parseAddress(const std::string &saddr) const;
bool parseValidate();
BitAddress parseBitAddress() const;
FunctionMap functions{
{"list", &Caller::list},
@@ -451,6 +460,10 @@ class Caller {
{"dbitpipeline", &Caller::dbitpipeline},
{"defaultdac", &Caller::defaultdac},
{"defaultpattern", &Caller::defaultpattern},
{"define_bit", &Caller::define_bit},
{"define_reg", &Caller::define_reg},
{"definelist_bit", &Caller::definelist_bit},
{"definelist_reg", &Caller::definelist_reg},
{"delay", &Caller::delay},
{"delayl", &Caller::delayl},
{"detectorserverversion", &Caller::detectorserverversion},

View File

@@ -1437,4 +1437,398 @@ std::string Caller::sleep(int action) {
return os.str();
}
std::string Caller::define_reg(int action) {
std::ostringstream os;
if (action == defs::HELP_ACTION) {
os << "[Ctb][Xilinx Ctb]"
"\n\t[reg name] [reg address]"
"\n\n\tSets a user defined register in shared memory. The name "
"can be upto 32 characters long."
"\n\teg."
"\n\tsls_detector_put define_reg test_reg 0x200"
"\n\n\tOne can retrieve the address using the name and vice "
"versa."
"\n\teg."
"\n\tsls_detector_get define_reg test_reg"
"\n\tsls_detector_get define_reg 0x200"
"\n\n\tOne can then use this user-defined name in other commands "
"instead of hard coding the address such as for reg, setbit, "
"clearbit and getbit commands."
"\n\teg."
"\n\tsls_detector_put reg test_reg 0x1"
"\n\tsls_detector_put setbit test_reg 2"
"\n\tsls_detector_put clearbit test_reg 2"
"\n\tsls_detector_get getbit test_reg 2"
<< '\n';
return os.str();
}
auto det_type = det->getDetectorType().squash();
if (det_type != defs::XILINX_CHIPTESTBOARD &&
det_type != defs::CHIPTESTBOARD) {
throw RuntimeError(
"define_reg command only supported for ctb and xilinx_ctb");
}
if (det_id != -1) {
throw RuntimeError("Cannot use define at module level. Use the default "
"multi-module level");
}
if (action == defs::GET_ACTION) {
if (args.size() != 1) {
WrongNumberOfParameters(1);
}
// get name from address
if (is_hex_or_dec_uint(args[0])) {
auto addr = RegisterAddress(args[0]);
auto t = det->getRegisterDefinitionName(addr);
os << t << '\n';
}
// get address from name
else {
auto t = det->getRegisterDefinitionAddress(args[0]);
os << t.str() << '\n';
}
} else if (action == defs::PUT_ACTION) {
if (args.size() != 2) {
WrongNumberOfParameters(2);
}
auto name = args[0];
auto addr = RegisterAddress(args[1]);
det->setRegisterDefinition(name, addr);
os << "addr " << name << ' ' << addr.str() << '\n';
} else {
throw RuntimeError("Unknown action");
}
return os.str();
}
std::string Caller::define_bit(int action) {
std::ostringstream os;
if (action == defs::HELP_ACTION) {
os << "[Ctb][Xilinx Ctb]"
"\n\t[bit name] [regiser name/address] [bit position]"
"\n\n\tSets a user defined bit name in shared memory "
"representing the register address and the bit position. The "
"address can be named prior using define_reg command. The name "
"can be upto 32 characters long."
"\n\teg."
"\n\tsls_detector_put define_bit test_bit test_reg 2"
"\n\tsls_detector_put define_bit test_bit 0x200 2"
"\n\n\tOne can retrieve the bit address using the name and vice "
"versa using both register name or address and bit position."
"\n\teg."
"\n\tsls_detector_get define_bit test_bit"
"\n\tsls_detector_get define_bit test_reg 2"
"\n\tsls_detector_get define_bit 0x200 2"
"\n\n\tOne can then use this user-defined name in other commands "
"such as for setbit, clearbit and getbit commands. When using "
"bit names, please dont use register name or address as bit name "
"is already tied to a specific register."
"\n\teg."
"\n\tsls_detector_put setbit test_bit"
"\n\tsls_detector_put clearbit test_bit"
"\n\tsls_detector_get getbit test_bit"
<< '\n';
return os.str();
}
auto det_type = det->getDetectorType().squash();
if (det_type != defs::XILINX_CHIPTESTBOARD &&
det_type != defs::CHIPTESTBOARD) {
throw RuntimeError(
"define_bit command only supported for ctb and xilinx_ctb");
}
if (det_id != -1) {
throw RuntimeError("Cannot use define at module level. Use the default "
"multi-module level");
}
if (action == defs::GET_ACTION) {
// get position from name
if (args.size() == 1) {
auto t = det->getBitDefinitionAddress(args[0]);
bool found_addr = det->hasRegisterDefinition(t.address());
if (found_addr) {
os << '[' << det->getRegisterDefinitionName(t.address()) << ", "
<< std::to_string(t.bitPosition()) << "]\n";
} else {
os << t.str() << '\n';
}
}
// get name from position and address
else if (args.size() == 2) {
auto reg = parseAddress(args[0]);
BitAddress addr(reg.str(), args[1]);
try {
auto t = det->getBitDefinitionName(addr);
os << t << '\n';
} catch (const RuntimeError &e) {
std::string err_str = e.what();
if (err_str.find("No bit definition found") !=
std::string::npos &&
!is_hex_or_dec_uint(args[0])) {
err_str += " and addr = " + args[0];
throw RuntimeError(err_str);
}
throw;
}
} else {
WrongNumberOfParameters(1);
}
} else if (action == defs::PUT_ACTION) {
if (args.size() != 3) {
WrongNumberOfParameters(3);
}
if (!is_int(args[2])) {
throw RuntimeError("Bit position must be an integer value.");
}
auto name = args[0];
auto reg = parseAddress(args[1]);
BitAddress addr(reg.str(), args[2]);
det->setBitDefinition(name, addr);
os << ToString(args) << '\n';
} else {
throw RuntimeError("Unknown action");
}
return os.str();
}
std::string Caller::definelist_reg(int action) {
std::ostringstream os;
if (action == defs::HELP_ACTION) {
os << "List of user-defined register definitions in shared memory."
<< '\n';
} else if (action == defs::PUT_ACTION) {
throw RuntimeError("cannot put");
} else if (action == defs::GET_ACTION) {
auto det_type = det->getDetectorType().squash();
if (det_type != defs::XILINX_CHIPTESTBOARD &&
det_type != defs::CHIPTESTBOARD) {
throw RuntimeError(
"definelist_reg command only supported for ctb and xilinx_ctb");
}
if (!args.empty()) {
WrongNumberOfParameters(0);
}
auto t = det->getRegisterDefinitions();
os << '\n' << ToString(t) << '\n';
} else {
throw RuntimeError("Unknown action");
}
return os.str();
}
std::string Caller::definelist_bit(int action) {
std::ostringstream os;
if (action == defs::HELP_ACTION) {
os << "List of user-defined bit definitions in shared memory." << '\n';
} else if (action == defs::PUT_ACTION) {
throw RuntimeError("cannot put");
} else if (action == defs::GET_ACTION) {
auto det_type = det->getDetectorType().squash();
if (det_type != defs::XILINX_CHIPTESTBOARD &&
det_type != defs::CHIPTESTBOARD) {
throw RuntimeError(
"definelist_bit command only supported for ctb and xilinx_ctb");
}
if (!args.empty()) {
WrongNumberOfParameters(0);
}
auto t = det->getBitDefinitions();
os << "\n[";
for (const auto &[key, val] : t) {
os << key << ": ";
bool found_addr = det->hasRegisterDefinition(val.address());
if (found_addr) {
os << '[' << det->getRegisterDefinitionName(val.address())
<< ", " << std::to_string(val.bitPosition()) << "]";
} else {
os << val.str();
}
if (&key != &t.rbegin()->first) {
os << ", ";
}
os << '\n';
}
os << "]\n";
} else {
throw RuntimeError("Unknown action");
}
return os.str();
}
std::string Caller::reg(int action) {
std::ostringstream os;
if (action == defs::HELP_ACTION) {
os << "[address] [32 bit value][(optional)--validate]"
"\n\tReads/writes to a 32 bit register in hex."
"\n\tAdvanced Function!\n\tGoes to stop server. Hence, can be "
"called while calling blocking acquire()."
"\n\t\t Use --validate to enforce validation when writing to "
"register."
"\n\t[Eiger] +0x100 for only left, +0x200 for only right."
"\n\t[Ctb][Xilinx_Ctb] Address can also be a user-defined name "
"that was set previously using the define command."
"\n\t\teg."
"\n\t\tsls_detector_put reg 0x200 0xFFF --validate"
"\n\t\tsls_detector_get reg test_reg"
"\n\t\tsls_detector_put reg test_reg 0xFF"
<< '\n';
} else {
if (action == defs::PUT_ACTION) {
if (args.size() < 2 || args.size() > 3) {
WrongNumberOfParameters(2);
}
auto validate = parseValidate();
auto addr = parseAddress(args[0]);
auto val = RegisterValue(args[1]);
det->writeRegister(addr, val, validate, std::vector<int>{det_id});
os << addr.str() << " " << val.str() << '\n';
} else if (action == defs::GET_ACTION) {
if (args.size() != 1) {
WrongNumberOfParameters(1);
}
auto addr = parseAddress(args[0]);
auto t = det->readRegister(addr, std::vector<int>{det_id});
os << OutString(t) << '\n';
} else {
throw RuntimeError("Unknown action");
}
}
return os.str();
}
std::string Caller::getbit(int action) { return bitoperations(action); }
std::string Caller::setbit(int action) { return bitoperations(action); }
std::string Caller::clearbit(int action) { return bitoperations(action); }
std::string Caller::bitoperations(int action) {
std::ostringstream os;
if (action == defs::HELP_ACTION) {
if (cmd == "getbit") {
os << "[reg address in hex] [bit index]\n\tGets bit in address."
<< '\n';
} else if (cmd == "setbit") {
os << "[reg address in hex] [bit index]\n\tSets bit in "
"address.\n\tUse --validate to force validation."
<< '\n';
} else if (cmd == "clearbit") {
os << "[reg address in hex] [bit index]\n\tClears bit in "
"address.\n\tUse --validate to force validation."
<< '\n';
} else {
throw RuntimeError("Unknown command");
}
os << "\n\t\t[Ctb][Xilinx_Ctb] Address or bit position can also be a "
"user-defined name that was set previously using the define "
"command. When using bit names, avoid register name/ address as "
"the bit name is tied to a specific register already."
"\n\n\teg."
"\n\tsls_detector_get getbit 0x200 2"
"\n\tsls_detector_get getbit test_reg 2"
"\n\tsls_detector_get getbit test_bit"
"\n\tsls_detector_put setbit 0x200 2"
"\n\tsls_detector_put setbit test_reg 2"
"\n\tsls_detector_put setbit test_bit"
"\n\tsls_detector_put clearbit test_bit";
os << '\n';
} else {
if (action != defs::GET_ACTION && action != defs::PUT_ACTION) {
throw RuntimeError("Unknown action");
}
auto validate = parseValidate();
auto BitAddress = parseBitAddress();
if (action == defs::GET_ACTION) {
if (cmd == "setbit" || cmd == "clearbit")
throw RuntimeError("Cannot get");
auto t = det->getBit(BitAddress, std::vector<int>{det_id});
os << OutString(t) << '\n';
} else {
if (cmd == "getbit")
throw RuntimeError("Cannot put");
if (cmd == "setbit")
det->setBit(BitAddress, validate, std::vector<int>{det_id});
else if (cmd == "clearbit")
det->clearBit(BitAddress, validate, std::vector<int>{det_id});
else
throw RuntimeError("Unknown command");
os << ToString(args) << "\n";
}
}
return os.str();
}
RegisterAddress Caller::parseAddress(const std::string &saddr) const {
if (is_hex_or_dec_uint(saddr)) {
return RegisterAddress(saddr);
}
auto det_type = det->getDetectorType().squash();
if (det_type != defs::XILINX_CHIPTESTBOARD &&
det_type != defs::CHIPTESTBOARD) {
throw RuntimeError(
"Could not parse address " + saddr +
". User defined register definitions only supported for ctb and "
"xilinx_ctb. Use an actual hard coded address for this detector.");
}
return det->getRegisterDefinitionAddress(saddr);
}
bool Caller::parseValidate() {
auto it = std::find(args.begin(), args.end(), "--validate");
bool validate = (it != args.end());
// throw for any -- options other than --validate
if (!validate) {
auto invalid_it =
std::find_if(args.begin(), args.end(), [](const auto &s) {
// only looks for the first characters
return s.rfind("--", 0) == 0 && s != "--validate";
});
if (invalid_it != args.end()) {
throw RuntimeError("Unknown option '" + *invalid_it +
"'. Did you mean '--validate'?");
}
}
// --validate should be the last argument
else {
if (it != args.end() - 1) {
throw RuntimeError("'--validate' should be the last argument.");
}
args.pop_back();
}
return validate;
}
BitAddress Caller::parseBitAddress() const {
int argsSize = args.size();
std::string addr_or_bitname = args[0];
// bit name
if (argsSize == 1) {
auto det_type = det->getDetectorType().squash();
if (det_type != defs::XILINX_CHIPTESTBOARD &&
det_type != defs::CHIPTESTBOARD) {
throw RuntimeError("Could not parse bit name " + addr_or_bitname +
". User defined bit definitions only supported "
"for ctb and xilinx_ctb. Use an actual hard "
"coded bit position for this detector.");
}
return det->getBitDefinitionAddress(addr_or_bitname);
}
// address and bit position
else if (argsSize == 2) {
auto reg = parseAddress(addr_or_bitname);
return BitAddress(reg.str(), args[1]);
} else {
throw RuntimeError("Command " + cmd +
" expected (1-4) parameter/s but got " +
std::to_string(args.size()) + "\n");
}
}
} // namespace sls

View File

@@ -238,4 +238,125 @@ std::vector<std::string> CtbConfig::getSlowADCNames() const {
const char *CtbConfig::shm_tag() { return shm_tag_; }
int CtbConfig::getRegisterNamesCount() const { return num_regs; }
void CtbConfig::setRegisterName(const std::string &name, RegisterAddress addr) {
addEntry<RegisterDefinition, RegisterAddress>(
name, addr, registers, num_regs, max_regs, "register");
}
bool CtbConfig::hasRegisterName(const std::string &name) const {
return lookupEntryByName<RegisterDefinition, RegisterAddress>(
name, registers, num_regs)
.has_value();
}
bool CtbConfig::hasRegisterAddress(RegisterAddress addr) const {
return lookupEntryByValue<RegisterDefinition, RegisterAddress>(
addr, registers, num_regs)
.has_value();
}
RegisterAddress CtbConfig::getRegisterAddress(const std::string &name) const {
auto val = lookupEntryByName<RegisterDefinition, RegisterAddress>(
name, registers, num_regs);
if (!val.has_value()) {
throw RuntimeError("No register definition found for name: " + name);
}
return val.value();
}
std::string CtbConfig::getRegisterName(RegisterAddress addr) const {
auto val = lookupEntryByValue<RegisterDefinition, RegisterAddress>(
addr, registers, num_regs);
if (!val.has_value()) {
throw RuntimeError("No register definition found for address: " +
addr.str());
}
return val.value();
}
void CtbConfig::clearRegisterNames() {
memset(registers, 0, sizeof(registers));
num_regs = 0;
}
void CtbConfig::setRegisterNames(
const std::map<std::string, RegisterAddress> &list) {
if (list.size() >= max_regs) {
throw RuntimeError("Register names need to be of size less than " +
std::to_string(max_regs));
}
clearRegisterNames();
for (const auto &[name, value] : list) {
setRegisterName(name, value);
}
}
std::map<std::string, RegisterAddress> CtbConfig::getRegisterNames() const {
std::map<std::string, RegisterAddress> names;
for (size_t i = 0; i != num_regs; ++i)
names[registers[i].name()] = registers[i].value();
return names;
}
int CtbConfig::getBitNamesCount() const { return num_bits; }
void CtbConfig::setBitName(const std::string &name, BitAddress bitPos) {
addEntry<BitDefinition, BitAddress>(name, bitPos, bits, num_bits, max_bits,
"bit");
}
bool CtbConfig::hasBitName(const std::string &name) const {
return lookupEntryByName<BitDefinition, BitAddress>(name, bits, num_bits)
.has_value();
}
bool CtbConfig::hasBitAddress(BitAddress bitPos) const {
return lookupEntryByValue<BitDefinition, BitAddress>(bitPos, bits, num_bits)
.has_value();
}
BitAddress CtbConfig::getBitAddress(const std::string &name) const {
auto val =
lookupEntryByName<BitDefinition, BitAddress>(name, bits, num_bits);
if (!val.has_value()) {
throw RuntimeError("No bit definition found for name: " + name);
}
return val.value();
}
std::string CtbConfig::getBitName(BitAddress bitPos) const {
auto val =
lookupEntryByValue<BitDefinition, BitAddress>(bitPos, bits, num_bits);
if (!val.has_value()) {
throw RuntimeError("No bit definition found for bit position: " +
bitPos.str());
}
return val.value();
}
void CtbConfig::clearBitNames() {
memset(bits, 0, sizeof(bits));
num_bits = 0;
}
void CtbConfig::setBitNames(const std::map<std::string, BitAddress> &list) {
if (list.size() >= max_bits) {
throw RuntimeError("Bit names need to be of size less than " +
std::to_string(max_bits));
}
clearBitNames();
for (const auto &[name, value] : list) {
setBitName(name, value);
}
}
std::map<std::string, BitAddress> CtbConfig::getBitNames() const {
std::map<std::string, BitAddress> names;
for (size_t i = 0; i != num_bits; ++i)
names[bits[i].name()] = bits[i].value();
return names;
}
} // namespace sls

View File

@@ -1,31 +1,88 @@
#pragma once
#include "sls/bit_utils.h"
#include "sls/sls_detector_defs.h"
#include "sls/string_utils.h"
#include <map>
#include <optional>
#include <string>
#include <variant>
#include <vector>
namespace sls {
#define CTB_SHMAPIVERSION 0x250820
#define CTB_SHMVERSION 0x250820
inline constexpr size_t CTB_NAME_LENGTH = 32;
class RegisterDefinition {
private:
char name_[CTB_NAME_LENGTH]{};
RegisterAddress addr_;
public:
RegisterDefinition() noexcept = default;
RegisterDefinition(const std::string &name, RegisterAddress address)
: addr_(address) {
if (name.empty()) {
throw sls::RuntimeError("Register name cannot be empty.");
}
strcpy_checked(name_, name);
}
std::string name() const noexcept { return name_; }
RegisterAddress value() const noexcept { return addr_; }
void setValue(RegisterAddress address) noexcept { addr_ = address; }
};
class BitDefinition {
private:
char name_[CTB_NAME_LENGTH]{};
BitAddress bitPos_;
public:
BitDefinition() noexcept = default;
BitDefinition(const std::string &name, BitAddress bitPos)
: bitPos_(bitPos) {
if (name.empty()) {
throw sls::RuntimeError("Bit name cannot be empty.");
}
strcpy_checked(name_, name);
}
std::string name() const noexcept { return name_; }
BitAddress value() const noexcept { return bitPos_; }
void setValue(BitAddress bitPos) noexcept { bitPos_ = bitPos; }
};
class CtbConfig {
public:
/** fixed pattern */
int shmversion{CTB_SHMVERSION};
static constexpr int SHM_VERSION = 0x251215;
int shmversion{SHM_VERSION};
bool isValid{true}; // false if freed to block access from python or c++ api
/** end of fixed pattern */
private:
static constexpr size_t name_length = 20;
static constexpr const char *shm_tag_ = "ctbdacs";
static constexpr size_t name_length = CTB_NAME_LENGTH;
static constexpr size_t num_dacs = 18;
static constexpr size_t num_adcs = 32;
static constexpr size_t num_signals = 64;
static constexpr size_t num_powers = 5;
static constexpr size_t num_slowADCs = 8;
static constexpr const char *shm_tag_ = "ctbdacs";
char dacnames[name_length * num_dacs]{};
char adcnames[name_length * num_adcs]{};
char signalnames[name_length * num_signals]{};
char powernames[name_length * num_powers]{};
char slowADCnames[name_length * num_slowADCs]{};
static constexpr size_t max_regs = 64;
static constexpr size_t max_bits = 64;
size_t num_regs{0};
size_t num_bits{0};
RegisterDefinition registers[max_regs];
BitDefinition bits[max_bits];
void check_dac_index(size_t i) const;
void check_adc_index(size_t i) const;
void check_signal_index(size_t i) const;
@@ -33,12 +90,99 @@ class CtbConfig {
void check_slow_adc_index(size_t i) const;
void check_size(const std::string &name) const;
template <typename T>
std::optional<T *> findEntryByName(const std::string &name, T *array,
size_t count) {
auto it = std::find_if(array, array + count,
[&name](T &e) { return (e.name() == name); });
if (it != array + count)
return it;
return std::nullopt;
}
template <typename T>
std::optional<const T *> findEntryByName(const std::string &name,
const T *array,
size_t count) const {
auto it = std::find_if(array, array + count, [&name](const T &e) {
return (e.name() == name);
});
if (it != array + count)
return it;
return std::nullopt;
}
template <typename T, typename Tval>
std::optional<T *> findEntryByValue(Tval value, T *array, size_t count) {
auto it = std::find_if(array, array + count,
[&value](T &e) { return e.value() == value; });
if (it != array + count)
return it;
return std::nullopt;
}
template <typename T, typename Tval>
std::optional<const T *> findEntryByValue(Tval value, const T *array,
size_t count) const {
auto it = std::find_if(array, array + count, [&value](const T &e) {
return e.value() == value;
});
if (it != array + count)
return it;
return std::nullopt;
}
template <typename T, typename Tval>
std::optional<const Tval> lookupEntryByName(const std::string &name,
const T *array,
size_t count) const {
auto entry = findEntryByName<T>(name, array, count);
return (entry ? std::optional<Tval>((*entry)->value()) : std::nullopt);
}
template <typename T, typename Tval>
std::optional<std::string> lookupEntryByValue(Tval value, const T *array,
size_t count) const {
auto entry = findEntryByValue<T>(value, array, count);
return (entry ? std::optional<std::string>((*entry)->name())
: std::nullopt);
}
template <typename T, typename Tval>
void addEntry(const std::string &name, Tval value, T *array, size_t &count,
size_t max_count, const std::string &type_name) {
check_size(name);
// exists: overwrite value
if (auto entry = findEntryByName<T>(name, array, count)) {
(*entry)->setValue(value);
return;
}
// check size
if (count >= max_count) {
throw RuntimeError("Maximum number of " + type_name +
" reached. Clear shared memory and try again.");
}
// check value exists
if (auto entry = findEntryByValue<T>(value, array, count)) {
throw RuntimeError(value.str() + " already assigned to " +
type_name + " '" + (*entry)->name() +
"'. Cannot assign to '" + name + "'");
}
// add new entry
array[count] = T(name, value);
++(count);
}
public:
CtbConfig();
CtbConfig(const CtbConfig &) = default;
CtbConfig(CtbConfig &&) = default;
CtbConfig &operator=(const CtbConfig &) = default;
~CtbConfig() = default;
void setDacNames(const std::vector<std::string> &names);
void setDacName(size_t index, const std::string &name);
@@ -65,6 +209,26 @@ class CtbConfig {
std::string getSlowADCName(size_t index) const;
std::vector<std::string> getSlowADCNames() const;
static const char *shm_tag();
int getRegisterNamesCount() const;
void setRegisterName(const std::string &name, RegisterAddress addr);
bool hasRegisterName(const std::string &name) const;
bool hasRegisterAddress(RegisterAddress addr) const;
RegisterAddress getRegisterAddress(const std::string &name) const;
std::string getRegisterName(RegisterAddress addr) const;
void clearRegisterNames();
void setRegisterNames(const std::map<std::string, RegisterAddress> &list);
std::map<std::string, RegisterAddress> getRegisterNames() const;
int getBitNamesCount() const;
void setBitName(const std::string &name, BitAddress bitPos);
bool hasBitName(const std::string &name) const;
bool hasBitAddress(BitAddress bitPos) const;
BitAddress getBitAddress(const std::string &name) const;
std::string getBitName(BitAddress bitPos) const;
void clearBitNames();
void setBitNames(const std::map<std::string, BitAddress> &list);
std::map<std::string, BitAddress> getBitNames() const;
};
} // namespace sls

View File

@@ -2377,26 +2377,21 @@ void Detector::setLEDEnable(bool enable, Positions pos) {
}
void Detector::setDacNames(const std::vector<std::string> names) {
auto dettype = getDetectorType().squash();
if (dettype != defs::CHIPTESTBOARD && dettype != defs::XILINX_CHIPTESTBOARD)
throw RuntimeError("Named dacs only for CTB");
pimpl->setCtbDacNames(names);
}
std::vector<std::string> Detector::getDacNames() const {
std::vector<std::string> names;
auto type = getDetectorType().squash();
if (type == defs::CHIPTESTBOARD || type == defs::XILINX_CHIPTESTBOARD)
if (pimpl->isChipTestBoard())
return pimpl->getCtbDacNames();
std::vector<std::string> names;
for (const auto &index : getDacList())
names.push_back(ToString(index));
return names;
}
defs::dacIndex Detector::getDacIndex(const std::string &name) const {
auto type = getDetectorType().squash();
if (type == defs::CHIPTESTBOARD || type == defs::XILINX_CHIPTESTBOARD) {
if (pimpl->isChipTestBoard()) {
auto names = getDacNames();
auto it = std::find(names.begin(), names.end(), name);
if (it == names.end())
@@ -2407,37 +2402,24 @@ defs::dacIndex Detector::getDacIndex(const std::string &name) const {
}
void Detector::setDacName(const defs::dacIndex i, const std::string &name) {
auto dettype = getDetectorType().squash();
if (dettype != defs::CHIPTESTBOARD && dettype != defs::XILINX_CHIPTESTBOARD)
throw RuntimeError("Named dacs only for CTB");
pimpl->setCtbDacName(i, name);
}
std::string Detector::getDacName(const defs::dacIndex i) const {
auto dettype = getDetectorType().squash();
if (dettype == defs::CHIPTESTBOARD || dettype == defs::XILINX_CHIPTESTBOARD)
if (pimpl->isChipTestBoard())
return pimpl->getCtbDacName(i);
return ToString(i);
}
void Detector::setAdcNames(const std::vector<std::string> names) {
auto dettype = getDetectorType().squash();
if (dettype != defs::CHIPTESTBOARD && dettype != defs::XILINX_CHIPTESTBOARD)
throw RuntimeError("Named adcs only for CTB");
pimpl->setCtbAdcNames(names);
}
std::vector<std::string> Detector::getAdcNames() const {
auto dettype = getDetectorType().squash();
if (dettype != defs::CHIPTESTBOARD && dettype != defs::XILINX_CHIPTESTBOARD)
throw RuntimeError("Named adcs only for CTB");
return pimpl->getCtbAdcNames();
}
int Detector::getAdcIndex(const std::string &name) const {
auto dettype = getDetectorType().squash();
if (dettype != defs::CHIPTESTBOARD && dettype != defs::XILINX_CHIPTESTBOARD)
throw RuntimeError("Named adcs only for CTB");
auto names = getAdcNames();
auto it = std::find(names.begin(), names.end(), name);
if (it == names.end())
@@ -2446,37 +2428,22 @@ int Detector::getAdcIndex(const std::string &name) const {
}
void Detector::setAdcName(const int index, const std::string &name) {
auto dettype = getDetectorType().squash();
if (dettype != defs::CHIPTESTBOARD && dettype != defs::XILINX_CHIPTESTBOARD)
throw RuntimeError("Named adcs only for CTB");
pimpl->setCtbAdcName(index, name);
}
std::string Detector::getAdcName(const int i) const {
auto dettype = getDetectorType().squash();
if (dettype != defs::CHIPTESTBOARD && dettype != defs::XILINX_CHIPTESTBOARD)
throw RuntimeError("Named adcs only for CTB");
return pimpl->getCtbAdcName(i);
}
void Detector::setSignalNames(const std::vector<std::string> names) {
auto dettype = getDetectorType().squash();
if (dettype != defs::CHIPTESTBOARD && dettype != defs::XILINX_CHIPTESTBOARD)
throw RuntimeError("Named signals only for CTB");
pimpl->setCtbSignalNames(names);
}
std::vector<std::string> Detector::getSignalNames() const {
auto dettype = getDetectorType().squash();
if (dettype != defs::CHIPTESTBOARD && dettype != defs::XILINX_CHIPTESTBOARD)
throw RuntimeError("Named signals only for CTB");
return pimpl->getCtbSignalNames();
}
int Detector::getSignalIndex(const std::string &name) const {
auto dettype = getDetectorType().squash();
if (dettype != defs::CHIPTESTBOARD && dettype != defs::XILINX_CHIPTESTBOARD)
throw RuntimeError("Named signals only for CTB");
auto names = getSignalNames();
auto it = std::find(names.begin(), names.end(), name);
if (it == names.end())
@@ -2485,38 +2452,22 @@ int Detector::getSignalIndex(const std::string &name) const {
}
void Detector::setSignalName(const int index, const std::string &name) {
auto dettype = getDetectorType().squash();
if (dettype != defs::CHIPTESTBOARD && dettype != defs::XILINX_CHIPTESTBOARD)
throw RuntimeError("Named signals only for CTB");
pimpl->setCtbSignalName(index, name);
}
std::string Detector::getSignalName(const int i) const {
auto dettype = getDetectorType().squash();
if (dettype != defs::CHIPTESTBOARD && dettype != defs::XILINX_CHIPTESTBOARD)
throw RuntimeError("Named signals only for CTB");
return pimpl->getCtbSignalName(i);
}
void Detector::setPowerNames(const std::vector<std::string> names) {
auto dettype = getDetectorType().squash();
if (getDetectorType().squash() != defs::CHIPTESTBOARD &&
dettype != defs::XILINX_CHIPTESTBOARD)
throw RuntimeError("Named powers only for CTB");
pimpl->setCtbPowerNames(names);
}
std::vector<std::string> Detector::getPowerNames() const {
auto dettype = getDetectorType().squash();
if (dettype != defs::CHIPTESTBOARD && dettype != defs::XILINX_CHIPTESTBOARD)
throw RuntimeError("Named powers only for CTB");
return pimpl->getCtbPowerNames();
}
defs::dacIndex Detector::getPowerIndex(const std::string &name) const {
auto dettype = getDetectorType().squash();
if (dettype != defs::CHIPTESTBOARD && dettype != defs::XILINX_CHIPTESTBOARD)
throw RuntimeError("Named powers only for CTB");
auto names = getPowerNames();
auto it = std::find(names.begin(), names.end(), name);
if (it == names.end())
@@ -2526,37 +2477,22 @@ defs::dacIndex Detector::getPowerIndex(const std::string &name) const {
void Detector::setPowerName(const defs::dacIndex index,
const std::string &name) {
auto dettype = getDetectorType().squash();
if (dettype != defs::CHIPTESTBOARD && dettype != defs::XILINX_CHIPTESTBOARD)
throw RuntimeError("Named powers only for CTB");
pimpl->setCtbPowerName(index, name);
}
std::string Detector::getPowerName(const defs::dacIndex i) const {
auto dettype = getDetectorType().squash();
if (dettype != defs::CHIPTESTBOARD && dettype != defs::XILINX_CHIPTESTBOARD)
throw RuntimeError("Named powers only for CTB");
return pimpl->getCtbPowerName(i);
}
void Detector::setSlowADCNames(const std::vector<std::string> names) {
auto dettype = getDetectorType().squash();
if (dettype != defs::CHIPTESTBOARD && dettype != defs::XILINX_CHIPTESTBOARD)
throw RuntimeError("Named SlowADCs only for CTB");
pimpl->setCtbSlowADCNames(names);
}
std::vector<std::string> Detector::getSlowADCNames() const {
auto dettype = getDetectorType().squash();
if (dettype != defs::CHIPTESTBOARD && dettype != defs::XILINX_CHIPTESTBOARD)
throw RuntimeError("Named SlowADCs only for CTB");
return pimpl->getCtbSlowADCNames();
}
defs::dacIndex Detector::getSlowADCIndex(const std::string &name) const {
auto dettype = getDetectorType().squash();
if (dettype != defs::CHIPTESTBOARD && dettype != defs::XILINX_CHIPTESTBOARD)
throw RuntimeError("Named SlowADCs only for CTB");
auto names = getSlowADCNames();
auto it = std::find(names.begin(), names.end(), name);
if (it == names.end())
@@ -2566,19 +2502,86 @@ defs::dacIndex Detector::getSlowADCIndex(const std::string &name) const {
void Detector::setSlowADCName(const defs::dacIndex index,
const std::string &name) {
auto dettype = getDetectorType().squash();
if (dettype != defs::CHIPTESTBOARD && dettype != defs::XILINX_CHIPTESTBOARD)
throw RuntimeError("Named SlowADCs only for CTB");
pimpl->setCtbSlowADCName(index, name);
}
std::string Detector::getSlowADCName(const defs::dacIndex i) const {
auto dettype = getDetectorType().squash();
if (dettype != defs::CHIPTESTBOARD && dettype != defs::XILINX_CHIPTESTBOARD)
throw RuntimeError("Named SlowADCs only for CTB");
return pimpl->getCtbSlowADCName(i);
}
int Detector::getRegisterDefinitionsCount() const {
return pimpl->getRegisterDefinitionsCount();
}
void Detector::setRegisterDefinition(const std::string &name,
RegisterAddress addr) {
pimpl->setRegisterDefinition(name, addr);
}
bool Detector::hasRegisterDefinition(const std::string &name) const {
return pimpl->hasRegisterDefinition(name);
}
bool Detector::hasRegisterDefinition(RegisterAddress addr) const {
return pimpl->hasRegisterDefinition(addr);
}
RegisterAddress
Detector::getRegisterDefinitionAddress(const std::string &name) const {
return pimpl->getRegisterDefinitionAddress(name);
}
std::string Detector::getRegisterDefinitionName(RegisterAddress addr) const {
return pimpl->getRegisterDefinitionName(addr);
}
void Detector::clearRegisterDefinitions() { pimpl->clearRegisterDefinitions(); }
void Detector::setRegisterDefinitions(
const std::map<std::string, RegisterAddress> &list) {
pimpl->setRegisterDefinitions(list);
}
std::map<std::string, RegisterAddress>
Detector::getRegisterDefinitions() const {
return pimpl->getRegisterDefinitions();
}
int Detector::getBitDefinitionsCount() const {
return pimpl->getBitDefinitionsCount();
}
void Detector::setBitDefinition(const std::string &name, BitAddress addr) {
pimpl->setBitDefinition(name, addr);
}
bool Detector::hasBitDefinition(const std::string &name) const {
return pimpl->hasBitDefinition(name);
}
bool Detector::hasBitDefinition(BitAddress addr) const {
return pimpl->hasBitDefinition(addr);
}
BitAddress Detector::getBitDefinitionAddress(const std::string &name) const {
return pimpl->getBitDefinitionAddress(name);
}
std::string Detector::getBitDefinitionName(BitAddress addr) const {
return pimpl->getBitDefinitionName(addr);
}
void Detector::clearBitDefinitions() { pimpl->clearBitDefinitions(); }
void Detector::setBitDefinitions(
const std::map<std::string, BitAddress> &list) {
pimpl->setBitDefinitions(list);
}
std::map<std::string, BitAddress> Detector::getBitDefinitions() const {
return pimpl->getBitDefinitions();
}
// Xilinx Ctb Specific
void Detector::configureTransceiver(Positions pos) {
@@ -2782,26 +2785,78 @@ void Detector::setUpdateMode(const bool updatemode, Positions pos) {
}
}
Result<RegisterValue> Detector::readRegister(RegisterAddress addr,
Positions pos) const {
return pimpl->readRegister(addr, pos);
}
void Detector::writeRegister(RegisterAddress addr, RegisterValue val,
bool validate, Positions pos) {
pimpl->writeRegister(addr, val, validate, pos);
}
void Detector::setBit(BitAddress addr, bool validate, Positions pos) {
pimpl->setBit(addr, validate, pos);
}
void Detector::clearBit(BitAddress addr, bool validate, Positions pos) {
pimpl->clearBit(addr, validate, pos);
}
Result<int> Detector::getBit(BitAddress addr, Positions pos) const {
return pimpl->getBit(addr, pos);
}
Result<RegisterValue> Detector::readRegister(const std::string &reg_name,
Positions pos) const {
return pimpl->readRegister(reg_name, pos);
}
void Detector::writeRegister(const std::string &reg_name, RegisterValue val,
bool validate, Positions pos) {
pimpl->writeRegister(reg_name, val, validate, pos);
}
void Detector::setBit(const std::string &bit_name, bool validate,
Positions pos) {
pimpl->setBit(bit_name, validate, pos);
}
void Detector::clearBit(const std::string &bit_name, bool validate,
Positions pos) {
pimpl->clearBit(bit_name, validate, pos);
}
Result<int> Detector::getBit(const std::string &bit_name, Positions pos) const {
return pimpl->getBit(bit_name, pos);
}
Result<uint32_t> Detector::readRegister(uint32_t addr, Positions pos) const {
return pimpl->Parallel(&Module::readRegister, pos, addr);
auto t = pimpl->readRegister(RegisterAddress(addr), pos);
Result<uint32_t> res;
for (const auto &val : t) {
res.push_back(val.value());
}
return res;
}
void Detector::writeRegister(uint32_t addr, uint32_t val, bool validate,
Positions pos) {
pimpl->Parallel(&Module::writeRegister, pos, addr, val, validate);
pimpl->writeRegister(RegisterAddress(addr), RegisterValue(val), validate,
pos);
}
void Detector::setBit(uint32_t addr, int bitnr, bool validate, Positions pos) {
pimpl->Parallel(&Module::setBit, pos, addr, bitnr, validate);
pimpl->setBit(BitAddress(RegisterAddress(addr), bitnr), validate, pos);
}
void Detector::clearBit(uint32_t addr, int bitnr, bool validate,
Positions pos) {
pimpl->Parallel(&Module::clearBit, pos, addr, bitnr, validate);
pimpl->clearBit(BitAddress(RegisterAddress(addr), bitnr), validate, pos);
}
Result<int> Detector::getBit(uint32_t addr, int bitnr, Positions pos) {
return pimpl->Parallel(&Module::getBit, pos, addr, bitnr);
Result<int> Detector::getBit(uint32_t addr, int bitnr, Positions pos) const {
return pimpl->getBit(BitAddress(RegisterAddress(addr), bitnr), pos);
}
void Detector::executeFirmwareTest(Positions pos) {

View File

@@ -80,10 +80,10 @@ void DetectorImpl::initSharedMemory() {
}
if (ctb_shm.exists()) {
ctb_shm.openSharedMemory(true);
if (ctb_shm()->shmversion != CTB_SHMVERSION) {
if (ctb_shm()->shmversion != CtbConfig::SHM_VERSION) {
LOG(logERROR)
<< "CTB shared memory version mismatch (expected 0x"
<< std::hex << CTB_SHMVERSION << " but got 0x"
<< std::hex << CtbConfig::SHM_VERSION << " but got 0x"
<< ctb_shm()->shmversion << std::dec
<< ". Free Shared memory to continue.";
ctb_shm.unmapSharedMemory();
@@ -1935,86 +1935,314 @@ void DetectorImpl::setBadChannels(const std::vector<int> list, Positions pos) {
}
std::vector<std::string> DetectorImpl::getCtbDacNames() const {
if (!isChipTestBoard())
throw RuntimeError("Named DACs only for CTB");
return ctb_shm()->getDacNames();
}
void DetectorImpl::setCtbDacNames(const std::vector<std::string> &names) {
if (!isChipTestBoard())
throw RuntimeError("Named DACs only for CTB");
ctb_shm()->setDacNames(names);
}
std::string DetectorImpl::getCtbDacName(defs::dacIndex i) const {
if (!isChipTestBoard())
throw RuntimeError("Named DACs only for CTB");
return ctb_shm()->getDacName(static_cast<int>(i));
}
void DetectorImpl::setCtbDacName(const defs::dacIndex index,
const std::string &name) {
if (!isChipTestBoard())
throw RuntimeError("Named DACs only for CTB");
ctb_shm()->setDacName(index, name);
}
std::vector<std::string> DetectorImpl::getCtbAdcNames() const {
if (!isChipTestBoard())
throw RuntimeError("Named ADCs only for CTB");
return ctb_shm()->getAdcNames();
}
void DetectorImpl::setCtbAdcNames(const std::vector<std::string> &names) {
if (!isChipTestBoard())
throw RuntimeError("Named ADCs only for CTB");
ctb_shm()->setAdcNames(names);
}
std::string DetectorImpl::getCtbAdcName(const int i) const {
if (!isChipTestBoard())
throw RuntimeError("Named ADCs only for CTB");
return ctb_shm()->getAdcName(i);
}
void DetectorImpl::setCtbAdcName(const int index, const std::string &name) {
if (!isChipTestBoard())
throw RuntimeError("Named ADCs only for CTB");
ctb_shm()->setAdcName(index, name);
}
std::vector<std::string> DetectorImpl::getCtbSignalNames() const {
if (!isChipTestBoard())
throw RuntimeError("Named signals only for CTB");
return ctb_shm()->getSignalNames();
}
void DetectorImpl::setCtbSignalNames(const std::vector<std::string> &names) {
if (!isChipTestBoard())
throw RuntimeError("Named signals only for CTB");
ctb_shm()->setSignalNames(names);
}
std::string DetectorImpl::getCtbSignalName(const int i) const {
if (!isChipTestBoard())
throw RuntimeError("Named signals only for CTB");
return ctb_shm()->getSignalName(i);
}
void DetectorImpl::setCtbSignalName(const int index, const std::string &name) {
if (!isChipTestBoard())
throw RuntimeError("Named signals only for CTB");
ctb_shm()->setSignalName(index, name);
}
std::vector<std::string> DetectorImpl::getCtbPowerNames() const {
if (!isChipTestBoard())
throw RuntimeError("Named Powers only for CTB");
return ctb_shm()->getPowerNames();
}
void DetectorImpl::setCtbPowerNames(const std::vector<std::string> &names) {
if (!isChipTestBoard())
throw RuntimeError("Named Powers only for CTB");
ctb_shm()->setPowerNames(names);
}
std::string DetectorImpl::getCtbPowerName(const defs::dacIndex i) const {
if (!isChipTestBoard())
throw RuntimeError("Named Powers only for CTB");
return ctb_shm()->getPowerName(static_cast<int>(i - defs::V_POWER_A));
}
void DetectorImpl::setCtbPowerName(const defs::dacIndex index,
const std::string &name) {
if (!isChipTestBoard())
throw RuntimeError("Named Powers only for CTB");
ctb_shm()->setPowerName(static_cast<int>(index - defs::V_POWER_A), name);
}
std::vector<std::string> DetectorImpl::getCtbSlowADCNames() const {
if (!isChipTestBoard())
throw RuntimeError("Named Slow ADCs only for CTB");
return ctb_shm()->getSlowADCNames();
}
void DetectorImpl::setCtbSlowADCNames(const std::vector<std::string> &names) {
if (!isChipTestBoard())
throw RuntimeError("Named Slow ADCs only for CTB");
ctb_shm()->setSlowADCNames(names);
}
std::string DetectorImpl::getCtbSlowADCName(const defs::dacIndex i) const {
if (!isChipTestBoard())
throw RuntimeError("Named Slow ADCs only for CTB");
return ctb_shm()->getSlowADCName(static_cast<int>(i - defs::SLOW_ADC0));
}
void DetectorImpl::setCtbSlowADCName(const defs::dacIndex index,
const std::string &name) {
if (!isChipTestBoard())
throw RuntimeError("Named Slow ADCs only for CTB");
ctb_shm()->setSlowADCName(static_cast<int>(index - defs::SLOW_ADC0), name);
}
int DetectorImpl::getRegisterDefinitionsCount() const {
if (!isChipTestBoard())
throw RuntimeError("Register Definitions only for CTB");
return ctb_shm()->getRegisterNamesCount();
}
void DetectorImpl::setRegisterDefinition(const std::string &name,
RegisterAddress addr) {
if (!isChipTestBoard())
throw RuntimeError("Register Definitions only for CTB");
ctb_shm()->setRegisterName(name, addr);
}
bool DetectorImpl::hasRegisterDefinition(const std::string &name) const {
if (!isChipTestBoard())
throw RuntimeError("Register Definitions only for CTB");
return ctb_shm()->hasRegisterName(name);
}
bool DetectorImpl::hasRegisterDefinition(RegisterAddress addr) const {
if (!isChipTestBoard())
throw RuntimeError("Register Definitions only for CTB");
return ctb_shm()->hasRegisterAddress(addr);
}
RegisterAddress
DetectorImpl::getRegisterDefinitionAddress(const std::string &name) const {
if (!isChipTestBoard())
throw RuntimeError("Register Definitions only for CTB");
return ctb_shm()->getRegisterAddress(name);
}
std::string
DetectorImpl::getRegisterDefinitionName(RegisterAddress addr) const {
if (!isChipTestBoard())
throw RuntimeError("Register Definitions only for CTB");
return ctb_shm()->getRegisterName(addr);
}
void DetectorImpl::clearRegisterDefinitions() {
if (!isChipTestBoard())
throw RuntimeError("Register Definitions only for CTB");
ctb_shm()->clearRegisterNames();
}
void DetectorImpl::setRegisterDefinitions(
const std::map<std::string, RegisterAddress> &list) {
if (!isChipTestBoard())
throw RuntimeError("Register Definitions only for CTB");
ctb_shm()->setRegisterNames(list);
}
std::map<std::string, RegisterAddress>
DetectorImpl::getRegisterDefinitions() const {
if (!isChipTestBoard())
throw RuntimeError("Register Definitions only for CTB");
return ctb_shm()->getRegisterNames();
}
int DetectorImpl::getBitDefinitionsCount() const {
if (!isChipTestBoard())
throw RuntimeError("Bit Definitions only for CTB");
return ctb_shm()->getBitNamesCount();
}
void DetectorImpl::setBitDefinition(const std::string &name,
BitAddress bitPos) {
if (!isChipTestBoard())
throw RuntimeError("Bit Definitions only for CTB");
ctb_shm()->setBitName(name, bitPos);
}
bool DetectorImpl::hasBitDefinition(const std::string &name) const {
if (!isChipTestBoard())
throw RuntimeError("Bit Definitions only for CTB");
return ctb_shm()->hasBitName(name);
}
bool DetectorImpl::hasBitDefinition(BitAddress bitPos) const {
if (!isChipTestBoard())
throw RuntimeError("Bit Definitions only for CTB");
return ctb_shm()->hasBitAddress(bitPos);
}
BitAddress
DetectorImpl::getBitDefinitionAddress(const std::string &name) const {
if (!isChipTestBoard())
throw RuntimeError("Bit Definitions only for CTB");
return ctb_shm()->getBitAddress(name);
}
std::string DetectorImpl::getBitDefinitionName(BitAddress bitPos) const {
if (!isChipTestBoard())
throw RuntimeError("Bit Definitions only for CTB");
return ctb_shm()->getBitName(bitPos);
}
void DetectorImpl::clearBitDefinitions() {
if (!isChipTestBoard())
throw RuntimeError("Bit Definitions only for CTB");
ctb_shm()->clearBitNames();
}
void DetectorImpl::setBitDefinitions(
const std::map<std::string, BitAddress> &list) {
if (!isChipTestBoard())
throw RuntimeError("Bit Definitions only for CTB");
ctb_shm()->setBitNames(list);
}
std::map<std::string, BitAddress> DetectorImpl::getBitDefinitions() const {
if (!isChipTestBoard())
throw RuntimeError("Bit Definitions only for CTB");
return ctb_shm()->getBitNames();
}
Result<RegisterValue> DetectorImpl::readRegister(const std::string &reg_name,
Positions pos) const {
if (!isChipTestBoard()) {
throw RuntimeError("Register Definitions only for CTB. Use hard coded "
"values instead.");
}
auto addr = getRegisterDefinitionAddress(reg_name);
return readRegister(addr, pos);
}
void DetectorImpl::writeRegister(const std::string &reg_name, RegisterValue val,
bool validate, Positions pos) {
if (!isChipTestBoard()) {
throw RuntimeError("Register Definitions only for CTB. Use hard coded "
"values instead.");
}
auto addr = getRegisterDefinitionAddress(reg_name);
writeRegister(addr, val, validate, pos);
}
void DetectorImpl::setBit(const std::string &bit_name, bool validate,
Positions pos) {
if (!isChipTestBoard()) {
throw RuntimeError(
"Bit Definitions only for CTB. Use hard coded values instead.");
}
auto addr = getBitDefinitionAddress(bit_name);
setBit(addr, validate, pos);
}
void DetectorImpl::clearBit(const std::string &bit_name, bool validate,
Positions pos) {
if (!isChipTestBoard()) {
throw RuntimeError(
"Bit Definitions only for CTB. Use hard coded values instead.");
}
auto addr = getBitDefinitionAddress(bit_name);
clearBit(addr, validate, pos);
}
Result<int> DetectorImpl::getBit(const std::string &bit_name,
Positions pos) const {
if (!isChipTestBoard()) {
throw RuntimeError(
"Bit Definitions only for CTB. Use hard coded values instead.");
}
auto addr = getBitDefinitionAddress(bit_name);
return getBit(addr, pos);
}
Result<RegisterValue> DetectorImpl::readRegister(RegisterAddress addr,
Positions pos) const {
return Parallel(&Module::readRegister, pos, addr);
}
void DetectorImpl::writeRegister(RegisterAddress addr, RegisterValue val,
bool validate, Positions pos) {
Parallel(&Module::writeRegister, pos, addr, val, validate);
}
void DetectorImpl::setBit(BitAddress addr, bool validate, Positions pos) {
Parallel(&Module::setBit, pos, addr, validate);
}
void DetectorImpl::clearBit(BitAddress addr, bool validate, Positions pos) {
Parallel(&Module::clearBit, pos, addr, validate);
}
Result<int> DetectorImpl::getBit(BitAddress addr, Positions pos) const {
return Parallel(&Module::getBit, pos, addr);
}
} // namespace sls

View File

@@ -183,6 +183,11 @@ class DetectorImpl : public virtual slsDetectorDefs {
bool isAllPositions(Positions pos) const;
inline bool isChipTestBoard() const {
return (shm()->detType == defs::CHIPTESTBOARD ||
shm()->detType == defs::XILINX_CHIPTESTBOARD);
}
/** set acquiring flag in shared memory */
void setAcquiringFlag(bool flag);
@@ -328,6 +333,42 @@ class DetectorImpl : public virtual slsDetectorDefs {
void setCtbSlowADCNames(const std::vector<std::string> &names);
void setCtbSlowADCName(const defs::dacIndex index, const std::string &name);
int getRegisterDefinitionsCount() const;
void setRegisterDefinition(const std::string &name, RegisterAddress addr);
bool hasRegisterDefinition(const std::string &name) const;
bool hasRegisterDefinition(RegisterAddress addr) const;
RegisterAddress getRegisterDefinitionAddress(const std::string &name) const;
std::string getRegisterDefinitionName(RegisterAddress addr) const;
void clearRegisterDefinitions();
void
setRegisterDefinitions(const std::map<std::string, RegisterAddress> &list);
std::map<std::string, RegisterAddress> getRegisterDefinitions() const;
int getBitDefinitionsCount() const;
void setBitDefinition(const std::string &name, BitAddress bitPos);
bool hasBitDefinition(const std::string &name) const;
bool hasBitDefinition(BitAddress bitPos) const;
BitAddress getBitDefinitionAddress(const std::string &name) const;
std::string getBitDefinitionName(BitAddress bitPos) const;
void clearBitDefinitions();
void setBitDefinitions(const std::map<std::string, BitAddress> &list);
std::map<std::string, BitAddress> getBitDefinitions() const;
Result<RegisterValue> readRegister(const std::string &reg_name,
Positions pos) const;
void writeRegister(const std::string &reg_name, RegisterValue val,
bool validate, Positions pos);
void setBit(const std::string &bit_name, bool validate, Positions pos);
void clearBit(const std::string &bit_name, bool validate, Positions pos);
Result<int> getBit(const std::string &bit_name, Positions pos) const;
Result<RegisterValue> readRegister(RegisterAddress addr,
Positions pos = {}) const;
void writeRegister(RegisterAddress addr, RegisterValue val,
bool validate = false, Positions pos = {});
void setBit(BitAddress addr, bool validate = false, Positions pos = {});
void clearBit(BitAddress addr, bool validate = false, Positions pos = {});
Result<int> getBit(BitAddress addr, Positions pos = {}) const;
private:
/**
* Creates/open shared memory, initializes detector structure and members

View File

@@ -2568,17 +2568,16 @@ std::vector<int> Module::getReceiverDbitList() const {
void Module::setReceiverDbitList(std::vector<int> list) {
LOG(logDEBUG1) << "Setting Receiver Dbit List";
if (list.size() > 64) {
throw RuntimeError("Dbit list size cannot be greater than 64\n");
}
for (auto &it : list) {
if (it < 0 || it > 63) {
throw RuntimeError("Dbit list value must be between 0 and 63\n");
}
}
std::sort(begin(list), end(list));
auto last = std::unique(begin(list), end(list));
list.erase(last, list.end());
auto r = stableRemoveDuplicates(list);
if (r) {
LOG(logWARNING) << "Removed duplicated from receiver dbit list";
}
StaticVector<int, MAX_RX_DBIT> arg = list;
sendToReceiver(F_SET_RECEIVER_DBIT_LIST, arg, nullptr);
@@ -2916,29 +2915,30 @@ void Module::setUpdateMode(const bool updatemode) {
<< "): Update Mode set to " << updatemode << "!";
}
uint32_t Module::readRegister(uint32_t addr) const {
return sendToDetectorStop<uint32_t>(F_READ_REGISTER, addr);
RegisterValue Module::readRegister(RegisterAddress addr) const {
return sendToDetectorStop<RegisterValue>(F_READ_REGISTER, addr.value());
}
void Module::writeRegister(uint32_t addr, uint32_t val, bool validate) {
uint32_t args[]{addr, val, static_cast<uint32_t>(validate)};
void Module::writeRegister(RegisterAddress addr, RegisterValue val,
bool validate) {
uint32_t args[]{addr.value(), val.value(), static_cast<uint32_t>(validate)};
return sendToDetectorStop(F_WRITE_REGISTER, args, nullptr);
}
void Module::setBit(uint32_t addr, int n, bool validate) {
uint32_t args[] = {addr, static_cast<uint32_t>(n),
void Module::setBit(BitAddress bitAddr, bool validate) {
uint32_t args[] = {bitAddr.address().value(), bitAddr.bitPosition(),
static_cast<uint32_t>(validate)};
sendToDetectorStop(F_SET_BIT, args, nullptr);
}
void Module::clearBit(uint32_t addr, int n, bool validate) {
uint32_t args[] = {addr, static_cast<uint32_t>(n),
void Module::clearBit(BitAddress bitAddr, bool validate) {
uint32_t args[] = {bitAddr.address().value(), bitAddr.bitPosition(),
static_cast<uint32_t>(validate)};
sendToDetectorStop(F_CLEAR_BIT, args, nullptr);
}
int Module::getBit(uint32_t addr, int n) {
uint32_t args[2] = {addr, static_cast<uint32_t>(n)};
int Module::getBit(BitAddress bitAddr) const {
uint32_t args[2] = {bitAddr.address().value(), bitAddr.bitPosition()};
return sendToDetectorStop<int>(F_GET_BIT, args);
}

View File

@@ -5,6 +5,7 @@
#include "sls/ClientSocket.h"
#include "sls/Pattern.h"
#include "sls/StaticVector.h"
#include "sls/bit_utils.h"
#include "sls/logger.h"
#include "sls/network_utils.h"
#include "sls/sls_detector_defs.h"
@@ -579,11 +580,11 @@ class Module : public virtual slsDetectorDefs {
void rebootController();
bool getUpdateMode() const;
void setUpdateMode(const bool updatemode);
uint32_t readRegister(uint32_t addr) const;
void writeRegister(uint32_t addr, uint32_t val, bool validate);
void setBit(uint32_t addr, int n, bool validate);
void clearBit(uint32_t addr, int n, bool validate);
int getBit(uint32_t addr, int n);
RegisterValue readRegister(RegisterAddress addr) const;
void writeRegister(RegisterAddress addr, RegisterValue val, bool validate);
void setBit(BitAddress bitAddr, bool validate);
void clearBit(BitAddress bitAddr, bool validate);
int getBit(BitAddress bitAddr) const;
void executeFirmwareTest();
void executeBusTest();
void writeAdcRegister(uint32_t addr, uint32_t val);

View File

@@ -28,25 +28,26 @@
// ********************** Defines for shared memory. **********************
// WARNING! before chaning these search the codebase for their usage!
// date when IsValid boolean introduced into every shm structure
// (to look out for shm that still exists due to other mapped resources)
#define SHM_IS_VALID_CHECK_VERSION 0x250820
//Max shared memory name length in macOS is 31 characters
// Max shared memory name length in macOS is 31 characters
#ifdef __APPLE__
#define SHM_DETECTOR_PREFIX "/sls_"
#define SHM_MODULE_PREFIX "_mod_"
#define SHM_DETECTOR_PREFIX "/sls_"
#define SHM_MODULE_PREFIX "_mod_"
#else
#define SHM_DETECTOR_PREFIX "/slsDetectorPackage_detector_"
#define SHM_MODULE_PREFIX "_module_"
#define SHM_DETECTOR_PREFIX "/slsDetectorPackage_detector_"
#define SHM_MODULE_PREFIX "_module_"
#endif
#define SHM_ENV_NAME "SLSDETNAME"
#define SHM_ENV_NAME "SLSDETNAME"
// ************************************************************************
namespace sls {
class CtbConfig;
template <typename T, typename U> constexpr bool is_type() {
return std::is_same_v<std::decay_t<U>, T>;
}
@@ -94,17 +95,16 @@ template <typename T> class SharedMemory {
unmapSharedMemory();
}
/** memory is valid if it has the IsValid flag and is true */
bool memoryHasValidFlag() const {
if (shared_struct == nullptr) {
throw SharedMemoryError(
"Shared memory not mapped. Cannot check validity.");
}
// CtbConfig did not have shmversion before, so exact value check
if constexpr (is_type<CtbConfig, T>()) {
if (shared_struct->shmversion == SHM_IS_VALID_CHECK_VERSION) {
return true;
}
} else if (shared_struct->shmversion >= SHM_IS_VALID_CHECK_VERSION) {
// CtbConfig also works (shmversion didnt exist prior, but it would read
// "20" = length size) so shmversion should always be >= isValid
// introduced date (0x250820)
if (shared_struct->shmversion >= SHM_IS_VALID_CHECK_VERSION) {
return true;
}
return false;
@@ -279,11 +279,12 @@ template <typename T> class SharedMemory {
throw SharedMemoryError(msg);
}
#ifdef __APPLE__
// On macOS, fstat returns the allocated size and not the requested size.
// This means we can't check for size since we always get for example 16384 bytes.
#ifdef __APPLE__
// On macOS, fstat returns the allocated size and not the requested
// size. This means we can't check for size since we always get for
// example 16384 bytes.
return;
#endif
#endif
auto actual_size = static_cast<size_t>(sb.st_size);
auto expected_size = sizeof(T);
if (actual_size != expected_size) {

View File

@@ -400,6 +400,10 @@ int InferAction::chipversion() {
int InferAction::clearbit() {
if (args.size() == 1) {
return slsDetectorDefs::PUT_ACTION;
}
if (args.size() == 2) {
return slsDetectorDefs::PUT_ACTION;
}
@@ -788,6 +792,66 @@ int InferAction::defaultpattern() {
}
}
int InferAction::define_bit() {
if (args.size() == 1) {
return slsDetectorDefs::GET_ACTION;
}
if (args.size() == 2) {
return slsDetectorDefs::GET_ACTION;
}
if (args.size() == 3) {
return slsDetectorDefs::PUT_ACTION;
}
else {
throw RuntimeError("Could not infer action: Wrong number of arguments");
}
}
int InferAction::define_reg() {
if (args.size() == 1) {
return slsDetectorDefs::GET_ACTION;
}
if (args.size() == 2) {
return slsDetectorDefs::PUT_ACTION;
}
else {
throw RuntimeError("Could not infer action: Wrong number of arguments");
}
}
int InferAction::definelist_bit() {
if (args.size() == 0) {
return slsDetectorDefs::GET_ACTION;
}
else {
throw RuntimeError("Could not infer action: Wrong number of arguments");
}
}
int InferAction::definelist_reg() {
if (args.size() == 0) {
return slsDetectorDefs::GET_ACTION;
}
else {
throw RuntimeError("Could not infer action: Wrong number of arguments");
}
}
int InferAction::delay() {
if (args.size() == 0) {
@@ -1498,6 +1562,10 @@ int InferAction::gates() {
int InferAction::getbit() {
if (args.size() == 1) {
return slsDetectorDefs::GET_ACTION;
}
if (args.size() == 2) {
return slsDetectorDefs::GET_ACTION;
}
@@ -3055,6 +3123,10 @@ int InferAction::serialnumber() {
int InferAction::setbit() {
if (args.size() == 1) {
return slsDetectorDefs::PUT_ACTION;
}
if (args.size() == 2) {
return slsDetectorDefs::PUT_ACTION;
}

View File

@@ -62,6 +62,10 @@ class InferAction {
int dbitpipeline();
int defaultdac();
int defaultpattern();
int define_bit();
int define_reg();
int definelist_bit();
int definelist_reg();
int delay();
int delayl();
int detectorserverversion();
@@ -394,6 +398,10 @@ class InferAction {
{"dbitpipeline", &InferAction::dbitpipeline},
{"defaultdac", &InferAction::defaultdac},
{"defaultpattern", &InferAction::defaultpattern},
{"define_bit", &InferAction::define_bit},
{"define_reg", &InferAction::define_reg},
{"definelist_bit", &InferAction::definelist_bit},
{"definelist_reg", &InferAction::definelist_reg},
{"delay", &InferAction::delay},
{"delayl", &InferAction::delayl},
{"detectorserverversion", &InferAction::detectorserverversion},

View File

@@ -1330,4 +1330,367 @@ TEST_CASE("led", "[.cmdcall]") {
}
}
TEST_CASE("define_reg", "[.cmdcall][.definecmds]") {
Detector det;
Caller caller(&det);
auto det_type = det.getDetectorType().squash();
if (det_type == defs::CHIPTESTBOARD ||
det_type == defs::XILINX_CHIPTESTBOARD) {
auto prev_reg_defines = det.getRegisterDefinitions();
auto prev_bit_defines = det.getBitDefinitions();
det.clearRegisterDefinitions();
det.clearBitDefinitions();
{
// invalid puts
// missing arg
REQUIRE_THROWS(caller.call("define_reg", {}, -1, GET));
// missing arg
REQUIRE_THROWS(caller.call("define_reg", {"TEST_REG"}, -1, PUT));
// invalid module id
REQUIRE_THROWS(
caller.call("define_reg", {"TEST_REG", "0x201"}, 0, PUT));
// valid put
REQUIRE_NOTHROW(
caller.call("define_reg", {"TEST_REG", "0x200"}, -1, PUT));
// modify reg
REQUIRE_NOTHROW(
caller.call("define_reg", {"TEST_REG", "0x201"}, -1, PUT));
REQUIRE_NOTHROW(
caller.call("define_reg", {"TEST_REG2", "0x202"}, -1, PUT));
// invalid puts
// existing reg addr
REQUIRE_THROWS(
caller.call("define_reg", {"TEST_REG3", "0x201"}, -1, PUT));
// valid gets
{
// get by name
std::ostringstream oss;
REQUIRE_NOTHROW(
caller.call("define_reg", {"TEST_REG"}, -1, GET, oss));
REQUIRE(oss.str() == "define_reg 0x201\n");
}
{
// get by addr
std::ostringstream oss;
REQUIRE_NOTHROW(
caller.call("define_reg", {"0x201"}, -1, GET, oss));
REQUIRE(oss.str() == "define_reg TEST_REG\n");
}
// invalid gets
// doesnt exist
REQUIRE_THROWS(caller.call("define_reg", {"TEST_REG3"}, -1, GET));
REQUIRE_THROWS(caller.call("define_reg", {"0x203"}, -1, GET));
// ensure correct exception message
try {
caller.call("define_reg", {"0x203"}, -1, GET);
} catch (const std::exception &e) {
REQUIRE(std::string(e.what()) ==
"No register definition found for address: 0x203");
}
}
det.clearRegisterDefinitions();
det.clearBitDefinitions();
det.setRegisterDefinitions(prev_reg_defines);
det.setBitDefinitions(prev_bit_defines);
} else {
REQUIRE_THROWS(
caller.call("define_reg", {"TEST_REG", "0x200"}, -1, PUT));
REQUIRE_THROWS(caller.call("define_reg", {"TEST_REG"}, -1, GET));
}
}
TEST_CASE("define_bit", "[.cmdcall][.definecmds]") {
Detector det;
Caller caller(&det);
auto det_type = det.getDetectorType().squash();
if (det_type == defs::CHIPTESTBOARD ||
det_type == defs::XILINX_CHIPTESTBOARD) {
auto prev_reg_defines = det.getRegisterDefinitions();
auto prev_bit_defines = det.getBitDefinitions();
det.clearRegisterDefinitions();
det.clearBitDefinitions();
det.setRegisterDefinition("TEST_REG", RegisterAddress(0x201));
det.setRegisterDefinition("TEST_REG2", RegisterAddress(0x202));
{
// invalid puts
// skipped register
REQUIRE_THROWS(
caller.call("define_bit", {"TEST_BIT", "1"}, -1, PUT));
// named register doesnt exist
REQUIRE_THROWS(caller.call(
"define_bit", {"TEST_BIT", "RANDOM_REG", "1"}, -1, PUT));
// invalid bit position
REQUIRE_THROWS(
caller.call("define", {"TEST_BIT", "TEST_REG", "32"}, -1, PUT));
// valid puts
REQUIRE_NOTHROW(caller.call(
"define_bit", {"TEST_BIT", "TEST_REG2", "1"}, -1, PUT));
// modify reg
REQUIRE_NOTHROW(caller.call(
"define_bit", {"TEST_BIT", "TEST_REG", "1"}, -1, PUT));
// modify position
REQUIRE_NOTHROW(caller.call(
"define_bit", {"TEST_BIT", "TEST_REG", "2"}, -1, PUT));
// another bit to same reg
REQUIRE_NOTHROW(caller.call(
"define_bit", {"TEST_BIT2", "TEST_REG", "4"}, -1, PUT));
// bit to a different reg
REQUIRE_NOTHROW(caller.call(
"define_bit", {"TEST_BIT3", "TEST_REG2", "3"}, -1, PUT));
// valid gets
{
// get by name
std::ostringstream oss;
REQUIRE_NOTHROW(
caller.call("define_bit", {"TEST_BIT"}, -1, GET, oss));
REQUIRE(oss.str() == "define_bit [TEST_REG, 2]\n");
}
{
// get by addr+pos name
std::ostringstream oss;
REQUIRE_NOTHROW(
caller.call("define_bit", {"TEST_REG", "2"}, -1, GET, oss));
REQUIRE(oss.str() == "define_bit TEST_BIT\n");
}
{
// get by addr val + pos
std::ostringstream oss;
REQUIRE_NOTHROW(
caller.call("define_bit", {"0x201", "2"}, -1, GET, oss));
REQUIRE(oss.str() == "define_bit TEST_BIT\n");
}
// invalid gets
// bit doesnt exist
REQUIRE_THROWS(
caller.call("define_bit", {"TEST_REG", "3"}, -1, GET));
// addr doesnt exist
REQUIRE_THROWS(
caller.call("define_bit", {"TEST_REG3", "2"}, -1, GET));
// ensure correct exception message
try {
caller.call("define_bit", {"TEST_REG", "3"}, -1, GET);
} catch (const std::exception &e) {
REQUIRE(std::string(e.what()) ==
"No bit definition found for bit position: [0x201, 3] "
"and addr = TEST_REG");
}
}
det.clearRegisterDefinitions();
det.clearBitDefinitions();
det.setRegisterDefinitions(prev_reg_defines);
det.setBitDefinitions(prev_bit_defines);
} else {
REQUIRE_THROWS(
caller.call("define_bit", {"TEST_BIT", "0x200", "2"}, -1, PUT));
REQUIRE_THROWS(caller.call("define_bit", {"0x200", "2"}, -1, GET));
}
}
TEST_CASE("using define for reg, setbit, getbit and clearbit",
"[.cmdcall][.definecmds]") {
Detector det;
Caller caller(&det);
auto det_type = det.getDetectorType().squash();
if (det_type == defs::CHIPTESTBOARD ||
det_type == defs::XILINX_CHIPTESTBOARD) {
if (det.isVirtualDetectorServer().tsquash(
"inconsistent virtual values")) {
auto prev_reg_defines = det.getRegisterDefinitions();
auto prev_bit_defines = det.getBitDefinitions();
det.clearRegisterDefinitions();
det.clearBitDefinitions();
det.setRegisterDefinition("TEST_REG", RegisterAddress(0x201));
det.setRegisterDefinition("TEST_REG2", RegisterAddress(0x202));
det.setBitDefinition("TEST_BIT",
BitAddress(RegisterAddress(0x201), 2));
det.setBitDefinition("TEST_BIT2",
BitAddress(RegisterAddress(0x201), 4));
det.setBitDefinition("TEST_BIT3",
BitAddress(RegisterAddress(0x202), 3));
auto prev_val_addr = det.readRegister(RegisterAddress(0x201));
auto prev_val_addr2 = det.readRegister(RegisterAddress(0x202));
// invalid puts
// doesnt exist addr
REQUIRE_THROWS(
caller.call("reg", {"RANDOM_REG", "0xf00"}, -1, PUT));
REQUIRE_THROWS(
caller.call("clearbit", {"RANDOM_REG", "TEST_BIT"}, -1, PUT));
REQUIRE_THROWS(
caller.call("setbit", {"RANDOM_REG", "TEST_BIT"}, -1, PUT));
REQUIRE_THROWS(
caller.call("getbit", {"RANDOM_REG", "TEST_BIT"}, -1, GET));
// using bit name for reg (only hardcoded values allowed)
REQUIRE_THROWS(
caller.call("reg", {"TEST_REG", "TEST_BIT"}, -1, PUT));
// using bit name and reg (only bit names or both reg and bit
// hardcoded allowed)
REQUIRE_THROWS(
caller.call("clearbit", {"TEST_REG", "TEST_BIT"}, -1, PUT));
REQUIRE_THROWS(
caller.call("setbit", {"TEST_REG", "TEST_BIT"}, -1, PUT));
REQUIRE_THROWS(
caller.call("getbit", {"TEST_REG", "TEST_BIT"}, -1, GET));
// valid puts and gets
{
// reg hard coded value of 0
std::ostringstream oss;
REQUIRE_NOTHROW(
caller.call("reg", {"TEST_REG", "0x0"}, -1, PUT));
REQUIRE_NOTHROW(caller.call("reg", {"TEST_REG"}, -1, GET, oss));
REQUIRE(oss.str() == "reg 0x0\n");
}
{
// reg hard coded value
std::ostringstream oss;
REQUIRE_NOTHROW(
caller.call("reg", {"TEST_REG", "0x10"}, -1, PUT));
REQUIRE_NOTHROW(caller.call("reg", {"TEST_REG"}, -1, GET, oss));
REQUIRE(oss.str() == "reg 0x10\n");
}
{
// set bit
std::ostringstream oss;
REQUIRE_NOTHROW(caller.call("setbit", {"TEST_BIT"}, -1, PUT));
REQUIRE_NOTHROW(
caller.call("setbit", {"TEST_REG", "2"}, -1, PUT));
REQUIRE_NOTHROW(caller.call("reg", {"TEST_REG"}, -1, GET, oss));
REQUIRE(oss.str() == "reg 0x14\n");
}
{
// get bit
std::ostringstream oss, oss2;
REQUIRE_NOTHROW(
caller.call("getbit", {"TEST_REG", "2"}, -1, GET, oss));
REQUIRE(oss.str() == "getbit 1\n");
REQUIRE_NOTHROW(
caller.call("getbit", {"TEST_BIT"}, -1, GET, oss2));
REQUIRE(oss2.str() == "getbit 1\n");
}
{
// clear bit
std::ostringstream oss;
REQUIRE_NOTHROW(caller.call("clearbit", {"TEST_BIT"}, -1, PUT));
REQUIRE_NOTHROW(
caller.call("clearbit", {"TEST_REG", "2"}, -1, PUT));
REQUIRE_NOTHROW(caller.call("reg", {"TEST_REG"}, -1, GET, oss));
REQUIRE(oss.str() == "reg 0x10\n");
}
for (int i = 0; i != det.size(); ++i) {
det.writeRegister(RegisterAddress(0x201),
RegisterValue(prev_val_addr[i]), false, {i});
det.writeRegister(RegisterAddress(0x202),
RegisterValue(prev_val_addr2[i]), false, {i});
}
det.clearRegisterDefinitions();
det.clearBitDefinitions();
det.setRegisterDefinitions(prev_reg_defines);
det.setBitDefinitions(prev_bit_defines);
}
} else {
REQUIRE_THROWS(caller.call("reg", {"TEST_REG", "0x200"}, -1, PUT));
REQUIRE_THROWS(caller.call("reg", {"TEST_REG"}, -1, GET));
}
}
TEST_CASE("definelist_reg", "[.cmdcall][.definecmds]") {
Detector det;
Caller caller(&det);
auto det_type = det.getDetectorType().squash();
if (det_type == defs::CHIPTESTBOARD ||
det_type == defs::XILINX_CHIPTESTBOARD) {
auto prev_reg_defines = det.getRegisterDefinitions();
det.clearRegisterDefinitions();
det.clearBitDefinitions();
det.setRegisterDefinition("TEST_REG", RegisterAddress(0x201));
det.setRegisterDefinition("TEST_REG2", RegisterAddress(0x202));
// invalid
// cannot put
REQUIRE_THROWS(
caller.call("definelist_reg", {"TEST_REG", "0x201"}, -1, PUT));
// too many args
REQUIRE_THROWS(caller.call("definelist_reg", {"TEST_MACRO"}, -1, GET));
// valid
REQUIRE_NOTHROW(caller.call("definelist_reg", {}, -1, GET));
det.clearRegisterDefinitions();
det.clearBitDefinitions();
det.setRegisterDefinitions(prev_reg_defines);
} else {
REQUIRE_THROWS(caller.call("definelist_reg", {}, -1, GET));
}
}
TEST_CASE("definelist_bit", "[.cmdcall][.definecmds]") {
Detector det;
Caller caller(&det);
auto det_type = det.getDetectorType().squash();
if (det_type == defs::CHIPTESTBOARD ||
det_type == defs::XILINX_CHIPTESTBOARD) {
auto prev_reg_defines = det.getRegisterDefinitions();
auto prev_bit_defines = det.getBitDefinitions();
det.clearRegisterDefinitions();
det.clearBitDefinitions();
det.setRegisterDefinition("TEST_REG", RegisterAddress(0x201));
det.setRegisterDefinition("TEST_REG2", RegisterAddress(0x202));
det.setBitDefinition("TEST_BIT", BitAddress(RegisterAddress(0x201), 2));
det.setBitDefinition("TEST_BIT2",
BitAddress(RegisterAddress(0x201), 4));
det.setBitDefinition("TEST_BIT3",
BitAddress(RegisterAddress(0x202), 3));
// invalid
// cannot put
REQUIRE_THROWS(
caller.call("definelist_bit", {"TEST_BIT", "0x201", "2"}, -1, PUT));
// too many args
REQUIRE_THROWS(caller.call("definelist_bit", {"TEST_BIT"}, -1, GET));
// valid
REQUIRE_NOTHROW(caller.call("definelist_bit", {}, -1, GET));
det.clearRegisterDefinitions();
det.clearBitDefinitions();
det.setRegisterDefinitions(prev_reg_defines);
det.setBitDefinitions(prev_bit_defines);
} else {
REQUIRE_THROWS(caller.call("definelist_bit", {}, -1, GET));
}
}
} // namespace sls

View File

@@ -3267,7 +3267,7 @@ TEST_CASE("update", "[.cmdcall]") {
}
}
TEST_CASE("reg", "[.cmdcall]") {
TEST_CASE("reg", "[.cmdcall][.definecmds]") {
Detector det;
Caller caller(&det);
auto det_type = det.getDetectorType().squash();
@@ -3284,14 +3284,14 @@ TEST_CASE("reg", "[.cmdcall]") {
{
std::ostringstream oss1, oss2;
caller.call("reg", {saddr, "0x6", "--validate"}, -1, PUT, oss1);
REQUIRE(oss1.str() == "reg [" + saddr + ", 0x6]\n");
REQUIRE(oss1.str() == "reg " + saddr + " 0x6\n");
caller.call("reg", {saddr}, -1, GET, oss2);
REQUIRE(oss2.str() == "reg 0x6\n");
}
{
std::ostringstream oss1, oss2;
caller.call("reg", {saddr, "0x5"}, -1, PUT, oss1);
REQUIRE(oss1.str() == "reg [" + saddr + ", 0x5]\n");
REQUIRE(oss1.str() == "reg " + saddr + " 0x5\n");
caller.call("reg", {saddr}, -1, GET, oss2);
REQUIRE(oss2.str() == "reg 0x5\n");
}
@@ -3326,7 +3326,7 @@ TEST_CASE("adcreg", "[.cmdcall]") {
}
}
TEST_CASE("setbit", "[.cmdcall]") {
TEST_CASE("setbit", "[.cmdcall][.definecmds]") {
Detector det;
Caller caller(&det);
auto det_type = det.getDetectorType().squash();
@@ -3356,7 +3356,7 @@ TEST_CASE("setbit", "[.cmdcall]") {
}
}
TEST_CASE("clearbit", "[.cmdcall]") {
TEST_CASE("clearbit", "[.cmdcall][.definecmds]") {
Detector det;
Caller caller(&det);
auto det_type = det.getDetectorType().squash();
@@ -3386,7 +3386,7 @@ TEST_CASE("clearbit", "[.cmdcall]") {
}
}
TEST_CASE("getbit", "[.cmdcall]") {
TEST_CASE("getbit", "[.cmdcall][.definecmds]") {
Detector det;
Caller caller(&det);
auto det_type = det.getDetectorType().squash();

View File

@@ -6,13 +6,16 @@
#include "CtbConfig.h"
#include "SharedMemory.h"
#include <fstream>
#include <set>
namespace sls {
TEST_CASE("Default construction") {
static_assert(sizeof(CtbConfig) ==
(2 * sizeof(int) + (18 + 32 + 64 + 5 + 8) * 20),
"Size of CtbConfig does not match ");
/*TODO static_assert(sizeof(CtbConfig) ==
(2 * sizeof(int) + (18 + 32 + 64 + 5 + 8) * 32) +
(sizeof(size_t) * 2) + ((sizeof(uint32_t) + 32) * 64) +
((32 + sizeof(uint32_t) + sizeof(int)) * 64), "Size of CtbConfig does not
match "); //8952 (8696)*/
CtbConfig c;
auto dacnames = c.getDacNames();
@@ -46,6 +49,16 @@ TEST_CASE("Default construction") {
REQUIRE(sensenames[1] == "SLOWADC1");
REQUIRE(sensenames[2] == "SLOWADC2");
REQUIRE(sensenames[3] == "SLOWADC3");
auto regisernames = c.getRegisterNames();
REQUIRE(regisernames.size() == 0);
auto bitnames = c.getBitNames();
REQUIRE(bitnames.size() == 0);
REQUIRE(c.getRegisterNamesCount() == 0);
auto registerNames = c.getRegisterNames();
REQUIRE(registerNames.size() == 0);
REQUIRE(c.getBitNamesCount() == 0);
auto bitNames = c.getBitNames();
REQUIRE(bitNames.size() == 0);
}
TEST_CASE("Set and get a single dac name") {
@@ -85,4 +98,164 @@ TEST_CASE("Move CtbConfig ") {
REQUIRE(c2.getDacName(3) == "yetanothername");
}
TEST_CASE("Add or modify a register name", "[.reg]") {
CtbConfig c;
auto addr = RegisterAddress(100);
auto addr1 = RegisterAddress(300);
REQUIRE(c.getRegisterNamesCount() == 0);
REQUIRE_THROWS(
c.setRegisterName("reg1_with_a_really_long_name_to_crash", addr));
// add an entry
REQUIRE_NOTHROW(c.setRegisterName("reg1", addr));
REQUIRE(c.getRegisterName(addr) == "reg1");
REQUIRE(c.getRegisterAddress("reg1") == addr);
REQUIRE(c.getRegisterNamesCount() == 1);
// modify an entry
REQUIRE_NOTHROW(c.setRegisterName("reg1", addr1));
REQUIRE(c.getRegisterAddress("reg1") == addr1);
REQUIRE(c.getRegisterName(addr1) == "reg1");
// clear all entries
REQUIRE_NOTHROW(c.clearRegisterNames());
REQUIRE(c.getRegisterNamesCount() == 0);
REQUIRE_THROWS(c.getRegisterName(addr));
REQUIRE_THROWS(c.getRegisterAddress("reg1"));
REQUIRE_THROWS(c.getRegisterName(addr1));
}
TEST_CASE("Add a register list", "[.reg]") {
CtbConfig c;
REQUIRE(c.getRegisterNamesCount() == 0);
// add a list
std::map<std::string, RegisterAddress> list = {
{"reg1", RegisterAddress(0x100)},
{"reg2", RegisterAddress(0x200)},
{"reg3", RegisterAddress(0x300)}};
REQUIRE_NOTHROW(c.setRegisterNames(list));
REQUIRE(c.getRegisterNamesCount() == static_cast<int>(list.size()));
auto names = c.getRegisterNames();
REQUIRE(names.size() == 3);
// TODO std::set<RegisterAddress> seen_values;
for (const auto &[key, val] : list) {
// check for duplicate keys, and key-value match
REQUIRE(names.count(key) == 1);
REQUIRE(names.at(key) == val);
// check for duplicate values
// TODO REQUIRE(seen_values.count(val) == 0);
// TODO seen_values.insert(val);
}
// clear all entries
REQUIRE_NOTHROW(c.clearRegisterNames());
REQUIRE(c.getRegisterNames().size() == 0);
}
TEST_CASE("Finding a regiser name or address", "[.reg]") {
CtbConfig c;
RegisterAddress addr1(0x100);
RegisterAddress addr2(0x200);
RegisterAddress addr3(0x300);
// find nothing
REQUIRE(c.getRegisterNamesCount() == 0);
REQUIRE_THROWS(c.getRegisterName(addr1));
REQUIRE_THROWS(c.getRegisterAddress("reg1"));
std::map<std::string, RegisterAddress> list = {
{"reg1", addr1}, {"reg2", addr2}, {"reg3", addr3}};
REQUIRE_NOTHROW(c.setRegisterNames(list));
// find
REQUIRE(c.getRegisterName(addr1) == "reg1");
REQUIRE(c.getRegisterName(addr2) == "reg2");
REQUIRE(c.getRegisterAddress("reg3") == addr3);
}
TEST_CASE("Add or modify a bit name", "[.reg]") {
CtbConfig c;
RegisterAddress addr(0x100);
BitAddress pos(addr, 2);
BitAddress pos1(addr, 5);
REQUIRE(c.getBitNamesCount() == 0);
REQUIRE_THROWS(c.setBitName("bit1_with_a_really_long_name_to_crash",
BitAddress(addr, 100)));
REQUIRE_THROWS(c.setBitName("bit1", BitAddress(addr, 32)));
REQUIRE_THROWS(c.setBitName("bit1", BitAddress(addr, -1)));
// add an entry
REQUIRE_NOTHROW(c.setBitName("bit1", pos));
REQUIRE(c.getBitName(pos) == "bit1");
REQUIRE(c.getBitAddress("bit1") == pos);
REQUIRE(c.getBitNamesCount() == 1);
// modify an entry
REQUIRE_NOTHROW(c.setBitName("bit1", pos1));
REQUIRE(c.getBitAddress("bit1") == pos1);
REQUIRE(c.getBitName(pos1) == "bit1");
// clear all entries
REQUIRE_NOTHROW(c.clearBitNames());
REQUIRE(c.getBitNamesCount() == 0);
REQUIRE_THROWS(c.getBitName(pos));
REQUIRE_THROWS(c.getBitAddress("bit1"));
REQUIRE_THROWS(c.getBitName(pos1));
}
TEST_CASE("Add a bit list", "[.reg]") {
CtbConfig c;
REQUIRE(c.getBitNamesCount() == 0);
RegisterAddress addr(0x100);
BitAddress pos1(addr, 2);
BitAddress pos2(addr, 21);
BitAddress pos3(addr, 31);
// add a list
std::map<std::string, BitAddress> list = {
{"bit1", pos1}, {"bit2", pos2}, {"bit3", pos3}};
REQUIRE_NOTHROW(c.setBitNames(list));
REQUIRE(c.getBitNamesCount() == 3);
auto names = c.getBitNames();
REQUIRE(names.size() == 3);
// TODO std::set<BitAddress> seen_values;
for (const auto &[key, val] : list) {
// check for duplicate keys, and key-value match
REQUIRE(names.count(key) == 1);
REQUIRE(names.at(key) == val);
// check for duplicate values
// TODO REQUIRE(seen_values.count(val) == 0);
// TODO seen_values.insert(val);
}
// clear all entries
REQUIRE_NOTHROW(c.clearBitNames());
REQUIRE(c.getBitNames().size() == 0);
}
TEST_CASE("Finding a bit value", "[.reg]") {
CtbConfig c;
RegisterAddress addr(0x100);
BitAddress pos(addr, 2);
BitAddress pos1(addr, 21);
BitAddress pos2(addr, 31);
// find nothing
REQUIRE(c.getBitNamesCount() == 0);
REQUIRE_THROWS(c.getBitAddress("bit"));
std::map<std::string, BitAddress> list = {
{"bit0", pos}, {"bit1", pos1}, {"bit2", pos2}};
REQUIRE_NOTHROW(c.setBitNames(list));
// find
REQUIRE(c.getBitAddress("bit2") == pos2);
REQUIRE(c.getBitName(pos1) == "bit1");
}
} // namespace sls

View File

@@ -39,15 +39,13 @@ void freeShm(const int dindex, const int mIndex) {
constexpr int shm_id = 10;
//macOS does not expose shm in the filesystem
// macOS does not expose shm in the filesystem
#ifndef __APPLE__
const std::string file_path =
std::string("/dev/shm/slsDetectorPackage_detector_") +
std::to_string(shm_id);
TEST_CASE("Free obsolete (without isValid)", "[detector][shm]") {
// ensure its clean to start
@@ -106,8 +104,8 @@ TEST_CASE("Create SharedMemory read and write", "[detector][shm]") {
const char *env_p = std::getenv(SHM_ENV_NAME);
std::string env_name = env_p ? ("_" + std::string(env_p)) : "";
CHECK(shm.getName() == std::string(SHM_DETECTOR_PREFIX) +
std::to_string(shm_id) + env_name);
CHECK(shm.getName() ==
std::string(SHM_DETECTOR_PREFIX) + std::to_string(shm_id) + env_name);
shm()->x = 3;
shm()->y = 5.7;
strcpy_safe(shm()->mess, "Some string");
@@ -180,8 +178,8 @@ TEST_CASE("Move SharedMemory", "[detector][shm]") {
std::string env_name = env_p ? ("_" + std::string(env_p)) : "";
SharedMemory<Data> shm(shm_id, -1);
CHECK(shm.getName() == std::string(SHM_DETECTOR_PREFIX) +
std::to_string(shm_id) + env_name);
CHECK(shm.getName() ==
std::string(SHM_DETECTOR_PREFIX) + std::to_string(shm_id) + env_name);
shm.createSharedMemory();
shm()->x = 9;
@@ -191,8 +189,8 @@ TEST_CASE("Move SharedMemory", "[detector][shm]") {
CHECK(shm2()->x == 9);
REQUIRE_THROWS(
shm()); // trying to access should throw instead of returning a nullptr
CHECK(shm2.getName() == std::string(SHM_DETECTOR_PREFIX) +
std::to_string(shm_id) + env_name);
CHECK(shm2.getName() ==
std::string(SHM_DETECTOR_PREFIX) + std::to_string(shm_id) + env_name);
shm2.removeSharedMemory();
}
@@ -243,7 +241,8 @@ TEST_CASE("Create create a shared memory with a tag when SLSDETNAME is set") {
setenv(SHM_ENV_NAME, "myprefix", 1);
SharedMemory<Data> shm(0, -1, "ctbdacs");
REQUIRE(shm.getName() == std::string(SHM_DETECTOR_PREFIX) + "0_myprefix_ctbdacs");
REQUIRE(shm.getName() ==
std::string(SHM_DETECTOR_PREFIX) + "0_myprefix_ctbdacs");
// Clean up after us
if (old_slsdetname.empty())

View File

@@ -49,7 +49,7 @@ target_link_libraries(slsReceiverObject
slsProjectOptions
slsSupportStatic
PRIVATE
slsProjectWarnings #don't propagate warnigns
slsProjectWarnings #don't propagate warnings
)
target_compile_definitions(slsReceiverObject
@@ -118,8 +118,6 @@ if (SLS_USE_RECEIVER_BINARIES)
target_link_libraries(slsReceiver PUBLIC
PUBLIC
slsReceiverStatic
pthread
rt
PRIVATE
slsProjectWarnings
)
@@ -138,8 +136,6 @@ if (SLS_USE_RECEIVER_BINARIES)
target_link_libraries(slsMultiReceiver
PUBLIC
slsReceiverStatic
pthread
rt
PRIVATE
slsProjectWarnings
)
@@ -158,8 +154,6 @@ if (SLS_USE_RECEIVER_BINARIES)
target_link_libraries(slsFrameSynchronizer
PUBLIC
slsReceiverStatic
pthread
rt
PRIVATE
slsProjectWarnings

View File

@@ -138,7 +138,8 @@ TEST_CASE("Parse version and help", "[detector]") {
}
}
TEST_CASE("Parse port and uid", "[detector]") {
// TODO: fails on gitea CI due to uid issue, fix later
TEST_CASE("Parse port and uid", "[.failsongitea][detector]") {
uid_t uid = getuid();
std::string uidStr = std::to_string(uid);
uid_t invalidUid = uid + 1000;
@@ -147,9 +148,12 @@ TEST_CASE("Parse port and uid", "[detector]") {
for (auto app : {AppType::SingleReceiver, AppType::MultiReceiver,
AppType::FrameSynchronizer}) {
CommandLineOptions s(app);
REQUIRE_THROWS(
s.parse({"", "-p", "1234", "-u", invalidUidStr})); // invalid uid
REQUIRE_THROWS(s.parse({"", "-p", "500"})); // invalid port
// TODO! This test fails on gitea CI probably because the user can set
// the uid commenting it out for now. Revisit later. REQUIRE_THROWS(
// s.parse({"", "-p", "1234", "-u", invalidUidStr})); // invalid uid
REQUIRE_THROWS(s.parse({"", "-p", "500"})); // invalid port
auto opts = s.parse({"", "-p", "1234", "-u", uidStr});
std::visit(

View File

@@ -64,7 +64,8 @@ class DataProcessorTest : public DataProcessor {
* num_transceiver_bytes = 2 both bytes have a value of 125
* num_digital_bytes is variable and is defined by number of samples
* default num sample is 5
* all bytes in digital data take a value of 255
* all bytes in digital data take a value of 0xFF (alternating bits between 0,
* 1)
*/
class DataProcessorTestFixture {
public:
@@ -106,7 +107,7 @@ class DataProcessorTestFixture {
num_random_offset_bytes);
}
void set_data() {
void set_data(const std::bitset<8> pattern = 0xFF) {
delete[] data;
uint64_t max_bytes_per_bit =
num_samples % 8 == 0 ? num_samples / 8 : num_samples / 8 + 1;
@@ -118,7 +119,8 @@ class DataProcessorTestFixture {
memset(data, dummy_value, num_analog_bytes); // set to dummy value
memset(data + num_analog_bytes, 0,
num_random_offset_bytes); // set to zero
memset(data + num_analog_bytes + num_random_offset_bytes, 0xFF,
memset(data + num_analog_bytes + num_random_offset_bytes,
static_cast<uint8_t>(pattern.to_ulong()),
num_digital_bytes); // all digital bits are one
memset(data + num_digital_bytes + num_analog_bytes +
num_random_offset_bytes,
@@ -170,7 +172,7 @@ TEST_CASE_METHOD(DataProcessorTestFixture, "Remove Trailing Bits",
TEST_CASE_METHOD(DataProcessorTestFixture, "Reorder all",
"[.dataprocessor][.reorder]") {
// parameters: num_samples, expected_num_digital_bytes,
// expected_digital_part
// expected_digital_part_for_each_bit
auto parameters = GENERATE(
std::make_tuple(5, 64, std::vector<uint8_t>{0b00011111}),
std::make_tuple(10, 2 * 64, std::vector<uint8_t>{0xFF, 0b00000011}),
@@ -264,11 +266,13 @@ TEST_CASE_METHOD(DataProcessorTestFixture, "Arrange bitlist with reorder false",
// expected_digital_part
auto parameters = GENERATE(
std::make_tuple(5, std::vector<int>{1, 4, 5}, 5,
std::vector<uint8_t>{0b00000111}),
std::vector<uint8_t>{0b00000010}),
std::make_tuple(5, std::vector<int>{1, 5, 4}, 5,
std::vector<uint8_t>{0b00000100}),
std::make_tuple(5, std::vector<int>{1, 5, 3, 7, 8, 50, 42, 60, 39}, 10,
std::vector<uint8_t>{0xFF, 0b00000001}),
std::vector<uint8_t>{0b11110000, 0b00000000}),
std::make_tuple(5, std::vector<int>{1, 5, 3, 7, 8, 50, 42, 60}, 5,
std::vector<uint8_t>{0xFF}));
std::vector<uint8_t>{0b11110000}));
size_t num_samples, expected_num_digital_bytes;
std::vector<uint8_t> expected_digital_part;
@@ -281,7 +285,7 @@ TEST_CASE_METHOD(DataProcessorTestFixture, "Arrange bitlist with reorder false",
generaldata->SetCtbDbitReorder(false);
set_num_samples(num_samples);
set_data();
set_data(0b01010101); // set digital data to 0x55 to have alternating bits
size_t expected_size =
num_analog_bytes + num_transceiver_bytes + expected_num_digital_bytes;
@@ -316,11 +320,15 @@ TEST_CASE_METHOD(DataProcessorTestFixture, "Arrange bitlist with reorder true",
// expected_digital_part
auto parameters = GENERATE(
std::make_tuple(5, std::vector<int>{1, 4, 5}, 3,
std::vector<uint8_t>{0b00011111}),
std::vector<uint8_t>{0x00, 0b00011111, 0x00}),
std::make_tuple(5, std::vector<int>{1, 5, 4}, 3,
std::vector<uint8_t>{0x00, 0x00, 0b00011111}),
std::make_tuple(10, std::vector<int>{1, 4, 5}, 6,
std::vector<uint8_t>{0xFF, 0b00000011}),
std::vector<uint8_t>{0x00, 0x00, 0b11111111, 0b00000011,
0x00, 0x00}),
std::make_tuple(8, std::vector<int>{1, 5, 3, 7, 8, 50, 42, 60, 39}, 9,
std::vector<uint8_t>{0xFF}));
std::vector<uint8_t>{0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF,
0xFF, 0xFF, 0x00}));
size_t num_samples, expected_num_digital_bytes;
std::vector<uint8_t> expected_digital_part;
@@ -333,7 +341,7 @@ TEST_CASE_METHOD(DataProcessorTestFixture, "Arrange bitlist with reorder true",
generaldata->SetCtbDbitReorder(true);
set_num_samples(num_samples);
set_data();
set_data(0b01010101);
size_t expected_size =
num_analog_bytes + num_transceiver_bytes + expected_num_digital_bytes;
@@ -343,11 +351,8 @@ TEST_CASE_METHOD(DataProcessorTestFixture, "Arrange bitlist with reorder true",
memset(expected_data, dummy_value, num_analog_bytes);
for (size_t sample = 0; sample < bitlist.size(); ++sample) {
memcpy(expected_data + num_analog_bytes +
expected_digital_part.size() * sample,
expected_digital_part.data(), expected_digital_part.size());
}
memcpy(expected_data + num_analog_bytes, expected_digital_part.data(),
expected_digital_part.size());
memset(expected_data + expected_num_digital_bytes + num_analog_bytes,
dummy_value, num_transceiver_bytes);

View File

@@ -1,5 +1,8 @@
# SPDX-License-Identifier: LGPL-3.0-or-other
# Copyright (C) 2021 Contributors to the SLS Detector Package
set(SOURCES
src/string_utils.cpp
src/file_utils.cpp
@@ -14,6 +17,7 @@ set(SOURCES
src/sls_detector_exceptions.cpp
src/md5_helper.cpp
src/Version.cpp
src/bit_utils.cpp
)
# Header files to install as a part of the library
@@ -26,6 +30,7 @@ set(PUBLICHEADERS
include/sls/ToString.h
include/sls/TypeTraits.h
include/sls/TimeHelper.h
include/sls/bit_utils.h
)
# Additional headers to be installed if SLS_DEVEL_HEADERS
@@ -89,12 +94,17 @@ target_link_libraries(slsSupportObject
PUBLIC
slsProjectOptions
${STD_FS_LIB} # from helpers.cmake
Threads::Threads # slsDetector and Receiver need this
PRIVATE
slsProjectWarnings
md5sls
)
#RH8 glibc 2.28, RH9 glibc 2.34 linking rt is only needed with glibc < 2.34
#but we do it for all Linux builds to avoid too many conditionals
target_link_libraries (slsSupportObject PUBLIC $<$<PLATFORM_ID:Linux>:rt>)
#Treat both vendored and system zmq as interface for receiver binaries
if(SLS_USE_SYSTEM_ZMQ)
message(STATUS "slsSupportLib using ZEROMQ_TARGET=${ZEROMQ_TARGET}")

View File

@@ -65,6 +65,7 @@ std::ostream &operator<<(std::ostream &os,
std::string ToString(const slsDetectorDefs::pedestalParameters &r);
std::ostream &operator<<(std::ostream &os,
const slsDetectorDefs::pedestalParameters &r);
const std::string &ToString(const std::string &s);
/** Convert std::chrono::duration with specified output unit */

View File

@@ -3,6 +3,7 @@
#pragma once
#include <bitset>
#include <cstdint>
#include <vector>
namespace sls {
template <typename T> std::vector<int> getSetBits(T val) {
@@ -18,4 +19,91 @@ template <typename T> std::vector<int> getSetBits(T val) {
}
return set_bits;
}
class RegisterAddress {
private:
uint32_t value_{0};
public:
constexpr RegisterAddress() noexcept = default;
constexpr explicit RegisterAddress(uint32_t value) : value_(value) {}
explicit RegisterAddress(const std::string &value);
std::string str() const;
constexpr uint32_t value() const noexcept { return value_; }
constexpr bool operator==(const RegisterAddress &other) const {
return (value_ == other.value_);
}
constexpr bool operator!=(const RegisterAddress &other) const {
return (value_ != other.value_);
}
};
class BitAddress {
private:
RegisterAddress addr_{0};
uint32_t bitPos_{0};
public:
constexpr BitAddress() noexcept = default;
BitAddress(RegisterAddress address, uint32_t bitPosition);
BitAddress(const std::string &address, const std::string &bitPosition);
std::string str() const;
constexpr RegisterAddress address() const noexcept { return addr_; }
constexpr uint32_t bitPosition() const noexcept { return bitPos_; }
constexpr bool operator==(const BitAddress &other) const {
return (addr_ == other.addr_ && bitPos_ == other.bitPos_);
}
constexpr bool operator!=(const BitAddress &other) const {
return !(*this == other);
}
};
class RegisterValue {
private:
uint32_t value_{0};
public:
constexpr RegisterValue() noexcept = default;
explicit constexpr RegisterValue(uint32_t value) noexcept : value_(value) {}
explicit RegisterValue(const std::string &value);
std::string str() const;
constexpr uint32_t value() const noexcept { return value_; }
constexpr RegisterValue &operator|=(const RegisterValue &rhs) noexcept {
value_ |= rhs.value();
return *this;
}
constexpr RegisterValue operator|(const RegisterValue &rhs) const noexcept {
RegisterValue tmp(*this);
tmp |= rhs;
return tmp;
}
constexpr RegisterValue &operator|=(uint32_t rhs) noexcept {
value_ |= rhs;
return *this;
}
constexpr RegisterValue operator|(uint32_t rhs) const noexcept {
RegisterValue tmp(*this);
tmp |= rhs;
return tmp;
}
constexpr bool operator==(const RegisterValue &other) const noexcept {
return value_ == other.value_;
}
constexpr bool operator!=(const RegisterValue &other) const noexcept {
return value_ != other.value_;
}
};
std::ostream &operator<<(std::ostream &os, const RegisterAddress &r);
std::ostream &operator<<(std::ostream &os, const BitAddress &r);
std::ostream &operator<<(std::ostream &os, const RegisterValue &r);
} // namespace sls

View File

@@ -6,6 +6,7 @@
#include <algorithm>
#include <memory>
#include <numeric>
#include <set>
#include <sstream>
#include <string>
#include <type_traits>
@@ -155,6 +156,10 @@ template <typename Container> bool hasDuplicates(Container c) {
return pos != c.end(); // if we found something there are duplicates
}
/**
* @brief Sorts the container and removes duplicated elements
* returns true if elements were removed otherwiese false
*/
template <typename T>
typename std::enable_if<is_container<T>::value, bool>::type
removeDuplicates(T &c) {
@@ -167,6 +172,27 @@ removeDuplicates(T &c) {
return false;
}
/**
* @brief Removed duplicated entries while preserving the oder
* returns true if elements were removed otherwiese false
*/
template <typename T>
typename std::enable_if<is_container<T>::value, bool>::type
stableRemoveDuplicates(T &c) {
auto containerSize = c.size();
std::set<typename T::value_type> seen;
c.erase(std::remove_if(
c.begin(), c.end(),
[&](const typename T::value_type &val) {
return !seen.insert(val).second; // erase if already seen
}),
c.end());
if (c.size() != containerSize) {
return true;
}
return false;
}
} // namespace sls
#endif // CONTAINER_UTILS_H

View File

@@ -5,6 +5,7 @@
#include <cassert>
#include <cstdint>
#include <cstring>
#include <stdexcept>
#include <string>
#include <utility>
#include <vector>
@@ -33,6 +34,35 @@ void strcpy_safe(char (&destination)[array_size], const std::string &source) {
destination[array_size - 1] = '\0';
}
// Runtime-checked variant — throws if it won't fit
template <size_t array_size>
void strcpy_checked(char (&destination)[array_size], const char *source) {
if (!source)
throw std::runtime_error("Null source pointer in strcpy_checked");
size_t len = std::strlen(source);
if (len >= (array_size - 1)) {
throw std::runtime_error("String length (" + std::to_string(len) +
") should be less than " +
std::to_string(array_size - 1) + " chars");
}
std::strncpy(destination, source, array_size - 1);
destination[array_size - 1] = '\0';
}
template <size_t array_size>
void strcpy_checked(char (&destination)[array_size],
const std::string &source) {
if (source.size() >= (array_size - 1)) {
throw std::runtime_error("String length (" +
std::to_string(source.size()) +
") should be less than " +
std::to_string(array_size - 1) + " chars");
}
std::strncpy(destination, source.c_str(), array_size - 1);
destination[array_size - 1] = '\0';
}
/*
Removes all occurrences of the specified char from a c string
Templated on array size to ensure no access after buffer limits.
@@ -58,6 +88,8 @@ std::vector<std::string> split(const std::string &strToSplit, char delimeter);
std::string RemoveUnit(std::string &str);
bool is_int(const std::string &s);
/** '0x200' is also an int here */
bool is_hex_or_dec_uint(const std::string &s);
bool replace_first(std::string *s, const std::string &substr,
const std::string &repl);

View File

@@ -0,0 +1,69 @@
// SPDX-License-Identifier: LGPL-3.0-or-other
// Copyright (C) 2021 Contributors to the SLS Detector Package
#include "sls/bit_utils.h"
#include "sls/ToString.h"
#include "sls/sls_detector_exceptions.h"
namespace sls {
RegisterAddress::RegisterAddress(const std::string &value) {
if (!is_hex_or_dec_uint(value)) {
throw RuntimeError("Address must be an integer value.");
}
value_ = StringTo<uint32_t>(value);
}
std::string RegisterAddress::str() const { return ToStringHex(value_); }
BitAddress::BitAddress(RegisterAddress address, uint32_t bitPosition)
: addr_(address) {
if (bitPosition > 31) {
throw RuntimeError("Bit position must be between 0 and 31.");
}
bitPos_ = bitPosition;
}
BitAddress::BitAddress(const std::string &address,
const std::string &bitPosition) {
addr_ = RegisterAddress(address);
if (!is_hex_or_dec_uint(bitPosition)) {
throw RuntimeError("Bit position must be an integer value.");
}
uint32_t bitPos = StringTo<uint32_t>(bitPosition);
if (bitPos > 31) {
throw RuntimeError("Bit position must be between 0 and 31.");
}
bitPos_ = bitPos;
}
std::string BitAddress::str() const {
std::ostringstream os;
os << '[' << addr_.str() << ", " << ToString(bitPos_) << ']';
return os.str();
}
RegisterValue::RegisterValue(const std::string &value) {
if (!is_hex_or_dec_uint(value)) {
throw RuntimeError("Value must be an integer value.");
}
value_ = StringTo<uint32_t>(value);
}
std::string RegisterValue::str() const { return ToStringHex(value_); }
std::ostream &operator<<(std::ostream &os, const RegisterAddress &r) {
os << r.str();
return os;
}
std::ostream &operator<<(std::ostream &os, const BitAddress &r) {
os << r.str();
return os;
}
std::ostream &operator<<(std::ostream &os, const RegisterValue &r) {
os << r.str();
return os;
}
} // namespace sls

View File

@@ -256,24 +256,22 @@ std::string getAbsolutePathFromCurrentProcess(const std::string &fname) {
return fname;
}
//in case PATH_MAX defines the longest possible path on linux and macOS
//use string instead of char array to avoid overflow
std::string path(PATH_MAX, '\0');
// in case PATH_MAX defines the longest possible path on linux and macOS
// use string instead of char array to avoid overflow
std::string path(PATH_MAX, '\0');
#if defined(__APPLE__)
#if defined(__APPLE__)
uint32_t size = PATH_MAX;
if (_NSGetExecutablePath(path.data(), &size) != 0) {
throw std::runtime_error("Failed to get executable path");
}
// Resolve any symlinks and .. components
std::string resolved(PATH_MAX, '\0');
std::string resolved(PATH_MAX, '\0');
if (!realpath(path.data(), resolved.data())) {
throw std::runtime_error("realpath failed for executable");
}
path = resolved;
#else
#else
ssize_t len = readlink("/proc/self/exe", path.data(), PATH_MAX - 1);
if (len < 0) {
@@ -281,7 +279,7 @@ std::string getAbsolutePathFromCurrentProcess(const std::string &fname) {
}
path[len] = '\0';
#endif
#endif
// get dir path and attach file name
std::string absPath = (std::string(dirname(path.data())) + '/' + fname);

View File

@@ -179,8 +179,7 @@ IpAddr InterfaceNameToIp(const std::string &ifn) {
MacAddr InterfaceNameToMac(const std::string &inf) {
#ifdef __APPLE__
throw RuntimeError(
"InterfaceNameToMac not implemented on macOS yet");
throw RuntimeError("InterfaceNameToMac not implemented on macOS yet");
#else
// TODO! Copied from genericSocket needs to be refactored!

View File

@@ -43,6 +43,15 @@ bool is_int(const std::string &s) {
}) == s.end();
}
bool is_hex_or_dec_uint(const std::string &s) {
try {
StringTo<uint32_t>(s);
return true;
} catch (...) {
}
return false;
}
bool replace_first(std::string *s, const std::string &substr,
const std::string &repl) {
auto pos = s->find(substr);

View File

@@ -84,8 +84,8 @@ TEST_CASE("Shutdown socket without hanging when waiting for data") {
// Start a thread and wait for package
// if the socket is left open we would block
std::future<bool> ret =
std::async(std::launch::async, &UdpRxSocket::ReceivePacket, &s, (char *)&buff);
std::future<bool> ret = std::async(
std::launch::async, &UdpRxSocket::ReceivePacket, &s, (char *)&buff);
s.Shutdown();
auto r = ret.get();

View File

@@ -2,6 +2,7 @@
// Copyright (C) 2021 Contributors to the SLS Detector Package
#include "catch.hpp"
#include "sls/bit_utils.h"
#include <sstream>
#include <vector>
namespace sls {
@@ -42,4 +43,148 @@ TEST_CASE("Get set bits from 523") {
REQUIRE(vec == std::vector<int>{0, 1, 3, 9});
}
TEST_CASE("Convert RegisterAddress using classes ", "[support][.bit_utils]") {
std::vector<uint32_t> vec_addr{0x305, 0xffffffff, 0x0, 0x34550987,
0x1fff1fff};
std::vector<std::string> vec_ans{"0x305", "0xffffffff", "0x0", "0x34550987",
"0x1fff1fff"};
for (size_t i = 0; i != vec_addr.size(); ++i) {
auto reg0 = RegisterAddress(vec_addr[i]);
auto reg1 = RegisterAddress(vec_ans[i]);
auto reg2 = RegisterAddress(vec_addr[0]);
CHECK(reg0 == reg1);
if (i != 0)
CHECK(reg2 != reg1);
CHECK(reg0.value() == vec_addr[i]);
CHECK(reg1.value() == vec_addr[i]);
CHECK(reg0.str() == vec_ans[i]);
CHECK(reg1.str() == vec_ans[i]);
}
}
TEST_CASE("Convert RegisterValue using classes ", "[support][.bit_utils]") {
std::vector<uint32_t> vec_addr{0x305, 0xffffffff, 0x0, 500254562,
0x1fff1fff};
std::vector<std::string> vec_ans{"0x305", "0xffffffff", "0x0", "0x1dd14762",
"0x1fff1fff"};
for (size_t i = 0; i != vec_addr.size(); ++i) {
auto reg0 = RegisterValue(vec_addr[i]);
auto reg1 = RegisterValue(vec_ans[i]);
auto reg2 = RegisterValue(vec_addr[0]);
CHECK(reg0 == reg1);
if (i != 0)
CHECK(reg2 != reg1);
CHECK(reg0.value() == vec_addr[i]);
CHECK(reg1.value() == vec_addr[i]);
CHECK(reg0.str() == vec_ans[i]);
CHECK(reg1.str() == vec_ans[i]);
CHECK((reg0 | 0xffffffffu) == RegisterValue(0xffffffffu));
CHECK((reg0 | 0x0) == reg0);
CHECK((reg0 | reg1) == reg0);
}
}
TEST_CASE("Convert BitAddress using classes", "[support][.bit_utils]") {
std::vector<RegisterAddress> vec_addr{
RegisterAddress(0x305), RegisterAddress(0xffffffffu),
RegisterAddress(0x0), RegisterAddress(0x34550987),
RegisterAddress(0x1fff1fff)};
std::vector<std::string> vec_addr_str{"0x305", "0xffffffff", "0x0",
"0x34550987", "0x1fff1fff"};
std::vector<uint32_t> vec_bitpos{0, 15, 31, 7, 23};
std::vector<std::string> vec_bitpos_str{"0", "15", "31", "7", "23"};
std::vector<std::string> vec_ans{
"[0x305, 0]", "[0xffffffff, 15]", "[0x0, 31]",
"[0x34550987, 7]", "[0x1fff1fff, 23]",
};
for (size_t i = 0; i != vec_addr.size(); ++i) {
auto reg0 = BitAddress(vec_addr[i], vec_bitpos[i]);
BitAddress reg1(vec_addr_str[i], vec_bitpos_str[i]);
CHECK(reg1.address() == vec_addr[i]);
CHECK(reg1.bitPosition() == vec_bitpos[i]);
auto reg2 = BitAddress(vec_addr[0], vec_bitpos[0]);
CHECK(reg0 == reg1);
if (i != 0)
CHECK(reg2 != reg1);
CHECK(reg0.address() == vec_addr[i]);
CHECK(reg1.address() == vec_addr[i]);
CHECK(reg0.bitPosition() == vec_bitpos[i]);
CHECK(reg1.bitPosition() == vec_bitpos[i]);
CHECK(std::to_string(reg0.bitPosition()) == vec_bitpos_str[i]);
CHECK(std::to_string(reg1.bitPosition()) == vec_bitpos_str[i]);
CHECK(reg0.str() == vec_ans[i]);
CHECK(reg1.str() == vec_ans[i]);
}
}
TEST_CASE("Output operator gives same result as string",
"[support][.bit_utils]") {
{
RegisterAddress addr{"0x3456af"};
std::ostringstream os;
os << addr;
CHECK(os.str() == "0x3456af");
CHECK(os.str() == addr.str());
}
{
BitAddress addr("0x3456af", "15");
std::ostringstream os;
os << addr;
CHECK(os.str() == "[0x3456af, 15]");
CHECK(os.str() == addr.str());
}
{
RegisterValue addr{"0x3456af"};
std::ostringstream os;
os << addr;
CHECK(os.str() == "0x3456af");
CHECK(os.str() == addr.str());
}
}
TEST_CASE("Strange input throws", "[support][.bit_utils]") {
REQUIRE_THROWS(RegisterAddress("hej"));
// ensure correct exception message
try {
RegisterAddress("hej");
} catch (const std::exception &e) {
REQUIRE(std::string(e.what()) == "Address must be an integer value.");
}
REQUIRE_THROWS(BitAddress("0x305", "hej"));
// ensure correct exception message
try {
BitAddress("0x305", "hej");
} catch (const std::exception &e) {
REQUIRE(std::string(e.what()) ==
"Bit position must be an integer value.");
}
REQUIRE_THROWS(BitAddress(RegisterAddress(0x305), 32));
// ensure correct exception message
try {
BitAddress(RegisterAddress(0x305), 32);
} catch (const std::exception &e) {
REQUIRE(std::string(e.what()) ==
"Bit position must be between 0 and 31.");
}
REQUIRE_THROWS(RegisterValue("hej"));
// ensure correct exception message
try {
RegisterValue("hej");
} catch (const std::exception &e) {
REQUIRE(std::string(e.what()) == "Value must be an integer value.");
}
}
} // namespace sls

View File

@@ -153,13 +153,34 @@ TEST_CASE("check for duplicates in vector of pairs") {
REQUIRE(hasDuplicates(vec) == true);
}
TEST_CASE("remove duplicates from vector") {
TEST_CASE("sorts the vector and remove duplicates") {
std::vector<int> v{5, 6, 5, 3};
auto r = removeDuplicates(v);
CHECK(r == true); // did indeed remove elements
CHECK(v == std::vector<int>{3, 5, 6});
}
TEST_CASE("remove duplicates but keep order") {
std::vector<int> v{5, 6, 5, 3};
auto r = stableRemoveDuplicates(v);
CHECK(r == true); // did indeed remove elements
CHECK(v == std::vector<int>{5, 6, 3});
}
TEST_CASE("remove duplicates but keep order, all elements the same ") {
std::vector<char> v{'c', 'c', 'c', 'c', 'c', 'c'};
auto r = stableRemoveDuplicates(v);
CHECK(r == true); // did indeed remove elements
CHECK(v == std::vector<char>{'c'});
}
TEST_CASE("remove duplicates but keep order, pattern ") {
std::vector<int> v{8, 1, 2, 8, 8, 3, 2};
auto r = stableRemoveDuplicates(v);
CHECK(r == true); // did indeed remove elements
CHECK(v == std::vector<int>{8, 1, 2, 3});
}
TEST_CASE("remove duplicated empty vector") {
std::vector<int> v;
auto r = removeDuplicates(v);
@@ -167,4 +188,11 @@ TEST_CASE("remove duplicated empty vector") {
CHECK(v == std::vector<int>{});
}
TEST_CASE("remove duplicated empty vector using stable version") {
std::vector<int> v;
auto r = stableRemoveDuplicates(v);
CHECK(r == false); // no elements to remove
CHECK(v == std::vector<int>{});
}
} // namespace sls

View File

@@ -24,7 +24,6 @@ target_link_libraries(tests
PUBLIC
slsProjectOptions
slsSupportStatic
pthread
PRIVATE
slsProjectWarnings
)

View File

@@ -113,7 +113,7 @@ def startTestsForAll(args, fp):
startDetectorVirtualServer(server, args.num_mods, fp)
startFrameSynchronizerPullSocket(server, fp)
startFrameSynchronizer(args.num_mods, fp)
d = loadConfig(name=server, rx_hostname=args.rx_hostname, settingsdir=args.settingspath, fp=fp, num_mods=args.num_mods, num_frames=args.num_frames)
d = loadConfig(name=server, rx_hostname=args.rx_hostname, settingsdir=args.settingspath, log_file_fp=fp, num_mods=args.num_mods, num_frames=args.num_frames)
loadBasicSettings(name=server, d=d, fp=fp)
acquire(fp, d)
testFramesCaught(server, d, args.num_frames)

View File

@@ -18,9 +18,11 @@ from utils_for_test import (
RuntimeException,
cleanup,
startProcessInBackground,
startReceiver,
startDetectorVirtualServer,
connectToVirtualServers,
loadBasicSettings,
loadConfig,
runProcessWithLogFile
)
@@ -28,45 +30,6 @@ LOG_PREFIX_FNAME = '/tmp/slsDetectorPackage_virtual_roi_test'
MAIN_LOG_FNAME = LOG_PREFIX_FNAME + '_log.txt'
ROI_TEST_FNAME = LOG_PREFIX_FNAME + '_results_'
def startReceiver(num_mods, fp):
if num_mods == 1:
cmd = ['slsReceiver']
else:
cmd = ['slsMultiReceiver', str(DEFAULT_TCP_RX_PORTNO), str(num_mods)]
# in 10.0.0
#cmd = ['slsMultiReceiver', '-p', str(DEFAULT_TCP_RX_PORTNO), '-n', str(num_mods)]
startProcessInBackground(cmd, fp)
time.sleep(1)
def loadConfigForRoi(name, fp, num_mods = 1, num_interfaces = 1):
Log(LogLevel.INFO, 'Loading config')
Log(LogLevel.INFO, 'Loading config', fp)
try:
d = connectToVirtualServers(name, num_mods)
if name == 'jungfrau' or name == 'moench':
d.numinterfaces = num_interfaces
d.udp_dstport = DEFAULT_UDP_DST_PORTNO
if name == 'eiger' or name == 'jungfrau' or name == 'moench':
d.udp_dstport2 = DEFAULT_UDP_DST_PORTNO + 1
d.rx_hostname = 'localhost'
d.udp_dstip = 'auto'
if name != "eiger":
d.udp_srcip = 'auto'
if name == 'jungfrau' or name == 'moench':
d.udp_dstip2 = 'auto'
d.powerchip = 1
d.frames = 5
except Exception as e:
raise RuntimeException(f'Could not load config for {name}. Error: {str(e)}') from e
return d
def startTestsForAll(fp):
servers = [
'eiger',
@@ -89,7 +52,7 @@ def startTestsForAll(fp):
cleanup(fp)
startDetectorVirtualServer(server, nmods, fp)
startReceiver(nmods, fp)
d = loadConfigForRoi(name=server, fp=fp, num_mods=nmods, num_interfaces=ninterfaces)
d = loadConfig(name=server, log_file_fp = fp, num_mods=nmods, num_frames=5, num_interfaces=ninterfaces)
loadBasicSettings(name=server, d=d, fp=fp)
fname = ROI_TEST_FNAME + server + '.txt'

View File

@@ -63,7 +63,7 @@ def startCmdTestsForAll(args, fp):
cleanup(fp)
startDetectorVirtualServer(name=server, num_mods=num_mods, fp=fp)
startReceiver(num_mods, fp)
d = loadConfig(name=server, rx_hostname=args.rx_hostname, settingsdir=args.settingspath, fp=fp, num_mods=num_mods)
d = loadConfig(name=server, rx_hostname=args.rx_hostname, settingsdir=args.settingspath, log_file_fp=fp, num_mods=num_mods)
loadBasicSettings(name=server, d=d, fp=fp)
runProcessWithLogFile('Cmd Tests (' + args.markers + ') for ' + server, cmd, fp, fname)
except Exception as e:

View File

@@ -16,7 +16,6 @@ SERVER_START_PORTNO=1900
init(autoreset=True)
class LogLevel(Enum):
INFO = 0
INFORED = 1
@@ -193,32 +192,51 @@ def connectToVirtualServers(name, num_mods, ctb_object=False):
return d
def startReceiver(num_mods, fp):
if num_mods == 1:
cmd = ['slsReceiver']
else:
cmd = ['slsMultiReceiver', str(DEFAULT_TCP_RX_PORTNO), str(num_mods)]
# in 10.0.0
#cmd = ['slsMultiReceiver', '-p', str(DEFAULT_TCP_RX_PORTNO), '-n', str(num_mods)]
startProcessInBackground(cmd, fp)
time.sleep(1)
def loadConfig(name, rx_hostname, settingsdir, fp, num_mods = 1, num_frames = 1):
def loadConfig(name, rx_hostname = 'localhost', settingsdir = None, log_file_fp = None, num_mods = 1, num_frames = 1, num_interfaces = 1):
Log(LogLevel.INFO, 'Loading config')
Log(LogLevel.INFO, 'Loading config', fp)
Log(LogLevel.INFO, 'Loading config', log_file_fp)
try:
d = connectToVirtualServers(name, num_mods)
if name == 'jungfrau' or name == 'moench':
d.numinterfaces = num_interfaces
d.udp_dstport = DEFAULT_UDP_DST_PORTNO
if name == 'eiger':
if name == 'eiger' or name == 'jungfrau' or name == 'moench':
d.udp_dstport2 = DEFAULT_UDP_DST_PORTNO + 1
d.rx_hostname = rx_hostname
d.udp_dstip = 'auto'
if name != "eiger":
d.udp_srcip = 'auto'
if name == "jungfrau" or name == "moench":
d.udp_dstip2 = 'auto'
if name == "jungfrau" or name == "moench" or name == "xilinx_ctb":
d.powerchip = 1
if name == "xilinx_ctb":
d.configureTransceiver()
if name == "eiger":
d.trimen = [4500, 5400, 6400]
d.settingspath = settingsdir + '/eiger/'
d.setThresholdEnergy(4500, detectorSettings.STANDARD)
if settingsdir is not None and name in ['eiger', 'mythen3']:
d.settingspath = settingsdir + '/' + name + '/'
d.trimen = [4500, 5400, 6400] if name == 'eiger' else [4000, 6000, 8000, 12000]
d.setThresholdEnergy(4500, detectorSettings.STANDARD)
d.frames = num_frames
except Exception as e:

View File

@@ -1,39 +1,14 @@
# SPDX-License-Identifier: LGPL-3.0-or-other
# Copyright (C) 2021 Contributors to the SLS Detector Package
#echo $#
#if [ $# = 0 ]; then
# f=$0
#else
# f=$1
#fi
#echo $f
if [ "x${BASH_ARGV[0]}" = "x" ]; then
#if [ "x$f" = "x" ]; then
if [ ! -f this_build_bin_path.sh ]; then
f=$0
echo "aaaa"
#thispath=$(dirname ${BASH_ARGV[0]})
thispath=$(dirname $f)
p=$(cd ${thispath};pwd);
THIS_PATH="$p/build/bin/"
# echo "ERROR: must cd where/this/package/is before calling this_path.sh"
# echo "Try sourcing it"
else
echo "bbb"
THIS_PATH="$PWD/build/bin/";
fi
else
thispath=$(dirname ${BASH_ARGV[0]})
p=$(cd ${thispath};pwd);
THIS_PATH="$p/build/bin/"
echo "ccc"
fi
#!/bin/bash
echo "this_path="$THIS_PATH
export PATH=$THIS_PATH:$PATH
export LD_LIBRARY_PATH=$THIS_PATH:$LD_LIBRARY_PATH
export PYTHONPATH=$THIS_PATH:$PYTHONPATH
echo "path="$PATH
echo "ld_library_path="$LD_LIBRARY_PATH
echo "pythonpath="$PYTHON_PATH
# Since this script could be sourced, $0 is not sufficent, BASH_SOURCE[0] is necessary
SCRIPT_LOCATION="$(realpath ${BASH_SOURCE[0]})"
SCRIPT_LOCATION="$(dirname ${SCRIPT_LOCATION})"
BUILDBIN_LOCATION="${SCRIPT_LOCATION}/build/bin"
if [ ! -d "${BUILDBIN_LOCATION}" ]; then
echo Cannot find path ${BUILDBIN_LOCATION}
else
echo Adding ${BUILDBIN_LOCATION} to PATH and PYTHONPATH
export PATH=${BUILDBIN_LOCATION}:${PATH}
export PYTHONPATH=${BUILDBIN_LOCATION}:${PYTHONPATH}
fi