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