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