15#include <fmt/format.h>
16#include <fmt/printf.h>
26constexpr uint64_t HAMMING_CODE_OFFSET = 0;
27constexpr uint64_t HEADER_PARITY_OFFSET = 6;
28constexpr uint64_t PACKET_TYPE_OFFSET = 7;
29constexpr uint64_t NUMBER_OF_1OBITS_WORDS_OFFSET = 10;
30constexpr uint64_t CHIP_ADDRESS_OFFSET = 20;
31constexpr uint64_t CHANNEL_ADDRESS_OFFSET = 24;
32constexpr uint64_t BUNCH_CROSSING_OFFSET = 29;
33constexpr uint64_t PARITY_OFFSET = 49;
35constexpr uint64_t HAMMING_CODE_NOFBITS = HEADER_PARITY_OFFSET - HAMMING_CODE_OFFSET;
36constexpr uint64_t HEADER_PARITY_NOFBITS = PACKET_TYPE_OFFSET - HEADER_PARITY_OFFSET;
37constexpr uint64_t PACKET_TYPE_NOFBITS = NUMBER_OF_1OBITS_WORDS_OFFSET - PACKET_TYPE_OFFSET;
38constexpr uint64_t NUMBER_OF_1OBITS_WORDS_NOFBITS = CHIP_ADDRESS_OFFSET - NUMBER_OF_1OBITS_WORDS_OFFSET;
39constexpr uint64_t CHIP_ADDRESS_NOFBITS = CHANNEL_ADDRESS_OFFSET - CHIP_ADDRESS_OFFSET;
40constexpr uint64_t CHANNEL_ADDRESS_NOFBITS = BUNCH_CROSSING_OFFSET - CHANNEL_ADDRESS_OFFSET;
41constexpr uint64_t BUNCH_CROSSING_NOFBITS = PARITY_OFFSET - BUNCH_CROSSING_OFFSET;
42constexpr uint64_t PARITY_NOFBITS = 50 - PARITY_OFFSET;
48 if (HAMMING_CODE_NOFBITS != 6) {
49 throw std::invalid_argument(fmt::format(
"HAMMING_CODE_NOFBITS is {0}. Should be 6", HAMMING_CODE_NOFBITS));
51 if (HEADER_PARITY_NOFBITS != 1) {
52 throw std::invalid_argument(fmt::format(
"HEADER_PARITY_NOFBITS is {0}. Should be 1", HEADER_PARITY_NOFBITS));
54 if (PACKET_TYPE_NOFBITS != 3) {
55 throw std::invalid_argument(fmt::format(
"PACKET_TYPE_NOFBITS is {0}. Should be 3", PACKET_TYPE_NOFBITS));
57 if (NUMBER_OF_1OBITS_WORDS_NOFBITS != 10) {
58 throw std::invalid_argument(fmt::format(
"NUMBER_OF_1OBITS_WORDS_NOFBITS is {0}. Should be 10", NUMBER_OF_1OBITS_WORDS_NOFBITS));
60 if (CHIP_ADDRESS_NOFBITS != 4) {
61 throw std::invalid_argument(fmt::format(
"CHIP_ADDRESS_NOFBITS is {0}. Should be 4", CHIP_ADDRESS_NOFBITS));
63 if (CHANNEL_ADDRESS_NOFBITS != 5) {
64 throw std::invalid_argument(fmt::format(
"CHANNEL_ADDRESS_NOFBITS is {0}. Should be 5", CHANNEL_ADDRESS_NOFBITS));
66 if (BUNCH_CROSSING_NOFBITS != 20) {
67 throw std::invalid_argument(fmt::format(
"BUNCH_CROSSING_NOFBITS is {0}. Should be 20", BUNCH_CROSSING_NOFBITS));
69 if (PARITY_NOFBITS != 1) {
70 throw std::invalid_argument(fmt::format(
"PARITY_NOFBITS is {0}. Should be 1", PARITY_NOFBITS));
75CHECKNOFBITS checknofbits;
77constexpr uint64_t HAMMING_CODE_MASK = 0x000000000003F;
78constexpr uint64_t HEADER_PARITY_MASK = 0x0000000000040;
79constexpr uint64_t PACKET_TYPE_MASK = 0x0000000000380;
80constexpr uint64_t NUMBER_OF_1OBITS_WORDS_MASK = 0x00000000FFC00;
81constexpr uint64_t CHIP_ADDRESS_MASK = 0x0000000F00000;
82constexpr uint64_t CHANNEL_ADDRESS_MASK = 0x000001F000000;
83constexpr uint64_t BUNCH_CROSSING_MASK = 0x1FFFFE0000000;
84constexpr uint64_t PARITY_MASK = 0x2000000000000;
86constexpr uint64_t hammingCode(uint64_t header)
88 return ((header & HAMMING_CODE_MASK) >> HAMMING_CODE_OFFSET);
91constexpr uint64_t headerParity(uint64_t header)
93 return ((header & HEADER_PARITY_MASK) >> HEADER_PARITY_OFFSET);
95constexpr uint64_t packetType(uint64_t header)
97 return ((header & PACKET_TYPE_MASK) >> PACKET_TYPE_OFFSET);
100constexpr uint64_t nof10BitWords(uint64_t header)
102 return ((header & NUMBER_OF_1OBITS_WORDS_MASK) >> NUMBER_OF_1OBITS_WORDS_OFFSET);
105constexpr uint64_t chipAddress(uint64_t header)
107 return ((header & CHIP_ADDRESS_MASK) >> CHIP_ADDRESS_OFFSET);
109constexpr uint64_t channelAddress(uint64_t header)
111 return ((header & CHANNEL_ADDRESS_MASK) >> CHANNEL_ADDRESS_OFFSET);
114constexpr uint64_t bunchCrossingCounter(uint64_t header)
116 return ((header & BUNCH_CROSSING_MASK) >> BUNCH_CROSSING_OFFSET);
119constexpr uint64_t payloadParity(uint64_t header)
121 return ((header & PARITY_MASK) >> PARITY_OFFSET);
124bool checkBit(uint64_t
value,
int i,
bool bitStatus)
126 return (
value >>
i & 1) ==
static_cast<int>(bitStatus);
129bool isHeartbeat(uint64_t header)
136 for (
int i = 7;
i <= 9;
i++) {
137 if (!checkBit(header,
i,
false)) {
141 for (
int i = 10;
i <= 19;
i++) {
142 if (!checkBit(header,
i,
false)) {
146 if (!checkBit(header, 24,
true) || !checkBit(header, 26,
true) || !checkBit(header, 28,
true) || !checkBit(header, 25,
false) || !checkBit(header, 27,
false) || !checkBit(header, 49,
false)) {
167 return "DataTruncated";
173 return "DataTruncatedTriggerTooEarly";
179 return "DataNumWords";
182 return "DataTriggerTooEarl";
185 return "DataTriggerTooEarlyNumWords";
187 throw std::out_of_range(
"should not happen");
237 mValue &= ~HEADER_PARITY_MASK;
238 mValue += (
static_cast<uint64_t
>(p) << HEADER_PARITY_OFFSET) & HEADER_PARITY_MASK;
243 mValue &= ~PARITY_MASK;
244 mValue += (
static_cast<uint64_t
>(dp) << PARITY_OFFSET) & PARITY_MASK;
249 mValue &= ~CHIP_ADDRESS_MASK;
250 mValue += (
static_cast<uint64_t
>(
h) << CHIP_ADDRESS_OFFSET) & CHIP_ADDRESS_MASK;
255 mValue &= ~CHANNEL_ADDRESS_MASK;
256 mValue += (
static_cast<uint64_t
>(ch) << CHANNEL_ADDRESS_OFFSET) & CHANNEL_ADDRESS_MASK;
261 mValue &= ~BUNCH_CROSSING_MASK;
262 mValue += (
static_cast<uint64_t
>(bx) << BUNCH_CROSSING_OFFSET) & BUNCH_CROSSING_MASK;
267 mValue &= ~HAMMING_CODE_MASK;
268 mValue += (
static_cast<uint64_t
>(hamming) << HAMMING_CODE_OFFSET) & HAMMING_CODE_MASK;
273 mValue &= ~NUMBER_OF_1OBITS_WORDS_MASK;
274 mValue += (
static_cast<uint64_t
>(nofwords) << NUMBER_OF_1OBITS_WORDS_OFFSET) & NUMBER_OF_1OBITS_WORDS_MASK;
279 mValue &= ~PACKET_TYPE_MASK;
280 mValue += (
static_cast<uint64_t
>(pkt) << PACKET_TYPE_OFFSET) & PACKET_TYPE_MASK;
305 return mValue == rhs.mValue;
310 return !(*
this == rhs);
315 return ::isHeartbeat(mValue);
320 return ::hammingCode(mValue) & 0X3F;
325 return ::headerParity(mValue) == 1;
337 return ::nof10BitWords(mValue) & 0x3FF;
343 return ::chipAddress(mValue) & 0xF;
349 return ::channelAddress(mValue) & 0x1F;
355 return ::bunchCrossingCounter(mValue) & 0x1FFFFF;
360 return ::payloadParity(mValue) == 1;
391 std::stringstream os;
394 std::vector<int> sep = {5, 6, 9, 19, 23, 28, 48};
395 for (
int i = 0;
i < 50;
i++) {
396 os << ((sh.
uint64() & (
one <<
i)) ?
"1" :
"0");
397 if (std::find(begin(sep),
end(sep),
i) !=
end(sep)) {
402 os << fmt::sprintf(
"%6x %d %3x %10x %4x %5x %20x %d (0x%x) | HeaderType: %s %s",
428constexpr std::array<int, 49>
conv = {-1, -1, 7, -1, 8, 9, 10, -1, 11, 12, 13, 14, 15, 16, 17,
429 -1, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28,
430 29, 30, 31, 32, -1, 33, 34, 35, 36, 37, 38, 39,
431 40, 41, 42, 43, 44, 45, 46, 47, 48, 49};
444 for (uint64_t
i = 0;
i < 49;
i++) {
448 if ((
i + 1) &
test) {
454 return (
n + 1) % 2 == 0;
463 for (
int i = 0;
i < 6;
i++) {
475 for (
auto i = 0;
i <
pos.size();
i++) {
476 n += ((
value & (one << pos[i])) > 0);
478 return (
n + 1) % 2 == 0;
485 for (
auto i = 0;
i < masks.size();
i++) {
488 return (
n + 1) % 2 == 0;
491std::array<int, 24>
p0{7, 8, 10, 11, 13, 15, 17, 18, 20, 22, 24, 26, 28, 30, 32, 33, 35, 37, 39, 41, 43, 45, 47, 49};
492std::array<int, 23>
p1{7, 9, 10, 12, 13, 16, 17, 19, 20, 23, 24, 27, 28, 31, 32, 34, 35, 38, 39, 42, 43, 46, 47};
493std::array<int, 23>
p2{8, 9, 10, 14, 15, 16, 17, 21, 22, 23, 24, 29, 30, 31, 32, 36, 37, 38, 39, 44, 45, 46, 47};
494std::array<int, 23>
p3{11, 12, 13, 14, 15, 16, 17, 25, 26, 27, 28, 29, 30, 31, 32, 40, 41, 42, 43, 44, 45, 46, 47};
495std::array<int, 17>
p4{18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 48, 49};
496std::array<int, 17>
p5{33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49};
509 return h0 + h1 * 2 + h2 * 4 + h3 * 8 + h4 * 16 + h5 * 32;
512std::array<uint64_t, 24>
m0 = {0x80, 0x100, 0x400, 0x800, 0x2000, 0x8000, 0x20000, 0x40000, 0x100000, 0x400000, 0x1000000, 0x4000000, 0x10000000, 0x40000000, 0x100000000, 0x200000000, 0x800000000, 0x2000000000, 0x8000000000, 0x20000000000, 0x80000000000, 0x200000000000, 0x800000000000, 0x2000000000000};
513std::array<uint64_t, 23>
m1 = {0x80, 0x200, 0x400, 0x1000, 0x2000, 0x10000, 0x20000, 0x80000, 0x100000, 0x800000, 0x1000000, 0x8000000, 0x10000000, 0x80000000, 0x100000000, 0x400000000, 0x800000000, 0x4000000000, 0x8000000000, 0x40000000000, 0x80000000000, 0x400000000000, 0x800000000000};
514std::array<uint64_t, 23>
m2 = {0x100, 0x200, 0x400, 0x4000, 0x8000, 0x10000, 0x20000, 0x200000, 0x400000, 0x800000, 0x1000000, 0x20000000, 0x40000000, 0x80000000, 0x100000000, 0x1000000000, 0x2000000000, 0x4000000000, 0x8000000000, 0x100000000000, 0x200000000000, 0x400000000000, 0x800000000000};
515std::array<uint64_t, 23>
m3 = {0x800, 0x1000, 0x2000, 0x4000, 0x8000, 0x10000, 0x20000, 0x2000000, 0x4000000, 0x8000000, 0x10000000, 0x20000000, 0x40000000, 0x80000000, 0x100000000, 0x10000000000, 0x20000000000, 0x40000000000, 0x80000000000, 0x100000000000, 0x200000000000, 0x400000000000, 0x800000000000};
516std::array<uint64_t, 17>
m4 = {0x40000, 0x80000, 0x100000, 0x200000, 0x400000, 0x800000, 0x1000000, 0x2000000, 0x4000000, 0x8000000, 0x10000000, 0x20000000, 0x40000000, 0x80000000, 0x100000000, 0x1000000000000, 0x2000000000000};
517std::array<uint64_t, 17>
m5 = {0x200000000, 0x400000000, 0x800000000, 0x1000000000, 0x2000000000, 0x4000000000, 0x8000000000, 0x10000000000, 0x20000000000, 0x40000000000, 0x80000000000, 0x100000000000, 0x200000000000, 0x400000000000, 0x800000000000, 0x1000000000000, 0x2000000000000};
535 return h0 + h1 * 2 + h2 * 4 + h3 * 8 + h4 * 16 + h5 * 32;
542 for (
auto i = 0;
i < masks.size();
i++) {
545 std::cout << fmt::format(
"0x{:X},",
v);
554 constexpr std::array<uint64_t, 6> masks = {0x2AAAB5556AD80,
555 0xCCCD999B3680, 0xF0F1E1E3C700,
556 0xFF01FE03F800, 0x30001FFFC0000,
564 return h0 + h1 * 2 + h2 * 4 + h3 * 8 + h4 * 16 + h5 * 32;
578 constexpr uint64_t
one{1};
579 for (
int i = 0;
i < 6;
i++) {
580 if (
v & (
one <<
i)) {
584 for (
int i = 7;
i < 50;
i++) {
585 if (
v & (
one <<
i)) {
589 return (
n + 1) % 2 == 0;
592constexpr std::array<uint64_t, 49>
parityMasks = {0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000, 0x10000, 0x20000, 0x40000, 0x80000, 0x100000, 0x200000, 0x400000, 0x800000, 0x1000000, 0x2000000, 0x4000000, 0x8000000, 0x10000000, 0x20000000, 0x40000000, 0x80000000, 0x100000000, 0x200000000, 0x400000000, 0x800000000, 0x1000000000, 0x2000000000, 0x4000000000, 0x8000000000, 0x10000000000, 0x20000000000, 0x40000000000, 0x80000000000, 0x100000000000, 0x200000000000, 0x400000000000, 0x800000000000, 0x1000000000000, 0x2000000000000};
603 return (
n + 1) % 2 == 0;
615 return (
short)(
result & 0x1);
626 return (
short)(no & 0x1);
631 constexpr uint64_t
one{1};
Class for time synchronization of RawReader instances.
GLsizei const GLfloat * value
void assertNofBits(std::string_view msg, T value, int n)
constexpr std::array< uint64_t, 49 > parityMasks
int computeHeaderParity(uint64_t value)
int computeHammingCode3(uint64_t value)
DualSampaChannelId getDualSampaChannelId(const SampaHeader &sh)
Return channel number (0..63)
std::string packetTypeName(SampaPacketType pkt)
packetTypeName returns a string representation of the given packet type.
int partialOddParity3(uint64_t value, int pos)
constexpr std::array< int, 49 > conv
int computeHeaderParity1(uint64_t value)
SampaHeader sampaHeartbeat(uint8_t elinkId, uint20_t bunchCrossing)
Heartbeat packet.
std::array< uint64_t, 24 > m0
SampaHeader sampaSync()
The 50-bits Sampa SYNC word.
int computeHammingCode2(uint64_t value)
std::array< uint64_t, 23 > m2
int computeHeaderParity4(uint64_t value)
@ DataTriggerTooEarlyNumWords
@ DataTruncatedTriggerTooEarly
int computeParity(uint64_t v)
int computeHammingCode1(uint64_t value)
int partialOddParity(uint64_t value, const std::array< uint64_t, N > &masks)
int computeHeaderParity2(uint64_t value)
std::array< uint64_t, 17 > m5
std::array< uint64_t, 17 > m4
uint6_t DualSampaChannelId
int computeHeaderParity3(uint64_t value)
std::string asString(const SampaCluster &sc)
std::array< uint64_t, 23 > m3
int computeHammingCode4(uint64_t value)
uint64_t computeMask(const std::array< uint64_t, N > &masks)
int computeHammingCode(uint64_t value)
std::array< uint64_t, 23 > m1
int partialOddParity2(uint64_t value, const std::array< int, N > &pos)
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
std::ostream & operator<<(std::ostream &stream, o2::InteractionRecord const &ir)
FIXME: do not use data model tables.