35template <
class Mapping>
41 mTimerFetchData.Stop();
49template <
class Mapping>
52 double cpu = 0, real = 0;
53 auto& tmrS =
const_cast<TStopwatch&
>(mTimerTFStart);
54 LOGP(info,
"{} Timing Start TF: CPU = {:.3e} Real = {:.3e} in {} slots", mSelfName, tmrS.CpuTime(), tmrS.RealTime(), tmrS.Counter() - 1);
55 cpu += tmrS.CpuTime();
56 real += tmrS.RealTime();
57 auto& tmrD =
const_cast<TStopwatch&
>(mTimerDecode);
58 LOGP(info,
"{} Timing Decode: CPU = {:.3e} Real = {:.3e} in {} slots", mSelfName, tmrD.CpuTime(), tmrD.RealTime(), tmrD.Counter() - 1);
59 cpu += tmrD.CpuTime();
60 real += tmrD.RealTime();
61 auto& tmrF =
const_cast<TStopwatch&
>(mTimerFetchData);
62 LOGP(info,
"{} Timing FetchData: CPU = {:.3e} Real = {:.3e} in {} slots", mSelfName, tmrF.CpuTime(), tmrF.RealTime(), tmrF.Counter() - 1);
63 cpu += tmrF.CpuTime();
64 real += tmrF.RealTime();
65 LOGP(info,
"{} Timing Total: CPU = {:.3e} Real = {:.3e} in {} slots in {} mode", mSelfName,
cpu, real, tmrS.Counter() - 1,
66 mDecodeNextAuto ?
"AutoDecode" :
"ExternalCall");
68 LOGP(info,
"{} decoded {} hits in {} non-empty chips in {} ROFs with {} threads, {} external triggers", mSelfName, mNPixelsFired, mNChipsFired, mROFCounter, mNThreads, mNExtTriggers);
70 LOG(info) <<
"GBT Links decoding statistics" << (skipNoErr ?
" (only links with errors are reported)" :
"");
71 for (
auto& lnk : mGBTLinks) {
72 lnk.statistics.print(skipNoErr);
73 lnk.chipStat.print(skipNoErr);
80template <
class Mapping>
85 mInteractionRecord.clear();
86 if (mROFRampUpStage && mSkipRampUpData) {
89 int nru = mRUDecodeVec.size();
90 int prevNTrig = mExtTriggers.size();
93#pragma omp parallel for schedule(dynamic) num_threads(mNThreads)
95 for (
int iru = 0; iru < nru; iru++) {
96 collectROFCableData(iru);
101 if (!doIRMajorityPoll()) {
106#pragma omp parallel for schedule(dynamic) num_threads(mNThreads) reduction(+ : mNChipsFiredROF, mNPixelsFiredROF)
108 for (
int iru = 0; iru < nru; iru++) {
109 auto& ru = mRUDecodeVec[iru];
110 if (ru.nNonEmptyLinks) {
111 ru.ROFRampUpStage = mROFRampUpStage;
112 mNPixelsFiredROF += ru.decodeROF(mMAP, mInteractionRecord, mVerifyDecoder);
113 mNChipsFiredROF += ru.nChipsFired;
115 ru.clearSeenChipIDs();
119 if (mNChipsFiredROF || (mAlloEmptyROFs && mNLinksDone < mNLinksInTF)) {
120 mTrigger = mLinkForTriggers ? mLinkForTriggers->trigger : 0;
121 mNChipsFired += mNChipsFiredROF;
122 mNPixelsFired += mNPixelsFiredROF;
124 mLastReadChipID = -1;
128 }
while (mNLinksDone < mNLinksInTF);
129 mNExtTriggers += mExtTriggers.size() - prevNTrig;
130 ensureChipOrdering();
133 return (mNLinksDone < mNLinksInTF) ? mNChipsFiredROF : -1;
138template <
class Mapping>
141 mTimerTFStart.Start(
false);
142 for (
auto&
link : mGBTLinks) {
143 link.lastRDH =
nullptr;
144 link.clear(
false,
true);
146 for (
auto& ru : mRUDecodeVec) {
149 ru.linkHBFToDump.clear();
154 mExtTriggers.clear();
155 mTimerTFStart.Stop();
160template <
class Mapping>
163 auto& ru = mRUDecodeVec[iru];
166 auto*
link = getGBTLink(ru.links[il]);
168 auto res =
link->collectROFCableData(mMAP);
180template <
class Mapping>
184 mInteractionRecord.clear();
185 for (
auto&
link : mGBTLinks) {
189 if (mVerbosity >= GBTLink::Verbosity::VerboseHeaders) {
190 LOGP(info,
"doIRMajorityPoll: {} contributes to poll {}",
link.describe(),
link.ir.asString());
194 if (mVerbosity >= GBTLink::Verbosity::VerboseHeaders) {
195 LOGP(info,
"doIRMajorityPoll: {} DONE, status = {}",
link.describe(),
int(
link.status));
201 if (mNLinksDone == mNLinksInTF) {
202 if (mVerbosity >= GBTLink::Verbosity::VerboseHeaders) {
203 LOGP(info,
"doIRMajorityPoll: All {} links registered in TF are done", mNLinksInTF);
208 for (
const auto& entIR : mIRPoll) {
209 if (entIR.second > majIR) {
210 majIR = entIR.second;
211 mInteractionRecord = entIR.first;
214 if (mInteractionRecord.isDummy()) {
215 if (mVerbosity >= GBTLink::Verbosity::VerboseHeaders) {
216 LOG(info) <<
"doIRMajorityPoll: did not find any valid IR";
220 if (mVerbosity >= GBTLink::Verbosity::VerboseHeaders) {
221 LOG(info) <<
"doIRMajorityPoll: " << mInteractionRecord.asString() <<
" majority = " << majIR <<
" for " << mNLinksInTF <<
" links seen, LinksDone = " << mNLinksDone;
228template <
class Mapping>
231 constexpr uint32_t ROF_RAMP_FLAG = 0x1 << 4;
232 constexpr uint32_t LINK_RECOVERY_FLAG = 0x1 << 5;
234 mCurRUDecodeID = NORUDECODED;
235 auto nLinks = mGBTLinks.size();
241 static size_t contDeadBeef = 0;
244 const auto dh = o2::framework::DataRefUtils::getHeader<o2::header::DataHeader*>(
ref);
246 if (payloadSize == 0) {
248 if (++contDeadBeef <= maxWarn) {
249 LOGP(warn,
"Found input [{}/{}/{:#x}] TF#{} 1st_orbit:{} Payload {} : assuming no payload for all links in this TF{}",
250 dh->dataOrigin.str, dh->dataDescription.str, dh->subSpecification, dh->tfCounter, dh->firstTForbit, payloadSize,
251 contDeadBeef == maxWarn ? fmt::format(
". {} such inputs in row received, stopping reporting", contDeadBeef) :
"");
258 mROFRampUpStage =
false;
261 static size_t cntParserFailures = 0;
262 parser.setExtFailureCounter(&cntParserFailures);
264 uint32_t currSSpec = 0xffffffff;
267 for (
auto it = parser.begin(); it != parser.end(); ++it) {
268 auto const* dh = it.o2DataHeader();
269 auto& lnkref = mSubsSpec2LinkID[dh->subSpecification];
270 const auto& rdh = *
reinterpret_cast<const header::RDHAny*
>(it.raw());
271 const auto feeID = RDHUtils::getFEEID(rdh);
272 mMAP.expandFEEId(feeID, lr, dummy, dummy);
274 if (lnkref.entry == -1) {
275 lnkref.entry =
int(mGBTLinks.size());
276 auto& lnk = mGBTLinks.emplace_back(RDHUtils::getCRUID(rdh), feeID, RDHUtils::getEndPointID(rdh), RDHUtils::getLinkID(rdh), lnkref.entry);
277 lnk.subSpec = dh->subSpecification;
279 getCreateRUDecode(mMAP.FEEId2RUSW(feeID));
281 lnk.alwaysParseTrigger = mAlwaysParseTrigger;
282 if (mVerbosity >= GBTLink::Verbosity::VerboseHeaders) {
283 LOG(info) << mSelfName <<
" registered new " << lnk.describe() <<
" RUSW=" <<
int(mMAP.FEEId2RUSW(lnk.feeID));
287 auto&
link = mGBTLinks[lnkref.entry];
288 if (currSSpec != dh->subSpecification) {
289 currSSpec = dh->subSpecification;
291 static bool errorDone =
false;
293 LOGP(error,
"{} was already registered, inform PDP on-call about error!!!",
link.describe());
300 auto detField = RDHUtils::getDetectorField(&rdh);
301 if (detField & ROF_RAMP_FLAG) {
302 mROFRampUpStage =
true;
306 link.rawData.clear();
308 link.accountLinkRecovery(RDHUtils::getHeartBeatIR(rdh));
312 link.cacheData(it.raw(), RDHUtils::getMemorySize(rdh));
318 if (mVerbosity >= GBTLink::Verbosity::VerboseHeaders) {
319 LOG(warn) << mSelfName <<
" New links appeared although the initialization was already done";
321 for (
auto& ru : mRUDecodeVec) {
327 std::sort(mRUDecodeVec.begin(), mRUDecodeVec.end(), [](
const RUDecodeData& ruA,
const RUDecodeData& ruB) ->
bool { return ruA.ruSWID < ruB.ruSWID; });
328 for (
auto i = 0;
i < mRUDecodeVec.size();
i++) {
329 mRUEntry[mRUDecodeVec[
i].ruSWID] =
i;
331 nLinks = mGBTLinks.size();
333 for (
int il = 0; il < nLinks; il++) {
334 auto&
link = mGBTLinks[il];
335 bool newLinkAdded = (
link.ruPtr ==
nullptr);
336 link.ruPtr = getRUDecode(mMAP.FEEId2RUSW(
link.feeID));
337 uint16_t lr, ruOnLr, linkInRU;
338 mMAP.expandFEEId(
link.feeID, lr, ruOnLr, linkInRU);
340 if (mVerbosity >= GBTLink::Verbosity::VerboseHeaders) {
341 LOGP(info,
"{} Attaching {} to RU#{:02} (stave {:02} of layer {})", mSelfName,
link.describe(),
int(mMAP.FEEId2RUSW(
link.feeID)), ruOnLr, lr);
344 link.idInRU = linkInRU;
345 link.ruPtr->links[linkInRU] = il;
346 link.ruPtr->nLinks++;
350 for (
auto&
link : mGBTLinks) {
352 link.extTrigVec = &mExtTriggers;
353 mLinkForTriggers = &
link;
361template <
class Mapping>
364 assert(ruSW < mMAP.getNRUs());
365 if (mRUEntry[ruSW] < 0) {
366 mRUEntry[ruSW] = mRUDecodeVec.size();
367 auto& ru = mRUDecodeVec.emplace_back();
369 ru.ruInfo = mMAP.getRUInfoSW(ruSW);
370 ru.chipsData.resize(mMAP.getNChipsOnRUType(ru.ruInfo->ruType));
371 ru.verbosity = mVerbosity;
372 if (mVerbosity >= GBTLink::Verbosity::VerboseHeaders) {
373 LOG(info) << mSelfName <<
" Defining container for RU " << ruSW <<
" at slot " << mRUEntry[ruSW];
376 return mRUDecodeVec[mRUEntry[ruSW]];
380template <
class Mapping>
384 for (; mCurRUDecodeID < mRUDecodeVec.size(); mCurRUDecodeID++) {
385 auto& ru = mRUDecodeVec[mCurRUDecodeID];
386 if (ru.lastChipChecked < ru.nChipsFired) {
387 auto& chipData = ru.chipsData[ru.lastChipChecked++];
389 if (mLastReadChipID >= chipData.getChipID()) {
390 if (!mROFRampUpStage) {
391 const int MaxErrLog = 2;
392 static int errLocCount = 0;
393 if (errLocCount < MaxErrLog) {
394 LOGP(warn,
"Wrong order/duplication: encountered chip {} after processing chip {}, skipping.",
395 chipData.getChipID(), mLastReadChipID, ++errLocCount, MaxErrLog);
400 mLastReadChipID = chipData.getChipID();
401 chipDataVec[mLastReadChipID].swap(chipData);
402 return &chipDataVec[mLastReadChipID];
406 if (!mDecodeNextAuto || decodeNextTrigger() < 0) {
409 return getNextChipData(chipDataVec);
413template <
class Mapping>
417 for (; mCurRUDecodeID < mRUDecodeVec.size(); mCurRUDecodeID++) {
418 auto& ru = mRUDecodeVec[mCurRUDecodeID];
419 if (ru.lastChipChecked < ru.nChipsFired) {
420 auto& ruchip = ru.chipsData[ru.lastChipChecked++];
421 assert(mLastReadChipID < chipData.
getChipID());
423 chipData.
swap(ruchip);
428 if (!mDecodeNextAuto || decodeNextTrigger() < 0) {
431 return getNextChipData(chipData);
438 mOrderedChipsPtr.clear();
440 if (mCurRUDecodeID < mRUDecodeVec.size()) {
441 for (; mCurRUDecodeID < mRUDecodeVec.size(); mCurRUDecodeID++) {
442 auto& ru = mRUDecodeVec[mCurRUDecodeID];
443 while (ru.lastChipChecked < ru.nChipsFired) {
444 mOrderedChipsPtr.push_back(&ru.chipsData[ru.lastChipChecked++]);
448 std::sort(mOrderedChipsPtr.begin(), mOrderedChipsPtr.end(), [](
const ChipPixelData*
a,
const ChipPixelData*
b) { return a->getChipID() > b->getChipID(); });
456 if (!mOrderedChipsPtr.empty()) {
457 auto chipData = *mOrderedChipsPtr.back();
458 assert(mLastReadChipID < chipData.getChipID());
459 mLastReadChipID = chipData.getChipID();
460 chipDataVec[mLastReadChipID].swap(chipData);
461 mOrderedChipsPtr.pop_back();
462 return &chipDataVec[mLastReadChipID];
465 if (!mDecodeNextAuto || decodeNextTrigger() < 0) {
468 return getNextChipData(chipDataVec);
475 if (!mOrderedChipsPtr.empty()) {
476 auto ruChip = *mOrderedChipsPtr.back();
477 assert(mLastReadChipID < ruChip.getChipID());
478 mLastReadChipID = ruChip.getChipID();
479 ruChip.swap(chipData);
480 mOrderedChipsPtr.pop_back();
484 if (!mDecodeNextAuto || decodeNextTrigger() < 0) {
487 return getNextChipData(chipData);
491template <
class Mapping>
495 for (
auto&
link : mGBTLinks) {
501template <
class Mapping>
505 mNThreads =
n > 0 ?
n : 1;
507 LOG(warning) << mSelfName <<
" Multithreading is not supported, imposing single thread";
513template <
class Mapping>
517 for (
auto& lnk : mGBTLinks) {
518 lnk.clear(
true, resetRaw);
520 mNChipsFiredROF = mNPixelsFiredROF = 0;
521 mNChipsFired = mNPixelsFired = mNExtTriggers = 0;
525template <
class Mapping>
529 bool dumpFullTF =
false;
530 for (
auto& ru : mRUDecodeVec) {
531 if (ru.linkHBFToDump.size()) {
532 if (
dump ==
int(GBTLink::RawDataDumps::DUMP_TF)) {
536 for (
auto it : ru.linkHBFToDump) {
537 if (
dump ==
int(GBTLink::RawDataDumps::DUMP_HBF)) {
538 const auto& lnk = mGBTLinks[mSubsSpec2LinkID[it.first >> 32].entry];
539 int entry = it.first & 0xffffffff;
540 bool allHBFs =
false;
542 if (
entry >= lnk.rawData.getNPieces()) {
545 fnm = fmt::format(
"{}{}rawdump_{}_run{}_tf_orb{}_full_feeID{:#06x}.raw", mRawDumpDirectory, mRawDumpDirectory.empty() ?
"" :
"/",
548 fnm = fmt::format(
"{}{}rawdump_{}_run{}_tf_orb{}_hbf_orb{}_feeID{:#06x}.raw", mRawDumpDirectory, mRawDumpDirectory.empty() ?
"" :
"/",
551 std::ofstream ostrm(fnm, std::ios::binary);
553 LOG(error) <<
"failed to open " << fnm;
556 while (
entry < lnk.rawData.getNPieces()) {
557 const auto* piece = lnk.rawData.getPiece(
entry);
558 if (!allHBFs && RDHUtils::getHeartBeatOrbit(
reinterpret_cast<const RDH*
>(piece->data)) != it.second) {
561 ostrm.write(
reinterpret_cast<const char*
>(piece->data), piece->size);
562 outSize += piece->size;
565 LOG(info) <<
"produced " << std::filesystem::current_path().c_str() <<
'/' << fnm;
571 std::string fnm = fmt::format(
"rawdump_{}_run{}_tf_orb{}_full.raw",
573 std::ofstream ostrm(fnm, std::ios::binary);
575 LOG(error) <<
"failed to open " << fnm;
578 for (
const auto& lnk : mGBTLinks) {
579 for (
size_t i = 0;
i < lnk.rawData.getNPieces();
i++) {
580 const auto* piece = lnk.rawData.getPiece(
i);
581 ostrm.write(
reinterpret_cast<const char*
>(piece->data), piece->size);
582 outSize += piece->size;
585 LOG(info) <<
"produced " << std::filesystem::current_path().c_str() <<
'/' << fnm;
592template <
class Mapping>
595 mTimerTFStart.Reset();
596 mTimerDecode.Reset();
597 mTimerFetchData.Reset();
598 for (
auto& ru : mRUDecodeVec) {
599 for (
auto& cab : ru.cableData) {
603 for (
auto&
link : mGBTLinks) {
604 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"