VIS
|
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 */