Project
Loading...
Searching...
No Matches
HmpidDecoder.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 ---------
20*/
21
22#include <fairlogger/Logger.h> // for LOG
23#include "Framework/Logger.h"
27
28using namespace o2::hmpid;
29
30// ============= HmpidDecoder Class implementation =======
31
33char HmpidDecoder::sErrorDescription[MAXERRORS][MAXDESCRIPTIONLENGHT] = {"Word that I don't known !",
34 "Row Marker Word with 0 words", "Duplicated Pad Word !", "Row Marker Wrong/Lost -> to EoE",
35 "Row Marker Wrong/Lost -> to EoE", "Row Marker reports an ERROR !", "Lost EoE Marker !", "Double EoE marker",
36 "Wrong size definition in EoE Marker", "Double Mark Word", "Wrong Size in Segment Marker", "Lost EoS Marker !",
37 "HMPID Header Errors"};
38
41 "L0 Missing,"
42 "L1 is received without L0",
43 "L1A signal arrived before the L1 Latency", "L1A signal arrived after the L1 Latency",
44 "L1A is missing or L1 timeout", "L1A Message is missing or L1 Message"};
45
51HmpidDecoder::HmpidDecoder(int numOfEquipments)
52{
53 // The standard definition of HMPID equipments at P2
54 int EqIds[] = {0, 1, 2, 3, 4, 5, 8, 9, 6, 7, 10, 11, 12, 13};
55 int CruIds[] = {0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 3, 3, 3};
56 int LinkIds[] = {0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 0, 1, 2};
57
58 mNumberOfEquipments = numOfEquipments;
59 for (int i = 0; i < mNumberOfEquipments; i++) {
60 mTheEquipments[i] = new HmpidEquipment(EqIds[i], CruIds[i], LinkIds[i]);
61 }
62}
63
73HmpidDecoder::HmpidDecoder(int* EqIds, int* CruIds, int* LinkIds, int numOfEquipments)
74{
75 mNumberOfEquipments = numOfEquipments;
76 for (int i = 0; i < mNumberOfEquipments; i++) {
77 mTheEquipments[i] = new HmpidEquipment(EqIds[i], CruIds[i], LinkIds[i]);
78 }
79}
80
83{
84 for (int i = 0; i < mNumberOfEquipments; i++) {
85 delete mTheEquipments[i];
86 }
87}
88
91{
92 mRDHSize = sizeof(o2::header::RAWDataHeader) / sizeof(uint32_t);
93
94 mVerbose = 0;
95 mHeEvent = 0;
96 mHeBusy = 0;
98 mPayloadTail = 0;
99
100 mHeFEEID = 0;
101 mHeSize = 0;
102 mHeVer = 0;
103 mHePrior = 0;
104 mHeStop = 0;
105 mHePages = 0;
106 mEquipment = 0;
107
109 mHeMemorySize = 0;
110
111 mHeDetectorID = 0;
112 mHeDW = 0;
113 mHeCruID = 0;
114 mHePackNum = 0;
115 mHePAR = 0;
116 mHePageNum = 0;
117 mHeLinkNum = 0;
119 mHeHmpidError = 0;
120 mHeBCDI = 0;
121 mHeORBIT = 0;
122 mHeTType = 0;
123
124 mActualStreamPtr = nullptr;
125 mEndStreamPtr = nullptr;
126 mStartStreamPtr = nullptr;
127
128 for (int i = 0; i < mNumberOfEquipments; i++) {
130 }
131}
132
138int HmpidDecoder::getEquipmentIndex(int CruId, int LinkId)
139{
140 for (int i = 0; i < mNumberOfEquipments; i++) {
141 if (mTheEquipments[i]->getEquipmentId(CruId, LinkId) != -1) {
142 return (i);
143 }
144 }
145 return (-1);
146}
147
153{
154 for (int i = 0; i < mNumberOfEquipments; i++) {
155 if (mTheEquipments[i]->getEquipmentId() == EquipmentId) {
156 return (i);
157 }
158 }
159 return (-1);
160}
161
166int HmpidDecoder::getEquipmentID(int CruId, int LinkId)
167{
168 for (int i = 0; i < mNumberOfEquipments; i++) {
169 if (mTheEquipments[i]->getEquipmentId(CruId, LinkId) != -1) {
170 return (mTheEquipments[i]->getEquipmentId());
171 }
172 }
173 return (-1);
174}
175
184int HmpidDecoder::checkType(uint32_t wp, int* p1, int* p2, int* p3, int* p4)
185{
186 if ((wp & 0x0000ffff) == 0x000036A8 || (wp & 0x0000ffff) == 0x000032A8 || (wp & 0x0000ffff) == 0x000030A0 || (wp & 0x0800ffff) == 0x080010A0) {
187 *p2 = (wp & 0x03ff0000) >> 16; // Number of words of row
188 *p1 = wp & 0x0000ffff;
189 return (WTYPE_ROW);
190 }
191 if ((wp & 0xfff00000) >> 20 == 0xAB0) {
192 *p2 = (wp & 0x000fff00) >> 8; // Number of words of Segment
193 *p1 = (wp & 0xfff00000) >> 20;
194 *p3 = wp & 0x0000000F;
195 if (*p3 < 4 && *p3 > 0) {
196 return (WTYPE_EOS);
197 }
198 }
199 // #EX MASK Raul 0x3803FF80 # ex mask 0xF803FF80 - this is EoE marker 0586800B0
200 if ((wp & 0x0803FF80) == 0x08000080) {
201 *p1 = (wp & 0x07c00000) >> 22;
202 *p2 = (wp & 0x003C0000) >> 18;
203 *p3 = (wp & 0x0000007F);
204 if (*p1 < 25 && *p2 < 11) {
205 return (WTYPE_EOE);
206 }
207 }
208 if ((wp & 0x08000000) == 0) { // # this is a pad
209 // PAD:0000.0ccc.ccdd.ddnn.nnnn.vvvv.vvvv.vvvv :: c=col,d=dilo,n=chan,v=value
210 *p1 = (wp & 0x07c00000) >> 22;
211 *p2 = (wp & 0x003C0000) >> 18;
212 *p3 = (wp & 0x0003F000) >> 12;
213 *p4 = (wp & 0x00000FFF);
214 if (*p1 > 0 && *p1 < 25 && *p2 > 0 && *p2 < 11 && *p3 < 48) {
215 return (WTYPE_PAD);
216 }
217 } else {
218 return (WTYPE_NONE);
219 }
220 return (WTYPE_NONE);
221}
222
229bool HmpidDecoder::isRowMarker(uint32_t wp, int* Err, int* rowSize, int* mark)
230{
231 if ((wp & 0x0000ffff) == 0x36A8 || (wp & 0x0000ffff) == 0x32A8 || (wp & 0x0000ffff) == 0x30A0 || (wp & 0x0800ffff) == 0x080010A0) {
232 *rowSize = (wp & 0x03ff0000) >> 16; // # Number of words of row
233 *mark = wp & 0x0000ffff;
234 *Err = false;
235 return (true);
236 } else {
237 *Err = true;
238 return (false);
239 }
240}
241
249bool HmpidDecoder::isSegmentMarker(uint32_t wp, int* Err, int* segSize, int* Seg, int* mark)
250{
251 *Err = false;
252 if ((wp & 0xfff00000) >> 20 == 0xAB0) {
253 *segSize = (wp & 0x000fff00) >> 8; // # Number of words of Segment
254 *mark = (wp & 0xfff00000) >> 20;
255 *Seg = wp & 0x0000000F;
256 if (*Seg > 3 || *Seg < 1) {
257 LOG(info) << " Wrong segment Marker Word, bad Number of segment" << *Seg << "!";
258 *Err = true;
259 }
260 return (true);
261 } else {
262 return (false);
263 }
264}
265
275bool HmpidDecoder::isPadWord(uint32_t wp, int* Err, int* Col, int* Dilogic, int* Channel, int* Charge)
276{
277 *Err = false;
278 // if ((wp & 0x08000000) != 0) {
279 if ((wp & 0x08000000) != 0) {
280 return (false);
281 }
282 *Col = (wp & 0x07c00000) >> 22;
283 *Dilogic = (wp & 0x003C0000) >> 18;
284 *Channel = (wp & 0x0003F000) >> 12;
285 *Charge = (wp & 0x00000FFF);
286
287 if ((wp & 0x0ffff) == 0x036A8 || (wp & 0x0ffff) == 0x032A8 || (wp & 0x0ffff) == 0x030A0 || (wp & 0x0ffff) == 0x010A0) { // # ! this is a pad
288 if (*Dilogic > 10 || *Channel > 47 || *Dilogic < 1 || *Col > 24 || *Col < 1) {
289 return (false);
290 }
291 } else {
292 if (*Dilogic > 10 || *Channel > 47 || *Dilogic < 1 || *Col > 24 || *Col < 1) {
293 // LOG(warning) << " Wrong Pad values Col=" << *Col << " Dilogic=" << *Dilogic << " Channel=" << *Channel << " Charge=" << *Charge << " wp:0x" << std::hex << wp << std::dec;
294 *Err = true;
295 return (false);
296 }
297 }
298 return (true);
299}
300
308bool HmpidDecoder::isEoEmarker(uint32_t wp, int* Err, int* Col, int* Dilogic, int* Eoesize)
309{
310 *Err = false;
311 // #EX MASK Raul 0x3803FF80 # ex mask 0xF803FF80 - this is EoE marker 0586800B0
312 if ((wp & 0x0803FF80) == 0x08000080) {
313 *Col = (wp & 0x07c00000) >> 22;
314 *Dilogic = (wp & 0x003C0000) >> 18;
315 *Eoesize = (wp & 0x0000007F);
316 if (*Col > 24 || *Dilogic > 10) {
317 LOG(info) << " EoE size wrong definition. Col=" << *Col << " Dilogic=" << *Dilogic;
318 *Err = true;
319 }
320 return (true);
321 } else {
322 return (false);
323 }
324}
325
332bool HmpidDecoder::decodeHmpidError(int ErrorField, char* outbuf)
333{
334 int res = false;
335 outbuf[0] = '\0';
336 for (int i = 0; i < MAXHMPIDERRORS; i++) {
337 if ((ErrorField & (0x01 << i)) != 0) {
338 res = true;
339 strcat(outbuf, sHmpidErrorDescription[i]);
340 }
341 }
342 return (res);
343}
344
358int HmpidDecoder::decodeHeader(uint32_t* streamPtrAdr, int* EquipIndex)
359{
360 uint32_t* buffer = streamPtrAdr; // Sets the pointer to buffer
362
363 /*
364 mHeFEEID = (buffer[0] & 0x000f0000) >> 16;
365 mHeSize = (buffer[0] & 0x0000ff00) >> 8;
366 mHeVer = (buffer[0] & 0x000000ff);
367 mHePrior = (buffer[1] & 0x000000FF);
368 mHeDetectorID = (buffer[1] & 0x0000FF00) >> 8;
369 mHeOffsetNewPack = (buffer[2] & 0x0000FFFF);
370 mHeMemorySize = (buffer[2] & 0xffff0000) >> 16;
371 mHeDW = (buffer[3] & 0xF0000000) >> 24;
372 mHeCruID = (buffer[3] & 0x0FF0000) >> 16;
373 mHePackNum = (buffer[3] & 0x0000FF00) >> 8;
374 mHeLinkNum = (buffer[3] & 0x000000FF);
375 mHeBCDI = (buffer[4] & 0x00000FFF);
376 mHeORBIT = buffer[5];
377 mHeTType = buffer[8];
378 mHePageNum = (buffer[9] & 0x0000FFFF);
379 mHeStop = (buffer[9] & 0x00ff0000) >> 16;
380 mHeBusy = (buffer[12] & 0xfffffe00) >> 9;
381 mHeFirmwareVersion = buffer[12] & 0x0000000f;
382 mHeHmpidError = (buffer[12] & 0x000001F0) >> 4;
383 mHePAR = buffer[13] & 0x0000FFFF;
384 */
385 mHeFEEID = hpt->feeId;
386 mHeSize = hpt->headerSize;
387 mHeVer = hpt->version;
388 mHePrior = hpt->priority;
389 mHeDetectorID = hpt->sourceID;
392 mHeDW = hpt->endPointID;
393 mHeCruID = hpt->cruID;
395 mHeLinkNum = hpt->linkID;
396 mHeBCDI = hpt->bunchCrossing;
397 mHeORBIT = hpt->orbit;
398 mHeTType = hpt->triggerType;
399 mHePageNum = hpt->pageCnt;
400 mHeStop = hpt->stop;
401 mHeBusy = (hpt->detectorField & 0xfffffe00) >> 9;
402 mHeFirmwareVersion = hpt->detectorField & 0x0000000f;
403 mHeHmpidError = (hpt->detectorField & 0x000001F0) >> 4;
404 mHePAR = hpt->detectorPAR;
405
406 *EquipIndex = getEquipmentIndex(mHeCruID, mHeLinkNum);
407 // mEquipment = (*EquipIndex != -1) ? mTheEquipments[*EquipIndex]->getEquipmentId() : -1;
408 mEquipment = mHeFEEID & 0x000F;
409 mNumberWordToRead = ((mHeMemorySize - mHeSize) / sizeof(uint32_t));
410 mPayloadTail = ((mHeOffsetNewPack - mHeMemorySize) / sizeof(uint32_t));
411
412 // ---- Event ID : Actualy based on ORBIT NUMBER and BC
413 mHeEvent = (mHeORBIT << 12) | mHeBCDI;
414
415 LOG(debug) << "FEE-ID=" << mHeFEEID << " HeSize=" << mHeSize << " HePrior=" << mHePrior << " Det.Id=" << mHeDetectorID << " HeMemorySize=" << mHeMemorySize << " HeOffsetNewPack=" << mHeOffsetNewPack;
416 LOG(debug) << " Equipment=" << mEquipment << " PakCounter=" << mHePackNum << " Link=" << mHeLinkNum << " CruID=" << mHeCruID << " DW=" << mHeDW << " BC=" << mHeBCDI << " ORBIT=" << mHeORBIT;
417 LOG(debug) << " TType=" << mHeTType << " HeStop=" << mHeStop << " PagesCounter=" << mHePageNum << " FirmVersion=" << mHeFirmwareVersion << " BusyTime=" << mHeBusy << " Error=" << mHeHmpidError << " PAR=" << mHePAR;
418 LOG(debug) << " EquIdx = " << *EquipIndex << " Event = " << mHeEvent << " Payload : Words to read=" << mNumberWordToRead << " PailoadTail=" << mPayloadTail;
419
420 if (*EquipIndex == -1) {
421 LOG(error) << "ERROR ! Bad equipment Number: " << mEquipment;
422 throw TH_WRONGEQUIPINDEX;
423 }
424 // std::cout << "HMPID ! Exit decode header" << std::endl;
425 return (true);
426}
427
432{
434 eq->mEventSizeAverage = ((eq->mEventSizeAverage * (eq->mNumberOfEvents - 1)) + eq->mEventSize) / (eq->mNumberOfEvents);
436 if (eq->mSampleNumber == 0) {
437 eq->mNumberOfEmptyEvents += 1;
438 }
439 if (eq->mErrorsCounter > 0) {
440 eq->mNumberOfWrongEvents += 1;
441 }
442 eq->mTotalPads += eq->mSampleNumber;
443 eq->mTotalErrors += eq->mErrorsCounter;
444
445 //std::cout << ">>>updateStatistics() >>> "<< eq->getEquipmentId() << "="<< eq->mNumberOfEvents<<" :" << eq->mEventSize <<","<< eq->mTotalPads << ", " << eq->mSampleNumber << std::endl;
446
447 return;
448}
449
455{
456 //std::cout << "Enter evaluateHeaderContents..";
457 HmpidEquipment* eq = mTheEquipments[EquipmentIndex];
458 if (mHeEvent != eq->mEventNumber) { // Is a new event
459 if (eq->mEventNumber != OUTRANGEEVENTNUMBER) { // skip the first
460 updateStatistics(eq); // update previous statistics
461 }
462 eq->mNumberOfEvents++;
464 eq->mBusyTimeValue = mHeBusy * 0.00000005;
465 eq->mEventSize = 0; // reset the event
466 eq->mSampleNumber = 0;
467 eq->mErrorsCounter = 0;
468 mIntReco = {(uint16_t)mHeBCDI, (uint32_t)mHeORBIT};
469 }
470 eq->mEventSize += mNumberWordToRead * sizeof(uint32_t); // Calculate the size in bytes
471 if (mHeHmpidError != 0) {
472 LOG(info) << "HMPID Header reports an error : " << mHeHmpidError;
474 eq->setError(ERR_HMPID);
475 }
476 // std::cout << ".. end evaluateHeaderContents = " << eq->mEventNumber << std::endl;
477 return (eq);
478}
479
485void HmpidDecoder::decodePage(uint32_t** streamBuf)
486{
487 int equipmentIndex;
488 try {
489 getHeaderFromStream(streamBuf);
490 } catch (int e) {
491 // The stream end !
492 LOG(debug) << "End main decoding loop !";
493 throw TH_BUFFEREMPTY;
494 }
495 try {
496 decodeHeader(*streamBuf, &equipmentIndex);
497 } catch (int e) {
498 LOG(error) << "Failed to decode the Header !";
499 throw TH_WRONGHEADER;
500 }
501
502 HmpidEquipment* eq = evaluateHeaderContents(equipmentIndex);
503
504 uint32_t wpprev = 0;
505 uint32_t wp = 0;
506 int newOne = true;
507 int p1, p2, p3, p4;
508 int error;
509 int type;
510 bool isIt;
511
512 int payIndex = 0;
513 while (payIndex < mNumberWordToRead) { //start the payload loop word by word
514 if (newOne == true) {
515 wpprev = wp;
516 if (!getWordFromStream(&wp)) { // end the stream
517 break;
518 }
519 type = checkType(wp, &p1, &p2, &p3, &p4);
520 if (type == WTYPE_NONE) {
521 if (eq->mWillBePad == true) { // try to recover the first pad !
522 type = checkType((wp & 0xF7FFFFFF), &p1, &p2, &p3, &p4);
523 if (type == WTYPE_PAD && p3 == 0 && eq->mWordsPerDilogicCounter == 0) {
524 newOne = false; // # reprocess as pad
525 continue;
526 }
527 }
529 LOG(debug) << "Equip=" << mEquipment << sErrorDescription[ERR_NOTKNOWN] << " [" << wp << "]";
532 payIndex++;
533 continue;
534 }
535 }
536 if (mEquipment == 8) {
537 LOG(info) << "Event" << eq->mEventNumber << " >" << std::hex << wp << std::dec << "<" << type;
538 }
539 if (eq->mWillBeRowMarker == true) { // #shoud be a Row Marker
540 if (type == WTYPE_ROW) {
541 eq->mColumnCounter++;
543 eq->mRowSize = p2;
544 switch (p2) {
545 case 0: // Empty column
547 LOG(debug) << "Equip=" << mEquipment << sErrorDescription[ERR_ROWMARKEMPTY] << " col=" << (eq->mSegment) * 8 + eq->mColumnCounter << "[" << p1 << "]";
548 eq->mWillBeRowMarker = true;
549 break;
550 case 0x3FF: // Error in column
552 LOG(debug) << "Equip=" << mEquipment << sErrorDescription[ERR_ROWMARKERROR] << " col=" << (eq->mSegment) * 8 + eq->mColumnCounter << "[" << p1 << "]";
553 eq->mWillBeRowMarker = true;
554 break;
555 case 0x3FE: // Masked column
556 LOG(info) << "Equip=" << mEquipment << "The column=" << (eq->mSegment) * 8 + eq->mColumnCounter << " is Masked !";
557 eq->mWillBeRowMarker = true;
558 break;
559 default:
560 eq->mWillBeRowMarker = false;
561 eq->mWillBePad = true;
562 break;
563 }
564 newOne = true;
565 } else {
566 if (wp == wpprev) {
568 LOG(debug) << "Equip=" << mEquipment << sErrorDescription[ERR_DUPLICATEPAD] << " col=" << (eq->mSegment) * 8 + eq->mColumnCounter << "[" << p1 << "]";
569 newOne = true;
570 } else if (type == WTYPE_EOE) { // # Could be a EoE
571 eq->mColumnCounter++;
573 eq->mWillBeRowMarker = false;
574 eq->mWillBePad = true;
575 newOne = true;
576 } else if (type == WTYPE_PAD) { //# Could be a PAD
577 eq->mColumnCounter++;
579 LOG(debug) << "Equip=" << mEquipment << sErrorDescription[ERR_ROWMARKLOST] << " col=" << (eq->mSegment) * 8 + eq->mColumnCounter << "[" << p1 << "]";
580 eq->mWillBeRowMarker = false;
581 eq->mWillBePad = true;
582 newOne = true;
583 } else if (type == WTYPE_EOS) { // # Could be a EoS
584 eq->mWillBeRowMarker = false;
585 eq->mWillBeSegmentMarker = true;
586 newOne = false;
587 } else {
588 eq->mColumnCounter++;
590 LOG(debug) << "Equip=" << mEquipment << sErrorDescription[ERR_ROWMARKLOST] << " col=" << (eq->mSegment) * 8 + eq->mColumnCounter << "[" << p1 << "]";
591 eq->mWillBeRowMarker = false;
592 eq->mWillBePad = true;
593 newOne = true;
594 }
595 }
596 } else if (eq->mWillBePad == true) { // # We expect a pad
597 //# PAD:0000.0ccc.ccdd.ddnn.nnnn.vvvv.vvvv.vvvv :: c=col,d=dilo,n=chan,v=value
598 // c = 1..24 d = 1..10 n = 0..47
599 if (type == WTYPE_PAD) {
600 newOne = true;
601 if (wp == wpprev) {
603 LOG(debug) << "Equip=" << mEquipment << sErrorDescription[ERR_DUPLICATEPAD] << " col=" << (eq->mSegment) * 8 + eq->mColumnCounter << "[" << p1 << "]";
604 } else if (p1 != (eq->mSegment * 8 + eq->mColumnCounter)) { // # Manage
605 // We try to recover the RowMarker misunderstanding
606 isIt = isRowMarker(wp, &error, &p2, &p1);
607 if (isIt == true && error == false) {
608 type = WTYPE_ROW;
609 newOne = false;
610 eq->mWillBeEoE = true;
611 eq->mWillBePad = false;
612 } else {
613 LOG(debug) << "Equip=" << mEquipment << " Mismatch in column"
614 << " col=" << (eq->mSegment) * 8 + eq->mColumnCounter << "[" << p1 << "]";
615 eq->mColumnCounter = p1 % 8;
616 }
617 } else {
618 setPad(eq, p1 - 1, p2 - 1, p3, p4);
619 if (mEquipment == 8) {
620 LOG(info) << "Event" << eq->mEventNumber << " >" << p1 - 1 << "," << p2 - 1 << "," << p3 << "," << p4;
621 }
623 eq->mSampleNumber++;
624 if (p3 == 47) {
625 eq->mWillBeEoE = true;
626 eq->mWillBePad = false;
627 }
628 }
631 } else if (type == WTYPE_EOE) { //# the pads are end ok
632 eq->mWillBeEoE = true;
633 eq->mWillBePad = false;
634 newOne = false;
635 } else if (type == WTYPE_ROW) { // # We Lost the EoE !
636 // We try to recover the PAD misunderstanding
637 isIt = isPadWord(wp, &error, &p1, &p2, &p3, &p4);
638 if (isIt == true && error == false) {
639 type = WTYPE_PAD;
640 newOne = false; // # reprocess as pad
641 } else {
643 LOG(debug) << "Equip=" << mEquipment << sErrorDescription[ERR_LOSTEOEMARK] << " col=" << (eq->mSegment) * 8 + eq->mColumnCounter << "[" << p1 << "]";
644 eq->mWillBeRowMarker = true;
645 eq->mWillBePad = false;
646 newOne = false;
647 }
648 } else if (type == WTYPE_EOS) { // # We Lost the EoE !
650 LOG(debug) << "Equip=" << mEquipment << sErrorDescription[ERR_LOSTEOEMARK] << " col=" << (eq->mSegment) * 8 + eq->mColumnCounter << "[" << p1 << "]";
651 eq->mWillBeSegmentMarker = true;
652 eq->mWillBePad = false;
653 newOne = false;
654 }
655 } else if (eq->mWillBeEoE == true) { // # We expect a EoE
656 if (type == WTYPE_EOE) {
659 if (wpprev == wp) {
661 LOG(debug) << "Equip=" << mEquipment << sErrorDescription[ERR_DOUBLEEOEMARK] << " col=" << p1;
662 } else if (p3 != eq->mWordsPerDilogicCounter) {
664 LOG(debug) << "Equip=" << mEquipment << sErrorDescription[ERR_WRONGSIZEINEOE] << " col=" << p1;
665 }
667 if (p2 == 10) {
668 if (p1 % 8 != 0) { // # we expect the Row Marker
669 eq->mWillBeRowMarker = true;
670 } else {
671 eq->mWillBeSegmentMarker = true;
672 }
673 } else {
674 eq->mWillBePad = true;
675 }
676 eq->mWillBeEoE = false;
677 newOne = true;
678 } else if (type == WTYPE_EOS) { // We Lost the EoE !
680 LOG(debug) << "Equip=" << mEquipment << sErrorDescription[ERR_LOSTEOEMARK] << " col=" << (eq->mSegment) * 8 + eq->mColumnCounter << "[" << p1 << "]";
681 eq->mWillBeSegmentMarker = true;
682 eq->mWillBeEoE = false;
683 newOne = false;
684 } else if (type == WTYPE_ROW) { //# We Lost the EoE !
686 LOG(debug) << "Equip=" << mEquipment << sErrorDescription[ERR_LOSTEOEMARK] << " col=" << (eq->mSegment) * 8 + eq->mColumnCounter << "[" << p1 << "]";
687 eq->mWillBeRowMarker = true;
688 eq->mWillBeEoE = false;
689 newOne = false;
690 } else if (type == WTYPE_PAD) { // # We Lost the EoE !
691 int typb, p1b, p2b, p3b, p4b;
692 typb = checkType((wp | 0x08000000), &p1b, &p2b, &p3b, &p4b);
693 if (typb == WTYPE_EOE && p3b == 48) {
694 type = typb;
695 p1 = p1b;
696 p2 = p2b;
697 p3 = p3b;
698 p4 = p4b;
699 newOne = false; // # reprocess as EoE
700 } else {
702 LOG(debug) << "Equip=" << mEquipment << sErrorDescription[ERR_LOSTEOEMARK] << " col=" << (eq->mSegment) * 8 + eq->mColumnCounter << "[" << p1 << "]";
703 eq->mWillBePad = true;
704 eq->mWillBeEoE = false;
705 newOne = false;
706 }
707 }
708 } else if (eq->mWillBeSegmentMarker == true) { // # We expect a EoSegment
709 if (wpprev == wp) {
711 LOG(debug) << "Equip=" << mEquipment << sErrorDescription[ERR_DOUBLEMARKWORD] << " col=" << (eq->mSegment) * 8 + eq->mColumnCounter << "[" << p1 << "]";
712 newOne = true;
713 } else if (type == 2) {
714 if (abs(eq->mWordsPerSegCounter - p2) > 5) {
716 LOG(debug) << "Equip=" << mEquipment << sErrorDescription[ERR_WRONGSIZESEGMENTMARK] << " Seg=" << p2;
717 }
718 eq->mWordsPerSegCounter = 0;
719 eq->mWordsPerRowCounter = 0;
720 eq->mColumnCounter = 0;
721 eq->mSegment = p3 % 3;
722 eq->mWillBeRowMarker = true;
723 eq->mWillBeSegmentMarker = false;
724 newOne = true;
725 } else {
727 LOG(debug) << "Equip=" << mEquipment << sErrorDescription[ERR_LOSTEOSMARK] << " col=" << (eq->mSegment) * 8 + eq->mColumnCounter << "[" << p1 << "]";
728 eq->mWillBeSegmentMarker = false;
729 eq->mWillBeRowMarker = true;
730 newOne = false;
731 }
732 }
733 if (newOne) {
734 payIndex += 1;
735 }
736 }
737 for (int i = 0; i < mPayloadTail; i++) { // move the pointer to skip the Payload Tail
739 }
740}
741
747{
748 // ---------resets the PAdMap-----------
749 for (int i = 0; i < mNumberOfEquipments; i++) {
753 }
754
755 int type;
756 int equipmentIndex = -1;
757 int isIt;
758 HmpidEquipment* eq;
759 uint32_t* streamBuf;
760 LOG(debug) << "Enter decoding !";
761
762 // Input Stream Main Loop
763 while (true) {
764 try {
765 decodePage(&streamBuf);
766 } catch (int e) {
767 LOG(debug) << "End main buffer decoding loop !";
768 break;
769 }
770 } // this is the end of stream
771
772 // cycle in order to update info for the last event
773 for (int i = 0; i < mNumberOfEquipments; i++) {
774 if (mTheEquipments[i]->mNumberOfEvents > 0) {
776 }
777 }
778 return (true);
779}
780
786void HmpidDecoder::decodePageFast(uint32_t** streamBuf)
787{
788 int equipmentIndex;
789 try {
790 getHeaderFromStream(streamBuf);
791 } catch (int e) {
792 // The stream end !
793 LOG(info) << "End Fast Page decoding loop !";
794 throw TH_BUFFEREMPTY;
795 }
796 try {
797 decodeHeader(*streamBuf, &equipmentIndex);
798 } catch (int e) {
799 LOG(info) << "Failed to decode the Header !";
800 throw TH_WRONGHEADER;
801 }
802 HmpidEquipment* eq = evaluateHeaderContents(equipmentIndex);
803 uint32_t wpprev = 0;
804 uint32_t wp = 0;
805 int newOne = true;
806 int Column, Dilogic, Channel, Charge;
807 int pwer;
808 int payIndex = 0;
809 while (payIndex < mNumberWordToRead) { //start the payload loop word by word
810 wpprev = wp;
811 if (!getWordFromStream(&wp)) { // end the stream
812 break;
813 }
814 if (wp == wpprev) {
815 LOG(debug) << "Equip=" << mEquipment << sErrorDescription[ERR_DUPLICATEPAD] << " col=" << (eq->mSegment) * 8 + eq->mColumnCounter << "[" << Column << "]";
816 } else {
817 if (isPadWord(wp, &pwer, &Column, &Dilogic, &Channel, &Charge) == true) {
818 if (pwer != true) {
819 setPad(eq, Column - 1, Dilogic - 1, Channel, Charge);
820 eq->mSampleNumber++;
821 }
822 }
823 }
824 payIndex += 1;
825 }
826 for (int i = 0; i < mPayloadTail; i++) { // move the pointer to skip the Payload Tail
828 }
829 return;
830}
837{
838 // ---------resets the PAdMap-----------
839 for (int i = 0; i < mNumberOfEquipments; i++) {
842 }
843
844 uint32_t* streamBuf;
845 LOG(info) << "Enter FAST decoding !";
846
847 // Input Stream Main Loop
848 while (true) {
849 try {
850 decodePageFast(&streamBuf);
851 } catch (int e) {
852 LOG(info) << " End Buffer Fast Decoding !";
853 break;
854 }
855 } // this is the end of stream
856
857 // cycle in order to update info for the last event
858 for (int i = 0; i < mNumberOfEquipments; i++) {
859 if (mTheEquipments[i]->mNumberOfEvents > 0) {
861 }
862 }
863 return (true);
864}
865
866// =========================================================
867
873uint16_t HmpidDecoder::getPadSamples(int Module, int Row, int Column)
874{
875 int e, c, d, h;
876 o2::hmpid::Digit::absolute2Equipment(Module, Row, Column, &e, &c, &d, &h);
877 int EqInd = getEquipmentIndex(e);
878 if (EqInd < 0) {
879 return (0);
880 }
881 return (mTheEquipments[EqInd]->mPadSamples[c][d][h]);
882}
883
889double HmpidDecoder::getPadSum(int Module, int Row, int Column)
890{
891 int e, c, d, h;
892 o2::hmpid::Digit::absolute2Equipment(Module, Row, Column, &e, &c, &d, &h);
893 int EqInd = getEquipmentIndex(e);
894 if (EqInd < 0) {
895 return (0);
896 }
897 return (mTheEquipments[EqInd]->mPadSum[c][d][h]);
898}
899
905double HmpidDecoder::getPadSquares(int Module, int Row, int Column)
906{
907 int e, c, d, h;
908 o2::hmpid::Digit::absolute2Equipment(Module, Row, Column, &e, &c, &d, &h);
909 int EqInd = getEquipmentIndex(e);
910 if (EqInd < 0) {
911 return (0);
912 }
913 return (mTheEquipments[EqInd]->mPadSquares[c][d][h]);
914}
915
922uint16_t HmpidDecoder::getChannelSamples(int EquipmId, int Column, int Dilogic, int Channel)
923{
924 int EqInd = getEquipmentIndex(EquipmId);
925 if (EqInd < 0) {
926 return (0);
927 }
928 return (mTheEquipments[EqInd]->mPadSamples[Column][Dilogic][Channel]);
929}
930
937double HmpidDecoder::getChannelSum(int EquipmId, int Column, int Dilogic, int Channel)
938{
939 int EqInd = getEquipmentIndex(EquipmId);
940 if (EqInd < 0) {
941 return (0);
942 }
943 return (mTheEquipments[EqInd]->mPadSum[Column][Dilogic][Channel]);
944}
945
952double HmpidDecoder::getChannelSquare(int EquipmId, int Column, int Dilogic, int Channel)
953{
954 int EqInd = getEquipmentIndex(EquipmId);
955 if (EqInd < 0) {
956 return (0);
957 }
958 return (mTheEquipments[EqInd]->mPadSquares[Column][Dilogic][Channel]);
959}
960
965{
966 int EqInd = getEquipmentIndex(EquipmId);
967 if (EqInd < 0) {
968 return (0.0);
969 }
970 return (mTheEquipments[EqInd]->mEventSizeAverage);
971}
972
977{
978 int EqInd = getEquipmentIndex(EquipmId);
979 if (EqInd < 0) {
980 return (0.0);
981 }
982 return (mTheEquipments[EqInd]->mBusyTimeAverage);
983}
984
985// ===================================================
986// Methods to dump info
987
991void HmpidDecoder::dumpErrors(int EquipmId)
992{
993 int EqInd = getEquipmentIndex(EquipmId);
994 if (EqInd < 0) {
995 return;
996 }
997 std::cout << "Dump Errors for the Equipment = " << EquipmId << std::endl;
998 for (int i = 0; i < MAXERRORS; i++) {
999 std::cout << sErrorDescription[i] << " = " << mTheEquipments[EqInd]->mErrors[i] << std::endl;
1000 }
1001 std::cout << " -------- " << std::endl;
1002 return;
1003}
1004
1009void HmpidDecoder::dumpPads(int EquipmId, int type)
1010{
1011 int EqInd = getEquipmentIndex(EquipmId);
1012 if (EqInd < 0) {
1013 return;
1014 }
1015 int Module = EquipmId / 2;
1016 int StartRow = (EquipmId % 2 == 1) ? 80 : 0;
1017 int EndRow = (EquipmId % 2 == 1) ? 160 : 80;
1018 std::cout << "Dump Pads for the Equipment = " << EquipmId << std::endl;
1019 for (int c = 0; c < 144; c++) {
1020 for (int r = StartRow; r < EndRow; r++) {
1021 switch (type) {
1022 case 0:
1023 std::cout << getPadSamples(Module, r, c) << ",";
1024 break;
1025 case 1:
1026 std::cout << getPadSum(Module, r, c) << ",";
1027 break;
1028 case 2:
1029 std::cout << getPadSquares(Module, r, c) << ",";
1030 break;
1031 }
1032 }
1033 std::cout << std::endl;
1034 }
1035 std::cout << " -------- " << std::endl;
1036 return;
1037}
1038
1042{
1043 char printbuf[MAXHMPIDERRORS * MAXDESCRIPTIONLENGHT];
1044 if (decodeHmpidError(ErrorField, printbuf) == true) {
1045 LOG(error) << "HMPID Error field = " << ErrorField << " : " << printbuf;
1046 }
1047 return;
1048}
1049
1054void HmpidDecoder::writeSummaryFile(char* summaryFileName)
1055{
1056 FILE* fs = fopen(summaryFileName, "w");
1057 if (fs == nullptr) {
1058 printf("Error opening the file %s !\n", summaryFileName);
1059 throw TH_CREATEFILE;
1060 }
1061
1062 fprintf(fs, "HMPID Readout Raw Data Decoding Summary File\n");
1063 fprintf(fs, "Equipment Id\t");
1064 for (int i = 0; i < Geo::MAXEQUIPMENTS; i++) {
1065 fprintf(fs, "%d\t", mTheEquipments[i]->getEquipmentId());
1066 }
1067 fprintf(fs, "\n");
1068
1069 fprintf(fs, "Number of events\t");
1070 for (int i = 0; i < Geo::MAXEQUIPMENTS; i++) {
1071 fprintf(fs, "%d\t", mTheEquipments[i]->mNumberOfEvents);
1072 }
1073 fprintf(fs, "\n");
1074
1075 fprintf(fs, "Average Event Size\t");
1076 for (int i = 0; i < Geo::MAXEQUIPMENTS; i++) {
1077 fprintf(fs, "%f\t", mTheEquipments[i]->mEventSizeAverage);
1078 }
1079 fprintf(fs, "\n");
1080
1081 fprintf(fs, "Total pads\t");
1082 for (int i = 0; i < Geo::MAXEQUIPMENTS; i++) {
1083 fprintf(fs, "%d\t", mTheEquipments[i]->mTotalPads);
1084 }
1085 fprintf(fs, "\n");
1086
1087 fprintf(fs, "Average pads per event\t");
1088 for (int i = 0; i < Geo::MAXEQUIPMENTS; i++) {
1089 fprintf(fs, "%f\t", mTheEquipments[i]->mPadsPerEventAverage);
1090 }
1091 fprintf(fs, "\n");
1092
1093 fprintf(fs, "Busy Time average\t");
1094 for (int i = 0; i < Geo::MAXEQUIPMENTS; i++) {
1095 fprintf(fs, "%e\t", mTheEquipments[i]->mBusyTimeAverage);
1096 }
1097 fprintf(fs, "\n");
1098
1099 fprintf(fs, "Event rate\t");
1100 for (int i = 0; i < Geo::MAXEQUIPMENTS; i++) {
1101 fprintf(fs, "%e\t", 1 / mTheEquipments[i]->mBusyTimeAverage);
1102 }
1103 fprintf(fs, "\n");
1104
1105 fprintf(fs, "Number of Empty Events\t");
1106 for (int i = 0; i < Geo::MAXEQUIPMENTS; i++) {
1107 fprintf(fs, "%d\t", mTheEquipments[i]->mNumberOfEmptyEvents);
1108 }
1109 fprintf(fs, "\n");
1110
1111 fprintf(fs, "-------------Errors--------------------\n");
1112 fprintf(fs, "Wrong events\t");
1113 for (int i = 0; i < Geo::MAXEQUIPMENTS; i++) {
1114 fprintf(fs, "%d\t", mTheEquipments[i]->mNumberOfWrongEvents);
1115 }
1116 fprintf(fs, "\n");
1117
1118 for (int j = 0; j < MAXERRORS; j++) {
1119 fprintf(fs, "%s\t", sErrorDescription[j]);
1120 for (int i = 0; i < Geo::MAXEQUIPMENTS; i++) {
1121 fprintf(fs, "%d\t", mTheEquipments[i]->mErrors[j]);
1122 }
1123 fprintf(fs, "\n");
1124 }
1125
1126 fprintf(fs, "Total errors\t");
1127 for (int i = 0; i < Geo::MAXEQUIPMENTS; i++) {
1128 fprintf(fs, "%d\t", mTheEquipments[i]->mTotalErrors);
1129 }
1130 fprintf(fs, "\n");
1131
1132 fclose(fs);
1133 return;
1134}
int32_t i
constexpr int p2()
constexpr int p1()
constexpr to accelerate the coordinates changing
Base Class to decode HMPID Raw Data stream.
#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 res
Definition RawData.h:0
uint32_t c
Definition RawData.h:2
std::ostringstream debug
Class for time synchronization of RawReader instances.
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
double getChannelSum(int Equipment, int Column, int Dilogic, int Channel)
uint16_t getPadSamples(int Module, int Row, int Column)
bool isRowMarker(uint32_t wp, int *Err, int *rowSize, int *mark)
int checkType(uint32_t wp, int *p1, int *p2, int *p3, int *p4)
int decodeHeader(uint32_t *streamPtrAdr, int *EquipIndex)
void decodePage(uint32_t **streamBuffer)
uint16_t getChannelSamples(int Equipment, int Column, int Dilogic, int Channel)
static char sErrorDescription[MAXERRORS][MAXDESCRIPTIONLENGHT]
Decoding Error Messages Definitions.
virtual bool getHeaderFromStream(uint32_t **streamPtr)=0
bool decodeHmpidError(int ErrorField, char *outbuf)
void updateStatistics(HmpidEquipment *eq)
void dumpHmpidError(int ErrorField)
double getPadSquares(int Module, int Row, int Column)
int getEquipmentIndex(int EquipmentId)
bool isPadWord(uint32_t wp, int *Err, int *Col, int *Dilogic, int *Channel, int *Charge)
void decodePageFast(uint32_t **streamBuf)
virtual bool getWordFromStream(uint32_t *word)=0
virtual void setPad(HmpidEquipment *eq, int col, int dil, int ch, uint16_t charge)=0
~HmpidDecoder()
Destructor : remove the Equipments instances.
bool isEoEmarker(uint32_t wp, int *Err, int *Col, int *Dilogic, int *Eoesize)
double getChannelSquare(int Equipment, int Column, int Dilogic, int Channel)
HmpidDecoder(int *EqIds, int *CruIds, int *LinkIds, int numOfEquipments)
HmpidEquipment * evaluateHeaderContents(int EquipmentIndex)
o2::InteractionRecord mIntReco
void writeSummaryFile(char *summaryFileName)
HmpidEquipment * mTheEquipments[Geo::MAXEQUIPMENTS]
float getAverageBusyTime(int Equipment)
void init()
Init all the members variables.
double getPadSum(int Module, int Row, int Column)
static char sHmpidErrorDescription[MAXHMPIDERRORS][MAXDESCRIPTIONLENGHT]
HMPID Firmware Error Messages Definitions.
float getAverageEventSize(int Equipment)
void dumpErrors(int Equipment)
void dumpPads(int Equipment, int type=0)
int getEquipmentID(int CruId, int LinkId)
bool isSegmentMarker(uint32_t wp, int *Err, int *segSize, int *Seg, int *mark)
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.
GLuint buffer
Definition glcorearb.h:655
GLint GLint GLsizei GLint GLenum GLenum type
Definition glcorearb.h:275
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 ERR_ROWMARKEMPTY
const int ERR_HMPID
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 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"