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
00013
00014
00029
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);
00042
00043
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
00117
00118
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);
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
00165 }
00166 }
00167 } catch(...) {
00168 cout << "Exception sending primitive\n";
00169 cont = false;
00170 }
00171 }
00172 }
00173
00174 finishTime = rdtsc() / (mhz * 1e6);
00175
00176 cout << "Complete\n";
00177 } catch(...) {
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
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
00207
00208 break;
00209 }
00210 }
00211 }
00212 }
00213
00214 if(correct) cerr << ".";
00215
00216 return correct;
00217 }
00218
00219 void buildData() {
00220
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
00275
00276
00277
00278
00279
00280
00281 if(result) {
00282 if(!checkResponse(result, returnLength)) {
00283
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
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
00375 }
00376 }
00377 } catch(...) {
00378 cout << "Exception sending primitive\n";
00379 cont = false;
00380 }
00381 }
00382 }