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(myarr[i_r][i_c],
74 : (dunedaq::fddetdataformats::get_adc_2d<wordtype_t, nrows, ncols, bits_per_word>(
75 : i_r, i_c, myarr))); // NOLINT(cppcoreguidelines-pro-bounds-constant-array-index)
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(inputarr[i_r][i_c],
93 : (dunedaq::fddetdataformats::get_adc_2d<wordtype_t, nrows, ncols, bits_per_word>(
94 : i_r, i_c, myarr))); // NOLINT(cppcoreguidelines-pro-bounds-constant-array-index)
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 1 : constexpr wordtype_t inputarr2[nsamples][nchannels] = { // NOLINT(modernize-avoid-c-arrays)
108 : { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
109 : { 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48 }
110 : };
111 :
112 3 : for (int i_smp = 0; i_smp < nsamples; ++i_smp) {
113 34 : for (int i_ch = 0; i_ch < nchannels; ++i_ch) {
114 32 : dunedaq::fddetdataformats::set_adc_2d<wordtype_t, nrows, ncols, bits_per_adc>(
115 32 : i_smp, i_ch, inputarr2[i_smp][i_ch], myarr); // NOLINT(cppcoreguidelines-pro-bounds-constant-array-index)
116 : }
117 : }
118 :
119 3 : for (int i_smp = 0; i_smp < nsamples; ++i_smp) {
120 34 : for (int i_ch = 0; i_ch < nchannels; ++i_ch) {
121 32 : BOOST_REQUIRE_EQUAL(
122 : inputarr2[i_smp][i_ch], // NOLINT(cppcoreguidelines-pro-bounds-constant-array-index)
123 : (dunedaq::fddetdataformats::get_adc_2d<wordtype_t, nrows, ncols, bits_per_adc>(i_smp, i_ch, myarr)));
124 : }
125 : }
126 :
127 : // Note that in the range checks below, 0 is an obviously good index and -1 is an obviously bad index
128 :
129 : constexpr int bad_channel_index = ncols * bits_per_word / bits_per_adc;
130 : constexpr wordtype_t good_adc_val = 1;
131 : constexpr wordtype_t bad_adc_val = static_cast<wordtype_t>(1) << bits_per_adc;
132 :
133 1 : BOOST_CHECK_THROW((dunedaq::fddetdataformats::get_adc_2d<wordtype_t, nrows, ncols, bits_per_adc>(-1, 0, myarr)),
134 : std::out_of_range);
135 1 : BOOST_CHECK_THROW((dunedaq::fddetdataformats::get_adc_2d<wordtype_t, nrows, ncols, bits_per_adc>(nrows, 0, myarr)),
136 : std::out_of_range);
137 1 : BOOST_CHECK_THROW((dunedaq::fddetdataformats::get_adc_2d<wordtype_t, nrows, ncols, bits_per_adc>(0, -1, myarr)),
138 : std::out_of_range);
139 1 : BOOST_CHECK_THROW(
140 : (dunedaq::fddetdataformats::get_adc_2d<wordtype_t, nrows, ncols, bits_per_adc>(0, bad_channel_index, myarr)),
141 : std::out_of_range);
142 :
143 1 : BOOST_CHECK_THROW(
144 : (dunedaq::fddetdataformats::set_adc_2d<wordtype_t, nrows, ncols, bits_per_adc>(-1, 0, good_adc_val, myarr)),
145 : std::out_of_range);
146 1 : BOOST_CHECK_THROW(
147 : (dunedaq::fddetdataformats::set_adc_2d<wordtype_t, nrows, ncols, bits_per_adc>(nrows, 0, good_adc_val, myarr)),
148 : std::out_of_range);
149 1 : BOOST_CHECK_THROW(
150 : (dunedaq::fddetdataformats::set_adc_2d<wordtype_t, nrows, ncols, bits_per_adc>(0, -1, good_adc_val, myarr)),
151 : std::out_of_range);
152 1 : BOOST_CHECK_THROW((dunedaq::fddetdataformats::set_adc_2d<wordtype_t, nrows, ncols, bits_per_adc>(
153 : 0, bad_channel_index, good_adc_val, myarr)),
154 : std::out_of_range);
155 :
156 1 : BOOST_CHECK_THROW(
157 : (dunedaq::fddetdataformats::set_adc_2d<wordtype_t, nrows, ncols, bits_per_adc>(0, 0, bad_adc_val, myarr)),
158 : std::out_of_range);
159 1 : }
160 :
161 : BOOST_AUTO_TEST_SUITE_END()
162 :
163 : // NOLINTEND(build/unsigned)
|