14#ifndef ALICEO2_ITSMFT_RAWPIXELREADER_H_
15#define ALICEO2_ITSMFT_RAWPIXELREADER_H_
33#include <TStopwatch.h>
34#include <fairlogger/Logger.h>
47#define _RAW_READER_ERROR_CHECKS_
49#define OUTHEX(v, l) "0x" << std::hex << std::setfill('0') << std::setw(l) << v << std::dec
88 void print(
bool skipNoErr =
true)
const
90 printf(
"\nDecoding statistics\n");
98 printf(
"Decoding errors: %d\n", nErr);
106 static constexpr std::array<std::string_view, NErrorsDefined>
ErrNames = {
107 "RDH cointains invalid FEEID"
119template <
class Mapping = o2::itsmft::ChipMappingITS>
133 printf(
"RawPixelReader IO time: ");
136 printf(
"Cache filling time: ");
169 if (mCurRUDecodeID >= 0) {
170 for (; mCurRUDecodeID < mNRUs; mCurRUDecodeID++) {
171 auto& ru = mRUDecodeVec[mCurRUDecodeID];
172 if (ru.lastChipChecked < ru.nChipsFired) {
173 auto& chipData = ru.chipsData[ru.lastChipChecked++];
174 int id = chipData.getChipID();
175 chipDataVec[
id].swap(chipData);
176 return &chipDataVec[
id];
185 if (mMinTriggersCached < 2) {
201 LOG(info) <<
"Cleaning decoder, reset_statistics_flag " << resetStat;
203 mDecodingStat.
clear();
205 for (
auto& rudec : mRUDecodeVec) {
208 for (
auto& lnk : mGBTLinks) {
209 lnk.clear(resetStat);
211 mMinTriggersCached = 0;
221 uint8_t ruSWMin = 0, uint8_t ruSWMax = 0xff)
227 int nDigTot = digiVec.size();
228 assert(from < nDigTot);
229 int last = (from + ndig <= nDigTot) ? from + ndig : nDigTot;
233 UShort_t curChipID = 0xffff;
235 ruSWMax = (ruSWMax < uint8_t(mMAP.getNRUs())) ? ruSWMax : mMAP.getNRUs() - 1;
237 if (mNRUs <
int(ruSWMax) - ruSWMin) {
238 for (uint8_t ru = ruSWMin; ru <= ruSWMax; ru++) {
242 nLinks += ruData.links[il] < 0 ? 0 : 1;
246 LOG(info) <<
"Imposing single link readout for RU " <<
int(ru);
248 getGBTLink(ruData.links[0])->
lanes = mMAP.getCablesOnRUType(ruData.ruInfo->ruType);
255 for (
int id = from;
id < last;
id++) {
256 const auto& dig = digiVec[
id];
257 if (curChipID != dig.getChipIndex()) {
258 mMAP.getChipInfoSW(dig.getChipIndex(), chInfo);
259 if (chInfo.
ru < ruSWMin || chInfo.
ru > ruSWMax) {
262 curChipID = dig.getChipIndex();
263 mCurRUDecodeID = chInfo.
ru;
264 curRUDecode = &mRUDecodeVec[mCurRUDecodeID];
268 curChipData->
getData().emplace_back(&dig);
271 int minPages = 0xffffff;
272 for (mCurRUDecodeID = ruSWMin; mCurRUDecodeID <=
int(ruSWMax); mCurRUDecodeID++) {
273 curRUDecode = &mRUDecodeVec[mCurRUDecodeID];
274 uint16_t next2Proc = 0, nchTot = mMAP.getNChipsOnRUType(curRUDecode->
ruInfo->
ruType);
275 for (
int ich = 0; ich < curRUDecode->
nChipsFired; ich++) {
276 auto& chipData = curRUDecode->
chipsData[ich];
278 next2Proc = chipData.getChipID() + 1;
284 if (minPageRU < minPages) {
285 minPages = minPageRU;
297 auto& ruData = mRUDecodeVec[mCurRUDecodeID];
299 const auto& chip = *mMAP.getChipOnRUInfo(ruData.ruInfo->ruType, chipData.
getChipID());
300 ruData.cableHWID[chip.cableHWPos] = chip.cableHW;
304 [](
auto lhs,
auto rhs) {
305 if (lhs.getRow() < rhs.getRow()) {
308 if (lhs.getRow() > rhs.getRow()) {
311 return lhs.getCol() < rhs.getCol();
313 ruData.cableData[chip.cableHWPos].ensureFreeCapacity(40 * (2 +
pixels.size()));
314 mCoder.encodeChip(ruData.cableData[chip.cableHWPos], chipData, chip.chipOnModuleHW,
mInteractionRecord.
bc);
321 auto& ruData = mRUDecodeVec[mCurRUDecodeID];
322 for (
int chipIDSW = fromChip; chipIDSW < uptoChip; chipIDSW++) {
323 const auto& chip = *mMAP.getChipOnRUInfo(ruData.ruInfo->ruType, chipIDSW);
324 ruData.cableHWID[chip.cableHWPos] = chip.cableHW;
325 ruData.cableData[chip.cableHWPos].ensureFreeCapacity(100);
326 mCoder.addEmptyChip(ruData.cableData[chip.cableHWPos], chip.chipOnModuleHW, mInteractionRecord.bc);
335 const int dummyNPages = 0xffffff;
336 int minPages = dummyNPages;
337 auto& ruData = mRUDecodeVec[mCurRUDecodeID];
343 RDHUtils::setHeartBeatBC(rdh, mInteractionRecord.
orbit);
347 int maxGBTWordsPerPacket = (
MaxGBTPacketBytes - RDHUtils::getHeaderSize(rdh)) / mGBTWordSize - 2;
352 auto* link = getGBTLink(ruData.links[il]);
356 int nGBTWordsNeeded = 0;
357 for (
int icab = ruData.ruInfo->nCables; icab--;) {
358 if ((link->lanes & (0x1 << icab))) {
359 int nb = ruData.cableData[icab].getSize();
360 nGBTWordsNeeded += nb ? 1 + (nb - 1) / 9 : 0;
368 int loadsize = RDHUtils::getHeaderSize(rdh) + (nGBTWordsNeeded + 2) * mGBTWordSize;
373 link->data.addFast(
reinterpret_cast<uint8_t*
>(&rdh), RDHUtils::getHeaderSize(rdh));
378 gbtHeader.
packetIdx = RDHUtils::getPageCounter(rdh);
379 link->data.addFast(gbtHeader.
getW8(), mGBTWordSize);
381 LOG(info) <<
"Filling RU data";
383 gbtHeader.
printX(mPadding128);
387 int nGBTWordsInPacket = 0;
389 for (
int icab = 0; icab < ruData.ruInfo->nCables; icab++) {
390 if ((link->lanes & (0x1 << icab))) {
391 auto& cableData = ruData.cableData[icab];
392 int nb = cableData.getUnusedSize();
399 int gbtWordStart = link->data.getSize();
400 link->data.addFast(cableData.getPtr(), nb);
401 link->data.addFast(zero16, mGBTWordSize - nb);
402 link->data[gbtWordStart + 9] = mMAP.getGBTHeaderRUType(ruData.ruInfo->ruType, ruData.cableHWID[icab]);
403 cableData.setPtr(cableData.getPtr() + nb);
406 ((
GBTData*)(&link->data[gbtWordStart]))->printX(mPadding128);
408 if (++nGBTWordsInPacket == maxGBTWordsPerPacket) {
414 if (nGBTWordsNeeded && nGBTWordsInPacket >= maxGBTWordsPerPacket) {
416 link->data.add(gbtTrailer.
getW8(), mGBTWordSize);
418 gbtTrailer.
printX(mPadding128);
423 loadsize = RDHUtils::getHeaderSize(rdh) + (nGBTWordsNeeded + 2) * mGBTWordSize;
427 link->data.addFast(
reinterpret_cast<uint8_t*
>(&rdh), RDHUtils::getHeaderSize(rdh));
432 gbtHeader.
packetIdx = RDHUtils::getPageCounter(rdh);
433 link->data.addFast(gbtHeader.
getW8(), mGBTWordSize);
435 gbtHeader.
printX(mPadding128);
437 nGBTWordsInPacket = 0;
439 }
while (nGBTWordsNeeded);
443 link->data.addFast(gbtTrailer.
getW8(), mGBTWordSize);
445 gbtTrailer.
printX(mPadding128);
449 if (minPages > link->nTriggers) {
450 minPages = link->nTriggers;
455 return minPages == dummyNPages ? 0 : minPages;
465 for (
int ru = 0; ru < mMAP.getNRUs(); ru++) {
466 auto* ruData = getRUDecode(ru);
471 auto link = getGBTLink(ruData->links[il]);
472 if (!link || link->data.isEmpty()) {
477 const auto* ptrIni = link->data.getPtr();
478 while (nPages < maxPages && !link->
data.isEmpty()) {
479 const auto ptr = link->data.getPtr();
481 sink.
addFast(
ptr, RDHUtils::getMemorySize(rdh));
483 link->data.setPtr(
ptr + RDHUtils::getMemorySize(rdh));
489 link->data.moveUnusedToHead();
503 LOG(info) <<
"Caching links data, currently in cache: " << mMinTriggersCached <<
" triggers";
504 auto nRead = loadInput(
buffer);
508 mSWCache.Start(
false);
509 enum LinkFlag : int8_t { NotUpdated,
512 LinkFlag linkFlags[Mapping::getNRUs()][3] = {NotUpdated};
513 int nLEnoughTriggers = 0;
519 if (!findNextRDH(
buffer)) {
529 int ruIDSW = mMAP.FEEId2RUSW(RDHUtils::getFEEID(rdh));
530#ifdef _RAW_READER_ERROR_CHECKS_
531 if (ruIDSW >= mMAP.getNRUs()) {
534 <<
" : FEEId:" <<
OUTHEX(RDHUtils::getFEEID(rdh), 4) <<
", skipping CRU page";
536 ptr += RDHUtils::getOffsetToNext(rdh);
539 nRead += loadInput(
buffer);
545 auto& ruDecode = getCreateRUDecode(ruIDSW);
547 bool newTrigger =
true;
548 uint16_t lr, ruOnLr, linkIDinRU;
549 mMAP.expandFEEId(RDHUtils::getFEEID(rdh), lr, ruOnLr, linkIDinRU);
550 auto link = getGBTLink(ruDecode.links[linkIDinRU]);
553 if (isSameRUandTrigger(rdhPrev, rdh)) {
557 ruDecode.links[linkIDinRU] = addGBTLink();
558 link = getGBTLink(ruDecode.links[linkIDinRU]);
559 link->statistics.feeID = RDHUtils::getFEEID(rdh);
560 LOG(info) <<
"Adding new GBT LINK FEEId:" <<
OUTHEX(link->statistics.feeID, 4);
563 if (linkFlags[ruIDSW][linkIDinRU] == NotUpdated) {
564 link->data.moveUnusedToHead();
565 linkFlags[ruIDSW][linkIDinRU] = Updated;
568 link->data.add(
ptr, RDHUtils::getMemorySize(rdh));
569 link->lastPageSize = RDHUtils::getMemorySize(rdh);
575 if (link->nTriggers >= mMinTriggersToCache && linkFlags[ruIDSW][linkIDinRU] != HasEnoughTriggers) {
577 linkFlags[ruIDSW][linkIDinRU] = HasEnoughTriggers;
581 ptr += RDHUtils::getOffsetToNext(rdh);
584 nRead += loadInput(
buffer);
590 if (mNLinks == nLEnoughTriggers) {
594 }
while (!
buffer.isEmpty());
596 if (mNLinks == nLEnoughTriggers) {
597 mMinTriggersCached = mMinTriggersToCache;
599 mMinTriggersCached = INT_MAX;
600 for (
int ir = 0;
ir < mNRUs;
ir++) {
601 const auto& ruDecData = mRUDecodeVec[
ir];
602 for (
auto linkID : ruDecData.links) {
603 const auto* link = getGBTLink(linkID);
604 if (link && link->nTriggers < mMinTriggersCached) {
605 mMinTriggersCached = link->nTriggers;
611 LOG(info) <<
"Cached at least " << mMinTriggersCached <<
" triggers on " << mNLinks <<
" links of " << mNRUs <<
" RUs";
620 if (mMinTriggersCached < 1) {
621 cacheLinksData(mRawBuffer);
622 if (mMinTriggersCached < 1) {
627 for (
int ir = mNRUs;
ir--;) {
628 auto& ruDecode = mRUDecodeVec[
ir];
630 for (
auto linkID : ruDecode.links) {
631 auto* link = getGBTLink(linkID);
632 if (link && !link->data.isEmpty()) {
634 mInteractionRecord = RDHUtils::getTriggerIR(rdh);
635 mTrigger = RDHUtils::getTriggerType(rdh);
636 mInteractionRecordHB = RDHUtils::getHeartBeatIR(rdh);
642 nlinks += decodeNextRUData(ruDecode);
643 mDecodingStat.nRUsProcessed++;
646 mDecodingStat.nTriggersProcessed++;
649 mMinTriggersCached--;
657 int minTriggers = INT_MAX;
660 bool aborted =
false;
661 for (
auto linkID : ruDecData.
links) {
662 auto* link = getGBTLink(linkID);
663 if (link && !link->data.isEmpty()) {
664 link->data.setPtr(decodeRUData(link->data.getPtr(), ruDecData, aborted));
667 if (--link->nTriggers < minTriggers) {
668 minTriggers = link->nTriggers;
671 if (link->data.isEmpty()) {
677 decodeAlpideData(ruDecData);
688 bool goodRDH =
false;
693 auto nrl = loadInput(
buffer);
709 LOG(info) <<
"End of pointer recovery after skipping " << scan <<
" GBT words, RDH is"
710 << (goodRDH ?
"" :
" not") <<
" found";
728#ifdef _RAW_READER_ERROR_CHECKS_
730 LOG(error) <<
"Page does not start with RDH";
732 for (
int i = 0;
i < 4;
i++) {
734 gbtD->
printX(mPadding128);
742 int ruIDSW = mMAP.FEEId2RUSW(RDHUtils::getFEEID(rdh));
743#ifdef _RAW_READER_ERROR_CHECKS_
744 if (ruIDSW >= mMAP.getNRUs()) {
747 <<
" : FEEId:" <<
OUTHEX(RDHUtils::getFEEID(rdh), 4) <<
", skipping CRU page";
749 raw += RDHUtils::getOffsetToNext(rdh);
754 LOG(error) <<
"RDG RU IDSW " << ruIDSW <<
" differs from expected " << ruDecData.
ruInfo->
idSW;
759 uint16_t lr, ruOnLr, linkIDinRU;
760 mMAP.expandFEEId(RDHUtils::getFEEID(rdh), lr, ruOnLr, linkIDinRU);
761 auto* ruLink = getGBTLink(ruDecData.
links[linkIDinRU]);
762 auto& ruLinkStat = ruLink->statistics;
764 ruLinkStat.nPackets++;
766#ifdef _RAW_READER_ERROR_CHECKS_
767 if (RDHUtils::getPacketCounter(rdh) > ruLink->packetCounter + 1) {
770 <<
" : FEEId:" <<
OUTHEX(RDHUtils::getFEEID(rdh), 4) <<
": jump from " <<
int(ruLink->packetCounter)
771 <<
" to " <<
int(RDHUtils::getPacketCounter(rdh));
776 ruLink->packetCounter = RDHUtils::getPacketCounter(rdh);
778 mDecodingStat.nBytesProcessed += RDHUtils::getMemorySize(rdh);
779 mDecodingStat.nPagesProcessed++;
780 raw += RDHUtils::getHeaderSize(rdh);
781 int nGBTWords = (RDHUtils::getMemorySize(rdh) - RDHUtils::getHeaderSize(rdh)) / mGBTWordSize - 2;
784#ifdef _RAW_READER_ERROR_CHECKS_
787 gbtH->printX(mPadding128);
791 if (!gbtH->isDataHeader()) {
792 gbtH->printX(mPadding128);
793 LOG(error) <<
"FEEId:" <<
OUTHEX(RDHUtils::getFEEID(rdh), 4) <<
" GBT payload header was expected, abort page decoding";
796 gbtH->printX(mPadding128);
801 if (gbtH->packetIdx != RDHUtils::getPageCounter(rdh)) {
802 LOG(error) <<
"FEEId:" <<
OUTHEX(RDHUtils::getFEEID(rdh), 4) <<
" Different GBT header " << gbtH->packetIdx
803 <<
" and RDH page " << RDHUtils::getPageCounter(rdh) <<
" counters";
808 if (ruLink->lanesActive == ruLink->lanesStop) {
809 if (RDHUtils::getPageCounter(rdh)) {
810 LOG(error) <<
"FEEId:" <<
OUTHEX(RDHUtils::getFEEID(rdh), 4) <<
" Non-0 page counter (" << RDHUtils::getPageCounter(rdh) <<
") while all lanes were stopped";
816 ruLink->lanesActive = gbtH->activeLanes;
818 if (~(mMAP.getCablesOnRUType(ruDecData.
ruInfo->
ruType)) & ruLink->lanesActive) {
819 std::bitset<32> expectL(mMAP.getCablesOnRUType(ruDecData.
ruInfo->
ruType)), gotL(ruLink->lanesActive);
820 LOG(error) <<
"FEEId:" <<
OUTHEX(RDHUtils::getFEEID(rdh), 4) <<
" Active lanes pattern " << gotL
821 <<
" conflicts with expected " << expectL <<
" for given RU type, skip page";
824 raw = ((uint8_t*)rdh) + RDHUtils::getOffsetToNext(rdh);
828 if (!RDHUtils::getPageCounter(rdh)) {
829 ruLink->lanesStop = 0;
830 ruLink->lanesWithData = 0;
835 for (
int iw = 0; iw <
nGBTWords; iw++, raw += mGBTWordSize) {
840 printf(
"W%4d |", iw);
841 gbtD->printX(mPadding128);
843 if (gbtD->isDataTrailer()) {
848 int cableHW = gbtD->getCableID();
849 int cableSW = mMAP.cableHW2SW(ruDecData.
ruInfo->
ruType, cableHW);
850 ruDecData.
cableData[cableSW].add(gbtD->getW8(), 9);
853#ifdef _RAW_READER_ERROR_CHECKS_
854 int cableHWPos = mMAP.cableHW2Pos(ruDecData.
ruInfo->
ruType, cableHW);
856 ruLink->lanesWithData |= 0x1 << cableHWPos;
857 if (ruLink->lanesStop & (0x1 << cableHWPos)) {
859 LOG(error) <<
"FEEId:" <<
OUTHEX(RDHUtils::getFEEID(rdh), 4) <<
" Data received for stopped lane " << cableHW <<
" (sw:" << cableSW <<
")";
867#ifdef _RAW_READER_ERROR_CHECKS_
870 gbtT->
printX(mPadding128);
873 if (!gbtT->isDataTrailer()) {
874 gbtT->printX(mPadding128);
875 LOG(error) <<
"FEEId:" <<
OUTHEX(RDHUtils::getFEEID(rdh), 4) << std::dec
876 <<
" GBT payload trailer was expected, abort page decoding NW" <<
nGBTWords;
883 ruLink->lanesTimeOut |= gbtT->lanesTimeout;
884 ruLink->lanesStop |= gbtT->lanesStops;
889 if (!RDHUtils::getOffsetToNext(rdh)) {
893 raw = ((uint8_t*)rdh) + RDHUtils::getOffsetToNext(rdh);
896 if (!isSameRUandTrigger(rdh, rdhN)) {
898#ifdef _RAW_READER_ERROR_CHECKS_
900 if ((ruLink->lanesActive & ~ruLink->lanesStop) &&
nGBTWords) {
902 std::bitset<32>
active(ruLink->lanesActive), stopped(ruLink->lanesStop);
903 LOG(error) <<
"FEEId:" <<
OUTHEX(RDHUtils::getFEEID(rdh), 4) <<
" end of FEE data but not all lanes received stop"
904 <<
"| active: " <<
active <<
" stopped: " << stopped;
911 if ((~ruLink->lanesWithData & ruLink->lanesActive) != ruLink->lanesTimeOut &&
nGBTWords) {
912 std::bitset<32> withData(ruLink->lanesWithData),
active(ruLink->lanesActive), timeOut(ruLink->lanesTimeOut);
913 LOG(error) <<
"FEEId:" <<
OUTHEX(RDHUtils::getFEEID(rdh), 4) <<
" Lanes not in time-out but not sending data"
914 <<
"\n| with data: " << withData <<
" active: " <<
active <<
" timeOut: " << timeOut;
920 ruLinkStat.packetStates[gbtT->getPacketState()]++;
924#ifdef _RAW_READER_ERROR_CHECKS_
926 if (RDHUtils::getPageCounter(rdhN) != RDHUtils::getPageCounter(rdh) + 1) {
927 LOG(error) <<
"FEEId:" <<
OUTHEX(RDHUtils::getFEEID(rdh), 4) <<
" Discontinuity in the RDH page counter of the same RU trigger: old "
928 << RDHUtils::getPageCounter(rdh) <<
" new: " << RDHUtils::getPageCounter(rdhN);
938#ifdef _RAW_READER_ERROR_CHECKS_
951 loadInput(mRawBuffer);
955 if (!mRawBuffer.isEmpty()) {
956 bool aborted =
false;
958 auto ptr = skimPaddedRUData(mRawBuffer.getPtr(), outBuffer, aborted);
959 mDecodingStat.nRUsProcessed++;
961 mRawBuffer.setPtr(
ptr);
963 if (mRawBuffer.isEmpty()) {
967 if (findNextRDH(mRawBuffer)) {
968 ptr = mRawBuffer.getPtr();
988#ifdef _RAW_READER_ERROR_CHECKS_
990 LOG(error) <<
"Page does not start with RDH";
992 for (
int i = 0;
i < 4;
i++) {
994 gbtD->
printX(mPadding128);
999 int ruIDSWD = mMAP.FEEId2RUSW(RDHUtils::getFEEID(rdh));
1000 if (ruIDSWD >= mMAP.getNRUs()) {
1003 <<
" : FEEId:" <<
OUTHEX(RDHUtils::getFEEID(rdh), 4) <<
", skipping CRU page";
1005 raw += RDHUtils::getOffsetToNext(rdh);
1009 uint16_t lr, ruOnLr, linkIDinRU;
1010 mMAP.expandFEEId(RDHUtils::getFEEID(rdh), lr, ruOnLr, linkIDinRU);
1011 int ruIDSW = mMAP.FEEId2RUSW(RDHUtils::getFEEID(rdh));
1012 auto& ruDecode = getCreateRUDecode(ruIDSW);
1013 auto ruInfo = mMAP.getRUInfoSW(ruIDSW);
1015 if (ruDecode.links[linkIDinRU] < 0) {
1016 ruDecode.links[linkIDinRU] = addGBTLink();
1017 getGBTLink(ruDecode.links[linkIDinRU])->statistics.feeID = RDHUtils::getFEEID(rdh);
1021 mInteractionRecord = RDHUtils::getTriggerIR(rdh);
1023 mTrigger = RDHUtils::getTriggerType(rdh);
1025 auto ruLink = getGBTLink(ruDecode.links[linkIDinRU]);
1026 auto& ruLinkStat = ruLink->statistics;
1028 ruLinkStat.nPackets++;
1030#ifdef _RAW_READER_ERROR_CHECKS_
1031 if (RDHUtils::getPacketCounter(rdh) > ruLink->packetCounter + 1) {
1034 <<
" : FEEId:" <<
OUTHEX(RDHUtils::getFEEID(rdh), 4) <<
": jump from " <<
int(ruLink->packetCounter)
1035 <<
" to " <<
int(RDHUtils::getPacketCounter(rdh));
1039 ruLink->packetCounter = RDHUtils::getPacketCounter(rdh);
1041 int sizeAtEntry = outBuffer.
getSize();
1044 mDecodingStat.nPagesProcessed++;
1045 mDecodingStat.nBytesProcessed += RDHUtils::getMemorySize(rdh);
1046 raw += RDHUtils::getHeaderSize(rdh);
1051#ifdef _RAW_READER_ERROR_CHECKS_
1057 if (!gbtH->isDataHeader()) {
1059 LOG(error) <<
"FEEId:" <<
OUTHEX(RDHUtils::getFEEID(rdh), 4) <<
" GBT payload header was expected, abort page decoding";
1067 if (gbtH->packetIdx != RDHUtils::getPageCounter(rdh)) {
1068 LOG(error) <<
"FEEId:" <<
OUTHEX(RDHUtils::getFEEID(rdh), 4) <<
" Different GBT header " << gbtH->packetIdx
1069 <<
" and RDH page " << RDHUtils::getPageCounter(rdh) <<
" counters";
1074 if (ruLink->lanesActive == ruLink->lanesStop) {
1075 if (RDHUtils::getPageCounter(rdh)) {
1076 LOG(error) <<
"FEEId:" <<
OUTHEX(RDHUtils::getFEEID(rdh), 4) <<
" Non-0 page counter (" << RDHUtils::getPageCounter(rdh) <<
") while all lanes were stopped";
1082 ruLink->lanesActive = gbtH->activeLanes;
1084 if (!RDHUtils::getPageCounter(rdh)) {
1085 ruLink->lanesStop = 0;
1086 ruLink->lanesWithData = 0;
1093 outBuffer.
addFast(
reinterpret_cast<const uint8_t*
>(rdh), RDHUtils::getHeaderSize(rdh));
1095 outBuffer.
addFast(
reinterpret_cast<const uint8_t*
>(gbtH), mGBTWordSize);
1103 printf(
"W%4d |", iw);
1104 gbtD->printX(mPadding128);
1106 if (gbtD->isDataTrailer()) {
1111 int cableHW = gbtD->getCableID();
1112 int cableSW = mMAP.cableHW2SW(ruInfo->ruType, cableHW);
1114 outBuffer.
addFast(
reinterpret_cast<const uint8_t*
>(gbtD), mGBTWordSize);
1116#ifdef _RAW_READER_ERROR_CHECKS_
1117 int cableHWPos = mMAP.cableHW2Pos(ruInfo->ruType, cableHW);
1118 ruLink->lanesWithData |= 0x1 << cableHWPos;
1119 if (ruLink->lanesStop & (0x1 << cableHWPos)) {
1121 LOG(error) <<
"FEEId:" <<
OUTHEX(RDHUtils::getFEEID(rdh), 4) <<
" Data received for stopped lane " << cableHW <<
" (sw:" << cableSW <<
")";
1129#ifdef _RAW_READER_ERROR_CHECKS_
1135 if (!gbtT->isDataTrailer()) {
1137 LOG(error) <<
"FEEId:" <<
OUTHEX(RDHUtils::getFEEID(rdh), 4) <<
" GBT payload trailer was expected, abort page decoding at NW" <<
nGBTWords;
1145 ruLink->lanesTimeOut |= gbtT->lanesTimeout;
1146 ruLink->lanesStop |= gbtT->lanesStops;
1149 outBuffer.
addFast(
reinterpret_cast<const uint8_t*
>(gbtT), mGBTWordSize);
1157 if (!RDHUtils::getOffsetToNext(rdh)) {
1161 raw = ((uint8_t*)rdh) + RDHUtils::getOffsetToNext(rdh);
1164 if (!isSameRUandTrigger(rdh, rdhN)) {
1166#ifdef _RAW_READER_ERROR_CHECKS_
1168 if (ruLink->lanesActive != ruLink->lanesStop &&
nGBTWords) {
1170 std::bitset<32>
active(ruLink->lanesActive), stopped(ruLink->lanesStop);
1171 LOG(error) <<
"FEEId:" <<
OUTHEX(RDHUtils::getFEEID(rdh), 4) <<
" end of FEE data but not all lanes received stop"
1172 <<
"| active: " <<
active <<
" stopped: " << stopped;
1179 if ((~ruLink->lanesWithData & ruLink->lanesActive) != ruLink->lanesTimeOut &&
nGBTWords) {
1180 std::bitset<32> withData(ruLink->lanesWithData),
active(ruLink->lanesActive), timeOut(ruLink->lanesTimeOut);
1181 LOG(error) <<
"FEEId:" <<
OUTHEX(RDHUtils::getFEEID(rdh), 4) <<
" Lanes not in time-out but not sending data"
1182 <<
"| with data: " << withData <<
" active: " <<
active <<
" timeOut: " << timeOut;
1188 ruLinkStat.packetStates[gbtT->getPacketState()]++;
1193#ifdef _RAW_READER_ERROR_CHECKS_
1195 if (RDHUtils::getPageCounter(rdhN) != RDHUtils::getPageCounter(rdh) + 1) {
1196 LOG(error) <<
"FEEId:" <<
OUTHEX(RDHUtils::getFEEID(rdh), 4) <<
" Discontinuity in the RDH page counter of the same RU trigger: old "
1197 << RDHUtils::getPageCounter(rdh) <<
" new: " << RDHUtils::getPageCounter(rdhN);
1207#ifdef _RAW_READER_ERROR_CHECKS_
1220 if (RDHUtils::getPageCounter(rdhNew) == 0 || RDHUtils::getFEEID(rdhNew) != RDHUtils::getFEEID(rdhOld) ||
1221 RDHUtils::getTriggerIR(rdhNew) != RDHUtils::getTriggerIR(rdhOld) ||
1222 RDHUtils::getHeartBeatIR(rdhNew) != RDHUtils::getHeartBeatIR(rdhOld) ||
1223 !(RDHUtils::getTriggerType(rdhNew) & RDHUtils::getTriggerType(rdhOld))) {
1238 for (
int icab = 0; icab < decData.
ruInfo->
nCables; icab++) {
1239 auto& cableData = decData.
cableData[icab];
1242#ifdef _RAW_READER_ERROR_CHECKS_
1243 auto& ruLinkStat = getGBTLink(decData.
links[decData.
cableLinkID[icab]])->statistics;
1247 if (cableData.current(
h) && !mCoder.isChipHeaderOrEmpty(
h)) {
1249 <<
" data does not start with ChipHeader or ChipEmpty";
1255 auto ri = decData.
ruInfo;
1256 auto chIdGetter = [
this, cabHW, ri](
int cid) {
1257 return this->mMAP.getGlobalChipID(cid, cabHW, *ri);
1259 std::vector<uint16_t> dummyStat;
1260 while ((
res = mCoder.decodeChip(*chipData, cableData, dummyStat, chIdGetter))) {
1262#ifdef _RAW_READER_ERROR_CHECKS_
1264 if (mMAP.getName() ==
"ITS" && decData.
ruInfo->
ruType == 0) {
1265 if (chipData->getChipID() != icab) {
1267 <<
" shipped chip ID= " << chipData->getChipID();
1275 chipData->setInteractionRecord(mInteractionRecord);
1276 chipData->setTrigger(mTrigger);
1277 mDecodingStat.nNonEmptyChips++;
1278 mDecodingStat.nHitsDecoded += chipData->getData().size();
1297 if (mCurRUDecodeID >= 0) {
1298 for (; mCurRUDecodeID < mNRUs; mCurRUDecodeID++) {
1299 auto& ru = mRUDecodeVec[mCurRUDecodeID];
1300 if (ru.lastChipChecked < ru.nChipsFired) {
1301 chipData.
swap(ru.chipsData[ru.lastChipChecked++]);
1309 if (!mDecodeNextAuto) {
1313 if (mMinTriggersCached < 2) {
1314 cacheLinksData(mRawBuffer);
1316 if (mMinTriggersCached < 1 || !decodeNextTrigger()) {
1317 mCurRUDecodeID = -1;
1320 return getNextChipData(chipData);
1330 LOG(info) <<
"opening raw data input file " <<
filename;
1331 mIOFile.open(
filename.c_str(), std::ifstream::binary);
1332 assert(mIOFile.good());
1334 mRawBuffer.expand(RawBufferSize);
1343 RawBufferSize > 3 * RawBufferMargin,
1344 "raw buffer size is too small");
1349 if (
buffer.getUnusedSize() > RawBufferMargin) {
1354 mIOFile.read(
reinterpret_cast<char*
>(
ptr),
n);
1355 return mIOFile.gcount();
1368 return &getGBTLink(mRUDecodeVec[mRUEntry[idSW]].links[ruLink])->statistics;
1375 int idsw = mMAP.FEEId2RUSW(idHW);
1376 assert(idsw != 0xffff);
1377 return getGBTLinkDecodingStatSW(idsw, ruLink);
1411 return mRUEntry[ruSW] < 0 ? nullptr : &mRUDecodeVec[mRUEntry[ruSW]];
1417 assert(ruSW < mMAP.getNRUs());
1418 if (mRUEntry[ruSW] < 0) {
1419 mRUEntry[ruSW] = mNRUs++;
1420 mRUDecodeVec[mRUEntry[ruSW]].ruInfo = mMAP.getRUInfoSW(ruSW);
1421 mRUDecodeVec[mRUEntry[ruSW]].chipsData.resize(mMAP.getNChipsOnRUType(mMAP.getRUInfoSW(ruSW)->ruType));
1422 LOG(info) <<
"Defining container for RU " << ruSW <<
" at slot " << mRUEntry[ruSW];
1424 return mRUDecodeVec[mRUEntry[ruSW]];
1430 int sz = mGBTLinks.size();
1431 mGBTLinks.emplace_back();
1440 std::ifstream mIOFile;
1444 int mCurRUDecodeID = -1;
1448 std::array<
RUDecodeData, Mapping::getNRUs()> mRUDecodeVec;
1449 std::array<
int, Mapping::getNRUs()> mRUEntry;
1450 std::vector<GBTLink> mGBTLinks;
1456 int mMinTriggersCached = 0;
1462 TStopwatch mSWCache;
1464 static constexpr int RawBufferMargin = 5000000;
1465 static constexpr int RawBufferSize = 10000000 + 2 * RawBufferMargin;
1466 bool mPadding128 =
true;
1467 bool mImposeMaxPage =
true;
1474template <
class Mapping>
1475constexpr int RawPixelReader<Mapping>::RawBufferMargin;
1477template <
class Mapping>
1478constexpr int RawPixelReader<Mapping>::RawBufferSize;
class for the ALPIDE data decoding/encoding
Definition of the 32 Central Trigger System (CTS) Trigger Types defined in https://twiki....
Declarations of helper classes for the ITS/MFT raw data decoding.
Declaration of class for continuos buffer of ALPIDE data.
Declaration of class for scatter-gather buffer.
Transient data classes for single pixel and set of pixels from current chip.
Abstract class for Alpide data reader class.
Declaration of the Readout Unite decoder class.
Checks validity of hardware address (HW) and transform it to digit AbsId index.
Class for time synchronization of RawReader instances.
void setChipID(uint16_t id)
void swap(ChipPixelData &other)
uint16_t getChipID() const
const std::vector< PixelData > & getData() const
void ensureFreeCapacity(size_t n)
fill n bytes with given symbol w/o checking for the size
void shrinkToSize(size_t sz)
direct const access to value at a given slot, w/o checking for overflow
size_t getSize() const
get offset of the current ptr from the head
void clear()
get unused size
void addFast(const uint8_t *ptr, size_t n)
add new byte to the buffer w/o checking for the size
void fillFast(const uint8_t c, size_t n)
add n bytes to the buffer w/o checking for the size
PixelReader class for the ITSMFT.
o2::InteractionRecord mInteractionRecord
int digits2raw(const std::vector< o2::itsmft::Digit > &digiVec, int from, int ndig, const o2::InteractionRecord &bcData, uint8_t ruSWMin=0, uint8_t ruSWMax=0xff)
================================== Encoding methods ========================
void setMinTriggersToCache(int n)
set min number of triggers to cache per frame
const GBTLinkDecodingStat * getGBTLinkDecodingStatHW(uint16_t idHW, int ruLink) const
bool getNextChipData(ChipPixelData &chipData) override
void imposeMaxPage(bool v)
CRU pages are of max size of 8KB.
PayLoadCont & getRawBuffer()
int skimNextRUData(PayLoadCont &outBuffer)
~RawPixelReader() override
uint8_t * decodeRUData(uint8_t *raw, RUDecodeData &ruDecData, bool &aborted)
int decodeNextRUData(RUDecodeData &ruDecData)
const GBTLinkDecodingStat * getGBTLinkDecodingStatSW(uint16_t idSW, int ruLink) const
int getMinTriggersToCache() const
const GBTLinkDecodingStat * getRUDecodingStatSW(uint16_t idSW, int ruLink=0) const
void openInput(const std::string filename)
int decodeNextTrigger() final
const std::array< int, Mapping::getNRUs()> & getRUEntries() const
bool isPadding128() const
do we interpred GBT words as padded to 128 bits?
GBTLink * getGBTLink(int i)
size_t cacheLinksData(PayLoadCont &buffer)
================================== Decoding methods ========================
uint8_t * skimPaddedRUData(uint8_t *raw, PayLoadCont &outBuffer, bool &aborted)
bool isMaxPageImposed() const
do we treat CRU pages as having max size?
const GBTLinkDecodingStat * getRUDecodingStatHW(uint16_t idHW, int ruLink=0) const
const RawDecodingStat & getDecodingStat() const
int getGBTWordSize() const
assumed GBT word size (accounting for eventual padding)
void convertEmptyChips(int fromChip, int uptoChip)
void convertChip(o2::itsmft::ChipPixelData &chipData)
void clear(bool resetStat=true)
bool isSameRUandTrigger(const o2::header::RAWDataHeader *rdhOld, const o2::header::RAWDataHeader *rdhNew) const
const RUDecodeData * getCurrRUDecodeData() const
int decodeAlpideData(RUDecodeData &decData)
size_t loadInput(PayLoadCont &buffer)
int flushSuperPages(int maxPages, PayLoadCont &sink, bool unusedToHead=true)
bool findNextRDH(PayLoadCont &buffer)
const std::array< RUDecodeData, Mapping::getNRUs()> & getRUDecodeVec() const
void setPadding128(bool v)
impose padding model for GBT words
RUDecodeData & getCreateRUDecode(int ruSW)
const RUDecodeData * getRUDecode(int ruSW) const
ChipPixelData * getNextChipData(std::vector< ChipPixelData > &chipDataVec) override
const GBTLink * getGBTLink(int i) const
TGeoManager * readFromFile(std::string filename)
GLint GLint GLsizei GLint GLenum GLenum const void * pixels
constexpr int GBTPaddedWordLength
constexpr int MaxGBTPacketBytes
constexpr int GBTWordLength
constexpr int NCRUPagesPerSuperpage
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
uint16_t bc
bunch crossing ID of interaction
const ChipOnRUInfo * chOnRU
Statistics for per-link decoding.
@ ErrPageCounterDiscontinuity
@ ErrNonZeroPageAfterStop
support for the GBT single link data
const uint8_t * getW8() const
void printX(bool padded=true, std::string com="") const
uint64_t packetDone
56:63 reserved
std::vector< o2::itsmft::ChipPixelData > chipsData
std::array< int, MaxLinksPerRU > links
std::array< PayLoadCont, MaxCablesPerRU > cableData
static constexpr int MaxLinksPerRU
std::array< uint8_t, MaxCablesPerRU > cableHWID
std::array< uint8_t, MaxCablesPerRU > cableLinkID
std::array< int, NErrorsDefined > errorCounts
static constexpr std::array< std::string_view, NErrorsDefined > ErrNames
uint64_t nTriggersProcessed
void print(bool skipNoErr=true) const
RawDecodingStat()=default
ClassDefNV(RawDecodingStat, 2)
static void setLinkID(H &rdh, uint8_t v, NOTPTR(H))
static void setDetectorField(H &rdh, uint32_t v, NOTPTR(H))
static void setTriggerType(H &rdh, uint32_t v, NOTPTR(H))
static void setPageCounter(H &rdh, uint16_t v, NOTPTR(H))
static void setMemorySize(H &rdh, uint16_t v, NOTPTR(H))
static void printRDH(const RDHv4 &rdh)
static bool checkRDH(const RDHv4 &rdh, bool verbose=true, bool checkZeros=false)
static void setTriggerBC(RDHv4 &rdh, uint16_t v)
static void setTriggerOrbit(RDHv4 &rdh, uint32_t v)
static void setHeartBeatOrbit(RDHv4 &rdh, uint32_t v)
static void setFEEID(RDHv4 &rdh, uint16_t v)
static void setOffsetToNext(H &rdh, uint16_t v, NOTPTR(H))
static void setStop(H &rdh, uint8_t v, NOTPTR(H))
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"
o2::InteractionRecord ir(0, 0)