Back to home page

Project CMSSW displayed by LXR

 
 

    


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

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 numberFdlBoards = 0;
0317 
0318   for (CItBoardMaps itBoard = boardMaps.begin(); itBoard != boardMaps.end(); ++itBoard) {
0319     int iActiveBit = itBoard->gtBitEvmActiveBoards();
0320     bool activeBoardToUnpack = false;
0321 
0322     if (iActiveBit >= 0) {
0323       activeBoardToUnpack = activeBoardsGt & (1 << iActiveBit);
0324     } else {
0325       // board not in the ActiveBoards for the record
0326       continue;
0327     }
0328 
0329     if (activeBoardToUnpack) {
0330       switch (itBoard->gtBoardType()) {
0331         case GTFE:
0332           break;
0333         case FDL: {
0334           numberFdlBoards++;
0335         }
0336 
0337         break;
0338         case PSB:
0339           break;
0340         case GMT:
0341           break;
0342         case TCS:
0343           break;
0344         case TIM:
0345           break;
0346         default: {
0347           // do nothing, all blocks are given in GtBoardType enum
0348           if (m_verbosity) {
0349             LogDebug("L1GlobalTriggerEvmRawToDigi")
0350                 << "\nBoard of type " << itBoard->gtBoardType() << " not expected  in record.\n"
0351                 << std::endl;
0352           }
0353 
0354         }
0355 
0356         break;
0357       }
0358     }
0359   }
0360 
0361   // produce the L1GlobalTriggerEvmReadoutRecord now, after we found how many
0362   // BxInEvent the record has and how many boards are active
0363   //LogDebug("L1GlobalTriggerEvmRawToDigi")
0364   //<< "\nL1GlobalTriggerEvmRawToDigi: producing L1GlobalTriggerEvmReadoutRecord\n"
0365   //<< std::endl;
0366 
0367   // get number of Bx in the event from GTFE block corresponding to alternative 0 and 1 in
0368   m_recordLength0 = m_gtfeWord->recordLength();
0369   m_recordLength1 = m_gtfeWord->recordLength1();
0370 
0371   int maxBxInEvent = std::max(m_recordLength0, m_recordLength1);
0372 
0373   std::unique_ptr<L1GlobalTriggerEvmReadoutRecord> gtReadoutRecord(
0374       new L1GlobalTriggerEvmReadoutRecord(maxBxInEvent, numberFdlBoards));
0375 
0376   // ... then unpack modules other than GTFE, if requested
0377 
0378   for (CItBoardMaps itBoard = gtRecordMap.begin(); itBoard != gtRecordMap.end(); ++itBoard) {
0379     int iActiveBit = itBoard->gtBitEvmActiveBoards();
0380 
0381     bool activeBoardToUnpack = false;
0382     bool activeBoardInitial = false;
0383 
0384     int altNrBxBoardVal = -1;
0385 
0386     if (iActiveBit >= 0) {
0387       activeBoardInitial = activeBoardsGtInitial & (1 << iActiveBit);
0388       activeBoardToUnpack = activeBoardsGt & (1 << iActiveBit);
0389 
0390       altNrBxBoardVal = (altNrBxBoardInitial & (1 << iActiveBit)) >> iActiveBit;
0391 
0392       if (altNrBxBoardVal == 1) {
0393         m_totalBxInEvent = m_recordLength1;
0394       } else if (altNrBxBoardVal == 0) {
0395         m_totalBxInEvent = m_recordLength0;
0396       } else {
0397         if (m_verbosity) {
0398           edm::LogWarning("L1GlobalTriggerEvmRawToDigi")
0399               << "\n\nWARNING: Wrong value altNrBxBoardVal = " << altNrBxBoardVal << " for board " << std::hex
0400               << (itBoard->gtBoardId()) << std::dec << "\n  iActiveBit =            " << iActiveBit
0401               << "\n  altNrBxBoardInitial = 0x" << std::hex << altNrBxBoardInitial << std::dec
0402               << "\n  activeBoardsGt =      0x" << std::hex << activeBoardsGt << std::dec
0403               << "\n  activeBoardInitial =    " << activeBoardInitial
0404               << "\n  activeBoardToUnpack =   " << activeBoardToUnpack << "\n Set altNrBxBoardVal tentatively to "
0405               << m_recordLength0 << "\n Job may crash or produce wrong results!\n\n"
0406               << std::endl;
0407         }
0408 
0409         m_totalBxInEvent = m_recordLength0;
0410       }
0411 
0412       // number of BX required to be unpacked
0413 
0414       if (m_unpackBxInEvent > m_totalBxInEvent) {
0415         if (m_verbosity) {
0416           LogDebug("L1GlobalTriggerEvmRawToDigi")
0417               << "\nWARNING: Number of available bunch crosses for board" << (itBoard->gtBoardId())
0418               << " in the record ( " << m_totalBxInEvent
0419               << " ) \n is smaller than the number of bunch crosses requested to be unpacked (" << m_unpackBxInEvent
0420               << " )!!! \n         Unpacking only " << m_totalBxInEvent << " bunch crosses.\n"
0421               << std::endl;
0422         }
0423 
0424         m_lowSkipBxInEvent = 0;
0425         m_uppSkipBxInEvent = m_totalBxInEvent;
0426 
0427       } else if (m_unpackBxInEvent < 0) {
0428         m_lowSkipBxInEvent = 0;
0429         m_uppSkipBxInEvent = m_totalBxInEvent;
0430 
0431         if (m_verbosity) {
0432           LogDebug("L1GlobalTriggerEvmRawToDigi")
0433               << "\nUnpacking all " << m_totalBxInEvent << " bunch crosses available."
0434               << "\n"
0435               << std::endl;
0436         }
0437 
0438       } else if (m_unpackBxInEvent == 0) {
0439         m_lowSkipBxInEvent = m_totalBxInEvent;
0440         m_uppSkipBxInEvent = m_totalBxInEvent;
0441 
0442         if (m_verbosity) {
0443           LogDebug("L1GlobalTriggerEvmRawToDigi")
0444               << "\nNo bxInEvent required to be unpacked from " << m_totalBxInEvent << " bunch crosses available."
0445               << "\n"
0446               << std::endl;
0447         }
0448 
0449         // change RecordLength
0450         // cast int to cms_uint16_t (there are normally 3 or 5 BxInEvent)
0451         m_gtfeWord->setRecordLength(static_cast<cms_uint16_t>(m_unpackBxInEvent));
0452         m_gtfeWord->setRecordLength1(static_cast<cms_uint16_t>(m_unpackBxInEvent));
0453 
0454       } else {
0455         m_lowSkipBxInEvent = (m_totalBxInEvent - m_unpackBxInEvent) / 2;
0456         m_uppSkipBxInEvent = m_totalBxInEvent - m_lowSkipBxInEvent;
0457 
0458         if (m_verbosity) {
0459           LogDebug("L1GlobalTriggerEvmRawToDigi") << "\nUnpacking " << m_unpackBxInEvent << " bunch crosses from "
0460                                                   << m_totalBxInEvent << " bunch crosses available."
0461                                                   << "\n"
0462                                                   << std::endl;
0463         }
0464 
0465         // change RecordLength
0466         // cast int to cms_uint16_t (there are normally 3 or 5 BxInEvent)
0467         m_gtfeWord->setRecordLength(static_cast<cms_uint16_t>(m_unpackBxInEvent));
0468         m_gtfeWord->setRecordLength1(static_cast<cms_uint16_t>(m_unpackBxInEvent));
0469       }
0470 
0471     } else {
0472       // board not in the ActiveBoards for the record
0473       continue;
0474     }
0475 
0476     if (!activeBoardInitial) {
0477       if (m_verbosity) {
0478         LogDebug("L1GlobalTriggerEvmRawToDigi") << "\nBoard of type " << itBoard->gtBoardName() << " with index "
0479                                                 << itBoard->gtBoardIndex() << " not active initially in raw data.\n"
0480                                                 << std::endl;
0481       }
0482       continue;
0483     }
0484 
0485     // active board initially, could unpack it
0486     switch (itBoard->gtBoardType()) {
0487       case TCS: {
0488         // if pointer after TCS payload is greater than pointer at
0489         // the end of GT payload, produce empty products and quit unpacking
0490         if ((ptrGt + m_tcsWord->getSize()) > endPtrGt) {
0491           edm::LogError("L1GlobalTriggerEvmRawToDigi") << "\nError: Pointer after TCS "
0492                                                        << " greater than end pointer."
0493                                                        << "\n Put empty products in the event!"
0494                                                        << "\n Quit unpacking this event." << std::endl;
0495 
0496           produceEmptyProducts(iEvent);
0497 
0498           return;
0499         }
0500 
0501         // unpack only if requested, otherwise skip it
0502         if (activeBoardToUnpack) {
0503           m_tcsWord->unpack(ptrGt);
0504 
0505           // add 1 to the GT luminosity number to use the same convention as
0506           // offline, where LS number starts with 1;
0507           // in GT hardware, LS starts with 0
0508           cms_uint16_t lsNr = m_tcsWord->luminositySegmentNr() + 1;
0509           m_tcsWord->setLuminositySegmentNr(lsNr);
0510 
0511           // add TCS block to GT EVM readout record
0512           gtReadoutRecord->setTcsWord(*m_tcsWord);
0513 
0514           if (m_verbosity && m_isDebugEnabled) {
0515             std::ostringstream myCoutStream;
0516             m_tcsWord->print(myCoutStream);
0517             LogTrace("L1GlobalTriggerEvmRawToDigi") << myCoutStream.str() << "\n" << std::endl;
0518           }
0519 
0520           // ... and reset it
0521           m_tcsWord->reset();
0522         }
0523 
0524         ptrGt += m_tcsWord->getSize();  // advance with TCS block size
0525 
0526       } break;
0527       case FDL: {
0528         for (int iFdl = 0; iFdl < m_totalBxInEvent; ++iFdl) {
0529           // if pointer after FDL payload is greater than pointer at
0530           // the end of GT payload, produce empty products and quit unpacking
0531           if ((ptrGt + m_gtFdlWord->getSize()) > endPtrGt) {
0532             edm::LogError("L1GlobalTriggerEvmRawToDigi")
0533                 << "\nError: Pointer after FDL " << iFdl << " greater than end pointer."
0534                 << "\n Put empty products in the event!"
0535                 << "\n Quit unpacking this event." << std::endl;
0536 
0537             produceEmptyProducts(iEvent);
0538 
0539             return;
0540           }
0541 
0542           // unpack only if requested, otherwise skip it
0543           if (activeBoardToUnpack) {
0544             // unpack only bxInEvent requested, otherwise skip it
0545             if ((iFdl >= m_lowSkipBxInEvent) && (iFdl < m_uppSkipBxInEvent)) {
0546               m_gtFdlWord->unpack(ptrGt);
0547 
0548               // add 1 to the GT luminosity number to use the same convention as
0549               // offline, where LS number starts with 1;
0550               // in GT hardware, LS starts with 0
0551               cms_uint16_t lsNr = m_gtFdlWord->lumiSegmentNr() + 1;
0552               m_gtFdlWord->setLumiSegmentNr(lsNr);
0553 
0554               // add FDL block to GT readout record
0555               gtReadoutRecord->setGtFdlWord(*m_gtFdlWord);
0556 
0557               if (m_verbosity && m_isDebugEnabled) {
0558                 std::ostringstream myCoutStream;
0559                 m_gtFdlWord->print(myCoutStream);
0560                 LogTrace("L1GlobalTriggerEvmRawToDigi") << myCoutStream.str() << "\n" << std::endl;
0561               }
0562 
0563               // ... and reset it
0564               m_gtFdlWord->reset();
0565             }
0566           }
0567 
0568           ptrGt += m_gtFdlWord->getSize();  // advance with FDL block size
0569         }
0570       }
0571 
0572       break;
0573       default: {
0574         // do nothing, all blocks are given in GtBoardType enum
0575         if (m_verbosity) {
0576           LogDebug("L1GlobalTriggerEvmRawToDigi")
0577               << "\nBoard of type " << itBoard->gtBoardType() << " not expected  in record.\n"
0578               << std::endl;
0579         }
0580       } break;
0581     }
0582   }
0583 
0584   // add GTFE block to GT readout record, after updating active boards and record length
0585 
0586   gtReadoutRecord->setGtfeWord(*m_gtfeWord);
0587 
0588   // ... and reset it
0589   m_gtfeWord->reset();
0590 
0591   // unpack trailer
0592 
0593   int trailerSize = 8;
0594 
0595   // if pointer after trailer is greater than pointer at
0596   // the end of GT payload, produce empty products and quit unpacking
0597   if ((ptrGt + trailerSize) > endPtrGt) {
0598     edm::LogError("L1GlobalTriggerEvmRawToDigi") << "\nError: Pointer after trailer "
0599                                                  << " greater than end pointer."
0600                                                  << "\n Put empty products in the event!"
0601                                                  << "\n Quit unpacking this event." << std::endl;
0602 
0603     produceEmptyProducts(iEvent);
0604 
0605     return;
0606   }
0607 
0608   unpackTrailer(ptrGt, cmsTrailer);
0609 
0610   if (m_verbosity && m_isDebugEnabled) {
0611     std::ostringstream myCoutStream;
0612     gtReadoutRecord->print(myCoutStream);
0613     LogTrace("L1GlobalTriggerEvmRawToDigi") << "\n The following L1 GT EVM readout record was unpacked.\n"
0614                                             << myCoutStream.str() << "\n"
0615                                             << std::endl;
0616   }
0617 
0618   // put records into event
0619   iEvent.put(std::move(gtReadoutRecord));
0620 }
0621 
0622 // unpack header
0623 void L1GlobalTriggerEvmRawToDigi::unpackHeader(const unsigned char* gtPtr, FEDHeader& cmsHeader) {
0624   // TODO  if needed in another format
0625 
0626   // print the header info
0627   if (edm::isDebugEnabled()) {
0628     const cms_uint64_t* payload = reinterpret_cast<cms_uint64_t*>(const_cast<unsigned char*>(gtPtr));
0629 
0630     std::ostringstream myCoutStream;
0631 
0632     // one word only
0633     int iWord = 0;
0634 
0635     myCoutStream << std::setw(4) << iWord << "  " << std::hex << std::setfill('0') << std::setw(16) << payload[iWord]
0636                  << std::dec << std::setfill(' ') << "\n"
0637                  << std::endl;
0638 
0639     myCoutStream << "  Event_type:  " << std::hex << " hex: "
0640                  << "     " << std::setw(1) << std::setfill('0') << cmsHeader.triggerType() << std::setfill(' ')
0641                  << std::dec << " dec: " << cmsHeader.triggerType() << std::endl;
0642 
0643     myCoutStream << "  LVL1_Id:     " << std::hex << " hex: "
0644                  << "" << std::setw(6) << std::setfill('0') << cmsHeader.lvl1ID() << std::setfill(' ') << std::dec
0645                  << " dec: " << cmsHeader.lvl1ID() << std::endl;
0646 
0647     myCoutStream << "  BX_Id:       " << std::hex << " hex: "
0648                  << "   " << std::setw(3) << std::setfill('0') << cmsHeader.bxID() << std::setfill(' ') << std::dec
0649                  << " dec: " << cmsHeader.bxID() << std::endl;
0650 
0651     myCoutStream << "  Source_Id:   " << std::hex << " hex: "
0652                  << "   " << std::setw(3) << std::setfill('0') << cmsHeader.sourceID() << std::setfill(' ') << std::dec
0653                  << " dec: " << cmsHeader.sourceID() << std::endl;
0654 
0655     myCoutStream << "  FOV:         " << std::hex << " hex: "
0656                  << "     " << std::setw(1) << std::setfill('0') << cmsHeader.version() << std::setfill(' ') << std::dec
0657                  << " dec: " << cmsHeader.version() << std::endl;
0658 
0659     myCoutStream << "  H:           " << std::hex << " hex: "
0660                  << "     " << std::setw(1) << std::setfill('0') << cmsHeader.moreHeaders() << std::setfill(' ')
0661                  << std::dec << " dec: " << cmsHeader.moreHeaders() << std::endl;
0662 
0663     LogDebug("L1GlobalTriggerEvmRawToDigi") << "\n CMS Header \n" << myCoutStream.str() << "\n" << std::endl;
0664   }
0665 }
0666 
0667 // unpack trailer word
0668 // trPtr pointer to the beginning of trailer obtained from gtPtr
0669 void L1GlobalTriggerEvmRawToDigi::unpackTrailer(const unsigned char* trlPtr, FEDTrailer& cmsTrailer) {
0670   // TODO  if needed in another format
0671 
0672   // print the trailer info
0673   if (m_verbosity && m_isDebugEnabled) {
0674     const cms_uint64_t* payload = reinterpret_cast<cms_uint64_t*>(const_cast<unsigned char*>(trlPtr));
0675 
0676     std::ostringstream myCoutStream;
0677 
0678     // one word only
0679     int iWord = 0;
0680 
0681     myCoutStream << std::setw(4) << iWord << "  " << std::hex << std::setfill('0') << std::setw(16) << payload[iWord]
0682                  << std::dec << std::setfill(' ') << "\n"
0683                  << std::endl;
0684 
0685     myCoutStream << "  Event_length:  " << std::hex << " hex: "
0686                  << "" << std::setw(6) << std::setfill('0') << cmsTrailer.fragmentLength() << std::setfill(' ')
0687                  << std::dec << " dec: " << cmsTrailer.fragmentLength() << std::endl;
0688 
0689     myCoutStream << "  CRC:           " << std::hex << " hex: "
0690                  << "  " << std::setw(4) << std::setfill('0') << cmsTrailer.crc() << std::setfill(' ') << std::dec
0691                  << " dec: " << cmsTrailer.crc() << std::endl;
0692 
0693     myCoutStream << "  Event_status:  " << std::hex << " hex: "
0694                  << "    " << std::setw(2) << std::setfill('0') << cmsTrailer.evtStatus() << std::setfill(' ')
0695                  << std::dec << " dec: " << cmsTrailer.evtStatus() << std::endl;
0696 
0697     myCoutStream << "  TTS_bits:      " << std::hex << " hex: "
0698                  << "     " << std::setw(1) << std::setfill('0') << cmsTrailer.ttsBits() << std::setfill(' ')
0699                  << std::dec << " dec: " << cmsTrailer.ttsBits() << std::endl;
0700 
0701     myCoutStream << "  More trailers: " << std::hex << " hex: "
0702                  << "     " << std::setw(1) << std::setfill('0') << cmsTrailer.moreTrailers() << std::setfill(' ')
0703                  << std::dec << " dec: " << cmsTrailer.moreTrailers() << std::endl;
0704 
0705     LogDebug("L1GlobalTriggerEvmRawToDigi") << "\n CMS Trailer \n" << myCoutStream.str() << "\n" << std::endl;
0706   }
0707 }
0708 
0709 // produce empty products in case of problems
0710 void L1GlobalTriggerEvmRawToDigi::produceEmptyProducts(edm::Event& iEvent) {
0711   std::unique_ptr<L1GlobalTriggerEvmReadoutRecord> gtReadoutRecord(new L1GlobalTriggerEvmReadoutRecord());
0712 
0713   // put empty records into event
0714 
0715   iEvent.put(std::move(gtReadoutRecord));
0716 }
0717 
0718 // dump FED raw data
0719 void L1GlobalTriggerEvmRawToDigi::dumpFedRawData(const unsigned char* gtPtr, int gtSize, std::ostream& myCout) {
0720   LogDebug("L1GlobalTriggerEvmRawToDigi") << "\nDump FED raw data.\n" << std::endl;
0721 
0722   int wLength = L1GlobalTriggerReadoutSetup::WordLength;
0723   int uLength = L1GlobalTriggerReadoutSetup::UnitLength;
0724 
0725   int gtWords = gtSize / uLength;
0726   LogTrace("L1GlobalTriggerEvmRawToDigi") << "\nFED GT words (" << wLength << " bits):" << gtWords << "\n" << std::endl;
0727 
0728   const cms_uint64_t* payload = reinterpret_cast<cms_uint64_t*>(const_cast<unsigned char*>(gtPtr));
0729 
0730   for (unsigned int i = 0; i < gtSize / sizeof(cms_uint64_t); i++) {
0731     myCout << std::setw(4) << i << "  " << std::hex << std::setfill('0') << std::setw(16) << payload[i] << std::dec
0732            << std::setfill(' ') << std::endl;
0733   }
0734 }
0735 
0736 // static class members