File indexing completed on 2024-12-17 02:41:13
0001 #include <iomanip>
0002 #include <map>
0003
0004 #include "FWCore/Framework/interface/Event.h"
0005 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0006 #include "FWCore/Utilities/interface/calculateCRC32.h"
0007
0008 #include "EventFilter/L1TRawToDigi/interface/AMC13Spec.h"
0009
0010
0011
0012 namespace amc13 {
0013 Header::Header(unsigned int namc, unsigned int orbit) {
0014 data_ = (static_cast<uint64_t>(namc & nAMC_mask) << nAMC_shift) |
0015 (static_cast<uint64_t>(orbit & OrN_mask) << OrN_shift) |
0016 (static_cast<uint64_t>(fov & uFOV_mask) << uFOV_shift);
0017 }
0018
0019 bool Header::check() const { return (getNumberOfAMCs() <= max_amc) && (getFormatVersion() == fov); }
0020
0021 Trailer::Trailer(unsigned int blk, unsigned int lv1, unsigned int bx) {
0022 data_ = (static_cast<uint64_t>(blk & BlkNo_mask) << BlkNo_shift) |
0023 (static_cast<uint64_t>(lv1 & LV1_mask) << LV1_shift) | (static_cast<uint64_t>(bx & BX_mask) << BX_shift);
0024 }
0025
0026 bool Trailer::check(unsigned int crc, unsigned int block, unsigned int lv1_id, unsigned int bx) const {
0027 if ((crc != 0 && crc != getCRC()) || block != getBlock() || (lv1_id & LV1_mask) != getLV1ID() ||
0028 (bx & BX_mask) != getBX()) {
0029 edm::LogWarning("L1T") << "Found AMC13 trailer with:"
0030 << "\n\tBX " << getBX() << ", LV1 ID " << getLV1ID() << ", block # " << getBlock()
0031 << ", CRC " << std::hex << std::setw(8) << std::setfill('0') << getCRC() << std::dec
0032 << "\nBut expected:"
0033 << "\n\tBX " << (bx & BX_mask) << ", LV1 ID " << (lv1_id & LV1_mask) << ", block # "
0034 << block << ", CRC " << std::hex << std::setw(8) << std::setfill('0') << crc;
0035 return false;
0036 }
0037 return true;
0038 }
0039
0040 void Trailer::writeCRC(const uint64_t* start, uint64_t* end) {
0041 std::string_view dstring(reinterpret_cast<const char*>(start), reinterpret_cast<const char*>(end) + 4);
0042 auto crc = cms::calculateCRC32(dstring);
0043
0044 *end = ((*end) & ~(uint64_t(CRC_mask) << CRC_shift)) | (static_cast<uint64_t>(crc & CRC_mask) << CRC_shift);
0045 }
0046
0047 void Packet::add(unsigned int amc_no,
0048 unsigned int board,
0049 unsigned int lv1id,
0050 unsigned int orbit,
0051 unsigned int bx,
0052 const std::vector<uint64_t>& load,
0053 unsigned int user) {
0054 edm::LogInfo("AMC") << "Adding board " << board << " with payload size " << load.size() << " as payload #"
0055 << amc_no;
0056
0057 payload_.push_back(amc::Packet(amc_no, board, lv1id, orbit, bx, load, user));
0058 }
0059
0060 bool Packet::parse(const uint64_t* start,
0061 const uint64_t* data,
0062 unsigned int size,
0063 unsigned int lv1,
0064 unsigned int bx,
0065 bool legacy_mc,
0066 bool mtf7_mode) {
0067
0068
0069 if (size < 2) {
0070 edm::LogError("AMC") << "AMC13 packet size too small";
0071 return false;
0072 }
0073
0074 std::map<int, int> amc_index;
0075
0076 header_ = Header(data++);
0077
0078 if (!header_.check()) {
0079 edm::LogError("AMC") << "Invalid header for AMC13 packet: "
0080 << "format version " << header_.getFormatVersion() << ", " << header_.getNumberOfAMCs()
0081 << " AMC packets";
0082 return false;
0083 }
0084
0085 if (size < 2 + header_.getNumberOfAMCs())
0086 return false;
0087
0088
0089
0090 for (unsigned int i = 0; i < header_.getNumberOfAMCs(); ++i) {
0091 payload_.push_back(amc::Packet(data++));
0092 amc_index[payload_.back().blockHeader().getAMCNumber()] = i;
0093 }
0094
0095 unsigned int tot_size = 0;
0096 unsigned int tot_nblocks = 0;
0097 unsigned int maxblocks = 0;
0098
0099 bool check_crc = false;
0100 for (const auto& amc : payload_) {
0101 tot_size += amc.blockHeader().getSize();
0102 tot_nblocks += amc.blockHeader().getBlocks();
0103 maxblocks = std::max(maxblocks, amc.blockHeader().getBlocks());
0104
0105 if (amc.blockHeader().validCRC())
0106 check_crc = true;
0107 }
0108
0109 unsigned int words = tot_size +
0110 tot_nblocks +
0111 2 * maxblocks;
0112
0113 if (size < words) {
0114 edm::LogError("L1T") << "Encountered AMC 13 packet with " << size << " words, "
0115 << "but expected " << words << " words: " << tot_size << " payload words, " << tot_nblocks
0116 << " AMC header words, and 2 AMC 13 header words.";
0117 return false;
0118 }
0119
0120
0121
0122 for (auto& amc : payload_) {
0123 amc.addPayload(data, amc.blockHeader().getBlockSize());
0124 data += amc.blockHeader().getBlockSize();
0125 }
0126
0127 Trailer t(data++);
0128
0129 int crc = 0;
0130 if (check_crc) {
0131 std::string_view check(reinterpret_cast<const char*>(start), reinterpret_cast<const char*>(data) - 4);
0132 crc = cms::calculateCRC32(check);
0133
0134 LogDebug("L1T") << "checking data checksum of " << std::hex << crc << std::dec;
0135 }
0136
0137 t.check(crc, 0, lv1, bx);
0138
0139
0140 for (unsigned int b = 1; b < maxblocks; ++b) {
0141 Header block_h(data++);
0142 std::vector<amc::BlockHeader> headers;
0143
0144 for (unsigned int i = 0; i < block_h.getNumberOfAMCs(); ++i)
0145 headers.push_back(amc::BlockHeader(data++));
0146
0147 check_crc = false;
0148 for (const auto& amc : headers) {
0149 payload_[amc_index[amc.getAMCNumber()]].addPayload(data, amc.getBlockSize());
0150 data += amc.getBlockSize();
0151
0152 if (amc.validCRC())
0153 check_crc = true;
0154 }
0155
0156 t = Trailer(data++);
0157
0158 if (check_crc) {
0159 std::string_view check(reinterpret_cast<const char*>(start), reinterpret_cast<const char*>(data) - 4);
0160 crc = cms::calculateCRC32(check);
0161
0162 LogDebug("L1T") << "checking data checksum of " << std::hex << crc << std::dec;
0163 } else {
0164 crc = 0;
0165 }
0166
0167 t.check(crc, b, lv1, bx);
0168 }
0169
0170 for (auto& amc : payload_) {
0171 amc.finalize(lv1, bx, legacy_mc, mtf7_mode);
0172 }
0173
0174 return true;
0175 }
0176
0177 unsigned int Packet::blocks() const {
0178 unsigned int maxblocks = 0;
0179
0180 for (const auto& amc : payload_)
0181 maxblocks = std::max(maxblocks, amc.blocks());
0182
0183 return maxblocks;
0184 }
0185
0186 unsigned int Packet::size() const {
0187 unsigned int words = 0;
0188 unsigned int blocks = 0;
0189 unsigned int maxblocks = 0;
0190
0191 for (const auto& amc : payload_) {
0192 words += amc.header().getSize();
0193 blocks += amc.blocks();
0194 maxblocks = std::max(maxblocks, amc.blocks());
0195 }
0196
0197
0198
0199 return words + blocks + maxblocks * 2;
0200 }
0201
0202 bool Packet::write(const edm::Event& ev, unsigned char* ptr, unsigned int skip, unsigned int size) const {
0203 if (size < this->size() * 8)
0204 return false;
0205
0206 if (size % 8 != 0)
0207 return false;
0208
0209 uint64_t* data = reinterpret_cast<uint64_t*>(ptr + skip);
0210
0211 for (unsigned int b = 0; b < blocks(); ++b) {
0212
0213
0214 std::vector<uint64_t> block_headers;
0215 std::vector<uint64_t> block_load;
0216 for (const auto& amc : payload_) {
0217 edm::LogInfo("AMC") << "Considering block " << b << " for payload " << amc.blockHeader().getBoardID()
0218 << " with size " << amc.size() << " and " << amc.blocks() << " blocks";
0219 if (amc.blocks() < b + 1)
0220 continue;
0221
0222 block_headers.push_back(amc.blockHeader(b));
0223 auto words = amc.block(b);
0224 block_load.insert(block_load.end(), words.begin(), words.end());
0225 }
0226
0227 if (b == 0) {
0228 amc13::Header h(block_headers.size(), ev.orbitNumber());
0229 edm::LogInfo("AMC") << "Writing header for AMC13 packet: "
0230 << "format version " << h.getFormatVersion() << ", " << h.getNumberOfAMCs()
0231 << " AMC packets, orbit " << h.getOrbitNumber();
0232 }
0233
0234 *(data++) = amc13::Header(block_headers.size(), ev.orbitNumber()).raw();
0235
0236 block_headers.insert(block_headers.end(), block_load.begin(), block_load.end());
0237 for (const auto& word : block_headers)
0238 *(data++) = word;
0239
0240 *data = Trailer(b, ev.id().event(), ev.bunchCrossing()).raw();
0241 Trailer::writeCRC(reinterpret_cast<uint64_t*>(ptr), data);
0242 }
0243
0244 return true;
0245 }
0246 }