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();
100 B2FATAL(
"no valid SVD Channel Mapping. We stop here.");
106 B2ERROR(
"SVD xml map not loaded." << std::endl <<
107 "No SVDShaperDigit will be produced for this run!");
137 B2ERROR(
"SVDDetectorConfiguration not valid!! Setting relativeTimeShift to 0 for this reconstruction.");
143 #pragma GCC diagnostic push
144 #pragma GCC diagnostic ignored "-Wstack-usage="
156 B2WARNING(
"Unpacking SVDShaperDigits to a non-empty pre-existing \n"
157 <<
"StoreArray. This can lead to undesired behaviour. At least\n"
158 <<
"remember to use SVDShaperDigitSorter in your path and \n"
159 <<
"set the silentlyAppend parameter of SVDUnpacker to true.");
162 vector<SVDDAQDiagnostic*> vDiagnostic_ptr;
164 map<SVDShaperDigit, SVDDAQDiagnostic*> diagnosticMap;
166 map<unsigned short, set<pair<unsigned short, unsigned short> > > apvsByPipeline;
169 B2ERROR(
"Missing valid EventMetaData." << std::endl <<
"No SVDShaperDigit produced for this event!");
173 bool nFADCmatch =
true;
174 bool nAPVmatch =
true;
175 bool badMapping =
false;
176 bool badHeader =
false;
177 bool badTrailer =
false;
178 bool missedHeader =
false;
179 bool missedTrailer =
false;
182 bool isSetEventInfo =
false;
185 bool isSetNAPVsamples =
false;
187 unsigned short nAPVheaders = 999;
188 set<short> seenAPVHeaders = {};
190 unsigned short nEntries_rawSVD = rawSVDList.
getEntries();
193 short fadc = 255, apv = 63;
204 for (
unsigned int i = 0; i < nEntries_rawSVD; i++) {
206 unsigned int numEntries_rawSVD = rawSVDList[ i ]->GetNumEntries();
207 for (
unsigned int j = 0; j < numEntries_rawSVD; j++) {
209 unsigned short nWords[4];
210 nWords[0] = rawSVDList[i]->Get1stDetectorNwords(j);
211 nWords[1] = rawSVDList[i]->Get2ndDetectorNwords(j);
212 nWords[2] = rawSVDList[i]->Get3rdDetectorNwords(j);
213 nWords[3] = rawSVDList[i]->Get4thDetectorNwords(j);
215 uint32_t* data32tab[4];
217 data32tab[0] = (uint32_t*)rawSVDList[i]->Get1stDetectorBuffer(j);
218 data32tab[1] = (uint32_t*)rawSVDList[i]->Get2ndDetectorBuffer(j);
219 data32tab[2] = (uint32_t*)rawSVDList[i]->Get3rdDetectorBuffer(j);
220 data32tab[3] = (uint32_t*)rawSVDList[i]->Get4thDetectorBuffer(j);
223 unsigned short ftbError = 0;
224 unsigned short trgType = 0;
225 unsigned short trgNumber = 0;
226 unsigned short daqMode = -1;
227 unsigned short daqType = 0;
230 unsigned short apvErrors;
231 unsigned short pipAddr;
232 unsigned short ftbFlags = 0;
233 unsigned short apvErrorsOR = 0;
235 bool is3sampleData =
false;
236 bool is6sampleData =
false;
238 for (
unsigned int buf = 0; buf < 4; buf++) {
240 if (data32tab[buf] == NULL && nWords[buf] == 0)
continue;
241 if (
m_printRaw)
printB2Debug(data32tab[buf], data32tab[buf], &data32tab[buf][nWords[buf] - 1], nWords[buf]);
243 missedHeader =
false;
244 missedTrailer =
false;
246 uint32_t* data32_it = data32tab[buf];
247 short strip, sample[6];
248 vector<uint32_t> crc16vec;
250 for (; data32_it != &data32tab[buf][nWords[buf]]; data32_it++) {
260 crc16vec.push_back(*data32_it);
266 if (ftbError != 240) {
270 switch (ftbError - 240) {
272 B2ERROR(
"FADC Event Number is different from (FTB & TTD) Event Numbers");
275 B2ERROR(
"TTD Event Number is different from (FTB & FADC) Event Numbers");
278 B2ERROR(
"FTB Event Number is different from (TTD & FADC) Event Numbers");
281 B2ERROR(
"(FTB, TTD & FADC) Event Numbers are different from each other");
284 B2ERROR(
"Problem with errorsField variable in FTB Header" <<
LogVar(
"abnormal value", ftbError));
290 (eventNo & 0xFFFFFF)) {
294 B2ERROR(
"Event number mismatch detected! The event number given by EventMetaData object is different from the one in the FTB Header."
295 <<
LogVar(
"Expected event number & 0xFFFFFF",
316 if (daqType) daqMode = 3;
324 is3sampleData =
false;
325 is6sampleData =
false;
327 if (daqMode == 0) B2ERROR(
"SVDDataFormatCheck: the event " << eventNo <<
328 " is apparently taken with 1-sample mode, this is not expected.");
329 if (daqMode == 1) is3sampleData =
true;
330 if (daqMode == 2) is6sampleData =
true;
338 B2ERROR(
"Event number mismatch detected! The event number given by EventMetaData object is different from the one in the FADC Header. "
339 <<
LogVar(
"Event number", eventNo) <<
LogVar(
"FADC", fadc) <<
LogVar(
"Trigger number LSByte reported by the FADC",
348 if (!isSetEventInfo) {
359 isSetEventInfo =
true;
370 seenAPVHeaders.insert(apv);
377 if (apvErrors != 0) {
384 currentDAQDiagnostic = DAQDiagnostics.
appendNew(trgNumber, trgType, pipAddr, cmc1, cmc2, apvErrors, ftbError, nFADCmatch, nAPVmatch,
385 badHeader, missedHeader, missedTrailer,
387 vDiagnostic_ptr.push_back(currentDAQDiagnostic);
389 apvsByPipeline[pipAddr].insert(make_pair(fadc, apv));
409 if (!isSetNAPVsamples) {
411 isSetNAPVsamples =
true;
414 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!");
428 if (!isSetNAPVsamples) {
430 isSetNAPVsamples =
true;
433 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!");
439 if (newShaperDigit) {
440 diagnosticMap.insert(make_pair(*newShaperDigit, currentDAQDiagnostic));
441 delete newShaperDigit;
443 B2FATAL(
"Respective FADC/APV combination not found -->> incorrect payload in the database! ");
456 if (
APVmap->find(fadc) ==
APVmap->end()) badMapping =
true;
459 unsigned short nAPVs =
APVmap->count(fadc);
461 if (nAPVheaders == 0) {
462 currentDAQDiagnostic = DAQDiagnostics.
appendNew(0, 0, 0, 0, 0, 0, ftbError, nFADCmatch, nAPVmatch, badHeader, 0, 0, fadc, 0);
463 vDiagnostic_ptr.push_back(currentDAQDiagnostic);
466 if (nAPVs != nAPVheaders) {
468 for (
const auto& fadcApv : *
APVmap) {
469 if (fadcApv.first != fadc)
continue;
470 if (seenAPVHeaders.find(fadcApv.second) == seenAPVHeaders.end()) {
472 auto missingRec =
m_missingAPVs.find(make_pair(fadcApv.first, fadcApv.second));
475 if (missingRec->second.first > eventNo)
476 missingRec->second.first = eventNo;
477 if (missingRec->second.second < eventNo)
478 missingRec->second.second = eventNo;
483 make_pair(fadcApv.first, fadcApv.second),
484 make_pair(eventNo, eventNo)
487 int(fadcApv.second)) <<
LogVar(
"FADC",
488 int(fadcApv.first)));
495 seenAPVHeaders.clear();
498 if ((ftbFlags >> 5) != 0) badTrailer =
true;
502 B2ERROR(
" FTB Flags variable has an active error bit(s)" <<
LogVar(
"on FADC number", fadc));
504 if (ftbFlags & 16) B2ERROR(
"----> CRC error has been detected. Data might be corrupted!");
505 if (ftbFlags & 8) B2ERROR(
"----> Bad Event indication has been detected. Data might be corrupted!");
506 if (ftbFlags & 4) B2ERROR(
"----> Double Header has been detected. Data might be corrupted!");
507 if (ftbFlags & 2) B2ERROR(
"----> Time Out has been detected. Data might be corrupted!");
508 if (ftbFlags & 1) B2ERROR(
"----> Event Too Long! Data might be corrupted!");
523 unsigned short iCRC = crc16vec.size();
524 uint32_t crc16input[iCRC];
526 for (
unsigned short icrc = 0; icrc < iCRC; icrc++)
527 crc16input[icrc] = htonl(crc16vec.at(icrc));
530 boost::crc_basic<16> bcrc(0x8005, 0xffff, 0,
false,
false);
531 bcrc.process_block(crc16input, crc16input + iCRC);
532 unsigned int checkCRC = bcrc.checksum();
535 B2WARNING(
"FTB CRC16 checksum DOES NOT MATCH" <<
LogVar(
"for FADC no.", fadc));
547 if (!(
seenHeadersAndTrailers & 1)) {B2ERROR(
"Missing FTB Header is detected. SVD data might be corrupted!" <<
LogVar(
"Event number", eventNo) <<
LogVar(
"FADC", fadc)); missedHeader =
true;}
548 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;}
549 if (!(
seenHeadersAndTrailers & 4)) {B2ERROR(
"Missing FADC Trailer is detected. SVD data might be corrupted!" <<
LogVar(
"Event number", eventNo) <<
LogVar(
"FADC", fadc)); missedTrailer =
true;}
550 if (!(
seenHeadersAndTrailers & 8)) {B2ERROR(
"Missing FTB Trailer is detected. SVD data might be corrupted!" <<
LogVar(
"Event number", eventNo) <<
LogVar(
"FADC", fadc)); missedTrailer =
true;}
556 for (
auto p : vDiagnostic_ptr) {
558 p->setFTBFlags(ftbFlags);
559 p->setApvErrorOR(apvErrorsOR);
560 p->setAPVMatch(nAPVmatch);
561 p->setBadMapping(badMapping);
562 p->setBadTrailer(badTrailer);
563 p->setMissedHeader(missedHeader);
564 p->setMissedTrailer(missedTrailer);
566 vDiagnostic_ptr.clear();
574 auto major_apv = max_element(apvsByPipeline.begin(), apvsByPipeline.end(),
575 [](
const decltype(apvsByPipeline)::value_type & p1,
576 const decltype(apvsByPipeline)::value_type & p2) ->
bool
577 {
return p1.second.size() < p2.second.size(); }
581 for (
auto& p : DAQDiagnostics)
582 p.setEmuPipelineAddress(major_apv->first);
584 if (apvsByPipeline.size() > 1)
585 for (
const auto& p : apvsByPipeline) {
586 if (p.first == major_apv->first)
continue;
587 for (
const auto& fadcApv : p.second) {
589 auto upsetRec =
m_upsetAPVs.find(make_pair(fadcApv.first, fadcApv.second));
592 if (upsetRec->second.first > eventNo)
593 upsetRec->second.first = eventNo;
594 if (upsetRec->second.second < eventNo)
595 upsetRec->second.second = eventNo;
600 make_pair(fadcApv.first, fadcApv.second),
601 make_pair(eventNo, eventNo)
603 for (
auto& pp : DAQDiagnostics) {
605 if (pp.getFADCNumber() == fadcApv.first and pp.getAPVNumber() == fadcApv.second)
606 pp.setUpsetAPV(
true);
609 int(fadcApv.first)) <<
LogVar(
"Event number", eventNo));
616 for (
auto& p : diagnosticMap) {
618 if ((
m_killUpsetDigits && p.second->getPipelineAddress() != p.second->getEmuPipelineAddress()) || p.second->getFTBError() != 240
619 || p.second->getFTBFlags() || p.second->getAPVError() || !(p.second->getAPVMatch()) || !(p.second->getFADCMatch())
620 || p.second->getBadHeader()
621 || p.second->getBadMapping() || p.second->getUpsetAPV() || p.second->getMissedHeader() || p.second->getMissedTrailer())
continue;
631 #pragma GCC diagnostic pop
638 B2WARNING(
"SVDUnpacker summary 1: Missing APVs");
640 B2WARNING(
LogVar(
"Missing APV", miss.first.second) <<
LogVar(
"FADC", miss.first.first) <<
LogVar(
"since event",
641 miss.second.first) <<
LogVar(
"to event", miss.second.second));
644 B2WARNING(
"SVDUnpacker summary 2: Upset APVs");
646 B2WARNING(
LogVar(
"Upset APV", upst.first.second) <<
LogVar(
"FADC", upst.first.first) <<
647 LogVar(
"since event", upst.second.first) <<
LogVar(
"to event", upst.second.second));
656 uint32_t* min = std::max((data32 - nWords), data32_min);
657 uint32_t* max = std::min((data32 + nWords), data32_max);
660 std::stringstream os;
661 os << std::hex << std::setfill(
'0');
662 for (uint32_t* ptr = min; ptr <= max; ++ptr) {
663 os << std::setw(8) << *ptr;
664 if (++counter % 10 == 0) os << std::endl;