File indexing completed on 2025-06-04 22:36:08
0001 #include <array>
0002 #include <iomanip>
0003 #include <iostream>
0004 #include <iterator>
0005 #include <vector>
0006
0007 #include "CondFormats/HGCalObjects/interface/HGCalMappingCellIndexer.h"
0008 #include "CondFormats/HGCalObjects/interface/HGCalMappingModuleIndexer.h"
0009 #include "DataFormats/FEDRawData/interface/FEDRawData.h"
0010 #include "DataFormats/HGCalDigi/interface/HGCalDigiHost.h"
0011 #include "DataFormats/HGCalDigi/interface/HGCalECONDPacketInfoHost.h"
0012 #include "DataFormats/HGCalDigi/interface/HGCalFEDPacketInfoHost.h"
0013 #include "DataFormats/HGCalDigi/interface/HGCalRawDataDefinitions.h"
0014 #include "EventFilter/HGCalRawToDigi/interface/HGCalUnpacker.h"
0015 #include "EventFilter/HGCalRawToDigi/interface/UnpackerTools.h"
0016 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0017 #include "FWCore/Utilities/interface/Exception.h"
0018
0019 using namespace hgcal;
0020
0021 uint16_t HGCalUnpacker::parseFEDData(unsigned fedId,
0022 const FEDRawData& fed_data,
0023 const HGCalMappingModuleIndexer& moduleIndexer,
0024 const HGCalConfiguration& config,
0025 hgcaldigi::HGCalDigiHost& digis,
0026 hgcaldigi::HGCalECONDPacketInfoHost& econdPacketInfo,
0027 bool headerOnlyMode) {
0028
0029 const auto& fedReadoutSequence = moduleIndexer.getFEDReadoutSequences()[fedId];
0030
0031 const auto& fedConfig = config.feds[fedId];
0032
0033
0034 auto to_32b_words = [](const uint64_t* ptr_64b) {
0035 auto* ptr_32b = reinterpret_cast<const uint32_t*>(ptr_64b);
0036 return std::array<uint32_t, 2>{{ptr_32b[1], ptr_32b[0]}};
0037 };
0038
0039 auto to_econd_payload = [](const uint64_t* ptr_64b, uint64_t payload_length) -> std::vector<uint32_t> {
0040 std::vector<uint32_t> payload(payload_length, 0);
0041 auto* ptr_32b = reinterpret_cast<const uint32_t*>(ptr_64b);
0042 for (unsigned i = 0; i < payload_length; ++i) {
0043 payload[i] = ptr_32b[(i % 2 == 0) ? i + 1 : i - 1];
0044 }
0045 return payload;
0046 };
0047
0048
0049
0050
0051 const auto* const header = reinterpret_cast<const uint64_t*>(fed_data.data());
0052 const auto* const trailer = reinterpret_cast<const uint64_t*>(fed_data.data() + fed_data.size());
0053 LogDebug("[HGCalUnpacker]") << "fedId = " << fedId << " nwords (64b) = " << std::distance(header, trailer);
0054 const auto* ptr = header;
0055
0056 #ifdef EDM_ML_DEBUG
0057 for (unsigned iword = 0; ptr < trailer; ++iword) {
0058 LogDebug("[HGCalUnpacker]") << std::setw(8) << iword << ": 0x" << std::hex << std::setfill('0') << std::setw(16)
0059 << *ptr << " (" << std::setfill('0') << std::setw(8)
0060 << *(reinterpret_cast<const uint32_t*>(ptr) + 1) << " " << std::setfill('0')
0061 << std::setw(8) << *reinterpret_cast<const uint32_t*>(ptr) << ")" << std::dec;
0062 ++ptr;
0063 }
0064 LogDebug("[HGCalUnpacker]") << "@@@\n";
0065 ptr = header;
0066 #endif
0067
0068
0069
0070 auto slink_header = *(ptr + 1);
0071 if (((slink_header >> (BACKEND_FRAME::SLINK_BOE_POS + 32)) & BACKEND_FRAME::SLINK_BOE_MASK) !=
0072 fedConfig.slinkHeaderMarker) {
0073 uint32_t ECONDdenseIdx = moduleIndexer.getIndexForModule(fedId, 0);
0074 econdPacketInfo.view()[ECONDdenseIdx].exception() = 1;
0075 econdPacketInfo.view()[ECONDdenseIdx].location() = 0;
0076 edm::LogWarning("[HGCalUnpacker]") << "Expected a S-Link header (BOE: 0x" << std::hex << fedConfig.slinkHeaderMarker
0077 << "), got 0x" << std::hex
0078 << ((slink_header >> (BACKEND_FRAME::SLINK_BOE_POS + 32)) &
0079 BACKEND_FRAME::SLINK_BOE_MASK)
0080 << " from " << slink_header << ".";
0081 return (0x1 << hgcaldigi::FEDUnpackingFlags::ErrorSLinkHeader);
0082 }
0083
0084 ptr += 2;
0085
0086
0087 uint32_t globalECONDIdx = static_cast<uint32_t>(-1);
0088
0089
0090 bool hasActiveCBFlags(false);
0091 for (uint32_t captureblockIdx = 0; captureblockIdx < HGCalMappingModuleIndexer::maxCBperFED_ && ptr < trailer - 2;
0092 captureblockIdx++) {
0093
0094 LogDebug("[HGCalUnpacker]") << "@" << std::setw(8) << std::distance(header, ptr) << ": 0x" << std::hex
0095 << std::setfill('0') << std::setw(16) << *ptr << std::dec;
0096 auto cb_header = *ptr;
0097 LogDebug("[HGCalUnpacker]") << "fedId = " << fedId << ", captureblockIdx = " << captureblockIdx
0098 << ", cb_header = " << std::hex << std::setfill('0') << std::setw(16) << cb_header
0099 << std::dec;
0100
0101 if (((cb_header >> (BACKEND_FRAME::CAPTUREBLOCK_RESERVED_POS + 32)) & BACKEND_FRAME::CAPTUREBLOCK_RESERVED_MASK) !=
0102 fedConfig.cbHeaderMarker) {
0103
0104
0105 uint32_t ECONDdenseIdx = moduleIndexer.getIndexForModule(fedId, 0);
0106 econdPacketInfo.view()[ECONDdenseIdx].location() = (uint32_t)(ptr - header);
0107 if (cb_header == 0x0) {
0108 auto nToEnd = (fed_data.size() / 8 - 2) - std::distance(header, ptr);
0109 if (nToEnd == 1) {
0110 ptr++;
0111 LogDebug("[HGCalUnpacker]")
0112 << "fedId = " << fedId
0113 << ", 64b padding word caught before parsing all max capture blocks, captureblockIdx = "
0114 << captureblockIdx;
0115 econdPacketInfo.view()[ECONDdenseIdx].exception() = 7;
0116 return (0x1 << hgcaldigi::FEDUnpackingFlags::ErrorCaptureBlockHeader);
0117 }
0118 }
0119 econdPacketInfo.view()[ECONDdenseIdx].exception() = 2;
0120 edm::LogWarning("[HGCalUnpacker]") << "Expected a capture block header at word " << std::dec
0121 << (uint32_t)(ptr - header) << "/0x" << std::hex << (uint32_t)(ptr - header)
0122 << " (reserved word: 0x" << fedConfig.cbHeaderMarker << "), got 0x"
0123 << ((cb_header >> (BACKEND_FRAME::CAPTUREBLOCK_RESERVED_POS + 32)) &
0124 BACKEND_FRAME::CAPTUREBLOCK_RESERVED_MASK)
0125 << " from 0x" << cb_header << ".";
0126 return (0x1 << hgcaldigi::FEDUnpackingFlags::ErrorCaptureBlockHeader);
0127 }
0128 ++ptr;
0129
0130
0131 for (uint32_t econdIdx = 0; econdIdx < HGCalMappingModuleIndexer::maxECONDperCB_; econdIdx++) {
0132 auto econd_pkt_status = (cb_header >> (3 * econdIdx)) & 0b111;
0133 LogDebug("[HGCalUnpacker]") << "fedId = " << fedId << ", captureblockIdx = " << captureblockIdx
0134 << ", econdIdx = " << econdIdx << ", econd_pkt_status = " << econd_pkt_status;
0135 if (econd_pkt_status != backend::ECONDPacketStatus::InactiveECOND) {
0136
0137 globalECONDIdx++;
0138 }
0139 hasActiveCBFlags = (econd_pkt_status != backend::ECONDPacketStatus::Normal) &&
0140 (econd_pkt_status != backend::ECONDPacketStatus::InactiveECOND);
0141 bool pkt_exists =
0142 (econd_pkt_status == backend::ECONDPacketStatus::Normal) ||
0143 (econd_pkt_status == backend::ECONDPacketStatus::PayloadCRCError) ||
0144 (econd_pkt_status == backend::ECONDPacketStatus::EventIDMismatch) ||
0145 (fedConfig.mismatchPassthroughMode && econd_pkt_status == backend::ECONDPacketStatus::BCIDOrbitIDMismatch);
0146 if (!pkt_exists) {
0147 continue;
0148 }
0149
0150
0151 LogDebug("[HGCalUnpacker]") << "@" << std::setw(8) << std::distance(header, ptr) << ": 0x" << std::hex
0152 << std::setfill('0') << std::setw(16) << *ptr << std::dec;
0153 auto econd_headers = to_32b_words(ptr);
0154 uint32_t ECONDdenseIdx = moduleIndexer.getIndexForModule(fedId, globalECONDIdx);
0155 econdPacketInfo.view()[ECONDdenseIdx].location() = (uint32_t)(ptr - header);
0156 const auto econd_payload_length = ((econd_headers[0] >> ECOND_FRAME::PAYLOAD_POS) & ECOND_FRAME::PAYLOAD_MASK);
0157
0158
0159 if (((econd_headers[0] >> ECOND_FRAME::HEADER_POS) & ECOND_FRAME::HEADER_MASK) !=
0160 fedConfig.econds[globalECONDIdx].headerMarker) {
0161 econdPacketInfo.view()[ECONDdenseIdx].exception() = 3;
0162 edm::LogWarning("[HGCalUnpacker]")
0163 << "Expected a ECON-D header at word " << std::dec << (uint32_t)(ptr - header) << "/0x" << std::hex
0164 << (uint32_t)(ptr - header) << " (marker: 0x" << fedConfig.econds[globalECONDIdx].headerMarker
0165 << "), got 0x" << econd_headers[0] << " and payload=" << econd_payload_length << ".";
0166 return (0x1 << hgcaldigi::FEDUnpackingFlags::ErrorECONDHeader) |
0167 (hasActiveCBFlags << hgcaldigi::FEDUnpackingFlags::ActiveCaptureBlockFlags);
0168 }
0169
0170
0171 bool crcvalid = hgcal::econdCRCAnalysis(ptr, 0, econd_payload_length);
0172 LogDebug("[HGCalUnpacker]") << "crc value " << crcvalid;
0173 ++ptr;
0174
0175 if (!crcvalid) {
0176 hasActiveCBFlags = true;
0177 econd_pkt_status |=
0178 backend::ECONDPacketStatus::OfflinePayloadCRCError;
0179 }
0180 econdPacketInfo.view()[ECONDdenseIdx].cbFlag() = (uint16_t)(econd_pkt_status);
0181
0182
0183
0184 if (econd_payload_length > 469) {
0185 econdPacketInfo.view()[ECONDdenseIdx].exception() = 4;
0186 edm::LogWarning("[HGCalUnpacker]")
0187 << "Unpacked payload length=" << econd_payload_length << " exceeds the maximal length=469";
0188 return (0x1 << hgcaldigi::FEDUnpackingFlags::ECONDPayloadLengthOverflow) |
0189 (hasActiveCBFlags << hgcaldigi::FEDUnpackingFlags::ActiveCaptureBlockFlags);
0190 }
0191 const auto econdFlag = ((econd_headers[0] >> ECOND_FRAME::BITT_POS) & 0b1111111) +
0192 (((econd_headers[1] >> ECOND_FRAME::BITS_POS) & 0b1) << hgcaldigi::ECONDFlag::BITS_POS);
0193 econdPacketInfo.view()[ECONDdenseIdx].payloadLength() = (uint16_t)econd_payload_length;
0194 econdPacketInfo.view()[ECONDdenseIdx].econdFlag() = (uint8_t)econdFlag;
0195 econdPacketInfo.view()[ECONDdenseIdx].exception() = 0;
0196
0197
0198 auto econd_payload = to_econd_payload(ptr, econd_payload_length);
0199
0200
0201 ptr += (econd_payload_length + 1) / 2;
0202
0203 LogDebug("[HGCalUnpacker]") << "fedId = " << fedId << ", captureblockIdx = " << captureblockIdx
0204 << ", econdIdx = " << econdIdx << ", econd_headers = " << std::hex
0205 << std::setfill('0') << std::setw(8) << econd_headers[0] << " " << econd_headers[1]
0206 << std::dec << ", econd_payload_length = " << econd_payload_length;
0207
0208 if ((((econd_headers[0] >> ECOND_FRAME::HT_POS) & ECOND_FRAME::HT_MASK) >= 0b10) ||
0209 (((econd_headers[0] >> ECOND_FRAME::EBO_POS) & ECOND_FRAME::EBO_MASK) >= 0b10) ||
0210 (((econd_headers[0] >> ECOND_FRAME::BITM_POS) & 0b1) == 0) || econd_payload_length == 0 ||
0211 econd_pkt_status == backend::ECONDPacketStatus::OfflinePayloadCRCError ||
0212 econd_pkt_status == backend::ECONDPacketStatus::InactiveECOND || headerOnlyMode) {
0213 continue;
0214 }
0215
0216
0217 const auto enabledErx = fedReadoutSequence.enabledErx_[globalECONDIdx];
0218 const auto erxMax = moduleIndexer.getGlobalTypesNErx()[fedReadoutSequence.readoutTypes_[globalECONDIdx]];
0219 const bool pass_through_mode = (econd_headers[0] >> ECOND_FRAME::BITP_POS) & 0b1;
0220
0221 unsigned iword = 0;
0222 if (!pass_through_mode) {
0223
0224 LogDebug("[HGCalUnpacker]") << "Standard ECON-D, erxMax=" << erxMax << "enabledErx= " << enabledErx;
0225 for (uint32_t erxIdx = 0; erxIdx < erxMax; erxIdx++) {
0226
0227 if ((enabledErx >> erxIdx & 1) == 0) {
0228 continue;
0229 }
0230 LogDebug("[HGCalUnpacker]") << "fedId = " << fedId << ", captureblockIdx = " << captureblockIdx
0231 << ", econdIdx = " << econdIdx << ", erxIdx=" << erxIdx;
0232
0233 econdPacketInfo.view()[ECONDdenseIdx].cm()(erxIdx, 0) =
0234 (econd_payload[iword] >> ECOND_FRAME::COMMONMODE0_POS) & ECOND_FRAME::COMMONMODE0_MASK;
0235 econdPacketInfo.view()[ECONDdenseIdx].cm()(erxIdx, 1) =
0236 (econd_payload[iword] >> ECOND_FRAME::COMMONMODE1_POS) & ECOND_FRAME::COMMONMODE1_MASK;
0237
0238 if (((econd_payload[iword] >> ECOND_FRAME::ERXFORMAT_POS) & ECOND_FRAME::ERXFORMAT_MASK) == 1) {
0239 LogDebug("[HGCalUnpacker]") << "eRx " << erxIdx << " is empty";
0240 iword += 1;
0241 continue;
0242 }
0243
0244
0245 uint16_t cmSum = ((econd_payload[iword] >> ECOND_FRAME::COMMONMODE0_POS) & ECOND_FRAME::COMMONMODE0_MASK) +
0246 ((econd_payload[iword] >> ECOND_FRAME::COMMONMODE1_POS) & ECOND_FRAME::COMMONMODE1_MASK);
0247 uint64_t erxHeader = ((uint64_t)econd_payload[iword] << 32) | ((uint64_t)econd_payload[iword + 1]);
0248 LogDebug("[HGCalUnpacker]") << "erx_headers = 0x" << std::hex << std::setfill('0') << std::setw(16)
0249 << erxHeader << ", cmSum = " << std::dec << cmSum;
0250 iword += 2;
0251
0252
0253 uint32_t iBit = 0;
0254 for (uint32_t channelIdx = 0; channelIdx < HGCalMappingCellIndexer::maxChPerErx_; channelIdx++) {
0255 uint32_t denseIdx = moduleIndexer.getIndexForModuleData(fedId, globalECONDIdx, erxIdx, channelIdx);
0256
0257
0258 if (((erxHeader >> channelIdx) & 1) == 0) {
0259 continue;
0260 }
0261
0262 const uint32_t tempIndex = iBit / 32 + iword;
0263 const uint32_t tempBit = iBit % 32;
0264 const uint32_t temp = (tempBit == 0) ? econd_payload[tempIndex]
0265 : (econd_payload[tempIndex] << tempBit) |
0266 (econd_payload[tempIndex + 1] >> (32 - tempBit));
0267 const uint32_t code = temp >> 28;
0268 digis.view()[denseIdx].tctp() = tctp_[code];
0269 digis.view()[denseIdx].adcm1() = (temp >> adcm1Shift_[code]) & adcm1Mask_[code];
0270 digis.view()[denseIdx].adc() = (temp >> adcShift_[code]) & adcMask_[code];
0271 digis.view()[denseIdx].tot() = (temp >> totShift_[code]) & totMask_[code];
0272 digis.view()[denseIdx].toa() = (temp >> toaShift_[code] & toaMask_[code]);
0273 digis.view()[denseIdx].cm() = cmSum;
0274 digis.view()[denseIdx].flags() = 0;
0275 iBit += erxBodyBits_[code];
0276 }
0277 iword += iBit / 32;
0278 if (iBit % 32 != 0) {
0279 iword += 1;
0280 }
0281 }
0282 } else {
0283
0284 LogDebug("[HGCalUnpacker]") << "Passthrough ECON-D, erxMax=" << erxMax << "enabledErx= " << enabledErx;
0285 for (uint32_t erxIdx = 0; erxIdx < erxMax; erxIdx++) {
0286
0287 if ((enabledErx >> erxIdx & 1) == 0) {
0288 continue;
0289 }
0290 LogDebug("[HGCalUnpacker]") << "fedId = " << fedId << ", captureblockIdx = " << captureblockIdx
0291 << ", econdIdx = " << econdIdx << ", erxIdx=" << erxIdx;
0292
0293 econdPacketInfo.view()[ECONDdenseIdx].cm()(erxIdx, 0) =
0294 (econd_payload[iword] >> ECOND_FRAME::COMMONMODE0_POS) & ECOND_FRAME::COMMONMODE0_MASK;
0295 econdPacketInfo.view()[ECONDdenseIdx].cm()(erxIdx, 1) =
0296 (econd_payload[iword] >> ECOND_FRAME::COMMONMODE1_POS) & ECOND_FRAME::COMMONMODE1_MASK;
0297
0298 if (((econd_payload[iword] >> ECOND_FRAME::ERXFORMAT_POS) & ECOND_FRAME::ERXFORMAT_MASK) == 1) {
0299 LogDebug("[HGCalUnpacker]") << "eRx " << erxIdx << " is empty";
0300 iword += 1;
0301 continue;
0302 }
0303
0304
0305 uint16_t cmSum = ((econd_payload[iword] >> ECOND_FRAME::COMMONMODE0_POS) & ECOND_FRAME::COMMONMODE0_MASK) +
0306 ((econd_payload[iword] >> ECOND_FRAME::COMMONMODE1_POS) & ECOND_FRAME::COMMONMODE1_MASK);
0307 uint64_t erxHeader = ((uint64_t)econd_payload[iword] << 32) | ((uint64_t)econd_payload[iword + 1]);
0308 LogDebug("[HGCalUnpacker]") << "erx_headers = 0x" << std::hex << std::setfill('0') << std::setw(16)
0309 << erxHeader << ", cmSum = " << std::dec << cmSum;
0310 iword += 2;
0311
0312
0313 for (uint32_t channelIdx = 0; channelIdx < HGCalMappingCellIndexer::maxChPerErx_; channelIdx++) {
0314 uint32_t denseIdx = moduleIndexer.getIndexForModuleData(fedId, globalECONDIdx, erxIdx, channelIdx);
0315
0316
0317 if (((erxHeader >> channelIdx) & 1) == 0) {
0318 continue;
0319 }
0320
0321
0322 if (fedConfig.econds[globalECONDIdx].rocs[erxIdx / 2].charMode) {
0323
0324 digis.view()[denseIdx].tctp() = (econd_payload[iword] >> 30) & 0b11;
0325 digis.view()[denseIdx].adcm1() = 0;
0326 digis.view()[denseIdx].adc() = (econd_payload[iword] >> 20) & 0b1111111111;
0327 digis.view()[denseIdx].tot() = (econd_payload[iword] >> 10) & 0b1111111111;
0328 digis.view()[denseIdx].toa() = econd_payload[iword] & 0b1111111111;
0329 digis.view()[denseIdx].cm() = cmSum;
0330 digis.view()[denseIdx].flags() = hgcal::DIGI_FLAG::Characterization;
0331 } else {
0332
0333 digis.view()[denseIdx].tctp() = (econd_payload[iword] >> 30) & 0b11;
0334
0335 digis.view()[denseIdx].adcm1() = (econd_payload[iword] >> 20) & 0b1111111111;
0336 if (econd_payload[iword] >> 31 & 0b1) {
0337 digis.view()[denseIdx].adc() = 0;
0338 digis.view()[denseIdx].tot() = (econd_payload[iword] >> 10) & 0b1111111111;
0339 } else {
0340 digis.view()[denseIdx].adc() = (econd_payload[iword] >> 10) & 0b1111111111;
0341 digis.view()[denseIdx].tot() = 0;
0342 }
0343 digis.view()[denseIdx].toa() = econd_payload[iword] & 0b1111111111;
0344 digis.view()[denseIdx].cm() = cmSum;
0345 digis.view()[denseIdx].flags() = hgcal::DIGI_FLAG::Normal;
0346 }
0347
0348 iword += 1;
0349 }
0350 }
0351 }
0352
0353 if (iword != econd_payload_length - 1) {
0354 econdPacketInfo.view()[ECONDdenseIdx].exception() = 5;
0355 edm::LogWarning("[HGCalUnpacker]")
0356 << "Mismatch between unpacked and expected ECON-D #" << (int)globalECONDIdx << " payload length\n"
0357 << " unpacked payload length=" << iword + 1 << "\n"
0358 << " expected payload length=" << econd_payload_length;
0359 return (0x1 << hgcaldigi::FEDUnpackingFlags::ECONDPayloadLengthMismatch) |
0360 (hasActiveCBFlags << hgcaldigi::FEDUnpackingFlags::ActiveCaptureBlockFlags);
0361 }
0362 }
0363 }
0364
0365
0366 if (std::distance(ptr, header) % 2) {
0367 ++ptr;
0368 }
0369
0370
0371 if (ptr + 2 != trailer) {
0372 uint32_t ECONDdenseIdx = moduleIndexer.getIndexForModule(fedId, 0);
0373 econdPacketInfo.view()[ECONDdenseIdx].exception() = 6;
0374 edm::LogWarning("[HGCalUnpacker]") << "Error finding the S-link trailer, expected at" << std::dec
0375 << (uint32_t)(trailer - header) << "/0x" << std::hex
0376 << (uint32_t)(trailer - header) << "Unpacked trailer at" << std::dec
0377 << (uint32_t)(trailer - header + 2) << "/0x" << std::hex
0378 << (uint32_t)(ptr - header + 2);
0379 return (0x1 << hgcaldigi::FEDUnpackingFlags::ErrorSLinkTrailer) |
0380 (hasActiveCBFlags << hgcaldigi::FEDUnpackingFlags::ActiveCaptureBlockFlags);
0381 }
0382
0383 return (0x1 << hgcaldigi::FEDUnpackingFlags::NormalUnpacking) |
0384 (hasActiveCBFlags << hgcaldigi::FEDUnpackingFlags::ActiveCaptureBlockFlags);
0385 }