Main Page   Modules   Namespace List   Class Hierarchy   Data Structures   File List   Namespace Members   Data Fields   Globals   Related Pages  

FullBypassAlgorithm.cpp

Go to the documentation of this file.
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     // -2=nodata, -1=not_analysed, 0=fail, 1=pass
00051     short module_status[result->getNScans()];
00052 
00053     int direct_token[result->getNScans()][nChipModule];
00054     int bypass_token[result->getNScans()][nChipModule];
00055 
00056     // Algorithm by Peter Phillips & Lars Eklund.
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 // if (debug) cout << "content of bin "<< iconfig << " = " << content << endl;
00082             
00083             if (content > 0.90 && 
00084             content < 1.03 ) {      // CORRECT behaviour
00085             chip_status[iconfig][ichip]=1;
00086             } else if (content <= 0.90 ) { // chip dead
00087             chip_status[iconfig][ichip]=0;
00088             } else {
00089             chip_status[iconfig][ichip]=2;           // undefined status
00090             } // end of if
00091             
00092         } // loop over confs
00093         
00094         } //loop over configs
00095 
00096         //
00097         // Now attempt to find the sum of 2^ichip for each link.
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 //          if(debug) cout << "chip_status" << the_chip << "="
00113 //                     << chip_status[iconfig][the_chip]<<endl;
00114             if (chip_status[iconfig][the_chip] == 0){
00115                 // dead - do nothing
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; // BAD!
00120                 break;
00121             }
00122             }
00123 //          if (debug) cout << "conf_sum[" << ilink << "]= " << conf_sum[ilink] <<endl;
00124         }
00125         
00126         // check matches predicted pattern.
00127         if (iconfig<20){ // reading-out links in parallel
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;   // reading out through link iconfig%2
00143             } else {  
00144             conf_status[iconfig][iconfig%2] = 0;            
00145             }
00146             conf_status[iconfig][(iconfig+1)%2] = -1;  // other link no data
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;   // reading out through link iconfig%2
00153             } else {  
00154             conf_status[iconfig][iconfig%2] = 0;            
00155             }
00156             conf_status[iconfig][(iconfig+1)%2] = -1;  // other link no data
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 //          cout << "conf_status: iconfig=" <<iconfig
00168 //               << ", ilink="<<ilink<<", value = " << conf_status[iconfig][ilink] <<endl;
00169             }
00170         }
00171 #endif
00172 
00173 
00174         } // loop over configs
00175         
00176         if (debug) cout << "\n\n------------------> Checking chip status" << endl;
00177 
00178         int chip_accessible[nChipModule];
00179         //determine if a chip is acessible in the read-out chain.
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         // loop over token/data links to determine if they are working/accessible
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){ //token link accessible?
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; // not-tested
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{        // Chip not accessible, but do we really test that
00244             // configuration?
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; // Not accessible
00279                 }else{
00280                 direct_token[index][the_chip] = -2; // Not tested
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             } // end of switch ichip
00289             } // end of if chip_accessible
00290         } // loop over chips
00291         } // loop over links
00292     
00293         if (debug) cout << "\n\n-------------------------> Check if passed" << endl; 
00294         // Finally , has the module passed?
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     }// loop over vdd
00310 
00311     if (debug) cout << "\n\n---------------> looping over vdd" << endl;
00312 
00313     // Check overall status of chips - do they work at any bias?
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 // not tested:
00322         case -2 :
00323             cr.vdd_direct=0; 
00324             cr.status_direct=-2; 
00325             keep_going_with_chip=false;
00326             break;
00327 
00328 // working at this voltage:
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 // failure is true malfunction:
00341         case  0 : 
00342             cr.status_direct=0; 
00343             keep_going_with_chip=false;
00344             break;
00345 
00346 // not accessible:
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         } // loop over bias
00358 
00359         // check at max voltage.
00360         if (direct_token[0][ichip]==0) {
00361         cr.status_direct=-3;
00362         result->getDefects().addDefect(ModuleDefect::TOKEN,Chip(ichip));
00363         }
00364     } // loop over chips
00365 
00366     // NOW check the bypass token
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         } // loop over scans
00400         // check at max voltage.
00401         if (bypass_token[0][ichip]==0) {
00402         cr.status_bypass=-3;
00403         result->getDefects().addDefect(ModuleDefect::RTOKEN,Chip(ichip));
00404         }
00405     } // loop over chips
00406     
00407     if (debug) cout << "\n\n---------------------> nearly done" << endl;
00408 
00409     // find the nominal voltage.
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     /* look-up table used for speed. Equivalent algorithm is :
00454        unsigned conf[MAX_CONF];
00455        int confno = -1;
00456        
00457        for(int i=0;i<MAX_CONF;i++){
00458        conf[i] = 0;
00459        }
00460        
00461        for(int ichip=1;ichip<=8;ichip++){
00462        if(ichip==1){
00463        conf[0] = 0x1;
00464        } else if(ichip==2){
00465        conf[1] = 0x3;
00466        } else{
00467        for(int i=0;i<Fib(ichip-2);i++){
00468        conf[(int)sumFib(ichip-1)+i] = conf[(int)sumFib(ichip-3)+i] + (0x1 << (ichip-1));
00469        }
00470        for(int i=0;i<Fib(ichip-1);i++){
00471        conf[(int)sumFib(ichip-1)+(int)Fib(ichip-2)+i] = conf[(int)sumFib(ichip-2)+i] + (0x1 << (ichip-1));
00472        }
00473        }
00474        }
00475     */
00476     }
00477 
00478     unsigned FullBypassAlgorithm::sumFib(const unsigned int n) {
00479     // Return the sum of all Fibonacci numbers up to n
00480     // new version by PWP 01.11.01
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 } // end of namespace SctAnalysis

Generated on Mon Dec 15 19:36:02 2003 for SCT DAQ/DCS Software by doxygen1.3-rc3