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)
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
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);
0061
0062 if (msb >= 32)
0063 it_data = data.insert(data.end(), 0);
0064 msb %= 32;
0065
0066 if (msb > 0)
0067 *it_data &= ((1 << msb) - 1);
0068 if (msb + nbits > 32) {
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
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
0103 const uint32_t chmapw0(channels_map & hgcal::ECOND_FRAME::CHMAP0_MASK),
0104 chmapw1((channels_map >> 32) & hgcal::ECOND_FRAME::CHMAP32_MASK);
0105
0106
0107 if (chmapw0 == 0 && chmapw1 == 0) {
0108 header[0] |= (bitE << hgcal::ECOND_FRAME::ERX_E_POS);
0109 header[0] |= (1 << hgcal::ECOND_FRAME::ERXFORMAT_POS);
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;
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 }