Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-05-23 23:00:39

0001 #include "CSCFileReader.h"
0002 
0003 #include <cerrno>
0004 #include <cstdlib>
0005 #include <cstring>
0006 
0007 #include <IORawData/CSCCommissioning/src/CSCFileReader.h>
0008 
0009 #include <DataFormats/FEDRawData/interface/FEDHeader.h>
0010 #include <DataFormats/FEDRawData/interface/FEDTrailer.h>
0011 #include <DataFormats/FEDRawData/interface/FEDNumbering.h>
0012 
0013 #include <DataFormats/Provenance/interface/EventID.h>
0014 #include <DataFormats/Provenance/interface/Timestamp.h>
0015 #include <DataFormats/FEDRawData/interface/FEDRawData.h>
0016 #include <DataFormats/FEDRawData/interface/FEDRawDataCollection.h>
0017 
0018 #include <FWCore/ParameterSet/interface/ParameterSet.h>
0019 #include <FWCore/Utilities/interface/Exception.h>
0020 
0021 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0022 
0023 #include <vector>
0024 #include <string>
0025 #include <iosfwd>
0026 #include <sstream>
0027 #include <iostream>
0028 #include <algorithm>
0029 
0030 #define nRUIs 40
0031 #define nFUs 4
0032 
0033 CSCFileReader::CSCFileReader(const edm::ParameterSet &pset) {
0034   runNumber = pset.getUntrackedParameter<unsigned int>("runNumber", 1);
0035   LogDebug("CSCFileReader|ctor") << "Started ...";
0036   // Below some data members are recycled for both cases: RUIs and FUs
0037   //  this is ok as long as eighter of RUI or FU are are provided in .cfg (not both)
0038   nActiveRUIs = 0;
0039   nActiveFUs = 0;
0040 
0041   /// Legacy first read EDM EvendID bug (fixed?).
0042   /// Currently disabled to fix number of events with data
0043   /// Added as configurable parameter
0044   // fFirstReadBug = true;
0045   fFirstReadBug = pset.getUntrackedParameter<bool>("FirstReadBug", false);
0046   for (int unit = 0; unit < nRUIs; unit++) {
0047     std::ostringstream ruiName, fuName;
0048     ruiName << "RUI" << (unit < 10 ? "0" : "") << unit << std::ends;
0049     fuName << "FU" << unit << std::ends;
0050     std::vector<std::string> ruiFiles =
0051         pset.getUntrackedParameter<std::vector<std::string> >(ruiName.str().c_str(), std::vector<std::string>(0));
0052     std::vector<std::string> fuFiles =
0053         pset.getUntrackedParameter<std::vector<std::string> >(fuName.str().c_str(), std::vector<std::string>(0));
0054     if (ruiFiles.begin() != ruiFiles.end())
0055       nActiveRUIs++;
0056     if (fuFiles.begin() != fuFiles.end())
0057       nActiveFUs++;
0058   }
0059   if (nActiveFUs && nActiveRUIs)
0060     throw cms::Exception("CSCFileReader|configuration")
0061         << "RUIs and FUs in conflict: either RUI or FU may be defined at a time, not both";
0062   if (!nActiveFUs && !nActiveRUIs)
0063     throw cms::Exception("CSCFileReader|configuration") << "Module lacks configuration";
0064 
0065   // Get list of RUI input files from cfg file
0066   for (int rui = 0; rui < nRUIs && !nActiveFUs; rui++) {
0067     std::ostringstream name;
0068     name << "RUI" << (rui < 10 ? "0" : "") << rui << std::ends;
0069 
0070     // Obtain list of files associated with current RUI
0071     fileNames[rui] =
0072         pset.getUntrackedParameter<std::vector<std::string> >(name.str().c_str(), std::vector<std::string>(0));
0073     currentFile[rui] = fileNames[rui].begin();
0074 
0075     // If list of files is not empty, open first file
0076     if (currentFile[rui] != fileNames[rui].end()) {
0077       try {
0078         RUI[rui].open(currentFile[rui]->c_str());
0079       } catch (std::runtime_error &err) {
0080         throw cms::Exception("CSCFileReader") << "InputFileMissing: " << err.what() << " (errno=" << errno << ")";
0081       }
0082       nActiveRUIs++;
0083     }
0084 
0085     // Filter out possible corruptions
0086     RUI[rui].reject(FileReaderDDU::DDUoversize | FileReaderDDU::FFFF | FileReaderDDU::Unknown);
0087     // Do not select anything in particular
0088     RUI[rui].select(0);
0089 
0090     currentL1A[rui] = -1;
0091   }
0092 
0093   // Get list of FU input files from .cfg file
0094   for (int fu = 0; fu < nFUs && !nActiveRUIs; fu++) {
0095     std::ostringstream name;
0096     name << "FU" << fu << std::ends;
0097 
0098     // Obtain list of files associated with current FU
0099     fileNames[fu] =
0100         pset.getUntrackedParameter<std::vector<std::string> >(name.str().c_str(), std::vector<std::string>(0));
0101     currentFile[fu] = fileNames[fu].begin();
0102 
0103     // If list of files is not empty, open first file
0104     if (currentFile[fu] != fileNames[fu].end()) {
0105       try {
0106         FU[fu].open(currentFile[fu]->c_str());
0107       } catch (std::runtime_error &err) {
0108         throw cms::Exception("CSCFileReader") << "InputFileMissing: " << err.what() << " (errno=" << errno << ")";
0109       }
0110       nActiveFUs++;
0111     }
0112 
0113     // Filter out possible corruptions
0114     FU[fu].reject(FileReaderDCC::DCCoversize | FileReaderDCC::FFFF | FileReaderDCC::Unknown);
0115     // Do not select anything in particular
0116     FU[fu].select(0);
0117 
0118     currentL1A[fu] = -1;
0119   }
0120 
0121   if (nActiveRUIs && !nActiveFUs) {
0122     // Assign RUIs to FEDs
0123     for (int fed = FEDNumbering::MINCSCFEDID; fed <= FEDNumbering::MAXCSCFEDID; fed++) {
0124       std::ostringstream name;
0125       name << "FED" << fed << std::ends;
0126       std::vector<std::string> rui_list =
0127           pset.getUntrackedParameter<std::vector<std::string> >(name.str().c_str(), std::vector<std::string>(0));
0128       for (std::vector<std::string>::const_iterator rui = rui_list.begin(); rui != rui_list.end(); rui++)
0129         FED[fed].push_back((unsigned int)atoi(rui->c_str() + rui->length() - 2));
0130     }
0131     for (int fed = FEDNumbering::MINCSCDDUFEDID; fed <= FEDNumbering::MAXCSCDDUFEDID; fed++) {
0132       std::ostringstream name;
0133       name << "FED" << fed << std::ends;
0134       std::vector<std::string> rui_list =
0135           pset.getUntrackedParameter<std::vector<std::string> >(name.str().c_str(), std::vector<std::string>(0));
0136       for (std::vector<std::string>::const_iterator rui = rui_list.begin(); rui != rui_list.end(); rui++)
0137         FED[fed].push_back((unsigned int)atoi(rui->c_str() + rui->length() - 2));
0138     }
0139 
0140     // Do the same for Track-Finder FED
0141     for (int fed = FEDNumbering::MINCSCTFFEDID; fed <= FEDNumbering::MAXCSCTFFEDID; fed++) {
0142       std::ostringstream name;
0143       name << "FED" << fed << std::ends;
0144       std::vector<std::string> rui_list =
0145           pset.getUntrackedParameter<std::vector<std::string> >(name.str().c_str(), std::vector<std::string>(0));
0146       for (std::vector<std::string>::const_iterator rui = rui_list.begin(); rui != rui_list.end(); rui++)
0147         FED[fed].push_back((unsigned int)atoi(rui->c_str() + rui->length() - 2));
0148     }
0149   }
0150   // Starting point
0151   firstEvent = pset.getUntrackedParameter<int>("firstEvent", 0);
0152   nEvents = 0;
0153   expectedNextL1A = -1;
0154 
0155   // If Track-Finder was in readout specify its position in the record or set -1 otherwise
0156   //  Current agriment is that if there is a TF event it is first DDU record
0157   tfDDUnumber = pset.getUntrackedParameter<int>("tfDDUnumber", -1);
0158 
0159   // For efficiency reasons create this big chunk of data only once
0160   tmpBuf = new unsigned short[200000 * nRUIs + 4 * 4];
0161   // Event buffer and its length for every FU
0162   fuEvent[0] = nullptr;
0163   fuEventSize[0] = 0;
0164   fuEvent[1] = nullptr;
0165   fuEventSize[1] = 0;
0166   fuEvent[2] = nullptr;
0167   fuEventSize[2] = 0;
0168   fuEvent[3] = nullptr;
0169   fuEventSize[3] = 0;
0170   // Event buffer and its length for every RU
0171   for (int rui = 0; rui < nRUIs; rui++) {
0172     ruBuf[rui] = nullptr;
0173     ruBufSize[rui] = 0;
0174   }
0175   LogDebug("CSCFileReader|ctor") << "... and finished";
0176   produces<FEDRawDataCollection>();
0177 }
0178 
0179 CSCFileReader::~CSCFileReader(void) {
0180   if (tmpBuf)
0181     delete[] tmpBuf;
0182 }
0183 
0184 int CSCFileReader::readRUI(int rui, const unsigned short *&buf, size_t &length) {
0185   if (currentFile[rui] == fileNames[rui].end())
0186     return -1;
0187   do {
0188     try {
0189       length = RUI[rui].next(buf);
0190     } catch (std::runtime_error &err) {
0191       throw cms::Exception("CSCFileReader|reading") << "EndOfStream: " << err.what() << " (errno=" << errno << ")";
0192     }
0193     if (length == 0)  // end of file, try next one
0194     {
0195       if (++currentFile[rui] != fileNames[rui].end()) {
0196         try {
0197           RUI[rui].open(currentFile[rui]->c_str());
0198         } catch (std::runtime_error &err) {
0199           throw cms::Exception("CSCFileReader|reading")
0200               << "InputFileMissing: " << err.what() << " (errno=" << errno << ")";
0201         }
0202       } else
0203         return -1;
0204     }
0205   } while (length == 0);
0206   return buf[2] | ((buf[3] & 0xFF) << 16);
0207 }
0208 
0209 int CSCFileReader::readFU(int fu, const unsigned short *&buf, size_t &length) {
0210   if (currentFile[fu] == fileNames[fu].end())
0211     return -1;
0212   do {
0213     try {
0214       length = FU[fu].next(buf);
0215     } catch (std::runtime_error &err) {
0216       throw cms::Exception("CSCFileReader|reading") << "EndOfStream: " << err.what() << " (errno=" << errno << ")";
0217     }
0218     if (length == 0)  // end of file, try next one
0219     {
0220       if (++currentFile[fu] != fileNames[fu].end()) {
0221         try {
0222           FU[fu].open(currentFile[fu]->c_str());
0223         } catch (std::runtime_error &err) {
0224           throw cms::Exception("CSCFileReader|reading")
0225               << "InputFileMissing: " << err.what() << " (errno=" << errno << ")";
0226         }
0227       } else
0228         return -1;
0229     }
0230   } while (length == 0);
0231   // Take L1A from first DDU header in the DCC record (shift=8)
0232   return buf[2 + 8] | ((buf[3 + 8] & 0xFF) << 16);
0233 }
0234 
0235 int CSCFileReader::buildEventFromRUIs(FEDRawDataCollection *data) {
0236   int eventNumber = -1;  // Will determine below
0237 
0238   do {
0239     // Read next event from RUIs
0240     for (int rui = 0; rui < nRUIs; rui++) {
0241       // read event from the RUI only in two cases:
0242       //     1) it is readable (currentL1A>0) and we expect next event from the RUI
0243       //     2) it is first time (expectedNextL1A<0)
0244       if ((currentL1A[rui] > 0 && currentL1A[rui] < expectedNextL1A) || expectedNextL1A < 0) {
0245         currentL1A[rui] = readRUI(rui, ruBuf[rui], ruBufSize[rui]);
0246         //      std::cout << "read rui" << rui << " l1a: " << currentL1A[rui] << " size: " << ruBufSize[rui] << std::endl;
0247       }
0248     }
0249     eventNumber = -1;
0250 
0251     // Select lowest L1A from all RUIs and don't expect next event from RUIs that currently hold higher L1A
0252     for (int rui = 0; rui < nRUIs; rui++)
0253       if (currentL1A[rui] >= 0 && (eventNumber > currentL1A[rui] || eventNumber == -1))
0254         eventNumber = currentL1A[rui];
0255     // No readable RUIs => fall out
0256     if (eventNumber < 0)
0257       return -1;
0258     // Expect next event to be incremented by 1 wrt. to the current event
0259     expectedNextL1A = eventNumber + 1;
0260 
0261   } while (nEvents++ < firstEvent);
0262 
0263   for (std::map<unsigned int, std::list<unsigned int> >::const_iterator fed = FED.begin(); fed != FED.end(); fed++)
0264     if (fed->first < (unsigned int)FEDNumbering::MINCSCTFFEDID) {
0265       // Now let's pretend that DDU data were wrapped with DCC Header (2 64-bit words) and Trailer (2 64-bit words):
0266       unsigned short *dccBuf = tmpBuf, *dccCur = dccBuf;
0267       dccCur[3] = 0x5000;
0268       dccCur[2] = 0x0000;
0269       dccCur[1] = 0x0000;
0270       dccCur[0] = 0x005F;  // Fake DCC Header 1
0271       dccCur[7] = 0xD900;
0272       dccCur[6] = 0x0000;
0273       dccCur[5] = 0x0000;
0274       dccCur[4] = 0x0017;  // Fake DCC Header 2
0275       dccCur += 8;
0276 
0277       for (std::list<unsigned int>::const_iterator rui = fed->second.begin(); rui != fed->second.end(); rui++) {
0278         //cout<<"Event:"<<eventNumber<<"  FED:"<<fed->first<<"  RUI:"<<*(fed->second.begin())<<" currL1A:"<<currentL1A[*rui]<<endl;
0279         if (currentL1A[*rui] == eventNumber) {
0280           if (dccCur - dccBuf + ruBufSize[*rui] >= 200000 * nRUIs + 8)
0281             throw cms::Exception("CSCFileReader|eventBuffer")
0282                 << "OutOfBuffer: Event size exceeds maximal size allowed!";
0283           memcpy(dccCur, ruBuf[*rui], ruBufSize[*rui] * sizeof(unsigned short));
0284           dccCur += ruBufSize[*rui];
0285         }
0286       }
0287       dccCur[3] = 0xEF00;
0288       dccCur[2] = 0x0000;
0289       dccCur[1] = 0x0000;
0290       dccCur[0] = 0x0000;  // Fake DCC Trailer 2
0291       dccCur[7] = 0xAF00;
0292       dccCur[6] = 0x0000;
0293       dccCur[5] = 0x0000;
0294       dccCur[4] = 0x0007;  // Fake DCC Trailer 2
0295       dccCur += 8;
0296 
0297       FEDRawData &fedRawData = data->FEDData(fed->first);
0298       fedRawData.resize((dccCur - dccBuf) * sizeof(unsigned short));
0299       std::copy((unsigned char *)dccBuf, (unsigned char *)dccCur, fedRawData.data());
0300     } else {
0301       for (std::list<unsigned int>::const_iterator rui = fed->second.begin(); rui != fed->second.end(); rui++) {
0302         FEDRawData &fedRawData = data->FEDData(fed->first);
0303         fedRawData.resize(ruBufSize[*rui] * sizeof(unsigned short));
0304         std::copy((unsigned char *)ruBuf[*rui], (unsigned char *)(ruBuf[*rui] + ruBufSize[*rui]), fedRawData.data());
0305       }
0306     }
0307 
0308   return eventNumber;
0309 }
0310 
0311 int CSCFileReader::nextEventFromFUs(FEDRawDataCollection *data) {
0312   int eventNumber = -1;  // Will determine below
0313 
0314   // If this is a first time - read one event from each FU
0315   if (expectedNextL1A < 0)
0316     for (int fu = 0; fu < nFUs; fu++)
0317       currentL1A[fu] = readFU(fu, fuEvent[fu], fuEventSize[fu]);
0318 
0319   // Keep buffers for every FU ready at all times
0320   // When buffer from some FU is ready to go as the next event,
0321   //  release it, but read next one
0322   int readyToGo = -1;
0323   for (int fu = 0; fu < nFUs; fu++) {
0324     // If FU is readable and (first loop of this cycle or current FU holds smallest L1A)
0325     if (currentL1A[fu] >= 0 && (eventNumber < 0 || currentL1A[fu] < eventNumber)) {
0326       readyToGo = fu;
0327       eventNumber = currentL1A[fu];
0328     }
0329   }
0330   // No readable FUs => fall out
0331   if (readyToGo < 0)
0332     return -1;
0333 
0334   expectedNextL1A = eventNumber + 1;
0335 
0336   // Compose event from DDC record striped of Track-Finder DDU and a separate TF DDU event
0337   unsigned long long *start = (unsigned long long *)fuEvent[readyToGo];
0338   unsigned long long *end = nullptr;
0339   enum { Header = 1, Trailer = 2 };
0340   unsigned int eventStatus = 0;
0341   for (int dduRecord = 0; dduRecord <= tfDDUnumber; dduRecord++) {
0342     unsigned long long word_0 = 0, word_1 = 0, word_2 = 0;
0343     size_t dduWordCount = 0;
0344     while (!end && dduWordCount < fuEventSize[readyToGo]) {
0345       unsigned long long *dduWord = start;
0346 
0347       while (dduWordCount < fuEventSize[readyToGo]) {
0348         word_0 = word_1;    // delay by 2 DDU words
0349         word_1 = word_2;    // delay by 1 DDU word
0350         word_2 = *dduWord;  // current DDU word
0351         if ((word_2 & 0xFFFFFFFFFFFF0000LL) == 0x8000000180000000LL) {
0352           if (eventStatus & Header)  // Second header
0353           {
0354             word_2 = word_1;
0355             end = dduWord;
0356             break;
0357           }
0358           start = dduWord;
0359         }
0360         if ((word_0 & 0xFFFFFFFFFFFF0000LL) == 0x8000FFFF80000000LL) {
0361           eventStatus |= Trailer;
0362           end = ++dduWord;
0363           break;
0364         }
0365         // Increase counters by one DDU word
0366         dduWord++;
0367         dduWordCount++;
0368       }
0369     }
0370     // If reach max length
0371     if (dduWordCount == fuEventSize[readyToGo]) {
0372       end = (unsigned long long *)(fuEvent[readyToGo] + fuEventSize[readyToGo]);
0373       break;
0374     }
0375   }
0376   // Include 0x5xxx preHeader if exists
0377   if (start > (unsigned long long *)fuEvent[readyToGo] && (*(start - 1) & 0xF000000000000000LL) == 0x5000000000000000LL)
0378     start--;
0379 
0380   // If Track-Finder DDU was in readout
0381   if (tfDDUnumber >= 0) {
0382     // Cut out Track-Finder DDU from the buffer
0383     if (!end)
0384       throw cms::Exception("CSCFileReader|lookingForTF") << " Sanity check failed (end==0)! Should never happen";
0385 
0386     FEDRawData &tfRawData = data->FEDData(FEDNumbering::MINCSCTFFEDID);
0387     tfRawData.resize((end - start) * sizeof(unsigned long long));
0388     std::copy((unsigned char *)start, (unsigned char *)end, tfRawData.data());
0389 
0390     // Create a new buffer from everything before and after TF DDU
0391     unsigned short *event = tmpBuf;
0392     memcpy(event, fuEvent[readyToGo], ((unsigned short *)start - fuEvent[readyToGo]) * sizeof(unsigned short));
0393     event += ((unsigned short *)start - fuEvent[readyToGo]);
0394     memcpy(event, end, (fuEvent[readyToGo] + fuEventSize[readyToGo] - (unsigned short *)end) * sizeof(unsigned short));
0395     event += fuEvent[readyToGo] + fuEventSize[readyToGo] - (unsigned short *)end;
0396     FEDRawData &fedRawData = data->FEDData(FEDNumbering::MINCSCFEDID);
0397     fedRawData.resize((fuEventSize[readyToGo] - ((unsigned short *)end - (unsigned short *)start)) *
0398                       sizeof(unsigned short));
0399     std::copy((unsigned char *)tmpBuf, (unsigned char *)event, fedRawData.data());
0400   } else {
0401     FEDRawData &fedRawData = data->FEDData(FEDNumbering::MINCSCFEDID);
0402     fedRawData.resize((fuEventSize[readyToGo]) * sizeof(unsigned short));
0403     std::copy((unsigned char *)fuEvent[readyToGo],
0404               (unsigned char *)(fuEvent[readyToGo] + fuEventSize[readyToGo]),
0405               fedRawData.data());
0406   }
0407 
0408   currentL1A[readyToGo] = readFU(readyToGo, fuEvent[readyToGo], fuEventSize[readyToGo]);
0409 
0410   return eventNumber;
0411 }
0412 
0413 int CSCFileReader::fillRawData(edm::Event &e, /* edm::Timestamp& tstamp,*/ FEDRawDataCollection *&data) {
0414   edm::EventID eID = e.id();
0415   data = new FEDRawDataCollection();
0416 
0417   if (fFirstReadBug) {
0418     eID = edm::EventID(runNumber, 1U, 1);
0419     fFirstReadBug = false;
0420     return true;
0421   }
0422 
0423   // int runNumber   = 0; // Unknown at the level of EMu local DAQ
0424   int eventNumber = -1;  // Will determine below
0425 
0426   if (!nActiveFUs && nActiveRUIs) {
0427     eventNumber = buildEventFromRUIs(data);
0428     //      std::cout << eventNumber << std::endl;
0429   } else {
0430     eventNumber = nextEventFromFUs(data);
0431   }
0432 
0433   if (eventNumber < 0)
0434     return false;
0435 
0436   eID = edm::EventID(runNumber, 1U, eventNumber);
0437 
0438   return true;
0439 }
0440 
0441 void CSCFileReader::produce(edm::Event &e, edm::EventSetup const &es) {
0442   edm::Handle<FEDRawDataCollection> rawdata;
0443   FEDRawDataCollection *fedcoll = nullptr;
0444   fillRawData(e, fedcoll);
0445   std::unique_ptr<FEDRawDataCollection> bare_product(fedcoll);
0446   e.put(std::move(bare_product));
0447 }
0448 
0449 #undef nRUIs
0450 #undef nFUs