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