10 template<
typename UserType,
bool isRaw>
12 const boost::shared_ptr<DeviceBackend>& dev,
const RegisterPath& registerPathName,
size_t numberOfWords,
20 _dev = boost::dynamic_pointer_cast<NumericAddressedBackend>(dev);
22 throw ChimeraTK::logic_error(
"NumericAddressedBackendRegisterAccessor is used with a backend which is not "
23 "a NumericAddressedBackend.");
49 if(numberOfWords == 0) {
52 if(numberOfWords > 1) {
54 "Requested number of words is larger than 1 in VOID register '" + registerPathName +
"'!");
56 if(wordOffsetInRegister > 0) {
61 if(numberOfWords == 0) {
72 registerPathName +
"'!");
82 _rawAccessor = boost::make_shared<NumericAddressedLowLevelTransferElement>(
89 if constexpr(!isRaw) {
91 RawConverter::ConverterLoopHelper::makeConverterLoopHelper<UserType>(
_registerInfo, 0, 0, *
this);
96 throw ChimeraTK::logic_error(
"Given UserType when obtaining the NumericAddressedBackendRegisterAccessor in "
97 "raw mode does not match the expected type. Use an " +
99 " instead! (Register name: " + registerPathName +
"')");
109 template<
typename UserType,
bool isRaw>
111 _rawAccessor->readTransfer();
116 template<
typename UserType,
bool isRaw>
120 _rawAccessor->writeTransfer(versionNumber);
126 template<
typename UserType,
bool isRaw>
128 if(!_dev->isOpen()) {
133 _rawAccessor->setActiveException(this->_activeException);
134 _rawAccessor->postRead(type, hasNewData);
140 if constexpr(!isRaw || std::is_same<UserType, std::string>::value) {
141 _converterLoopHelper->doPostRead();
146 auto* itsrc = _rawAccessor->begin(_registerInfo.address);
147 auto* itdst = buffer_2D[0].data();
148 const size_t stride = _registerInfo.elementPitchBits / 8;
149 if(stride ==
sizeof(UserType)) {
150 memcpy(itdst, itsrc, buffer_2D[0].size() *
sizeof(UserType));
153 for(
size_t i = 0; i < buffer_2D[0].size(); ++i) {
154 memcpy(itdst + i, itsrc + i * stride,
sizeof(UserType));
162 this->_versionNumber = _rawAccessor->getVersionNumber();
163 this->_dataValidity = _rawAccessor->dataValidity();
168 template<
typename UserType,
bool isRaw>
173 static_assert(std::is_same_v<UserType, CookedType>);
174 if constexpr(!isRaw) {
175 if constexpr(!std::is_same_v<RawType, ChimeraTK::Void>) {
176 auto* begin = _rawAccessor->begin(_registerInfo.address);
177 assert(begin !=
nullptr);
179 const size_t stride = _registerInfo.elementPitchBits / 8;
180 for(
auto [itsrc, itdst] = std::make_pair(begin, buffer_2D[0].begin()); itdst != buffer_2D[0].end();
181 itsrc += stride, ++itdst) {
183 memcpy(&temp, itsrc,
sizeof(RawType));
196 template<
typename UserType,
bool isRaw>
199 if(!_dev->isOpen()) {
204 _rawAccessor->preWrite(type, versionNumber);
206 if constexpr(!isRaw || std::is_same<UserType, std::string>::value) {
207 if(!_registerInfo.isWriteable()) {
209 "NumericAddressedBackend: Writing to a non-writeable register is not allowed (Register name: " +
210 _registerInfo.getRegisterName() +
").");
212 _converterLoopHelper->doPreWrite();
217 auto* itdst = _rawAccessor->begin(_registerInfo.address);
218 auto* itsrc = buffer_2D[0].data();
219 const size_t stride = _registerInfo.elementPitchBits / 8;
220 for(
size_t i = 0; i < buffer_2D[0].size(); ++i) {
221 memcpy(itdst + i * stride, itsrc + i,
sizeof(UserType));
225 _rawAccessor->setDataValidity(this->_dataValidity);
230 template<
typename UserType,
bool isRaw>
235 static_assert(std::is_same_v<UserType, CookedType>);
236 if constexpr(!isRaw) {
237 if constexpr(!std::is_same_v<RawType, ChimeraTK::Void>) {
238 auto* begin = _rawAccessor->begin(_registerInfo.address);
240 const size_t stride = _registerInfo.elementPitchBits / 8;
241 for(
auto [itsrc, itdst] = std::make_pair(buffer_2D[0].begin(), begin); itsrc != buffer_2D[0].end();
242 ++itsrc, itdst += stride) {
243 RawType temp = converter.
toRaw(*itsrc);
244 memcpy(itdst, &temp,
sizeof(RawType));
256 template<
typename UserType,
bool isRaw>
258 if(!_dev->isOpen()) {
261 if(!_registerInfo.isReadable()) {
263 "NumericAddressedBackend: Reading from a non-readable register is not allowed (Register name: " +
264 _registerInfo.getRegisterName() +
").");
266 _rawAccessor->preRead(type);
271 template<
typename UserType,
bool isRaw>
274 if(!_dev->isOpen()) {
278 _rawAccessor->setActiveException(this->_activeException);
279 _rawAccessor->postWrite(type, versionNumber);
284 template<
typename UserType,
bool isRaw>
286 const boost::shared_ptr<TransferElement const>& other)
const {
287 auto rhsCasted = boost::dynamic_pointer_cast<const NumericAddressedBackendRegisterAccessor<UserType, isRaw>>(other);
288 if(rhsCasted.get() ==
this) {
294 if(_dev != rhsCasted->_dev) {
297 if(_registerInfo != rhsCasted->_registerInfo) {
306 template<
typename UserType,
bool isRaw>
308 return isReadable() && !isWriteable();
313 template<
typename UserType,
bool isRaw>
315 return _registerInfo.isReadable();
320 template<
typename UserType,
bool isRaw>
322 return _registerInfo.isWriteable();
327 template<
typename UserType,
bool isRaw>
329 boost::shared_ptr<DeviceBackend> exceptionBackend) {
330 this->_exceptionBackend = exceptionBackend;
331 _rawAccessor->setExceptionBackend(exceptionBackend);
336 template<
typename UserType,
bool isRaw>
338 isRaw>::getHardwareAccessingElements() {
344 template<
typename UserType,
bool isRaw>
346 isRaw>::getInternalElements() {
347 return {_rawAccessor};
352 template<
typename UserType,
bool isRaw>
354 boost::shared_ptr<TransferElement> newElement) {
355 auto casted = boost::dynamic_pointer_cast<NumericAddressedLowLevelTransferElement>(newElement);
356 if(casted && casted->isMergeable(_rawAccessor)) {
357 size_t newStartAddress = std::min(casted->_startAddress, _rawAccessor->_startAddress);
358 size_t newStopAddress = std::max(
359 casted->_startAddress + casted->_numberOfBytes, _rawAccessor->_startAddress + _rawAccessor->_numberOfBytes);
360 size_t newNumberOfBytes = newStopAddress - newStartAddress;
361 casted->changeAddress(newStartAddress, newNumberOfBytes);
362 _rawAccessor = casted;
364 _rawAccessor->setExceptionBackend(this->_exceptionBackend);
369 template<
typename UserType,
bool isRaw>
370 template<
typename COOKED_TYPE>
372 unsigned int channel,
unsigned int sample) {
373 if constexpr(isRaw && std::is_integral_v<UserType>) {
374 if constexpr(isRawType<std::make_unsigned_t<UserType>>) {
377 RawConverter::withConverter<COOKED_TYPE, std::make_unsigned_t<UserType>>(_registerInfo, 0, [&](
auto converter) {
378 rv = converter.toCooked(
389 template<
typename UserType,
bool isRaw>
390 template<
typename COOKED_TYPE>
392 unsigned int channel,
unsigned int sample, COOKED_TYPE value) {
393 if constexpr(isRaw && std::is_integral_v<UserType>) {
394 if constexpr(isRawType<std::make_unsigned_t<UserType>>) {
396 RawConverter::withConverter<COOKED_TYPE, std::make_unsigned_t<UserType>>(_registerInfo, 0, [&](
auto converter) {
#define INSTANTIATE_MULTI_TEMPLATE_FOR_CHIMERATK_USER_TYPES(TemplateClass,...)
#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.
N-dimensional register accessor.
Base class for address-based device backends (e.g.
Implementation of the NDRegisterAccessor for NumericAddressedBackends for scalar and 1D registers.
void doPostWrite(TransferType type, VersionNumber versionNumber) override
Backend specific implementation of postWrite().
std::vector< boost::shared_ptr< TransferElement > > getHardwareAccessingElements() override
Obtain the underlying TransferElements with actual hardware access.
void doPreWriteImpl(RawConverter::Converter< CookedType, RawType, sc, fc, isSigned > converter, size_t implParameter)
void doPostReadImpl(RawConverter::Converter< CookedType, RawType, sc, fc, isSigned > converter, size_t implParameter)
bool isReadOnly() const override
Check if transfer element is read only, i.e.
void setExceptionBackend(boost::shared_ptr< DeviceBackend > exceptionBackend) override
Set the backend to which the exception has to be reported.
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...
void doPostRead(TransferType type, bool hasNewData) override
Backend specific implementation of postRead().
bool doWriteTransfer(ChimeraTK::VersionNumber versionNumber) override
Implementation version of writeTransfer().
std::unique_ptr< RawConverter::ConverterLoopHelper > _converterLoopHelper
Converter to interpret the data.
void setAsCooked_impl(unsigned int channel, unsigned int sample, COOKED_TYPE value)
bool isWriteable() const override
Check if transfer element is writeable.
void doPreRead(TransferType type) override
Backend specific implementation of preRead().
void doReadTransferSynchronously() override
Implementation version of readTransfer() for synchronous reads.
void replaceTransferElement(boost::shared_ptr< TransferElement > newElement) override
Search for all underlying TransferElements which are considered identical (see sameRegister()) with t...
boost::shared_ptr< NumericAddressedBackend > _dev
the backend to use for the actual hardware access
NumericAddressedRegisterInfo _registerInfo
Address, size and fixed-point representation information of the register from the map file.
boost::shared_ptr< NumericAddressedLowLevelTransferElement > _rawAccessor
raw accessor
COOKED_TYPE getAsCooked_impl(unsigned int channel, unsigned int sample)
void doPreWrite(TransferType type, VersionNumber versionNumber) override
Backend specific implementation of preWrite().
bool isReadable() const override
Check if transfer element is readable.
NumericAddressedBackendRegisterAccessor(const boost::shared_ptr< DeviceBackend > &dev, const RegisterPath ®isterPathName, size_t numberOfWords, size_t wordOffsetInRegister, AccessModeFlags flags)
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.
std::string engineeringUnit
unsigned int getNumberOfElements() const override
Return number of elements per channel.
Converter class for conversions from raw to cooked values.
UserType toCooked(RawType rawValue)
RawType toRaw(UserType cookedValue)
Class to store a register path name.
std::string _description
Description of this variable/register.
std::string _unit
Engineering unit.
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.
@ 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)