00001 #include "FullBypassAlgorithm.h"
00002 #include "AnalysisAlgorithmMap.h"
00003 #include "SctData/FullBypassTestResult.h"
00004 #include "SctData/ModuleDefect.h"
00005 #include "SctData/RawScanResult.h"
00006 #include "SctData/OccupancyProjector.h"
00007 #include "TH2.h"
00008
00009 using namespace std;
00010 using namespace boost;
00011 using namespace SctData;
00012 using namespace Sct;
00013
00014 namespace SctAnalysis {
00015
00016 bool FullBypassAlgorithm::inMap = AnalysisAlgorithmMap::instance().setAlgorithm("FullBypassTest", auto_ptr<AnalysisAlgorithm>(new FullBypassAlgorithm()));
00017
00018 shared_ptr<AnalysisAlgorithm> FullBypassAlgorithm::clone(const TestData& testData, const string& moduleName) const throw() {
00019 return shared_ptr<AnalysisAlgorithm>(new FullBypassAlgorithm(testData, moduleName));
00020 }
00021
00022 float FullBypassAlgorithm::s_vddNominal=4.0;
00023
00024 FullBypassAlgorithm::FullBypassAlgorithm() {
00025 }
00026
00027 void FullBypassAlgorithm::canAddRawScanResult(const string& name) throw(Sct::LogicError, Sct::IoError){
00028 bool debug=false;
00029
00030 shared_ptr<FullBypassTestResult> result = dynamic_pointer_cast<FullBypassTestResult> ( getTestResult() );
00031
00032 if (result.get()==0) {
00033 result = shared_ptr<FullBypassTestResult> (new FullBypassTestResult());
00034 setTestResult( result );
00035 initializeTestResult();
00036 if (debug) cout << "FullBypassTestResult created" << endl;
00037 }
00038
00039 addRaw(name);
00040
00041 if ( !result->hasAllRaws() ) return;
00042
00043 if (debug) cout << "FullBypassAlgorithm" << endl;
00044
00045 const unsigned nconfig=result->getRaw(0)->getPoints().getNPoints();
00046 result->setNConfig(nconfig);
00047
00048 short chip_status[nconfig][nChipModule];
00049
00050
00051 short module_status[result->getNScans()];
00052
00053 int direct_token[result->getNScans()][nChipModule];
00054 int bypass_token[result->getNScans()][nChipModule];
00055
00056
00057
00058 for (unsigned index=0; index<result->getNScans() ; ++index){
00059 shared_ptr<const RawScanResult> raw=result->getRaw(index);
00060
00061 if (debug) cout << "Looking at scan #" << index << endl;
00062
00063 if (!raw.get()) {
00064 ostringstream os;
00065 os << "FullBypassAlgorithm: unable to get scan at index " << index <<ends;
00066 throw IllegalStateError(os.str(), __FILE__, __LINE__);
00067 }
00068
00069 OccupancyProjector op(*raw);
00070
00071 short conf_status[nconfig][nLinkModule];
00072
00073 for (unsigned ichip=0; ichip<nChipModule; ++ichip){
00074
00075 auto_ptr<TH1> hist = op.getOccupancy("hist", Chip(ichip));
00076
00077 for (unsigned iconfig=0; iconfig<nconfig; ++iconfig){
00078
00079 double content = hist->GetBinContent(iconfig+1);
00080
00081
00082
00083 if (content > 0.90 &&
00084 content < 1.03 ) {
00085 chip_status[iconfig][ichip]=1;
00086 } else if (content <= 0.90 ) {
00087 chip_status[iconfig][ichip]=0;
00088 } else {
00089 chip_status[iconfig][ichip]=2;
00090 }
00091
00092 }
00093
00094 }
00095
00096
00097
00098
00099 #ifndef NDEBUG
00100 if (debug) cout << "finding 2^chip" << endl;
00101 #endif
00102
00103 for (unsigned iconfig=0; iconfig<nconfig; ++iconfig){
00104 int conf_sum[nLinkModule];
00105 for (short unsigned ilink=0; ilink<nLinkModule; ++ilink){
00106 conf_sum[ilink]=0;
00107 }
00108
00109 for (short unsigned ilink=0; ilink<nLinkModule; ++ilink){
00110 for (short unsigned ichip=0; ichip<nChipLink; ++ichip){
00111 unsigned the_chip = ichip+nChipLink*ilink;
00112
00113
00114 if (chip_status[iconfig][the_chip] == 0){
00115
00116 } else if (chip_status[iconfig][the_chip] == 1){
00117 conf_sum[ilink] += (1 << ichip);
00118 } else if (chip_status[iconfig][the_chip] == 2){
00119 conf_sum[ilink] = -1;
00120 break;
00121 }
00122 }
00123
00124 }
00125
00126
00127 if (iconfig<20){
00128
00129 for (short unsigned ilink=0; ilink<nLinkModule; ++ilink){
00130 if (conf_sum[ilink]==(int)getConf(iconfig)) {
00131 conf_status[iconfig][ilink] = 1;
00132 } else {
00133 conf_status[iconfig][ilink]=0;
00134 }
00135 }
00136
00137 } else if (iconfig<36){
00138
00139 if ( conf_sum[iconfig%2]==(int)getConf((iconfig-(20+iconfig%2) ) / 2 + 12 )
00140 && conf_sum[(iconfig+1)%2]==2) {
00141
00142 conf_status[iconfig][iconfig%2] = 1;
00143 } else {
00144 conf_status[iconfig][iconfig%2] = 0;
00145 }
00146 conf_status[iconfig][(iconfig+1)%2] = -1;
00147
00148 } else if (iconfig<62 ){
00149
00150 if ( conf_sum[iconfig%2]==(int)getConf((iconfig-(36+iconfig%2) ) / 2 + 7 )
00151 && conf_sum[(iconfig+1)%2]==1 ) {
00152 conf_status[iconfig][iconfig%2] = 1;
00153 } else {
00154 conf_status[iconfig][iconfig%2] = 0;
00155 }
00156 conf_status[iconfig][(iconfig+1)%2] = -1;
00157
00158 } else {
00159 ostringstream os;
00160 os << "FullBypassAlgorithm: iconfig out too big. max=61, val=" << iconfig <<ends;
00161 throw IllegalStateError(os.str(), __FILE__, __LINE__);
00162 }
00163
00164 #ifndef NDEBUG
00165 if (debug) {
00166 for (unsigned ilink=0; ilink<nLinkModule; ++ilink){
00167
00168
00169 }
00170 }
00171 #endif
00172
00173
00174 }
00175
00176 if (debug) cout << "\n\n------------------> Checking chip status" << endl;
00177
00178 int chip_accessible[nChipModule];
00179
00180 for (short unsigned ilink=0; ilink<nLinkModule; ++ilink){
00181 for (short unsigned ichip=0; ichip<nChipLink; ++ichip){
00182 short unsigned the_chip=ichip+nChipLink*ilink;
00183 chip_accessible[the_chip] = -1;
00184 for (int iconfig=(int)sumFib(ichip); iconfig<(int)sumFib(ichip+1); ++iconfig ){
00185 if (conf_status[iconfig][ilink]==1){
00186 chip_accessible[the_chip]=iconfig;
00187 }
00188 }
00189 }
00190 }
00191
00192 if (debug) cout << "\n\n--------------> finding token status" << endl;
00193
00194
00195
00196 for (short unsigned ilink=0; ilink<nLinkModule; ++ilink){
00197 for (short unsigned ichip=0; ichip<nChipLink; ++ichip){
00198 short unsigned the_chip=ichip+nChipLink*ilink;
00199 if (chip_accessible[the_chip] != -1){
00200 switch(ichip){
00201 case 4: {
00202 direct_token[index][the_chip] =
00203 conf_status[ getConfNo(getConf(chip_accessible[the_chip]) + (1 << (ichip+1))) ][ilink];
00204
00205
00206 unsigned test_config=36 + 2*(chip_accessible[the_chip] - 7) + ilink;
00207 if (test_config<nconfig){
00208 bypass_token[index][the_chip] =
00209 conf_status[test_config][ilink];
00210 }else{
00211 bypass_token[index][the_chip] = -2;
00212 }
00213 break;
00214 }
00215 case 5: {
00216 unsigned test_config;
00217 test_config=36 + 2*(chip_accessible[the_chip] - 7) + ilink;
00218
00219 if (test_config<nconfig) {
00220 direct_token[index][the_chip] =
00221 conf_status[test_config][ilink];
00222 } else {
00223 direct_token[index][the_chip] = -2;
00224 }
00225
00226 test_config = 20 + 2*(chip_accessible[the_chip] - 12);
00227 if (test_config<nconfig) {
00228 bypass_token[index][the_chip] =
00229 conf_status[test_config][ilink];
00230 } else {
00231 bypass_token[index][the_chip] = -2;
00232 }
00233 break;
00234 }
00235 default: {
00236 direct_token[index][the_chip] =
00237 conf_status[ getConfNo(getConf(chip_accessible[the_chip]) + (int)pow(2.,(ichip+1))) ][ilink];
00238 bypass_token[index][the_chip] =
00239 conf_status[ getConfNo(getConf(chip_accessible[the_chip]) + (int)pow(2.,(ichip+2))) ][ilink];
00240 break;
00241 }
00242 }
00243 } else{
00244
00245 if (debug) {
00246 cout << "\n\n -------------> CHIP " << ichip
00247 << " not accessikble;" << endl;
00248 }
00249 switch(ichip){
00250 case 4:
00251 if(nconfig>=20){
00252 direct_token[index][the_chip] = -1;
00253 }else{
00254 direct_token[index][the_chip] = -2;
00255 }
00256 if(nconfig>=(unsigned)(45+ilink)){
00257 bypass_token[index][the_chip] = -1;
00258 }else{
00259 bypass_token[index][the_chip] = -2;
00260 }
00261 break;
00262
00263 case 5:
00264 if(nconfig>=(unsigned)(61+ilink)){
00265 direct_token[index][the_chip] = -1;
00266 }else{
00267 direct_token[index][the_chip] = -2;
00268 }
00269 if(nconfig>=(unsigned)(35+ilink)){
00270 bypass_token[index][the_chip] = -1;
00271 }else{
00272 bypass_token[index][the_chip] = -2;
00273 }
00274 break;
00275
00276 default:
00277 if(sumFib(ichip+2)+ilink<=nconfig+1){
00278 direct_token[index][the_chip] = -1;
00279 }else{
00280 direct_token[index][the_chip] = -2;
00281 }
00282 if(sumFib(ichip+3)+ilink<=nconfig+1){
00283 bypass_token[index][the_chip] = -1;
00284 }else{
00285 bypass_token[index][the_chip] = -2;
00286 }
00287 break;
00288 }
00289 }
00290 }
00291 }
00292
00293 if (debug) cout << "\n\n-------------------------> Check if passed" << endl;
00294
00295 module_status[index]=1;
00296 for (unsigned ichip=0; ichip<nChipModule; ++ichip){
00297 if (direct_token[index][ichip] == -1 || bypass_token[index][ichip] == -1
00298 || direct_token[index][ichip] == 0 || bypass_token[index][ichip] == 0 ){
00299 if (debug) cout << "Problem with chip " << ichip
00300 << "\tD=" << direct_token[index][ichip]
00301 << "\tB=" << bypass_token[index][ichip] << endl;
00302 module_status[index] = 0;
00303 }
00304 }
00305 if (debug) {
00306 cout << ( (module_status[index]==1) ? "PASS" : "FAIL" )
00307 << "\n----------------------------------------\n" << endl;
00308 }
00309 }
00310
00311 if (debug) cout << "\n\n---------------> looping over vdd" << endl;
00312
00313
00314 for (unsigned ichip=0; ichip<nChipModule; ++ichip){
00315 SctData::FullBypassTestResult::ChipFBResult& cr = result->getChipResult(ichip);
00316
00317 bool keep_going_with_chip=true;
00318 for (unsigned index=0; index<result->getNScans() && keep_going_with_chip; ++index){
00319
00320 switch (direct_token[index][ichip]){
00321
00322 case -2 :
00323 cr.vdd_direct=0;
00324 cr.status_direct=-2;
00325 keep_going_with_chip=false;
00326 break;
00327
00328
00329 case +1 :
00330 #ifndef NDEBUG
00331 if (debug){
00332 cout << "Chip " << ichip << " working at vdd=";
00333 cout << result->getTestPointAt(index) << " index="<<index << endl;
00334 }
00335 #endif
00336 cr.vdd_direct=result->getTestPointAt(index);
00337 cr.status_direct=1;
00338 break;
00339
00340
00341 case 0 :
00342 cr.status_direct=0;
00343 keep_going_with_chip=false;
00344 break;
00345
00346
00347 case -1 :
00348 cr.status_direct=-1;
00349 keep_going_with_chip=false;
00350 break;
00351 default:
00352 cerr << __FILE__ << ":" << __LINE__
00353 << " ERROR direct_token["<<index<<"]["<<ichip
00354 << "] =" << direct_token[index][ichip] << endl;
00355 break;
00356 }
00357 }
00358
00359
00360 if (direct_token[0][ichip]==0) {
00361 cr.status_direct=-3;
00362 result->getDefects().addDefect(ModuleDefect::TOKEN,Chip(ichip));
00363 }
00364 }
00365
00366
00367 for (unsigned ichip=0; ichip<nChipModule; ++ichip){
00368 SctData::FullBypassTestResult::ChipFBResult& cr = result->getChipResult(ichip);
00369
00370 cr.status_bypass=-3;
00371 cr.vdd_bypass=10.;
00372
00373 bool keep_going_with_chip=true;
00374 for (unsigned index=0; index<result->getNScans() && keep_going_with_chip; ++index){
00375 switch (bypass_token[index][ichip]){
00376 case -2 :
00377 cr.vdd_bypass=0.;
00378 cr.status_bypass=-2;
00379 keep_going_with_chip=false;
00380 break;
00381 case 1:
00382 cr.vdd_bypass=result->getTestPointAt(index);
00383 cr.status_bypass=1;
00384 break;
00385 case 0:
00386 cr.status_bypass=0;
00387 keep_going_with_chip=false;
00388 break;
00389 case -1:
00390 cr.status_bypass=-1;
00391 keep_going_with_chip=false;
00392 break;
00393 default:
00394 cerr << __FILE__ << ":" << __LINE__
00395 << " ERROR bypass_token["<<index<<"]["<<ichip
00396 << "] =" << bypass_token[index][ichip] << endl;
00397 break;
00398 }
00399 }
00400
00401 if (bypass_token[0][ichip]==0) {
00402 cr.status_bypass=-3;
00403 result->getDefects().addDefect(ModuleDefect::RTOKEN,Chip(ichip));
00404 }
00405 }
00406
00407 if (debug) cout << "\n\n---------------------> nearly done" << endl;
00408
00409
00410 short i_vdd_nom;
00411 for (unsigned index=0; index<result->getNScans(); ++index){
00412 if ( fabs(result->getTestPointAt(index)-getVddNom()) < 0.05 ) {
00413 result->setVddNom(result->getTestPointAt(index)) ;
00414 i_vdd_nom=index;
00415 if (module_status[index]==1){
00416 result->setPassed(true);
00417 }
00418 }
00419 if (module_status[index]!=1) result->setProblem(true);
00420 }
00421 if (debug) cout << "Module pass = " << (result->getPassed() ? "TRUE" : "FALSE") << endl;
00422
00423 finish();
00424 }
00425
00426 unsigned FullBypassAlgorithm::getConfNo(const unsigned token){
00427 const unsigned MAX_CONF=60;
00428 for(unsigned i=0;i<MAX_CONF;i++){
00429 if(getConf(i)==token){
00430 return i;
00431 }
00432 }
00433 ostringstream os;
00434 os << "No configuration matches your token="<<token;
00435 throw IllegalStateError(os.str(),__FILE__,__LINE__);
00436 }
00437
00438
00439 unsigned FullBypassAlgorithm::getConf(const unsigned iconf) {
00440 const unsigned MAX_CONF=60;
00441 if (iconf<0 || iconf>= MAX_CONF) {
00442 throw Sct::OutOfRangeError<int> ("FullBypassAlgorithm::getConf",__FILE__, __LINE__, iconf, 0, MAX_CONF-1);
00443 }
00444 const unsigned conf[MAX_CONF]
00445 = { 1, 3, 5, 7, 11, 13, 15, 21, 23, 27,
00446 29, 31, 43, 45, 47, 53, 55, 59, 61, 63,
00447 85, 87, 91, 93, 95, 107, 109, 111, 117, 119,
00448 123, 125, 127, 171, 173, 175, 181, 183, 187, 189,
00449 191, 213, 215, 219, 221, 223, 235, 237, 239, 245,
00450 247, 251, 253, 255, 0, 0, 0, 0, 0, 0};
00451
00452 return conf[iconf];
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476 }
00477
00478 unsigned FullBypassAlgorithm::sumFib(const unsigned int n) {
00479
00480
00481 unsigned i = 1;
00482 unsigned m = 1;
00483 unsigned m1 = 1;
00484 unsigned m2 = 0;
00485 unsigned s = 1;
00486 if(n<1) return 0;
00487 while(i<n){
00488 m = m1 + m2;
00489 m2 = m1;
00490 m1 = m;
00491 s+=m;
00492 i++;
00493 }
00494 return s;
00495 }
00496
00497 }