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