Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:10:45

0001 #include "EventFilter/HGCalRawToDigi/interface/HGCalRawDataPackingTools.h"
0002 #include "EventFilter/HGCalRawToDigi/interface/HGCalRawDataDefinitions.h"
0003 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0004 #include "FWCore/Utilities/interface/Exception.h"
0005 
0006 std::vector<uint32_t> hgcal::econd::produceERxData(const ERxChannelEnable& channel_enable,
0007                                                    const ERxData& erx,
0008                                                    bool passZS,
0009                                                    bool passZSm1,
0010                                                    bool hasToA,
0011                                                    bool char_mode) {
0012   auto format_word = [&erx, &passZS, &passZSm1, &hasToA, &char_mode](size_t i) -> std::pair<uint32_t, uint8_t> {
0013     if (i >= erx.tctp.size())
0014       throw cms::Exception("HGCalEmulator")
0015           << "Not enough channels in eRx data payload: " << i << " >= " << erx.tctp.size() << ".";
0016     if (char_mode)  // characterisation mode is easy
0017       return std::make_pair(((uint8_t)erx.tctp.at(i) & 0x3) << 30 | (erx.adc.at(i) & 0x3ff) << 20 |
0018                                 (erx.tot.at(i) & 0x3ff) << 10 | (erx.toa.at(i) & 0x3ff),
0019                             32);
0020     switch (erx.tctp.at(i)) {
0021       case ToTStatus::ZeroSuppressed: {
0022         if (!passZS)
0023           throw cms::Exception("HGCalEmulator") << "ToT status is ZeroSuppressed, but event frame does not pass ZS.";
0024         if (passZSm1) {
0025           if (hasToA)
0026             return std::make_pair((0x1 << 30) | ((erx.adcm.at(i) & 0x3ff) << 20) | ((erx.adc.at(i) & 0x3ff) << 10) |
0027                                       (erx.toa.at(i) & 0x3ff),
0028                                   32);
0029           else
0030             return std::make_pair(((erx.adcm.at(i) & 0x3ff) << 10) | (erx.adc.at(i) & 0x3ff), 24);
0031         }
0032         // at this point, does not have any BX-1 ZS info
0033         if (hasToA)
0034           return std::make_pair((0x3 << 20) | ((erx.adc.at(i) & 0x3ff) << 10) | (erx.toa.at(i) & 0x3ff), 24);
0035         return std::make_pair((0x1 << 10) | (erx.adc.at(i) & 0x3ff), 16);
0036       }
0037       case ToTStatus::noZeroSuppressed_TOASuppressed:
0038         return std::make_pair((0x2 << 20) | ((erx.adcm.at(i) & 0x3ff) << 10) | (erx.adc.at(i) & 0x3ff), 24);
0039       case ToTStatus::invalid:
0040         return std::make_pair(
0041             (0x2 << 30) | ((erx.adcm.at(i) & 0x3ff) << 20) | ((erx.adc.at(i) & 0x3ff) << 10) | (erx.toa.at(i) & 0x3ff),
0042             32);
0043       case ToTStatus::AutomaticFull:
0044         return std::make_pair(
0045             (0x3 << 30) | ((erx.adcm.at(i) & 0x3ff) << 20) | ((erx.tot.at(i) & 0x3ff) << 10) | (erx.toa.at(i) & 0x3ff),
0046             32);
0047       default:
0048         throw cms::Exception("HGCalEmulator")
0049             << "Invalid ToT status retrieved for channel " << i << ": " << (int)erx.tctp.at(i) << ".";
0050     }
0051   };
0052 
0053   std::vector<uint32_t> data{0};
0054   std::vector<uint32_t>::iterator it_data = data.begin();
0055 
0056   uint8_t msb = 0;
0057   for (size_t i = 0; i < channel_enable.size(); ++i) {
0058     if (!channel_enable.at(i))
0059       continue;
0060     const auto [word, nbits] = format_word(i);  // retrieve the channel word in its proper formatting
0061 
0062     if (msb >= 32)  // if we are already at the next word
0063       it_data = data.insert(data.end(), 0);
0064     msb %= 32;  // 0 <= msb < 32
0065 
0066     if (msb > 0)  // do we have some room for additional information?
0067       *it_data &= ((1 << msb) - 1);
0068     if (msb + nbits > 32) {  // spilling onto the next word
0069       uint8_t nbits_word1 = 32 - msb - nbits;
0070       *it_data |= (word & ((1 << nbits_word1) - 1)) << msb;
0071       it_data = data.insert(data.end(), word >> nbits_word1);
0072     } else  // everything fits into one word
0073       *it_data |= word << msb;
0074     msb += nbits;
0075   }
0076   return data;
0077 }
0078 
0079 //
0080 std::vector<uint32_t> hgcal::econd::eRxSubPacketHeader(uint8_t stat,
0081                                                        uint8_t hamming,
0082                                                        bool bitE,
0083                                                        uint16_t common_mode0,
0084                                                        uint16_t common_mode1,
0085                                                        const ERxChannelEnable& channel_enable) {
0086   uint64_t channels_map64b(0);
0087   size_t i = 0;
0088   for (const auto& ch : channel_enable)
0089     channels_map64b |= (ch << i++);
0090   return hgcal::econd::eRxSubPacketHeader(stat, hamming, bitE, common_mode0, common_mode1, channels_map64b);
0091 }
0092 
0093 //
0094 std::vector<uint32_t> hgcal::econd::eRxSubPacketHeader(
0095     uint8_t stat, uint8_t hamming, bool bitE, uint16_t common_mode0, uint16_t common_mode1, uint64_t channels_map) {
0096   std::vector<uint32_t> header = {
0097       (stat & hgcal::ECOND_FRAME::ERXSTAT_MASK) << hgcal::ECOND_FRAME::ERXSTAT_POS |
0098       (hamming & hgcal::ECOND_FRAME::ERXHAM_MASK) << hgcal::ECOND_FRAME::ERXHAM_POS |
0099       (common_mode0 & hgcal::ECOND_FRAME::COMMONMODE0_MASK) << hgcal::ECOND_FRAME::COMMONMODE0_POS |
0100       (common_mode1 & hgcal::ECOND_FRAME::COMMONMODE1_MASK) << hgcal::ECOND_FRAME::COMMONMODE1_POS};
0101 
0102   //summarize the channel status map
0103   const uint32_t chmapw0(channels_map & hgcal::ECOND_FRAME::CHMAP0_MASK),
0104       chmapw1((channels_map >> 32) & hgcal::ECOND_FRAME::CHMAP32_MASK);
0105 
0106   //add the channel map
0107   if (chmapw0 == 0 && chmapw1 == 0) {  // empty channels map (empty eRx)
0108     header[0] |= (bitE << hgcal::ECOND_FRAME::ERX_E_POS);
0109     header[0] |= (1 << hgcal::ECOND_FRAME::ERXFORMAT_POS);  //raise the F bit (empty eRX)
0110   } else {
0111     header[0] |= (chmapw1 & hgcal::ECOND_FRAME::CHMAP32_MASK) << hgcal::ECOND_FRAME::CHMAP32_POS;
0112     header.push_back((chmapw0 & hgcal::ECOND_FRAME::CHMAP0_MASK) << hgcal::ECOND_FRAME::CHMAP0_POS);
0113   }
0114 
0115   return header;
0116 }
0117 
0118 static uint8_t computeCRC8bit(const std::vector<uint32_t>& event_header) {
0119   uint8_t crc = 0x42;  //TODO: implement 8-bit Bluetooth CRC
0120   return crc;
0121 }
0122 
0123 //
0124 std::vector<uint32_t> hgcal::econd::eventPacketHeader(uint16_t header,
0125                                                       uint16_t payload,
0126                                                       bool bitP,
0127                                                       bool bitE,
0128                                                       uint8_t ht,
0129                                                       uint8_t ebo,
0130                                                       bool bitM,
0131                                                       bool bitT,
0132                                                       uint8_t ehHam,
0133                                                       uint16_t bx,
0134                                                       uint16_t l1a,
0135                                                       uint8_t orb,
0136                                                       bool bitS,
0137                                                       uint8_t rr) {
0138   std::vector<uint32_t> words(2, 0);
0139 
0140   words[0] = (header & hgcal::ECOND_FRAME::HEADER_MASK) << hgcal::ECOND_FRAME::HEADER_POS |
0141              (payload & hgcal::ECOND_FRAME::PAYLOAD_MASK) << hgcal::ECOND_FRAME::PAYLOAD_POS |
0142              bitP << hgcal::ECOND_FRAME::BITP_POS | bitE << hgcal::ECOND_FRAME::BITE_POS |
0143              (ht & hgcal::ECOND_FRAME::HT_MASK) << hgcal::ECOND_FRAME::HT_POS |
0144              (ebo & hgcal::ECOND_FRAME::EBO_MASK) << hgcal::ECOND_FRAME::EBO_POS |
0145              bitM << hgcal::ECOND_FRAME::BITM_POS | bitT << hgcal::ECOND_FRAME::BITT_POS |
0146              (ehHam & hgcal::ECOND_FRAME::EHHAM_MASK) << hgcal::ECOND_FRAME::EHHAM_POS;
0147 
0148   words[1] = (bx & hgcal::ECOND_FRAME::BX_MASK) << hgcal::ECOND_FRAME::BX_POS |
0149              (l1a & hgcal::ECOND_FRAME::L1A_MASK) << hgcal::ECOND_FRAME::L1A_POS |
0150              (orb & hgcal::ECOND_FRAME::ORBIT_MASK) << hgcal::ECOND_FRAME::ORBIT_POS |
0151              bitS << hgcal::ECOND_FRAME::BITS_POS | (rr & hgcal::ECOND_FRAME::RR_MASK) << hgcal::ECOND_FRAME::RR_POS;
0152 
0153   const auto crc = computeCRC8bit(words);
0154   words[1] |= (crc & hgcal::ECOND_FRAME::EHCRC_MASK) << hgcal::ECOND_FRAME::EHCRC_POS;
0155 
0156   return words;
0157 }
0158 
0159 uint32_t hgcal::econd::buildIdleWord(uint8_t bufStat, uint8_t err, uint8_t rr, uint32_t progPattern) {
0160   return (progPattern & 0xffffff) << 8 | (rr & 0x3) << 6 | (err & 0x7) << 3 | (bufStat & 0x7) << 0;
0161 }
0162 
0163 //
0164 std::vector<uint32_t> hgcal::backend::buildCaptureBlockHeader(
0165     uint32_t bunch_crossing,
0166     uint32_t event_counter,
0167     uint32_t orbit_counter,
0168     const std::vector<hgcal::backend::ECONDPacketStatus>& econd_statuses) {
0169   if (econd_statuses.size() > 12)
0170     throw cms::Exception("HGCalEmulator") << "Invalid size for ECON-D statuses: " << econd_statuses.size() << ".";
0171   std::vector<uint32_t> header(2, 0);
0172   header[0] =
0173       (bunch_crossing & hgcal::BACKEND_FRAME::CAPTUREBLOCK_BC_MASK) << hgcal::BACKEND_FRAME::CAPTUREBLOCK_BC_POS |
0174       (event_counter & hgcal::BACKEND_FRAME::CAPTUREBLOCK_EC_MASK) << hgcal::BACKEND_FRAME::CAPTUREBLOCK_EC_POS |
0175       (orbit_counter & hgcal::BACKEND_FRAME::CAPTUREBLOCK_OC_MASK) << hgcal::BACKEND_FRAME::CAPTUREBLOCK_OC_POS |
0176       (econd_statuses[11] & 0x7) << 1 | ((econd_statuses[10] >> 2) & 0x1);
0177   for (size_t i = 0; i < 11; i++)
0178     header[1] |= (econd_statuses[i] & 0x7) << i * 3;
0179   return header;
0180 }
0181 
0182 //
0183 std::vector<uint32_t> hgcal::backend::buildSlinkHeader(
0184     uint8_t boe, uint8_t v, uint64_t global_event_id, uint32_t content_id, uint32_t fed_id) {
0185   std::vector<uint32_t> header(4, 0);
0186   header[0] = (boe & hgcal::BACKEND_FRAME::SLINK_BOE_MASK) << hgcal::BACKEND_FRAME::SLINK_BOE_POS |
0187               (v & hgcal::BACKEND_FRAME::SLINK_V_MASK) << hgcal::BACKEND_FRAME::SLINK_V_POS |
0188               ((global_event_id >> 41) & SLINK_GLOBAL_EVENTID_MSB_MASK)
0189                   << hgcal::BACKEND_FRAME::SLINK_GLOBAL_EVENTID_MSB_POS;
0190   header[1] = (global_event_id & SLINK_GLOBAL_EVENTID_LSB_MASK);
0191   header[2] = (content_id & hgcal::BACKEND_FRAME::SLINK_CONTENTID_MASK) << hgcal::BACKEND_FRAME::SLINK_CONTENTID_POS;
0192   header[3] = (fed_id & hgcal::BACKEND_FRAME::SLINK_SOURCEID_MASK) << hgcal::BACKEND_FRAME::SLINK_SOURCEID_POS;
0193 
0194   return header;
0195 }
0196 
0197 //
0198 std::vector<uint32_t> hgcal::backend::buildSlinkTrailer(uint8_t eoe,
0199                                                         uint16_t daqcrc,
0200                                                         uint32_t event_length,
0201                                                         uint16_t bxid,
0202                                                         uint32_t orbit_id,
0203                                                         uint16_t crc,
0204                                                         uint16_t status) {
0205   std::vector<uint32_t> trailer(4, 0);
0206 
0207   trailer[0] = (eoe & hgcal::BACKEND_FRAME::SLINK_EOE_MASK) << hgcal::BACKEND_FRAME::SLINK_EOE_POS |
0208                (daqcrc & hgcal::BACKEND_FRAME::SLINK_DAQCRC_MASK) << hgcal::BACKEND_FRAME::SLINK_DAQCRC_POS;
0209   trailer[1] = (event_length & hgcal::BACKEND_FRAME::SLINK_EVLENGTH_MASK) << hgcal::BACKEND_FRAME::SLINK_EVLENGTH_POS |
0210                (bxid & hgcal::BACKEND_FRAME::SLINK_BXID_MASK) << hgcal::BACKEND_FRAME::SLINK_BXID_POS;
0211   trailer[2] = (orbit_id & hgcal::BACKEND_FRAME::SLINK_ORBID_MASK) << hgcal::BACKEND_FRAME::SLINK_ORBID_POS;
0212   trailer[3] = (crc & hgcal::BACKEND_FRAME::SLINK_CRC_MASK) << hgcal::BACKEND_FRAME::SLINK_CRC_POS |
0213                (status & hgcal::BACKEND_FRAME::SLINK_STATUS_MASK) << hgcal::BACKEND_FRAME::SLINK_STATUS_POS;
0214 
0215   return trailer;
0216 }
0217 
0218 //
0219 uint32_t hgcal::backend::buildSlinkContentId(SlinkEmulationFlag e, uint8_t l1a_subtype, uint16_t l1a_fragment_cnt) {
0220   return 0x0 | (l1a_fragment_cnt & 0xffff) | (l1a_subtype & 0xff) << 16 | (e & 0x3) << 24;
0221 }
0222 
0223 uint16_t hgcal::backend::buildSlinkRocketStatus(
0224     bool fed_crc_err, bool slinkrocket_crc_err, bool source_id_err, bool sync_lost, bool fragment_trunc) {
0225   return 0x0 | (fed_crc_err & 0x1) << 0 | (slinkrocket_crc_err & 0x1) << 1 | (source_id_err & 0x1) << 2 |
0226          (sync_lost & 0x1) << 3 | (fragment_trunc & 0x1) << 4;
0227 }