VIS

src/bmc/bmcBmc.c

Go to the documentation of this file.
00001 
00017 #include "bmcInt.h"
00018 
00019 static char rcsid[] UNUSED = "$Id: bmcBmc.c,v 1.72 2005/10/14 04:41:11 awedh Exp $";
00020 
00021 /*---------------------------------------------------------------------------*/
00022 /* Constant declarations                                                     */
00023 /*---------------------------------------------------------------------------*/
00024 
00025 /*---------------------------------------------------------------------------*/
00026 /* Type declarations                                                         */
00027 /*---------------------------------------------------------------------------*/
00028 
00029 /*---------------------------------------------------------------------------*/
00030 /* Structure declarations                                                    */
00031 /*---------------------------------------------------------------------------*/
00032 
00033 /*---------------------------------------------------------------------------*/
00034 /* Variable declarations                                                     */
00035 /*---------------------------------------------------------------------------*/
00036 
00039 /*---------------------------------------------------------------------------*/
00040 /* Static function prototypes                                                */
00041 /*---------------------------------------------------------------------------*/
00042 
00043 static int checkIndex(int index, BmcCnfClauses_t *cnfClauses);
00044 static int doAnd(int left, int right);
00045 static int doOr(int left, int right);
00046 
00049 /*---------------------------------------------------------------------------*/
00050 /* Definition of exported functions                                          */
00051 /*---------------------------------------------------------------------------*/
00052 
00053 /*---------------------------------------------------------------------------*/
00054 /* Definition of internal functions                                          */
00055 /*---------------------------------------------------------------------------*/
00056 
00073 void
00074 BmcLtlVerifyProp(
00075    Ntk_Network_t   *network,
00076    Ctlsp_Formula_t *ltlFormula,
00077    st_table        *CoiTable,
00078    BmcOption_t     *options)
00079 {
00080   mAig_Manager_t    *manager = Ntk_NetworkReadMAigManager(network);
00081   st_table          *nodeToMvfAigTable = NIL(st_table);  /* maps each node to its mvfAig */
00082   BmcCnfClauses_t   *cnfClauses = NIL(BmcCnfClauses_t);
00083   
00084 
00085   FILE              *cnfFile;
00086 
00087   array_t           *result = NIL(array_t);
00088   long              startTime, endTime;
00089   bAigEdge_t        property;
00090   array_t           *unitClause;
00091   
00092   assert(Ctlsp_isPropositionalFormula(ltlFormula));
00093   
00094   startTime = util_cpu_ctime();
00095   
00096   if (options->verbosityLevel != BmcVerbosityNone_c){
00097     (void) fprintf(vis_stdout, "LTL formula is propositional\n");
00098   }
00099   property = BmcCreateMaigOfPropFormula(network, manager, ltlFormula);
00100  
00101   if (property == mAig_NULL){
00102     return;
00103   }
00104   if (property == bAig_One){
00105     (void) fprintf(vis_stdout,"# BMC: Empty counterexample because the property is always FALSE\n");
00106     (void) fprintf(vis_stdout,"# BMC: formula failed\n");
00107     if (options->verbosityLevel != BmcVerbosityNone_c){
00108       fprintf(vis_stdout, "-- bmc time = %10g\n",
00109               (double)(util_cpu_ctime() - startTime) / 1000.0);
00110     }
00111     return;
00112   } else if (property == bAig_Zero){
00113     (void) fprintf(vis_stdout,"# BMC: The property is always TRUE\n");
00114     (void) fprintf(vis_stdout,"# BMC: formula passed\n");
00115     if (options->verbosityLevel != BmcVerbosityNone_c){
00116       fprintf(vis_stdout, "-- bmc time = %10g\n",
00117               (double)(util_cpu_ctime() - startTime) / 1000.0);
00118     }
00119     return;
00120   }
00121   cnfFile = Cmd_FileOpen(options->satInFile, "w", NIL(char *), 0);    
00122   if (cnfFile == NIL(FILE)) {
00123     (void) fprintf(vis_stderr,
00124                    "** bmc error: Cannot create CNF output file %s\n",
00125                    options->satInFile);
00126     return;
00127   }
00128   /* nodeToMvfAigTable Maps each node to its Multi-function And/Inv graph */
00129   nodeToMvfAigTable = (st_table *) Ntk_NetworkReadApplInfo(network,
00130                                                            MVFAIG_NETWORK_APPL_KEY);
00131   assert(nodeToMvfAigTable != NIL(st_table));
00132   /*
00133     Create clauses database 
00134   */
00135   cnfClauses = BmcCnfClausesAlloc();
00136   unitClause = array_alloc(int, 1);
00137 
00138   /*
00139     Create an initialized path of length 0
00140    */
00141   BmcCnfGenerateClausesForPath(network, 0, 0, BMC_INITIAL_STATES, cnfClauses, nodeToMvfAigTable, CoiTable);
00142    
00143   /* Generate CNF for the property */
00144   array_insert(int, unitClause, 0,
00145                BmcGenerateCnfFormulaForAigFunction(manager, property, 0, cnfClauses));
00146   
00147   BmcCnfInsertClause(cnfClauses, unitClause);
00148   BmcWriteClauses(manager, cnfFile, cnfClauses, options);
00149   (void) fclose(cnfFile);
00150 
00151   result = BmcCheckSAT(options);
00152   if (options->satSolverError){
00153     (void) fprintf(vis_stdout,"# BMC: Error in calling SAT solver\n");
00154   } else {
00155     if (result != NIL(array_t)){
00156       (void) fprintf(vis_stdout, "# BMC: formula failed\n");
00157       if(options->verbosityLevel != BmcVerbosityNone_c){
00158         (void) fprintf(vis_stdout,
00159                        "# BMC: Found a counterexample of length = 0 \n");
00160       }
00161       if (options->dbgLevel == 1) {
00162         BmcPrintCounterExample(network, nodeToMvfAigTable, cnfClauses,
00163                                result, 0, CoiTable, options, NIL(array_t));
00164       }
00165       array_free(result);
00166     } else {
00167       if(options->verbosityLevel != BmcVerbosityNone_c){
00168         fprintf(vis_stdout,"# BMC: no counterexample found of length up to 0\n");
00169       }
00170       (void) fprintf(vis_stdout, "# BMC: formula Passed\n");
00171     }
00172   }
00173   array_free(unitClause);   
00174   BmcCnfClausesFree(cnfClauses);
00175   
00176   if (options->verbosityLevel != BmcVerbosityNone_c){
00177     endTime = util_cpu_ctime();
00178     fprintf(vis_stdout, "-- bmc time = %10g\n",
00179             (double)(endTime - startTime) / 1000.0);
00180   }
00181   fflush(vis_stdout);
00182   return;
00183 } /* BmcLtlVerifyProp  */
00184 
00185 
00216 int
00217 BmcLtlCheckInductiveInvariant(
00218   Ntk_Network_t   *network,
00219   bAigEdge_t      property,
00220   BmcOption_t     *options,
00221   st_table        *CoiTable)
00222 {
00223   mAig_Manager_t    *manager = Ntk_NetworkReadMAigManager(network);
00224   BmcCnfClauses_t   *cnfClauses = NIL(BmcCnfClauses_t);
00225   array_t           *unitClause;
00226   int               cnfIndex;
00227   array_t           *result = NIL(array_t);
00228   FILE              *cnfFile;
00229   st_table          *nodeToMvfAigTable = NIL(st_table);  /* maps each node to its mvfAig */
00230   int               savedVerbosityLevel = options->verbosityLevel;
00231   int               returnValue = 0;  /* the property is not an inductive invariant */
00232 
00233   cnfFile = Cmd_FileOpen(options->satInFile, "w", NIL(char *), 0);    
00234   if (cnfFile == NIL(FILE)) {
00235     (void) fprintf(vis_stderr,
00236                    "** bmc error: Cannot create CNF output file %s\n",
00237                    options->satInFile);
00238     return -1;
00239   }
00240   /*
00241     nodeToMvfAigTable Maps each node to its Multi-function And/Inv graph
00242   */
00243   nodeToMvfAigTable =
00244     (st_table *) Ntk_NetworkReadApplInfo(network, MVFAIG_NETWORK_APPL_KEY);
00245   
00246   assert(nodeToMvfAigTable != NIL(st_table));
00247 
00248   /*
00249     Clause database
00250    */
00251   cnfClauses = BmcCnfClausesAlloc();
00252   /*
00253     Check if the property holds in all intial states
00254   */
00255   /*
00256     Generate CNF clauses for initial states
00257   */
00258   BmcCnfGenerateClausesForPath(network, 0, 0, BMC_INITIAL_STATES,
00259                                cnfClauses, nodeToMvfAigTable, CoiTable);
00260   /*
00261     Generate CNF clauses for the property
00262   */
00263   cnfIndex = BmcGenerateCnfFormulaForAigFunction(manager, property, 0, cnfClauses);
00264   unitClause = array_alloc(int, 1);
00265   array_insert(int, unitClause, 0, cnfIndex); /* because property is the negation of
00266                                                 the LTL formula*/
00267   BmcCnfInsertClause(cnfClauses, unitClause);
00268   
00269   options->verbosityLevel = BmcVerbosityNone_c;
00270   BmcWriteClauses(manager, cnfFile, cnfClauses, options);
00271   (void) fclose(cnfFile);
00272   result = BmcCheckSAT(options);    
00273   options->verbosityLevel = (Bmc_VerbosityLevel) savedVerbosityLevel;
00274   BmcCnfClausesFree(cnfClauses);
00275   if (options->satSolverError){
00276     return -1;
00277   }
00278   if (result == NIL(array_t)){ /* the property holds at all initial states */
00279     cnfFile = Cmd_FileOpen(options->satInFile, "w", NIL(char *), 0);    
00280     if (cnfFile == NIL(FILE)) {
00281       (void) fprintf(vis_stderr,
00282                      "** bmc error: Cannot create CNF output file %s\n",
00283                      options->satInFile);
00284       return -1;
00285     }
00286     /*
00287       Check if the property holds in state i, it also holds in state i+1
00288     */
00289     cnfClauses = BmcCnfClausesAlloc();  
00290     /*
00291       Generate CNF clauses for a transition from state i to state i+1.
00292     */
00293     BmcCnfGenerateClausesForPath(network, 0, 1, BMC_NO_INITIAL_STATES,
00294                                  cnfClauses, nodeToMvfAigTable, CoiTable);
00295     
00296     cnfIndex = BmcGenerateCnfFormulaForAigFunction(manager, property, 0, cnfClauses);
00297     array_insert(int, unitClause, 0, -cnfIndex); /* because property is the negation of
00298                                                     the LTL formula */
00299     BmcCnfInsertClause(cnfClauses, unitClause);
00300     
00301     cnfIndex = BmcGenerateCnfFormulaForAigFunction(manager, property, 1, cnfClauses);
00302     array_insert(int, unitClause, 0, cnfIndex); /* because property is the negation of
00303                                                    the LTL formula */
00304     BmcCnfInsertClause(cnfClauses, unitClause);
00305     options->verbosityLevel = BmcVerbosityNone_c;
00306     BmcWriteClauses(manager, cnfFile, cnfClauses, options);
00307     (void) fclose(cnfFile);
00308     result = BmcCheckSAT(options);
00309     options->verbosityLevel = (Bmc_VerbosityLevel) savedVerbosityLevel;
00310     BmcCnfClausesFree(cnfClauses);
00311     if (options->satSolverError){
00312       returnValue = -1;
00313     }
00314     if (result != NIL(array_t)){
00315       returnValue = 0; /* the property is not an inductive invariant */
00316     } else {
00317       returnValue = 1;  /* the property is an inductive invariant */
00318     }
00319   }
00320   array_free(unitClause);
00321   return returnValue; 
00322 } /* BmcLtlCheckInductiveInvariant() */
00323 
00324 
00346 void
00347 BmcLtlVerifyGp(  
00348    Ntk_Network_t   *network,
00349    Ctlsp_Formula_t *ltlFormula,
00350    st_table        *CoiTable,
00351    BmcOption_t     *options)
00352 {
00353   mAig_Manager_t    *manager = Ntk_NetworkReadMAigManager(network);
00354   st_table          *nodeToMvfAigTable = NIL(st_table);  /* maps each node to its mvfAig */
00355   BmcCnfClauses_t   *cnfClauses = NIL(BmcCnfClauses_t);
00356   BmcCnfStates_t    *state;
00357 
00358   FILE              *cnfFile;
00359   array_t           *Pclause = array_alloc(int, 0);
00360 
00361   int               k, bound, initK, propK;
00362   array_t           *result = NIL(array_t);
00363   long              startTime, endTime;
00364   bAigEdge_t        property;
00365   int               minK = options->minK;
00366   int               maxK = options->maxK;
00367   int               i, initState = BMC_INITIAL_STATES;
00368   array_t           *unitClause;
00369   
00370   int               bmcError = FALSE;
00371   
00372   Bmc_PropertyStatus formulaStatus;
00373   
00374   assert(Ctlsp_LtlFormulaIsFp(ltlFormula));
00375   
00376   startTime = util_cpu_ctime();
00377 
00378   if (options->verbosityLevel != BmcVerbosityNone_c){
00379     (void)fprintf(vis_stdout, "LTL formula is of type G(p)\n");
00380   }
00381   property = BmcCreateMaigOfPropFormula(network, manager, ltlFormula->right);
00382 
00383   if (property == mAig_NULL){
00384     return;
00385   }
00386   if (property == bAig_One){
00387     (void) fprintf(vis_stdout,"# BMC: Empty counterexample because the property is always FALSE\n");
00388     (void) fprintf(vis_stdout,"# BMC: formula failed\n");
00389     if (options->verbosityLevel != BmcVerbosityNone_c){
00390       fprintf(vis_stdout, "-- bmc time = %10g\n",
00391               (double)(util_cpu_ctime() - startTime) / 1000.0);
00392     }
00393     return;
00394   } else if (property == bAig_Zero){
00395     (void) fprintf(vis_stdout,"# BMC: The property is always TRUE\n");
00396     (void) fprintf(vis_stdout,"# BMC: formula passed\n");
00397     if (options->verbosityLevel != BmcVerbosityNone_c){
00398       fprintf(vis_stdout, "-- bmc time = %10g\n",
00399               (double)(util_cpu_ctime() - startTime) / 1000.0);
00400     }
00401     return;
00402   }
00403 
00404 #if 0
00405   if (options->verbosityLevel == BmcVerbosityMax_c){
00406     (void) fprintf(vis_stdout, "\nBMC: Check if the property is an inductive invariant\n");
00407   }
00408   checkInductiveInvariant = BmcLtlCheckInductiveInvariant(network, property, options, CoiTable);
00409   
00410   if(checkInductiveInvariant == -1){
00411     return;
00412   }
00413   if (checkInductiveInvariant == 1){
00414     (void) fprintf(vis_stdout,"# BMC: The property is an inductive invariant\n");
00415     (void) fprintf(vis_stdout,"# BMC: formula passed\n");
00416     if (options->verbosityLevel != BmcVerbosityNone_c){
00417       fprintf(vis_stdout, "-- bmc time = %10g\n",
00418               (double)(util_cpu_ctime() - startTime) / 1000.0);
00419     }
00420     return;
00421   }
00422 #endif
00423   if (options->verbosityLevel != BmcVerbosityNone_c){
00424     (void)fprintf(vis_stdout, "Apply BMC on counterexample of length >= %d and <= %d (+%d)\n",
00425                   minK, maxK, options->step);
00426   }
00427   initK  = 0;
00428   propK  = 0;
00429   formulaStatus = BmcPropertyUndecided_c;
00430   
00431   /* nodeToMvfAigTable Maps each node to its Multi-function And/Inv graph */
00432   nodeToMvfAigTable =
00433     (st_table *) Ntk_NetworkReadApplInfo(network, MVFAIG_NETWORK_APPL_KEY);
00434   assert(nodeToMvfAigTable != NIL(st_table));
00435 
00436   /*
00437     Create clauses database 
00438   */
00439   cnfClauses = BmcCnfClausesAlloc();
00440   /*
00441     init = BmcCreateMaigOfInitialStates(network, nodeToMvfAigTable, CoiTable);
00442   */
00443   for(bound = minK; bound <= maxK; bound += options->step){
00444     if (options->verbosityLevel == BmcVerbosityMax_c) {
00445       (void) fprintf(vis_stdout,
00446                      "\nBMC: Generate counterexample of length %d\n",
00447                      bound);
00448     }
00449     cnfFile = Cmd_FileOpen(options->satInFile, "w", NIL(char *), 0);    
00450     if (cnfFile == NIL(FILE)) {
00451       (void) fprintf(vis_stderr,
00452                      "** bmc error: Cannot create CNF output file %s\n",
00453                      options->satInFile);
00454       bmcError = TRUE;
00455       break;
00456     }
00457     BmcCnfGenerateClausesForPath(network, initK, bound, initState, cnfClauses, nodeToMvfAigTable, CoiTable);
00458 
00459     initState = BMC_NO_INITIAL_STATES;
00460    
00461     /* Generate CNF for the property */
00462     Pclause = array_alloc(int, 0);
00463     /*
00464     state = BmcCnfClausesFreeze(cnfClauses);
00465     */
00466     for(k=propK; k <= bound; k++){
00467       array_insert_last(
00468         int, Pclause, BmcGenerateCnfFormulaForAigFunction(manager, property,
00469                                                           k, cnfClauses));
00470     }
00471     
00472     state = BmcCnfClausesFreeze(cnfClauses);
00473     
00474     BmcCnfInsertClause(cnfClauses, Pclause);
00475     BmcWriteClauses(manager, cnfFile, cnfClauses, options);
00476     (void) fclose(cnfFile);
00477     BmcCnfClausesRestore(cnfClauses, state);
00478     result = BmcCheckSAT(options);
00479     if (options->satSolverError){
00480       array_free(Pclause);
00481       break;
00482     }
00483     if (result != NIL(array_t)){
00484       bound++;
00485       array_free(Pclause);
00486       /*
00487         formula failed\n"
00488       */
00489       formulaStatus = BmcPropertyFailed_c;
00490       break;
00491     }
00492     unitClause = array_alloc(int, 1);
00493     for(i=0; i<array_n(Pclause); i++){
00494       array_insert(int, unitClause, 0, -array_fetch(int, Pclause, i));
00495       BmcCnfInsertClause(cnfClauses, unitClause);
00496     }
00497     array_free(unitClause);   
00498     array_free(Pclause);
00499     FREE(state);
00500     initK = bound;
00501     propK = bound+1;
00502 
00503     /*
00504       Prove if the property passes using the induction proof of SSS0.
00505      */
00506     if((result == NIL(array_t)) &&
00507        (options->inductiveStep !=0) &&
00508        (bound % options->inductiveStep == 0)){
00509       BmcCnfClauses_t   *cnfClauses;
00510       array_t           *result = NIL(array_t);
00511       array_t           *unitClause =  array_alloc(int, 1);
00512       int               savedVerbosityLevel = options->verbosityLevel;
00513       long              startTime = util_cpu_ctime();
00514         
00515       if (options->verbosityLevel == BmcVerbosityMax_c) {
00516         (void) fprintf(vis_stdout, "\nBMC: Check for induction\n");
00517       }
00518       options->verbosityLevel = BmcVerbosityNone_c;
00519 
00520       if(options->earlyTermination){
00521         /*
00522           Early termination condition
00523           
00524           Check if there is no simple path of length 'bound' starts from
00525           initial states
00526           
00527         */
00528         cnfClauses = BmcCnfClausesAlloc();
00529         
00530         cnfFile = Cmd_FileOpen(options->satInFile, "w", NIL(char *), 0);  
00531         if (cnfFile == NIL(FILE)) {
00532           (void)fprintf(vis_stderr,
00533                         "** bmc error: Cannot create CNF output file %s\n",
00534                         options->satInFile);
00535           bmcError = TRUE;
00536           break;
00537         }
00538         /*
00539           Generate an initialized simple path path of length bound.
00540         */
00541         BmcCnfGenerateClausesForLoopFreePath(network, 0, bound, BMC_INITIAL_STATES,
00542                                              cnfClauses, nodeToMvfAigTable, CoiTable);
00543         BmcWriteClauses(manager, cnfFile, cnfClauses, options);
00544         (void) fclose(cnfFile);
00545         BmcCnfClausesFree(cnfClauses);
00546         
00547         result = BmcCheckSAT(options);
00548         if(options->satSolverError){
00549           break;
00550         }
00551         if(result == NIL(array_t)){
00552           if (savedVerbosityLevel == BmcVerbosityMax_c) {
00553             (void) fprintf(vis_stdout,
00554                            "# BMC: No simple path starting at an initial state\n");
00555           }
00556           formulaStatus = BmcPropertyPassed_c;
00557         } else {
00558           array_free(result);
00559         }
00560       } /* Early termination */
00561       if(formulaStatus != BmcPropertyPassed_c){
00562         cnfFile = Cmd_FileOpen(options->satInFile, "w", NIL(char *), 0);  
00563         if (cnfFile == NIL(FILE)) {
00564           (void)fprintf(vis_stderr,
00565                         "** bmc error: Cannot create CNF output file %s\n",
00566                         options->satInFile);
00567           bmcError = TRUE;
00568           break;
00569         }
00570         cnfClauses = BmcCnfClausesAlloc();
00571         /*
00572           Generate a simple path of length k+1
00573         */
00574         BmcCnfGenerateClausesForLoopFreePath(network, 0, bound+1, BMC_NO_INITIAL_STATES,
00575                                              cnfClauses, nodeToMvfAigTable, CoiTable);
00576         /*
00577           All the states to bound satisfy the property.
00578         */
00579         unitClause = array_alloc(int, 1);
00580         for(k=0; k <= bound; k++){
00581           array_insert(
00582             int, unitClause, 0, -BmcGenerateCnfFormulaForAigFunction(manager, property,
00583                                                                      k, cnfClauses));
00584           BmcCnfInsertClause(cnfClauses, unitClause);
00585         }
00586         /*
00587           The property fails at bound +1
00588         */
00589         array_insert(int, unitClause, 0,
00590                      BmcGenerateCnfFormulaForAigFunction(manager, property,
00591                                                          bound+1, cnfClauses));
00592         BmcCnfInsertClause(cnfClauses, unitClause);
00593         array_free(unitClause);
00594         
00595         BmcWriteClauses(manager, cnfFile, cnfClauses, options);
00596         BmcCnfClausesFree(cnfClauses);
00597         (void) fclose(cnfFile);
00598         result = BmcCheckSAT(options);
00599         if (options->satSolverError){
00600           break;
00601         }
00602         if(result == NIL(array_t)) {
00603           if (savedVerbosityLevel == BmcVerbosityMax_c) {
00604             (void) fprintf(vis_stdout,
00605                            "# BMC: No simple path leading to a bad state\n");
00606           }
00607           formulaStatus = BmcPropertyPassed_c;
00608         }
00609       }
00610       options->verbosityLevel = (Bmc_VerbosityLevel) savedVerbosityLevel;
00611       if (options->verbosityLevel != BmcVerbosityNone_c){
00612         endTime = util_cpu_ctime();
00613         fprintf(vis_stdout, "-- check for induction time = %10g\n",
00614                 (double)(endTime - startTime) / 1000.0);
00615       }
00616     } /* Check induction */
00617     if(formulaStatus != BmcPropertyUndecided_c){
00618       break;
00619     }
00620   } /* for bound loop */
00621   if( bmcError == FALSE){
00622     if (options->satSolverError){
00623       (void) fprintf(vis_stdout,"# BMC: Error in calling SAT solver\n");
00624     } else {
00625       if(formulaStatus == BmcPropertyUndecided_c){
00626         if (options->verbosityLevel != BmcVerbosityNone_c){
00627           (void) fprintf(vis_stdout,
00628                          "# BMC: no counterexample found of length up to %d \n",
00629                          options->maxK);
00630         }
00631       }
00632       if(formulaStatus == BmcPropertyFailed_c) {
00633         (void) fprintf(vis_stdout, "# BMC: formula failed\n");
00634          if(options->verbosityLevel != BmcVerbosityNone_c){
00635            (void) fprintf(vis_stdout,
00636                           "# BMC: Found a counterexample of length = %d \n", bound-1);
00637          }
00638         if (options->dbgLevel == 1) {
00639           BmcPrintCounterExample(network, nodeToMvfAigTable, cnfClauses,
00640                                  result, bound-1, CoiTable, options, NIL(array_t));
00641         }
00642       } else if(formulaStatus == BmcPropertyPassed_c) {
00643         (void) fprintf(vis_stdout, "# BMC: formula Passed\n");
00644       } else if(formulaStatus == BmcPropertyUndecided_c) {
00645         (void) fprintf(vis_stdout,"# BMC: formula undecided\n");
00646       }
00647     }
00648   }
00649   /* free all used memories */
00650   if(cnfClauses != NIL(BmcCnfClauses_t)){
00651     BmcCnfClausesFree(cnfClauses);
00652   }
00653   if(result != NIL(array_t)) {
00654     array_free(result);
00655   }
00656   /*
00657   array_free(Pclause);
00658   */
00659   if (options->verbosityLevel != BmcVerbosityNone_c){
00660     endTime = util_cpu_ctime();
00661     fprintf(vis_stdout, "-- bmc time = %10g\n",
00662             (double)(endTime - startTime) / 1000.0);
00663   }
00664   fflush(vis_stdout);
00665   return;
00666 } /* BmcLtlVerifyGp()  */
00667 
00687 void
00688 BmcLtlVerifyFp(
00689    Ntk_Network_t   *network,
00690    Ctlsp_Formula_t *ltlFormula,
00691    st_table        *CoiTable,
00692    BmcOption_t     *options)
00693 {
00694   mAig_Manager_t  *manager   = Ntk_NetworkReadMAigManager(network);
00695   st_table        *nodeToMvfAigTable = NIL(st_table);  /* maps each node to its mvfAig */
00696   BmcCnfClauses_t *cnfClauses = NIL(BmcCnfClauses_t);
00697   
00698   
00699   FILE       *cnfFile;
00700   array_t    *unitClause= array_alloc(int, 1), *outClause;
00701   int        outIndex;
00702   int        k;
00703   array_t    *result  = NIL(array_t);
00704   long       startTime, endTime;
00705   bAigEdge_t property;
00706   int        bound;
00707   int        bmcError = FALSE;
00708     
00709   Bmc_PropertyStatus formulaStatus = BmcPropertyUndecided_c;
00710 
00711   assert(Ctlsp_LtlFormulaIsGp(ltlFormula));
00712    
00713   startTime = util_cpu_ctime();
00714   if (options->verbosityLevel != BmcVerbosityNone_c){
00715     (void)fprintf(vis_stdout, "LTL formula is of type F(p)\n");
00716   }
00717   property = BmcCreateMaigOfPropFormula(network, manager, ltlFormula->right);
00718   if (property == mAig_NULL){
00719     return;
00720   }
00721   if (property == bAig_One){
00722     (void) fprintf(vis_stdout, "# BMC: formula failed\n");
00723     (void) fprintf(vis_stdout, "       Empty counterexample because the property is always FALSE\n");
00724     if (options->verbosityLevel != BmcVerbosityNone_c) {
00725       endTime = util_cpu_ctime();
00726       fprintf(vis_stdout, "-- bmc time = %10g\n",
00727               (double)(endTime - startTime) / 1000.0);
00728     }
00729     return;
00730   } else if (property == bAig_Zero){
00731     (void) fprintf(vis_stdout,"# BMC: The property is always TRUE\n");
00732     formulaStatus = BmcPropertyPassed_c;
00733     (void) fprintf(vis_stdout,"# BMC: formula passed\n");
00734     if (options->verbosityLevel != BmcVerbosityNone_c) {
00735       endTime = util_cpu_ctime();
00736       fprintf(vis_stdout, "-- bmc time = %10g\n",
00737               (double)(endTime - startTime) / 1000.0);
00738     }
00739     return;
00740   }
00741   if (options->verbosityLevel != BmcVerbosityNone_c){
00742     (void)fprintf(vis_stdout, "Apply BMC on counterexample of length >= %d and <= %d (+%d) \n",
00743                   options->minK, options->maxK, options->step);
00744   }
00745   /*
00746     nodeToMvfAigTable Maps each node to its Multi-function AIG graph
00747   */
00748   nodeToMvfAigTable = (st_table *) Ntk_NetworkReadApplInfo(network, MVFAIG_NETWORK_APPL_KEY);
00749   assert(nodeToMvfAigTable != NIL(st_table));
00750   outClause = NIL(array_t);
00751   bound = options->minK;
00752   BmcGetCoiForLtlFormula(network, ltlFormula, CoiTable);
00753   
00754   while( (result == NIL(array_t)) && (bound <= options->maxK)){
00755     if (options->verbosityLevel == BmcVerbosityMax_c) {
00756       (void) fprintf(vis_stdout,
00757                      "\nBMC: Generate counterexample of length %d\n", bound);
00758     }
00759     cnfClauses = BmcCnfClausesAlloc();
00760     cnfFile = Cmd_FileOpen(options->satInFile, "w", NIL(char *), 0);    
00761     if (cnfFile == NIL(FILE)) {
00762       (void)fprintf(vis_stderr,
00763                     "** bmc error: Cannot create CNF output file %s\n",
00764                     options->satInFile);
00765       bmcError = TRUE;
00766       break;
00767     }
00768     /*
00769       Generate clauses for an initialized path of length "bound".
00770     */
00771     BmcCnfGenerateClausesForPath(network, 0, bound, BMC_INITIAL_STATES,
00772                                  cnfClauses, nodeToMvfAigTable, CoiTable);
00773     /*
00774       Generate CNF for the property. Property fails at all states
00775      */
00776     for(k=0; k <= bound; k++){
00777       array_insert(int, unitClause, 0,
00778                    BmcGenerateCnfFormulaForAigFunction(manager, property,
00779                                                        k, cnfClauses));
00780       BmcCnfInsertClause(cnfClauses, unitClause);
00781     }
00782 
00783     /* Generate CNF for a loop-back (loop from the last state to any
00784        state) path.
00785        (Sk -> S0) + (Sk -> S1) + ..... + (Sk-> Sk-1) + (Sk-> Sk)
00786        Each transition consisits of one or more latches.  We
00787        AND the transiton relation of these latches.  For multi-valued
00788        latches, we OR the equivalence of each value of the latch. To
00789        do the AND we use the CNF equivalent of the AND.  a = b*c => (b
00790        + !a) * (c + !a)
00791     */
00792     outClause = array_alloc(int, bound);   
00793     for (k=0; k <= bound; k++){
00794       /*
00795         Create new var for the output of the AND node.
00796       */
00797       outIndex = cnfClauses->cnfGlobalIndex++;
00798       BmcCnfGenerateClausesFromStateToState(network, bound, k, cnfClauses,
00799                                             nodeToMvfAigTable, CoiTable, outIndex);
00800       array_insert(int, outClause, k, outIndex);
00801     }  /* for k state loop */
00802     BmcCnfInsertClause(cnfClauses, outClause);
00803   
00804     BmcWriteClauses(manager, cnfFile, cnfClauses, options);
00805     (void) fclose(cnfFile);
00806     
00807     result = BmcCheckSAT(options);
00808     if (options->satSolverError){
00809       break;
00810     }
00811     if(result != NIL(array_t)){
00812       formulaStatus = BmcPropertyFailed_c;
00813       break;
00814     }
00815     BmcCnfClausesFree(cnfClauses);
00816     array_free(outClause);
00817     if((result == NIL(array_t)) &&
00818        (options->inductiveStep !=0) &&
00819        (bound % options->inductiveStep == 0)
00820        )    
00821       {
00822       int     savedVerbosityLevel = options->verbosityLevel;
00823       long    startTime = util_cpu_ctime();
00824       array_t *result  = NIL(array_t);
00825 
00826       if (options->verbosityLevel == BmcVerbosityMax_c) {
00827         (void) fprintf(vis_stdout,
00828                        "\nBMC: Check if the property passes\n");
00829       }
00830       cnfFile = Cmd_FileOpen(options->satInFile, "w", NIL(char *), 0);  
00831       if (cnfFile == NIL(FILE)) {
00832         (void)fprintf(vis_stderr,
00833                       "** bmc error: Cannot create CNF output file %s\n",
00834                       options->satInFile);
00835         bmcError = TRUE;
00836         break;
00837       }
00838       cnfClauses = BmcCnfClausesAlloc();
00839       /*
00840         CNF for an initialized simple path.
00841        */
00842       BmcCnfGenerateClausesForLoopFreePath(network, 0, bound, BMC_INITIAL_STATES,
00843                                            cnfClauses, nodeToMvfAigTable, CoiTable);
00844       /*
00845         Generate CNF for the property. Property fails at all states
00846       */
00847       for(k=0; k <= bound; k++){
00848         array_insert(int, unitClause, 0,
00849                      BmcGenerateCnfFormulaForAigFunction(manager, property,
00850                                                          k, cnfClauses));
00851         BmcCnfInsertClause(cnfClauses, unitClause);
00852       }
00853       BmcWriteClauses(manager, cnfFile, cnfClauses, options);
00854       BmcCnfClausesFree(cnfClauses);
00855       (void) fclose(cnfFile);
00856       /*
00857         Do not print any detail information when checking the clauses
00858        */
00859       options->verbosityLevel = BmcVerbosityNone_c;
00860       result = BmcCheckSAT(options);
00861       options->verbosityLevel = (Bmc_VerbosityLevel) savedVerbosityLevel;
00862       if (options->satSolverError){
00863         break;
00864       }
00865       if (options->verbosityLevel != BmcVerbosityNone_c){
00866         endTime = util_cpu_ctime();
00867         fprintf(vis_stdout, "--  checking time = %10g\n",
00868                 (double)(endTime - startTime) / 1000.0);
00869       }
00870       if (result == NIL(array_t)){ /* UNSAT */
00871         formulaStatus = BmcPropertyPassed_c;
00872         break;  /* formula is satisfiable */
00873       }
00874       array_free(result);
00875     } /* Check induction */
00876 
00877     /* free all used memories 
00878     BmcCnfClausesFree(cnfClauses); */
00879 
00880     bound += options->step;
00881   } /* while result and bound */
00882   if (bmcError == FALSE){
00883     if(!options->satSolverError){
00884       if(formulaStatus == BmcPropertyFailed_c) {
00885         (void) fprintf(vis_stdout, "# BMC: formula failed\n");
00886         if(options->verbosityLevel != BmcVerbosityNone_c){
00887           (void) fprintf(vis_stdout,
00888                          "# BMC: Found a counterexample of length = %d \n", bound);
00889         }
00890         if (options->dbgLevel == 1) {
00891           BmcPrintCounterExample(network, nodeToMvfAigTable, cnfClauses,
00892                                  result, bound, CoiTable, options, outClause);
00893         }
00894         array_free(result);
00895         BmcCnfClausesFree(cnfClauses);
00896         array_free(outClause);
00897       } else if(formulaStatus == BmcPropertyPassed_c) {
00898         (void) fprintf(vis_stdout, "# BMC: formula Passed\n");
00899       } else if(formulaStatus == BmcPropertyUndecided_c) {
00900         (void) fprintf(vis_stdout,"# BMC: formula undecided\n");
00901         if (options->verbosityLevel != BmcVerbosityNone_c){
00902           (void) fprintf(vis_stdout,
00903                        "# BMC: no counterexample found of length up to %d \n",
00904                          options->maxK);
00905         }
00906       }
00907     } else {
00908       (void) fprintf(vis_stdout,"# BMC: Error in calling SAT solver\n");
00909     }
00910   }
00911   if (options->verbosityLevel != BmcVerbosityNone_c) {
00912     endTime = util_cpu_ctime();
00913     fprintf(vis_stdout, "-- bmc time = %10g\n",
00914             (double)(endTime - startTime) / 1000.0);
00915   }
00916   if(unitClause != NIL(array_t)) {
00917     array_free(unitClause);
00918   }
00919   fflush(vis_stdout);  
00920   return;
00921 } /* BmcLtlVerifyFp() */
00922 
00944 void
00945 BmcLtlVerifyFGp(
00946    Ntk_Network_t   *network,
00947    Ctlsp_Formula_t *ltlFormula,
00948    st_table        *CoiTable,
00949    BmcOption_t     *options)
00950 {
00951   mAig_Manager_t   *manager = Ntk_NetworkReadMAigManager(network);
00952   st_table         *nodeToMvfAigTable = NIL(st_table);  /* node to mvfAig */
00953   BmcCnfClauses_t  *cnfClauses = NIL(BmcCnfClauses_t);
00954   FILE             *cnfFile;
00955   
00956   array_t          *orClause, *tmpClause, *loopClause;
00957   int              k, l, andIndex, loop;
00958   array_t          *result = NIL(array_t);
00959   long             startTime, endTime;
00960   int              minK = options->minK;
00961   int              maxK = options->maxK;
00962   Ctlsp_Formula_t  *propFormula;
00963   bAigEdge_t       property;
00964 
00965   Bmc_PropertyStatus formulaStatus;
00966   int                bmcError = FALSE;
00967   
00968   int              m=-1, n=-1;
00969   int              checkLevel = 0;
00970   /*
00971     Refer to Theorem 1 in the paper "Proving More Properties with Bounded Model Checking"
00972     
00973     If checkLevel == 0 -->  check for beta' only. If UNSAT, m=k and chekLevel = 1
00974     If checkLevel == 1 -->  check for beta  only. If UNSAT, checkLevel = 2.
00975     If checkLevel == 2 -->  check for alpha only. If UNSAT, n=k and checkLevel = 3.
00976     If gama is UNSAT up to (m+n-1) and checkLvel = 3, formula passes.
00977     checkLevel = 4 if (m+n-1) > maxK; */
00978 
00979   /*
00980     Remember the LTL property was negated
00981    */
00982   assert(Ctlsp_LtlFormulaIsGFp(ltlFormula));
00983 
00984   /* ************** */
00985   
00986   /* Initialization */
00987   
00988   /* ************** */
00989   loopClause = NIL(array_t);
00990   startTime = util_cpu_ctime();
00991   /*
00992     nodeToMvfAigTable maps each node to its multi-function And/Inv graph
00993   */
00994   nodeToMvfAigTable =
00995     (st_table *) Ntk_NetworkReadApplInfo(network, MVFAIG_NETWORK_APPL_KEY);
00996   if (nodeToMvfAigTable == NIL(st_table)){
00997     (void) fprintf(vis_stderr,
00998                    "** bmc error: you need to build the AIG structure first\n");
00999     return;
01000   }
01001   propFormula = Ctlsp_FormulaReadRightChild(Ctlsp_FormulaReadRightChild(ltlFormula));
01002   property    = BmcCreateMaigOfPropFormula(network, manager, propFormula);
01003   if (options->verbosityLevel != BmcVerbosityNone_c){
01004     (void)fprintf(vis_stdout, "LTL formula is of type FG(p)\n");
01005     (void) fprintf(vis_stdout, "Apply BMC on counterexample of length >= %d and <= %d (+%d) \n",
01006                   minK, maxK, options->step);
01007   }
01008   tmpClause  = array_alloc(int, 2);
01009   k= minK;
01010   formulaStatus = BmcPropertyUndecided_c;
01011   while( (result == NIL(array_t)) && (k <= maxK)){
01012     /*
01013       Search for a k-loop counterexample of length k.
01014      */
01015     if (options->verbosityLevel == BmcVerbosityMax_c) {
01016       (void) fprintf(vis_stdout, "\nGenerate counterexample of length %d\n", k);
01017     }
01018     /*
01019       Create a clause database
01020      */
01021     cnfClauses = BmcCnfClausesAlloc();
01022 
01023     cnfFile = Cmd_FileOpen(options->satInFile, "w", NIL(char *), 0);  
01024     if (cnfFile == NIL(FILE)) {
01025       (void)fprintf(vis_stderr,
01026                     "** bmc error: Cannot create CNF output file %s\n",
01027                     options->satInFile);
01028       bmcError = TRUE;
01029       break;
01030     }
01031     
01032     /**********************************************
01033        \gama(k)
01034     ***********************************************/
01035     /*
01036       Generate an initialized path of length k.
01037      */
01038     BmcCnfGenerateClausesForPath(network, 0, k, BMC_INITIAL_STATES, cnfClauses, nodeToMvfAigTable, CoiTable);
01039     /*
01040       k-loop
01041      */
01042     orClause   = array_alloc(int, 0);
01043     loopClause = array_alloc(int, k+1);
01044     for(l=0; l<=k; l++){
01045       /*
01046         Use to check if there is a loop from k to l.
01047        */
01048       loop = cnfClauses->cnfGlobalIndex++;
01049       BmcCnfGenerateClausesFromStateToState(network, k, l, cnfClauses, nodeToMvfAigTable, CoiTable, loop);
01050       array_insert(int, loopClause, l, loop);
01051       
01052       andIndex   = cnfClauses->cnfGlobalIndex++;
01053       array_insert(int, tmpClause, 0, loop);
01054       array_insert(int, tmpClause, 1, -andIndex);
01055       BmcCnfInsertClause(cnfClauses, tmpClause);
01056 
01057       /*
01058                  l
01059         If [[F p]]  if p true in a state from l to k.
01060                  k
01061        */
01062       array_insert(int, tmpClause, 0,
01063                    BmcGenerateCnfForLtl(network, Ctlsp_FormulaCreate(Ctlsp_F_c, propFormula, NIL(Ctlsp_Formula_t)),
01064                                         l, k, -1, cnfClauses));
01065       BmcCnfInsertClause(cnfClauses, tmpClause);
01066       
01067       array_insert_last(int, orClause, andIndex);
01068     } /* for l loop */
01069     BmcCnfInsertClause(cnfClauses, orClause);
01070     array_free(orClause);
01071     BmcWriteClauses(manager, cnfFile, cnfClauses, options);
01072     (void) fclose(cnfFile);
01073       
01074     result = BmcCheckSAT(options);
01075     if(options->satSolverError){
01076       break;
01077     }
01078     if(result != NIL(array_t)) {
01079       formulaStatus = BmcPropertyFailed_c;
01080       break;
01081     }
01082     array_free(loopClause);
01083     /* free all used memories */
01084     BmcCnfClausesFree(cnfClauses);
01085 
01086     /* ====================================================================
01087              Use termination criteria to prove that the property passes.
01088        ==================================================================== */
01089     if((result == NIL(array_t)) &&
01090        (options->inductiveStep !=0) &&
01091        (k % options->inductiveStep == 0)
01092        )
01093       {
01094         array_t *unitClause = array_alloc(int, 0);
01095         array_t *result = NIL(array_t);
01096         int     savedVerbosityLevel = options->verbosityLevel;
01097 
01098         options->verbosityLevel = BmcVerbosityNone_c;
01099         /* ===========================
01100            Early termination condition
01101            =========================== */
01102         if(options->earlyTermination){
01103           if (savedVerbosityLevel == BmcVerbosityMax_c) {
01104             (void) fprintf(vis_stdout, "\nChecking the early termination at k= %d\n", k);
01105           }
01106           cnfClauses = BmcCnfClausesAlloc();
01107 
01108           cnfFile = Cmd_FileOpen(options->satInFile, "w", NIL(char *), 0);  
01109           if (cnfFile == NIL(FILE)) {
01110             (void)fprintf(vis_stderr,
01111                           "** abmc error: Cannot create CNF output file %s\n",
01112                           options->satInFile);
01113             bmcError = TRUE;
01114             break;
01115           }
01116           /*
01117             Generate an initialized simple path path of length k.
01118           */
01119           BmcCnfGenerateClausesForLoopFreePath(network, 0, k, BMC_INITIAL_STATES,
01120                                                cnfClauses, nodeToMvfAigTable, CoiTable);
01121           BmcWriteClauses(manager, cnfFile, cnfClauses, options);
01122           (void) fclose(cnfFile);
01123           BmcCnfClausesFree(cnfClauses);
01124           
01125           result = BmcCheckSAT(options);
01126           if(options->satSolverError){
01127             break;
01128           }
01129           if(result == NIL(array_t)) {
01130             formulaStatus = BmcPropertyPassed_c;
01131             if (savedVerbosityLevel == BmcVerbosityMax_c) {
01132               (void) fprintf(vis_stdout, "# BMC: By early termination\n");
01133             }
01134             break;
01135           }
01136         } /* Early termination */
01137 
01138         /*
01139           Check \beta''(k)
01140         */
01141         if(checkLevel == 0){
01142           int i;
01143           
01144           cnfClauses = BmcCnfClausesAlloc();
01145           if (savedVerbosityLevel == BmcVerbosityMax_c) {
01146             (void) fprintf(vis_stdout, "# BMC: Check beta'' \n");
01147           }
01148           cnfFile = Cmd_FileOpen(options->satInFile, "w", NIL(char *), 0);  
01149           if (cnfFile == NIL(FILE)) {
01150             (void)fprintf(vis_stderr,
01151                           "** bmc error: Cannot create CNF output file %s\n",
01152                           options->satInFile);
01153             bmcError = TRUE;
01154             break;
01155           }
01156           /*
01157             Generate a simple path of length k+1.
01158           */
01159           BmcCnfGenerateClausesForLoopFreePath(network, 0, k+1, BMC_NO_INITIAL_STATES,
01160                                                cnfClauses, nodeToMvfAigTable, CoiTable);
01161           for(i=1; i<=k+1; i++){
01162             array_insert(int, unitClause, 0,
01163                          -BmcGenerateCnfFormulaForAigFunction(manager, property,
01164                                                               i, cnfClauses));
01165             BmcCnfInsertClause(cnfClauses, unitClause);
01166           }
01167           array_insert(int, unitClause, 0,
01168                        BmcGenerateCnfFormulaForAigFunction(manager, property,
01169                                                            0, cnfClauses));
01170           BmcCnfInsertClause(cnfClauses, unitClause);
01171           
01172           BmcWriteClauses(manager, cnfFile, cnfClauses, options);
01173           (void) fclose(cnfFile);
01174           
01175           result = BmcCheckSAT(options);
01176           BmcCnfClausesFree(cnfClauses);
01177           if(options->satSolverError){
01178             break;
01179           }
01180           if(result == NIL(array_t)) {
01181             m = k;
01182             printf("Beta'': Value of m = %d\n", m);
01183             checkLevel = 1;
01184           }
01185         } /* Check for beta'' */
01186         
01187         /*
01188           Check \beta'(k) 
01189         */
01190         if(checkLevel == 0){
01191           int i;
01192           
01193           cnfClauses = BmcCnfClausesAlloc();
01194           if (savedVerbosityLevel == BmcVerbosityMax_c) {
01195             (void) fprintf(vis_stdout, "# BMC: Check beta' \n");
01196           }
01197           cnfFile = Cmd_FileOpen(options->satInFile, "w", NIL(char *), 0);  
01198           if (cnfFile == NIL(FILE)) {
01199             (void)fprintf(vis_stderr,
01200                           "** bmc error: Cannot create CNF output file %s\n",
01201                           options->satInFile);
01202             bmcError = TRUE;
01203             break;
01204           }
01205           /*
01206             Generate a simple path of length k+1.
01207           */
01208           BmcCnfGenerateClausesForLoopFreePath(network, 0, k+1, BMC_NO_INITIAL_STATES,
01209                                                cnfClauses, nodeToMvfAigTable, CoiTable);
01210           for(i=0; i<=k; i++){
01211             array_insert(int, unitClause, 0,
01212                          -BmcGenerateCnfFormulaForAigFunction(manager, property,
01213                                                               i, cnfClauses));
01214             BmcCnfInsertClause(cnfClauses, unitClause);
01215           }
01216           array_insert(int, unitClause, 0,
01217                        BmcGenerateCnfFormulaForAigFunction(manager, property,
01218                                                            k+1, cnfClauses));
01219           BmcCnfInsertClause(cnfClauses, unitClause);
01220           
01221           BmcWriteClauses(manager, cnfFile, cnfClauses, options);
01222           (void) fclose(cnfFile);
01223           
01224           result = BmcCheckSAT(options);
01225           BmcCnfClausesFree(cnfClauses);
01226           if(options->satSolverError){
01227             break;
01228           }
01229           if(result == NIL(array_t)) {
01230             m = k;
01231             printf("Beta': Value of m = %d\n", m);
01232             checkLevel = 1;
01233           }
01234         } /* Check for beta' */
01235         /*
01236           Check for beta
01237         */
01238         if(checkLevel == 1){
01239           cnfClauses = BmcCnfClausesAlloc();
01240           if (savedVerbosityLevel == BmcVerbosityMax_c) {
01241             (void) fprintf(vis_stdout, "# BMC: Check beta\n");
01242           }       
01243           cnfFile = Cmd_FileOpen(options->satInFile, "w", NIL(char *), 0);  
01244           if (cnfFile == NIL(FILE)) {
01245             (void)fprintf(vis_stderr,
01246                           "** bmc error: Cannot create CNF output file %s\n",
01247                           options->satInFile);
01248             bmcError = TRUE;
01249             break;
01250           }
01251           /*
01252             Generate a simple path of length k+1.
01253           */
01254           BmcCnfGenerateClausesForLoopFreePath(network, 0, k+1, BMC_NO_INITIAL_STATES,
01255                                                cnfClauses, nodeToMvfAigTable, CoiTable);
01256           array_insert(int, unitClause, 0,
01257                        -BmcGenerateCnfFormulaForAigFunction(manager, property,
01258                                                             k, cnfClauses));
01259           BmcCnfInsertClause(cnfClauses, unitClause);
01260           array_insert(int, unitClause, 0,
01261                        BmcGenerateCnfFormulaForAigFunction(manager, property,
01262                                                            k+1, cnfClauses));
01263           BmcCnfInsertClause(cnfClauses, unitClause);
01264           
01265           BmcWriteClauses(manager, cnfFile, cnfClauses, options);
01266           (void) fclose(cnfFile);
01267           
01268           result = BmcCheckSAT(options);
01269           BmcCnfClausesFree(cnfClauses);
01270           if(options->satSolverError){
01271             break;
01272           }
01273           if(result == NIL(array_t)) {
01274             checkLevel = 2;
01275           }
01276         } /* Check beta */
01277       
01278         if(checkLevel == 2){ /* we check \alpha if \beta UNSAT */
01279           if (savedVerbosityLevel == BmcVerbosityMax_c) {
01280             (void) fprintf(vis_stdout, "# BMC: Check alpha \n");
01281           }       
01282           /*
01283             \alpha(k)
01284           */
01285           cnfClauses = BmcCnfClausesAlloc();
01286          
01287           cnfFile = Cmd_FileOpen(options->satInFile, "w", NIL(char *), 0);  
01288           if (cnfFile == NIL(FILE)) {
01289             (void)fprintf(vis_stderr,
01290                           "** bmc error: Cannot create CNF output file %s\n",
01291                           options->satInFile);
01292             bmcError = TRUE;
01293             break;
01294           }
01295           /*
01296             Generate an initialized path of length k.
01297           */
01298           BmcCnfGenerateClausesForLoopFreePath(network, 0, k, BMC_INITIAL_STATES,
01299                                                cnfClauses, nodeToMvfAigTable, CoiTable);
01300           
01301           array_insert(int, unitClause, 0,
01302                        BmcGenerateCnfFormulaForAigFunction(manager, property,
01303                                                            k, cnfClauses));
01304           BmcCnfInsertClause(cnfClauses, unitClause);
01305           
01306           
01307           BmcWriteClauses(manager, cnfFile, cnfClauses, options);
01308           (void) fclose(cnfFile);
01309           
01310           result = BmcCheckSAT(options);
01311           BmcCnfClausesFree(cnfClauses);
01312           if(options->satSolverError){
01313             break;
01314           }
01315           if(result == NIL(array_t)) {
01316             n = k;
01317             checkLevel = 3;
01318             printf("m=%d  n=%d\n",m,n);
01319             if ((m+n-1) <= maxK){
01320               maxK = m+n-1;
01321             } else {
01322               checkLevel = 4;
01323             }
01324           }
01325         }/* Check alpha */
01326         array_free(unitClause);
01327         options->verbosityLevel = (Bmc_VerbosityLevel) savedVerbosityLevel;
01328       } /* Prove the property passes*/
01329     k += options->step;
01330   } /* while result and k*/
01331   if (bmcError == FALSE){
01332     if(options->satSolverError){
01333       (void) fprintf(vis_stdout,"# BMC: Error in calling SAT solver\n");
01334     } else {
01335       if(checkLevel == 3){
01336         (void) fprintf(vis_stdout, "# BMC: (m+n-1) Complete the theorem\n");
01337         formulaStatus = BmcPropertyPassed_c;
01338       }
01339       if(formulaStatus == BmcPropertyFailed_c) {
01340         (void) fprintf(vis_stdout, "# BMC: formula failed\n");
01341         if(options->verbosityLevel != BmcVerbosityNone_c){
01342           (void) fprintf(vis_stdout,
01343                          "# BMC: Found a counterexample of length = %d \n", k);
01344         }
01345         if (options->dbgLevel == 1) {
01346           BmcPrintCounterExample(network, nodeToMvfAigTable, cnfClauses,
01347                                  result, k, CoiTable, options, loopClause);
01348           BmcCnfClausesFree(cnfClauses);
01349           array_free(loopClause);
01350         }
01351       } else if(formulaStatus == BmcPropertyPassed_c) {
01352         (void) fprintf(vis_stdout, "# BMC: formula Passed\n");
01353       } else if(formulaStatus == BmcPropertyUndecided_c) {
01354         (void) fprintf(vis_stdout,"# BMC: formula undecided\n");
01355         if (options->verbosityLevel != BmcVerbosityNone_c){
01356           (void) fprintf(vis_stdout,
01357                          "# BMC: no counterexample found of length up to %d \n",
01358                          maxK);
01359         }
01360       }
01361     }
01362   }
01363   /*
01364     free all used memories
01365   */
01366   array_free(tmpClause);
01367  
01368   if(result != NIL(array_t)){
01369     array_free(result);
01370   }
01371   if (options->verbosityLevel != BmcVerbosityNone_c) {
01372     endTime = util_cpu_ctime();
01373     fprintf(vis_stdout, "-- abmc time = %10g\n",
01374             (double)(endTime - startTime) / 1000.0);
01375   }
01376   fflush(vis_stdout);
01377   return;
01378 } /* BmcLtlVerifyGFp() */
01379 
01399 void
01400 BmcLtlVerifyUnitDepth(
01401    Ntk_Network_t   *network,
01402    Ctlsp_Formula_t *ltlFormula,
01403    st_table        *CoiTable,
01404    BmcOption_t     *options)
01405 {
01406   mAig_Manager_t    *manager = Ntk_NetworkReadMAigManager(network);
01407   st_table          *nodeToMvfAigTable = NIL(st_table);  /* node to mvfAig */
01408   BmcCnfClauses_t   *cnfClauses = NIL(BmcCnfClauses_t);
01409   FILE              *cnfFile;
01410 
01411   array_t           *orClause =NIL(array_t);
01412   array_t           *loopClause, *tmpclause;
01413   int               l, loopIndex, andIndex, loop;
01414   int               noLoopIndex;
01415   array_t           *result = NIL(array_t);
01416   
01417   int               leftValue  = 0;
01418   int               rightValue = 0;
01419   long              startTime, endTime;
01420   int               k;
01421   int               minK = options->minK;
01422   int               maxK = options->maxK;
01423                     /* Store the index of a loop from k to all sate from 0 to k */
01424   
01425   Bmc_PropertyStatus       formulaStatus;
01426   BmcCheckForTermination_t *terminationStatus = 0;
01427   int                      bmcStatus=0; /* Holds the status of running BMC
01428                                            = -1 if there is an error */
01429   
01430   assert(Ctlsp_LtlFormulaDepth(ltlFormula) == 1);
01431   
01432   /* ************** */
01433   /* Initialization */
01434   /* ************** */
01435   
01436   startTime = util_cpu_ctime();
01437   /*
01438     nodeToMvfAigTable maps each node to its multi-function AIG graph
01439   */
01440   nodeToMvfAigTable =
01441     (st_table *) Ntk_NetworkReadApplInfo(network, MVFAIG_NETWORK_APPL_KEY);
01442   assert(nodeToMvfAigTable != NIL(st_table));
01443 
01444   loopClause = NIL(array_t);
01445   
01446   if (options->verbosityLevel != BmcVerbosityNone_c){
01447     (void) fprintf(vis_stdout, "Unit depth LTL formula\n");
01448     (void) fprintf(vis_stdout, "Apply BMC on counterexample of length >= %d and <= %d (+%d) \n",
01449                   minK, maxK, options->step);
01450   }
01451    if(options->inductiveStep !=0){
01452      /*
01453        Use the termination criteria to prove the property passes.    
01454      */
01455      terminationStatus = BmcAutTerminationAlloc(network,
01456                                                 Ctlsp_LtllFormulaNegate(ltlFormula),
01457                                                 NIL(array_t));
01458      assert(terminationStatus);
01459    }
01460   k = minK;
01461   formulaStatus = BmcPropertyUndecided_c;
01462   while( (result == NIL(array_t)) && (k <= maxK)){
01463     if (options->verbosityLevel == BmcVerbosityMax_c) {
01464       (void) fprintf(vis_stdout, "\nGenerate counterexample of length %d\n", k);
01465     }
01466     /*
01467       Create clause database
01468      */
01469     cnfClauses = BmcCnfClausesAlloc();
01470 
01471     cnfFile = Cmd_FileOpen(options->satInFile, "w", NIL(char *), 0);  
01472     if (cnfFile == NIL(FILE)) {
01473       (void)fprintf(vis_stderr,
01474                     "** bmc error: Cannot create CNF output file %s\n",
01475                     options->satInFile);
01476       bmcStatus = -1;
01477       break;
01478     }
01479     /*
01480       Generate clauses represent an initialized path of length k
01481      */
01482     BmcCnfGenerateClausesForPath(network, 0, k, BMC_INITIAL_STATES,
01483                                  cnfClauses, nodeToMvfAigTable, CoiTable);
01484     /*
01485       Generate clauses represent paths which satisfy the LTL formula if
01486       there is no loop.
01487     */
01488     noLoopIndex = BmcGenerateCnfForLtl(network, ltlFormula, 0, k, -1, cnfClauses);
01489     leftValue   = checkIndex(noLoopIndex, cnfClauses);
01490     if (leftValue != 1) { /* no loop  part of the basic encoding is not TRUE */
01491       orClause = array_alloc(int, 0);   
01492       /*
01493         No need to check for !Lk in the basic encoding 
01494       */
01495       if (leftValue == -1){ /* no loop part of the basic encoding is not FALSE */
01496         array_insert_last(int, orClause, noLoopIndex);
01497       }
01498       /*
01499         Generate clauses represent paths which satisfy the LTL formula if
01500         there is a loop.
01501       */
01502       loopIndex = BmcGenerateCnfForLtl(network, ltlFormula, 0, k, 0, cnfClauses);
01503       rightValue = checkIndex(loopIndex, cnfClauses);
01504       if (rightValue == 0){ /* loop  part of the basic encoding is FALSE */
01505         break;
01506       }
01507       /*
01508         rightValue can be 1 or -1
01509         leftValue can be 0 or -1
01510        */
01511       if (noLoopIndex == loopIndex){ /* do not check for the existence of a loop*/
01512         break;
01513       }
01514       /*
01515         Clauses for loop-back path.
01516        */
01517       loopClause = array_alloc(int, k+2);
01518       for(l=0; l<=k; l++){
01519           loop = cnfClauses->cnfGlobalIndex++;
01520           BmcCnfGenerateClausesFromStateToState(network, k, l, cnfClauses,
01521                                                 nodeToMvfAigTable, CoiTable, loop);
01522           array_insert(int, loopClause, l, loop);
01523       } /* for l loop */
01524       loop = cnfClauses->cnfGlobalIndex++;
01525       array_insert(int, loopClause, k+1, -loop);
01526       BmcCnfInsertClause(cnfClauses, loopClause);
01527       if(rightValue == -1){
01528         andIndex   = cnfClauses->cnfGlobalIndex++;
01529         tmpclause  = array_alloc(int, 2);
01530         
01531         array_insert(int, tmpclause, 0, loop);
01532         array_insert(int, tmpclause, 1, -andIndex);
01533         BmcCnfInsertClause(cnfClauses, tmpclause);
01534         
01535         array_insert(int, tmpclause, 0, loopIndex);
01536         array_insert(int, tmpclause, 1, -andIndex);
01537         BmcCnfInsertClause(cnfClauses, tmpclause);
01538         
01539         array_free(tmpclause);
01540         array_insert_last(int, orClause, andIndex);
01541       } else {
01542         array_insert_last(int, orClause, loop);
01543       }
01544     }
01545     /* if((leftValue == 1) || (rightValue == 1)){ */
01546     if(leftValue == 1){
01547       assert(k==1);
01548       /*
01549         formula failed
01550       */
01551       formulaStatus = BmcPropertyFailed_c;
01552       if (options->verbosityLevel != BmcVerbosityNone_c){
01553         (void) fprintf(vis_stdout,"# BMC: Empty counterexample because the property is always FALSE\n");
01554       }
01555       break;
01556     } else if((leftValue == 0) && (rightValue == 0)){
01557       if (options->verbosityLevel != BmcVerbosityNone_c){
01558         (void) fprintf(vis_stdout,"# BMC: the formula is trivially true");
01559         (void) fprintf(vis_stdout," for counterexamples of length %d\n", k);
01560       }
01561     } else {
01562       BmcCnfInsertClause(cnfClauses, orClause);
01563       array_free(orClause);
01564       BmcWriteClauses(manager, cnfFile, cnfClauses, options);
01565       (void) fclose(cnfFile);
01566       
01567       result = BmcCheckSAT(options);
01568       if(options->satSolverError){
01569         break;
01570       }
01571       if(result != NIL(array_t)) {
01572         /*
01573           formula failed
01574         */
01575         formulaStatus = BmcPropertyFailed_c;
01576       } else {
01577         /* free some used memories */
01578         BmcCnfClausesFree(cnfClauses);
01579         array_free(loopClause);
01580         /*
01581           Use the termination check
01582         */
01583 
01584         if(terminationStatus && (formulaStatus == BmcPropertyUndecided_c) && (bmcStatus != 1)){
01585           if((options->inductiveStep !=0) &&
01586              (k % options->inductiveStep == 0)
01587              )
01588             {
01589               /*
01590                 Check for termination for the current value of k.
01591               */
01592               terminationStatus->k = k;
01593               bmcStatus = BmcAutLtlCheckForTermination(network,
01594                                                        NIL(array_t), terminationStatus,
01595                                                        nodeToMvfAigTable, CoiTable, options);
01596               if(bmcStatus == 1){
01597                 maxK = options->maxK;
01598               }
01599               if(bmcStatus == 3){
01600                 formulaStatus = BmcPropertyPassed_c;
01601                 break;
01602               }
01603               if(bmcStatus == -1){
01604                 break;
01605               }
01606             }
01607         } /* terminationStatus */
01608       }
01609     }
01610     k += options->step;
01611   } /* while result and k*/
01612 
01613  /*
01614     If no error.
01615    */
01616   if(bmcStatus != -1){
01617     if(bmcStatus == 1){
01618       (void) fprintf(vis_stdout,
01619                      "# BMC: no counterexample found of length up to %d \n", options->maxK);
01620       (void) fprintf(vis_stdout, "# BMC: By termination criterion (m+n-1)\n");
01621       formulaStatus = BmcPropertyPassed_c;
01622     }
01623     if(options->satSolverError){
01624       (void) fprintf(vis_stdout,"# BMC: Error in calling SAT solver\n");
01625     } else {
01626       if(formulaStatus == BmcPropertyFailed_c) {
01627         (void) fprintf(vis_stdout, "# BMC: formula failed\n");
01628         if(options->verbosityLevel != BmcVerbosityNone_c){
01629           (void) fprintf(vis_stdout,
01630                          "# BMC: Found a counterexample of length = %d \n", k);
01631         }
01632         if ((options->dbgLevel == 1) && (result != NIL(array_t))) {
01633           BmcPrintCounterExample(network, nodeToMvfAigTable, cnfClauses,
01634                                  result, k, CoiTable, options, loopClause);
01635         }
01636         /* free some used memories */
01637         BmcCnfClausesFree(cnfClauses);
01638         array_free(loopClause);
01639         array_free(result);
01640       } else if(formulaStatus == BmcPropertyPassed_c) {
01641         (void) fprintf(vis_stdout, "# BMC: formula Passed\n");
01642         (void) fprintf(vis_stdout, "#      Termination depth = %d\n", maxK);
01643       } else if(formulaStatus == BmcPropertyUndecided_c) {
01644         (void) fprintf(vis_stdout,"# BMC: formula undecided\n");
01645         if (options->verbosityLevel != BmcVerbosityNone_c){
01646           (void) fprintf(vis_stdout,
01647                          "# BMC: no counterexample found of length up to %d \n",
01648                          maxK);
01649         }
01650       }
01651     }
01652   }
01653   if (options->verbosityLevel != BmcVerbosityNone_c) {
01654     endTime = util_cpu_ctime();
01655     fprintf(vis_stdout, "-- bmc time = %10g\n",
01656             (double)(endTime - startTime) / 1000.0);
01657   }
01658   if(terminationStatus){
01659     BmcAutTerminationFree(terminationStatus);
01660   }
01661   fflush(vis_stdout);
01662   return;
01663 } /* Bmc_VerifyUnitDepth() */
01664 
01679 void
01680 BmcLtlVerifyGeneralLtl(
01681    Ntk_Network_t   *network,
01682    Ctlsp_Formula_t *ltlFormula,
01683    st_table        *CoiTable,
01684    array_t         *constraintArray,
01685    BmcOption_t     *options)
01686 {
01687   mAig_Manager_t    *manager = Ntk_NetworkReadMAigManager(network);
01688   st_table          *nodeToMvfAigTable = NIL(st_table);  /* node to mvfAig */
01689   BmcCnfClauses_t   *cnfClauses = NIL(BmcCnfClauses_t);
01690   FILE              *cnfFile;
01691 
01692   array_t           *orClause = NIL(array_t);
01693   array_t           *loopClause, *tmpclause;
01694   int               l, loopIndex, andIndex, loop;
01695   int               noLoopIndex;
01696   array_t           *result = NIL(array_t);
01697   array_t           *fairnessArray = NIL(array_t);
01698   int               leftValue  = 0;
01699   int               rightValue = 0;
01700   long              startTime, endTime;
01701   int               k;
01702   int               minK = options->minK;
01703   int               maxK = options->maxK;
01704   boolean           boundedFormula;
01705   int               depth;
01706                     /* Store the index of loop from k to all sate from 0 to k */
01707   
01708   array_t           *ltlConstraintArray;        /* constraints converted to LTL */
01709   int               f;
01710   boolean           fairness  = (constraintArray != NIL(array_t));
01711 
01712   BmcCheckForTermination_t *terminationStatus = 0;
01713   Bmc_PropertyStatus       formulaStatus;
01714   int                      bmcStatus=0; /* Holds the status of running BMC
01715                                            = -1 if there is an error */
01716   
01717   /* ************** */
01718   /* Initialization */
01719   /* ************** */
01720   startTime = util_cpu_ctime();
01721   /*
01722     nodeToMvfAigTable maps each node to its multi-function And/Inv graph
01723   */
01724   nodeToMvfAigTable =
01725     (st_table *) Ntk_NetworkReadApplInfo(network, MVFAIG_NETWORK_APPL_KEY);
01726   assert(nodeToMvfAigTable != NIL(st_table));
01727 
01728   loopClause = NIL(array_t);
01729   noLoopIndex = 0;
01730   ltlConstraintArray = NIL(array_t);
01731   if(fairness){
01732     Ctlsp_Formula_t *formula;
01733     int              i;
01734     /*
01735       All formulae in constraintArray are propositional, propositional
01736       constraint.
01737     */
01738     ltlConstraintArray = array_alloc(Ctlsp_Formula_t *, 0);
01739     arrayForEachItem(Ctlsp_Formula_t *, constraintArray, i, formula) {
01740       /*
01741         To help making propositional constraint easy to encode.
01742       */
01743       formula =  Ctlsp_FormulaCreate(Ctlsp_F_c, formula, NIL(Ctlsp_Formula_t));
01744       array_insert(Ctlsp_Formula_t *, ltlConstraintArray, i, formula);
01745       BmcGetCoiForLtlFormula(network, formula, CoiTable);
01746     }
01747   }
01748   /*
01749     For bounded formulae use a tighter upper bound if possible.
01750   */
01751   boundedFormula = Ctlsp_LtlFormulaTestIsBounded(ltlFormula, &depth);
01752   if (boundedFormula && depth < maxK && depth >= minK) {
01753     maxK = depth;
01754   } else {
01755     if(options->inductiveStep !=0){
01756       /*
01757         Use the termination criteria to prove the property passes.    
01758       */
01759       terminationStatus = BmcAutTerminationAlloc(network,
01760                                                  Ctlsp_LtllFormulaNegate(ltlFormula),
01761                                                  constraintArray);
01762       assert(terminationStatus);
01763     }
01764   }
01765   if (options->verbosityLevel != BmcVerbosityNone_c){
01766     (void) fprintf(vis_stdout, "General LTL BMC\n");
01767     if (boundedFormula){
01768       (void) fprintf(vis_stdout, "Bounded formula of depth %d\n", depth);
01769     }
01770     (void) fprintf(vis_stdout, "Apply BMC on counterexample of length >= %d and <= %d (+%d) \n",
01771                   minK, maxK, options->step);
01772   }
01773   k= minK;
01774   formulaStatus = BmcPropertyUndecided_c;
01775   while( (result == NIL(array_t)) && (k <= maxK)){
01776     if (options->verbosityLevel == BmcVerbosityMax_c) {
01777       (void) fprintf(vis_stdout, "\nGenerate counterexample of length %d\n", k);
01778     }
01779 
01780     cnfFile = Cmd_FileOpen(options->satInFile, "w", NIL(char *), 0);  
01781     if (cnfFile == NIL(FILE)) {
01782       (void)fprintf(vis_stderr,
01783                     "** bmc error: Cannot create CNF output file %s\n",
01784                     options->satInFile);
01785       bmcStatus = -1;
01786       break;
01787     }
01788     /*
01789       Create a clause database
01790      */
01791     cnfClauses = BmcCnfClausesAlloc();
01792     /*
01793       Gnerate clauses for an initialized path of length k
01794      */
01795     BmcCnfGenerateClausesForPath(network, 0, k, BMC_INITIAL_STATES,
01796                                  cnfClauses, nodeToMvfAigTable, CoiTable);
01797 
01798     if(!fairness){ /* No fairness constraint */
01799       noLoopIndex = BmcGenerateCnfForLtl(network, ltlFormula, 0, k, -1, cnfClauses);
01800       leftValue   = checkIndex(noLoopIndex, cnfClauses);
01801     } else {
01802       leftValue = 0; /* the path must have a loop*/
01803     }
01804     if (leftValue != 1) {
01805       orClause = array_alloc(int, 0);   
01806       /*
01807         No need to check for !Lk in the basic encoding 
01808       */
01809       if (leftValue == -1){
01810         array_insert_last(int, orClause, noLoopIndex);
01811       }
01812       loopClause = array_alloc(int, k+1);
01813      
01814       for(l=0; l<=k; l++){
01815         loopIndex = BmcGenerateCnfForLtl(network, ltlFormula, 0, k, l, cnfClauses);
01816         rightValue = checkIndex(loopIndex, cnfClauses);
01817         if (rightValue == 0){
01818           break;
01819         }
01820         if(fairness){
01821           Ctlsp_Formula_t *formula;
01822           int             i;
01823 
01824           fairnessArray = array_alloc(int, 0);
01825           arrayForEachItem(Ctlsp_Formula_t *, ltlConstraintArray, i, formula) {
01826             array_insert_last(int, fairnessArray,
01827                               BmcGenerateCnfForLtl(network, formula, l, k, -1, cnfClauses));
01828           }
01829         }
01830         if (rightValue !=0){
01831           loop = cnfClauses->cnfGlobalIndex++;
01832           BmcCnfGenerateClausesFromStateToState(network, k, l, cnfClauses,
01833                                                 nodeToMvfAigTable, CoiTable, loop);
01834           array_insert(int, loopClause, l, loop);
01835           if(rightValue == -1){
01836             
01837             andIndex   = cnfClauses->cnfGlobalIndex++;
01838             tmpclause  = array_alloc(int, 2);
01839             array_insert(int, tmpclause, 0, loop);
01840             array_insert(int, tmpclause, 1, -andIndex);
01841             BmcCnfInsertClause(cnfClauses, tmpclause);
01842 
01843             array_insert(int, tmpclause, 0, loopIndex);
01844             array_insert(int, tmpclause, 1, -andIndex);
01845             BmcCnfInsertClause(cnfClauses, tmpclause);
01846             
01847             if(fairness){
01848               for(f=0; f < array_n(fairnessArray); f++){
01849                 array_insert(int, tmpclause, 0, array_fetch(int, fairnessArray, f)); 
01850                 array_insert(int, tmpclause, 1, -andIndex);
01851                 BmcCnfInsertClause(cnfClauses, tmpclause);
01852               }
01853             }
01854             array_free(tmpclause);
01855             array_insert_last(int, orClause, andIndex);
01856           } else {
01857             array_insert_last(int, orClause, loop);
01858           }
01859         }
01860         if(fairness){
01861           array_free(fairnessArray);
01862         }
01863       } /* for l loop */
01864     }
01865     if((leftValue == 1) || (rightValue == 1)){
01866       assert(k==1);
01867       if (options->verbosityLevel != BmcVerbosityNone_c){
01868         formulaStatus = BmcPropertyFailed_c;
01869         (void) fprintf(vis_stdout,"# BMC: Empty counterexample because the property is always FALSE\n");
01870       }
01871       break;
01872     } else if((leftValue == 0) && (rightValue == 0)){
01873       if (options->verbosityLevel != BmcVerbosityNone_c){
01874         (void) fprintf(vis_stdout,"# BMC: the formula is trivially true");
01875         (void) fprintf(vis_stdout," for counterexamples of length %d\n", k);
01876       }
01877     } else {
01878       /*
01879       BmcCnfInsertClause(cnfClauses, loopClause);
01880       */
01881       BmcCnfInsertClause(cnfClauses, orClause);
01882       /*
01883       array_free(loopClause);
01884       */
01885       array_free(orClause);
01886       BmcWriteClauses(manager, cnfFile, cnfClauses, options);
01887       (void) fclose(cnfFile);
01888       
01889       result = BmcCheckSAT(options);
01890       if(options->satSolverError){
01891         break;
01892       }
01893       if(result != NIL(array_t)) {
01894         /*
01895           formula failed\n"
01896          */
01897         formulaStatus = BmcPropertyFailed_c;
01898         break;
01899       }
01900       array_free(loopClause);
01901     }
01902     /* free all used memories */
01903     BmcCnfClausesFree(cnfClauses);
01904     cnfClauses = NIL(BmcCnfClauses_t);
01905     
01906     /*
01907       Use the termination check if the the LTL formula is not bounded
01908      */
01909     if(terminationStatus && (formulaStatus == BmcPropertyUndecided_c) && (bmcStatus != 1)){
01910       if((options->inductiveStep !=0) &&
01911          (k % options->inductiveStep == 0)
01912          )
01913         {
01914           /*
01915             Check for termination for the current value of k.
01916            */
01917           terminationStatus->k = k;
01918           bmcStatus = BmcAutLtlCheckForTermination(network,
01919                                                    constraintArray, terminationStatus,
01920                                                    nodeToMvfAigTable, CoiTable, options);
01921           if(bmcStatus == 1){
01922             maxK = terminationStatus->k;
01923           }
01924           if(bmcStatus == 3){
01925             formulaStatus = BmcPropertyPassed_c;
01926             break;
01927           }
01928           if(bmcStatus == -1){
01929             break;
01930           }
01931         }
01932     } /* terminationStatus */
01933     k += options->step;
01934   } /* while result and k*/
01935 
01936   /*
01937     If no error.
01938    */
01939   if(bmcStatus != -1){
01940     /*
01941     if(result == NIL(array_t)){
01942     */
01943     if(formulaStatus == BmcPropertyUndecided_c){
01944       if(bmcStatus == 1){
01945         (void) fprintf(vis_stdout,
01946                        "# BMC: no counterexample found of length up to %d \n", maxK);
01947         (void) fprintf(vis_stdout, "# BMC: By termination criterion (m+n-1)\n");
01948         formulaStatus = BmcPropertyPassed_c;
01949       }
01950       if (boundedFormula && depth <= options->maxK){
01951         (void) fprintf(vis_stdout,
01952                        "# BMC: no counterexample found of length up to %d \n", depth);
01953         formulaStatus = BmcPropertyPassed_c;
01954       }
01955     }
01956     if(options->satSolverError){
01957       (void) fprintf(vis_stdout,"# BMC: Error in calling SAT solver\n");
01958     } else {
01959       if(formulaStatus == BmcPropertyFailed_c) {
01960         (void) fprintf(vis_stdout, "# BMC: formula failed\n");
01961         if(options->verbosityLevel != BmcVerbosityNone_c){
01962           (void) fprintf(vis_stdout,
01963                          "# BMC: Found a counterexample of length = %d \n", k);
01964         }
01965         if ((options->dbgLevel == 1) && (result != NIL(array_t))) {
01966           BmcPrintCounterExample(network, nodeToMvfAigTable, cnfClauses,
01967                                  result, k, CoiTable, options, loopClause);
01968         }
01969         /*BmcCnfClausesFree(cnfClauses);*/
01970         array_free(loopClause);
01971       } else if(formulaStatus == BmcPropertyPassed_c) {
01972         (void) fprintf(vis_stdout, "# BMC: formula Passed\n");
01973         (void) fprintf(vis_stdout, "#      Termination depth = %d\n", maxK);
01974       } else if(formulaStatus == BmcPropertyUndecided_c) {
01975         (void) fprintf(vis_stdout,"# BMC: formula undecided\n");
01976         if (options->verbosityLevel != BmcVerbosityNone_c){
01977           (void) fprintf(vis_stdout,
01978                          "# BMC: no counterexample found of length up to %d \n",
01979                          maxK);
01980         }
01981       }
01982     }
01983   }
01984   if (options->verbosityLevel != BmcVerbosityNone_c) {
01985     endTime = util_cpu_ctime();
01986     fprintf(vis_stdout, "-- bmc time = %10g\n",
01987             (double)(endTime - startTime) / 1000.0);
01988   }
01989   /*
01990     free all used memories
01991   */
01992   if(terminationStatus){
01993     BmcAutTerminationFree(terminationStatus);
01994   }
01995   if(result != NIL(array_t)){
01996     array_free(result);
01997   }
01998   if(cnfClauses != NIL(BmcCnfClauses_t)){
01999     BmcCnfClausesFree(cnfClauses);
02000   }
02001   if(fairness){
02002     /*Ctlsp_FormulaArrayFree(ltlConstraintArray);*/
02003   }
02004   fflush(vis_stdout);
02005   return;
02006 } /* BmcLtlVerifyGeneralLtl() */
02007 
02027 int
02028 BmcGenerateCnfForLtl(
02029    Ntk_Network_t   *network,
02030    Ctlsp_Formula_t *ltlFormula,
02031    int             i /* from state i */,
02032    int             k /* to state k   */,
02033    int             l /* loop         */,
02034    BmcCnfClauses_t *cnfClauses)
02035 {
02036   int left, right, cnfIndex;
02037   int andIndex, orIndex;
02038   int j, n;
02039   int leftValue, rightValue, andValue, orValue;
02040   
02041   mAig_Manager_t  *manager = Ntk_NetworkReadMAigManager(network);
02042   array_t         *clause, *tmpclause, *orClause, *rightClause, *leftClause;
02043   BmcCnfStates_t  *state;
02044   
02045   assert(ltlFormula != NIL(Ctlsp_Formula_t));
02046   right = 0;
02047   rightValue = 0;
02048   
02049   if(Ctlsp_isPropositionalFormula(ltlFormula)){
02050     bAigEdge_t property = BmcCreateMaigOfPropFormula(network, manager, ltlFormula);
02051        
02052     if (property == bAig_Zero){ /* FALSE */
02053       /* add an empty clause to indicate FALSE property */
02054       BmcAddEmptyClause(cnfClauses);
02055       return 0;
02056     }
02057     if (property == bAig_One){ /* TRUE */
02058       /* Don't generate any clause to indicate TRUE property.*/
02059       return 0;
02060     }
02061     /* Generate the clause of the propositional formula */
02062     /* The state of the input variables is the same as the state of the state variables. */
02063     cnfIndex = BmcGenerateCnfFormulaForAigFunction(manager, property, i, cnfClauses);    
02064     return cnfIndex;
02065   }
02066   /*
02067    * Formula is NOT propositional formula 
02068    */
02069   switch(ltlFormula->type) {
02070     case Ctlsp_NOT_c:
02071       /* reach here if formula-left is always not propositional*/
02072       /* NOT must only appears infront of a propositional formula.*/
02073       if (!Ctlsp_isPropositionalFormula(ltlFormula->left)){
02074         fprintf(vis_stderr,"BMC error: the LTL formula is not in NNF\n");
02075         return 0;
02076       }
02077       /*
02078       return -1*BmcGenerateCnfForLtlNoLoop(network, ltlFormula->left, i, k,
02079                                            cnfIndexTable, clauseArray);
02080       */
02081       break;
02082     case Ctlsp_AND_c:
02083       /*
02084           c = a * b  -->  (!a + !b + c) * (a + !c) * (b + !c).
02085           Because a and b must be one, so we need only the last two clauses.
02086        */
02087       
02088       state = BmcCnfClausesFreeze(cnfClauses);
02089       rightValue = 1;
02090       
02091       left      = BmcGenerateCnfForLtl(network, ltlFormula->left,  i, k, l, cnfClauses);
02092       leftValue = checkIndex(left, cnfClauses);
02093 
02094       if (leftValue !=0){
02095         right      = BmcGenerateCnfForLtl(network, ltlFormula->right, i, k, l, cnfClauses);
02096         rightValue = checkIndex(right, cnfClauses);
02097       }
02098       if ((leftValue == 0) || (rightValue == 0)){
02099         /* restore the information */
02100         BmcCnfClausesRestore(cnfClauses, state);
02101         /* add an empty clause*/
02102         BmcAddEmptyClause(cnfClauses);
02103         FREE(state);
02104         return 0;  /* FALSE */
02105       }
02106       if ((leftValue == 1) && (rightValue == 1)){
02107         /* restore the information */
02108         BmcCnfClausesRestore(cnfClauses, state);
02109         FREE(state);
02110         return 0; /* TRUE */
02111       }
02112       BmcCnfClausesUnFreeze(cnfClauses, state);
02113       FREE(state);
02114       /*
02115       tmpclause  = array_alloc(int, 3);
02116       array_insert(int, tmpclause, 0, -left);
02117       array_insert(int, tmpclause, 1, -right);
02118       array_insert(int, tmpclause, 2,  cnfIndex);
02119       array_insert_last(array_t *, clauseArray, tmpclause);
02120       */
02121       if (leftValue == 1){
02122         return right;
02123       }
02124       if (rightValue == 1){
02125         return left;
02126       }
02127       cnfIndex = cnfClauses->cnfGlobalIndex++;      
02128       tmpclause  = array_alloc(int, 2);
02129       
02130       array_insert(int, tmpclause, 0, left);
02131       array_insert(int, tmpclause, 1, -cnfIndex);
02132       BmcCnfInsertClause(cnfClauses, tmpclause);
02133       
02134       array_insert(int, tmpclause, 0, right);
02135       array_insert(int, tmpclause, 1, -cnfIndex);
02136       BmcCnfInsertClause(cnfClauses, tmpclause);
02137       array_free(tmpclause);
02138 
02139       return cnfIndex;
02140     case Ctlsp_OR_c:
02141       /*
02142           c = a + b  -->  (a + b + !c) * (!a + c) * (!b + c).
02143           Because a and b must be one, so we need only the first clause.
02144        */
02145       state = BmcCnfClausesFreeze(cnfClauses);
02146             
02147       left      = BmcGenerateCnfForLtl(network, ltlFormula->left,  i, k, l, cnfClauses);
02148       leftValue = checkIndex(left, cnfClauses);
02149 
02150       if (leftValue !=1){
02151         right      = BmcGenerateCnfForLtl(network, ltlFormula->right, i, k, l, cnfClauses);
02152         rightValue = checkIndex(right, cnfClauses);
02153       }
02154       if ((leftValue == 1) || (rightValue == 1)){
02155         /* restore the information */
02156         BmcCnfClausesRestore(cnfClauses, state);
02157         FREE(state);
02158         return 0;  /* TRUE */
02159       } 
02160       if ((leftValue == 0) && (rightValue == 0)){
02161         /* restore the information */
02162         BmcCnfClausesRestore(cnfClauses, state);
02163         /* add an empty clause*/
02164         BmcAddEmptyClause(cnfClauses);
02165         FREE(state);
02166         return 0;  /* FALSE */
02167       }
02168       BmcCnfClausesUnFreeze(cnfClauses, state);
02169       FREE(state);
02170       /* Either leftValue or rightValue = 0 and the other != 1
02171          At least one clause will be added
02172        */
02173       if (leftValue == 0){
02174         return right;
02175       }
02176       if (rightValue == 0){
02177         return left;
02178       }      
02179       cnfIndex = cnfClauses->cnfGlobalIndex++;
02180 
02181       tmpclause  = array_alloc(int, 0);
02182       array_insert_last(int, tmpclause, -cnfIndex);
02183       
02184       array_insert_last(int, tmpclause, left);
02185         /*
02186         tmpclause  = array_alloc(int, 2);
02187         array_insert(int, tmpclause, 0, -left);
02188         array_insert(int, tmpclause, 1, cnfIndex);
02189         array_insert_last(array_t *, clauseArray, tmpclause);
02190         */
02191       array_insert_last(int, tmpclause, right);
02192         /*
02193         tmpclause  = array_alloc(int, 2);
02194         array_insert(int, tmpclause, 0, -right);
02195         array_insert(int, tmpclause, 1, cnfIndex);
02196         array_insert_last(array_t *, clauseArray, tmpclause);
02197         */
02198       BmcCnfInsertClause(cnfClauses, tmpclause);
02199       array_free(tmpclause);
02200       
02201       return cnfIndex;
02202     case Ctlsp_F_c:
02203       if (l >= 0){ /* loop */
02204         i = (l < i)? l: i;
02205       }
02206       cnfIndex = cnfClauses->cnfGlobalIndex++;
02207       clause   = array_alloc(int, 0);
02208       for (j=i; j<= k; j++){
02209         left      = BmcGenerateCnfForLtl(network, ltlFormula->left, j, k, l, cnfClauses);
02210         leftValue = checkIndex(left, cnfClauses);
02211         if (leftValue != -1){
02212           array_free(clause);
02213           return 0;
02214         }
02215         array_insert_last(int, clause, left);
02216           /*
02217           tmpclause  = array_alloc(int, 2);
02218           array_insert(int, tmpclause, 1, cnfIndex);
02219           array_insert(int, tmpclause, 0, -left);
02220           array_insert_last(array_t *, clauseArray, tmpclause);
02221           */
02222       }
02223       array_insert_last(int, clause, -cnfIndex);
02224       BmcCnfInsertClause(cnfClauses, clause);
02225       array_free(clause);
02226  
02227       return cnfIndex;
02228     case Ctlsp_G_c:
02229       if (l < 0){ /* FALSE */
02230         /* add an empty clause */
02231         BmcAddEmptyClause(cnfClauses);
02232         return 0;
02233       } else {
02234        i = (l < i)? l: i;
02235        andIndex = cnfClauses->cnfGlobalIndex++;
02236        for (j=i; j<= k; j++){
02237          left      = BmcGenerateCnfForLtl(network, ltlFormula->left, j, k, l, cnfClauses);
02238          leftValue = checkIndex(left, cnfClauses);
02239          if (leftValue != -1){
02240            return 0;
02241          }
02242          tmpclause  = array_alloc(int, 2);
02243          array_insert(int, tmpclause, 0, left);
02244          array_insert(int, tmpclause, 1, -andIndex);
02245          BmcCnfInsertClause(cnfClauses, tmpclause);
02246          array_free(tmpclause);
02247        }/* for j loop*/
02248       } /* else */
02249       return andIndex;
02250     case Ctlsp_X_c:
02251       /* X left */
02252       if((l >= 0) && (i == k) ){
02253         i = l;
02254       } else if (i < k){
02255         i = i + 1;
02256       } else { /* FALSE */
02257         /* add an empty clause */
02258         BmcAddEmptyClause(cnfClauses);
02259         return 0;
02260       }
02261       return BmcGenerateCnfForLtl(network, ltlFormula->left, i, k, l, cnfClauses);
02262     case Ctlsp_U_c: /* (left U right) */
02263       state = BmcCnfClausesFreeze(cnfClauses);
02264       
02265       leftValue  = 1; /* left is TRUE*/
02266       rightValue = 1; /* right is TRUE*/
02267       orIndex    = cnfClauses->cnfGlobalIndex++;
02268       orClause   = array_alloc(int, 0);
02269       array_insert_last(int, orClause, -orIndex);
02270 
02271       orValue = 0;
02272       for (j=i; j<= k; j++){
02273         right = BmcGenerateCnfForLtl(network, ltlFormula->right, j, k, l, cnfClauses);
02274         rightValue = checkIndex(right, cnfClauses);
02275         andIndex   = cnfClauses->cnfGlobalIndex++;
02276         if (rightValue == -1){
02277           rightClause  = array_alloc(int, 2);
02278           array_insert(int, rightClause, 0, right);
02279           array_insert(int, rightClause, 1, -andIndex);
02280           BmcCnfInsertClause(cnfClauses, rightClause);
02281           array_free(rightClause);
02282         }
02283         andValue = rightValue;
02284         for (n=i; (n <= j-1) && (andValue != 0); n++){
02285           left = BmcGenerateCnfForLtl(network, ltlFormula->left, n, k, l, cnfClauses);
02286           leftValue = checkIndex(left, cnfClauses);
02287           andValue  = doAnd(andValue, leftValue);
02288           if (leftValue == -1){
02289             leftClause  = array_alloc(int, 2);
02290             array_insert(int, leftClause, 0, left);
02291             array_insert(int, leftClause, 1, -andIndex);
02292             BmcCnfInsertClause(cnfClauses, leftClause);
02293             array_free(leftClause);
02294           }
02295         } /* for n loop */
02296         orValue = doOr(orValue, andValue);
02297         if (orValue == 1){ /* TRUE */
02298           break;
02299         }
02300         if (andValue != 0){
02301           array_insert_last(int, orClause, andIndex);
02302         }
02303       } /* for j loop*/
02304       if ( (l >=0) && (orValue !=1)){ /* loop */
02305         for (j=l; j<= i-1; j++){
02306           right = BmcGenerateCnfForLtl(network, ltlFormula->right, j, k, l, cnfClauses);
02307           rightValue = checkIndex(right, cnfClauses);
02308           andIndex   = cnfClauses->cnfGlobalIndex++;
02309           if (rightValue == -1){
02310             rightClause  = array_alloc(int, 2);
02311             array_insert(int, rightClause, 0, right);
02312             array_insert(int, rightClause, 1, -andIndex);
02313             BmcCnfInsertClause(cnfClauses, rightClause);
02314             array_free(rightClause);
02315           }
02316           andValue = rightValue;  
02317           for (n=i; (n<= k) && (andValue != 0); n++){
02318             left = BmcGenerateCnfForLtl(network, ltlFormula->left, n, k, l, cnfClauses);
02319             leftValue = checkIndex(left, cnfClauses);
02320             andValue  = doAnd(andValue, leftValue);
02321             if (leftValue == -1){
02322               leftClause  = array_alloc(int, 2);
02323               array_insert(int, leftClause, 0, left);
02324               array_insert(int, leftClause, 1, -andIndex);
02325               BmcCnfInsertClause(cnfClauses, leftClause);
02326               array_free(leftClause);
02327             }
02328           } /* for n loop */
02329           for (n=l; (n<= j-1)  && (andValue != 0); n++){
02330             left = BmcGenerateCnfForLtl(network, ltlFormula->left, n, k, l, cnfClauses);
02331             leftValue = checkIndex(left, cnfClauses);
02332             andValue  = doAnd(andValue, leftValue);
02333             if (leftValue == -1){
02334               leftClause  = array_alloc(int, 2);
02335               array_insert(int, leftClause, 0, left);
02336               array_insert(int, leftClause, 1, -andIndex);
02337               BmcCnfInsertClause(cnfClauses, leftClause);
02338               array_free(leftClause);
02339             }
02340           } /* for n loop */
02341           orValue = doOr(orValue, andValue);
02342           if (orValue == 1){ /* TRUE */
02343             break;
02344           }
02345           if (andValue != 0){
02346             array_insert_last(int, orClause, andIndex);
02347           }
02348         }/* j loop*/
02349       } /* if (l>=0) */
02350       if ((orValue == 1) || (orValue == 0)){
02351         /*restore the infomration back*/
02352         BmcCnfClausesRestore(cnfClauses, state);
02353         FREE(state);
02354         array_free(orClause);
02355         if (orValue == 0){
02356           /* add an empty clause*/
02357           BmcAddEmptyClause(cnfClauses);
02358         }
02359         return 0;
02360       } else {
02361         BmcCnfClausesUnFreeze(cnfClauses, state);
02362         FREE(state);
02363         BmcCnfInsertClause(cnfClauses, orClause);
02364         array_free(orClause);
02365         return orIndex;
02366       }
02367     case Ctlsp_R_c:
02368       /* (left R right) */
02369       state = BmcCnfClausesFreeze(cnfClauses);
02370       
02371       orIndex  = cnfClauses->cnfGlobalIndex++;
02372       orClause = array_alloc(int, 0);
02373       array_insert_last(int, orClause, -orIndex);
02374       
02375       orValue = 0;
02376       if (l >= 0){ /* loop */
02377         andIndex = cnfClauses->cnfGlobalIndex++;
02378         andValue = 1;
02379         for (j=(i<l?i:l); (j<= k) && (andValue != 0); j++){
02380           right = BmcGenerateCnfForLtl(network, ltlFormula->right, j, k, l, cnfClauses);
02381           rightValue = checkIndex(right, cnfClauses);
02382           andValue  = doAnd(andValue, rightValue);
02383           if (rightValue == -1){
02384             rightClause  = array_alloc(int, 2);
02385             array_insert(int, rightClause, 0, right);
02386             array_insert(int, rightClause, 1, -andIndex);
02387             BmcCnfInsertClause(cnfClauses, rightClause);
02388             array_free(rightClause);
02389           }
02390         } /* for j loop*/
02391         if (andValue == -1){
02392           array_insert_last(int, orClause, andIndex);
02393         }
02394         orValue = doOr(orValue, andValue);
02395       } /* loop */
02396       if(orValue != 1){
02397         for (j=i; j<= k; j++){
02398           left = BmcGenerateCnfForLtl(network, ltlFormula->left,
02399                                       j, k, l, cnfClauses);
02400           leftValue = checkIndex(left, cnfClauses);
02401           andIndex = cnfClauses->cnfGlobalIndex++;
02402           if (leftValue == -1){
02403             leftClause  = array_alloc(int, 2);
02404             array_insert(int, leftClause, 0, left);
02405             array_insert(int, leftClause, 1, -andIndex);
02406             BmcCnfInsertClause(cnfClauses, leftClause);
02407             array_free(leftClause);
02408           }
02409           andValue = leftValue;
02410           for (n=i; (n<= j) && (andValue != 0); n++){
02411             right = BmcGenerateCnfForLtl(network, ltlFormula->right,
02412                                          n, k, l, cnfClauses);
02413             rightValue = checkIndex(right, cnfClauses);
02414             andValue   = doAnd(andValue, rightValue);
02415             if (rightValue == -1){
02416               rightClause  = array_alloc(int, 2);
02417               array_insert(int, rightClause, 0, right);
02418               array_insert(int, rightClause, 1, -andIndex);
02419               BmcCnfInsertClause(cnfClauses, rightClause);
02420               array_free(rightClause);
02421             }
02422           } /* for n loop */
02423           orValue = doOr(orValue, andValue);
02424           if (orValue == 1){ /* TRUE */
02425             break;
02426           }
02427           if (andValue != 0){
02428             array_insert_last(int, orClause, andIndex);
02429           }
02430         }/* for j loop*/
02431         if ((l >= 0)  && (orValue !=1)) { /* loop */
02432           for (j=l; j<= i-1; j++){
02433             left = BmcGenerateCnfForLtl(network, ltlFormula->left,
02434                                         j, k, l, cnfClauses);
02435             leftValue = checkIndex(left, cnfClauses);
02436             andIndex = cnfClauses->cnfGlobalIndex++;
02437             if (leftValue == -1){
02438               leftClause  = array_alloc(int, 2);
02439               array_insert(int, leftClause, 0, left);
02440               array_insert(int, leftClause, 1, -andIndex);
02441               BmcCnfInsertClause(cnfClauses, leftClause);
02442               array_free(leftClause);
02443             }
02444             andValue = leftValue;
02445             for (n=i; (n<= k)  && (andValue != 0); n++){
02446               right = BmcGenerateCnfForLtl(network, ltlFormula->right,
02447                                            n, k, l, cnfClauses);
02448               rightValue = checkIndex(right, cnfClauses);
02449               andValue = doAnd(andValue, rightValue);
02450               if (rightValue == -1){
02451                 rightClause  = array_alloc(int, 2);
02452                 array_insert(int, rightClause, 0, right);
02453                 array_insert(int, rightClause, 1, -andIndex);
02454                 BmcCnfInsertClause(cnfClauses, rightClause);
02455                 array_free(rightClause);
02456               }
02457             } /* for n loop */
02458             for (n=l; (n<= j) && (andValue != 0); n++){
02459               right = BmcGenerateCnfForLtl(network, ltlFormula->right,
02460                                            n, k, l, cnfClauses);
02461               rightValue = checkIndex(right, cnfClauses);
02462               andValue = doAnd(andValue, rightValue);
02463               if (rightValue == -1){
02464                 rightClause  = array_alloc(int, 2);
02465                 array_insert(int, rightClause, 0, right);
02466                 array_insert(int, rightClause, 1, -andIndex);
02467                 BmcCnfInsertClause(cnfClauses, rightClause);
02468                 array_free(rightClause);
02469               }
02470             } /* for n loop */
02471             orValue = doOr(orValue, andValue);
02472             if (orValue == 1){ /* TRUE */
02473               break;
02474             }
02475             if (andValue != 0){
02476               array_insert_last(int, orClause, andIndex);
02477             }
02478           } /* for j loop*/
02479         } /* if (l>=0) */
02480       }/* orValue !=1*/
02481       if ((orValue == 1) || (orValue == 0)){
02482         /*restore the infomration back*/
02483         BmcCnfClausesRestore(cnfClauses, state);
02484         FREE(state);
02485         array_free(orClause);
02486         if (orValue == 0){
02487           /* add an empty clause*/
02488           BmcAddEmptyClause(cnfClauses);
02489         }
02490         return 0;
02491       } else {
02492         BmcCnfClausesUnFreeze(cnfClauses, state);
02493         FREE(state);
02494         BmcCnfInsertClause(cnfClauses, orClause);
02495         array_free(orClause);
02496         return orIndex;
02497       }
02498     default:
02499       fail("Unexpected LTL formula type");
02500       break;
02501   }
02502   return -1; /* we should never get here */
02503 }
02504 /*  BmcLTLFormulaNoLoopTranslation() */
02505 
02506 
02523 void
02524 BmcLtlCheckSafety(
02525    Ntk_Network_t   *network,
02526    Ctlsp_Formula_t *ltlFormula,
02527    BmcOption_t     *options,
02528    st_table        *CoiTable)
02529 {
02530   mAig_Manager_t    *manager = Ntk_NetworkReadMAigManager(network);
02531   st_table          *nodeToMvfAigTable = NIL(st_table);  /* node to mvfAig */
02532   BmcCnfClauses_t   *cnfClauses = NIL(BmcCnfClauses_t);
02533   FILE              *cnfFile;
02534   int               noLoopIndex;
02535   array_t           *result = NIL(array_t);
02536   int               leftValue  = 0;
02537   long              startTime, endTime;
02538   int               k;
02539   int               minK = options->minK;
02540   int               maxK = options->maxK;
02541   boolean           boundedFormula;
02542   int               depth;
02543   array_t           *unitClause =  array_alloc(int, 1);
02544   
02545   array_t           *orClause =  array_alloc(int, 2);
02546 
02547   /* ************** */
02548   /* Initialization */
02549   /* ************** */
02550   startTime = util_cpu_ctime();
02551   /* nodeToMvfAigTable maps each node to its multi-function And/Inv graph */
02552   nodeToMvfAigTable =
02553     (st_table *) Ntk_NetworkReadApplInfo(network, MVFAIG_NETWORK_APPL_KEY);
02554   assert(nodeToMvfAigTable != NIL(st_table));
02555 
02556   /* For bounded formulae use a tighter upper bound if possible. */
02557   boundedFormula = Ctlsp_LtlFormulaTestIsBounded(ltlFormula, &depth);
02558   if (boundedFormula && depth < maxK && depth >= minK) {
02559     maxK = depth;
02560   }
02561   if (options->verbosityLevel != BmcVerbosityNone_c){
02562     (void) fprintf(vis_stdout, "saftey LTL BMC\n");
02563     if (boundedFormula){
02564       (void) fprintf(vis_stdout, "Bounded formula of depth %d\n", depth);
02565     }
02566     (void) fprintf(vis_stdout, "Apply BMC on counterexample of length >= %d and <= %d (+%d) \n",
02567                   minK, maxK, options->step);
02568   }
02569   k= minK;
02570   while( (result == NIL(array_t)) && (k <= maxK)){
02571     if (options->verbosityLevel == BmcVerbosityMax_c) {
02572       (void) fprintf(vis_stdout, "\nGenerate counterexample of length %d\n", k);
02573     }
02574     cnfClauses = BmcCnfClausesAlloc();
02575     cnfFile = Cmd_FileOpen(options->satInFile, "w", NIL(char *), 0);  
02576     if (cnfFile == NIL(FILE)) {
02577       (void)fprintf(vis_stderr,
02578                     "** bmc error: Cannot create CNF output file %s\n",
02579                     options->satInFile);
02580       return;
02581     }
02582     BmcCnfGenerateClausesForPath(network, 0, k, BMC_INITIAL_STATES,
02583                                  cnfClauses, nodeToMvfAigTable, CoiTable);
02584     noLoopIndex = BmcGenerateCnfForLtl(network, ltlFormula, 0, k, -1, cnfClauses);
02585     leftValue   = checkIndex(noLoopIndex, cnfClauses);
02586 
02587     if(leftValue == 1){
02588       assert(k==1);
02589       if (options->verbosityLevel != BmcVerbosityNone_c){
02590         (void) fprintf(vis_stdout,"# BMC: formula failed\n");
02591         (void) fprintf(vis_stdout,"# BMC: Empty counterexample because the property is always FALSE\n");
02592       }
02593       break;
02594     } else if(leftValue == 0){
02595       if (options->verbosityLevel != BmcVerbosityNone_c){
02596         (void) fprintf(vis_stdout,"# BMC: the formula is trivially true");
02597         (void) fprintf(vis_stdout," for counterexamples of length %d\n", k);
02598       }
02599       /*
02600       break;
02601       */
02602     } else {
02603       array_insert(int, unitClause, 0, noLoopIndex);
02604       
02605       BmcCnfInsertClause(cnfClauses, unitClause);
02606       
02607       BmcWriteClauses(manager, cnfFile, cnfClauses, options);
02608       (void) fclose(cnfFile);
02609       result = BmcCheckSAT(options);
02610       if (options->satSolverError){
02611         break;
02612       }
02613       if(result != NIL(array_t)) {
02614         (void) fprintf(vis_stdout, "# BMC: formula failed\n");
02615         if(options->verbosityLevel != BmcVerbosityNone_c){
02616           (void) fprintf(vis_stdout,
02617                          "# BMC: Found a counterexample of length = %d \n", k);
02618         }
02619         if (options->dbgLevel == 1) {
02620           BmcPrintCounterExample(network, nodeToMvfAigTable, cnfClauses,
02621                                  result, k, CoiTable, options, NIL(array_t));
02622         }
02623         break;
02624       }
02625     }
02626     /* free all used memories */
02627     BmcCnfClausesFree(cnfClauses);
02628 #if 0
02629 
02630     /*
02631       Check induction
02632      */
02633     {
02634       BmcCnfClauses_t   *noLoopCnfClauses = BmcCnfClausesAlloc();
02635       array_t           *noLoopResult = NIL(array_t);
02636       array_t           *unitClause =  array_alloc(int, 1);
02637       int               i;
02638 
02639       printf("Check Induction \n");
02640 
02641       cnfFile = Cmd_FileOpen(options->satInFile, "w", NIL(char *), 0);  
02642       if (cnfFile == NIL(FILE)) {
02643         (void)fprintf(vis_stderr,
02644                       "** bmc error: Cannot create CNF output file %s\n",
02645                       options->satInFile);
02646         return;
02647       }
02648       /*
02649         Generate a loop free path
02650       */
02651       BmcCnfGenerateClausesForLoopFreePath(network, 0, k+1, BMC_NO_INITIAL_STATES,
02652                                            noLoopCnfClauses, nodeToMvfAigTable, CoiTable);
02653       /*
02654         The property true at states from 0 to k
02655        */
02656       unitClause = array_alloc(int, 1);
02657       for(i=0; i<=k; i++){
02658         array_insert(int, unitClause, 0, 
02659                      -BmcGenerateCnfForLtl(network, ltlFormula, i, k, -1, noLoopCnfClauses));
02660         BmcCnfInsertClause(noLoopCnfClauses, unitClause);
02661       }
02662       
02663       /*
02664         The property fails at k +1
02665        */
02666       array_insert(int, unitClause, 0, 
02667                    BmcGenerateCnfForLtl(network, ltlFormula, 0, k+1, -1, noLoopCnfClauses));
02668       BmcCnfInsertClause(noLoopCnfClauses, unitClause);
02669       array_free(unitClause);
02670    
02671       BmcWriteClauses(manager, cnfFile, noLoopCnfClauses, options);
02672       (void) fclose(cnfFile);
02673       noLoopResult = BmcCheckSAT(options);
02674       if(noLoopResult == NIL(array_t)) {
02675         (void) fprintf(vis_stdout, "# BMC: formula passed\n");
02676         (void) fprintf(vis_stdout,
02677                        "# BMC: No more loop free path \n");
02678         
02679         break;
02680       }
02681       /*
02682         BmcPrintCounterExample(network, nodeToMvfAigTable, noLoopCnfClauses,
02683         noLoopResult, bound+1, CoiTable, options, NIL(array_t));
02684       */
02685       BmcCnfClausesFree(noLoopCnfClauses);
02686     } /* Check induction */
02687  
02688 #endif
02689     k += options->step;
02690 
02691 #if 0
02692     
02693     /* Check if reach the depth of the model */
02694     cnfClauses = BmcCnfClausesAlloc();
02695     cnfFile = Cmd_FileOpen(options->satInFile, "w", NIL(char *), 0);  
02696     if (cnfFile == NIL(FILE)) {
02697       (void)fprintf(vis_stderr,
02698                     "** bmc error: Cannot create CNF output file %s\n",
02699                     options->satInFile);
02700       return;
02701     }
02702     /*
02703       Generate a loop free path
02704      */
02705     {
02706       BmcCnfGenerateClausesForPath(network, 0, k, BMC_INITIAL_STATES,
02707                                    cnfClauses, nodeToMvfAigTable, CoiTable);
02708       /*
02709         initIndex   = BmcCnfGenerateClausesFromStateToState(network, -1, 0, cnfClauses, nodeToMvfAigTable, CoiTable, -1);
02710         noLoopIndex = BmcGenerateCnfForLtl(network, ltlFormula, 0, k, -1, cnfClauses);
02711         
02712         array_insert(int, orClause, 0, initIndex);
02713         array_insert(int, orClause, 1, -noLoopIndex);
02714         
02715         BmcCnfInsertClause(cnfClauses, orClause);
02716       */
02717       BmcWriteClauses(manager, cnfFile, cnfClauses, options);
02718       (void) fclose(cnfFile);
02719       result = BmcCheckSAT(options);
02720       if(result == NIL(array_t)) {
02721         (void) fprintf(vis_stdout, "# BMC: formula passed\n");
02722         (void) fprintf(vis_stdout,
02723                        "# BMC: No more loop free path \n");
02724         
02725         return;
02726       }
02727       /*
02728         BmcPrintCounterExample(network, nodeToMvfAigTable, cnfClauses,
02729         result, k, CoiTable, options, NIL(array_t));
02730       */
02731       result = NIL(array_t);
02732     }
02733     BmcCnfClausesFree(cnfClauses);
02734 
02735 
02736     /* Check if reach the depth of the model */
02737     cnfClauses = BmcCnfClausesAlloc();
02738     cnfFile = Cmd_FileOpen(options->satInFile, "w", NIL(char *), 0);  
02739     if (cnfFile == NIL(FILE)) {
02740       (void)fprintf(vis_stderr,
02741                     "** bmc error: Cannot create CNF output file %s\n",
02742                     options->satInFile);
02743       return;
02744     }
02745     /*
02746       Generate a loop free path
02747      */
02748     {
02749       BmcCnfGenerateClausesForPath(network, 0, k, BMC_NO_INITIAL_STATES,
02750                                    cnfClauses, nodeToMvfAigTable, CoiTable);
02751       /*
02752         initIndex   = BmcCnfGenerateClausesFromStateToState(network, -1, 0, cnfClauses, nodeToMvfAigTable, CoiTable, -1);
02753       */
02754       noLoopIndex = BmcGenerateCnfForLtl(network, ltlFormula, 0, k, -1, cnfClauses);
02755       array_insert(int, unitClause, 0, noLoopIndex);
02756       
02757       BmcCnfInsertClause(cnfClauses, unitClause);
02758       /*
02759         array_insert(int, orClause, 0, initIndex);
02760         array_insert(int, orClause, 1, -noLoopIndex);
02761         
02762         BmcCnfInsertClause(cnfClauses, orClause);
02763       */
02764       BmcWriteClauses(manager, cnfFile, cnfClauses, options);
02765       (void) fclose(cnfFile);
02766       result = BmcCheckSAT(options);
02767       if(result == NIL(array_t)) {
02768         (void) fprintf(vis_stdout, "# BMC: (Bad state) formula passed\n");
02769         (void) fprintf(vis_stdout,
02770                        "# BMC: No more loop free path \n");
02771         
02772         return;
02773       }
02774       /*
02775         BmcPrintCounterExample(network, nodeToMvfAigTable, cnfClauses,
02776         result, k, CoiTable, options, NIL(array_t));
02777       */
02778       result = NIL(array_t);
02779     }
02780     BmcCnfClausesFree(cnfClauses);
02781 #endif
02782     
02783     
02784   } /* while result and k*/
02785   if (options->satSolverError == FALSE){
02786     if ((result == NIL(array_t)) && (k > maxK)){
02787       if (boundedFormula && depth <= options->maxK){
02788         (void) fprintf(vis_stdout,"# BMC: formula passed\n");
02789       } else {
02790         (void) fprintf(vis_stdout,"# BMC: formula undecided\n");
02791       }
02792       if (options->verbosityLevel != BmcVerbosityNone_c){
02793         (void) fprintf(vis_stdout,
02794                        "# BMC: no counterexample found of length up to %d \n",
02795                        maxK);
02796       }
02797     }
02798   }
02799   /* free all used memories */
02800   if (k == 0){
02801      BmcCnfClausesFree(cnfClauses);
02802   }
02803   if(result != NIL(array_t)){
02804     array_free(result);
02805   }
02806   if (options->verbosityLevel != BmcVerbosityNone_c) {
02807     endTime = util_cpu_ctime();
02808     fprintf(vis_stdout, "-- bmc time = %10g\n",
02809             (double)(endTime - startTime) / 1000.0);
02810   }
02811   array_free(unitClause);
02812   array_free(orClause);
02813   fflush(vis_stdout);
02814   return;
02815 } /* BmcLtlCheckSafety() */
02816 
02817 
02818 /*---------------------------------------------------------------------------*/
02819 /* Definition of static functions                                            */
02820 /*---------------------------------------------------------------------------*/
02821 
02822 
02833 static int
02834 checkIndex(
02835   int             index,
02836   BmcCnfClauses_t *cnfClauses)
02837 {
02838   int     rtnValue = -1; /* it is not TRUE or FALSE*/
02839 
02840   if (index == 0){ /* TRUE or FALSE*/
02841     if (cnfClauses->emptyClause){   /* last added clause was empty = FALSE*/
02842       rtnValue = 0; /* FALSE */
02843     } else {
02844       /*
02845         if (cnfClauses->noOfClauses == 0)
02846         rtnValue = 1;
02847         }
02848       */
02849       rtnValue = 1; /* TRUE */
02850     }
02851   }
02852   return rtnValue;
02853 }
02854 
02871 static int
02872 doAnd(
02873   int left,
02874   int right)
02875 {
02876   if ((left == -1) && (right == -1)){
02877     return -1;
02878   }
02879   return (left * right);
02880   
02881 } /* doAnd */
02882 
02899 static int
02900 doOr(
02901   int left,
02902   int right)
02903 {
02904   if ((left == -1) || (right == -1)){
02905     return -1;
02906   }
02907   if ((left == 1) || (right == 1)){
02908     return 1;
02909   }
02910   return 0;
02911   
02912 } /* doOr */