Project
Loading...
Searching...
No Matches
RawPixelDecoder.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 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}
45
48template <class Mapping>
49void RawPixelDecoder<Mapping>::printReport(bool decstat, bool skipNoErr) const
50{
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");
66
67 LOGP(info, "{} decoded {} hits in {} non-empty chips in {} ROFs with {} threads, {} external triggers", mSelfName, mNPixelsFired, mNChipsFired, mROFCounter, mNThreads, mNExtTriggers);
68 if (decstat) {
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);
73 }
74 }
75}
76
79template <class Mapping>
81{
82 mNChipsFiredROF = 0;
83 mNPixelsFiredROF = 0;
84 mInteractionRecord.clear();
85 if (mROFRampUpStage && mSkipRampUpData) {
86 return -1;
87 }
88 int nru = mRUDecodeVec.size();
89 int prevNTrig = mExtTriggers.size();
90 do {
91#ifdef WITH_OPENMP
92#pragma omp parallel for schedule(dynamic) num_threads(mNThreads)
93#endif
94 for (int iru = 0; iru < nru; iru++) {
95 collectROFCableData(iru);
96 }
97
98 mROFCounter++;
99
100 if (!doIRMajorityPoll()) {
101 continue; // no links with data
102 }
103
104#ifdef WITH_OPENMP
105#pragma omp parallel for schedule(dynamic) num_threads(mNThreads) reduction(+ \
106 : 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 } else if (link.status == GBTLink::StoppedOnEndOfData || link.status == GBTLink::AbortedOnError) {
190 link.statusInTF = GBTLink::StoppedOnEndOfData;
191 if (mVerbosity >= GBTLink::Verbosity::VerboseHeaders) {
192 LOGP(info, "doIRMajorityPoll: {} DONE, status = {}", link.describe(), int(link.status));
193 }
194 mNLinksDone++;
195 }
196 }
197 }
198 int majIR = -1;
199 for (const auto& entIR : mIRPoll) {
200 if (entIR.second > majIR) {
201 majIR = entIR.second;
202 mInteractionRecord = entIR.first;
203 }
204 }
205 mInteractionRecordHB = mInteractionRecord;
206 if (mInteractionRecord.isDummy()) {
207 if (mVerbosity >= GBTLink::Verbosity::VerboseHeaders) {
208 LOG(info) << "doIRMajorityPoll: did not find any valid IR";
209 }
210 return false;
211 }
212 mInteractionRecordHB.bc = 0;
213 if (mVerbosity >= GBTLink::Verbosity::VerboseHeaders) {
214 LOG(info) << "doIRMajorityPoll: " << mInteractionRecordHB.asString() << " majority = " << majIR << " for " << mNLinksInTF << " links seen, LinksDone = " << mNLinksDone;
215 }
216 return true;
217}
218
221template <class Mapping>
223{
224 constexpr uint32_t ROF_RAMP_FLAG = 0x1 << 4;
225 constexpr uint32_t LINK_RECOVERY_FLAG = 0x1 << 5;
226 mNLinksInTF = 0;
227 mCurRUDecodeID = NORUDECODED;
228 auto nLinks = mGBTLinks.size();
229 auto origin = (mUserDataOrigin == o2::header::gDataOriginInvalid) ? mMAP.getOrigin() : mUserDataOrigin;
230 auto datadesc = (mUserDataDescription == o2::header::gDataDescriptionInvalid) ? o2::header::gDataDescriptionRawData : mUserDataDescription;
231 std::vector<InputSpec> filter{InputSpec{"filter", ConcreteDataTypeMatcher{origin, datadesc}}};
232
233 // if we see requested data type input with 0xDEADBEEF subspec and 0 payload this means that the "delayed message"
234 // mechanism created it in absence of real data from upstream. Processor should send empty output to not block the workflow
235 {
236 static size_t contDeadBeef = 0; // number of times 0xDEADBEEF was seen continuously
237 std::vector<InputSpec> dummy{InputSpec{"dummy", ConcreteDataMatcher{origin, datadesc, 0xDEADBEEF}}};
238 for (const auto& ref : InputRecordWalker(inputs, dummy)) {
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) : "");
247 }
248 return;
249 }
250 }
251 contDeadBeef = 0; // if good data, reset the counter
252 }
253 mROFRampUpStage = false;
254 DPLRawParser parser(inputs, filter, o2::conf::VerbosityConfig::Instance().rawParserSeverity);
255 parser.setMaxFailureMessages(o2::conf::VerbosityConfig::Instance().maxWarnRawParser);
256 static size_t cntParserFailures = 0;
257 parser.setExtFailureCounter(&cntParserFailures);
258
259 uint32_t currSSpec = 0xffffffff; // dummy starting subspec
260 int linksAdded = 0;
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()); // RSTODO this is a hack in absence of generic header getter
265
266 if (lnkref.entry == -1) { // new link needs to be added
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;
270 lnk.wordLength = (lnk.expectPadding = (RDHUtils::getDataFormat(rdh) == 0)) ? o2::itsmft::GBTPaddedWordLength : o2::itsmft::GBTWordLength;
271 getCreateRUDecode(mMAP.FEEId2RUSW(RDHUtils::getFEEID(rdh))); // make sure there is a RU for this link
272 lnk.verbosity = GBTLink::Verbosity(mVerbosity);
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));
276 }
277 linksAdded++;
278 }
279 auto& link = mGBTLinks[lnkref.entry];
280 if (currSSpec != dh->subSpecification) { // this is the 1st part for this link in this TF, next parts must follow contiguously!!!
281 currSSpec = dh->subSpecification;
282 if (link.statusInTF != GBTLink::None) {
283 static bool errorDone = false;
284 if (!errorDone) {
285 LOGP(error, "{} was already registered, inform PDP on-call about error!!!", link.describe());
286 errorDone = true;
287 }
288 }
289 link.statusInTF = GBTLink::DataSeen;
290 mNLinksInTF++;
291 }
292 auto detField = RDHUtils::getDetectorField(&rdh);
293 if (detField & ROF_RAMP_FLAG) {
294 mROFRampUpStage = true;
295 }
296 if ((detField & LINK_RECOVERY_FLAG) && (link.statusInTF != GBTLink::Recovery)) {
297 link.statusInTF = GBTLink::Recovery; // data will be discarded
298 link.rawData.clear();
300 link.accountLinkRecovery(RDHUtils::getHeartBeatIR(rdh));
301 mNLinksInTF--;
302 }
303 if (link.statusInTF != GBTLink::Recovery) {
304 link.cacheData(it.raw(), RDHUtils::getMemorySize(rdh));
305 }
306 }
307
308 if (linksAdded) { // new links were added, update link<->RU mapping, usually is done for 1st TF only
309 if (nLinks) {
310 if (mVerbosity >= GBTLink::Verbosity::VerboseHeaders) {
311 LOG(warn) << mSelfName << " New links appeared although the initialization was already done";
312 }
313 for (auto& ru : mRUDecodeVec) { // reset RU->link references since they may have been changed
314 memset(&ru.links[0], -1, RUDecodeData::MaxLinksPerRU * sizeof(int));
315 memset(&ru.cableLinkPtr[0], 0, RUDecodeData::MaxCablesPerRU * sizeof(GBTLink*));
316 }
317 }
318 // sort RUs in stave increasing order
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;
322 }
323 nLinks = mGBTLinks.size();
324 // attach link to corresponding RU: this can be done once all RUs are created, to make sure their pointers don't change
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)); // link to RU reference, reattach even it was already set before
329 uint16_t lr, ruOnLr, linkInRU;
330 mMAP.expandFEEId(link.feeID, lr, ruOnLr, linkInRU);
331 if (newLinkAdded) {
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 << ')';
334 }
335 }
336 link.idInRU = linkInRU;
337 link.ruPtr->links[linkInRU] = il; // RU to link reference
338 link.ruPtr->nLinks++;
339 }
340 }
341 // set the link extracting triggers
342 for (auto& link : mGBTLinks) {
343 if (link.statusInTF == GBTLink::DataSeen) { // designate 1st link with valid data to register triggers
344 link.extTrigVec = &mExtTriggers;
345 mLinkForTriggers = &link;
346 break;
347 }
348 }
349}
350
353template <class Mapping>
355{
356 assert(ruSW < mMAP.getNRUs());
357 if (mRUEntry[ruSW] < 0) {
358 mRUEntry[ruSW] = mRUDecodeVec.size();
359 auto& ru = mRUDecodeVec.emplace_back();
360 ru.ruSWID = ruSW;
361 ru.ruInfo = mMAP.getRUInfoSW(ruSW); // info on the stave/RU
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];
366 }
367 }
368 return mRUDecodeVec[mRUEntry[ruSW]];
369}
370
372template <class Mapping>
373ChipPixelData* RawPixelDecoder<Mapping>::getNextChipData(std::vector<ChipPixelData>& chipDataVec)
374{
375 // decode new RU if no cached non-empty chips
376 for (; mCurRUDecodeID < mRUDecodeVec.size(); mCurRUDecodeID++) {
377 auto& ru = mRUDecodeVec[mCurRUDecodeID];
378 if (ru.lastChipChecked < ru.nChipsFired) {
379 auto& chipData = ru.chipsData[ru.lastChipChecked++];
380 // assert(mLastReadChipID < chipData.getChipID());
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);
388 }
389 }
390 continue;
391 }
392 mLastReadChipID = chipData.getChipID();
393 chipDataVec[mLastReadChipID].swap(chipData);
394 return &chipDataVec[mLastReadChipID];
395 }
396 }
397 // will need to decode new trigger
398 if (!mDecodeNextAuto || decodeNextTrigger() < 0) { // no more data to decode
399 return nullptr;
400 }
401 return getNextChipData(chipDataVec);
402}
403
405template <class Mapping>
407{
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());
414 mLastReadChipID = chipData.getChipID();
415 chipData.swap(ruchip);
416 return true;
417 }
418 }
419 // will need to decode new trigger
420 if (!mDecodeNextAuto || decodeNextTrigger() < 0) { // no more data to decode
421 return false;
422 }
423 return getNextChipData(chipData); // is it ok to use recursion here?
424}
425
427template <>
429{
430 mOrderedChipsPtr.clear();
431 // define looping order, if mCurRUDecodeID < mRUDecodeVec.size(), this means that decodeNextTrigger() was called before
432 if (mCurRUDecodeID < mRUDecodeVec.size()) { // define sort order
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++]);
437 }
438 }
439 // sort in decreasing order
440 std::sort(mOrderedChipsPtr.begin(), mOrderedChipsPtr.end(), [](const ChipPixelData* a, const ChipPixelData* b) { return a->getChipID() > b->getChipID(); });
441 }
442}
443
445template <>
446ChipPixelData* RawPixelDecoder<ChipMappingMFT>::getNextChipData(std::vector<ChipPixelData>& chipDataVec)
447{
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];
455 }
456 // will need to decode new trigger
457 if (!mDecodeNextAuto || decodeNextTrigger() < 0) { // no more data to decode
458 return nullptr;
459 }
460 return getNextChipData(chipDataVec);
461}
462
464template <>
466{
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();
473 return true;
474 }
475 // will need to decode new trigger
476 if (!mDecodeNextAuto || decodeNextTrigger() < 0) { // no more data to decode
477 return false;
478 }
479 return getNextChipData(chipData); // is it ok to use recursion here?
480}
481
483template <class Mapping>
485{
486 mVerbosity = v;
487 for (auto& link : mGBTLinks) {
488 link.verbosity = GBTLink::Verbosity(v);
489 }
490}
491
493template <class Mapping>
495{
496#ifdef WITH_OPENMP
497 mNThreads = n > 0 ? n : 1;
498#else
499 LOG(warning) << mSelfName << " Multithreading is not supported, imposing single thread";
500 mNThreads = 1;
501#endif
502}
503
505template <class Mapping>
507{
508 // clear statistics
509 for (auto& lnk : mGBTLinks) {
510 lnk.clear(true, resetRaw);
511 }
512 mNChipsFiredROF = mNPixelsFiredROF = 0;
513 mNChipsFired = mNPixelsFired = mNExtTriggers = 0;
514}
515
517template <class Mapping>
519{
520 size_t outSize = 0;
521 bool dumpFullTF = false;
522 for (auto& ru : mRUDecodeVec) {
523 if (ru.linkHBFToDump.size()) {
524 if (dump == int(GBTLink::RawDataDumps::DUMP_TF)) {
525 dumpFullTF = true;
526 break;
527 }
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;
533 std::string fnm;
534 if (entry >= lnk.rawData.getNPieces()) {
535 allHBFs = true;
536 entry = 0;
537 fnm = fmt::format("{}{}rawdump_{}_run{}_tf_orb{}_full_feeID{:#06x}.raw", mRawDumpDirectory, mRawDumpDirectory.empty() ? "" : "/",
538 Mapping::getName(), tinfo.runNumber, tinfo.firstTForbit, lnk.feeID);
539 } else {
540 fnm = fmt::format("{}{}rawdump_{}_run{}_tf_orb{}_hbf_orb{}_feeID{:#06x}.raw", mRawDumpDirectory, mRawDumpDirectory.empty() ? "" : "/",
541 Mapping::getName(), tinfo.runNumber, tinfo.firstTForbit, it.second, lnk.feeID);
542 }
543 std::ofstream ostrm(fnm, std::ios::binary);
544 if (!ostrm.good()) {
545 LOG(error) << "failed to open " << fnm;
546 continue;
547 }
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) {
551 break;
552 }
553 ostrm.write(reinterpret_cast<const char*>(piece->data), piece->size);
554 outSize += piece->size;
555 entry++;
556 }
557 LOG(info) << "produced " << std::filesystem::current_path().c_str() << '/' << fnm;
558 }
559 }
560 }
561 }
562 while (dumpFullTF) {
563 std::string fnm = fmt::format("rawdump_{}_run{}_tf_orb{}_full.raw",
564 Mapping::getName(), tinfo.runNumber, tinfo.firstTForbit);
565 std::ofstream ostrm(fnm, std::ios::binary);
566 if (!ostrm.good()) {
567 LOG(error) << "failed to open " << fnm;
568 break;
569 }
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;
575 }
576 }
577 LOG(info) << "produced " << std::filesystem::current_path().c_str() << '/' << fnm;
578 break;
579 }
580 return outSize;
581}
582
584template <class Mapping>
586{
587 mTimerTFStart.Reset();
588 mTimerDecode.Reset();
589 mTimerFetchData.Reset();
590 for (auto& ru : mRUDecodeVec) {
591 for (auto& cab : ru.cableData) {
592 cab.clear();
593 }
594 }
595 for (auto& link : mGBTLinks) {
596 link.rofJumpWasSeen = false;
597 link.statusInTF = GBTLink::None;
598 }
599 clearStat(true);
600}
601
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
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
Definition glcorearb.h:1308
GLboolean GLboolean GLboolean GLboolean a
Definition glcorearb.h:1233
constexpr o2::header::DataDescription gDataDescriptionInvalid
Definition DataHeader.h:596
constexpr o2::header::DataOrigin gDataOriginInvalid
Definition DataHeader.h:561
constexpr o2::header::DataDescription gDataDescriptionRawData
Definition DataHeader.h:597
uint8_t itsSharedClusterMap uint8_t
consteval header::DataOrigin origin()
Definition ASoA.h:345
Defining PrimaryVertex explicitly as messageable.
Definition TFIDInfo.h:20
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"