Project
Loading...
Searching...
No Matches
RawPixelDecoder.cxx
Go to the documentation of this file.
1// Copyright 2019-2026 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
14
23#include <filesystem>
24
25#ifdef WITH_OPENMP
26#include <omp.h>
27#endif
28
29using namespace o2::itsmft;
30using namespace o2::framework;
32
35template <class Mapping>
37{
38 mRUEntry.fill(-1); // no known links in the beginning
39 mTimerTFStart.Stop();
40 mTimerDecode.Stop();
41 mTimerFetchData.Stop();
42 mSelfName = o2::utils::Str::concat_string(Mapping::getName(), "Decoder");
43 DPLRawParser<>::setCheckIncompleteHBF(false); // Disable incomplete HBF checking, see ErrPacketCounterJump check in GBTLink.cxx
44 mInputFilter = {InputSpec{"filter", ConcreteDataTypeMatcher{Mapping::getOrigin(), o2::header::gDataDescriptionRawData}}}; // by default take all raw data
45}
46
49template <class Mapping>
50void RawPixelDecoder<Mapping>::printReport(bool decstat, bool skipNoErr) const
51{
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");
67
68 LOGP(info, "{} decoded {} hits in {} non-empty chips in {} ROFs with {} threads, {} external triggers", mSelfName, mNPixelsFired, mNChipsFired, mROFCounter, mNThreads, mNExtTriggers);
69 if (decstat) {
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);
74 }
75 }
76}
77
80template <class Mapping>
82{
83 mNChipsFiredROF = 0;
84 mNPixelsFiredROF = 0;
85 mInteractionRecord.clear();
86 if (mROFRampUpStage && mSkipRampUpData) {
87 return -1;
88 }
89 int nru = mRUDecodeVec.size();
90 int prevNTrig = mExtTriggers.size();
91 do {
92#ifdef WITH_OPENMP
93#pragma omp parallel for schedule(dynamic) num_threads(mNThreads)
94#endif
95 for (int iru = 0; iru < nru; iru++) {
96 collectROFCableData(iru);
97 }
98
99 mROFCounter++;
100
101 if (!doIRMajorityPoll()) {
102 continue; // no links with data
103 }
104
105#ifdef WITH_OPENMP
106#pragma omp parallel for schedule(dynamic) num_threads(mNThreads) reduction(+ : mNChipsFiredROF, mNPixelsFiredROF)
107#endif
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;
114 } else {
115 ru.clearSeenChipIDs();
116 }
117 }
118
119 if (mNChipsFiredROF || (mAlloEmptyROFs && mNLinksDone < mNLinksInTF)) { // fill some statistics
120 mTrigger = mLinkForTriggers ? mLinkForTriggers->trigger : 0;
121 mNChipsFired += mNChipsFiredROF;
122 mNPixelsFired += mNPixelsFiredROF;
123 mCurRUDecodeID = 0; // getNextChipData will start from here
124 mLastReadChipID = -1;
125 break;
126 }
127
128 } while (mNLinksDone < mNLinksInTF);
129 mNExtTriggers += mExtTriggers.size() - prevNTrig;
130 ensureChipOrdering();
131 mTimerDecode.Stop();
132
133 return (mNLinksDone < mNLinksInTF) ? mNChipsFiredROF : -1;
134}
135
138template <class Mapping>
140{
141 mTimerTFStart.Start(false);
142 for (auto& link : mGBTLinks) {
143 link.lastRDH = nullptr; // pointers will be invalid
144 link.clear(false, true); // clear data but not the statistics
145 }
146 for (auto& ru : mRUDecodeVec) {
147 ru.clear();
148 // ru.chipErrorsTF.clear(); // will be cleared in the collectDecodingErrors
149 ru.linkHBFToDump.clear();
150 ru.nLinksDone = 0;
151 }
152 setupLinks(inputs);
153 mNLinksDone = 0;
154 mExtTriggers.clear();
155 mTimerTFStart.Stop();
156}
157
160template <class Mapping>
162{
163 auto& ru = mRUDecodeVec[iru];
164 ru.clear();
165 for (int il = 0; il < RUDecodeData::MaxLinksPerRU; il++) {
166 auto* link = getGBTLink(ru.links[il]);
167 if (link && link->statusInTF == GBTLink::DataSeen) {
168 auto res = link->collectROFCableData(mMAP);
169 if (res == GBTLink::DataSeen || res == GBTLink::CachedDataExist) { // at the moment process only DataSeen
170 ru.nNonEmptyLinks++;
171 } else if (res == GBTLink::StoppedOnEndOfData || res == GBTLink::AbortedOnError) { // this link has exhausted its data or it has to be discarded due to the error
172 ru.nLinksDone++;
173 }
174 }
175 }
176}
177
179// do majority IR poll for synchronization
180template <class Mapping>
182{
183 mIRPoll.clear();
184 mInteractionRecord.clear();
185 for (auto& link : mGBTLinks) {
186 if (link.statusInTF == GBTLink::DataSeen) {
187 if (link.status == GBTLink::DataSeen || link.status == GBTLink::CachedDataExist) {
188 mIRPoll[link.ir]++;
189 if (mVerbosity >= GBTLink::Verbosity::VerboseHeaders) {
190 LOGP(info, "doIRMajorityPoll: {} contributes to poll {}", link.describe(), link.ir.asString());
191 }
192 } else if (link.status == GBTLink::StoppedOnEndOfData || link.status == GBTLink::AbortedOnError) {
194 if (mVerbosity >= GBTLink::Verbosity::VerboseHeaders) {
195 LOGP(info, "doIRMajorityPoll: {} DONE, status = {}", link.describe(), int(link.status));
196 }
197 mNLinksDone++;
198 }
199 }
200 }
201 if (mNLinksDone == mNLinksInTF) {
202 if (mVerbosity >= GBTLink::Verbosity::VerboseHeaders) {
203 LOGP(info, "doIRMajorityPoll: All {} links registered in TF are done", mNLinksInTF);
204 }
205 return false;
206 }
207 int majIR = -1;
208 for (const auto& entIR : mIRPoll) {
209 if (entIR.second > majIR) {
210 majIR = entIR.second;
211 mInteractionRecord = entIR.first;
212 }
213 }
214 if (mInteractionRecord.isDummy()) {
215 if (mVerbosity >= GBTLink::Verbosity::VerboseHeaders) {
216 LOG(info) << "doIRMajorityPoll: did not find any valid IR";
217 }
218 return false;
219 }
220 if (mVerbosity >= GBTLink::Verbosity::VerboseHeaders) {
221 LOG(info) << "doIRMajorityPoll: " << mInteractionRecord.asString() << " majority = " << majIR << " for " << mNLinksInTF << " links seen, LinksDone = " << mNLinksDone;
222 }
223 return true;
224}
225
228template <class Mapping>
230{
231 constexpr uint32_t ROF_RAMP_FLAG = 0x1 << 4;
232 constexpr uint32_t LINK_RECOVERY_FLAG = 0x1 << 5;
233 mNLinksInTF = 0;
234 mCurRUDecodeID = NORUDECODED;
235 auto nLinks = mGBTLinks.size();
236 auto origin = (mUserDataOrigin == o2::header::gDataOriginInvalid) ? mMAP.getOrigin() : mUserDataOrigin;
237 auto datadesc = (mUserDataDescription == o2::header::gDataDescriptionInvalid) ? o2::header::gDataDescriptionRawData : mUserDataDescription;
238 if (mUserDataDescription != o2::header::gDataDescriptionInvalid) { // overwrite data filter origin&descriptions with user defined ones if possible
239 for (auto& filt : mInputFilter) {
240 if (std::holds_alternative<o2::framework::ConcreteDataMatcher>(filt.matcher)) {
241 std::get<o2::framework::ConcreteDataMatcher>(filt.matcher).origin = origin;
242 std::get<o2::framework::ConcreteDataMatcher>(filt.matcher).description = datadesc;
243 }
244 }
245 }
246
247 // if we see requested data type input with 0xDEADBEEF subspec and 0 payload this means that the "delayed message"
248 // mechanism created it in absence of real data from upstream. Processor should send empty output to not block the workflow
249 {
250 static size_t contDeadBeef = 0; // number of times 0xDEADBEEF was seen continuously
251 std::vector<InputSpec> dummy{InputSpec{"dummy", ConcreteDataMatcher{origin, datadesc, 0xDEADBEEF}}};
252 for (const auto& ref : InputRecordWalker(inputs, dummy)) {
253 const auto dh = o2::framework::DataRefUtils::getHeader<o2::header::DataHeader*>(ref);
255 if (payloadSize == 0) {
257 if (++contDeadBeef <= maxWarn) {
258 LOGP(warn, "Found input [{}/{}/{:#x}] TF#{} 1st_orbit:{} Payload {} : assuming no payload for all links in this TF{}",
259 dh->dataOrigin.str, dh->dataDescription.str, dh->subSpecification, dh->tfCounter, dh->firstTForbit, payloadSize,
260 contDeadBeef == maxWarn ? fmt::format(". {} such inputs in row received, stopping reporting", contDeadBeef) : "");
261 }
262 return;
263 }
264 }
265 contDeadBeef = 0; // if good data, reset the counter
266 }
267 mROFRampUpStage = false;
268 DPLRawParser parser(inputs, mInputFilter, o2::conf::VerbosityConfig::Instance().rawParserSeverity);
269 parser.setMaxFailureMessages(o2::conf::VerbosityConfig::Instance().maxWarnRawParser);
270 static size_t cntParserFailures = 0;
271 parser.setExtFailureCounter(&cntParserFailures);
272
273 uint32_t currSSpec = 0xffffffff; // dummy starting subspec
274 int linksAdded = 0;
275 uint16_t lr, dummy; // extraxted info from FEEId
276 for (auto it = parser.begin(); it != parser.end(); ++it) {
277 auto const* dh = it.o2DataHeader();
278 auto& lnkref = mSubsSpec2LinkID[dh->subSpecification];
279 const auto& rdh = *reinterpret_cast<const header::RDHAny*>(it.raw()); // RSTODO this is a hack in absence of generic header getter
280 const auto feeID = RDHUtils::getFEEID(rdh);
281 mMAP.expandFEEId(feeID, lr, dummy, dummy);
282
283 if (lnkref.entry == -1) { // new link needs to be added
284 lnkref.entry = int(mGBTLinks.size());
285 auto& lnk = mGBTLinks.emplace_back(RDHUtils::getCRUID(rdh), feeID, RDHUtils::getEndPointID(rdh), RDHUtils::getLinkID(rdh), lnkref.entry);
286 lnk.subSpec = dh->subSpecification;
287 lnk.wordLength = (lnk.expectPadding = (RDHUtils::getDataFormat(rdh) == 0)) ? o2::itsmft::GBTPaddedWordLength : o2::itsmft::GBTWordLength;
288 getCreateRUDecode(mMAP.FEEId2RUSW(feeID)); // make sure there is a RU for this link
289 lnk.verbosity = GBTLink::Verbosity(mVerbosity);
290 lnk.alwaysParseTrigger = mAlwaysParseTrigger;
291 if (mVerbosity >= GBTLink::Verbosity::VerboseHeaders) {
292 LOG(info) << mSelfName << " registered new " << lnk.describe() << " RUSW=" << int(mMAP.FEEId2RUSW(lnk.feeID));
293 }
294 linksAdded++;
295 }
296 auto& link = mGBTLinks[lnkref.entry];
297 if (currSSpec != dh->subSpecification) { // this is the 1st part for this link in this TF, next parts must follow contiguously!!!
298 currSSpec = dh->subSpecification;
299 if (link.statusInTF != GBTLink::None) {
300 static bool errorDone = false;
301 if (!errorDone) {
302 LOGP(error, "{} was already registered, inform PDP on-call about error!!!", link.describe());
303 errorDone = true;
304 }
305 }
306 link.statusInTF = GBTLink::DataSeen;
307 mNLinksInTF++;
308 }
309 auto detField = RDHUtils::getDetectorField(&rdh);
310 if (detField & ROF_RAMP_FLAG) {
311 mROFRampUpStage = true;
312 }
313 if ((detField & LINK_RECOVERY_FLAG) && (link.statusInTF != GBTLink::Recovery)) {
314 link.statusInTF = GBTLink::Recovery; // data will be discarded
315 link.rawData.clear();
317 link.accountLinkRecovery(RDHUtils::getHeartBeatIR(rdh));
318 mNLinksInTF--;
319 }
320 if (link.statusInTF != GBTLink::Recovery) {
321 link.cacheData(it.raw(), RDHUtils::getMemorySize(rdh));
322 }
323 }
324
325 if (linksAdded) { // new links were added, update link<->RU mapping, usually is done for 1st TF only
326 if (nLinks) {
327 if (mVerbosity >= GBTLink::Verbosity::VerboseHeaders) {
328 LOG(warn) << mSelfName << " New links appeared although the initialization was already done";
329 }
330 for (auto& ru : mRUDecodeVec) { // reset RU->link references since they may have been changed
331 memset(&ru.links[0], -1, RUDecodeData::MaxLinksPerRU * sizeof(int));
332 memset(&ru.cableLinkPtr[0], 0, RUDecodeData::MaxCablesPerRU * sizeof(GBTLink*));
333 }
334 }
335 // sort RUs in stave increasing order
336 std::sort(mRUDecodeVec.begin(), mRUDecodeVec.end(), [](const RUDecodeData& ruA, const RUDecodeData& ruB) -> bool { return ruA.ruSWID < ruB.ruSWID; });
337 for (auto i = 0; i < mRUDecodeVec.size(); i++) {
338 mRUEntry[mRUDecodeVec[i].ruSWID] = i;
339 }
340 nLinks = mGBTLinks.size();
341 // attach link to corresponding RU: this can be done once all RUs are created, to make sure their pointers don't change
342 for (int il = 0; il < nLinks; il++) {
343 auto& link = mGBTLinks[il];
344 bool newLinkAdded = (link.ruPtr == nullptr);
345 link.ruPtr = getRUDecode(mMAP.FEEId2RUSW(link.feeID)); // link to RU reference, reattach even it was already set before
346 uint16_t lr, ruOnLr, linkInRU;
347 mMAP.expandFEEId(link.feeID, lr, ruOnLr, linkInRU);
348 if (newLinkAdded) {
349 if (mVerbosity >= GBTLink::Verbosity::VerboseHeaders) {
350 LOGP(info, "{} Attaching {} to RU#{:02} (stave {:02} of layer {})", mSelfName, link.describe(), int(mMAP.FEEId2RUSW(link.feeID)), ruOnLr, lr);
351 }
352 }
353 link.idInRU = linkInRU;
354 link.ruPtr->links[linkInRU] = il; // RU to link reference
355 link.ruPtr->nLinks++;
356 }
357 }
358 // set the link extracting triggers
359 for (auto& link : mGBTLinks) {
360 if (link.statusInTF == GBTLink::DataSeen) { // designate 1st link with valid data to register triggers
361 link.extTrigVec = &mExtTriggers;
362 mLinkForTriggers = &link;
363 break;
364 }
365 }
366}
367
370template <class Mapping>
372{
373 assert(ruSW < mMAP.getNRUs());
374 if (mRUEntry[ruSW] < 0) {
375 mRUEntry[ruSW] = mRUDecodeVec.size();
376 auto& ru = mRUDecodeVec.emplace_back();
377 ru.ruSWID = ruSW;
378 ru.ruInfo = mMAP.getRUInfoSW(ruSW); // info on the stave/RU
379 ru.chipsData.resize(mMAP.getNChipsOnRUType(ru.ruInfo->ruType));
380 ru.verbosity = mVerbosity;
381 if (mVerbosity >= GBTLink::Verbosity::VerboseHeaders) {
382 LOG(info) << mSelfName << " Defining container for RU " << ruSW << " at slot " << mRUEntry[ruSW];
383 }
384 }
385 return mRUDecodeVec[mRUEntry[ruSW]];
386}
387
389template <class Mapping>
390ChipPixelData* RawPixelDecoder<Mapping>::getNextChipData(std::vector<ChipPixelData>& chipDataVec)
391{
392 // decode new RU if no cached non-empty chips
393 for (; mCurRUDecodeID < mRUDecodeVec.size(); mCurRUDecodeID++) {
394 auto& ru = mRUDecodeVec[mCurRUDecodeID];
395 if (ru.lastChipChecked < ru.nChipsFired) {
396 auto& chipData = ru.chipsData[ru.lastChipChecked++];
397 // assert(mLastReadChipID < chipData.getChipID());
398 if (mLastReadChipID >= chipData.getChipID()) {
399 if (!mROFRampUpStage) {
400 const int MaxErrLog = 2;
401 static int errLocCount = 0;
402 if (errLocCount < MaxErrLog) {
403 LOGP(warn, "Wrong order/duplication: encountered chip {} after processing chip {}, skipping.",
404 chipData.getChipID(), mLastReadChipID, ++errLocCount, MaxErrLog);
405 }
406 }
407 continue;
408 }
409 mLastReadChipID = chipData.getChipID();
410 chipDataVec[mLastReadChipID].swap(chipData);
411 return &chipDataVec[mLastReadChipID];
412 }
413 }
414 // will need to decode new trigger
415 if (!mDecodeNextAuto || decodeNextTrigger() < 0) { // no more data to decode
416 return nullptr;
417 }
418 return getNextChipData(chipDataVec);
419}
420
422template <class Mapping>
424{
426 for (; mCurRUDecodeID < mRUDecodeVec.size(); mCurRUDecodeID++) {
427 auto& ru = mRUDecodeVec[mCurRUDecodeID];
428 if (ru.lastChipChecked < ru.nChipsFired) {
429 auto& ruchip = ru.chipsData[ru.lastChipChecked++];
430 assert(mLastReadChipID < chipData.getChipID());
431 mLastReadChipID = chipData.getChipID();
432 chipData.swap(ruchip);
433 return true;
434 }
435 }
436 // will need to decode new trigger
437 if (!mDecodeNextAuto || decodeNextTrigger() < 0) { // no more data to decode
438 return false;
439 }
440 return getNextChipData(chipData); // is it ok to use recursion here?
441}
442
444template <>
446{
447 mOrderedChipsPtr.clear();
448 // define looping order, if mCurRUDecodeID < mRUDecodeVec.size(), this means that decodeNextTrigger() was called before
449 if (mCurRUDecodeID < mRUDecodeVec.size()) { // define sort order
450 for (; mCurRUDecodeID < mRUDecodeVec.size(); mCurRUDecodeID++) {
451 auto& ru = mRUDecodeVec[mCurRUDecodeID];
452 while (ru.lastChipChecked < ru.nChipsFired) {
453 mOrderedChipsPtr.push_back(&ru.chipsData[ru.lastChipChecked++]);
454 }
455 }
456 // sort in decreasing order
457 std::sort(mOrderedChipsPtr.begin(), mOrderedChipsPtr.end(), [](const ChipPixelData* a, const ChipPixelData* b) { return a->getChipID() > b->getChipID(); });
458 }
459}
460
462template <>
463ChipPixelData* RawPixelDecoder<ChipMappingMFT>::getNextChipData(std::vector<ChipPixelData>& chipDataVec)
464{
465 if (!mOrderedChipsPtr.empty()) {
466 auto chipData = *mOrderedChipsPtr.back();
467 assert(mLastReadChipID < chipData.getChipID());
468 mLastReadChipID = chipData.getChipID();
469 chipDataVec[mLastReadChipID].swap(chipData);
470 mOrderedChipsPtr.pop_back();
471 return &chipDataVec[mLastReadChipID];
472 }
473 // will need to decode new trigger
474 if (!mDecodeNextAuto || decodeNextTrigger() < 0) { // no more data to decode
475 return nullptr;
476 }
477 return getNextChipData(chipDataVec);
478}
479
481template <>
483{
484 if (!mOrderedChipsPtr.empty()) {
485 auto ruChip = *mOrderedChipsPtr.back();
486 assert(mLastReadChipID < ruChip.getChipID());
487 mLastReadChipID = ruChip.getChipID();
488 ruChip.swap(chipData);
489 mOrderedChipsPtr.pop_back();
490 return true;
491 }
492 // will need to decode new trigger
493 if (!mDecodeNextAuto || decodeNextTrigger() < 0) { // no more data to decode
494 return false;
495 }
496 return getNextChipData(chipData); // is it ok to use recursion here?
497}
498
500template <class Mapping>
502{
503 mVerbosity = v;
504 for (auto& link : mGBTLinks) {
505 link.verbosity = GBTLink::Verbosity(v);
506 }
507}
508
510template <class Mapping>
512{
513#ifdef WITH_OPENMP
514 mNThreads = n > 0 ? n : 1;
515#else
516 LOG(warning) << mSelfName << " Multithreading is not supported, imposing single thread";
517 mNThreads = 1;
518#endif
519}
520
522template <class Mapping>
524{
525 // clear statistics
526 for (auto& lnk : mGBTLinks) {
527 lnk.clear(true, resetRaw);
528 }
529 mNChipsFiredROF = mNPixelsFiredROF = 0;
530 mNChipsFired = mNPixelsFired = mNExtTriggers = 0;
531}
532
534template <class Mapping>
536{
537 size_t outSize = 0;
538 bool dumpFullTF = false;
539 for (auto& ru : mRUDecodeVec) {
540 if (ru.linkHBFToDump.size()) {
541 if (dump == int(GBTLink::RawDataDumps::DUMP_TF)) {
542 dumpFullTF = true;
543 break;
544 }
545 for (auto it : ru.linkHBFToDump) {
546 if (dump == int(GBTLink::RawDataDumps::DUMP_HBF)) {
547 const auto& lnk = mGBTLinks[mSubsSpec2LinkID[it.first >> 32].entry];
548 int entry = it.first & 0xffffffff;
549 bool allHBFs = false;
550 std::string fnm;
551 if (entry >= lnk.rawData.getNPieces()) {
552 allHBFs = true;
553 entry = 0;
554 fnm = fmt::format("{}{}rawdump_{}_run{}_tf_orb{}_full_feeID{:#06x}.raw", mRawDumpDirectory, mRawDumpDirectory.empty() ? "" : "/",
555 Mapping::getName(), tinfo.runNumber, tinfo.firstTForbit, lnk.feeID);
556 } else {
557 fnm = fmt::format("{}{}rawdump_{}_run{}_tf_orb{}_hbf_orb{}_feeID{:#06x}.raw", mRawDumpDirectory, mRawDumpDirectory.empty() ? "" : "/",
558 Mapping::getName(), tinfo.runNumber, tinfo.firstTForbit, it.second, lnk.feeID);
559 }
560 std::ofstream ostrm(fnm, std::ios::binary);
561 if (!ostrm.good()) {
562 LOG(error) << "failed to open " << fnm;
563 continue;
564 }
565 while (entry < lnk.rawData.getNPieces()) {
566 const auto* piece = lnk.rawData.getPiece(entry);
567 if (!allHBFs && RDHUtils::getHeartBeatOrbit(reinterpret_cast<const RDH*>(piece->data)) != it.second) {
568 break;
569 }
570 ostrm.write(reinterpret_cast<const char*>(piece->data), piece->size);
571 outSize += piece->size;
572 entry++;
573 }
574 LOG(info) << "produced " << std::filesystem::current_path().c_str() << '/' << fnm;
575 }
576 }
577 }
578 }
579 while (dumpFullTF) {
580 std::string fnm = fmt::format("rawdump_{}_run{}_tf_orb{}_full.raw",
581 Mapping::getName(), tinfo.runNumber, tinfo.firstTForbit);
582 std::ofstream ostrm(fnm, std::ios::binary);
583 if (!ostrm.good()) {
584 LOG(error) << "failed to open " << fnm;
585 break;
586 }
587 for (const auto& lnk : mGBTLinks) {
588 for (size_t i = 0; i < lnk.rawData.getNPieces(); i++) {
589 const auto* piece = lnk.rawData.getPiece(i);
590 ostrm.write(reinterpret_cast<const char*>(piece->data), piece->size);
591 outSize += piece->size;
592 }
593 }
594 LOG(info) << "produced " << std::filesystem::current_path().c_str() << '/' << fnm;
595 break;
596 }
597 return outSize;
598}
599
601template <class Mapping>
603{
604 mTimerTFStart.Reset();
605 mTimerDecode.Reset();
606 mTimerFetchData.Reset();
607 for (auto& ru : mRUDecodeVec) {
608 for (auto& cab : ru.cableData) {
609 cab.clear();
610 }
611 }
612 for (auto& link : mGBTLinks) {
613 link.rofJumpWasSeen = false;
614 link.statusInTF = GBTLink::None;
615 }
616 clearStat(true);
617}
618
header::DataOrigin origin
A raw page parser for DPL input.
int32_t i
void setupLinks(o2::itsmft::MC2RawEncoder< MAP > &m2r, std::string_view outDir, std::string_view outPrefix, std::string_view fileFor)
Definition digi2raw.cxx:407
A helper class to iteratate over all parts of all input routes.
uint32_t cpu
Definition RawData.h:6
uint32_t res
Definition RawData.h:0
Definition of the Alpide pixel reader for raw data processing.
The parser handles transparently input in the format of raw pages.
static void setCheckIncompleteHBF(bool v)
A helper class to iteratate over all parts of all input routes.
The input API of the Data Processing Layer This class holds the inputs which are valid for processing...
void swap(ChipPixelData &other)
Definition PixelData.h:156
uint16_t getChipID() const
Definition PixelData.h:108
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)
void dump(const std::string what, DPMAP m, int verbose)
Definition dcs-ccdb.cxx:79
GLdouble n
Definition glcorearb.h:1982
GLuint entry
Definition glcorearb.h:5735
const GLdouble * v
Definition glcorearb.h:832
GLboolean GLboolean GLboolean b
Definition glcorearb.h:1233
GLboolean GLboolean GLboolean GLboolean a
Definition glcorearb.h:1233
constexpr o2::header::DataDescription gDataDescriptionInvalid
Definition DataHeader.h:597
constexpr o2::header::DataOrigin gDataOriginInvalid
Definition DataHeader.h:561
constexpr o2::header::DataDescription gDataDescriptionRawData
Definition DataHeader.h:598
uint8_t itsSharedClusterMap uint8_t
Defining ITS Vertex explicitly as messageable.
Definition Cartesian.h:288
constexpr int GBTPaddedWordLength
Definition GBTWord.h:56
constexpr int GBTWordLength
Definition GBTWord.h:55
static o2::header::DataHeader::PayloadSizeType getPayloadSize(const DataRef &ref)
static constexpr int MaxCablesPerRU
static constexpr int MaxLinksPerRU
static std::string concat_string(Ts const &... ts)
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"