Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2023-03-17 10:59:40

0001 
0002 #include "EventFilter/EcalRawToDigi/interface/DCCDataUnpacker.h"
0003 #include "EventFilter/EcalRawToDigi/interface/EcalDCCHeaderRuntypeDecoder.h"
0004 #include "EventFilter/EcalRawToDigi/interface/EcalElectronicsMapper.h"
0005 #include "EventFilter/EcalRawToDigi/interface/DCCMemBlock.h"
0006 
0007 #include "EventFilter/EcalRawToDigi/interface/DCCEBEventBlock.h"
0008 #include "EventFilter/EcalRawToDigi/interface/DCCTowerBlock.h"
0009 #include "EventFilter/EcalRawToDigi/interface/DCCEBTCCBlock.h"
0010 #include "EventFilter/EcalRawToDigi/interface/DCCEBSRPBlock.h"
0011 #include <sys/time.h>
0012 
0013 #include <iomanip>
0014 #include <sstream>
0015 
0016 DCCEBEventBlock::DCCEBEventBlock(DCCDataUnpacker* u,
0017                                  EcalElectronicsMapper* m,
0018                                  bool hU,
0019                                  bool srpU,
0020                                  bool tccU,
0021                                  bool feU,
0022                                  bool memU,
0023                                  bool forceToKeepFRdata)
0024     : DCCEventBlock(u, m, hU, srpU, tccU, feU, memU, forceToKeepFRdata) {
0025   //Builds a tower unpacker block
0026   towerBlock_ = new DCCTowerBlock(u, m, this, feUnpacking_, forceToKeepFRdata_);
0027 
0028   //Builds a srp unpacker block
0029   srpBlock_ = new DCCEBSRPBlock(u, m, this, srpUnpacking_);
0030 
0031   //Builds a tcc unpacker block
0032   tccBlock_ = new DCCEBTCCBlock(u, m, this, tccUnpacking_);
0033 
0034   // This field is not used in EB
0035   mem_ = 0;
0036 }
0037 
0038 void DCCEBEventBlock::unpack(const uint64_t* buffer, size_t numbBytes, unsigned int expFedId) {
0039   reset();
0040 
0041   eventSize_ = numbBytes;
0042   data_ = buffer;
0043 
0044   // First Header Word of fed block
0045   fedId_ = ((*data_) >> H_FEDID_B) & H_FEDID_MASK;
0046   bx_ = ((*data_) >> H_BX_B) & H_BX_MASK;
0047   l1_ = ((*data_) >> H_L1_B) & H_L1_MASK;
0048   triggerType_ = ((*data_) >> H_TTYPE_B) & H_TTYPE_MASK;
0049 
0050   // Check if fed id is the same as expected...
0051   if (fedId_ != expFedId) {
0052     if (!DCCDataUnpacker::silentMode_) {
0053       edm::LogWarning("IncorrectEvent") << "\n For event L1A: " << l1_ << "\n Expected FED id is: " << expFedId
0054                                         << " while current FED id is: " << fedId_
0055                                         << "\n => Skipping to next fed block...";
0056     }
0057 
0058     //TODO : add this to an error event collection
0059 
0060     return;
0061   }
0062 
0063   // Check if this event is an empty event
0064   if (eventSize_ == EMPTYEVENTSIZE) {
0065     if (!DCCDataUnpacker::silentMode_) {
0066       edm::LogWarning("IncorrectEvent") << "\n Event L1A: " << l1_ << " is empty for fed: " << fedId_
0067                                         << "\n => Skipping to next fed block...";
0068     }
0069     return;
0070 
0071   }
0072 
0073   //Check if event size allows at least building the header
0074   else if (eventSize_ < HEADERSIZE) {
0075     if (!DCCDataUnpacker::silentMode_) {
0076       edm::LogError("IncorrectEvent") << "\n Event L1A: " << l1_ << " in fed: " << fedId_ << "\n Event size is "
0077                                       << eventSize_ << " bytes while the minimum is " << HEADERSIZE << " bytes"
0078                                       << "\n => Skipping to next fed block...";
0079     }
0080 
0081     //TODO : add this to a dcc size error collection
0082 
0083     return;
0084   }
0085 
0086   //Second Header Word of fed block
0087   data_++;
0088 
0089   blockLength_ = (*data_) & H_EVLENGTH_MASK;
0090   dccErrors_ = ((*data_) >> H_ERRORS_B) & H_ERRORS_MASK;
0091   runNumber_ = ((*data_) >> H_RNUMB_B) & H_RNUMB_MASK;
0092 
0093   if (eventSize_ != blockLength_ * 8) {
0094     if (!DCCDataUnpacker::silentMode_) {
0095       edm::LogError("IncorrectEvent") << "\n Event L1A: " << l1_ << " in fed: " << fedId_ << "\n size is " << eventSize_
0096                                       << " bytes while " << (blockLength_ * 8) << " are set in the event header "
0097                                       << "\n => Skipping to next fed block...";
0098       //TODO : add this to a dcc size error collection
0099     }
0100     return;
0101   }
0102 
0103   //Third Header Word  of fed block
0104   data_++;
0105 
0106   // bits 0.. 31 of the 3rd DCC header word
0107   runType_ = (*data_) & H_RTYPE_MASK;
0108 
0109   fov_ = ((*data_) >> H_FOV_B) & H_FOV_MASK;
0110 
0111   // bits 32.. 47 of the 3rd DCC header word
0112   detailedTriggerType_ = ((*data_) >> H_DET_TTYPE_B) & H_DET_TTYPE_MASK;
0113 
0114   //Forth Header Word
0115   data_++;
0116   orbitCounter_ = ((*data_) >> H_ORBITCOUNTER_B) & H_ORBITCOUNTER_MASK;
0117   sr_ = ((*data_) >> H_SR_B) & B_MASK;
0118   zs_ = ((*data_) >> H_ZS_B) & B_MASK;
0119   tzs_ = ((*data_) >> H_TZS_B) & B_MASK;
0120   srChStatus_ = ((*data_) >> H_SRCHSTATUS_B) & H_CHSTATUS_MASK;
0121 
0122   bool ignoreSR(true);
0123 
0124   // getting TCC channel status bits
0125   tccChStatus_[0] = ((*data_) >> H_TCC1CHSTATUS_B) & H_CHSTATUS_MASK;
0126   tccChStatus_[1] = ((*data_) >> H_TCC2CHSTATUS_B) & H_CHSTATUS_MASK;
0127   tccChStatus_[2] = ((*data_) >> H_TCC3CHSTATUS_B) & H_CHSTATUS_MASK;
0128   tccChStatus_[3] = ((*data_) >> H_TCC4CHSTATUS_B) & H_CHSTATUS_MASK;
0129 
0130   // FE  channel Status data
0131   int channel(0);
0132   for (int dw = 0; dw < 5; dw++) {
0133     data_++;
0134     for (int i = 0; i < 14; i++, channel++) {
0135       unsigned int shift = i * 4;  //each channel has 4 bits
0136       feChStatus_[channel] = ((*data_) >> shift) & H_CHSTATUS_MASK;
0137     }
0138   }
0139 
0140   // debugging
0141   //display(cout);
0142 
0143   // Update number of available dwords
0144   dwToEnd_ = blockLength_ - HEADERLENGTH;
0145 
0146   int STATUS = unpackTCCBlocks();
0147 
0148   if (STATUS != STOP_EVENT_UNPACKING && (feUnpacking_ || srpUnpacking_)) {
0149     //NMGA note : SR comes before TCC blocks
0150     // Emmanuelle please change this in the digi to raw
0151 
0152     // Unpack SRP block
0153     if (srChStatus_ != CH_TIMEOUT && srChStatus_ != CH_DISABLED) {
0154       STATUS = srpBlock_->unpack(&data_, &dwToEnd_, SRP_NUMBFLAGS);
0155       if (STATUS == BLOCK_UNPACKED) {
0156         ignoreSR = false;
0157       }
0158     }
0159   }
0160 
0161   // See number of FE channels that we need according to the trigger type //
0162   // TODO : WHEN IN LOCAL MODE WE SHOULD CHECK RUN TYPE
0163   unsigned int numbChannels(0);
0164 
0165   if (triggerType_ == PHYSICTRIGGER) {
0166     numbChannels = 68;
0167   } else if (triggerType_ == CALIBRATIONTRIGGER) {
0168     numbChannels = 70;
0169   } else {
0170     if (!DCCDataUnpacker::silentMode_) {
0171       edm::LogError("IncorrectEvent") << "\n Event L1A: " << l1_ << " in fed: " << fedId_
0172                                       << "\n Event has an unsupported trigger type " << triggerType_
0173                                       << "\n => Skipping to next fed block...";
0174       //TODO : add this to a dcc trigger type error collection
0175     }
0176     return;
0177   }
0178 
0179   // note: there is no a-priori check that number_active_channels_from_header
0180   //          equals number_channels_found_in_data.
0181   //          The checks are doing f.e. by f.e. only.
0182 
0183   if (feUnpacking_ || memUnpacking_) {
0184     // pointer for the
0185     std::vector<short>::iterator it = feChStatus_.begin();
0186 
0187     // fields for tower recovery code
0188     unsigned int next_tower_id = 1000;
0189     const uint64_t* next_data = data_;
0190     unsigned int next_dwToEnd = dwToEnd_;
0191 
0192     // looping over FE channels, i.e. tower blocks
0193     for (unsigned int chNumber = 1; chNumber <= numbChannels && STATUS != STOP_EVENT_UNPACKING; chNumber++, it++) {
0194       //for( unsigned int i=1; chNumber<= numbChannels; chNumber++, it++ ){
0195 
0196       const short chStatus(*it);
0197 
0198       // regular cases
0199       const bool regular = (chStatus == CH_DISABLED || chStatus == CH_SUPPRESS);
0200 
0201       // problematic cases
0202       const bool problematic = (chStatus == CH_TIMEOUT || chStatus == CH_HEADERERR || chStatus == CH_LINKERR ||
0203                                 chStatus == CH_LENGTHERR || chStatus == CH_IFIFOFULL || chStatus == CH_L1AIFIFOFULL);
0204 
0205       // issuiung messages for problematic cases, even though handled by the DCC
0206       if (problematic) {
0207         if (!DCCDataUnpacker::silentMode_) {
0208           const int val = unpacker_->getCCUValue(fedId_, chNumber);
0209           const bool ttProblem = (val == 13) || (val == 14);
0210           if (!ttProblem) {
0211             edm::LogWarning("IncorrectBlock") << "Bad DCC channel status: " << chStatus << " (LV1 " << l1_ << " fed "
0212                                               << fedId_ << " tower " << chNumber << ")\n"
0213                                               << "  => DCC channel is not being unpacked";
0214           }
0215         }
0216       }
0217 
0218       // skip unpack in case of bad status
0219       if (regular || problematic) {
0220         continue;
0221       }
0222 
0223       // preserve data pointer
0224       const uint64_t* const prev_data = data_;
0225       const unsigned int prev_dwToEnd = dwToEnd_;
0226 
0227       // skip corrupted/problematic data block
0228       if (chNumber >= next_tower_id) {
0229         data_ = next_data;
0230         dwToEnd_ = next_dwToEnd;
0231         next_tower_id = 1000;
0232       }
0233 
0234       // Unpack Tower (Xtal Block)
0235       if (feUnpacking_ && chNumber <= 68) {
0236         //  in case of SR (data are 0 suppressed)
0237         if (sr_) {
0238           const bool applyZS = (fov_ == 0) ||  // backward compatibility with FOV = 0;
0239                                ignoreSR || (chStatus == CH_FORCEDZS1) ||
0240                                ((srpBlock_->srFlag(chNumber) & SRP_SRVAL_MASK) != SRP_FULLREADOUT);
0241 
0242           STATUS = towerBlock_->unpack(&data_, &dwToEnd_, applyZS, chNumber);
0243 
0244           // If there is an action to suppress SR channel the associated channel status should be updated
0245           // so we can remove this piece of code
0246           // if ( ( srpBlock_->srFlag(chNumber) & SRP_SRVAL_MASK) != SRP_NREAD ){
0247           //
0248           //  STATUS = towerBlock_->unpack(&data_,&dwToEnd_,applyZS,chNumber);
0249           //}
0250         }
0251         // no SR (possibly 0 suppression flags)
0252         else {
0253           // if tzs_ data are not really suppressed, even though zs flags are calculated
0254           if (tzs_) {
0255             zs_ = false;
0256           }
0257           STATUS = towerBlock_->unpack(&data_, &dwToEnd_, zs_, chNumber);
0258         }
0259       }
0260 
0261       // Unpack Mem blocks
0262       if (memUnpacking_ && chNumber > 68) {
0263         STATUS = memBlock_->unpack(&data_, &dwToEnd_, chNumber);
0264       }
0265 
0266       // corruption recovery
0267       if (STATUS == SKIP_BLOCK_UNPACKING) {
0268         data_ = prev_data;
0269         dwToEnd_ = prev_dwToEnd;
0270 
0271         next_tower_id = next_tower_search(chNumber);
0272 
0273         next_data = data_;
0274         next_dwToEnd = dwToEnd_;
0275 
0276         data_ = prev_data;
0277         dwToEnd_ = prev_dwToEnd;
0278       }
0279     }
0280     // closing loop over FE/TTblock channels
0281 
0282   }  // check if we need to perform unpacking of FE or mem data
0283 
0284   if (headerUnpacking_)
0285     addHeaderToCollection();
0286 }
0287 
0288 // Unpack TCC blocks
0289 int DCCEBEventBlock::unpackTCCBlocks() {
0290   if (tccChStatus_[0] != CH_TIMEOUT && tccChStatus_[0] != CH_DISABLED)
0291     return tccBlock_->unpack(&data_, &dwToEnd_, 0);
0292   else
0293     return BLOCK_UNPACKED;
0294 }