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
#define srand(x)
unsigned short int uint16_t
int32_t i
Timeframe settings Average distance in cm of events merged into Randomize distance around average distance of merged events Simulate correct bunch interactions instead of placing only the average number of events A value[n] sets TFlen for[n] collisions in Number of bunches per trainsort Number of bunch trains Instantaneous interaction rate Do not simulate border Total number of collisions to be placed in the interior of all time Do not select random but walk over array of events in stride steps h Event generator settings h configStandalone Use CPU for GPU Force usage of the specified GPU device no CPU fallback Continue processing after an error s
Timeframe settings Average distance in cm of events merged into Randomize distance around average distance of merged events Simulate correct bunch interactions instead of placing only the average number of events A value[n] sets TFlen for[n] collisions in Number of bunches per trainsort Number of bunch trains Instantaneous interaction rate Do not simulate border Total number of collisions to be placed in the interior of all time Do not select random but walk over array of events in stride steps h Event generator settings h configStandalone Use CPU for GPU Force usage of the specified GPU device no CPU fallback Continue processing after an error First event to Number of events to Number of iterations to Number of iterations to Number of initial iterations excluded from const char Directory with events to Events directory is and not inside events Show standalone event Run event generator maximum time bin of continuous for triggered for automatic continuous for automatic continuous triggered uint64_t
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())