13 #include <svd/modules/svdUnpacker/SVDUnpackerModule.h>
14 #include <svd/calibration/SVDDetectorConfiguration.h>
16 #include <framework/datastore/DataStore.h>
17 #include <framework/datastore/StoreObjPtr.h>
18 #include <framework/logging/Logger.h>
20 #include <boost/crc.hpp>
21 #define CRC16POLYREV 0x8005 // CRC-16 polynomial, normal representation
23 #include <arpa/inet.h>
49 SVDUnpackerModule::SVDUnpackerModule() :
Module(),
50 m_mapping(m_xmlFileName),
52 m_FADCTriggerNumberOffset(0)
55 setDescription(
"Produce SVDShaperDigits from RawSVD. NOTE: only zero-suppressed mode is currently supported!");
62 "if >0 is the number of reported FTB header ERRORs before quiet operations. If <0 full log produced.", -1);
64 "number to be added to the FADC trigger number to match the main trigger number", 0);
68 addParam(
"silentlyAppend",
m_silentAppend,
"Append digits to a pre-existing non-empty storeArray",
bool(
false));
70 addParam(
"UnpackerErrorRate",
m_errorRate,
"Unpacker will print one error every UnpackerErrorRate",
int(1000));
71 addParam(
"PrintRawData",
m_printRaw,
"Printing Raw data words for debugging",
bool(
false));
88 storeDAQDiagnostics.registerInDataStore();
92 storeShaperDigits.registerInDataStore();
101 B2FATAL(
"no valid SVD Channel Mapping. We stop here.");
107 B2ERROR(
"SVD xml map not loaded." << std::endl <<
108 "No SVDShaperDigit will be produced for this run!");
138 B2ERROR(
"SVDDetectorConfiguration not valid!! Setting relativeTimeShift to 0 for this reconstruction.");
144 #pragma GCC diagnostic push
145 #pragma GCC diagnostic ignored "-Wstack-usage="
157 B2WARNING(
"Unpacking SVDShaperDigits to a non-empty pre-existing \n"
158 <<
"StoreArray. This can lead to undesired behaviour. At least\n"
159 <<
"remember to use SVDShaperDigitSorter in your path and \n"
160 <<
"set the silentlyAppend parameter of SVDUnpacker to true.");
163 vector<SVDDAQDiagnostic*> vDiagnostic_ptr;
165 map<SVDShaperDigit, SVDDAQDiagnostic*> diagnosticMap;
167 map<unsigned short, set<pair<unsigned short, unsigned short> > > apvsByPipeline;
170 B2ERROR(
"Missing valid EventMetaData." << std::endl <<
"No SVDShaperDigit produced for this event!");
174 bool nFADCmatch =
true;
175 bool nAPVmatch =
true;
176 bool badMapping =
false;
177 bool badHeader =
false;
178 bool badTrailer =
false;
179 bool missedHeader =
false;
180 bool missedTrailer =
false;
183 bool isSetEventInfo =
false;
186 bool isSetNAPVsamples =
false;
188 unsigned short nAPVheaders = 999;
189 set<short> seenAPVHeaders = {};
191 unsigned short nEntries_rawSVD = rawSVDList.
getEntries();
194 short fadc = 255, apv = 63;
205 for (
unsigned int i = 0; i < nEntries_rawSVD; i++) {
207 unsigned int numEntries_rawSVD = rawSVDList[ i ]->GetNumEntries();
208 for (
unsigned int j = 0; j < numEntries_rawSVD; j++) {
210 unsigned short nWords[4];
211 nWords[0] = rawSVDList[i]->Get1stDetectorNwords(j);
212 nWords[1] = rawSVDList[i]->Get2ndDetectorNwords(j);
213 nWords[2] = rawSVDList[i]->Get3rdDetectorNwords(j);
214 nWords[3] = rawSVDList[i]->Get4thDetectorNwords(j);
216 uint32_t* data32tab[4];
218 data32tab[0] = (uint32_t*)rawSVDList[i]->Get1stDetectorBuffer(j);
219 data32tab[1] = (uint32_t*)rawSVDList[i]->Get2ndDetectorBuffer(j);
220 data32tab[2] = (uint32_t*)rawSVDList[i]->Get3rdDetectorBuffer(j);
221 data32tab[3] = (uint32_t*)rawSVDList[i]->Get4thDetectorBuffer(j);
224 unsigned short ftbError = 0;
225 unsigned short trgType = 0;
226 unsigned short trgNumber = 0;
227 unsigned short daqMode = -1;
228 unsigned short daqType = 0;
231 unsigned short apvErrors;
232 unsigned short pipAddr;
233 unsigned short ftbFlags = 0;
234 unsigned short apvErrorsOR = 0;
236 bool is3sampleData =
false;
237 bool is6sampleData =
false;
239 for (
unsigned int buf = 0; buf < 4; buf++) {
241 if (data32tab[buf] == NULL && nWords[buf] == 0)
continue;
242 if (
m_printRaw)
printB2Debug(data32tab[buf], data32tab[buf], &data32tab[buf][nWords[buf] - 1], nWords[buf]);
244 missedHeader =
false;
245 missedTrailer =
false;
247 uint32_t* data32_it = data32tab[buf];
248 short strip, sample[6];
249 vector<uint32_t> crc16vec;
251 for (; data32_it != &data32tab[buf][nWords[buf]]; data32_it++) {
261 crc16vec.push_back(*data32_it);
267 if (ftbError != 240) {
271 switch (ftbError - 240) {
273 B2ERROR(
"FADC Event Number is different from (FTB & TTD) Event Numbers");
276 B2ERROR(
"TTD Event Number is different from (FTB & FADC) Event Numbers");
279 B2ERROR(
"FTB Event Number is different from (TTD & FADC) Event Numbers");
282 B2ERROR(
"(FTB, TTD & FADC) Event Numbers are different from each other");
285 B2ERROR(
"Problem with errorsField variable in FTB Header" <<
LogVar(
"abnormal value", ftbError));
291 (eventNo & 0xFFFFFF)) {
295 B2ERROR(
"Event number mismatch detected! The event number given by EventMetaData object is different from the one in the FTB Header."
296 <<
LogVar(
"Expected event number & 0xFFFFFF",
317 if (daqType) daqMode = 3;
325 is3sampleData =
false;
326 is6sampleData =
false;
328 if (daqMode == 0) B2ERROR(
"SVDDataFormatCheck: the event " << eventNo <<
329 " is apparently taken with 1-sample mode, this is not expected.");
330 if (daqMode == 1) is3sampleData =
true;
331 if (daqMode == 2) is6sampleData =
true;
339 B2ERROR(
"Event number mismatch detected! The event number given by EventMetaData object is different from the one in the FADC Header. "
340 <<
LogVar(
"Event number", eventNo) <<
LogVar(
"FADC", fadc) <<
LogVar(
"Trigger number LSByte reported by the FADC",
349 if (!isSetEventInfo) {
360 isSetEventInfo =
true;
371 seenAPVHeaders.insert(apv);
378 if (apvErrors != 0) {
385 currentDAQDiagnostic = DAQDiagnostics.
appendNew(trgNumber, trgType, pipAddr, cmc1, cmc2, apvErrors, ftbError, nFADCmatch, nAPVmatch,
386 badHeader, missedHeader, missedTrailer,
388 vDiagnostic_ptr.push_back(currentDAQDiagnostic);
390 apvsByPipeline[pipAddr].insert(make_pair(fadc, apv));
410 if (!isSetNAPVsamples) {
412 isSetNAPVsamples =
true;
415 B2ERROR(
"DAQMode value (indicating 3-sample acquisition mode) doesn't correspond to the actual number of samples (6) in the data! The data might be corrupted!");
429 if (!isSetNAPVsamples) {
431 isSetNAPVsamples =
true;
434 B2ERROR(
"DAQMode value (indicating 6-sample acquisition mode) doesn't correspond to the actual number of samples (3) in the data! The data might be corrupted!");
440 if (newShaperDigit) {
441 diagnosticMap.insert(make_pair(*newShaperDigit, currentDAQDiagnostic));
442 delete newShaperDigit;
444 B2FATAL(
"Respective FADC/APV combination not found -->> incorrect payload in the database! ");
457 if (
APVmap->find(fadc) ==
APVmap->end()) badMapping =
true;
460 unsigned short nAPVs =
APVmap->count(fadc);
462 if (nAPVheaders == 0) {
463 currentDAQDiagnostic = DAQDiagnostics.
appendNew(0, 0, 0, 0, 0, 0, ftbError, nFADCmatch, nAPVmatch, badHeader, 0, 0, fadc, 0);
464 vDiagnostic_ptr.push_back(currentDAQDiagnostic);
467 if (nAPVs != nAPVheaders) {
469 for (
const auto& fadcApv : *
APVmap) {
470 if (fadcApv.first != fadc)
continue;
471 if (seenAPVHeaders.find(fadcApv.second) == seenAPVHeaders.end()) {
473 auto missingRec =
m_missingAPVs.find(make_pair(fadcApv.first, fadcApv.second));
476 if (missingRec->second.first > eventNo)
477 missingRec->second.first = eventNo;
478 if (missingRec->second.second < eventNo)
479 missingRec->second.second = eventNo;
484 make_pair(fadcApv.first, fadcApv.second),
485 make_pair(eventNo, eventNo)
488 int(fadcApv.second)) <<
LogVar(
"FADC",
489 int(fadcApv.first)));
496 seenAPVHeaders.clear();
499 if ((ftbFlags >> 5) != 0) badTrailer =
true;
503 B2ERROR(
" FTB Flags variable has an active error bit(s)" <<
LogVar(
"on FADC number", fadc));
505 if (ftbFlags & 16) B2ERROR(
"----> CRC error has been detected. Data might be corrupted!");
506 if (ftbFlags & 8) B2ERROR(
"----> Bad Event indication has been detected. Data might be corrupted!");
507 if (ftbFlags & 4) B2ERROR(
"----> Double Header has been detected. Data might be corrupted!");
508 if (ftbFlags & 2) B2ERROR(
"----> Time Out has been detected. Data might be corrupted!");
509 if (ftbFlags & 1) B2ERROR(
"----> Event Too Long! Data might be corrupted!");
524 unsigned short iCRC = crc16vec.size();
525 uint32_t crc16input[iCRC];
527 for (
unsigned short icrc = 0; icrc < iCRC; icrc++)
528 crc16input[icrc] = htonl(crc16vec.at(icrc));
531 boost::crc_basic<16> bcrc(0x8005, 0xffff, 0,
false,
false);
532 bcrc.process_block(crc16input, crc16input + iCRC);
533 unsigned int checkCRC = bcrc.checksum();
536 B2WARNING(
"FTB CRC16 checksum DOES NOT MATCH" <<
LogVar(
"for FADC no.", fadc));
548 if (!(
seenHeadersAndTrailers & 1)) {B2ERROR(
"Missing FTB Header is detected. SVD data might be corrupted!" <<
LogVar(
"Event number", eventNo) <<
LogVar(
"FADC", fadc)); missedHeader =
true;}
549 if (!(
seenHeadersAndTrailers & 2)) {B2ERROR(
"Missing FADC Header is detected -> related FADC number couldn't be retreived. SVD data might be corrupted! " <<
LogVar(
"Event number", eventNo) <<
LogVar(
"previous FADC", fadc)); missedHeader =
true;}
550 if (!(
seenHeadersAndTrailers & 4)) {B2ERROR(
"Missing FADC Trailer is detected. SVD data might be corrupted!" <<
LogVar(
"Event number", eventNo) <<
LogVar(
"FADC", fadc)); missedTrailer =
true;}
551 if (!(
seenHeadersAndTrailers & 8)) {B2ERROR(
"Missing FTB Trailer is detected. SVD data might be corrupted!" <<
LogVar(
"Event number", eventNo) <<
LogVar(
"FADC", fadc)); missedTrailer =
true;}
557 for (
auto p : vDiagnostic_ptr) {
559 p->setFTBFlags(ftbFlags);
560 p->setApvErrorOR(apvErrorsOR);
561 p->setAPVMatch(nAPVmatch);
562 p->setBadMapping(badMapping);
563 p->setBadTrailer(badTrailer);
564 p->setMissedHeader(missedHeader);
565 p->setMissedTrailer(missedTrailer);
567 vDiagnostic_ptr.clear();
575 auto major_apv = max_element(apvsByPipeline.begin(), apvsByPipeline.end(),
576 [](
const decltype(apvsByPipeline)::value_type & p1,
577 const decltype(apvsByPipeline)::value_type & p2) ->
bool
578 {
return p1.second.size() < p2.second.size(); }
582 for (
auto& p : DAQDiagnostics)
583 p.setEmuPipelineAddress(major_apv->first);
585 if (apvsByPipeline.size() > 1)
586 for (
const auto& p : apvsByPipeline) {
587 if (p.first == major_apv->first)
continue;
588 for (
const auto& fadcApv : p.second) {
590 auto upsetRec =
m_upsetAPVs.find(make_pair(fadcApv.first, fadcApv.second));
593 if (upsetRec->second.first > eventNo)
594 upsetRec->second.first = eventNo;
595 if (upsetRec->second.second < eventNo)
596 upsetRec->second.second = eventNo;
601 make_pair(fadcApv.first, fadcApv.second),
602 make_pair(eventNo, eventNo)
604 for (
auto& pp : DAQDiagnostics) {
606 if (pp.getFADCNumber() == fadcApv.first and pp.getAPVNumber() == fadcApv.second)
607 pp.setUpsetAPV(
true);
610 int(fadcApv.first)) <<
LogVar(
"Event number", eventNo));
617 for (
auto& p : diagnosticMap) {
619 if ((
m_killUpsetDigits && p.second->getPipelineAddress() != p.second->getEmuPipelineAddress()) || p.second->getFTBError() != 240
620 || p.second->getFTBFlags() || p.second->getAPVError() || !(p.second->getAPVMatch()) || !(p.second->getFADCMatch())
621 || p.second->getBadHeader()
622 || p.second->getBadMapping() || p.second->getUpsetAPV() || p.second->getMissedHeader() || p.second->getMissedTrailer())
continue;
632 #pragma GCC diagnostic pop
639 B2WARNING(
"SVDUnpacker summary 1: Missing APVs");
641 B2WARNING(
LogVar(
"Missing APV", miss.first.second) <<
LogVar(
"FADC", miss.first.first) <<
LogVar(
"since event",
642 miss.second.first) <<
LogVar(
"to event", miss.second.second));
645 B2WARNING(
"SVDUnpacker summary 2: Upset APVs");
647 B2WARNING(
LogVar(
"Upset APV", upst.first.second) <<
LogVar(
"FADC", upst.first.first) <<
648 LogVar(
"since event", upst.second.first) <<
LogVar(
"to event", upst.second.second));
657 uint32_t* min = std::max((data32 - nWords), data32_min);
658 uint32_t* max = std::min((data32 + nWords), data32_max);
661 std::stringstream os;
662 os << std::hex << std::setfill(
'0');
663 for (uint32_t* ptr = min; ptr <= max; ++ptr) {
664 os << std::setw(8) << *ptr;
665 if (++counter % 10 == 0) os << std::endl;