Back to home page

Project CMSSW displayed by LXR

 
 

    


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       // from l1t::mtf7::mtf7_block_t enum definition
0013       mtf7::EvHd,   // Event Record Header
0014       mtf7::CnBlk,  // Block of Counters
0015       mtf7::ME,     // ME Data Record
0016       mtf7::RPC,    // RPC Data Record
0017       mtf7::GEM,    // GEM Data Record
0018       mtf7::ME0,    // ME0 Data Record
0019       mtf7::SPOut,  // SP Output Data Record
0020       mtf7::EvTr    // Event Record Trailer
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     // if (type_ == MTF7) {
0033     //    LogTrace("L1T") << "Writing MTF7 link header";
0034     //    return ((id_ & ID_mask) << ID_shift) | ((size_ & size_mask) << size_shift) | ((capID_ & capID_mask) << capID_shift);
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     // For MP7 format
0044     unsigned int wordsPerBx = payloadWordsPerBx;
0045     if (bxHeader) {
0046       ++wordsPerBx;
0047     }
0048     // Calculate how many BxBlock objects can be made with the available payload
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       // Pick the words from the block payload that correspond to the BX and add a BxBlock to the BxBlocks
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     // For legacy MC (74 first MC campaigns) skip one empty word that was
0093     // reserved for the header.  With data, read out infrastructure
0094     // version and algorithm version.
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 (  // Check bits for EMTF Event Record Header
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 (  // Check bits for EMTF MPC Link Errors
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     // Check bits for EMTF Event Record Trailer, get firmware version
0133     algo_ = 0;  // Firmware version
0134 
0135     // Start after always present Counters block
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)) {             // Indicators for the Trailer block
0142         algo_ = (((data16[4 * i + 2] >> 4) & 0x3F) << 9);   // Year  (6 bits)
0143         algo_ |= (((data16[4 * i + 2] >> 0) & 0x0F) << 5);  // Month (4 bits)
0144         algo_ |= (((data16[4 * i + 4] >> 0) & 0x1F) << 0);  // Day   (5 bits)
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     // Read in blocks equivalent to 64 bit words, trying to match the
0181     // pattern of first bits to what is deemed valid.
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     // only one block type, use dummy id
0226     unsigned blockId = 0;
0227     // CTP7 header contains number of BX in payload and the bunch crossing ID
0228     // Not sure how to map to generic BlockHeader variables, so just packing
0229     // it all in flags variable
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 }  // namespace l1t