CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_6_1_2_SLHC4_patch1/src/EventFilter/EcalTBRawToDigi/src/DCCDataParser.cc

Go to the documentation of this file.
00001 #include "DCCDataParser.h"
00002 
00003 
00004 
00005 /*----------------------------------------------*/
00006 /* DCCTBDataParser::DCCTBDataParser                 */
00007 /* class constructor                            */
00008 /*----------------------------------------------*/
00009 DCCTBDataParser::DCCTBDataParser(std::vector<uint32_t> parserParameters, bool parseInternalData,bool debug):
00010   buffer_(0),parseInternalData_(parseInternalData),debug_(debug), parameters(parserParameters){
00011         
00012   mapper_ = new DCCTBDataMapper(this);       //build a new data mapper
00013   resetErrorCounters();                    //restart error counters
00014   computeBlockSizes();                     //calculate block sizes
00015   
00016 }
00017 
00018 
00019 /*----------------------------------------------*/
00020 /* DCCTBDataParser::resetErrorCounters            */
00021 /* resets error counters                        */
00022 /*----------------------------------------------*/
00023 void DCCTBDataParser::resetErrorCounters(){
00024   //set error counters to 0
00025   errors_["DCC::BOE"] = 0;               //begin of event (header B[60-63])
00026   errors_["DCC::EOE"] = 0;               //end of event (trailer B[60-63])
00027   errors_["DCC::EVENT LENGTH"] = 0;      //event length (trailer B[32-55])
00028 }
00029 
00030 
00031 /*----------------------------------------------*/
00032 /* DCCTBDataParser::computeBlockSizes             */
00033 /* calculate the size of TCC and SR blocks      */
00034 /*----------------------------------------------*/
00035 void DCCTBDataParser::computeBlockSizes(){
00036   uint32_t nTT = numbTTs();                                      //gets the number of the trigger towers (default:68)  
00037   uint32_t tSamples = numbTriggerSamples();                      //gets the number of trigger time samples (default: 1)
00038   uint32_t nSr = numbSRF();                                      //gests the number of SR flags (default:68)
00039 
00040   uint32_t tf(0), srf(0);
00041         
00042   if( (nTT*tSamples)<4 || (nTT*tSamples)%4 ) tf=1;            //test is there is no TTC primitives or if it's a multiple of 4?
00043   else tf=0;
00044   
00045 
00046   if( srf<16 || srf%16 ) srf=1;                               //??? by default srf=0 why do we make this test ?????
00047   else srf=0;
00048   
00049   //TTC block size: header (8 bytes) + 17 words with 4 trigger primitives (17*8bytes)
00050   tccBlockSize_ = 8 + ((nTT*tSamples)/4)*8 + tf*8 ;          
00051 
00052   //SR block size: header (8 bytes) + 4 words with 16 SR flags + 1 word with 4 SR flags (5*8bytes)
00053   srpBlockSize_ = 8 + (nSr/16)*8 + srf*8;
00054 }
00055 
00056 
00057 /*------------------------------------------------*/
00058 /* DCCTBDataParser::parseFile                       */
00059 /* reada data from file and parse it              */
00060 /*------------------------------------------------*/
00061 void DCCTBDataParser::parseFile(std::string fileName, bool singleEvent){
00062         
00063   std::ifstream inputFile;                            //open file as input
00064   inputFile.open(fileName.c_str());
00065         
00066   resetErrorCounters();                          //reset error counters
00067 
00068   //for debug purposes
00069   //std::cout << "Now in DCCTBDataParser::parseFile " << std::endl;
00070 
00071         
00072   //if file opened correctly read data to a buffer and parse it
00073   //else throw an exception
00074   if( !inputFile.fail() ){ 
00075         
00076     std::string myWord;                               //word read from line
00077     std::vector<std::string> dataVector;                   //data vector
00078     
00079     //until the end of file read each line as a string and add it to the data vector
00080     while( inputFile >> myWord ){ 
00081       dataVector.push_back( myWord ); 
00082     }
00083     
00084     bufferSize_ = (dataVector.size() ) * 4 ;      //buffer size in bytes (note:each char is an hex number)
00085     if( buffer_ ){ delete [] buffer_; }           //delete current vector if any
00086     buffer_ = new uint32_t[dataVector.size()];       //allocate memory for new data buffer
00087 
00088     uint32_t *myData_ = (uint32_t *) buffer_;         
00089     
00090     //fill buffer data with data from file lines
00091     for(uint32_t i = 1; i <= dataVector.size() ; i++, myData_++ ){
00092       sscanf((dataVector[i-1]).c_str(),"%x",(unsigned int *)myData_);
00093       
00094       //for debug purposes
00095       //std::cout << std::endl << "Data position: " << dec << i << " val = " << getHexString(*myData_);
00096     }
00097     
00098     inputFile.close();                              //close file
00099     
00100     parseBuffer( buffer_,bufferSize_,singleEvent);  //parse data from buffer
00101     
00102   }
00103   else{ 
00104     std::string errorMessage = std::string(" Error::Unable to open file :") + fileName;
00105     throw ECALTBParserException(errorMessage);
00106   }
00107 }
00108 
00109 
00110 /*----------------------------------------------------------*/
00111 /* DCCTBDataParser::parseBuffer                               */
00112 /* parse data from a buffer                                 */
00113 /*----------------------------------------------------------*/
00114 void DCCTBDataParser::parseBuffer(uint32_t * buffer, uint32_t bufferSize, bool singleEvent){
00115         
00116   resetErrorCounters();                           //reset error counters
00117         
00118   buffer_ = buffer;                               //set class buffer
00119   
00120   //clear stored data
00121   processedEvent_ = 0;
00122   events_.clear();
00123   std::vector<DCCTBEventBlock *>::iterator it;
00124   for( it = dccEvents_.begin(); it!=dccEvents_.end(); it++ ) { delete *it; }
00125   dccEvents_.clear();
00126   eventErrors_ = "";
00127         
00128   //for debug purposes
00129   //std::cout << std::endl << "Now in DCCTBDataParser::parseBuffer" << std::endl;
00130   //std::cout << std::endl << "Buffer Size:" << dec << bufferSize << std::endl;
00131         
00132   //check if we have a coherent buffer size
00133   if( bufferSize%8  ){
00134     std::string fatalError ;
00135     fatalError += "\n ======================================================================";          
00136     fatalError += "\n Fatal error at event = " + getDecString(events_.size()+1);
00137     fatalError += "\n Buffer Size of = "+ getDecString(bufferSize) + "[bytes] is not divisible by 8 ... ";
00138     fatalError += "\n ======================================================================";
00139     throw ECALTBParserException(fatalError);
00140   }
00141   if ( bufferSize < EMPTYEVENTSIZE ){
00142     std::string fatalError ;
00143     fatalError += "\n ======================================================================";          
00144     fatalError += "\n Fatal error at event = " + getDecString(events_.size()+1);
00145     fatalError += "\n Buffer Size of = "+ getDecString(bufferSize) + "[bytes] is less than an empty event ... ";
00146     fatalError += "\n ======================================================================";
00147     throw ECALTBParserException(fatalError);
00148   }
00149 
00150   uint32_t *myPointer =  buffer_;                        
00151   
00152   //  uint32_t processedBytes(0), wordIndex(0), lastEvIndex(0),eventSize(0), eventLength(0), errorMask(0);
00153   uint32_t processedBytes(0), wordIndex(0), eventLength(0), errorMask(0);
00154   
00155   //parse until there are no more events
00156   while( processedBytes + EMPTYEVENTSIZE <= bufferSize ){
00157 
00158     //for debug purposes
00159     //std::cout << "-> processedBytes.  =   " << dec << processedBytes << std::endl;
00160     //std::cout << " -> Processed Event index =   " << dec << processedEvent_ << std::endl;
00161     //std::cout << "-> First ev.word    = 0x" << hex << (*myPointer) << std::endl;
00162     //std::cout << "-> word index       =   " << dec << wordIndex << std::endl;
00163     
00164     //check if Event Length is coherent /////////////////////////////////////////
00165     uint32_t bytesToEnd         = bufferSize - processedBytes;
00166     std::pair<uint32_t,uint32_t> eventD = checkEventLength(myPointer,bytesToEnd,singleEvent);
00167     eventLength              = eventD.second; 
00168     errorMask                = eventD.first;
00170      
00171     //for debug purposes
00172     //std::cout <<" -> EventSizeBytes        =   " << dec << eventLength*8 << std::endl;
00173    
00174           
00175              
00176     //for debug purposes debug 
00177     //std::cout<<std::endl;
00178     //std::cout<<" out... Bytes To End.... =   "<<dec<<bytesToEnd<<std::endl;
00179     //std::cout<<" out... Processed Event  =   "<<dec<<processedEvent_<<std::endl;      
00180     //std::cout<<" out... Event Length     =   "<<dec<<eventLength<<std::endl;
00181     //std::cout<<" out... LastWord         = 0x"<<hex<<*(myPointer+eventLength*2-1)<<std::endl;
00182     
00183     if (parseInternalData_){ 
00184       //build a new event block from buffer
00185       DCCTBEventBlock *myBlock = new DCCTBEventBlock(this,myPointer,eventLength*8, eventLength*2 -1 ,wordIndex,0);
00186       
00187       //add event to dccEvents vector
00188       dccEvents_.push_back(myBlock);
00189     }
00190     
00191     //build the event pointer with error mask and add it to the events vector
00192     std::pair<uint32_t *, uint32_t> eventPointer(myPointer,eventLength);
00193     std::pair<uint32_t, std::pair<uint32_t*, uint32_t> > eventPointerWithErrorMask(errorMask,eventPointer);
00194     events_.push_back(eventPointerWithErrorMask);
00195                 
00196     //update processed buffer size 
00197     processedEvent_++;
00198     processedBytes += eventLength*8;
00199     //std::cout << std::endl << "Processed Bytes = " << dec << processedBytes << std::endl;
00200     
00201     //go to next event
00202     myPointer     += eventLength*2;
00203     wordIndex     += eventLength*2;
00204   } 
00205 }
00206 
00207 
00208 /*---------------------------------------------*/
00209 /* DCCTBDataParser::checkEventLength             */
00210 /* check if event length is consistent with    */
00211 /* the words written in buffer                 */
00212 /* returns a 3 bit error mask codified as:     */
00213 /*   bit 1 - BOE error                         */
00214 /*   bit 2 - EVENT LENGTH error                */
00215 /*   bit 3 - EOE Error                         */
00216 /* and the event length                        */
00217 /*---------------------------------------------*/
00218 std::pair<uint32_t,uint32_t> DCCTBDataParser::checkEventLength(uint32_t *pointerToEvent, uint32_t bytesToEnd, bool singleEvent){
00219         
00220   std::pair<uint32_t,uint32_t> result;    //returns error mask and event length 
00221   uint32_t errorMask(0);          //error mask to return
00222 
00223   //check begin of event (BOE bits field) 
00224   //(Note: we have to add one to read the 2nd 32 bit word where BOE is written)
00225   uint32_t *boePointer = pointerToEvent + 1;
00226   if( (  ((*boePointer)>>BOEBEGIN)& BOEMASK  )  != BOE ) { 
00227     (errors_["DCC::BOE"])++; errorMask = 1; 
00228   }
00229         
00230         
00231   //get Event Length from buffer (Note: we have to add two to read the 3rd 32 bit word where EVENT LENGTH is written)
00232   uint32_t * myPointer = pointerToEvent + 2; 
00233   uint32_t eventLength = (*myPointer)&EVENTLENGTHMASK;
00234 
00235   // std::cout << " Event Length(from decoding) = " << dec << eventLength << "... bytes to end... " << bytesToEnd << ", event numb : " << processedEvent_ << std::endl;
00236   
00237   bool eoeError = false;
00238 
00239   //check if event is empty but but EVENT LENGTH is not corresponding to it
00240   if( singleEvent && eventLength != bytesToEnd/8 ){
00241     eventLength = bytesToEnd/8;
00242     (errors_["DCC::EVENT LENGTH"])++; 
00243     errorMask = errorMask | (1<<1);
00244   }
00245   //check if event length mismatches the number of words written as data
00246   else if( eventLength == 0 || eventLength > (bytesToEnd / 8) || eventLength < (EMPTYEVENTSIZE/8) ){  
00247     // How to handle bad event length in multiple event buffers
00248     // First approach : Send an exception       
00249     // Second aproach : Try to find the EOE (To be done? If yes check dataDecoder tBeam implementation)
00250     std::string fatalError;
00251                 
00252     fatalError +="\n ======================================================================";           
00253     fatalError +="\n Fatal error at event = " + getDecString(events_.size()+1);
00254     fatalError +="\n Decoded event length = " + getDecString(eventLength);
00255     fatalError +="\n bytes to buffer end  = " + getDecString(bytesToEnd);
00256     fatalError +="\n Unable to procead the data decoding ...";
00257 
00258     if(eventLength > (bytesToEnd / 8)){ fatalError +=" (eventLength > (bytesToEnd / 8)";}
00259     else{ fatalError += "\n event length not big enough heaven to build an empty event ( 4x8 bytes)";}
00260 
00261     fatalError +="\n ======================================================================";
00262 
00263     throw ECALTBParserException(fatalError);
00264   }
00265 
00266   //check end of event (EOE bits field) 
00267   //(Note: event length is multiplied by 2 because its written as 32 bit words and not 64 bit words)
00268   uint32_t *endOfEventPointer = pointerToEvent + eventLength*2 -1;
00269   if ( (  ((*endOfEventPointer) >> EOEBEGIN & EOEMASK )  != EOEMASK) && !eoeError ){ 
00270     (errors_["DCC::EOE"])++; 
00271     errorMask = errorMask | (1<<2); 
00272   }
00273   
00274   //build result to return
00275   result.first  = errorMask;
00276   result.second = eventLength;
00277   
00278   return result;
00279 }
00280 
00281 
00282 
00283 /*----------------------------------------------*/
00284 /* DCCTBDataParser::index                         */
00285 /* build an index string                        */
00286 /*----------------------------------------------*/
00287 std::string DCCTBDataParser::index(uint32_t position){
00288 
00289   char indexBuffer[20];
00290   long unsigned int pos = position;
00291   sprintf(indexBuffer,"W[%08lu]",pos);        //build an index string for display purposes, p.e.  W[15] 
00292 
00293   return std::string(indexBuffer);      
00294 }
00295 
00296 
00297 /*-----------------------------------------------*/
00298 /* DCCTBDataParser::getDecString                   */
00299 /* print decimal data to a string                */
00300 /*-----------------------------------------------*/
00301 std::string DCCTBDataParser::getDecString(uint32_t dat){
00302         
00303   char buffer[10];
00304   long unsigned int data = dat;
00305   sprintf(buffer,"%lu",data);
00306 
00307   return std::string(buffer);   
00308 }
00309 
00310 
00311 /*-------------------------------------------------*/
00312 /* DCCTBDataParser::getHexString                     */
00313 /* print data in hexadecimal base to a string      */
00314 /*-------------------------------------------------*/
00315 std::string DCCTBDataParser::getHexString(uint32_t data){
00316         
00317   char buffer[10];
00318   sprintf(buffer,"0x%08x",(uint16_t)(data));
00319 
00320   return std::string(buffer);   
00321 }
00322 
00323 
00324 /*------------------------------------------------*/
00325 /* DCCTBDataParser::getIndexedData                  */
00326 /* build a string with index and data             */
00327 /*------------------------------------------------*/
00328 std::string DCCTBDataParser::getIndexedData(uint32_t position, uint32_t *pointer){
00329   std::string ret;
00330   
00331   //char indexBuffer[20];
00332   //char dataBuffer[20];
00333   //sprintf(indexBuffer,"W[%08u] = ",position);
00334   //sprintf(dataBuffer,"0x%08x",*pointer);
00335   //ret = std::string(indexBuffer)+std::string(dataBuffer);
00336 
00337   ret = index(position) + getHexString(*pointer);
00338   
00339   return ret;   
00340 }
00341 
00342 
00343 /*-------------------------------------------------*/
00344 /* DCCTBDataParser::~DCCTBDataParser                   */
00345 /* destructor                                      */
00346 /*-------------------------------------------------*/
00347 DCCTBDataParser::~DCCTBDataParser(){
00348   
00349   // delete DCCTBEvents if any...
00350   std::vector<DCCTBEventBlock *>::iterator it;
00351   for(it=dccEvents_.begin();it!=dccEvents_.end();it++){delete *it;}
00352   dccEvents_.clear();
00353     
00354   delete mapper_;
00355 }