BlockReads.cxx

00001 #define USELIBRARY
00002 
00003 #include <iostream>
00004 #include <vector>
00005 
00006 #include <boost/bind.hpp>
00007 #include <boost/thread.hpp>
00008 #include <boost/timer.hpp>
00009 
00010 #include "../TApi.h"
00011 
00012 //AJB #include "memoryPartitions.h"
00013 
00014 
00029 // Get intel processor instruction counter!
00030 static __inline__ unsigned long long int rdtsc()
00031 {
00032   unsigned long long int x;
00033   __asm__ volatile (".byte 0x0f, 0x31" : "=A" (x));
00034   return x;
00035 }
00036 
00037 double getCpuMhz() {
00038   FILE *cpuinfo = fopen("/proc/cpuinfo", "r");
00039 
00040   unsigned int length = 200;
00041   char *line = (char*)malloc(length); // Use malloc because getline may realloc
00042 
00043   // Double accurately stores 6 dps
00044   double mhz;
00045   while(!feof(cpuinfo)) {
00046     getline(&line, &length, cpuinfo);
00047 
00048     if(strncmp("cpu MHz", line, 7) == 0) {
00049       char *colon = strchr(line, ':');
00050       sscanf(colon+1, "%lf", &mhz);
00051       printf("Found MHz %lf\n", mhz);
00052     }
00053   }
00054 
00055   fclose(cpuinfo);
00056 
00057   return mhz;
00058 }
00059 
00060 using namespace std;
00061 
00062 std::list<boost::thread *> threads;
00063 
00064 struct { 
00065   unsigned long *blockData;
00066   int repetitions;
00067   unsigned int length;
00068   int multiRod;
00069   long address;
00070   int dsp;
00071   int usePrimitive;
00072   int useThreads;
00073   int threadStart;
00074   int checkData;
00075 
00076   int doneCount;
00077 
00078   std::list<SctApi::RodLabel> rodList;
00079 } globalConf;
00080 
00081 void usage();
00082 void parseArgs(int argc, char **argv);
00083 void buildData();
00084 void setupThreads(TApi &tapi);
00085 void startThreads();
00086 void writeData(TApi &tapi);
00087 bool readDataNoThread(TApi &tapi);
00088 bool readData(TApi &tapi, const SctApi::RodLabel &rl);
00089 bool checkResponse(unsigned long *body, unsigned long length);
00090 
00091 void threadLoop(TApi &tapi, const SctApi::RodLabel &rl);
00092 
00093 int main (int argc, char **argv) {
00094   TApi tapi;
00095 
00096   bool cont = true;
00097 
00098   globalConf.repetitions = 1;
00099   globalConf.length = 2000;
00100   globalConf.multiRod = 0;
00101   globalConf.address = 0xb0000000;
00102   globalConf.dsp = -1;
00103   globalConf.usePrimitive = 0;
00104   globalConf.useThreads = 0;
00105   globalConf.threadStart = 0;
00106   globalConf.checkData = 0;
00107 
00108   globalConf.doneCount = 0;
00109 
00110   parseArgs(argc, argv);
00111 
00112   buildData();
00113 
00114   tapi.initialiseAll(0);
00115 
00116 //   tapi.setDebugOption("print_in_prim");
00117 //   tapi.setDebugOption("print_out_prim");
00118 //   tapi.setDebugOption("print_raw");
00119 
00120   cout << "Config:\n";
00121   cout << " no.  repetitions: " << globalConf.repetitions << "\n";
00122   cout << " data length: " << globalConf.length << endl;
00123   cout << " use all RODs: " << (globalConf.multiRod?"yes":"no") << endl;
00124   cout << " data address: 0x" << hex << globalConf.address << dec << endl;
00125   cout << " dsp to use: " << globalConf.dsp << endl;
00126   cout << " use primitive: " << (globalConf.usePrimitive?"yes":"no") << endl;
00127   cout << " use threads: " << (globalConf.useThreads?"yes":"no") << endl;
00128   cout << " check valid: " << (globalConf.checkData?"yes":"no") << endl;
00129 
00130   if(globalConf.multiRod) {
00131     globalConf.rodList = tapi.listRods();
00132   } else {
00133     SctApi::RodLabel rl(0, 0, 0);
00134     globalConf.rodList.push_back(rl);
00135   }
00136 
00137   cout << "Writing block data to RODs...\n";
00138 
00139   writeData(tapi);
00140 
00141   if(globalConf.useThreads) {
00142     setupThreads(tapi);
00143   }
00144 
00145   cout << "Testing block reads on " << globalConf.rodList.size() << " RODs\n";
00146 
00147   double mhz = getCpuMhz();
00148   double startTime = rdtsc() / (mhz * 1e6); // timer t;
00149   double finishTime = startTime - 10;
00150 
00151   try {
00152     if(globalConf.useThreads) {
00153       startThreads();
00154       for(std::list<boost::thread *>::iterator iter = threads.begin();
00155           iter != threads.end();
00156           iter++) {
00157         (*iter)->join();
00158       }
00159     } else {
00160       for(int rep=0; rep<globalConf.repetitions && cont == true; rep++) {
00161         try {
00162           if(cont) {
00163             if(!readDataNoThread(tapi)) {
00164               //             cout << "Read or check failed on rep: " << rep << endl;
00165             }
00166           }
00167         } catch(...) {
00168           cout << "Exception sending primitive\n";
00169           cont = false;
00170         }
00171       }
00172     }
00173 
00174     finishTime = rdtsc() / (mhz * 1e6); // t.elapsed();
00175 
00176     cout << "Complete\n";
00177   } catch(...) { // SctPixelRod::BaseException &b) {
00178     cout << "Got exception!" << endl;
00179   }
00180 
00181   if(globalConf.repetitions > 1) {
00182     cout << "Did " << (globalConf.doneCount/globalConf.rodList.size()) << " successful repetitions\n";
00183   }
00184 
00185   int words = globalConf.length * (globalConf.doneCount/globalConf.rodList.size());
00186   int totalWords = globalConf.length * globalConf.doneCount;
00187   cout << " " << words << " words in " << (finishTime - startTime) << " seconds\n";
00188   cout << " ROD bandwidth: " << ((words/(finishTime - startTime))/1000) << " kWords/sec\n";
00189   cout << " VME bandwidth: " << ((totalWords/(finishTime - startTime))/1000) << " kWords/sec\n";
00190 
00191   delete [] globalConf.blockData;
00192 
00193   tapi.shutdownAll();
00194 }
00195 
00196 bool checkResponse(unsigned long *outBody, unsigned long outLength) {
00197   bool correct = true;
00198   if(globalConf.checkData) {
00199     if(outLength != globalConf.length) {
00200 //     cout << "Length check failed\n";
00201       correct = false;
00202     } else {
00203       for(unsigned int i=0; i<globalConf.length; i++) {
00204         if(outBody[i] != globalConf.blockData[i]) {
00205           correct = false;
00206 //         cout << "Check failed at word " << i << "\n";
00207 //         cout << "\t0x" << hex << outBody[i] << " != 0x" << globalConf.blockData[i] << dec << "\n";
00208           break;
00209         }
00210       }
00211     }
00212   }
00213 
00214   if(correct) cerr << ".";
00215 
00216   return correct;
00217 }
00218 
00219 void buildData() {
00220   // Create the data
00221   globalConf.blockData = new unsigned long[globalConf.length];
00222 
00223   if(globalConf.length < 3) {
00224     if(globalConf.length > 0) globalConf.blockData[0] = 0xDEADF00D;
00225     if(globalConf.length > 1) globalConf.blockData[1] = 0x0;
00226   } else {
00227     for (unsigned int i=0; i<globalConf.length; i++) {
00228       globalConf.blockData[i] = 0xBEAD0000 + i;
00229     }
00230   }
00231 }
00232 
00233 void writeData(TApi &tapi) {
00234   if(globalConf.multiRod) {
00235     for(list<SctApi::RodLabel>::const_iterator ri = globalConf.rodList.begin(); 
00236         ri != globalConf.rodList.end(); 
00237         ri++) {
00238       tapi.dspBlockWrite(ri->rod, 
00239                          globalConf.blockData, globalConf.address, globalConf.length, 
00240                          globalConf.dsp, globalConf.usePrimitive);
00241     }
00242   } else {
00243     tapi.dspBlockWrite(0,
00244                        globalConf.blockData, globalConf.address, globalConf.length, 
00245                        globalConf.dsp, globalConf.usePrimitive);
00246   }
00247 }
00248 
00249 bool readDataNoThread(TApi &tapi) {
00250   bool success = true;
00251 
00252   if(globalConf.multiRod) {
00253     for(list<SctApi::RodLabel>::const_iterator ri = globalConf.rodList.begin(); 
00254         ri != globalConf.rodList.end(); 
00255         ri++) {
00256 
00257       readData(tapi, *ri);
00258     }
00259   } else {
00260     static SctApi::RodLabel rl(0, 0, 0);
00261     readData(tapi, rl);
00262   }
00263 
00264   return success;
00265 }
00266 
00267 bool readData(TApi &tapi, const SctApi::RodLabel &rl) {
00268   bool success = true;
00269 
00270   unsigned long returnLength;
00271   unsigned long *result = tapi.dspBlockRead(rl.rod, 
00272                                             globalConf.address, globalConf.length, globalConf.dsp,
00273                                             &returnLength, globalConf.usePrimitive);
00274 //       tapi.dspBlockDump(rl->partition, rl->crate, rl->rod, 
00275 //                                                 globalConf.address, globalConf.length, globalConf.dsp);
00276 
00277 //     tapi.dspBlockDumpFile(0, 0, 0, 
00278 //                           globalConf.address, globalConf.length, globalConf.dsp, "blockDump.bin");
00279 
00280   
00281   if(result) {
00282     if(!checkResponse(result, returnLength)) {
00283       //          cout << "Check failed repetition " << rep << "\n";
00284       success = false;
00285     } else {
00286       globalConf.doneCount ++;
00287     }
00288     delete [] result;
00289   } else {
00290     cout << "Response was null\n";
00291   }
00292 
00293   return success;
00294 }
00295 
00296 void parseArgs(int argc, char **argv) {
00297   if(argc > 1) {
00298     for(int i=1; i<argc; i++) {
00299       if(argv[i][0] == '-') {
00300         switch(argv[i][1]) {
00301         case 'r':
00302           globalConf.repetitions = atoi(&argv[i][2]);
00303           break;
00304         case 'l':
00305           globalConf.length = atoi(&argv[i][2]);
00306           break;
00307         case 'd':
00308           globalConf.dsp = atoi(&argv[i][2]);
00309           break;
00310         case 'm':
00311           globalConf.multiRod = 1;
00312           break;
00313         case 'p':
00314           globalConf.usePrimitive = 1;
00315           break;
00316         case 't':
00317           globalConf.useThreads = 1;
00318           break;
00319         case 'c':
00320           globalConf.checkData = 1;
00321           break;
00322         case 'h':
00323           usage();
00324           exit(1);
00325           break;
00326         }
00327       }
00328     }
00329   }
00330 }
00331 
00332 void usage() {
00333   cout << "BlockReads [opts]\n";
00334   cout << "\t-r# Repeat # times\n";
00335   cout << "\t-l# Use buffer with length #\n";
00336   cout << "\t-d# Use dsp number # (-1 for master)\n";
00337   //  cout << "\t-a# Read/write address #\n";
00338   cout << "\t-m  Use all RODs\n";
00339   cout << "\t-p  Use RW_SLAVE_PRIM instead of direct\n";
00340   cout << "\t-t  Use threads to do reads concurrently?\n";
00341   cout << "\t-c  Check the return data\n";
00342   cout << "\t-h  Show this help\n";
00343 }
00344 
00345 void setupThreads(TApi &tapi) {
00346   if(globalConf.multiRod) {
00347     for(list<SctApi::RodLabel>::const_iterator ri = globalConf.rodList.begin(); 
00348         ri != globalConf.rodList.end(); 
00349         ri++) {
00350       threads.push_back(new boost::thread(boost::bind(&threadLoop, boost::ref(tapi), *ri)));
00351     }
00352   } else {
00353     static SctApi::RodLabel rl(0, 0, 0);
00354     threads.push_back(new boost::thread(boost::bind(&threadLoop, boost::ref(tapi), rl)));
00355   }
00356 }
00357 
00358 void startThreads() {
00359   globalConf.threadStart = 1;
00360 }
00361 
00362 void threadLoop(TApi &tapi, const SctApi::RodLabel &rl) {
00363   volatile int &ts = globalConf.threadStart;
00364   while(ts == 0);
00365 
00366   cout << "Thread starting to read...\n";
00367 
00368   bool cont = true;
00369 
00370   for(int rep=0; rep<globalConf.repetitions && cont == true; rep++) {
00371     try {
00372       if(cont) {
00373         if(!readData(tapi, rl)) {
00374           //             cout << "Read or check failed on rep: " << rep << endl;
00375         }
00376       }
00377     } catch(...) {
00378       cout << "Exception sending primitive\n";
00379       cont = false;
00380     }
00381   }
00382 }

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