FullBypassAlgorithm.cpp

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     // -2=nodata, -1=not_analysed, 0=fail, 1=pass
00053     short module_status[result->getNScans()];
00054 
00055     int direct_token[result->getNScans()][nChipModule];
00056     int bypass_token[result->getNScans()][nChipModule];
00057 
00058     // Algorithm by Peter Phillips & Lars Eklund.
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 // if (debug) cout << "content of bin "<< iconfig << " = " << content << endl;
00084             
00085             if (content > 0.90 && 
00086             content < 1.03 ) {      // CORRECT behaviour
00087             chip_status[iconfig][ichip]=1;
00088             } else if (content <= 0.90 ) { // chip dead
00089             chip_status[iconfig][ichip]=0;
00090             } else {
00091             chip_status[iconfig][ichip]=2;           // undefined status
00092             } // end of if
00093             
00094         } // loop over confs
00095         
00096         } //loop over configs
00097 
00098         //
00099         // Now attempt to find the sum of 2^ichip for each link.
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 //          if(debug) cout << "chip_status" << the_chip << "="
00115 //                     << chip_status[iconfig][the_chip]<<endl;
00116             if (chip_status[iconfig][the_chip] == 0){
00117                 // dead - do nothing
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; // BAD!
00122                 break;
00123             }
00124             }
00125 //          if (debug) cout << "conf_sum[" << ilink << "]= " << conf_sum[ilink] <<endl;
00126         }
00127         
00128         // check matches predicted pattern.
00129         if (iconfig<20){ // reading-out links in parallel
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;   // reading out through link iconfig%2
00145             } else {  
00146             conf_status[iconfig][iconfig%2] = 0;            
00147             }
00148             conf_status[iconfig][(iconfig+1)%2] = -1;  // other link no data
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;   // reading out through link iconfig%2
00156             } else {  
00157             conf_status[iconfig][iconfig%2] = 0;            
00158             }
00159             conf_status[iconfig][(iconfig+1)%2] = -1;  // other link no data            
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 //          cout << "conf_status: iconfig=" <<iconfig
00171 //               << ", ilink="<<ilink<<", value = " << conf_status[iconfig][ilink] <<endl;
00172             }
00173         }
00174 #endif
00175 
00176 
00177         } // loop over configs
00178         
00179         if (debug) cout << "\n\n------------------> Checking chip status" << endl;
00180 
00181         int chip_accessible[nChipModule];
00182         //determine if a chip is acessible in the read-out chain.
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         // loop over token/data links to determine if they are working/accessible
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){ //token link accessible?
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; // not-tested
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{        // Chip not accessible, but do we really test that
00247             // configuration?
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; // Not accessible
00282                 }else{
00283                 direct_token[index][the_chip] = -2; // Not tested
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             } // end of switch ichip
00292             } // end of if chip_accessible
00293         } // loop over chips
00294         } // loop over links
00295     
00296         if (debug) cout << "\n\n-------------------------> Check if passed" << endl; 
00297         // Finally , has the module passed?
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     }// loop over vdd
00313 
00314     if (debug) cout << "\n\n---------------> looping over vdd" << endl;
00315 
00316     // Check overall status of chips - do they work at any bias?
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 // not tested:
00325         case -2 :
00326             cr.vdd_direct=0; 
00327             cr.status_direct=-2; 
00328             keep_going_with_chip=false;
00329             break;
00330 
00331 // working at this voltage:
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 // failure is true malfunction:
00344         case  0 : 
00345             cr.status_direct=0; 
00346             keep_going_with_chip=false;
00347             break;
00348 
00349 // not accessible:
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         } // loop over bias
00361 
00362         // check at max voltage.
00363         if (direct_token[0][ichip]==0) {
00364         cr.status_direct=-3;
00365         result->getDefects().addDefect(Defect(StandardDefects::TOKEN, ModuleElement::Chip(ichip)));
00366         }
00367     } // loop over chips
00368 
00369     // NOW check the bypass token
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         } // loop over scans
00403         // check at max voltage.
00404         if (bypass_token[0][ichip]==0) {
00405         cr.status_bypass=-3;
00406         result->getDefects().addDefect(Defect(StandardDefects::RTOKEN, ModuleElement::Chip(ichip)));
00407         }
00408     } // loop over chips
00409     
00410     if (debug) cout << "\n\n---------------------> nearly done" << endl;
00411 
00412     // find the nominal voltage.
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     /* look-up table used for speed. Equivalent algorithm is :
00455        unsigned conf[MAX_CONF];
00456        int confno = -1;
00457        
00458        for(int i=0;i<MAX_CONF;i++){
00459        conf[i] = 0;
00460        }
00461        
00462        for(int ichip=1;ichip<=8;ichip++){
00463        if(ichip==1){
00464        conf[0] = 0x1;
00465        } else if(ichip==2){
00466        conf[1] = 0x3;
00467        } else{
00468        for(int i=0;i<Fib(ichip-2);i++){
00469        conf[(int)sumFib(ichip-1)+i] = conf[(int)sumFib(ichip-3)+i] + (0x1 << (ichip-1));
00470        }
00471        for(int i=0;i<Fib(ichip-1);i++){
00472        conf[(int)sumFib(ichip-1)+(int)Fib(ichip-2)+i] = conf[(int)sumFib(ichip-2)+i] + (0x1 << (ichip-1));
00473        }
00474        }
00475        }
00476     */
00477     }
00478 
00479     unsigned FullBypassAlgorithm::sumFib(const unsigned int n) {
00480     // Return the sum of all Fibonacci numbers up to n
00481     // new version by PWP 01.11.01
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 } // end of namespace SctAnalysis

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