Merge branch 'developer' into fix/rx_dbitlist
Build on RHEL9 docker image / build (push) Successful in 3m48s
Build on RHEL8 docker image / build (push) Successful in 5m7s
Run Simulator Tests on local RHEL9 / build (push) Successful in 20m42s
Run Simulator Tests on local RHEL8 / build (push) Successful in 24m12s

This commit is contained in:
mazzol_a authored and GitHub committed 2026-10-12 09:39:20 +02:00
commit 78b1b61a05
43 files changed
+975 -659

No files matched your search

+97
View File
@@ -0,0 +1,97 @@
name: Build RPMs on RHEL8 docker image
on:
workflow_dispatch:
inputs:
deploy:
description: "Upload the RPMs to the Gitea package registry"
type: boolean
default: false
permissions:
contents: read
jobs:
build:
runs-on: "ubuntu-latest"
container:
image: gitea.psi.ch/detectors/rhel8-detectors-dev
steps:
- name: Clone repository
run: |
git lfs install --skip-smudge
echo Cloning ${{ github.ref_name }}
git clone https://${{secrets.GITHUB_TOKEN}}@gitea.psi.ch/${{ github.repository }}.git --branch=${{ github.ref_name }} .
- name: Install build dependencies
run: |
dnf -y install rpm-build qt5-qtbase-devel qt5-qtsvg-devel \
libpng-devel zlib-devel expat-devel libtiff-devel
- name: Build with versioned binaries
run: |
cmake -S . -B build \
-DCMAKE_BUILD_TYPE=Release \
-DSLS_USE_GUI=ON \
-DSLS_USE_MOENCH=ON \
-DSLS_INSTALL_VERSIONED_BINARIES=ON
cmake --build build -j 2
- name: Build RPMs
run: |
cpack --config build/CPackConfig.cmake -G RPM \
-D 'CPACK_COMPONENTS_ALL=cli;receiver;zmq;gui' -B build/rpms
- name: Inspect RPMs
run: |
for rpm in build/rpms/*.rpm; do
echo "::group::$rpm"
rpm -qpi "$rpm"
rpm -qpl "$rpm"
rpm -qpR "$rpm"
echo "::endgroup::"
done
- name: Install RPMs and check versioned binaries
run: |
VERSION=$(cat VERSION)
dnf -y install build/rpms/*.rpm
for component in cli receiver zmq gui; do
rpm -q slsdetectorpackage-${VERSION}-${component}
done
for exe in sls_detector_get sls_detector_put slsReceiver \
slsMultiReceiver slsFrameSynchronizer moench03ZmqProcess slsDetectorGui; do
test -x /usr/bin/${exe}-${VERSION}
test ! -e /usr/bin/${exe}
done
sls_detector_get-${VERSION} --version
slsReceiver-${VERSION} --version
- name: Upload RPMs to Gitea
if: ${{ inputs.deploy }}
env:
SERVICE: ${{ secrets.SERVICE }}
run: |
url=https://gitea.psi.ch/api/packages/${{ github.repository_owner }}/rpm/el8
upload() {
curl --silent --show-error --output /tmp/upload-response \
--write-out "%{http_code}" \
--user "detectors-gitea:${SERVICE}" \
--upload-file "$1" "$url/upload"
}
for rpm in build/rpms/*.rpm; do
echo "Uploading $rpm"
code=$(upload "$rpm")
if [ "$code" = 409 ]; then
echo "Already in the registry, replacing"
curl --silent --show-error --fail -X DELETE \
--user "detectors-gitea:${SERVICE}" \
"$url/package/$(rpm -qp --queryformat '%{NAME}/%{VERSION}-%{RELEASE}/%{ARCH}' "$rpm")"
code=$(upload "$rpm")
fi
if [ "$code" != 201 ]; then
echo "Upload failed with HTTP $code"
cat /tmp/upload-response
exit 1
fi
done
+93
View File
@@ -0,0 +1,93 @@
name: Build RPMs on RHEL9 docker image
on:
workflow_dispatch:
inputs:
deploy:
description: "Upload the RPMs to the Gitea package registry"
type: boolean
default: false
permissions:
contents: read
jobs:
build:
runs-on: "ubuntu-latest"
container:
image: gitea.psi.ch/detectors/rhel9-detectors-dev
steps:
- uses: actions/checkout@v4
- name: Install build dependencies
run: |
dnf -y install rpm-build qt5-qtbase-devel qt5-qtsvg-devel \
libpng-devel zlib-devel expat-devel libtiff-devel
- name: Build with versioned binaries
run: |
cmake -S . -B build \
-DCMAKE_BUILD_TYPE=Release \
-DSLS_USE_GUI=ON \
-DSLS_USE_MOENCH=ON \
-DSLS_INSTALL_VERSIONED_BINARIES=ON
cmake --build build -j 2
- name: Build RPMs
run: |
cpack --config build/CPackConfig.cmake -G RPM \
-D 'CPACK_COMPONENTS_ALL=cli;receiver;zmq;gui' -B build/rpms
- name: Inspect RPMs
run: |
for rpm in build/rpms/*.rpm; do
echo "::group::$rpm"
rpm -qpi "$rpm"
rpm -qpl "$rpm"
rpm -qpR "$rpm"
echo "::endgroup::"
done
- name: Install RPMs and check versioned binaries
run: |
VERSION=$(cat VERSION)
dnf -y install build/rpms/*.rpm
for component in cli receiver zmq gui; do
rpm -q slsdetectorpackage-${VERSION}-${component}
done
for exe in sls_detector_get sls_detector_put slsReceiver \
slsMultiReceiver slsFrameSynchronizer moench03ZmqProcess slsDetectorGui; do
test -x /usr/bin/${exe}-${VERSION}
test ! -e /usr/bin/${exe}
done
sls_detector_get-${VERSION} --version
slsReceiver-${VERSION} --version
- name: Upload RPMs to Gitea
if: ${{ inputs.deploy }}
env:
SERVICE: ${{ secrets.SERVICE }}
run: |
url=https://gitea.psi.ch/api/packages/${{ github.repository_owner }}/rpm/el9
upload() {
curl --silent --show-error --output /tmp/upload-response \
--write-out "%{http_code}" \
--user "detectors-gitea:${SERVICE}" \
--upload-file "$1" "$url/upload"
}
for rpm in build/rpms/*.rpm; do
echo "Uploading $rpm"
code=$(upload "$rpm")
if [ "$code" = 409 ]; then
echo "Already in the registry, replacing"
curl --silent --show-error --fail -X DELETE \
--user "detectors-gitea:${SERVICE}" \
"$url/package/$(rpm -qp --queryformat '%{NAME}/%{VERSION}-%{RELEASE}/%{ARCH}' "$rpm")"
code=$(upload "$rpm")
fi
if [ "$code" != 201 ]; then
echo "Upload failed with HTTP $code"
cat /tmp/upload-response
exit 1
fi
done
+18 -11
View File
@@ -26,9 +26,9 @@ jobs:
build-and-deploy:
strategy:
matrix:
patform: [ubuntu-latest]
platform: [ubuntu-latest]
python-version: ["3.12"]
runs-on: ${{ matrix.patform }}
runs-on: ${{ matrix.platform }}
defaults:
run:
@@ -74,24 +74,31 @@ jobs:
cmake -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DSLS_BUILD_DOCS=ON -DSLS_USE_HDF5=ON -DSLS_USE_PYTHON=ON ..
make -j4
make docs
# Update main index if this is a release
- name: Update version index
- name: Render Documentation index
if: github.event_name == 'release'
run: |
python docs/main_index/render_main_index.py \
--version "${{ steps.version.outputs.version }}" \
--date "$(date +'%d.%m.%Y')"
gh release list --json tagName,publishedAt > releases.json
python docs/main_index/render_main_index.py --json_releases releases.json --new_version ${{ steps.version.outputs.version }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Checkout gh-pages
uses: actions/checkout@v6
with:
ref: gh-pages
path: gh-pages
- name: Copy documentation to versioned folder for developer branch
if: github.event_name == 'push' && github.ref == 'refs/heads/developer'
run: |
VERSION="${{ steps.version.outputs.version }}"
mkdir -p "gh-pages/${VERSION}"
cp -r build/docs/html/. "gh-pages/${VERSION}/"
- name: Copy documentation and Release notes to versioned folder
if: github.event_name == 'release' || (github.event_name == 'push')
if: github.event_name == 'release'
run: |
VERSION="${{ steps.version.outputs.version }}"
mkdir -p "gh-pages/${VERSION}"
+17 -17
View File
@@ -22,6 +22,7 @@ endif()
include(cmake/project_version.cmake)
include(cmake/SlsAddFlag.cmake)
include(cmake/helpers.cmake)
include(cmake/SlsInstallExecutable.cmake)
find_package(Threads REQUIRED)
@@ -219,7 +220,6 @@ option(SLS_BUILD_SHARED_LIBRARIES "Build shared libaries" OFF)
option(SLS_USE_TEXTCLIENT "Text Client" ON)
option(SLS_USE_DETECTOR "Detector libs" ON)
option(SLS_USE_RECEIVER "Receiver" ON)
option(SLS_USE_SERVER "Server" ON)
option(SLS_USE_RECEIVER_BINARIES "Receiver binaries" ON)
option(SLS_USE_GUI "GUI" OFF)
option(SLS_USE_SIMULATOR "Simulator" OFF)
@@ -235,7 +235,7 @@ option(SLS_DEVEL_HEADERS "install headers for devel" OFF)
option(SLS_USE_MOENCH "compile zmq and post processing for Moench" OFF)
option(SLS_USE_JUNGFRAU "compile post processing for Jungfrau" OFF)
option(SLS_USE_MATTERHORN "compile matterhorn server" OFF)
option(SLS_INSTALL_VERSIONED_BINARIES "Add version number to binaries on install" OFF) #Needed for multi version RPM
option(SLS_INSTALL_VERSIONED_BINARIES "Add version number to installed executables and RPM package names" OFF)
option(SLS_TREAT_WARNINGS_AS_ERRORS "Treat warnings as errors" OFF)
#Convenience option to switch off defaults when building Moench binaries only
@@ -258,7 +258,6 @@ if(SLS_BUILD_ONLY_MATTERHORN)
set(SLS_USE_DETECTOR ON CACHE BOOL "Disabled for MATTERHORN_ONLY" FORCE)
set(SLS_USE_RECEIVER OFF CACHE BOOL "Disabled for MATTERHORN_ONLY" FORCE)
set(SLS_USE_RECEIVER_BINARIES OFF CACHE BOOL "Disabled for MATTERHORN_ONLY" FORCE)
set(SLS_USE_SERVER ON CACHE BOOL "Enable building cpp server" FORCE)
set(SLS_USE_MATTERHORN ON CACHE BOOL "Enable Matterhorn" FORCE)
endif()
@@ -438,11 +437,6 @@ if (SLS_USE_DETECTOR OR SLS_USE_TEXTCLIENT)
add_subdirectory(slsDetectorSoftware)
endif()
# TODO refactor with simulators
if (SLS_USE_SERVER)
add_subdirectory(slsDetectorServers/slsDetectorServer_cpp)
endif()
if (SLS_USE_RECEIVER)
add_subdirectory(slsReceiverSoftware)
endif (SLS_USE_RECEIVER)
@@ -452,14 +446,10 @@ if (SLS_USE_GUI)
add_subdirectory(slsDetectorGui)
endif (SLS_USE_GUI)
if (SLS_USE_SIMULATOR)
if (SLS_USE_SIMULATOR OR SLS_USE_MATTERHORN)
add_subdirectory(slsDetectorServers)
endif (SLS_USE_SIMULATOR)
endif (SLS_USE_SIMULATOR OR SLS_USE_MATTERHORN)
# cant add_subdirectory twice
if (SLS_USE_MATTERHORN AND !SLS_USE_SIMULATOR)
add_subdirectory(slsDetectorServers/matterhornServer)
endif()
if (SLS_USE_PYTHON)
find_package (Python 3.8 COMPONENTS Interpreter Development.Module REQUIRED)
@@ -531,14 +521,18 @@ set(CPACK_PACKAGE_VERSION "${PROJECT_VERSION}")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "DAQ software for PSI developed detectors")
# RPM-specific settings
string(TOLOWER "${CPACK_PACKAGE_NAME}" CPACK_RPM_PACKAGE_NAME)
if(SLS_INSTALL_VERSIONED_BINARIES)
string(APPEND CPACK_RPM_PACKAGE_NAME "-${PROJECT_VERSION}")
endif()
set(CPACK_GENERATOR "RPM")
set(CPACK_RPM_FILE_NAME "RPM-DEFAULT")
set(CPACK_RPM_FILE_NAME
"${PROJECT_NAME_LOWER}-%{VERSION}-%{RELEASE}.%{ARCH}.rpm")
set(CPACK_RPM_PACKAGE_LICENSE "LGPL-3.0")
set(CPACK_RPM_PACKAGE_GROUP "Applications/System")
set(CPACK_RPM_PACKAGE_RELEASE 1)
# Adds %{?dist} to the RPM Release field
set(CPACK_RPM_PACKAGE_RELEASE_DIST ON)
set(CPACK_RPM_PACKAGE_ARCHITECTURE "${CMAKE_SYSTEM_PROCESSOR}")
set(CPACK_RPM_COMPONENT_INSTALL ON)
@@ -548,4 +542,10 @@ set(CPACK_RPM_GUI_PACKAGE_REQUIRES
#control which RPMs are generated
set(CPACK_COMPONENTS_ALL cli receiver zmq gui)
include(CPack)
# Keep the project version only once in filenames; RPM expands its metadata.
foreach(component IN LISTS CPACK_COMPONENTS_ALL)
string(TOUPPER "${component}" component_upper)
set(CPACK_RPM_${component_upper}_FILE_NAME
"${PROJECT_NAME_LOWER}-${component}-%{VERSION}-%{RELEASE}.%{ARCH}.rpm")
endforeach()
include(CPack)
+30
View File
@@ -0,0 +1,30 @@
# SPDX-License-Identifier: LGPL-3.0-or-other
# Copyright (C) 2026 Contributors to the SLS Detector Package
function(sls_install_executable target)
cmake_parse_arguments(ARG "" "DESTINATION;COMPONENT;EXPORT" "" ${ARGN})
if(NOT ARG_DESTINATION)
set(ARG_DESTINATION "${CMAKE_INSTALL_BINDIR}")
endif()
set(install_args DESTINATION "${ARG_DESTINATION}")
if(ARG_COMPONENT)
list(APPEND install_args COMPONENT "${ARG_COMPONENT}")
endif()
if(SLS_INSTALL_VERSIONED_BINARIES)
install(PROGRAMS "$<TARGET_FILE:${target}>"
${install_args}
RENAME "$<TARGET_FILE_BASE_NAME:${target}>-${PROJECT_VERSION}${CMAKE_EXECUTABLE_SUFFIX}"
)
else()
set(export_args)
if(ARG_EXPORT)
list(APPEND export_args EXPORT "${ARG_EXPORT}")
endif()
install(TARGETS ${target}
${export_args}
RUNTIME ${install_args}
)
endif()
endfunction()
+5 -8
View File
@@ -99,9 +99,8 @@
</thead>
<tbody>
{% for v in versions %}
{# Check if version >= 10.0.0 for .md vs .txt #}
{% set version_parts = v["version"].split('.') | map('int') | list %}
{% set is_new_format = (version_parts[0] > 10) or (version_parts[0] == 10 and version_parts[1] > 0 and version_parts[2] > 0) %}
{% set is_new_format = (version_parts[0] > 10) or (version_parts[0] == 10 and (version_parts[1] > 0 or version_parts[2] > 0)) %}
{% set release_ext = '.md' if is_new_format else '.txt' %}
<tr class="row-{{ 'even' if loop.index is even else 'odd' }}">
<td><p><a class="reference external" href="https://github.com/slsdetectorgroup/slsDetectorPackage/releases/tag/{{ v["version"] }}">{{ v["version"] }}</a></p></td>
@@ -151,10 +150,8 @@
</div>
<script>
jQuery(function () {
SphinxRtdTheme.Navigation.enable(true);ion>
SphinxRtdTheme.Navigation.enable(true);
});
</script>
ery(function () {
</body>hinxRtdTheme.Navigation.enable(true);
</html></body>
</html>
</script>
</body>
</html>
+73 -72
View File
@@ -1,98 +1,101 @@
"""
Render the index HTML from a Jinja2 template with version data.
Can also add new versions to the YAML data file.
Render the index HTML from a Jinja2 template with release data.
The release data is a JSON list as produced by
gh release list --json tagName,publishedAt
Usage:
# Just render from existing data
python render_main_index.py --template main_index.html.j2 --output main_index.html --data versions.yaml
# Add a new version and render
python render_main_index.py --data versions.yaml --add-version 10.1.0 --type Minor --date "15.10.2025" --template main_index.html.j2 --output main_index.html
python render_main_index.py --data releases.json --template index.html.j2 --output index.html
"""
import argparse
import json
from pathlib import Path
from jinja2 import Template
import yaml
import os
from datetime import date
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
def load_versions(data_path: Path):
"""Load version data from YAML file."""
with open(data_path, 'r') as f:
data = yaml.safe_load(f)
return data['versions']
MIN_VERSION = (5, 0, 0) # releases older than this are not listed
MIN_DOCS_VERSION = (9, 0, 0) # releases older than this have no docs
def save_versions(data_path: Path, versions):
"""Save version data to YAML file."""
data = {
'versions': versions
}
with open(data_path, 'w') as f:
yaml.dump(data, f, default_flow_style=False, sort_keys=False)
print(f"✓ Saved version data to {data_path}")
def parse_version(tag: str):
"""Return (major, minor, patch) for a tag like '10.0.1', or None for e.g. '7.0.0.rc1'."""
parts = tag.split('.')
if len(parts) != 3 or not all(p.isdigit() for p in parts):
return None
return tuple(int(p) for p in parts)
def extract_release_type(version: str) -> str:
"""Extract release type from version string."""
parts = version.split('.')
if len(parts) != 3:
return "Unknown"
major, minor, patch = map(int, parts)
if minor == 0 and patch == 0:
return "Major"
elif patch == 0:
return "Minor"
else:
def release_type(version):
"""Derive the release type from the version number."""
_, minor, patch = version
if patch != 0:
return "Bug Fix"
if minor != 0:
return "Minor"
return "Major"
def add_version(data_path: Path, version: str, release_type: str, date: str, has_docs: bool = True):
"""Add a new version to the YAML data file."""
versions = load_versions(data_path)
# Add to table (check if not already present)
new_entry = {
'version': version,
'type': release_type,
'date': date,
'has_docs': has_docs
}
versions.insert(0, new_entry)
print(f"✓ Added version {new_entry} to version data")
save_versions(data_path, versions)
def read_release_json(data_path: Path):
"""Load release data from JSON file, newest version first."""
with open(data_path, 'r') as f:
releases = json.load(f)
versions = []
for release in releases:
version = parse_version(release['tagName'])
if version is None or version < MIN_VERSION:
continue
versions.append({
'version': release['tagName'],
'type': release_type(version),
'date': release['publishedAt'].split('T')[0],
'has_docs': version >= MIN_DOCS_VERSION,
'_key': version,
})
def render_template(template_path: Path, output_path: Path, data_path: Path):
versions.sort(key=lambda v: v['_key'], reverse=True)
return versions
def render_template(template_path: Path, output_path: Path, versions : list):
"""Render the Jinja2 template with version data."""
versions = load_versions(data_path)
with open(template_path, 'r') as f:
template = Template(f.read())
html = template.render(
versions=versions
)
with open(output_path, 'w') as f:
f.write(html)
print(f"✓ Rendered {output_path}")
def add_version(version: str, versions : list):
"""Add a version to the versions dict if it is not already present."""
tuple_version = parse_version(version)
if version not in versions:
versions.insert(0,{
'version': version,
'type': release_type(tuple_version),
'date': date.today().strftime("%Y-%m-%d"),
'has_docs': tuple_version >= MIN_DOCS_VERSION,
'_key': tuple_version,
})
versions.sort(key=lambda v: v['_key'], reverse=True)
def main():
parser = argparse.ArgumentParser(description='Manage versions and render main index HTML')
parser.add_argument('--data', type=Path, default=Path(SCRIPT_DIR + "/versions.yaml"),
help='Path to versions YAML data file')
# Options for adding a new version
parser.add_argument('--version', type=str,
help='new version (e.g., 10.1.0)')
parser.add_argument('--date', type=str,
help='Release date (e.g., 15.10.2025)')
parser = argparse.ArgumentParser(description='Render main index HTML from release data')
parser.add_argument('--json_releases', type=Path,
help='Path to releases JSON data file')
parser.add_argument('--new_version', type=str,
help='New version to add to the releases data')
# Options for rendering
parser.add_argument('--template', type=Path, default=Path(SCRIPT_DIR + "/index.html.j2"),
help='Path to Jinja2 template file')
@@ -100,17 +103,15 @@ def main():
help='Path to output HTML file')
args = parser.parse_args()
# Add new version if requested
if args.version:
if not args.date:
parser.error("--version requires --date")
release_type = extract_release_type(args.version)
add_version(args.data, args.version, release_type, args.date, has_docs=True)
versions = read_release_json(args.json_releases)
if args.new_version:
add_version(args.new_version, versions)
# Render template if requested
if args.template and args.output:
render_template(args.template, args.output, args.data)
render_template(args.template, args.output, versions)
elif args.template or args.output:
parser.error("--template and --output must be used together")
-77
View File
@@ -1,77 +0,0 @@
versions:
- version: 10.0.0
type: Major
date: 10.09.2025
has_docs: true
- version: 9.2.0
type: Minor
date: 02.06.2025
has_docs: true
- version: 9.1.1
type: Bug Fix
date: 22.05.2025
has_docs: true
- version: 9.1.0
type: Minor
date: 28.03.2025
has_docs: true
- version: 9.0.0
type: Major
date: 26.11.2024
has_docs: true
- version: 8.0.2
type: Bug Fix
date: 18.09.2024
has_docs: false
- version: 8.0.1
type: Bug Fix
date: 16.01.2024
has_docs: false
- version: 8.0.0
type: Major
date: 13.11.2023
has_docs: false
- version: 7.0.3
type: Bug Fix
date: 14.11.2023
has_docs: false
- version: 7.0.2
type: Bug Fix
date: 12.07.2023
has_docs: false
- version: 7.0.1
type: Bug Fix
date: 24.03.2023
has_docs: false
- version: 7.0.0
type: Major
date: 24.02.2023
has_docs: false
- version: 6.1.2
type: Bug Fix
date: 25.11.2022
has_docs: false
- version: 6.1.1
type: Bug Fix
date: 04.01.2022
has_docs: false
- version: 6.1.0
type: Minor
date: 25.11.2021
has_docs: false
- version: 6.0.0
type: Major
date: 20.10.2021
has_docs: false
- version: 5.1.0
type: Minor
date: 22.03.2021
has_docs: false
- version: 5.0.1
type: Bug Fix
date: 25.11.2020
has_docs: false
- version: 5.0.0
type: Major
date: 18.11.2020
has_docs: false
+46
View File
@@ -240,6 +240,52 @@ Example cmake options Comment
For v7.x.x of slsDetectorPackage and older, refer :ref:`zeromq notes for cmk script option to hint library location. <zeromq for different slsDetectorPackage versions>`
3.2.3. Build RPM packages
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
CPack builds separate RPMs for the command line tools (``cli``), receiver
executables (``receiver``), Moench processing tools (``zmq``), and GUI (``gui``).
Install ``rpm-build`` and the dependencies for the selected features, and build
on the target distribution or a matching container.
For example, to package the command line tools, receiver and GUI:
.. code-block:: bash
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=/usr -DSLS_USE_GUI=ON \
-DSLS_INSTALL_VERSIONED_BINARIES=ON
cmake --build build -j4
cpack --config build/CPackConfig.cmake -G RPM \
-D 'CPACK_COMPONENTS_ALL=cli;receiver;gui' -B build
Select only components enabled in the build. Add ``-DSLS_USE_MOENCH=ON`` and
the ``zmq`` component to package the Moench tools.
``SLS_INSTALL_VERSIONED_BINARIES=ON`` includes the project version in the RPM
package names, for example ``slsdetectorpackage-10.1.0-cli`` and
``slsdetectorpackage-10.1.0-gui``. Installed executables also receive a version
suffix, such as ``sls_detector_get-10.1.0`` and ``slsDetectorGui-10.1.0``. This
allows RPMs for different project versions to be installed side by side.
RPM revisions of the same project version retain the same package names and
can be upgraded normally.
RPM filenames include the version once, for example
``slsdetectorpackage-cli-10.1.0-1.fc44.x86_64.rpm``. The package's internal name
remains ``slsdetectorpackage-10.1.0-cli`` and its RPM version remains ``10.1.0``.
The option also applies to Jungfrau processing tools and virtual detector
servers installed with ``cmake --install``. These are outside the current RPM
component selection. Executables in the build directory keep their original
names. With the option set to ``OFF`` (the default), installed executables and
RPM package names omit the project version.
The RPM components contain executables; Python bindings, libraries and headers
are not included. A full ``cmake --install`` still installs libraries and
headers at their usual paths, so use separate prefixes for full installations
of different versions.
3.3. Build on old distributions using conda
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+10 -3
View File
@@ -2,6 +2,7 @@
# Copyright (C) 2021 Contributors to the SLS Detector Package
"""
Script to update VERSION file with semantic versioning if provided as an argument, or with 0.0.0 if no argument is provided.
Script also updates VERSION in RELEASE.md and adds the new version to version.yaml
"""
import sys
@@ -32,7 +33,7 @@ def write_version_to_file(version):
version_file_path = Path(SCRIPT_DIR / "VERSION")
with open(version_file_path, "w") as version_file:
version_file.write(version)
print(f"Version {version} written to VERSION file.")
print(f"✓ Version {version} written to VERSION file.")
def extract_release_type(version: str) -> str:
@@ -59,9 +60,11 @@ def get_previous_version(data_path: Path, version : str) -> str:
return prev_version
def main():
parser = argparse.ArgumentParser(description='Update version release notes')
parser.add_argument('--version', required=True, type=str, help='version to write to VERSION file')
parser.add_argument('--prev_version', required=False, type=str, help='previous version to write to RELEASE.md file')
parser.add_argument('--update_version_only', action="store_true", help='Only update version in VERSION file, do not generate release notes')
args = parser.parse_args()
@@ -69,8 +72,12 @@ def main():
write_version_to_file(version)
if not args.update_version_only:
if args.prev_version is None:
raise ValueError("Previous version must be provided when generating release notes. Use --prev_version to specify the previous version.")
release_type = extract_release_type(version)
prev_version = get_previous_version(ROOT_DIR / "docs/main_index/versions.yaml", version)
prev_version = args.prev_version
# Read template
template = Path(ROOT_DIR / "RELEASE.md").read_text()
@@ -83,7 +90,7 @@ def main():
# Write output
Path(ROOT_DIR / "RELEASE.md").write_text(output)
print(f"Generated RELEASE.md for version {version}")
print(f"✓ Generated RELEASE.md for version {version}")
# Main script
if __name__ == "__main__":
+1 -1
View File
@@ -125,7 +125,7 @@ class PlotTab(QtWidgets.QWidget):
nMaxX = lambda : self.transceiverTab.nTransceiverCols
for index, image_view in enumerate(self.transceiverTab.transceiverImageViews):
frame = lambda : image_view.getImageItem().image
frame = lambda image_view=image_view: image_view.getImageItem().image
image_view.scene.sigMouseMoved.connect(partial(self.showPlotValues, image_view, nMaxX, nMaxY, frame))
image_view.getHistogramWidget().item.sigLevelChangeFinished.connect(partial(self.handleHistogramChange, image_view))
+94 -22
View File
@@ -7,6 +7,9 @@ to be installed.
When the Detector API is updated this file should be run
manually.
Tested with libclang 17-23. The output is formatted with
clang-format 17.
"""
import os
from clang import cindex
@@ -38,11 +41,11 @@ def find_libclang():
"""Find libclang in the current Conda/Mamba environment."""
conda_prefix = os.environ.get("CONDA_PREFIX")
if conda_prefix:
lib_dir = os.path.join(conda_prefix, "lib")
# Look for libclang*.so files
for f in os.listdir(lib_dir):
if f.startswith("libclang") and f.endswith(".so"):
return os.path.join(lib_dir, f)
# Match the name exactly, lib also holds libclang-cpp and libclang_rt.*
for name in ("libclang.so", "libclang.dylib"):
path = os.path.join(conda_prefix, "lib", name)
if os.path.exists(path):
return path
# fallback: system-wide search
path = ctypes.util.find_library("clang")
@@ -52,7 +55,7 @@ def find_libclang():
raise FileNotFoundError("libclang not found in CONDA_PREFIX or system paths.")
def check_libclang_version(required="12"):
def check_libclang_version(supported):
# Use already-loaded libclang, or let cindex resolve it
lib = ctypes.CDLL(cindex.Config.library_file or ctypes.util.find_library("clang"))
@@ -63,11 +66,13 @@ def check_libclang_version(required="12"):
# Parse and check version
match = re.search(r"version\s+(\d+)", version_str)
if not match or match.group(1) != required:
msg = red(f"libclang version {match.group(1) if match else '?'} found, but version {required} required. Bye!")
version = int(match.group(1)) if match else None
if version not in supported:
versions = ", ".join(str(v) for v in supported)
msg = red(f"libclang version {version or '?'} found, but one of {versions} required. Bye!")
print(msg)
sys.exit(1)
msg = green(f"Found libclang version {required}")
msg = green(f"Found libclang version {version}")
print(msg)
@@ -95,8 +100,25 @@ def check_for_compile_commands_json(path):
print(msg)
def check_for_parse_errors(tu):
# Types that libclang fails to parse silently turn into int. Errors without
# a location come from compiler flags that clang does not know and are harmless
errors = [
d
for d in tu.diagnostics
if d.severity >= cindex.Diagnostic.Error and d.location.file
]
if errors:
print(red("FAILED"))
for d in errors:
print(red(f"{d.location.file}:{d.location.line}: {d.spelling}"))
print(red("Errors while parsing, the generated types can't be trusted. Bye!"))
sys.exit(1)
default_build_path = "/home/l_frojdh/sls/build/"
fpath = "../../slsDetectorSoftware/src/Detector.cpp"
supported_libclang_versions = (17, 18, 19, 20, 21, 22, 23)
m = []
@@ -118,13 +140,64 @@ def get_arguments(node):
return args
def qualified_name(decl):
"""Name of a declaration including its enclosing scopes, e.g. sls::Positions"""
parts = []
while decl is not None and decl.kind != cindex.CursorKind.TRANSLATION_UNIT:
if decl.spelling:
parts.append(decl.spelling)
decl = decl.semantic_parent
return "::".join(reversed(parts))
def referenced_types(node):
"""Declarations of the types named in the return type of a method or in a parameter"""
for child in node.get_children():
if child.kind == cindex.CursorKind.TYPE_REF:
yield child.referenced
elif node.kind == child.kind == cindex.CursorKind.PARM_DECL:
# parameters of a function pointer
yield from referenced_types(child)
def type_spelling(node, type):
"""
Spelling of the return type of a method or the type of a parameter.
libclang gives a type name as it is written in the source (Positions).
The generated file is outside the sls namespace, so we look up the
declarations and add the scope ourselves (sls::Positions). Names already
written with a scope (defs::xy) are left as they are.
"""
spelling = type.spelling
for decl in referenced_types(node):
unqualified = rf"(?<![\w:]){re.escape(decl.spelling)}(?![\w:])"
spelling = re.sub(unqualified, qualified_name(decl), spelling)
return spelling
def get_compile_args(build_path):
"""Arguments to parse Detector.cpp with, from the compilation database"""
db = cindex.CompilationDatabase.fromDirectory(build_path)
args = list(next(iter(db.getCompileCommands(fpath))).arguments)
# Drop the compiler and the source file. libclang puts "--" before the
# file and anything we add after that is read as a file name
args = args[1:-1]
if args and args[-1] == "--":
args.pop()
args += "-x c++ --std=c++17".split()
for inc in system_include_paths("clang++"):
args += ["-isystem", inc]
return args
def get_arguments_with_default(node):
args = []
for arg in node.get_arguments():
tokens = [t.spelling for t in arg.get_tokens()]
# print(tokens)
if "=" in tokens:
if arg.type.spelling == "sls::Positions": # TODO! automate
if type_spelling(arg, arg.type) == "sls::Positions": # TODO! automate
args.append("py::arg() = Positions{}")
else:
args.append("py::arg()" + "".join(tokens[tokens.index("=") :]))
@@ -137,9 +210,9 @@ def get_arguments_with_default(node):
def get_fdec(node):
args = [a.type.spelling for a in node.get_arguments()]
args = [type_spelling(a, a.type) for a in node.get_arguments()]
if node.result_type.spelling:
return_type = node.result_type.spelling
return_type = type_spelling(node, node.result_type)
else:
return_type = "void"
@@ -223,22 +296,21 @@ if __name__ == "__main__":
libclang_path = find_libclang()
cindex.Config.set_library_file(libclang_path)
check_libclang_version("12")
check_clang_format_version(12)
check_libclang_version(supported_libclang_versions)
check_clang_format_version(17)
check_for_compile_commands_json(cargs.build_path)
print("Parsing functions in Detector.h - ", end="", flush=True)
t0 = time.perf_counter()
# parse functions
db = cindex.CompilationDatabase.fromDirectory(cargs.build_path)
index = cindex.Index.create()
args = db.getCompileCommands(fpath)
args = list(iter(args).__next__().arguments)[0:-1]
args = args + "-x c++ --std=c++11".split()
syspath = system_include_paths("clang++")
incargs = ["-I" + inc for inc in syspath]
args = args + incargs
tu = index.parse(fpath, args=args)
tu = index.parse(
fpath,
args=get_compile_args(cargs.build_path),
# we only need the declarations
options=cindex.TranslationUnit.PARSE_SKIP_FUNCTION_BODIES,
)
check_for_parse_errors(tu)
visit(tu.cursor)
print(green("OK"))
print(f"Parsing took {time.perf_counter()-t0:.3f}s")
+315 -318
View File
File diff suppressed because it is too large. Load diff
@@ -92,7 +92,5 @@ foreach(exe ${JUNGFRAU_EXECUTABLES})
set_property(TARGET ${exe} PROPERTY INTERPROCEDURAL_OPTIMIZATION True)
endif()
sls_install_executable(${exe} DESTINATION bin)
endforeach(exe ${JUNGFRAU_EXECUTABLES})
install(TARGETS ${JUNGFRAU_EXECUTABLES} DESTINATION bin)
@@ -92,19 +92,6 @@ foreach(exe ${MOENCH_EXECUTABLES})
set_property(TARGET ${exe} PROPERTY INTERPROCEDURAL_OPTIMIZATION True)
endif()
# Mainly for RPMs to enable side by side installations of different versions
if(SLS_INSTALL_VERSIONED_BINARIES)
install(PROGRAMS "$<TARGET_FILE:${exe}>"
DESTINATION bin
RENAME "$<TARGET_FILE_BASE_NAME:${exe}>-${PROJECT_VERSION}"
COMPONENT zmq
)
else()
install(TARGETS ${exe}
DESTINATION bin
COMPONENT zmq
)
endif()
sls_install_executable(${exe} DESTINATION bin COMPONENT zmq)
endforeach(exe ${MOENCH_EXECUTABLES})
+1 -5
View File
@@ -119,8 +119,4 @@ if((CMAKE_BUILD_TYPE STREQUAL "Release") AND SLS_LTO_AVAILABLE)
set_property(TARGET slsDetectorGui PROPERTY INTERPROCEDURAL_OPTIMIZATION True)
endif()
install(TARGETS slsDetectorGui
# EXPORT "${TARGETS_EXPORT_NAME}" #do not export gui
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT gui
)
sls_install_executable(slsDetectorGui COMPONENT gui)
+15 -8
View File
@@ -8,12 +8,19 @@ install(TARGETS slsProjectCSettings
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
)
add_subdirectory(ctbDetectorServer)
add_subdirectory(xilinx_ctbDetectorServer)
add_subdirectory(eigerDetectorServer)
add_subdirectory(jungfrauDetectorServer)
add_subdirectory(mythen3DetectorServer)
add_subdirectory(gotthard2DetectorServer)
add_subdirectory(moenchDetectorServer)
add_subdirectory(matterhornServer)
add_subdirectory(slsDetectorServer_cpp)
if(SLS_USE_SIMULATOR)
add_subdirectory(ctbDetectorServer)
add_subdirectory(xilinx_ctbDetectorServer)
add_subdirectory(eigerDetectorServer)
add_subdirectory(jungfrauDetectorServer)
add_subdirectory(mythen3DetectorServer)
add_subdirectory(gotthard2DetectorServer)
add_subdirectory(moenchDetectorServer)
endif()
if(SLS_USE_MATTERHORN OR SLS_USE_SIMULATOR)
add_subdirectory(matterhornServer)
endif()
@@ -44,6 +44,4 @@ set_target_properties(ctbDetectorServer_virtual PROPERTIES
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin
)
install(TARGETS ctbDetectorServer_virtual
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)
sls_install_executable(ctbDetectorServer_virtual)
@@ -2629,13 +2629,10 @@ void *start_timer(void *arg) {
int packetsPerFrame = ceil((double)imageSize / (double)dataSize);
// Generate Data
char *imageData = (char *)malloc(imageSize);
memset(imageData, 0, imageSize);
char *imageData = (char *)calloc(imageSize, 1);
if (imageData == NULL) {
LOG(logERROR, ("Can not allocate image Data RAM."
"Probable cause: Memory Leak.\n"));
return NULL;
LOG(logERROR, ("Could not allocate memory for virtual image\n"));
exit(EXIT_FAILURE);
}
/*
for (int i = 0; i < imageSize; i += sizeof(uint16_t)) {
@@ -38,9 +38,7 @@ set_target_properties(eigerDetectorServer_virtual PROPERTIES
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin
)
install(TARGETS eigerDetectorServer_virtual
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)
sls_install_executable(eigerDetectorServer_virtual)
configure_file(config_eiger.txt ${CMAKE_BINARY_DIR}/bin/config_eiger.txt COPYONLY)
@@ -2783,8 +2783,11 @@ void *start_timer(void *arg) {
npixelsx, databytes));
// Generate data
char imageData[databytes * 2];
memset(imageData, 0, databytes * 2);
char *imageData = (char *)calloc(databytes * 2, 1);
if (imageData == NULL) {
LOG(logERROR, ("Could not allocate memory for virtual image\n"));
exit(EXIT_FAILURE);
}
{
int npixels = NCHAN * NCHIP;
const int pixelsPerPacket = (double)datasize / bytesPerPixel;
@@ -3014,6 +3017,7 @@ void *start_timer(void *arg) {
}
setNextFrameNumber(frameNr + numFrames);
}
free(imageData);
closeUDPSocket(0);
closeUDPSocket(1);
@@ -39,9 +39,7 @@ set_target_properties(gotthard2DetectorServer_virtual PROPERTIES
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin
)
install(TARGETS gotthard2DetectorServer_virtual
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)
sls_install_executable(gotthard2DetectorServer_virtual)
configure_file(config_gotthard2.txt ${CMAKE_BINARY_DIR}/bin/config_gotthard2.txt COPYONLY)
configure_file(detid_gotthard2.txt ${CMAKE_BINARY_DIR}/bin/detid_gotthard2.txt COPYONLY)
@@ -41,9 +41,8 @@ set_target_properties(jungfrauDetectorServer_virtual PROPERTIES
#target_compile_options(jungfrauDetectorServer_virtual PRIVATE -m32)
#target_link_options(jungfrauDetectorServer_virtual PRIVATE -m32)
install(TARGETS jungfrauDetectorServer_virtual
sls_install_executable(jungfrauDetectorServer_virtual
EXPORT "${TARGETS_EXPORT_NAME}"
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)
configure_file(config_jungfrau.txt ${CMAKE_BINARY_DIR}/bin/config_jungfrau.txt COPYONLY)
@@ -301,7 +301,8 @@
#define CONFIG_V12_STRG_CLL_OFST (0)
#define CONFIG_V12_STRG_CLL_MSK (0x0000FFFF << CONFIG_V12_STRG_CLL_OFST)
#define CONFIG_V12_RST_STP_RDCTN_OFST (18)
#define CONFIG_V12_RST_STP_RDCTN_MSK (0x00000001 << CONFIG_V12_RST_STP_RDCTN_OFST)
// CSM mode = high current (100%), low current (16%)
#define CONFIG_V11_CRRNT_SRC_LOW_OFST (19)
#define CONFIG_V11_CRRNT_SRC_LOW_MSK (0x00000001 << CONFIG_V11_CRRNT_SRC_LOW_OFST)
@@ -412,6 +413,10 @@
#define DAQ_CRRNT_SRC_CLMN_SLCT_OFST (20)
#define DAQ_CRRNT_SRC_CLMN_SLCT_MSK (0x0000003F << DAQ_CRRNT_SRC_CLMN_SLCT_OFST)
#define DAQ_GAIN_MODE_MASK (DAQ_FRCE_SWTCH_GAIN_MSK | DAQ_FIX_GAIN_MSK | DAQ_CMP_RST_MSK)
#define DAQ_CDS_BYPASS_OFST (28)
#define DAQ_CDS_BYPASS_MSK (0x00000001 << DAQ_CDS_BYPASS_OFST)
#define DAQ_CDS_RESET_OFST (29)
#define DAQ_CDS_RESET_MSK (0x00000001 << DAQ_CDS_RESET_OFST)
/** Chip Power Register */
#define CHIP_POWER_REG (0x5E << MEM_MAP_SHIFT)
@@ -494,8 +499,8 @@ Time before end of exposure when comparator is disabled */
// tDS = (DST + 1) * 25ns
#define ASIC_CTRL_DS_TMR_OFST (8)
#define ASIC_CTRL_DS_TMR_MSK (0x000000FF << ASIC_CTRL_DS_TMR_OFST)
#define ASIC_CTRL_DS_TMR_VAL ((0x1F << ASIC_CTRL_DS_TMR_OFST) & ASIC_CTRL_DS_TMR_MSK)
#define ASIC_CTRL_DS_TMR_CHIP1_1_VAL ((0xFF << ASIC_CTRL_DS_TMR_OFST) & ASIC_CTRL_DS_TMR_MSK)
#define ASIC_CTRL_DS_TMR_LOW_RES_VAL ((0x1F << ASIC_CTRL_DS_TMR_OFST) & ASIC_CTRL_DS_TMR_MSK)
#define ASIC_CTRL_DS_TMR_HIGH_RES_VAL ((0x5F << ASIC_CTRL_DS_TMR_OFST) & ASIC_CTRL_DS_TMR_MSK)
/* ADC 0 Deserializer Control */
#define ADC_DSRLZR_0_REG (0xF0 << MEM_MAP_SHIFT)
@@ -49,9 +49,15 @@ enum detectorSettings thisSettings = UNINITIALIZED;
static enum CHIPINDEX chipIndex = v1_0;
int highvoltage = 0;
int dacValues[NDAC] = {};
int defaultDacValues[] = DEFAULT_DAC_VALS;
int defaultDacValue_G0[] = SPECIAL_DEFAULT_DYNAMIC_GAIN_VALS;
int defaultDacValue_HG0[] = SPECIAL_DEFAULT_DYNAMICHG0_GAIN_VALS;
int defaultDacValues[NDAC] = DEFAULT_DAC_VALS;
static int defaultDacList_G0[NSPECIALDACS] = SPECIAL_DEFAULT_DYNAMIC_GAIN_VALS;
static int defaultDacList_HG0[NSPECIALDACS] =
SPECIAL_DEFAULT_DYNAMICHG0_GAIN_VALS;
static int defaultDacList_v1_2[NSPECIALDACS] = SPECIAL_DEFAULT_V1_2_GAIN_VALS;
int *defaultDacValue_G0 = defaultDacList_G0;
int *defaultDacValue_HG0 = defaultDacList_HG0;
int32_t clkPhase[NUM_CLOCKS] = {};
int detPos[4] = {};
bool chipConfigured = false;
@@ -67,6 +73,7 @@ bool has_current_src_normal = false;
bool has_current_src_64bit_selection = false;
bool has_current_src_reverse_bits_selection = false;
bool has_storage_start_in_chip_config = false;
bool has_step_reduction = false;
int isInitCheckDone() { return initCheckDone; }
@@ -406,6 +413,8 @@ int setChipIndex(enum CHIPINDEX ind, char *mess) {
return setChipVersionInFPGA(mess);
}
enum CHIPINDEX getChipIndex() { return chipIndex; }
int validateChipIndex(enum CHIPINDEX ind, char *mess) {
if (ind < 0 || ind >= NUM_CHIP_INDICES) {
sprintf(mess, "Invalid chip index %d. Options: %s\n", (int)ind,
@@ -437,6 +446,9 @@ void setChipIndexAllowedFeatures() {
has_current_src_64bit_selection = false;
has_current_src_reverse_bits_selection = false;
has_storage_start_in_chip_config = false;
has_step_reduction = false;
defaultDacValue_G0 = defaultDacList_G0;
defaultDacValue_HG0 = defaultDacList_HG0;
break;
case v1_1:
has_configure_chip = true;
@@ -447,6 +459,9 @@ void setChipIndexAllowedFeatures() {
has_current_src_64bit_selection = true;
has_current_src_reverse_bits_selection = true;
has_storage_start_in_chip_config = true;
has_step_reduction = false;
defaultDacValue_G0 = defaultDacList_G0;
defaultDacValue_HG0 = defaultDacList_HG0;
break;
case v1_2_NORMAL:
case v1_2_LOW_NOISE:
@@ -459,6 +474,9 @@ void setChipIndexAllowedFeatures() {
has_current_src_64bit_selection = true;
has_current_src_reverse_bits_selection = false;
has_storage_start_in_chip_config = true;
has_step_reduction = true;
defaultDacValue_G0 = defaultDacList_v1_2;
defaultDacValue_HG0 = defaultDacList_v1_2;
break;
default:
LOG(logERROR, ("Unknown chip index %d\n", (int)chipIndex));
@@ -617,6 +635,9 @@ void setupDetector() {
clkPhase[i] = 0;
}
chipConfigured = false;
defaultDacValue_G0 = defaultDacList_G0;
defaultDacValue_HG0 = defaultDacList_HG0;
#ifdef VIRTUAL
if (isControlServer) {
sharedMemory_setStatus(IDLE);
@@ -700,6 +721,10 @@ void setupDetector() {
return;
setGainMode(DEFAULT_GAINMODE);
autoCompDisable(DEFAULT_AUTO_COMP_DISABLE);
setComparatorDisableTime(chipIndex == v1_0 ? DEFAULT_COMP_DISABLE_TIME_v1_0
: DEFAULT_COMP_DISABLE_TIME);
setNumFrames(DEFAULT_NUM_FRAMES);
setNumTriggers(DEFAULT_NUM_CYCLES);
setExpTime(DEFAULT_EXPTIME);
@@ -725,6 +750,8 @@ void setupDetector() {
setFilterResistor(DEFAULT_FILTER_RESISTOR);
if (hasFilterCellsFeature())
setNumberOfFilterCells(DEFAULT_FILTER_CELL);
if (hasStepReductionFeature())
enableStepReduction();
if (!isHardwareVersion_1_0()) {
setFlipRows(DEFAULT_FLIP_ROWS);
@@ -2225,6 +2252,8 @@ bool hasStorageCellStartInChipConfig() {
return has_storage_start_in_chip_config;
}
bool hasStepReductionFeature() { return has_step_reduction; }
bool isChipConfigured() { return chipConfigured; }
void configureChip() {
@@ -2292,16 +2321,31 @@ int64_t getComparatorDisableTime() {
}
void configureASICTimer() {
configureAsicPrechargeTimer();
configureAsicDSTimer();
}
void configureAsicPrechargeTimer() {
bus_w(ASIC_CTRL_REG, (bus_r(ASIC_CTRL_REG) & ~ASIC_CTRL_PRCHRG_TMR_MSK) |
ASIC_CTRL_PRCHRG_TMR_VAL);
uint32_t retval = ((bus_r(ASIC_CTRL_REG) & ASIC_CTRL_PRCHRG_TMR_MSK) >>
ASIC_CTRL_PRCHRG_TMR_OFST);
LOG(logINFO, ("Configured ASIC Precharge Timer [0x%x]\n", retval));
}
uint32_t val = ASIC_CTRL_DS_TMR_CHIP1_1_VAL;
// TODO: value of chipindex v1_2 value to be decided.
if (chipIndex == v1_0) {
val = ASIC_CTRL_DS_TMR_VAL;
void configureAsicDSTimer() {
// chipv1.0 => always low res val
// chipv1.1+ => depending on res filter
uint32_t val = ASIC_CTRL_DS_TMR_LOW_RES_VAL;
if (chipIndex != v1_0 && getFilterResistor() == 1) {
val = ASIC_CTRL_DS_TMR_HIGH_RES_VAL;
}
bus_w(ASIC_CTRL_REG, (bus_r(ASIC_CTRL_REG) & ~ASIC_CTRL_DS_TMR_MSK) | val);
LOG(logINFO, ("Configured ASIC Timer [0x%x]\n", bus_r(ASIC_CTRL_REG)));
uint32_t retval = ((bus_r(ASIC_CTRL_REG) & ASIC_CTRL_DS_TMR_MSK) >>
ASIC_CTRL_DS_TMR_OFST);
LOG(logINFO, ("Configured ASIC DS Timer [0x%x]\n", retval));
LOG(logINFO, ("asic reg:0x%x\n", bus_r(ASIC_CTRL_REG)));
}
int setReadoutSpeed(int val) {
@@ -2652,22 +2696,26 @@ int getFilterResistor() {
}
int setFilterResistor(int value) {
if (value != 0 && value != 1) {
LOG(logERROR, ("Invalid value for Filter Resistor: %d\n", value));
return FAIL;
}
// lower resistor
if (value == 0) {
LOG(logINFO, ("Setting Lower Filter Resistor\n"));
bus_w(CONFIG_V11_REG,
bus_r(CONFIG_V11_REG) | CONFIG_V11_FLTR_RSSTR_SMLR_MSK);
return OK;
}
// higher resistor
else if (value == 1) {
LOG(logINFO, ("Setting Higher Filter Resistor\n"));
bus_w(CONFIG_V11_REG,
bus_r(CONFIG_V11_REG) & ~CONFIG_V11_FLTR_RSSTR_SMLR_MSK);
return OK;
}
LOG(logERROR, ("Could not set Filter Resistor. Invalid value %d\n", value));
return FAIL;
configureAsicDSTimer();
return OK;
}
int getNumberOfFilterCells() {
@@ -2681,8 +2729,8 @@ int getNumberOfFilterCells() {
// flip all contents of register //TODO FIRMWARE FIX
regval ^= BIT32_MASK;
#endif
uint32_t retval =
(regval & CONFIG_V11_FLTR_CLL_MSK) >> CONFIG_V11_FLTR_CLL_OFST;
uint32_t retval = (regval & CONFIG_V11_STATUS_FLTR_CLL_MSK) >>
CONFIG_V11_STATUS_FLTR_CLL_OFST;
// count number of bits = which icell
return (__builtin_popcount(retval));
}
@@ -2919,6 +2967,11 @@ void setPedestalMode(int enable, uint8_t frames, uint16_t loops) {
}
}
void enableStepReduction() {
LOG(logINFO, ("Enabling step reduction\n"));
bus_w(CONFIG_V11_REG, bus_r(CONFIG_V11_REG) | CONFIG_V12_RST_STP_RDCTN_MSK);
}
int setTimingInfoDecoder(enum timingInfoDecoder val) {
switch (val) {
case SWISSFEL:
@@ -2962,11 +3015,17 @@ int getElectronCollectionMode() {
void setElectronCollectionMode(int enable) {
LOG(logINFO,
("Setting Collection Mode to %s\n", enable == 0 ? "Hole" : "Electron"));
uint32_t val = bus_r(DAQ_REG);
uint32_t mask =
DAQ_ELCTRN_CLLCTN_MDE_MSK | DAQ_CDS_BYPASS_MSK | DAQ_CDS_RESET_MSK;
if (enable) {
bus_w(DAQ_REG, bus_r(DAQ_REG) | DAQ_ELCTRN_CLLCTN_MDE_MSK);
val |= mask;
LOG(logINFO, ("\tCDS reset and bypassed\n"));
} else {
bus_w(DAQ_REG, bus_r(DAQ_REG) & ~DAQ_ELCTRN_CLLCTN_MDE_MSK);
val &= ~mask;
}
bus_w(DAQ_REG, val);
configureChip();
}
@@ -3070,16 +3129,19 @@ void *start_timer(void *arg) {
const int maxRows = MAX_ROWS_PER_READOUT;
int readNRows = getReadNRows();
if (readNRows == -1) {
LOG(logERROR,
("number of rows is -1. Assuming no partial readout (#rows).\n"));
LOG(logERROR, ("number of rows is -1. Assuming no partial readout "
"(#rows).\n"));
readNRows = MAX_ROWS_PER_READOUT;
}
const int packetsPerFrame =
((maxPacketsPerFrame / 2) * readNRows) / (maxRows / 2);
// Generate data
char imageData[DATA_BYTES];
memset(imageData, 0, DATA_BYTES);
char *imageData = (char *)calloc(DATA_BYTES, 1);
if (imageData == NULL) {
LOG(logERROR, ("Could not allocate memory for virtual image\n"));
exit(EXIT_FAILURE);
}
{
const int npixels = (NCHAN * NCHIP);
const int pixelsPerPacket = dataSize / NUM_BYTES_PER_PIXEL;
@@ -3252,6 +3314,7 @@ void *start_timer(void *arg) {
}
setNextFrameNumber(frameNr + numFrames);
}
free(imageData);
closeUDPSocket(0);
if (numInterfaces == 2) {
@@ -3300,7 +3363,8 @@ int softwareTrigger(int block) {
LOG(logINFO, ("Sending Software Trigger\n"));
bus_w(CONTROL_REG, bus_r(CONTROL_REG) | CONTROL_SOFTWARE_TRIGGER_MSK);
bus_w(CONTROL_REG, bus_r(CONTROL_REG) & ~CONTROL_SOFTWARE_TRIGGER_MSK);
// wait to make sure its out of this state and even 'wait for start frame'
// wait to make sure its out of this state and even 'wait for start
// frame'
usleep(100);
#ifndef VIRTUAL
@@ -63,6 +63,7 @@ int setChipVersionIntFromConfigFile(int val,
char *mess); // for backward compatibility
int setChipVersionStringFromConfigFile(char *cval, char *mess);
int setChipIndex(enum CHIPINDEX ind, char *mess);
enum CHIPINDEX getChipIndex();
int validateChipIndex(enum CHIPINDEX ind, char *mess);
void setChipIndexAllowedFeatures();
int setChipVersionInFPGA(char *mess);
@@ -189,12 +190,15 @@ bool hasCurrentSourceNormalFeature();
bool hasCurrentSource64BitSelectionFeature();
bool hasCurrentSourceReverseBitsSelectionFeature();
bool hasStorageCellStartInChipConfig();
bool hasStepReductionFeature();
bool isChipConfigured();
void configureChip();
int autoCompDisable(int on);
int setComparatorDisableTime(int64_t val);
int64_t getComparatorDisableTime();
void configureASICTimer();
void configureAsicPrechargeTimer();
void configureAsicDSTimer();
int setReadoutSpeed(int val);
int getReadoutSpeed(int *retval);
int setPhase(enum CLKINDEX ind, int val, int degrees);
@@ -220,6 +224,7 @@ uint64_t getSelectCurrentSource();
int getPedestalMode();
void getPedestalParameters(uint8_t *frames, uint16_t *loops);
void setPedestalMode(int enable, uint8_t frames, uint16_t loops);
void enableStepReduction();
int setTimingInfoDecoder(enum timingInfoDecoder val);
int getTimingInfoDecoder(enum timingInfoDecoder *retval);
int getElectronCollectionMode();
@@ -37,6 +37,9 @@
#define CONFIG_FILE ("config_jungfrau.txt")
/** Default Parameters */
#define DEFAULT_AUTO_COMP_DISABLE (0)
#define DEFAULT_COMP_DISABLE_TIME_v1_0 (5 * 1000) // 5us
#define DEFAULT_COMP_DISABLE_TIME (2 * 1000) // 2us
#define DEFAULT_NUM_FRAMES (100 * 1000 * 1000)
#define DEFAULT_STARTING_FRAME_NUMBER (1)
#define DEFAULT_NUM_CYCLES (1)
@@ -55,7 +58,7 @@
#define DEFAULT_STRG_CLL_STRT_CHIP11 (0x3)
#define DEFAULT_STRG_CLL_DLY (0)
#define DEFAULT_FLIP_ROWS (0)
#define DEFAULT_FILTER_RESISTOR (1) // higher resistor
#define DEFAULT_FILTER_RESISTOR (0) // lower resistor
#define DEFAULT_FILTER_CELL (0)
#define DEFAULT_PEDESTAL_MODE (0)
#define DEFAULT_PEDESTAL_FRAMES (1)
@@ -236,6 +239,8 @@ enum MASTERINDEX { MASTER_HARDWARE, OW_MASTER, OW_SLAVE };
{ 1450, 480, 420 }
#define SPECIAL_DEFAULT_DYNAMICHG0_GAIN_VALS \
{ 1550, 450, 620 }
#define SPECIAL_DEFAULT_V1_2_GAIN_VALS \
{ 1500, 480, 460 }
enum NETWORKINDEX { TXN_FRAME, FLOWCTRL_10G };
enum CLKINDEX { RUN_CLK, ADC_CLK, DBIT_CLK, NUM_CLOCKS };
@@ -41,9 +41,7 @@ if(SLS_USE_SIMULATOR)
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin
)
install(TARGETS matterhornDetectorServer_virtual
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)
sls_install_executable(matterhornDetectorServer_virtual)
endif() # maybe better to have a else if build with simulators on one always uses the virtual server in MatterhornApp
if(SLS_USE_MATTERHORN)
@@ -91,9 +89,7 @@ if(SLS_USE_MATTERHORN)
RUNTIME_OUTPUT_DIRECTORY ${RUNTIME_OUTPUT_DIRECTORY}
)
install(TARGETS matterhornDetectorServer
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)
sls_install_executable(matterhornDetectorServer)
endif()
if(SLS_USE_TESTS)
@@ -21,6 +21,8 @@ class BaseMatterhornServerImpl
: public DetectorServerImpl<
is_stop_server<DerivedMatterhornServerImpl>::value> {
public:
using BaseServerImpl =
DetectorServerImpl<is_stop_server<DerivedMatterhornServerImpl>::value>;
BaseMatterhornServerImpl();
~BaseMatterhornServerImpl() = default;
@@ -93,7 +95,7 @@ void BaseMatterhornServerImpl<DerivedMatterhornServerImpl>::setupDetector() {
// TODO: extend
try {
// stop server does not talk to the board
if constexpr (!this->stop_server) {
if constexpr (!BaseServerImpl::stop_server) {
set_num_frames(1);
set_num_triggers(1);
set_counter_mask(0xF); // enable counter all counters by default
@@ -37,9 +37,8 @@ set_target_properties(moenchDetectorServer_virtual PROPERTIES
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin
)
install(TARGETS moenchDetectorServer_virtual
sls_install_executable(moenchDetectorServer_virtual
EXPORT "${TARGETS_EXPORT_NAME}"
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)
configure_file(detid_moench.txt ${CMAKE_BINARY_DIR}/bin/detid_moench.txt COPYONLY)
@@ -1972,8 +1972,11 @@ void *start_timer(void *arg) {
((maxPacketsPerFrame / 2) * readNRows) / (maxRows / 2);
// Generate data
char imageData[DATA_BYTES];
memset(imageData, 0, DATA_BYTES);
char *imageData = (char *)calloc(DATA_BYTES, 1);
if (imageData == NULL) {
LOG(logERROR, ("Could not allocate memory for virtual image\n"));
exit(EXIT_FAILURE);
}
{
const int npixels = (NCHAN * NCHIP);
const int pixelsPerPacket = dataSize / NUM_BYTES_PER_PIXEL;
@@ -2101,6 +2104,7 @@ void *start_timer(void *arg) {
}
setNextFrameNumber(frameNr + numFrames);
}
free(imageData);
closeUDPSocket(0);
if (numInterfaces == 2) {
@@ -41,9 +41,7 @@ set_target_properties(mythen3DetectorServer_virtual PROPERTIES
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin
)
install(TARGETS mythen3DetectorServer_virtual
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)
sls_install_executable(mythen3DetectorServer_virtual)
configure_file(DefaultPattern_mythen3.txt ${CMAKE_BINARY_DIR}/bin/DefaultPattern_mythen3.txt COPYONLY)
configure_file(detid_mythen3.txt ${CMAKE_BINARY_DIR}/bin/detid_mythen3.txt COPYONLY)
@@ -2277,7 +2277,7 @@ int set_num_additional_storage_cells(int file_des) {
#else
// only set
if (Server_VerifyLock() == OK) {
if (!hasStorageCellsFeature()) {
if (!hasStorageCellsFeature() || getChipIndex() > v1_1) {
ret = FAIL;
sprintf(mess, "Cannot set addl. number of storage cells for this "
"chip version\n");
@@ -5,9 +5,6 @@
namespace sls {
template class DetectorServerImpl<true>; // forward declare
template class DetectorServerImpl<false>; // forward declare
template <bool isStopServer>
DetectorServerImpl<isStopServer>::DetectorServerImpl() {
udpDetails[0].srcport = DEFAULT_UDP_SRC_PORTNO;
@@ -114,4 +111,9 @@ DetectorServerImpl<isStopServer>::get_detector_setup_status() const {
return detectorSetupStatus;
}
template class DetectorServerImpl<true>; // explicit instantiation for stop
// server
template class DetectorServerImpl<false>; // explicit instantiation for control
// server
} // namespace sls
@@ -41,9 +41,7 @@ set_target_properties(xilinx_ctbDetectorServer_virtual PROPERTIES
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin
)
install(TARGETS xilinx_ctbDetectorServer_virtual
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)
sls_install_executable(xilinx_ctbDetectorServer_virtual)
configure_file(chip_config_xilinx.txt ${CMAKE_BINARY_DIR}/bin/chip_config_xilinx.txt COPYONLY)
configure_file(reset_chip_xilinx.txt ${CMAKE_BINARY_DIR}/bin/reset_chip_xilinx.txt COPYONLY)
@@ -1601,11 +1601,10 @@ void *start_timer(void *arg) {
packetSize, packetsPerFrame));
// Generate Data
char *imageData = (char *)malloc(imageSize);
memset(imageData, 0, imageSize);
char *imageData = (char *)calloc(imageSize, 1);
if (imageData == NULL) {
LOG(logERROR, ("Can not allocate image.\n"));
return NULL;
LOG(logERROR, ("Could not allocate memory for virtual image\n"));
exit(EXIT_FAILURE);
}
for (int i = 0; i < imageSize; i += sizeof(uint16_t)) {
*((uint16_t *)(imageData + i)) = i;
@@ -1672,6 +1671,8 @@ void *start_timer(void *arg) {
}
}
setNextFrameNumber(frameNr + numFrames);
free(imageData);
closeUDPSocket(0);
sharedMemory_setStatus(IDLE);
+2 -14
View File
@@ -109,21 +109,9 @@ if(SLS_USE_TEXTCLIENT)
set_property(TARGET ${val1} PROPERTY INTERPROCEDURAL_OPTIMIZATION True)
endif()
# Mainly for RPMs to enable side by side installations of different versions
if(SLS_INSTALL_VERSIONED_BINARIES)
install(PROGRAMS "$<TARGET_FILE:${val1}>"
DESTINATION bin
RENAME "$<TARGET_FILE_BASE_NAME:${val1}>-${PROJECT_VERSION}"
COMPONENT cli
)
else()
install(TARGETS ${val1}
DESTINATION bin
COMPONENT cli
)
endif()
sls_install_executable(${val1} DESTINATION bin COMPONENT cli)
endforeach()
endif(SLS_USE_TEXTCLIENT)
@@ -277,8 +277,8 @@ TEST_CASE("extrastoragecells", "[.detectorintegration]") {
auto det_type = det.getDetectorType().squash();
if (det_type == defs::JUNGFRAU) {
auto chipVersion = chipVersionToX10(det.getChipVersion().squash());
// chip version 1.0 and 1.2
if (chipVersion == 10 || chipVersion == 12) {
// currently only chip version 1.0, later firmware for 1.2
if (chipVersion == 10) { //} || chipVersion == 12) {
auto prev_val = det.getNumberOfAdditionalStorageCells().tsquash(
"inconsistent #additional storage cells to test");
{
+3 -13
View File
@@ -173,22 +173,12 @@ if (SLS_USE_RECEIVER_BINARIES)
slsMultiReceiver
slsFrameSynchronizer
)
if(SLS_INSTALL_VERSIONED_BINARIES)
message(STATUS "Versioned binaries will be installed")
foreach(target IN LISTS SLS_RECEIVER_BINARIES)
install(PROGRAMS "$<TARGET_FILE:${target}>"
DESTINATION ${CMAKE_INSTALL_BINDIR}
RENAME "$<TARGET_FILE_BASE_NAME:${target}>-${PROJECT_VERSION}"
COMPONENT receiver
)
endforeach()
else()
install(TARGETS ${SLS_RECEIVER_BINARIES}
foreach(target IN LISTS SLS_RECEIVER_BINARIES)
sls_install_executable(${target}
EXPORT "${TARGETS_EXPORT_NAME}"
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
COMPONENT receiver
)
endif()
endforeach()
+4 -1
View File
@@ -81,7 +81,10 @@ void Fifo::DestroyFifos() {
fifoStream = nullptr;
}
void Fifo::FreeAddress(char *&address) { fifoFree->push(address); }
void Fifo::FreeAddress(char *&address) {
std::lock_guard<std::mutex> lock(fifoFreeMutex);
fifoFree->push(address);
}
void Fifo::GetNewAddress(char *&address) {
int temp = fifoFree->getDataValue();
+4
View File
@@ -16,6 +16,7 @@
#include "sls/sls_detector_defs.h"
#include <atomic>
#include <mutex>
namespace sls {
@@ -52,6 +53,9 @@ class Fifo : private virtual slsDetectorDefs {
int fifoDepth;
std::atomic<int> status_fifoBound;
std::atomic<int> status_fifoFree;
/** fifoFree has several producers, CircularFifo allows only one.
* Aligned to avoid false sharing with the members above */
alignas(128) std::mutex fifoFreeMutex;
};
} // namespace sls
+1 -1
View File
@@ -8,6 +8,6 @@
#define APIMOENCH "0.0.0 0x260424"
#define APIEIGER "0.0.0 0x260807"
#define APIXILINXCTB "0.0.0 0x260813"
#define APIJUNGFRAU "0.0.0 0x260902"
#define APIJUNGFRAU "0.0.0 0x261002"
#define APIMYTHEN3 "0.0.0 0x260506"
#define APIMATTERHORN "0.0.0 0x260529"