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(+ \
106 : 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) {
191 if (mVerbosity >= GBTLink::Verbosity::VerboseHeaders) {
192 LOGP(info,
"doIRMajorityPoll: {} DONE, status = {}", link.describe(),
int(link.status));
199 for (
const auto& entIR : mIRPoll) {
200 if (entIR.second > majIR) {
201 majIR = entIR.second;
202 mInteractionRecord = entIR.first;
205 mInteractionRecordHB = mInteractionRecord;
206 if (mInteractionRecord.isDummy()) {
207 if (mVerbosity >= GBTLink::Verbosity::VerboseHeaders) {
208 LOG(info) <<
"doIRMajorityPoll: did not find any valid IR";
212 mInteractionRecordHB.bc = 0;
213 if (mVerbosity >= GBTLink::Verbosity::VerboseHeaders) {
214 LOG(info) <<
"doIRMajorityPoll: " << mInteractionRecordHB.asString() <<
" majority = " << majIR <<
" for " << mNLinksInTF <<
" links seen, LinksDone = " << mNLinksDone;
221template <
class Mapping>
224 constexpr uint32_t ROF_RAMP_FLAG = 0x1 << 4;
225 constexpr uint32_t LINK_RECOVERY_FLAG = 0x1 << 5;
227 mCurRUDecodeID = NORUDECODED;
228 auto nLinks = mGBTLinks.size();
236 static size_t contDeadBeef = 0;
239 const auto dh = o2::framework::DataRefUtils::getHeader<o2::header::DataHeader*>(
ref);
241 if (payloadSize == 0) {
243 if (++contDeadBeef <= maxWarn) {
244 LOGP(warn,
"Found input [{}/{}/{:#x}] TF#{} 1st_orbit:{} Payload {} : assuming no payload for all links in this TF{}",
245 dh->dataOrigin.str, dh->dataDescription.str, dh->subSpecification, dh->tfCounter, dh->firstTForbit, payloadSize,
246 contDeadBeef == maxWarn ? fmt::format(
". {} such inputs in row received, stopping reporting", contDeadBeef) :
"");
253 mROFRampUpStage =
false;
256 static size_t cntParserFailures = 0;
257 parser.setExtFailureCounter(&cntParserFailures);
259 uint32_t currSSpec = 0xffffffff;
261 for (
auto it = parser.begin(); it != parser.end(); ++it) {
262 auto const* dh = it.o2DataHeader();
263 auto& lnkref = mSubsSpec2LinkID[dh->subSpecification];
264 const auto& rdh = *
reinterpret_cast<const header::RDHAny*
>(it.raw());
266 if (lnkref.entry == -1) {
267 lnkref.entry =
int(mGBTLinks.size());
268 auto& lnk = mGBTLinks.emplace_back(RDHUtils::getCRUID(rdh), RDHUtils::getFEEID(rdh), RDHUtils::getEndPointID(rdh), RDHUtils::getLinkID(rdh), lnkref.entry);
269 lnk.subSpec = dh->subSpecification;
271 getCreateRUDecode(mMAP.FEEId2RUSW(RDHUtils::getFEEID(rdh)));
273 lnk.alwaysParseTrigger = mAlwaysParseTrigger;
274 if (mVerbosity >= GBTLink::Verbosity::VerboseHeaders) {
275 LOG(info) << mSelfName <<
" registered new link " << lnk.describe() <<
" RUSW=" <<
int(mMAP.FEEId2RUSW(lnk.feeID));
279 auto& link = mGBTLinks[lnkref.entry];
280 if (currSSpec != dh->subSpecification) {
281 currSSpec = dh->subSpecification;
283 static bool errorDone =
false;
285 LOGP(error,
"{} was already registered, inform PDP on-call about error!!!", link.describe());
292 auto detField = RDHUtils::getDetectorField(&rdh);
293 if (detField & ROF_RAMP_FLAG) {
294 mROFRampUpStage =
true;
298 link.rawData.clear();
300 link.accountLinkRecovery(RDHUtils::getHeartBeatIR(rdh));
304 link.cacheData(it.raw(), RDHUtils::getMemorySize(rdh));
310 if (mVerbosity >= GBTLink::Verbosity::VerboseHeaders) {
311 LOG(warn) << mSelfName <<
" New links appeared although the initialization was already done";
313 for (
auto& ru : mRUDecodeVec) {
319 std::sort(mRUDecodeVec.begin(), mRUDecodeVec.end(), [](
const RUDecodeData& ruA,
const RUDecodeData& ruB) ->
bool { return ruA.ruSWID < ruB.ruSWID; });
320 for (
auto i = 0;
i < mRUDecodeVec.size();
i++) {
321 mRUEntry[mRUDecodeVec[
i].ruSWID] =
i;
323 nLinks = mGBTLinks.size();
325 for (
int il = 0; il < nLinks; il++) {
326 auto& link = mGBTLinks[il];
327 bool newLinkAdded = (link.ruPtr ==
nullptr);
328 link.ruPtr = getRUDecode(mMAP.FEEId2RUSW(link.feeID));
329 uint16_t lr, ruOnLr, linkInRU;
330 mMAP.expandFEEId(link.feeID, lr, ruOnLr, linkInRU);
332 if (mVerbosity >= GBTLink::Verbosity::VerboseHeaders) {
333 LOG(info) << mSelfName <<
" Attaching " << link.describe() <<
" to RU#" <<
int(mMAP.FEEId2RUSW(link.feeID)) <<
" (stave " << ruOnLr <<
" of layer " << lr <<
')';
336 link.idInRU = linkInRU;
337 link.ruPtr->links[linkInRU] = il;
338 link.ruPtr->nLinks++;
342 for (
auto& link : mGBTLinks) {
344 link.extTrigVec = &mExtTriggers;
345 mLinkForTriggers = &link;
353template <
class Mapping>
356 assert(ruSW < mMAP.getNRUs());
357 if (mRUEntry[ruSW] < 0) {
358 mRUEntry[ruSW] = mRUDecodeVec.size();
359 auto& ru = mRUDecodeVec.emplace_back();
361 ru.ruInfo = mMAP.getRUInfoSW(ruSW);
362 ru.chipsData.resize(mMAP.getNChipsOnRUType(ru.ruInfo->ruType));
363 ru.verbosity = mVerbosity;
364 if (mVerbosity >= GBTLink::Verbosity::VerboseHeaders) {
365 LOG(info) << mSelfName <<
" Defining container for RU " << ruSW <<
" at slot " << mRUEntry[ruSW];
368 return mRUDecodeVec[mRUEntry[ruSW]];
372template <
class Mapping>
376 for (; mCurRUDecodeID < mRUDecodeVec.size(); mCurRUDecodeID++) {
377 auto& ru = mRUDecodeVec[mCurRUDecodeID];
378 if (ru.lastChipChecked < ru.nChipsFired) {
379 auto& chipData = ru.chipsData[ru.lastChipChecked++];
381 if (mLastReadChipID >= chipData.getChipID()) {
382 if (!mROFRampUpStage) {
383 const int MaxErrLog = 2;
384 static int errLocCount = 0;
385 if (errLocCount < MaxErrLog) {
386 LOGP(warn,
"Wrong order/duplication: encountered chip {} after processing chip {}, skipping.",
387 chipData.getChipID(), mLastReadChipID, ++errLocCount, MaxErrLog);
392 mLastReadChipID = chipData.getChipID();
393 chipDataVec[mLastReadChipID].swap(chipData);
394 return &chipDataVec[mLastReadChipID];
398 if (!mDecodeNextAuto || decodeNextTrigger() < 0) {
401 return getNextChipData(chipDataVec);
405template <
class Mapping>
409 for (; mCurRUDecodeID < mRUDecodeVec.size(); mCurRUDecodeID++) {
410 auto& ru = mRUDecodeVec[mCurRUDecodeID];
411 if (ru.lastChipChecked < ru.nChipsFired) {
412 auto& ruchip = ru.chipsData[ru.lastChipChecked++];
413 assert(mLastReadChipID < chipData.
getChipID());
415 chipData.
swap(ruchip);
420 if (!mDecodeNextAuto || decodeNextTrigger() < 0) {
423 return getNextChipData(chipData);
430 mOrderedChipsPtr.clear();
432 if (mCurRUDecodeID < mRUDecodeVec.size()) {
433 for (; mCurRUDecodeID < mRUDecodeVec.size(); mCurRUDecodeID++) {
434 auto& ru = mRUDecodeVec[mCurRUDecodeID];
435 while (ru.lastChipChecked < ru.nChipsFired) {
436 mOrderedChipsPtr.push_back(&ru.chipsData[ru.lastChipChecked++]);
440 std::sort(mOrderedChipsPtr.begin(), mOrderedChipsPtr.end(), [](
const ChipPixelData*
a,
const ChipPixelData*
b) { return a->getChipID() > b->getChipID(); });
448 if (!mOrderedChipsPtr.empty()) {
449 auto chipData = *mOrderedChipsPtr.back();
450 assert(mLastReadChipID < chipData.getChipID());
451 mLastReadChipID = chipData.getChipID();
452 chipDataVec[mLastReadChipID].swap(chipData);
453 mOrderedChipsPtr.pop_back();
454 return &chipDataVec[mLastReadChipID];
457 if (!mDecodeNextAuto || decodeNextTrigger() < 0) {
460 return getNextChipData(chipDataVec);
467 if (!mOrderedChipsPtr.empty()) {
468 auto ruChip = *mOrderedChipsPtr.back();
469 assert(mLastReadChipID < ruChip.getChipID());
470 mLastReadChipID = ruChip.getChipID();
471 ruChip.swap(chipData);
472 mOrderedChipsPtr.pop_back();
476 if (!mDecodeNextAuto || decodeNextTrigger() < 0) {
479 return getNextChipData(chipData);
483template <
class Mapping>
487 for (
auto& link : mGBTLinks) {
493template <
class Mapping>
497 mNThreads =
n > 0 ?
n : 1;
499 LOG(warning) << mSelfName <<
" Multithreading is not supported, imposing single thread";
505template <
class Mapping>
509 for (
auto& lnk : mGBTLinks) {
510 lnk.clear(
true, resetRaw);
512 mNChipsFiredROF = mNPixelsFiredROF = 0;
513 mNChipsFired = mNPixelsFired = mNExtTriggers = 0;
517template <
class Mapping>
521 bool dumpFullTF =
false;
522 for (
auto& ru : mRUDecodeVec) {
523 if (ru.linkHBFToDump.size()) {
524 if (
dump ==
int(GBTLink::RawDataDumps::DUMP_TF)) {
528 for (
auto it : ru.linkHBFToDump) {
529 if (
dump ==
int(GBTLink::RawDataDumps::DUMP_HBF)) {
530 const auto& lnk = mGBTLinks[mSubsSpec2LinkID[it.first >> 32].entry];
531 int entry = it.first & 0xffffffff;
532 bool allHBFs =
false;
534 if (
entry >= lnk.rawData.getNPieces()) {
537 fnm = fmt::format(
"{}{}rawdump_{}_run{}_tf_orb{}_full_feeID{:#06x}.raw", mRawDumpDirectory, mRawDumpDirectory.empty() ?
"" :
"/",
540 fnm = fmt::format(
"{}{}rawdump_{}_run{}_tf_orb{}_hbf_orb{}_feeID{:#06x}.raw", mRawDumpDirectory, mRawDumpDirectory.empty() ?
"" :
"/",
543 std::ofstream ostrm(fnm, std::ios::binary);
545 LOG(error) <<
"failed to open " << fnm;
548 while (
entry < lnk.rawData.getNPieces()) {
549 const auto* piece = lnk.rawData.getPiece(
entry);
550 if (!allHBFs && RDHUtils::getHeartBeatOrbit(
reinterpret_cast<const RDH*
>(piece->data)) != it.second) {
553 ostrm.write(
reinterpret_cast<const char*
>(piece->data), piece->size);
554 outSize += piece->size;
557 LOG(info) <<
"produced " << std::filesystem::current_path().c_str() <<
'/' << fnm;
563 std::string fnm = fmt::format(
"rawdump_{}_run{}_tf_orb{}_full.raw",
565 std::ofstream ostrm(fnm, std::ios::binary);
567 LOG(error) <<
"failed to open " << fnm;
570 for (
const auto& lnk : mGBTLinks) {
571 for (
size_t i = 0;
i < lnk.rawData.getNPieces();
i++) {
572 const auto* piece = lnk.rawData.getPiece(
i);
573 ostrm.write(
reinterpret_cast<const char*
>(piece->data), piece->size);
574 outSize += piece->size;
577 LOG(info) <<
"produced " << std::filesystem::current_path().c_str() <<
'/' << fnm;
584template <
class Mapping>
587 mTimerTFStart.Reset();
588 mTimerDecode.Reset();
589 mTimerFetchData.Reset();
590 for (
auto& ru : mRUDecodeVec) {
591 for (
auto& cab : ru.cableData) {
595 for (
auto& link : mGBTLinks) {
596 link.rofJumpWasSeen =
false;
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
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
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
consteval header::DataOrigin origin()
Defining PrimaryVertex 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"