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