15#define BOOST_TEST_MODULE Test MCHRaw UserLogicElinkDecoder
16#define BOOST_TEST_MAIN
17#define BOOST_TEST_DYN_LINK
19#include <boost/test/unit_test.hpp>
32#include <fmt/printf.h>
35#include <boost/test/data/test_case.hpp>
36#include <boost/mpl/list.hpp>
39namespace bdata = boost::unit_test::data;
50 ((0x0200ul << 50) & 0xFFFC000000000000ul) + 0x1555540F00113ul,
51 ((0x0200ul << 50) & 0xFFFC000000000000ul) + 0x3F04ECA103E5Cul,
52 ((0x0200ul << 50) & 0xFFFC000000000000ul) + 0x0000040215C0Dul,
53 ((0x0200ul << 50) & 0xFFFC000000000000ul) + 0x00000C0301004ul,
54 ((0x0204ul << 50) & 0xFFFC000000000000ul) + 0x0000000000400ul,
55 ((0x0200ul << 50) & 0xFFFC000000000000ul) + 0x1555540F00113ul,
56 ((0x0200ul << 50) & 0xFFFC000000000000ul) + 0x1F080CA100E4Dul,
57 ((0x0204ul << 50) & 0xFFFC000000000000ul) + 0x00044C0100001ul,
58 ((0x3FBBul << 50) & 0xFFFC000000000000ul) + 0x1DEEDFEEDDEEDul,
59 ((0x3FBBul << 50) & 0xFFFC000000000000ul) + 0x1DEEDFEEDDEEDul,
60 ((0x3FBBul << 50) & 0xFFFC000000000000ul) + 0x1DEEDFEEDDEEDul,
61 ((0x3FBBul << 50) & 0xFFFC000000000000ul) + 0x1DEEDFEEDDEEDul};
72 ((0x0200ul << 50) & 0xFFFC000000000000ul) + 0x1555540F00113ul,
73 ((0x0200ul << 50) & 0xFFFC000000000000ul) + 0x3F04ECA103E5Cul,
74 ((0x0200ul << 50) & 0xFFFC000000000000ul) + 0x0000040215C0Eul,
75 ((0x0200ul << 50) & 0xFFFC000000000000ul) + 0x00000C0301004ul,
76 ((0x0204ul << 50) & 0xFFFC000000000000ul) + 0x0000000000400ul,
77 ((0x0200ul << 50) & 0xFFFC000000000000ul) + 0x1555540F00113ul,
78 ((0x0200ul << 50) & 0xFFFC000000000000ul) + 0x1F080CA100E4Dul,
79 ((0x0204ul << 50) & 0xFFFC000000000000ul) + 0x00044C0100001ul,
80 ((0x3FBBul << 50) & 0xFFFC000000000000ul) + 0x1DEEDFEEDDEEDul,
81 ((0x3FBBul << 50) & 0xFFFC000000000000ul) + 0x1DEEDFEEDDEEDul,
82 ((0x3FBBul << 50) & 0xFFFC000000000000ul) + 0x1DEEDFEEDDEEDul,
83 ((0x3FBBul << 50) & 0xFFFC000000000000ul) + 0x1DEEDFEEDDEEDul};
94 ((0x0200ul << 50) & 0xFFFC000000000000ul) + 0x1555540F00113ul,
95 ((0x0200ul << 50) & 0xFFFC000000000000ul) + 0x3F04ECA103E5Cul,
96 ((0x0200ul << 50) & 0xFFFC000000000000ul) + 0x0000040215C08ul,
98 ((0x0204ul << 50) & 0xFFFC000000000000ul) + 0x0000000000400ul,
99 ((0x0200ul << 50) & 0xFFFC000000000000ul) + 0x1555540F00113ul,
100 ((0x0200ul << 50) & 0xFFFC000000000000ul) + 0x1F080CA100E4Dul,
101 ((0x0204ul << 50) & 0xFFFC000000000000ul) + 0x00044C0100001ul,
102 ((0x3FBBul << 50) & 0xFFFC000000000000ul) + 0x1DEEDFEEDDEEDul,
103 ((0x3FBBul << 50) & 0xFFFC000000000000ul) + 0x1DEEDFEEDDEEDul,
104 ((0x3FBBul << 50) & 0xFFFC000000000000ul) + 0x1DEEDFEEDDEEDul,
105 ((0x3FBBul << 50) & 0xFFFC000000000000ul) + 0x1DEEDFEEDDEEDul,
106 ((0x3FBBul << 50) & 0xFFFC000000000000ul) + 0x1DEEDFEEDDEEDul
112 result += fmt::format(
"{}-ch-{}-ts-{}-q",
asString(dsId), channel, sc.sampaTime);
113 if (sc.isClusterSum()) {
114 result += fmt::format(
"-{}-cs-{}", sc.chargeSum, sc.clusterSize);
116 for (
auto s : sc.samples) {
117 result += fmt::format(
"-{}",
s);
133 std::optional<size_t> insertSync = std::nullopt)
141 std::vector<std::byte> b8;
145 b8.insert(b8.end(),
b.payload.begin(),
b.payload.end());
149 std::vector<uint64_t> b64;
150 impl::copyBuffer(b8, b64);
153 if (insertSync.has_value() && insertSync.value() < b64.size()) {
154 uint64_t prefix = b64[0] & 0xFFFC00000000000F;
155 b64.insert(b64.begin() + insertSync.value(), prefix |
sampaSyncWord);
159 std::vector<std::byte>
bytes;
160 impl::copyBuffer(b64,
bytes);
164template <
typename CHARGESUM,
int VERSION>
177template <
typename CHARGESUM,
int VERSION>
180 const std::vector<SampaCluster>& clustersFirstChannel,
183 const std::vector<SampaCluster>& clustersSecondChannel = {},
184 std::optional<size_t> insertSync = std::nullopt)
191 encoder->startHeartbeatFrame(0, 0);
196 if (!
f1.has_value()) {
197 throw std::invalid_argument(
"invalid solarId for ds1");
199 if (!clustersSecondChannel.empty()) {
200 auto f2 = solar2feelink(ds2.solarId());
201 if (!
f2.has_value()) {
202 throw std::invalid_argument(
"invalid solarId for ds2");
204 if (
f2->feeId() !=
f1->feeId()) {
205 throw std::invalid_argument(
"this test is only meant to work with 2 solars in the same cru endpoint");
211 encoder->addChannelData(ds1, ch1, clustersFirstChannel);
212 if (!clustersSecondChannel.empty()) {
213 encoder->addChannelData(ds2, ch2, clustersSecondChannel);
216 std::vector<std::byte>
buffer;
217 encoder->moveToBuffer(
buffer);
220 return decodeBuffer<CHARGESUM, VERSION>(feeId, payloadBuffer);
223template <
int VERSION>
237 std::vector<uint64_t> pagev1{
page.begin(),
page.end()};
238 constexpr int rdhSize{8};
239 for (
int i = rdhSize;
i < pagev1.size();
i++) {
240 if (pagev1[
i] == 0xFEEDDEEDFEEDDEED || pagev1[
i] == 0) {
248 v1.incomplete =
v0.incomplete;
250 v1.linkID =
v0.linkID;
256template <
int VERSION = 0>
259 std::vector<uint64_t>
page = convert<VERSION>(ipage);
261 const void* rdhP =
reinterpret_cast<const void*
>(
page.data());
262 uint16_t feeId = o2::raw::RDHUtils::getFEEID(rdhP);
263 auto rdhSize = o2::raw::RDHUtils::getHeaderSize(rdhP);
264 auto payloadSize = o2::raw::RDHUtils::getMemorySize(rdhP) - rdhSize;
266 gsl::span<const std::byte>
buffer(
reinterpret_cast<const std::byte*
>(
page.data()),
page.size() * 8);
267 gsl::span<const std::byte> payloadBuffer =
buffer.subspan(rdhSize, payloadSize);
272 return decodeBuffer<ChargeSumMode, VERSION>(
f.id, payloadBuffer);
274 return decodeBuffer<SampleMode, VERSION>(
f.id, payloadBuffer);
287BOOST_AUTO_TEST_SUITE(o2_mch_raw)
289BOOST_AUTO_TEST_SUITE(userlogicdsdecoder)
296 auto r = testPayloadDecode<SampleMode, V::value>(
DsElecId{728, 1, 0}, 63, {cl});
305 auto r = testPayloadDecode<SampleMode, V::value>(
DsElecId{448, 6, 4}, 63, {cl});
313 SampaCluster cl2(346, 6789, {1001, 1002, 1003, 1004, 1005, 1006, 1007});
314 auto r = testPayloadDecode<SampleMode, V::value>(
DsElecId{361, 6, 2}, 63, {cl},
DsElecId{361, 6, 2}, 47, {cl2});
316 "S361-J6-DS2-ch-63-ts-345-q-123-456-789-901-902\n"
317 "S361-J6-DS2-ch-47-ts-346-q-1001-1002-1003-1004-1005-1006-1007\n");
325 auto r = testPayloadDecode<ChargeSumMode, V::value>(
DsElecId{728, 1, 0}, 63, {cl});
335 auto r = testPayloadDecode<ChargeSumMode, V::value>(
DsElecId{448, 6, 4}, 63, {cl1, cl2});
337 "S448-J6-DS4-ch-63-ts-345-q-123456-cs-789\n"
338 "S448-J6-DS4-ch-63-ts-346-q-789012-cs-345\n");
348 auto r = testPayloadDecode<ChargeSumMode, V::value>(
DsElecId{361, 6, 2}, 63, {cl1, cl2},
DsElecId{361, 6, 2}, 47, {cl3, cl4});
350 "S361-J6-DS2-ch-63-ts-345-q-123456-cs-789\n"
351 "S361-J6-DS2-ch-63-ts-346-q-789012-cs-345\n"
352 "S361-J6-DS2-ch-47-ts-347-q-1357-cs-890\n"
353 "S361-J6-DS2-ch-47-ts-348-q-7912-cs-345\n");
366 auto r = testPayloadDecode<ChargeSumMode, V::value>(
367 DsElecId{361, 6, 2}, 63, {cl1, cl2},
368 DsElecId{361, 6, 2}, 47, {cl3, cl4},
370 std::string r2 =
"S361-J6-DS2-ch-63-ts-345-q-123456-cs-789\n";
371 r2 +=
"S361-J6-DS2-ch-63-ts-346-q-789012-cs-345\n";
379 std::string
r = testPayloadDecodeCruPages<V::value>(
page);
381 "S81-J0-DS0-ch-42-ts-87-q-2-1-0-4-4-3-3-0-0-1-0-0-0\n"
382 "S81-J0-DS0-ch-42-ts-0-q-1\n");
388 std::string
r = testPayloadDecodeCruPages<V::value>(
page);
390 fmt::format(
"S81-J0-DS0-chip-1-error-{}\nS81-J0-DS0-ch-42-ts-0-q-1\n", (
int)
ErrorBadClusterSize));
396 std::string
r = testPayloadDecodeCruPages<V::value>(
page);
398 fmt::format(
"S81-J0-DS0-ch-42-ts-87-q-2-1-0-0-1-0-0-0\nS81-J0-DS0-chip-1-error-{}\nS81-J0-DS0-ch-42-ts-0-q-1\n",
403BOOST_AUTO_TEST_SUITE_END()
404BOOST_AUTO_TEST_SUITE_END()
unsigned short int uint16_t
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
char error[CURL_ERROR_SIZE]
constexpr uint16_t solarId() const
solarId is an identifier that uniquely identify a solar board
A UserLogicEndpointDecoder groups 12 x (40 UserLogicElinkDecoder objects)
size_t append(Payload bytes)
Append the equivalent n 64-bits words bytes size (=n) must be a multiple of 8.
GLboolean GLboolean GLboolean b
GLsizei const GLfloat * value
std::function< std::optional< uint16_t >(FeeLinkId)> createFeeLink2SolarMapper< ElectronicMapperGenerated >()
@ ErrorUnexpectedSyncPacket
constexpr uint64_t sampaSyncWord
std::function< void(DsElecId dsId, DualSampaChannelId channel, SampaCluster)> SampaChannelHandler
std::string asString(const SampaCluster &sc)
int forEachDataBlockRef(gsl::span< const std::byte > buffer, std::function< void(DataBlockRef ref)> f)
std::function< void(DsElecId dsId, int8_t chip, uint32_t error)> SampaErrorHandler
std::function< std::optional< FeeLinkId >(uint16_t)> createSolar2FeeLinkMapper< ElectronicMapperGenerated >()
std::unique_ptr< PayloadEncoder > createPayloadEncoder(Solar2FeeLinkMapper solar2feelink, bool userLogic, int version, bool chargeSumMode)
a DataBlockRef is a pair (DataBlock,offset) The offset is an offset into some external buffer
SampaChannelHandler sampaChannelHandler
SampaErrorHandler sampaErrorHandler
Piece of data for one Sampa channel.
std::map< std::string, ID > expected
boost::mpl::list< o2::dcs::DataPointIdentifier, o2::dcs::DataPointValue, o2::dcs::DataPointCompositeObject > testTypes
SampaErrorHandler handleError(std::string &result)
const uint64_t CruPageBadN10bitWords[]
std::vector< uint64_t > convert< 0 >(gsl::span< const uint64_t > page)
std::vector< std::byte > convertBuffer2PayloadBuffer(gsl::span< const std::byte > buffer, std::optional< size_t > insertSync=std::nullopt)
std::vector< uint64_t > convert(gsl::span< const uint64_t > page)
BOOST_AUTO_TEST_CASE_TEMPLATE(SampleModeSimplest, V, testTypes)
std::vector< uint64_t > convert< 1 >(gsl::span< const uint64_t > page)
std::string testPayloadDecodeCruPages(gsl::span< const uint64_t > ipage)
const uint64_t CruPageBadClusterSize[]
boost::mpl::list< V0, V1 > testTypes
std::string decodeBuffer(int feeId, gsl::span< const std::byte > buffer)
SampaChannelHandler handlePacket(std::string &result)
std::string testPayloadDecode(DsElecId ds1, DualSampaChannelId ch1, const std::vector< SampaCluster > &clustersFirstChannel, DsElecId ds2=DsElecId{0, 0, 0}, DualSampaChannelId ch2=47, const std::vector< SampaCluster > &clustersSecondChannel={}, std::optional< size_t > insertSync=std::nullopt)
const uint64_t CruPageOK[]
BOOST_CHECK_EQUAL(triggersD.size(), triggers.size())