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
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
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
0080 if (!processCDFHeaders(fed, word, word_end, crc, *counters)) {
0081 continue;
0082 }
0083
0084
0085 if (!processCDFTrailers(fed, nwords, word, word_end, crc, *counters)) {
0086 continue;
0087 }
0088
0089
0090 if (!processBlocks(fed, word, word_end, crc, *counters, amc_payload)) {
0091 continue;
0092 }
0093
0094
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));
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
0152
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
0187
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) {
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);