ChimeraTK-DeviceAccess 03.25.00
Loading...
Searching...
No Matches
testDoubleBufferingHW.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#define BOOST_TEST_DYN_LINK
5#define BOOST_TEST_MODULE SubdeviceBackendUnifiedTest
6#include <boost/test/unit_test.hpp>
7using namespace boost::unit_test_framework;
8
9#include "Device.h"
10
11#include <boost/thread/barrier.hpp>
12
13#include <fstream>
14
15using namespace ChimeraTK;
16
17BOOST_AUTO_TEST_SUITE(DoubleBufferingBackendTestSuite)
18
19/**********************************************************************************************************************/
20
21// We need a test that is not run as unit test and which is used as long-running data consistency check
22// - perhalps call CGs python scripts as init for hw?
23// firmware provides double buffering region with continuously changing data (counter signal)
27 std::map<int16_t, unsigned> jumpHist; // for a historgram jump -> count in corrupt data
28
30 setDMapFilePath("doubleBufferHW.dmap");
31 d.open("logicalDev");
32 doubleBufferingEnabled.replace(d.getScalarRegisterAccessor<uint32_t>("enableDoubleBuffering"));
33 writingBufferNum.replace(d.getScalarRegisterAccessor<uint32_t>("currentBufferNumber"));
34 fifoStatus.replace(d.getScalarRegisterAccessor<uint32_t>("fifoStatus"));
35 }
36
37 // try several times (with random sleeps inbetween) to read signal from reg and return
38 // the number of times signal was detected as corrupted
39 unsigned checkDataCorruption(std::string reg, unsigned tries) {
40 unsigned short goodStep = 100;
41 bool writeCorruptData = true;
42 unsigned dataCorruptionCount = 0;
43 auto accessorA = d.getOneDRegisterAccessor<int16_t>(reg);
44
45 for(unsigned t = 0; t < tries; t++) {
46 accessorA.readLatest();
47 fifoStatus.readLatest();
48
49 unsigned i = 0;
50 int16_t previousVal = 0;
51 for(int16_t val : accessorA) {
52 // val is allowed to increase by goodStep or wrap-around
53 if(previousVal != 0 && val != (int16_t)(previousVal + goodStep)) {
54 std::cout << "found data corruption at index " << i << ": step from " << previousVal << " to " << val
55 << " while DAQ fifoStatus=" << fifoStatus << std::endl;
56 if(writeCorruptData) {
57 char fname[100];
58 snprintf(fname, sizeof(fname), "corruptData%03i.dat", i);
59 std::cout << "writing corrupt data to " << fname << std::endl;
60 std::ofstream f(fname);
61 for(int16_t val1 : accessorA) {
62 f << val1 << std::endl;
63 }
64 f.close();
65 }
66 dataCorruptionCount++;
67 jumpHist[(int16_t)(val - previousVal)]++;
68 }
69 previousVal = val;
70 i++;
71 }
72 // random sleep of [0..0.1] seconds
73 boost::this_thread::sleep_for(boost::chrono::milliseconds(std::rand() % 100));
74 };
75 return dataCorruptionCount;
76 }
77 void enableDoubleBuf(bool ena) {
78 doubleBufferingEnabled = ena;
79 doubleBufferingEnabled.write();
80 }
81 unsigned getActiveBufferNo() {
82 writingBufferNum.readLatest();
83 return writingBufferNum;
84 }
85 void printHist() {
86 std::cout << "histogram of wrong count-up values in data:" << std::endl;
87 for(auto p : jumpHist) {
88 std::cout << " distance=" << p.first << " : " << p.second << " times" << std::endl;
89 }
90 }
91};
92
93/**********************************************************************************************************************/
94
96 /*
97 * Here we check that we can actually detect corrupted data, if double buffer feature is off
98 * This is a prerequesite for following test to make sense.
99 * Note, we would even expect corrup data when double buffering still on, if we read to currently written
100 * buffer, only less often.
101 */
102 enableDoubleBuf(false);
103 unsigned bufferNo = getActiveBufferNo();
104 // read from the buffer which is currently written to
105 unsigned dataCorruptionCount = checkDataCorruption(bufferNo == 0 ? "channel10buf0" : "channel10buf1", 200);
106 printHist();
107 BOOST_CHECK(dataCorruptionCount > 0);
108}
109
110/**********************************************************************************************************************/
111
113 /*
114 * Here we look for data corruption when firmware uses double buffering.
115 * This test is long-running.
116 *
117 * Note, this test will probably fail even with double-buffering enabled.
118 * This happens if data loss appears due to congestion in dma controller. This must be solved on the firmware side.
119 * For discussion see https://redmine.msktools.desy.de/issues/10522
120 */
121 unsigned dataCorruptionCount = checkDataCorruption("channel10", 1000);
122 printHist();
123 BOOST_CHECK(dataCorruptionCount == 0);
124}
125
126/**********************************************************************************************************************/
127
128BOOST_AUTO_TEST_SUITE_END()
Class allows to read/write registers from device.
Definition Device.h:39
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
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
void replace(const NDRegisterAccessorAbstractor< UserType > &newAccessor)
Assign a new accessor to this NDRegisterAccessorAbstractor.
Accessor class to read and write scalar registers transparently by using the accessor object like a v...
bool readLatest()
Read the latest value, discarding any other update since the last read if present.
bool write(ChimeraTK::VersionNumber versionNumber={})
Write the data to device.
void setDMapFilePath(std::string dmapFilePath)
Set the location of the dmap file.
void enableDoubleBuf(bool ena)
ScalarRegisterAccessor< uint32_t > doubleBufferingEnabled
unsigned checkDataCorruption(std::string reg, unsigned tries)
std::map< int16_t, unsigned > jumpHist
BOOST_FIXTURE_TEST_CASE(testWithHardware0, DeviceFixture_HW)