ChimeraTK-DeviceAccess 03.25.00
Loading...
Searching...
No Matches
SubdeviceBackend.cc
Go to the documentation of this file.
1// SPDX-FileCopyrightText: Deutsches Elektronen-Synchrotron DESY, MSK, ChimeraTK Project <chimeratk-support@desy.de>
2// SPDX-License-Identifier: LGPL-3.0-or-later
3
4#include "SubdeviceBackend.h"
5
6#include "BackendFactory.h"
7#include "Exception.h"
9#include "MapFileParser.h"
12#include "TransferElement.h"
13
14#include <boost/algorithm/string.hpp>
15#include <boost/algorithm/string/predicate.hpp>
16
17#include <utility>
18
19using namespace std::string_literals;
20
21namespace ChimeraTK {
22
23 boost::shared_ptr<DeviceBackend> SubdeviceBackend::createInstance(
24 std::string address, std::map<std::string, std::string> parameters) {
25 if(parameters["map"].empty()) {
26 throw ChimeraTK::logic_error("Map file name not specified.");
27 }
28
29 if(!address.empty()) {
30 if(parameters.size() > 1) {
31 throw ChimeraTK::logic_error("SubdeviceBackend: You cannot specify both the address string and "
32 "parameters "
33 "other than the map file in the device descriptor.");
34 }
35 // decode target information from the instance
36 std::vector<std::string> tokens;
37 boost::split(tokens, address, boost::is_any_of(","));
38 if(tokens.size() != 3) {
39 throw ChimeraTK::logic_error("SubdeviceBackend: There must be exactly 3 "
40 "parameters in the address string.");
41 }
42 parameters["type"] = tokens[0];
43 parameters["device"] = tokens[1];
44 parameters["area"] = tokens[2];
45 }
46
47 return boost::shared_ptr<DeviceBackend>(new SubdeviceBackend(parameters));
48 }
49
50 /********************************************************************************************************************/
51
52 SubdeviceBackend::SubdeviceBackend(std::map<std::string, std::string> parameters) {
54
55 // check if type is specified
56 if(parameters["type"].empty()) {
57 throw ChimeraTK::logic_error("SubdeviceBackend: Type must be specified in the device descriptor.");
58 }
59
60 // check if target device is specified and open the target device
61 if(parameters["device"].empty()) {
62 throw ChimeraTK::logic_error("SubdeviceBackend: Target device name must be "
63 "specified in the device descriptor.");
64 }
65 targetAlias = parameters["device"];
66
67 // type "area":
68 if(parameters["type"] == "area") {
70 }
71 else if(parameters["type"] == "areaHandshake") {
73 }
74 // type "3regs":
75 else if(parameters["type"] == "3regs") {
77 }
78 else if(parameters["type"] == "2regs") {
80
81 if(parameters["sleep"].empty()) {
82 throw ChimeraTK::logic_error("SubdeviceBackend: Target sleep time must be specified in the device "
83 "descriptor for type '2regs'.");
84 }
85 }
86 // unknown type
87 else {
88 throw ChimeraTK::logic_error("SubdeviceBackend: Unknown type '" + parameters["type"] + "' specified.");
89 }
90
91 if(needAreaParam()) {
92 // check if target register name is specified
93 if(parameters["area"].empty()) {
94 throw ChimeraTK::logic_error("SubdeviceBackend: Target register name "
95 "must be specified in the device "
96 "descriptor for types 'area' and 'areaHandshake'.");
97 }
98 targetArea = parameters["area"];
99 }
100 else {
101 // if area is not given, data and address are required
102 if(parameters["data"].empty()) {
103 throw ChimeraTK::logic_error("SubdeviceBackend: Target data register "
104 "name must be specified in the device "
105 "descriptor for types '2regs' and '3regs'.");
106 }
107 targetData = parameters["data"];
108
109 // check if all target register names are specified
110 if(parameters["address"].empty()) {
111 throw ChimeraTK::logic_error("SubdeviceBackend: Target address register "
112 "name must be specified in the device "
113 "descriptor for type '2regs' and '3regs'.");
114 }
115 targetAddress = parameters["address"];
116 // optional parameter for delay between address write and data write
117 if(!parameters["dataDelay"].empty()) {
118 try {
119 addressToDataDelay = std::stoul(parameters["dataDelay"]);
120 }
121 catch(std::exception& e) {
122 throw ChimeraTK::logic_error("SubdeviceBackend: Invalid value for parameter 'dataDelay': '" +
123 parameters["dataDelay"] + "': " + e.what());
124 }
125 }
126 }
127 if(needStatusParam()) {
128 if(parameters["status"].empty()) {
129 throw ChimeraTK::logic_error("SubdeviceBackend: Target status register "
130 "name must be specified in the device "
131 "descriptor for types '3regs' and 'areaHandshake'.");
132 }
133 targetControl = parameters["status"];
134 if(!parameters["timeout"].empty()) {
135 try {
136 timeout = std::stoul(parameters["timeout"]);
137 }
138 catch(std::exception& e) {
140 "SubdeviceBackend: Invalid value for parameter 'timeout': '" + parameters["timeout"] + "': " + e.what());
141 }
142 }
143 }
144 // sleep parameter for 2regs, 3regs or areaHandshake case
145 if(!parameters["sleep"].empty()) {
146 try {
147 sleepTime = std::stoul(parameters["sleep"]);
148 }
149 catch(std::exception& e) {
151 "SubdeviceBackend: Invalid value for parameter 'sleep': '" + parameters["sleep"] + "': " + e.what());
152 }
153 }
154 // parse map file
155 if(parameters["map"].empty()) {
156 throw ChimeraTK::logic_error("SubdeviceBackend: Map file must be specified.");
157 }
158 MapFileParser parser;
159 std::tie(_registerMap, _metadataCatalogue) = parser.parse(parameters["map"]);
161 // FIXME: Turn off readable flag in 2reg/3reg mode
162 for(auto info : _registerMap) {
163 // we are modifying a copy here
165 _registerMap.modifyRegister(info); // Should be OK. Should not change the iterator
166 }
167 }
168 }
169
170 /********************************************************************************************************************/
171
173 if(targetDevice != nullptr) return;
174 BackendFactory& factoryInstance = BackendFactory::getInstance();
175 targetDevice = factoryInstance.createBackend(targetAlias);
176 }
177
178 /********************************************************************************************************************/
179
182 // open target backend, unconditionally as it is also used for recovery
183 targetDevice->open();
185 }
186
187 /********************************************************************************************************************/
188
191 targetDevice->close();
192 _opened = false;
193 }
194
195 /********************************************************************************************************************/
196
200
201 /********************************************************************************************************************/
202
206
207 /********************************************************************************************************************/
208
209 template<typename UserType, typename TargetUserType>
210 class FixedPointConvertingDecorator : public NDRegisterAccessorDecorator<UserType, TargetUserType> {
211 public:
214 : NDRegisterAccessorDecorator<UserType, TargetUserType>(target),
215 _fixedPointConverter(std::move(fixedPointConverter)) {}
216
217 void doPreRead(TransferType type) override { _target->preRead(type); }
218
219 void doPostRead(TransferType type, bool hasNewData) override {
220 _target->postRead(type, hasNewData);
221 if(!hasNewData) return;
222 for(size_t i = 0; i < this->buffer_2D.size(); ++i) {
223 _fixedPointConverter.template vectorToCooked<UserType>(
224 _target->accessChannel(i).begin(), _target->accessChannel(i).end(), buffer_2D[i].begin());
225 }
226 this->_dataValidity = _target->dataValidity();
227 this->_versionNumber = _target->getVersionNumber();
228 }
229
230 void doPreWrite(TransferType type, VersionNumber versionNumber) override {
231 for(size_t i = 0; i < this->buffer_2D.size(); ++i) {
232 for(size_t j = 0; j < this->buffer_2D[i].size(); ++j) {
233 _target->accessChannel(i)[j] = _fixedPointConverter.toRaw<UserType>(buffer_2D[i][j]);
234 }
235 }
236 _target->setDataValidity(this->_dataValidity);
237 _target->preWrite(type, versionNumber);
238 }
239
240 void doPostWrite(TransferType type, VersionNumber versionNumber) override {
241 _target->postWrite(type, versionNumber);
242 }
243
244 [[nodiscard]] bool mayReplaceOther(
245 const boost::shared_ptr<ChimeraTK::TransferElement const>& other) const override {
246 auto casted = boost::dynamic_pointer_cast<FixedPointConvertingDecorator<UserType, TargetUserType> const>(other);
247 if(!casted) return false;
248 if(_fixedPointConverter != casted->_fixedPointConverter) return false;
249 return _target->mayReplaceOther(casted->_target);
250 }
251
252 protected:
254
255 using NDRegisterAccessorDecorator<UserType, TargetUserType>::_target;
256 using NDRegisterAccessor<UserType>::buffer_2D;
257 };
258
259 /********************************************************************************************************************/
260
261 template<typename TargetUserType>
263 public:
270
271 template<typename COOKED_TYPE>
272 COOKED_TYPE getAsCooked_impl(unsigned int channel, unsigned int sample) {
273 std::vector<int32_t> rawVector(1);
274 std::vector<COOKED_TYPE> cookedVector(1);
275 rawVector[0] = buffer_2D[channel][sample];
276 _fixedPointConverter.template vectorToCooked<COOKED_TYPE>(
277 rawVector.begin(), rawVector.end(), cookedVector.begin());
278 return cookedVector[0];
279 }
280
281 template<typename COOKED_TYPE>
282 void setAsCooked_impl(unsigned int channel, unsigned int sample, COOKED_TYPE value) {
283 buffer_2D[channel][sample] = _fixedPointConverter.toRaw<COOKED_TYPE>(value);
284 }
285
286 [[nodiscard]] bool mayReplaceOther(
287 const boost::shared_ptr<ChimeraTK::TransferElement const>& other) const override {
288 auto casted = boost::dynamic_pointer_cast<FixedPointConvertingRawDecorator<TargetUserType> const>(other);
289 if(!casted) return false;
290 if(_fixedPointConverter != casted->_fixedPointConverter) return false;
291 return _target->mayReplaceOther(casted->_target);
292 }
293
294 protected:
296
301
302 using NDRegisterAccessorDecorator<TargetUserType>::_target;
303 using NDRegisterAccessor<TargetUserType>::buffer_2D;
304 };
305
306 /********************************************************************************************************************/
307
308 template<typename UserType>
309 boost::shared_ptr<NDRegisterAccessor<UserType>> SubdeviceBackend::getRegisterAccessor_impl(
310 const RegisterPath& registerPathName, size_t numberOfWords, size_t wordOffsetInRegister, AccessModeFlags flags) {
312 boost::shared_ptr<NDRegisterAccessor<UserType>> returnValue;
313 if(type == Type::area) {
314 returnValue = getRegisterAccessor_area<UserType>(registerPathName, numberOfWords, wordOffsetInRegister, flags);
315 }
317 returnValue =
318 getRegisterAccessor_synchronized<UserType>(registerPathName, numberOfWords, wordOffsetInRegister, flags);
319 }
320 if(!returnValue) {
321 throw ChimeraTK::logic_error("Unknown type");
322 }
323 returnValue->setExceptionBackend(shared_from_this());
324
325 return returnValue;
326 }
327
328 /********************************************************************************************************************/
329
331 size_t wordOffsetInRegister, bool forceAlignment) {
332 // check that the bar is 0
333 if(info.bar != 0) {
334 // throw ChimeraTK::logic_error("SubdeviceBackend: BARs other then 0 are not supported. Register '" +
335 // registerPathName + "' is in BAR " + std::to_string(info->bar) + ".");
336 std::cout << "SubdeviceBackend: WARNING: BAR others then 0 detected. BAR 0 will be used instead. Register "
337 << info.pathName << " is in BAR " << std::to_string(info.bar) << "." << std::endl;
338 }
339
340 // check that the register is not a 2D multiplexed register, which is not yet
341 // supported
342 if(info.channels.size() != 1) {
343 throw ChimeraTK::logic_error("SubdeviceBackend: 2D multiplexed registers are not yet supported.");
344 }
345
346 // Partial accessors are not implemented correctly yet. Better throw than getting something that seems to work but
347 // does the wrong thing.
349 if(wordOffsetInRegister != 0) {
350 throw ChimeraTK::logic_error("SubdeviceBackend: Partial accessors are not supported yet for type "
351 "threeRegisters and twoRegisters. Register " +
352 info.pathName + " has requested offset " + std::to_string(wordOffsetInRegister));
353 }
354 if((numberOfWords != 0) && (numberOfWords != info.nElements)) {
355 throw ChimeraTK::logic_error("SubdeviceBackend: Partial accessors are not supported yet for type "
356 "threeRegisters and twoRegisters. Register " +
357 info.pathName + " has requested nElements " + std::to_string(numberOfWords) + " of " +
359 }
360 }
361
362 // compute full offset (from map file and function arguments)
363 size_t byteOffset = info.address + sizeof(int32_t) * wordOffsetInRegister;
364 if(forceAlignment && (byteOffset % 4 != 0)) {
365 throw ChimeraTK::logic_error("SubdeviceBackend: Only addresses which are a "
366 "multiple of 4 are supported.");
367 }
368
369 // compute effective length
370 if(numberOfWords == 0) {
371 numberOfWords = info.nElements;
372 }
373 else if(numberOfWords > info.nElements) {
374 throw ChimeraTK::logic_error("SubdeviceBackend: Requested " + std::to_string(numberOfWords) +
375 " elements from register '" + info.pathName + "', which only has a length of " +
376 std::to_string(info.nElements) + " elements.");
377 }
378
379 // Check that the requested register fits in the register description. The downstream register might be larger
380 // so we cannot delegate the check
381 if(numberOfWords + wordOffsetInRegister > info.nElements) {
383 "SubdeviceBackend: Requested offset + number of words exceeds the size of the register '" + info.pathName +
384 "'!");
385 }
386 }
387
388 /********************************************************************************************************************/
389
390 template<typename UserType>
391 boost::shared_ptr<NDRegisterAccessor<UserType>> SubdeviceBackend::getRegisterAccessor_area(
392 const RegisterPath& registerPathName, size_t numberOfWords, size_t wordOffsetInRegister, AccessModeFlags flags) {
393 assert(type == Type::area);
394
395 // obtain register info
396 auto info = _registerMap.getBackendRegister(registerPathName);
397 verifyRegisterAccessorSize(info, numberOfWords, wordOffsetInRegister, true);
398
399 // store raw flag for later (since we modify the flags)
400 bool isRaw = flags.has(AccessMode::raw);
401
402 // obtain target accessor in raw mode
403 size_t wordOffset = (info.address + sizeof(int32_t) * wordOffsetInRegister) / 4;
404 flags.add(AccessMode::raw);
405 auto rawAcc = targetDevice->getRegisterAccessor<int32_t>(targetArea, numberOfWords, wordOffset, flags);
406
407 // decorate with appropriate FixedPointConvertingDecorator. This is done even
408 // when in raw mode so we can properly implement getAsCooked()/setAsCooked().
409 if(!isRaw) {
410 return boost::make_shared<FixedPointConvertingDecorator<UserType, int32_t>>(rawAcc,
411 FixedPointConverter<DEPRECATED_FIXEDPOINT_DEFAULT>(registerPathName, info.channels.front().width,
412 info.channels.front().nFractionalBits, info.channels.front().signedFlag));
413 }
414 // this is handled by the template specialisation for int32_t
415 throw ChimeraTK::logic_error("Given UserType when obtaining the SubdeviceBackend in raw mode does not "s +
416 "match the expected type. Use an int32_t instead! (Register name: " + registerPathName + "')");
417 }
418
419 /********************************************************************************************************************/
420
421 boost::shared_ptr<SubdeviceRegisterAccessor> SubdeviceBackend::getRegisterAccessor_helper(
422 const NumericAddressedRegisterInfo& info, size_t numberOfWords, size_t wordOffsetInRegister,
423 AccessModeFlags flags) {
425
426 verifyRegisterAccessorSize(info, numberOfWords, wordOffsetInRegister, false);
427
428 // check if register access properly specified in map file
429 if(!info.isWriteable()) {
430 throw ChimeraTK::logic_error("SubdeviceBackend: Subdevices of type 3reg or "
431 "2reg or areaHandshake must have writeable registers only!");
432 }
433
434 // obtain target accessors
435 boost::shared_ptr<NDRegisterAccessor<int32_t>> accAddress, accData;
436 if(!needAreaParam()) {
437 accAddress = targetDevice->getRegisterAccessor<int32_t>(targetAddress, 1, 0, {});
438 accData = targetDevice->getRegisterAccessor<int32_t>(targetData, 0, 0, {});
439 }
440 else {
441 // check alignment just like it is done in 'area' type subdevice which is based on raw int32 accessors to target
442 verifyRegisterAccessorSize(info, numberOfWords, wordOffsetInRegister, true);
443
444 // obtain target accessor in raw mode
445 size_t wordOffset = (info.address + sizeof(int32_t) * wordOffsetInRegister) / 4;
446 flags.add(AccessMode::raw);
447 accData = targetDevice->getRegisterAccessor<int32_t>(targetArea, numberOfWords, wordOffset, flags);
448 }
449 boost::shared_ptr<NDRegisterAccessor<int32_t>> accStatus;
450 if(needStatusParam()) {
451 accStatus = targetDevice->getRegisterAccessor<int32_t>(targetControl, 1, 0, {});
452 }
453
454 size_t byteOffset = info.address + sizeof(int32_t) * wordOffsetInRegister;
455 auto sharedThis = boost::enable_shared_from_this<DeviceBackend>::shared_from_this();
456
457 return boost::make_shared<SubdeviceRegisterAccessor>(boost::dynamic_pointer_cast<SubdeviceBackend>(sharedThis),
458 info.pathName, accAddress, accData, accStatus, byteOffset, numberOfWords);
459 }
460
461 /********************************************************************************************************************/
462
463 template<typename UserType>
464 boost::shared_ptr<NDRegisterAccessor<UserType>> SubdeviceBackend::getRegisterAccessor_synchronized(
465 const RegisterPath& registerPathName, size_t numberOfWords, size_t wordOffsetInRegister,
466 const AccessModeFlags& flags) {
467 auto info = _registerMap.getBackendRegister(registerPathName);
468 boost::shared_ptr<SubdeviceRegisterAccessor> rawAcc =
469 getRegisterAccessor_helper(info, numberOfWords, wordOffsetInRegister, flags);
470
471 // decorate with appropriate FixedPointConvertingDecorator. This is done even
472 // when in raw mode so we can properly implement getAsCooked()/setAsCooked().
473 if(!flags.has(AccessMode::raw)) {
474 return boost::make_shared<FixedPointConvertingDecorator<UserType, int32_t>>(rawAcc,
475 FixedPointConverter<DEPRECATED_FIXEDPOINT_DEFAULT>(registerPathName, info.channels.front().width,
476 info.channels.front().nFractionalBits, info.channels.front().signedFlag));
477 }
478 // this is handled by the template specialisation for int32_t
479 throw ChimeraTK::logic_error("Given UserType when obtaining the SubdeviceBackend in raw mode does not "s +
480 "match the expected type. Use an int32_t instead! (Register name: " + registerPathName + "')");
481 }
482
483 /********************************************************************************************************************/
484
485 template<>
486 boost::shared_ptr<NDRegisterAccessor<int32_t>> SubdeviceBackend::getRegisterAccessor_area<int32_t>(
487 const RegisterPath& registerPathName, size_t numberOfWords, size_t wordOffsetInRegister, AccessModeFlags flags) {
488 assert(type == Type::area);
489
490 // obtain register info
491 auto info = _registerMap.getBackendRegister(registerPathName);
492 verifyRegisterAccessorSize(info, numberOfWords, wordOffsetInRegister, true);
493
494 // store raw flag for later (since we modify the flags)
495 bool isRaw = flags.has(AccessMode::raw);
496
497 // obtain target accessor in raw mode
498 size_t wordOffset = (info.address + sizeof(int32_t) * wordOffsetInRegister) / 4;
499 flags.add(AccessMode::raw);
500 auto rawAcc = targetDevice->getRegisterAccessor<int32_t>(targetArea, numberOfWords, wordOffset, flags);
501
502 // decorate with appropriate FixedPointConvertingDecorator. This is done even
503 // when in raw mode so we can properly implement getAsCooked()/setAsCooked().
504 if(!isRaw) {
505 return boost::make_shared<FixedPointConvertingDecorator<int32_t, int32_t>>(rawAcc,
506 FixedPointConverter<DEPRECATED_FIXEDPOINT_DEFAULT>(registerPathName, info.channels.front().width,
507 info.channels.front().nFractionalBits, info.channels.front().signedFlag));
508 }
509 return boost::make_shared<FixedPointConvertingRawDecorator<int32_t>>(rawAcc,
510 FixedPointConverter<DEPRECATED_FIXEDPOINT_DEFAULT>(registerPathName, info.channels.front().width,
511 info.channels.front().nFractionalBits, info.channels.front().signedFlag));
512 }
513
514 /********************************************************************************************************************/
515
516 template<>
517 boost::shared_ptr<NDRegisterAccessor<int32_t>> SubdeviceBackend::getRegisterAccessor_synchronized<int32_t>(
518 const RegisterPath& registerPathName, size_t numberOfWords, size_t wordOffsetInRegister,
519 const AccessModeFlags& flags) {
520 auto info = _registerMap.getBackendRegister(registerPathName);
521 boost::shared_ptr<SubdeviceRegisterAccessor> rawAcc =
522 getRegisterAccessor_helper(info, numberOfWords, wordOffsetInRegister, flags);
523
524 // decorate with appropriate FixedPointConvertingDecorator. This is done even
525 // when in raw mode so we can properly implement getAsCooked()/setAsCooked().
526 if(!flags.has(AccessMode::raw)) {
527 return boost::make_shared<FixedPointConvertingDecorator<int32_t, int32_t>>(rawAcc,
528 FixedPointConverter<DEPRECATED_FIXEDPOINT_DEFAULT>(registerPathName, info.channels.front().width,
529 info.channels.front().nFractionalBits, info.channels.front().signedFlag));
530 }
531 return boost::make_shared<FixedPointConvertingRawDecorator<int32_t>>(rawAcc,
532 FixedPointConverter<DEPRECATED_FIXEDPOINT_DEFAULT>(registerPathName, info.channels.front().width,
533 info.channels.front().nFractionalBits, info.channels.front().signedFlag));
534 }
535
536 /********************************************************************************************************************/
537
542
543 /********************************************************************************************************************/
544
547 targetDevice->activateAsyncRead();
548 }
549 /********************************************************************************************************************/
550
551 std::set<DeviceBackend::BackendID> SubdeviceBackend::getInvolvedBackendIDs() {
553 std::set<DeviceBackend::BackendID> retVal{getBackendID()};
554 retVal.merge(targetDevice->getInvolvedBackendIDs());
555 return retVal;
556 }
557
558} // namespace ChimeraTK
#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.
Definition AccessMode.h:48
bool has(AccessMode flag) const
Check if a certain flag is in the set.
Definition AccessMode.cc:20
void add(AccessMode flag)
Add the given flag to the set.
Definition AccessMode.cc:62
void checkForUnknownFlags(const std::set< AccessMode > &knownFlags) const
Check of any flag which is not in the given set "knownFlags" is set.
Definition AccessMode.cc:32
BackendFactory is a the factory class to create devices.
static BackendFactory & getInstance()
Static function to get an instance of factory.
boost::shared_ptr< DeviceBackend > createBackend(const std::string &aliasOrUri)
Create a new backend and return the instance as a shared pointer.
void modifyRegister(const BackendRegisterInfo &registerInfo)
Replaces the register information for the matching register.
BackendID getBackendID()
Get a unique ID for this backend instance.
void setOpenedAndClearException() noexcept
Backends should call this function at the end of a (successful) open() call.
std::string getActiveExceptionMessage() noexcept
std::atomic< bool > _opened
flag if backend is opened
The fixed point converter provides conversion functions between a user type and up to 32 bit fixed po...
RawType toRaw(UserType cookedValue) const
Conversion function from type T to fixed point.
FixedPointConvertingDecorator(const boost::shared_ptr< ChimeraTK::NDRegisterAccessor< TargetUserType > > &target, FixedPointConverter< DEPRECATED_FIXEDPOINT_DEFAULT > fixedPointConverter)
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().
bool mayReplaceOther(const boost::shared_ptr< ChimeraTK::TransferElement const > &other) const override
void doPostRead(TransferType type, bool hasNewData) override
Backend specific implementation of postRead().
FixedPointConverter< DEPRECATED_FIXEDPOINT_DEFAULT > _fixedPointConverter
DEFINE_VIRTUAL_FUNCTION_TEMPLATE_VTABLE_FILLER(FixedPointConvertingRawDecorator< TargetUserType >, setAsCooked_impl, 3)
void setAsCooked_impl(unsigned int channel, unsigned int sample, COOKED_TYPE value)
FixedPointConverter< DEPRECATED_FIXEDPOINT_DEFAULT > _fixedPointConverter
bool mayReplaceOther(const boost::shared_ptr< ChimeraTK::TransferElement const > &other) const override
FixedPointConvertingRawDecorator(const boost::shared_ptr< ChimeraTK::NDRegisterAccessor< TargetUserType > > &target, FixedPointConverter< DEPRECATED_FIXEDPOINT_DEFAULT > fixedPointConverter)
COOKED_TYPE getAsCooked_impl(unsigned int channel, unsigned int sample)
DEFINE_VIRTUAL_FUNCTION_TEMPLATE_VTABLE_FILLER(FixedPointConvertingRawDecorator< TargetUserType >, getAsCooked_impl, 2)
static std::pair< NumericAddressedRegisterCatalogue, MetadataCatalogue > parse(const std::string &fileName)
Performs parsing of specified MAP file, resulting in catalogue objects describing all registers and m...
Container for backend metadata.
Base class for decorators of the NDRegisterAccessor.
N-dimensional register accessor.
std::vector< std::vector< UserType > > buffer_2D
Buffer of converted data elements.
NumericAddressedRegisterInfo getBackendRegister(const RegisterPath &registerPathName) const override
Note: Override this function if backend has "hidden" registers which are not added to the map and hen...
std::unique_ptr< BackendRegisterCatalogueBase > clone() const override
Create deep copy of the catalogue.
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)
uint64_t address
Lower part of the address relative to BAR, in bytes.
bool isWriteable() const override
Return whether the register is writeable.
Catalogue of register information.
Class to store a register path name.
Backend for subdevices which are passed through some register or area of another device (subsequently...
std::string targetAddress
for type == threeRegisters or twoRegisters: the name of the target registers
size_t timeout
timeout (in milliseconds), used in threeRegisters to throw a runtime_error if status register stuck a...
NumericAddressedRegisterCatalogue _registerMap
map from register names to addresses
size_t addressToDataDelay
for type == threeRegisters or twoRegisters: sleep time between address and data write
void open() override
Open the device.
static boost::shared_ptr< DeviceBackend > createInstance(std::string address, std::map< std::string, std::string > parameters)
void close() override
Close the device.
MetadataCatalogue getMetadataCatalogue() const override
Return the device metadata catalogue.
std::string targetAlias
the target device name
void setExceptionImpl() noexcept override
Function to be (optionally) implemented by backends if additional actions are needed when switching t...
MetadataCatalogue _metadataCatalogue
SubdeviceBackend(std::map< std::string, std::string > parameters)
void obtainTargetBackend()
obtain the target backend if not yet done
boost::shared_ptr< NDRegisterAccessor< UserType > > getRegisterAccessor_impl(const RegisterPath &registerPathName, size_t numberOfWords, size_t wordOffsetInRegister, AccessModeFlags flags)
std::string targetArea
for type == area: the name of the target register
void verifyRegisterAccessorSize(const NumericAddressedRegisterInfo &info, size_t &numberOfWords, size_t wordOffsetInRegister, bool enforceAlignment)
Check consistency of the passed sizes and offsets against the information in the map file Will adjust...
Type type
type of the subdeivce
boost::shared_ptr< SubdeviceRegisterAccessor > getRegisterAccessor_helper(const NumericAddressedRegisterInfo &info, size_t numberOfWords, size_t wordOffsetInRegister, AccessModeFlags flags)
size_t sleepTime
for type == threeRegisters or twoRegisters: sleep time of polling loop resp. between operations,...
boost::shared_ptr< ChimeraTK::DeviceBackend > targetDevice
The target device backend itself.
boost::shared_ptr< NDRegisterAccessor< UserType > > getRegisterAccessor_area(const RegisterPath &registerPathName, size_t numberOfWords, size_t wordOffsetInRegister, AccessModeFlags flags)
getRegisterAccessor implemenation for area types
RegisterCatalogue getRegisterCatalogue() const override
Return the register catalogue with detailed information on all registers.
void activateAsyncRead() noexcept override
Activate asyncronous read for all transfer elements where AccessMode::wait_for_new_data is set.
std::set< DeviceBackend::BackendID > getInvolvedBackendIDs() override
Get the backend IDs of all involved backends.
boost::shared_ptr< NDRegisterAccessor< UserType > > getRegisterAccessor_synchronized(const RegisterPath &registerPathName, size_t numberOfWords, size_t wordOffsetInRegister, const AccessModeFlags &flags)
getRegisterAccessor implemenation for threeRegisters types
DataValidity _dataValidity
The validity of the data in the application buffer.
VersionNumber _versionNumber
The version number of the last successful transfer.
Class for generating and holding version numbers without exposing a numeric representation.
Exception thrown when a logic error has occured.
Definition Exception.h:51
@ 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.
STL namespace.
std::string to_string(const std::string &v)