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#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
33namespace 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();
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
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: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.
#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:560
#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.
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