Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-02-14 13:14:55

0001 #include "DCCDataParser.h"
0002 
0003 /*----------------------------------------------*/
0004 /* DCCTBDataParser::DCCTBDataParser                 */
0005 /* class constructor                            */
0006 /*----------------------------------------------*/
0007 DCCTBDataParser::DCCTBDataParser(const std::vector<uint32_t> &parserParameters, bool parseInternalData, bool debug)
0008     : buffer_(nullptr), parseInternalData_(parseInternalData), debug_(debug), parameters(parserParameters) {
0009   mapper_ = new DCCTBDataMapper(this);  //build a new data mapper
0010   resetErrorCounters();                 //restart error counters
0011   computeBlockSizes();                  //calculate block sizes
0012 }
0013 
0014 /*----------------------------------------------*/
0015 /* DCCTBDataParser::resetErrorCounters            */
0016 /* resets error counters                        */
0017 /*----------------------------------------------*/
0018 void DCCTBDataParser::resetErrorCounters() {
0019   //set error counters to 0
0020   errors_["DCC::BOE"] = 0;           //begin of event (header B[60-63])
0021   errors_["DCC::EOE"] = 0;           //end of event (trailer B[60-63])
0022   errors_["DCC::EVENT LENGTH"] = 0;  //event length (trailer B[32-55])
0023 }
0024 
0025 /*----------------------------------------------*/
0026 /* DCCTBDataParser::computeBlockSizes             */
0027 /* calculate the size of TCC and SR blocks      */
0028 /*----------------------------------------------*/
0029 void DCCTBDataParser::computeBlockSizes() {
0030   uint32_t nTT = numbTTs();                  //gets the number of the trigger towers (default:68)
0031   uint32_t tSamples = numbTriggerSamples();  //gets the number of trigger time samples (default: 1)
0032   uint32_t nSr = numbSRF();                  //gests the number of SR flags (default:68)
0033 
0034   uint32_t tf(0), srf(0);
0035 
0036   if ((nTT * tSamples) < 4 || (nTT * tSamples) % 4)
0037     tf = 1;  //test is there is no TTC primitives or if it's a multiple of 4?
0038   else
0039     tf = 0;
0040 
0041   if (srf < 16 || srf % 16)
0042     srf = 1;  //??? by default srf=0 why do we make this test ?????
0043   else
0044     srf = 0;
0045 
0046   //TTC block size: header (8 bytes) + 17 words with 4 trigger primitives (17*8bytes)
0047   tccBlockSize_ = 8 + ((nTT * tSamples) / 4) * 8 + tf * 8;
0048 
0049   //SR block size: header (8 bytes) + 4 words with 16 SR flags + 1 word with 4 SR flags (5*8bytes)
0050   srpBlockSize_ = 8 + (nSr / 16) * 8 + srf * 8;
0051 }
0052 
0053 /*------------------------------------------------*/
0054 /* DCCTBDataParser::parseFile                       */
0055 /* reada data from file and parse it              */
0056 /*------------------------------------------------*/
0057 void DCCTBDataParser::parseFile(std::string fileName, bool singleEvent) {
0058   std::ifstream inputFile;  //open file as input
0059   inputFile.open(fileName.c_str());
0060 
0061   resetErrorCounters();  //reset error counters
0062 
0063   //for debug purposes
0064   //std::cout << "Now in DCCTBDataParser::parseFile " << std::endl;
0065 
0066   //if file opened correctly read data to a buffer and parse it
0067   //else throw an exception
0068   if (!inputFile.fail()) {
0069     std::string myWord;                   //word read from line
0070     std::vector<std::string> dataVector;  //data vector
0071 
0072     //until the end of file read each line as a string and add it to the data vector
0073     while (inputFile >> myWord) {
0074       dataVector.push_back(myWord);
0075     }
0076 
0077     bufferSize_ = (dataVector.size()) * 4;  //buffer size in bytes (note:each char is an hex number)
0078 
0079     uint32_t *myData = new uint32_t[dataVector.size()];  //allocate memory for a new data buffer
0080     uint32_t *const myDataBeginning = myData;            //pointer that stays at the beginning of the allocated memory
0081 
0082     //fill buffer data with data from file lines
0083     for (uint32_t i = 1; i <= dataVector.size(); i++, myData++) {
0084       sscanf((dataVector[i - 1]).c_str(), "%x", myData);
0085 
0086       //for debug purposes
0087       //std::cout << std::endl << "Data position: " << dec << i << " val = " << getHexString(*myData);
0088     }
0089 
0090     inputFile.close();  //close file
0091 
0092     parseBuffer(myData, bufferSize_, singleEvent);  //parse data from the newly filled myData
0093     delete[] myDataBeginning;
0094   } else {
0095     std::string errorMessage = std::string(" Error::Unable to open file :") + fileName;
0096     throw ECALTBParserException(errorMessage);
0097   }
0098 }
0099 
0100 /*----------------------------------------------------------*/
0101 /* DCCTBDataParser::parseBuffer                               */
0102 /* parse data from a buffer                                 */
0103 /*----------------------------------------------------------*/
0104 void DCCTBDataParser::parseBuffer(const uint32_t *buffer, uint32_t bufferSize, bool singleEvent) {
0105   resetErrorCounters();  //reset error counters
0106 
0107   buffer_ = buffer;  //set class buffer
0108 
0109   //clear stored data
0110   processedEvent_ = 0;
0111   events_.clear();
0112   std::vector<DCCTBEventBlock *>::iterator it;
0113   for (it = dccEvents_.begin(); it != dccEvents_.end(); it++) {
0114     delete *it;
0115   }
0116   dccEvents_.clear();
0117   eventErrors_ = "";
0118 
0119   //for debug purposes
0120   //std::cout << std::endl << "Now in DCCTBDataParser::parseBuffer" << std::endl;
0121   //std::cout << std::endl << "Buffer Size:" << dec << bufferSize << std::endl;
0122 
0123   //check if we have a coherent buffer size
0124   if (bufferSize % 8) {
0125     std::string fatalError;
0126     fatalError += "\n ======================================================================";
0127     fatalError += "\n Fatal error at event = " + getDecString(events_.size() + 1);
0128     fatalError += "\n Buffer Size of = " + getDecString(bufferSize) + "[bytes] is not divisible by 8 ... ";
0129     fatalError += "\n ======================================================================";
0130     throw ECALTBParserException(fatalError);
0131   }
0132   if (bufferSize < EMPTYEVENTSIZE) {
0133     std::string fatalError;
0134     fatalError += "\n ======================================================================";
0135     fatalError += "\n Fatal error at event = " + getDecString(events_.size() + 1);
0136     fatalError += "\n Buffer Size of = " + getDecString(bufferSize) + "[bytes] is less than an empty event ... ";
0137     fatalError += "\n ======================================================================";
0138     throw ECALTBParserException(fatalError);
0139   }
0140 
0141   const uint32_t *myPointer = buffer_;
0142 
0143   //  uint32_t processedBytes(0), wordIndex(0), lastEvIndex(0),eventSize(0), eventLength(0), errorMask(0);
0144   uint32_t processedBytes(0), wordIndex(0), eventLength(0), errorMask(0);
0145 
0146   //parse until there are no more events
0147   while (processedBytes + EMPTYEVENTSIZE <= bufferSize) {
0148     //for debug purposes
0149     //std::cout << "-> processedBytes.  =   " << dec << processedBytes << std::endl;
0150     //std::cout << " -> Processed Event index =   " << dec << processedEvent_ << std::endl;
0151     //std::cout << "-> First ev.word    = 0x" << hex << (*myPointer) << std::endl;
0152     //std::cout << "-> word index       =   " << dec << wordIndex << std::endl;
0153 
0154     //check if Event Length is coherent /////////////////////////////////////////
0155     uint32_t bytesToEnd = bufferSize - processedBytes;
0156     std::pair<uint32_t, uint32_t> eventD = checkEventLength(myPointer, bytesToEnd, singleEvent);
0157     eventLength = eventD.second;
0158     errorMask = eventD.first;
0159     //////////////////////////////////////////////////////////////////////////////
0160 
0161     //for debug purposes
0162     //std::cout <<" -> EventSizeBytes        =   " << dec << eventLength*8 << std::endl;
0163 
0164     //for debug purposes debug
0165     //std::cout<<std::endl;
0166     //std::cout<<" out... Bytes To End.... =   "<<dec<<bytesToEnd<<std::endl;
0167     //std::cout<<" out... Processed Event  =   "<<dec<<processedEvent_<<std::endl;
0168     //std::cout<<" out... Event Length     =   "<<dec<<eventLength<<std::endl;
0169     //std::cout<<" out... LastWord         = 0x"<<hex<<*(myPointer+eventLength*2-1)<<std::endl;
0170 
0171     if (parseInternalData_) {
0172       //build a new event block from buffer
0173       DCCTBEventBlock *myBlock =
0174           new DCCTBEventBlock(this, myPointer, eventLength * 8, eventLength * 2 - 1, wordIndex, 0);
0175 
0176       //add event to dccEvents vector
0177       dccEvents_.push_back(myBlock);
0178     }
0179 
0180     //build the event pointer with error mask and add it to the events vector
0181     std::pair<const uint32_t *, uint32_t> eventPointer(myPointer, eventLength);
0182     std::pair<uint32_t, std::pair<const uint32_t *, uint32_t> > eventPointerWithErrorMask(errorMask, eventPointer);
0183     events_.push_back(eventPointerWithErrorMask);
0184 
0185     //update processed buffer size
0186     processedEvent_++;
0187     processedBytes += eventLength * 8;
0188     //std::cout << std::endl << "Processed Bytes = " << dec << processedBytes << std::endl;
0189 
0190     //go to next event
0191     myPointer += eventLength * 2;
0192     wordIndex += eventLength * 2;
0193   }
0194 }
0195 
0196 /*---------------------------------------------*/
0197 /* DCCTBDataParser::checkEventLength             */
0198 /* check if event length is consistent with    */
0199 /* the words written in buffer                 */
0200 /* returns a 3 bit error mask codified as:     */
0201 /*   bit 1 - BOE error                         */
0202 /*   bit 2 - EVENT LENGTH error                */
0203 /*   bit 3 - EOE Error                         */
0204 /* and the event length                        */
0205 /*---------------------------------------------*/
0206 std::pair<uint32_t, uint32_t> DCCTBDataParser::checkEventLength(const uint32_t *pointerToEvent,
0207                                                                 uint32_t bytesToEnd,
0208                                                                 bool singleEvent) {
0209   std::pair<uint32_t, uint32_t> result;  //returns error mask and event length
0210   uint32_t errorMask(0);                 //error mask to return
0211 
0212   //check begin of event (BOE bits field)
0213   //(Note: we have to add one to read the 2nd 32 bit word where BOE is written)
0214   const uint32_t *boePointer = pointerToEvent + 1;
0215   if ((((*boePointer) >> BOEBEGIN) & BOEMASK) != BOE) {
0216     (errors_["DCC::BOE"])++;
0217     errorMask = 1;
0218   }
0219 
0220   //get Event Length from buffer (Note: we have to add two to read the 3rd 32 bit word where EVENT LENGTH is written)
0221   const uint32_t *myPointer = pointerToEvent + 2;
0222   uint32_t eventLength = (*myPointer) & EVENTLENGTHMASK;
0223 
0224   // std::cout << " Event Length(from decoding) = " << dec << eventLength << "... bytes to end... " << bytesToEnd << ", event numb : " << processedEvent_ << std::endl;
0225 
0226   bool eoeError = false;
0227 
0228   //check if event is empty but but EVENT LENGTH is not corresponding to it
0229   if (singleEvent && eventLength != bytesToEnd / 8) {
0230     eventLength = bytesToEnd / 8;
0231     (errors_["DCC::EVENT LENGTH"])++;
0232     errorMask = errorMask | (1 << 1);
0233   }
0234   //check if event length mismatches the number of words written as data
0235   else if (eventLength == 0 || eventLength > (bytesToEnd / 8) || eventLength < (EMPTYEVENTSIZE / 8)) {
0236     // How to handle bad event length in multiple event buffers
0237     // First approach : Send an exception
0238     // Second aproach : Try to find the EOE (To be done? If yes check dataDecoder tBeam implementation)
0239     std::string fatalError;
0240 
0241     fatalError += "\n ======================================================================";
0242     fatalError += "\n Fatal error at event = " + getDecString(events_.size() + 1);
0243     fatalError += "\n Decoded event length = " + getDecString(eventLength);
0244     fatalError += "\n bytes to buffer end  = " + getDecString(bytesToEnd);
0245     fatalError += "\n Unable to procead the data decoding ...";
0246 
0247     if (eventLength > (bytesToEnd / 8)) {
0248       fatalError += " (eventLength > (bytesToEnd / 8)";
0249     } else {
0250       fatalError += "\n event length not big enough heaven to build an empty event ( 4x8 bytes)";
0251     }
0252 
0253     fatalError += "\n ======================================================================";
0254 
0255     throw ECALTBParserException(fatalError);
0256   }
0257 
0258   //check end of event (EOE bits field)
0259   //(Note: event length is multiplied by 2 because its written as 32 bit words and not 64 bit words)
0260   const uint32_t *endOfEventPointer = pointerToEvent + eventLength * 2 - 1;
0261   if ((((*endOfEventPointer) >> EOEBEGIN & EOEMASK) != EOEMASK) && !eoeError) {
0262     (errors_["DCC::EOE"])++;
0263     errorMask = errorMask | (1 << 2);
0264   }
0265 
0266   //build result to return
0267   result.first = errorMask;
0268   result.second = eventLength;
0269 
0270   return result;
0271 }
0272 
0273 /*----------------------------------------------*/
0274 /* DCCTBDataParser::index                         */
0275 /* build an index string                        */
0276 /*----------------------------------------------*/
0277 std::string DCCTBDataParser::index(uint32_t position) {
0278   char indexBuffer[20];
0279   long unsigned int pos = position;
0280   snprintf(
0281       indexBuffer, sizeof(indexBuffer), "W[%08lu]", pos);  //build an index string for display purposes, p.e.  W[15]
0282 
0283   return std::string(indexBuffer);
0284 }
0285 
0286 /*-----------------------------------------------*/
0287 /* DCCTBDataParser::getDecString                   */
0288 /* print decimal data to a string                */
0289 /*-----------------------------------------------*/
0290 std::string DCCTBDataParser::getDecString(uint32_t dat) {
0291   char buffer[15];
0292   long unsigned int data = dat;
0293   snprintf(buffer, sizeof(buffer), "%lu", data);
0294 
0295   return std::string(buffer);
0296 }
0297 
0298 /*-------------------------------------------------*/
0299 /* DCCTBDataParser::getHexString                     */
0300 /* print data in hexadecimal base to a string      */
0301 /*-------------------------------------------------*/
0302 std::string DCCTBDataParser::getHexString(uint32_t data) {
0303   char buffer[15];
0304   snprintf(buffer, sizeof(buffer), "0x%08x", (uint16_t)(data));
0305 
0306   return std::string(buffer);
0307 }
0308 
0309 /*------------------------------------------------*/
0310 /* DCCTBDataParser::getIndexedData                  */
0311 /* build a string with index and data             */
0312 /*------------------------------------------------*/
0313 std::string DCCTBDataParser::getIndexedData(uint32_t position, uint32_t *pointer) {
0314   std::string ret;
0315 
0316   //char indexBuffer[20];
0317   //char dataBuffer[20];
0318   //sprintf(indexBuffer,"W[%08u] = ",position);
0319   //sprintf(dataBuffer,"0x%08x",*pointer);
0320   //ret = std::string(indexBuffer)+std::string(dataBuffer);
0321 
0322   ret = index(position) + getHexString(*pointer);
0323 
0324   return ret;
0325 }
0326 
0327 /*-------------------------------------------------*/
0328 /* DCCTBDataParser::~DCCTBDataParser                   */
0329 /* destructor                                      */
0330 /*-------------------------------------------------*/
0331 DCCTBDataParser::~DCCTBDataParser() {
0332   // delete DCCTBEvents if any...
0333   std::vector<DCCTBEventBlock *>::iterator it;
0334   for (it = dccEvents_.begin(); it != dccEvents_.end(); it++) {
0335     delete *it;
0336   }
0337   dccEvents_.clear();
0338 
0339   delete mapper_;
0340 }