Project
Loading...
Searching...
No Matches
testPayloadEncoder.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
19#define BOOST_TEST_MODULE Test MCHRaw Encoder
20#define BOOST_TEST_MAIN
21#define BOOST_TEST_DYN_LINK
22
23#include <boost/test/unit_test.hpp>
24#include "BareElinkEncoder.h"
26#include "EncoderImplHelper.h"
27#include "GBTEncoder.h"
33#include <boost/mpl/list.hpp>
34#include <cstdint>
35#include <fmt/printf.h>
36#include <vector>
37
38using namespace o2::mch::raw;
39
40template <typename ELECMAP, typename FORMAT, int VERSION = 0>
41std::vector<std::byte> makeBuffer(int norbit = 1,
42 uint32_t firstOrbit = 12345,
43 uint16_t firstBC = 678,
44 bool withHB = false)
45{
46 const DsElecId ds1{728, 1, 0};
47 const DsElecId ds2{361, 0, 4};
48 const DsElecId ds3{448, 6, 2};
49 const DsElecId ds4{728, 1, 2};
50
51 std::set<DsElecId> dsElecIds;
52 if (withHB) {
53 dsElecIds.insert(ds1);
54 dsElecIds.insert(ds2);
55 dsElecIds.insert(ds3);
56 if (norbit > 1) {
57 dsElecIds.insert(ds4);
58 }
59 }
60 auto encoder = createPayloadEncoder(createSolar2FeeLinkMapper<ELECMAP>(),
62 VERSION,
64
65 uint16_t sampaTime{24};
66 uint32_t bunchCrossing = 567;
67 uint16_t bc(firstBC);
68
69 encoder->startHeartbeatFrame(firstOrbit, bc);
70 if (withHB) {
71 encoder->addHeartbeatHeaders(dsElecIds);
72 }
73
74 encoder->addChannelData(ds1, 3, {SampaCluster(sampaTime, bunchCrossing, 13, 14)});
75 encoder->addChannelData(ds1, 13, {SampaCluster(sampaTime, bunchCrossing, 133, 134)});
76 encoder->addChannelData(ds1, 23, {SampaCluster(sampaTime, bunchCrossing, 163, 164)});
77
78 encoder->addChannelData(ds2, 0, {SampaCluster(sampaTime, bunchCrossing, 10, 11)});
79 encoder->addChannelData(ds2, 1, {SampaCluster(sampaTime, bunchCrossing, 20, 21)});
80 encoder->addChannelData(ds2, 2, {SampaCluster(sampaTime, bunchCrossing, 30, 31)});
81 encoder->addChannelData(ds2, 3, {SampaCluster(sampaTime, bunchCrossing, 40, 41)});
82
83 encoder->addChannelData(ds3, 22, {SampaCluster(sampaTime, bunchCrossing, 420, 421)});
84 encoder->addChannelData(ds3, 23, {SampaCluster(sampaTime, bunchCrossing, 430, 431)});
85 encoder->addChannelData(ds3, 24, {SampaCluster(sampaTime, bunchCrossing, 440, 441)});
86 encoder->addChannelData(ds3, 25, {SampaCluster(sampaTime, bunchCrossing, 450, 451)});
87 encoder->addChannelData(ds3, 26, {SampaCluster(sampaTime, bunchCrossing, 460, 461)});
88 encoder->addChannelData(ds3, 42, {SampaCluster(sampaTime, bunchCrossing, 420, 421)});
89
90 if (norbit > 1) {
91 encoder->startHeartbeatFrame(firstOrbit + 1, bc);
92 encoder->addChannelData(ds4, 0, {SampaCluster(sampaTime, bunchCrossing, 10, 11)});
93 encoder->addChannelData(ds4, 1, {SampaCluster(sampaTime, bunchCrossing, 10, 11)});
94 encoder->addChannelData(ds2, 0, {SampaCluster(sampaTime, bunchCrossing, 10, 11)});
95 encoder->addChannelData(ds2, 1, {SampaCluster(sampaTime, bunchCrossing, 20, 21)});
96 encoder->addChannelData(ds2, 2, {SampaCluster(sampaTime, bunchCrossing, 30, 31)});
97 encoder->addChannelData(ds2, 3, {SampaCluster(sampaTime, bunchCrossing, 40, 41)});
98 }
99
100 if (norbit > 2) {
101 encoder->startHeartbeatFrame(firstOrbit + 2, bc);
102 encoder->addChannelData(ds3, 12, {SampaCluster(sampaTime, bunchCrossing, 420, 421)});
103 }
104
105 std::vector<std::byte> buffer;
106 encoder->moveToBuffer(buffer);
107
108 return buffer;
109}
110
111template <typename ELECMAP, typename FORMAT>
112std::unique_ptr<PayloadEncoder> defaultEncoder()
113{
114 return createPayloadEncoder(createSolar2FeeLinkMapper<ELECMAP>(),
116 0,
117 isChargeSumMode<SampleMode>::value /* i.e. use sample mode */);
118}
119
120struct BareGen {
123 static constexpr int version = 0;
124};
125
129 static constexpr int version = 0;
130};
131
135 static constexpr int version = 1;
136};
137
138struct BareDummy {
141 static constexpr int version = 0;
142};
143
147 static constexpr int version = 0;
148};
149
153 static constexpr int version = 1;
154};
155
156typedef boost::mpl::list<BareGen, UserLogicGen, UserLogicGen1, BareDummy, UserLogicDummy, UserLogicDummy1> testTypes;
157
158BOOST_AUTO_TEST_SUITE(o2_mch_raw)
159
160BOOST_AUTO_TEST_SUITE(encoder)
161
162BOOST_AUTO_TEST_CASE_TEMPLATE(StartHBFrameBunchCrossingMustBe12Bits, T, testTypes)
163{
164 auto encoder = defaultEncoder<typename T::elecmap, typename T::format>();
165 BOOST_CHECK_THROW(encoder->startHeartbeatFrame(0, 1 << 12), std::invalid_argument);
166 BOOST_CHECK_NO_THROW(encoder->startHeartbeatFrame(0, 0xFFF));
167}
168
169BOOST_AUTO_TEST_CASE_TEMPLATE(EmptyEncoderHasEmptyBufferIfPhaseIsZero, T, testTypes)
170{
171 srand(time(nullptr));
172 auto encoder = defaultEncoder<typename T::elecmap, typename T::format>();
173 encoder->startHeartbeatFrame(12345, 123);
174 std::vector<std::byte> buffer;
175 encoder->moveToBuffer(buffer);
176 BOOST_CHECK_EQUAL(buffer.size(), 0);
177}
178
179BOOST_AUTO_TEST_CASE_TEMPLATE(MultipleOrbitsWithNoDataIsAnEmptyBufferIfPhaseIsZero, T, testTypes)
180{
181 srand(time(nullptr));
182 auto encoder = defaultEncoder<typename T::elecmap, typename T::format>();
183 encoder->startHeartbeatFrame(12345, 123);
184 encoder->startHeartbeatFrame(12345, 125);
185 encoder->startHeartbeatFrame(12345, 312);
186 std::vector<std::byte> buffer;
187 encoder->moveToBuffer(buffer);
188 BOOST_CHECK_EQUAL(buffer.size(), 0);
189}
190
191int estimateUserLogicSize(int nofDS, int maxNofChPerDS)
192{
193 // counting first in number of 10 bits
194
195 size_t sync = 5;
196 size_t sampaHeaders = nofDS * maxNofChPerDS * 5;
197 size_t sampaData = nofDS * maxNofChPerDS * 4;
198
199 size_t n10 = sync + sampaHeaders + sampaData;
200 while (n10 % 5) {
201 n10++;
202 }
203
204 return (n10 / 5) * (64 / 8) + sizeof(DataBlockHeader);
205}
206
207int estimateBareSize(int nofDS, int maxNofChPerGBT)
208{
209 size_t headerSize = 2; // equivalent to 2 64-bits words
210 size_t nbits = nofDS * 50 + maxNofChPerGBT * 90;
211 size_t n128bitwords = nbits / 2;
212 size_t n64bitwords = n128bitwords * 2;
213 return 8 * (n64bitwords + headerSize); // size in bytes
214}
215
216template <typename FORMAT>
217int estimateSize(bool withHB = false);
218
219template <>
221{
222 int size = estimateBareSize(1, 3) +
223 estimateBareSize(1, 4) +
224 estimateBareSize(1, 6);
225 if (withHB) {
226 size += 3 * 50 * 8;
227 }
228 return size; // in bytes
229}
230
231template <>
233{
234 int size = estimateUserLogicSize(1, 3) +
237 2 * 8; // 8 bytes per FEE (to ensure the payload size is a multiple of 128 bits = 1 GBT word)
238 if (withHB) {
239 size += 6 * 8;
240 }
241 return size; // in bytes
242}
243
244BOOST_AUTO_TEST_CASE_TEMPLATE(CheckNumberOfPayloadHeaders, T, testTypes)
245{
246 auto buffer = makeBuffer<typename T::elecmap, typename T::format, T::version>();
247 int nheaders = o2::mch::raw::countHeaders(buffer);
248 BOOST_CHECK_EQUAL(nheaders, 3);
249}
250
252{
253 auto buffer = makeBuffer<typename T::elecmap, typename T::format, T::version>();
254 size_t expectedSize = estimateSize<typename T::format>();
256}
257
259{
260 auto buffer = makeBuffer<typename T::elecmap, typename T::format, T::version>(1, 12345, 678, true);
261 size_t expectedSize = estimateSize<typename T::format>(true);
263}
264
265std::string asBinary(uint64_t value)
266{
267 std::string s;
268 uint64_t one = 1;
269 int space{0};
270 for (auto i = 63; i >= 0; i--) {
271 if (value & (one << i)) {
272 s += "1";
273 } else {
274 s += "0";
275 }
276 if (i % 4 == 0 && i) {
277 s += " ";
278 }
279 }
280 return s;
281}
282
283std::string binaryRule(bool top, std::vector<int> stops)
284{
285 std::string s;
286 for (auto i = 63; i >= 0; i--) {
287 if (std::find(stops.begin(), stops.end(), i) != stops.end()) {
288 s += fmt::format("{}", (top ? i / 10 : i % 10));
289 } else {
290 s += " ";
291 }
292 if (i % 4 == 0) {
293 s += " ";
294 }
295 }
296 return s;
297}
298
299void dump(uint64_t value, std::vector<int> stops = {63, 47, 31, 15, 0})
300{
301 std::cout << asBinary(value) << "\n";
302 std::cout << binaryRule(true, stops) << "\n";
303 std::cout << binaryRule(false, stops) << "\n";
304}
305
307{
308 std::vector<uint10_t> b10;
309 impl::append(b10, sampaSyncWord);
310 std::vector<uint64_t> b64;
311 impl::b10to64(b10, b64, 24);
312 auto w = b64[0];
313 BOOST_CHECK_EQUAL(asBinary(w), "0000 0000 0110 0001 0101 0101 0101 0101 0100 0000 1111 0000 0000 0001 0001 0011");
314}
315
317{
318 dump(static_cast<uint64_t>(7) << 50, {50, 51, 52, 0});
319}
320
321BOOST_AUTO_TEST_SUITE_END()
322BOOST_AUTO_TEST_SUITE_END()
uint64_t bc
Definition RawEventData.h:5
int16_t time
Definition RawEventData.h:4
int32_t i
uint32_t one
Definition RawData.h:4
GLuint buffer
Definition glcorearb.h:655
GLsizeiptr size
Definition glcorearb.h:659
GLdouble GLdouble GLdouble GLdouble top
Definition glcorearb.h:4077
GLsizei const GLfloat * value
Definition glcorearb.h:819
GLubyte GLubyte GLubyte GLubyte w
Definition glcorearb.h:852
int countHeaders(gsl::span< const std::byte > buffer)
Count the headers in the input buffer.
Definition DataBlock.cxx:42
constexpr uint64_t sampaSyncWord
std::unique_ptr< PayloadEncoder > createPayloadEncoder(Solar2FeeLinkMapper solar2feelink, bool userLogic, int version, bool chargeSumMode)
BOOST_AUTO_TEST_CASE(FlatHisto)
static constexpr int version
static constexpr int version
static constexpr int version
static constexpr int version
static constexpr int version
static constexpr int version
A lightweight struct to describe a MCH Raw Data Block.
Definition DataBlock.h:26
Piece of data for one Sampa channel.
boost::mpl::list< o2::dcs::DataPointIdentifier, o2::dcs::DataPointValue, o2::dcs::DataPointCompositeObject > testTypes
float expectedSize()
int estimateBareSize(int nofDS, int maxNofChPerGBT)
void dump(uint64_t value, std::vector< int > stops={63, 47, 31, 15, 0})
int estimateUserLogicSize(int nofDS, int maxNofChPerDS)
std::unique_ptr< PayloadEncoder > defaultEncoder()
boost::mpl::list< BareGen, UserLogicGen, UserLogicGen1, BareDummy, UserLogicDummy, UserLogicDummy1 > testTypes
std::string asBinary(uint64_t value)
std::string binaryRule(bool top, std::vector< int > stops)
int estimateSize< BareFormat >(bool withHB)
int estimateSize(bool withHB=false)
int estimateSize< UserLogicFormat >(bool withHB)
std::vector< std::byte > makeBuffer(int norbit=1, uint32_t firstOrbit=12345, uint16_t firstBC=678, bool withHB=false)
BOOST_AUTO_TEST_CASE_TEMPLATE(StartHBFrameBunchCrossingMustBe12Bits, T, testTypes)
BOOST_CHECK_NO_THROW(algorithm::merge(target, other))
BOOST_CHECK_EQUAL(triggersD.size(), triggers.size())