File indexing completed on 2024-04-06 12:10:54
0001 #include <iomanip>
0002
0003 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0004
0005 #include "EventFilter/L1TRawToDigi/interface/Block.h"
0006
0007 #define EDM_ML_DEBUG 1
0008
0009 namespace l1t {
0010
0011 const std::vector<unsigned int> MTF7Payload::block_patterns_ = {
0012
0013 mtf7::EvHd,
0014 mtf7::CnBlk,
0015 mtf7::ME,
0016 mtf7::RPC,
0017 mtf7::GEM,
0018 mtf7::ME0,
0019 mtf7::SPOut,
0020 mtf7::EvTr
0021 };
0022
0023 uint32_t BlockHeader::raw() const {
0024 if (type_ == MP7) {
0025 LogTrace("L1T") << "Writing MP7 link header";
0026 return ((id_ & ID_mask) << ID_shift) | ((size_ & size_mask) << size_shift) |
0027 ((capID_ & capID_mask) << capID_shift) | ((flags_ & flags_mask) << flags_shift);
0028 } else if (type_ == CTP7) {
0029 LogTrace("L1T") << "Writing CTP7 link header";
0030 return flags_;
0031 }
0032
0033
0034
0035
0036 LogTrace("L1T") << "Writing meaningless link header";
0037 return 0;
0038 }
0039
0040 BxBlocks Block::getBxBlocks(unsigned int payloadWordsPerBx, bool bxHeader) const {
0041 BxBlocks bxBlocks;
0042
0043
0044 unsigned int wordsPerBx = payloadWordsPerBx;
0045 if (bxHeader) {
0046 ++wordsPerBx;
0047 }
0048
0049 unsigned int nBxBlocks = payload_.size() / wordsPerBx;
0050 for (size_t bxCtr = 0; bxCtr < nBxBlocks; ++bxCtr) {
0051 size_t startIdx = bxCtr * wordsPerBx;
0052 auto startBxBlock = payload_.cbegin() + startIdx;
0053
0054 if (bxHeader) {
0055 bxBlocks.emplace_back(startBxBlock, startBxBlock + wordsPerBx);
0056 } else {
0057 bxBlocks.emplace_back(bxCtr, nBxBlocks, startBxBlock, startBxBlock + wordsPerBx);
0058 }
0059 }
0060
0061 return bxBlocks;
0062 }
0063
0064 std::unique_ptr<Block> Payload::getBlock() {
0065 if (end_ - data_ < getHeaderSize()) {
0066 LogDebug("L1T") << "Reached end of payload";
0067 return std::unique_ptr<Block>();
0068 }
0069
0070 if (data_[0] == 0xffffffff) {
0071 LogDebug("L1T") << "Skipping padding word";
0072 ++data_;
0073 return getBlock();
0074 }
0075
0076 auto header = getHeader();
0077
0078 if (end_ - data_ < header.getSize()) {
0079 edm::LogError("L1T") << "Expecting a block size of " << header.getSize() << " but only " << (end_ - data_)
0080 << " words remaining";
0081 return std::unique_ptr<Block>();
0082 }
0083
0084 LogTrace("L1T") << "Creating block with size " << header.getSize();
0085
0086 auto res = std::make_unique<Block>(header, data_, data_ + header.getSize());
0087 data_ += header.getSize();
0088 return res;
0089 }
0090
0091 MP7Payload::MP7Payload(const uint32_t* data, const uint32_t* end, bool legacy_mc) : Payload(data, end) {
0092
0093
0094
0095 if (legacy_mc) {
0096 LogTrace("L1T") << "Skipping " << std::hex << *data_;
0097 ++data_;
0098 } else {
0099 infra_ = data_[0];
0100 algo_ = data_[1];
0101 data_ += 2;
0102 }
0103 }
0104
0105 BlockHeader MP7Payload::getHeader() {
0106 LogTrace("L1T") << "Getting header from " << std::hex << std::setw(8) << *data_;
0107
0108 return BlockHeader(data_++);
0109 }
0110
0111 MTF7Payload::MTF7Payload(const uint32_t* data, const uint32_t* end) : Payload(data, end) {
0112 const uint16_t* data16 = reinterpret_cast<const uint16_t*>(data);
0113 const uint16_t* end16 = reinterpret_cast<const uint16_t*>(end);
0114
0115 if (end16 - data16 < header_size + counter_size + trailer_size) {
0116 edm::LogError("L1T") << "MTF7 payload smaller than allowed!";
0117 data_ = end_;
0118 } else if (
0119 ((data16[0] >> 12) != 0x9) || ((data16[1] >> 12) != 0x9) || ((data16[2] >> 12) != 0x9) ||
0120 ((data16[3] >> 12) != 0x9) || ((data16[4] >> 12) != 0xA) || ((data16[5] >> 12) != 0xA) ||
0121 ((data16[6] >> 12) != 0xA) || ((data16[7] >> 12) != 0xA) || ((data16[8] >> 15) != 0x1) ||
0122 ((data16[9] >> 15) != 0x0) || ((data16[10] >> 15) != 0x0) || ((data16[11] >> 15) != 0x0)) {
0123 edm::LogError("L1T") << "MTF7 payload has invalid header!";
0124 data_ = end_;
0125 } else if (
0126 ((data16[12] >> 15) != 0) || ((data16[13] >> 15) != 1) || ((data16[14] >> 15) != 0) ||
0127 ((data16[15] >> 15) != 0)) {
0128 edm::LogError("L1T") << "MTF7 payload has invalid counter block!";
0129 data_ = end_;
0130 }
0131
0132
0133 algo_ = 0;
0134
0135
0136 for (unsigned i = DAQ_PAYLOAD_OFFSET; i < PAYLOAD_MAX_SIZE; i++) {
0137 if (((data16[4 * i + 0] >> 12) == 0xF) && ((data16[4 * i + 1] >> 12) == 0xF) &&
0138 ((data16[4 * i + 2] >> 12) == 0xF) && ((data16[4 * i + 3] >> 12) == 0xF) &&
0139 ((data16[4 * i + 4] >> 12) == 0xE) && ((data16[4 * i + 5] >> 12) == 0xE) &&
0140 ((data16[4 * i + 6] >> 12) == 0xE) &&
0141 ((data16[4 * i + 7] >> 12) == 0xE)) {
0142 algo_ = (((data16[4 * i + 2] >> 4) & 0x3F) << 9);
0143 algo_ |= (((data16[4 * i + 2] >> 0) & 0x0F) << 5);
0144 algo_ |= (((data16[4 * i + 4] >> 0) & 0x1F) << 0);
0145 break;
0146 }
0147 }
0148 if (algo_ == 0) {
0149 edm::LogError("L1T") << "MTF7 payload has no valid EMTF firmware version!";
0150 data_ = end_;
0151 }
0152 }
0153
0154 int MTF7Payload::count(unsigned int pattern, unsigned int length) const {
0155 unsigned int mask = 0;
0156 for (; length > 0; length--)
0157 mask = (mask << 4) | 0xf;
0158
0159 int count = 0;
0160 for (const auto& p : block_patterns_)
0161 count += (p & mask) == pattern;
0162 return count;
0163 }
0164
0165 bool MTF7Payload::valid(unsigned int pattern) const {
0166 for (const auto& p : block_patterns_) {
0167 if (p == pattern)
0168 return true;
0169 }
0170 return false;
0171 }
0172
0173 std::unique_ptr<Block> MTF7Payload::getBlock() {
0174 if (end_ - data_ < 2)
0175 return std::unique_ptr<Block>();
0176
0177 const uint16_t* data16 = reinterpret_cast<const uint16_t*>(data_);
0178 const uint16_t* end16 = reinterpret_cast<const uint16_t*>(end_);
0179
0180
0181
0182 std::vector<uint32_t> payload;
0183 unsigned int pattern = 0;
0184 unsigned int i = 0;
0185 for (; i < max_block_length_ and data16 + (i + 1) * 4 <= end16; ++i) {
0186 for (int j = 0; j < 4; ++j) {
0187 auto n = i * 4 + j;
0188 pattern |= (data16[n] >> 15) << n;
0189 payload.push_back(data16[n]);
0190 }
0191
0192 if (count(pattern, i + 1) == 1 and valid(pattern))
0193 break;
0194 }
0195
0196 if (not valid(pattern)) {
0197 edm::LogWarning("L1T") << "MTF7 block with unrecognized id 0x" << std::hex << pattern;
0198 return std::unique_ptr<Block>();
0199 }
0200
0201 data_ += (i + 1) * 2;
0202 return std::make_unique<Block>(pattern, payload, 0, MTF7);
0203 }
0204
0205 CTP7Payload::CTP7Payload(const uint32_t* data, const uint32_t* end, amc::Header amcHeader)
0206 : Payload(data, end), amcHeader_(amcHeader) {
0207 if (not(*data_ == 0xA110CA7E)) {
0208 edm::LogError("L1T") << "CTP7 block with invalid header:" << std::hex << *data_;
0209 }
0210 ++data_;
0211 bx_per_l1a_ = (*data_ >> 16) & 0xff;
0212 calo_bxid_ = *data_ & 0xfff;
0213 capId_ = 0;
0214 six_hcal_feature_bits_ = (*data_ >> 15) & 0x1;
0215 slot7_card_ = (*data_ >> 14) & 0x1;
0216 if (bx_per_l1a_ > 1) {
0217 edm::LogInfo("L1T") << "CTP7 block with multiple bunch crossings:" << bx_per_l1a_;
0218 }
0219 algo_ = amcHeader_.getUserData();
0220 infra_ = 0;
0221 ++data_;
0222 }
0223
0224 BlockHeader CTP7Payload::getHeader() {
0225
0226 unsigned blockId = 0;
0227
0228
0229
0230 unsigned blockFlags = ((bx_per_l1a_ & 0xf) << 16) | (calo_bxid_ & 0xfff) | ((six_hcal_feature_bits_ & 0x1) << 15) |
0231 ((slot7_card_ & 0x1) << 14);
0232 unsigned blockSize = (slot7_card_ == 1) ? 6 : ((192 + (int)six_hcal_feature_bits_ * 28) * (int)bx_per_l1a_);
0233 return BlockHeader(blockId, blockSize, capId_, blockFlags, CTP7);
0234 }
0235
0236 std::unique_ptr<Block> CTP7Payload::getBlock() {
0237 if (end_ - data_ < getHeaderSize()) {
0238 LogDebug("L1T") << "Reached end of payload";
0239 return std::unique_ptr<Block>();
0240 }
0241 if (capId_ > bx_per_l1a_) {
0242 edm::LogWarning("L1T") << "CTP7 with more bunch crossings than expected";
0243 }
0244
0245 auto header = getHeader();
0246
0247 if (end_ - data_ < header.getSize()) {
0248 edm::LogError("L1T") << "Expecting a block size of " << header.getSize() << " but only " << (end_ - data_)
0249 << " words remaining";
0250 return std::unique_ptr<Block>();
0251 }
0252
0253 LogTrace("L1T") << "Creating block with size " << header.getSize();
0254
0255 auto res = std::make_unique<Block>(header, data_, data_ + header.getSize());
0256 data_ += header.getSize();
0257 capId_++;
0258 return res;
0259 }
0260 }