Line data Source code
1 : /**
2 : * @file Utils_fddetdataformats_test.cxx Utils Unit Tests
3 : *
4 : * This is part of the DUNE DAQ Application Framework, copyright 2022.
5 : * Licensing/copyright details are in the COPYING file that you should have
6 : * received with this code.
7 : */
8 :
9 : #include "fddetdataformats/Utils.hpp"
10 :
11 : #define BOOST_TEST_MODULE Utils_fddetdataformats_test // NOLINT
12 :
13 : #include "boost/test/unit_test.hpp"
14 :
15 : #include <iostream>
16 : #include <limits>
17 :
18 : // NOLINTBEGIN(build/unsigned)
19 :
20 : BOOST_AUTO_TEST_SUITE(Utils_fddetdataformats_test)
21 :
22 2 : BOOST_AUTO_TEST_CASE(Utils_fddetdataformats_ADCOperation_LowLevelChecks)
23 : {
24 : // Start with something really low level
25 :
26 1 : constexpr int tiny_adc_width = 3;
27 :
28 : // Three bytes chosen since adc_width needs to evenly divide into the total bits of the array
29 1 : constexpr int nbytes = 3;
30 1 : uint8_t tiny_adc_arr[nbytes] = { 0, 0, 0 }; // NOLINT(modernize-avoid-c-arrays)
31 :
32 : // the third (index 2) _logical_ 3-bit ADC entry of 7 (111 in binary) means
33 : // the last two bits of the first byte and the first bit of the
34 : // second byte should be flipped on:
35 :
36 : // 00000011 10000000 00000000
37 :
38 1 : dunedaq::fddetdataformats::set_adc_1d<uint8_t, nbytes, tiny_adc_width>(2, 7, tiny_adc_arr);
39 1 : BOOST_REQUIRE_EQUAL(tiny_adc_arr[0], 192);
40 1 : BOOST_REQUIRE_EQUAL(tiny_adc_arr[1], 1);
41 1 : BOOST_REQUIRE_EQUAL(tiny_adc_arr[2], 0);
42 :
43 1 : BOOST_REQUIRE_EQUAL(7, (dunedaq::fddetdataformats::get_adc_1d<uint8_t, nbytes, tiny_adc_width>(2, tiny_adc_arr)));
44 :
45 1 : tiny_adc_arr[0] = tiny_adc_arr[1] = tiny_adc_arr[2] = 0;
46 :
47 1 : constexpr int adcs_per_channel = 4;
48 1 : constexpr int nchannels = 2;
49 1 : dunedaq::fddetdataformats::set_adc_2d_as_1d<uint8_t, nbytes, tiny_adc_width, adcs_per_channel, nchannels>(
50 : 1, 0, 7, tiny_adc_arr);
51 1 : BOOST_REQUIRE_EQUAL(tiny_adc_arr[0], 192);
52 1 : BOOST_REQUIRE_EQUAL(tiny_adc_arr[1], 1);
53 1 : BOOST_REQUIRE_EQUAL(tiny_adc_arr[2], 0);
54 1 : BOOST_REQUIRE_EQUAL(
55 : 7,
56 : (dunedaq::fddetdataformats::get_adc_2d_as_1d<uint8_t, nbytes, tiny_adc_width, adcs_per_channel, nchannels>(
57 : 1, 0, tiny_adc_arr)));
58 1 : }
59 :
60 2 : BOOST_AUTO_TEST_CASE(Utils_fddetdataformats_ADCOperation_BasicChecks)
61 : {
62 :
63 1 : using wordtype_t = uint32_t;
64 1 : constexpr int bits_per_word = std::numeric_limits<wordtype_t>::digits;
65 :
66 1 : constexpr int nrows = 2;
67 1 : constexpr int ncols = 3;
68 1 : wordtype_t myarr[nrows][ncols] = { { 1, 2, 3 }, { 1001, 1002, 1003 } }; // NOLINT(modernize-avoid-c-arrays)
69 :
70 : // First, test get_adc_2d if the ADC representation aligns with the C++ type
71 3 : for (int i_r = 0; i_r < nrows; ++i_r) {
72 8 : for (int i_c = 0; i_c < ncols; ++i_c) {
73 6 : BOOST_REQUIRE_EQUAL(
74 : myarr[i_r][i_c], // NOLINT(cppcoreguidelines-pro-bounds-constant-array-index)
75 : (dunedaq::fddetdataformats::get_adc_2d<wordtype_t, nrows, ncols, bits_per_word>(i_r, i_c, myarr)));
76 : }
77 : }
78 :
79 : // Next, test set_adc_1d if the ADC representation aligns with the C++ type
80 :
81 1 : constexpr wordtype_t inputarr[nrows][ncols] = { { 1234, 5678, 9101 }, // NOLINT(modernize-avoid-c-arrays)
82 : { 1121, 3141, 5161 } };
83 3 : for (int i_r = 0; i_r < nrows; ++i_r) {
84 8 : for (int i_c = 0; i_c < ncols; ++i_c) {
85 6 : dunedaq::fddetdataformats::set_adc_2d<wordtype_t, nrows, ncols, bits_per_word>(
86 6 : i_r, i_c, inputarr[i_r][i_c], myarr); // NOLINT(cppcoreguidelines-pro-bounds-constant-array-index)
87 : }
88 : }
89 :
90 3 : for (int i_r = 0; i_r < nrows; ++i_r) {
91 8 : for (int i_c = 0; i_c < ncols; ++i_c) {
92 6 : BOOST_REQUIRE_EQUAL(
93 : inputarr[i_r][i_c], // NOLINT(cppcoreguidelines-pro-bounds-constant-array-index)
94 : (dunedaq::fddetdataformats::get_adc_2d<wordtype_t, nrows, ncols, bits_per_word>(i_r, i_c, myarr)));
95 : }
96 : }
97 :
98 : // Now let's see what happens when ADC representation doesn't align with the C++ type
99 :
100 1 : constexpr int bits_per_adc = 6;
101 1 : static_assert(bits_per_word % bits_per_adc != 0);
102 1 : static_assert((bits_per_word * ncols) % bits_per_adc == 0);
103 :
104 1 : constexpr int nsamples = nrows;
105 1 : constexpr int nchannels = bits_per_word * ncols / bits_per_adc;
106 :
107 : // NOLINTNEXTLINE(modernize-avoid-c-arrays)
108 1 : constexpr wordtype_t inputarr2[nsamples][nchannels] = {
109 : { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
110 : { 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48 }
111 : };
112 :
113 3 : for (int i_smp = 0; i_smp < nsamples; ++i_smp) {
114 34 : for (int i_ch = 0; i_ch < nchannels; ++i_ch) {
115 32 : dunedaq::fddetdataformats::set_adc_2d<wordtype_t, nrows, ncols, bits_per_adc>(
116 32 : i_smp, i_ch, inputarr2[i_smp][i_ch], myarr); // NOLINT(cppcoreguidelines-pro-bounds-constant-array-index)
117 : }
118 : }
119 :
120 3 : for (int i_smp = 0; i_smp < nsamples; ++i_smp) {
121 34 : for (int i_ch = 0; i_ch < nchannels; ++i_ch) {
122 32 : BOOST_REQUIRE_EQUAL(
123 : inputarr2[i_smp][i_ch], // NOLINT(cppcoreguidelines-pro-bounds-constant-array-index)
124 : (dunedaq::fddetdataformats::get_adc_2d<wordtype_t, nrows, ncols, bits_per_adc>(i_smp, i_ch, myarr)));
125 : }
126 : }
127 :
128 : // Note that in the range checks below, 0 is an obviously good index and -1 is an obviously bad index
129 :
130 : constexpr int bad_channel_index = ncols * bits_per_word / bits_per_adc;
131 : constexpr wordtype_t good_adc_val = 1;
132 : constexpr wordtype_t bad_adc_val = static_cast<wordtype_t>(1) << bits_per_adc;
133 :
134 1 : BOOST_CHECK_THROW((dunedaq::fddetdataformats::get_adc_2d<wordtype_t, nrows, ncols, bits_per_adc>(-1, 0, myarr)),
135 : std::out_of_range);
136 1 : BOOST_CHECK_THROW((dunedaq::fddetdataformats::get_adc_2d<wordtype_t, nrows, ncols, bits_per_adc>(nrows, 0, myarr)),
137 : std::out_of_range);
138 1 : BOOST_CHECK_THROW((dunedaq::fddetdataformats::get_adc_2d<wordtype_t, nrows, ncols, bits_per_adc>(0, -1, myarr)),
139 : std::out_of_range);
140 1 : BOOST_CHECK_THROW(
141 : (dunedaq::fddetdataformats::get_adc_2d<wordtype_t, nrows, ncols, bits_per_adc>(0, bad_channel_index, myarr)),
142 : std::out_of_range);
143 :
144 1 : BOOST_CHECK_THROW(
145 : (dunedaq::fddetdataformats::set_adc_2d<wordtype_t, nrows, ncols, bits_per_adc>(-1, 0, good_adc_val, myarr)),
146 : std::out_of_range);
147 1 : BOOST_CHECK_THROW(
148 : (dunedaq::fddetdataformats::set_adc_2d<wordtype_t, nrows, ncols, bits_per_adc>(nrows, 0, good_adc_val, myarr)),
149 : std::out_of_range);
150 1 : BOOST_CHECK_THROW(
151 : (dunedaq::fddetdataformats::set_adc_2d<wordtype_t, nrows, ncols, bits_per_adc>(0, -1, good_adc_val, myarr)),
152 : std::out_of_range);
153 1 : BOOST_CHECK_THROW((dunedaq::fddetdataformats::set_adc_2d<wordtype_t, nrows, ncols, bits_per_adc>(
154 : 0, bad_channel_index, good_adc_val, myarr)),
155 : std::out_of_range);
156 :
157 1 : BOOST_CHECK_THROW(
158 : (dunedaq::fddetdataformats::set_adc_2d<wordtype_t, nrows, ncols, bits_per_adc>(0, 0, bad_adc_val, myarr)),
159 : std::out_of_range);
160 1 : }
161 :
162 : BOOST_AUTO_TEST_SUITE_END()
163 :
164 : // NOLINTEND(build/unsigned)
|