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