Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-02-14 13:15:07

0001 /**
0002  * \class L1GlobalTriggerEvmRawToDigi
0003  *
0004  *
0005  * Description: unpack raw data into digitized data.
0006  *
0007  * Implementation:
0008  *    <TODO: enter implementation details>
0009  *
0010  * \author: Vasile Mihai Ghete - HEPHY Vienna
0011  *
0012  *
0013  */
0014 
0015 // this class header
0016 #include "EventFilter/L1GlobalTriggerRawToDigi/interface/L1GlobalTriggerEvmRawToDigi.h"
0017 
0018 // system include files
0019 #include <iostream>
0020 #include <iomanip>
0021 #include <algorithm>
0022 
0023 // user include files
0024 #include "DataFormats/L1GlobalTrigger/interface/L1GlobalTriggerReadoutSetup.h"
0025 #include "DataFormats/L1GlobalTrigger/interface/L1GlobalTriggerEvmReadoutRecord.h"
0026 
0027 #include "DataFormats/FEDRawData/interface/FEDNumbering.h"
0028 #include "DataFormats/FEDRawData/interface/FEDHeader.h"
0029 #include "DataFormats/FEDRawData/interface/FEDTrailer.h"
0030 #include "DataFormats/FEDRawData/interface/FEDRawDataCollection.h"
0031 
0032 #include "DataFormats/L1GlobalTrigger/interface/L1GtfeWord.h"
0033 #include "DataFormats/L1GlobalTrigger/interface/L1GtfeExtWord.h"
0034 #include "DataFormats/L1GlobalTrigger/interface/L1TcsWord.h"
0035 #include "DataFormats/L1GlobalTrigger/interface/L1GtFdlWord.h"
0036 
0037 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0038 #include "FWCore/Utilities/interface/InputTag.h"
0039 
0040 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0041 #include "FWCore/MessageLogger/interface/MessageDrop.h"
0042 
0043 #include "FWCore/Framework/interface/EventSetup.h"
0044 #include "FWCore/Framework/interface/ESHandle.h"
0045 
0046 #include "CondFormats/L1TObjects/interface/L1GtFwd.h"
0047 #include "CondFormats/L1TObjects/interface/L1GtBoard.h"
0048 
0049 // constructor(s)
0050 L1GlobalTriggerEvmRawToDigi::L1GlobalTriggerEvmRawToDigi(const edm::ParameterSet& pSet)
0051     :
0052 
0053       // input tag for EVM GT record
0054       m_evmGtInputTag(pSet.getParameter<edm::InputTag>("EvmGtInputTag")),
0055 
0056       // FED Id for GT EVM record
0057       // default value defined in DataFormats/FEDRawData/src/FEDNumbering.cc
0058       // default value: assume the EVM record is the first GT record
0059       m_evmGtFedId(pSet.getUntrackedParameter<int>("EvmGtFedId", FEDNumbering::MINTriggerGTPFEDID)),
0060 
0061       /// EventSetup Token for L1GtBoardMaps
0062       m_l1GtBMToken(esConsumes<L1GtBoardMaps, L1GtBoardMapsRcd>()),
0063 
0064       // mask for active boards
0065       m_activeBoardsMaskGt(pSet.getParameter<unsigned int>("ActiveBoardsMask")),
0066 
0067       // number of bunch crossing to be unpacked
0068       m_unpackBxInEvent(pSet.getParameter<int>("UnpackBxInEvent")),
0069 
0070       m_lowSkipBxInEvent(0),
0071       m_uppSkipBxInEvent(0),
0072 
0073       m_recordLength0(0),
0074       m_recordLength1(0),
0075 
0076       m_totalBxInEvent(0),
0077 
0078       // length of BST record (in bytes)
0079       m_bstLengthBytes(pSet.getParameter<int>("BstLengthBytes")),
0080 
0081       m_verbosity(pSet.getUntrackedParameter<int>("Verbosity", 0)),
0082 
0083       m_isDebugEnabled(edm::isDebugEnabled())
0084 
0085 {
0086   produces<L1GlobalTriggerEvmReadoutRecord>();
0087 
0088   if (m_verbosity && m_isDebugEnabled) {
0089     LogDebug("L1GlobalTriggerEvmRawToDigi")
0090         << "\nInput tag for EVM GT record:             " << m_evmGtInputTag
0091         << "\nFED Id for EVM GT record:                " << m_evmGtFedId
0092         << "\nMask for active boards (hex format):     " << std::hex << std::setw(sizeof(m_activeBoardsMaskGt) * 2)
0093         << std::setfill('0') << m_activeBoardsMaskGt << std::dec << std::setfill(' ')
0094         << "\nNumber of bunch crossing to be unpacked: " << m_unpackBxInEvent
0095         << "\nLength of BST message [bytes]:           " << m_bstLengthBytes << "\n"
0096         << std::endl;
0097   }
0098 
0099   if ((m_unpackBxInEvent > 0) && ((m_unpackBxInEvent % 2) == 0)) {
0100     m_unpackBxInEvent = m_unpackBxInEvent - 1;
0101 
0102     if (m_verbosity) {
0103       edm::LogInfo("L1GlobalTriggerEvmRawToDigi")
0104           << "\nWARNING: Number of bunch crossing to be unpacked rounded to: " << m_unpackBxInEvent
0105           << "\n         The number must be an odd number!\n"
0106           << std::endl;
0107     }
0108   }
0109 
0110   // create GTFE, TCS, FDL cards once per analyzer
0111   // content will be reset whenever needed
0112 
0113   m_gtfeWord = new L1GtfeExtWord();
0114   m_tcsWord = new L1TcsWord();
0115   m_gtFdlWord = new L1GtFdlWord();
0116   consumes<FEDRawDataCollection>(m_evmGtInputTag);
0117 
0118   /// EventSetup Token for L1GtParameters
0119   if (m_bstLengthBytes < 0) {
0120     m_l1GtParamToken = esConsumes<L1GtParameters, L1GtParametersRcd>();
0121   }
0122 }
0123 
0124 // destructor
0125 L1GlobalTriggerEvmRawToDigi::~L1GlobalTriggerEvmRawToDigi() {
0126   delete m_gtfeWord;
0127   delete m_tcsWord;
0128   delete m_gtFdlWord;
0129 }
0130 
0131 // member functions
0132 
0133 // method called to produce the data
0134 void L1GlobalTriggerEvmRawToDigi::produce(edm::Event& iEvent, const edm::EventSetup& evSetup) {
0135   // get records from EventSetup
0136 
0137   //  board maps
0138   edm::ESHandle<L1GtBoardMaps> l1GtBM = evSetup.getHandle(m_l1GtBMToken);
0139 
0140   const std::vector<L1GtBoard> boardMaps = l1GtBM->gtBoardMaps();
0141   int boardMapsSize = boardMaps.size();
0142 
0143   typedef std::vector<L1GtBoard>::const_iterator CItBoardMaps;
0144 
0145   // create an ordered vector for the GT EVM record
0146   // header (pos 0 in record) and trailer (last position in record)
0147   // not included, as they are not in board list
0148   std::vector<L1GtBoard> gtRecordMap;
0149   gtRecordMap.reserve(boardMapsSize);
0150 
0151   for (int iPos = 0; iPos < boardMapsSize; ++iPos) {
0152     for (CItBoardMaps itBoard = boardMaps.begin(); itBoard != boardMaps.end(); ++itBoard) {
0153       if (itBoard->gtPositionEvmRecord() == iPos) {
0154         gtRecordMap.push_back(*itBoard);
0155         break;
0156       }
0157     }
0158   }
0159 
0160   // raw collection
0161 
0162   edm::Handle<FEDRawDataCollection> fedHandle;
0163   iEvent.getByLabel(m_evmGtInputTag, fedHandle);
0164 
0165   if (!fedHandle.isValid()) {
0166     if (m_verbosity) {
0167       edm::LogWarning("L1GlobalTriggerEvmRawToDigi")
0168           << "\nWarning: FEDRawDataCollection with input tag " << m_evmGtInputTag
0169           << "\nrequested in configuration, but not found in the event."
0170           << "\nQuit unpacking this event" << std::endl;
0171     }
0172 
0173     produceEmptyProducts(iEvent);
0174 
0175     return;
0176   }
0177 
0178   // retrieve data for Global Trigger EVM FED
0179   const FEDRawData& raw = (fedHandle.product())->FEDData(m_evmGtFedId);
0180 
0181   int gtSize = raw.size();
0182 
0183   // get a const pointer to the beginning of the data buffer
0184   const unsigned char* ptrGt = raw.data();
0185 
0186   // get a const pointer to the end of the data buffer
0187   const unsigned char* endPtrGt = ptrGt + gtSize;
0188 
0189   //
0190   if (m_verbosity && m_isDebugEnabled) {
0191     LogTrace("L1GlobalTriggerEvmRawToDigi") << "\n Size of raw data: " << gtSize << "\n" << std::endl;
0192 
0193     std::ostringstream myCoutStream;
0194     dumpFedRawData(ptrGt, gtSize, myCoutStream);
0195 
0196     LogTrace("L1GlobalTriggerEvmRawToDigi") << "\n Dump FEDRawData\n" << myCoutStream.str() << "\n" << std::endl;
0197   }
0198 
0199   // unpack header
0200   int headerSize = 8;
0201 
0202   if ((ptrGt + headerSize) > endPtrGt) {
0203     edm::LogError("L1GlobalTriggerEvmRawToDigi") << "\nError: Pointer after header greater than end pointer."
0204                                                  << "\n Put empty products in the event!"
0205                                                  << "\n Quit unpacking this event." << std::endl;
0206 
0207     produceEmptyProducts(iEvent);
0208 
0209     return;
0210   }
0211 
0212   FEDHeader cmsHeader(ptrGt);
0213   FEDTrailer cmsTrailer(ptrGt + gtSize - headerSize);
0214 
0215   unpackHeader(ptrGt, cmsHeader);
0216   ptrGt += headerSize;  // advance with header size
0217 
0218   // unpack first GTFE to find the length of the record and the active boards
0219   // here GTFE assumed immediately after the header
0220 
0221   bool gtfeUnpacked = false;
0222 
0223   // get the length of the BST message from parameter set or from event setup
0224 
0225   int bstLengthBytes = 0;
0226 
0227   if (m_bstLengthBytes < 0) {
0228     // length from event setup // TODO cache it, if too slow
0229 
0230     edm::ESHandle<L1GtParameters> l1GtPar = evSetup.getHandle(m_l1GtParamToken);
0231     const L1GtParameters* m_l1GtPar = l1GtPar.product();
0232 
0233     bstLengthBytes = static_cast<int>(m_l1GtPar->gtBstLengthBytes());
0234 
0235   } else {
0236     // length from parameter set
0237     bstLengthBytes = m_bstLengthBytes;
0238   }
0239 
0240   if (m_verbosity) {
0241     LogTrace("L1GlobalTriggerEvmRawToDigi") << "\n Length of BST message (in bytes): " << bstLengthBytes << "\n"
0242                                             << std::endl;
0243   }
0244 
0245   for (CItBoardMaps itBoard = boardMaps.begin(); itBoard != boardMaps.end(); ++itBoard) {
0246     if (itBoard->gtBoardType() == GTFE) {
0247       // unpack GTFE
0248       if (itBoard->gtPositionEvmRecord() == 1) {
0249         // resize to the right size before unapacking
0250         m_gtfeWord->resize(bstLengthBytes);
0251 
0252         m_gtfeWord->unpack(ptrGt);
0253         ptrGt += m_gtfeWord->getSize();  // advance with GTFE block size
0254         gtfeUnpacked = true;
0255 
0256         if (m_verbosity && m_isDebugEnabled) {
0257           std::ostringstream myCoutStream;
0258           m_gtfeWord->print(myCoutStream);
0259           LogTrace("L1GlobalTriggerEvmRawToDigi") << myCoutStream.str() << "\n" << std::endl;
0260         }
0261 
0262         // break the loop - GTFE was found
0263         break;
0264 
0265       } else {
0266         if (m_verbosity) {
0267           edm::LogWarning("L1GlobalTriggerEvmRawToDigi")
0268               << "\nWarning: GTFE block found in raw data does not follow header."
0269               << "\nAssumed start position of the block is wrong!"
0270               << "\nQuit unpacking this event" << std::endl;
0271         }
0272 
0273         produceEmptyProducts(iEvent);
0274 
0275         return;
0276       }
0277     }
0278   }
0279 
0280   // quit if no GTFE found
0281   if (!gtfeUnpacked) {
0282     if (m_verbosity) {
0283       edm::LogWarning("L1GlobalTriggerEvmRawToDigi")
0284           << "\nWarning: no GTFE block found in raw data."
0285           << "\nCan not find the record length (BxInEvent) and the active boards!"
0286           << "\nQuit unpacking this event" << std::endl;
0287     }
0288 
0289     produceEmptyProducts(iEvent);
0290 
0291     return;
0292   }
0293 
0294   // life normal here, GTFE found
0295 
0296   // get list of active blocks
0297   // blocks not active are not written to the record
0298   cms_uint16_t activeBoardsGtInitial = m_gtfeWord->activeBoards();
0299   cms_uint16_t altNrBxBoardInitial = m_gtfeWord->altNrBxBoard();
0300 
0301   // mask some boards, if needed
0302   cms_uint16_t activeBoardsGt = activeBoardsGtInitial & m_activeBoardsMaskGt;
0303   m_gtfeWord->setActiveBoards(activeBoardsGt);
0304 
0305   if (m_verbosity) {
0306     LogDebug("L1GlobalTriggerEvmRawToDigi")
0307         << "\nActive boards before masking(hex format): " << std::hex << std::setw(sizeof(activeBoardsGtInitial) * 2)
0308         << std::setfill('0') << activeBoardsGtInitial << std::dec << std::setfill(' ')
0309         << "\nActive boards after masking(hex format):  " << std::hex << std::setw(sizeof(activeBoardsGt) * 2)
0310         << std::setfill('0') << activeBoardsGt << std::dec << std::setfill(' ') << " \n"
0311         << std::endl;
0312   }
0313 
0314   // loop over other blocks in the raw record, count them if they are active
0315 
0316   int numberGtfeBoards = 0;
0317   int numberFdlBoards = 0;
0318   int numberPsbBoards = 0;
0319   int numberGmtBoards = 0;
0320   int numberTcsBoards = 0;
0321   int numberTimBoards = 0;
0322 
0323   for (CItBoardMaps itBoard = boardMaps.begin(); itBoard != boardMaps.end(); ++itBoard) {
0324     int iActiveBit = itBoard->gtBitEvmActiveBoards();
0325     bool activeBoardToUnpack = false;
0326 
0327     if (iActiveBit >= 0) {
0328       activeBoardToUnpack = activeBoardsGt & (1 << iActiveBit);
0329     } else {
0330       // board not in the ActiveBoards for the record
0331       continue;
0332     }
0333 
0334     if (activeBoardToUnpack) {
0335       switch (itBoard->gtBoardType()) {
0336         case GTFE: {
0337           numberGtfeBoards++;
0338         }
0339 
0340         break;
0341         case FDL: {
0342           numberFdlBoards++;
0343         }
0344 
0345         break;
0346         case PSB: {
0347           numberPsbBoards++;
0348         }
0349 
0350         break;
0351         case GMT: {
0352           numberGmtBoards++;
0353         }
0354 
0355         break;
0356         case TCS: {
0357           numberTcsBoards++;
0358         }
0359 
0360         break;
0361         case TIM: {
0362           numberTimBoards++;
0363         }
0364 
0365         break;
0366         default: {
0367           // do nothing, all blocks are given in GtBoardType enum
0368           if (m_verbosity) {
0369             LogDebug("L1GlobalTriggerEvmRawToDigi")
0370                 << "\nBoard of type " << itBoard->gtBoardType() << " not expected  in record.\n"
0371                 << std::endl;
0372           }
0373 
0374         }
0375 
0376         break;
0377       }
0378     }
0379   }
0380 
0381   // produce the L1GlobalTriggerEvmReadoutRecord now, after we found how many
0382   // BxInEvent the record has and how many boards are active
0383   //LogDebug("L1GlobalTriggerEvmRawToDigi")
0384   //<< "\nL1GlobalTriggerEvmRawToDigi: producing L1GlobalTriggerEvmReadoutRecord\n"
0385   //<< std::endl;
0386 
0387   // get number of Bx in the event from GTFE block corresponding to alternative 0 and 1 in
0388   m_recordLength0 = m_gtfeWord->recordLength();
0389   m_recordLength1 = m_gtfeWord->recordLength1();
0390 
0391   int maxBxInEvent = std::max(m_recordLength0, m_recordLength1);
0392 
0393   std::unique_ptr<L1GlobalTriggerEvmReadoutRecord> gtReadoutRecord(
0394       new L1GlobalTriggerEvmReadoutRecord(maxBxInEvent, numberFdlBoards));
0395 
0396   // ... then unpack modules other than GTFE, if requested
0397 
0398   for (CItBoardMaps itBoard = gtRecordMap.begin(); itBoard != gtRecordMap.end(); ++itBoard) {
0399     int iActiveBit = itBoard->gtBitEvmActiveBoards();
0400 
0401     bool activeBoardToUnpack = false;
0402     bool activeBoardInitial = false;
0403 
0404     int altNrBxBoardVal = -1;
0405 
0406     if (iActiveBit >= 0) {
0407       activeBoardInitial = activeBoardsGtInitial & (1 << iActiveBit);
0408       activeBoardToUnpack = activeBoardsGt & (1 << iActiveBit);
0409 
0410       altNrBxBoardVal = (altNrBxBoardInitial & (1 << iActiveBit)) >> iActiveBit;
0411 
0412       if (altNrBxBoardVal == 1) {
0413         m_totalBxInEvent = m_recordLength1;
0414       } else if (altNrBxBoardVal == 0) {
0415         m_totalBxInEvent = m_recordLength0;
0416       } else {
0417         if (m_verbosity) {
0418           edm::LogWarning("L1GlobalTriggerEvmRawToDigi")
0419               << "\n\nWARNING: Wrong value altNrBxBoardVal = " << altNrBxBoardVal << " for board " << std::hex
0420               << (itBoard->gtBoardId()) << std::dec << "\n  iActiveBit =            " << iActiveBit
0421               << "\n  altNrBxBoardInitial = 0x" << std::hex << altNrBxBoardInitial << std::dec
0422               << "\n  activeBoardsGt =      0x" << std::hex << activeBoardsGt << std::dec
0423               << "\n  activeBoardInitial =    " << activeBoardInitial
0424               << "\n  activeBoardToUnpack =   " << activeBoardToUnpack << "\n Set altNrBxBoardVal tentatively to "
0425               << m_recordLength0 << "\n Job may crash or produce wrong results!\n\n"
0426               << std::endl;
0427         }
0428 
0429         m_totalBxInEvent = m_recordLength0;
0430       }
0431 
0432       // number of BX required to be unpacked
0433 
0434       if (m_unpackBxInEvent > m_totalBxInEvent) {
0435         if (m_verbosity) {
0436           LogDebug("L1GlobalTriggerEvmRawToDigi")
0437               << "\nWARNING: Number of available bunch crosses for board" << (itBoard->gtBoardId())
0438               << " in the record ( " << m_totalBxInEvent
0439               << " ) \n is smaller than the number of bunch crosses requested to be unpacked (" << m_unpackBxInEvent
0440               << " )!!! \n         Unpacking only " << m_totalBxInEvent << " bunch crosses.\n"
0441               << std::endl;
0442         }
0443 
0444         m_lowSkipBxInEvent = 0;
0445         m_uppSkipBxInEvent = m_totalBxInEvent;
0446 
0447       } else if (m_unpackBxInEvent < 0) {
0448         m_lowSkipBxInEvent = 0;
0449         m_uppSkipBxInEvent = m_totalBxInEvent;
0450 
0451         if (m_verbosity) {
0452           LogDebug("L1GlobalTriggerEvmRawToDigi")
0453               << "\nUnpacking all " << m_totalBxInEvent << " bunch crosses available."
0454               << "\n"
0455               << std::endl;
0456         }
0457 
0458       } else if (m_unpackBxInEvent == 0) {
0459         m_lowSkipBxInEvent = m_totalBxInEvent;
0460         m_uppSkipBxInEvent = m_totalBxInEvent;
0461 
0462         if (m_verbosity) {
0463           LogDebug("L1GlobalTriggerEvmRawToDigi")
0464               << "\nNo bxInEvent required to be unpacked from " << m_totalBxInEvent << " bunch crosses available."
0465               << "\n"
0466               << std::endl;
0467         }
0468 
0469         // change RecordLength
0470         // cast int to cms_uint16_t (there are normally 3 or 5 BxInEvent)
0471         m_gtfeWord->setRecordLength(static_cast<cms_uint16_t>(m_unpackBxInEvent));
0472         m_gtfeWord->setRecordLength1(static_cast<cms_uint16_t>(m_unpackBxInEvent));
0473 
0474       } else {
0475         m_lowSkipBxInEvent = (m_totalBxInEvent - m_unpackBxInEvent) / 2;
0476         m_uppSkipBxInEvent = m_totalBxInEvent - m_lowSkipBxInEvent;
0477 
0478         if (m_verbosity) {
0479           LogDebug("L1GlobalTriggerEvmRawToDigi") << "\nUnpacking " << m_unpackBxInEvent << " bunch crosses from "
0480                                                   << m_totalBxInEvent << " bunch crosses available."
0481                                                   << "\n"
0482                                                   << std::endl;
0483         }
0484 
0485         // change RecordLength
0486         // cast int to cms_uint16_t (there are normally 3 or 5 BxInEvent)
0487         m_gtfeWord->setRecordLength(static_cast<cms_uint16_t>(m_unpackBxInEvent));
0488         m_gtfeWord->setRecordLength1(static_cast<cms_uint16_t>(m_unpackBxInEvent));
0489       }
0490 
0491     } else {
0492       // board not in the ActiveBoards for the record
0493       continue;
0494     }
0495 
0496     if (!activeBoardInitial) {
0497       if (m_verbosity) {
0498         LogDebug("L1GlobalTriggerEvmRawToDigi") << "\nBoard of type " << itBoard->gtBoardName() << " with index "
0499                                                 << itBoard->gtBoardIndex() << " not active initially in raw data.\n"
0500                                                 << std::endl;
0501       }
0502       continue;
0503     }
0504 
0505     // active board initially, could unpack it
0506     switch (itBoard->gtBoardType()) {
0507       case TCS: {
0508         // if pointer after TCS payload is greater than pointer at
0509         // the end of GT payload, produce empty products and quit unpacking
0510         if ((ptrGt + m_tcsWord->getSize()) > endPtrGt) {
0511           edm::LogError("L1GlobalTriggerEvmRawToDigi") << "\nError: Pointer after TCS "
0512                                                        << " greater than end pointer."
0513                                                        << "\n Put empty products in the event!"
0514                                                        << "\n Quit unpacking this event." << std::endl;
0515 
0516           produceEmptyProducts(iEvent);
0517 
0518           return;
0519         }
0520 
0521         // unpack only if requested, otherwise skip it
0522         if (activeBoardToUnpack) {
0523           m_tcsWord->unpack(ptrGt);
0524 
0525           // add 1 to the GT luminosity number to use the same convention as
0526           // offline, where LS number starts with 1;
0527           // in GT hardware, LS starts with 0
0528           cms_uint16_t lsNr = m_tcsWord->luminositySegmentNr() + 1;
0529           m_tcsWord->setLuminositySegmentNr(lsNr);
0530 
0531           // add TCS block to GT EVM readout record
0532           gtReadoutRecord->setTcsWord(*m_tcsWord);
0533 
0534           if (m_verbosity && m_isDebugEnabled) {
0535             std::ostringstream myCoutStream;
0536             m_tcsWord->print(myCoutStream);
0537             LogTrace("L1GlobalTriggerEvmRawToDigi") << myCoutStream.str() << "\n" << std::endl;
0538           }
0539 
0540           // ... and reset it
0541           m_tcsWord->reset();
0542         }
0543 
0544         ptrGt += m_tcsWord->getSize();  // advance with TCS block size
0545 
0546       } break;
0547       case FDL: {
0548         for (int iFdl = 0; iFdl < m_totalBxInEvent; ++iFdl) {
0549           // if pointer after FDL payload is greater than pointer at
0550           // the end of GT payload, produce empty products and quit unpacking
0551           if ((ptrGt + m_gtFdlWord->getSize()) > endPtrGt) {
0552             edm::LogError("L1GlobalTriggerEvmRawToDigi")
0553                 << "\nError: Pointer after FDL " << iFdl << " greater than end pointer."
0554                 << "\n Put empty products in the event!"
0555                 << "\n Quit unpacking this event." << std::endl;
0556 
0557             produceEmptyProducts(iEvent);
0558 
0559             return;
0560           }
0561 
0562           // unpack only if requested, otherwise skip it
0563           if (activeBoardToUnpack) {
0564             // unpack only bxInEvent requested, otherwise skip it
0565             if ((iFdl >= m_lowSkipBxInEvent) && (iFdl < m_uppSkipBxInEvent)) {
0566               m_gtFdlWord->unpack(ptrGt);
0567 
0568               // add 1 to the GT luminosity number to use the same convention as
0569               // offline, where LS number starts with 1;
0570               // in GT hardware, LS starts with 0
0571               cms_uint16_t lsNr = m_gtFdlWord->lumiSegmentNr() + 1;
0572               m_gtFdlWord->setLumiSegmentNr(lsNr);
0573 
0574               // add FDL block to GT readout record
0575               gtReadoutRecord->setGtFdlWord(*m_gtFdlWord);
0576 
0577               if (m_verbosity && m_isDebugEnabled) {
0578                 std::ostringstream myCoutStream;
0579                 m_gtFdlWord->print(myCoutStream);
0580                 LogTrace("L1GlobalTriggerEvmRawToDigi") << myCoutStream.str() << "\n" << std::endl;
0581               }
0582 
0583               // ... and reset it
0584               m_gtFdlWord->reset();
0585             }
0586           }
0587 
0588           ptrGt += m_gtFdlWord->getSize();  // advance with FDL block size
0589         }
0590       }
0591 
0592       break;
0593       default: {
0594         // do nothing, all blocks are given in GtBoardType enum
0595         if (m_verbosity) {
0596           LogDebug("L1GlobalTriggerEvmRawToDigi")
0597               << "\nBoard of type " << itBoard->gtBoardType() << " not expected  in record.\n"
0598               << std::endl;
0599         }
0600       } break;
0601     }
0602   }
0603 
0604   // add GTFE block to GT readout record, after updating active boards and record length
0605 
0606   gtReadoutRecord->setGtfeWord(*m_gtfeWord);
0607 
0608   // ... and reset it
0609   m_gtfeWord->reset();
0610 
0611   // unpack trailer
0612 
0613   int trailerSize = 8;
0614 
0615   // if pointer after trailer is greater than pointer at
0616   // the end of GT payload, produce empty products and quit unpacking
0617   if ((ptrGt + trailerSize) > endPtrGt) {
0618     edm::LogError("L1GlobalTriggerEvmRawToDigi") << "\nError: Pointer after trailer "
0619                                                  << " greater than end pointer."
0620                                                  << "\n Put empty products in the event!"
0621                                                  << "\n Quit unpacking this event." << std::endl;
0622 
0623     produceEmptyProducts(iEvent);
0624 
0625     return;
0626   }
0627 
0628   unpackTrailer(ptrGt, cmsTrailer);
0629 
0630   if (m_verbosity && m_isDebugEnabled) {
0631     std::ostringstream myCoutStream;
0632     gtReadoutRecord->print(myCoutStream);
0633     LogTrace("L1GlobalTriggerEvmRawToDigi") << "\n The following L1 GT EVM readout record was unpacked.\n"
0634                                             << myCoutStream.str() << "\n"
0635                                             << std::endl;
0636   }
0637 
0638   // put records into event
0639   iEvent.put(std::move(gtReadoutRecord));
0640 }
0641 
0642 // unpack header
0643 void L1GlobalTriggerEvmRawToDigi::unpackHeader(const unsigned char* gtPtr, FEDHeader& cmsHeader) {
0644   // TODO  if needed in another format
0645 
0646   // print the header info
0647   if (edm::isDebugEnabled()) {
0648     const cms_uint64_t* payload = reinterpret_cast<cms_uint64_t*>(const_cast<unsigned char*>(gtPtr));
0649 
0650     std::ostringstream myCoutStream;
0651 
0652     // one word only
0653     int iWord = 0;
0654 
0655     myCoutStream << std::setw(4) << iWord << "  " << std::hex << std::setfill('0') << std::setw(16) << payload[iWord]
0656                  << std::dec << std::setfill(' ') << "\n"
0657                  << std::endl;
0658 
0659     myCoutStream << "  Event_type:  " << std::hex << " hex: "
0660                  << "     " << std::setw(1) << std::setfill('0') << cmsHeader.triggerType() << std::setfill(' ')
0661                  << std::dec << " dec: " << cmsHeader.triggerType() << std::endl;
0662 
0663     myCoutStream << "  LVL1_Id:     " << std::hex << " hex: "
0664                  << "" << std::setw(6) << std::setfill('0') << cmsHeader.lvl1ID() << std::setfill(' ') << std::dec
0665                  << " dec: " << cmsHeader.lvl1ID() << std::endl;
0666 
0667     myCoutStream << "  BX_Id:       " << std::hex << " hex: "
0668                  << "   " << std::setw(3) << std::setfill('0') << cmsHeader.bxID() << std::setfill(' ') << std::dec
0669                  << " dec: " << cmsHeader.bxID() << std::endl;
0670 
0671     myCoutStream << "  Source_Id:   " << std::hex << " hex: "
0672                  << "   " << std::setw(3) << std::setfill('0') << cmsHeader.sourceID() << std::setfill(' ') << std::dec
0673                  << " dec: " << cmsHeader.sourceID() << std::endl;
0674 
0675     myCoutStream << "  FOV:         " << std::hex << " hex: "
0676                  << "     " << std::setw(1) << std::setfill('0') << cmsHeader.version() << std::setfill(' ') << std::dec
0677                  << " dec: " << cmsHeader.version() << std::endl;
0678 
0679     myCoutStream << "  H:           " << std::hex << " hex: "
0680                  << "     " << std::setw(1) << std::setfill('0') << cmsHeader.moreHeaders() << std::setfill(' ')
0681                  << std::dec << " dec: " << cmsHeader.moreHeaders() << std::endl;
0682 
0683     LogDebug("L1GlobalTriggerEvmRawToDigi") << "\n CMS Header \n" << myCoutStream.str() << "\n" << std::endl;
0684   }
0685 }
0686 
0687 // unpack trailer word
0688 // trPtr pointer to the beginning of trailer obtained from gtPtr
0689 void L1GlobalTriggerEvmRawToDigi::unpackTrailer(const unsigned char* trlPtr, FEDTrailer& cmsTrailer) {
0690   // TODO  if needed in another format
0691 
0692   // print the trailer info
0693   if (m_verbosity && m_isDebugEnabled) {
0694     const cms_uint64_t* payload = reinterpret_cast<cms_uint64_t*>(const_cast<unsigned char*>(trlPtr));
0695 
0696     std::ostringstream myCoutStream;
0697 
0698     // one word only
0699     int iWord = 0;
0700 
0701     myCoutStream << std::setw(4) << iWord << "  " << std::hex << std::setfill('0') << std::setw(16) << payload[iWord]
0702                  << std::dec << std::setfill(' ') << "\n"
0703                  << std::endl;
0704 
0705     myCoutStream << "  Event_length:  " << std::hex << " hex: "
0706                  << "" << std::setw(6) << std::setfill('0') << cmsTrailer.fragmentLength() << std::setfill(' ')
0707                  << std::dec << " dec: " << cmsTrailer.fragmentLength() << std::endl;
0708 
0709     myCoutStream << "  CRC:           " << std::hex << " hex: "
0710                  << "  " << std::setw(4) << std::setfill('0') << cmsTrailer.crc() << std::setfill(' ') << std::dec
0711                  << " dec: " << cmsTrailer.crc() << std::endl;
0712 
0713     myCoutStream << "  Event_status:  " << std::hex << " hex: "
0714                  << "    " << std::setw(2) << std::setfill('0') << cmsTrailer.evtStatus() << std::setfill(' ')
0715                  << std::dec << " dec: " << cmsTrailer.evtStatus() << std::endl;
0716 
0717     myCoutStream << "  TTS_bits:      " << std::hex << " hex: "
0718                  << "     " << std::setw(1) << std::setfill('0') << cmsTrailer.ttsBits() << std::setfill(' ')
0719                  << std::dec << " dec: " << cmsTrailer.ttsBits() << std::endl;
0720 
0721     myCoutStream << "  More trailers: " << std::hex << " hex: "
0722                  << "     " << std::setw(1) << std::setfill('0') << cmsTrailer.moreTrailers() << std::setfill(' ')
0723                  << std::dec << " dec: " << cmsTrailer.moreTrailers() << std::endl;
0724 
0725     LogDebug("L1GlobalTriggerEvmRawToDigi") << "\n CMS Trailer \n" << myCoutStream.str() << "\n" << std::endl;
0726   }
0727 }
0728 
0729 // produce empty products in case of problems
0730 void L1GlobalTriggerEvmRawToDigi::produceEmptyProducts(edm::Event& iEvent) {
0731   std::unique_ptr<L1GlobalTriggerEvmReadoutRecord> gtReadoutRecord(new L1GlobalTriggerEvmReadoutRecord());
0732 
0733   // put empty records into event
0734 
0735   iEvent.put(std::move(gtReadoutRecord));
0736 }
0737 
0738 // dump FED raw data
0739 void L1GlobalTriggerEvmRawToDigi::dumpFedRawData(const unsigned char* gtPtr, int gtSize, std::ostream& myCout) {
0740   LogDebug("L1GlobalTriggerEvmRawToDigi") << "\nDump FED raw data.\n" << std::endl;
0741 
0742   int wLength = L1GlobalTriggerReadoutSetup::WordLength;
0743   int uLength = L1GlobalTriggerReadoutSetup::UnitLength;
0744 
0745   int gtWords = gtSize / uLength;
0746   LogTrace("L1GlobalTriggerEvmRawToDigi") << "\nFED GT words (" << wLength << " bits):" << gtWords << "\n" << std::endl;
0747 
0748   const cms_uint64_t* payload = reinterpret_cast<cms_uint64_t*>(const_cast<unsigned char*>(gtPtr));
0749 
0750   for (unsigned int i = 0; i < gtSize / sizeof(cms_uint64_t); i++) {
0751     myCout << std::setw(4) << i << "  " << std::hex << std::setfill('0') << std::setw(16) << payload[i] << std::dec
0752            << std::setfill(' ') << std::endl;
0753   }
0754 }
0755 
0756 // static class members