35template <
class Mapping>
41 mTimerFetchData.Stop();
48template <
class Mapping>
51 double cpu = 0, real = 0;
52 auto& tmrS =
const_cast<TStopwatch&
>(mTimerTFStart);
53 LOGP(info,
"{} Timing Start TF: CPU = {:.3e} Real = {:.3e} in {} slots", mSelfName, tmrS.CpuTime(), tmrS.RealTime(), tmrS.Counter() - 1);
54 cpu += tmrS.CpuTime();
55 real += tmrS.RealTime();
56 auto& tmrD =
const_cast<TStopwatch&
>(mTimerDecode);
57 LOGP(info,
"{} Timing Decode: CPU = {:.3e} Real = {:.3e} in {} slots", mSelfName, tmrD.CpuTime(), tmrD.RealTime(), tmrD.Counter() - 1);
58 cpu += tmrD.CpuTime();
59 real += tmrD.RealTime();
60 auto& tmrF =
const_cast<TStopwatch&
>(mTimerFetchData);
61 LOGP(info,
"{} Timing FetchData: CPU = {:.3e} Real = {:.3e} in {} slots", mSelfName, tmrF.CpuTime(), tmrF.RealTime(), tmrF.Counter() - 1);
62 cpu += tmrF.CpuTime();
63 real += tmrF.RealTime();
64 LOGP(info,
"{} Timing Total: CPU = {:.3e} Real = {:.3e} in {} slots in {} mode", mSelfName,
cpu, real, tmrS.Counter() - 1,
65 mDecodeNextAuto ?
"AutoDecode" :
"ExternalCall");
67 LOGP(info,
"{} decoded {} hits in {} non-empty chips in {} ROFs with {} threads, {} external triggers", mSelfName, mNPixelsFired, mNChipsFired, mROFCounter, mNThreads, mNExtTriggers);
69 LOG(info) <<
"GBT Links decoding statistics" << (skipNoErr ?
" (only links with errors are reported)" :
"");
70 for (
auto& lnk : mGBTLinks) {
71 lnk.statistics.print(skipNoErr);
72 lnk.chipStat.print(skipNoErr);
79template <
class Mapping>
84 mInteractionRecord.clear();
85 if (mROFRampUpStage && mSkipRampUpData) {
88 int nru = mRUDecodeVec.size();
89 int prevNTrig = mExtTriggers.size();
92#pragma omp parallel for schedule(dynamic) num_threads(mNThreads)
94 for (
int iru = 0; iru < nru; iru++) {
95 collectROFCableData(iru);
100 if (!doIRMajorityPoll()) {
105#pragma omp parallel for schedule(dynamic) num_threads(mNThreads) reduction(+ : mNChipsFiredROF, mNPixelsFiredROF)
107 for (
int iru = 0; iru < nru; iru++) {
108 auto& ru = mRUDecodeVec[iru];
109 if (ru.nNonEmptyLinks) {
110 ru.ROFRampUpStage = mROFRampUpStage;
111 mNPixelsFiredROF += ru.decodeROF(mMAP, mInteractionRecord, mVerifyDecoder);
112 mNChipsFiredROF += ru.nChipsFired;
114 ru.clearSeenChipIDs();
118 if (mNChipsFiredROF || (mAlloEmptyROFs && mNLinksDone < mNLinksInTF)) {
119 mTrigger = mLinkForTriggers ? mLinkForTriggers->trigger : 0;
120 mNChipsFired += mNChipsFiredROF;
121 mNPixelsFired += mNPixelsFiredROF;
123 mLastReadChipID = -1;
127 }
while (mNLinksDone < mNLinksInTF);
128 mNExtTriggers += mExtTriggers.size() - prevNTrig;
129 ensureChipOrdering();
132 return (mNLinksDone < mNLinksInTF) ? mNChipsFiredROF : -1;
137template <
class Mapping>
140 mTimerTFStart.Start(
false);
141 for (
auto&
link : mGBTLinks) {
142 link.lastRDH =
nullptr;
143 link.clear(
false,
true);
145 for (
auto& ru : mRUDecodeVec) {
148 ru.linkHBFToDump.clear();
153 mExtTriggers.clear();
154 mTimerTFStart.Stop();
159template <
class Mapping>
162 auto& ru = mRUDecodeVec[iru];
165 auto*
link = getGBTLink(ru.links[il]);
167 auto res =
link->collectROFCableData(mMAP);
179template <
class Mapping>
183 mInteractionRecord.clear();
184 for (
auto&
link : mGBTLinks) {
188 if (mVerbosity >= GBTLink::Verbosity::VerboseHeaders) {
189 LOGP(info,
"doIRMajorityPoll: {} contributes to poll {}",
link.describe(),
link.ir.asString());
193 if (mVerbosity >= GBTLink::Verbosity::VerboseHeaders) {
194 LOGP(info,
"doIRMajorityPoll: {} DONE, status = {}",
link.describe(),
int(
link.status));
200 if (mNLinksDone == mNLinksInTF) {
201 if (mVerbosity >= GBTLink::Verbosity::VerboseHeaders) {
202 LOGP(info,
"doIRMajorityPoll: All {} links registered in TF are done", mNLinksInTF);
207 for (
const auto& entIR : mIRPoll) {
208 if (entIR.second > majIR) {
209 majIR = entIR.second;
210 mInteractionRecord = entIR.first;
213 if (mInteractionRecord.isDummy()) {
214 if (mVerbosity >= GBTLink::Verbosity::VerboseHeaders) {
215 LOG(info) <<
"doIRMajorityPoll: did not find any valid IR";
219 if (mVerbosity >= GBTLink::Verbosity::VerboseHeaders) {
220 LOG(info) <<
"doIRMajorityPoll: " << mInteractionRecord.asString() <<
" majority = " << majIR <<
" for " << mNLinksInTF <<
" links seen, LinksDone = " << mNLinksDone;
227template <
class Mapping>
230 constexpr uint32_t ROF_RAMP_FLAG = 0x1 << 4;
231 constexpr uint32_t LINK_RECOVERY_FLAG = 0x1 << 5;
233 mCurRUDecodeID = NORUDECODED;
234 auto nLinks = mGBTLinks.size();
238 if (mInputFilter.empty()) {
245 static size_t contDeadBeef = 0;
248 const auto dh = o2::framework::DataRefUtils::getHeader<o2::header::DataHeader*>(
ref);
250 if (payloadSize == 0) {
252 if (++contDeadBeef <= maxWarn) {
253 LOGP(warn,
"Found input [{}/{}/{:#x}] TF#{} 1st_orbit:{} Payload {} : assuming no payload for all links in this TF{}",
254 dh->dataOrigin.str, dh->dataDescription.str, dh->subSpecification, dh->tfCounter, dh->firstTForbit, payloadSize,
255 contDeadBeef == maxWarn ? fmt::format(
". {} such inputs in row received, stopping reporting", contDeadBeef) :
"");
262 mROFRampUpStage =
false;
265 static size_t cntParserFailures = 0;
266 parser.setExtFailureCounter(&cntParserFailures);
268 uint32_t currSSpec = 0xffffffff;
271 for (
auto it = parser.begin(); it != parser.end(); ++it) {
272 auto const* dh = it.o2DataHeader();
273 auto& lnkref = mSubsSpec2LinkID[dh->subSpecification];
274 const auto& rdh = *
reinterpret_cast<const header::RDHAny*
>(it.raw());
275 const auto feeID = RDHUtils::getFEEID(rdh);
276 mMAP.expandFEEId(feeID, lr, dummy, dummy);
278 if (lnkref.entry == -1) {
279 lnkref.entry =
int(mGBTLinks.size());
280 auto& lnk = mGBTLinks.emplace_back(RDHUtils::getCRUID(rdh), feeID, RDHUtils::getEndPointID(rdh), RDHUtils::getLinkID(rdh), lnkref.entry);
281 lnk.subSpec = dh->subSpecification;
283 getCreateRUDecode(mMAP.FEEId2RUSW(feeID));
285 lnk.alwaysParseTrigger = mAlwaysParseTrigger;
286 if (mVerbosity >= GBTLink::Verbosity::VerboseHeaders) {
287 LOG(info) << mSelfName <<
" registered new " << lnk.describe() <<
" RUSW=" <<
int(mMAP.FEEId2RUSW(lnk.feeID));
291 auto&
link = mGBTLinks[lnkref.entry];
292 if (currSSpec != dh->subSpecification) {
293 currSSpec = dh->subSpecification;
295 static bool errorDone =
false;
297 LOGP(error,
"{} was already registered, inform PDP on-call about error!!!",
link.describe());
304 auto detField = RDHUtils::getDetectorField(&rdh);
305 if (detField & ROF_RAMP_FLAG) {
306 mROFRampUpStage =
true;
310 link.rawData.clear();
312 link.accountLinkRecovery(RDHUtils::getHeartBeatIR(rdh));
316 link.cacheData(it.raw(), RDHUtils::getMemorySize(rdh));
322 if (mVerbosity >= GBTLink::Verbosity::VerboseHeaders) {
323 LOG(warn) << mSelfName <<
" New links appeared although the initialization was already done";
325 for (
auto& ru : mRUDecodeVec) {
331 std::sort(mRUDecodeVec.begin(), mRUDecodeVec.end(), [](
const RUDecodeData& ruA,
const RUDecodeData& ruB) ->
bool { return ruA.ruSWID < ruB.ruSWID; });
332 for (
auto i = 0;
i < mRUDecodeVec.size();
i++) {
333 mRUEntry[mRUDecodeVec[
i].ruSWID] =
i;
335 nLinks = mGBTLinks.size();
337 for (
int il = 0; il < nLinks; il++) {
338 auto&
link = mGBTLinks[il];
339 bool newLinkAdded = (
link.ruPtr ==
nullptr);
340 link.ruPtr = getRUDecode(mMAP.FEEId2RUSW(
link.feeID));
341 uint16_t lr, ruOnLr, linkInRU;
342 mMAP.expandFEEId(
link.feeID, lr, ruOnLr, linkInRU);
344 if (mVerbosity >= GBTLink::Verbosity::VerboseHeaders) {
345 LOGP(info,
"{} Attaching {} to RU#{:02} (stave {:02} of layer {})", mSelfName,
link.describe(),
int(mMAP.FEEId2RUSW(
link.feeID)), ruOnLr, lr);
348 link.idInRU = linkInRU;
349 link.ruPtr->links[linkInRU] = il;
350 link.ruPtr->nLinks++;
354 for (
auto&
link : mGBTLinks) {
356 link.extTrigVec = &mExtTriggers;
357 mLinkForTriggers = &
link;
365template <
class Mapping>
368 assert(ruSW < mMAP.getNRUs());
369 if (mRUEntry[ruSW] < 0) {
370 mRUEntry[ruSW] = mRUDecodeVec.size();
371 auto& ru = mRUDecodeVec.emplace_back();
373 ru.ruInfo = mMAP.getRUInfoSW(ruSW);
374 ru.chipsData.resize(mMAP.getNChipsOnRUType(ru.ruInfo->ruType));
375 ru.verbosity = mVerbosity;
376 if (mVerbosity >= GBTLink::Verbosity::VerboseHeaders) {
377 LOG(info) << mSelfName <<
" Defining container for RU " << ruSW <<
" at slot " << mRUEntry[ruSW];
380 return mRUDecodeVec[mRUEntry[ruSW]];
384template <
class Mapping>
388 for (; mCurRUDecodeID < mRUDecodeVec.size(); mCurRUDecodeID++) {
389 auto& ru = mRUDecodeVec[mCurRUDecodeID];
390 if (ru.lastChipChecked < ru.nChipsFired) {
391 auto& chipData = ru.chipsData[ru.lastChipChecked++];
393 if (mLastReadChipID >= chipData.getChipID()) {
394 if (!mROFRampUpStage) {
395 const int MaxErrLog = 2;
396 static int errLocCount = 0;
397 if (errLocCount < MaxErrLog) {
398 LOGP(warn,
"Wrong order/duplication: encountered chip {} after processing chip {}, skipping.",
399 chipData.getChipID(), mLastReadChipID, ++errLocCount, MaxErrLog);
404 mLastReadChipID = chipData.getChipID();
405 chipDataVec[mLastReadChipID].swap(chipData);
406 return &chipDataVec[mLastReadChipID];
410 if (!mDecodeNextAuto || decodeNextTrigger() < 0) {
413 return getNextChipData(chipDataVec);
417template <
class Mapping>
421 for (; mCurRUDecodeID < mRUDecodeVec.size(); mCurRUDecodeID++) {
422 auto& ru = mRUDecodeVec[mCurRUDecodeID];
423 if (ru.lastChipChecked < ru.nChipsFired) {
424 auto& ruchip = ru.chipsData[ru.lastChipChecked++];
425 assert(mLastReadChipID < chipData.
getChipID());
427 chipData.
swap(ruchip);
432 if (!mDecodeNextAuto || decodeNextTrigger() < 0) {
435 return getNextChipData(chipData);
442 mOrderedChipsPtr.clear();
444 if (mCurRUDecodeID < mRUDecodeVec.size()) {
445 for (; mCurRUDecodeID < mRUDecodeVec.size(); mCurRUDecodeID++) {
446 auto& ru = mRUDecodeVec[mCurRUDecodeID];
447 while (ru.lastChipChecked < ru.nChipsFired) {
448 mOrderedChipsPtr.push_back(&ru.chipsData[ru.lastChipChecked++]);
452 std::sort(mOrderedChipsPtr.begin(), mOrderedChipsPtr.end(), [](
const ChipPixelData*
a,
const ChipPixelData*
b) { return a->getChipID() > b->getChipID(); });
460 if (!mOrderedChipsPtr.empty()) {
461 auto chipData = *mOrderedChipsPtr.back();
462 assert(mLastReadChipID < chipData.getChipID());
463 mLastReadChipID = chipData.getChipID();
464 chipDataVec[mLastReadChipID].swap(chipData);
465 mOrderedChipsPtr.pop_back();
466 return &chipDataVec[mLastReadChipID];
469 if (!mDecodeNextAuto || decodeNextTrigger() < 0) {
472 return getNextChipData(chipDataVec);
479 if (!mOrderedChipsPtr.empty()) {
480 auto ruChip = *mOrderedChipsPtr.back();
481 assert(mLastReadChipID < ruChip.getChipID());
482 mLastReadChipID = ruChip.getChipID();
483 ruChip.swap(chipData);
484 mOrderedChipsPtr.pop_back();
488 if (!mDecodeNextAuto || decodeNextTrigger() < 0) {
491 return getNextChipData(chipData);
495template <
class Mapping>
499 for (
auto&
link : mGBTLinks) {
505template <
class Mapping>
509 mNThreads =
n > 0 ?
n : 1;
511 LOG(warning) << mSelfName <<
" Multithreading is not supported, imposing single thread";
517template <
class Mapping>
521 for (
auto& lnk : mGBTLinks) {
522 lnk.clear(
true, resetRaw);
524 mNChipsFiredROF = mNPixelsFiredROF = 0;
525 mNChipsFired = mNPixelsFired = mNExtTriggers = 0;
529template <
class Mapping>
533 bool dumpFullTF =
false;
534 for (
auto& ru : mRUDecodeVec) {
535 if (ru.linkHBFToDump.size()) {
536 if (
dump ==
int(GBTLink::RawDataDumps::DUMP_TF)) {
540 for (
auto it : ru.linkHBFToDump) {
541 if (
dump ==
int(GBTLink::RawDataDumps::DUMP_HBF)) {
542 const auto& lnk = mGBTLinks[mSubsSpec2LinkID[it.first >> 32].entry];
543 int entry = it.first & 0xffffffff;
544 bool allHBFs =
false;
546 if (
entry >= lnk.rawData.getNPieces()) {
549 fnm = fmt::format(
"{}{}rawdump_{}_run{}_tf_orb{}_full_feeID{:#06x}.raw", mRawDumpDirectory, mRawDumpDirectory.empty() ?
"" :
"/",
552 fnm = fmt::format(
"{}{}rawdump_{}_run{}_tf_orb{}_hbf_orb{}_feeID{:#06x}.raw", mRawDumpDirectory, mRawDumpDirectory.empty() ?
"" :
"/",
555 std::ofstream ostrm(fnm, std::ios::binary);
557 LOG(error) <<
"failed to open " << fnm;
560 while (
entry < lnk.rawData.getNPieces()) {
561 const auto* piece = lnk.rawData.getPiece(
entry);
562 if (!allHBFs && RDHUtils::getHeartBeatOrbit(
reinterpret_cast<const RDH*
>(piece->data)) != it.second) {
565 ostrm.write(
reinterpret_cast<const char*
>(piece->data), piece->size);
566 outSize += piece->size;
569 LOG(info) <<
"produced " << std::filesystem::current_path().c_str() <<
'/' << fnm;
575 std::string fnm = fmt::format(
"rawdump_{}_run{}_tf_orb{}_full.raw",
577 std::ofstream ostrm(fnm, std::ios::binary);
579 LOG(error) <<
"failed to open " << fnm;
582 for (
const auto& lnk : mGBTLinks) {
583 for (
size_t i = 0;
i < lnk.rawData.getNPieces();
i++) {
584 const auto* piece = lnk.rawData.getPiece(
i);
585 ostrm.write(
reinterpret_cast<const char*
>(piece->data), piece->size);
586 outSize += piece->size;
589 LOG(info) <<
"produced " << std::filesystem::current_path().c_str() <<
'/' << fnm;
596template <
class Mapping>
599 mTimerTFStart.Reset();
600 mTimerDecode.Reset();
601 mTimerFetchData.Reset();
602 for (
auto& ru : mRUDecodeVec) {
603 for (
auto& cab : ru.cableData) {
607 for (
auto&
link : mGBTLinks) {
608 link.rofJumpWasSeen =
false;
header::DataOrigin origin
A raw page parser for DPL input.
void setupLinks(o2::itsmft::MC2RawEncoder< MAP > &m2r, std::string_view outDir, std::string_view outPrefix, std::string_view fileFor)
Definition of the Alpide pixel reader for raw data processing.
static const VerbosityConfig & Instance()
The parser handles transparently input in the format of raw pages.
static void setCheckIncompleteHBF(bool v)
void swap(ChipPixelData &other)
uint16_t getChipID() const
void ensureChipOrdering()
void startNewTF(o2::framework::InputRecord &inputs)
size_t produceRawDataDumps(int dump, const o2::framework::TimingInfo &tinfo)
void printReport(bool decstat=true, bool skipNoErr=true) const
bool getNextChipData(ChipPixelData &chipData) final
void clearStat(bool resetRaw=false)
int decodeNextTrigger() final
void collectROFCableData(int iru)
void dump(const std::string what, DPMAP m, int verbose)
GLboolean GLboolean GLboolean b
GLboolean GLboolean GLboolean GLboolean a
constexpr o2::header::DataDescription gDataDescriptionInvalid
constexpr o2::header::DataOrigin gDataOriginInvalid
constexpr o2::header::DataDescription gDataDescriptionRawData
uint8_t itsSharedClusterMap uint8_t
Defining ITS Vertex explicitly as messageable.
constexpr int GBTPaddedWordLength
constexpr int GBTWordLength
static o2::header::DataHeader::PayloadSizeType getPayloadSize(const DataRef &ref)
support for the GBT single link data
static constexpr int MaxCablesPerRU
static constexpr int MaxLinksPerRU
static std::string concat_string(Ts const &... ts)
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"