10 #include <top/modules/TOPUnpacker/TOPUnpackerModule.h>
11 #include <top/RawDataTypes.h>
14 #include <framework/datastore/DataStore.h>
15 #include <framework/datastore/StoreArray.h>
16 #include <framework/datastore/StoreObjPtr.h>
19 #include <framework/logging/Logger.h>
22 #include <framework/dataobjects/EventMetaData.h>
52 setDescription(
"Raw data unpacker for TOP");
53 setPropertyFlags(c_ParallelProcessingCertified);
56 addParam(
"inputRawDataName", m_inputRawDataName,
57 "name of RawTOP store array",
string(
""));
58 addParam(
"outputDigitsName", m_outputDigitsName,
59 "name of TOPDigit store array",
string(
""));
60 addParam(
"outputWaveformsName", m_outputWaveformsName,
61 "name of TOP(Raw/Production)Waveform store array",
string(
""));
62 addParam(
"outputRawDigitsName", m_outputRawDigitsName,
63 "name of TOPRawDigit store array",
string(
""));
64 addParam(
"outputTemplateFitResultName", m_templateFitResultName,
65 "name of TOPTemplateFitResult",
string(
""));
66 addParam(
"swapBytes", m_swapBytes,
"if true, swap bytes",
false);
67 addParam(
"dataFormat", m_dataFormat,
68 "data format as defined in top/include/RawDataTypes.h, 0 = auto detect", 0);
69 addParam(
"addRelations", m_addRelations,
70 "if true, make relations to TOPProductionHitDebugs (production debug data format only)",
true);
73 TOPUnpackerModule::~TOPUnpackerModule()
77 void TOPUnpackerModule::initialize()
82 m_rawData.isRequired(m_inputRawDataName);
86 m_digits.registerInDataStore(m_outputDigitsName);
87 m_rawDigits.registerInDataStore(m_outputRawDigitsName);
88 m_slowData.registerInDataStore();
89 m_interimFEInfos.registerInDataStore(DataStore::c_DontWriteOut);
90 m_waveforms.registerInDataStore(m_outputWaveformsName, DataStore::c_DontWriteOut);
91 m_productionEventDebugs.registerInDataStore(DataStore::c_DontWriteOut);
92 m_productionHitDebugs.registerInDataStore(DataStore::c_DontWriteOut);
93 m_templateFitResults.registerInDataStore(m_templateFitResultName, DataStore::c_DontWriteOut);
95 m_rawDigits.registerRelationTo(m_waveforms, DataStore::c_Event, DataStore::c_DontWriteOut);
96 m_rawDigits.registerRelationTo(m_templateFitResults, DataStore::c_Event, DataStore::c_DontWriteOut);
97 m_rawDigits.registerRelationTo(m_interimFEInfos, DataStore::c_Event, DataStore::c_DontWriteOut);
98 m_rawDigits.registerRelationTo(m_productionHitDebugs, DataStore::c_Event, DataStore::c_DontWriteOut);
99 m_waveforms.registerRelationTo(m_interimFEInfos, DataStore::c_Event, DataStore::c_DontWriteOut);
102 const auto& mapper = m_topgp->getFrontEndMapper();
103 int mapSize = mapper.getMapSize();
104 if (mapSize == 0) B2ERROR(
"TOPUnpacker: No front-end mapping available for TOP");
108 void TOPUnpackerModule::beginRun()
110 m_channelStatistics.clear();
113 void TOPUnpackerModule::event()
119 m_productionEventDebugs.clear();
120 m_productionHitDebugs.clear();
121 m_templateFitResults.clear();
123 m_interimFEInfos.clear();
126 for (
auto& raw : m_rawData) {
127 for (
int finesse = 0; finesse < raw.GetMaxNumOfCh(0); finesse++) {
128 const int* buffer = raw.GetDetectorBuffer(0, finesse);
129 int bufferSize = raw.GetDetectorNwords(0, finesse);
130 if (bufferSize < 1)
continue;
134 int dataFormat = m_dataFormat;
135 if (dataFormat == 0) {
136 DataArray array(buffer, bufferSize, m_swapBytes);
137 unsigned word = array.
getWord();
138 dataFormat = (word >> 16);
139 bool isKnownDataFormat =
false;
140 for (
auto& t : TOP::membersRawDataType) {
141 if (
static_cast<int>(t) == dataFormat) {
142 isKnownDataFormat =
true;
147 if (!isKnownDataFormat) {
148 if (evtMetaData->getExperiment() == 1) {
152 if (unpackHeadersInterimFEVer01(buffer, bufferSize,
true)) {
153 B2DEBUG(22,
"Assuming interim FW data format");
157 B2WARNING(
"TOPUnpacker: Could not establish data format.");
164 switch (dataFormat) {
165 case static_cast<int>(TOP::RawDataType::c_Type0Ver16):
166 unpackType0Ver16(buffer, bufferSize);
168 case static_cast<int>(TOP::RawDataType::c_Type2Ver1):
169 err = unpackInterimFEVer01(buffer, bufferSize,
false);
171 case static_cast<int>(TOP::RawDataType::c_Type3Ver1):
172 err = unpackInterimFEVer01(buffer, bufferSize,
true);
174 case static_cast<int>(TOP::RawDataType::c_Draft):
175 unpackProductionDraft(buffer, bufferSize);
177 case static_cast<int>(TOP::RawDataType::c_ProductionDebug01):
178 err = unpackProdDebug(buffer, bufferSize, TOP::RawDataType::c_ProductionDebug01,
true);
180 case static_cast<int>(TOP::RawDataType::c_ProductionDebug02):
181 err = unpackProdDebug(buffer, bufferSize, TOP::RawDataType::c_ProductionDebug02,
true);
185 B2ERROR(
"TOPUnpacker: unknown data format."
186 <<
LogVar(
"Type", (dataFormat >> 8))
187 <<
LogVar(
"Version", (dataFormat & 0xFF)));
194 if (raw.GetMaxNumOfCh(0) <= 4) {
195 stringstream copperName;
197 copperName <<
"cpr" << ((raw.GetNodeID(0) >> 24) * 1000 + (raw.GetNodeID(0) & 0x3FF)) << char(
'a' + finesse);
198 B2ERROR(
"TOPUnpacker: error in unpacking data from frontend " << copperName.str()
199 <<
LogVar(
"words unused", err)
200 <<
LogVar(
"copper", copperName.str()));
202 int slot = (raw.GetNodeID(0) & 0xF) * 8 - 7 + finesse / 4;
203 std::string name = (slot < 10) ?
"s0" :
"s";
204 name += std::to_string(slot) + char(
'a' + finesse % 4);
205 B2ERROR(
"TOPUnpacker: error in unpacking data from boardstack " << name <<
" "
206 <<
LogVar(
"words unused", err));
216 void TOPUnpackerModule::unpackProductionDraft(
const int* buffer,
int bufferSize)
219 B2DEBUG(22,
"Unpacking ProductionDraft to TOPDigits, dataSize = " << bufferSize);
221 unsigned short scrodID = buffer[0] & 0xFFFF;
222 const auto* feemap = m_topgp->getFrontEndMapper().getMap(scrodID);
224 B2ERROR(
"TOPUnpacker: no front-end map available."
225 <<
LogVar(
"SCROD ID", scrodID));
228 int moduleID = feemap->getModuleID();
229 int boardstack = feemap->getBoardstackNumber();
230 const auto& mapper = m_topgp->getChannelMapper();
232 const auto* geo = m_topgp->getGeometry();
233 auto subBits = geo->getNominalTDC().getSubBits();
234 int sampleDivisions = 0x1 << subBits;
236 for (
int i = 1; i < bufferSize; i++) {
237 int word = buffer[i];
238 int tdc = word & 0xFFFF;
239 double rawTime = double(tdc) / sampleDivisions;
240 unsigned chan = ((word >> 16) & 0x7F) + boardstack * 128;
241 unsigned flags = (word >> 24) & 0xFF;
242 int pixelID = mapper.getPixelID(chan);
243 auto* digit = m_digits.appendNew(moduleID, pixelID, rawTime);
244 digit->setTime(geo->getNominalTDC().getTime(tdc));
245 digit->setChannel(chan);
252 void TOPUnpackerModule::unpackType0Ver16(
const int* buffer,
int bufferSize)
255 B2DEBUG(22,
"Unpacking Type0Ver16 to TOPRawDigits, dataSize = " << bufferSize);
257 DataArray array(buffer, bufferSize, m_swapBytes);
258 unsigned word = array.
getWord();
259 unsigned short scrodID = word & 0x0FFF;
262 int Nhits = last & 0x01FF;
263 if (bufferSize != 5 * Nhits + 2) {
264 B2ERROR(
"TOPUnpacker: corrupted data (feature-extraction format)."
265 <<
LogVar(
"SCROD ID", scrodID));
269 short SDType = last >> 24;
270 short SDValue = (last >> 12) & 0x0FFF;
271 if (SDType != 0) m_slowData.appendNew(scrodID, SDType, SDValue);
273 unsigned short errorFlags = 0;
274 if (((word >> 12) & 0x0F) != 0x0A) errorFlags |= TOPRawDigit::c_HeadMagic;
275 if (((last >> 9) & 0x07) != 0x05) errorFlags |= TOPRawDigit::c_TailMagic;
277 for (
int hit = 0; hit < Nhits; hit++) {
278 auto* digit = m_rawDigits.appendNew(scrodID, TOPRawDigit::c_Production);
281 digit->setCarrierNumber((word >> 30) & 0x03);
282 digit->setASICNumber((word >> 28) & 0x03);
283 digit->setASICChannel((word >> 25) & 0x07);
284 digit->setASICWindow((word >> 16) & 0x1FF);
285 digit->setTFine((word >> 8) & 0x0F);
286 auto flags = errorFlags;
287 if (((word >> 12) & 0x0F) != 0x0B) flags |= TOPRawDigit::c_HitMagic;
288 unsigned short checkSum = sumShorts(word);
291 digit->setValuePeak(expand13to16bits(word >> 16));
292 digit->setIntegral(word & 0xFFFF);
293 checkSum += sumShorts(word);
296 digit->setValueRise0(expand13to16bits(word >> 16));
297 digit->setValueRise1(expand13to16bits(word));
298 checkSum += sumShorts(word);
301 digit->setValueFall0(expand13to16bits(word >> 16));
302 digit->setValueFall1(expand13to16bits(word));
303 checkSum += sumShorts(word);
306 digit->setSampleRise(word >> 24);
307 digit->setDeltaSamplePeak((word >> 20) & 0x0F);
308 digit->setDeltaSampleFall((word >> 16) & 0x0F);
309 checkSum += sumShorts(word);
310 if (checkSum != 0) flags |= TOPRawDigit::c_HitChecksum;
312 digit->setErrorFlags(flags);
318 bool TOPUnpackerModule::unpackHeadersInterimFEVer01(
const int* buffer,
int bufferSize,
bool swapBytes)
320 B2DEBUG(22,
"Checking whether buffer unpacks as InterimFEVer01, dataSize = " << bufferSize);
322 DataArray array(buffer, bufferSize, swapBytes);
327 unsigned header = array.
getWord();
328 if ((header & 0xFF) == 0xBE) {
332 if (header != 0xaaaa0104 and header != 0xaaaa0103 and header != 0xaaaa0100) {
340 if (header != 0xaaaa0104) {
356 unsigned magicWord = array.
getWord();
357 if (magicWord != 0x7473616c) {
361 if (header != 0xaaaa0103)
continue;
374 int numWords = 4 * 32;
379 for (
int i = 0; i < numWords; i++) {
388 int TOPUnpackerModule::unpackInterimFEVer01(
const int* buffer,
int bufferSize,
389 bool pedestalSubtracted)
392 B2DEBUG(22,
"Unpacking InterimFEVer01 to TOPRawDigits and TOPRawWaveforms, "
393 "dataSize = " << bufferSize);
398 DataArray array(buffer, bufferSize, m_swapBytes);
400 map<unsigned short, int> evtNumCounter;
401 std::vector<unsigned short> channelCounter(128, 0);
403 unsigned word = array.
getWord();
404 unsigned short scrodID = word & 0x0FFF;
405 auto* info = m_interimFEInfos.appendNew(scrodID, bufferSize);
412 unsigned header = array.
getWord();
414 if ((header & 0xFF) == 0xBE) {
417 unsigned short scrodID_SSFE;
418 unsigned short carrier_SSFE;
419 unsigned short asic_SSFE;
420 unsigned short channel_SSFE;
421 unsigned short evtNum_SSFE;
423 evtNum_SSFE = (header >> 8) & 0xFF;
424 scrodID_SSFE = (header >> 16) & 0x7F;
425 channel_SSFE = (header >> 24) & 0x07;
426 asic_SSFE = (header >> 27) & 0x03;
427 carrier_SSFE = (header >> 29) & 0x03;
429 const auto* feemap = m_topgp->getFrontEndMapper().getMap(scrodID_SSFE);
431 moduleID = feemap->getModuleID();
432 boardstack = feemap->getBoardstackNumber();
434 B2ERROR(
"TOPUnpacker: no front-end map available."
435 <<
LogVar(
"SCROD ID", scrodID_SSFE));
436 info->setErrorFlag(TOPInterimFEInfo::c_InvalidScrodID);
439 if (scrodID_SSFE != scrodID) {
440 B2ERROR(
"TOPUnpacker: corrupted data - "
441 <<
"different scrodID's in HLSB and super short FE header."
442 <<
LogVar(
"SCROD", scrodID_SSFE)
443 <<
LogVar(
"slot", moduleID)
444 <<
LogVar(
"BS", boardstack));
445 B2DEBUG(21,
"Different scrodID's in HLSB and FE header: " << scrodID <<
" " << scrodID_SSFE <<
" word = 0x" << std::hex << word);
446 info->setErrorFlag(TOPInterimFEInfo::c_DifferentScrodIDs);
450 B2DEBUG(21, scrodID_SSFE <<
"\t" << carrier_SSFE <<
"\t" << asic_SSFE <<
"\t" << channel_SSFE <<
"\t" << evtNum_SSFE);
452 int channelID = carrier_SSFE * 32 + asic_SSFE * 8 + channel_SSFE;
453 channelCounter[channelID] += 1;
454 evtNumCounter[evtNum_SSFE] += 1;
456 info->incrementFEHeadersCount();
457 info->incrementEmptyFEHeadersCount();
462 if (header != 0xaaaa0104 and header != 0xaaaa0103 and header != 0xaaaa0100) {
463 B2ERROR(
"TOPUnpacker: corrupted data - invalid FE header word");
464 B2DEBUG(21,
"Invalid FE header word: " << std::hex << header <<
" 0b" << std::bitset<32>(header));
465 B2DEBUG(21,
"SCROD ID: " << scrodID <<
" " << std::hex << scrodID);
467 info->setErrorFlag(TOPInterimFEInfo::c_InvalidFEHeader);
473 unsigned short scrodID_FE = word >> 25;
474 unsigned short convertedAddr = (word >> 16) & 0x1FF;
475 unsigned short evtNum_numWin_trigPat_FEheader = word & 0xFFFF;
476 unsigned short evtNum_FEheader = evtNum_numWin_trigPat_FEheader & 0xFF;
477 evtNumCounter[evtNum_FEheader] += 1;
479 if (scrodID_FE != scrodID) {
480 B2ERROR(
"TOPUnpacker: different scrodID's in HLSB and FE header."
481 <<
LogVar(
"scrodID (HSLB)", scrodID)
482 <<
LogVar(
"scrodID (FE)", scrodID_FE));
484 info->setErrorFlag(TOPInterimFEInfo::c_DifferentScrodIDs);
490 unsigned lastWrAddr = (word & 0x0FF) << 1;
492 unsigned short asicChannelFE = (word >> 8) & 0x07;
493 unsigned short asicFE = (word >> 12) & 0x03;
494 unsigned short carrierFE = (word >> 14) & 0x03;
495 unsigned short channelID = carrierFE * 32 + asicFE * 8 + asicChannelFE;
498 B2DEBUG(21, scrodID_FE <<
"\t" << carrierFE <<
"\t" << asicFE <<
"\t" << asicChannelFE <<
"\t" << evtNum_FEheader);
500 channelCounter[channelID] += 1;
502 std::vector<TOPRawDigit*> digits;
504 if (header != 0xaaaa0104) {
508 short samplePeak_p = word & 0xFFFF;
509 short valuePeak_p = (word >> 16) & 0xFFFF;
512 short sampleRise_p = word & 0xFFFF;
513 short valueRise0_p = (word >> 16) & 0xFFFF;
516 short valueRise1_p = word & 0xFFFF;
517 short sampleFall_p = (word >> 16) & 0xFFFF;
520 short valueFall0_p = word & 0xFFFF;
521 short valueFall1_p = (word >> 16) & 0xFFFF;
524 short integral_p = word & 0xFFFF;
532 short samplePeak_n = word & 0xFFFF;
533 short valuePeak_n = (word >> 16) & 0xFFFF;
551 short integral_n = word & 0xFFFF;
552 short qualityFlags_n = (word >> 16) & 0xFFFF;
554 if (abs(valuePeak_p) != 9999) {
555 auto* digit = m_rawDigits.appendNew(scrodID, TOPRawDigit::c_Interim);
556 digit->setCarrierNumber(carrierFE);
557 digit->setASICNumber(asicFE);
558 digit->setASICChannel(asicChannelFE);
559 digit->setASICWindow(convertedAddr);
560 digit->setLastWriteAddr(lastWrAddr);
561 digit->setSampleRise(sampleRise_p);
562 digit->setDeltaSamplePeak(samplePeak_p - sampleRise_p);
563 digit->setDeltaSampleFall(sampleFall_p - sampleRise_p);
564 digit->setValueRise0(valueRise0_p);
565 digit->setValueRise1(valueRise1_p);
566 digit->setValuePeak(valuePeak_p);
567 digit->setValueFall0(valueFall0_p);
568 digit->setValueFall1(valueFall1_p);
569 digit->setIntegral(integral_p);
571 digit->addRelationTo(info);
572 digits.push_back(digit);
574 if (valuePeak_p < 150) {
575 auto* tlpfResult = m_templateFitResults.appendNew();
576 tlpfResult->setBackgroundOffset(samplePeak_n);
577 tlpfResult->setAmplitude(valuePeak_n);
578 tlpfResult->setChisquare(qualityFlags_n);
579 tlpfResult->setRisingEdgeAndConvert(integral_n);
580 digit->addRelationTo(tlpfResult);
607 if (word != 0x7473616c) {
611 info->setErrorFlag(TOPInterimFEInfo::c_InvalidMagicWord);
617 info->incrementFEHeadersCount();
618 if (digits.empty()) info->incrementEmptyFEHeadersCount();
620 if (header != 0xaaaa0103)
continue;
624 unsigned long evtNum_numWaves_refWin_WFheader = word;
625 unsigned short evtNum_WFheader = (evtNum_numWaves_refWin_WFheader >> 24) & 0xFF;
627 if (evtNum_WFheader != evtNum_FEheader) {
628 B2ERROR(
"TOPUnpacker: different carrier event number in WF and FE header."
629 <<
LogVar(
"Event number (FE header)", evtNum_FEheader)
630 <<
LogVar(
"Event number (WF header)", evtNum_WFheader));
637 unsigned short carrier = (word >> 14) & 0x03;
638 unsigned short asic = (word >> 12) & 0x03;
640 unsigned short window = word & 0x1FF;
643 if (carrier != carrierFE) {
644 B2ERROR(
"TOPUnpacker: different carrier numbers in FE and WF header");
645 B2DEBUG(21,
"Different carrier numbers in FE and WF header: "
646 << carrierFE <<
" " << carrier);
647 info->setErrorFlag(TOPInterimFEInfo::c_DifferentCarriers);
649 if (asic != asicFE) {
650 B2ERROR(
"TOPUnpacker: different ASIC numbers in FE and WF header");
651 B2DEBUG(21,
"Different ASIC numbers in FE and WF header: "
652 << asicFE <<
" " << asic);
653 info->setErrorFlag(TOPInterimFEInfo::c_DifferentAsics);
656 B2ERROR(
"TOPUnpacker: different ASIC channel numbers in FE and WF header");
657 B2DEBUG(21,
"Different ASIC channel numbers in FE and WF header: "
659 info->setErrorFlag(TOPInterimFEInfo::c_DifferentChannels);
661 if (window != convertedAddr) {
662 B2ERROR(
"TOPUnpacker: different window numbers in FE and WF header");
663 B2DEBUG(21,
"Different window numbers in FE and WF header: "
664 << convertedAddr <<
" " << window);
665 info->setErrorFlag(TOPInterimFEInfo::c_DifferentWindows);
670 std::vector<unsigned short> windows;
671 windows.push_back(window);
674 windows.push_back(word & 0x1FF);
677 windows.push_back(word & 0x1FF);
680 windows.push_back(word & 0x1FF);
682 int numWords = 4 * 32;
684 B2ERROR(
"TOPUnpacker: too few words for waveform data."
685 <<
LogVar(
"needed", numWords)
687 info->setErrorFlag(TOPInterimFEInfo::c_InsufficientWFData);
692 std::vector<short> adcData;
693 for (
int i = 0; i < numWords; i++) {
695 adcData.push_back(word & 0xFFFF);
696 adcData.push_back((word >> 16) & 0xFFFF);
703 const auto* feemap = m_topgp->getFrontEndMapper().getMap(scrodID);
705 moduleID = feemap->getModuleID();
706 boardstack = feemap->getBoardstackNumber();
708 B2ERROR(
"TOPUnpacker: no front-end map available."
709 <<
LogVar(
"SCROD ID", scrodID));
710 info->setErrorFlag(TOPInterimFEInfo::c_InvalidScrodID);
714 const auto& mapper = m_topgp->getChannelMapper();
715 unsigned channel = mapper.getChannel(boardstack, carrier, asic,
asicChannel);
716 int pixelID = mapper.getPixelID(channel);
719 auto* waveform = m_waveforms.appendNew(moduleID, pixelID, channel, scrodID,
721 waveform->setLastWriteAddr(lastWrAddr);
722 waveform->setStorageWindows(windows);
723 waveform->setPedestalSubtractedFlag(pedestalSubtracted);
724 waveform->addRelationTo(info);
725 info->incrementWaveformsCount();
728 for (
auto& digit : digits) digit->addRelationTo(waveform);
732 if (evtNumCounter.size() != 1) {
733 B2ERROR(
"TOPUnpacker: Possible frame shift detected "
734 <<
"(More than one unique carrier event number in this readout event)."
735 <<
LogVar(
"SCROD", scrodID)
736 <<
LogVar(
"slot", moduleID)
737 <<
LogVar(
"BS", boardstack));
742 string evtNumOutputString;
743 evtNumOutputString +=
"Carrier event numbers and their counts for SCROD ID " + std::to_string(scrodID) +
":\n";
744 for (
auto const& it : evtNumCounter) {
746 evtNumOutputString += std::to_string(it.first) +
":\t" + std::to_string(it.second) +
"\n";
748 evtNumOutputString +=
"Total:\t" + std::to_string(nASICs);
749 B2DEBUG(21, evtNumOutputString);
752 int nChannelsDiff = 0;
754 string channelOutputString;
755 channelOutputString +=
"Detected channels and their counts for SCROD ID (channels with count == 1 are omitted)" + std::to_string(
759 for (
auto const& it : channelCounter) {
765 int channelID = channelIndex;
766 int carrier = channelID / 32;
767 int asic = (channelID % 32) / 8;
768 int chn = channelID % 8;
771 channelOutputString +=
"carrier: " + std::to_string(carrier) +
" asic: " + std::to_string(asic) +
" chn: " + std::to_string(
772 chn) +
" occurence: " + std::to_string(it) +
"\n";
773 B2WARNING(
"TOPUnpacker: interim FE - ASIC channel seen more than once"
774 <<
LogVar(
"ScrodID", scrodID)
775 <<
LogVar(
"carrier", carrier)
778 <<
LogVar(
"times seen", it));
783 m_channelStatistics[nChannels] += 1;
785 channelOutputString +=
"Total:\t" + std::to_string(nChannels) +
" " + std::to_string(nChannelsDiff);
786 B2DEBUG(21, channelOutputString);
794 int TOPUnpackerModule::unpackProdDebug(
const int* buffer,
int bufferSize, TOP::RawDataType dataFormat,
795 bool pedestalSubtracted)
798 B2DEBUG(22,
"Unpacking Production firmware debug data format to TOPRawDigits "
799 "dataSize = " << bufferSize);
801 DataArray array(buffer, bufferSize, m_swapBytes);
805 unsigned int evtType = word >> 24;
806 unsigned int evtVersion = (word >> 16) & 0xFF;
807 unsigned int evtMagicHeader = (word >> 12) & 0xF;
808 unsigned int evtScrodID = word & 0xFFF;
813 const auto* feemap = m_topgp->getFrontEndMapper().getMap(evtScrodID);
815 moduleID = feemap->getModuleID();
816 boardstack = feemap->getBoardstackNumber();
818 B2WARNING(
"TOPUnpacker: no front-end map available."
819 <<
LogVar(
"SCROD ID", evtScrodID));
823 B2DEBUG(22, std::dec << array.
getIndex() <<
":\t" << setfill(
'0') << setw(4) << std::hex <<
824 (word >> 16) <<
" " << setfill(
'0') << setw(4) << (word & 0xFFFF) << std::dec
825 <<
"\tevtType = " << evtType
826 <<
", evtVersion = " << evtVersion
827 <<
", evtMagicHeader = " << evtMagicHeader
828 <<
", evtScrodID = " << evtScrodID);
830 if (evtMagicHeader != 0xA) {
831 B2WARNING(
"TOPUnpacker: event header magic word mismatch. should be 0xA."
832 <<
LogVar(
"Magic word", evtMagicHeader));
837 unsigned int evtExtra = word >> 29;
838 unsigned int evtNumWordsBonus = (word >> 16) & 0x1FFF;
839 unsigned int evtPhase = (word >> 12) & 0xF;
840 unsigned int evtNumWordsCore = word & 0xFFF;
842 B2DEBUG(22, std::dec << array.
getIndex() <<
":\t" << setfill(
'0') << setw(4) << std::hex <<
843 (word >> 16) <<
" " << setfill(
'0') << setw(4) << (word & 0xFFFF) << std::dec
844 <<
"\tevtExtra = " << evtExtra
845 <<
", evtNumWordsBonus = " << evtNumWordsBonus
846 <<
", evtPhase = " << evtPhase
847 <<
", numWordsCore = " << evtNumWordsCore);
850 bool evtSkipHit = word >> 29;
851 unsigned int evtCtime = (word >> 16) & 0x7FF;
852 unsigned int evtRevo9Counter = word & 0xFFFF;
854 B2DEBUG(22, std::dec << array.
getIndex() <<
":\t" << setfill(
'0') << setw(4) << std::hex <<
855 (word >> 16) <<
" " << setfill(
'0') << setw(4) << (word & 0xFFFF) << std::dec
856 <<
"\tevtSkipHit = " << evtSkipHit
857 <<
", evtCtime = " << evtCtime
858 <<
", evtRevo9Counter = " << evtRevo9Counter);
861 unsigned int evtAsicMask = word >> 16;
862 unsigned int evtEventQueueDepth = (word >> 8) & 0xFF;
863 unsigned int evtEventNumberByte = word & 0xFF;
865 B2DEBUG(22, std::dec << array.
getIndex() <<
":\t" << setfill(
'0') << setw(4) << std::hex <<
866 (word >> 16) <<
" " << setfill(
'0') << setw(4) << (word & 0xFFFF) << std::dec
867 <<
"\tevtAsicMask = " << evtAsicMask
868 <<
", evtEventQueueDepth = " << evtEventQueueDepth
869 <<
", evtEventNumberByte = " << evtEventNumberByte);
871 m_productionEventDebugs.appendNew(evtType,
881 B2DEBUG(22,
"end of event header, start of hits:");
883 const int numWordsPerHit = 4 + evtExtra;
884 unsigned int numHitsFound = 0;
885 unsigned int numExpectedWaveforms = 0;
887 std::vector<TOPRawDigit*> digitsWithWaveform;
890 && array.
getIndex() < evtNumWordsCore - 2) {
895 unsigned int hitCarrier = 0;
896 unsigned int hitAsic = 0;
897 unsigned int hitChannel = 0;
898 unsigned int hitWindow = 0;
899 unsigned int hitMagicHeader = 0;
900 unsigned int hitTFine = 0;
901 bool hitHasWaveform =
false;
902 bool hitIsOnHeap =
false;
903 unsigned int hitHeapWindow = 0;
904 bool hitIsOnHeapStraddle =
false;
905 unsigned int hitHeapWindowStraddle = 0;
906 bool hitIsWindowStraddle =
false;
907 short hitIntegral = 0;
910 if (dataFormat == TOP::RawDataType::c_ProductionDebug01) {
912 hitCarrier = word >> 30;
913 hitAsic = (word >> 28) & 0x3;
914 hitChannel = (word >> 25) & 0x7;
915 hitWindow = (word >> 16) & 0x1FF;
916 hitMagicHeader = (word >> 12) & 0xF;
917 hitTFine = (word >> 8) & 0xF;
918 hitHasWaveform = (word >> 7) & 0x1;
919 hitIsOnHeap = (word >> 6) & 0x1;
920 hitHeapWindow = word & 0x3F;
923 B2DEBUG(22, std::dec << array.
getIndex() <<
":\t" << setfill(
'0') << setw(4) << std::hex <<
924 (word >> 16) <<
" " << setfill(
'0') << setw(4) << (word & 0xFFFF) << std::dec
925 <<
"\thitCarrier = " << hitCarrier
926 <<
", hitAsic = " << hitAsic
927 <<
", hitChannel = " << hitChannel
928 <<
", hitWindow = " << hitWindow
931 <<
", hitHasWaveform = " << hitHasWaveform
938 hitVPeak = expand13to16bits(word >> 16);
939 hitIntegral = word & 0xFFFF;
940 B2DEBUG(22, std::dec << array.
getIndex() <<
":\t" << setfill(
'0') << setw(4) << std::hex <<
941 (word >> 16) <<
" " << setfill(
'0') << setw(4) << (word & 0xFFFF) << std::dec
942 <<
"\thitVPeak = " << hitVPeak
943 <<
", hitIntegral = " << hitIntegral);
945 }
else if (dataFormat == TOP::RawDataType::c_ProductionDebug02) {
947 hitCarrier = word >> 30;
948 hitAsic = (word >> 28) & 0x3;
949 hitChannel = (word >> 25) & 0x7;
950 hitWindow = (word >> 16) & 0x1FF;
951 hitMagicHeader = (word >> 12) & 0xF;
952 hitTFine = (word >> 8) & 0xF;
953 hitHasWaveform = (word >> 7) & 0x1;
954 hitIsWindowStraddle = (word >> 6) & 0x1;
955 hitIntegral = word & 0x3F;
958 B2DEBUG(22, std::dec << array.
getIndex() <<
":\t" << setfill(
'0') << setw(4) << std::hex <<
959 (word >> 16) <<
" " << setfill(
'0') << setw(4) << (word & 0xFFFF) << std::dec
960 <<
"\thitCarrier = " << hitCarrier
961 <<
", hitAsic = " << hitAsic
962 <<
", hitChannel = " << hitChannel
963 <<
", hitWindow = " << hitWindow
966 <<
", hitHasWaveform = " << hitHasWaveform
967 <<
", hitIsWindowStraddle = " << hitHasWaveform
968 <<
", hitIntegral = " << hitIntegral
973 hitVPeak = expand13to16bits(word >> 16);
974 hitIsOnHeapStraddle = (word >> 15) & 0x1;
975 hitHeapWindowStraddle = (word >> 8) & 0x7F;
976 hitIsOnHeap = (word >> 7) & 0x1;
977 hitHeapWindow = word & 0x1;
979 B2DEBUG(22, std::dec << array.
getIndex() <<
":\t" << setfill(
'0') << setw(4) << std::hex <<
980 (word >> 16) <<
" " << setfill(
'0') << setw(4) << (word & 0xFFFF) << std::dec
981 <<
"\thitVPeak = " << hitVPeak
982 <<
", hitIsOnHeapStraddle = " << hitIsOnHeapStraddle
983 <<
", hitHeapWindowStraddle = " << hitHeapWindowStraddle
984 <<
", hitIsOnHeap = " << hitIsOnHeap
985 <<
", hitHeapWindow = " << hitHeapWindow);
987 B2WARNING(
"TOPUnpacker: could not match data type inside unpackProdDebug()"
988 <<
LogVar(
"evtType", evtType) <<
LogVar(
"evtVersion", evtVersion));
993 if (hitHasWaveform) {
994 numExpectedWaveforms += 1;
997 if (hitMagicHeader != 0xB) {
998 B2WARNING(
"TOPUnpacker: hit header magic word mismatch. should be 0xB."
999 <<
LogVar(
"Magic word", hitMagicHeader));
1004 short hitVRise0 = expand13to16bits(word >> 16);
1005 short hitVRise1 = expand13to16bits(word);
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 <<
"\thitVRise0 = " << hitVRise0
1009 <<
", hitVRise1 = " << hitVRise1);
1012 short hitVFall0 = expand13to16bits(word >> 16);
1013 short hitVFall1 = expand13to16bits(word);
1014 B2DEBUG(22, std::dec << array.
getIndex() <<
":\t" << setfill(
'0') << setw(4) << std::hex <<
1015 (word >> 16) <<
" " << setfill(
'0') << setw(4) << (word & 0xFFFF) << std::dec
1016 <<
"\thitVFall0 = " << hitVFall0
1017 <<
", hitVFall1 = " << hitVFall1);
1020 unsigned short hitSampleRise = (word >> 24);
1021 short hitDSampPeak = (word >> 20) & 0xF;
1022 short hitDSampFall = (word >> 16) & 0xF;
1023 unsigned short hitHeaderChecksum = word & 0xFFFF;
1024 B2DEBUG(22, std::dec << array.
getIndex() <<
":\t" << setfill(
'0') << setw(4) << std::hex <<
1025 (word >> 16) <<
" " << setfill(
'0') << setw(4) << (word & 0xFFFF) << std::dec
1026 <<
"\thitSampleRise = " << hitSampleRise
1027 <<
", hitDSampPeak = " << hitDSampPeak
1028 <<
", hitDSampFall = " << hitDSampFall
1029 <<
", hitheaderChecksum = " << hitHeaderChecksum
1033 B2WARNING(
"TOPUnpacker: hit checksum invalid.");
1038 auto* digit = m_rawDigits.appendNew(evtScrodID, TOPRawDigit::c_ProductionDebug);
1039 digit->setCarrierNumber(hitCarrier);
1040 digit->setASICNumber(hitAsic);
1041 digit->setASICChannel(hitChannel);
1042 digit->setASICWindow(hitWindow);
1043 digit->setLastWriteAddr(0);
1044 digit->setSampleRise(hitSampleRise);
1045 digit->setDeltaSamplePeak(hitDSampPeak);
1046 digit->setDeltaSampleFall(hitDSampFall);
1047 digit->setValueRise0(hitVRise0);
1048 digit->setValueRise1(hitVRise1);
1049 digit->setValuePeak(hitVPeak);
1050 digit->setValueFall0(hitVFall0);
1051 digit->setValueFall1(hitVFall1);
1052 digit->setTFine(hitTFine);
1053 digit->setIntegral(hitIntegral);
1054 digit->setRevo9Counter(evtRevo9Counter);
1055 digit->setPhase(evtPhase);
1058 if (hitHasWaveform) {
1059 digitsWithWaveform.push_back(digit);
1063 if (dataFormat == TOP::RawDataType::c_ProductionDebug01) {
1064 hitDebug = m_productionHitDebugs.appendNew(hitHasWaveform,
1067 hitIsOnHeap ? 428 + hitHeapWindow : hitWindow,
1068 hitIsWindowStraddle);
1069 }
else if (dataFormat == TOP::RawDataType::c_ProductionDebug02) {
1070 hitDebug = m_productionHitDebugs.appendNew(hitHasWaveform,
1073 hitIsOnHeap ? 428 + hitHeapWindow : hitWindow,
1074 hitIsWindowStraddle,
1076 hitIsOnHeapStraddle ? 428 + hitHeapWindowStraddle : hitWindow +
1081 for (
unsigned int i = 0; i < evtExtra; ++i) {
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 <<
"\thit extra word " << i <<
" (" << evtExtra <<
")");
1089 if (m_addRelations and hitDebug) {
1090 digit->addRelationTo(hitDebug);
1097 unsigned int evtSdType = (word >> 24);
1098 unsigned int evtSdData = (word >> 12) & 0xFFF;
1099 unsigned int evtMagicFooter = (word >> 9) & 0x7;
1100 unsigned int evtNHits = word & 0x1FF;
1101 B2DEBUG(22, std::dec << array.
getIndex() <<
":\t" << setfill(
'0') << setw(4) << std::hex <<
1102 (word >> 16) <<
" " << setfill(
'0') << setw(4) << (word & 0xFFFF) << std::dec
1103 <<
"\tevtSdType = " << evtSdType
1104 <<
", evtSdData = " << evtSdData
1105 <<
", evtMagicFooter = " << evtMagicFooter
1106 <<
", evtNHits = " << evtNHits <<
" (" << numHitsFound <<
")");
1108 if (evtSdType != 0) {
1109 m_slowData.appendNew(evtScrodID, evtSdType, evtSdData);
1112 if (evtMagicFooter != 0x5) {
1113 B2WARNING(
"TOPUnpacker: event footer magic word mismatch. should be 0x5."
1114 <<
LogVar(
"Magic word", evtMagicFooter));
1118 B2DEBUG(22,
"the rest:");
1120 unsigned int numParsedWaveforms = 0;
1121 while (array.
peekWord() != 0x6c617374
1125 unsigned int wfNSamples = (word >> 16);
1126 unsigned int wfNWindows = (word >> 8) & 0x7;
1127 unsigned int wfCarrier = (word >> 5) & 0x3;
1128 unsigned int wfAsic = (word >> 3) & 0x3;
1129 unsigned int wfChannel = word & 0x7;
1132 const auto& mapper = m_topgp->getChannelMapper();
1133 unsigned channel = mapper.getChannel(boardstack, wfCarrier, wfAsic, wfChannel);
1134 int pixelID = mapper.getPixelID(channel);
1136 B2DEBUG(22, std::dec << array.
getIndex() <<
":\t" << setfill(
'0') << setw(4) << std::hex <<
1137 (word >> 16) <<
" " << setfill(
'0') << setw(4) << (word & 0xFFFF) << std::dec
1138 <<
"\twfNSamples = " << wfNSamples
1139 <<
", wfNWindows = " << wfNWindows
1140 <<
", wfCarrier = " << wfCarrier
1141 <<
", wfAsic = " << wfAsic
1142 <<
", wfChannel " << wfChannel);
1144 if (wfNSamples != 32 && wfNSamples != 16) {
1145 B2WARNING(
"TOPUnpacker: suspicious value for wfNSamples."
1146 <<
LogVar(
"wfNSamples", wfNSamples));
1151 unsigned int wfStartSample = (word >> 25) & 0x3F;
1152 unsigned int wfWindowLogic = (word >> 16) & 0x1FF;
1153 unsigned int wfEventNumber = (word >> 9) & 0x7F;
1154 unsigned int wfWindowPhysical = word & 0x1FF;
1156 B2DEBUG(22, std::dec << array.
getIndex() <<
":\t" << setfill(
'0') << setw(4) << std::hex <<
1157 (word >> 16) <<
" " << setfill(
'0') << setw(4) << (word & 0xFFFF) << std::dec
1158 <<
"\twfStartSample = " << wfStartSample
1159 <<
", wfWindowLogic = " << wfWindowLogic
1160 <<
", wfEventNumber = " << wfEventNumber
1161 <<
", wfWindowPhysical = " << wfWindowPhysical);
1163 std::vector<short> wfSamples;
1165 for (
unsigned int i = 0; i < wfNSamples / 2; ++i) {
1166 short wfSampleLast = 0;
1167 short wfSampleFirst = 0;
1171 if (pedestalSubtracted) {
1172 wfSampleLast = (word >> 16);
1173 wfSampleFirst = word & 0xFFFF;
1175 wfSampleLast = (word >> 16) & 0xFFF;
1176 wfSampleFirst = word & 0xFFF;
1180 B2DEBUG(22, std::dec << array.
getIndex() <<
":\t" << setfill(
'0') << setw(4) << std::hex <<
1181 (word >> 16) <<
" " << setfill(
'0') << setw(4) << (word & 0xFFFF) << std::dec
1182 <<
"\twfSample" << 2 * i + 1 <<
" = " << wfSampleLast
1183 <<
", wfSample" << 2 * i <<
" = " << wfSampleFirst);
1185 wfSamples.push_back(wfSampleFirst);
1186 wfSamples.push_back(wfSampleLast);
1190 auto* waveform = m_waveforms.appendNew(moduleID, pixelID, channel, evtScrodID,
1191 wfWindowLogic, wfStartSample, wfSamples);
1192 waveform->setPedestalSubtractedFlag(pedestalSubtracted);
1193 waveform->setPhysicalWindow(wfWindowPhysical);
1194 if (numParsedWaveforms < digitsWithWaveform.size()) {
1195 const auto* digit = digitsWithWaveform[numParsedWaveforms];
1196 if (digit->getScrodChannel() == channel % 128) {
1197 digit->addRelationTo(waveform);
1199 B2WARNING(
"TOPUnpacker: hit and its waveform have different channel number."
1200 <<
LogVar(
"channel (hit)", digit->getScrodChannel())
1201 <<
LogVar(
"channel (waveform)", channel % 128));
1204 numParsedWaveforms += 1;
1208 if (numExpectedWaveforms != numParsedWaveforms) {
1209 B2WARNING(
"TOPUnpacker: number of expected and parsed waveforms does not match."
1210 <<
LogVar(
"expected", numExpectedWaveforms)
1211 <<
LogVar(
"parsed", numParsedWaveforms));
1218 void TOPUnpackerModule::endRun()
1220 B2INFO(
"TOPUnpacker: Channels seen per event statistics:");
1221 B2INFO(
"TOPUnpacker: nChn\tcount");
1222 for (
auto& entry : m_channelStatistics) {
1223 B2INFO(
"TOPUnpacker: " << entry.first <<
"\t\t" << entry.second);
1227 void TOPUnpackerModule::terminate()
Type-safe access to single objects in the data store.
EHitQuality
hit quality enumerators
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.
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.
Class to store variables with their name which were sent to the logging service.
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Abstract base class for different kinds of events.
record to be used to store ASIC info