Project
Loading...
Searching...
No Matches
HmpidDecoder2.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
18
19/* ------ HISTORY ---------
2024/01/2024 - review of pointer management from the stream AF
21 */
22
23#include <fairlogger/Logger.h> // for LOG
24#include "Framework/Logger.h"
29
30using namespace o2::hmpid;
31
32// ============= HmpidDecoder Class implementation =======
33
35char HmpidDecoder2::sErrorDescription[MAXERRORS][MAXDESCRIPTIONLENGHT] = {"Word that I don't known !",
36 "Row Marker Word with 0 words",
37 "Duplicated Pad Word !",
38 "Row Marker Wrong/Lost -> to EoE",
39 "Row Marker Wrong/Lost -> to EoE",
40 "Row Marker reports an ERROR !",
41 "Lost EoE Marker !",
42 "Double EoE marker",
43 "Wrong size definition in EoE Marker",
44 "Double Mark Word", "Wrong Size in Segment Marker",
45 "Lost EoS Marker !",
46 "HMPID Header Errors"};
47
50 "L1-Trigger received without L0",
51 "L1-Trigger received before the L1-Latency",
52 "L1-Trigger received after the L1-Time-Latency-Window",
53 "L1-Trigger after L1-Message or after timeout (12.8us)",
54 "L1-Message before L1-Trigger or after timeout (12.8us)"};
55
61HmpidDecoder2::HmpidDecoder2(int numOfEquipments)
62{
63 mNumberOfEquipments = numOfEquipments;
64 for (int i = 0; i < mNumberOfEquipments; i++) {
66 }
67}
68
78HmpidDecoder2::HmpidDecoder2(int* EqIds, int* CruIds, int* LinkIds, int numOfEquipments)
79{
80 mNumberOfEquipments = numOfEquipments;
81 for (int i = 0; i < mNumberOfEquipments; i++) {
82 mTheEquipments[i] = new HmpidEquipment(EqIds[i], CruIds[i], LinkIds[i]);
83 }
84}
85
88{
89 for (int i = 0; i < mNumberOfEquipments; i++) {
90 delete mTheEquipments[i];
91 }
92}
93
96{
97 mVerbose = 0;
98
99 mRDHSize = sizeof(o2::header::RAWDataHeader) / sizeof(uint32_t);
100
101 mHeEvent = 0;
102 mHeBusy = 0;
104 mPayloadTail = 0;
105
106 mHeFEEID = 0;
107 mHeSize = 0;
108 mHeVer = 0;
109 mHePrior = 0;
110 mHeStop = 0;
111 mHePages = 0;
112 mEquipment = 0;
113
115 mHeMemorySize = 0;
116
117 mHeDetectorID = 0;
118 mHeDW = 0;
119 mHeCruID = 0;
120 mHePackNum = 0;
121 mHePAR = 0;
122 mHePageNum = 0;
123 mHeLinkNum = 0;
125 mHeHmpidError = 0;
126 mHeBCDI = 0;
127 mHeORBIT = 0;
128 mHeTType = 0;
129
130 mActualStreamPtr = nullptr;
131 mEndStreamPtr = nullptr;
132 mStartStreamPtr = nullptr;
133
134 for (int i = 0; i < mNumberOfEquipments; i++) {
138 }
139
140 mDigits.clear();
141}
142
148int HmpidDecoder2::getEquipmentIndex(int CruId, int LinkId)
149{
150 for (int i = 0; i < mNumberOfEquipments; i++) {
151 if (mTheEquipments[i]->getEquipmentId(CruId, LinkId) != -1) {
152 return (i);
153 }
154 }
155 return (-1);
156}
157
163{
164 for (int i = 0; i < mNumberOfEquipments; i++) {
165 if (mTheEquipments[i]->getEquipmentId() == EquipmentId) {
166 return (i);
167 }
168 }
169 return (-1);
170}
171
176int HmpidDecoder2::getEquipmentID(int CruId, int LinkId)
177{
178 for (int i = 0; i < mNumberOfEquipments; i++) {
179 if (mTheEquipments[i]->getEquipmentId(CruId, LinkId) != -1) {
180 return (mTheEquipments[i]->getEquipmentId());
181 }
182 }
183 return (-1);
184}
185
194int HmpidDecoder2::checkType(uint32_t wp, int* p1, int* p2, int* p3, int* p4)
195{
196 if ((wp & 0x0000ffff) == 0x000036A8 || (wp & 0x0000ffff) == 0x000032A8 || (wp & 0x0000ffff) == 0x000030A0 || (wp & 0x0800ffff) == 0x080010A0) {
197 *p2 = (wp & 0x03ff0000) >> 16; // Number of words of row
198 *p1 = wp & 0x0000ffff;
199 return (WTYPE_ROW);
200 }
201 if ((wp & 0xfff00000) >> 20 == 0xAB0) {
202 *p2 = (wp & 0x000fff00) >> 8; // Number of words of Segment
203 *p1 = (wp & 0xfff00000) >> 20;
204 *p3 = wp & 0x0000000F;
205 if (*p3 < 4 && *p3 > 0) {
206 return (WTYPE_EOS);
207 }
208 }
209 // #EX MASK Raul 0x3803FF80 # ex mask 0xF803FF80 - this is EoE marker 0586800B0
210 if ((wp & 0x0803FF80) == 0x08000080) {
211 *p1 = (wp & 0x07c00000) >> 22;
212 *p2 = (wp & 0x003C0000) >> 18;
213 *p3 = (wp & 0x0000007F);
214 if (*p1 < 25 && *p2 < 11) {
215 return (WTYPE_EOE);
216 }
217 }
218 if ((wp & 0x08000000) == 0) { // # this is a pad
219 // PAD:0000.0ccc.ccdd.ddnn.nnnn.vvvv.vvvv.vvvv :: c=col,d=dilo,n=chan,v=value
220 *p1 = (wp & 0x07c00000) >> 22;
221 *p2 = (wp & 0x003C0000) >> 18;
222 *p3 = (wp & 0x0003F000) >> 12;
223 *p4 = (wp & 0x00000FFF);
224 if (*p1 > 0 && *p1 < 25 && *p2 > 0 && *p2 < 11 && *p3 < 48) {
225 return (WTYPE_PAD);
226 }
227 } else {
228 return (WTYPE_NONE);
229 }
230 return (WTYPE_NONE);
231}
232
239bool HmpidDecoder2::isRowMarker(uint32_t wp, int* Err, int* rowSize, int* mark)
240{
241 if ((wp & 0x0000ffff) == 0x36A8 || (wp & 0x0000ffff) == 0x32A8 || (wp & 0x0000ffff) == 0x30A0 || (wp & 0x0800ffff) == 0x080010A0) {
242 *rowSize = (wp & 0x03ff0000) >> 16; // # Number of words of row
243 *mark = wp & 0x0000ffff;
244 *Err = false;
245 return (true);
246 } else {
247 *Err = true;
248 return (false);
249 }
250}
251
259bool HmpidDecoder2::isSegmentMarker(uint32_t wp, int* Err, int* segSize, int* Seg, int* mark)
260{
261 *Err = false;
262 if ((wp & 0xfff00000) >> 20 == 0xAB0) {
263 *segSize = (wp & 0x000fff00) >> 8; // # Number of words of Segment
264 *mark = (wp & 0xfff00000) >> 20;
265 *Seg = wp & 0x0000000F;
266 if (*Seg > 3 || *Seg < 1) {
267 if (mVerbose > 6) {
268 std::cout << "HMPID Decoder2 : [INFO] "
269 << " Wrong segment Marker Word, bad Number of segment" << *Seg << "!" << std::endl;
270 }
271 *Err = true;
272 }
273 return (true);
274 } else {
275 return (false);
276 }
277}
278
288bool HmpidDecoder2::isPadWord(uint32_t wp, int* Err, int* Col, int* Dilogic, int* Channel, int* Charge)
289{
290 *Err = false;
291 // if ((wp & 0x08000000) != 0) {
292 if ((wp & 0x08000000) != 0) {
293 return (false);
294 }
295 *Col = (wp & 0x07c00000) >> 22;
296 *Dilogic = (wp & 0x003C0000) >> 18;
297 *Channel = (wp & 0x0003F000) >> 12;
298 *Charge = (wp & 0x00000FFF);
299 uint16_t mark, row;
300 mark = wp & 0x0ffff;
301 row = (wp & 0x03ff0000) >> 16;
302
303 if (mark == 0x036A8 || mark == 0x032A8 || mark == 0x030A0 || mark == 0x010A0) { // # ! this is a pad
304 if (*Dilogic > 10 || *Channel > 47 || *Dilogic < 1 || *Col > 24 || *Col < 1 || row <= 490 || row > 10) {
305 return (false);
306 }
307 } else {
308 if (*Dilogic > 10 || *Channel > 47 || *Dilogic < 1 || *Col > 24 || *Col < 1) {
309 // LOG_WARNING << " Wrong Pad values Col=" << *Col << " Dilogic=" << *Dilogic << " Channel=" << *Channel << " Charge=" << *Charge << " wp:0x" << std::hex << wp << std::dec;
310 *Err = true;
311 return (false);
312 }
313 }
314 return (true);
315}
316
324bool HmpidDecoder2::isEoEmarker(uint32_t wp, int* Err, int* Col, int* Dilogic, int* Eoesize)
325{
326 *Err = false;
327 // #EX MASK Raul 0x3803FF80 # ex mask 0xF803FF80 - this is EoE marker 0586800B0
328 if ((wp & 0x0803FF80) == 0x08000080) {
329 *Col = (wp & 0x07c00000) >> 22;
330 *Dilogic = (wp & 0x003C0000) >> 18;
331 *Eoesize = (wp & 0x0000007F);
332 if (*Col > 24 || *Dilogic > 10) {
333 if (mVerbose > 8) {
334 std::cout << "HMPID Decoder2 : [DEBUG] "
335 << " EoE size wrong definition. Col=" << *Col << " Dilogic=" << *Dilogic << std::endl;
336 }
337 *Err = true;
338 }
339 return (true);
340 } else {
341 return (false);
342 }
343}
344
351bool HmpidDecoder2::decodeHmpidError(int ErrorField, char* outbuf)
352{
353 int res = false;
354 outbuf[0] = '\0';
355 for (int i = 0; i < MAXHMPIDERRORS; i++) {
356 if ((ErrorField & (0x01 << i)) != 0) {
357 res = true;
358 strcat(outbuf, sHmpidErrorDescription[i]);
359 }
360 }
361 return (res);
362}
363
377int HmpidDecoder2::decodeHeader(uint32_t* streamPtrAdr, int* EquipIndex)
378{
379 uint32_t* buffer = streamPtrAdr; // Sets the pointer to buffer
381
382 mHeFEEID = hpt->feeId;
383 mHeSize = hpt->headerSize;
384 mHeVer = hpt->version;
385 mHePrior = hpt->priority;
386 mHeDetectorID = hpt->sourceID;
389 mHeDW = hpt->endPointID;
390 mHeCruID = hpt->cruID;
392 mHeLinkNum = hpt->linkID;
393 mHeBCDI = hpt->bunchCrossing;
394 mHeORBIT = hpt->orbit;
395 mHeTType = hpt->triggerType;
396 mHePageNum = hpt->pageCnt;
397 mHeStop = hpt->stop;
398 mHeBusy = (hpt->detectorField & 0xfffffe00) >> 9;
399 mHeFirmwareVersion = hpt->detectorField & 0x0000000f;
400 mHeHmpidError = (hpt->detectorField & 0x000001F0) >> 4;
401 mHePAR = hpt->detectorPAR;
402
403 *EquipIndex = getEquipmentIndex(mHeCruID, mHeLinkNum);
404 mEquipment = mHeFEEID & 0x000F;
405 mNumberWordToRead = ((mHeMemorySize - mHeSize) / sizeof(uint32_t));
406 mPayloadTail = ((mHeOffsetNewPack - mHeMemorySize) / sizeof(uint32_t));
407
408 // ---- Event ID : Actualy based on ORBIT NUMBER and BC
409 mHeEvent = (mHeORBIT << 12) | mHeBCDI;
410 if (mVerbose > 6 || (*EquipIndex == -1 && mVerbose > 1)) {
411 std::cout << "HMPID Decoder2 : [INFO] "
412 << "FEE-ID=" << mHeFEEID << " HeSize=" << mHeSize << " HePrior=" << mHePrior << " Det.Id=" << mHeDetectorID << " HeMemorySize=" << mHeMemorySize << " HeOffsetNewPack=" << mHeOffsetNewPack << std::endl;
413 std::cout << " Equipment=" << mEquipment << " PakCounter=" << mHePackNum << " Link=" << mHeLinkNum << " CruID=" << mHeCruID << " DW=" << mHeDW << " BC=" << mHeBCDI << " ORBIT=" << mHeORBIT << std::endl;
414 std::cout << " TType=" << mHeTType << " HeStop=" << mHeStop << " PagesCounter=" << mHePageNum << " FirmVersion=" << mHeFirmwareVersion << " BusyTime=" << mHeBusy << " Error=" << mHeHmpidError << " PAR=" << mHePAR << std::endl;
415 std::cout << " EquIdx = " << *EquipIndex << " Event = " << mHeEvent << " Payload : Words to read=" << mNumberWordToRead << " PailoadTail=" << mPayloadTail << std::endl;
416 }
417 if (*EquipIndex == -1) {
418 if (mVerbose > 1) {
419 std::cout << "HMPID Decoder2 : [ERROR] "
420 << "ERROR ! Bad equipment Number: " << mEquipment << std::endl;
421 }
422 throw TH_WRONGEQUIPINDEX;
423 }
424 if (mHeDetectorID != 0x06) {
425 if (mVerbose > 1) {
426 std::cout << "HMPID Decoder2 : [ERROR] "
427 << "ERROR ! Bad Detector Id Number: " << mHeDetectorID << std::endl;
428 }
429 throw TH_WRONGHEADER;
430 }
431 return (true);
432}
433
438{
440 eq->mEventSizeAverage = ((eq->mEventSizeAverage * (eq->mNumberOfEvents - 1)) + eq->mEventSize) / (eq->mNumberOfEvents);
442 if (eq->mSampleNumber == 0) {
443 eq->mNumberOfEmptyEvents += 1;
444 }
445 if (eq->mErrorsCounter > 0) {
446 eq->mNumberOfWrongEvents += 1;
447 }
448 eq->mTotalPads += eq->mSampleNumber;
449 eq->mTotalErrors += eq->mErrorsCounter;
450
451 return;
452}
453
459{
460 if (EquipmentIndex < 0 || EquipmentIndex > 13) {
461 if (mVerbose > 1) {
462 std::cout << "HMPID Decoder2 : [ERROR] "
463 << "Bad Equipment number !" << EquipmentIndex << std::endl;
464 }
465 throw TH_WRONGEQUIPINDEX;
466 }
467 HmpidEquipment* eq = mTheEquipments[EquipmentIndex];
468 if (mHeEvent != eq->mEventNumber) { // Is a new event
469 if (eq->mEventNumber != OUTRANGEEVENTNUMBER) { // skip the first
470 updateStatistics(eq); // update previous statistics
471 }
472 eq->mNumberOfEvents++;
474 eq->mBusyTimeValue = mHeBusy * 0.00000005;
475 eq->mEventSize = 0; // reset the event
476 eq->mSampleNumber = 0;
477 eq->mErrorsCounter = 0;
478 mIntReco = {(uint16_t)mHeBCDI, (uint32_t)mHeORBIT};
479 }
480 eq->mEventSize += mNumberWordToRead * sizeof(uint32_t); // Calculate the size in bytes
481 if (mHeHmpidError != 0) {
482 std::cout << "HMPID Header reports an error : " << mHeHmpidError << std::endl;
484 eq->setError(ERR_HMPID);
485 }
486 return (eq);
487}
488
494void HmpidDecoder2::decodePage(uint32_t** streamBuf)
495{
496 mActualStreamPtr = *streamBuf;
497 int equipmentIndex;
498 try {
499 getHeaderFromStream(streamBuf);
500 } catch (int e) {
501 // The stream end !
502 if (mVerbose > 8) {
503 std::cout << "HMPID Decoder2 : [DEBUG] "
504 << "End main decoding loop !" << std::endl;
505 }
506 throw TH_BUFFEREMPTY;
507 }
508 try {
509 decodeHeader(*streamBuf, &equipmentIndex);
510 } catch (int e) {
511 if (mVerbose > 1) {
512 std::cout << "HMPID Decoder2 : [ERROR] "
513 << "Failed to decode the Header !" << std::endl;
514 }
515 throw TH_WRONGHEADER;
516 }
517 HmpidEquipment* eq;
518 try {
519 eq = evaluateHeaderContents(equipmentIndex);
520 } catch (int e) {
521 throw TH_WRONGHEADER;
522 }
523
524 uint32_t wpprev = 0;
525 uint32_t wp = 0;
526 int newOne = true;
527 int p1, p2, p3, p4;
528 int error;
529 int type;
530 bool isIt;
531
532 int payIndex = 0;
533 while (payIndex < mNumberWordToRead) { // start the payload loop word by word
534 if (newOne == true) {
535 wpprev = wp;
536 wp = readWordFromStream();
537 type = checkType(wp, &p1, &p2, &p3, &p4);
538 if (type == WTYPE_NONE) {
539 if (eq->mWillBePad == true) { // try to recover the first pad !
540 type = checkType((wp & 0xF7FFFFFF), &p1, &p2, &p3, &p4);
541 if (type == WTYPE_PAD && p3 == 0 && eq->mWordsPerDilogicCounter == 0) {
542 newOne = false; // # reprocess as pad
543 continue;
544 }
545 }
549 payIndex++;
550 continue;
551 }
552 }
553 if (mEquipment == 8) {
554 if (mVerbose > 6) {
555 std::cout << "HMPID Decoder2 : [INFO] "
556 "Event"
557 << eq->mEventNumber << " >" << std::hex << wp << std::dec << "<" << type << std::endl;
558 }
559 }
560 if (eq->mWillBeRowMarker == true) { // #shoud be a Row Marker
561 if (type == WTYPE_ROW) {
562 eq->mColumnCounter++;
564 eq->mRowSize = p2;
565 switch (p2) {
566 case 0: // Empty column
568 eq->mWillBeRowMarker = true;
569 break;
570 case 0x3FF: // Error in column
572 eq->mWillBeRowMarker = true;
573 break;
574 case 0x3FE: // Masked column
575 if (mVerbose > 6) {
576 std::cout << "HMPID Decoder2 : [INFO] "
577 << "Equip=" << mEquipment << "The column=" << (eq->mSegment) * 8 + eq->mColumnCounter << " is Masked !" << std::endl;
578 }
579 eq->mWillBeRowMarker = true;
580 break;
581 default:
582 eq->mWillBeRowMarker = false;
583 eq->mWillBePad = true;
584 break;
585 }
586 newOne = true;
587 } else {
588 if (wp == wpprev) {
590 newOne = true;
591 } else if (type == WTYPE_EOE) { // # Could be a EoE
592 eq->mColumnCounter++;
594 eq->mWillBeRowMarker = false;
595 eq->mWillBePad = true;
596 newOne = true;
597 } else if (type == WTYPE_PAD) { //# Could be a PAD
598 eq->mColumnCounter++;
600 eq->mWillBeRowMarker = false;
601 eq->mWillBePad = true;
602 newOne = true;
603 } else if (type == WTYPE_EOS) { // # Could be a EoS
604 eq->mWillBeRowMarker = false;
605 eq->mWillBeSegmentMarker = true;
606 newOne = false;
607 } else {
608 eq->mColumnCounter++;
610 eq->mWillBeRowMarker = false;
611 eq->mWillBePad = true;
612 newOne = true;
613 }
614 }
615 } else if (eq->mWillBePad == true) { // # We expect a pad
616 //# PAD:0000.0ccc.ccdd.ddnn.nnnn.vvvv.vvvv.vvvv :: c=col,d=dilo,n=chan,v=value
617 // c = 1..24 d = 1..10 n = 0..47
618 if (type == WTYPE_PAD) {
619 newOne = true;
620 if (wp == wpprev) {
622 } else if (p1 != (eq->mSegment * 8 + eq->mColumnCounter)) { // # Manage
623 // We try to recover the RowMarker misunderstanding
624 isIt = isRowMarker(wp, &error, &p2, &p1);
625 if (isIt == true && error == false) {
626 type = WTYPE_ROW;
627 newOne = false;
628 eq->mWillBeEoE = true;
629 eq->mWillBePad = false;
630 } else {
631 eq->mColumnCounter = p1 % 8;
632 }
633 } else {
634 setPad(eq, p1 - 1, p2 - 1, p3, p4);
635 if (mEquipment == 8) {
636 if (mVerbose > 6) {
637 std::cout << "HMPID Decoder2 : [INFO] "
638 << "Event" << eq->mEventNumber << " >" << p1 - 1 << "," << p2 - 1 << "," << p3 << "," << p4 << std::endl;
639 }
640 }
642 eq->mSampleNumber++;
643 if (p3 == 47) {
644 eq->mWillBeEoE = true;
645 eq->mWillBePad = false;
646 }
647 }
650 } else if (type == WTYPE_EOE) { //# the pads are end ok
651 eq->mWillBeEoE = true;
652 eq->mWillBePad = false;
653 newOne = false;
654 } else if (type == WTYPE_ROW) { // # We Lost the EoE !
655 // We try to recover the PAD misunderstanding
656 isIt = isPadWord(wp, &error, &p1, &p2, &p3, &p4);
657 if (isIt == true && error == false) {
658 type = WTYPE_PAD;
659 newOne = false; // # reprocess as pad
660 } else {
662 eq->mWillBeRowMarker = true;
663 eq->mWillBePad = false;
664 newOne = false;
665 }
666 } else if (type == WTYPE_EOS) { // # We Lost the EoE !
668 eq->mWillBeSegmentMarker = true;
669 eq->mWillBePad = false;
670 newOne = false;
671 }
672 } else if (eq->mWillBeEoE == true) { // # We expect a EoE
673 if (type == WTYPE_EOE) {
676 if (wpprev == wp) {
678 } else if (p3 != eq->mWordsPerDilogicCounter) {
680 }
682 if (p2 == 10) {
683 if (p1 % 8 != 0) { // # we expect the Row Marker
684 eq->mWillBeRowMarker = true;
685 } else {
686 eq->mWillBeSegmentMarker = true;
687 }
688 } else {
689 eq->mWillBePad = true;
690 }
691 eq->mWillBeEoE = false;
692 newOne = true;
693 } else if (type == WTYPE_EOS) { // We Lost the EoE !
695 eq->mWillBeSegmentMarker = true;
696 eq->mWillBeEoE = false;
697 newOne = false;
698 } else if (type == WTYPE_ROW) { //# We Lost the EoE !
700 eq->mWillBeRowMarker = true;
701 eq->mWillBeEoE = false;
702 newOne = false;
703 } else if (type == WTYPE_PAD) { // # We Lost the EoE !
704 int typb, p1b, p2b, p3b, p4b;
705 typb = checkType((wp | 0x08000000), &p1b, &p2b, &p3b, &p4b);
706 if (typb == WTYPE_EOE && p3b == 48) {
707 type = typb;
708 p1 = p1b;
709 p2 = p2b;
710 p3 = p3b;
711 p4 = p4b;
712 newOne = false; // # reprocess as EoE
713 } else {
715 eq->mWillBePad = true;
716 eq->mWillBeEoE = false;
717 newOne = false;
718 }
719 }
720 } else if (eq->mWillBeSegmentMarker == true) { // # We expect a EoSegment
721 if (wpprev == wp) {
723 newOne = true;
724 } else if (type == 2) {
725 if (abs(eq->mWordsPerSegCounter - p2) > 5) {
727 }
728 eq->mWordsPerSegCounter = 0;
729 eq->mWordsPerRowCounter = 0;
730 eq->mColumnCounter = 0;
731 eq->mSegment = p3 % 3;
732 eq->mWillBeRowMarker = true;
733 eq->mWillBeSegmentMarker = false;
734 newOne = true;
735 } else {
737 eq->mWillBeSegmentMarker = false;
738 eq->mWillBeRowMarker = true;
739 newOne = false;
740 }
741 }
742 if (newOne) {
743 payIndex += 1;
744 }
745 }
746 for (int i = 0; i < mPayloadTail; i++) { // move the pointer to skip the Payload Tail
747 wp = readWordFromStream();
748 }
749 *streamBuf = mActualStreamPtr;
750}
751
757{
758 // ---------resets the PAdMap-----------
759 for (int i = 0; i < mNumberOfEquipments; i++) {
763 }
764
765 uint32_t* streamBuf = mStartStreamPtr;
766 if (mVerbose > 8) {
767 std::cout << "HMPID Decoder2 : [DEBUG] "
768 << "Enter decoding !" << std::endl;
769 }
770
771 // Input Stream Main Loop
772 while (true) {
773 try {
774 decodePage(&streamBuf);
775 } catch (int e) {
776 if (mVerbose > 8) {
777 std::cout << "HMPID Decoder2 : [DEBUG] "
778 << "End main buffer decoding loop !" << std::endl;
779 }
780 break;
781 }
782 } // this is the end of stream
783
784 // cycle in order to update info for the last event
785 for (int i = 0; i < mNumberOfEquipments; i++) {
786 if (mTheEquipments[i]->mNumberOfEvents > 0) {
788 }
789 }
790 return (true);
791}
792
802void HmpidDecoder2::setPad(HmpidEquipment* eq, int col, int dil, int ch, uint16_t charge)
803{
804 eq->setPad(col, dil, ch, charge);
805 mDigits.push_back(o2::hmpid::Digit(charge, eq->getEquipmentId(), col, dil, ch));
806 // std::cout << "DI " << mDigits.back() << " "<<col<<","<< dil<<","<< ch<<"="<< charge<<std::endl;
807 return;
808}
809
815void HmpidDecoder2::decodePageFast(uint32_t** streamBuf)
816{
817 mActualStreamPtr = *streamBuf;
818 int equipmentIndex;
819 try {
820 getHeaderFromStream(streamBuf);
821 } catch (int e) {
822 // The stream end !
823 if (mVerbose > 6) {
824 std::cout << "HMPID Decoder2 : [INFO] "
825 << "End Fast Page decoding loop ! (" << e << ")" << std::endl;
826 }
827 throw TH_BUFFEREMPTY;
828 }
829 try {
830 decodeHeader(*streamBuf, &equipmentIndex);
831 } catch (int e) {
832 if (mVerbose > 6) {
833 std::cout << "HMPID Decoder2 : [INFO] "
834 << "Failed to decode the Header ! (" << e << ")" << std::endl;
835 }
836 throw e;
837 }
838 HmpidEquipment* eq;
839 try {
840 eq = evaluateHeaderContents(equipmentIndex);
841 } catch (int e) {
842 if (mVerbose > 6) {
843 std::cout << "HMPID Decoder2 : [INFO] "
844 << "Failed to evaluate the Header ! (" << e << ")" << std::endl;
845 }
846 throw e;
847 }
848 uint32_t wpprev = 0;
849 uint32_t wp = 0;
850 int newOne = true;
851 int Column, Dilogic, Channel, Charge;
852 int pwer;
853 int payIndex = 0;
854 while (payIndex < mNumberWordToRead) { // start the payload loop word by word
855 wpprev = wp;
856 wp = readWordFromStream();
857 if (wp == wpprev) {
858 if (mVerbose > 8) {
859 std::cout << "HMPID Decoder2 : [DEBUG] "
860 << "Equip=" << mEquipment << sErrorDescription[ERR_DUPLICATEPAD] << " col=" << (eq->mSegment) * 8 + eq->mColumnCounter << "[" << Column << "]" << std::endl;
861 }
862 } else {
863 if (isPadWord(wp, &pwer, &Column, &Dilogic, &Channel, &Charge) == true) {
864 if (pwer != true) {
865 if (!((equipmentIndex == 6 && Column == 16 && Dilogic == 10) || (equipmentIndex == 13 && Column == 18 && Dilogic == 2))) {
866 setPad(eq, Column - 1, Dilogic - 1, Channel, Charge);
867 eq->mSampleNumber++;
868 }
869 }
870 }
871 }
872 payIndex += 1;
873 }
874 for (int i = 0; i < mPayloadTail; i++) { // move the pointer to skip the Payload Tail
875 wp = readWordFromStream();
876 }
877 *streamBuf = mActualStreamPtr;
878 return;
879}
880
887{
888 bool isNotEmpty = true; // suppress the Error Decoding Superpage message in normal verbosity
889 // ---------resets the PAdMap-----------
890 for (int i = 0; i < mNumberOfEquipments; i++) {
893 }
894 uint32_t* streamBuf = mStartStreamPtr;
895 if (mVerbose > 6) {
896 std::cout << "HMPID Decoder2 : [INFO] "
897 << "Enter FAST decoding !" << std::endl;
898 }
899 // Input Stream Main Loop
900 while (true) {
901 try {
902 decodePageFast(&streamBuf);
903 } catch (int e) {
904 if (mVerbose > 6) { // print all the decode errors eccept the end buffer
905 std::cout << "HMPID Decoder2 : [ERROR] "
906 << "End Buffer Fast Decoding! Exit code error = " << e << std::endl;
907 isNotEmpty = false;
908 }
909 break;
910 }
911 }
912 // cycle in order to update info for the last event
913 for (int i = 0; i < mNumberOfEquipments; i++) {
914 if (mTheEquipments[i]->mNumberOfEvents > 0) {
916 }
917 }
918 return (isNotEmpty);
919}
920
921// =========================================================
922
928uint16_t HmpidDecoder2::getPadSamples(int Module, int Row, int Column)
929{
930 int e, c, d, h;
931 o2::hmpid::Digit::absolute2Equipment(Module, Row, Column, &e, &c, &d, &h);
932 int EqInd = getEquipmentIndex(e);
933 if (EqInd < 0) {
934 return (0);
935 }
936 return (mTheEquipments[EqInd]->mPadSamples[c][d][h]);
937}
938
944double HmpidDecoder2::getPadSum(int Module, int Row, int Column)
945{
946 int e, c, d, h;
947 o2::hmpid::Digit::absolute2Equipment(Module, Row, Column, &e, &c, &d, &h);
948 int EqInd = getEquipmentIndex(e);
949 if (EqInd < 0) {
950 return (0);
951 }
952 return (mTheEquipments[EqInd]->mPadSum[c][d][h]);
953}
954
960double HmpidDecoder2::getPadSquares(int Module, int Row, int Column)
961{
962 int e, c, d, h;
963 o2::hmpid::Digit::absolute2Equipment(Module, Row, Column, &e, &c, &d, &h);
964 int EqInd = getEquipmentIndex(e);
965 if (EqInd < 0) {
966 return (0);
967 }
968 return (mTheEquipments[EqInd]->mPadSquares[c][d][h]);
969}
970
977uint16_t HmpidDecoder2::getChannelSamples(int EquipmId, int Column, int Dilogic, int Channel)
978{
979 int EqInd = getEquipmentIndex(EquipmId);
980 if (EqInd < 0) {
981 return (0);
982 }
983 return (mTheEquipments[EqInd]->mPadSamples[Column][Dilogic][Channel]);
984}
985
992double HmpidDecoder2::getChannelSum(int EquipmId, int Column, int Dilogic, int Channel)
993{
994 int EqInd = getEquipmentIndex(EquipmId);
995 if (EqInd < 0) {
996 return (0);
997 }
998 return (mTheEquipments[EqInd]->mPadSum[Column][Dilogic][Channel]);
999}
1000
1007double HmpidDecoder2::getChannelSquare(int EquipmId, int Column, int Dilogic, int Channel)
1008{
1009 int EqInd = getEquipmentIndex(EquipmId);
1010 if (EqInd < 0) {
1011 return (0);
1012 }
1013 return (mTheEquipments[EqInd]->mPadSquares[Column][Dilogic][Channel]);
1014}
1015
1020{
1021 int EqInd = getEquipmentIndex(EquipmId);
1022 if (EqInd < 0) {
1023 return (0.0);
1024 }
1025 return (mTheEquipments[EqInd]->mEventSizeAverage);
1026}
1027
1032{
1033 int EqInd = getEquipmentIndex(EquipmId);
1034 if (EqInd < 0) {
1035 return (0.0);
1036 }
1037 return (mTheEquipments[EqInd]->mBusyTimeAverage);
1038}
1039
1040// ===================================================
1041// Methods to dump info
1042
1047{
1048 int EqInd = getEquipmentIndex(EquipmId);
1049 if (EqInd < 0) {
1050 return;
1051 }
1052 std::cout << "Dump Errors for the Equipment = " << EquipmId << std::endl;
1053 for (int i = 0; i < MAXERRORS; i++) {
1054 std::cout << sErrorDescription[i] << " = " << mTheEquipments[EqInd]->mErrors[i] << std::endl;
1055 }
1056 std::cout << " -------- " << std::endl;
1057 return;
1058}
1059
1064void HmpidDecoder2::dumpPads(int EquipmId, int type)
1065{
1066 int EqInd = getEquipmentIndex(EquipmId);
1067 if (EqInd < 0) {
1068 return;
1069 }
1070 int Module = EquipmId / 2;
1071 int StartRow = (EquipmId % 2 == 1) ? 80 : 0;
1072 int EndRow = (EquipmId % 2 == 1) ? 160 : 80;
1073 std::cout << "Dump Pads for the Equipment = " << EquipmId << std::endl;
1074 for (int c = 0; c < 144; c++) {
1075 for (int r = StartRow; r < EndRow; r++) {
1076 switch (type) {
1077 case 0:
1078 std::cout << getPadSamples(Module, r, c) << ",";
1079 break;
1080 case 1:
1081 std::cout << getPadSum(Module, r, c) << ",";
1082 break;
1083 case 2:
1084 std::cout << getPadSquares(Module, r, c) << ",";
1085 break;
1086 }
1087 }
1088 std::cout << std::endl;
1089 }
1090 std::cout << " -------- " << std::endl;
1091 return;
1092}
1093
1096void HmpidDecoder2::dumpHmpidError(HmpidEquipment* eq, int ErrorField, int mHeBCDI, int mHeORBIT)
1097{
1098 char printbuf[MAXHMPIDERRORS * MAXDESCRIPTIONLENGHT + 255];
1099 if (decodeHmpidError(ErrorField, printbuf) == true) {
1100 if (mVerbose > 1) {
1101 std::cout << "HMPID Decoder2 : [ERROR] "
1102 << "HMPID Error field = " << ErrorField << " : " << printbuf << std::endl;
1103 }
1104 LOG(warn) << "HMPID Header Error Field =" << ErrorField << " [" << printbuf << "]"
1105 << "Equi = " << eq->getEquipmentId() << " Event = " << eq->mEventNumber
1106 << " Orbit = " << mHeORBIT << " BC = " << mHeBCDI;
1107 }
1108 return;
1109}
1110
1114void HmpidDecoder2::dumpMemory(const void* MemoryStartPtr, std::size_t Dimension)
1115{
1116 const unsigned char* data = static_cast<const unsigned char*>(MemoryStartPtr);
1117 for (std::size_t i = 0; i < Dimension; i += 16) {
1118 std::cout << std::hex << std::setw(4) << std::setfill('0') << i << " : ";
1119 // Print hexadecimal values
1120 for (std::size_t j = 0; j < 16; ++j) {
1121 if (i + j < Dimension) {
1122 std::cout << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(data[i + j]) << " ";
1123 } else {
1124 std::cout << " ";
1125 }
1126 }
1127 // Print ASCII values
1128 std::cout << " - ";
1129 for (std::size_t j = 0; j < 16 && i + j < Dimension; ++j) {
1130 char ch = (data[i + j] >= 32 && data[i + j] <= 126) ? static_cast<char>(data[i + j]) : '.';
1131 std::cout << ch;
1132 }
1133 std::cout << std::endl;
1134 }
1135 return;
1136}
1137
1142void HmpidDecoder2::writeSummaryFile(char* summaryFileName)
1143{
1144 FILE* fs = fopen(summaryFileName, "w");
1145 if (fs == nullptr) {
1146 printf("Error opening the file %s !\n", summaryFileName);
1147 throw TH_CREATEFILE;
1148 }
1149
1150 fprintf(fs, "HMPID Readout Raw Data Decoding Summary File\n");
1151 fprintf(fs, "Equipment Id\t");
1152 for (int i = 0; i < Geo::MAXEQUIPMENTS; i++) {
1153 fprintf(fs, "%d\t", mTheEquipments[i]->getEquipmentId());
1154 }
1155 fprintf(fs, "\n");
1156
1157 fprintf(fs, "Number of events\t");
1158 for (int i = 0; i < Geo::MAXEQUIPMENTS; i++) {
1159 fprintf(fs, "%d\t", mTheEquipments[i]->mNumberOfEvents);
1160 }
1161 fprintf(fs, "\n");
1162
1163 fprintf(fs, "Average Event Size\t");
1164 for (int i = 0; i < Geo::MAXEQUIPMENTS; i++) {
1165 fprintf(fs, "%f\t", mTheEquipments[i]->mEventSizeAverage);
1166 }
1167 fprintf(fs, "\n");
1168
1169 fprintf(fs, "Total pads\t");
1170 for (int i = 0; i < Geo::MAXEQUIPMENTS; i++) {
1171 fprintf(fs, "%d\t", mTheEquipments[i]->mTotalPads);
1172 }
1173 fprintf(fs, "\n");
1174
1175 fprintf(fs, "Average pads per event\t");
1176 for (int i = 0; i < Geo::MAXEQUIPMENTS; i++) {
1177 fprintf(fs, "%f\t", mTheEquipments[i]->mPadsPerEventAverage);
1178 }
1179 fprintf(fs, "\n");
1180
1181 fprintf(fs, "Busy Time average\t");
1182 for (int i = 0; i < Geo::MAXEQUIPMENTS; i++) {
1183 fprintf(fs, "%e\t", mTheEquipments[i]->mBusyTimeAverage);
1184 }
1185 fprintf(fs, "\n");
1186
1187 fprintf(fs, "Event rate\t");
1188 for (int i = 0; i < Geo::MAXEQUIPMENTS; i++) {
1189 fprintf(fs, "%e\t", 1 / mTheEquipments[i]->mBusyTimeAverage);
1190 }
1191 fprintf(fs, "\n");
1192
1193 fprintf(fs, "Number of Empty Events\t");
1194 for (int i = 0; i < Geo::MAXEQUIPMENTS; i++) {
1195 fprintf(fs, "%d\t", mTheEquipments[i]->mNumberOfEmptyEvents);
1196 }
1197 fprintf(fs, "\n");
1198
1199 fprintf(fs, "-------------Errors--------------------\n");
1200 fprintf(fs, "Wrong events\t");
1201 for (int i = 0; i < Geo::MAXEQUIPMENTS; i++) {
1202 fprintf(fs, "%d\t", mTheEquipments[i]->mNumberOfWrongEvents);
1203 }
1204 fprintf(fs, "\n");
1205
1206 for (int j = 0; j < MAXERRORS; j++) {
1207 fprintf(fs, "%s\t", sErrorDescription[j]);
1208 for (int i = 0; i < Geo::MAXEQUIPMENTS; i++) {
1209 fprintf(fs, "%d\t", mTheEquipments[i]->mErrors[j]);
1210 }
1211 fprintf(fs, "\n");
1212 }
1213
1214 fprintf(fs, "Total errors\t");
1215 for (int i = 0; i < Geo::MAXEQUIPMENTS; i++) {
1216 fprintf(fs, "%d\t", mTheEquipments[i]->mTotalErrors);
1217 }
1218 fprintf(fs, "\n");
1219
1220 fclose(fs);
1221 return;
1222}
1223
1230bool HmpidDecoder2::getBlockFromStream(uint32_t** streamPtr, uint32_t Size)
1231{
1234 return (false);
1235 }
1236 *streamPtr = mActualStreamPtr;
1239 throw TH_WRONGBUFFERDIM;
1240 return (false);
1241 }
1242 return (true);
1243}
1244
1248bool HmpidDecoder2::getHeaderFromStream(uint32_t** streamPtr)
1249{
1250 return (getBlockFromStream(streamPtr, mRDHSize));
1251}
1252
1257{
1258 uint32_t word = 0;
1261 return (word);
1262 }
1263 word = *mActualStreamPtr;
1265 return (word);
1266}
1267
1277bool HmpidDecoder2::setUpStream(void* Buffer, long BufferLen)
1278{
1279 long wordsBufferLen = BufferLen / (sizeof(int32_t) / sizeof(char)); // Converts the len in words
1280 if (Buffer == nullptr) {
1281 if (mVerbose > 1) {
1282 std::cout << "HMPID Decoder2 : [ERROR] "
1283 << "Raw data buffer null Pointer ! " << std::endl;
1284 }
1286 }
1287 if (wordsBufferLen == 0) {
1288 if (mVerbose > 1) {
1289 std::cout << "HMPID Decoder2 : [ERROR] "
1290 << "Raw data buffer Empty ! " << std::endl;
1291 }
1292 throw TH_BUFFEREMPTY;
1293 }
1294 if (wordsBufferLen < 16) {
1295 if (mVerbose > 1) {
1296 std::cout << "HMPID Decoder2 : [ERROR] "
1297 << "Raw data buffer less then the Header Dimension = " << wordsBufferLen << std::endl;
1298 }
1299 throw TH_WRONGBUFFERDIM;
1300 }
1301
1302 mActualStreamPtr = (uint32_t*)Buffer; // sets the pointer to the Buffer
1303 mEndStreamPtr = ((uint32_t*)Buffer) + wordsBufferLen - 1; // sets the End of buffer
1304 mStartStreamPtr = ((uint32_t*)Buffer);
1305
1306 if (mVerbose > 6) {
1307 std::cout << "HMPID Decoder2 : setUpStream() "
1308 << "Buffer addr = " << std::hex << mActualStreamPtr << " End addr = " << mEndStreamPtr
1309 << " BufferLen = " << std::dec << BufferLen << std::endl;
1310 if (BufferLen < 256) {
1311 dumpMemory((const void*)mActualStreamPtr, (std::size_t)BufferLen);
1312 }
1313 }
1314 return (true);
1315}
int16_t charge
Definition RawEventData.h:5
int32_t i
constexpr int p2()
constexpr int p1()
constexpr to accelerate the coordinates changing
#define WTYPE_NONE
#define WTYPE_ROW
#define MAXDESCRIPTIONLENGHT
#define WTYPE_EOS
#define WTYPE_PAD
#define WTYPE_EOE
Definition of the RAW Data Header.
uint32_t j
Definition RawData.h:0
uint32_t col
Definition RawData.h:4
uint32_t res
Definition RawData.h:0
uint32_t c
Definition RawData.h:2
Class for time synchronization of RawReader instances.
HMPID Digit declaration.
Definition Digit.h:36
static void absolute2Equipment(int Module, int x, int y, int *Equi, int *Colu, int *Dilo, int *Chan)
Definition Digit.cxx:171
static constexpr int MAXEQUIPMENTS
Definition Geo.h:79
float getAverageEventSize(int Equipment)
HmpidDecoder2(int *EqIds, int *CruIds, int *LinkIds, int numOfEquipments)
static char sHmpidErrorDescription[MAXHMPIDERRORS][MAXDESCRIPTIONLENGHT]
HMPID Firmware Error Messages Definitions.
void dumpPads(int Equipment, int type=0)
bool isPadWord(uint32_t wp, int *Err, int *Col, int *Dilogic, int *Channel, int *Charge)
void setPad(HmpidEquipment *eq, int col, int dil, int ch, uint16_t charge)
int checkType(uint32_t wp, int *p1, int *p2, int *p3, int *p4)
bool isEoEmarker(uint32_t wp, int *Err, int *Col, int *Dilogic, int *Eoesize)
void decodePageFast(uint32_t **streamBuf)
void init()
Init all the members variables.
std::vector< o2::hmpid::Digit > mDigits
bool decodeHmpidError(int ErrorField, char *outbuf)
void dumpMemory(const void *MemoryStartPtr, std::size_t Dimension)
double getChannelSquare(int Equipment, int Column, int Dilogic, int Channel)
static char sErrorDescription[MAXERRORS][MAXDESCRIPTIONLENGHT]
Decoding Error Messages Definitions.
HmpidEquipment * evaluateHeaderContents(int EquipmentIndex)
void decodePage(uint32_t **streamBuffer)
uint16_t getChannelSamples(int Equipment, int Column, int Dilogic, int Channel)
~HmpidDecoder2()
Destructor : remove the Equipments instances.
bool isRowMarker(uint32_t wp, int *Err, int *rowSize, int *mark)
o2::InteractionRecord mIntReco
bool setUpStream(void *Buffer, long BufferLen)
int decodeHeader(uint32_t *streamPtrAdr, int *EquipIndex)
void writeSummaryFile(char *summaryFileName)
void dumpErrors(int Equipment)
int getEquipmentIndex(int EquipmentId)
double getPadSum(int Module, int Row, int Column)
bool isSegmentMarker(uint32_t wp, int *Err, int *segSize, int *Seg, int *mark)
HmpidEquipment * mTheEquipments[Geo::MAXEQUIPMENTS]
uint16_t getPadSamples(int Module, int Row, int Column)
bool getHeaderFromStream(uint32_t **streamPtr)
void updateStatistics(HmpidEquipment *eq)
void dumpHmpidError(HmpidEquipment *eq, int ErrorField, int mHeBCDI, int mHeORBIT)
float getAverageBusyTime(int Equipment)
bool getBlockFromStream(uint32_t **streamPtr, uint32_t Size)
double getPadSquares(int Module, int Row, int Column)
double getChannelSum(int Equipment, int Column, int Dilogic, int Channel)
int getEquipmentID(int CruId, int LinkId)
void setPad(int col, int dil, int cha, uint16_t charge)
void init()
Inits the members for the decoding.
void resetPadMap()
Resets the matrix that contains the results of the decoding.
void resetErrors()
Resets the decoding errors statistics.
static int FeeId(unsigned int idx)
Definition Geo.h:144
static int CruId(unsigned int idx)
Definition Geo.h:145
static int LnkId(unsigned int idx)
Definition Geo.h:146
GLuint buffer
Definition glcorearb.h:655
GLint GLint GLsizei GLint GLenum GLenum type
Definition glcorearb.h:275
GLboolean * data
Definition glcorearb.h:298
GLboolean r
Definition glcorearb.h:1233
RAWDataHeaderV7 RAWDataHeader
const int ERR_DOUBLEEOEMARK
const int TH_WRONGEQUIPINDEX
const int ERR_DOUBLEMARKWORD
const int TH_BUFFEREMPTY
const int ERR_NOTKNOWN
const int ERR_DUPLICATEPAD
const int ERR_LOSTEOEMARK
const int TH_WRONGHEADER
const int ERR_WRONGSIZESEGMENTMARK
const int TH_NULLBUFFERPOINTER
const int ERR_ROWMARKEMPTY
const int ERR_HMPID
const int TH_BUFFERPOINTERTOEND
const uint64_t OUTRANGEEVENTNUMBER
const int TH_CREATEFILE
const int ERR_LOSTEOSMARK
const int ERR_ROWMARKWRONG
const int ERR_ROWMARKERROR
const int ERR_ROWMARKLOST
const int MAXHMPIDERRORS
const int TH_WRONGBUFFERDIM
const int ERR_WRONGSIZEINEOE
const int MAXERRORS
uint32_t orbit
bit 12 to 31: reserved
uint32_t endPointID
bit 112 to 123: CRU ID
uint32_t packetCounter
bit 96 to 103: link id
uint64_t detectorPAR
bit 0 to 31: detector field
uint64_t sourceID
bit 32 to 39: priority bit
uint32_t linkID
bit 80 to 95: memory size
uint16_t cruID
bit 104 to 111: packet counter
uint64_t stop
bit 32 to 47: pages counter
uint32_t memorySize
bit 64 to 79: offset to next packet in memory
uint64_t headerSize
bit 0 to 7: header version
uint64_t priority
bit 16 to 31: FEE identifier
uint64_t feeId
bit 8 to 15: header size
uint64_t pageCnt
bit 0 to 31: trigger type
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"
std::vector< int > row