ChimeraTK-DeviceAccess 03.29.00
Loading...
Searching...
No Matches
testNumericAddressedBackendUnified.cpp
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#define BOOST_TEST_DYN_LINK
5// Define a name for the test module.
6#define BOOST_TEST_MODULE NumericAddressedBackendUnified
7// Only after defining the name include the unit test header.
8#include <boost/test/unit_test.hpp>
9using namespace boost::unit_test_framework;
10
11#include "BackendFactory.h"
12#include "Device.h"
13#include "DummyBackend.h"
16#include "TransferGroup.h"
17#include "UnifiedBackendTest.h"
18
19namespace ChimeraTK {
20 using namespace ChimeraTK;
21}
22using namespace ChimeraTK;
23
24/* ===============================================================================================
25 * Despite its name, this test also qualifies as an unified test for the (Exception)DummyBackend.
26 * They are thinish implementations of the NumericAddressedBackend's internal interface.
27 * ==============================================================================================*/
28
29// Create a test suite which holds all your tests.
30BOOST_AUTO_TEST_SUITE(NumericAddressedBackendUnifiedTestSuite)
31
32/**********************************************************************************************************************/
33
34static std::string cdd("(ExceptionDummy:1?map=test3.map)");
35static auto exceptionDummy =
36 boost::dynamic_pointer_cast<ExceptionDummy>(BackendFactory::getInstance().createBackend(cdd));
37
38static std::string cddMuxed("(ExceptionDummy:1?map=muxedDataAccessor.jmap)");
39static auto exceptionDummyMuxed =
40 boost::dynamic_pointer_cast<ExceptionDummy>(BackendFactory::getInstance().createBackend(cddMuxed));
41
42static std::string cddBitRange("(ExceptionDummy:1?map=unifiedTest.jmap)");
43static auto exceptionDummyBitRange =
44 boost::dynamic_pointer_cast<ExceptionDummy>(BackendFactory::getInstance().createBackend(cddBitRange));
45
46/**********************************************************************************************************************/
47
49 std::string path() { return "/Integers/signed32"; }
50 bool isWriteable() { return true; }
51 bool isReadable() { return true; }
53 size_t nChannels() { return 1; }
54 size_t nElementsPerChannel() { return 1; }
55 size_t writeQueueLength() { return std::numeric_limits<size_t>::max(); }
56 size_t nRuntimeErrorCases() { return 1; }
57 typedef int32_t minimumUserType;
59
60 static constexpr auto capabilities = TestCapabilities<>()
62 .disableAsyncReadInconsistency()
63 .disableSwitchReadOnly()
64 .disableSwitchWriteOnly()
65 .disableTestWriteNeverLosesData()
66 .enableTestRawTransfer();
67
69
70 template<typename Type>
71 std::vector<std::vector<Type>> generateValue([[maybe_unused]] bool raw = false) {
72 return {{acc + 3}};
73 }
74
75 template<typename UserType>
76 std::vector<std::vector<UserType>> getRemoteValue([[maybe_unused]] bool raw = false) {
77 return {{acc}};
78 }
79
80 void setRemoteValue() { acc = generateValue<minimumUserType>()[0][0]; }
81
82 void setForceRuntimeError(bool enable, size_t) {
83 exceptionDummy->throwExceptionRead = enable;
84 exceptionDummy->throwExceptionWrite = enable;
85 exceptionDummy->throwExceptionOpen = enable;
86 }
87};
88
90 std::string path() { return "/Integers/signed32_async"; }
91 bool isWriteable() { return false; }
92 bool isReadable() { return true; }
96 size_t nChannels() { return 1; }
97 size_t nElementsPerChannel() { return 1; }
98 size_t writeQueueLength() { return std::numeric_limits<size_t>::max(); }
99 size_t nRuntimeErrorCases() { return 1; }
100 typedef int32_t minimumUserType;
102
103 static constexpr auto capabilities = TestCapabilities<>()
105 .disableAsyncReadInconsistency()
106 .disableSwitchReadOnly()
107 .disableSwitchWriteOnly()
108 .disableTestWriteNeverLosesData()
109 .enableTestRawTransfer();
110
112
113 template<typename Type>
114 std::vector<std::vector<Type>> generateValue([[maybe_unused]] bool raw = false) {
115 return {{acc + 3}};
116 }
117
118 template<typename UserType>
119 std::vector<std::vector<UserType>> getRemoteValue([[maybe_unused]] bool raw = false) {
120 return {{acc}};
121 }
122
124 acc = generateValue<minimumUserType>()[0][0];
125 if(exceptionDummy->isOpen()) exceptionDummy->triggerInterrupt(6);
126 }
127
128 void forceAsyncReadInconsistency() { acc = generateValue<minimumUserType>()[0][0]; }
129
130 void setForceRuntimeError(bool enable, size_t) {
131 exceptionDummy->throwExceptionRead = enable;
132 exceptionDummy->throwExceptionWrite = enable;
133 exceptionDummy->throwExceptionOpen = enable;
134 if(exceptionDummy->isOpen()) exceptionDummy->triggerInterrupt(6);
135 }
136};
138 // Using the DUMMY_WRITEABLE register here since usually an async register is r/o implicitly
139 std::string path() { return "/Integers/signed32_async/DUMMY_WRITEABLE"; }
140 bool isWriteable() { return true; }
141 bool isReadable() { return true; }
145 size_t nChannels() { return 1; }
146 size_t nElementsPerChannel() { return 1; }
147 size_t writeQueueLength() { return std::numeric_limits<size_t>::max(); }
148 size_t nRuntimeErrorCases() { return 1; }
149 typedef int32_t minimumUserType;
151
152 static constexpr auto capabilities = TestCapabilities<>()
154 .disableAsyncReadInconsistency()
155 .disableSwitchReadOnly()
156 .disableSwitchWriteOnly()
157 .disableTestWriteNeverLosesData()
158 .enableTestRawTransfer();
159
160 DummyRegisterAccessor<int32_t> acc{exceptionDummy.get(), "", "/Integers/signed32_async"};
161
162 template<typename Type>
163 std::vector<std::vector<Type>> generateValue([[maybe_unused]] bool raw = false) {
164 return {{acc + 3}};
165 }
166
167 template<typename UserType>
168 std::vector<std::vector<UserType>> getRemoteValue([[maybe_unused]] bool raw = false) {
169 return {{acc}};
170 }
171
173 acc = generateValue<minimumUserType>()[0][0];
174 if(exceptionDummy->isOpen()) exceptionDummy->triggerInterrupt(6);
175 }
176
177 void forceAsyncReadInconsistency() { acc = generateValue<minimumUserType>()[0][0]; }
178
179 void setForceRuntimeError(bool enable, size_t) {
180 exceptionDummy->throwExceptionRead = enable;
181 exceptionDummy->throwExceptionWrite = enable;
182 exceptionDummy->throwExceptionOpen = enable;
183 if(exceptionDummy->isOpen()) exceptionDummy->triggerInterrupt(6);
184 }
185};
186
187/**********************************************************************************************************************/
188
189template<typename Derived, typename rawUserType>
191 Derived* derived{static_cast<Derived*>(this)};
192
193 bool isWriteable() { return true; }
194 bool isReadable() { return true; }
196 size_t nChannels() { return 1; }
197 size_t nElementsPerChannel() { return 1; }
198 size_t writeQueueLength() { return std::numeric_limits<size_t>::max(); }
199 size_t nRuntimeErrorCases() { return 1; }
200
201 // The padding (i.e. the bits of the 32 bit word which are not part of the register under test but of the neighbouring
202 // registers) needs to be checked to be unchanged in write operations. This test assumes that in between the calls to
203 // generateValue() and getRemoteValue() the padding bits are not *intentionally* changed (e.g. by testing another
204 // register in between). This is true for the UnifiedBackendTest right now.
205 // TODO: In future it may be better to foresee a "no-side-effect" test in the UnifiedBackendTest, which tests that
206 // other registers stay unchanged (caveat: need to specify which registers to look at! We have intentionally
207 // overlapping registers in this test which of course will change!)
208 int32_t lastPadding{0};
210
211 static constexpr auto capabilities = TestCapabilities<>()
213 .disableAsyncReadInconsistency()
214 .disableSwitchReadOnly()
215 .disableSwitchWriteOnly()
216 .disableTestWriteNeverLosesData()
217 .enableTestRawTransfer();
218
219 // This register shares the address space with all our test registers. It gives us direct access to the 4 byte
220 // address range, so we can test the correct placement of the unaligned values.
221 DummyRegisterRawAccessor acc{exceptionDummy, "", "/Integers/unsigned32"};
222
223 rawUserType get() { return (acc & derived->bitmask) >> derived->bitshift; }
224
225 void set(rawUserType val) {
226 acc &= ~derived->bitmask;
229 acc |= (val << derived->bitshift) & derived->bitmask;
230 }
231
232 // Type can be user type or raw type, depeding of the raw flag
233 template<typename Type>
234 std::vector<std::vector<Type>> generateValue(bool raw = false) {
235 rawUserType newRawValue = static_cast<rawUserType>(get() + derived->rawIncrement);
236 Type v = ChimeraTK::numeric::convert<Type>(raw ? newRawValue : (newRawValue * derived->rawToCooked));
237 /* std::cout << "generateValue " << derived->path() << " " << float(rawUserType(get() + derived->rawIncrement))
238 << " -> " << float(v) << std::endl; */
239 lastPadding = acc & ~derived->bitmask;
241 return {{v}};
242 }
243
244 // We use the same function to implement raw and cooked reading.
245 // Do the calculation on the target type, then decide on the padding error.
246 // rawToCooked might undo the ++ effect in case
247 // of rounding. When getting cooked, the ++ must happen on the UserType.
248 // Type can be UserType or RawType.
249 template<typename Type>
250 std::vector<std::vector<Type>> getRemoteValue(bool raw = false) {
251 Type v = get() * (raw ? 1 : derived->rawToCooked);
252 if((acc & ~derived->bitmask) != lastPadding) {
254 std::cerr << "getRemoteValue(): Padding data has changed. Test will be failed by returing a false remote value "
255 << "(off by one)." << std::endl;
257 }
258 v++;
259 return {{v}};
260 }
261 /* std::cout << "getRemoteValue " << derived->path() << " " << float(get()) << " -> " << float(v) << std::endl; */
262 return {{v}};
263 }
264
266 set(get() + derived->rawIncrement);
267 /* std::cout << "setRemoteValue " << derived->path() << " " << float(get()) << " -> " <<
268 getRemoteValue<float>()[0][0]
269 << std::endl; */
270 }
271
272 void setForceRuntimeError(bool enable, size_t) {
273 exceptionDummy->throwExceptionRead = enable;
274 exceptionDummy->throwExceptionWrite = enable;
275 exceptionDummy->throwExceptionOpen = enable;
276 }
277};
278
279/**********************************************************************************************************************/
280
281struct ShortRaw_signed16 : ShortRaw_base<ShortRaw_signed16, int16_t> {
282 std::string path() { return "/ShortRaw/signed16"; }
283 typedef int16_t minimumUserType;
285
286 int16_t rawToCooked = 1;
287 // The rawIncrements are chosen such that we generate different values for different variables, and to cover the
288 // specific value range with very few values (to check signed vs. unsigned). Uncomment the above couts in the base
289 // class to check the generated values.
290 int16_t rawIncrement = 17117;
291 int bitshift = 0;
292 int32_t bitmask = 0x0000FFFF;
293};
294
295/**********************************************************************************************************************/
296
297struct ShortRaw_unsigned16 : ShortRaw_base<ShortRaw_unsigned16, uint16_t> {
298 std::string path() { return "/ShortRaw/unsigned16"; }
299 typedef uint16_t minimumUserType;
300 typedef int16_t rawUserType;
301
302 int16_t rawToCooked = 1;
303 int16_t rawIncrement = 17119;
304 int bitshift = 16;
305 int32_t bitmask = 0xFFFF0000;
306};
307
308/**********************************************************************************************************************/
309
310struct ShortRaw_fixedPoint16_8u : ShortRaw_base<ShortRaw_fixedPoint16_8u, uint16_t> {
311 std::string path() { return "/ShortRaw/fixedPoint16_8u"; }
312 typedef float minimumUserType;
313 typedef int16_t rawUserType;
314
315 float rawToCooked = 1. / 256.;
316 int16_t rawIncrement = 17121;
317 int bitshift = 0;
318 int32_t bitmask = 0x0000FFFF;
319};
320
321/**********************************************************************************************************************/
322
323struct ShortRaw_fixedPoint16_8s : ShortRaw_base<ShortRaw_fixedPoint16_8s, int16_t> {
324 std::string path() { return "/ShortRaw/fixedPoint16_8s"; }
325 typedef float minimumUserType;
326 typedef int16_t rawUserType;
327
328 float rawToCooked = 1. / 256.;
329 int16_t rawIncrement = 17123;
330 int bitshift = 16;
331 int32_t bitmask = 0xFFFF0000;
332};
333
334/**********************************************************************************************************************/
335
336struct ByteRaw_signed8 : ShortRaw_base<ByteRaw_signed8, int8_t> {
337 std::string path() { return "/ByteRaw/signed8"; }
338 typedef int8_t minimumUserType;
339 typedef int8_t rawUserType;
340
341 int8_t rawToCooked = 1;
342 int8_t rawIncrement = 119;
343 int bitshift = 0;
344 int32_t bitmask = 0x000000FF;
345};
346
347/**********************************************************************************************************************/
348
349struct ByteRaw_unsigned8 : ShortRaw_base<ByteRaw_unsigned8, uint8_t> {
350 std::string path() { return "/ByteRaw/unsigned8"; }
351 typedef uint8_t minimumUserType;
352 typedef int8_t rawUserType;
353
354 uint8_t rawToCooked = 1;
355 int8_t rawIncrement = 121;
356 int bitshift = 8;
357 int32_t bitmask = 0x0000FF00;
358};
359
360/**********************************************************************************************************************/
361
362struct ByteRaw_fixedPoint8_4u : ShortRaw_base<ByteRaw_fixedPoint8_4u, uint8_t> {
363 std::string path() { return "/ByteRaw/fixedPoint8_4u"; }
364 typedef float minimumUserType;
365 typedef int8_t rawUserType;
366
367 float rawToCooked = 1. / 16.;
368 int8_t rawIncrement = 123;
369 int bitshift = 16;
370 int32_t bitmask = 0x00FF0000;
371};
372
373/**********************************************************************************************************************/
374
375struct ByteRaw_fixedPoint8_4s : ShortRaw_base<ByteRaw_fixedPoint8_4s, int8_t> {
376 std::string path() { return "/ByteRaw/fixedPoint8_4s"; }
377 typedef float minimumUserType;
378 typedef int8_t rawUserType;
379
380 float rawToCooked = 1. / 16.;
381 int8_t rawIncrement = 125;
382 int bitshift = 24;
383 int32_t bitmask = 0xFF000000;
384};
385
386/**********************************************************************************************************************/
387
388struct AsciiData {
389 static std::string path() { return "/Text/someAsciiData"; }
390 static bool isWriteable() { return true; }
391 static bool isReadable() { return true; }
392 using minimumUserType = std::string;
394
395 static size_t nChannels() { return 1; }
396 static size_t nElementsPerChannel() { return 1; }
397 static size_t writeQueueLength() { return std::numeric_limits<size_t>::max(); }
398 static size_t nRuntimeErrorCases() { return 1; }
399
400 static constexpr auto capabilities = TestCapabilities<>()
402 .disableAsyncReadInconsistency()
403 .disableSwitchReadOnly()
404 .disableSwitchWriteOnly()
405 .disableTestWriteNeverLosesData()
406 .disableTestRawTransfer();
407
408 // Note: The DummyRegisterAccessor does not yet work properly with none 32-bit word sizes.
409 DummyRegisterAccessor<uint32_t> acc{exceptionDummy.get(), "Text", "someAsciiData_as_i32"};
410
411 std::string textBase{"Some $%#@! characters "};
412 size_t counter{0};
413 const size_t asciiLength{35};
414
415 template<typename UserType>
416 std::vector<std::vector<UserType>> generateValue() {
417 return {{textBase + std::to_string(counter++)}};
418 }
419
420 template<typename UserType>
421 std::vector<std::vector<UserType>> getRemoteValue() {
422 std::vector<std::vector<UserType>> v{{""}};
423 for(size_t i = 0; i < asciiLength; ++i) {
424 size_t word = i / 4;
425 size_t byteInWord = i % 4;
426 char ch = char((acc[word] >> (byteInWord * 8U)) & 0xFF);
427 if(ch == 0) break;
428 v[0][0] += ch;
429 }
430 std::cout << "getRemoteValue: " << v[0][0] << std::endl;
431 return v;
432 }
433
435 auto v = generateValue<minimumUserType>();
436 for(size_t i = 0; i < acc.getNumberOfElements(); ++i) {
437 acc[i] = 0;
438 }
439 for(size_t i = 0; i < std::min(asciiLength, v[0][0].length()); ++i) {
440 char ch = v[0][0][i];
441 size_t word = i / 4;
442 size_t byteInWord = i % 4;
443 acc[word] = acc[word] | uint32_t(ch) << (byteInWord * 8U);
444 }
445 std::cout << "setRemoteValue: " << v[0][0] << std::endl;
446 }
447
448 static void setForceRuntimeError(bool enable, size_t) {
449 exceptionDummy->throwExceptionRead = enable;
450 exceptionDummy->throwExceptionWrite = enable;
451 exceptionDummy->throwExceptionOpen = enable;
452 }
453};
454
455/**********************************************************************************************************************/
456
458 std::string path() { return "/TEST/NODMA"; }
459 bool isWriteable() { return true; }
460 bool isReadable() { return true; }
462
463 size_t nChannels() { return 16; }
464 size_t nElementsPerChannel() { return 4; }
465 size_t writeQueueLength() { return std::numeric_limits<size_t>::max(); }
466 size_t nRuntimeErrorCases() { return 1; }
467 typedef uint16_t minimumUserType;
469
470 static constexpr auto capabilities = TestCapabilities<>()
472 .disableAsyncReadInconsistency()
473 .disableSwitchReadOnly()
474 .disableSwitchWriteOnly()
475 .disableTestWriteNeverLosesData()
476 .disableTestRawTransfer();
477
478 DummyMultiplexedRegisterAccessor<uint16_t> acc{exceptionDummyMuxed.get(), "TEST", "NODMA"};
479
480 template<typename UserType>
481 std::vector<std::vector<UserType>> generateValue() {
482 std::vector<std::vector<UserType>> v;
483 v.resize(nChannels());
484 for(size_t c = 0; c < nChannels(); ++c) {
485 for(size_t e = 0; e < nElementsPerChannel(); ++e) {
486 v[c].push_back(uint16_t(acc[c][e] + 7 * c + 3 * e));
487 }
488 }
489 return v;
490 }
491
492 template<typename UserType>
493 std::vector<std::vector<UserType>> getRemoteValue() {
494 std::vector<std::vector<UserType>> v;
495 v.resize(nChannels());
496 for(size_t c = 0; c < nChannels(); ++c) {
497 for(size_t e = 0; e < nElementsPerChannel(); ++e) {
498 v[c].push_back(acc[c][e]);
499 }
500 }
501 return v;
502 }
503
505 auto v = generateValue<minimumUserType>();
506 for(size_t c = 0; c < nChannels(); ++c) {
507 for(size_t e = 0; e < nElementsPerChannel(); ++e) {
508 acc[c][e] = v[c][e];
509 }
510 }
511 }
512
513 void setForceRuntimeError(bool enable, size_t) {
514 exceptionDummyMuxed->throwExceptionRead = enable;
515 exceptionDummyMuxed->throwExceptionWrite = enable;
516 exceptionDummyMuxed->throwExceptionOpen = enable;
517 }
518};
519
520// Read-only 1D channel slice of the 2D register TEST/NODMA. The setRemoteValue()/getRemoteValue()
521// pair exercises the strided access: values are written into the corresponding row of the full 2D
522// register (DummyMultiplexedRegisterAccessor, already pitch-aware) and read back through the slice's
523// DummyRegisterAccessor (whose getElement() must stride by the element pitch as well).
525 std::string path() { return "/TEST/NODMA.0"; }
526 bool isWriteable() { return false; }
527 bool isReadable() { return true; }
529 size_t nChannels() { return 1; }
530 size_t nElementsPerChannel() { return 4; }
531 size_t writeQueueLength() { return std::numeric_limits<size_t>::max(); }
532 size_t nRuntimeErrorCases() { return 1; }
533 typedef uint16_t minimumUserType;
534 typedef int16_t rawUserType;
535
536 static constexpr auto capabilities = TestCapabilities<>()
538 .disableAsyncReadInconsistency()
539 .disableSwitchReadOnly()
540 .disableSwitchWriteOnly()
541 .disableTestWriteNeverLosesData()
542 .enableTestRawTransfer();
543
544 static const size_t channelIndex = 0;
545 DummyRegisterAccessor<uint16_t> acc{exceptionDummyMuxed.get(), "TEST/NODMA", "0"};
546 DummyMultiplexedRegisterAccessor<uint16_t> full{exceptionDummyMuxed.get(), "TEST", "NODMA"};
547
548 template<typename UserType>
549 std::vector<std::vector<UserType>> generateValue([[maybe_unused]] bool raw = false) {
550 std::vector<std::vector<UserType>> v(1);
551 for(size_t e = 0; e < nElementsPerChannel(); ++e) {
552 v[0].push_back(uint16_t(full[channelIndex][e] + 37 + 11 * e));
553 }
554 return v;
555 }
556
557 template<typename UserType>
558 std::vector<std::vector<UserType>> getRemoteValue([[maybe_unused]] bool raw = false) {
559 std::vector<std::vector<UserType>> v(1);
560 for(size_t e = 0; e < nElementsPerChannel(); ++e) {
561 v[0].push_back(acc[e]);
562 }
563 return v;
564 }
565
567 auto v = generateValue<minimumUserType>();
568 for(size_t e = 0; e < nElementsPerChannel(); ++e) {
569 full[channelIndex][e] = v[0][e];
570 }
571 }
572
573 void setForceRuntimeError(bool enable, size_t) {
574 exceptionDummyMuxed->throwExceptionRead = enable;
575 exceptionDummyMuxed->throwExceptionWrite = enable;
576 exceptionDummyMuxed->throwExceptionOpen = enable;
577 }
578};
579
581 std::string path() { return "/TEST/NODMA.3"; }
582 bool isWriteable() { return false; }
583 bool isReadable() { return true; }
585 size_t nChannels() { return 1; }
586 size_t nElementsPerChannel() { return 4; }
587 size_t writeQueueLength() { return std::numeric_limits<size_t>::max(); }
588 size_t nRuntimeErrorCases() { return 1; }
589 typedef uint16_t minimumUserType;
590 typedef int16_t rawUserType;
591
592 static constexpr auto capabilities = TestCapabilities<>()
594 .disableAsyncReadInconsistency()
595 .disableSwitchReadOnly()
596 .disableSwitchWriteOnly()
597 .disableTestWriteNeverLosesData()
598 .enableTestRawTransfer();
599
600 // Channel "3" sits at byte offset 6 and is *not* thus 4-byte aligned, which the Dummy backdoor accessor
601 // (getElement, working on 32-bit words) requires for a strided 16-bit channel slice. Hence we do not use
602 // it in this case and instead rely solely on the muxed backdoor accessor.
603 static const size_t channelIndex = 3;
604 DummyMultiplexedRegisterAccessor<uint16_t> full{exceptionDummyMuxed.get(), "TEST", "NODMA"};
605
606 template<typename UserType>
607 std::vector<std::vector<UserType>> generateValue([[maybe_unused]] bool raw = false) {
608 std::vector<std::vector<UserType>> v(1);
609 for(size_t e = 0; e < nElementsPerChannel(); ++e) {
610 v[0].push_back(uint16_t(full[channelIndex][e] + 53 + 7 * e));
611 }
612 return v;
613 }
614
615 template<typename UserType>
616 std::vector<std::vector<UserType>> getRemoteValue([[maybe_unused]] bool raw = false) {
617 std::vector<std::vector<UserType>> v(1);
618 for(size_t e = 0; e < nElementsPerChannel(); ++e) {
619 v[0].push_back(full[channelIndex][e]);
620 }
621 return v;
622 }
623
625 auto v = generateValue<minimumUserType>();
626 for(size_t e = 0; e < nElementsPerChannel(); ++e) {
627 full[channelIndex][e] = v[0][e];
628 }
629 }
630
631 void setForceRuntimeError(bool enable, size_t) {
632 exceptionDummyMuxed->throwExceptionRead = enable;
633 exceptionDummyMuxed->throwExceptionWrite = enable;
634 exceptionDummyMuxed->throwExceptionOpen = enable;
635 }
636};
637
639 std::string path() { return "/TEST/NODMAASYNC"; }
640 bool isWriteable() { return false; }
641 bool isReadable() { return true; }
643
644 size_t nChannels() { return 16; }
645 size_t nElementsPerChannel() { return 4; }
646 size_t writeQueueLength() { return std::numeric_limits<size_t>::max(); }
647 size_t nRuntimeErrorCases() { return 1; }
648 typedef uint16_t minimumUserType;
650
651 static constexpr auto capabilities = TestCapabilities<>()
653 .disableAsyncReadInconsistency()
654 .disableSwitchReadOnly()
655 .disableSwitchWriteOnly()
656 .disableTestWriteNeverLosesData()
657 .disableTestRawTransfer();
658
659 DummyMultiplexedRegisterAccessor<uint16_t> acc{exceptionDummyMuxed.get(), "TEST", "NODMAASYNC"};
660
661 template<typename UserType>
662 std::vector<std::vector<UserType>> generateValue() {
663 std::vector<std::vector<UserType>> v;
664 v.resize(nChannels());
665 for(size_t c = 0; c < nChannels(); ++c) {
666 for(size_t e = 0; e < nElementsPerChannel(); ++e) {
667 v[c].push_back(uint16_t(acc[c][e] + 7 * c + 3 * e));
668 }
669 }
670 return v;
671 }
672
673 template<typename UserType>
674 std::vector<std::vector<UserType>> getRemoteValue() {
675 std::vector<std::vector<UserType>> v;
676 v.resize(nChannels());
677 for(size_t c = 0; c < nChannels(); ++c) {
678 for(size_t e = 0; e < nElementsPerChannel(); ++e) {
679 v[c].push_back(acc[c][e]);
680 }
681 }
682 return v;
683 }
684
686 auto v = generateValue<minimumUserType>();
687 for(size_t c = 0; c < nChannels(); ++c) {
688 for(size_t e = 0; e < nElementsPerChannel(); ++e) {
689 acc[c][e] = v[c][e];
690 }
691 }
692 if(exceptionDummyMuxed->isOpen()) exceptionDummyMuxed->triggerInterrupt(6);
693 }
694
695 void setForceRuntimeError(bool enable, size_t) {
696 exceptionDummyMuxed->throwExceptionRead = enable;
697 exceptionDummyMuxed->throwExceptionWrite = enable;
698 exceptionDummyMuxed->throwExceptionOpen = enable;
699 if(exceptionDummyMuxed->isOpen()) exceptionDummyMuxed->triggerInterrupt(6);
700 }
701};
702
704 std::string path() { return "/TEST/NODMAASYNC.0"; }
705 bool isWriteable() { return false; }
706 bool isReadable() { return true; }
710
711 size_t nChannels() { return 1; }
712 size_t nElementsPerChannel() { return 4; }
713 size_t writeQueueLength() { return std::numeric_limits<size_t>::max(); }
714 size_t nRuntimeErrorCases() { return 1; }
715 typedef uint16_t minimumUserType;
716 typedef int16_t rawUserType;
717
718 static constexpr auto capabilities = TestCapabilities<>()
720 .disableAsyncReadInconsistency()
721 .disableSwitchReadOnly()
722 .disableSwitchWriteOnly()
723 .disableTestWriteNeverLosesData()
724 .enableTestRawTransfer();
725
726 static const size_t channelIndex = 0;
727 DummyMultiplexedRegisterAccessor<uint16_t> full{exceptionDummyMuxed.get(), "TEST", "NODMAASYNC"};
728
729 template<typename UserType>
730 std::vector<std::vector<UserType>> generateValue([[maybe_unused]] bool raw = false) {
731 std::vector<std::vector<UserType>> v(1);
732 for(size_t e = 0; e < nElementsPerChannel(); ++e) {
733 v[0].push_back(uint16_t(full[channelIndex][e] + 41 + 7 * e));
734 }
735 return v;
736 }
737
738 template<typename UserType>
739 std::vector<std::vector<UserType>> getRemoteValue([[maybe_unused]] bool raw = false) {
740 std::vector<std::vector<UserType>> v(1);
741 for(size_t e = 0; e < nElementsPerChannel(); ++e) {
742 v[0].push_back(full[channelIndex][e]);
743 }
744 return v;
745 }
746
748 auto v = generateValue<minimumUserType>();
749 for(size_t e = 0; e < nElementsPerChannel(); ++e) {
750 full[channelIndex][e] = v[0][e];
751 }
752 if(exceptionDummyMuxed->isOpen()) exceptionDummyMuxed->triggerInterrupt(6);
753 }
754
755 void setForceRuntimeError(bool enable, size_t) {
756 exceptionDummyMuxed->throwExceptionRead = enable;
757 exceptionDummyMuxed->throwExceptionWrite = enable;
758 exceptionDummyMuxed->throwExceptionOpen = enable;
759 if(exceptionDummyMuxed->isOpen()) exceptionDummyMuxed->triggerInterrupt(6);
760 }
761};
762
763/**********************************************************************************************************************/
764
766 std::string path() { return "/TEST/FLOAT"; }
767 bool isWriteable() { return true; }
768 bool isReadable() { return true; }
770
771 size_t nChannels() { return 4; }
772 size_t nElementsPerChannel() { return 8; }
773 size_t nRuntimeErrorCases() { return 1; }
774 typedef float minimumUserType;
775 // typedef int32_t rawUserType;
776
777 static constexpr auto capabilities = TestCapabilities<>()
779 .disableAsyncReadInconsistency()
780 .disableSwitchReadOnly()
781 .disableSwitchWriteOnly()
782 .disableTestWriteNeverLosesData()
783 .disableTestRawTransfer();
784
785 DummyMultiplexedRegisterAccessor<float> acc{exceptionDummyMuxed.get(), "TEST", "FLOAT"};
786
787 template<typename UserType>
788 std::vector<std::vector<UserType>> generateValue() {
789 std::vector<std::vector<UserType>> v;
790 v.resize(nChannels());
791 for(uint32_t c = 0; c < nChannels(); ++c) {
792 for(uint32_t e = 0; e < nElementsPerChannel(); ++e) {
793 v[c].push_back(acc[c][e] + 0.7f * c + 3 * e);
794 }
795 }
796 return v;
797 }
798
799 template<typename UserType>
800 std::vector<std::vector<UserType>> getRemoteValue() {
801 std::vector<std::vector<UserType>> v;
802 v.resize(nChannels());
803 for(uint32_t c = 0; c < nChannels(); ++c) {
804 for(uint32_t e = 0; e < nElementsPerChannel(); ++e) {
805 v[c].push_back(acc[c][e]);
806 }
807 }
808 return v;
809 }
810
812 auto v = generateValue<minimumUserType>();
813 for(uint32_t c = 0; c < nChannels(); ++c) {
814 for(uint32_t e = 0; e < nElementsPerChannel(); ++e) {
815 acc[c][e] = v[c][e];
816 }
817 }
818 }
819
820 void setForceRuntimeError(bool enable, size_t) {
821 exceptionDummyMuxed->throwExceptionRead = enable;
822 exceptionDummyMuxed->throwExceptionWrite = enable;
823 exceptionDummyMuxed->throwExceptionOpen = enable;
824 }
825};
826
827/**********************************************************************************************************************/
828
829// Base descriptor with defaults, used for all register descriptor which use the base classes from this file
830template<typename Derived>
832 Derived* derived{static_cast<Derived*>(this)};
833
834 static constexpr auto capabilities = TestCapabilities<>()
836 .disableAsyncReadInconsistency()
837 .disableSwitchReadOnly()
838 .disableSwitchWriteOnly()
839 .disableTestWriteNeverLosesData()
840 .enableTestRawTransfer();
841
842 bool isWriteable() { return true; }
843 bool isReadable() { return true; }
844 bool isPush() { return false; }
850 size_t writeQueueLength() { return std::numeric_limits<size_t>::max(); }
851 size_t nRuntimeErrorCases() { return 1; }
852
853 void setForceRuntimeError(bool enable, size_t) {
854 auto& dummy = dynamic_cast<ExceptionDummy&>(derived->acc.getBackend());
855 dummy.throwExceptionRead = enable;
856 dummy.throwExceptionWrite = enable;
857 dummy.throwExceptionOpen = enable;
858 if(derived->isPush() && enable) {
859 dummy.triggerInterrupt(6);
860 }
861 }
862};
863
865template<typename Derived>
867 using RegisterDescriptorBase<Derived>::derived;
868
869 size_t nChannels() { return 1; }
870
871 size_t myOffset() { return 0; }
872
873 // T is always minimumUserType, but C++ doesn't allow to use Derived::minimumUserType here (circular dependency)
874 template<typename T, typename Traw>
875 T convertRawToCooked(Traw value) {
876 return static_cast<T>(value);
877 }
878
879 template<typename UserType>
880 void generateValueHook(std::vector<UserType>&) {} // override in derived if needed
881
882 // type can be user type or raw type
883 template<typename Type>
884 std::vector<std::vector<Type>> generateValue(bool getRaw = false) {
885 std::vector<Type> v;
886 typedef typename Derived::rawUserType Traw;
887 typedef typename Derived::minimumUserType T;
888 auto cv = derived->template getRemoteValue<Traw>(true)[0];
889 for(size_t i = 0; i < derived->nElementsPerChannel(); ++i) {
890 Traw e = cv[i] + derived->increment * (static_cast<Traw>(i) + 1);
891 if(!getRaw) {
892 v.push_back(derived->template convertRawToCooked<T, Traw>(e));
893 }
894 else {
895 v.push_back(static_cast<T>(e));
896 }
897 }
898 derived->generateValueHook(v);
899 return {v};
900 }
901
902 template<typename UserType>
903 std::vector<std::vector<UserType>> getRemoteValue(bool getRaw = false) {
904 typedef typename Derived::rawUserType Traw;
905
906 std::vector<UserType> cookedValues(derived->nElementsPerChannel());
907 std::vector<Traw> rawValues(derived->nElementsPerChannel());
908
909 // Keep the scope of the dummy buffer lock as limited as possible (see #12332).
910 // The rawToCooked conversion will acquire a lock via the math plugin decorator,
911 // which will cause lock order inversion if you hold the dummy buffer lock at that point.
912 {
913 auto bufferLock = derived->acc.getBufferLock();
914
915 for(size_t i = 0; i < derived->nElementsPerChannel(); ++i) {
916 rawValues[i] = derived->acc[i + derived->myOffset()];
917 }
918 } // end of bufferLock scope
919
920 for(size_t i = 0; i < derived->nElementsPerChannel(); ++i) {
921 if(!getRaw) {
922 cookedValues[i] = derived->template convertRawToCooked<UserType, Traw>(rawValues[i]);
923 }
924 else {
925 cookedValues[i] = static_cast<UserType>(rawValues[i]);
926 }
927 }
928 return {cookedValues};
929 }
930
932 auto v = generateValue<typename Derived::rawUserType>(true)[0];
933 { // scope for the buffer lock
934 auto bufferLock = derived->acc.getBufferLock();
935 for(size_t i = 0; i < derived->nElementsPerChannel(); ++i) {
936 derived->acc[i + derived->myOffset()] = v[i];
937 }
938 } // release the buffer lock before triggering another thread
939 if(derived->isPush()) {
940 dynamic_cast<ExceptionDummy&>(derived->acc.getBackend()).triggerInterrupt(6);
941 }
942 }
943};
944
946template<typename Derived>
948 size_t nElementsPerChannel() { return 1; }
949};
950
951// Base descriptor for bit accessors
952template<typename Derived>
954 using RegisterDescriptorBase<Derived>::derived;
956
957 size_t nChannels() { return 1; }
958 size_t nElementsPerChannel() { return 1; }
959
961 size_t nValuesToTest() { return 1; }
962
963 size_t nRuntimeErrorCases() { return derived->target.nRuntimeErrorCases(); }
964
965 template<typename UserType>
966 std::vector<std::vector<UserType>> generateValue([[maybe_unused]] bool getRaw = false) {
967 return derived->target.template generateValue<UserType>();
968 }
969
970 template<typename UserType>
971 std::vector<std::vector<UserType>> getRemoteValue(bool getRaw = false) {
972 if(getRaw) {
973 // For raw mode, return the full word value (raw accessor returns full parent word)
974 return derived->target.template getRemoteValue<UserType>(true);
975 }
976 // For cooked mode, extract the bit range
977 uint64_t v = derived->target.template getRemoteValue<uint64_t>()[0][0];
978 uint64_t mask = ((1ULL << derived->width) - 1) << derived->shift;
979 UserType result = (v & mask) >> derived->shift;
980 return {{result}};
981 }
982
983 void setRemoteValue() { derived->target.setRemoteValue(); }
984
986 uint64_t debugReadRawFullWord() { return static_cast<uint64_t>(static_cast<uint32_t>(derived->target.acc)); }
987
988 void setForceRuntimeError(bool enable, size_t caseIndex) { derived->target.setForceRuntimeError(enable, caseIndex); }
989};
990
991struct BitRangeAccessorTarget : ScalarRegisterDescriptorBase<BitRangeAccessorTarget> {
992 std::string path() { return "/WORD_FIRMWARE"; }
993
994 const uint32_t increment = 0x1313'2131;
995
996 using minimumUserType = uint32_t;
997 using rawUserType = uint32_t;
998 DummyRegisterAccessor<minimumUserType> acc{exceptionDummyBitRange.get(), "", "/WORD_FIRMWARE"};
999};
1000
1001struct RegLowerHalfOfFirmware : RegBitRangeDescriptor<RegLowerHalfOfFirmware> {
1002 std::string path() { return "/WORD_FIRMWARE/BitRangeLower"; }
1003
1004 using minimumUserType = int8_t;
1005 using rawUserType = uint32_t;
1006
1007 uint16_t width = 8;
1008 uint16_t shift = 8;
1009
1011};
1012
1013struct RegUpperHalfOfFirmware : RegBitRangeDescriptor<RegUpperHalfOfFirmware> {
1014 std::string path() { return "/WORD_FIRMWARE/BitRangeUpper"; }
1015
1016 using minimumUserType = int16_t;
1017 using rawUserType = uint32_t;
1018
1019 uint16_t width = 16;
1020 uint16_t shift = 16;
1021
1023};
1024
1025struct RegBitRangeMiddle : RegBitRangeDescriptor<RegBitRangeMiddle> {
1026 std::string path() { return "/WORD_FIRMWARE/BitRangeMiddle"; }
1027
1028 using minimumUserType = int8_t;
1029 using rawUserType = uint32_t;
1030
1031 uint16_t width = 8;
1032 uint16_t shift = 4;
1033
1035};
1036
1037/**********************************************************************************************************************/
1038
1040template<typename Derived>
1042 using RegisterDescriptorBase<Derived>::derived;
1044
1045 size_t nChannels() { return 1; }
1046 size_t nElementsPerChannel() { return derived->target.nElementsPerChannel(); }
1047
1049 size_t nValuesToTest() { return 1; }
1050
1051 size_t nRuntimeErrorCases() { return derived->target.nRuntimeErrorCases(); }
1052
1053 template<typename UserType>
1054 std::vector<std::vector<UserType>> generateValue([[maybe_unused]] bool getRaw = false) {
1055 return derived->target.template generateValue<UserType>();
1056 }
1057
1058 template<typename UserType>
1059 std::vector<std::vector<UserType>> getRemoteValue(bool getRaw = false) {
1060 if(getRaw) {
1061 // For raw mode, return the full word value (raw accessor returns full parent words)
1062 return derived->target.template getRemoteValue<UserType>(true);
1063 }
1064 // For cooked mode, extract the bit range from each element
1065 auto rawValues = derived->target.template getRemoteValue<uint64_t>();
1066 std::vector<UserType> result;
1067 for(size_t i = 0; i < rawValues[0].size(); ++i) {
1068 uint64_t v = rawValues[0][i];
1069 uint64_t mask = ((1ULL << derived->width) - 1) << derived->shift;
1070 result.push_back(static_cast<UserType>((v & mask) >> derived->shift));
1071 }
1072 return {result};
1073 }
1074
1075 void setRemoteValue() { derived->target.setRemoteValue(); }
1076
1077 void setForceRuntimeError(bool enable, size_t caseIndex) { derived->target.setForceRuntimeError(enable, caseIndex); }
1078};
1079
1081 std::string path() { return "/ARRAY_REG"; }
1082
1083 // The test framework iterates generateValue a few times; use a small increment to avoid overflow across 3 elements
1084 const uint32_t increment = 0x0101'0101;
1085
1086 using minimumUserType = uint32_t;
1087 using rawUserType = uint32_t;
1088
1089 size_t nElementsPerChannel() { return 3; }
1090
1091 DummyRegisterAccessor<minimumUserType> acc{exceptionDummyBitRange.get(), "", "/ARRAY_REG"};
1092};
1093
1095 std::string path() { return "/ARRAY_REG/ArrayBitRangeLow"; }
1096
1097 using minimumUserType = uint8_t;
1098 using rawUserType = int32_t;
1099
1100 uint16_t width = 8;
1101 uint16_t shift = 0;
1102
1104};
1105
1107 std::string path() { return "/ARRAY_REG/ArrayBitRangeHigh"; }
1108
1109 using minimumUserType = uint8_t;
1110 using rawUserType = int32_t;
1111
1112 uint16_t width = 8;
1113 uint16_t shift = 8;
1114
1116};
1117
1118/**********************************************************************************************************************/
1119
1120BOOST_AUTO_TEST_CASE(testRegisterAccessor) {
1121 std::cout << "*** testRegisterAccessor *** " << std::endl;
1124 .addRegister<Integers_signed32_async>()
1125 /* .addRegister<Integers_signed32_async_rw>() // disabled for now as .DUMMY_WRITABLE no longer supports
1126 wait_for_new_data */
1127 .addRegister<ShortRaw_signed16>()
1128 .addRegister<ShortRaw_unsigned16>()
1129 .addRegister<ShortRaw_fixedPoint16_8u>()
1130 .addRegister<ShortRaw_fixedPoint16_8s>()
1131 .addRegister<ByteRaw_signed8>()
1132 .addRegister<ByteRaw_unsigned8>()
1133 .addRegister<ByteRaw_fixedPoint8_4s>()
1134 .addRegister<ByteRaw_fixedPoint8_4u>()
1135 .addRegister<AsciiData>()
1136 .runTests(cdd);
1137}
1138
1139/**********************************************************************************************************************/
1140
1141BOOST_AUTO_TEST_CASE(testMultiplexedRegisterAccessor) {
1142 std::cout << "*** testMultiplexedRegisterAccessor *** " << std::endl;
1145 .addRegister<MuxedNodmaAsync>()
1146 .addRegister<MuxedFloat>()
1147 .runTests(cddMuxed);
1148}
1149
1150/**********************************************************************************************************************/
1151
1152BOOST_AUTO_TEST_CASE(testNamedChannelSlices) {
1153 std::cout << "*** testNamedChannelSlices *** " << std::endl;
1154 ChimeraTK::UnifiedBackendTest<>().addRegister<NamedChannelSlice0>().addRegister<NamedChannelSlice3>().runTests(
1155 cddMuxed);
1156}
1157
1158/**********************************************************************************************************************/
1159
1160BOOST_AUTO_TEST_CASE(testNamedChannelSliceAsync) {
1161 std::cout << "*** testNamedChannelSliceAsync *** " << std::endl;
1163}
1164
1165/**********************************************************************************************************************/
1166
1167BOOST_AUTO_TEST_CASE(testBitRanges) {
1168 std::cout << "*** testBitRanges *** " << std::endl;
1169
1172 .addRegister<RegUpperHalfOfFirmware>()
1173 .addRegister<RegBitRangeMiddle>()
1174 .addRegister<ArrayBitRangeLow>()
1175 .addRegister<ArrayBitRangeHigh>()
1176 .runTests(cddBitRange);
1177}
1178
1179/**********************************************************************************************************************/
1180
1181BOOST_AUTO_TEST_SUITE_END()
Set of AccessMode flags with additional functionality for an easier handling.
Definition AccessMode.h:48
void add(AccessMode flag)
Add the given flag to the set.
Definition AccessMode.cc:62
static BackendFactory & getInstance()
Static function to get an instance of factory.
std::atomic< bool > throwExceptionRead
Register accessor for accessing multiplexed 2D array registers internally of a DummyBackend implement...
Register accessor for accessing single word or 1D array registers internally of a DummyBackend implem...
unsigned int getNumberOfElements()
return number of elements
Accessor for raw 32 bit integer access to the underlying memory space.
Class to test any backend for correct behaviour.
UnifiedBackendTest< typename boost::mpl::push_back< VECTOR_OF_REGISTERS_T, REG_T >::type > addRegister()
Add a register to be used by the test.
@ wait_for_new_data
Make any read blocking until new data has arrived since the last read.
@ raw
Raw access: disable any possible conversion from the original hardware data type into the given UserT...
std::string to_string(const std::string &v)
Base descriptor for array bit-range accessors.
void setForceRuntimeError(bool enable, size_t caseIndex)
std::vector< std::vector< UserType > > getRemoteValue(bool getRaw=false)
std::vector< std::vector< UserType > > generateValue(bool getRaw=false)
DummyRegisterAccessor< minimumUserType > acc
std::vector< std::vector< UserType > > generateValue()
std::vector< std::vector< UserType > > getRemoteValue()
DummyRegisterAccessor< uint32_t > acc
static constexpr auto capabilities
static ChimeraTK::AccessModeFlags supportedFlags()
static void setForceRuntimeError(bool enable, size_t)
DummyRegisterAccessor< minimumUserType > acc
Descriptor for the test capabilities for each register.
constexpr TestCapabilities< _syncRead, TestCapability::disabled, _asyncReadInconsistency, _switchReadOnly, _switchWriteOnly, _writeNeverLosesData, _testWriteOnly, _testReadOnly, _testRawTransfer, _testCatalogue, _setRemoteValueIncrementsVersion, _testPartialAccessor > disableForceDataLossWrite() const
std::vector< std::vector< Type > > generateValue(bool raw=false)
std::vector< std::vector< UserType > > getRemoteValue(bool raw=false)
std::vector< std::vector< Type > > generateValue(bool raw=false)
ChimeraTK::AccessModeFlags supportedFlags()
std::vector< std::vector< UserType > > getRemoteValue(bool raw=false)
DummyRegisterAccessor< int32_t > acc
std::vector< std::vector< Type > > generateValue(bool raw=false)
void setForceRuntimeError(bool enable, size_t)
DummyRegisterAccessor< int32_t > acc
ChimeraTK::AccessModeFlags supportedFlags()
std::vector< std::vector< UserType > > getRemoteValue(bool raw=false)
static constexpr auto capabilities
void setForceRuntimeError(bool enable, size_t)
std::vector< std::vector< UserType > > generateValue()
ChimeraTK::AccessModeFlags supportedFlags()
DummyMultiplexedRegisterAccessor< float > acc
std::vector< std::vector< UserType > > getRemoteValue()
std::vector< std::vector< UserType > > getRemoteValue()
DummyMultiplexedRegisterAccessor< uint16_t > acc
ChimeraTK::AccessModeFlags supportedFlags()
void setForceRuntimeError(bool enable, size_t)
std::vector< std::vector< UserType > > generateValue()
DummyMultiplexedRegisterAccessor< uint16_t > acc
void setForceRuntimeError(bool enable, size_t)
std::vector< std::vector< UserType > > getRemoteValue()
ChimeraTK::AccessModeFlags supportedFlags()
static constexpr auto capabilities
std::vector< std::vector< UserType > > generateValue()
std::vector< std::vector< UserType > > generateValue(bool raw=false)
DummyRegisterAccessor< uint16_t > acc
ChimeraTK::AccessModeFlags supportedFlags()
DummyMultiplexedRegisterAccessor< uint16_t > full
std::vector< std::vector< UserType > > getRemoteValue(bool raw=false)
void setForceRuntimeError(bool enable, size_t)
std::vector< std::vector< UserType > > generateValue(bool raw=false)
std::vector< std::vector< UserType > > getRemoteValue(bool raw=false)
void setForceRuntimeError(bool enable, size_t)
DummyMultiplexedRegisterAccessor< uint16_t > full
ChimeraTK::AccessModeFlags supportedFlags()
DummyMultiplexedRegisterAccessor< uint16_t > full
std::vector< std::vector< UserType > > getRemoteValue(bool raw=false)
ChimeraTK::AccessModeFlags supportedFlags()
std::vector< std::vector< UserType > > generateValue(bool raw=false)
Base descriptor for 1D accessors (and scalars)
std::vector< std::vector< UserType > > getRemoteValue(bool getRaw=false)
void generateValueHook(std::vector< UserType > &)
std::vector< std::vector< Type > > generateValue(bool getRaw=false)
void setForceRuntimeError(bool enable, size_t caseIndex)
static constexpr auto capabilities
uint64_t debugReadRawFullWord()
Read the raw full word value from _barContents directly via the DummyRegisterAccessor.
std::vector< std::vector< UserType > > getRemoteValue(bool getRaw=false)
ChimeraTK::AccessModeFlags supportedFlags()
std::vector< std::vector< UserType > > generateValue(bool getRaw=false)
BitRangeAccessorTarget target
Base descriptor with defaults, used for all registers.
ChimeraTK::AccessModeFlags supportedFlags()
static constexpr auto capabilities
Base descriptor for scalars.
void setForceRuntimeError(bool enable, size_t)
ChimeraTK::AccessModeFlags supportedFlags()
std::vector< std::vector< Type > > generateValue(bool raw=false)
std::vector< std::vector< Type > > getRemoteValue(bool raw=false)
std::string cdd
auto exceptionDummy
BOOST_AUTO_TEST_CASE(testRegisterAccessor)