Belle II Software development
TOPUnpackerModule.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 <top/modules/TOPUnpacker/TOPUnpackerModule.h>
11
12// TOP headers.
13#include <top/RawDataTypes.h>
14
15// framework - DataStore
16#include <framework/datastore/DataStore.h>
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
26#include <bitset>
27#include <iomanip>
28#include <fstream>
29#include <algorithm>
30
31using namespace std;
32
33namespace Belle2 {
38
39 using namespace TOP;
40
41 //-----------------------------------------------------------------
43 //-----------------------------------------------------------------
44
45 REG_MODULE(TOPUnpacker);
46
47 //-----------------------------------------------------------------
48 // Implementation
49 //-----------------------------------------------------------------
50
52 {
53 // set module description
54 setDescription("Raw data unpacker for TOP");
56
57 // Add parameters
58 addParam("inputRawDataName", m_inputRawDataName,
59 "name of RawTOP store array", string(""));
60 addParam("outputDigitsName", m_outputDigitsName,
61 "name of TOPDigit store array", string(""));
62 addParam("outputWaveformsName", m_outputWaveformsName,
63 "name of TOP(Raw/Production)Waveform store array", string(""));
64 addParam("outputRawDigitsName", m_outputRawDigitsName,
65 "name of TOPRawDigit store array", string(""));
66 addParam("outputTemplateFitResultName", m_templateFitResultName,
67 "name of TOPTemplateFitResult", string(""));
68 addParam("swapBytes", m_swapBytesDefault, "if true, swap bytes", false);
69 addParam("dataFormat", m_dataFormat,
70 "data format as defined in top/include/RawDataTypes.h, 0 = auto detect", 0);
71 addParam("addRelations", m_addRelations,
72 "if true, make relations to TOPProductionHitDebugs (production debug data format only)", true);
73 addParam("errorSuppressFactor", m_errorSuppressFactor,
74 "error messages suppression factor (0 = no suppression)", (unsigned) 1000);
75
76 }
77
79 {
80
81 // input
82
83 m_rawData.isRequired(m_inputRawDataName);
84
85 // output
86
87 m_digits.registerInDataStore(m_outputDigitsName);
88 m_rawDigits.registerInDataStore(m_outputRawDigitsName);
89 m_slowData.registerInDataStore();
95 m_injectionVeto.registerInDataStore();
96
102
103 // check if front end mappings are available
104 const auto& mapper = m_topgp->getFrontEndMapper();
105 int mapSize = mapper.getMapSize();
106 if (mapSize == 0) B2ERROR("TOPUnpacker: No front-end mapping available for TOP");
107
108 }
109
111 {
112 m_channelStatistics.clear();
113 }
114
116 {
117 if (m_resetEventCount) {
119 m_errorCount = 0;
120 m_eventCount = 0;
121 m_resetEventCount = false;
122 }
123 m_eventCount++;
124
125 // clear output store arrays
126 m_digits.clear();
127 m_rawDigits.clear();
128 m_waveforms.clear();
130 m_productionHitDebugs.clear();
131 m_templateFitResults.clear();
132 m_slowData.clear();
133 m_interimFEInfos.clear();
134
135 // create injection veto object
136 m_injectionVeto.create();
137
138 StoreObjPtr<EventMetaData> evtMetaData;
139 for (auto& raw : m_rawData) {
140 for (int finesse = 0; finesse < raw.GetMaxNumOfCh(0); finesse++) {
141 const int* buffer = raw.GetDetectorBuffer(0, finesse);
142 int bufferSize = raw.GetDetectorNwords(0, finesse);
143 if (bufferSize < 1) continue;
144
145 int err = 0;
147 int dataFormat = m_dataFormat;
148 if (dataFormat == 0) { // auto detect data format
149 DataArray array(buffer, bufferSize, m_swapBytes);
150 unsigned word = array.getWord();
151 dataFormat = (word >> 16);
152 bool isKnownDataFormat = false;
153 for (auto& t : TOP::membersRawDataType) {
154 if (static_cast<int>(t) == dataFormat) {
155 isKnownDataFormat = true;
156 break;
157 }
158 }
159
160 if (!isKnownDataFormat) { //dataformat word is not recognised, might be interim format.
161 if (evtMetaData->getExperiment() == 1) { // all exp.1 data was taken with interim format
162 dataFormat = 0x0301;
163 m_swapBytes = true;
164 } else {
165 if (unpackHeadersInterimFEVer01(buffer, bufferSize, true)) { //if buffer unpacks without errors assuming it's interim format
166 B2DEBUG(22, "Assuming interim FW data format");
167 dataFormat = 0x0301; //assume it's interim format
168 m_swapBytes = true;
169 } else {
170 B2DEBUG(22, "TOPUnpacker: Could not establish data format.");
171 }
172 }
173 }
174 }
175
176 switch (dataFormat) {
177 case static_cast<int>(TOP::RawDataType::c_Type0Ver16):
178 unpackType0Ver16(buffer, bufferSize);
179 break;
180 case static_cast<int>(TOP::RawDataType::c_Type2Ver1):
181 err = unpackInterimFEVer01(buffer, bufferSize, false);
182 break;
183 case static_cast<int>(TOP::RawDataType::c_Type3Ver1):
184 err = unpackInterimFEVer01(buffer, bufferSize, true);
185 break;
186 case static_cast<int>(TOP::RawDataType::c_Draft):
187 unpackProductionDraft(buffer, bufferSize);
188 break;
189 case static_cast<int>(TOP::RawDataType::c_ProductionDebug01):
190 err = unpackProdDebug(buffer, bufferSize, TOP::RawDataType::c_ProductionDebug01, true, evtMetaData->getExperiment());
191 break;
192 case static_cast<int>(TOP::RawDataType::c_ProductionDebug02):
193 err = unpackProdDebug(buffer, bufferSize, TOP::RawDataType::c_ProductionDebug02, true, evtMetaData->getExperiment());
194 break;
195
196 default:
197 if (printTheError()) {
198 auto boardstackName = getFrontEndName(raw, finesse);
199 B2ERROR("TOPUnpacker: unknown data format from " << boardstackName
200 << LogVar("Type", (dataFormat >> 8))
201 << LogVar("Version", (dataFormat & 0xFF))
202 << LogVar("Buffer size", bufferSize));
203 }
204 continue;
205 }
206
207 if (err != 0) {
208 if (printTheError()) {
209 auto boardstackName = getFrontEndName(raw, finesse);
210 B2ERROR("TOPUnpacker: error in unpacking data from " << boardstackName
211 << LogVar("words unused", err));
212 }
213 }
214
215 } // finesse loop
216 } // m_rawData loop
217
218 }
219
220
221 std::string TOPUnpackerModule::getFrontEndName(RawTOP& raw, int finesse)
222 {
223 std::string name;
224 if (raw.GetMaxNumOfCh(0) <= 4) { // COPPER
225 int copper = ((raw.GetNodeID(0) >> 24) * 1000 + (raw.GetNodeID(0) & 0x3FF));
226 name = "frontend cpr" + std::to_string(copper) + char('a' + finesse);
227 } else { // PCIe40
228 int slot = (raw.GetNodeID(0) & 0xF) * 8 - 7 + finesse / 4;
229 name = (slot < 10) ? "boardstack s0" : "boardstack s";
230 name += std::to_string(slot) + char('a' + finesse % 4);
231 }
232 return name;
233 }
234
235
237 {
238 if (m_eventCount < m_errorSuppressFactor * m_numErrors) return false;
239 m_errorCount++;
240 m_resetEventCount = true;
241 return true;
242 }
243
244
245 void TOPUnpackerModule::unpackProductionDraft(const int* buffer, int bufferSize)
246 {
247
248 B2DEBUG(22, "Unpacking ProductionDraft to TOPDigits, dataSize = " << bufferSize);
249
250 unsigned short scrodID = buffer[0] & 0xFFFF;
251 const auto* feemap = m_topgp->getFrontEndMapper().getMap(scrodID);
252 if (!feemap) {
253 B2ERROR("TOPUnpacker: no front-end map available."
254 << LogVar("SCROD ID", scrodID));
255 return;
256 }
257 int moduleID = feemap->getModuleID();
258 int boardstack = feemap->getBoardstackNumber();
259 const auto& mapper = m_topgp->getChannelMapper();
260
261 const auto* geo = m_topgp->getGeometry();
262 auto subBits = geo->getNominalTDC().getSubBits();
263 int sampleDivisions = 0x1 << subBits;
264
265 for (int i = 1; i < bufferSize; i++) {
266 int word = buffer[i];
267 int tdc = word & 0xFFFF;
268 double rawTime = double(tdc) / sampleDivisions;
269 unsigned chan = ((word >> 16) & 0x7F) + boardstack * 128;
270 unsigned flags = (word >> 24) & 0xFF;
271 int pixelID = mapper.getPixelID(chan);
272 auto* digit = m_digits.appendNew(moduleID, pixelID, rawTime);
273 digit->setTime(geo->getNominalTDC().getTime(tdc));
274 digit->setChannel(chan);
275 digit->setHitQuality((TOPDigit::EHitQuality) flags);
276 }
277
278 }
279
280
281 void TOPUnpackerModule::unpackType0Ver16(const int* buffer, int bufferSize)
282 {
283
284 B2DEBUG(22, "Unpacking Type0Ver16 to TOPRawDigits, dataSize = " << bufferSize);
285
286 DataArray array(buffer, bufferSize, m_swapBytes);
287 unsigned word = array.getWord();
288 unsigned short scrodID = word & 0x0FFF;
289
290 unsigned last = array.getLastWord();
291 int Nhits = last & 0x01FF;
292 if (bufferSize != 5 * Nhits + 2) {
293 B2ERROR("TOPUnpacker: corrupted data (feature-extraction format)."
294 << LogVar("SCROD ID", scrodID));
295 return;
296 }
297
298 short SDType = last >> 24;
299 short SDValue = (last >> 12) & 0x0FFF;
300 if (SDType != 0) m_slowData.appendNew(scrodID, SDType, SDValue);
301
302 unsigned short errorFlags = 0;
303 if (((word >> 12) & 0x0F) != 0x0A) errorFlags |= TOPRawDigit::c_HeadMagic;
304 if (((last >> 9) & 0x07) != 0x05) errorFlags |= TOPRawDigit::c_TailMagic;
305
306 for (int hit = 0; hit < Nhits; hit++) {
307 auto* digit = m_rawDigits.appendNew(scrodID, TOPRawDigit::c_Production);
308
309 word = array.getWord(); // word 1
310 digit->setCarrierNumber((word >> 30) & 0x03);
311 digit->setASICNumber((word >> 28) & 0x03);
312 digit->setASICChannel((word >> 25) & 0x07);
313 digit->setASICWindow((word >> 16) & 0x1FF);
314 digit->setTFine((word >> 8) & 0x0F);
315 auto flags = errorFlags;
316 if (((word >> 12) & 0x0F) != 0x0B) flags |= TOPRawDigit::c_HitMagic;
317 unsigned short checkSum = sumShorts(word);
318
319 word = array.getWord(); // word 2
320 digit->setValuePeak(expand13to16bits(word >> 16));
321 digit->setIntegral(word & 0xFFFF);
322 checkSum += sumShorts(word);
323
324 word = array.getWord(); // word 3
325 digit->setValueRise0(expand13to16bits(word >> 16));
326 digit->setValueRise1(expand13to16bits(word));
327 checkSum += sumShorts(word);
328
329 word = array.getWord(); // word 4
330 digit->setValueFall0(expand13to16bits(word >> 16));
331 digit->setValueFall1(expand13to16bits(word));
332 checkSum += sumShorts(word);
333
334 word = array.getWord(); // word 5
335 digit->setSampleRise(word >> 24);
336 digit->setDeltaSamplePeak((word >> 20) & 0x0F);
337 digit->setDeltaSampleFall((word >> 16) & 0x0F);
338 checkSum += sumShorts(word);
339 if (checkSum != 0) flags |= TOPRawDigit::c_HitChecksum;
340
341 digit->setErrorFlags(flags);
342
343 }
344
345 }
346
347 bool TOPUnpackerModule::unpackHeadersInterimFEVer01(const int* buffer, int bufferSize, bool swapBytes)
348 {
349 B2DEBUG(22, "Checking whether buffer unpacks as InterimFEVer01, dataSize = " << bufferSize);
350
351 DataArray array(buffer, bufferSize, swapBytes);
352
353 array.getWord(); // header word 0
354 array.getWord(); // header word 1 (what it contains?)
355 while (array.getRemainingWords() > 0) {
356 unsigned header = array.getWord(); // word 0
357 if ((header & 0xFF) == 0xBE) { //this is a super short FE header
358 continue;
359 }
360
361 if (header != 0xaaaa0104 and header != 0xaaaa0103 and header != 0xaaaa0100) {//cannot be interim firmware
362 return false; //abort
363 }
364
365
366 array.getWord(); // word 1
367 array.getWord(); // word 2
368
369 if (header != 0xaaaa0104) {
370 // feature-extracted data (positive signal)
371 array.getWord(); // word 3
372 array.getWord(); // word 4
373 array.getWord(); // word 5
374 array.getWord(); // word 6
375 array.getWord(); // word 7
376 array.getWord(); // word 8
377 array.getWord(); // word 9
378 array.getWord(); // word 10
379 array.getWord(); // word 11
380 array.getWord(); // word 12
381 array.getWord(); // word 13
382 array.getWord(); // word 14
383 }
384
385 unsigned magicWord = array.getWord(); // word 15
386 if (magicWord != 0x7473616c) {//invalid magic word
387 return false; //abort
388 }
389
390 if (header != 0xaaaa0103) continue;
391 array.getWord(); // word 16
392
393 array.getWord(); // word 17
394 array.getWord(); // word 18
395 array.getWord(); // word 19
396
397 array.getWord(); // word 20
398
399 array.getWord(); // word 21
400
401 array.getWord(); // word 22
402
403 int numWords = 4 * 32; // (numPoints + 1) / 2;
404 if (array.getRemainingWords() < numWords) { //not enough remaining words for waveform data
405 return false; //abort
406 }
407
408 for (int i = 0; i < numWords; i++) {
409 array.getWord();
410 }
411 }
412
413 return true;
414 }
415
416
417 int TOPUnpackerModule::unpackInterimFEVer01(const int* buffer, int bufferSize,
418 bool pedestalSubtracted)
419 {
420
421 B2DEBUG(22, "Unpacking InterimFEVer01 to TOPRawDigits and TOPRawWaveforms, "
422 "dataSize = " << bufferSize);
423
424 int moduleID = 0;
425 int boardstack = 0;
426
427 DataArray array(buffer, bufferSize, m_swapBytes);
428
429 map<unsigned short, int> evtNumCounter; //counts the occurrence of carrier-generated event numbers.
430 std::vector<unsigned short> channelCounter(128, 0); //counts occurrence of carrier/asic/channel combinations
431
432 unsigned word = array.getWord(); // header word 0
433 unsigned short scrodID = word & 0x0FFF;
434 auto* info = m_interimFEInfos.appendNew(scrodID, bufferSize);
435
436 word = array.getWord(); // header word 1 (what it contains?)
437
438
439 while (array.getRemainingWords() > 0) {
440
441 unsigned header = array.getWord(); // word 0
442
443 if ((header & 0xFF) == 0xBE) { //this is a super short FE header
444// B2DEBUG(21, "0b" << std::bitset<8>(header & 0xFF) << " " << std::bitset<8>((header>>8) & 0xFF) << " " << std::bitset<8>((header>>16) & 0xFF) << " " << std::bitset<8>((header>>24) & 0xFF));
445
446 unsigned short scrodID_SSFE;
447 unsigned short carrier_SSFE;
448 unsigned short asic_SSFE;
449 unsigned short channel_SSFE;
450 unsigned short evtNum_SSFE;
451
452 evtNum_SSFE = (header >> 8) & 0xFF;
453 scrodID_SSFE = (header >> 16) & 0x7F;
454 channel_SSFE = (header >> 24) & 0x07;
455 asic_SSFE = (header >> 27) & 0x03;
456 carrier_SSFE = (header >> 29) & 0x03;
457
458 const auto* feemap = m_topgp->getFrontEndMapper().getMap(scrodID_SSFE);
459 if (feemap) {
460 moduleID = feemap->getModuleID();
461 boardstack = feemap->getBoardstackNumber();
462 } else {
463 B2ERROR("TOPUnpacker: no front-end map available."
464 << LogVar("SCROD ID", scrodID_SSFE));
465 info->setErrorFlag(TOPInterimFEInfo::c_InvalidScrodID);
466 }
467
468 if (scrodID_SSFE != scrodID) {
469 B2ERROR("TOPUnpacker: corrupted data - "
470 << "different scrodID's in HLSB and super short FE header."
471 << LogVar("SCROD", scrodID_SSFE)
472 << LogVar("slot", moduleID)
473 << LogVar("BS", boardstack));
474 B2DEBUG(21, "Different scrodID's in HLSB and FE header: " << scrodID << " " << scrodID_SSFE << " word = 0x" << std::hex << word);
475 info->setErrorFlag(TOPInterimFEInfo::c_DifferentScrodIDs);
476 return array.getRemainingWords();
477 }
478
479 B2DEBUG(21, scrodID_SSFE << "\t" << carrier_SSFE << "\t" << asic_SSFE << "\t" << channel_SSFE << "\t" << evtNum_SSFE);
480
481 int channelID = carrier_SSFE * 32 + asic_SSFE * 8 + channel_SSFE;
482 channelCounter[channelID] += 1;
483 evtNumCounter[evtNum_SSFE] += 1;
484
485 info->incrementFEHeadersCount();
486 info->incrementEmptyFEHeadersCount();
487
488 continue;
489 }
490
491 if (header != 0xaaaa0104 and header != 0xaaaa0103 and header != 0xaaaa0100) {
492 B2ERROR("TOPUnpacker: corrupted data - invalid FE header word");
493 B2DEBUG(21, "Invalid FE header word: " << std::hex << header << " 0b" << std::bitset<32>(header));
494 B2DEBUG(21, "SCROD ID: " << scrodID << " " << std::hex << scrodID);
495
496 info->setErrorFlag(TOPInterimFEInfo::c_InvalidFEHeader);
497 return array.getRemainingWords();
498 }
499
500
501 word = array.getWord(); // word 1
502 unsigned short scrodID_FE = word >> 25;
503 unsigned short convertedAddr = (word >> 16) & 0x1FF;
504 unsigned short evtNum_numWin_trigPat_FEheader = word & 0xFFFF;
505 unsigned short evtNum_FEheader = evtNum_numWin_trigPat_FEheader & 0xFF;
506 evtNumCounter[evtNum_FEheader] += 1;
507
508 if (scrodID_FE != scrodID) {
509 B2ERROR("TOPUnpacker: different scrodID's in HLSB and FE header."
510 << LogVar("scrodID (HSLB)", scrodID)
511 << LogVar("scrodID (FE)", scrodID_FE));
512
513 info->setErrorFlag(TOPInterimFEInfo::c_DifferentScrodIDs);
514 return array.getRemainingWords();
515 }
516
517 word = array.getWord(); // word 2
518 // unsigned lastWrAddr = word & 0x1FF;
519 unsigned lastWrAddr = (word & 0x0FF) << 1;
520 //unsigned short asicChannelFE = (word >> 9) & 0x07;
521 unsigned short asicChannelFE = (word >> 8) & 0x07;
522 unsigned short asicFE = (word >> 12) & 0x03;
523 unsigned short carrierFE = (word >> 14) & 0x03;
524 unsigned short channelID = carrierFE * 32 + asicFE * 8 + asicChannelFE;
525 //B2DEBUG(21, "carrier asic chn " << carrierFE << " " << asicFE << " " << asicChannelFE << " " << channelID << " 0b" << std::bitset<32>(word) );
526
527 B2DEBUG(21, scrodID_FE << "\t" << carrierFE << "\t" << asicFE << "\t" << asicChannelFE << "\t" << evtNum_FEheader);
528
529 channelCounter[channelID] += 1;
530
531 std::vector<TOPRawDigit*> digits; // needed for creating relations to waveforms
532
533 if (header != 0xaaaa0104) {
534 // feature-extracted data (positive signal)
535 array.getWord(); // word 3
536 word = array.getWord(); // word 4
537 short samplePeak_p = word & 0xFFFF;
538 short valuePeak_p = (word >> 16) & 0xFFFF;
539
540 word = array.getWord(); // word 5
541 short sampleRise_p = word & 0xFFFF;
542 short valueRise0_p = (word >> 16) & 0xFFFF;
543
544 word = array.getWord(); // word 6
545 short valueRise1_p = word & 0xFFFF;
546 short sampleFall_p = (word >> 16) & 0xFFFF;
547
548 word = array.getWord(); // word 7
549 short valueFall0_p = word & 0xFFFF;
550 short valueFall1_p = (word >> 16) & 0xFFFF;
551
552 word = array.getWord(); // word 8
553 short integral_p = word & 0xFFFF;
554 // short qualityFlags_p = (word >> 16) & 0xFFFF;
555
556 // feature-extracted data (negative signal)
557 array.getWord(); // word 9
558 //word = array.getWord(); // word 9
559 //short n_samp_i = (word >> 16) & 0xFFFF;
560 word = array.getWord(); // word 10
561 short samplePeak_n = word & 0xFFFF;
562 short valuePeak_n = (word >> 16) & 0xFFFF;
563
564 array.getWord(); // word 11
565 //word = array.getWord(); // word 11
566 //short sampleRise_n = word & 0xFFFF;
567 //short valueRise0_n = (word >> 16) & 0xFFFF;
568
569 array.getWord(); // word 12
570 //word = array.getWord(); // word 12
571 //short valueRise1_n = word & 0xFFFF;
572 //short sampleFall_n = (word >> 16) & 0xFFFF;
573
574 array.getWord(); // word 13
575 //word = array.getWord(); // word 13
576 //short valueFall0_n = word & 0xFFFF;
577 //short valueFall1_n = (word >> 16) & 0xFFFF;
578
579 word = array.getWord(); // word 14
580 short integral_n = word & 0xFFFF;
581 short qualityFlags_n = (word >> 16) & 0xFFFF;
582
583 if (abs(valuePeak_p) != 9999) {
584 auto* digit = m_rawDigits.appendNew(scrodID, TOPRawDigit::c_Interim);
585 digit->setCarrierNumber(carrierFE);
586 digit->setASICNumber(asicFE);
587 digit->setASICChannel(asicChannelFE);
588 digit->setASICWindow(convertedAddr);
589 digit->setLastWriteAddr(lastWrAddr);
590 digit->setSampleRise(sampleRise_p);
591 digit->setDeltaSamplePeak(samplePeak_p - sampleRise_p);
592 digit->setDeltaSampleFall(sampleFall_p - sampleRise_p);
593 digit->setValueRise0(valueRise0_p);
594 digit->setValueRise1(valueRise1_p);
595 digit->setValuePeak(valuePeak_p);
596 digit->setValueFall0(valueFall0_p);
597 digit->setValueFall1(valueFall1_p);
598 digit->setIntegral(integral_p);
599 // digit->setErrorFlags(qualityFlags_p); // not good solution !
600 digit->addRelationTo(info);
601 digits.push_back(digit);
602 //template fit result is saved in negative pulse fe data
603 if (valuePeak_p < 150) {
604 auto* tlpfResult = m_templateFitResults.appendNew();
605 tlpfResult->setBackgroundOffset(samplePeak_n);
606 tlpfResult->setAmplitude(valuePeak_n);
607 tlpfResult->setChisquare(qualityFlags_n);
608 tlpfResult->setRisingEdgeAndConvert(integral_n);
609 digit->addRelationTo(tlpfResult);
610 }
611 }
612 /*if (abs(valuePeak_n) != 9999) {
613 auto* digit = m_rawDigits.appendNew(scrodID, TOPRawDigit::c_Interim);
614 digit->setCarrierNumber(carrierFE);
615 digit->setASICNumber(asicFE);
616 digit->setASICChannel(asicChannelFE);
617 digit->setASICWindow(convertedAddr);
618 digit->setLastWriteAddr(lastWrAddr);
619 digit->setSampleRise(sampleRise_n);
620 digit->setDeltaSamplePeak(samplePeak_n - sampleRise_n);
621 digit->setDeltaSampleFall(sampleFall_n - sampleRise_n);
622 digit->setValueRise0(valueRise0_n);
623 digit->setValueRise1(valueRise1_n);
624 digit->setValuePeak(valuePeak_n);
625 digit->setValueFall0(valueFall0_n);
626 digit->setValueFall1(valueFall1_n);
627 digit->setIntegral(integral_n);
628 // digit->setErrorFlags(qualityFlags_n); // not good solution !
629 digit->addRelationTo(info);
630 digits.push_back(digit);
631 }*/
632 }
633
634 // magic word
635 word = array.getWord(); // word 15
636 if (word != 0x7473616c) {
637 //B2ERROR("TOPUnpacker: corrupted data - no magic word at the end of FE header");
638 //B2DEBUG(21, "No magic word at the end of FE header, found: "
639 //<< std::hex << word);
640 info->setErrorFlag(TOPInterimFEInfo::c_InvalidMagicWord);
641 //return array.getRemainingWords(); do not abort event for now as footer is invalid in current debugging version of firmware
642 }
643
644 // store to raw digits
645
646 info->incrementFEHeadersCount();
647 if (digits.empty()) info->incrementEmptyFEHeadersCount();
648
649 if (header != 0xaaaa0103) continue;
650
651 // waveform header
652 word = array.getWord(); // word 16
653 unsigned long evtNum_numWaves_refWin_WFheader = word;
654 unsigned short evtNum_WFheader = (evtNum_numWaves_refWin_WFheader >> 24) & 0xFF;
655
656 if (evtNum_WFheader != evtNum_FEheader) {
657 B2ERROR("TOPUnpacker: different carrier event number in WF and FE header."
658 << LogVar("Event number (FE header)", evtNum_FEheader)
659 << LogVar("Event number (WF header)", evtNum_WFheader));
660 }
661
662 array.getWord(); // word 17
663 array.getWord(); // word 18
664 word = array.getWord(); // word 19
665 // int numPoints = (word >> 16) & 0xFFFF;
666 unsigned short carrier = (word >> 14) & 0x03;
667 unsigned short asic = (word >> 12) & 0x03;
668 unsigned short asicChannel = (word >> 9) & 0x07;
669 unsigned short window = word & 0x1FF;
670
671 // checks for data corruption
672 if (carrier != carrierFE) {
673 B2ERROR("TOPUnpacker: different carrier numbers in FE and WF header");
674 B2DEBUG(21, "Different carrier numbers in FE and WF header: "
675 << carrierFE << " " << carrier);
676 info->setErrorFlag(TOPInterimFEInfo::c_DifferentCarriers);
677 }
678 if (asic != asicFE) {
679 B2ERROR("TOPUnpacker: different ASIC numbers in FE and WF header");
680 B2DEBUG(21, "Different ASIC numbers in FE and WF header: "
681 << asicFE << " " << asic);
682 info->setErrorFlag(TOPInterimFEInfo::c_DifferentAsics);
683 }
684 if (asicChannel != asicChannelFE) {
685 B2ERROR("TOPUnpacker: different ASIC channel numbers in FE and WF header");
686 B2DEBUG(21, "Different ASIC channel numbers in FE and WF header: "
687 << asicChannelFE << " " << asicChannel);
688 info->setErrorFlag(TOPInterimFEInfo::c_DifferentChannels);
689 }
690 if (window != convertedAddr) {
691 B2ERROR("TOPUnpacker: different window numbers in FE and WF header");
692 B2DEBUG(21, "Different window numbers in FE and WF header: "
693 << convertedAddr << " " << window);
694 info->setErrorFlag(TOPInterimFEInfo::c_DifferentWindows);
695 }
696
697 // reading out all four window addresses
698 // to be for correcnt alignment of individual readout windows in written waveform
699 std::vector<unsigned short> windows;
700 windows.push_back(window);
701
702 word = array.getWord(); // word 20
703 windows.push_back(word & 0x1FF);
704
705 word = array.getWord(); // word 21
706 windows.push_back(word & 0x1FF);
707
708 word = array.getWord(); // word 22
709 windows.push_back(word & 0x1FF);
710
711 int numWords = 4 * 32; // (numPoints + 1) / 2;
712 if (array.getRemainingWords() < numWords) {
713 B2ERROR("TOPUnpacker: too few words for waveform data."
714 << LogVar("needed", numWords)
715 << LogVar("available", array.getRemainingWords()));
716 info->setErrorFlag(TOPInterimFEInfo::c_InsufficientWFData);
717 return array.getRemainingWords();
718 }
719
720 // unpack waveforms
721 std::vector<short> adcData;
722 for (int i = 0; i < numWords; i++) {
723 word = array.getWord();
724 adcData.push_back(word & 0xFFFF);
725 adcData.push_back((word >> 16) & 0xFFFF);
726 }
727 // if (numWords * 2 != numPoints) adcData.pop_back(); // numPoints is even
728
729 // determine slot number (moduleID) and boardstack
730 moduleID = 0;
731 boardstack = 0;
732 const auto* feemap = m_topgp->getFrontEndMapper().getMap(scrodID);
733 if (feemap) {
734 moduleID = feemap->getModuleID();
735 boardstack = feemap->getBoardstackNumber();
736 } else {
737 B2ERROR("TOPUnpacker: no front-end map available."
738 << LogVar("SCROD ID", scrodID));
739 info->setErrorFlag(TOPInterimFEInfo::c_InvalidScrodID);
740 }
741
742 // determine hardware channel and pixelID (valid only if feemap available!)
743 const auto& mapper = m_topgp->getChannelMapper();
744 unsigned channel = mapper.getChannel(boardstack, carrier, asic, asicChannel);
745 int pixelID = mapper.getPixelID(channel);
746
747 // store to raw waveforms
748 auto* waveform = m_waveforms.appendNew(moduleID, pixelID, channel, scrodID,
749 window, 0, adcData);
750 waveform->setLastWriteAddr(lastWrAddr);
751 waveform->setStorageWindows(windows);
752 waveform->setPedestalSubtractedFlag(pedestalSubtracted);
753 waveform->addRelationTo(info);
754 info->incrementWaveformsCount();
755
756 // create relations btw. raw digits and waveform
757 for (const auto* digit : digits) digit->addRelationTo(waveform);
758
759 }
760
761 if (evtNumCounter.size() != 1) {
762 B2ERROR("TOPUnpacker: Possible frame shift detected "
763 << "(More than one unique carrier event number in this readout event)."
764 << LogVar("SCROD", scrodID)
765 << LogVar("slot", moduleID)
766 << LogVar("BS", boardstack));
767 }
768
769 int nASICs = 0;
770
771 string evtNumOutputString;
772 evtNumOutputString += "Carrier event numbers and their counts for SCROD ID " + std::to_string(scrodID) + ":\n";
773 for (auto const& it : evtNumCounter) {
774 nASICs += it.second;
775 evtNumOutputString += std::to_string(it.first) + ":\t" + std::to_string(it.second) + "\n";
776 }
777 evtNumOutputString += "Total:\t" + std::to_string(nASICs);
778 B2DEBUG(21, evtNumOutputString);
779
780 int nChannels = 0;
781 int nChannelsDiff = 0;
782
783 string channelOutputString;
784 channelOutputString += "Detected channels and their counts for SCROD ID (channels with count == 1 are omitted)" + std::to_string(
785 scrodID) + ":\n";
786
787 int channelIndex(0);
788 for (auto const& it : channelCounter) {
789 if (it > 0) {
790 nChannelsDiff += 1;
791 }
792 nChannels += it;
793
794 if (it != 1) {
795 int channelID = channelIndex;
796 int carrier = channelID / 32;
797 int asic = (channelID % 32) / 8;
798 int chn = channelID % 8;
799 channelOutputString += "carrier: " + std::to_string(carrier) + " asic: " + std::to_string(asic) + " chn: " + std::to_string(
800 chn) + " occurrence: " + std::to_string(it) + "\n";
801 B2WARNING("TOPUnpacker: interim FE - ASIC channel seen more than once"
802 << LogVar("ScrodID", scrodID)
803 << LogVar("carrier", carrier)
804 << LogVar("ASIC", asic)
805 << LogVar("channel", chn)
806 << LogVar("times seen", it));
807 }
808 channelIndex += 1;
809 }
810
811 m_channelStatistics[nChannels] += 1;
812
813 channelOutputString += "Total:\t" + std::to_string(nChannels) + " " + std::to_string(nChannelsDiff);
814 B2DEBUG(21, channelOutputString);
815
816 return array.getRemainingWords();
817
818
819 }
820
821
822 int TOPUnpackerModule::unpackProdDebug(const int* buffer, int bufferSize, TOP::RawDataType dataFormat,
823 bool pedestalSubtracted, int expNo)
824 {
825
826 B2DEBUG(22, "Unpacking Production firmware debug data format to TOPRawDigits "
827 "dataSize = " << bufferSize);
828
829 DataArray array(buffer, bufferSize, m_swapBytes);
830 unsigned word;
831
832 word = array.getWord(); // word 0, type(8)/version(8)/0xA(4)/ScrodID(12)
833 unsigned int evtType = word >> 24;
834 unsigned int evtVersion = (word >> 16) & 0xFF;
835 unsigned int evtMagicHeader = (word >> 12) & 0xF;
836 unsigned int evtScrodID = word & 0xFFF;
837
838 // determine slot number (moduleID) and boardstack
839 int moduleID = 0;
840 int boardstack = 0;
841 const auto* feemap = m_topgp->getFrontEndMapper().getMap(evtScrodID);
842 if (feemap) {
843 moduleID = feemap->getModuleID();
844 boardstack = feemap->getBoardstackNumber();
845 } else {
846 B2WARNING("TOPUnpacker: no front-end map available."
847 << LogVar("SCROD ID", evtScrodID));
848 }
849
850
851 B2DEBUG(22, std::dec << array.getIndex() << ":\t" << setfill('0') << setw(4) << std::hex <<
852 (word >> 16) << " " << setfill('0') << setw(4) << (word & 0xFFFF) << std::dec
853 << "\tevtType = " << evtType
854 << ", evtVersion = " << evtVersion
855 << ", evtMagicHeader = " << evtMagicHeader
856 << ", evtScrodID = " << evtScrodID);
857
858 if (evtMagicHeader != 0xA) {
859 B2WARNING("TOPUnpacker: event header magic word mismatch. should be 0xA."
860 << LogVar("Magic word", evtMagicHeader));
861 return array.getRemainingWords();
862 }
863
864 word = array.getWord(); // word 1, extra(3)/numWordsBonus(13)/phase(4)/numWordsCore(12)
865 unsigned int evtExtra = word >> 29;
866 unsigned int evtNumWordsBonus = (word >> 16) & 0x1FFF;
867 unsigned int evtPhase = (word >> 12) & 0xF;
868 unsigned int evtNumWordsCore = word & 0xFFF;
869
870 B2DEBUG(22, std::dec << array.getIndex() << ":\t" << setfill('0') << setw(4) << std::hex <<
871 (word >> 16) << " " << setfill('0') << setw(4) << (word & 0xFFFF) << std::dec
872 << "\tevtExtra = " << evtExtra
873 << ", evtNumWordsBonus = " << evtNumWordsBonus
874 << ", evtPhase = " << evtPhase
875 << ", numWordsCore = " << evtNumWordsCore);
876
877 word = array.getWord(); // word 2, skipHit(1)/injVetoFlag(1)/PSBypass(3)/ctime LSBs(11)/revo9counter(16)
878 bool evtSkipHit = word >> 31;
879 bool injVetoFlag = (word >> 30) & 0x1;
880 unsigned int PSBypass = (word >> 27) & 0x7;
881 unsigned int evtCtime = (word >> 16) & 0x7FF;
882 unsigned int evtRevo9Counter = word & 0xFFFF;
883
884 if (expNo > 36) m_injectionVeto->set(injVetoFlag); // before this experiment the bit field is not used and may not be correctly set
885
886 B2DEBUG(22, std::dec << array.getIndex() << ":\t" << setfill('0') << setw(4) << std::hex <<
887 (word >> 16) << " " << setfill('0') << setw(4) << (word & 0xFFFF) << std::dec
888 << "\tevtSkipHit = " << evtSkipHit
889 << ", injVetoFlag = " << injVetoFlag
890 << ", PSBypass = " << PSBypass
891 << ", evtCtime = " << evtCtime
892 << ", evtRevo9Counter = " << evtRevo9Counter);
893
894 word = array.getWord(); // word 3, asicMask(16)/eventQueueDepth(8)/eventNumberByte(8)
895 unsigned int evtAsicMask = word >> 16;
896 unsigned int evtEventQueueDepth = (word >> 8) & 0xFF;
897 unsigned int evtEventNumberByte = word & 0xFF;
898
899 B2DEBUG(22, std::dec << array.getIndex() << ":\t" << setfill('0') << setw(4) << std::hex <<
900 (word >> 16) << " " << setfill('0') << setw(4) << (word & 0xFFFF) << std::dec
901 << "\tevtAsicMask = " << evtAsicMask
902 << ", evtEventQueueDepth = " << evtEventQueueDepth
903 << ", evtEventNumberByte = " << evtEventNumberByte);
904
905 m_productionEventDebugs.appendNew(evtType,
906 evtVersion,
907 evtScrodID,
908 evtSkipHit,
909 injVetoFlag,
910 PSBypass,
911 evtCtime,
912 evtPhase,
913 evtAsicMask,
914 evtEventQueueDepth,
915 evtEventNumberByte);
916
917 B2DEBUG(22, "end of event header, start of hits:");
918
919 const int numWordsPerHit = 4 + evtExtra;
920 unsigned int numHitsFound = 0;
921 unsigned int numExpectedWaveforms = 0;
922
923 std::vector<TOPRawDigit*> digitsWithWaveform; // digits that have waveforms
924
925 while (array.getRemainingWords() > numWordsPerHit //one more full hit + one word of footer
926 && array.getIndex() < evtNumWordsCore - 2) { // -1 for 0-based counting, -1 for hit footer word
927 array.resetChecksum();
928
929
930 //need to predefine some variables here as we need to branch out between two data format versions for the next two words
931 unsigned int hitCarrier = 0;
932 unsigned int hitAsic = 0;
933 unsigned int hitChannel = 0;
934 unsigned int hitWindow = 0;
935 unsigned int hitMagicHeader = 0;
936 unsigned int hitTFine = 0;
937 bool hitHasWaveform = false;
938 bool hitIsOnHeap = false;
939 unsigned int hitHeapWindow = 0;
940 bool hitIsOnHeapStraddle = false;
941 unsigned int hitHeapWindowStraddle = 0;
942 bool hitIsWindowStraddle = false;
943 short hitIntegral = 0;
944 short hitVPeak = 0;
945
946 if (dataFormat == TOP::RawDataType::c_ProductionDebug01) { //dataformat 0x0401
947 word = array.getWord(); // hit word 0, carrier(2)/asic(2)/channel(3)/window(9)/0xB(4)/tFine(4)/hasWaveform(1)/isOnHeap(1)/heapWindow(6)
948 hitCarrier = word >> 30;
949 hitAsic = (word >> 28) & 0x3;
950 hitChannel = (word >> 25) & 0x7;
951 hitWindow = (word >> 16) & 0x1FF;
952 hitMagicHeader = (word >> 12) & 0xF;
953 hitTFine = (word >> 8) & 0xF;
954 hitHasWaveform = (word >> 7) & 0x1;
955 hitIsOnHeap = (word >> 6) & 0x1;
956 hitHeapWindow = word & 0x3F;
957
958
959 B2DEBUG(22, std::dec << array.getIndex() << ":\t" << setfill('0') << setw(4) << std::hex <<
960 (word >> 16) << " " << setfill('0') << setw(4) << (word & 0xFFFF) << std::dec
961 << "\thitCarrier = " << hitCarrier
962 << ", hitAsic = " << hitAsic
963 << ", hitChannel = " << hitChannel
964 << ", hitWindow = " << hitWindow
965 // << ", hitMagicHeader = " << hitMagicHeader
966 // << ", hitTFine = " << hitTFine
967 << ", hitHasWaveform = " << hitHasWaveform
968 // << ", hitIsOnHeap = " << hitIsOnHeap
969 // << ", hitHeapWindow = " << hitHeapWindow
970 );
971
972
973 word = array.getWord(); // hit word 1, reserved(3)/vPeak(13)/integral(16)
974 hitVPeak = expand13to16bits(word >> 16);
975 hitIntegral = word & 0xFFFF;
976 B2DEBUG(22, std::dec << array.getIndex() << ":\t" << setfill('0') << setw(4) << std::hex <<
977 (word >> 16) << " " << setfill('0') << setw(4) << (word & 0xFFFF) << std::dec
978 << "\thitVPeak = " << hitVPeak
979 << ", hitIntegral = " << hitIntegral);
980
981 } else if (dataFormat == TOP::RawDataType::c_ProductionDebug02) { //dataformat 0x0402
982 word = array.getWord(); // hit word 0, carrier(2)/asic(2)/channel(3)/window(9)/0xB(4)/tFine(4)/hasWaveform(1)/isWindowStraddle(1)/integral(6)
983 hitCarrier = word >> 30;
984 hitAsic = (word >> 28) & 0x3;
985 hitChannel = (word >> 25) & 0x7;
986 hitWindow = (word >> 16) & 0x1FF;
987 hitMagicHeader = (word >> 12) & 0xF;
988 hitTFine = (word >> 8) & 0xF;
989 hitHasWaveform = (word >> 7) & 0x1;
990 hitIsWindowStraddle = (word >> 6) & 0x1;
991 hitIntegral = word & 0x3F;
992
993
994 B2DEBUG(22, std::dec << array.getIndex() << ":\t" << setfill('0') << setw(4) << std::hex <<
995 (word >> 16) << " " << setfill('0') << setw(4) << (word & 0xFFFF) << std::dec
996 << "\thitCarrier = " << hitCarrier
997 << ", hitAsic = " << hitAsic
998 << ", hitChannel = " << hitChannel
999 << ", hitWindow = " << hitWindow
1000 // << ", hitMagicHeader = " << hitMagicHeader
1001 // << ", hitTFine = " << hitTFine
1002 << ", hitHasWaveform = " << hitHasWaveform
1003 << ", hitIsWindowStraddle = " << hitHasWaveform
1004 << ", hitIntegral = " << hitIntegral
1005 // << ", hitHeapWindow = " << hitHeapWindow
1006 );
1007
1008 word = array.getWord(); // hit word 1, reserved(3)/vPeak(13)/isOnHeap1(1)/heapWindow1(7)/isOnHeap0(1)/heapWindow0(7)
1009 hitVPeak = expand13to16bits(word >> 16);
1010 hitIsOnHeapStraddle = (word >> 15) & 0x1;
1011 hitHeapWindowStraddle = (word >> 8) & 0x7F;
1012 hitIsOnHeap = (word >> 7) & 0x1;
1013 hitHeapWindow = word & 0x1;
1014
1015 B2DEBUG(22, std::dec << array.getIndex() << ":\t" << setfill('0') << setw(4) << std::hex <<
1016 (word >> 16) << " " << setfill('0') << setw(4) << (word & 0xFFFF) << std::dec
1017 << "\thitVPeak = " << hitVPeak
1018 << ", hitIsOnHeapStraddle = " << hitIsOnHeapStraddle
1019 << ", hitHeapWindowStraddle = " << hitHeapWindowStraddle
1020 << ", hitIsOnHeap = " << hitIsOnHeap
1021 << ", hitHeapWindow = " << hitHeapWindow);
1022 } else { //could not match the data format
1023 B2WARNING("TOPUnpacker: could not match data type inside unpackProdDebug()"
1024 << LogVar("evtType", evtType) << LogVar("evtVersion", evtVersion));
1025 return array.getRemainingWords();
1026 }
1027
1028
1029 if (hitHasWaveform) {
1030 numExpectedWaveforms += 1;
1031 }
1032
1033 if (hitMagicHeader != 0xB) {
1034 B2WARNING("TOPUnpacker: hit header magic word mismatch. should be 0xB."
1035 << LogVar("Magic word", hitMagicHeader));
1036 return array.getRemainingWords();
1037 }
1038
1039 word = array.getWord(); // hit word 2, reserved(3)/vRise0(13)/reserved(3)/vRise1(13)
1040 short hitVRise0 = expand13to16bits(word >> 16);
1041 short hitVRise1 = expand13to16bits(word);
1042 B2DEBUG(22, std::dec << array.getIndex() << ":\t" << setfill('0') << setw(4) << std::hex <<
1043 (word >> 16) << " " << setfill('0') << setw(4) << (word & 0xFFFF) << std::dec
1044 << "\thitVRise0 = " << hitVRise0
1045 << ", hitVRise1 = " << hitVRise1);
1046
1047 word = array.getWord(); // hit word 3, reserved(3)/vFall0(13)/reserved(3)/vFall1(13)
1048 short hitVFall0 = expand13to16bits(word >> 16);
1049 short hitVFall1 = expand13to16bits(word);
1050 B2DEBUG(22, std::dec << array.getIndex() << ":\t" << setfill('0') << setw(4) << std::hex <<
1051 (word >> 16) << " " << setfill('0') << setw(4) << (word & 0xFFFF) << std::dec
1052 << "\thitVFall0 = " << hitVFall0
1053 << ", hitVFall1 = " << hitVFall1);
1054
1055 word = array.getWord(); // hit word 4, sampleRise(8)/dSampPeak(4)/dSampFall(4)/headerChecksum(16)
1056 unsigned short hitSampleRise = (word >> 24);
1057 short hitDSampPeak = (word >> 20) & 0xF;
1058 short hitDSampFall = (word >> 16) & 0xF;
1059 unsigned short hitHeaderChecksum = word & 0xFFFF;
1060 B2DEBUG(22, std::dec << array.getIndex() << ":\t" << setfill('0') << setw(4) << std::hex <<
1061 (word >> 16) << " " << setfill('0') << setw(4) << (word & 0xFFFF) << std::dec
1062 << "\thitSampleRise = " << hitSampleRise
1063 << ", hitDSampPeak = " << hitDSampPeak
1064 << ", hitDSampFall = " << hitDSampFall
1065 << ", hitheaderChecksum = " << hitHeaderChecksum
1066 << ", checksum " << (array.validateChecksum() ? "OK" : "NOT OK"));
1067
1068 if (!array.validateChecksum()) {
1069 B2WARNING("TOPUnpacker: hit checksum invalid.");
1070 return array.getRemainingWords();
1071 }
1072
1073 // append digit
1074 auto* digit = m_rawDigits.appendNew(evtScrodID, TOPRawDigit::c_ProductionDebug);
1075 digit->setCarrierNumber(hitCarrier);
1076 digit->setASICNumber(hitAsic);
1077 digit->setASICChannel(hitChannel);
1078 digit->setASICWindow(hitWindow);
1079 digit->setLastWriteAddr(0);
1080 digit->setSampleRise(hitSampleRise);
1081 digit->setDeltaSamplePeak(hitDSampPeak);
1082 digit->setDeltaSampleFall(hitDSampFall);
1083 digit->setValueRise0(hitVRise0);
1084 digit->setValueRise1(hitVRise1);
1085 digit->setValuePeak(hitVPeak);
1086 digit->setValueFall0(hitVFall0);
1087 digit->setValueFall1(hitVFall1);
1088 digit->setTFine(hitTFine);
1089 digit->setIntegral(hitIntegral);
1090 digit->setRevo9Counter(evtRevo9Counter);
1091 digit->setPhase(evtPhase);
1092
1093
1094 if (hitHasWaveform) {
1095 digitsWithWaveform.push_back(digit);
1096 }
1097
1098 TOPProductionHitDebug* hitDebug = 0;
1099 if (dataFormat == TOP::RawDataType::c_ProductionDebug01) { // dataformat 0x0401
1100 hitDebug = m_productionHitDebugs.appendNew(hitHasWaveform,
1101 hitIsOnHeap,
1102 hitWindow,
1103 hitIsOnHeap ? 428 + hitHeapWindow : hitWindow, //hitHeapWindow is counted from the start of the heap
1104 hitIsWindowStraddle);
1105 } else if (dataFormat == TOP::RawDataType::c_ProductionDebug02) { // dataformat 0x0402
1106 hitDebug = m_productionHitDebugs.appendNew(hitHasWaveform,
1107 hitIsOnHeap,
1108 hitWindow,
1109 hitIsOnHeap ? 428 + hitHeapWindow : hitWindow, //hitHeapWindow is counted from the start of the heap
1110 hitIsWindowStraddle,
1111 hitWindow + 1, //logical address of straddle window is always +1
1112 hitIsOnHeapStraddle ? 428 + hitHeapWindowStraddle : hitWindow +
1113 1); //physical address might be entirely different if straddled window is on heap
1114 }
1115
1116 //parse extra words if exist:
1117 for (unsigned int i = 0; i < evtExtra; ++i) {
1118 word = array.getWord(); // extra hit word i, undefined so far
1119 B2DEBUG(22, std::dec << array.getIndex() << ":\t" << setfill('0') << setw(4) << std::hex <<
1120 (word >> 16) << " " << setfill('0') << setw(4) << (word & 0xFFFF) << std::dec
1121 << "\thit extra word " << i << " (" << evtExtra << ")");
1122 hitDebug->appendExtraWord(word);
1123 }
1124
1125 if (m_addRelations and hitDebug) {
1126 digit->addRelationTo(hitDebug);
1127 }
1128
1129 numHitsFound += 1;
1130 } // end of hits loop
1131
1132 word = array.getWord(); // event footer word, sdType(8)/sdData(12)/0x5(3)/nHits(9)
1133 unsigned int evtSdType = (word >> 24);
1134 unsigned int evtSdData = (word >> 12) & 0xFFF;
1135 unsigned int evtMagicFooter = (word >> 9) & 0x7;
1136 unsigned int evtNHits = word & 0x1FF;
1137 B2DEBUG(22, std::dec << array.getIndex() << ":\t" << setfill('0') << setw(4) << std::hex <<
1138 (word >> 16) << " " << setfill('0') << setw(4) << (word & 0xFFFF) << std::dec
1139 << "\tevtSdType = " << evtSdType
1140 << ", evtSdData = " << evtSdData
1141 << ", evtMagicFooter = " << evtMagicFooter
1142 << ", evtNHits = " << evtNHits << " (" << numHitsFound << ")");
1143
1144 if (evtSdType != 0) {
1145 m_slowData.appendNew(evtScrodID, evtSdType, evtSdData);
1146 }
1147
1148 if (evtMagicFooter != 0x5) {
1149 B2WARNING("TOPUnpacker: event footer magic word mismatch. should be 0x5."
1150 << LogVar("Magic word", evtMagicFooter));
1151 return array.getRemainingWords();
1152 }
1153
1154 B2DEBUG(22, "the rest:");
1155
1156 unsigned int numParsedWaveforms = 0;
1157 while (array.peekWord() != 0x6c617374 //next word is not wf footer word
1158 && array.getRemainingWords() > 0) {
1159
1160 word = array.getWord(); // waveform word 0, nSamples(16)/0x0(5)/nWindows(3)/0(1)/carrier(2)/asic(2)/channel(3)
1161 unsigned int wfNSamples = (word >> 16);
1162 unsigned int wfNWindows = (word >> 8) & 0x7;
1163 unsigned int wfCarrier = (word >> 5) & 0x3;
1164 unsigned int wfAsic = (word >> 3) & 0x3;
1165 unsigned int wfChannel = word & 0x7;
1166
1167 // determine hardware channel and pixelID (valid only if feemap available!)
1168 const auto& mapper = m_topgp->getChannelMapper();
1169 unsigned channel = mapper.getChannel(boardstack, wfCarrier, wfAsic, wfChannel);
1170 int pixelID = mapper.getPixelID(channel);
1171
1172 B2DEBUG(22, std::dec << array.getIndex() << ":\t" << setfill('0') << setw(4) << std::hex <<
1173 (word >> 16) << " " << setfill('0') << setw(4) << (word & 0xFFFF) << std::dec
1174 << "\twfNSamples = " << wfNSamples
1175 << ", wfNWindows = " << wfNWindows
1176 << ", wfCarrier = " << wfCarrier
1177 << ", wfAsic = " << wfAsic
1178 << ", wfChannel " << wfChannel);
1179
1180 if (wfNSamples != 32 && wfNSamples != 16) {
1181 B2WARNING("TOPUnpacker: suspicious value for wfNSamples."
1182 << LogVar("wfNSamples", wfNSamples));
1183 return array.getRemainingWords();
1184 }
1185
1186 word = array.getWord(); // waveform word 1, 0x0(1)/startSamp(6)/logAddress(9)/carrierEventNumber(7)/readAddr(9)
1187 unsigned int wfStartSample = (word >> 25) & 0x3F;
1188 unsigned int wfWindowLogic = (word >> 16) & 0x1FF;
1189 unsigned int wfEventNumber = (word >> 9) & 0x7F;
1190 unsigned int wfWindowPhysical = word & 0x1FF;
1191
1192 B2DEBUG(22, std::dec << array.getIndex() << ":\t" << setfill('0') << setw(4) << std::hex <<
1193 (word >> 16) << " " << setfill('0') << setw(4) << (word & 0xFFFF) << std::dec
1194 << "\twfStartSample = " << wfStartSample
1195 << ", wfWindowLogic = " << wfWindowLogic
1196 << ", wfEventNumber = " << wfEventNumber
1197 << ", wfWindowPhysical = " << wfWindowPhysical);
1198
1199 std::vector<short> wfSamples;
1200
1201 for (unsigned int i = 0; i < wfNSamples / 2; ++i) {
1202 short wfSampleLast = 0;
1203 short wfSampleFirst = 0;
1204
1205
1206 word = array.getWord(); // waveform sample word i, reserved(4)/sample 2*i+1(12)/reserved(4)/sample 2*i(12)
1207 if (pedestalSubtracted) {
1208 wfSampleLast = (word >> 16);
1209 wfSampleFirst = word & 0xFFFF;
1210 } else {
1211 wfSampleLast = (word >> 16) & 0xFFF;
1212 wfSampleFirst = word & 0xFFF;
1213
1214 }
1215
1216 B2DEBUG(22, std::dec << array.getIndex() << ":\t" << setfill('0') << setw(4) << std::hex <<
1217 (word >> 16) << " " << setfill('0') << setw(4) << (word & 0xFFFF) << std::dec
1218 << "\twfSample" << 2 * i + 1 << " = " << wfSampleLast
1219 << ", wfSample" << 2 * i << " = " << wfSampleFirst);
1220
1221 wfSamples.push_back(wfSampleFirst);
1222 wfSamples.push_back(wfSampleLast);
1223 }
1224
1225 // append waveform
1226 auto* waveform = m_waveforms.appendNew(moduleID, pixelID, channel, evtScrodID,
1227 wfWindowLogic, wfStartSample, wfSamples);
1228 waveform->setPedestalSubtractedFlag(pedestalSubtracted);
1229 waveform->setPhysicalWindow(wfWindowPhysical);
1230 if (numParsedWaveforms < digitsWithWaveform.size()) {
1231 const auto* digit = digitsWithWaveform[numParsedWaveforms];
1232 if (digit->getScrodChannel() == channel % 128) {
1233 digit->addRelationTo(waveform);
1234 } else {
1235 B2WARNING("TOPUnpacker: hit and its waveform have different channel number."
1236 << LogVar("channel (hit)", digit->getScrodChannel())
1237 << LogVar("channel (waveform)", channel % 128));
1238 }
1239 }
1240 numParsedWaveforms += 1;
1241
1242 } // end of waveform segments loop
1243
1244 if (numExpectedWaveforms != numParsedWaveforms) {
1245 B2WARNING("TOPUnpacker: number of expected and parsed waveforms does not match."
1246 << LogVar("expected", numExpectedWaveforms)
1247 << LogVar("parsed", numParsedWaveforms));
1248 }
1249
1250 return array.getRemainingWords();
1251 }
1252
1253
1255 {
1256 B2INFO("TOPUnpacker: Channels seen per event statistics:");
1257 B2INFO("TOPUnpacker: nChn\tcount");
1258 for (const auto& entry : m_channelStatistics) {
1259 B2INFO("TOPUnpacker: " << entry.first << "\t\t" << entry.second);
1260 }
1261 }
1262
1263
1265} // end Belle2 namespace
@ c_DontWriteOut
Object/array should be NOT saved by output modules.
Definition DataStore.h:71
@ c_Event
Different object in each event, all objects/arrays are invalidated after event() function has been ca...
Definition DataStore.h:59
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
Module()
Constructor.
Definition Module.cc:30
@ 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
The Raw TOP class Class for RawCOPPER class data taken by TOP Currently, this class is almost same as...
Definition RawTOP.h:27
Type-safe access to single objects in the data store.
Definition StoreObjPtr.h:96
EHitQuality
hit quality enumerators
Definition TOPDigit.h:33
@ c_DifferentChannels
in FE and WF header
@ c_DifferentScrodIDs
in HLSB and FE header
@ c_InvalidMagicWord
at the end of FE header
@ c_InvalidScrodID
no front-end map available
@ c_DifferentCarriers
in FE and WF header
@ c_DifferentWindows
in FE and WF header
@ c_InsufficientWFData
too few words for waveform data
@ c_InvalidFEHeader
invalid FE header word
@ c_DifferentAsics
in FE and WF header
Class to store debugging information about the hit headers in the TOP production debugging raw data f...
void appendExtraWord(unsigned int extraWord)
Appends extra word to vector of additional event words.
@ c_Interim
from interim feature extraction
Definition TOPRawDigit.h:44
@ c_ProductionDebug
from production debugging format
Definition TOPRawDigit.h:46
@ c_Production
from the future production format
Definition TOPRawDigit.h:45
@ c_HitMagic
if magic number not 0xB
Definition TOPRawDigit.h:33
@ c_TailMagic
if magic bits not '101' = 0x5
Definition TOPRawDigit.h:32
@ c_HitChecksum
if sum of 16-bit words not zero
Definition TOPRawDigit.h:34
@ c_HeadMagic
if magic number not 0xA
Definition TOPRawDigit.h:31
StoreArray< TOPRawWaveform > m_waveforms
collection of waveforms
StoreArray< TOPRawDigit > m_rawDigits
collection of raw digits
unsigned m_numErrors
number of error messages per event
unsigned m_errorCount
error messages count within single event
std::map< int, int > m_channelStatistics
counts how many different channels have been parsed in a given SCROD packet
StoreArray< TOPSlowData > m_slowData
collection of slow data
bool m_swapBytes
if true, swap bytes (used in unpacking)
StoreArray< TOPProductionEventDebug > m_productionEventDebugs
collection of event debug data
std::string m_outputRawDigitsName
name of TOPRawDigit store array
std::string m_outputWaveformsName
name of TOPRawWaveform store array
StoreArray< RawTOP > m_rawData
collection of raw data
StoreArray< TOPInterimFEInfo > m_interimFEInfos
collection of interim information
bool m_resetEventCount
request for event count reset
StoreObjPtr< TOPInjectionVeto > m_injectionVeto
injection veto flag
StoreArray< TOPProductionHitDebug > m_productionHitDebugs
collection of hit debug data
std::string m_outputDigitsName
name of TOPDigit store array
StoreArray< TOPTemplateFitResult > m_templateFitResults
collection of template fit results
bool m_swapBytesDefault
if true, swap bytes (default by module parameter)
std::string m_inputRawDataName
name of RawTOP store array
unsigned m_errorSuppressFactor
error messages suppression factor
static short expand13to16bits(unsigned short x)
Expand 13-bit signed-word to 16-bit signed-word.
StoreArray< TOPDigit > m_digits
collection of digits
unsigned m_eventCount
event count since last printed error message
bool m_addRelations
switch ON/OFF relations to TOPProductionHitDebugs
static unsigned short sumShorts(unsigned int x)
sum both 16-bit words of 32-bit integer
std::string m_templateFitResultName
name of TOPTemplateFitResult store array
TOP::TOPGeometryPar * m_topgp
geometry param
Helper class for getting data words from a finesse buffer Keeps checksum counter for each extracted d...
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:559
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Definition Module.h:649
void unpackProductionDraft(const int *buffer, int bufferSize)
Unpack raw data given in a tentative production format (will vanish in future)
static std::string getFrontEndName(RawTOP &raw, int finesse)
Returns the name of the front-end.
virtual void initialize() override
Initialize the Module.
virtual void event() override
Event processor.
virtual void endRun() override
End-of-run action.
void unpackType0Ver16(const int *buffer, int bufferSize)
Unpack raw data given in feature-extraction production format.
virtual void beginRun() override
Called when entering a new run.
static bool unpackHeadersInterimFEVer01(const int *buffer, int bufferSize, bool swapBytes)
Tries to unpack raw data assuming it is in feature-extraction interim format.
int unpackProdDebug(const int *buffer, int bufferSize, TOP::RawDataType dataFormat, bool pedestalSubtracted, int expNo)
Unpack raw data given in production debugging format.
int unpackInterimFEVer01(const int *buffer, int bufferSize, bool pedestalSubtracted)
Unpack raw data given in feature-extraction interim format.
bool printTheError()
Error messages suppression logic.
Abstract base class for different kinds of events.
STL namespace.
record to be used to store ASIC info