Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:10:58

0001 #include "EventFilter/RPCRawToDigi/plugins/RPCAMCRawToDigi.h"
0002 
0003 #include <memory>
0004 
0005 #include "DataFormats/Common/interface/Handle.h"
0006 #include "FWCore/Framework/interface/Event.h"
0007 #include "FWCore/Framework/interface/EventSetup.h"
0008 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0009 #include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
0010 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0011 #include "FWCore/Utilities/interface/InputTag.h"
0012 
0013 #include "DataFormats/FEDRawData/interface/FEDHeader.h"
0014 #include "DataFormats/FEDRawData/interface/FEDTrailer.h"
0015 #include "EventFilter/RPCRawToDigi/interface/RPCAMCLinkEvents.h"
0016 #include "EventFilter/RPCRawToDigi/interface/RPCAMCRecord.h"
0017 #include "EventFilter/RPCRawToDigi/plugins/RPCAMCUnpacker.h"
0018 #include "EventFilter/RPCRawToDigi/plugins/RPCAMCUnpackerFactory.h"
0019 
0020 RPCAMCRawToDigi::RPCAMCRawToDigi(edm::ParameterSet const &config)
0021     : calculate_crc_(config.getParameter<bool>("calculateCRC")),
0022       fill_counters_(config.getParameter<bool>("fillCounters")),
0023       rpc_unpacker_(
0024           RPCAMCUnpackerFactory::get()->create(config.getParameter<std::string>("RPCAMCUnpacker"),
0025                                                config.getParameter<edm::ParameterSet>("RPCAMCUnpackerSettings"),
0026                                                consumesCollector(),
0027                                                producesCollector())) {
0028   if (fill_counters_) {
0029     produces<RPCAMCLinkCounters>();
0030   }
0031 
0032   raw_token_ = consumes<FEDRawDataCollection>(config.getParameter<edm::InputTag>("inputTag"));
0033 }
0034 
0035 RPCAMCRawToDigi::~RPCAMCRawToDigi() {}
0036 
0037 void RPCAMCRawToDigi::fillDescriptions(edm::ConfigurationDescriptions &descs) {
0038   edm::ParameterSetDescription desc;
0039   desc.add<edm::InputTag>("inputTag", edm::InputTag("rawDataCollector", ""));
0040   desc.add<bool>("calculateCRC", true);
0041   desc.add<bool>("fillCounters", true);
0042   desc.add<std::string>("RPCAMCUnpacker", "RPCAMCUnpacker");
0043   RPCAMCUnpacker::fillDescription(desc);
0044   descs.add("RPCAMCRawToDigi", desc);
0045 }
0046 
0047 void RPCAMCRawToDigi::beginRun(edm::Run const &run, edm::EventSetup const &setup) {
0048   rpc_unpacker_->beginRun(run, setup);
0049 }
0050 
0051 void RPCAMCRawToDigi::produce(edm::Event &event, edm::EventSetup const &setup) {
0052   // Get RAW Data
0053   edm::Handle<FEDRawDataCollection> raw_data_collection;
0054   event.getByToken(raw_token_, raw_data_collection);
0055 
0056   std::unique_ptr<RPCAMCLinkCounters> counters(new RPCAMCLinkCounters());
0057 
0058   std::map<RPCAMCLink, rpcamc13::AMCPayload> amc_payload;
0059 
0060   // Loop over the FEDs
0061   for (int fed : rpc_unpacker_->getFeds()) {
0062     if (fill_counters_) {
0063       counters->add(RPCAMCLinkEvents::fed_event_, RPCAMCLink(fed, RPCAMCLink::wildcard_));
0064     }
0065 
0066     std::uint16_t crc(0xffff);
0067 
0068     FEDRawData const &raw_data = raw_data_collection->FEDData(fed);
0069     unsigned int nwords(raw_data.size() / sizeof(std::uint64_t));
0070     if (!nwords) {
0071       continue;
0072     }
0073 
0074     std::uint64_t const *word(reinterpret_cast<std::uint64_t const *>(raw_data.data()));
0075     std::uint64_t const *word_end = word + nwords;
0076 
0077     LogDebug("RPCAMCRawToDigi") << "Handling FED " << fed << " with length " << nwords;
0078 
0079     // Handle the CDF Headers
0080     if (!processCDFHeaders(fed, word, word_end, crc, *counters)) {
0081       continue;
0082     }
0083 
0084     // Handle the CDF Trailers
0085     if (!processCDFTrailers(fed, nwords, word, word_end, crc, *counters)) {
0086       continue;
0087     }
0088 
0089     // Loop over the Blocks
0090     if (!processBlocks(fed, word, word_end, crc, *counters, amc_payload)) {
0091       continue;
0092     }
0093 
0094     // Complete CRC check with trailer
0095     if (calculate_crc_) {
0096       word = word_end;
0097       word_end = reinterpret_cast<std::uint64_t const *>(raw_data.data()) + nwords - 1;
0098       for (; word < word_end; ++word) {
0099         compute_crc16_64bit(crc, *word);
0100       }
0101       compute_crc16_64bit(crc, (*word & 0xffffffff0000ffff));  // trailer excluding crc
0102       FEDTrailer trailer(reinterpret_cast<unsigned char const *>(word_end));
0103       if ((unsigned int)(trailer.crc()) != crc) {
0104         if (fill_counters_) {
0105           counters->add(RPCAMCLinkEvents::fed_trailer_crc_mismatch_, RPCAMCLink(fed, RPCAMCLink::wildcard_));
0106         }
0107         edm::LogWarning("RPCAMCRawToDigi") << "FED Trailer CRC doesn't match for FED id " << fed;
0108         continue;
0109       }
0110     }
0111   }
0112 
0113   rpc_unpacker_->produce(event, setup, amc_payload);
0114 
0115   if (fill_counters_) {
0116     event.put(std::move(counters));
0117   }
0118 }
0119 
0120 bool RPCAMCRawToDigi::processCDFHeaders(int fed,
0121                                         std::uint64_t const *&word,
0122                                         std::uint64_t const *&word_end,
0123                                         std::uint16_t &crc,
0124                                         RPCAMCLinkCounters &counters) const {
0125   bool more_headers(true);
0126   for (; word < word_end && more_headers; ++word) {
0127     if (calculate_crc_) {
0128       compute_crc16_64bit(crc, *word);
0129     }
0130 
0131     LogDebug("RPCAMCRawToDigi") << "CDF Header " << std::hex << *word << std::dec;
0132     FEDHeader header(reinterpret_cast<unsigned char const *>(word));
0133     if (!header.check()) {
0134       if (fill_counters_) {
0135         counters.add(RPCAMCLinkEvents::fed_header_check_fail_, RPCAMCLink(fed, RPCAMCLink::wildcard_));
0136       }
0137       edm::LogWarning("RPCAMCRawToDigi") << "FED Header check failed for FED id " << fed;
0138       ++word;
0139       return false;
0140     }
0141     if (header.sourceID() != fed) {
0142       if (fill_counters_) {
0143         counters.add(RPCAMCLinkEvents::fed_header_id_mismatch_, RPCAMCLink(fed, RPCAMCLink::wildcard_));
0144       }
0145       edm::LogWarning("RPCAMCRawToDigi") << "FED Header Source ID " << header.sourceID()
0146                                          << " does not match requested FED id " << fed;
0147       ++word;
0148       return false;
0149     }
0150 
0151     // moreHeaders() not used
0152     // more_headers = header.moreHeaders();
0153     more_headers = false;
0154   }
0155 
0156   return !more_headers;
0157 }
0158 
0159 bool RPCAMCRawToDigi::processCDFTrailers(int fed,
0160                                          unsigned int nwords,
0161                                          std::uint64_t const *&word,
0162                                          std::uint64_t const *&word_end,
0163                                          std::uint16_t &crc,
0164                                          RPCAMCLinkCounters &counters) const {
0165   bool more_trailers(true);
0166   for (--word_end; word_end > word && more_trailers; --word_end) {
0167     FEDTrailer trailer(reinterpret_cast<unsigned char const *>(word_end));
0168     LogDebug("RPCAMCRawToDigi") << "CDF Trailer " << std::hex << *word_end << std::dec << ", length "
0169                                 << trailer.fragmentLength();
0170     if (!trailer.check()) {
0171       if (fill_counters_) {
0172         counters.add(RPCAMCLinkEvents::fed_trailer_check_fail_, RPCAMCLink(fed, RPCAMCLink::wildcard_));
0173       }
0174       edm::LogWarning("RPCAMCRawToDigi") << "FED Trailer check failed for FED id " << fed;
0175       return false;
0176     }
0177     if (trailer.fragmentLength() != nwords) {
0178       if (fill_counters_) {
0179         counters.add(RPCAMCLinkEvents::fed_trailer_length_mismatch_, RPCAMCLink(fed, RPCAMCLink::wildcard_));
0180       }
0181       edm::LogWarning("RPCAMCRawToDigi") << "FED Trailer length " << trailer.fragmentLength()
0182                                          << " does not match actual data size " << nwords << " for FED id " << fed;
0183       return false;
0184     }
0185 
0186     // moreTrailers() not used
0187     // more_trailers = trailer.moreTrailers();
0188     more_trailers = false;
0189   }
0190 
0191   ++word_end;
0192 
0193   return !more_trailers;
0194 }
0195 
0196 bool RPCAMCRawToDigi::processBlocks(int fed,
0197                                     std::uint64_t const *&word,
0198                                     std::uint64_t const *word_end,
0199                                     std::uint16_t &crc,
0200                                     RPCAMCLinkCounters &counters,
0201                                     std::map<RPCAMCLink, rpcamc13::AMCPayload> &amc_payload) const {
0202   while (word < word_end) {
0203     rpcamc13::Header header(*word);
0204     if (calculate_crc_) {
0205       compute_crc16_64bit(crc, *word);
0206     }
0207     ++word;
0208 
0209     unsigned int n_amc(header.getNAMC());
0210     if (word + n_amc + 1 >= word_end) {  // AMC Headers and AMC13 Trailer
0211       if (fill_counters_) {
0212         counters.add(RPCAMCLinkEvents::fed_amc13_block_incomplete_, RPCAMCLink(fed, RPCAMCLink::wildcard_));
0213       }
0214       edm::LogWarning("RPCAMCRawToDigi") << "AMC13 Block can not be complete for FED " << fed;
0215       word = word_end;
0216       return false;
0217     }
0218 
0219     std::uint64_t const *payload_word(word + n_amc);
0220     std::uint64_t const *payload_word_end(payload_word);
0221     for (unsigned int amc = 0; amc < n_amc; ++amc) {
0222       rpcamc13::AMCHeader amc13_amc_header(*word);
0223       if (calculate_crc_) {
0224         compute_crc16_64bit(crc, *word);
0225       }
0226       ++word;
0227 
0228       unsigned int size_in_block(amc13_amc_header.getSizeInBlock());
0229       if (size_in_block == 0) {
0230         continue;
0231       }
0232       payload_word = payload_word_end;
0233       payload_word_end += size_in_block;
0234 
0235       unsigned int amc_number(amc13_amc_header.getAMCNumber());
0236       if (amc_number > (unsigned int)RPCAMCLink::max_amcnumber_) {
0237         if (fill_counters_) {
0238           counters.add(RPCAMCLinkEvents::fed_amc13_amc_number_invalid_, RPCAMCLink(fed, RPCAMCLink::wildcard_));
0239         }
0240         edm::LogWarning("RPCAMCRawToDigi") << "Invalid AMC Number " << amc_number << " for FED " << fed;
0241         continue;
0242       }
0243 
0244       if (payload_word_end > word_end) {
0245         if (fill_counters_) {
0246           counters.add(RPCAMCLinkEvents::amc_amc13_block_incomplete_, RPCAMCLink(fed, amc_number));
0247         }
0248         edm::LogWarning("RPCAMCRawToDigi")
0249             << "AMC Block can not be complete for FED " << fed << " at AMC " << amc_number;
0250         return false;
0251       }
0252 
0253       rpcamc13::AMCPayload &payload(amc_payload[RPCAMCLink(fed, amc_number)]);
0254 
0255       if (amc13_amc_header.isFirstBlock()) {
0256         payload.setAMCHeader(amc13_amc_header);
0257         if (fill_counters_) {
0258           counters.add(RPCAMCLinkEvents::amc_event_, RPCAMCLink(fed, amc_number));
0259         }
0260 
0261         if (!amc13_amc_header.isValid()) {
0262           if (fill_counters_) {
0263             counters.add(RPCAMCLinkEvents::amc_amc13_evc_bc_invalid_, RPCAMCLink(fed, amc_number));
0264           }
0265           edm::LogWarning("RPCAMCRawToDigi")
0266               << "AMC13 AMC Header is reporting an invalid "
0267               << "Event Counter or Bunch Counter for FED " << fed << ", AMC " << amc_number;
0268           payload.setValid(false);
0269         }
0270 
0271         rpcamc::Header amc_amc_header(payload_word);
0272         if (amc_number != amc_amc_header.getAMCNumber()) {
0273           if (fill_counters_) {
0274             counters.add(RPCAMCLinkEvents::amc_number_mismatch_, RPCAMCLink(fed, amc_number));
0275           }
0276           edm::LogWarning("RPCAMCRawToDigi")
0277               << "AMC Number inconsistent in AMC13 AMC Header vs AMC Header: " << amc_number << " vs "
0278               << amc_amc_header.getAMCNumber();
0279           payload.setValid(false);
0280         }
0281 
0282         if (amc_amc_header.hasDataLength() && amc13_amc_header.hasTotalSize() &&
0283             amc13_amc_header.getSize() != amc_amc_header.getDataLength()) {
0284           if (fill_counters_) {
0285             counters.add(RPCAMCLinkEvents::amc_size_mismatch_, RPCAMCLink(fed, amc_number));
0286           }
0287           edm::LogWarning("RPCAMCRawToDigi")
0288               << "AMC size inconsistent in AMC13 AMC Header vs AMC Header: " << amc13_amc_header.getSize() << " vs "
0289               << amc_amc_header.getDataLength();
0290           payload.setValid(false);
0291         }
0292       }
0293 
0294       if (amc13_amc_header.isLastBlock()) {
0295         if (!amc13_amc_header.isFirstBlock()) {
0296           edm::LogWarning("RPCAMCRawToDigi") << "Multiple blocks";
0297         }
0298         payload.getAMCHeader().setCRCOk(amc13_amc_header.isCRCOk());
0299         payload.getAMCHeader().setLengthCorrect(amc13_amc_header.isLengthCorrect());
0300 
0301         if (!amc13_amc_header.isCRCOk()) {
0302           if (fill_counters_) {
0303             counters.add(RPCAMCLinkEvents::amc_amc13_crc_mismatch_, RPCAMCLink(fed, amc_number));
0304           }
0305           edm::LogWarning("RPCAMCRawToDigi")
0306               << "AMC13 AMC Header is reporting a mismatched  "
0307               << "Event Counter or Bunch Counter for FED " << fed << ", AMC " << amc_number;
0308           payload.setValid(false);
0309         }
0310 
0311         if (!amc13_amc_header.isLengthCorrect()) {
0312           if (fill_counters_) {
0313             counters.add(RPCAMCLinkEvents::amc_amc13_length_incorrect_, RPCAMCLink(fed, amc_number));
0314           }
0315           edm::LogWarning("RPCAMCRawToDigi") << "AMC13 AMC Header is reporting an incorrect length "
0316                                              << "for FED " << fed << ", AMC " << amc_number;
0317           payload.setValid(false);
0318         }
0319 
0320         if (amc13_amc_header.hasTotalSize() &&
0321             amc13_amc_header.getSize() != (payload.getData().size() + size_in_block)) {
0322           if (fill_counters_) {
0323             counters.add(RPCAMCLinkEvents::amc_amc13_size_inconsistent_, RPCAMCLink(fed, amc_number));
0324           }
0325           edm::LogWarning("RPCAMCRawToDigi") << "Size in AMC13 AMC Header doesn't match payload size "
0326                                              << "for FED " << fed << ", AMC " << amc_number;
0327           payload.setValid(false);
0328         }
0329 
0330         if (!payload.getData().empty() && (payload.getData().size() + size_in_block) < 3) {
0331           if (fill_counters_) {
0332             counters.add(RPCAMCLinkEvents::amc_payload_incomplete_, RPCAMCLink(fed, amc_number));
0333           }
0334           edm::LogWarning("RPCAMCRawToDigi") << "Size in AMC13 AMC Header doesn't match payload size "
0335                                              << "for FED " << fed << ", AMC " << amc_number;
0336           payload.setValid(false);
0337         }
0338       }
0339 
0340       if (size_in_block > 0) {
0341         payload.insert(payload_word, size_in_block);
0342       }
0343     }
0344 
0345     if (calculate_crc_) {
0346       for (; word < payload_word_end; ++word) {
0347         compute_crc16_64bit(crc, *word);
0348       }
0349     } else {
0350       word = payload_word_end;
0351     }
0352 
0353     if (calculate_crc_) {
0354       compute_crc16_64bit(crc, *word);
0355     }
0356     ++word;
0357   }
0358   return true;
0359 }
0360 
0361 #include "FWCore/Framework/interface/MakerMacros.h"
0362 DEFINE_FWK_MODULE(RPCAMCRawToDigi);