12#include <ChimeraTK/cppext/finally.hpp>
16 template<
typename UserType,
typename DataConverterType,
bool isRaw>
17 class NumericAddressedBackendRegisterAccessor;
24 template<
typename UserType,
typename DataConverterType,
bool isRaw>
35 _dev = boost::dynamic_pointer_cast<NumericAddressedBackend>(dev);
37 throw ChimeraTK::logic_error(
"NumericAddressedBackendRegisterAccessor is used with a backend which is not "
38 "a NumericAddressedBackend.");
60 if(numberOfWords == 0) {
63 if(numberOfWords > 1) {
65 "Requested number of words is larger than 1 in VOID register '" + registerPathName +
"'!");
67 if(wordOffsetInRegister > 0) {
72 if(numberOfWords == 0) {
83 registerPathName +
"'!");
93 _rawAccessor = boost::make_shared<NumericAddressedLowLevelTransferElement>(
107 throw ChimeraTK::logic_error(
"Given UserType when obtaining the NumericAddressedBackendRegisterAccessor in "
108 "raw mode does not match the expected type. Use an " +
110 " instead! (Register name: " + registerPathName +
"')");
127 if(!
_dev->isOpen())
return;
132 if(!hasNewData)
return;
134 if constexpr(!isRaw || std::is_same<UserType, std::string>::value) {
136 typedef decltype(t) RawType;
137 auto itsrc = (RawType*)_rawAccessor->begin(_registerInfo.address);
138 _dataConverter.template vectorToCooked<UserType>(itsrc, itsrc + buffer_2D[0].size(), buffer_2D[0].begin());
145 memcpy(itdst, itsrc,
buffer_2D[0].size() *
sizeof(UserType));
161 if constexpr(!isRaw || std::is_same<UserType, std::string>::value) {
164 "NumericAddressedBackend: Writing to a non-writeable register is not allowed (Register name: " +
168 typedef decltype(t) RawType;
169 auto itsrc = (RawType*)_rawAccessor->begin(_registerInfo.address);
170 for(auto itdst = buffer_2D[0].begin(); itdst != buffer_2D[0].end(); ++itdst) {
171 *itsrc = _dataConverter.template toRaw<UserType>(*itdst);
180 memcpy(&(*itdst), &(*itsrc),
buffer_2D[0].size() *
sizeof(UserType));
188 if(!_registerInfo.isReadable()) {
190 "NumericAddressedBackend: Reading from a non-readable register is not allowed (Register name: " +
191 _registerInfo.getRegisterName() +
").");
193 _rawAccessor->preRead(type);
197 if(!_dev->isOpen())
return;
198 _rawAccessor->setActiveException(this->_activeException);
199 _rawAccessor->postWrite(type, versionNumber);
202 [[nodiscard]]
bool mayReplaceOther(
const boost::shared_ptr<TransferElement const>& other)
const override {
203 auto rhsCasted = boost::dynamic_pointer_cast<
205 if(rhsCasted.get() ==
this) {
208 if(!rhsCasted)
return false;
209 if(_dev != rhsCasted->_dev)
return false;
210 if(_registerInfo != rhsCasted->_registerInfo)
return false;
211 if(_dataConverter != rhsCasted->_dataConverter)
return false;
215 [[nodiscard]]
bool isReadOnly()
const override {
return isReadable() && !isWriteable(); }
217 [[nodiscard]]
bool isReadable()
const override {
return _registerInfo.isReadable(); }
219 [[nodiscard]]
bool isWriteable()
const override {
return _registerInfo.isWriteable(); }
221 template<
typename COOKED_TYPE>
222 COOKED_TYPE getAsCooked_impl(
unsigned int channel,
unsigned int sample);
224 template<
typename COOKED_TYPE>
225 void setAsCooked_impl(
unsigned int channel,
unsigned int sample, COOKED_TYPE value);
235 this->_exceptionBackend = exceptionBackend;
236 _rawAccessor->setExceptionBackend(exceptionBackend);
248 boost::shared_ptr<NumericAddressedLowLevelTransferElement>
_rawAccessor;
251 boost::shared_ptr<NumericAddressedBackend>
_dev;
254 return _rawAccessor->getHardwareAccessingElements();
258 return {_rawAccessor};
262 auto casted = boost::dynamic_pointer_cast<NumericAddressedLowLevelTransferElement>(newElement);
263 if(casted && casted->isMergeable(_rawAccessor)) {
264 size_t newStartAddress = std::min(casted->_startAddress, _rawAccessor->_startAddress);
265 size_t newStopAddress = std::max(
266 casted->_startAddress + casted->_numberOfBytes, _rawAccessor->_startAddress + _rawAccessor->_numberOfBytes);
267 size_t newNumberOfBytes = newStopAddress - newStartAddress;
268 casted->changeAddress(newStartAddress, newNumberOfBytes);
269 _rawAccessor = casted;
271 _rawAccessor->setExceptionBackend(this->_exceptionBackend);
278 template<
typename RawT,
typename CookedT>
280 static CookedT
vectorToCooked(DataConverterType&,
const typename std::vector<RawT>::const_iterator&,
281 const typename std::vector<RawT>::const_iterator&,
const typename std::vector<CookedT>::iterator&) {
284 static RawT
toRaw(DataConverterType&, CookedT&) {
288 template<
typename CookedT>
291 const typename std::vector<int8_t>::const_iterator& start,
292 const typename std::vector<int8_t>::const_iterator& end,
293 const typename std::vector<CookedT>::iterator& cooked) {
294 dataConverter.template vectorToCooked<CookedT>(start, end, cooked);
296 static int8_t
toRaw(DataConverterType& dataConverter, CookedT& value) {
return dataConverter.toRaw(value); }
298 template<
typename CookedT>
301 const typename std::vector<int16_t>::const_iterator& start,
302 const typename std::vector<int16_t>::const_iterator& end,
303 const typename std::vector<CookedT>::iterator& cooked) {
304 dataConverter.template vectorToCooked<CookedT>(start, end, cooked);
306 static int16_t
toRaw(DataConverterType& dataConverter, CookedT& value) {
return dataConverter.toRaw(value); }
308 template<
typename CookedT>
311 const typename std::vector<int32_t>::const_iterator& start,
312 const typename std::vector<int32_t>::const_iterator& end,
313 const typename std::vector<CookedT>::iterator& cooked) {
314 dataConverter.template vectorToCooked<CookedT>(start, end, cooked);
316 static int32_t
toRaw(DataConverterType& dataConverter, CookedT& value) {
return dataConverter.toRaw(value); }
324 template<
typename UserType,
typename DataConverterType,
bool isRaw>
325 template<
typename COOKED_TYPE>
327 unsigned int channel,
unsigned int sample) {
329 std::vector<COOKED_TYPE> cookedData(1);
333 return cookedData[0];
340 template<
typename UserType,
typename DataConverterType,
bool isRaw>
341 template<
typename COOKED_TYPE>
343 unsigned int channel,
unsigned int sample, COOKED_TYPE value) {
#define DECLARE_MULTI_TEMPLATE_FOR_CHIMERATK_USER_TYPES(TemplateClass,...)
Macro to declare a template class with multiple template parameters for all supported user types.
#define FILL_VIRTUAL_FUNCTION_TEMPLATE_VTABLE(functionName)
Fill the vtable of a virtual function template defined with DEFINE_VIRTUAL_FUNCTION_TEMPLATE.
Set of AccessMode flags with additional functionality for an easier handling.
bool has(AccessMode flag) const
Check if a certain flag is in the set.
void checkForUnknownFlags(const std::set< AccessMode > &knownFlags) const
Check of any flag which is not in the given set "knownFlags" is set.
DataType rawDataType() const
Get the raw data type.
A class to describe which of the supported data types is used.
std::string getAsString() const
Return string representation of the data type.
The fixed point converter provides conversion functions between a user type and up to 32 bit fixed po...
N-dimensional register accessor.
std::vector< std::vector< UserType > > buffer_2D
Buffer of converted data elements.
Base class for address-based device backends (e.g.
Implementation of the NDRegisterAccessor for NumericAddressedBackends for scalar and 1D registers.
std::vector< boost::shared_ptr< TransferElement > > getHardwareAccessingElements() override
Obtain the underlying TransferElements with actual hardware access.
bool mayReplaceOther(const boost::shared_ptr< TransferElement const > &other) const override
Check whether the TransferElement can be used in places where the TransferElement "other" is currentl...
NumericAddressedRegisterInfo _registerInfo
Address, size and fixed-point representation information of the register from the map file.
COOKED_TYPE getAsCooked_impl(unsigned int channel, unsigned int sample)
DEFINE_VIRTUAL_FUNCTION_TEMPLATE_VTABLE_FILLER(THIS_TYPE, getAsCooked_impl, 2)
void doReadTransferSynchronously() override
Implementation version of readTransfer() for synchronous reads.
NumericAddressedBackendRegisterAccessor(const boost::shared_ptr< DeviceBackend > &dev, const RegisterPath ®isterPathName, size_t numberOfWords, size_t wordOffsetInRegister, AccessModeFlags flags)
bool doWriteTransfer(ChimeraTK::VersionNumber versionNumber) override
Implementation version of writeTransfer().
void doPreWrite(TransferType type, VersionNumber versionNumber) override
Backend specific implementation of preWrite().
void doPostWrite(TransferType type, VersionNumber versionNumber) override
Backend specific implementation of postWrite().
void doPreRead(TransferType type) override
Backend specific implementation of preRead().
DataConverterType _dataConverter
Converter to interpret the data.
void setExceptionBackend(boost::shared_ptr< DeviceBackend > exceptionBackend) override
Set the backend to which the exception has to be reported.
bool isReadOnly() const override
Check if transfer element is read only, i.e.
std::list< boost::shared_ptr< TransferElement > > getInternalElements() override
Obtain the full list of TransferElements internally used by this TransferElement.
void setAsCooked_impl(unsigned int channel, unsigned int sample, COOKED_TYPE value)
boost::shared_ptr< NumericAddressedBackend > _dev
the backend to use for the actual hardware access
boost::shared_ptr< NumericAddressedLowLevelTransferElement > _rawAccessor
raw accessor
DEFINE_VIRTUAL_FUNCTION_TEMPLATE_VTABLE_FILLER(THIS_TYPE, setAsCooked_impl, 3)
void replaceTransferElement(boost::shared_ptr< TransferElement > newElement) override
Search for all underlying TransferElements which are considered identical (see sameRegister()) with t...
bool isReadable() const override
Check if transfer element is readable.
bool isWriteable() const override
Check if transfer element is writeable.
void doPostRead(TransferType type, bool hasNewData) override
Backend specific implementation of postRead().
uint32_t nElements
Number of elements in register.
std::vector< ChannelInfo > channels
Define per-channel information (bit interpretation etc.), 1D/scalars have exactly one entry.
uint64_t bar
Upper part of the address (name originally from PCIe, meaning now generalised)
const DataDescriptor & getDataDescriptor() const override
Return description of the actual payload data for this register.
uint32_t elementPitchBits
Distance in bits (!) between two elements (of the same channel)
uint64_t address
Lower part of the address relative to BAR, in bytes.
RegisterPath getRegisterName() const override
Return full path name of the register (including modules)
bool isWriteable() const override
Return whether the register is writeable.
unsigned int getNumberOfElements() const override
Return number of elements per channel.
Class to store a register path name.
DataValidity _dataValidity
The validity of the data in the application buffer.
std::exception_ptr _activeException
Exception to be rethrown in postXXX() in case hasSeenException == true Can be set via setActiveExcept...
VersionNumber _versionNumber
The version number of the last successful transfer.
bool _isInTransferGroup
Flag whether this TransferElement has been added to a TransferGroup or not.
Class for generating and holding version numbers without exposing a numeric representation.
Exception thrown when a logic error has occured.
void callForRawType(const DataType &type, LAMBDATYPE lambda)
callForRawType() is similar to callForType(), just with a subset of supported data types which can be...
@ raw
Raw access: disable any possible conversion from the original hardware data type into the given UserT...
TransferType
Used to indicate the applicable operation on a Transferelement.
std::string to_string(const std::string &v)
Needs to have the same interface as FixedPointConverter, except for the constructor.
static void vectorToCooked(DataConverterType &dataConverter, const typename std::vector< int8_t >::const_iterator &start, const typename std::vector< int8_t >::const_iterator &end, const typename std::vector< CookedT >::iterator &cooked)
static int8_t toRaw(DataConverterType &dataConverter, CookedT &value)
static int16_t toRaw(DataConverterType &dataConverter, CookedT &value)
static void vectorToCooked(DataConverterType &dataConverter, const typename std::vector< int16_t >::const_iterator &start, const typename std::vector< int16_t >::const_iterator &end, const typename std::vector< CookedT >::iterator &cooked)
static void vectorToCooked(DataConverterType &dataConverter, const typename std::vector< int32_t >::const_iterator &start, const typename std::vector< int32_t >::const_iterator &end, const typename std::vector< CookedT >::iterator &cooked)
static int32_t toRaw(DataConverterType &dataConverter, CookedT &value)
A helper class to implement template specialisation on certain functions.
static RawT toRaw(DataConverterType &, CookedT &)
static CookedT vectorToCooked(DataConverterType &, const typename std::vector< RawT >::const_iterator &, const typename std::vector< RawT >::const_iterator &, const typename std::vector< CookedT >::iterator &)