Back to home page

Project CMSSW displayed by LXR

 
 

    


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

0001 #include "EventFilter/GctRawToDigi/plugins/GctRawToDigi.h"
0002 
0003 // System headers
0004 #include <vector>
0005 #include <sstream>
0006 #include <iostream>
0007 
0008 // Framework headers
0009 #include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
0010 #include "FWCore/ParameterSet/interface/ParameterSetDescription.h"
0011 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0012 #include "FWCore/Framework/interface/MakerMacros.h"
0013 
0014 // Raw data collection headers
0015 #include "DataFormats/FEDRawData/interface/FEDNumbering.h"
0016 #include "DataFormats/FEDRawData/interface/FEDRawDataCollection.h"
0017 
0018 // GCT Format Translators
0019 #include "EventFilter/GctRawToDigi/src/GctFormatTranslateMCLegacy.h"
0020 #include "EventFilter/GctRawToDigi/src/GctFormatTranslateV35.h"
0021 #include "EventFilter/GctRawToDigi/src/GctFormatTranslateV38.h"
0022 
0023 // Unpack collections class
0024 #include "EventFilter/GctRawToDigi/src/GctUnpackCollections.h"
0025 
0026 // Namespace resolution
0027 using std::cout;
0028 using std::dec;
0029 using std::endl;
0030 using std::hex;
0031 using std::string;
0032 using std::vector;
0033 
0034 GctRawToDigi::GctRawToDigi(const edm::ParameterSet& iConfig)
0035     : inputLabel_(iConfig.getParameter<edm::InputTag>("inputLabel")),
0036       fedId_(iConfig.getUntrackedParameter<int>("gctFedId", FEDNumbering::MINTriggerGCTFEDID)),
0037       hltMode_(iConfig.getParameter<bool>("hltMode")),
0038       numberOfGctSamplesToUnpack_(iConfig.getParameter<unsigned>("numberOfGctSamplesToUnpack")),
0039       numberOfRctSamplesToUnpack_(iConfig.getParameter<unsigned>("numberOfRctSamplesToUnpack")),
0040       unpackSharedRegions_(iConfig.getParameter<bool>("unpackSharedRegions")),
0041       formatVersion_(iConfig.getParameter<unsigned>("unpackerVersion")),
0042       checkHeaders_(iConfig.getUntrackedParameter<bool>("checkHeaders", false)),
0043       verbose_(iConfig.getUntrackedParameter<bool>("verbose", false)),
0044       formatTranslator_(nullptr),
0045       errors_(nullptr),
0046       errorCounters_(MAX_ERR_CODE + 1),  // initialise with the maximum error codes!
0047       unpackFailures_(0) {
0048   LogDebug("GCT") << "GctRawToDigi will unpack FED Id " << fedId_;
0049 
0050   // If the GctFormatTranslate version has been forced from config file, instantiate the relevant one.
0051   /***  THIS OBVIOUSLY STINKS - NEED TO REPLACE WITH SOMETHING BETTER THAN MASSIVE IF-ELSE SOON ***/
0052   /***  WHEN THIS MESS IS REMOVED REMEMBER THAT THE V38 FORMAT TRANSLATE HAS A DIFERENT CTOR TO THE OTHERS ***/
0053   if (formatVersion_ == 0) {
0054     edm::LogInfo("GCT")
0055         << "The required GCT Format Translator will be automatically determined from the first S-Link packet header.";
0056   } else if (formatVersion_ == 1) {
0057     edm::LogInfo("GCT") << "You have selected to use GctFormatTranslateMCLegacy";
0058     formatTranslator_ = new GctFormatTranslateMCLegacy(hltMode_, unpackSharedRegions_);
0059   } else if (formatVersion_ == 2) {
0060     edm::LogInfo("GCT") << "You have selected to use GctFormatTranslateV35";
0061     formatTranslator_ = new GctFormatTranslateV35(hltMode_, unpackSharedRegions_);
0062   } else if (formatVersion_ == 3) {
0063     edm::LogInfo("GCT") << "You have selected to use GctFormatTranslateV38";
0064     formatTranslator_ = new GctFormatTranslateV38(
0065         hltMode_, unpackSharedRegions_, numberOfGctSamplesToUnpack_, numberOfRctSamplesToUnpack_);
0066   } else {
0067     edm::LogWarning("GCT")
0068         << "You have requested a version of GctFormatTranslate that does not exist! Will attempt to auto-detect "
0069            "the required GCT Format Translator from the first S-Link packet header instead.";
0070   }
0071 
0072   if (hltMode_) {
0073     edm::LogInfo("GCT") << "HLT unpack mode selected: HLT unpack optimisations will be used.";
0074   }
0075   if (unpackSharedRegions_) {
0076     edm::LogInfo("GCT") << "You have selected to unpack shared RCT calo regions - be warned: "
0077                            "this is for commissioning purposes only!";
0078   }
0079 
0080   /** Register Products **/
0081   // GCT input collections
0082   produces<L1GctFibreCollection>();
0083   produces<L1CaloEmCollection>();
0084   produces<L1CaloRegionCollection>();
0085 
0086   // GCT internal collections
0087   produces<L1GctInternEmCandCollection>();
0088   produces<L1GctInternJetDataCollection>();
0089   produces<L1GctInternEtSumCollection>();
0090   produces<L1GctInternHFDataCollection>();
0091   produces<L1GctInternHtMissCollection>();
0092 
0093   // GCT output collections
0094   produces<L1GctEmCandCollection>("isoEm");
0095   produces<L1GctEmCandCollection>("nonIsoEm");
0096   produces<L1GctJetCandCollection>("cenJets");
0097   produces<L1GctJetCandCollection>("forJets");
0098   produces<L1GctJetCandCollection>("tauJets");
0099   produces<L1GctHFBitCountsCollection>();
0100   produces<L1GctHFRingEtSumsCollection>();
0101   produces<L1GctEtTotalCollection>();
0102   produces<L1GctEtHadCollection>();
0103   produces<L1GctEtMissCollection>();
0104   produces<L1GctHtMissCollection>();
0105   produces<L1GctJetCountsCollection>();  // Deprecated (empty collection still needed by GT)
0106 
0107   // Error collection
0108   produces<L1TriggerErrorCollection>();
0109   consumes<FEDRawDataCollection>(inputLabel_);
0110 }
0111 
0112 GctRawToDigi::~GctRawToDigi() {
0113   // do anything here that needs to be done at destruction time
0114   // (e.g. close files, deallocate resources etc.)
0115   delete formatTranslator_;
0116 }
0117 
0118 void GctRawToDigi::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
0119   edm::ParameterSetDescription desc;
0120   desc.add<bool>("unpackSharedRegions", false);
0121   desc.add<unsigned int>("numberOfGctSamplesToUnpack", 1);
0122   desc.add<unsigned int>("numberOfRctSamplesToUnpack", 1);
0123   desc.add<bool>("hltMode", false);
0124   desc.add<edm::InputTag>("inputLabel", edm::InputTag("rawDataCollector"));
0125   static const char* const kComment =
0126       " \n"
0127       "   value   |                        Unpacker/RAW Format Version \n"
0128       "-----------|---------------------------------------------------------------------------- \n"
0129       "     0     |   Auto-detects RAW Format in use - the recommended option \n"
0130       "     1     |   Force usage of the Monte-Carlo Legacy unpacker (unpacks DigiToRaw events) \n"
0131       "     2     |   Force usage of the RAW Format V35 unpacker \n"
0132       "     3     |   Force usage of the RAW Format V38 unpacker \n";
0133   desc.add<unsigned int>("unpackerVersion", 0)->setComment(kComment);
0134   desc.addUntracked<int>("gctFedId", 745);
0135   desc.addUntracked<bool>("checkHeaders", false), desc.addUntracked<bool>("verbose", false);
0136   descriptions.add("gctRawToDigi", desc);
0137 }
0138 
0139 //
0140 // member functions
0141 //
0142 
0143 // ------------ method called to produce the data  ------------
0144 void GctRawToDigi::produce(edm::Event& iEvent, const edm::EventSetup& iSetup) {
0145   using namespace edm;
0146 
0147   // Instantiate all the collections the unpacker needs; puts them in event when this object goes out of scope.
0148   std::unique_ptr<GctUnpackCollections> colls(new GctUnpackCollections(iEvent));
0149   errors_ = colls->errors();
0150 
0151   // get raw data collection
0152   edm::Handle<FEDRawDataCollection> feds;
0153   iEvent.getByLabel(inputLabel_, feds);
0154 
0155   // if raw data collection is present, do the unpacking
0156   if (feds.isValid()) {
0157     const FEDRawData& gctRcd = feds->FEDData(fedId_);
0158 
0159     LogDebug("GCT") << "Upacking FEDRawData of size " << std::dec << gctRcd.size();
0160 
0161     // check for empty events
0162     if (gctRcd.size() < 16) {
0163       LogDebug("GCT") << "Cannot unpack: empty/invalid GCT raw data (size = " << gctRcd.size()
0164                       << "). Returning empty collections!";
0165       addError(1);
0166       return;
0167     }
0168 
0169     // If no format translator yet set, need to auto-detect from header.
0170     // If auto format detection fails, we have no concrete format
0171     // translator instantiated... set error and bail
0172     if (!formatTranslator_) {
0173       if (!autoDetectRequiredFormatTranslator(gctRcd.data()))
0174         return;
0175     }
0176 
0177     // reset collection of block headers
0178     blockHeaders_.clear();
0179 
0180     // do the unpacking
0181     unpack(gctRcd, iEvent, colls.get());
0182 
0183     // check headers, if enabled
0184     if (checkHeaders_)
0185       checkHeaders();
0186 
0187     // dump summary in verbose mode
0188     if (verbose_) {
0189       doVerboseOutput(blockHeaders_, colls.get());
0190     }
0191   }
0192 }
0193 
0194 void GctRawToDigi::unpack(const FEDRawData& d, edm::Event& e, GctUnpackCollections* const colls) {
0195   // We should now have a valid formatTranslator pointer
0196   formatTranslator_->setUnpackCollections(colls);
0197 
0198   const unsigned char* data = d.data();  // The 8-bit wide raw-data array.
0199 
0200   // Data offset - starts at 16 as there is a 64-bit S-Link header followed
0201   // by a 64-bit software-controlled header (for pipeline format version
0202   // info that is not yet used).
0203   unsigned dPtr = 16;
0204 
0205   const unsigned dEnd = d.size() - 8;  // End of payload is at (packet size - final slink header)
0206 
0207   // read blocks
0208   for (unsigned nb = 0; dPtr < dEnd; ++nb) {
0209     if (nb >= MAX_BLOCKS) {
0210       LogDebug("GCT") << "Reached block limit - bailing out from this event!";
0211       addError(6);
0212       break;
0213     }
0214 
0215     // read block header
0216     GctBlockHeader blockHeader = formatTranslator_->generateBlockHeader(&data[dPtr]);
0217 
0218     // unpack the block; dPtr+4 is to get to the block data.
0219     if (!formatTranslator_->convertBlock(&data[dPtr + 4],
0220                                          blockHeader))  // Record if we had an unpack problem then skip rest of event.
0221     {
0222       LogDebug("GCT") << "Encountered block unpack error - bailing out from this event!";
0223       addError(4);
0224       break;
0225     }
0226 
0227     // advance pointer
0228     dPtr += 4 * (blockHeader.blockLength() * blockHeader.nSamples() +
0229                  1);  // *4 because blockLen is in 32-bit words, +1 for header
0230 
0231     // if verbose or checking block headers, store the header
0232     if (verbose_ || checkHeaders_)
0233       blockHeaders_.push_back(blockHeader);
0234   }
0235 }
0236 
0237 // detect raw data format version from known raw data address
0238 bool GctRawToDigi::autoDetectRequiredFormatTranslator(const unsigned char* d) {
0239   LogDebug("GCT") << "About to auto-detect the required format translator from the firmware version header.";
0240 
0241   const uint32_t* p32 = reinterpret_cast<const uint32_t*>(d);
0242   unsigned firmwareHeader = p32[2];
0243 
0244   /***  THIS OBVIOUSLY STINKS - NEED TO REPLACE WITH SOMETHING BETTER THAN MASSIVE IF-ELSE SOON ***/
0245   /***  WHEN THIS MESS IS REMOVED REMEMBER THAT THE V38 FORMAT TRANSLATE HAS A DIFERENT CTOR TO THE OTHERS ***/
0246 
0247   if (firmwareHeader >= 25 && firmwareHeader <= 35) {
0248     edm::LogInfo("GCT") << "Firmware Version V" << firmwareHeader << " detected: GctFormatTranslateV" << firmwareHeader
0249                         << " will be used to unpack.";
0250     formatTranslator_ = new GctFormatTranslateV35(hltMode_, unpackSharedRegions_);
0251     return true;
0252   } else if (firmwareHeader == 38) {
0253     edm::LogInfo("GCT") << "Firmware Version V" << firmwareHeader << " detected: GctFormatTranslateV" << firmwareHeader
0254                         << " will be used to unpack.";
0255     formatTranslator_ = new GctFormatTranslateV38(
0256         hltMode_, unpackSharedRegions_, numberOfGctSamplesToUnpack_, numberOfRctSamplesToUnpack_);
0257     return true;
0258   } else if (firmwareHeader == 0x00000000) {
0259     edm::LogInfo("GCT") << "Legacy Monte-Carlo data detected: GctFormatTranslateMCLegacy will be used to unpack.";
0260     formatTranslator_ = new GctFormatTranslateMCLegacy(hltMode_, unpackSharedRegions_);
0261     return true;
0262   }
0263   // these lines comments otherwise error is not reported!!!
0264   //  else if(firmwareHeader == 0xdeadffff) { /* Driver detected unknown firmware version. L1TriggerError code? */ }
0265   //  else if( firmwareHeader == 0xaaaaaaaa) { /* Before driver firmware version checks implemented. L1TriggerError code?  */ }
0266   else { /* Totally unknown firmware header */
0267 
0268     LogDebug("GCT") << "Failed to determine unpacker to use from the firmware version header! "
0269                        "(firmware header = 0x"
0270                     << hex << firmwareHeader << dec << ")";
0271     addError(2);
0272     return false;
0273   }
0274 }
0275 
0276 void GctRawToDigi::checkHeaders() {
0277   // TODO : loop over block headers found this event and check for consistency
0278 }
0279 
0280 void GctRawToDigi::doVerboseOutput(const GctBlockHeaderCollection& bHdrs,
0281                                    const GctUnpackCollections* const colls) const {
0282   std::ostringstream os;
0283   os << "Found " << bHdrs.size() << " GCT block headers" << endl;
0284   for (unsigned i = 0, size = bHdrs.size(); i < size; ++i) {
0285     os << "GCT Raw Data Block : " << formatTranslator_->getBlockDescription(bHdrs[i]) << " : " << bHdrs[i] << endl;
0286   }
0287   os << *colls << endl;
0288   edm::LogVerbatim("GCT") << os.str();
0289 }
0290 
0291 void GctRawToDigi::addError(const unsigned code) {
0292   // check this isn't going to break error handling
0293   if (code > MAX_ERR_CODE) {
0294     LogDebug("GCT") << "Unknown error code : " << code;
0295     return;
0296   }
0297 
0298   // print message on first instance of this error and if verbose flag set to true
0299   if (errorCounters_.at(code) == 0 && verbose_) {
0300     std::ostringstream os;
0301     switch (code) {
0302       case 0:
0303         os << "Reserved error code - not in use";
0304         break;
0305       case 1:
0306         os << "FED record empty or too short";
0307         break;
0308       case 2:
0309         os << "Unknown raw data version";
0310         break;
0311       case 3:
0312         os << "Detected unknown firmware version";
0313         break;
0314       case 4:
0315         os << "Detected unknown data block";
0316         break;
0317       case 5:
0318         os << "Block headers out of sync";
0319         break;
0320       case 6:
0321         os << "Too many blocks";
0322         break;
0323       default:
0324         os << "Unknown error code";
0325     }
0326     edm::LogError("GCT") << "Unpacking error " << code << " : " << os.str();
0327   }
0328 
0329   // increment error counter
0330   ++(errorCounters_.at(code));
0331 
0332   // store error in event if possible
0333   if (errors_ != nullptr) {
0334     errors_->push_back(L1TriggerError(fedId_, code));
0335   } else
0336     LogDebug("GCT") << "Detected error (code=" << code << ") but no error collection available!";
0337 }
0338 
0339 // ------------ method called once each job just after ending the event loop  ------------
0340 void GctRawToDigi::endJob() {
0341   unsigned total = 0;
0342   std::ostringstream os;
0343 
0344   for (unsigned i = 0; i <= MAX_ERR_CODE; ++i) {
0345     total += errorCounters_.at(i);
0346     os << "Error " << i << " (" << errorCounters_.at(i) << ")";
0347     if (i < MAX_ERR_CODE) {
0348       os << ", ";
0349     }
0350   }
0351 
0352   if (total > 0 && verbose_) {
0353     edm::LogError("GCT") << "Encountered " << total << " unpacking errors: " << os.str();
0354   }
0355 }
0356 
0357 /// make this a plugin
0358 DEFINE_FWK_MODULE(GctRawToDigi);