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 #include "FWCore/Utilities/interface/CRC32Calculator.h"
0005 
0006 #include "EventFilter/L1TRawToDigi/interface/AMCSpec.h"
0007 
0008 #define EDM_ML_DEBUG 1
0009 
0010 namespace amc {
0011   BlockHeader::BlockHeader(unsigned int amc_no, unsigned int board_id, unsigned int size, unsigned int block) {
0012     // Determine size
0013     unsigned int max_block_no = 0;
0014     if (size >= 0x13ff)
0015       max_block_no = (size - 1023) / 4096;
0016 
0017     if (block != max_block_no)
0018       size = split_block_size;
0019     else if (block != 0)
0020       size -= split_block_size * max_block_no;
0021 
0022     data_ = (static_cast<uint64_t>(size & Size_mask) << Size_shift) |
0023             (static_cast<uint64_t>(block & BlkNo_mask) << BlkNo_shift) |
0024             (static_cast<uint64_t>(amc_no & AmcNo_mask) << AmcNo_shift) |
0025             (static_cast<uint64_t>(board_id & BoardID_mask) << BoardID_shift) | (1llu << Enabled_bit_shift) |
0026             (1llu << Present_bit_shift);
0027 
0028     if (block == getBlocks() - 1) {
0029       // Last block
0030       data_ |= (1llu << CRC_bit_shift) | (1llu << Valid_bit_shift) | (1llu << Length_bit_shift);
0031     }
0032 
0033     if (block == 0 && getBlocks() == 1) {
0034       // Bits already zeroed - only one block
0035     } else if (block == 0) {
0036       // First of many blocks
0037       data_ |= 1llu << More_bit_shift;
0038     } else if (block == getBlocks() - 1) {
0039       // Last of many blocks
0040       data_ |= 1llu << Segmented_bit_shift;
0041     } else {
0042       // Intermediate of many blocks
0043       data_ |= (1llu << More_bit_shift) | (1llu << Segmented_bit_shift);
0044     }
0045   }
0046 
0047   unsigned int BlockHeader::getBlocks() const {
0048     // The first block of a segmented event has a size of 1023, all
0049     // following have a max size of 4096.  Segmentation only happens
0050     // for AMC payloads >= 0x13ff 64 bit words.
0051     unsigned int size = getSize();
0052     if (size >= 0x13ff)
0053       return (size - 1023) / 4096 + 1;
0054     return 1;
0055   }
0056 
0057   unsigned int BlockHeader::getBlockSize() const {
0058     // More and not Segmented means the first of multiple blocks.  For
0059     // these, getSize() returns the total size of the AMC packet, not the
0060     // size of the first block.
0061     if (getMore() && !getSegmented())
0062       return split_block_size;
0063     return getSize();
0064   }
0065 
0066   Header::Header(unsigned int amc_no,
0067                  unsigned int lv1_id,
0068                  unsigned int bx_id,
0069                  unsigned int size,
0070                  unsigned int or_n,
0071                  unsigned int board_id,
0072                  unsigned int user)
0073       : data0_((uint64_t(amc_no & AmcNo_mask) << AmcNo_shift) | (uint64_t(lv1_id & LV1ID_mask) << LV1ID_shift) |
0074                (uint64_t(bx_id & BX_mask) << BX_shift) | (uint64_t(size & Size_mask) << Size_shift)),
0075         data1_((uint64_t(or_n & OrN_mask) << OrN_shift) | (uint64_t(board_id & BoardID_mask) << BoardID_shift) |
0076                (uint64_t(user & User_mask) << User_shift)) {}
0077 
0078   Trailer::Trailer(unsigned int crc, unsigned int lv1_id, unsigned int size)
0079       : data_((uint64_t(crc & CRC_mask) << CRC_shift) | (uint64_t(lv1_id & LV1ID_mask) << LV1ID_shift) |
0080               (uint64_t(size & Size_mask) << Size_shift)) {}
0081 
0082   bool Trailer::check(unsigned int crc, unsigned int lv1_id, unsigned int size, bool mtf7_mode) const {
0083     if ((crc != getCRC() || size != getSize() || (lv1_id & LV1ID_mask) != getLV1ID()) && !mtf7_mode) {
0084       edm::LogWarning("L1T") << "Found AMC trailer with:"
0085                              << "\n\tLV1 ID " << getLV1ID() << ", size " << getSize() << ", CRC " << std::hex
0086                              << std::setw(8) << std::setfill('0') << getCRC() << std::dec << "\nBut expected:"
0087                              << "\n\tLV1 ID " << (lv1_id & LV1ID_mask) << ", size " << size << ", CRC " << std::hex
0088                              << std::setw(8) << std::setfill('0') << crc;
0089       return false;
0090     }
0091     return true;
0092   }
0093 
0094   void Trailer::writeCRC(const uint64_t *start, uint64_t *end) {
0095     std::string dstring(reinterpret_cast<const char *>(start), reinterpret_cast<const char *>(end) + 4);
0096     auto crc = cms::CRC32Calculator(dstring).checksum();
0097 
0098     *end = ((*end) & ~(uint64_t(CRC_mask) << CRC_shift)) | (static_cast<uint64_t>(crc & CRC_mask) << CRC_shift);
0099   }
0100 
0101   Packet::Packet(unsigned int amc,
0102                  unsigned int board,
0103                  unsigned int lv1id,
0104                  unsigned int orbit,
0105                  unsigned int bx,
0106                  const std::vector<uint64_t> &load,
0107                  unsigned int user)
0108       : block_header_(amc, board, load.size() + 3),  // add 3 words for header (2) and trailer (1)
0109         header_(amc, lv1id, bx, load.size() + 3, orbit, board, user),
0110         trailer_(0, lv1id, load.size() + 3) {
0111     auto hdata = header_.raw();
0112     payload_.reserve(load.size() + 3);
0113     payload_.insert(payload_.end(), hdata.begin(), hdata.end());
0114     payload_.insert(payload_.end(), load.begin(), load.end());
0115     payload_.insert(payload_.end(), trailer_.raw());
0116 
0117     auto ptr = payload_.data();
0118     Trailer::writeCRC(ptr, ptr + payload_.size() - 1);
0119   }
0120 
0121   void Packet::addPayload(const uint64_t *data, unsigned int size) {
0122     payload_.insert(payload_.end(), data, data + size);
0123   }
0124 
0125   void Packet::finalize(unsigned int lv1, unsigned int bx, bool legacy_mc, bool mtf7_mode) {
0126     if (legacy_mc) {
0127       header_ =
0128           Header(block_header_.getAMCNumber(), lv1, bx, block_header_.getSize(), 0, block_header_.getBoardID(), 0);
0129 
0130       payload_.insert(payload_.begin(), {0, 0});
0131       payload_.insert(payload_.end(), {0});
0132     } else {
0133       header_ = Header(payload_.data());
0134       trailer_ = Trailer(&payload_.back());
0135 
0136       std::string check(reinterpret_cast<const char *>(payload_.data()), payload_.size() * 8 - 4);
0137       auto crc = cms::CRC32Calculator(check).checksum();
0138 
0139       trailer_.check(crc, lv1, header_.getSize(), mtf7_mode);
0140     }
0141   }
0142 
0143   std::vector<uint64_t> Packet::block(unsigned int id) const {
0144     if (id == 0 and id == block_header_.getBlocks() - 1) {
0145       return payload_;
0146     } else if (id == block_header_.getBlocks() - 1) {
0147       return std::vector<uint64_t>(payload_.begin() + id * split_block_size, payload_.end());
0148     } else {
0149       return std::vector<uint64_t>(payload_.begin() + id * split_block_size,
0150                                    payload_.begin() + (id + 1) * split_block_size);
0151     }
0152   }
0153 
0154   std::unique_ptr<uint64_t[]> Packet::data() {
0155     // Remove 3 words: 2 for the header, 1 for the trailer
0156     std::unique_ptr<uint64_t[]> res(new uint64_t[payload_.size() - 3]);
0157     for (unsigned int i = 0; i < payload_.size() - 3; ++i)
0158       res.get()[i] = payload_[i + 2];
0159     return res;
0160   }
0161 }  // namespace amc