mirror of
https://github.com/slsdetectorgroup/slsDetectorPackage.git
synced 2026-03-10 19:47:42 +01:00
Merge branch 'developer' into fix/pyfixture_test
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -8,6 +8,7 @@ to be installed.
|
||||
When the Detector API is updated this file should be run
|
||||
manually.
|
||||
"""
|
||||
import os
|
||||
from clang import cindex
|
||||
import subprocess
|
||||
import argparse
|
||||
@@ -33,6 +34,24 @@ def green(msg):
|
||||
return f"{GREENC}{msg}{ENDC}"
|
||||
|
||||
|
||||
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)
|
||||
|
||||
# fallback: system-wide search
|
||||
path = ctypes.util.find_library("clang")
|
||||
if path:
|
||||
return path
|
||||
|
||||
raise FileNotFoundError("libclang not found in CONDA_PREFIX or system paths.")
|
||||
|
||||
|
||||
def check_libclang_version(required="12"):
|
||||
# Use already-loaded libclang, or let cindex resolve it
|
||||
lib = ctypes.CDLL(cindex.Config.library_file or ctypes.util.find_library("clang"))
|
||||
@@ -201,7 +220,9 @@ if __name__ == "__main__":
|
||||
action="store_true",
|
||||
)
|
||||
cargs = parser.parse_args()
|
||||
|
||||
|
||||
libclang_path = find_libclang()
|
||||
cindex.Config.set_library_file(libclang_path)
|
||||
check_libclang_version("12")
|
||||
check_clang_format_version(12)
|
||||
check_for_compile_commands_json(cargs.build_path)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -1813,6 +1814,148 @@ class Detector(CppDetectorApi):
|
||||
[Eiger] Address is +0x100 for only left, +0x200 for only right.
|
||||
"""
|
||||
return self._register
|
||||
|
||||
def define_reg(self, *, name: str, addr):
|
||||
"""
|
||||
[Ctb] Define a name for a register to be used later with reg.
|
||||
|
||||
Example
|
||||
--------
|
||||
|
||||
d.define_reg('myreg',addr=0x6)
|
||||
d.define_reg('myreg',addr=RegisterAddress(0x6))')
|
||||
"""
|
||||
if isinstance(addr, int):
|
||||
addr = RegisterAddress(addr)
|
||||
elif not isinstance(addr, RegisterAddress):
|
||||
raise ValueError("addr must int or RegisterAddress")
|
||||
self.setRegisterDefinition(name, addr)
|
||||
|
||||
|
||||
def define_bit(self, *, name: str, addr, bit_position:int=None):
|
||||
"""
|
||||
[Ctb] Define a name for a bit in a register to be used later with setBit/clearBit/getBit
|
||||
|
||||
Example
|
||||
--------
|
||||
|
||||
bit1 = BitAddress(RegisterAddress(0x6),7)
|
||||
d.define_bit('mybit',addr=bit1)
|
||||
d.define_bit('mybit',addr=0x6, bit=7)
|
||||
d.define_bit('mybit',addr=RegisterAddress(0x6), bit=7)
|
||||
d.define_bit('mybit',addr='myreg', bit=7) #if myreg defined before
|
||||
"""
|
||||
|
||||
# bitAddress
|
||||
if isinstance(addr, BitAddress):
|
||||
if bit_position is not None:
|
||||
raise ValueError("If addr is BitAddress, bit_position must be None")
|
||||
bitaddr = addr
|
||||
# register name/address + bit_position
|
||||
else:
|
||||
if isinstance(addr, str):
|
||||
addr = self.getRegisterAddress(addr)
|
||||
elif isinstance(addr, int):
|
||||
addr = RegisterAddress(addr)
|
||||
elif not isinstance(addr, RegisterAddress):
|
||||
raise ValueError("addr must be str, int or RegisterAddress")
|
||||
|
||||
if bit_position is None:
|
||||
raise ValueError("bit_position must be provided if addr is used.")
|
||||
if not isinstance(bit_position, int):
|
||||
raise ValueError("bit_position must be int")
|
||||
|
||||
bitaddr = BitAddress(addr, bit_position)
|
||||
|
||||
self.setBitDefinition(name, bitaddr)
|
||||
|
||||
def _resolve_bit_name_or_addr(self, bitname_or_addr, bit_position=None):
|
||||
"""
|
||||
Internal function to resolve bit name or address arguments for setBit, clearBit and getBit
|
||||
Returns a BitAddress
|
||||
"""
|
||||
#Old usage passing two ints or [RegisterAddress and int]
|
||||
if isinstance(bitname_or_addr, (int, RegisterAddress)):
|
||||
if bit_position is None:
|
||||
raise ValueError("bit_position must be provided when passing int address")
|
||||
if not isinstance(bit_position, int):
|
||||
raise ValueError("bit_position must be int")
|
||||
return BitAddress(bitname_or_addr, bit_position)
|
||||
|
||||
# New usage with str or BitAddress
|
||||
# str
|
||||
if isinstance(bitname_or_addr, str):
|
||||
bitname_or_addr = self.getBitAddress(bitname_or_addr)
|
||||
|
||||
if bit_position is not None:
|
||||
raise ValueError("bit_position must be None when passing str or BitAddress")
|
||||
|
||||
#must now be a BitAddress
|
||||
if not isinstance(bitname_or_addr, BitAddress):
|
||||
raise ValueError("bitname_or_addr must be str, BitAddress, int or RegisterAddress")
|
||||
|
||||
return bitname_or_addr
|
||||
|
||||
|
||||
def setBit(self, bitname_or_addr, bit_position=None):
|
||||
"""
|
||||
Set a bit in a register
|
||||
[Ctb] Can use a named bit address
|
||||
|
||||
Example
|
||||
--------
|
||||
d.setBit(0x5, 3)
|
||||
d.setBit(RegisterAddress(0x5), 3)
|
||||
|
||||
#Ctb
|
||||
d.setBit('mybit')
|
||||
|
||||
myreg = RegisterAddress(0x5)
|
||||
mybit = BitAddress(myreg, 5)
|
||||
d.setBit(mybit)
|
||||
"""
|
||||
resolved = self._resolve_bit_name_or_addr(bitname_or_addr, bit_position)
|
||||
return super().setBit(resolved)
|
||||
|
||||
def clearBit(self, bitname_or_addr, bit_position=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)
|
||||
"""
|
||||
resolved = self._resolve_bit_name_or_addr(bitname_or_addr, bit_position)
|
||||
return super().clearBit(resolved)
|
||||
|
||||
@element
|
||||
def getBit(self, bitname_or_addr, bit_position=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)
|
||||
"""
|
||||
resolved = self._resolve_bit_name_or_addr(bitname_or_addr, bit_position)
|
||||
return super().getBit(resolved)
|
||||
|
||||
|
||||
@property
|
||||
def slowadc(self):
|
||||
|
||||
@@ -1,13 +1,30 @@
|
||||
# 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.getRegisterAddress(key)
|
||||
elif isinstance(key, int):
|
||||
key = RegisterAddress(key)
|
||||
return self._detector.readRegister(key)
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
if isinstance(key, str):
|
||||
key = self._detector.getRegisterAddress(key)
|
||||
elif isinstance(key, int):
|
||||
key = RegisterAddress(key)
|
||||
|
||||
if isinstance(value, int):
|
||||
value = RegisterValue(value)
|
||||
|
||||
self._detector.writeRegister(key, value, False)
|
||||
|
||||
class Adc_register:
|
||||
|
||||
@@ -141,20 +141,19 @@ def make_ip(arg):
|
||||
def make_mac(arg):
|
||||
return _make(arg, _slsdet.MacAddr)
|
||||
|
||||
|
||||
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)
|
||||
return tuple(_make(a, transform) for a in arg)
|
||||
else:
|
||||
return transform(arg)
|
||||
|
||||
|
||||
67
python/src/bit.cpp
Normal file
67
python/src/bit.cpp
Normal file
@@ -0,0 +1,67 @@
|
||||
// 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<uint32_t>())
|
||||
.def(py::init<const RegisterAddress &>())
|
||||
.def("__repr__",
|
||||
[](const RegisterAddress &addr) {
|
||||
return "RegisterAddress(" + addr.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("__repr__",
|
||||
[](const BitAddress &addr) {
|
||||
return "BitAddress(" + addr.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<uint32_t>())
|
||||
.def(py::init<const RegisterValue &>())
|
||||
.def("__repr__",
|
||||
[](const RegisterValue &val) {
|
||||
return "RegisterValue(" + val.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);
|
||||
}
|
||||
@@ -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",
|
||||
@@ -942,7 +946,6 @@ void init_det(py::module &m) {
|
||||
(void (Detector::*)(const std::vector<defs::ROI> &)) &
|
||||
Detector::setRxROI,
|
||||
py::arg());
|
||||
|
||||
CppDetectorApi.def("clearRxROI",
|
||||
(void (Detector::*)()) & Detector::clearRxROI);
|
||||
CppDetectorApi.def(
|
||||
@@ -1796,6 +1799,82 @@ 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(
|
||||
"getRegisterAddress",
|
||||
(sls::RegisterAddress(Detector::*)(const std::string &) const) &
|
||||
Detector::getRegisterAddress,
|
||||
py::arg());
|
||||
CppDetectorApi.def("getRegisterName",
|
||||
(std::string(Detector::*)(sls::RegisterAddress) const) &
|
||||
Detector::getRegisterName,
|
||||
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("toRegisterNameBitString",
|
||||
(std::string(Detector::*)(sls::BitAddress) const) &
|
||||
Detector::toRegisterNameBitString,
|
||||
py::arg());
|
||||
CppDetectorApi.def(
|
||||
"getBitAddress",
|
||||
(sls::BitAddress(Detector::*)(const std::string &) const) &
|
||||
Detector::getBitAddress,
|
||||
py::arg());
|
||||
CppDetectorApi.def("getBitName",
|
||||
(std::string(Detector::*)(sls::BitAddress) const) &
|
||||
Detector::getBitName,
|
||||
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,
|
||||
@@ -1969,6 +2048,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) &
|
||||
@@ -1991,7 +2122,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",
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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");
|
||||
|
||||
385
python/tests/test_CtbAPI.py
Normal file
385
python/tests/test_CtbAPI.py
Normal file
@@ -0,0 +1,385 @@
|
||||
'''
|
||||
cd python/tests
|
||||
Specific test: pytest -s -x test_CtbAPI.py::test_define_bit #-x=abort on first failure
|
||||
Specific test with specific server: pytest -s -x test_CtbAPI.py::test_define_reg[ctb]
|
||||
|
||||
'''
|
||||
|
||||
import pytest, sys, 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,
|
||||
startDetectorVirtualServer,
|
||||
connectToVirtualServers,
|
||||
SERVER_START_PORTNO,
|
||||
)
|
||||
|
||||
from slsdet import Detector, detectorType
|
||||
|
||||
|
||||
@pytest.fixture(
|
||||
scope="session",
|
||||
params=['ctb', 'xilinx_ctb', 'mythen3']
|
||||
)
|
||||
def simulator(request):
|
||||
"""Fixture to start the detector server once and clean up at the end."""
|
||||
det_name = request.param
|
||||
num_mods = 1
|
||||
fp = sys.stdout
|
||||
|
||||
# set up: once per server
|
||||
Log(LogLevel.INFOBLUE, f'---- {det_name} ----')
|
||||
cleanup(fp)
|
||||
startDetectorVirtualServer(det_name, num_mods, fp)
|
||||
|
||||
Log(LogLevel.INFOBLUE, f'Waiting for server to start up and connect')
|
||||
connectToVirtualServers(det_name, num_mods)
|
||||
|
||||
yield det_name # tests run here
|
||||
|
||||
cleanup(fp)
|
||||
|
||||
|
||||
@pytest.mark.withdetectorsimulators
|
||||
def test_define_reg(simulator, request):
|
||||
""" Test setting define_reg for ctb and xilinx_ctb."""
|
||||
det_name = simulator
|
||||
from slsdet import RegisterAddress
|
||||
|
||||
d = Detector()
|
||||
d.hostname = f"localhost:{SERVER_START_PORTNO}"
|
||||
|
||||
if det_name in ['ctb', 'xilinx_ctb']:
|
||||
prev_reg_defs = d.getRegisterDefinitions()
|
||||
prev_bit_defs = d.getBitDefinitions()
|
||||
d.clearRegisterDefinitions()
|
||||
d.clearBitDefinitions()
|
||||
|
||||
addr1 = RegisterAddress(0x201)
|
||||
addr2 = RegisterAddress(0x202)
|
||||
d.define_reg(name="test_reg", addr=RegisterAddress(0x200)) # valid
|
||||
d.define_reg(name="test_reg", addr=addr1) # takes a register address
|
||||
d.define_reg(name="test_reg2", addr=0x202) # takes an int
|
||||
|
||||
# not using keyword arguments
|
||||
with pytest.raises(TypeError) as exc_info:
|
||||
d.define_reg("randomreg", 0x203)
|
||||
|
||||
# invalid value type
|
||||
with pytest.raises(Exception) as exc_info:
|
||||
d.define_reg(name="test_reg3", addr='0x203')
|
||||
assert "addr must int or RegisterAddress" in str(exc_info.value)
|
||||
|
||||
# defining with duplicate value
|
||||
with pytest.raises(Exception) as exc_info:
|
||||
d.define_reg(name="test_reg3", addr=addr1)
|
||||
assert "Value already assigned" in str(exc_info.value)
|
||||
|
||||
assert(d.getRegisterAddress("test_reg") == addr1)
|
||||
assert(d.getRegisterName(addr1) == "test_reg")
|
||||
|
||||
# accessing non existent reg name
|
||||
with pytest.raises(Exception) as exc_info:
|
||||
d.reg['random_reg']
|
||||
assert "No entry found for key" in str(exc_info.value)
|
||||
|
||||
# get non existing reg address
|
||||
with pytest.raises(Exception) as exc_info:
|
||||
d.getRegisterName(RegisterAddress(0x300))
|
||||
assert "No entry found for value" in str(exc_info.value)
|
||||
|
||||
d.clearRegisterDefinitions()
|
||||
|
||||
d.setRegisterDefinitions(prev_reg_defs)
|
||||
d.setBitDefinitions(prev_bit_defs)
|
||||
|
||||
else:
|
||||
with pytest.raises(Exception) as exc_info:
|
||||
d.define_reg(name="test_reg", addr=0x201)
|
||||
assert "Register Definitions only for CTB" in str(exc_info.value)
|
||||
|
||||
Log(LogLevel.INFOGREEN, f"✅ {request.node.name} passed")
|
||||
|
||||
|
||||
@pytest.mark.withdetectorsimulators
|
||||
def test_define_bit(simulator, request):
|
||||
""" Test setting define_bit for ctb and xilinx_ctb."""
|
||||
det_name = simulator
|
||||
from slsdet import RegisterAddress, BitAddress
|
||||
|
||||
# setup
|
||||
d = Detector()
|
||||
d.hostname = f"localhost:{SERVER_START_PORTNO}"
|
||||
|
||||
if det_name in ['ctb', 'xilinx_ctb']:
|
||||
prev_reg_defs = d.getRegisterDefinitions()
|
||||
prev_bit_defs = d.getBitDefinitions()
|
||||
d.clearRegisterDefinitions()
|
||||
d.clearBitDefinitions()
|
||||
|
||||
addr1 = RegisterAddress(0x201)
|
||||
addr2 = RegisterAddress(0x202)
|
||||
d.define_reg(name="test_reg1", addr=addr1)
|
||||
d.define_reg(name="test_reg2", addr=addr2)
|
||||
|
||||
# not using keyword arguments
|
||||
with pytest.raises(TypeError) as exc_info:
|
||||
d.define_bit("randombit", 0x203, 1)
|
||||
|
||||
# invalid value type (bit=string)
|
||||
with pytest.raises(ValueError) as exc_info:
|
||||
d.define_bit(name="test_bit1", addr='test_reg1', bit_position='1')
|
||||
|
||||
# invalid bit_position
|
||||
with pytest.raises(Exception) as exc_info:
|
||||
d.define_bit(name="test_bit1", addr='test_reg1', bit_position=32)
|
||||
assert "Bit position must be between 0 and 31" in str(exc_info.value)
|
||||
|
||||
# defining with random reg value
|
||||
with pytest.raises(Exception) as exc_info:
|
||||
d.define_bit(name='test_bit1', addr='random_reg', bit_position=1)
|
||||
assert "No entry found for key" in str(exc_info.value)
|
||||
|
||||
bit1 = BitAddress(addr1, 2)
|
||||
bit2 = BitAddress(addr1, 4)
|
||||
bit3 = BitAddress(addr2, 3)
|
||||
|
||||
# defining bit address with bit_position as well
|
||||
with pytest.raises(ValueError) as exc_info:
|
||||
d.define_bit(name='test_bit1', addr=bit1, bit_position=1)
|
||||
assert "bit_position must be None" in str(exc_info.value)
|
||||
|
||||
|
||||
d.define_bit(name="test_bit1", addr='test_reg2', bit_position=1)
|
||||
d.define_bit(name="test_bit1", addr='test_reg1', bit_position=1) # modify reg
|
||||
d.define_bit(name='test_bit1', addr=bit1) # modify pos
|
||||
d.define_bit(name="test_bit2", addr=0x201, bit_position=4) # int addr
|
||||
d.define_bit(name="test_bit3", addr=addr2, bit_position=3) # RegisterAddress addr
|
||||
|
||||
|
||||
assert(d.getBitAddress('test_bit1') == bit1)
|
||||
assert(d.getBitAddress('test_bit2') == bit2)
|
||||
assert(d.getBitAddress('test_bit3') == bit3)
|
||||
assert(d.getBitAddress('test_bit1').address() == addr1)
|
||||
assert(d.getBitAddress('test_bit1').bitPosition() == 2)
|
||||
assert(d.getBitAddress('test_bit2') == BitAddress(addr1, 4))
|
||||
|
||||
assert(d.getBitName(bit1) == 'test_bit1')
|
||||
assert(d.getBitName(bit2) == 'test_bit2')
|
||||
assert(d.getBitName(bit3) == 'test_bit3')
|
||||
assert(d.getBitName(BitAddress(addr2,3)) == 'test_bit3')
|
||||
|
||||
# bit doesnt exist for that reg
|
||||
with pytest.raises(Exception) as exc_info:
|
||||
d.getBitName(BitAddress(addr1, 5))
|
||||
assert "No entry found for value" in str(exc_info.value)
|
||||
|
||||
# addr doesnt exist for that reg
|
||||
with pytest.raises(Exception) as exc_info:
|
||||
d.getBitName(BitAddress(RegisterAddress(0x300), 5))
|
||||
assert "No entry found for value" in str(exc_info.value)
|
||||
|
||||
d.clearRegisterDefinitions()
|
||||
d.clearBitDefinitions()
|
||||
|
||||
d.setRegisterDefinitions(prev_reg_defs)
|
||||
d.setBitDefinitions(prev_bit_defs)
|
||||
else:
|
||||
with pytest.raises(Exception) as exc_info:
|
||||
d.define_bit(name="test_bit", addr=0x300, bit_position=1)
|
||||
assert "Bit Definitions only for CTB" in str(exc_info.value)
|
||||
|
||||
|
||||
Log(LogLevel.INFOGREEN, f"✅ {request.node.name} passed")
|
||||
|
||||
|
||||
@pytest.mark.withdetectorsimulators
|
||||
def test_using_defined_reg_and_bit(simulator, request):
|
||||
""" Test using defined reg and bit define_bit for ctb and xilinx_ctb."""
|
||||
det_name = simulator
|
||||
from slsdet import RegisterAddress, BitAddress, RegisterValue
|
||||
|
||||
# setup
|
||||
d = Detector()
|
||||
d.hostname = f"localhost:{SERVER_START_PORTNO}"
|
||||
|
||||
if det_name in ['ctb', 'xilinx_ctb']:
|
||||
prev_reg_defs = d.getRegisterDefinitions()
|
||||
prev_bit_defs = d.getBitDefinitions()
|
||||
d.clearRegisterDefinitions()
|
||||
d.clearBitDefinitions()
|
||||
|
||||
addr1 = RegisterAddress(0x201)
|
||||
addr2 = RegisterAddress(0x202)
|
||||
d.setRegisterDefinition('test_reg1', addr1)
|
||||
d.setRegisterDefinition('test_reg2', addr2)
|
||||
bit1 = BitAddress(addr1, 2)
|
||||
bit2 = BitAddress(addr1, 4)
|
||||
bit3 = BitAddress(addr2, 3)
|
||||
d.setBitDefinition('test_bit1', bit1)
|
||||
d.setBitDefinition('test_bit2', bit2)
|
||||
d.setBitDefinition('test_bit3', bit3)
|
||||
|
||||
prev_val_addr1 = d.reg[addr1]
|
||||
prev_val_addr2 = d.reg[addr2]
|
||||
|
||||
# reg name doesnt exist
|
||||
with pytest.raises(Exception) as exc_info:
|
||||
d.reg['random_reg']
|
||||
assert "No entry found for key" in str(exc_info.value)
|
||||
with pytest.raises(Exception) as exc_info:
|
||||
d.setBit('random_reg')
|
||||
assert "No entry found for key" in str(exc_info.value)
|
||||
with pytest.raises(Exception) as exc_info:
|
||||
d.clearBit('random_reg')
|
||||
assert "No entry found for key" in str(exc_info.value)
|
||||
with pytest.raises(Exception) as exc_info:
|
||||
d.getBit('random_reg')
|
||||
assert "No entry found for key" in str(exc_info.value)
|
||||
|
||||
# bit name doesnt exist
|
||||
with pytest.raises(Exception) as exc_info:
|
||||
d.setBit('test_bit1', bit_position=5)
|
||||
assert "bit_position must be None" in str(exc_info.value)
|
||||
with pytest.raises(Exception) as exc_info:
|
||||
d.clearBit('test_bit1', bit_position=5)
|
||||
assert "bit_position must be None" in str(exc_info.value)
|
||||
with pytest.raises(Exception) as exc_info:
|
||||
d.getBit('test_bit1', bit_position=5)
|
||||
assert "bit_position must be None" in str(exc_info.value)
|
||||
|
||||
d.reg['test_reg1'] = RegisterValue(0x0)
|
||||
assert(d.reg['test_reg1'].value() == 0x0)
|
||||
|
||||
d.reg['test_reg1'] = RegisterValue(0x10)
|
||||
assert(d.reg['test_reg1'].value() == 0x10)
|
||||
|
||||
d.setBit('test_bit1')
|
||||
assert(d.reg['test_reg1'].value() == 0x14) # 0x10 | (1 << 2)
|
||||
|
||||
d.clearBit('test_bit1')
|
||||
assert(d.reg['test_reg1'].value() == 0x10)
|
||||
|
||||
assert(d.getBit('test_bit1') == 0)
|
||||
|
||||
# restore previous values
|
||||
d.reg[addr1] = prev_val_addr1
|
||||
d.reg[addr2] = prev_val_addr2
|
||||
|
||||
d.clearRegisterDefinitions()
|
||||
d.clearBitDefinitions()
|
||||
|
||||
d.setRegisterDefinitions(prev_reg_defs)
|
||||
d.setBitDefinitions(prev_bit_defs)
|
||||
else:
|
||||
with pytest.raises(Exception) as exc_info:
|
||||
d.define_bit(name="test_bit", addr=0x300, bit_position=1)
|
||||
assert "Bit Definitions only for CTB" in str(exc_info.value)
|
||||
|
||||
Log(LogLevel.INFOGREEN, f"✅ {request.node.name} passed")
|
||||
|
||||
|
||||
@pytest.mark.withdetectorsimulators
|
||||
def test_definelist_reg(simulator, request):
|
||||
""" Test using definelist_reg for ctb and xilinx_ctb."""
|
||||
det_name = simulator
|
||||
from slsdet import RegisterAddress, BitAddress, RegisterValue
|
||||
|
||||
# setup
|
||||
d = Detector()
|
||||
d.hostname = f"localhost:{SERVER_START_PORTNO}"
|
||||
|
||||
if det_name in ['ctb', 'xilinx_ctb']:
|
||||
prev_reg_defs = d.getRegisterDefinitions()
|
||||
prev_bit_defs = d.getBitDefinitions()
|
||||
d.clearRegisterDefinitions()
|
||||
d.clearBitDefinitions()
|
||||
|
||||
addr1 = RegisterAddress(0x201)
|
||||
addr2 = RegisterAddress(0x202)
|
||||
bit1 = BitAddress(addr1, 2)
|
||||
bit2 = BitAddress(addr1, 4)
|
||||
bit3 = BitAddress(addr2, 3)
|
||||
|
||||
d.setRegisterDefinitions({
|
||||
'test_reg1': RegisterAddress(0x201),
|
||||
'test_reg2': RegisterAddress(0x202)
|
||||
})
|
||||
|
||||
res = d.getRegisterDefinitions()
|
||||
assert(res['test_reg1'] == addr1)
|
||||
assert(res['test_reg2'] == addr2)
|
||||
assert(len(res) == 2)
|
||||
|
||||
d.clearRegisterDefinitions()
|
||||
d.clearBitDefinitions()
|
||||
|
||||
d.setRegisterDefinitions(prev_reg_defs)
|
||||
d.setBitDefinitions(prev_bit_defs)
|
||||
else:
|
||||
with pytest.raises(Exception) as exc_info:
|
||||
d.define_bit(name="test_bit", addr=0x300, bit_position=1)
|
||||
assert "Bit Definitions only for CTB" in str(exc_info.value)
|
||||
|
||||
Log(LogLevel.INFOGREEN, f"✅ {request.node.name} passed")
|
||||
|
||||
|
||||
@pytest.mark.withdetectorsimulators
|
||||
def test_definelist_bit(simulator, request):
|
||||
""" Test using definelist_bit for ctb and xilinx_ctb."""
|
||||
det_name = simulator
|
||||
from slsdet import RegisterAddress, BitAddress, RegisterValue
|
||||
|
||||
# setup
|
||||
d = Detector()
|
||||
d.hostname = f"localhost:{SERVER_START_PORTNO}"
|
||||
|
||||
if det_name in ['ctb', 'xilinx_ctb']:
|
||||
prev_reg_defs = d.getRegisterDefinitions()
|
||||
prev_bit_defs = d.getBitDefinitions()
|
||||
d.clearRegisterDefinitions()
|
||||
d.clearBitDefinitions()
|
||||
|
||||
addr1 = RegisterAddress(0x201)
|
||||
addr2 = RegisterAddress(0x202)
|
||||
bit1 = BitAddress(addr1, 2)
|
||||
bit2 = BitAddress(addr1, 4)
|
||||
bit3 = BitAddress(addr2, 3)
|
||||
|
||||
d.setRegisterDefinitions({
|
||||
'test_reg1': RegisterAddress(0x201),
|
||||
'test_reg2': RegisterAddress(0x202)
|
||||
})
|
||||
d.setBitDefinitions({
|
||||
'test_bit1': BitAddress(addr1, 2),
|
||||
'test_bit2': BitAddress(addr1, 4),
|
||||
'test_bit3': BitAddress(addr2, 3)
|
||||
})
|
||||
|
||||
res = d.getBitDefinitions()
|
||||
assert(len(res) == 3)
|
||||
assert(res['test_bit1'] == bit1)
|
||||
assert(res['test_bit2'] == bit2)
|
||||
assert(res['test_bit3'] == bit3)
|
||||
assert(res['test_bit2'].address() == addr1)
|
||||
assert(res['test_bit2'].bitPosition() == 4)
|
||||
|
||||
d.clearRegisterDefinitions()
|
||||
d.clearBitDefinitions()
|
||||
|
||||
d.setRegisterDefinitions(prev_reg_defs)
|
||||
d.setBitDefinitions(prev_bit_defs)
|
||||
else:
|
||||
with pytest.raises(Exception) as exc_info:
|
||||
d.define_bit(name="test_bit", addr=0x300, bit_position=1)
|
||||
assert "Bit Definitions only for CTB" in str(exc_info.value)
|
||||
|
||||
Log(LogLevel.INFOGREEN, f"✅ {request.node.name} passed")
|
||||
@@ -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")
|
||||
|
||||
Reference in New Issue
Block a user