eventStreamDecoder.cxx

00001 #include <sys/mman.h>
00002 #include <sys/types.h>
00003 #include <sys/stat.h>
00004 #include <fcntl.h>
00005 #include <unistd.h>
00006 
00007 #include <stdio.h>
00008 
00009 #include <ipc/core.h>
00010 #include "cmdl/cmdargs.h"
00011 
00012 #include <iostream>
00013 #include <vector>
00014 #include <string>
00015 #include <utility>
00016 
00017 #include <boost/shared_ptr.hpp>
00018 
00019 // Unfortunately this is necessary for UINT16 etc
00020 #include "CommonWithDsp/processor.h"
00021 
00022 #ifdef USE_CONFIG_FOR_EVENT_DECODER
00023 #include "sctConf/configRegistry.h"
00024 #include "sctConf/configuration.h"
00025 #include "config/Configuration.h"
00026 #endif
00027 
00028 #ifdef USE_CONFIG_FOR_EVENT_DECODER
00029 using namespace SctConfiguration;
00030 
00031 boost::shared_ptr<SctConfiguration::Configuration> config;
00032 #endif
00033 
00034 using namespace std;
00035 
00036 namespace {
00037   void decodeEventWord(UINT16 currWord, int errorType, bool &linkCondensed, 
00038                        string &type, vector<pair<string, int> > &arguments, vector<string> &errors);
00039 
00040   vector<string> decodeEventFlags(UINT32 flags);
00041 
00042   bool findNextEvent(UINT32* &start, UINT32* &finish, UINT32 *end, UINT32 startWord);
00043 
00044   void decodeEvent(UINT32 *buffer, int length);
00045 }
00046 
00047 inline std::string str(const char * word)
00048 {
00049   return word ? word : "";
00050 } 
00051 
00052 int main(int argc, char **argv) {
00053 
00054   // Lets make eventStreamDecoder have some command line arguments. BD
00055 #ifdef USE_CONFIG_FOR_EVENT_DECODER
00056   CmdArgBool use_config ('c',"use_config","Should we use a config to look up modules from links?",CmdArg::isOPT);
00057 #endif
00058   CmdArgStr input_file ("input_file","Name of input_file to read ROD fragment data from");
00059   
00060   CmdLine cmd(*argv,
00061 #ifdef USE_CONFIG_FOR_EVENT_DECODER
00062           &use_config,
00063 #endif
00064           &input_file,NULL);
00065   cmd.description("An event stream decoder.");
00066   
00067   CmdArgvIter  argvIter(--argc,++argv);
00068   if (cmd.parse(argvIter)) 
00069     {
00070       std::cerr << "ERROR [eventStreamDecoder] Error parsing command line." << std::endl ;
00071       return EXIT_FAILURE;
00072     }
00073 
00074 #ifdef USE_CONFIG_FOR_EVENT_DECODER
00075   // If the user does want to look up modules from links, then start a config server. BD.
00076   unsigned convert = use_config.flags();
00077   if ( convert & CmdArg::GIVEN ) {
00078     // If the user has not provided a configuration file, use the standard one. 
00079     unsigned configflags = configuration.flags();
00080     if ((!(configflags & CmdArg::GIVEN) && (!(configflags & CmdArg::VALGIVEN)))) {
00081       cout << "*** No configuration file string given on the command line" << endl;
00082       cout << "*** Using " << std::getenv("SCTDAQ_ROD_CONFIGURATION_PATH") << endl;
00083       configuration=std::getenv("SCTDAQ_ROD_CONFIGURATION_PATH");
00084     }
00085     
00086     IPCCore::init(argc, argv);
00087     {
00088       std::string backendName = "xml";
00089       SctConfiguration::FactoryManager::instance().loadPlugin(backendName); 
00090       // These couts get printed later, but oh well. BD. 
00091       cout<< "The configuration service gets initialized from the default file" << endl;
00092       SctConfiguration::Factory &f = SctConfiguration::FactoryManager::instance().getFactory(backendName);
00093       cout<< "Now the configuration service gets reset from the default/user-defined file" << endl;
00094       config.reset(f.fromFile(str(configuration)));
00095     }
00096   }
00097 #endif
00098 
00099   struct stat statStruct;
00100   int st = stat(input_file, &statStruct);
00101 
00102   if(st!=0) {
00103     perror("Stat failed\n");
00104     return 1;
00105   }
00106 
00107   int length = statStruct.st_size;
00108 
00109   printf("Length: %d\n", length);
00110 
00111   int fd = open(input_file, O_RDONLY);
00112 
00113   if(fd == -1) {
00114     perror("File open failed\n");
00115     return 1;
00116   }
00117 
00118   UINT32 *buffer = (UINT32 *)mmap(0, length, PROT_READ, MAP_PRIVATE, fd, 0);
00119   UINT32 *endBuffer = &buffer[length/4];
00120 
00121   UINT32 *begin = buffer;
00122   UINT32 *end = buffer;
00123   bool found = findNextEvent(begin, end, endBuffer, 0xee1234ee);
00124 
00125   while(found) {
00126     printf("Event from %d to %d\n", begin-buffer, end-buffer);
00127 
00128     decodeEvent(begin, end-1-begin);
00129 
00130     //    begin = end;
00131     found = findNextEvent(begin, end, endBuffer, 0xee1234ee);
00132   }
00133 }
00134 
00135 namespace {
00136 
00137   
00138 bool findNextEvent(UINT32* &start, UINT32* &finish, UINT32 *end, UINT32 startWord) {
00139   start ++;
00140   if(start >= end) return false;
00141 
00142   while(*start != startWord) {
00143     start++;
00144     if(start >= end) return false;
00145   }
00146 
00147   finish = start+1;
00148 
00149   while(!( ((*finish & 0x00ffff00) == 0x00123400) || ((*finish & 0xffff0000) == 0x12340000))) {
00150     // Last one, return length
00151     if(finish >= end) break;
00152     finish++;
00153   }
00154   return true;
00155 }
00156 
00157 inline UINT32 eventWord(const UINT32 * const buffer, const int index, const int length) {
00158   if (index > length) {
00159     cout << "Attempt to read from the end of the buffer " << dec << index << " " << length << hex << endl;
00160     return 0;
00161   } else {
00162     return buffer[index-1];
00163   }
00164 }
00165 
00166 void decodeEvent(UINT32 *frameBuffer, int length) {
00167   if(frameBuffer[0] == 0xee1234ee) {
00168     cout << "Valid header\n";
00169   } else {
00170     cout << "Bad check 0x" << hex << frameBuffer[0] << dec << endl;
00171   }
00172 
00173   UINT32 headerLength = 9;     // Including bof
00174   UINT32 trailerLength = 5;    // Excluding eof
00175 
00176   if(frameBuffer[1] != headerLength) {
00177     cout << "Unknown header length (" << frameBuffer[1] << ")\n";
00178   } 
00179 
00180   cout << "New formatter version:\n";
00181   cout << "Version: 0x" << hex << eventWord(frameBuffer, 3, length) << dec
00182        << " ID: " << eventWord(frameBuffer, 4, length)
00183        << " Run number = " << eventWord(frameBuffer, 5, length) << endl;
00184   cout << "L1ID = 0x" << hex << eventWord(frameBuffer, 6, length) << dec 
00185        << " BCID = 0x" << hex << eventWord(frameBuffer, 7, length) << dec 
00186        << " TType = " << eventWord(frameBuffer, 8, length) 
00187        << " det type = " << eventWord(frameBuffer, 9, length) << endl;
00188   
00189   // The below assumes the old definition of headerLength (ie including 0xbof)
00190   headerLength=10;
00191   
00192   //   int eofAt = findEOF(frameBuffer, index);
00193   
00194   //   if(eofAt != -1) {
00195   //     cout << "Found end of frame!\n";
00196   //   } else {
00197   //     cout << "EOF not found\n";
00198   //     return;
00199   //   }
00200   
00201   // 2 is to correct for the bof and eof that aren't in the s-link format
00202   int eventLength = length - headerLength - trailerLength + 2;
00203   
00204   UINT32 rawOffset = headerLength;
00205   
00206   // Something different to the first word
00207   UINT16 lastWord = 1 + ((eventWord(frameBuffer, rawOffset, length) & 0xffff0000) >> 16);
00208   UINT32 repeats = 0;
00209   
00210   bool linkCondensed = true;
00211   
00212   for(int i=0; i<eventLength * 2; i++) {
00213     UINT16 currWord;
00214     {
00215       UINT32 rawWord = eventWord(frameBuffer, rawOffset + i/2, length);
00216       if(i&1) {
00217         currWord = rawWord & 0x00ffff;
00218       } else {
00219         currWord = (rawWord & 0xffff0000) >> 16;
00220       }
00221     }
00222 
00223     if(currWord == lastWord) {
00224       repeats ++;
00225       continue;
00226     } else if(repeats) {
00227       cout << "        Repeated " << repeats << " times\n";
00228       repeats = 0;
00229     }
00230 
00231     lastWord = currWord;
00232 
00233     cout.width(4);
00234     cout.fill('0');
00235     cout << hex << currWord << dec;
00236     cout.fill(' ');
00237 
00238     string type;
00239     vector<pair<string, int> > arguments;
00240     vector<string> errors;
00241 
00242     decodeEventWord(currWord, 0, linkCondensed, 
00243                     type, arguments, errors);
00244 
00245     cout << " " << type << " ";
00246     for(vector<pair<string, int> > :: const_iterator iter = arguments.begin();
00247         iter != arguments.end();
00248         iter ++) {
00249       cout << "  " << iter->first << ": " << iter->second;
00250     }
00251 
00252     if(errors.size() > 0) {
00253       cout << "  ERRORS: ";
00254     }
00255     for(vector<string> :: const_iterator iter = errors.begin();
00256         iter != errors.end();
00257         iter ++) {
00258       cout << " " << *iter;
00259     }
00260     cout << endl;
00261 
00262   }
00263 
00264   if(repeats) {
00265     cout << "        Repeated " << repeats << " times\n";
00266     repeats = 0;
00267   }
00268 
00269   cout << "Error count = 0x" << hex << eventWord(frameBuffer, length-trailerLength + 2, length) << dec << endl;
00270   cout << "Error flags = 0x" << hex << eventWord(frameBuffer, length-trailerLength + 3, length) << dec << endl;
00271 
00272   int flags = eventWord(frameBuffer, length-trailerLength + 3, length);
00273   vector<string> flagStrings = decodeEventFlags(flags);
00274   for(vector<string>::const_iterator iter = flagStrings.begin();
00275       iter != flagStrings.end();
00276       iter++) {
00277     cout << *iter << " ";
00278   }
00279 
00280   if(flagStrings.size() > 0) 
00281     cout << endl;
00282 
00283   cout << "nData = " << eventWord(frameBuffer, length-trailerLength + 5, length) 
00284        << " words found = " << (length - (headerLength + trailerLength) + 2) << endl;
00285 }
00286 
00287 void decodeEventWord(UINT16 currWord, int errorType, bool &linkCondensed, 
00288                      string &type, vector<pair<string, int> > &arguments, vector<string> &errors) {
00289   type = "UNKNOWN";
00290   arguments.clear();
00291   errors.clear();
00292 
00293   switch((currWord & 0xe000) >> 13) {
00294   case 0:
00295     {
00296       if(currWord & 0x1f80) 
00297         type = "INVALID";
00298       else {
00299         // Flagged error
00300         type = "Flagged error";
00301         errors.push_back("FLAGGED");
00302         arguments.push_back(make_pair("chip", (currWord & 0x78) >> 3));
00303         arguments.push_back(make_pair("value", currWord & 0x7));
00304       }
00305     }
00306     break;
00307   case 1:
00308     {
00309       // Header
00310       type = "Header";
00311       if(errorType) {
00312         // No indication of whether its condensed...??
00313         arguments.push_back(make_pair("L1", ((currWord & 0x0f00) >> 8)));
00314         arguments.push_back(make_pair("BCID", ((currWord & 0xff))));
00315         if(currWord & 0x1000) {
00316           errors.push_back("Preamble err");
00317         }
00318       } else {
00319     int link = (currWord & 0x7f);
00320         arguments.push_back(make_pair("Link", link));
00321 
00322     // Do this only if there is a configuration service that has been started already... BD
00323     // Look up MUR and module number from ROD and Link number and print it. 
00324 #ifdef USE_CONFIG_FOR_EVENT_DECODER
00325     if (config.get()) try {
00326       unsigned int mur, module, channel;
00327       unsigned int order = (link%128)/16;
00328       unsigned side = link%2;
00329       channel = (order*6) + (link%12)/2;
00330       
00331       config->translateFromROD(0,0,link/128, channel, mur, module); 
00332 #warning 'above line might still be BROKEN!  needs to be TESTED!!! :( BD'
00333       arguments.push_back(make_pair("MUR", mur));
00334       arguments.push_back(make_pair("Module",module));
00335       arguments.push_back(make_pair("Side",side));
00336     } catch ( std::exception& E ) {
00337       cout << " Caught exception in config lookup " << E.what() << endl;
00338     }   
00339 #endif
00340 
00341         if(currWord & 0x100) {
00342           arguments.push_back(make_pair("Condensed mode", 1));
00343           linkCondensed = true;
00344         } else {
00345           linkCondensed = false;
00346         }
00347         if(currWord & 0x200) 
00348           errors.push_back("BC err");
00349         if(currWord & 0x400)
00350           errors.push_back("L1 err");
00351         if(currWord & 0x800)
00352           errors.push_back("Time out err");
00353         if(currWord & 0x1000)
00354           errors.push_back("Preamble err");
00355       }
00356     }
00357     break;
00358   case 2:
00359     {
00360       if(currWord & 0x3ff) 
00361         type = "INVALID";
00362       else {
00363         // Trailer
00364         type = "Trailer";
00365         if(currWord & 0x400)
00366           errors.push_back("Data overflow err");
00367         if(currWord & 0x800)
00368           errors.push_back("H/T limit err");
00369         if(currWord & 0x1000)
00370           errors.push_back("Trailer bit err");
00371       }
00372     }
00373     break;
00374   case 3:
00375     {
00376       if(currWord & 0x300) 
00377         type = "INVALID";
00378       else {
00379         // Raw data
00380         type = "Raw";
00381         arguments.push_back(make_pair("bits", ((currWord & 0x1c00) >> 10) + 1));
00382         arguments.push_back(make_pair("value", (currWord & 0xff)));
00383       }
00384     }
00385     break;
00386   default:
00387     // Everything else (hits)
00388     {
00389       if((currWord & 0x2) == 0) {
00390         // Check if it should be condensed
00391         if(linkCondensed || errorType) {
00392           arguments.push_back(make_pair("Chip", ((currWord & 0x7800) >> 11)));
00393           arguments.push_back(make_pair("Channel", ((currWord & 0x7f0) >> 4)));
00394           if(currWord & 1) {
00395             type = "Condensed double hit";
00396             if(currWord & 0x4) errors.push_back("Error in hit1");
00397             if(currWord & 0x8) errors.push_back("Error in hit2");
00398           } else {
00399             type = "Condensed hit";
00400             if(currWord & 0x4) errors.push_back("Error in hit");
00401           }
00402         }
00403       }
00404 
00405       // Only check if expanded is a posibility
00406       if(!linkCondensed || errorType) {
00407         if((currWord & 0x8) == 0) {
00408           type = "1st hit clust exp";
00409           arguments.push_back(make_pair("Chip", ((currWord & 0x7800) >> 11)));
00410           arguments.push_back(make_pair("Channel", ((currWord & 0x7f0) >> 4)));
00411           arguments.push_back(make_pair("hits", currWord & 0x7));
00412         } else {
00413           if((currWord & 0x7f00) == 0) {
00414             type = "Clust exp";
00415             arguments.push_back(make_pair("hits", currWord & 0x7));
00416             if(currWord & 0x80) {
00417               arguments.push_back(make_pair("hits2", (currWord & 0x70) >> 4));
00418             }
00419           }
00420         }
00421       }
00422     }
00423   }
00424 }
00425 
00426 vector<string> decodeEventFlags(UINT32 flags) {
00427   vector<string> result;
00428 
00429   if(flags & 0x1) result.push_back("HEADER");
00430   if(flags & 0x2) result.push_back("TRAILER");
00431   if(flags & 0x4) result.push_back("FLAGGED");
00432   if(flags & 0x8) result.push_back("\"HIT PATTERN\"");
00433   if(flags & 0x10) result.push_back("SYNC");
00434   if(flags & 0x20) result.push_back("L1ID");
00435   if(flags & 0x40) result.push_back("BCID");
00436   if(flags & 0x80) result.push_back("TIMEOUT");
00437   if(flags & 0x100) result.push_back("\"ALMOST FULL\"");
00438   if(flags & 0x200) result.push_back("OVERFLOW");
00439   if(flags & 0x400) result.push_back("\"CHIP SEQ\"");
00440   if(flags & 0x800) result.push_back("\"BAD CHIP\"");
00441 
00442   return result;
00443 }
00444 } // Close null namespace

Generated on Mon Feb 6 14:01:19 2006 for SCT DAQ/DCS Software - C++ by  doxygen 1.4.6