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);
127 result += fmt::format(
"{}-chip-{}-error-{}",
asString(dsId), chip, error);
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>
224std::vector<uint64_t>
convert(gsl::span<const uint64_t> page);
227std::vector<uint64_t>
convert<0>(gsl::span<const uint64_t> page)
229 return {page.begin(), page.end()};
233std::vector<uint64_t>
convert<1>(gsl::span<const uint64_t> page)
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";
378 gsl::span<const uint64_t> page =
CruPageOK;
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()
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
uint6_t DualSampaChannelId
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())