Belle II Software  release-06-02-00
ARICHUnpackerModule.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 // Own include
10 #include <arich/modules/arichUnpacker/ARICHUnpackerModule.h>
11 
12 #include <arich/modules/arichUnpacker/ARICHRawDataHeader.h>
13 
14 #include <framework/core/ModuleManager.h>
15 
16 // framework - DataStore
17 #include <framework/datastore/StoreArray.h>
18 #include <framework/datastore/StoreObjPtr.h>
19 
20 // framework aux
21 #include <framework/logging/Logger.h>
22 
23 // Dataobject classes
24 #include <framework/dataobjects/EventMetaData.h>
25 #include <rawdata/dataobjects/RawARICH.h>
26 #include <arich/dataobjects/ARICHDigit.h>
27 #include <arich/dataobjects/ARICHInfo.h>
28 #include <arich/dataobjects/ARICHRawDigit.h>
29 
30 // print bitset
31 #include <bitset>
32 
33 using namespace std;
34 
35 namespace Belle2 {
41  //using namespace ARICH;
42 
43  //-----------------------------------------------------------------
44  // Register module
45  //-----------------------------------------------------------------
46 
47  REG_MODULE(ARICHUnpacker)
48 
49  //-----------------------------------------------------------------
50  // Implementation
51  //-----------------------------------------------------------------
52 
53  ARICHUnpackerModule::ARICHUnpackerModule() : Module(), m_bitMask(0), m_debug(0)
54  {
55  // set module description
56  setDescription("Raw data unpacker for ARICH");
57  setPropertyFlags(c_ParallelProcessingCertified);
58 
59  addParam("bitMask", m_bitMask, "hit bit mask (8 bits/channel, only used for unsuppresed format!)", (uint8_t)0xFF);
60  addParam("debug", m_debug, "prints debug information", 0);
61 
62  addParam("inputRawDataName", m_inputRawDataName, "name of RawARICH store array", string(""));
63  addParam("outputDigitsName", m_outputDigitsName, "name of ARICHDigit store array", string(""));
64  addParam("outputRawDigitsName", m_outputRawDigitsName, "name of ARICHRawDigit store array", string(""));
65  addParam("outputarichinfoName", m_outputarichinfoName, "name of ARICHInfo store array", string(""));
66  addParam("RawUnpackerMode", m_rawmode, "Activate RawUnpacker mode", 0);
67  addParam("DisableUnpackerMode", m_disable_unpacker, "Disable Regular Unpacker mode", 0);
68 
69  }
70 
71  ARICHUnpackerModule::~ARICHUnpackerModule()
72  {
73  }
74 
75  void ARICHUnpackerModule::initialize()
76  {
77 
78  StoreArray<RawARICH> rawData(m_inputRawDataName);
79  rawData.isRequired();
80 
81  StoreArray<ARICHDigit> digits(m_outputDigitsName);
82  digits.registerInDataStore();
83 
84  StoreArray<ARICHRawDigit> rawdigits(m_outputRawDigitsName);
85  rawdigits.registerInDataStore();
86 
87  StoreObjPtr<ARICHInfo> arichinfo(m_outputarichinfoName);
88  arichinfo.registerInDataStore();
89 
90  }
91 
92  void ARICHUnpackerModule::beginRun()
93  {
94  }
95 
96  void ARICHUnpackerModule::event()
97  {
98 
99  StoreArray<RawARICH> rawData(m_inputRawDataName);
100  StoreArray<ARICHDigit> digits(m_outputDigitsName);
101  StoreArray<ARICHRawDigit> rawdigits(m_outputRawDigitsName);
102  StoreObjPtr<ARICHInfo> arichinfo(m_outputarichinfoName);
103  arichinfo.create();
104  StoreObjPtr<EventMetaData> evtMetaData;
105 
106  digits.clear();
107  bool m_pciedata = false;
108  int trgtype = 16;
109  double vth_thscan = 0.0;
110 
111  if (m_debug) {
112  std::cout << std::endl << "------------------------" << std::endl;
113  std::cout << "Run: " << evtMetaData->getRun() << " Event: " << evtMetaData->getEvent() << std::endl;
114  std::cout << "------------------------" << std::endl << std::endl;
115  }
116 
117  unsigned thscan_mode = 0;
118  // regular Unpacker mode, fill ARICHDigit
119 // if (m_disable_unpacker == 0) {
120 
121  for (auto& raw : rawData) {
122  // Check PCIe40 data or Copper data
123  if (raw.GetMaxNumOfCh(0) == 48) { m_pciedata = true; } // Could be 36 or 48
124  else if (raw.GetMaxNumOfCh(0) == 4) { m_pciedata = false; }
125  else { B2FATAL("ARICHUnpackerModule: Invalid value of GetMaxNumOfCh from raw data: " << LogVar("Number of ch: ", raw.GetMaxNumOfCh(0))); }
126 
127  for (int finesse = 0; finesse < raw.GetMaxNumOfCh(0); finesse++) {
128  const int* buffer = raw.GetDetectorBuffer(0, finesse);
129  int bufferSize = raw.GetDetectorNwords(0, finesse);
130 
131  if (bufferSize < 1)
132  continue;
133 
134  // record the trigger type from the B2L data
135  trgtype = raw.GetTRGType(0);
136 
137  // read merger header
138  unsigned ibyte = 0;
139  ARICHRawHeader head;
140 
141  readHeader(buffer, ibyte, head);
142 
143  if (m_debug > 1) printBits(buffer, bufferSize);
144 
145  if (m_debug) {
146  std::cout << "Merger header" << std::endl;
147  head.print();
148  }
149  //-- RawDigit for Merger info
150  int type = (int)head.type;
151  int ver = (int)head.version;
152  int boardid = (int)head.mergerID;
153  int febno = (int)head.FEBSlot;
154  unsigned int length_all = (unsigned int)head.length;
155  unsigned int mrg_evtno = (unsigned int)head.trigger;
156  ARICHRawDigit* rawdigit = rawdigits.appendNew(type, ver, boardid, febno, length_all, mrg_evtno);
157 
158  if (!m_pciedata) {
159  rawdigit->setCopperId(raw.GetNodeID(0));
160  rawdigit->setHslbId(finesse);
161  } else {
162  if (raw.GetNodeID(0) == 0x4000001) {
163  rawdigit->setCopperId(raw.GetNodeID(0) + (int)(finesse / 4));
164  } else if (raw.GetNodeID(0) == 0x4000002) {
165  rawdigit->setCopperId(0x400000A + (int)(finesse / 4));
166  } else {
167  B2FATAL("ARICHUnpackerModule: Invalid Node ID from readout: " << LogVar("NodeID: ", raw.GetNodeID(0)));
168  }
169 
170  rawdigit->setHslbId(finesse % 4);
171  rawdigit->setPcieId(raw.GetNodeID(0));
172  rawdigit->setPcieChId(finesse);
173  }
174 
175  int nfebs = 0;
176  //-- end of RawDigit for Merger info
177 
178  // record the ibyte here
179  unsigned begin = ibyte;
180 
181  while (ibyte < head.length) {
182 
183  // new feb
184  ARICHRawHeader febHead;
185  readFEHeader(buffer, ibyte, febHead);
186  if (febHead.thscan_mode) {thscan_mode++;}
187  if (m_debug) febHead.print();
188 
189  if (/*febHead.type != head.type ||*/ febHead.version != head.version || febHead.mergerID != head.mergerID
190  || febHead.trigger != head.trigger) {
191  B2ERROR("ARICHUnpackerModule: data in FEB header not consistent with data in merger HEADER " << LogVar("FEB ID",
192  (unsigned)febHead.FEBSlot) <<
193  LogVar("merger ID", (unsigned)head.mergerID)); break;
194  }
195 
196  // feb header shift
197  ibyte += ARICHFEB_HEADER_SIZE;
198  int dataLen = febHead.length - ARICHFEB_HEADER_SIZE;
199 
200  febHead.FEBSlot += 1;
201 
202  unsigned mergID = m_mergerMap->getMergerIDfromSN((unsigned)head.mergerID);
203 
204  if (mergID == 99) { B2ERROR("ARICHUnpackerModule: unknown merger number. Merger data will be skipped. " << LogVar("merger ID", mergID) << LogVar("Serial Number", (unsigned)head.mergerID)); break;}
205 
206  unsigned moduleID = m_mergerMap->getModuleID(mergID, (unsigned)febHead.FEBSlot);
207 
208  if (!moduleID) { B2ERROR("ARICHUnpackerModule: no merger to FEB mapping. Merger data will be skipped. " << LogVar("merger ID", mergID) << LogVar("Serial Number", (unsigned)head.mergerID) << LogVar("FEB slot", (unsigned)febHead.FEBSlot)); break;}
209 
210  // read data
211  if (m_debug) std::cout << "Hit channels: " << std::endl;
212  if (febHead.type == 1) {
213  for (int i = 0; i < dataLen / 2; i++) {
214  int shift = (3 - ibyte % 4) * 8;
215  uint8_t asicCh = buffer[ibyte / 4] >> shift;
216  ibyte++;
217  shift = (3 - ibyte % 4) * 8;
218  uint8_t hitBitSet = buffer[ibyte / 4] >> shift;
219  if (m_debug && hitBitSet) std::cout << "ch: " << (unsigned)asicCh << " " << std::bitset<8>(hitBitSet) << std::endl;
220  // store digit
221  digits.appendNew(moduleID, (unsigned)asicCh, hitBitSet);
222  ibyte++;
223  }
224  } else if (febHead.type == 2) {
225  unsigned asicCh = 143;
226  for (int i = 0; i < dataLen; i++) {
227  int shift = (3 - ibyte % 4) * 8;
228  uint8_t hitBitSet = buffer[ibyte / 4] >> shift;
229  // store digit if hit
230  if (hitBitSet & m_bitMask) {
231  digits.appendNew(moduleID, asicCh, hitBitSet);
232  }
233  asicCh--;
234  ibyte++;
235  }
236  } else B2ERROR("ARICHUnpackerModule: Unknown data type" << LogVar("type", febHead.type));
237 
238  }
239 
240  if (ceil(ibyte / 4.) != (unsigned)bufferSize)
241  B2WARNING("ARICHUnpackerModule: data buffer size mismatch " << LogVar("size from copper", bufferSize) << LogVar("size from merger",
242  ceil(
243  ibyte / 4.)));
244 
245 
246  //-- If thscan_mode detected from header: proceed to fill ARICHRawDigit
247  //-- If m_rawmode is set to 1: proceed to fill ARICHRawDigit
248  if (thscan_mode == 0 && m_rawmode == 0) continue;
249  //-- go back to beginning again for second loop in case of thscan
250  m_ibyte = begin;
251 
252  while (m_ibyte < length_all) {
253  ARICHRawHeader febHead;
254  readFEHeader(buffer, m_ibyte, febHead);
255  int type_feb = febHead.type;
256  ver = febHead.version;
257  boardid = febHead.mergerID;
258  febno = febHead.FEBSlot;
259 
260  vth_thscan = (febHead.vth * 0.0024) - 1.27;
261  unsigned int length = febHead.length;
262  int evtno = febHead.trigger;
263  unsigned int jbyte = 0;
264  std::stringstream ss;
265  ss << "type=" << type_feb << ", ver=" << ver << " "
266  << ", boardid=" << boardid << ", febno=" << febno
267  << ", length=" << length << ", evtno=" << evtno << " ";
268  bool hasHit = false;
269  long long feb_trigno = 0;
270  for (int i = 0; i < 10; i++) {
271  int val = calbyte(buffer);
272  jbyte++;
273  if (i < 6) {
274  feb_trigno |= (0xff & val) << (5 - i) * 8;
275  }
276  }
278  nfebs++;
279  if (type_feb == 0x02) {//Raw mode
280  int ch = 143;
281  //B2INFO("raw mode");
282  while (jbyte < length) {
283  int val = calbyte(buffer);
284  if (val != 0) {
285  jbyte++;
286  ss << "ch# " << ch << "(" << val << ") ";
287  hasHit = true;
288  if (febno < 0 || febno > 6) {
289  B2ERROR("FEB is bad : " << LogVar("FEB no.", febno) << LogVar("hslb", finesse) << LogVar("type", type_feb) << LogVar("ver",
290  ver) << LogVar("boardid", boardid) << LogVar("febno", febno) << LogVar("length", length) << LogVar("evtno", evtno));
291  }
292  feb.push_back(ch, val);
293  }
294  ch--;
295  if (ch < 0) break;
296  }
297  } else if (type_feb == 0x01) { // Suppressed mode
298  // The below line is commented since it sometimes causes problem during processing threshold scan data.
299  // No harm to comment this line since it is only utilized for threshold scan data.
300  //if (length > 144 * 2 + 10) B2FATAL("error " << LogVar("length", length));
301  //B2INFO("suppreed mode");
302  while (jbyte < length) {
303  int ch = calbyte(buffer);
304  jbyte++;
305  int val = calbyte(buffer);
306  jbyte++;
307  if (val != 0) {
308  ss << "ch# " << ch << "(" << val << ") ";
309  hasHit = true;
310  if (febno < 0 || febno > 6) {
311  B2ERROR("FEB is bad : " << LogVar("FEB no.", febno) << LogVar("hslb", finesse) << LogVar("type", type_feb) << LogVar("ver",
312  ver) << LogVar("boardid", boardid) << LogVar("febno", febno) << LogVar("length", length) << LogVar("evtno", evtno));
313  return;
314  }
315  feb.push_back(ch, val);
316  }
317  }
318  }
319  rawdigit->addFEB(feb, type, ver, boardid, febno, length, evtno, feb_trigno);
320  if (m_debug && hasHit) {
321  B2INFO(ss.str());
322  }
323  }
324 
325 
326 
327  }
328  } // end of rawData loop
329 
330 // } // end of regular unpacker
331  /*
332  // RawUnpacker mode, fill ARICHRawDigit
333  if (m_rawmode == 1) {
334  for (auto& raw : rawData) {
335  for (int finesse = 0; finesse < 4; finesse++) {
336  const int* buf = (const int*)raw.GetDetectorBuffer(0, finesse);
337  int bufSize = raw.GetDetectorNwords(0, finesse);
338  if (bufSize < 1) continue;
339  m_ibyte = 0;
340  // read merger header
341  int type = calbyte(buf);
342  int ver = calbyte(buf);
343  int boardid = calbyte(buf);
344  int febno = calbyte(buf);
345  unsigned int length_all = calword(buf);
346  unsigned int mrg_evtno = calword(buf);
347  ARICHRawDigit* rawdigit = rawdigits.appendNew(type, ver, boardid, febno, length_all, mrg_evtno);
348  rawdigit->setCopperId(raw.GetNodeID(0));
349  rawdigit->setHslbId(finesse);
350  int nfebs = 0;
351  //--done
352  while (m_ibyte < length_all) {
353  int type_feb = calbyte(buf);
354  ver = calbyte(buf);
355  boardid = calbyte(buf);
356  febno = calbyte(buf);
357 
358  // first line: vth value
359  unsigned int vth_int = cal2byte(buf);
360  if (vth_int > 0) { vth_thscan = (vth_int * 0.0024) - 1.27; }
361  // second line: length
362  unsigned int length = cal2byte(buf);
363  int evtno = calword(buf);
364  unsigned int ibyte = 0;
365  std::stringstream ss;
366  ss << "type=" << type_feb << ", ver=" << ver << " "
367  << ", boardid=" << boardid << ", febno=" << febno
368  << ", length=" << length << ", evtno=" << evtno << " ";
369  bool hasHit = false;
370  long long feb_trigno = 0;
371  for (int i = 0; i < 10; i++) {
372  int val = calbyte(buf);
373  ibyte++;
374  if (i < 6) {
375  feb_trigno |= (0xff & val) << (5 - i) * 8;
376  }
377  }
378  ARICHRawDigit::FEBDigit feb;
379  nfebs++;
380  if (type_feb == 0x02) {//Raw mode
381  int ch = 143;
382  //B2INFO("raw mode");
383  while (ibyte < length) {
384  int val = calbyte(buf);
385  if (val != 0) {
386  ibyte++;
387  ss << "ch# " << ch << "(" << val << ") ";
388  hasHit = true;
389  if (febno < 0 || febno > 6) {
390  B2ERROR("FEB is bad : " << LogVar("FEB no.", febno) << LogVar("hslb", finesse) << LogVar("type", type_feb) << LogVar("ver",
391  ver) << LogVar("boardid", boardid) << LogVar("febno", febno) << LogVar("length", length) << LogVar("evtno", evtno));
392  }
393  feb.push_back(ch, val);
394  }
395  ch--;
396  if (ch < 0) break;
397  }
398  } else if (type_feb == 0x01) { // Suppressed mode
399  // The below line is commented since it sometimes causes problem during processing threshold scan data.
400  // No harm to comment this line since it is only utilized for threshold scan data.
401  //if (length > 144 * 2 + 10) B2FATAL("error " << LogVar("length", length));
402  //B2INFO("suppreed mode");
403  while (ibyte < length) {
404  int ch = calbyte(buf);
405  ibyte++;
406  int val = calbyte(buf);
407  ibyte++;
408  if (val != 0) {
409  ss << "ch# " << ch << "(" << val << ") ";
410  hasHit = true;
411  if (febno < 0 || febno > 6) {
412  B2ERROR("FEB is bad : " << LogVar("FEB no.", febno) << LogVar("hslb", finesse) << LogVar("type", type_feb) << LogVar("ver",
413  ver) << LogVar("boardid", boardid) << LogVar("febno", febno) << LogVar("length", length) << LogVar("evtno", evtno));
414  return;
415  }
416  feb.push_back(ch, val);
417  }
418  }
419  }
420  rawdigit->addFEB(feb, type, ver, boardid, febno, length, evtno, feb_trigno);
421  if (m_debug && hasHit) {
422  B2INFO(ss.str());
423  }
424  }
425  }
426  }
427 
428  } // end of raw unpacker
429  */
430  arichinfo->settrgtype(trgtype);
431  arichinfo->setpciedata(m_pciedata);
432  if (vth_thscan > -1.27) { arichinfo->setvth_thscan(vth_thscan); }
433  arichinfo->setntrack(0);
434  arichinfo->setnexthit(0);
435  arichinfo->setnhit(0);
436  if (thscan_mode > 0 || m_rawmode != 0)
437  { arichinfo->setthscan_mode(true); }
438  else
439  { arichinfo->setthscan_mode(false); }
440 
441  }
442 
443  void ARICHUnpackerModule::readHeader(const int* buffer, unsigned& ibyte, ARICHRawHeader& head)
444  {
445 
446  // read the first line of header
447  char line1[4];
448  int shift;
449  for (int i = 0; i < 4; i++) {
450  shift = (3 - ibyte % 4) * 8;
451  line1[3 - i] = buffer[ibyte / 4] >> shift;
452  ibyte++;
453  }
454 
455  head.type = line1[3];
456  head.version = line1[2];
457  head.mergerID = line1[1];
458  head.FEBSlot = line1[0];
459 
460  // data length
461  unsigned char len[4];
462  for (int i = 0; i < 4; i++) {
463  shift = (3 - ibyte % 4) * 8;
464  len[3 - i] = buffer[ibyte / 4] >> shift;
465  ibyte++;
466  }
467 
468  unsigned seu = len[2];
469  // This line (16 bits) is actaully not used for data length.
470  len[2] = 0;
471  len[3] = 0;
472  uint32_t* tmp = (uint32_t*)len;
473  head.length = *tmp;
474 
475  for (int i = 0; i < 6; i ++) {
476  head.SEU_FEB[i] = (seu & (1 << i)) != 0;
477  }
478 
479  // trigger number
480  char trg[4];
481  for (int i = 0; i < 4; i++) {
482  shift = (3 - ibyte % 4) * 8;
483  trg[3 - i] = buffer[ibyte / 4] >> shift;
484  ibyte++;
485  }
486  tmp = (uint32_t*)trg;
487  head.trigger = *tmp;
488 
489  }
490 
491  void ARICHUnpackerModule::readFEHeader(const int* buffer, unsigned& ibyte, ARICHRawHeader& head)
492  {
493 
494  // read the first line of header
495  char line1[4];
496  int shift;
497  for (int i = 0; i < 4; i++) {
498  shift = (3 - ibyte % 4) * 8;
499  line1[3 - i] = buffer[ibyte / 4] >> shift;
500  ibyte++;
501  }
502 
503  head.type = line1[3];
504  head.version = line1[2];
505  head.mergerID = line1[1];
506  head.FEBSlot = line1[0];
507 
508  // data length
509  unsigned char len[4];
510  for (int i = 0; i < 4; i++) {
511  shift = (3 - ibyte % 4) * 8;
512  len[3 - i] = buffer[ibyte / 4] >> shift;
513  ibyte++;
514  }
515 
516  unsigned vth_info = len[3] * 256 + len[2];
517  if (vth_info >= 32768) { head.thscan_mode = true; vth_info -= 32768; }
518  head.vth = vth_info;
519  // This line (16 bits) is actaully not used for data length.
520  len[2] = 0;
521  len[3] = 0;
522  uint32_t* tmp = (uint32_t*)len;
523  head.length = *tmp;
524 
525  // trigger number
526  char trg[4];
527  for (int i = 0; i < 4; i++) {
528  shift = (3 - ibyte % 4) * 8;
529  trg[3 - i] = buffer[ibyte / 4] >> shift;
530  ibyte++;
531  }
532  tmp = (uint32_t*)trg;
533  head.trigger = *tmp;
534 
535  }
536 
537  void ARICHUnpackerModule::printBits(const int* buffer, int bufferSize)
538  {
539  for (int i = 0; i < bufferSize; i++) {
540  std::cout << i << "-th word bitset: " << std::bitset<32>(*(buffer + i)) << std::endl;
541  }
542  }
543 
544 
545  void ARICHUnpackerModule::endRun()
546  {
547  }
548 
549  void ARICHUnpackerModule::terminate()
550  {
551  }
552 
553 
555 } // end Belle2 namespace
556 
Raw data unpacker for ARICH.
Base class for Modules.
Definition: Module.h:72
bool isRequired(const std::string &name="")
Ensure this array/object has been registered previously.
bool registerInDataStore(DataStore::EStoreFlags storeFlags=DataStore::c_WriteOut)
Register the object/array in the DataStore.
bool create(bool replace=false)
Create a default object in the data store.
Accessor to arrays stored in the data store.
Definition: StoreArray.h:113
T * appendNew()
Construct a new T object at the end of the array.
Definition: StoreArray.h:246
Type-safe access to single objects in the data store.
Definition: StoreObjPtr.h:95
Class to store variables with their name which were sent to the logging service.
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Definition: Module.h:650
Abstract base class for different kinds of events.