12 #include <top/modules/TOPUnpacker/TOPUnpackerModule.h>
13 #include <top/RawDataTypes.h>
16 #include <framework/datastore/DataStore.h>
17 #include <framework/datastore/StoreArray.h>
18 #include <framework/datastore/StoreObjPtr.h>
21 #include <framework/logging/Logger.h>
24 #include <framework/dataobjects/EventMetaData.h>
54 setDescription(
"Raw data unpacker for TOP");
55 setPropertyFlags(c_ParallelProcessingCertified);
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);
74 TOPUnpackerModule::~TOPUnpackerModule()
78 void TOPUnpackerModule::initialize()
83 m_rawData.isRequired(m_inputRawDataName);
87 m_digits.registerInDataStore(m_outputDigitsName);
88 m_rawDigits.registerInDataStore(m_outputRawDigitsName);
89 m_slowData.registerInDataStore();
90 m_interimFEInfos.registerInDataStore(DataStore::c_DontWriteOut);
91 m_waveforms.registerInDataStore(m_outputWaveformsName, DataStore::c_DontWriteOut);
92 m_productionEventDebugs.registerInDataStore(DataStore::c_DontWriteOut);
93 m_productionHitDebugs.registerInDataStore(DataStore::c_DontWriteOut);
94 m_templateFitResults.registerInDataStore(m_templateFitResultName, DataStore::c_DontWriteOut);
96 m_rawDigits.registerRelationTo(m_waveforms, DataStore::c_Event, DataStore::c_DontWriteOut);
97 m_rawDigits.registerRelationTo(m_templateFitResults, DataStore::c_Event, DataStore::c_DontWriteOut);
98 m_rawDigits.registerRelationTo(m_interimFEInfos, DataStore::c_Event, DataStore::c_DontWriteOut);
99 m_rawDigits.registerRelationTo(m_productionHitDebugs, DataStore::c_Event, DataStore::c_DontWriteOut);
100 m_waveforms.registerRelationTo(m_interimFEInfos, DataStore::c_Event, DataStore::c_DontWriteOut);
103 const auto& mapper = m_topgp->getFrontEndMapper();
104 int mapSize = mapper.getMapSize();
105 if (mapSize == 0) B2ERROR(
"TOPUnpacker: No front-end mapping available for TOP");
109 void TOPUnpackerModule::beginRun()
111 m_channelStatistics.clear();
114 void TOPUnpackerModule::event()
120 m_productionEventDebugs.clear();
121 m_productionHitDebugs.clear();
122 m_templateFitResults.clear();
124 m_interimFEInfos.clear();
127 for (
auto& raw : m_rawData) {
128 for (
int finesse = 0; finesse < raw.GetMaxNumOfCh(0); finesse++) {
129 const int* buffer = raw.GetDetectorBuffer(0, finesse);
130 int bufferSize = raw.GetDetectorNwords(0, finesse);
131 if (bufferSize < 1)
continue;
135 int dataFormat = m_dataFormat;
136 if (dataFormat == 0) {
137 DataArray array(buffer, bufferSize, m_swapBytes);
138 unsigned word = array.
getWord();
139 dataFormat = (word >> 16);
140 bool isKnownDataFormat =
false;
141 for (
auto& t : TOP::membersRawDataType) {
142 if (
static_cast<int>(t) == dataFormat) {
143 isKnownDataFormat =
true;
148 if (!isKnownDataFormat) {
149 if (evtMetaData->getExperiment() == 1) {
153 if (unpackHeadersInterimFEVer01(buffer, bufferSize,
true)) {
154 B2DEBUG(200,
"Assuming interim FW data format");
158 B2WARNING(
"TOPUnpacker: Could not establish data format.");
165 switch (dataFormat) {
166 case static_cast<int>(TOP::RawDataType::c_Type0Ver16):
167 unpackType0Ver16(buffer, bufferSize);
169 case static_cast<int>(TOP::RawDataType::c_Type2Ver1):
170 err = unpackInterimFEVer01(buffer, bufferSize,
false);
172 case static_cast<int>(TOP::RawDataType::c_Type3Ver1):
173 err = unpackInterimFEVer01(buffer, bufferSize,
true);
175 case static_cast<int>(TOP::RawDataType::c_Draft):
176 unpackProductionDraft(buffer, bufferSize);
178 case static_cast<int>(TOP::RawDataType::c_ProductionDebug01):
179 err = unpackProdDebug(buffer, bufferSize, TOP::RawDataType::c_ProductionDebug01,
true);
181 case static_cast<int>(TOP::RawDataType::c_ProductionDebug02):
182 err = unpackProdDebug(buffer, bufferSize, TOP::RawDataType::c_ProductionDebug02,
true);
186 B2ERROR(
"TOPUnpacker: unknown data format."
187 <<
LogVar(
"Type", (dataFormat >> 8))
188 <<
LogVar(
"Version", (dataFormat & 0xFF)));
194 stringstream copperName;
196 copperName <<
"cpr" << ((raw.GetNodeID(0) >> 24) * 1000 + (raw.GetNodeID(0) & 0x3FF)) << char(
'a' + finesse);
197 B2ERROR(
"TOPUnpacker: error in unpacking data from frontend " << copperName.str()
198 <<
LogVar(
"words unused", err)
199 <<
LogVar(
"copper", copperName.str()));
208 void TOPUnpackerModule::unpackProductionDraft(
const int* buffer,
int bufferSize)
211 B2DEBUG(200,
"Unpacking ProductionDraft to TOPDigits, dataSize = " << bufferSize);
213 unsigned short scrodID = buffer[0] & 0xFFFF;
214 const auto* feemap = m_topgp->getFrontEndMapper().getMap(scrodID);
216 B2ERROR(
"TOPUnpacker: no front-end map available."
217 <<
LogVar(
"SCROD ID", scrodID));
220 int moduleID = feemap->getModuleID();
221 int boardstack = feemap->getBoardstackNumber();
222 const auto& mapper = m_topgp->getChannelMapper();
224 const auto* geo = m_topgp->getGeometry();
225 auto subBits = geo->getNominalTDC().getSubBits();
226 int sampleDivisions = 0x1 << subBits;
228 for (
int i = 1; i < bufferSize; i++) {
229 int word = buffer[i];
230 int tdc = word & 0xFFFF;
231 double rawTime = double(tdc) / sampleDivisions;
232 unsigned chan = ((word >> 16) & 0x7F) + boardstack * 128;
233 unsigned flags = (word >> 24) & 0xFF;
234 int pixelID = mapper.getPixelID(chan);
235 auto* digit = m_digits.appendNew(moduleID, pixelID, rawTime);
236 digit->setTime(geo->getNominalTDC().getTime(tdc));
237 digit->setChannel(chan);
244 void TOPUnpackerModule::unpackType0Ver16(
const int* buffer,
int bufferSize)
247 B2DEBUG(200,
"Unpacking Type0Ver16 to TOPRawDigits, dataSize = " << bufferSize);
249 DataArray array(buffer, bufferSize, m_swapBytes);
250 unsigned word = array.
getWord();
251 unsigned short scrodID = word & 0x0FFF;
254 int Nhits = last & 0x01FF;
255 if (bufferSize != 5 * Nhits + 2) {
256 B2ERROR(
"TOPUnpacker: corrupted data (feature-extraction format)."
257 <<
LogVar(
"SCROD ID", scrodID));
261 short SDType = last >> 24;
262 short SDValue = (last >> 12) & 0x0FFF;
263 if (SDType != 0) m_slowData.appendNew(scrodID, SDType, SDValue);
265 unsigned short errorFlags = 0;
266 if (((word >> 12) & 0x0F) != 0x0A) errorFlags |= TOPRawDigit::c_HeadMagic;
267 if (((last >> 9) & 0x07) != 0x05) errorFlags |= TOPRawDigit::c_TailMagic;
269 for (
int hit = 0; hit < Nhits; hit++) {
270 auto* digit = m_rawDigits.appendNew(scrodID, TOPRawDigit::c_Production);
273 digit->setCarrierNumber((word >> 30) & 0x03);
274 digit->setASICNumber((word >> 28) & 0x03);
275 digit->setASICChannel((word >> 25) & 0x07);
276 digit->setASICWindow((word >> 16) & 0x1FF);
277 digit->setTFine((word >> 8) & 0x0F);
278 auto flags = errorFlags;
279 if (((word >> 12) & 0x0F) != 0x0B) flags |= TOPRawDigit::c_HitMagic;
280 unsigned short checkSum = sumShorts(word);
283 digit->setValuePeak(expand13to16bits(word >> 16));
284 digit->setIntegral(word & 0xFFFF);
285 checkSum += sumShorts(word);
288 digit->setValueRise0(expand13to16bits(word >> 16));
289 digit->setValueRise1(expand13to16bits(word));
290 checkSum += sumShorts(word);
293 digit->setValueFall0(expand13to16bits(word >> 16));
294 digit->setValueFall1(expand13to16bits(word));
295 checkSum += sumShorts(word);
298 digit->setSampleRise(word >> 24);
299 digit->setDeltaSamplePeak((word >> 20) & 0x0F);
300 digit->setDeltaSampleFall((word >> 16) & 0x0F);
301 checkSum += sumShorts(word);
302 if (checkSum != 0) flags |= TOPRawDigit::c_HitChecksum;
304 digit->setErrorFlags(flags);
310 bool TOPUnpackerModule::unpackHeadersInterimFEVer01(
const int* buffer,
int bufferSize,
bool swapBytes)
312 B2DEBUG(200,
"Checking whether buffer unpacks as InterimFEVer01, dataSize = " << bufferSize);
314 DataArray array(buffer, bufferSize, swapBytes);
319 unsigned header = array.
getWord();
320 if ((header & 0xFF) == 0xBE) {
324 if (header != 0xaaaa0104 and header != 0xaaaa0103 and header != 0xaaaa0100) {
332 if (header != 0xaaaa0104) {
348 unsigned magicWord = array.
getWord();
349 if (magicWord != 0x7473616c) {
353 if (header != 0xaaaa0103)
continue;
366 int numWords = 4 * 32;
371 for (
int i = 0; i < numWords; i++) {
380 int TOPUnpackerModule::unpackInterimFEVer01(
const int* buffer,
int bufferSize,
381 bool pedestalSubtracted)
384 B2DEBUG(200,
"Unpacking InterimFEVer01 to TOPRawDigits and TOPRawWaveforms, "
385 "dataSize = " << bufferSize);
390 DataArray array(buffer, bufferSize, m_swapBytes);
392 map<unsigned short, int> evtNumCounter;
393 std::vector<unsigned short> channelCounter(128, 0);
395 unsigned word = array.
getWord();
396 unsigned short scrodID = word & 0x0FFF;
397 auto* info = m_interimFEInfos.appendNew(scrodID, bufferSize);
404 unsigned header = array.
getWord();
406 if ((header & 0xFF) == 0xBE) {
409 unsigned short scrodID_SSFE;
410 unsigned short carrier_SSFE;
411 unsigned short asic_SSFE;
412 unsigned short channel_SSFE;
413 unsigned short evtNum_SSFE;
415 evtNum_SSFE = (header >> 8) & 0xFF;
416 scrodID_SSFE = (header >> 16) & 0x7F;
417 channel_SSFE = (header >> 24) & 0x07;
418 asic_SSFE = (header >> 27) & 0x03;
419 carrier_SSFE = (header >> 29) & 0x03;
421 const auto* feemap = m_topgp->getFrontEndMapper().getMap(scrodID_SSFE);
423 moduleID = feemap->getModuleID();
424 boardstack = feemap->getBoardstackNumber();
426 B2ERROR(
"TOPUnpacker: no front-end map available."
427 <<
LogVar(
"SCROD ID", scrodID_SSFE));
428 info->setErrorFlag(TOPInterimFEInfo::c_InvalidScrodID);
431 if (scrodID_SSFE != scrodID) {
432 B2ERROR(
"TOPUnpacker: corrupted data - "
433 <<
"different scrodID's in HLSB and super short FE header."
434 <<
LogVar(
"SCROD", scrodID_SSFE)
435 <<
LogVar(
"slot", moduleID)
436 <<
LogVar(
"BS", boardstack));
437 B2DEBUG(100,
"Different scrodID's in HLSB and FE header: " << scrodID <<
" " << scrodID_SSFE <<
" word = 0x" << std::hex << word);
438 info->setErrorFlag(TOPInterimFEInfo::c_DifferentScrodIDs);
442 B2DEBUG(100, scrodID_SSFE <<
"\t" << carrier_SSFE <<
"\t" << asic_SSFE <<
"\t" << channel_SSFE <<
"\t" << evtNum_SSFE);
444 int channelID = carrier_SSFE * 32 + asic_SSFE * 8 + channel_SSFE;
445 channelCounter[channelID] += 1;
446 evtNumCounter[evtNum_SSFE] += 1;
448 info->incrementFEHeadersCount();
449 info->incrementEmptyFEHeadersCount();
454 if (header != 0xaaaa0104 and header != 0xaaaa0103 and header != 0xaaaa0100) {
455 B2ERROR(
"TOPUnpacker: corrupted data - invalid FE header word");
456 B2DEBUG(100,
"Invalid FE header word: " << std::hex << header <<
" 0b" << std::bitset<32>(header));
457 B2DEBUG(100,
"SCROD ID: " << scrodID <<
" " << std::hex << scrodID);
459 info->setErrorFlag(TOPInterimFEInfo::c_InvalidFEHeader);
465 unsigned short scrodID_FE = word >> 25;
466 unsigned short convertedAddr = (word >> 16) & 0x1FF;
467 unsigned short evtNum_numWin_trigPat_FEheader = word & 0xFFFF;
468 unsigned short evtNum_FEheader = evtNum_numWin_trigPat_FEheader & 0xFF;
469 evtNumCounter[evtNum_FEheader] += 1;
471 if (scrodID_FE != scrodID) {
472 B2ERROR(
"TOPUnpacker: different scrodID's in HLSB and FE header."
473 <<
LogVar(
"scrodID (HSLB)", scrodID)
474 <<
LogVar(
"scrodID (FE)", scrodID_FE));
476 info->setErrorFlag(TOPInterimFEInfo::c_DifferentScrodIDs);
482 unsigned lastWrAddr = (word & 0x0FF) << 1;
484 unsigned short asicChannelFE = (word >> 8) & 0x07;
485 unsigned short asicFE = (word >> 12) & 0x03;
486 unsigned short carrierFE = (word >> 14) & 0x03;
487 unsigned short channelID = carrierFE * 32 + asicFE * 8 + asicChannelFE;
490 B2DEBUG(100, scrodID_FE <<
"\t" << carrierFE <<
"\t" << asicFE <<
"\t" << asicChannelFE <<
"\t" << evtNum_FEheader);
492 channelCounter[channelID] += 1;
494 std::vector<TOPRawDigit*> digits;
496 if (header != 0xaaaa0104) {
500 short samplePeak_p = word & 0xFFFF;
501 short valuePeak_p = (word >> 16) & 0xFFFF;
504 short sampleRise_p = word & 0xFFFF;
505 short valueRise0_p = (word >> 16) & 0xFFFF;
508 short valueRise1_p = word & 0xFFFF;
509 short sampleFall_p = (word >> 16) & 0xFFFF;
512 short valueFall0_p = word & 0xFFFF;
513 short valueFall1_p = (word >> 16) & 0xFFFF;
516 short integral_p = word & 0xFFFF;
524 short samplePeak_n = word & 0xFFFF;
525 short valuePeak_n = (word >> 16) & 0xFFFF;
543 short integral_n = word & 0xFFFF;
544 short qualityFlags_n = (word >> 16) & 0xFFFF;
546 if (abs(valuePeak_p) != 9999) {
547 auto* digit = m_rawDigits.appendNew(scrodID, TOPRawDigit::c_Interim);
548 digit->setCarrierNumber(carrierFE);
549 digit->setASICNumber(asicFE);
550 digit->setASICChannel(asicChannelFE);
551 digit->setASICWindow(convertedAddr);
552 digit->setLastWriteAddr(lastWrAddr);
553 digit->setSampleRise(sampleRise_p);
554 digit->setDeltaSamplePeak(samplePeak_p - sampleRise_p);
555 digit->setDeltaSampleFall(sampleFall_p - sampleRise_p);
556 digit->setValueRise0(valueRise0_p);
557 digit->setValueRise1(valueRise1_p);
558 digit->setValuePeak(valuePeak_p);
559 digit->setValueFall0(valueFall0_p);
560 digit->setValueFall1(valueFall1_p);
561 digit->setIntegral(integral_p);
563 digit->addRelationTo(info);
564 digits.push_back(digit);
566 if (valuePeak_p < 150) {
567 auto* tlpfResult = m_templateFitResults.appendNew();
568 tlpfResult->setBackgroundOffset(samplePeak_n);
569 tlpfResult->setAmplitude(valuePeak_n);
570 tlpfResult->setChisquare(qualityFlags_n);
571 tlpfResult->setRisingEdgeAndConvert(integral_n);
572 digit->addRelationTo(tlpfResult);
599 if (word != 0x7473616c) {
603 info->setErrorFlag(TOPInterimFEInfo::c_InvalidMagicWord);
609 info->incrementFEHeadersCount();
610 if (digits.empty()) info->incrementEmptyFEHeadersCount();
612 if (header != 0xaaaa0103)
continue;
616 unsigned long evtNum_numWaves_refWin_WFheader = word;
617 unsigned short evtNum_WFheader = (evtNum_numWaves_refWin_WFheader >> 24) & 0xFF;
619 if (evtNum_WFheader != evtNum_FEheader) {
620 B2ERROR(
"TOPUnpacker: different carrier event number in WF and FE header."
621 <<
LogVar(
"Event number (FE header)", evtNum_FEheader)
622 <<
LogVar(
"Event number (WF header)", evtNum_WFheader));
629 unsigned short carrier = (word >> 14) & 0x03;
630 unsigned short asic = (word >> 12) & 0x03;
632 unsigned short window = word & 0x1FF;
635 if (carrier != carrierFE) {
636 B2ERROR(
"TOPUnpacker: different carrier numbers in FE and WF header");
637 B2DEBUG(100,
"Different carrier numbers in FE and WF header: "
638 << carrierFE <<
" " << carrier);
639 info->setErrorFlag(TOPInterimFEInfo::c_DifferentCarriers);
641 if (asic != asicFE) {
642 B2ERROR(
"TOPUnpacker: different ASIC numbers in FE and WF header");
643 B2DEBUG(100,
"Different ASIC numbers in FE and WF header: "
644 << asicFE <<
" " << asic);
645 info->setErrorFlag(TOPInterimFEInfo::c_DifferentAsics);
648 B2ERROR(
"TOPUnpacker: different ASIC channel numbers in FE and WF header");
649 B2DEBUG(100,
"Different ASIC channel numbers in FE and WF header: "
651 info->setErrorFlag(TOPInterimFEInfo::c_DifferentChannels);
653 if (window != convertedAddr) {
654 B2ERROR(
"TOPUnpacker: different window numbers in FE and WF header");
655 B2DEBUG(100,
"Different window numbers in FE and WF header: "
656 << convertedAddr <<
" " << window);
657 info->setErrorFlag(TOPInterimFEInfo::c_DifferentWindows);
662 std::vector<unsigned short> windows;
663 windows.push_back(window);
666 windows.push_back(word & 0x1FF);
669 windows.push_back(word & 0x1FF);
672 windows.push_back(word & 0x1FF);
674 int numWords = 4 * 32;
676 B2ERROR(
"TOPUnpacker: too few words for waveform data."
677 <<
LogVar(
"needed", numWords)
679 info->setErrorFlag(TOPInterimFEInfo::c_InsufficientWFData);
684 std::vector<short> adcData;
685 for (
int i = 0; i < numWords; i++) {
687 adcData.push_back(word & 0xFFFF);
688 adcData.push_back((word >> 16) & 0xFFFF);
695 const auto* feemap = m_topgp->getFrontEndMapper().getMap(scrodID);
697 moduleID = feemap->getModuleID();
698 boardstack = feemap->getBoardstackNumber();
700 B2ERROR(
"TOPUnpacker: no front-end map available."
701 <<
LogVar(
"SCROD ID", scrodID));
702 info->setErrorFlag(TOPInterimFEInfo::c_InvalidScrodID);
706 const auto& mapper = m_topgp->getChannelMapper();
707 unsigned channel = mapper.getChannel(boardstack, carrier, asic,
asicChannel);
708 int pixelID = mapper.getPixelID(channel);
711 auto* waveform = m_waveforms.appendNew(moduleID, pixelID, channel, scrodID,
713 waveform->setLastWriteAddr(lastWrAddr);
714 waveform->setStorageWindows(windows);
715 waveform->setPedestalSubtractedFlag(pedestalSubtracted);
716 waveform->addRelationTo(info);
717 info->incrementWaveformsCount();
720 for (
auto& digit : digits) digit->addRelationTo(waveform);
724 if (evtNumCounter.size() != 1) {
725 B2ERROR(
"TOPUnpacker: Possible frame shift detected "
726 <<
"(More than one unique carrier event number in this readout event)."
727 <<
LogVar(
"SCROD", scrodID)
728 <<
LogVar(
"slot", moduleID)
729 <<
LogVar(
"BS", boardstack));
734 string evtNumOutputString;
735 evtNumOutputString +=
"Carrier event numbers and their counts for SCROD ID " + std::to_string(scrodID) +
":\n";
736 for (
auto const& it : evtNumCounter) {
738 evtNumOutputString += std::to_string(it.first) +
":\t" + std::to_string(it.second) +
"\n";
740 evtNumOutputString +=
"Total:\t" + std::to_string(nASICs);
741 B2DEBUG(100, evtNumOutputString);
744 int nChannelsDiff = 0;
746 string channelOutputString;
747 channelOutputString +=
"Detected channels and their counts for SCROD ID (channels with count == 1 are omitted)" + std::to_string(
751 for (
auto const& it : channelCounter) {
757 int channelID = channelIndex;
758 int carrier = channelID / 32;
759 int asic = (channelID % 32) / 8;
760 int chn = channelID % 8;
763 channelOutputString +=
"carrier: " + std::to_string(carrier) +
" asic: " + std::to_string(asic) +
" chn: " + std::to_string(
764 chn) +
" occurence: " + std::to_string(it) +
"\n";
765 B2WARNING(
"TOPUnpacker: interim FE - ASIC channel seen more than once"
766 <<
LogVar(
"ScrodID", scrodID)
767 <<
LogVar(
"carrier", carrier)
770 <<
LogVar(
"times seen", it));
775 m_channelStatistics[nChannels] += 1;
777 channelOutputString +=
"Total:\t" + std::to_string(nChannels) +
" " + std::to_string(nChannelsDiff);
778 B2DEBUG(100, channelOutputString);
786 int TOPUnpackerModule::unpackProdDebug(
const int* buffer,
int bufferSize, TOP::RawDataType dataFormat,
787 bool pedestalSubtracted)
790 B2DEBUG(200,
"Unpacking Production firmware debug data format to TOPRawDigits "
791 "dataSize = " << bufferSize);
793 DataArray array(buffer, bufferSize, m_swapBytes);
797 unsigned int evtType = word >> 24;
798 unsigned int evtVersion = (word >> 16) & 0xFF;
799 unsigned int evtMagicHeader = (word >> 12) & 0xF;
800 unsigned int evtScrodID = word & 0xFFF;
805 const auto* feemap = m_topgp->getFrontEndMapper().getMap(evtScrodID);
807 moduleID = feemap->getModuleID();
808 boardstack = feemap->getBoardstackNumber();
810 B2WARNING(
"TOPUnpacker: no front-end map available."
811 <<
LogVar(
"SCROD ID", evtScrodID));
815 B2DEBUG(200, std::dec << array.
getIndex() <<
":\t" << setfill(
'0') << setw(4) << std::hex <<
816 (word >> 16) <<
" " << setfill(
'0') << setw(4) << (word & 0xFFFF) << std::dec
817 <<
"\tevtType = " << evtType
818 <<
", evtVersion = " << evtVersion
819 <<
", evtMagicHeader = " << evtMagicHeader
820 <<
", evtScrodID = " << evtScrodID);
822 if (evtMagicHeader != 0xA) {
823 B2WARNING(
"TOPUnpacker: event header magic word mismatch. should be 0xA."
824 <<
LogVar(
"Magic word", evtMagicHeader));
829 unsigned int evtExtra = word >> 29;
830 unsigned int evtNumWordsBonus = (word >> 16) & 0x1FFF;
831 unsigned int evtPhase = (word >> 12) & 0xF;
832 unsigned int evtNumWordsCore = word & 0xFFF;
834 B2DEBUG(200, std::dec << array.
getIndex() <<
":\t" << setfill(
'0') << setw(4) << std::hex <<
835 (word >> 16) <<
" " << setfill(
'0') << setw(4) << (word & 0xFFFF) << std::dec
836 <<
"\tevtExtra = " << evtExtra
837 <<
", evtNumWordsBonus = " << evtNumWordsBonus
838 <<
", evtPhase = " << evtPhase
839 <<
", numWordsCore = " << evtNumWordsCore);
842 bool evtSkipHit = word >> 29;
843 unsigned int evtCtime = (word >> 16) & 0x7FF;
844 unsigned int evtRevo9Counter = word & 0xFFFF;
846 B2DEBUG(200, std::dec << array.
getIndex() <<
":\t" << setfill(
'0') << setw(4) << std::hex <<
847 (word >> 16) <<
" " << setfill(
'0') << setw(4) << (word & 0xFFFF) << std::dec
848 <<
"\tevtSkipHit = " << evtSkipHit
849 <<
", evtCtime = " << evtCtime
850 <<
", evtRevo9Counter = " << evtRevo9Counter);
853 unsigned int evtAsicMask = word >> 16;
854 unsigned int evtEventQueueDepth = (word >> 8) & 0xFF;
855 unsigned int evtEventNumberByte = word & 0xFF;
857 B2DEBUG(200, std::dec << array.
getIndex() <<
":\t" << setfill(
'0') << setw(4) << std::hex <<
858 (word >> 16) <<
" " << setfill(
'0') << setw(4) << (word & 0xFFFF) << std::dec
859 <<
"\tevtAsicMask = " << evtAsicMask
860 <<
", evtEventQueueDepth = " << evtEventQueueDepth
861 <<
", evtEventNumberByte = " << evtEventNumberByte);
863 m_productionEventDebugs.appendNew(evtType,
873 B2DEBUG(200,
"end of event header, start of hits:");
875 const int numWordsPerHit = 4 + evtExtra;
876 unsigned int numHitsFound = 0;
877 unsigned int numExpectedWaveforms = 0;
879 std::vector<TOPRawDigit*> digitsWithWaveform;
882 && array.
getIndex() < evtNumWordsCore - 2) {
887 unsigned int hitCarrier = 0;
888 unsigned int hitAsic = 0;
889 unsigned int hitChannel = 0;
890 unsigned int hitWindow = 0;
891 unsigned int hitMagicHeader = 0;
892 unsigned int hitTFine = 0;
893 bool hitHasWaveform =
false;
894 bool hitIsOnHeap =
false;
895 unsigned int hitHeapWindow = 0;
896 bool hitIsOnHeapStraddle =
false;
897 unsigned int hitHeapWindowStraddle = 0;
898 bool hitIsWindowStraddle =
false;
899 short hitIntegral = 0;
902 if (dataFormat == TOP::RawDataType::c_ProductionDebug01) {
904 hitCarrier = word >> 30;
905 hitAsic = (word >> 28) & 0x3;
906 hitChannel = (word >> 25) & 0x7;
907 hitWindow = (word >> 16) & 0x1FF;
908 hitMagicHeader = (word >> 12) & 0xF;
909 hitTFine = (word >> 8) & 0xF;
910 hitHasWaveform = (word >> 7) & 0x1;
911 hitIsOnHeap = (word >> 6) & 0x1;
912 hitHeapWindow = word & 0x3F;
915 B2DEBUG(200, std::dec << array.
getIndex() <<
":\t" << setfill(
'0') << setw(4) << std::hex <<
916 (word >> 16) <<
" " << setfill(
'0') << setw(4) << (word & 0xFFFF) << std::dec
917 <<
"\thitCarrier = " << hitCarrier
918 <<
", hitAsic = " << hitAsic
919 <<
", hitChannel = " << hitChannel
920 <<
", hitWindow = " << hitWindow
923 <<
", hitHasWaveform = " << hitHasWaveform
930 hitVPeak = expand13to16bits(word >> 16);
931 hitIntegral = word & 0xFFFF;
932 B2DEBUG(200, std::dec << array.
getIndex() <<
":\t" << setfill(
'0') << setw(4) << std::hex <<
933 (word >> 16) <<
" " << setfill(
'0') << setw(4) << (word & 0xFFFF) << std::dec
934 <<
"\thitVPeak = " << hitVPeak
935 <<
", hitIntegral = " << hitIntegral);
937 }
else if (dataFormat == TOP::RawDataType::c_ProductionDebug02) {
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 hitIsWindowStraddle = (word >> 6) & 0x1;
947 hitIntegral = word & 0x3F;
950 B2DEBUG(200, 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
958 <<
", hitHasWaveform = " << hitHasWaveform
959 <<
", hitIsWindowStraddle = " << hitHasWaveform
960 <<
", hitIntegral = " << hitIntegral
965 hitVPeak = expand13to16bits(word >> 16);
966 hitIsOnHeapStraddle = (word >> 15) & 0x1;
967 hitHeapWindowStraddle = (word >> 8) & 0x7F;
968 hitIsOnHeap = (word >> 7) & 0x1;
969 hitHeapWindow = word & 0x1;
971 B2DEBUG(200, std::dec << array.
getIndex() <<
":\t" << setfill(
'0') << setw(4) << std::hex <<
972 (word >> 16) <<
" " << setfill(
'0') << setw(4) << (word & 0xFFFF) << std::dec
973 <<
"\thitVPeak = " << hitVPeak
974 <<
", hitIsOnHeapStraddle = " << hitIsOnHeapStraddle
975 <<
", hitHeapWindowStraddle = " << hitHeapWindowStraddle
976 <<
", hitIsOnHeap = " << hitIsOnHeap
977 <<
", hitHeapWindow = " << hitHeapWindow);
979 B2WARNING(
"TOPUnpacker: could not match data type inside unpackProdDebug()"
980 <<
LogVar(
"evtType", evtType) <<
LogVar(
"evtVersion", evtVersion));
985 if (hitHasWaveform) {
986 numExpectedWaveforms += 1;
989 if (hitMagicHeader != 0xB) {
990 B2WARNING(
"TOPUnpacker: hit header magic word mismatch. should be 0xB."
991 <<
LogVar(
"Magic word", hitMagicHeader));
996 short hitVRise0 = expand13to16bits(word >> 16);
997 short hitVRise1 = expand13to16bits(word);
998 B2DEBUG(200, std::dec << array.
getIndex() <<
":\t" << setfill(
'0') << setw(4) << std::hex <<
999 (word >> 16) <<
" " << setfill(
'0') << setw(4) << (word & 0xFFFF) << std::dec
1000 <<
"\thitVRise0 = " << hitVRise0
1001 <<
", hitVRise1 = " << hitVRise1);
1004 short hitVFall0 = expand13to16bits(word >> 16);
1005 short hitVFall1 = expand13to16bits(word);
1006 B2DEBUG(200, std::dec << array.
getIndex() <<
":\t" << setfill(
'0') << setw(4) << std::hex <<
1007 (word >> 16) <<
" " << setfill(
'0') << setw(4) << (word & 0xFFFF) << std::dec
1008 <<
"\thitVFall0 = " << hitVFall0
1009 <<
", hitVFall1 = " << hitVFall1);
1012 unsigned short hitSampleRise = (word >> 24);
1013 short hitDSampPeak = (word >> 20) & 0xF;
1014 short hitDSampFall = (word >> 16) & 0xF;
1015 unsigned short hitHeaderChecksum = word & 0xFFFF;
1016 B2DEBUG(200, std::dec << array.
getIndex() <<
":\t" << setfill(
'0') << setw(4) << std::hex <<
1017 (word >> 16) <<
" " << setfill(
'0') << setw(4) << (word & 0xFFFF) << std::dec
1018 <<
"\thitSampleRise = " << hitSampleRise
1019 <<
", hitDSampPeak = " << hitDSampPeak
1020 <<
", hitDSampFall = " << hitDSampFall
1021 <<
", hitheaderChecksum = " << hitHeaderChecksum
1025 B2WARNING(
"TOPUnpacker: hit checksum invalid.");
1030 auto* digit = m_rawDigits.appendNew(evtScrodID, TOPRawDigit::c_ProductionDebug);
1031 digit->setCarrierNumber(hitCarrier);
1032 digit->setASICNumber(hitAsic);
1033 digit->setASICChannel(hitChannel);
1034 digit->setASICWindow(hitWindow);
1035 digit->setLastWriteAddr(0);
1036 digit->setSampleRise(hitSampleRise);
1037 digit->setDeltaSamplePeak(hitDSampPeak);
1038 digit->setDeltaSampleFall(hitDSampFall);
1039 digit->setValueRise0(hitVRise0);
1040 digit->setValueRise1(hitVRise1);
1041 digit->setValuePeak(hitVPeak);
1042 digit->setValueFall0(hitVFall0);
1043 digit->setValueFall1(hitVFall1);
1044 digit->setTFine(hitTFine);
1045 digit->setIntegral(hitIntegral);
1046 digit->setRevo9Counter(evtRevo9Counter);
1047 digit->setPhase(evtPhase);
1050 if (hitHasWaveform) {
1051 digitsWithWaveform.push_back(digit);
1055 if (dataFormat == TOP::RawDataType::c_ProductionDebug01) {
1056 hitDebug = m_productionHitDebugs.appendNew(hitHasWaveform,
1059 hitIsOnHeap ? 428 + hitHeapWindow : hitWindow,
1060 hitIsWindowStraddle);
1061 }
else if (dataFormat == TOP::RawDataType::c_ProductionDebug02) {
1062 hitDebug = m_productionHitDebugs.appendNew(hitHasWaveform,
1065 hitIsOnHeap ? 428 + hitHeapWindow : hitWindow,
1066 hitIsWindowStraddle,
1068 hitIsOnHeapStraddle ? 428 + hitHeapWindowStraddle : hitWindow +
1073 for (
unsigned int i = 0; i < evtExtra; ++i) {
1075 B2DEBUG(200, std::dec << array.
getIndex() <<
":\t" << setfill(
'0') << setw(4) << std::hex <<
1076 (word >> 16) <<
" " << setfill(
'0') << setw(4) << (word & 0xFFFF) << std::dec
1077 <<
"\thit extra word " << i <<
" (" << evtExtra <<
")");
1082 digit->addRelationTo(hitDebug);
1089 unsigned int evtSdType = (word >> 24);
1090 unsigned int evtSdData = (word >> 12) & 0xFFF;
1091 unsigned int evtMagicFooter = (word >> 9) & 0x7;
1092 unsigned int evtNHits = word & 0x1FF;
1093 B2DEBUG(200, std::dec << array.
getIndex() <<
":\t" << setfill(
'0') << setw(4) << std::hex <<
1094 (word >> 16) <<
" " << setfill(
'0') << setw(4) << (word & 0xFFFF) << std::dec
1095 <<
"\tevtSdType = " << evtSdType
1096 <<
", evtSdData = " << evtSdData
1097 <<
", evtMagicFooter = " << evtMagicFooter
1098 <<
", evtNHits = " << evtNHits <<
" (" << numHitsFound <<
")");
1100 if (evtSdType != 0) {
1101 m_slowData.appendNew(evtScrodID, evtSdType, evtSdData);
1104 if (evtMagicFooter != 0x5) {
1105 B2WARNING(
"TOPUnpacker: event footer magic word mismatch. should be 0x5."
1106 <<
LogVar(
"Magic word", evtMagicFooter));
1110 B2DEBUG(200,
"the rest:");
1112 unsigned int numParsedWaveforms = 0;
1113 while (array.
peekWord() != 0x6c617374
1117 unsigned int wfNSamples = (word >> 16);
1118 unsigned int wfNWindows = (word >> 8) & 0x7;
1119 unsigned int wfCarrier = (word >> 5) & 0x3;
1120 unsigned int wfAsic = (word >> 3) & 0x3;
1121 unsigned int wfChannel = word & 0x7;
1124 const auto& mapper = m_topgp->getChannelMapper();
1125 unsigned channel = mapper.getChannel(boardstack, wfCarrier, wfAsic, wfChannel);
1126 int pixelID = mapper.getPixelID(channel);
1128 B2DEBUG(200, std::dec << array.
getIndex() <<
":\t" << setfill(
'0') << setw(4) << std::hex <<
1129 (word >> 16) <<
" " << setfill(
'0') << setw(4) << (word & 0xFFFF) << std::dec
1130 <<
"\twfNSamples = " << wfNSamples
1131 <<
", wfNWindows = " << wfNWindows
1132 <<
", wfCarrier = " << wfCarrier
1133 <<
", wfAsic = " << wfAsic
1134 <<
", wfChannel " << wfChannel);
1136 if (wfNSamples != 32 && wfNSamples != 16) {
1137 B2WARNING(
"TOPUnpacker: suspicious value for wfNSamples."
1138 <<
LogVar(
"wfNSamples", wfNSamples));
1143 unsigned int wfStartSample = (word >> 25) & 0x3F;
1144 unsigned int wfWindowLogic = (word >> 16) & 0x1FF;
1145 unsigned int wfEventNumber = (word >> 9) & 0x7F;
1146 unsigned int wfWindowPhysical = word & 0x1FF;
1148 B2DEBUG(200, std::dec << array.
getIndex() <<
":\t" << setfill(
'0') << setw(4) << std::hex <<
1149 (word >> 16) <<
" " << setfill(
'0') << setw(4) << (word & 0xFFFF) << std::dec
1150 <<
"\twfStartSample = " << wfStartSample
1151 <<
", wfWindowLogic = " << wfWindowLogic
1152 <<
", wfEventNumber = " << wfEventNumber
1153 <<
", wfWindowPhysical = " << wfWindowPhysical);
1155 std::vector<short> wfSamples;
1157 for (
unsigned int i = 0; i < wfNSamples / 2; ++i) {
1158 short wfSampleLast = 0;
1159 short wfSampleFirst = 0;
1163 if (pedestalSubtracted) {
1164 wfSampleLast = (word >> 16);
1165 wfSampleFirst = word & 0xFFFF;
1167 wfSampleLast = (word >> 16) & 0xFFF;
1168 wfSampleFirst = word & 0xFFF;
1172 B2DEBUG(200, std::dec << array.
getIndex() <<
":\t" << setfill(
'0') << setw(4) << std::hex <<
1173 (word >> 16) <<
" " << setfill(
'0') << setw(4) << (word & 0xFFFF) << std::dec
1174 <<
"\twfSample" << 2 * i + 1 <<
" = " << wfSampleLast
1175 <<
", wfSample" << 2 * i <<
" = " << wfSampleFirst);
1177 wfSamples.push_back(wfSampleFirst);
1178 wfSamples.push_back(wfSampleLast);
1182 auto* waveform = m_waveforms.appendNew(moduleID, pixelID, channel, evtScrodID,
1183 wfWindowLogic, wfStartSample, wfSamples);
1184 waveform->setPedestalSubtractedFlag(pedestalSubtracted);
1185 waveform->setPhysicalWindow(wfWindowPhysical);
1186 if (numParsedWaveforms < digitsWithWaveform.size()) {
1187 const auto* digit = digitsWithWaveform[numParsedWaveforms];
1188 if (digit->getScrodChannel() == channel % 128) {
1189 digit->addRelationTo(waveform);
1191 B2WARNING(
"TOPUnpacker: hit and its waveform have different channel number."
1192 <<
LogVar(
"channel (hit)", digit->getScrodChannel())
1193 <<
LogVar(
"channel (waveform)", channel % 128));
1196 numParsedWaveforms += 1;
1200 if (numExpectedWaveforms != numParsedWaveforms) {
1201 B2WARNING(
"TOPUnpacker: number of expected and parsed waveforms does not match."
1202 <<
LogVar(
"expected", numExpectedWaveforms)
1203 <<
LogVar(
"parsed", numParsedWaveforms));
1210 void TOPUnpackerModule::endRun()
1212 B2INFO(
"TOPUnpacker: Channels seen per event statistics:");
1213 B2INFO(
"TOPUnpacker: nChn\tcount");
1214 for (
auto& entry : m_channelStatistics) {
1215 B2INFO(
"TOPUnpacker: " << entry.first <<
"\t\t" << entry.second);
1219 void TOPUnpackerModule::terminate()