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);
71 addParam(
"errorSuppressFactor", m_errorSuppressFactor,
72 "error messages suppression factor (0 = no suppression)", (
unsigned) 1000);
76 TOPUnpackerModule::~TOPUnpackerModule()
80 void TOPUnpackerModule::initialize()
85 m_rawData.isRequired(m_inputRawDataName);
89 m_digits.registerInDataStore(m_outputDigitsName);
90 m_rawDigits.registerInDataStore(m_outputRawDigitsName);
91 m_slowData.registerInDataStore();
92 m_interimFEInfos.registerInDataStore(DataStore::c_DontWriteOut);
93 m_waveforms.registerInDataStore(m_outputWaveformsName, DataStore::c_DontWriteOut);
94 m_productionEventDebugs.registerInDataStore(DataStore::c_DontWriteOut);
95 m_productionHitDebugs.registerInDataStore(DataStore::c_DontWriteOut);
96 m_templateFitResults.registerInDataStore(m_templateFitResultName, DataStore::c_DontWriteOut);
98 m_rawDigits.registerRelationTo(m_waveforms, DataStore::c_Event, DataStore::c_DontWriteOut);
99 m_rawDigits.registerRelationTo(m_templateFitResults, DataStore::c_Event, DataStore::c_DontWriteOut);
100 m_rawDigits.registerRelationTo(m_interimFEInfos, DataStore::c_Event, DataStore::c_DontWriteOut);
101 m_rawDigits.registerRelationTo(m_productionHitDebugs, DataStore::c_Event, DataStore::c_DontWriteOut);
102 m_waveforms.registerRelationTo(m_interimFEInfos, DataStore::c_Event, DataStore::c_DontWriteOut);
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");
111 void TOPUnpackerModule::beginRun()
113 m_channelStatistics.clear();
116 void TOPUnpackerModule::event()
118 if (m_resetEventCount) {
119 m_numErrors = m_errorCount;
122 m_resetEventCount =
false;
130 m_productionEventDebugs.clear();
131 m_productionHitDebugs.clear();
132 m_templateFitResults.clear();
134 m_interimFEInfos.clear();
137 for (
auto& raw : m_rawData) {
138 for (
int finesse = 0; finesse < raw.GetMaxNumOfCh(0); finesse++) {
139 const int* buffer = raw.GetDetectorBuffer(0, finesse);
140 int bufferSize = raw.GetDetectorNwords(0, finesse);
141 if (bufferSize < 1)
continue;
145 int dataFormat = m_dataFormat;
146 if (dataFormat == 0) {
147 DataArray array(buffer, bufferSize, m_swapBytes);
148 unsigned word = array.
getWord();
149 dataFormat = (word >> 16);
150 bool isKnownDataFormat =
false;
151 for (
auto& t : TOP::membersRawDataType) {
152 if (
static_cast<int>(t) == dataFormat) {
153 isKnownDataFormat =
true;
158 if (!isKnownDataFormat) {
159 if (evtMetaData->getExperiment() == 1) {
163 if (unpackHeadersInterimFEVer01(buffer, bufferSize,
true)) {
164 B2DEBUG(22,
"Assuming interim FW data format");
168 B2WARNING(
"TOPUnpacker: Could not establish data format.");
175 switch (dataFormat) {
176 case static_cast<int>(TOP::RawDataType::c_Type0Ver16):
177 unpackType0Ver16(buffer, bufferSize);
179 case static_cast<int>(TOP::RawDataType::c_Type2Ver1):
180 err = unpackInterimFEVer01(buffer, bufferSize,
false);
182 case static_cast<int>(TOP::RawDataType::c_Type3Ver1):
183 err = unpackInterimFEVer01(buffer, bufferSize,
true);
185 case static_cast<int>(TOP::RawDataType::c_Draft):
186 unpackProductionDraft(buffer, bufferSize);
188 case static_cast<int>(TOP::RawDataType::c_ProductionDebug01):
189 err = unpackProdDebug(buffer, bufferSize, TOP::RawDataType::c_ProductionDebug01,
true);
191 case static_cast<int>(TOP::RawDataType::c_ProductionDebug02):
192 err = unpackProdDebug(buffer, bufferSize, TOP::RawDataType::c_ProductionDebug02,
true);
196 if (printTheError()) {
197 B2ERROR(
"TOPUnpacker: unknown data format, " << getFrontEndName(raw, finesse)
198 <<
LogVar(
"Type", (dataFormat >> 8))
199 <<
LogVar(
"Version", (dataFormat & 0xFF)));
205 if (printTheError()) {
206 B2ERROR(
"TOPUnpacker: error in unpacking data from " << getFrontEndName(raw, finesse)
207 <<
LogVar(
"words unused", err));
217 std::string TOPUnpackerModule::getFrontEndName(
RawTOP& raw,
int finesse)
const
220 if (raw.GetMaxNumOfCh(0) <= 4) {
221 int copper = ((raw.GetNodeID(0) >> 24) * 1000 + (raw.GetNodeID(0) & 0x3FF));
222 name =
"frontend cpr" + std::to_string(copper) + char(
'a' + finesse);
224 int slot = (raw.GetNodeID(0) & 0xF) * 8 - 7 + finesse / 4;
225 name = (slot < 10) ?
"boardstack s0" :
"boardstack s";
226 name += std::to_string(slot) + char(
'a' + finesse % 4);
232 bool TOPUnpackerModule::printTheError()
234 if (m_eventCount < m_errorSuppressFactor * m_numErrors)
return false;
236 m_resetEventCount =
true;
241 void TOPUnpackerModule::unpackProductionDraft(
const int* buffer,
int bufferSize)
244 B2DEBUG(22,
"Unpacking ProductionDraft to TOPDigits, dataSize = " << bufferSize);
246 unsigned short scrodID = buffer[0] & 0xFFFF;
247 const auto* feemap = m_topgp->getFrontEndMapper().getMap(scrodID);
249 B2ERROR(
"TOPUnpacker: no front-end map available."
250 <<
LogVar(
"SCROD ID", scrodID));
253 int moduleID = feemap->getModuleID();
254 int boardstack = feemap->getBoardstackNumber();
255 const auto& mapper = m_topgp->getChannelMapper();
257 const auto* geo = m_topgp->getGeometry();
258 auto subBits = geo->getNominalTDC().getSubBits();
259 int sampleDivisions = 0x1 << subBits;
261 for (
int i = 1; i < bufferSize; i++) {
262 int word = buffer[i];
263 int tdc = word & 0xFFFF;
264 double rawTime = double(tdc) / sampleDivisions;
265 unsigned chan = ((word >> 16) & 0x7F) + boardstack * 128;
266 unsigned flags = (word >> 24) & 0xFF;
267 int pixelID = mapper.getPixelID(chan);
268 auto* digit = m_digits.appendNew(moduleID, pixelID, rawTime);
269 digit->setTime(geo->getNominalTDC().getTime(tdc));
270 digit->setChannel(chan);
277 void TOPUnpackerModule::unpackType0Ver16(
const int* buffer,
int bufferSize)
280 B2DEBUG(22,
"Unpacking Type0Ver16 to TOPRawDigits, dataSize = " << bufferSize);
282 DataArray array(buffer, bufferSize, m_swapBytes);
283 unsigned word = array.
getWord();
284 unsigned short scrodID = word & 0x0FFF;
287 int Nhits = last & 0x01FF;
288 if (bufferSize != 5 * Nhits + 2) {
289 B2ERROR(
"TOPUnpacker: corrupted data (feature-extraction format)."
290 <<
LogVar(
"SCROD ID", scrodID));
294 short SDType = last >> 24;
295 short SDValue = (last >> 12) & 0x0FFF;
296 if (SDType != 0) m_slowData.appendNew(scrodID, SDType, SDValue);
298 unsigned short errorFlags = 0;
299 if (((word >> 12) & 0x0F) != 0x0A) errorFlags |= TOPRawDigit::c_HeadMagic;
300 if (((last >> 9) & 0x07) != 0x05) errorFlags |= TOPRawDigit::c_TailMagic;
302 for (
int hit = 0; hit < Nhits; hit++) {
303 auto* digit = m_rawDigits.appendNew(scrodID, TOPRawDigit::c_Production);
306 digit->setCarrierNumber((word >> 30) & 0x03);
307 digit->setASICNumber((word >> 28) & 0x03);
308 digit->setASICChannel((word >> 25) & 0x07);
309 digit->setASICWindow((word >> 16) & 0x1FF);
310 digit->setTFine((word >> 8) & 0x0F);
311 auto flags = errorFlags;
312 if (((word >> 12) & 0x0F) != 0x0B) flags |= TOPRawDigit::c_HitMagic;
313 unsigned short checkSum = sumShorts(word);
316 digit->setValuePeak(expand13to16bits(word >> 16));
317 digit->setIntegral(word & 0xFFFF);
318 checkSum += sumShorts(word);
321 digit->setValueRise0(expand13to16bits(word >> 16));
322 digit->setValueRise1(expand13to16bits(word));
323 checkSum += sumShorts(word);
326 digit->setValueFall0(expand13to16bits(word >> 16));
327 digit->setValueFall1(expand13to16bits(word));
328 checkSum += sumShorts(word);
331 digit->setSampleRise(word >> 24);
332 digit->setDeltaSamplePeak((word >> 20) & 0x0F);
333 digit->setDeltaSampleFall((word >> 16) & 0x0F);
334 checkSum += sumShorts(word);
335 if (checkSum != 0) flags |= TOPRawDigit::c_HitChecksum;
337 digit->setErrorFlags(flags);
343 bool TOPUnpackerModule::unpackHeadersInterimFEVer01(
const int* buffer,
int bufferSize,
bool swapBytes)
345 B2DEBUG(22,
"Checking whether buffer unpacks as InterimFEVer01, dataSize = " << bufferSize);
347 DataArray array(buffer, bufferSize, swapBytes);
352 unsigned header = array.
getWord();
353 if ((header & 0xFF) == 0xBE) {
357 if (header != 0xaaaa0104 and header != 0xaaaa0103 and header != 0xaaaa0100) {
365 if (header != 0xaaaa0104) {
381 unsigned magicWord = array.
getWord();
382 if (magicWord != 0x7473616c) {
386 if (header != 0xaaaa0103)
continue;
399 int numWords = 4 * 32;
404 for (
int i = 0; i < numWords; i++) {
413 int TOPUnpackerModule::unpackInterimFEVer01(
const int* buffer,
int bufferSize,
414 bool pedestalSubtracted)
417 B2DEBUG(22,
"Unpacking InterimFEVer01 to TOPRawDigits and TOPRawWaveforms, "
418 "dataSize = " << bufferSize);
423 DataArray array(buffer, bufferSize, m_swapBytes);
425 map<unsigned short, int> evtNumCounter;
426 std::vector<unsigned short> channelCounter(128, 0);
428 unsigned word = array.
getWord();
429 unsigned short scrodID = word & 0x0FFF;
430 auto* info = m_interimFEInfos.appendNew(scrodID, bufferSize);
437 unsigned header = array.
getWord();
439 if ((header & 0xFF) == 0xBE) {
442 unsigned short scrodID_SSFE;
443 unsigned short carrier_SSFE;
444 unsigned short asic_SSFE;
445 unsigned short channel_SSFE;
446 unsigned short evtNum_SSFE;
448 evtNum_SSFE = (header >> 8) & 0xFF;
449 scrodID_SSFE = (header >> 16) & 0x7F;
450 channel_SSFE = (header >> 24) & 0x07;
451 asic_SSFE = (header >> 27) & 0x03;
452 carrier_SSFE = (header >> 29) & 0x03;
454 const auto* feemap = m_topgp->getFrontEndMapper().getMap(scrodID_SSFE);
456 moduleID = feemap->getModuleID();
457 boardstack = feemap->getBoardstackNumber();
459 B2ERROR(
"TOPUnpacker: no front-end map available."
460 <<
LogVar(
"SCROD ID", scrodID_SSFE));
461 info->setErrorFlag(TOPInterimFEInfo::c_InvalidScrodID);
464 if (scrodID_SSFE != scrodID) {
465 B2ERROR(
"TOPUnpacker: corrupted data - "
466 <<
"different scrodID's in HLSB and super short FE header."
467 <<
LogVar(
"SCROD", scrodID_SSFE)
468 <<
LogVar(
"slot", moduleID)
469 <<
LogVar(
"BS", boardstack));
470 B2DEBUG(21,
"Different scrodID's in HLSB and FE header: " << scrodID <<
" " << scrodID_SSFE <<
" word = 0x" << std::hex << word);
471 info->setErrorFlag(TOPInterimFEInfo::c_DifferentScrodIDs);
475 B2DEBUG(21, scrodID_SSFE <<
"\t" << carrier_SSFE <<
"\t" << asic_SSFE <<
"\t" << channel_SSFE <<
"\t" << evtNum_SSFE);
477 int channelID = carrier_SSFE * 32 + asic_SSFE * 8 + channel_SSFE;
478 channelCounter[channelID] += 1;
479 evtNumCounter[evtNum_SSFE] += 1;
481 info->incrementFEHeadersCount();
482 info->incrementEmptyFEHeadersCount();
487 if (header != 0xaaaa0104 and header != 0xaaaa0103 and header != 0xaaaa0100) {
488 B2ERROR(
"TOPUnpacker: corrupted data - invalid FE header word");
489 B2DEBUG(21,
"Invalid FE header word: " << std::hex << header <<
" 0b" << std::bitset<32>(header));
490 B2DEBUG(21,
"SCROD ID: " << scrodID <<
" " << std::hex << scrodID);
492 info->setErrorFlag(TOPInterimFEInfo::c_InvalidFEHeader);
498 unsigned short scrodID_FE = word >> 25;
499 unsigned short convertedAddr = (word >> 16) & 0x1FF;
500 unsigned short evtNum_numWin_trigPat_FEheader = word & 0xFFFF;
501 unsigned short evtNum_FEheader = evtNum_numWin_trigPat_FEheader & 0xFF;
502 evtNumCounter[evtNum_FEheader] += 1;
504 if (scrodID_FE != scrodID) {
505 B2ERROR(
"TOPUnpacker: different scrodID's in HLSB and FE header."
506 <<
LogVar(
"scrodID (HSLB)", scrodID)
507 <<
LogVar(
"scrodID (FE)", scrodID_FE));
509 info->setErrorFlag(TOPInterimFEInfo::c_DifferentScrodIDs);
515 unsigned lastWrAddr = (word & 0x0FF) << 1;
517 unsigned short asicChannelFE = (word >> 8) & 0x07;
518 unsigned short asicFE = (word >> 12) & 0x03;
519 unsigned short carrierFE = (word >> 14) & 0x03;
520 unsigned short channelID = carrierFE * 32 + asicFE * 8 + asicChannelFE;
523 B2DEBUG(21, scrodID_FE <<
"\t" << carrierFE <<
"\t" << asicFE <<
"\t" << asicChannelFE <<
"\t" << evtNum_FEheader);
525 channelCounter[channelID] += 1;
527 std::vector<TOPRawDigit*> digits;
529 if (header != 0xaaaa0104) {
533 short samplePeak_p = word & 0xFFFF;
534 short valuePeak_p = (word >> 16) & 0xFFFF;
537 short sampleRise_p = word & 0xFFFF;
538 short valueRise0_p = (word >> 16) & 0xFFFF;
541 short valueRise1_p = word & 0xFFFF;
542 short sampleFall_p = (word >> 16) & 0xFFFF;
545 short valueFall0_p = word & 0xFFFF;
546 short valueFall1_p = (word >> 16) & 0xFFFF;
549 short integral_p = word & 0xFFFF;
557 short samplePeak_n = word & 0xFFFF;
558 short valuePeak_n = (word >> 16) & 0xFFFF;
576 short integral_n = word & 0xFFFF;
577 short qualityFlags_n = (word >> 16) & 0xFFFF;
579 if (abs(valuePeak_p) != 9999) {
580 auto* digit = m_rawDigits.appendNew(scrodID, TOPRawDigit::c_Interim);
581 digit->setCarrierNumber(carrierFE);
582 digit->setASICNumber(asicFE);
583 digit->setASICChannel(asicChannelFE);
584 digit->setASICWindow(convertedAddr);
585 digit->setLastWriteAddr(lastWrAddr);
586 digit->setSampleRise(sampleRise_p);
587 digit->setDeltaSamplePeak(samplePeak_p - sampleRise_p);
588 digit->setDeltaSampleFall(sampleFall_p - sampleRise_p);
589 digit->setValueRise0(valueRise0_p);
590 digit->setValueRise1(valueRise1_p);
591 digit->setValuePeak(valuePeak_p);
592 digit->setValueFall0(valueFall0_p);
593 digit->setValueFall1(valueFall1_p);
594 digit->setIntegral(integral_p);
596 digit->addRelationTo(info);
597 digits.push_back(digit);
599 if (valuePeak_p < 150) {
600 auto* tlpfResult = m_templateFitResults.appendNew();
601 tlpfResult->setBackgroundOffset(samplePeak_n);
602 tlpfResult->setAmplitude(valuePeak_n);
603 tlpfResult->setChisquare(qualityFlags_n);
604 tlpfResult->setRisingEdgeAndConvert(integral_n);
605 digit->addRelationTo(tlpfResult);
632 if (word != 0x7473616c) {
636 info->setErrorFlag(TOPInterimFEInfo::c_InvalidMagicWord);
642 info->incrementFEHeadersCount();
643 if (digits.empty()) info->incrementEmptyFEHeadersCount();
645 if (header != 0xaaaa0103)
continue;
649 unsigned long evtNum_numWaves_refWin_WFheader = word;
650 unsigned short evtNum_WFheader = (evtNum_numWaves_refWin_WFheader >> 24) & 0xFF;
652 if (evtNum_WFheader != evtNum_FEheader) {
653 B2ERROR(
"TOPUnpacker: different carrier event number in WF and FE header."
654 <<
LogVar(
"Event number (FE header)", evtNum_FEheader)
655 <<
LogVar(
"Event number (WF header)", evtNum_WFheader));
662 unsigned short carrier = (word >> 14) & 0x03;
663 unsigned short asic = (word >> 12) & 0x03;
665 unsigned short window = word & 0x1FF;
668 if (carrier != carrierFE) {
669 B2ERROR(
"TOPUnpacker: different carrier numbers in FE and WF header");
670 B2DEBUG(21,
"Different carrier numbers in FE and WF header: "
671 << carrierFE <<
" " << carrier);
672 info->setErrorFlag(TOPInterimFEInfo::c_DifferentCarriers);
674 if (asic != asicFE) {
675 B2ERROR(
"TOPUnpacker: different ASIC numbers in FE and WF header");
676 B2DEBUG(21,
"Different ASIC numbers in FE and WF header: "
677 << asicFE <<
" " << asic);
678 info->setErrorFlag(TOPInterimFEInfo::c_DifferentAsics);
681 B2ERROR(
"TOPUnpacker: different ASIC channel numbers in FE and WF header");
682 B2DEBUG(21,
"Different ASIC channel numbers in FE and WF header: "
684 info->setErrorFlag(TOPInterimFEInfo::c_DifferentChannels);
686 if (window != convertedAddr) {
687 B2ERROR(
"TOPUnpacker: different window numbers in FE and WF header");
688 B2DEBUG(21,
"Different window numbers in FE and WF header: "
689 << convertedAddr <<
" " << window);
690 info->setErrorFlag(TOPInterimFEInfo::c_DifferentWindows);
695 std::vector<unsigned short> windows;
696 windows.push_back(window);
699 windows.push_back(word & 0x1FF);
702 windows.push_back(word & 0x1FF);
705 windows.push_back(word & 0x1FF);
707 int numWords = 4 * 32;
709 B2ERROR(
"TOPUnpacker: too few words for waveform data."
710 <<
LogVar(
"needed", numWords)
712 info->setErrorFlag(TOPInterimFEInfo::c_InsufficientWFData);
717 std::vector<short> adcData;
718 for (
int i = 0; i < numWords; i++) {
720 adcData.push_back(word & 0xFFFF);
721 adcData.push_back((word >> 16) & 0xFFFF);
728 const auto* feemap = m_topgp->getFrontEndMapper().getMap(scrodID);
730 moduleID = feemap->getModuleID();
731 boardstack = feemap->getBoardstackNumber();
733 B2ERROR(
"TOPUnpacker: no front-end map available."
734 <<
LogVar(
"SCROD ID", scrodID));
735 info->setErrorFlag(TOPInterimFEInfo::c_InvalidScrodID);
739 const auto& mapper = m_topgp->getChannelMapper();
740 unsigned channel = mapper.getChannel(boardstack, carrier, asic,
asicChannel);
741 int pixelID = mapper.getPixelID(channel);
744 auto* waveform = m_waveforms.appendNew(moduleID, pixelID, channel, scrodID,
746 waveform->setLastWriteAddr(lastWrAddr);
747 waveform->setStorageWindows(windows);
748 waveform->setPedestalSubtractedFlag(pedestalSubtracted);
749 waveform->addRelationTo(info);
750 info->incrementWaveformsCount();
753 for (
auto& digit : digits) digit->addRelationTo(waveform);
757 if (evtNumCounter.size() != 1) {
758 B2ERROR(
"TOPUnpacker: Possible frame shift detected "
759 <<
"(More than one unique carrier event number in this readout event)."
760 <<
LogVar(
"SCROD", scrodID)
761 <<
LogVar(
"slot", moduleID)
762 <<
LogVar(
"BS", boardstack));
767 string evtNumOutputString;
768 evtNumOutputString +=
"Carrier event numbers and their counts for SCROD ID " + std::to_string(scrodID) +
":\n";
769 for (
auto const& it : evtNumCounter) {
771 evtNumOutputString += std::to_string(it.first) +
":\t" + std::to_string(it.second) +
"\n";
773 evtNumOutputString +=
"Total:\t" + std::to_string(nASICs);
774 B2DEBUG(21, evtNumOutputString);
777 int nChannelsDiff = 0;
779 string channelOutputString;
780 channelOutputString +=
"Detected channels and their counts for SCROD ID (channels with count == 1 are omitted)" + std::to_string(
784 for (
auto const& it : channelCounter) {
790 int channelID = channelIndex;
791 int carrier = channelID / 32;
792 int asic = (channelID % 32) / 8;
793 int chn = channelID % 8;
796 channelOutputString +=
"carrier: " + std::to_string(carrier) +
" asic: " + std::to_string(asic) +
" chn: " + std::to_string(
797 chn) +
" occurence: " + std::to_string(it) +
"\n";
798 B2WARNING(
"TOPUnpacker: interim FE - ASIC channel seen more than once"
799 <<
LogVar(
"ScrodID", scrodID)
800 <<
LogVar(
"carrier", carrier)
803 <<
LogVar(
"times seen", it));
808 m_channelStatistics[nChannels] += 1;
810 channelOutputString +=
"Total:\t" + std::to_string(nChannels) +
" " + std::to_string(nChannelsDiff);
811 B2DEBUG(21, channelOutputString);
819 int TOPUnpackerModule::unpackProdDebug(
const int* buffer,
int bufferSize, TOP::RawDataType dataFormat,
820 bool pedestalSubtracted)
823 B2DEBUG(22,
"Unpacking Production firmware debug data format to TOPRawDigits "
824 "dataSize = " << bufferSize);
826 DataArray array(buffer, bufferSize, m_swapBytes);
830 unsigned int evtType = word >> 24;
831 unsigned int evtVersion = (word >> 16) & 0xFF;
832 unsigned int evtMagicHeader = (word >> 12) & 0xF;
833 unsigned int evtScrodID = word & 0xFFF;
838 const auto* feemap = m_topgp->getFrontEndMapper().getMap(evtScrodID);
840 moduleID = feemap->getModuleID();
841 boardstack = feemap->getBoardstackNumber();
843 B2WARNING(
"TOPUnpacker: no front-end map available."
844 <<
LogVar(
"SCROD ID", evtScrodID));
848 B2DEBUG(22, std::dec << array.
getIndex() <<
":\t" << setfill(
'0') << setw(4) << std::hex <<
849 (word >> 16) <<
" " << setfill(
'0') << setw(4) << (word & 0xFFFF) << std::dec
850 <<
"\tevtType = " << evtType
851 <<
", evtVersion = " << evtVersion
852 <<
", evtMagicHeader = " << evtMagicHeader
853 <<
", evtScrodID = " << evtScrodID);
855 if (evtMagicHeader != 0xA) {
856 B2WARNING(
"TOPUnpacker: event header magic word mismatch. should be 0xA."
857 <<
LogVar(
"Magic word", evtMagicHeader));
862 unsigned int evtExtra = word >> 29;
863 unsigned int evtNumWordsBonus = (word >> 16) & 0x1FFF;
864 unsigned int evtPhase = (word >> 12) & 0xF;
865 unsigned int evtNumWordsCore = word & 0xFFF;
867 B2DEBUG(22, std::dec << array.
getIndex() <<
":\t" << setfill(
'0') << setw(4) << std::hex <<
868 (word >> 16) <<
" " << setfill(
'0') << setw(4) << (word & 0xFFFF) << std::dec
869 <<
"\tevtExtra = " << evtExtra
870 <<
", evtNumWordsBonus = " << evtNumWordsBonus
871 <<
", evtPhase = " << evtPhase
872 <<
", numWordsCore = " << evtNumWordsCore);
875 bool evtSkipHit = word >> 29;
876 unsigned int evtCtime = (word >> 16) & 0x7FF;
877 unsigned int evtRevo9Counter = word & 0xFFFF;
879 B2DEBUG(22, std::dec << array.
getIndex() <<
":\t" << setfill(
'0') << setw(4) << std::hex <<
880 (word >> 16) <<
" " << setfill(
'0') << setw(4) << (word & 0xFFFF) << std::dec
881 <<
"\tevtSkipHit = " << evtSkipHit
882 <<
", evtCtime = " << evtCtime
883 <<
", evtRevo9Counter = " << evtRevo9Counter);
886 unsigned int evtAsicMask = word >> 16;
887 unsigned int evtEventQueueDepth = (word >> 8) & 0xFF;
888 unsigned int evtEventNumberByte = word & 0xFF;
890 B2DEBUG(22, std::dec << array.
getIndex() <<
":\t" << setfill(
'0') << setw(4) << std::hex <<
891 (word >> 16) <<
" " << setfill(
'0') << setw(4) << (word & 0xFFFF) << std::dec
892 <<
"\tevtAsicMask = " << evtAsicMask
893 <<
", evtEventQueueDepth = " << evtEventQueueDepth
894 <<
", evtEventNumberByte = " << evtEventNumberByte);
896 m_productionEventDebugs.appendNew(evtType,
906 B2DEBUG(22,
"end of event header, start of hits:");
908 const int numWordsPerHit = 4 + evtExtra;
909 unsigned int numHitsFound = 0;
910 unsigned int numExpectedWaveforms = 0;
912 std::vector<TOPRawDigit*> digitsWithWaveform;
915 && array.
getIndex() < evtNumWordsCore - 2) {
920 unsigned int hitCarrier = 0;
921 unsigned int hitAsic = 0;
922 unsigned int hitChannel = 0;
923 unsigned int hitWindow = 0;
924 unsigned int hitMagicHeader = 0;
925 unsigned int hitTFine = 0;
926 bool hitHasWaveform =
false;
927 bool hitIsOnHeap =
false;
928 unsigned int hitHeapWindow = 0;
929 bool hitIsOnHeapStraddle =
false;
930 unsigned int hitHeapWindowStraddle = 0;
931 bool hitIsWindowStraddle =
false;
932 short hitIntegral = 0;
935 if (dataFormat == TOP::RawDataType::c_ProductionDebug01) {
937 hitCarrier = word >> 30;
938 hitAsic = (word >> 28) & 0x3;
939 hitChannel = (word >> 25) & 0x7;
940 hitWindow = (word >> 16) & 0x1FF;
941 hitMagicHeader = (word >> 12) & 0xF;
942 hitTFine = (word >> 8) & 0xF;
943 hitHasWaveform = (word >> 7) & 0x1;
944 hitIsOnHeap = (word >> 6) & 0x1;
945 hitHeapWindow = word & 0x3F;
948 B2DEBUG(22, std::dec << array.
getIndex() <<
":\t" << setfill(
'0') << setw(4) << std::hex <<
949 (word >> 16) <<
" " << setfill(
'0') << setw(4) << (word & 0xFFFF) << std::dec
950 <<
"\thitCarrier = " << hitCarrier
951 <<
", hitAsic = " << hitAsic
952 <<
", hitChannel = " << hitChannel
953 <<
", hitWindow = " << hitWindow
956 <<
", hitHasWaveform = " << hitHasWaveform
963 hitVPeak = expand13to16bits(word >> 16);
964 hitIntegral = word & 0xFFFF;
965 B2DEBUG(22, std::dec << array.
getIndex() <<
":\t" << setfill(
'0') << setw(4) << std::hex <<
966 (word >> 16) <<
" " << setfill(
'0') << setw(4) << (word & 0xFFFF) << std::dec
967 <<
"\thitVPeak = " << hitVPeak
968 <<
", hitIntegral = " << hitIntegral);
970 }
else if (dataFormat == TOP::RawDataType::c_ProductionDebug02) {
972 hitCarrier = word >> 30;
973 hitAsic = (word >> 28) & 0x3;
974 hitChannel = (word >> 25) & 0x7;
975 hitWindow = (word >> 16) & 0x1FF;
976 hitMagicHeader = (word >> 12) & 0xF;
977 hitTFine = (word >> 8) & 0xF;
978 hitHasWaveform = (word >> 7) & 0x1;
979 hitIsWindowStraddle = (word >> 6) & 0x1;
980 hitIntegral = word & 0x3F;
983 B2DEBUG(22, std::dec << array.
getIndex() <<
":\t" << setfill(
'0') << setw(4) << std::hex <<
984 (word >> 16) <<
" " << setfill(
'0') << setw(4) << (word & 0xFFFF) << std::dec
985 <<
"\thitCarrier = " << hitCarrier
986 <<
", hitAsic = " << hitAsic
987 <<
", hitChannel = " << hitChannel
988 <<
", hitWindow = " << hitWindow
991 <<
", hitHasWaveform = " << hitHasWaveform
992 <<
", hitIsWindowStraddle = " << hitHasWaveform
993 <<
", hitIntegral = " << hitIntegral
998 hitVPeak = expand13to16bits(word >> 16);
999 hitIsOnHeapStraddle = (word >> 15) & 0x1;
1000 hitHeapWindowStraddle = (word >> 8) & 0x7F;
1001 hitIsOnHeap = (word >> 7) & 0x1;
1002 hitHeapWindow = word & 0x1;
1004 B2DEBUG(22, std::dec << array.
getIndex() <<
":\t" << setfill(
'0') << setw(4) << std::hex <<
1005 (word >> 16) <<
" " << setfill(
'0') << setw(4) << (word & 0xFFFF) << std::dec
1006 <<
"\thitVPeak = " << hitVPeak
1007 <<
", hitIsOnHeapStraddle = " << hitIsOnHeapStraddle
1008 <<
", hitHeapWindowStraddle = " << hitHeapWindowStraddle
1009 <<
", hitIsOnHeap = " << hitIsOnHeap
1010 <<
", hitHeapWindow = " << hitHeapWindow);
1012 B2WARNING(
"TOPUnpacker: could not match data type inside unpackProdDebug()"
1013 <<
LogVar(
"evtType", evtType) <<
LogVar(
"evtVersion", evtVersion));
1018 if (hitHasWaveform) {
1019 numExpectedWaveforms += 1;
1022 if (hitMagicHeader != 0xB) {
1023 B2WARNING(
"TOPUnpacker: hit header magic word mismatch. should be 0xB."
1024 <<
LogVar(
"Magic word", hitMagicHeader));
1029 short hitVRise0 = expand13to16bits(word >> 16);
1030 short hitVRise1 = expand13to16bits(word);
1031 B2DEBUG(22, std::dec << array.
getIndex() <<
":\t" << setfill(
'0') << setw(4) << std::hex <<
1032 (word >> 16) <<
" " << setfill(
'0') << setw(4) << (word & 0xFFFF) << std::dec
1033 <<
"\thitVRise0 = " << hitVRise0
1034 <<
", hitVRise1 = " << hitVRise1);
1037 short hitVFall0 = expand13to16bits(word >> 16);
1038 short hitVFall1 = expand13to16bits(word);
1039 B2DEBUG(22, std::dec << array.
getIndex() <<
":\t" << setfill(
'0') << setw(4) << std::hex <<
1040 (word >> 16) <<
" " << setfill(
'0') << setw(4) << (word & 0xFFFF) << std::dec
1041 <<
"\thitVFall0 = " << hitVFall0
1042 <<
", hitVFall1 = " << hitVFall1);
1045 unsigned short hitSampleRise = (word >> 24);
1046 short hitDSampPeak = (word >> 20) & 0xF;
1047 short hitDSampFall = (word >> 16) & 0xF;
1048 unsigned short hitHeaderChecksum = word & 0xFFFF;
1049 B2DEBUG(22, std::dec << array.
getIndex() <<
":\t" << setfill(
'0') << setw(4) << std::hex <<
1050 (word >> 16) <<
" " << setfill(
'0') << setw(4) << (word & 0xFFFF) << std::dec
1051 <<
"\thitSampleRise = " << hitSampleRise
1052 <<
", hitDSampPeak = " << hitDSampPeak
1053 <<
", hitDSampFall = " << hitDSampFall
1054 <<
", hitheaderChecksum = " << hitHeaderChecksum
1058 B2WARNING(
"TOPUnpacker: hit checksum invalid.");
1063 auto* digit = m_rawDigits.appendNew(evtScrodID, TOPRawDigit::c_ProductionDebug);
1064 digit->setCarrierNumber(hitCarrier);
1065 digit->setASICNumber(hitAsic);
1066 digit->setASICChannel(hitChannel);
1067 digit->setASICWindow(hitWindow);
1068 digit->setLastWriteAddr(0);
1069 digit->setSampleRise(hitSampleRise);
1070 digit->setDeltaSamplePeak(hitDSampPeak);
1071 digit->setDeltaSampleFall(hitDSampFall);
1072 digit->setValueRise0(hitVRise0);
1073 digit->setValueRise1(hitVRise1);
1074 digit->setValuePeak(hitVPeak);
1075 digit->setValueFall0(hitVFall0);
1076 digit->setValueFall1(hitVFall1);
1077 digit->setTFine(hitTFine);
1078 digit->setIntegral(hitIntegral);
1079 digit->setRevo9Counter(evtRevo9Counter);
1080 digit->setPhase(evtPhase);
1083 if (hitHasWaveform) {
1084 digitsWithWaveform.push_back(digit);
1088 if (dataFormat == TOP::RawDataType::c_ProductionDebug01) {
1089 hitDebug = m_productionHitDebugs.appendNew(hitHasWaveform,
1092 hitIsOnHeap ? 428 + hitHeapWindow : hitWindow,
1093 hitIsWindowStraddle);
1094 }
else if (dataFormat == TOP::RawDataType::c_ProductionDebug02) {
1095 hitDebug = m_productionHitDebugs.appendNew(hitHasWaveform,
1098 hitIsOnHeap ? 428 + hitHeapWindow : hitWindow,
1099 hitIsWindowStraddle,
1101 hitIsOnHeapStraddle ? 428 + hitHeapWindowStraddle : hitWindow +
1106 for (
unsigned int i = 0; i < evtExtra; ++i) {
1108 B2DEBUG(22, std::dec << array.
getIndex() <<
":\t" << setfill(
'0') << setw(4) << std::hex <<
1109 (word >> 16) <<
" " << setfill(
'0') << setw(4) << (word & 0xFFFF) << std::dec
1110 <<
"\thit extra word " << i <<
" (" << evtExtra <<
")");
1114 if (m_addRelations and hitDebug) {
1115 digit->addRelationTo(hitDebug);
1122 unsigned int evtSdType = (word >> 24);
1123 unsigned int evtSdData = (word >> 12) & 0xFFF;
1124 unsigned int evtMagicFooter = (word >> 9) & 0x7;
1125 unsigned int evtNHits = word & 0x1FF;
1126 B2DEBUG(22, std::dec << array.
getIndex() <<
":\t" << setfill(
'0') << setw(4) << std::hex <<
1127 (word >> 16) <<
" " << setfill(
'0') << setw(4) << (word & 0xFFFF) << std::dec
1128 <<
"\tevtSdType = " << evtSdType
1129 <<
", evtSdData = " << evtSdData
1130 <<
", evtMagicFooter = " << evtMagicFooter
1131 <<
", evtNHits = " << evtNHits <<
" (" << numHitsFound <<
")");
1133 if (evtSdType != 0) {
1134 m_slowData.appendNew(evtScrodID, evtSdType, evtSdData);
1137 if (evtMagicFooter != 0x5) {
1138 B2WARNING(
"TOPUnpacker: event footer magic word mismatch. should be 0x5."
1139 <<
LogVar(
"Magic word", evtMagicFooter));
1143 B2DEBUG(22,
"the rest:");
1145 unsigned int numParsedWaveforms = 0;
1146 while (array.
peekWord() != 0x6c617374
1150 unsigned int wfNSamples = (word >> 16);
1151 unsigned int wfNWindows = (word >> 8) & 0x7;
1152 unsigned int wfCarrier = (word >> 5) & 0x3;
1153 unsigned int wfAsic = (word >> 3) & 0x3;
1154 unsigned int wfChannel = word & 0x7;
1157 const auto& mapper = m_topgp->getChannelMapper();
1158 unsigned channel = mapper.getChannel(boardstack, wfCarrier, wfAsic, wfChannel);
1159 int pixelID = mapper.getPixelID(channel);
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 <<
"\twfNSamples = " << wfNSamples
1164 <<
", wfNWindows = " << wfNWindows
1165 <<
", wfCarrier = " << wfCarrier
1166 <<
", wfAsic = " << wfAsic
1167 <<
", wfChannel " << wfChannel);
1169 if (wfNSamples != 32 && wfNSamples != 16) {
1170 B2WARNING(
"TOPUnpacker: suspicious value for wfNSamples."
1171 <<
LogVar(
"wfNSamples", wfNSamples));
1176 unsigned int wfStartSample = (word >> 25) & 0x3F;
1177 unsigned int wfWindowLogic = (word >> 16) & 0x1FF;
1178 unsigned int wfEventNumber = (word >> 9) & 0x7F;
1179 unsigned int wfWindowPhysical = word & 0x1FF;
1181 B2DEBUG(22, std::dec << array.
getIndex() <<
":\t" << setfill(
'0') << setw(4) << std::hex <<
1182 (word >> 16) <<
" " << setfill(
'0') << setw(4) << (word & 0xFFFF) << std::dec
1183 <<
"\twfStartSample = " << wfStartSample
1184 <<
", wfWindowLogic = " << wfWindowLogic
1185 <<
", wfEventNumber = " << wfEventNumber
1186 <<
", wfWindowPhysical = " << wfWindowPhysical);
1188 std::vector<short> wfSamples;
1190 for (
unsigned int i = 0; i < wfNSamples / 2; ++i) {
1191 short wfSampleLast = 0;
1192 short wfSampleFirst = 0;
1196 if (pedestalSubtracted) {
1197 wfSampleLast = (word >> 16);
1198 wfSampleFirst = word & 0xFFFF;
1200 wfSampleLast = (word >> 16) & 0xFFF;
1201 wfSampleFirst = word & 0xFFF;
1205 B2DEBUG(22, std::dec << array.
getIndex() <<
":\t" << setfill(
'0') << setw(4) << std::hex <<
1206 (word >> 16) <<
" " << setfill(
'0') << setw(4) << (word & 0xFFFF) << std::dec
1207 <<
"\twfSample" << 2 * i + 1 <<
" = " << wfSampleLast
1208 <<
", wfSample" << 2 * i <<
" = " << wfSampleFirst);
1210 wfSamples.push_back(wfSampleFirst);
1211 wfSamples.push_back(wfSampleLast);
1215 auto* waveform = m_waveforms.appendNew(moduleID, pixelID, channel, evtScrodID,
1216 wfWindowLogic, wfStartSample, wfSamples);
1217 waveform->setPedestalSubtractedFlag(pedestalSubtracted);
1218 waveform->setPhysicalWindow(wfWindowPhysical);
1219 if (numParsedWaveforms < digitsWithWaveform.size()) {
1220 const auto* digit = digitsWithWaveform[numParsedWaveforms];
1221 if (digit->getScrodChannel() == channel % 128) {
1222 digit->addRelationTo(waveform);
1224 B2WARNING(
"TOPUnpacker: hit and its waveform have different channel number."
1225 <<
LogVar(
"channel (hit)", digit->getScrodChannel())
1226 <<
LogVar(
"channel (waveform)", channel % 128));
1229 numParsedWaveforms += 1;
1233 if (numExpectedWaveforms != numParsedWaveforms) {
1234 B2WARNING(
"TOPUnpacker: number of expected and parsed waveforms does not match."
1235 <<
LogVar(
"expected", numExpectedWaveforms)
1236 <<
LogVar(
"parsed", numParsedWaveforms));
1243 void TOPUnpackerModule::endRun()
1245 B2INFO(
"TOPUnpacker: Channels seen per event statistics:");
1246 B2INFO(
"TOPUnpacker: nChn\tcount");
1247 for (
auto& entry : m_channelStatistics) {
1248 B2INFO(
"TOPUnpacker: " << entry.first <<
"\t\t" << entry.second);
1252 void TOPUnpackerModule::terminate()
The Raw TOP class Class for RawCOPPER class data taken by TOP Currently, this class is almost same as...
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