ChimeraTK-DeviceAccess 03.25.00
Loading...
Searching...
No Matches
testNumericAddressedBackendRegisterAccessor.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 NumericAddressedBackendRegisterAccessorTest
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 "accessPrivateData.h"
12#include "BackendFactory.h"
13#include "Device.h"
14#include "DummyBackend.h"
16#include "TransferGroup.h"
17
18namespace ChimeraTK {
19 using namespace ChimeraTK;
20}
21using namespace ChimeraTK;
22
23// we need to access some private data of the low level transfer element
24// FIXME: redesign test so this is not necessary!
30
36
37// Create a test suite which holds all your tests.
38BOOST_AUTO_TEST_SUITE(NumericAddressedBackendRegisterAccessorTestSuite)
39
40/**********************************************************************************************************************/
41
42// Test the creation by using all possible options in Device
43BOOST_AUTO_TEST_CASE(testCreation) {
44 // it is always a 1D-type register (for scalar it's just 1x1)
47 device.open("DUMMYD1");
48
49 // we only check the size. That writing/reading from the offsets is ok is
50 // checked elsewere
51 // FIXME: Should it be moved here? seems really scattered around at the
52 // moment.
53
54 // the full register
55 auto accessor1 = device.getOneDRegisterAccessor<int>("MODULE1/TEST_AREA");
56 BOOST_CHECK(accessor1.getNElements() == 10);
57 // just a part
58 auto accessor2 = device.getOneDRegisterAccessor<int>("MODULE1/TEST_AREA", 5);
59 BOOST_CHECK(accessor2.getNElements() == 5);
60 // A part with offset
61 auto accessor3 = device.getOneDRegisterAccessor<int>("MODULE1/TEST_AREA", 3, 4);
62 BOOST_CHECK(accessor3.getNElements() == 3);
63
64 // some error cases:
65 // too many elements requested
66 BOOST_CHECK_THROW(std::ignore = device.getOneDRegisterAccessor<int>("MODULE1/TEST_AREA", 11), ChimeraTK::logic_error);
67 // offset exceeds range (or would result in accessor with 0 elements)
68 BOOST_CHECK_THROW(
69 std::ignore = device.getOneDRegisterAccessor<int>("MODULE1/TEST_AREA", 0, 10), ChimeraTK::logic_error);
70 BOOST_CHECK_THROW(
71 std::ignore = device.getOneDRegisterAccessor<int>("MODULE1/TEST_AREA", 0, 11), ChimeraTK::logic_error);
72 BOOST_CHECK_THROW(
73 std::ignore = device.getOneDRegisterAccessor<int>("MODULE1/TEST_AREA", 0, 2), ChimeraTK::logic_error);
74 // sum of requested elements and offset too large
75 BOOST_CHECK_THROW(
76 std::ignore = device.getOneDRegisterAccessor<int>("MODULE1/TEST_AREA", 5, 6), ChimeraTK::logic_error);
77
78 // get accessor in raw mode
79 // FIXME: This was never used, so raw mode is never tested anywhere
80 auto accessor5 = device.getOneDRegisterAccessor<int32_t>("MODULE1/TEST_AREA", 0, 0, {AccessMode::raw});
81 BOOST_CHECK(accessor5.getNElements() == 10);
82 // only int32_t works, other types fail
83 BOOST_CHECK_THROW(std::ignore = device.getOneDRegisterAccessor<double>("MODULE1/TEST_AREA", 0, 0, {AccessMode::raw}),
85}
86
87/**********************************************************************************************************************/
88
89BOOST_AUTO_TEST_CASE(testReadWrite) {
91 device.open("(dummy?map=goodMapFile.map)");
92
93 auto accessor = device.getScalarRegisterAccessor<int>("MODULE0/WORD_USER1");
94
95 // FIXME: systematically test reading and writing. Currently is scattered all
96 // over the place...
97}
98
99/**********************************************************************************************************************/
100
101BOOST_AUTO_TEST_CASE(testReadOnly) {
103 device.open("(dummy?map=goodMapFile.map)");
104
105 auto accToReadOnly = device.getScalarRegisterAccessor<int>("MODULE1/WORD_USER3");
106
107 BOOST_CHECK(accToReadOnly.isReadOnly());
108 BOOST_CHECK(!accToReadOnly.isWriteable());
109
110 BOOST_CHECK_THROW(accToReadOnly.write(), ChimeraTK::logic_error);
111}
112
113/**********************************************************************************************************************/
114
115BOOST_AUTO_TEST_CASE(testRawWrite) {
117 device.open("(dummy?map=goodMapFile.map)");
118
119 auto accessor1 = device.getOneDRegisterAccessor<int>("MODULE1/TEST_AREA", 0, 0, {AccessMode::raw});
120 for(auto& value : accessor1) {
121 value = 0xFF;
122 }
123 accessor1.write();
124
125 // another accessor for reading the same register
126 auto accessor2 = device.getOneDRegisterAccessor<int>("MODULE1/TEST_AREA", 0, 0, {AccessMode::raw});
127 accessor2.read();
128 for(auto& value : accessor2) {
129 BOOST_CHECK(value == 0xFF);
130 }
131
132 for(auto& value : accessor1) {
133 value = 0x77;
134 }
135 accessor1.write();
136 for(auto& value : accessor1) {
137 BOOST_CHECK(value == 0x77);
138 }
139
140 accessor2.read();
141 for(auto& value : accessor2) {
142 BOOST_CHECK(value == 0x77);
143 }
144
145 // do not change the content of accessor1. suspicion: it has old, swapped data
146 accessor1.write();
147 accessor2.read();
148 for(auto& value : accessor2) {
149 BOOST_CHECK(value == 0x77);
150 }
151}
152
153/**********************************************************************************************************************/
154
155BOOST_AUTO_TEST_CASE(testRawWithTransferGroup) {
157 device.open("(dummy?map=goodMapFile.map)");
158
159 // the whole register
160 auto a1 = device.getOneDRegisterAccessor<int>("MODULE1/TEST_AREA", 2, 0, {AccessMode::raw});
161 auto a2 = device.getOneDRegisterAccessor<int>("MODULE1/TEST_AREA", 2, 2, {AccessMode::raw});
162
163 // the whole register in a separate accessor which is not in the group
164 auto standalone = device.getOneDRegisterAccessor<int>("MODULE1/TEST_AREA", 0, 0, {AccessMode::raw});
165
166 // start with a single accessor so the low level transfer element is not
167 // shared
168 TransferGroup group;
169 group.addAccessor(a1);
170
171 for(auto& value : a1) {
172 value = 0x77;
173 }
174 group.write();
175
176 standalone.read();
177 BOOST_CHECK(standalone[0] == 0x77);
178 BOOST_CHECK(standalone[1] == 0x77);
179
180 // check that the swapping works as intended
181 for(auto& value : a1) {
182 value = 0xFF;
183 }
184
185 // writing twice without modifying the buffer certainly has to work
186 // In case the old values have accidentally been swapped out and not back in
187 // this is not the case, which would be a bug
188 for(int i = 0; i < 2; ++i) {
189 group.write();
190 // writing must not swap away the buffer
191 for(auto& value : a1) {
192 BOOST_CHECK(value == 0xFF);
193 }
194 standalone.read();
195 BOOST_CHECK(standalone[0] == 0xFF);
196 BOOST_CHECK(standalone[1] == 0xFF);
197 }
198
199 // test reading and mixed reading/writing
200 standalone[0] = 0xAA;
201 standalone[1] = 0xAA;
202 standalone.write();
203
204 for(int i = 0; i < 2; ++i) {
205 group.read();
206 for(auto& value : a1) {
207 BOOST_CHECK(value == 0xAA);
208 }
209 }
210
211 standalone[0] = 0xAB;
212 standalone[1] = 0xAB;
213 standalone.write();
214
215 group.read();
216 group.write();
217 for(auto& value : a1) {
218 BOOST_CHECK(value == 0xAB);
219 }
220
221 standalone.read();
222 BOOST_CHECK(standalone[0] == 0xAB);
223 BOOST_CHECK(standalone[1] == 0xAB);
224
225 // initialise the words pointed to by a2
226 for(auto& value : a2) {
227 value = 0x77;
228 }
229 a2.write();
230
231 // Now add the second accessor of the same register to the group and repeat
232 // the tests They will share the same low level transfer element.
233 group.addAccessor(a2);
234 for(auto& value : a1) {
235 value = 0xFD;
236 }
237 for(auto& value : a2) {
238 value = 0xFE;
239 }
240
241 for(int i = 0; i < 2; ++i) {
242 group.write();
243 for(auto& value : a1) {
244 BOOST_CHECK(value == 0xFD);
245 }
246 for(auto& value : a2) {
247 BOOST_CHECK(value == 0xFE);
248 }
249 standalone.read();
250 BOOST_CHECK(standalone[0] == 0xFD);
251 BOOST_CHECK(standalone[1] == 0xFD);
252 BOOST_CHECK(standalone[2] == 0xFE);
253 BOOST_CHECK(standalone[3] == 0xFE);
254 }
255
256 standalone[0] = 0xA1;
257 standalone[1] = 0xA2;
258 standalone[2] = 0xA3;
259 standalone[3] = 0xA4;
260 standalone.write();
261
262 group.read();
263 group.write();
264 BOOST_CHECK(a1[0] == 0xA1);
265 BOOST_CHECK(a1[1] == 0xA2);
266 BOOST_CHECK(a2[0] == 0xA3);
267 BOOST_CHECK(a2[1] == 0xA4);
268
269 standalone.read();
270 BOOST_CHECK(standalone[0] == 0xA1);
271 BOOST_CHECK(standalone[1] == 0xA2);
272 BOOST_CHECK(standalone[2] == 0xA3);
273 BOOST_CHECK(standalone[3] == 0xA4);
274}
275
276/**********************************************************************************************************************/
277
278BOOST_AUTO_TEST_CASE(testConverterTypes) {
279 // After the introduction of the IEEE754 floating point converter we have to test
280 // that all possible converters (two at the moment) are created when they should,
281 // and that raw and coocked accessors are working for all of them.
282
283 // As we cannot rely on any NumericAddressedRegisterAccessor at the moment we use the
284 // DummyRegisterRawAccessor to monitor what is going on in the target memory space on
285 // the device
286 auto deviceDescriptor = "(dummy?map=goodMapFile.map)";
287
288 auto dummyBackend =
289 boost::dynamic_pointer_cast<DummyBackend>(BackendFactory::getInstance().createBackend(deviceDescriptor));
290
292 device.open(deviceDescriptor);
293
294 // FixedPointConverter, raw and coocked accessors
295 // MODULE0.WORD_USER1 is fixed point, 16 bit, 3 fractional, signed
296 auto user1Dummy = dummyBackend->getRawAccessor("MODULE0", "WORD_USER1");
297 // Demonstrate the correct usage of the raw accessor, with using the lock. It would not be strictly needed here
298 // because this is single threaded, but in general it is required.
299 {
300 auto bufferLock = user1Dummy.getBufferLock();
301 user1Dummy = 0x4321;
302 }
303
304 auto user1Coocked = device.getScalarRegisterAccessor<float>("MODULE0/WORD_USER1");
305 user1Coocked.read();
306
307 BOOST_CHECK_CLOSE(float(user1Coocked), 2148.125, 0.0001);
308
309 user1Coocked = -1;
310 user1Coocked.write();
311
312 {
313 auto bufferLock = user1Dummy.getBufferLock();
314 BOOST_CHECK_EQUAL(int32_t(user1Dummy), 0xfff8);
315 }
316
317 auto user1Raw = device.getScalarRegisterAccessor<int32_t>("MODULE0/WORD_USER1", 0, {AccessMode::raw});
318 user1Raw.read();
319
320 BOOST_CHECK_EQUAL(int32_t(user1Raw), 0xfff8);
321 BOOST_CHECK_CLOSE(user1Raw.getAsCooked<float>(), -1, 0.0001);
322
323 user1Raw.setAsCooked(-2.5);
324
325 user1Raw.write();
326
327 {
328 auto bufferLock = user1Dummy.getBufferLock();
329 BOOST_CHECK_EQUAL(int32_t(user1Dummy), 0xffec);
330 }
331
332 // special case: int32 does not necessarily mean raw. There is also a cooked version:
333 auto user1CoockedInt = device.getScalarRegisterAccessor<int32_t>("MODULE0/WORD_USER1");
334 user1CoockedInt.read();
335
336 BOOST_CHECK_EQUAL(int(user1CoockedInt), -3);
337
338 user1CoockedInt = 16;
339 user1CoockedInt.write();
340
341 {
342 auto bufferLock = user1Dummy.getBufferLock();
343 BOOST_CHECK_EQUAL(int32_t(user1Dummy), 0x80);
344 }
345
346 // IEEE754 converter, raw and coocked accessors
347 // FLOAT_TEST.ARRAY is IEEE754. We use the 1 D version in constrast to FixedPoint where we use scalar (just because we
348 // can)
349 auto floatTestDummy = dummyBackend->getRawAccessor("FLOAT_TEST", "ARRAY");
350
351 float testValue = 1.1;
352 void* warningAvoider = &testValue; // directly reinterpret-casting float gives compiler warnings
353 {
354 auto bufferLock = floatTestDummy.getBufferLock();
355 floatTestDummy[0] = *(reinterpret_cast<int32_t*>(warningAvoider));
356 testValue = 2.2;
357 floatTestDummy[1] = *(reinterpret_cast<int32_t*>(warningAvoider));
358 testValue = 3.3;
359 floatTestDummy[2] = *(reinterpret_cast<int32_t*>(warningAvoider));
360 testValue = 4.4;
361 floatTestDummy[3] = *(reinterpret_cast<int32_t*>(warningAvoider));
362 } // release buffer lock
363
364 auto floatTestCoocked = device.getOneDRegisterAccessor<float>("FLOAT_TEST/ARRAY");
365 floatTestCoocked.read();
366
367 BOOST_CHECK_CLOSE(floatTestCoocked[0], 1.1, 0.0001);
368 BOOST_CHECK_CLOSE(floatTestCoocked[1], 2.2, 0.0001);
369 BOOST_CHECK_CLOSE(floatTestCoocked[2], 3.3, 0.0001);
370 BOOST_CHECK_CLOSE(floatTestCoocked[3], 4.4, 0.0001);
371
372 floatTestCoocked[3] = 44.4;
373 floatTestCoocked.write();
374
375 {
376 auto bufferLock = floatTestDummy.getBufferLock();
377 *(reinterpret_cast<int32_t*>(warningAvoider)) = floatTestDummy[3];
378 }
379 BOOST_CHECK_CLOSE(testValue, 44.4, 0.0001);
380
381 auto floatTestRaw = device.getOneDRegisterAccessor<int32_t>("FLOAT_TEST/ARRAY", 0, 0, {AccessMode::raw});
382 floatTestRaw.read();
383
384 *(reinterpret_cast<int32_t*>(warningAvoider)) = floatTestRaw[2];
385
386 BOOST_CHECK_CLOSE(testValue, 3.3, 0.0001);
387 BOOST_CHECK_CLOSE(floatTestRaw.getAsCooked<float>(0), 1.1, 0.0001);
388
389 floatTestRaw.setAsCooked(0, -2.5);
390
391 floatTestRaw.write();
392
393 {
394 auto bufferLock = floatTestDummy.getBufferLock();
395 *(reinterpret_cast<int32_t*>(warningAvoider)) = floatTestDummy[0];
396 }
397 BOOST_CHECK_CLOSE(testValue, -2.5, 0.0001);
398
399 // special case: int32 does not necessarily mean raw. There is also a cooked version:
400 auto floatTestCoockedInt = device.getOneDRegisterAccessor<int32_t>("FLOAT_TEST/ARRAY");
401 floatTestCoockedInt.read();
402
403 BOOST_CHECK_EQUAL(floatTestCoockedInt[0], -3); // was -2.5
404 BOOST_CHECK_EQUAL(floatTestCoockedInt[1], 2); // was 2.2
405 BOOST_CHECK_EQUAL(floatTestCoockedInt[2], 3); // was 3.3
406 BOOST_CHECK_EQUAL(floatTestCoockedInt[3], 44); // was 44.4
407
408 floatTestCoockedInt[1] = 16;
409 floatTestCoockedInt.write();
410
411 {
412 auto bufferLock = floatTestDummy.getBufferLock();
413 *(reinterpret_cast<int32_t*>(warningAvoider)) = floatTestDummy[1];
414 }
415 BOOST_CHECK_CLOSE(testValue, 16.0, 0.001);
416}
417
418/**********************************************************************************************************************/
419
420BOOST_AUTO_TEST_CASE(registerCatalogueCreation) {
421 Device d("(dummy?map=goodMapFile.map)");
422 auto catalogue = d.getRegisterCatalogue();
423 BOOST_CHECK_NO_THROW((void)catalogue.getRegister("MODULE0/WORD_USER1"));
424
425 BOOST_CHECK(d.isOpened() == false);
426 BOOST_CHECK_NO_THROW(d.open());
427 BOOST_CHECK(d.isOpened() == true);
428}
429
430/**********************************************************************************************************************/
431
432BOOST_AUTO_TEST_CASE(testMergeNumericRegisters) {
435
436 device.open("DUMMYD3");
437
438 // create register accessors of four registers with adjecent addresses
439 auto mux0 = device.getScalarRegisterAccessor<int>("/ADC/WORD_CLK_MUX_0");
440 auto mux1 = device.getScalarRegisterAccessor<int>("/ADC/WORD_CLK_MUX_1");
441 auto mux2 = device.getScalarRegisterAccessor<int>("/ADC/WORD_CLK_MUX_2");
442 auto mux3 = device.getScalarRegisterAccessor<int>("/ADC/WORD_CLK_MUX_3");
443
444 // create the same register accessors again, so we have a second set not part
445 // of the transfer group
446 auto mux0b = device.getScalarRegisterAccessor<int>("/ADC/WORD_CLK_MUX_0");
447 auto mux1b = device.getScalarRegisterAccessor<int>("/ADC/WORD_CLK_MUX_1");
448 auto mux2b = device.getScalarRegisterAccessor<int>("/ADC/WORD_CLK_MUX_2");
449 auto mux3b = device.getScalarRegisterAccessor<int>("/ADC/WORD_CLK_MUX_3");
450
451 // obtain the private pointers to the implementation of the accessor
452 auto mux0i = boost::dynamic_pointer_cast<NDRegisterAccessor<int>>(mux0.getHighLevelImplElement());
453 auto mux1i = boost::dynamic_pointer_cast<NDRegisterAccessor<int>>(mux1.getHighLevelImplElement());
454 auto mux2i = boost::dynamic_pointer_cast<NDRegisterAccessor<int>>(mux2.getHighLevelImplElement());
455 auto mux3i = boost::dynamic_pointer_cast<NDRegisterAccessor<int>>(mux3.getHighLevelImplElement());
456
457 // check that all underlying raw accessors are still different
458 BOOST_CHECK(mux0i->getHardwareAccessingElements()[0] != mux1i->getHardwareAccessingElements()[0]);
459 BOOST_CHECK(mux0i->getHardwareAccessingElements()[0] != mux2i->getHardwareAccessingElements()[0]);
460 BOOST_CHECK(mux0i->getHardwareAccessingElements()[0] != mux3i->getHardwareAccessingElements()[0]);
461 BOOST_CHECK(mux1i->getHardwareAccessingElements()[0] != mux2i->getHardwareAccessingElements()[0]);
462 BOOST_CHECK(mux1i->getHardwareAccessingElements()[0] != mux3i->getHardwareAccessingElements()[0]);
463 BOOST_CHECK(mux2i->getHardwareAccessingElements()[0] != mux3i->getHardwareAccessingElements()[0]);
464
465 // check that the underlying raw accessors have the right address range
466 NumericAddressedLowLevelTransferElement* llelem; // operator ->* does not work on a shared_ptr
467 llelem = boost::static_pointer_cast<NumericAddressedLowLevelTransferElement>(mux0i->getHardwareAccessingElements()[0])
468 .get();
471 llelem = boost::static_pointer_cast<NumericAddressedLowLevelTransferElement>(mux1i->getHardwareAccessingElements()[0])
472 .get();
475 llelem = boost::static_pointer_cast<NumericAddressedLowLevelTransferElement>(mux2i->getHardwareAccessingElements()[0])
476 .get();
479 llelem = boost::static_pointer_cast<NumericAddressedLowLevelTransferElement>(mux3i->getHardwareAccessingElements()[0])
480 .get();
483
484 // add accessors to the transfer group. The accessors are intentionally added
485 // out of order to check if the behaviour is also correct in that case
486 TransferGroup group;
487 group.addAccessor(mux0);
488 group.addAccessor(mux2);
489 group.addAccessor(mux1);
490 group.addAccessor(mux3);
491
492 // check that all underlying raw accessors are now all the same
493 BOOST_CHECK(mux0i->getHardwareAccessingElements()[0] == mux1i->getHardwareAccessingElements()[0]);
494 BOOST_CHECK(mux0i->getHardwareAccessingElements()[0] == mux2i->getHardwareAccessingElements()[0]);
495 BOOST_CHECK(mux0i->getHardwareAccessingElements()[0] == mux3i->getHardwareAccessingElements()[0]);
496
497 // check that the underlying raw accessor have the right address range
498 llelem = boost::static_pointer_cast<NumericAddressedLowLevelTransferElement>(mux0i->getHardwareAccessingElements()[0])
499 .get();
502
503 // check that reading and writing works
504 mux0 = 42;
505 mux1 = 120;
506 mux2 = 84;
507 mux3 = 240;
508 group.write();
509
510 mux0b.read();
511 BOOST_CHECK(mux0b == 42);
512 mux1b.read();
513 BOOST_CHECK(mux1b == 120);
514 mux2b.read();
515 BOOST_CHECK(mux2b == 84);
516 mux3b.read();
517 BOOST_CHECK(mux3b == 240);
518
519 mux0b = 123;
520 mux0b.write();
521 group.read();
522 BOOST_CHECK(mux0 == 123);
523 BOOST_CHECK(mux1 == 120);
524 BOOST_CHECK(mux2 == 84);
525 BOOST_CHECK(mux3 == 240);
526
527 mux1b = 234;
528 mux1b.write();
529 group.read();
530 BOOST_CHECK(mux0 == 123);
531 BOOST_CHECK(mux1 == 234);
532 BOOST_CHECK(mux2 == 84);
533 BOOST_CHECK(mux3 == 240);
534
535 mux2b = 345;
536 mux2b.write();
537 group.read();
538 BOOST_CHECK(mux0 == 123);
539 BOOST_CHECK(mux1 == 234);
540 BOOST_CHECK(mux2 == 345);
541 BOOST_CHECK(mux3 == 240);
542
543 mux3b = 456;
544 mux3b.write();
545 group.read();
546 BOOST_CHECK(mux0 == 123);
547 BOOST_CHECK(mux1 == 234);
548 BOOST_CHECK(mux2 == 345);
549 BOOST_CHECK(mux3 == 456);
550}
551
552/**********************************************************************************************************************/
553
554BOOST_AUTO_TEST_CASE(testMergeNumericRegistersDifferentTypes) {
557
558 device.open("DUMMYD3");
559
560 // create register accessors of four registers with adjecent addresses
561 auto mux0 = device.getScalarRegisterAccessor<uint16_t>("/ADC/WORD_CLK_MUX_0");
562 auto mux1 = device.getScalarRegisterAccessor<uint16_t>("/ADC/WORD_CLK_MUX_1");
563 auto mux2 = device.getScalarRegisterAccessor<int32_t>("/ADC/WORD_CLK_MUX_2", 0, {AccessMode::raw});
564 auto mux3 = device.getScalarRegisterAccessor<int64_t>("/ADC/WORD_CLK_MUX_3");
565
566 // create the same register accessors again, so we have a second set not part
567 // of the transfer group
568 auto mux0b = device.getScalarRegisterAccessor<uint16_t>("/ADC/WORD_CLK_MUX_0");
569 auto mux1b = device.getScalarRegisterAccessor<uint16_t>("/ADC/WORD_CLK_MUX_1");
570 auto mux2b = device.getScalarRegisterAccessor<int32_t>("/ADC/WORD_CLK_MUX_2", 0, {AccessMode::raw});
571 auto mux3b = device.getScalarRegisterAccessor<int64_t>("/ADC/WORD_CLK_MUX_3");
572
573 // obtain the private pointers to the implementation of the accessor
574 auto mux0i = boost::dynamic_pointer_cast<NDRegisterAccessor<uint16_t>>(mux0.getHighLevelImplElement());
575 auto mux1i = boost::dynamic_pointer_cast<NDRegisterAccessor<uint16_t>>(mux1.getHighLevelImplElement());
576 auto mux2i = boost::dynamic_pointer_cast<NDRegisterAccessor<int32_t>>(mux2.getHighLevelImplElement());
577 auto mux3i = boost::dynamic_pointer_cast<NDRegisterAccessor<int64_t>>(mux3.getHighLevelImplElement());
578
579 // check that all underlying raw accessors are still different
580 BOOST_CHECK(mux0i->getHardwareAccessingElements()[0] != mux1i->getHardwareAccessingElements()[0]);
581 BOOST_CHECK(mux0i->getHardwareAccessingElements()[0] != mux2i->getHardwareAccessingElements()[0]);
582 BOOST_CHECK(mux0i->getHardwareAccessingElements()[0] != mux3i->getHardwareAccessingElements()[0]);
583 BOOST_CHECK(mux1i->getHardwareAccessingElements()[0] != mux2i->getHardwareAccessingElements()[0]);
584 BOOST_CHECK(mux1i->getHardwareAccessingElements()[0] != mux3i->getHardwareAccessingElements()[0]);
585 BOOST_CHECK(mux2i->getHardwareAccessingElements()[0] != mux3i->getHardwareAccessingElements()[0]);
586
587 // add accessors to the transfer group. The accessors are intentionally added
588 // out of order to check if the behaviour is also correct in that case
589 TransferGroup group;
590 group.addAccessor(mux2);
591 group.addAccessor(mux1);
592 group.addAccessor(mux3);
593 group.addAccessor(mux0);
594
595 // check that all underlying raw accessors are now all the same
596 BOOST_CHECK(mux0i->getHardwareAccessingElements()[0] == mux1i->getHardwareAccessingElements()[0]);
597 BOOST_CHECK(mux0i->getHardwareAccessingElements()[0] == mux2i->getHardwareAccessingElements()[0]);
598 BOOST_CHECK(mux0i->getHardwareAccessingElements()[0] == mux3i->getHardwareAccessingElements()[0]);
599
600 // also check that all high-level implementations are still the same as
601 // previously
602 BOOST_CHECK(mux0i == boost::dynamic_pointer_cast<NDRegisterAccessor<uint16_t>>(mux0.getHighLevelImplElement()));
603 BOOST_CHECK(mux1i == boost::dynamic_pointer_cast<NDRegisterAccessor<uint16_t>>(mux1.getHighLevelImplElement()));
604 BOOST_CHECK(mux2i == boost::dynamic_pointer_cast<NDRegisterAccessor<int32_t>>(mux2.getHighLevelImplElement()));
605 BOOST_CHECK(mux3i == boost::dynamic_pointer_cast<NDRegisterAccessor<int64_t>>(mux3.getHighLevelImplElement()));
606
607 // check that reading and writing works
608 mux0 = 42;
609 mux1 = 120;
610 mux2 = 84;
611 mux3 = 240;
612 group.write();
613
614 mux0b.read();
615 BOOST_CHECK(mux0b == 42);
616 mux1b.read();
617 BOOST_CHECK(mux1b == 120);
618 mux2b.read();
619 BOOST_CHECK(mux2b == 84);
620 mux3b.read();
621 BOOST_CHECK(mux3b == 240);
622
623 mux0b = 123;
624 mux0b.write();
625 group.read();
626 BOOST_CHECK(mux0 == 123);
627 BOOST_CHECK(mux1 == 120);
628 BOOST_CHECK(mux2 == 84);
629 BOOST_CHECK(mux3 == 240);
630
631 mux1b = 234;
632 mux1b.write();
633 group.read();
634 BOOST_CHECK(mux0 == 123);
635 BOOST_CHECK(mux1 == 234);
636 BOOST_CHECK(mux2 == 84);
637 BOOST_CHECK(mux3 == 240);
638
639 mux2b = 345;
640 mux2b.write();
641 group.read();
642 BOOST_CHECK(mux0 == 123);
643 BOOST_CHECK(mux1 == 234);
644 BOOST_CHECK(mux2 == 345);
645 BOOST_CHECK(mux3 == 240);
646
647 mux3b = 456;
648 mux3b.write();
649 group.read();
650 BOOST_CHECK(mux0 == 123);
651 BOOST_CHECK(mux1 == 234);
652 BOOST_CHECK(mux2 == 345);
653 BOOST_CHECK(mux3 == 456);
654}
655
656/**********************************************************************************************************************/
657
658BOOST_AUTO_TEST_SUITE_END()
static BackendFactory & getInstance()
Static function to get an instance of factory.
void setDMapFilePath(std::string dMapFilePath)
This function sets the _DMapFilePath.
Class allows to read/write registers from device.
Definition Device.h:39
bool isOpened() const
Check if the device is currently opened.
Definition Device.cc:73
ScalarRegisterAccessor< UserType > getScalarRegisterAccessor(const RegisterPath &registerPathName, size_t wordOffsetInRegister=0, const AccessModeFlags &flags=AccessModeFlags({})) const
Get a ScalarRegisterObject object for the given register.
Definition Device.h:266
RegisterCatalogue getRegisterCatalogue() const
Return the register catalogue with detailed information on all registers.
Definition Device.cc:22
OneDRegisterAccessor< UserType > getOneDRegisterAccessor(const RegisterPath &registerPathName, size_t numberOfWords=0, size_t wordOffsetInRegister=0, const AccessModeFlags &flags=AccessModeFlags({})) const
Get a OneDRegisterAccessor object for the given register.
Definition Device.h:276
void open(std::string const &aliasName)
Open a device by the given alias name from the DMAP file.
Definition Device.cc:58
N-dimensional register accessor.
Implementation of the NDRegisterAccessor for NumericAddressedBackends, responsible for the underlying...
Group multiple data accessors to efficiently trigger data transfers on the whole group.
void addAccessor(TransferElementAbstractor &accessor)
Add a register accessor to the group.
void write(VersionNumber versionNumber={})
Trigger write transfer for all accessors in the group.
void read()
Trigger read transfer for all accessors in the group.
Exception thrown when a logic error has occured.
Definition Exception.h:51
ctk::Device device