Merge branch 'developer' into dev/xilinx_power_cmd
Run Simulator Tests on local RHEL9 / build (push) Failing after 3m45s
Build on RHEL8 docker image / build (push) Successful in 4m58s
Build on RHEL9 docker image / build (push) Successful in 5m0s
Run Simulator Tests on local RHEL8 / build (push) Failing after 5m24s

This commit is contained in:
2026-03-05 12:34:49 +01:00
33 changed files with 266 additions and 95 deletions
@@ -1,4 +1,4 @@
name: Build on RHEL8
name: Build on RHEL8 docker image
on:
push:
@@ -26,4 +26,17 @@ jobs:
- name: C++ unit tests
working-directory: ${{gitea.workspace}}/build
run: ctest -j1 --rerun-failed --output-on-failure
run: ctest -j1 --rerun-failed --output-on-failure
- name: Install Python dependencies
run: |
python3.12 -m pip install --upgrade pip
python3.12 -m pip install pytest
python3.12 -m pip install colorama
python3.12 -m pip install numpy
- name: Python unit tests
working-directory: ${{gitea.workspace}}
run: |
export PYTHONPATH=$PWD/build/bin:$PYTHONPATH
python3.12 -m pytest python/tests
@@ -0,0 +1,40 @@
name: Build on RHEL9 docker image
on:
push:
workflow_dispatch:
permissions:
contents: read
jobs:
build:
runs-on: "ubuntu-latest"
container:
image: gitea.psi.ch/detectors/rhel9-detectors-dev
steps:
- uses: actions/checkout@v4
- name: Build library
run: |
mkdir build && cd build
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 -j1 --rerun-failed --output-on-failure
- name: Install Python dependencies
run: |
python3.12 -m pip install --upgrade pip
python3.12 -m pip install pytest
python3.12 -m pip install colorama
python3.12 -m pip install numpy
- name: Python unit tests
working-directory: ${{gitea.workspace}}
run: |
export PYTHONPATH=$PWD/build/bin:$PYTHONPATH
python3.12 -m pytest python/tests
@@ -1,4 +1,4 @@
name: Build on local RHEL8
name: Build and Deploy on local RHEL8
on:
push:
@@ -21,7 +21,7 @@ jobs:
conda activate det
mkdir build && cd build
conda activate det
cmake .. -DSLS_USE_PYTHON=ON
cmake .. -DSLS_USE_PYTHON=ON -DSLS_USE_SIMULATOR=ON -DSLS_USE_GUI=ON
make -j 2
- name: Deploy to NFS update server
+1 -5
View File
@@ -2,11 +2,7 @@ name: Run Simulator Tests on local RHEL8
on:
push:
branches:
- developer
- main
- 'dev/*'
- '*.*.*.rc'
workflow_dispatch:
env:
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
@@ -1,4 +1,4 @@
name: Build on local RHEL9
name: Build and Deploy on local RHEL9
on:
push:
@@ -18,7 +18,7 @@ jobs:
- 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 ..
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 -DSLS_USE_SIMULATOR=ON -DSLS_USE_GUI=ON ..
make -j 2
- name: Deploy to NFS update server
+1 -5
View File
@@ -2,11 +2,7 @@ name: Run Simulator Tests on local RHEL9
on:
push:
branches:
- developer
- main
- 'dev/*'
- '*.*.*.rc'
workflow_dispatch:
env:
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
-27
View File
@@ -1,27 +0,0 @@
name: Build on RHEL9
on:
push:
workflow_dispatch:
permissions:
contents: read
jobs:
build:
runs-on: "ubuntu-latest"
container:
image: gitea.psi.ch/detectors/rhel9-detectors-dev
steps:
- uses: actions/checkout@v4
- name: Build library
run: |
mkdir build && cd build
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 -j1 --rerun-failed --output-on-failure
+6 -1
View File
@@ -25,8 +25,12 @@ void init_bit(py::module &m) {
})
.def("__str__", &RegisterAddress::str)
.def("value", &RegisterAddress::value)
.def("__int__", &RegisterAddress::value)
.def(py::self == py::self)
.def(py::self != py::self);
.def(py::self != py::self)
.def("__add__",&RegisterAddress::operator+)
.def("__radd__",&RegisterAddress::operator+)
.def("__iadd__",&RegisterAddress::operator+=, py::return_value_policy::reference_internal);
py::class_<BitAddress>(m, "BitAddress")
.def(py::init())
@@ -51,6 +55,7 @@ void init_bit(py::module &m) {
})
.def("__str__", &RegisterValue::str)
.def("value", &RegisterValue::value)
.def("__int__", &RegisterValue::value)
.def(py::self == py::self)
.def(py::self != py::self)
.def("__or__", [](const RegisterValue &lhs,
+11 -1
View File
@@ -1,4 +1,5 @@
from slsdet.bits import clearbit, clearbit_arr, setbit, setbit_arr
from slsdet import RegisterAddress
import numpy as np
@@ -47,4 +48,13 @@ def test_setbit_arr():
def test_clearbit_arr():
arr = np.array((5, 5, 5), dtype=np.int8)
clearbit_arr(0, arr)
assert all(arr == (4, 4, 4))
assert all(arr == (4, 4, 4))
def test_RegisterAddress_addition():
r = RegisterAddress(0x10)
r2 = r + 0x5
assert r2.value() == 0x15
r3 = 0x5 + r
assert r3.value() == 0x15
r += 0x5
assert r.value() == 0x15
@@ -28,7 +28,7 @@ boot: $(OBJS)
version_name=APICTB
version_path=slsDetectorServers/ctbDetectorServer
versioning:
cd ../../ && echo $(PWD) && echo `tput setaf 6; python updateAPIVersion.py $(version_name) $(version_path); tput sgr0;`
cd ../../ && echo $(PWD) && echo `tput setaf 6; python etc/updateAPIVersion.py $(version_name) $(version_path); tput sgr0;`
$(PROGS): $(OBJS)
@@ -28,7 +28,7 @@ boot: $(OBJS)
version_name=APIEIGER
version_path=slsDetectorServers/eigerDetectorServer
versioning:
cd ../../ && echo $(PWD) && echo `tput setaf 6; python updateAPIVersion.py $(version_name) $(version_path); tput sgr0;`
cd ../../ && echo $(PWD) && echo `tput setaf 6; python etc/updateAPIVersion.py $(version_name) $(version_path); tput sgr0;`
$(PROGS): $(OBJS)
@@ -27,7 +27,7 @@ boot: $(OBJS)
version_name=APIGOTTHARD2
version_path=slsDetectorServers/gotthard2DetectorServer
versioning:
cd ../../ && echo $(PWD) && echo `tput setaf 6; python updateAPIVersion.py $(version_name) $(version_path); tput sgr0;`
cd ../../ && echo $(PWD) && echo `tput setaf 6; python etc/updateAPIVersion.py $(version_name) $(version_path); tput sgr0;`
$(PROGS): $(OBJS)
@@ -27,7 +27,7 @@ boot: $(OBJS)
version_name=APIJUNGFRAU
version_path=slsDetectorServers/jungfrauDetectorServer
versioning:
cd ../../ && echo $(PWD) && echo `tput setaf 6; python updateAPIVersion.py $(version_name) $(version_path); tput sgr0;`
cd ../../ && echo $(PWD) && echo `tput setaf 6; python etc/updateAPIVersion.py $(version_name) $(version_path); tput sgr0;`
$(PROGS): $(OBJS)
@@ -27,7 +27,7 @@ boot: $(OBJS)
version_name=APIMOENCH
version_path=slsDetectorServers/moenchDetectorServer
versioning:
cd ../../ && echo $(PWD) && echo `tput setaf 6; python updateAPIVersion.py $(version_name) $(version_path); tput sgr0;`
cd ../../ && echo $(PWD) && echo `tput setaf 6; python etc/updateAPIVersion.py $(version_name) $(version_path); tput sgr0;`
$(PROGS): $(OBJS)
@@ -28,7 +28,7 @@ boot: $(OBJS)
version_name=APIMYTHEN3
version_path=slsDetectorServers/mythen3DetectorServer
versioning:
cd ../../ && echo $(PWD) && echo `tput setaf 6; python updateAPIVersion.py $(version_name) $(version_path); tput sgr0;`
cd ../../ && echo $(PWD) && echo `tput setaf 6; python etc/updateAPIVersion.py $(version_name) $(version_path); tput sgr0;`
$(PROGS): $(OBJS)
@@ -1641,7 +1641,9 @@ int get_adc(int file_des) {
// valid index
if (ret == OK) {
LOG(logDEBUG1, ("Getting ADC %d\n", serverAdcIndex));
#if defined(MYTHEN3D) || defined(GOTTHARD2D) || defined(XILINX_CHIPTESTBOARDD)
#if defined(XILINX_CHIPTESTBOARDD)
ret = getADC(serverAdcIndex, &retval, mess);
#elif defined(MYTHEN3D) || defined(GOTTHARD2D)
ret = getADC(serverAdcIndex, &retval);
if (ret == FAIL) {
if (ind == TEMPERATURE_FPGA) {
@@ -39,7 +39,7 @@ boot: $(OBJS)
version_name=APIXILINXCTB
version_path=slsDetectorServers/xilinx_ctbDetectorServer
versioning:
cd ../../ && echo $(PWD) && echo `tput setaf 6; python updateAPIVersion.py $(version_name) $(version_path); tput sgr0;`
cd ../../ && echo $(PWD) && echo `tput setaf 6; python etc/updateAPIVersion.py $(version_name) $(version_path); tput sgr0;`
$(PROGS): $(OBJS)
@@ -1482,11 +1482,8 @@ int setPower(enum DACINDEX ind, int val, char *mess) {
return OK;
}
int getADC(enum ADCINDEX ind, int *value) {
int getADC(enum ADCINDEX ind, int *value, char *mess) {
*value = 0;
#ifdef VIRTUAL
return OK;
#endif
switch (ind) {
// slow adcs
case S_ADC0:
@@ -1498,44 +1495,60 @@ int getADC(enum ADCINDEX ind, int *value) {
case S_ADC6:
case S_ADC7:
LOG(logDEBUG1, ("Reading Slow ADC Channel %d\n", (int)ind - S_ADC0));
return getSlowADC((int)ind - S_ADC0, value);
return getSlowADC((int)ind - S_ADC0, value, mess);
case TEMP_FPGA:
LOG(logDEBUG1, ("Reading FPGA Temperature\n"));
return getTemperature(value);
return getTemperature(value, mess);
default:
LOG(logERROR, ("Adc Index %d not defined \n", (int)ind));
snprintf(mess, MAX_STR_LENGTH, "Adc Index %d not defined\n", (int)ind);
LOG(logERROR, (mess));
return FAIL;
}
}
int getSlowADC(int ichan, int *retval) {
int getSlowADC(int ichan, int *retval, char *mess) {
*retval = 0;
#ifndef VIRTUAL
int fval = 0;
#ifdef VIRTUAL
fval = 1;
#else
char fname[MAX_STR_LENGTH];
memset(fname, 0, MAX_STR_LENGTH);
sprintf(fname, SLOWADC_DRIVER_FILE_NAME, ichan);
LOG(logDEBUG1, ("fname %s\n", fname));
if (readParameterFromFile(fname, "slow adc", retval) == FAIL) {
LOG(logERROR, ("Could not get slow adc\n"));
if (readParameterFromFile(fname, "slow adc", &fval) == FAIL) {
snprintf(mess, MAX_STR_LENGTH, "Could not read slow adc channel %d\n",
ichan);
LOG(logERROR, (mess));
return FAIL;
}
// TODO assuming already converted to uV
// convert to uV
// double value = SLOWDAC_CONVERTION_FACTOR_TO_UV * (double)(*retval);
// LOG(logINFO, ("Slow ADC [%d]: %f uV\n", ichan, value));
//*retval = (int)value;
LOG(logINFO, ("Slow ADC [%d]: %d uV\n", ichan, (*retval)));
#endif
// value in uV
int refMaxuv = SLOW_ADC_MAX_MV * 1000;
int regMinuv = 0;
int maxSteps = SLOW_ADC_MAX_STEPS;
if (ConvertToDifferentRange(0, maxSteps, regMinuv, refMaxuv, fval,
retval) == FAIL) {
snprintf(mess, MAX_STR_LENGTH,
"Could not convert slow adc channel (fval:0x%x) to uv\n",
fval);
LOG(logERROR, (mess));
return -1;
}
LOG(logINFO,
("\tSlow adc [%d]: %d uV (reg: 0x%x)\n", ichan, *retval, fval));
return OK;
}
int getTemperature(int *retval) {
int getTemperature(int *retval, char *mess) {
*retval = 0;
#ifndef VIRTUAL
if (readParameterFromFile(TEMP_DRIVER_FILE_NAME, "temperature", retval) ==
FAIL) {
snprintf(mess, MAX_STR_LENGTH, "Could not read temperature\n");
LOG(logERROR, ("Could not get temperature\n"));
return FAIL;
}
@@ -143,9 +143,9 @@ int getPowerRail(enum PWRINDEX ind, int *retval, char *mess);
int getPower(enum DACINDEX ind, int *retval, char *mess);
int setPower(enum DACINDEX ind, int val, char *mess);
int getADC(enum ADCINDEX ind, int *value);
int getSlowADC(int ichan, int *retval);
int getTemperature(int *retval);
int getADC(enum ADCINDEX ind, int *value, char *mess);
int getSlowADC(int ichan, int *retval, char *mess);
int getTemperature(int *retval, char *mess);
int setHighVoltage(int val);
// parameters - timing, extsig
@@ -65,11 +65,13 @@
#define MAX_ANALOG_SAMPLES (0x3FFF)
#define MAX_DIGITAL_SAMPLES (0x3FFF)
#define DAC_MIN_MV (0)
#define DAC_MAX_MV (2048)
#define POWER_RGLTR_MIN (1041)
#define POWER_RGLTR_MAX (2661)
#define VIO_MIN_MV (1200) // for fpga to function
#define DAC_MIN_MV (0)
#define DAC_MAX_MV (2048)
#define POWER_RGLTR_MIN (1041)
#define POWER_RGLTR_MAX (2661)
#define VIO_MIN_MV (1200) // for fpga to function
#define SLOW_ADC_MAX_MV (2500) // AD7689
#define SLOW_ADC_MAX_STEPS (0xFFFF + 1) // AD7689
/* Defines in the Firmware */
#define WAIT_TIME_PATTERN_READ (10)
+7
View File
@@ -1831,6 +1831,13 @@ void DetectorImpl::setRxROI(const std::vector<defs::ROI> &args) {
auto moduleGlobalRoi = getModuleROI(iModule);
// at most 2 rois per module (for each port)
std::vector<defs::ROI> portRois(nPortsPerModule);
for (auto &roi : portRois) {
roi.setNoRoi();
if (shm()->numberOfChannels.y == 1) {
roi.ymin = -1;
roi.ymax = -1;
}
}
// check overlap with module
for (const auto &arg : args) {
@@ -540,6 +540,16 @@ TEST_CASE("rx_roi", "[.detectorintegration][.disable_check_data_file]") {
REQUIRE(oss.str() == "rx_roi [[5, 10], [" + stringMin + ", " +
stringMax + "]]\n");
// setting to only one port and verify individual roi
{
REQUIRE_NOTHROW(
caller.call("rx_roi", {"[5, 10, -1, -1]"}, -1, PUT));
std::ostringstream oss, oss1;
REQUIRE_NOTHROW(caller.call("rx_roi", {}, 0, GET, oss));
REQUIRE_NOTHROW(caller.call("rx_roi", {}, 1, GET, oss1));
REQUIRE(oss.str() == "rx_roi [[5, 10]]\n");
REQUIRE(oss1.str() == "rx_roi [[0, 0]]\n");
}
// verify individual roi
{
stringMin = std::to_string(moduleSize.x - 50);
@@ -643,6 +653,38 @@ TEST_CASE("rx_roi", "[.detectorintegration][.disable_check_data_file]") {
REQUIRE(oss.str() == "rx_roi [[5, 10, 20, 30], [" + stringMin +
", " + stringMax + ", 20, 30]]\n");
// setting to only one port and verify individual roi
{
REQUIRE_NOTHROW(
caller.call("rx_roi", {"[5, 10, 20, 30]"}, -1, PUT));
std::ostringstream oss, oss1;
REQUIRE_NOTHROW(caller.call("rx_roi", {}, 0, GET, oss));
// eiger returns 2 values for 2 ports per module
if (det_type == defs::EIGER) {
REQUIRE(oss.str() ==
"rx_roi [[5, 10, 20, 30], [0, 0, 0, 0]]\n");
}
// others return only 1 roi per module (1 port per module)
else {
REQUIRE(oss.str() == "rx_roi [[5, 10, 20, 30]]\n");
}
if (det.size() > 1) {
REQUIRE_NOTHROW(
caller.call("rx_roi", {}, 1, GET, oss1));
// eiger returns 2 values for 2 ports per module
if (det_type == defs::EIGER) {
REQUIRE(oss1.str() ==
"rx_roi [[0, 0, 0, 0], [0, 0, 0, 0]]\n");
}
// others return only 1 roi per module (1 port per
// module)
else {
REQUIRE(oss1.str() == "rx_roi [[0, 0, 0, 0]]\n");
}
}
}
// verify individual roi
{
stringMin = std::to_string(portSize.x - delta);
@@ -710,6 +752,43 @@ TEST_CASE("rx_roi", "[.detectorintegration][.disable_check_data_file]") {
REQUIRE(oss.str() == "rx_roi [[5, 10, 20, 30], [25, 28, " +
stringMin + ", " + stringMax + "]]\n");
// setting to only one port and verify individual roi
{
REQUIRE_NOTHROW(
caller.call("rx_roi", {"[ 5, 10, 20, 30]"}, -1, PUT));
std::ostringstream oss, oss1;
REQUIRE_NOTHROW(caller.call("rx_roi", {}, 0, GET, oss));
// 2 ports
if (((det_type == defs::JUNGFRAU ||
det_type == defs::MOENCH) &&
(numinterfaces == 2)) ||
(det_type == defs::EIGER)) {
REQUIRE(oss.str() ==
"rx_roi [[5, 10, 20, 30], [0, 0, 0, 0]]\n");
}
// others return only 1 roi per module (1 port per module)
else {
REQUIRE(oss.str() == "rx_roi [[5, 10, 20, 30]]\n");
}
if (det.size() > 2) {
REQUIRE_NOTHROW(
caller.call("rx_roi", {}, 1, GET, oss1));
// 2 ports
if (((det_type == defs::JUNGFRAU ||
det_type == defs::MOENCH) &&
(numinterfaces == 2)) ||
(det_type == defs::EIGER)) {
REQUIRE(oss1.str() ==
"rx_roi [[0, 0, 0, 0], [0, 0, 0, 0]]\n");
}
// others return only 1 roi per module (1 port per
// module)
else {
REQUIRE(oss1.str() == "rx_roi [[0, 0, 0, 0]]\n");
}
}
}
// verify individual roi
{
stringMin = std::to_string(portSize.y - delta);
@@ -741,7 +820,7 @@ TEST_CASE("rx_roi", "[.detectorintegration][.disable_check_data_file]") {
REQUIRE(oss1.str() ==
"rx_roi [[20, 30, " + stringMin + ", " +
std::to_string(portSize.y - 1) +
"], [-1, -1]]\n");
"], [0, 0, 0, 0]]\n");
} else {
REQUIRE(oss1.str() ==
"rx_roi [[20, 30, " + stringMin + ", " +
@@ -42,9 +42,11 @@ constexpr int shm_id = 10;
// macOS does not expose shm in the filesystem
#ifndef __APPLE__
const char *env_p = std::getenv(SHM_ENV_NAME);
std::string env_name = env_p ? ("_" + std::string(env_p)) : "";
const std::string file_path =
std::string("/dev/shm/slsDetectorPackage_detector_") +
std::to_string(shm_id);
std::to_string(shm_id) + env_name;
TEST_CASE("Free obsolete (without isValid)", "[detector][shm]") {
+14
View File
@@ -36,6 +36,15 @@ class RegisterAddress {
constexpr bool operator!=(const RegisterAddress &other) const {
return (value_ != other.value_);
}
constexpr RegisterAddress &operator+=(uint32_t offset) noexcept {
value_ += offset;
return *this;
}
constexpr RegisterAddress operator+(uint32_t offset) const noexcept {
RegisterAddress tmp(*this);
tmp += offset;
return tmp;
}
};
class BitAddress {
@@ -102,4 +111,9 @@ 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);
constexpr RegisterAddress operator+(uint32_t offset,
const RegisterAddress &addr) noexcept {
return addr + offset;
}
} // namespace sls
+7 -7
View File
@@ -3,10 +3,10 @@
/** API versions */
#define APILIB "0.0.0 0x250909"
#define APIRECEIVER "0.0.0 0x250822"
#define APICTB "0.0.0 0x260219"
#define APIGOTTHARD2 "0.0.0 0x260218"
#define APIMOENCH "0.0.0 0x260218"
#define APIEIGER "0.0.0 0x260218"
#define APIXILINXCTB "0.0.0 0x260227"
#define APIJUNGFRAU "0.0.0 0x260218"
#define APIMYTHEN3 "0.0.0 0x260219"
#define APICTB "0.0.0 0x260227"
#define APIGOTTHARD2 "0.0.0 0x260227"
#define APIMOENCH "0.0.0 0x260227"
#define APIEIGER "0.0.0 0x260227"
#define APIXILINXCTB "0.0.0 0x260305"
#define APIJUNGFRAU "0.0.0 0x260227"
#define APIMYTHEN3 "0.0.0 0x260227"
+24 -5
View File
@@ -43,7 +43,7 @@ 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]") {
TEST_CASE("Convert RegisterAddress using classes ", "[support]") {
std::vector<uint32_t> vec_addr{0x305, 0xffffffff, 0x0, 0x34550987,
0x1fff1fff};
std::vector<std::string> vec_ans{"0x305", "0xffffffff", "0x0", "0x34550987",
@@ -64,7 +64,7 @@ TEST_CASE("Convert RegisterAddress using classes ", "[support][.bit_utils]") {
}
}
TEST_CASE("Convert RegisterValue using classes ", "[support][.bit_utils]") {
TEST_CASE("Convert RegisterValue using classes ", "[support]") {
std::vector<uint32_t> vec_addr{0x305, 0xffffffff, 0x0, 500254562,
0x1fff1fff};
std::vector<std::string> vec_ans{"0x305", "0xffffffff", "0x0", "0x1dd14762",
@@ -80,11 +80,10 @@ TEST_CASE("Convert RegisterValue using classes ", "[support][.bit_utils]") {
CHECK(reg0.str() == vec_ans[i]);
CHECK((reg0 | 0xffffffffu) == RegisterValue(0xffffffffu));
CHECK((reg0 | 0x0) == reg0);
CHECK((reg0 | 0x1) == reg0);
}
}
TEST_CASE("Convert BitAddress using classes", "[support][.bit_utils]") {
TEST_CASE("Convert BitAddress using classes", "[support]") {
std::vector<RegisterAddress> vec_addr{
RegisterAddress(0x305), RegisterAddress(0xffffffffu),
RegisterAddress(0x0), RegisterAddress(0x34550987),
@@ -123,7 +122,7 @@ TEST_CASE("Convert BitAddress using classes", "[support][.bit_utils]") {
}
TEST_CASE("Output operator gives same result as string",
"[support][.bit_utils]") {
"[support]") {
{
RegisterAddress addr{0x3456af};
std::ostringstream os;
@@ -148,3 +147,23 @@ TEST_CASE("Output operator gives same result as string",
}
} // namespace sls
TEST_CASE("RegisterAddress addition with uint", "[support]") {
using sls::RegisterAddress;
RegisterAddress r{0x10u};
// member operator+
auto r_plus = r + 5u;
CHECK(r_plus == RegisterAddress(0x15u));
// original unchanged
CHECK(r == RegisterAddress(0x10u));
// operator+=
r += 2u;
CHECK(r == RegisterAddress(0x12u));
// non-member uint + RegisterAddress
auto uint_plus = 3u + r; // 0x12 + 3 == 0x15
CHECK(uint_plus == RegisterAddress(0x15u));
}