Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-05-04 04:04:25

0001 /****************************************************************************
0002  *
0003  * This is a part of HGCAL offline software.
0004  * Authors:
0005  *   Yulun Miao, Northwestern University
0006  *   Huilin Qu, CERN
0007  *   Laurent Forthomme, CERN
0008  *
0009  ****************************************************************************/
0010 
0011 #include "EventFilter/HGCalRawToDigi/interface/HGCalUnpacker.h"
0012 
0013 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0014 #include "FWCore/Utilities/interface/Exception.h"
0015 
0016 template <class D>
0017 HGCalUnpacker<D>::HGCalUnpacker(HGCalUnpackerConfig config)
0018     : config_(config),
0019       channelData_(config_.channelMax),
0020       commonModeIndex_(config_.channelMax),
0021       commonModeData_(config_.commonModeMax) {}
0022 
0023 template <class D>
0024 void HGCalUnpacker<D>::parseSLink(
0025     const std::vector<uint32_t>& inputArray,
0026     const std::function<uint16_t(uint16_t sLink, uint8_t captureBlock, uint8_t econd)>& enabledERXMapping,
0027     const std::function<D(HGCalElectronicsId elecID)>& logicalMapping) {
0028   uint16_t sLink = 0;
0029 
0030   channelDataSize_ = 0;
0031   commonModeDataSize_ = 0;
0032   badECOND_.clear();
0033 
0034   for (uint32_t iword = 0; iword < inputArray.size();) {  // loop through the S-Link
0035     //----- parse the S-Link header
0036     if (((inputArray[iword] >> kSLinkBOEShift) & kSLinkBOEMask) != config_.sLinkBOE)  // sanity check
0037       throw cms::Exception("CorruptData")
0038           << "Expected a S-Link header at word " << std::dec << iword << "/0x" << std::hex << iword << " (BOE: 0x"
0039           << config_.sLinkBOE << "), got 0x" << inputArray[iword] << ".";
0040 
0041     iword += 4;  // length of the S-Link header (128 bits)
0042 
0043     LogDebug("HGCalUnpack") << "SLink=" << sLink;
0044 
0045     //----- parse the S-Link body
0046     for (uint8_t captureBlock = 0; captureBlock < config_.sLinkCaptureBlockMax;
0047          captureBlock++) {  // loop through all capture blocks
0048       //----- parse the capture block header
0049       if (((inputArray[iword] >> kCaptureBlockReservedShift) & kCaptureBlockReservedMask) !=
0050           config_.captureBlockReserved)  // sanity check
0051         throw cms::Exception("CorruptData")
0052             << "Expected a capture block header at word " << std::dec << iword << "/0x" << std::hex << iword
0053             << " (reserved word: 0x" << config_.captureBlockReserved << "), got 0x" << inputArray[iword] << ".";
0054 
0055       const uint64_t captureBlockHeader = ((uint64_t)inputArray[iword] << 32) | ((uint64_t)inputArray[iword + 1]);
0056       iword += 2;  // length of capture block header (64 bits)
0057 
0058       LogDebug("HGCalUnpack") << "Capture block=" << (int)captureBlock << ", capture block header=0x" << std::hex
0059                               << captureBlockHeader;
0060 
0061       //----- parse the capture block body
0062       for (uint8_t econd = 0; econd < config_.captureBlockECONDMax; econd++) {  // loop through all ECON-Ds
0063         if (((captureBlockHeader >> (3 * econd)) & kCaptureBlockECONDStatusMask) >= 0b100)
0064           continue;  // only pick active ECON-Ds
0065 
0066         //----- parse the ECON-D header
0067         // (the second word of ECON-D header contains no information for unpacking, use only the first one)
0068         if (((inputArray[iword] >> kHeaderShift) & kHeaderMask) != config_.econdHeaderMarker)  // sanity check
0069           throw cms::Exception("CorruptData")
0070               << "Expected a ECON-D header at word " << std::dec << iword << "/0x" << std::hex << iword
0071               << " (marker: 0x" << config_.econdHeaderMarker << "), got 0x" << inputArray[iword] << ".";
0072 
0073         const auto& econdHeader = inputArray[iword];
0074         iword += 2;  // length of ECON-D header (2 * 32 bits)
0075 
0076         LogDebug("HGCalUnpack") << "ECON-D #" << (int)econd << ", first word of ECON-D header=0x" << std::hex
0077                                 << econdHeader;
0078 
0079         //----- extract the payload length
0080         const uint32_t payloadLength = (econdHeader >> kPayloadLengthShift) & kPayloadLengthMask;
0081         if (payloadLength > config_.payloadLengthMax)  // if payload length too big
0082           throw cms::Exception("CorruptData") << "Unpacked payload length=" << payloadLength
0083                                               << " exceeds the maximal length=" << config_.payloadLengthMax;
0084 
0085         LogDebug("HGCalUnpack") << "ECON-D #" << (int)econd << ", payload length=" << payloadLength;
0086         //Quality check
0087         if ((((captureBlockHeader >> (3 * econd)) & kCaptureBlockECONDStatusMask) != 0b000) ||
0088             (((econdHeader >> kHTShift) & kHTMask) >= 0b10) || (((econdHeader >> kEBOShift) & kEBOMask) >= 0b10) ||
0089             (((econdHeader >> kMatchShift) & kMatchMask) == 0) ||
0090             (((econdHeader >> kTruncatedShift) & kTruncatedMask) == 1)) {  // bad ECOND
0091           LogDebug("HGCalUnpack") << "ECON-D failed quality check, HT=" << (econdHeader >> kHTShift & kHTMask)
0092                                   << ", EBO=" << (econdHeader >> kEBOShift & kEBOMask)
0093                                   << ", M=" << (econdHeader >> kMatchShift & kMatchMask)
0094                                   << ", T=" << (econdHeader >> kTruncatedShift & kTruncatedMask);
0095           badECOND_.emplace_back(iword - 2);
0096           iword += payloadLength;  // skip the current ECON-D (using the payload length parsed above)
0097 
0098           if (iword % 2 != 0) {  //TODO: check this
0099             LogDebug("HGCalUnpacker") << "Padding ECON-D payload to 2 32-bit words (remainder: " << (iword % 2) << ").";
0100             iword += 1;
0101           }
0102           continue;  // go to the next ECON-D
0103         }
0104         const uint32_t econdBodyStart = iword;  // for the ECON-D length check
0105         //----- parse the ECON-D body
0106         if (((econdHeader >> kPassThroughShift) & kPassThroughMask) == 0) {
0107           // standard ECON-D
0108           LogDebug("HGCalUnpack") << "Standard ECON-D";
0109           const auto enabledERX = enabledERXMapping(sLink, captureBlock, econd);
0110           for (uint8_t erx = 0; erx < config_.econdERXMax; erx++) {
0111             //loop through eRx
0112             //pick active eRx
0113             if ((enabledERX >> erx & 1) == 0)
0114               continue;
0115 
0116             //----- parse the eRX subpacket header
0117             //common mode
0118             LogDebug("HGCalUnpack") << "ECON-D:eRx=" << (int)econd << ":" << (int)erx
0119                                     << ", first word of the eRx header=0x" << std::hex << inputArray[iword] << "\n"
0120                                     << "  extracted common mode 0=0x" << std::hex
0121                                     << ((inputArray[iword] >> kCommonmode0Shift) & kCommonmode0Mask) << std::dec
0122                                     << ", saved at " << commonModeDataSize_ << "\n"
0123                                     << "  extracted common mode 1=0x" << std::hex
0124                                     << ((inputArray[iword] >> kCommonmode1Shift) & kCommonmode1Mask) << std::dec
0125                                     << ", saved at " << (commonModeDataSize_ + 1);
0126             commonModeData_[commonModeDataSize_] = (inputArray[iword] >> kCommonmode0Shift) & kCommonmode0Mask;
0127             commonModeData_[commonModeDataSize_ + 1] = (inputArray[iword] >> kCommonmode1Shift) & kCommonmode1Mask;
0128             if ((erx % 2 == 0 && (enabledERX >> (erx + 1) & 1) == 0) ||
0129                 (erx % 2 == 1 && (enabledERX >> (erx - 1) & 1) == 0)) {
0130               commonModeDataSize_ += 2;
0131               commonModeData_[commonModeDataSize_] = commonModeData_[commonModeDataSize_ - 2];
0132               commonModeData_[commonModeDataSize_ + 1] = commonModeData_[commonModeDataSize_ - 1];
0133               LogDebug("HGCalUnpack") << "half ROC turned on, padding to 4 common modes\n"
0134                                       << "0x" << std::hex << commonModeData_[commonModeDataSize_ - 2] << std::dec
0135                                       << " saved at " << commonModeDataSize_ << "\n"
0136                                       << "0x" << std::hex << commonModeData_[commonModeDataSize_ - 1] << std::dec
0137                                       << " saved at " << commonModeDataSize_ + 1;
0138             }
0139             // empty check
0140             if (((inputArray[iword] >> kFormatShift) & kFormatMask) == 1) {  // empty
0141               LogDebug("HGCalUnpack") << "eRx empty";
0142               iword += 1;  // length of an empty eRx header (32 bits)
0143               continue;    // go to the next eRx
0144             }
0145             // regular mode
0146             const uint64_t erxHeader = ((uint64_t)inputArray[iword] << 32) | ((uint64_t)inputArray[iword + 1]);
0147             iword += 2;  // length of a standard eRx header (2 * 32 bits)
0148             LogDebug("HGCalUnpack") << "whole eRx header=0x" << std::hex << erxHeader;
0149 
0150             //----- parse the eRx subpacket body
0151             uint32_t bitCounter = 0;
0152             for (uint8_t channel = 0; channel < config_.erxChannelMax; channel++) {  // loop through all channels in eRx
0153               if (((erxHeader >> channel) & 1) == 0)
0154                 continue;  // only pick active channels
0155               const HGCalElectronicsId id(true, sLink, captureBlock, econd, erx, channel);
0156               commonModeIndex_[channelDataSize_] = commonModeDataSize_ / 4 * 4;
0157               const uint32_t tempIndex = bitCounter / 32 + iword;
0158               const uint8_t tempBit = bitCounter % 32;
0159               const uint32_t temp =
0160                   (tempBit == 0) ? inputArray[tempIndex]
0161                                  : (inputArray[tempIndex] << tempBit) | (inputArray[tempIndex + 1] >> (32 - tempBit));
0162               const uint8_t code = temp >> 28;
0163               // use if and else here
0164               channelData_[channelDataSize_] = HGCROCChannelDataFrame<D>(
0165                   logicalMapping(id),
0166                   ((temp << erxBodyLeftShift_[code]) >> erxBodyRightShift_[code]) & erxBodyMask_[code]);
0167               bitCounter += erxBodyBits_[code];
0168               if (code == 0b0010)
0169                 channelData_[channelDataSize_].fillFlag1(1);
0170               LogDebug("HGCalUnpack") << "Word " << channelDataSize_ << ", ECON-D:eRx:channel=" << (int)econd << ":"
0171                                       << (int)erx << ":" << (int)channel << "\n"
0172                                       << "  assigned common mode index=" << commonModeIndex_.at(channelDataSize_)
0173                                       << "\n"
0174                                       << "  full word readout=0x" << std::hex << temp << std::dec << ", code=0x"
0175                                       << std::hex << (int)code << std::dec << "\n"
0176                                       << "  extracted channel data=0x" << std::hex
0177                                       << channelData_[channelDataSize_].raw();
0178               channelDataSize_++;
0179             }
0180             // pad to the whole word
0181             iword += bitCounter / 32;
0182             if (bitCounter % 32 != 0)
0183               iword += 1;
0184 
0185             if (commonModeDataSize_ + 1 > config_.commonModeMax)
0186               throw cms::Exception("HGCalUnpack") << "Too many common mode data unpacked: " << (commonModeDataSize_ + 1)
0187                                                   << " >= " << config_.commonModeMax << ".";
0188             commonModeDataSize_ += 2;
0189             // eRx subpacket has no trailer
0190           }
0191         } else {
0192           // passthrough ECON-D
0193           LogDebug("HGCalUnpack") << "Passthrough ECON-D";
0194           const auto enabledERX = enabledERXMapping(sLink, captureBlock, econd);
0195           for (uint8_t erx = 0; erx < config_.econdERXMax; erx++) {  // loop through all eRxs
0196             if ((enabledERX >> erx & 1) == 0)
0197               continue;  // only pick active eRxs
0198 
0199             //----- eRX subpacket header
0200             // common mode
0201             uint32_t temp = inputArray[iword];
0202             LogDebug("HGCalUnpack") << "ECON-D:eRx=" << (int)econd << ":" << (int)erx
0203                                     << ", first word of the eRx header=0x" << std::hex << temp << std::dec << "\n"
0204                                     << "  extracted common mode 0=0x" << std::hex
0205                                     << ((temp >> kCommonmode0Shift) & kCommonmode0Mask) << std::dec << ", saved at "
0206                                     << commonModeDataSize_ << "\n"
0207                                     << "  extracted common mode 1=0x" << std::hex
0208                                     << ((temp >> kCommonmode1Shift) & kCommonmode1Mask) << std::dec << ", saved at "
0209                                     << (commonModeDataSize_ + 1);
0210             commonModeData_[commonModeDataSize_] = (temp >> kCommonmode0Shift) & kCommonmode0Mask;
0211             commonModeData_[commonModeDataSize_ + 1] = (temp >> kCommonmode1Shift) & kCommonmode1Mask;
0212             if ((erx % 2 == 0 && (enabledERX >> (erx + 1) & 1) == 0) ||
0213                 (erx % 2 == 1 && (enabledERX >> (erx - 1) & 1) == 0)) {
0214               commonModeDataSize_ += 2;
0215               commonModeData_[commonModeDataSize_] = commonModeData_[commonModeDataSize_ - 2];
0216               commonModeData_[commonModeDataSize_ + 1] = commonModeData_[commonModeDataSize_ - 1];
0217               LogDebug("HGCalUnpack") << "half ROC turned on, padding to 4 common modes\n"
0218                                       << "0x" << std::hex << commonModeData_[commonModeDataSize_ - 2] << std::dec
0219                                       << " saved at " << commonModeDataSize_ << "\n"
0220                                       << "0x" << std::hex << commonModeData_[commonModeDataSize_ - 1] << std::dec
0221                                       << " saved at " << commonModeDataSize_ + 1;
0222             }
0223             iword += 2;  // length of the standard eRx header (2 * 32 bits)
0224             for (uint8_t channel = 0; channel < config_.erxChannelMax; channel++) {  // loop through all channels in eRx
0225               const HGCalElectronicsId id(true, sLink, captureBlock, econd, erx, channel);
0226               commonModeIndex_[channelDataSize_] = commonModeDataSize_ / 4 * 4;
0227               channelData_[channelDataSize_] =
0228                   HGCROCChannelDataFrame<HGCalElectronicsId>(logicalMapping(id), inputArray[iword]);
0229               LogDebug("HGCalUnpack") << "Word " << channelDataSize_ << ", ECON-D:eRx:channel=" << (int)econd << ":"
0230                                       << (int)erx << ":" << (int)channel << ", HGCalElectronicsId=" << id.raw()
0231                                       << ", assigned common mode index=" << commonModeIndex_.at(channelDataSize_)
0232                                       << "\n"
0233                                       << "extracted channel data=0x" << std::hex
0234                                       << channelData_.at(channelDataSize_).raw();
0235               channelDataSize_++;
0236               iword++;
0237             }
0238             if (commonModeDataSize_ + 1 > config_.commonModeMax)
0239               throw cms::Exception("HGCalUnpack") << "Too many common mode data unpacked: " << (commonModeDataSize_ + 1)
0240                                                   << " >= " << config_.commonModeMax << ".";
0241             commonModeDataSize_ += 2;
0242           }
0243         }
0244         //----- parse the ECON-D trailer
0245         // (no information needed from ECON-D trailer in unpacker, skip it)
0246         iword += 1;  // length of the ECON-D trailer (32 bits CRC)
0247 
0248         if (iword - econdBodyStart != payloadLength)
0249           throw cms::Exception("CorruptData")
0250               << "Mismatch between unpacked and expected ECON-D #" << (int)econd << " payload length\n"
0251               << "  unpacked payload length=" << iword - econdBodyStart << "\n"
0252               << "  expected payload length=" << payloadLength;
0253         // pad to 2 words
0254         if (iword % 2 != 0) {  //TODO: check this
0255           LogDebug("HGCalUnpacker") << "Padding ECON-D payload to 2 32-bit words (remainder: " << (iword % 2) << ").";
0256           iword += 1;
0257         }
0258       }
0259       //----- capture block has no trailer
0260       // pad to 4 words
0261       if (iword % 4 != 0) {  //TODO: check this
0262         LogDebug("HGCalUnpacker") << "Padding capture block to 4 32-bit words (remainder: " << (iword % 4) << ").";
0263         iword += 4 - (iword % 4);
0264       }
0265     }
0266     //----- parse the S-Link trailer
0267     // (no information is needed in unpacker)
0268 
0269     iword += 4;  // length of the S-Link trailer (128 bits)
0270     sLink++;
0271   }
0272   channelData_.resize(channelDataSize_);
0273   commonModeIndex_.resize(channelDataSize_);
0274   commonModeData_.resize(commonModeDataSize_);
0275   return;
0276 }
0277 
0278 template <class D>
0279 void HGCalUnpacker<D>::parseCaptureBlock(
0280     const std::vector<uint32_t>& inputArray,
0281     const std::function<uint16_t(uint16_t sLink, uint8_t captureBlock, uint8_t econd)>& enabledERXMapping,
0282     const std::function<D(HGCalElectronicsId elecID)>& logicalMapping) {
0283   uint16_t sLink = 0;
0284   uint8_t captureBlock = 0;
0285 
0286   channelDataSize_ = 0;
0287   commonModeDataSize_ = 0;
0288   badECOND_.clear();
0289 
0290   for (uint32_t iword = 0; iword < inputArray.size();) {  // loop through all capture blocks
0291 
0292     //----- parse the capture block header
0293     if (((inputArray[iword] >> kCaptureBlockReservedShift) & kCaptureBlockReservedMask) != config_.captureBlockReserved)
0294       throw cms::Exception("CorruptData")
0295           << "Expected a capture block header at word " << std::dec << iword << "/0x" << std::hex << iword
0296           << " (reserved word: 0x" << config_.captureBlockReserved << "), got 0x" << inputArray[iword] << ".";
0297 
0298     const uint64_t captureBlockHeader = ((uint64_t)inputArray[iword] << 32) | ((uint64_t)inputArray[iword + 1]);
0299     LogDebug("HGCalUnpack") << "Capture block=" << (int)captureBlock << ", capture block header=0x" << std::hex
0300                             << captureBlockHeader;
0301     iword += 2;  // length of capture block header (64 bits)
0302 
0303     //----- parse the capture block body
0304     for (uint8_t econd = 0; econd < config_.captureBlockECONDMax; econd++) {  // loop through all ECON-Ds
0305       if ((captureBlockHeader >> (3 * econd) & kCaptureBlockECONDStatusMask) >= 0b100)
0306         continue;  // only pick the active ECON-Ds
0307 
0308       //----- parse the ECON-D header
0309       // (the second word of ECON-D header contains no information useful for unpacking, use only the first one)
0310       if (((inputArray[iword] >> kHeaderShift) & kHeaderMask) != config_.econdHeaderMarker)  // sanity check
0311         throw cms::Exception("CorruptData")
0312             << "Expected a ECON-D header at word " << std::dec << iword << "/0x" << std::hex << iword << " (marker: 0x"
0313             << config_.econdHeaderMarker << "), got 0x" << inputArray[iword] << ".";
0314 
0315       const uint32_t econdHeader = inputArray[iword];
0316       iword += 2;  // length of ECON-D header (2 * 32 bits)
0317 
0318       LogDebug("HGCalUnpack") << "ECON-D #" << (int)econd << ", first word of ECON-D header=0x" << std::hex
0319                               << econdHeader;
0320 
0321       //----- extract the payload length
0322       const uint32_t payloadLength = ((econdHeader >> kPayloadLengthShift)) & kPayloadLengthMask;
0323       if (payloadLength > config_.payloadLengthMax)  // payload length is too large
0324         throw cms::Exception("CorruptData") << "Unpacked payload length=" << payloadLength
0325                                             << " exceeds the maximal length=" << config_.payloadLengthMax;
0326       LogDebug("HGCalUnpack") << "ECON-D #" << (int)econd << ", payload length = " << payloadLength;
0327 
0328       if ((((captureBlockHeader >> (3 * econd)) & kCaptureBlockECONDStatusMask) != 0b000) ||
0329           (((econdHeader >> kHTShift) & kHTMask) >= 0b10) || (((econdHeader >> kEBOShift) & kEBOMask) >= 0b10) ||
0330           (((econdHeader >> kMatchShift) & kMatchMask) == 0) ||
0331           (((econdHeader >> kTruncatedShift) & kTruncatedMask) == 1)) {  // quality check failed: bad ECON-D
0332         LogDebug("HGCalUnpack") << "ECON-D failed quality check, HT=" << (econdHeader >> kHTShift & kHTMask)
0333                                 << ", EBO=" << (econdHeader >> kEBOShift & kEBOMask)
0334                                 << ", M=" << (econdHeader >> kMatchShift & kMatchMask)
0335                                 << ", T=" << (econdHeader >> kTruncatedShift & kTruncatedMask);
0336         badECOND_.emplace_back(iword - 2);
0337         iword += payloadLength;  // skip the current ECON-D (using the payload length parsed above)
0338 
0339         if (iword % 2 != 0) {  //TODO: check this
0340           LogDebug("HGCalUnpacker") << "Padding ECON-D payload to 2 32-bit words (remainder: " << (iword % 2) << ").";
0341           iword += 1;
0342         }
0343         continue;  // go to the next ECON-D
0344       }
0345 
0346       //----- parse the ECON-D body
0347       const uint32_t econdBodyStart = iword;  // for the ECON-D length check
0348       if (((econdHeader >> kPassThroughShift) & kPassThroughMask) == 0) {
0349         // standard ECON-D
0350         LogDebug("HGCalUnpack") << "Standard ECON-D";
0351         const auto enabledERX = enabledERXMapping(sLink, captureBlock, econd);
0352         for (uint8_t erx = 0; erx < config_.econdERXMax; erx++) {  // loop through all eRxs
0353           if ((enabledERX >> erx & 1) == 0)
0354             continue;  // only pick active eRx
0355 
0356           //----- parse the eRX subpacket header
0357           // common mode
0358           LogDebug("HGCalUnpack") << "ECON-D:eRx=" << (int)econd << ":" << (int)erx
0359                                   << ", first word of the eRx header=0x" << std::hex << inputArray[iword] << std::dec
0360                                   << "\n"
0361                                   << "  extracted common mode 0=0x" << std::hex
0362                                   << ((inputArray[iword] >> kCommonmode0Shift) & kCommonmode0Mask) << std::dec
0363                                   << ", saved at " << commonModeDataSize_ << "\n"
0364                                   << "  extracted common mode 1=0x" << std::hex
0365                                   << ((inputArray[iword] >> kCommonmode1Shift) & kCommonmode1Mask) << std::dec
0366                                   << ", saved at " << (commonModeDataSize_ + 1);
0367 
0368           commonModeData_[commonModeDataSize_] = (inputArray[iword] >> kCommonmode0Shift) & kCommonmode0Mask;
0369           commonModeData_[commonModeDataSize_ + 1] = (inputArray[iword] >> kCommonmode1Shift) & kCommonmode1Mask;
0370           if ((erx % 2 == 0 && (enabledERX >> (erx + 1) & 1) == 0) ||
0371               (erx % 2 == 1 && (enabledERX >> (erx - 1) & 1) == 0)) {
0372             commonModeDataSize_ += 2;
0373             commonModeData_[commonModeDataSize_] = commonModeData_[commonModeDataSize_ - 2];
0374             commonModeData_[commonModeDataSize_ + 1] = commonModeData_[commonModeDataSize_ - 1];
0375             LogDebug("HGCalUnpack") << "half ROC turned on, padding to 4 common modes\n"
0376                                     << "0x" << std::hex << commonModeData_[commonModeDataSize_ - 2] << std::dec
0377                                     << " saved at " << commonModeDataSize_ << "\n"
0378                                     << "0x" << std::hex << commonModeData_[commonModeDataSize_ - 1] << std::dec
0379                                     << " saved at " << commonModeDataSize_ + 1;
0380           }
0381 
0382           // empty check
0383           if (((inputArray[iword] >> kFormatShift) & kFormatMask) == 1) {
0384             iword += 1;  // length of an empty eRx header (32 bits)
0385             LogDebug("HGCalUnpack") << "eRx #" << (int)erx << " is empty.";
0386             continue;  // go to next eRx
0387           }
0388 
0389           // regular mode
0390           const uint64_t erxHeader = ((uint64_t)inputArray[iword] << 32) | (uint64_t)inputArray[iword + 1];
0391           LogDebug("HGCalUnpack") << "whole eRx header=0x" << std::hex << erxHeader;
0392           iword += 2;  // length of a standard eRx header (2 * 32 bits)
0393 
0394           uint32_t bitCounter = 0;
0395           //----- parse the eRx subpacket body
0396           for (uint8_t channel = 0; channel < config_.erxChannelMax; channel++) {  // loop through channels in eRx
0397             if (((erxHeader >> channel) & 1) == 0)
0398               continue;  // only pick active channels
0399             const HGCalElectronicsId id(true, sLink, captureBlock, econd, erx, channel);
0400             commonModeIndex_[channelDataSize_] = commonModeDataSize_ / 4 * 4;
0401             const uint32_t tempIndex = bitCounter / 32 + iword;
0402             const uint8_t tempBit = bitCounter % 32;
0403             const uint32_t temp =
0404                 (tempBit == 0) ? inputArray[tempIndex]
0405                                : (inputArray[tempIndex] << tempBit) | (inputArray[tempIndex + 1] >> (32 - tempBit));
0406             const uint8_t code = temp >> 28;
0407             // use if and else here
0408             channelData_[channelDataSize_] = HGCROCChannelDataFrame<D>(
0409                 logicalMapping(id),
0410                 ((temp << erxBodyLeftShift_[code]) >> erxBodyRightShift_[code]) & erxBodyMask_[code]);
0411             bitCounter += erxBodyBits_[code];
0412             if (code == 0b0010)
0413               channelData_[channelDataSize_].fillFlag1(1);
0414             LogDebug("HGCalUnpack") << "Word " << channelDataSize_ << ", ECON-D:eRx:channel=" << (int)econd << ":"
0415                                     << (int)erx << ":" << (int)channel
0416                                     << ", assigned common mode index=" << commonModeIndex_[channelDataSize_] << "\n"
0417                                     << "  full word readout=0x" << std::hex << temp << std::dec << ", code=0x"
0418                                     << std::hex << (int)code << std::dec << "\n"
0419                                     << "  extracted channel data=0x" << std::hex
0420                                     << channelData_[channelDataSize_].raw();
0421             channelDataSize_++;
0422           }
0423           // pad to the whole word
0424           iword += bitCounter / 32;
0425           if (bitCounter % 32 != 0)
0426             iword += 1;
0427 
0428           if (commonModeDataSize_ + 1 > config_.commonModeMax)
0429             throw cms::Exception("HGCalUnpack") << "Too many common mode data unpacked: " << (commonModeDataSize_ + 1)
0430                                                 << " >= " << config_.commonModeMax << ".";
0431           commonModeDataSize_ += 2;
0432           // eRx subpacket has no trailer
0433         }
0434       } else {  // passthrough ECON-D
0435         LogDebug("HGCalUnpack") << "Passthrough ECON-D";
0436         const auto enabledERX = enabledERXMapping(sLink, captureBlock, econd);
0437         for (uint8_t erx = 0; erx < config_.econdERXMax; erx++) {  // loop through all eRx
0438           if ((enabledERX >> erx & 1) == 0)
0439             continue;  // only pick active eRx
0440 
0441           //----- parse the eRX subpacket header
0442           // common mode
0443           uint32_t temp = inputArray[iword];
0444           LogDebug("HGCalUnpack") << "ECON-D:eRx=" << (int)econd << ":" << (int)erx
0445                                   << ", first word of the eRx header=0x" << std::hex << temp << std::dec << "\n"
0446                                   << "  extracted common mode 0=0x" << std::hex
0447                                   << ((temp >> kCommonmode0Shift) & kCommonmode0Mask) << std::dec << ", saved at "
0448                                   << commonModeDataSize_ << "\n"
0449                                   << "  extracted common mode 1=0x" << std::hex
0450                                   << ((temp >> kCommonmode1Shift) & kCommonmode1Mask) << std::dec << ", saved at "
0451                                   << (commonModeDataSize_ + 1);
0452           commonModeData_[commonModeDataSize_] = (temp >> kCommonmode0Shift) & kCommonmode0Mask;
0453           commonModeData_[commonModeDataSize_ + 1] = (temp >> kCommonmode1Shift) & kCommonmode1Mask;
0454           if ((erx % 2 == 0 && (enabledERX >> (erx + 1) & 1) == 0) ||
0455               (erx % 2 == 1 && (enabledERX >> (erx - 1) & 1) == 0)) {
0456             commonModeDataSize_ += 2;
0457             commonModeData_[commonModeDataSize_] = commonModeData_[commonModeDataSize_ - 2];
0458             commonModeData_[commonModeDataSize_ + 1] = commonModeData_[commonModeDataSize_ - 1];
0459             LogDebug("HGCalUnpack") << "half ROC turned on, padding to 4 common modes\n"
0460                                     << "0x" << std::hex << commonModeData_[commonModeDataSize_ - 2] << std::dec
0461                                     << " saved at " << commonModeDataSize_ << "\n"
0462                                     << "0x" << std::hex << commonModeData_[commonModeDataSize_ - 1] << std::dec
0463                                     << " saved at " << commonModeDataSize_ + 1;
0464           }
0465           iword += 2;  // length of a standard eRx header (2 * 32 bits)
0466 
0467           for (uint8_t channel = 0; channel < config_.erxChannelMax; channel++) {  // loop through all channels in eRx
0468             const HGCalElectronicsId id(true, sLink, captureBlock, econd, erx, channel);
0469             commonModeIndex_[channelDataSize_] = commonModeDataSize_ / 4 * 4;
0470             channelData_[channelDataSize_] =
0471                 HGCROCChannelDataFrame<HGCalElectronicsId>(logicalMapping(id), inputArray[iword]);
0472             LogDebug("HGCalUnpack") << "Word" << channelDataSize_ << ", ECON-D:eRx:channel=" << (int)econd << ":"
0473                                     << (int)erx << ":" << (int)channel << ", HGCalElectronicsId=" << id.raw()
0474                                     << ", assigned common mode index=" << commonModeIndex_[channelDataSize_] << "\n"
0475                                     << "extracted channel data=0x" << std::hex << channelData_[channelDataSize_].raw();
0476             channelDataSize_++;
0477             iword++;
0478           }
0479           if (commonModeDataSize_ + 1 > config_.commonModeMax)
0480             throw cms::Exception("HGCalUnpack") << "Too many common mode data unpacked: " << (commonModeDataSize_ + 1)
0481                                                 << " >= " << config_.commonModeMax << ".";
0482           commonModeDataSize_ += 2;
0483         }
0484       }
0485 
0486       //----- parse the ECON-D trailer
0487       // (no information unpacked from ECON-D trailer, just skip it)
0488       iword += 1;  // length of an ECON-D trailer (32 bits CRC)
0489 
0490       if (iword - econdBodyStart != payloadLength)
0491         throw cms::Exception("CorruptData")
0492             << "Mismatch between unpacked and expected ECON-D #" << (int)econd << " payload length\n"
0493             << "  unpacked payload length=" << iword - econdBodyStart << "\n"
0494             << "  expected payload length=" << payloadLength;
0495       // pad to 2 words
0496       if (iword % 2 != 0) {
0497         LogDebug("HGCalUnpacker") << "Padding ECON-D payload to 2 32-bit words (remainder: " << (iword % 2) << ").";
0498         iword += 1;
0499       }
0500     }
0501     captureBlock++;  // the capture block has no trailer to parse
0502   }
0503   channelData_.resize(channelDataSize_);
0504   commonModeIndex_.resize(channelDataSize_);
0505   commonModeData_.resize(commonModeDataSize_);
0506   return;
0507 }
0508 
0509 template <class D>
0510 void HGCalUnpacker<D>::parseECOND(
0511     const std::vector<uint32_t>& inputArray,
0512     const std::function<uint16_t(uint16_t sLink, uint8_t captureBlock, uint8_t econd)>& enabledERXMapping,
0513     const std::function<D(HGCalElectronicsId elecID)>& logicalMapping) {
0514   uint16_t sLink = 0;
0515   uint8_t captureBlock = 0;
0516   uint8_t econd = 0;
0517 
0518   channelDataSize_ = 0;
0519   commonModeDataSize_ = 0;
0520   badECOND_.clear();
0521 
0522   for (uint32_t iword = 0; iword < inputArray.size();) {  // loop through all ECON-Ds
0523     //----- parse the ECON-D header
0524     // (the second word of ECON-D header contains no information for unpacking, use only the first one)
0525     if (((inputArray[iword] >> kHeaderShift) & kHeaderMask) != config_.econdHeaderMarker)  // sanity check
0526       throw cms::Exception("CorruptData")
0527           << "Expected a ECON-D header at word " << std::dec << iword << "/0x" << std::hex << iword << " (marker: 0x"
0528           << config_.econdHeaderMarker << "), got 0x" << inputArray[iword] << ".";
0529 
0530     const uint32_t econdHeader = inputArray[iword];
0531     iword += 2;  // length of ECON-D header (2 * 32 bits)
0532 
0533     LogDebug("HGCalUnpack") << "ECON-D #" << (int)econd << ", first word of ECON-D header=0x" << std::hex
0534                             << econdHeader;
0535 
0536     //----- extract the payload length
0537     const uint32_t payloadLength = (econdHeader >> kPayloadLengthShift) & kPayloadLengthMask;
0538     if (payloadLength > config_.payloadLengthMax)  // payload length too big
0539       throw cms::Exception("CorruptData")
0540           << "Unpacked payload length=" << payloadLength << " exceeds the maximal length=" << config_.payloadLengthMax;
0541 
0542     LogDebug("HGCalUnpack") << "ECON-D #" << (int)econd << ", payload length = " << payloadLength;
0543     //Quality check
0544     if (((econdHeader >> kHTShift & kHTMask) >= 0b10) || ((econdHeader >> kEBOShift & kEBOMask) >= 0b10) ||
0545         ((econdHeader >> kMatchShift & kMatchMask) == 0) ||
0546         ((econdHeader >> kTruncatedShift & kTruncatedMask) == 1)) {  // bad ECOND
0547       LogDebug("HGCalUnpack") << "ECON-D failed quality check, HT=" << (econdHeader >> kHTShift & kHTMask)
0548                               << ", EBO=" << (econdHeader >> kEBOShift & kEBOMask)
0549                               << ", M=" << (econdHeader >> kMatchShift & kMatchMask)
0550                               << ", T=" << (econdHeader >> kTruncatedShift & kTruncatedMask);
0551       badECOND_.emplace_back(iword - 2);
0552       iword += payloadLength;  // skip the current ECON-D (using the payload length parsed above)
0553 
0554       continue;  // go to the next ECON-D
0555     }
0556 
0557     //----- perse the ECON-D body
0558     const uint32_t econdBodyStart = iword;  // for the ECON-D length check
0559     if (((econdHeader >> kPassThroughShift) & kPassThroughMask) == 0) {
0560       // standard ECON-D
0561       LogDebug("HGCalUnpack") << "Standard ECON-D";
0562       const auto enabledERX = enabledERXMapping(sLink, captureBlock, econd);
0563       for (uint8_t erx = 0; erx < config_.econdERXMax; erx++) {  // loop through all eRxs
0564         if ((enabledERX >> erx & 1) == 0)
0565           continue;  // only pick active eRxs
0566 
0567         //----- parse the eRX subpacket header
0568         // common mode
0569         LogDebug("HGCalUnpack") << "ECON-D:eRx=" << (int)econd << ":" << (int)erx << ", first word of the eRx header=0x"
0570                                 << std::hex << inputArray[iword] << std::dec << "\n"
0571                                 << "  extracted common mode 0=0x" << std::hex
0572                                 << ((inputArray[iword] >> kCommonmode0Shift) & kCommonmode0Mask) << std::dec
0573                                 << ", saved at " << commonModeDataSize_ << "\n"
0574                                 << "  extracted common mode 1=0x" << std::hex
0575                                 << ((inputArray[iword] >> kCommonmode1Shift) & kCommonmode1Mask) << std::dec
0576                                 << ", saved at " << (commonModeDataSize_ + 1);
0577         commonModeData_[commonModeDataSize_] = (inputArray[iword] >> kCommonmode0Shift) & kCommonmode0Mask;
0578         commonModeData_[commonModeDataSize_ + 1] = (inputArray[iword] >> kCommonmode1Shift) & kCommonmode1Mask;
0579         if ((erx % 2 == 0 && (enabledERX >> (erx + 1) & 1) == 0) ||
0580             (erx % 2 == 1 && (enabledERX >> (erx - 1) & 1) == 0)) {
0581           commonModeDataSize_ += 2;
0582           commonModeData_[commonModeDataSize_] = commonModeData_[commonModeDataSize_ - 2];
0583           commonModeData_[commonModeDataSize_ + 1] = commonModeData_[commonModeDataSize_ - 1];
0584           LogDebug("HGCalUnpack") << "half ROC turned on, padding to 4 common modes\n"
0585                                   << "0x" << std::hex << commonModeData_[commonModeDataSize_ - 2] << std::dec
0586                                   << " saved at " << commonModeDataSize_ << "\n"
0587                                   << "0x" << std::hex << commonModeData_[commonModeDataSize_ - 1] << std::dec
0588                                   << " saved at " << commonModeDataSize_ + 1;
0589         }
0590         if (((inputArray[iword] >> kFormatShift) & kFormatMask) == 1) {  // empty eRx
0591           LogDebug("HGCalUnpack") << "eRx empty";
0592           iword += 1;  // length of an empty eRx header (32 bits)
0593 
0594           continue;  // skip to the next eRx
0595         }
0596 
0597         // regular mode
0598         const uint64_t erxHeader = ((uint64_t)inputArray[iword] << 32) | ((uint64_t)inputArray[iword + 1]);
0599         iword += 2;  // length of a standard eRx header (2 * 32 bits)
0600         LogDebug("HGCalUnpack") << "whole eRx header=0x" << std::hex << erxHeader;
0601 
0602         //----- parse eRx subpacket body
0603         uint32_t bitCounter = 0;
0604         for (uint8_t channel = 0; channel < config_.erxChannelMax; channel++) {  // loop through all channels in eRx
0605           if (((erxHeader >> channel) & 1) == 0)
0606             continue;  // only pick active channels
0607           const HGCalElectronicsId id(true, sLink, captureBlock, econd, erx, channel);
0608           commonModeIndex_[channelDataSize_] = commonModeDataSize_ / 4 * 4;
0609           const uint32_t tempIndex = bitCounter / 32 + iword;
0610           const uint8_t tempBit = bitCounter % 32;
0611           const uint32_t temp =
0612               (tempBit == 0) ? inputArray[tempIndex]
0613                              : (inputArray[tempIndex] << tempBit) | (inputArray[tempIndex + 1] >> (32 - tempBit));
0614           const uint8_t code = temp >> 28;
0615           // use if and else here
0616           channelData_[channelDataSize_] = HGCROCChannelDataFrame<D>(
0617               logicalMapping(id), ((temp << erxBodyLeftShift_[code]) >> erxBodyRightShift_[code]) & erxBodyMask_[code]);
0618           bitCounter += erxBodyBits_[code];
0619           if (code == 0b0010)
0620             channelData_[channelDataSize_].fillFlag1(1);
0621           LogDebug("HGCalUnpack") << "Word " << channelDataSize_ << ", ECON-D:eRx:channel=" << (int)econd << ":"
0622                                   << (int)erx << ":" << (int)channel << "\n"
0623                                   << "  assigned common mode index=" << commonModeIndex_.at(channelDataSize_) << "\n"
0624                                   << "  full word readout=0x" << std::hex << temp << std::dec << ", code=0x" << std::hex
0625                                   << (int)code << std::dec << "\n"
0626                                   << "  extracted channel data=0x" << std::hex << channelData_[channelDataSize_].raw();
0627           channelDataSize_++;
0628         }
0629         // pad to the whole word
0630         iword += bitCounter / 32;
0631         if (bitCounter % 32 != 0)
0632           iword += 1;
0633 
0634         if (commonModeDataSize_ + 1 > config_.commonModeMax)
0635           throw cms::Exception("HGCalUnpack") << "Too many common mode data unpacked: " << (commonModeDataSize_ + 1)
0636                                               << " >= " << config_.commonModeMax << ".";
0637         commonModeDataSize_ += 2;
0638         // eRx subpacket has no trailer
0639       }
0640     } else {
0641       // passthrough ECON-D
0642       LogDebug("HGCalUnpack") << "Passthrough ECON-D";
0643       const auto enabledERX = enabledERXMapping(sLink, captureBlock, econd);
0644       for (uint8_t erx = 0; erx < config_.econdERXMax; erx++) {  // loop through all eRxs
0645         if ((enabledERX >> erx & 1) == 0)
0646           continue;  // only pick active eRx
0647         //----- parse the eRX subpacket header
0648         // common mode
0649         uint32_t temp = inputArray[iword];
0650         LogDebug("HGCalUnpack") << "ECON-D:eRx=" << (int)econd << ":" << (int)erx << ", first word of the eRx header=0x"
0651                                 << std::hex << temp << std::dec << "\n"
0652                                 << "  extracted common mode 0=0x" << std::hex
0653                                 << ((temp >> kCommonmode0Shift) & kCommonmode0Mask) << std::dec << ", saved at "
0654                                 << commonModeDataSize_ << "\n"
0655                                 << "  extracted common mode 1=0x" << std::hex
0656                                 << ((temp >> kCommonmode1Shift) & kCommonmode1Mask) << std::dec << ", saved at "
0657                                 << (commonModeDataSize_ + 1);
0658         commonModeData_[commonModeDataSize_] = (temp >> kCommonmode0Shift) & kCommonmode0Mask;
0659         commonModeData_[commonModeDataSize_ + 1] = (temp >> kCommonmode1Shift) & kCommonmode1Mask;
0660         if ((erx % 2 == 0 && (enabledERX >> (erx + 1) & 1) == 0) ||
0661             (erx % 2 == 1 && (enabledERX >> (erx - 1) & 1) == 0)) {
0662           commonModeDataSize_ += 2;
0663           commonModeData_[commonModeDataSize_] = commonModeData_[commonModeDataSize_ - 2];
0664           commonModeData_[commonModeDataSize_ + 1] = commonModeData_[commonModeDataSize_ - 1];
0665           LogDebug("HGCalUnpack") << "half ROC turned on, padding to 4 common modes\n"
0666                                   << "0x" << std::hex << commonModeData_[commonModeDataSize_ - 2] << std::dec
0667                                   << " saved at " << commonModeDataSize_ << "\n"
0668                                   << "0x" << std::hex << commonModeData_[commonModeDataSize_ - 1] << std::dec
0669                                   << " saved at " << commonModeDataSize_ + 1;
0670         }
0671         iword += 2;  // length of the standard eRx header (2 * 32 bits)
0672 
0673         for (uint8_t channel = 0; channel < config_.erxChannelMax; channel++) {  // loop through all channels in eRx
0674           const HGCalElectronicsId id(true, sLink, captureBlock, econd, erx, channel);
0675           commonModeIndex_[channelDataSize_] = commonModeDataSize_ / 4 * 4;
0676           channelData_[channelDataSize_] =
0677               HGCROCChannelDataFrame<HGCalElectronicsId>(logicalMapping(id), inputArray[iword]);
0678           LogDebug("HGCalUnpack") << "Word " << channelDataSize_ << ", ECON-D:eRx:channel=" << (int)econd << ":"
0679                                   << (int)erx << ":" << (int)channel << ", HGCalElectronicsId=" << id.raw() << "\n"
0680                                   << "  assigned common mode index=" << commonModeIndex_.at(channelDataSize_) << "\n"
0681                                   << "extracted channel data=0x" << std::hex << channelData_.at(channelDataSize_).raw();
0682           channelDataSize_++;
0683           iword++;
0684         }
0685         if (commonModeDataSize_ + 1 > config_.commonModeMax)
0686           throw cms::Exception("HGCalUnpack") << "Too many common mode data unpacked: " << (commonModeDataSize_ + 1)
0687                                               << " >= " << config_.commonModeMax << ".";
0688         commonModeDataSize_ += 2;
0689       }
0690     }
0691     //----- fill the ECON-D trailer
0692     // (no information is needed from ECON-D trailer in unpacker, skip it)
0693     iword += 1;  // length of the ECON-D trailer (32 bits CRC)
0694 
0695     if (iword - econdBodyStart != payloadLength)
0696       throw cms::Exception("CorruptData")
0697           << "Mismatch between unpacked and expected ECON-D #" << (int)econd << " payload length\n"
0698           << "  unpacked payload length=" << iword - econdBodyStart << "\n"
0699           << "  expected payload length=" << payloadLength;
0700   }
0701   channelData_.resize(channelDataSize_);
0702   commonModeIndex_.resize(channelDataSize_);
0703   commonModeData_.resize(commonModeDataSize_);
0704   return;
0705 }
0706 
0707 // class specialisation for the electronics ID indexing
0708 template class HGCalUnpacker<HGCalElectronicsId>;