Belle II Software  release-06-00-14
SVDUnpackerModule.cc
1 /**************************************************************************
2  * basf2 (Belle II Analysis Software Framework) *
3  * Author: The Belle II Collaboration *
4  * *
5  * See git log for contributors and copyright holders. *
6  * This file is licensed under LGPL-3.0, see LICENSE.md. *
7  **************************************************************************/
8 
9 #include <svd/modules/svdUnpacker/SVDUnpackerModule.h>
10 
11 
12 #include <framework/datastore/DataStore.h>
13 #include <framework/datastore/StoreObjPtr.h>
14 #include <framework/logging/Logger.h>
15 
16 #include <boost/crc.hpp> // for boost::crc_basic, boost::augmented_crc
17 #define CRC16POLYREV 0x8005 // CRC-16 polynomial, normal representation
18 
19 #include <arpa/inet.h>
20 
21 #include <sstream>
22 #include <iomanip>
23 #include <cstring>
24 #include <vector>
25 #include <set>
26 #include <map>
27 #include <utility>
28 #include <algorithm>
29 
30 using namespace std;
31 using namespace Belle2;
32 using namespace Belle2::SVD;
33 
34 //-----------------------------------------------------------------
35 // Register the Module
36 //-----------------------------------------------------------------
37 REG_MODULE(SVDUnpacker)
38 
39 //-----------------------------------------------------------------
40 // Implementation
41 //-----------------------------------------------------------------
42 
43 std::string Belle2::SVD::SVDUnpackerModule::m_xmlFileName = std::string("SVDChannelMapping.xml");
44 
45 SVDUnpackerModule::SVDUnpackerModule() : Module(),
46  m_mapping(m_xmlFileName),
47  m_shutUpFTBError(0),
48  m_FADCTriggerNumberOffset(0)
49 {
50  //Set module properties
51  setDescription("Produce SVDShaperDigits from RawSVD. NOTE: only zero-suppressed mode is currently supported!");
53 
54  addParam("SVDEventInfo", m_svdEventInfoName, "Name of the SVDEventInfo object", string(""));
55  addParam("rawSVDListName", m_rawSVDListName, "Name of the raw SVD List", string(""));
56  addParam("svdShaperDigitListName", m_svdShaperDigitListName, "Name of the SVDShaperDigits list", string(""));
57  addParam("shutUpFTBError", m_shutUpFTBError,
58  "if >0 is the number of reported FTB header ERRORs before quiet operations. If <0 full log produced.", -1);
59  addParam("FADCTriggerNumberOffset", m_FADCTriggerNumberOffset,
60  "number to be added to the FADC trigger number to match the main trigger number", 0);
61  addParam("svdDAQDiagnosticsListName", m_svdDAQDiagnosticsListName, "Name of the DAQDiagnostics list", string(""));
62  addParam("softwarePipelineAddressEmulation", m_emulatePipelineAddress, "Estimate emulated pipeline address", bool(true));
63  addParam("killDigitsFromUpsetAPVs", m_killUpsetDigits, "Delete digits from upset APVs", bool(false));
64  addParam("silentlyAppend", m_silentAppend, "Append digits to a pre-existing non-empty storeArray", bool(false));
65  addParam("badMappingFatal", m_badMappingFatal, "Throw B2FATAL if there's a wrong payload in the database", bool(false));
66  addParam("UnpackerErrorRate", m_errorRate, "Unpacker will print one error every UnpackerErrorRate", int(1000));
67  addParam("PrintRawData", m_printRaw, "Printing Raw data words for debugging", bool(false));
68 }
69 
71 {
72 }
73 
75 {
76  m_eventMetaDataPtr.isRequired();
77  // Don't panic if no SVD data.
78  m_rawSVD.isOptional(m_rawSVDListName);
79 
80  // Register default SVDEventInfo for unpacking Raw Data
82 
85 
86  m_storeShaperDigits.registerInDataStore(m_svdShaperDigitListName);
88 
89 }
90 
92 {
93  if (!m_mapping.isValid())
94  B2FATAL("no valid SVD Channel Mapping. We stop here.");
95 
96  m_wrongFTBcrc = 0;
97  if (m_mapping.hasChanged()) { m_map = std::make_unique<SVDOnlineToOfflineMap>(m_mapping->getFileName()); }
98 
99  if (! m_map) { //give up
100  B2ERROR("SVD xml map not loaded." << std::endl <<
101  "No SVDShaperDigit will be produced for this run!");
102  return;
103  }
104 
105  //number of FADC boards
106  nFADCboards = m_map->getFADCboardsNumber();
107 
108  //passing APV<->FADC mapping from SVDOnlineToOfflineMap object
109  APVmap = &(m_map->APVforFADCmap);
110 
111  //setting UnpackerErrorRate factor to use it for BadMapping error suppression
112  m_map->setErrorRate(m_errorRate);
113 
114  nTriggerMatchErrors = -1;
115  nEventMatchErrors = -1;
116  nUpsetAPVsErrors = -1;
117  nErrorFieldErrors = -1;
118  nMissingAPVsErrors = -1;
119  nFADCMatchErrors = -1;
120  nAPVErrors = -1;
121  nFTBFlagsErrors = -1;
123 
125 
126  //get the relative time shift
127  if (!m_svdGlobalConfig.isValid())
128  B2FATAL("SVDGlobalConfigParameters not valid!!");
129 
130  m_relativeTimeShift = m_svdGlobalConfig->getRelativeTimeShift();
131 
132 }
133 
134 #ifndef __clang__
135 #pragma GCC diagnostic push
136 #pragma GCC diagnostic ignored "-Wstack-usage="
137 #endif
139 {
140  if (!m_rawSVD || !m_rawSVD.getEntries())
141  return;
142 
144  B2WARNING("Unpacking SVDShaperDigits to a non-empty pre-existing \n"
145  << "StoreArray. This can lead to undesired behaviour. At least\n"
146  << "remember to use SVDShaperDigitSorter in your path and \n"
147  << "set the silentlyAppend parameter of SVDUnpacker to true.");
148 
149  SVDDAQDiagnostic* currentDAQDiagnostic;
150  vector<SVDDAQDiagnostic*> vDiagnostic_ptr;
151 
152  map<SVDShaperDigit, SVDDAQDiagnostic*> diagnosticMap;
153  // Store encountered pipeline addresses with APVs in which they were observed
154  map<unsigned short, set<pair<unsigned short, unsigned short> > > apvsByPipeline;
155 
156  if (!m_eventMetaDataPtr.isValid()) { // give up...
157  B2ERROR("Missing valid EventMetaData." << std::endl << "No SVDShaperDigit produced for this event!");
158  return;
159  }
160 
161  bool nFADCmatch = true;
162  bool nAPVmatch = true;
163  bool badMapping = false;
164  bool badHeader = false;
165  bool badTrailer = false;
166  bool missedHeader = false;
167  bool missedTrailer = false;
168 
169  // flag to set SVDEventInfo once per event
170  bool isSetEventInfo = false;
171 
172  //flag to set nAPVsamples in SVDEventInfo once per event
173  bool isSetNAPVsamples = false;
174 
175  unsigned short nAPVheaders = 999;
176  set<short> seenAPVHeaders = {};
177 
178  unsigned short nEntries_rawSVD = m_rawSVD.getEntries();
179  auto eventNo = m_eventMetaDataPtr->getEvent();
180 
181  short fadc = 255, apv = 63;
182 
183  if (nEntries_rawSVD != nFADCboards) {
185  if (!(nFADCMatchErrors % m_errorRate)) B2ERROR("Number of RawSVD data objects do not match the number of FADC boards" <<
186  LogVar("#RawSVD",
187  nEntries_rawSVD) << LogVar("#FADCs", nFADCboards) << LogVar("Event number", eventNo));
188 
189  nFADCmatch = false;
190  }
191 
192  for (unsigned int i = 0; i < nEntries_rawSVD; i++) {
193 
194  unsigned int numEntries_rawSVD = m_rawSVD[ i ]->GetNumEntries();
195  for (unsigned int j = 0; j < numEntries_rawSVD; j++) {
196 
197  unsigned short nWords[4];
198  nWords[0] = m_rawSVD[i]->Get1stDetectorNwords(j);
199  nWords[1] = m_rawSVD[i]->Get2ndDetectorNwords(j);
200  nWords[2] = m_rawSVD[i]->Get3rdDetectorNwords(j);
201  nWords[3] = m_rawSVD[i]->Get4thDetectorNwords(j);
202 
203  uint32_t* data32tab[4]; //vector of pointers
204 
205  data32tab[0] = (uint32_t*)m_rawSVD[i]->Get1stDetectorBuffer(j); // points at the begining of the 1st buffer
206  data32tab[1] = (uint32_t*)m_rawSVD[i]->Get2ndDetectorBuffer(j);
207  data32tab[2] = (uint32_t*)m_rawSVD[i]->Get3rdDetectorBuffer(j);
208  data32tab[3] = (uint32_t*)m_rawSVD[i]->Get4thDetectorBuffer(j);
209 
210 
211  unsigned short ftbError = 0;
212  unsigned short trgType = 0;
213  unsigned short trgNumber = 0;
214  unsigned short daqMode = -1;
215  unsigned short daqType = 0;
216  unsigned short cmc1;
217  unsigned short cmc2;
218  unsigned short apvErrors;
219  unsigned short pipAddr;
220  unsigned short ftbFlags = 0;
221  unsigned short apvErrorsOR = 0;
222 
223  bool is3sampleData = false;
224  bool is6sampleData = false;
225 
226  for (unsigned int buf = 0; buf < 4; buf++) { // loop over 4 buffers
227 
228  if (data32tab[buf] == nullptr && nWords[buf] == 0) continue;
229  if (m_printRaw) printB2Debug(data32tab[buf], data32tab[buf], &data32tab[buf][nWords[buf] - 1], nWords[buf]);
230 
231  missedHeader = false;
232  missedTrailer = false;
233 
234  uint32_t* data32_it = data32tab[buf];
235  short strip, sample[6];
236  vector<uint32_t> crc16vec;
237 
238  for (; data32_it != &data32tab[buf][nWords[buf]]; data32_it++) {
239  m_data32 = *data32_it; //put current 32-bit frame to union
240 
241  if (m_data32 == 0xffaa0000) { // first part of FTB header
242  crc16vec.clear(); // clear the input container for crc16 calculation
243  crc16vec.push_back(m_data32);
244 
245  seenHeadersAndTrailers++; // we found FTB header
246 
247  data32_it++; // go to 2nd part of FTB header
248  crc16vec.push_back(*data32_it);
249 
250  m_data32 = *data32_it; //put the second 32-bit frame to union
251 
252  ftbError = m_FTBHeader.errorsField;
253 
254  if (ftbError != 240) {
256 
257  if (!(nErrorFieldErrors % m_errorRate) or nErrorFieldErrors < 100) {
258  switch (ftbError - 240) {
259  case 3:
260  B2ERROR("FADC Event Number is different from (FTB & TTD) Event Numbers");
261  break;
262  case 5:
263  B2ERROR("TTD Event Number is different from (FTB & FADC) Event Numbers");
264  break;
265  case 6:
266  B2ERROR("FTB Event Number is different from (TTD & FADC) Event Numbers");
267  break;
268  case 7:
269  B2ERROR("(FTB, TTD & FADC) Event Numbers are different from each other");
270  break;
271  default:
272  B2ERROR("Problem with errorsField variable in FTB Header" << LogVar("abnormal value", ftbError));
273  }
274  }
275  }
276 
277  if (m_FTBHeader.eventNumber !=
278  (eventNo & 0xFFFFFF)) {
281  m_shutUpFTBError -= 1;
282  B2ERROR("Event number mismatch detected! The event number given by EventMetaData object is different from the one in the FTB Header."
283  << LogVar("Expected event number & 0xFFFFFF",
284  (eventNo & 0xFFFFFF)) << LogVar("Event number in the FTB", m_FTBHeader.eventNumber));
285  }
286  }
287 
288  continue;
289  } // is FTB Header
290 
291  crc16vec.push_back(m_data32);
292 
293  if (m_MainHeader.check == 6) { // FADC header
294 
295  seenHeadersAndTrailers += 2; //we found FADC Header
296 
297  fadc = m_MainHeader.FADCnum;
298  trgType = m_MainHeader.trgType;
299  trgNumber = m_MainHeader.trgNumber;
300  daqMode = m_MainHeader.DAQMode;
301  daqType = m_MainHeader.DAQType;
302 
303  //Let's add run-dependent info: daqMode="11" in case of 3-mixed-6 sample acquisition mode.
304  if (daqType) daqMode = 3;
305 
306  nAPVheaders = 0; // start counting APV headers for this FADC
307  nAPVmatch = true; //assume correct # of APV headers
308  badMapping = false; //assume correct mapping
309  badHeader = false;
310  badTrailer = false;
311 
312  is3sampleData = false;
313  is6sampleData = false;
314 
315  if (daqMode == 0) B2ERROR("SVDDataFormatCheck: the event " << eventNo <<
316  " is apparently taken with 1-sample mode, this is not expected.");
317  if (daqMode == 1) is3sampleData = true;
318  if (daqMode == 2) is6sampleData = true;
319 
320  if (
322  ((eventNo - m_FADCTriggerNumberOffset) & 0xFF)) {
323 
326  B2ERROR("Event number mismatch detected! The event number given by EventMetaData object is different from the one in the FADC Header. "
327  << LogVar("Event number", eventNo) << LogVar("FADC", fadc) << LogVar("Trigger number LSByte reported by the FADC",
328  m_MainHeader.trgNumber) << LogVar("+ offset", m_FADCTriggerNumberOffset) << LogVar("expected", (eventNo & 0xFF)));
329  badHeader = true;
330  }
331 
332  // create SVDModeByte object from MainHeader vars
334 
335  // create SVDEventInfo and fill it with SVDModeByte & SVDTriggerType objects
336  if (!isSetEventInfo) {
337  m_SVDTriggerType = SVDTriggerType(trgType);
338  m_svdEventInfoPtr.create();
339  m_svdEventInfoPtr->setModeByte(m_SVDModeByte);
340  m_svdEventInfoPtr->setTriggerType(m_SVDTriggerType);
341 
342  //set relative time shift
343  m_svdEventInfoPtr->setRelativeShift(m_relativeTimeShift);
344  // set X-talk info online from Raw Data
345  m_svdEventInfoPtr->setCrossTalk(m_MainHeader.xTalk);
346 
347  isSetEventInfo = true;
348  } else { // let's check if the current SVDModeByte and SVDTriggerType are consistent with the one stored in SVDEventInfo
349  if (m_SVDModeByte != m_svdEventInfoPtr->getModeByte()) {m_svdEventInfoPtr->setMatchModeByte(false); badHeader = true; nEventInfoMatchErrors++;}
350  if (trgType != (m_svdEventInfoPtr->getTriggerType()).getType()) { m_svdEventInfoPtr->setMatchTriggerType(false); badHeader = true; nEventInfoMatchErrors++;}
351  }
352  } // is FADC header
353 
354  if (m_APVHeader.check == 2) { // APV header
355 
356  nAPVheaders++;
357  apv = m_APVHeader.APVnum;
358  seenAPVHeaders.insert(apv);
359 
360  cmc1 = m_APVHeader.CMC1;
361  cmc2 = m_APVHeader.CMC2;
362  apvErrors = m_APVHeader.apvErr;
363  pipAddr = m_APVHeader.pipelineAddr;
364 
365  if (apvErrors != 0) {
366  nAPVErrors++;
367  if (!(nAPVErrors % m_errorRate)
368  or nAPVErrors < 100) B2ERROR("APV error has been detected." << LogVar("FADC", fadc) << LogVar("APV", apv) << LogVar("Error value",
369  apvErrors));
370  }
371  // temporary SVDDAQDiagnostic object (no info from trailers and APVmatch code)
372  currentDAQDiagnostic = m_storeDAQDiagnostics.appendNew(trgNumber, trgType, pipAddr, cmc1, cmc2, apvErrors, ftbError, nFADCmatch,
373  nAPVmatch,
374  badHeader, missedHeader, missedTrailer,
375  fadc, apv);
376  vDiagnostic_ptr.push_back(currentDAQDiagnostic);
377 
378  apvsByPipeline[pipAddr].insert(make_pair(fadc, apv));
379  } //is APV Header
380 
381  if (m_data_A.check == 0) { // data
382  strip = m_data_A.stripNum;
383 
384  sample[0] = m_data_A.sample1;
385  sample[1] = m_data_A.sample2;
386  sample[2] = m_data_A.sample3;
387 
388  sample[3] = 0;
389  sample[4] = 0;
390  sample[5] = 0;
391 
392  // Let's check the next rawdata word to determine if we acquired 3 or 6 sample
393  data32_it++;
394  m_data32 = *data32_it;
395 
396  if (m_data_B.check == 0 && strip == m_data_B.stripNum) { // 2nd data frame with the same strip number -> six samples
397 
398  if (!isSetNAPVsamples) {
399  m_svdEventInfoPtr->setNSamples(6);
400  isSetNAPVsamples = true;
401  } else {
402  if (is3sampleData)
403  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!");
404  }
405 
406  crc16vec.push_back(m_data32);
407 
408  sample[3] = m_data_B.sample4;
409  sample[4] = m_data_B.sample5;
410  sample[5] = m_data_B.sample6;
411  }
412 
413  else { // three samples
414  data32_it--;
415  m_data32 = *data32_it;
416 
417  if (!isSetNAPVsamples) {
418  m_svdEventInfoPtr->setNSamples(3);
419  isSetNAPVsamples = true;
420  } else {
421  if (is6sampleData)
422  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!");
423  }
424  }
425 
426  // Generating SVDShaperDigit object
427  SVDShaperDigit* newShaperDigit = m_map->NewShaperDigit(fadc, apv, strip, sample, 0.0);
428  if (newShaperDigit) {
429  diagnosticMap.insert(make_pair(*newShaperDigit, currentDAQDiagnostic));
430  delete newShaperDigit;
431  } else if (m_badMappingFatal) {
432  B2FATAL("Respective FADC/APV combination not found -->> incorrect payload in the database! ");
433  } else {
434  badMapping = true;
435  }
436 
437  } //is data frame
438 
439 
440  if (m_FADCTrailer.check == 14) { // FADC trailer
441 
442  seenHeadersAndTrailers += 4; // we found FAD trailer
443 
444  //additional check if we have a faulty/fake FADC that is not in the map
445  if (APVmap->find(fadc) == APVmap->end()) badMapping = true;
446 
447  //comparing number of APV chips and the number of APV headers, for the current FADC
448  unsigned short nAPVs = APVmap->count(fadc);
449 
450  if (nAPVheaders == 0) {
451  currentDAQDiagnostic = m_storeDAQDiagnostics.appendNew(0, 0, 0, 0, 0, 0, ftbError, nFADCmatch, nAPVmatch, badHeader, 0, 0, fadc, 0);
452  vDiagnostic_ptr.push_back(currentDAQDiagnostic);
453  }
454 
455  if (nAPVs != nAPVheaders) {
456  // There is an APV missing, detect which it is.
457  for (const auto& fadcApv : *APVmap) {
458  if (fadcApv.first != fadc) continue;
459  if (seenAPVHeaders.find(fadcApv.second) == seenAPVHeaders.end()) {
460  // We have a missing APV. Look if it is a known one.
461  auto missingRec = m_missingAPVs.find(make_pair(fadcApv.first, fadcApv.second));
462  if (missingRec != m_missingAPVs.end()) {
463  // This is known to be missing, so keep quiet and just update event counters
464  if (missingRec->second.first > eventNo)
465  missingRec->second.first = eventNo;
466  if (missingRec->second.second < eventNo)
467  missingRec->second.second = eventNo;
468  } else {
469  // We haven't seen this previously.
471  m_missingAPVs.insert(make_pair(
472  make_pair(fadcApv.first, fadcApv.second),
473  make_pair(eventNo, eventNo)
474  ));
475  if (!(nMissingAPVsErrors % m_errorRate)) B2ERROR("missing APV header! " << LogVar("Event number", eventNo) << LogVar("APV",
476  int(fadcApv.second)) << LogVar("FADC",
477  int(fadcApv.first)));
478  }
479  }
480  }
481  nAPVmatch = false;
482  } // is nAPVs != nAPVheaders
483 
484  seenAPVHeaders.clear();
485 
486  ftbFlags = m_FADCTrailer.FTBFlags;
487  if ((ftbFlags >> 5) != 0) badTrailer = true;
488  if (ftbFlags != 0) {
489  nFTBFlagsErrors++;
490  if (!(nFTBFlagsErrors % m_errorRate) or nFTBFlagsErrors < 100) {
491  B2ERROR(" FTB Flags variable has an active error bit(s)" << LogVar("on FADC number", fadc));
492 
493  if (ftbFlags & 16) B2ERROR("----> CRC error has been detected. Data might be corrupted!");
494  if (ftbFlags & 8) B2ERROR("----> Bad Event indication has been detected. Data might be corrupted!");
495  if (ftbFlags & 4) B2ERROR("----> Double Header has been detected. Data might be corrupted!");
496  if (ftbFlags & 2) B2ERROR("----> Time Out has been detected. Data might be corrupted!");
497  if (ftbFlags & 1) B2ERROR("----> Event Too Long! Data might be corrupted!");
498  }
499  }
500 
501  apvErrorsOR = m_FADCTrailer.apvErrOR;
502 
503 
504  }// is FADC trailer
505 
506  if (m_FTBTrailer.controlWord == 0xff55) {// FTB trailer
507 
508  seenHeadersAndTrailers += 8; // we found FTB trailer
509 
510  //check CRC16
511  crc16vec.pop_back();
512  unsigned short iCRC = crc16vec.size();
513  uint32_t crc16input[iCRC];
514 
515  for (unsigned short icrc = 0; icrc < iCRC; icrc++)
516  crc16input[icrc] = htonl(crc16vec.at(icrc));
517 
518  //verify CRC16
519  boost::crc_basic<16> bcrc(0x8005, 0xffff, 0, false, false);
520  bcrc.process_block(crc16input, crc16input + iCRC);
521  unsigned int checkCRC = bcrc.checksum();
522 
523  if (checkCRC != m_FTBTrailer.crc16) {
524  B2WARNING("FTB CRC16 checksum DOES NOT MATCH" << LogVar("for FADC no.", fadc));
525  m_wrongFTBcrc++;
526  }
527 
528  } // is FTB trailer
529 
530  } // end loop over 32-bit frames in each buffer
531 
532  } // end iteration on 4 data buffers
533 
534  //Let's check if all the headers and trailers were in place in the last frame
535  if (seenHeadersAndTrailers != 0xf) {
536  if (!(seenHeadersAndTrailers & 1)) {B2ERROR("Missing FTB Header is detected. SVD data might be corrupted!" << LogVar("Event number", eventNo) << LogVar("FADC", fadc)); missedHeader = true;}
537  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;}
538  if (!(seenHeadersAndTrailers & 4)) {B2ERROR("Missing FADC Trailer is detected. SVD data might be corrupted!" << LogVar("Event number", eventNo) << LogVar("FADC", fadc)); missedTrailer = true;}
539  if (!(seenHeadersAndTrailers & 8)) {B2ERROR("Missing FTB Trailer is detected. SVD data might be corrupted!" << LogVar("Event number", eventNo) << LogVar("FADC", fadc)); missedTrailer = true;}
540  }
541 
542  //reset value for headers and trailers check
544 
545  for (auto p : vDiagnostic_ptr) {
546  // adding remaining info to Diagnostic object
547  p->setFTBFlags(ftbFlags);
548  p->setApvErrorOR(apvErrorsOR);
549  p->setAPVMatch(nAPVmatch);
550  p->setBadMapping(badMapping);
551  p->setBadTrailer(badTrailer);
552  p->setMissedHeader(missedHeader);
553  p->setMissedTrailer(missedTrailer);
554 
555  }
556 
557  vDiagnostic_ptr.clear();
558 
559  } // end event loop
560 
561  }// end loop over RawSVD objects
562 
563  // Detect upset APVs and report/treat
564  auto major_apv = max_element(apvsByPipeline.begin(), apvsByPipeline.end(),
565  [](const decltype(apvsByPipeline)::value_type & p1,
566  const decltype(apvsByPipeline)::value_type & p2) -> bool
567  { return p1.second.size() < p2.second.size(); }
568  );
569  // We set emuPipelineAddress fields in diagnostics to this.
571  for (auto& p : m_storeDAQDiagnostics)
572  p.setEmuPipelineAddress(major_apv->first);
573  // And report any upset apvs or update records
574  if (apvsByPipeline.size() > 1)
575  for (const auto& p : apvsByPipeline) {
576  if (p.first == major_apv->first) continue;
577  for (const auto& fadcApv : p.second) {
578  // We have an upset APV. Look if it is a known one.
579  auto upsetRec = m_upsetAPVs.find(make_pair(fadcApv.first, fadcApv.second));
580  if (upsetRec != m_upsetAPVs.end()) {
581  // This is known to be upset, so keep quiet and update event counters
582  if (upsetRec->second.first > eventNo)
583  upsetRec->second.first = eventNo;
584  if (upsetRec->second.second < eventNo)
585  upsetRec->second.second = eventNo;
586  } else {
587  // We haven't seen this one previously.
589  m_upsetAPVs.insert(make_pair(
590  make_pair(fadcApv.first, fadcApv.second),
591  make_pair(eventNo, eventNo)
592  ));
593  for (auto& pp : m_storeDAQDiagnostics) {
594 
595  if (pp.getFADCNumber() == fadcApv.first and pp.getAPVNumber() == fadcApv.second)
596  pp.setUpsetAPV(true);
597  }
598  if (!(nUpsetAPVsErrors % m_errorRate)) B2ERROR("Upset APV detected!!!" << LogVar("APV", int(fadcApv.second)) << LogVar("FADC",
599  int(fadcApv.first)) << LogVar("Event number", eventNo));
600  }
601  }
602  }
603 
604  // Here we can delete digits coming from upset APVs. We detect them by comparing
605  // actual and emulated pipeline address fields in DAQDiagnostics.
606  for (auto& p : diagnosticMap) {
607 
608  if ((m_killUpsetDigits && p.second->getPipelineAddress() != p.second->getEmuPipelineAddress()) || p.second->getFTBError() != 240
609  || p.second->getFTBFlags() || p.second->getAPVError() || !(p.second->getAPVMatch()) || !(p.second->getFADCMatch())
610  || p.second->getBadHeader()
611  || p.second->getBadMapping() || p.second->getUpsetAPV() || p.second->getMissedHeader() || p.second->getMissedTrailer()) continue;
612  m_storeShaperDigits.appendNew(p.first);
613  }
614 
615  if (!m_svdEventInfoPtr->getMatchTriggerType()) {if (!(nEventInfoMatchErrors % m_errorRate) or nEventInfoMatchErrors < 200) B2WARNING("Inconsistent SVD Trigger Type value for: " << LogVar("Event number", eventNo));}
616  if (!m_svdEventInfoPtr->getMatchModeByte()) {if (!(nEventInfoMatchErrors % m_errorRate) or nEventInfoMatchErrors < 200) B2WARNING("Inconsistent SVD ModeByte object for: " << LogVar("Event number", eventNo));}
617 
618 
619 } //end event function
620 #ifndef __clang__
621 #pragma GCC diagnostic pop
622 #endif
623 
625 {
626  // Summary report on missing APVs
627  if (m_missingAPVs.size() > 0) {
628  B2WARNING("SVDUnpacker summary 1: Missing APVs");
629  for (const auto& miss : m_missingAPVs)
630  B2WARNING(LogVar("Missing APV", miss.first.second) << LogVar("FADC", miss.first.first) << LogVar("since event",
631  miss.second.first) << LogVar("to event", miss.second.second));
632  }
633  if (m_upsetAPVs.size() > 0) {
634  B2WARNING("SVDUnpacker summary 2: Upset APVs");
635  for (const auto& upst : m_upsetAPVs)
636  B2WARNING(LogVar("Upset APV", upst.first.second) << LogVar("FADC", upst.first.first) <<
637  LogVar("since event", upst.second.first) << LogVar("to event", upst.second.second));
638  }
639 }
640 
641 
642 // additional printing function
643 void SVDUnpackerModule::printB2Debug(uint32_t* data32, uint32_t* data32_min, uint32_t* data32_max, int nWords)
644 {
645 
646  uint32_t* min = std::max((data32 - nWords), data32_min);
647  uint32_t* max = std::min((data32 + nWords), data32_max);
648 
649  size_t counter{0};
650  std::stringstream os;
651  os << std::hex << std::setfill('0');
652  for (uint32_t* ptr = min; ptr <= max; ++ptr) {
653  os << std::setw(8) << *ptr;
654  if (++counter % 10 == 0) os << std::endl;
655  else os << " ";
656  }
657 
658  os << std::endl;
659  B2INFO(os.str());
660  return;
661 
662 }
bool hasChanged()
Check whether the object has changed since the last call to hasChanged of the accessor).
bool isValid() const
isValid is always true if we have a filename
Definition: PayloadFile.h:64
@ c_ErrorIfAlreadyRegistered
If the object/array was already registered, produce an error (aborting initialisation).
Definition: DataStore.h:72
Base class for Modules.
Definition: Module.h:72
void setDescription(const std::string &description)
Sets the description of the module.
Definition: Module.cc:214
void setPropertyFlags(unsigned int propertyFlags)
Sets the flags for the module properties.
Definition: Module.cc:208
@ c_ParallelProcessingCertified
This module can be run in parallel processing mode safely (All I/O must be done through the data stor...
Definition: Module.h:80
std::string getFileName() const
Get the name of the downloaded payload file.
Definition: PayloadFile.h:35
Class to store SVD DAQ diagnostic information.
Class to store SVD mode information.
Definition: SVDModeByte.h:69
The SVD ShaperDigit class.
Class to store Trigger Type information.
int m_wrongFTBcrc
FTB CRC no-Match counter.
StoreArray< SVDDAQDiagnostic > m_storeDAQDiagnostics
SVDDAQDiagnostic array.
virtual ~SVDUnpackerModule()
Destructor of the module.
unsigned short seenHeadersAndTrailers
this 4-bits value should be 1111 if no headers/trailers are missing
int m_shutUpFTBError
regulates the number of "Event number mismatch" errors reported
MainHeader m_MainHeader
Implementation of FADC Header.
StoreArray< RawSVD > m_rawSVD
output for RawSVD
FADCTrailer m_FADCTrailer
Implementation of FADC Trailer.
StoreObjPtr< SVDEventInfo > m_svdEventInfoPtr
SVDEventInfo output per event.
virtual void initialize() override
Initializes the Module.
StoreArray< SVDShaperDigit > m_storeShaperDigits
SVDShaperDigit array.
virtual void event() override
event
int nAPVErrors
counter of APV errors
FTBHeader m_FTBHeader
Implementation of FTB Header.
virtual void endRun() override
end run
std::string m_rawSVDListName
RawSVD StoreArray name.
DBObjPtr< PayloadFile > m_mapping
pointer to the payload with the mapping
int nFADCMatchErrors
counter of FADC boards =/= n of RawData objects errors
bool m_killUpsetDigits
Optionally, we can kill digits coming from upset APVs right in the unpacker.
data_B m_data_B
Implementation of 2nd data word.
int m_FADCTriggerNumberOffset
FADC Trigger Offset.
std::map< std::pair< unsigned short, unsigned short >, std::pair< std::size_t, std::size_t > > m_missingAPVs
Map to store a list of missing APVs.
int nMissingAPVsErrors
counter of missing APVs errors
static std::string m_xmlFileName
XML filename.
int nEventMatchErrors
counter of Event match errors
FTBTrailer m_FTBTrailer
Implementation of FTB Trailer.
int m_errorRate
The parameter that indicates what fraction of B2ERRORs messages should be suppressed to not overload ...
APVHeader m_APVHeader
Implementation of APV Header.
int nUpsetAPVsErrors
counter of upset APV errors
void printB2Debug(uint32_t *data32, uint32_t *data32_min, uint32_t *data32_max, int nWords)
additional function that prints raw data words
virtual void beginRun() override
begin run
std::string m_svdShaperDigitListName
SVDShaperDigit StoreArray name.
std::string m_svdEventInfoName
SVDEventInfo name.
DBObjPtr< SVDGlobalConfigParameters > m_svdGlobalConfig
SVDGlobal Configuration payload.
bool m_printRaw
Optionally we can get printout of Raw Data words.
int nEventInfoMatchErrors
counter of inconsistencies in SVDEventInfo within an event
bool m_badMappingFatal
Optionally we can stop the unpacking if there is a missing APV/FADC combination in the mapping -> wro...
int nErrorFieldErrors
counter of event mismatch errors in FTB's ErrorField
data_A m_data_A
Implementation of 1st data word.
uint32_t m_data32
Input 32-bit data word.
StoreObjPtr< EventMetaData > m_eventMetaDataPtr
Required input for EventMetaData.
bool m_silentAppend
Silently append new SVDShaperDigits to a pre-existing non-empty SVDShaperDigits storeArray.
std::unordered_multimap< unsigned char, unsigned char > * APVmap
pointer to APVforFADCmap filled by mapping procedure
SVDTriggerType m_SVDTriggerType
SVDTriggerType object.
SVDModeByte m_SVDModeByte
instance of SVDModeByte for the event
std::unique_ptr< SVDOnlineToOfflineMap > m_map
Pointer to online-to-offline map.
int m_relativeTimeShift
latency difference between the 3- and 6-sample acquired events in usint of APV clock / 4,...
std::map< std::pair< unsigned short, unsigned short >, std::pair< std::size_t, std::size_t > > m_upsetAPVs
Map to store a list of upset APVs.
int nFTBFlagsErrors
counter of errors in FTBFlags variable
bool m_emulatePipelineAddress
Software emulation of pipeline address This is a replacement of hardware pipeline address emulation.
std::string m_svdDAQDiagnosticsListName
SVDDAQDiagnostic StoreArray name.
int nTriggerMatchErrors
counters for specific ERRORS produced by the Unpacker
unsigned short nFADCboards
how many FADCs we have
Class to store variables with their name which were sent to the logging service.
void addParam(const std::string &name, T &paramVariable, const std::string &description, const T &defaultValue)
Adds a new parameter to the module.
Definition: Module.h:560
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Definition: Module.h:650
Namespace to encapsulate code needed for simulation and reconstrucion of the SVD.
Definition: GeoSVDCreator.h:23
Abstract base class for different kinds of events.
unsigned int pipelineAddr
Pipeline Address.
unsigned int CMC1
Common Mode Noise w/o masking out particle signals.
unsigned int check
MSB "10" - for APV Header identification.
unsigned int CMC2
Common Mode Noise after masking out particle signals.
unsigned int apvErr
APV Errors field.
unsigned int apvErrOR
APV Errors Field OR.
unsigned int check
MSB "1110" - for FADC Trailer identification.
unsigned int errorsField
FTB error fields.
unsigned int eventNumber
FTB event number.
unsigned int controlWord
MSB "ff55" - FADC Trailer ID.
unsigned int crc16
FTB CRC16 Checksum
unsigned int DAQType
(from 2020c) Event type(0): "0"…3 or …6 acquisition mode, "1"…3-mixed-6 acquisition mode
unsigned int check
MSB "110" - for FADC Header identification.
unsigned int DAQMode
Event type(2:1): "00"…1-sample, "01"…3-sample, "10"…6-sample.
unsigned int sample3
3rd data sample
unsigned int sample2
2nd data sample
unsigned int check
MSB "1" - for Data word identification.
unsigned int sample1
1st data sample
unsigned int sample6
6th data sample
unsigned int check
MSB "1" - for Data word identification.
unsigned int sample4
4th data sample
unsigned int sample5
5th data sample