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