Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-02-14 13:26:08

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/CRC32Calculator.h"
0007 
0008 #include "EventFilter/L1TRawToDigi/interface/AMC13Spec.h"
0009 
0010 #define EDM_ML_DEBUG 1
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 dstring(reinterpret_cast<const char*>(start), reinterpret_cast<const char*>(end) + 4);
0042     auto crc = cms::CRC32Calculator(dstring).checksum();
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     // Start by indexing with 1
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     // Need at least a header and trailer
0068     // TODO check if this can be removed
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     // Initial filling of AMC payloads.  First, get the headers.  The
0089     // first payload follows afterwards.
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;     // total payload size
0096     unsigned int tot_nblocks = 0;  // total blocks of payload
0097     unsigned int maxblocks = 0;    // counting the # of amc13 header/trailers (1 ea per block)
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 +      // payload size
0110                          tot_nblocks +   // AMC headers
0111                          2 * maxblocks;  // AMC13 headers
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     // Read in the first AMC block and append the payload to the
0121     // corresponding AMC packet.
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 check(reinterpret_cast<const char*>(start), reinterpret_cast<const char*>(data) - 4);
0132       crc = cms::CRC32Calculator(check).checksum();
0133 
0134       LogDebug("L1T") << "checking data checksum of " << std::hex << crc << std::dec;
0135     }
0136 
0137     t.check(crc, 0, lv1, bx);
0138 
0139     // Read in remaining AMC blocks
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 check(reinterpret_cast<const char*>(start), reinterpret_cast<const char*>(data) - 4);
0160         crc = cms::CRC32Calculator(check).checksum();
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     // Size is total amount of words + # of blocks for AMC headers + # of
0198     // maxblocks for AMC13 block header, trailer
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       // uint64_t * block_start = data;
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 }  // namespace amc13