VIS
|
00001 00017 #include "ltlInt.h" 00018 #include <errno.h> 00019 00020 static char rcsid[] UNUSED = "$Id: ltl.c,v 1.74 2009/04/11 01:41:30 fabio Exp $"; 00021 00022 /*---------------------------------------------------------------------------*/ 00023 /* Constant declarations */ 00024 /*---------------------------------------------------------------------------*/ 00025 00026 /*---------------------------------------------------------------------------*/ 00027 /* Structure declarations */ 00028 /*---------------------------------------------------------------------------*/ 00029 00030 /*---------------------------------------------------------------------------*/ 00031 /* Type declarations */ 00032 /*---------------------------------------------------------------------------*/ 00033 00034 /*---------------------------------------------------------------------------*/ 00035 /* Variable declarations */ 00036 /*---------------------------------------------------------------------------*/ 00037 static jmp_buf timeOutEnv; 00038 00039 00040 /*---------------------------------------------------------------------------*/ 00041 /* Macro declarations */ 00042 /*---------------------------------------------------------------------------*/ 00043 00046 /*---------------------------------------------------------------------------*/ 00047 /* Static function prototypes */ 00048 /*---------------------------------------------------------------------------*/ 00049 00050 static int CommandLtlMc(Hrc_Manager_t ** hmgr, int argc, char ** argv); 00051 static int CommandLtl2Aut(Hrc_Manager_t ** hmgr, int argc, char ** argv); 00052 static LtlMcOption_t * ParseLtlMcOptions(int argc, char **argv); 00053 static LtlMcOption_t * ParseLtlTestOptions(int argc, char **argv); 00054 static boolean LtlMcAtomicFormulaCheckSemantics(Ctlsp_Formula_t *formula, Ntk_Network_t *network, boolean inputsAllowed); 00055 static void TimeOutHandle(void); 00056 static void ShuffleMddIdsToTop(mdd_manager *mddManager, array_t *mddIdArray); 00057 00061 /*---------------------------------------------------------------------------*/ 00062 /* Definition of exported functions */ 00063 /*---------------------------------------------------------------------------*/ 00064 00074 void 00075 Ltl_Init(void) 00076 { 00077 /* LTL model checking. Before using this command, the design must be read 00078 * and 'init_verify' has been executed. 00079 */ 00080 Cmd_CommandAdd("ltl_model_check", CommandLtlMc, 0); 00081 00082 /* Test the LTL->Buechi Automaton Translator, may or may not need to read 00083 * the design. But If the design is read, the semantic of the formula 00084 * will be checked on the model before translation 00085 */ 00086 Cmd_CommandAdd("ltl_to_aut", CommandLtl2Aut, 0); 00087 } 00088 00089 00099 void 00100 Ltl_End(void) 00101 { 00102 } 00103 00104 00116 Ltl_Automaton_t * 00117 Ltl_McFormulaToAutomaton( 00118 Ntk_Network_t *network, 00119 Ctlsp_Formula_t *Formula, 00120 int options_algorithm, 00121 int options_rewriting, 00122 int options_prunefair, 00123 int options_iocompatible, 00124 int options_directsim, 00125 int options_reversesim, 00126 int options_directsimMaximize, 00127 int options_verbosity, 00128 int checkSemantics 00129 ) 00130 { 00131 LtlMcOption_t *options = LtlMcOptionAlloc(); 00132 Ltl_Automaton_t *aut; 00133 00134 options->algorithm = (Ltl2AutAlgorithm) options_algorithm; 00135 if (options_algorithm == Ltl2Aut_WRING_c) { 00136 options->rewriting = 1; 00137 options->prunefair = 1; 00138 options->iocompatible = 1; 00139 options->directsim = 1; 00140 options->reversesim = 1; 00141 }else { 00142 options->rewriting = options_rewriting; 00143 options->prunefair = options_prunefair; 00144 options->iocompatible = options_iocompatible; 00145 options->directsim = options_directsim; 00146 options->reversesim = options_reversesim; 00147 } 00148 options->directsimMaximize = options_directsimMaximize; 00149 options->verbosity = (Mc_VerbosityLevel) options_verbosity; 00150 00151 aut = LtlMcFormulaToAutomaton(network, Formula, options, checkSemantics); 00152 00153 LtlMcOptionFree(options); 00154 00155 return aut; 00156 } 00157 00158 00175 Hrc_Manager_t * 00176 Ltl_McAutomatonToNetwork( 00177 Ntk_Network_t *designNetwork, 00178 Ltl_Automaton_t *automaton, 00179 int verbosity) 00180 { 00181 FILE *fp; 00182 Hrc_Manager_t *buechiHrcMgr; 00183 Hrc_Node_t *buechiHrcNode; 00184 Ntk_Network_t *buechiNetwork; 00185 int flag; 00186 00187 /* 1) translate the automaton to a temporary blif_mv file */ 00188 fp = tmpfile(); 00189 if (fp == NIL(FILE)) { 00190 fail("Aut->Ntk: can't open temp file"); 00191 } 00192 #ifdef DEBUG_LTLMC 00193 if (verbosity >= 2) { 00194 fprintf(vis_stdout, "\nPrint the automaton Blif_Mv file:\n"); 00195 flag = Ltl_AutomatonToBlifMv(vis_stdout, designNetwork, automaton); 00196 fprintf(vis_stdout, "\n"); 00197 fflush(vis_stdout); 00198 } 00199 #endif 00200 flag = Ltl_AutomatonToBlifMv(fp, designNetwork, automaton); 00201 if (!flag) { 00202 return NIL(Hrc_Manager_t); 00203 } 00204 00205 /* 2) read and parse the tmp blifmv file */ 00206 rewind(fp); 00207 error_init(); 00208 buechiHrcMgr = Io_BlifMvRead(fp, NIL(Hrc_Manager_t), 0, 0, 0); 00209 fclose(fp); 00210 if (buechiHrcMgr == NIL(Hrc_Manager_t)) 00211 fail(error_string()); 00212 00213 /* 3) flatten_hierarchy */ 00214 buechiHrcNode = Hrc_ManagerReadCurrentNode(buechiHrcMgr); 00215 buechiNetwork = Ntk_HrcNodeConvertToNetwork(buechiHrcNode, TRUE, (lsList)0); 00216 Hrc_NodeAddApplInfo(buechiHrcNode, NTK_HRC_NODE_APPL_KEY, 00217 (Hrc_ApplInfoFreeFn) Ntk_NetworkFreeCallback, 00218 (Hrc_ApplInfoChangeFn) NULL, 00219 (void *) buechiNetwork); 00220 00221 /* 4) static_order (!!! using the default mddManager) */ 00222 Ntk_NetworkSetMddManager(buechiNetwork, 00223 Ntk_NetworkReadMddManager(designNetwork)); 00224 Ord_NetworkOrderVariables(buechiNetwork, 00225 Ord_RootsByDefault_c, 00226 Ord_NodesByDefault_c, 00227 FALSE, 00228 Ord_InputAndLatch_c, 00229 Ord_Unassigned_c, 00230 (lsList)NULL, 00231 0); 00232 00233 return buechiHrcMgr; 00234 } 00235 00250 boolean 00251 Ltl_FormulaStaticSemanticCheckOnNetwork( 00252 Ctlsp_Formula_t *formula, 00253 Ntk_Network_t *network, 00254 boolean inputsAllowed 00255 ) 00256 { 00257 boolean lCheck; 00258 boolean rCheck; 00259 Ctlsp_Formula_t *leftChild; 00260 Ctlsp_Formula_t *rightChild; 00261 00262 if(formula == NIL(Ctlsp_Formula_t)){ 00263 return TRUE; 00264 } 00265 00266 if(Ctlsp_FormulaReadType(formula) == Ctlsp_ID_c){ 00267 return LtlMcAtomicFormulaCheckSemantics(formula, network, inputsAllowed); 00268 } 00269 00270 leftChild = Ctlsp_FormulaReadLeftChild(formula); 00271 rightChild = Ctlsp_FormulaReadRightChild(formula); 00272 00273 lCheck = Ltl_FormulaStaticSemanticCheckOnNetwork(leftChild, network, 00274 inputsAllowed); 00275 if(!lCheck) 00276 return FALSE; 00277 00278 rCheck = Ltl_FormulaStaticSemanticCheckOnNetwork(rightChild, network, 00279 inputsAllowed); 00280 if (!rCheck) 00281 return FALSE; 00282 00283 return TRUE; 00284 } 00285 00286 00287 /*---------------------------------------------------------------------------*/ 00288 /* Definition of internal functions */ 00289 /*---------------------------------------------------------------------------*/ 00290 00314 Ltl_Automaton_t * 00315 LtlMcFormulaToAutomaton( 00316 Ntk_Network_t *network, 00317 Ctlsp_Formula_t *Formula, 00318 LtlMcOption_t *options, 00319 int checkSemantics) 00320 { 00321 00322 char *tmpString; 00323 Ctlsp_Formula_t *ltlFormula, *negFormula; 00324 LtlTableau_t *tableau; 00325 Ltl_Automaton_t *automaton; 00326 00327 /* check the semantic of the formula on the given network */ 00328 if (checkSemantics && network != NIL(Ntk_Network_t)) { 00329 if (!network) { 00330 fprintf(vis_stderr, 00331 "ltl_mc error: empty network. use flatten_hierarchy\n"); 00332 return NIL(Ltl_Automaton_t); 00333 } 00334 error_init(); 00335 if (!Ltl_FormulaStaticSemanticCheckOnNetwork(Formula, network, 1)) { 00336 fprintf(vis_stderr, 00337 "ltl_mc error: formula semantic check on design fails:\n%s\n", 00338 error_string()); 00339 return NIL(Ltl_Automaton_t); 00340 } 00341 } 00342 00343 /* print out the given LTL formula */ 00344 fprintf(vis_stdout, "Formula: "); 00345 Ctlsp_FormulaPrint(vis_stdout, Formula); 00346 fprintf(vis_stdout, "\n"); 00347 00348 /* Negate Formula and Expand the abbreaviations */ 00349 negFormula = Ctlsp_FormulaCreate(Ctlsp_NOT_c, Formula, NIL(Ctlsp_Formula_t)); 00350 ltlFormula = Ctlsp_LtlFormulaExpandAbbreviation(negFormula); 00351 tmpString = Ctlsp_FormulaConvertToString(negFormula); 00352 FREE(negFormula); 00353 #ifdef DEBUG_LTLMC 00354 if (options->verbosity) 00355 fprintf(vis_stdout, "\nNegation Print: %s\n", tmpString); 00356 #endif 00357 00358 /* 1) Simplify the formula by 'Rewriting' */ 00359 if (options->rewriting) { 00360 Ctlsp_Formula_t *tmpF = ltlFormula; 00361 ltlFormula = Ctlsp_LtlFormulaSimpleRewriting(ltlFormula); 00362 Ctlsp_FormulaFree(tmpF); 00363 } 00364 00365 /* create the alph_beta table */ 00366 tableau = LtlTableauGenerateTableau(ltlFormula); 00367 tableau->verbosity = options->verbosity; 00368 tableau->algorithm = options->algorithm; 00369 tableau->booleanmin = options->booleanmin; 00370 #ifdef DEBUG_LTLMC 00371 /* print out the tableau rules */ 00372 if (options->verbosity > 1) 00373 LtlTableauPrint(vis_stdout, tableau); 00374 #endif 00375 00376 /* we dont' need this formula any more */ 00377 Ctlsp_FormulaFree(ltlFormula); 00378 00379 00380 /* 2) create the automaton */ 00381 automaton = LtlAutomatonGeneration(tableau); 00382 automaton->name = tmpString; 00383 00384 /* 3-1) minimize the automaton by Pruning fairness */ 00385 if (options->prunefair) { 00386 #ifdef DEBUG_LTLMC 00387 if (options->verbosity >= McVerbosityMax_c) { 00388 Ltl_AutomatonPrint(automaton, options->verbosity); 00389 fprintf(vis_stdout, "\nPruneF-Minimization:\n"); 00390 } 00391 #endif 00392 Ltl_AutomatonMinimizeByPrune(automaton, options->verbosity) ; 00393 } 00394 00395 /* 3-2) minimize the automaton by I/O compatible and dominance */ 00396 if (options->iocompatible) { 00397 #ifdef DEBUG_LTLMC 00398 if (options->verbosity >= McVerbosityMax_c) { 00399 Ltl_AutomatonPrint(automaton, options->verbosity); 00400 fprintf(vis_stdout, "\nIOC-Minimization:\n"); 00401 } 00402 #endif 00403 while(Ltl_AutomatonMinimizeByIOCompatible(automaton,options->verbosity)); 00404 } 00405 00406 /* 3-3) minimize the automaton by Direct Simulation */ 00407 if (options->directsim) { 00408 #ifdef DEBUG_LTLMC 00409 if (options->verbosity >= McVerbosityMax_c) { 00410 Ltl_AutomatonPrint(automaton, options->verbosity); 00411 fprintf(vis_stdout, "\nDirSim-Minimization:\n"); 00412 } 00413 #endif 00414 Ltl_AutomatonMinimizeByDirectSimulation(automaton, options->verbosity); 00415 } 00416 00417 /* 3-4) minimize the automaton by Direct Simulation */ 00418 if (options->reversesim) { 00419 #ifdef DEBUG_LTLMC 00420 if (options->verbosity >= McVerbosityMax_c) { 00421 Ltl_AutomatonPrint(automaton, options->verbosity); 00422 fprintf(vis_stdout, "\nRevSim-Minimization:\n"); 00423 } 00424 #endif 00425 Ltl_AutomatonMinimizeByReverseSimulation(automaton, options->verbosity); 00426 } 00427 00428 /* 3-5) minimize the automaton by Pruning fairness */ 00429 if (options->prunefair) { 00430 #ifdef DEBUG_LTLMC 00431 if (options->verbosity >= McVerbosityMax_c) { 00432 Ltl_AutomatonPrint(automaton, options->verbosity); 00433 fprintf(vis_stdout, "\nPruneF-Minimization:\n"); 00434 } 00435 #endif 00436 Ltl_AutomatonMinimizeByPrune(automaton, options->verbosity) ; 00437 } 00438 /* print out the Buechi automaton */ 00439 if (options->verbosity) { 00440 Ltl_AutomatonPrint(automaton, options->verbosity); 00441 } 00442 00443 return automaton; 00444 } 00445 00459 void 00460 LtlFsmLoadFairness( 00461 Fsm_Fsm_t *compFsm, 00462 Fsm_Fairness_t *designFairness, 00463 int NumberOfFairSets, 00464 int *AutomatonStrength) 00465 { 00466 array_t *fairformulaArray; 00467 Ctlp_Formula_t *F; 00468 int j; 00469 00470 /* The fairness constraint on the model (before ltl_model_check is invoked) 00471 * should be Buechi fairness 00472 */ 00473 if (!Fsm_FairnessTestIsBuchi(designFairness)) { 00474 fprintf(vis_stderr, "ltl_mc error: Can not handle non-Buchi Fairness \n"); 00475 assert(0); 00476 } 00477 00478 /* store the new fairness constraint (for compFsm) */ 00479 fairformulaArray = array_alloc(Ctlp_Formula_t *, 0); 00480 00481 /* copy the fairness constraints from the automaton */ 00482 if (*AutomatonStrength == Mc_Aut_Strong_c/*2*/) { 00483 if (NumberOfFairSets > 0) { 00484 for (j=0; j<NumberOfFairSets; j++) { 00485 char tmpstr[30]; 00486 sprintf(tmpstr, "fair%d$AUT$NTK2", j+1); 00487 F = Ctlp_FormulaCreate(Ctlp_ID_c, (void *)util_strsav(tmpstr), 00488 (void *)util_strsav("1")); 00489 array_insert_last(Ctlp_Formula_t *, fairformulaArray, F); 00490 } 00491 }else { 00492 F = Ctlp_FormulaCreate(Ctlp_ID_c, (void *)util_strsav("fair1$AUT$NTK2"), 00493 (void *)util_strsav("1")); 00494 array_insert_last(Ctlp_Formula_t *, fairformulaArray, F); 00495 } 00496 } 00497 00498 /* copy the fairness constraints on the model */ 00499 for (j=0; j<Fsm_FairnessReadNumConjunctsOfDisjunct(designFairness, 0); j++) { 00500 F = Fsm_FairnessReadFinallyInfFormula(designFairness, 0, j); 00501 if (array_n(fairformulaArray) && Ctlp_FormulaReadType(F) == Ctlp_TRUE_c) 00502 continue; 00503 array_insert_last(Ctlp_Formula_t *,fairformulaArray, Ctlp_FormulaDup(F)); 00504 } 00505 00506 /* this is a conservative conclusion ! */ 00507 if (*AutomatonStrength == Mc_Aut_Terminal_c /*0*/) { 00508 F = array_fetch(Ctlp_Formula_t *, fairformulaArray, 0); 00509 if (array_n(fairformulaArray) > 1 || 00510 Ctlp_FormulaReadType(F) != Ctlp_TRUE_c) { 00511 *AutomatonStrength = Mc_Aut_Weak_c /*1*/; 00512 } 00513 } 00514 00515 /* update the fairness constraints on 'compFsm' */ 00516 Fsm_FsmFairnessUpdate(compFsm, fairformulaArray); 00517 00518 array_free(fairformulaArray); 00519 } 00520 00529 LtlMcOption_t * 00530 LtlMcOptionAlloc(void) 00531 { 00532 LtlMcOption_t *result = ALLOC(LtlMcOption_t, 1); 00533 if (result == NIL(LtlMcOption_t)) 00534 return NIL(LtlMcOption_t); 00535 memset(result, 0, sizeof(LtlMcOption_t)); 00536 00537 result->algorithm = Ltl2Aut_WRING_c; 00538 result->schedule = McGSH_EL_c; 00539 result->lockstep = MC_LOCKSTEP_OFF; 00540 result->outputformat = Aut2File_ALL_c; 00541 00542 return result; 00543 } 00544 00553 void 00554 LtlMcOptionFree( 00555 LtlMcOption_t *result) 00556 { 00557 if (result->ltlFile) 00558 fclose(result->ltlFile); 00559 00560 if (result->debugFile) 00561 fclose(result->debugFile); 00562 00563 if (result->outputfilename) 00564 FREE(result->outputfilename); 00565 00566 FREE(result); 00567 } 00568 00569 00570 /*---------------------------------------------------------------------------*/ 00571 /* Definition of static functions */ 00572 /*---------------------------------------------------------------------------*/ 00573 00865 static int 00866 CommandLtlMc( 00867 Hrc_Manager_t ** hmgr, 00868 int argc, 00869 char ** argv) 00870 { 00871 array_t *ltlArray; 00872 LtlMcOption_t *options; 00873 Ctlsp_Formula_t *ltlFormula; 00874 Ltl_Automaton_t *automaton; 00875 LtlTableau_t *tableau; 00876 Hrc_Manager_t *buechiHrcMgr; 00877 Hrc_Node_t *designNode; 00878 Fsm_Fsm_t *designFsm = NIL(Fsm_Fsm_t); 00879 Fsm_Fsm_t *compFsm = NIL(Fsm_Fsm_t); 00880 Ntk_Network_t *designNetwork,*buechiNetwork = NIL(Ntk_Network_t); 00881 Ntk_Node_t *node1, *node2; 00882 array_t *modelCareStatesArray; 00883 lsGen lsgen2; 00884 lsList nodeList; 00885 graph_t *partition, *save_partition; 00886 mdd_t *fairInitStates, *modelCareStates, *mddOne; 00887 char *designModelName, *name1; 00888 int i; 00889 long startLtlMcTime, endLtlMcTime; 00890 static int timeOutPeriod = 0; 00891 00892 Img_ResetNumberOfImageComputation(Img_Both_c); 00893 00894 if (!(options = ParseLtlMcOptions(argc, argv))) { 00895 return 1; 00896 } 00897 timeOutPeriod = options->timeOutPeriod; 00898 00899 if (options->dbgLevel != 0 && options->direction == McFwd_c) { 00900 (void) fprintf(vis_stderr, "** ltl_mc error: -d is incompatible with -F\n"); 00901 LtlMcOptionFree(options); 00902 return 1; 00903 } 00904 if (options->dcLevel != McDcLevelRch_c && options->direction == McFwd_c) { 00905 (void) fprintf(vis_stderr, "** ltl_mc error: -F can only be used with -D1\n"); 00906 LtlMcOptionFree(options); 00907 return 1; 00908 } 00909 00910 /* 'designFsm' and 'designNetwork' are for the model */ 00911 designFsm = Fsm_HrcManagerReadCurrentFsm(*hmgr); 00912 if (designFsm == NIL(Fsm_Fsm_t)) { 00913 return 1; 00914 } 00915 designNetwork = Ntk_HrcManagerReadCurrentNetwork(*hmgr); 00916 00917 /* Parse LTL formulae */ 00918 ltlArray = Ctlsp_FileParseFormulaArray(options->ltlFile); 00919 if (ltlArray != NIL(array_t)) { 00920 array_t *tmpArray = Ctlsp_FormulaArrayConvertToLTL(ltlArray); 00921 Ctlsp_FormulaArrayFree(ltlArray); 00922 ltlArray = tmpArray; 00923 } 00924 if (ltlArray == NIL(array_t)) { 00925 (void) fprintf(vis_stderr, 00926 "** ltl_mc error: error in parsing formulas from file\n"); 00927 LtlMcOptionFree(options); 00928 return 1; 00929 } 00930 /* Semantic Check of the Ltl formula array on the network */ 00931 arrayForEachItem(Ctlsp_Formula_t *, ltlArray, i, ltlFormula) { 00932 if (!Ltl_FormulaStaticSemanticCheckOnNetwork(ltlFormula, 00933 designNetwork, 1)) { 00934 fprintf(vis_stderr, 00935 "ltl_mc error: formula semantic check on design fails:\n%s\n", 00936 error_string()); 00937 Ctlsp_FormulaArrayFree(ltlArray); 00938 LtlMcOptionFree(options); 00939 return 1; 00940 } 00941 } 00942 00943 /* Set time out processing (if timeOutPeriod is set) */ 00944 if (timeOutPeriod > 0) { 00945 (void) signal(SIGALRM, (void(*)(int))TimeOutHandle); 00946 (void) alarm(timeOutPeriod); 00947 if (setjmp(timeOutEnv) > 0) { 00948 (void) fprintf(vis_stdout, "# LTL_MC: Ltl modelchecking - timeout occurred after %d seconds.\n", timeOutPeriod); 00949 (void) fprintf(vis_stdout, "# LTL_MC: data may be corrupted.\n"); 00950 if (options->verbosity > McVerbosityNone_c) { 00951 (void) fprintf(vis_stdout, "-- total %d image computations and %d preimage computations\n", Img_GetNumberOfImageComputation(Img_Forward_c), Img_GetNumberOfImageComputation(Img_Backward_c)); 00952 } 00953 alarm(0); 00954 return 1; 00955 } 00956 } 00957 startLtlMcTime = util_cpu_time(); 00958 00959 mddOne = mdd_one(Ntk_NetworkReadMddManager(designNetwork)); 00960 00961 /* Start LTL model checking for each formula */ 00962 for (i=0; i<array_n(ltlArray); i++) { 00963 st_table *tbl; 00964 array_t *mddIds; 00965 lsList rootList; 00966 int NumberOfFairSet, AutomatonStrength; 00967 long initialTime, finalTime; /* for checking each formula */ 00968 int nImgComps, nPreComps; 00969 00970 /* stats */ 00971 if (options->verbosity > McVerbosityNone_c) { 00972 initialTime = util_cpu_time(); 00973 nImgComps = Img_GetNumberOfImageComputation(Img_Forward_c); 00974 nPreComps = Img_GetNumberOfImageComputation(Img_Backward_c); 00975 } else { 00976 /* to remove uninitialized variable warning */ 00977 initialTime = 0; 00978 nImgComps = 0; 00979 nPreComps = 0; 00980 } 00981 ltlFormula = array_fetch(Ctlsp_Formula_t *, ltlArray, i); 00982 00983 /*--------------------------------------------------------------------- 00984 * 1) create the Buechi Automaton/Network/Mdd_Order/Partition in a new 00985 * Hrc_Manager. It shares nothing with the Design but the mddManager. 00986 *--------------------------------------------------------------------*/ 00987 automaton = LtlMcFormulaToAutomaton(designNetwork, ltlFormula, options, 1); 00988 assert(automaton != NIL(Ltl_Automaton_t)); 00989 00990 if (options->noStrengthReduction) 00991 AutomatonStrength = Mc_Aut_Strong_c /*2*/; 00992 else 00993 AutomatonStrength = Ltl_AutomatonGetStrength(automaton); 00994 00995 /* add arcs by Direct Simulation, to reduce the counter-example length */ 00996 if (options->directsimMaximize) { 00997 #ifdef DEBUG_LTLMC 00998 if (options->verbosity >= McVerbosityMax_c) { 00999 Ltl_AutomatonPrint(automaton, options->verbosity); 01000 fprintf(vis_stdout, "\nDirSim-Maximization:\n"); 01001 } 01002 #endif 01003 Ltl_AutomatonMaximizeByDirectSimulation(automaton, options->verbosity); 01004 } 01005 NumberOfFairSet = lsLength(automaton->Fair); 01006 buechiHrcMgr = Ltl_McAutomatonToNetwork(designNetwork, automaton, 01007 options->verbosity); 01008 assert(buechiHrcMgr != NIL(Hrc_Manager_t)); 01009 tableau = automaton->tableau; 01010 Ltl_AutomatonFree((gGeneric) automaton); 01011 LtlTableauFree(tableau); 01012 buechiNetwork = Ntk_HrcManagerReadCurrentNetwork(buechiHrcMgr); 01013 01014 /*--------------------------------------------------------------------- 01015 * 2) build (M x A) by attaching buechiNetwork(A) to designNetwork(M). 01016 * The result network M x A (designNetwork) shares some data with the 01017 * buechiNetwork (Variables, and Tables). The newly created nodes in 01018 * designNetwork retain their MddId in buechiNetwork 01019 *--------------------------------------------------------------------*/ 01020 /* 2-a) Retrieve the Model (in the default hrc_manager) */ 01021 designNode = Hrc_ManagerReadCurrentNode(*hmgr); 01022 designModelName = Hrc_NodeReadModelName(designNode); 01023 /* 2-b) Attach buechiNetwork to designNetwork */ 01024 tbl = st_init_table(strcmp, st_strhash); 01025 Ntk_NetworkAppendNetwork(designNetwork, buechiNetwork, tbl); 01026 st_free_table(tbl); 01027 01028 /* Here we have the choice of incrementally build the partition, 01029 * or build it from scratch. In both cases, the original partition 01030 * will be saved (and restored later) 01031 */ 01032 if (!options->noIncrementalPartition) { 01033 rootList = lsCreate(); 01034 mddIds = array_alloc(int, 2); 01035 /* 2-c) Assign MddId to the newly-created nodes */ 01036 Ntk_NetworkForEachNode(buechiNetwork, lsgen2, node2) { 01037 if (!Ntk_NodeTestIsPrimaryInput(node2)) { 01038 name1 = util_strcat3(Ntk_NodeReadName(node2),"$NTK2", ""); 01039 node1 = Ntk_NetworkFindNodeByName(designNetwork, name1); 01040 Ntk_NodeSetMddId(node1, Ntk_NodeReadMddId(node2)); 01041 if (!strcmp(name1, "state$AUT$NTK2")) 01042 array_insert(int, mddIds, 1, Ntk_NodeReadMddId(node1)); 01043 else if (!strcmp(name1, "state$AUT$NS$NTK2")) 01044 array_insert(int, mddIds, 0, Ntk_NodeReadMddId(node1)); 01045 else if (!strcmp(name1, "selector$AUT$NTK2")) 01046 array_insert(int, mddIds, 2, Ntk_NodeReadMddId(node1)); 01047 FREE(name1); 01048 if (Ntk_NodeTestIsCombOutput(node1)) 01049 lsNewEnd(rootList, (lsGeneric)node1, (lsHandle *)0); 01050 } 01051 } 01052 /* move the automaton variables to the top most -- this is believed 01053 * to be an optimal ordering */ 01054 if (!options->noShuffleToTop) 01055 ShuffleMddIdsToTop(Ntk_NetworkReadMddManager(designNetwork), mddIds); 01056 array_free(mddIds); 01057 01058 /* 2-d) Create the Partition information for (M x A) */ 01059 save_partition = Part_NetworkReadPartition(designNetwork); 01060 partition = Part_PartitionDuplicate(save_partition); 01061 Part_UpdatePartitionFrontier(designNetwork, partition, rootList, 01062 (lsList)0, mddOne); 01063 Ntk_NetworkSetApplInfo(designNetwork, PART_NETWORK_APPL_KEY, 01064 (Ntk_ApplInfoFreeFn) Part_PartitionFreeCallback, 01065 (void *)partition); 01066 lsDestroy(rootList, (void (*)(lsGeneric))0); 01067 01068 }else { 01069 mddIds = array_alloc(int, 2); 01070 /* 2-c) Assign MddId to the newly-created nodes */ 01071 Ntk_NetworkForEachNode(buechiNetwork, lsgen2, node2) { 01072 if (Ntk_NodeTestIsPrimaryInput(node2)) continue; 01073 name1 = util_strcat3(Ntk_NodeReadName(node2),"$NTK2", ""); 01074 node1 = Ntk_NetworkFindNodeByName(designNetwork, name1); 01075 Ntk_NodeSetMddId(node1, Ntk_NodeReadMddId(node2)); 01076 if (!strcmp(name1, "state$AUT$NTK2")) 01077 array_insert(int, mddIds, 1, Ntk_NodeReadMddId(node1)); 01078 else if (!strcmp(name1, "state$AUT$NS$NTK2")) 01079 array_insert(int, mddIds, 0, Ntk_NodeReadMddId(node1)); 01080 else if (!strcmp(name1, "selector$AUT$NTK2")) 01081 array_insert(int, mddIds, 2, Ntk_NodeReadMddId(node1)); 01082 FREE(name1); 01083 } 01084 /* move the automaton variables to the top most. This might be the 01085 * best BDD variable ordering for (M x A)! */ 01086 if (!options->noShuffleToTop) 01087 ShuffleMddIdsToTop(Ntk_NetworkReadMddManager(designNetwork), mddIds); 01088 array_free(mddIds); 01089 01090 /* 2-d) Create the Partition information for (M x A) */ 01091 nodeList = lsCreate(); 01092 partition = Part_NetworkCreatePartition(designNetwork, 01093 designNode, 01094 designModelName, 01095 (lsList)0, 01096 (lsList)0, 01097 NIL(mdd_t), 01098 Part_Default_c, 01099 nodeList, 01100 FALSE, 0, 0); 01101 save_partition = Part_NetworkReadPartition(designNetwork); 01102 Ntk_NetworkSetApplInfo(designNetwork, PART_NETWORK_APPL_KEY, 01103 (Ntk_ApplInfoFreeFn) Part_PartitionFreeCallback, 01104 (void *)partition); 01105 01106 lsDestroy(nodeList, (void (*)(lsGeneric))0); 01107 } 01108 01109 /*--------------------------------------------------------------------- 01110 * 3) Create the FSM for (M x A) and load Fairness constraints 01111 *--------------------------------------------------------------------*/ 01112 /* try to get a reduced Fsm (w.r.t. each individual property) first */ 01113 { 01114 array_t *ctlArray = array_alloc(Ctlp_Formula_t *, 0); 01115 Ctlp_Formula_t *ctlF = Ctlp_FormulaCreate(Ctlp_ID_c, 01116 util_strsav("state$AUT$NTK2"), 01117 util_strsav("Trap")); 01118 array_insert(Ctlp_Formula_t *, ctlArray, 0, ctlF); 01119 compFsm = Mc_ConstructReducedFsm(designNetwork, ctlArray); 01120 Ctlp_FormulaFree(ctlF); 01121 array_free(ctlArray); 01122 if (compFsm == NIL(Fsm_Fsm_t)) 01123 compFsm = Fsm_FsmCreateFromNetworkWithPartition(designNetwork, 01124 NIL(graph_t)); 01125 } 01126 /* merge fairnesses from outside and those from the automaton ... */ 01127 LtlFsmLoadFairness(compFsm, Fsm_FsmReadFairnessConstraint(designFsm), 01128 NumberOfFairSet, &AutomatonStrength); 01129 01130 01131 /*--------------------------------------------------------------------- 01132 * 4) Language emptiness checking (store result if necessary) 01133 *--------------------------------------------------------------------*/ 01134 if (options->dcLevel == McDcLevelArdc_c) { 01135 Fsm_ArdcOptions_t *ardcOptions = Fsm_ArdcAllocOptionsStruct(); 01136 array_t *tmpArray; 01137 long startRchTime; 01138 Fsm_ArdcGetDefaultOptions(ardcOptions); 01139 startRchTime = util_cpu_time(); 01140 tmpArray = 01141 Fsm_ArdcComputeOverApproximateReachableStates(compFsm, 0, 01142 options->verbosity, 01143 0, 0, 0, 0, 0, 0, 01144 ardcOptions); 01145 modelCareStatesArray = mdd_array_duplicate(tmpArray); 01146 FREE(ardcOptions); 01147 if (options->verbosity > McVerbosityNone_c) 01148 Fsm_ArdcPrintReachabilityResults(compFsm, 01149 util_cpu_time() - startRchTime); 01150 }else if (options->dcLevel >= McDcLevelRch_c) { 01151 long startRchTime; 01152 startRchTime = util_cpu_time(); 01153 modelCareStates = 01154 Fsm_FsmComputeReachableStates(compFsm, 0, options->verbosity, 0, 0, 01155 (options->lockstep != MC_LOCKSTEP_OFF), 01156 0, 0, Fsm_Rch_Default_c, 0, 0, 01157 NIL(array_t), FALSE, NIL(array_t)); 01158 if (options->verbosity > McVerbosityNone_c) { 01159 Fsm_FsmReachabilityPrintResults(compFsm, 01160 util_cpu_time() - startRchTime, 01161 Fsm_Rch_Default_c); 01162 } 01163 modelCareStatesArray = array_alloc(mdd_t *, 0); 01164 array_insert_last(mdd_t *, modelCareStatesArray, modelCareStates); 01165 } else { 01166 modelCareStates = mdd_one(Fsm_FsmReadMddManager(compFsm)); 01167 modelCareStatesArray = array_alloc(mdd_t *, 0); 01168 array_insert_last(mdd_t *, modelCareStatesArray, modelCareStates); 01169 } 01170 /* 01171 Fsm_MinimizeTransitionRelationWithReachabilityInfo(compFsm, 01172 Img_Backward_c, 01173 options->verbosity > 1); 01174 */ 01175 01176 /* language emptiness checking */ 01177 fairInitStates = Mc_FsmCheckLanguageEmptiness(compFsm, 01178 modelCareStatesArray, 01179 (Mc_AutStrength_t) AutomatonStrength, 01180 options->leMethod, 01181 options->dcLevel, 01182 options->dbgLevel, 01183 options->printInputs, 01184 options->verbosity, 01185 options->schedule, 01186 options->direction, 01187 options->lockstep, 01188 options->debugFile, 01189 options->useMore, 01190 options->simValue, 01191 "LTL_MC"); 01192 mdd_array_free(modelCareStatesArray); 01193 01194 if (fairInitStates) 01195 mdd_free(fairInitStates); 01196 01197 /*--------------------------------------------------------------------- 01198 * 5) Remove 'A' from designNetwork (M x A), which contains 3 steps: 01199 * a) free compFsm/partition 01200 * b) remove newly-created nodes from designNetwork; 01201 * c) destory buechiHrcMgr (buechiNetwork) 01202 *--------------------------------------------------------------------*/ 01203 Ntk_NetworkAddApplInfo(designNetwork, PART_NETWORK_APPL_KEY, 01204 (Ntk_ApplInfoFreeFn) Part_PartitionFreeCallback, 01205 (void *)save_partition); 01206 Fsm_FsmFree(compFsm); 01207 { 01208 int tmpi, tmpj; 01209 Ntk_Node_t *node3, *node4; 01210 /* first, remove the newly-added A nodes ('xxxlabel$AUT$NTK2') from the 01211 * fanout list of the M nodes */ 01212 Ntk_NetworkForEachNode(buechiNetwork, lsgen2, node2) { 01213 if (strstr(Ntk_NodeReadName(node2), "label$AUT") == NULL) 01214 continue; 01215 name1 = util_strcat3(Ntk_NodeReadName(node2),"$NTK2", ""); 01216 node1 = Ntk_NetworkFindNodeByName(designNetwork, name1); 01217 FREE(name1); 01218 assert(node1); 01219 Ntk_NodeForEachFanin(node1, tmpi, node3) { 01220 array_t *oldFanouts = Ntk_NodeReadFanouts(node3); 01221 array_t *newFanouts; 01222 if (oldFanouts != NIL(array_t)) { 01223 newFanouts = array_alloc(Ntk_Node_t *, 0); 01224 arrayForEachItem(Ntk_Node_t *, oldFanouts, tmpj, node4) { 01225 if (node4 != node1) 01226 array_insert_last(Ntk_Node_t *, newFanouts, node4); 01227 } 01228 Ntk_NodeSetFanouts(node3, newFanouts); 01229 } 01230 } 01231 } 01232 /* Now we can safely remove all the newly-added A nodes */ 01233 Ntk_NetworkForEachNode(buechiNetwork, lsgen2, node2) { 01234 if (Ntk_NodeTestIsPrimaryInput(node2)) continue; 01235 name1 = util_strcat3(Ntk_NodeReadName(node2),"$NTK2", ""); 01236 node1 = Ntk_NetworkFindNodeByName(designNetwork, name1); 01237 FREE(name1); 01238 Ntk_NodeRemoveFromNetwork(designNetwork, node1, 1, 1, 0); 01239 Ntk_NodeFree(node1); 01240 } 01241 } 01242 Ntk_NetworkSetMddManager(buechiNetwork, (mdd_manager *)0); 01243 Hrc_ManagerFree(buechiHrcMgr); 01244 01245 if (options->verbosity > McVerbosityNone_c) { 01246 finalTime = util_cpu_time(); 01247 fprintf(vis_stdout, "-- ltl_mc time = %10g\n", 01248 (double)(finalTime - initialTime) / 1000.0); 01249 fprintf(vis_stdout, 01250 "-- %d image computations and %d preimage computations\n", 01251 Img_GetNumberOfImageComputation(Img_Forward_c) - nImgComps, 01252 Img_GetNumberOfImageComputation(Img_Backward_c) - nPreComps); 01253 } 01254 } 01255 01256 /* Print stats if verbose. */ 01257 endLtlMcTime = util_cpu_time(); 01258 if (options->verbosity > McVerbosityNone_c) { 01259 fprintf(vis_stdout, "-- total ltl_mc time: %10g\n", 01260 (double)(endLtlMcTime-startLtlMcTime)/1000.0); 01261 fprintf(vis_stdout, 01262 "-- total %d image computations and %d preimage computations\n", 01263 Img_GetNumberOfImageComputation(Img_Forward_c), 01264 Img_GetNumberOfImageComputation(Img_Backward_c)); 01265 } 01266 01267 /* Clean-ups */ 01268 Ctlsp_FormulaArrayFree(ltlArray); 01269 LtlMcOptionFree(options); 01270 mdd_free(mddOne); 01271 01272 alarm(0); 01273 return 0; /* normal exit */ 01274 } 01275 01360 static int 01361 CommandLtl2Aut( 01362 Hrc_Manager_t ** hmgr, 01363 int argc, 01364 char ** argv) 01365 { 01366 array_t *ltlArray; 01367 Ctlsp_Formula_t *ltlFormula; 01368 LtlTableau_t *tableau; 01369 Ltl_Automaton_t *automaton; 01370 int i; 01371 LtlMcOption_t *options; 01372 int verbosity = 0; /* verbosity level */ 01373 int algorithm = 0; /* translation algorithm */ 01374 int rewriting = 0; /* simplify Formula by rewriting */ 01375 int booleanmin = 0; /* boolean minimization */ 01376 int prunefair = 0; /* prune fairness */ 01377 int iocompatible = 0;/* simplify by io-compatible */ 01378 int directsim = 0; /* simplify by Direct simulation */ 01379 int reversesim = 0; /* simplify by reverse simulation */ 01380 int directsimMaximize = 0; /* simplify by Direct simulation */ 01381 Ntk_Network_t *network; 01382 char *tmpString; 01383 long beginTime, finalTime; 01384 01385 01386 if (!(options = ParseLtlTestOptions(argc, argv))) { 01387 return 1; 01388 } 01389 rewriting = options->rewriting; 01390 verbosity = options->verbosity; 01391 algorithm = options->algorithm; 01392 booleanmin = options->booleanmin; 01393 prunefair = options->prunefair; 01394 iocompatible = options->iocompatible; 01395 directsim = options->directsim; 01396 reversesim = options->reversesim; 01397 directsimMaximize = options->directsimMaximize; 01398 01399 beginTime = util_cpu_time(); 01400 network = Ntk_HrcManagerReadCurrentNetwork(*hmgr); 01401 01402 /* Parse the LTL Formulae */ 01403 ltlArray = Ctlsp_FileParseFormulaArray(options->ltlFile); 01404 if (ltlArray != NIL(array_t)) { 01405 array_t *tmpArray = Ctlsp_FormulaArrayConvertToLTL(ltlArray); 01406 Ctlsp_FormulaArrayFree(ltlArray); 01407 ltlArray = tmpArray; 01408 } 01409 if (ltlArray == NIL(array_t)) { 01410 (void) fprintf(vis_stderr, 01411 "** ltl_to_aut error: error in parsing formulas file\n"); 01412 LtlMcOptionFree(options); 01413 return 1; 01414 } 01415 01416 /* For each LTL formula, build a Buechi automaton ... */ 01417 for (i=0; i<array_n(ltlArray); i++) { 01418 ltlFormula = array_fetch(Ctlsp_Formula_t *, ltlArray, i); 01419 tmpString = Ctlsp_FormulaConvertToString(ltlFormula); 01420 01421 /* expand the abbreaviations */ 01422 ltlFormula = Ctlsp_LtlFormulaExpandAbbreviation(ltlFormula); 01423 fprintf(vis_stdout, "\nFormula: %s\n", tmpString); 01424 01425 /* 1) Simplify the formula by 'Rewriting' */ 01426 if (rewriting) { 01427 Ctlsp_Formula_t *tmpF = ltlFormula; 01428 ltlFormula = Ctlsp_LtlFormulaSimpleRewriting(ltlFormula); 01429 tmpString = Ctlsp_FormulaConvertToString(ltlFormula); 01430 Ctlsp_FormulaFree(tmpF); 01431 } 01432 01433 /* create the alph_beta table */ 01434 tableau = LtlTableauGenerateTableau(ltlFormula); 01435 tableau->verbosity = verbosity; 01436 tableau->algorithm = algorithm; 01437 tableau->booleanmin = booleanmin; 01438 /* print out the tableau rules */ 01439 if (verbosity >= McVerbosityMax_c) 01440 LtlTableauPrint(vis_stdout, tableau); 01441 01442 /* 2) create the automaton */ 01443 automaton = LtlAutomatonGeneration(tableau); 01444 automaton->name = tmpString; 01445 01446 /* 3) minimize the automaton by Pruning fairness */ 01447 if (prunefair) { 01448 if (verbosity >= McVerbosityMax_c) { 01449 Ltl_AutomatonPrint(automaton, verbosity); 01450 fprintf(vis_stdout, "\nPruneF-Minimization:\n"); 01451 } 01452 Ltl_AutomatonMinimizeByPrune(automaton, verbosity) ; 01453 } 01454 01455 /* 4) minimize the automaton by I/O compatible and dominance */ 01456 if (iocompatible) { 01457 if (verbosity >= McVerbosityMax_c) { 01458 Ltl_AutomatonPrint(automaton, verbosity); 01459 fprintf(vis_stdout, "\nIOC-Minimization:\n"); 01460 } 01461 while(Ltl_AutomatonMinimizeByIOCompatible(automaton, verbosity)); 01462 } 01463 01464 /* 5) minimize the automaton by Direct Simulation */ 01465 if (directsim) { 01466 if (verbosity >= McVerbosityMax_c) { 01467 Ltl_AutomatonPrint(automaton, verbosity); 01468 fprintf(vis_stdout, "\nDirSim-Minimization:\n"); 01469 } 01470 Ltl_AutomatonMinimizeByDirectSimulation(automaton, verbosity); 01471 } 01472 01473 /* 6) minimize the automaton by Reverse Simulation */ 01474 if (reversesim) { 01475 if (verbosity >= McVerbosityMax_c) { 01476 Ltl_AutomatonPrint(automaton, verbosity); 01477 fprintf(vis_stdout, "\nRevSim-Minimization:\n"); 01478 } 01479 Ltl_AutomatonMinimizeByReverseSimulation(automaton, verbosity); 01480 } 01481 01482 /* 7/3) minimize the automaton by Pruning fairness */ 01483 if (prunefair) { 01484 if (verbosity >= McVerbosityMax_c) { 01485 Ltl_AutomatonPrint(automaton, verbosity); 01486 fprintf(vis_stdout, "\nPruneF-Minimization:\n"); 01487 } 01488 Ltl_AutomatonMinimizeByPrune(automaton, verbosity) ; 01489 } 01490 01491 /* 8) add arcs by Direct Simulation, to reduce counter-example length */ 01492 if (directsimMaximize) { 01493 if (verbosity >= McVerbosityMax_c) { 01494 Ltl_AutomatonPrint(automaton, verbosity); 01495 fprintf(vis_stdout, "\nDirSim-Maximization:\n"); 01496 } 01497 Ltl_AutomatonMaximizeByDirectSimulation(automaton, verbosity); 01498 } 01499 01500 /* print out the Buechi automaton */ 01501 Ltl_AutomatonPrint(automaton, verbosity+1); 01502 01503 /* write the automaton in a file in the proper format */ 01504 if (options->outputfilename) { 01505 FILE *fp; 01506 fp = Cmd_FileOpen( options->outputfilename, (char *)((i==0)?"w":"a"), 01507 NIL(char *), 0); 01508 if (options->outputformat == Aut2File_DOT_c) 01509 Ltl_AutomatonToDot(fp, automaton, 0); 01510 else if (options->outputformat == Aut2File_BLIFMV_c) 01511 Ltl_AutomatonToBlifMv(fp, network, automaton); 01512 else if (options->outputformat == Aut2File_VERILOG_c) 01513 Ltl_AutomatonToVerilog(fp, network, automaton); 01514 else { 01515 Ltl_AutomatonToDot(fp, automaton, 0); 01516 Ltl_AutomatonToBlifMv(fp, network, automaton); 01517 Ltl_AutomatonToVerilog(fp, network, automaton); 01518 } 01519 fclose(fp); 01520 } 01521 01522 /* Clean-ups: the current formula*/ 01523 Ltl_AutomatonFree((gGeneric) automaton); 01524 LtlTableauFree(tableau); 01525 Ctlsp_FormulaFree(ltlFormula); 01526 } 01527 01528 /* Clean-ups */ 01529 Ctlsp_FormulaArrayFree(ltlArray); 01530 LtlMcOptionFree(options); 01531 01532 finalTime = util_cpu_time(); 01533 fprintf(vis_stdout, "# LTL_TO_AUT time: %10g\n", 01534 (double)(finalTime-beginTime)/1000.0); 01535 01536 return 0; /* normal exit */ 01537 } 01538 01539 01549 static LtlMcOption_t * 01550 ParseLtlMcOptions( 01551 int argc, 01552 char **argv) 01553 { 01554 LtlMcOption_t *options = LtlMcOptionAlloc(); 01555 char *ltlFileName = (char *)0; 01556 char *debugOutName = (char *)0; 01557 Mc_GSHScheduleType schedule = McGSH_EL_c; 01558 Mc_FwdBwdAnalysis direction = McBwd_c; 01559 int lockstep = MC_LOCKSTEP_OFF; 01560 int c; 01561 01562 if (options == NIL(LtlMcOption_t)) 01563 return NIL(LtlMcOption_t); 01564 options->leMethod = Mc_Le_Default_c; 01565 options->dcLevel = McDcLevelRch_c; 01566 options->noStrengthReduction = 0; 01567 options->noIncrementalPartition = 0; 01568 01569 /* Parse command line options. 01570 */ 01571 util_getopt_reset(); 01572 while ((c = util_getopt(argc, argv, "a:bd:f:t:A:D:v:S:L:FhimsXYM")) != EOF) { 01573 switch(c) { 01574 case 'a': 01575 options->algorithm = (Ltl2AutAlgorithm) atoi(util_optarg); 01576 if (options->algorithm < 0 || options->algorithm > 3) 01577 goto usage; 01578 break; 01579 case 'b': 01580 options->booleanmin = 1; 01581 break; 01582 case 'd': 01583 options->dbgLevel = (LtlMcDbgLevel) atoi(util_optarg); 01584 break; 01585 case 'f': 01586 debugOutName = util_strsav(util_optarg); 01587 break; 01588 case 't': 01589 options->timeOutPeriod = atoi(util_optarg); 01590 break; 01591 case 'A': 01592 options->leMethod = (Mc_LeMethod_t) atoi(util_optarg); 01593 break; 01594 case 'D': 01595 options->dcLevel = (Mc_DcLevel) atoi(util_optarg); 01596 break; 01597 case 'v': 01598 options->verbosity = (Mc_VerbosityLevel) atoi(util_optarg); 01599 break; 01600 case 'S' : 01601 schedule = Mc_StringConvertToScheduleType(util_optarg); 01602 break; 01603 case 'L' : 01604 lockstep = Mc_StringConvertToLockstepMode(util_optarg); 01605 break; 01606 case 'F' : 01607 direction = McFwd_c; 01608 break; 01609 case 'i': 01610 options->printInputs = 1; 01611 break; 01612 case 'm': 01613 options->useMore = TRUE; 01614 break; 01615 case 's' : 01616 options->simValue = TRUE; 01617 break; 01618 case 'X': 01619 options->noStrengthReduction = 1; 01620 break; 01621 case 'Y': 01622 options->noIncrementalPartition = 1; 01623 break; 01624 case 'Z': 01625 options->noShuffleToTop = 1; 01626 break; 01627 case 'M': 01628 options->directsimMaximize = 1; 01629 break; 01630 case 'h': 01631 goto usage; 01632 default: 01633 goto usage; 01634 } 01635 } 01636 if (options->algorithm == Ltl2Aut_WRING_c) { 01637 options->rewriting = TRUE; 01638 options->prunefair = TRUE; 01639 options->directsim = TRUE; 01640 options->reversesim = TRUE; 01641 options->iocompatible = TRUE; 01642 } 01643 01644 if (schedule == McGSH_Unassigned_c) { 01645 (void) fprintf(vis_stderr, "unknown schedule: %s\n", util_optarg); 01646 goto usage; 01647 } else { 01648 options->schedule = schedule; 01649 } 01650 if (lockstep == MC_LOCKSTEP_UNASSIGNED) { 01651 (void) fprintf(vis_stderr, "invalid lockstep option: %s\n", util_optarg); 01652 goto usage; 01653 } else { 01654 options->lockstep = lockstep; 01655 } 01656 options->direction = direction; 01657 01658 /* Open the ltl file. 01659 */ 01660 if (argc - util_optind == 0) { 01661 (void) fprintf(vis_stderr, "** ltl_mc error: file containing ltl formulae not provided\n"); 01662 goto usage; 01663 } 01664 else if (argc - util_optind > 1) { 01665 (void) fprintf(vis_stderr, "** ltl_mc error: too many arguments\n"); 01666 goto usage; 01667 } 01668 ltlFileName = util_strsav(argv[util_optind]); 01669 01670 /* Read LTL Formulae */ 01671 if (!ltlFileName) 01672 goto usage; 01673 options->ltlFile = Cmd_FileOpen(ltlFileName, "r", NIL(char *), 0); 01674 if (options->ltlFile == NIL(FILE)) { 01675 (void) fprintf(vis_stdout, "** ltl_mc error: error in opening file %s\n", ltlFileName); 01676 FREE(ltlFileName); 01677 LtlMcOptionFree(options); 01678 return NIL(LtlMcOption_t); 01679 } 01680 FREE(ltlFileName); 01681 01682 if (debugOutName != NIL(char)) { 01683 options->debugFile = Cmd_FileOpen(debugOutName, "w", NIL(char *), 0); 01684 if (options->debugFile == NIL(FILE)) { 01685 (void) fprintf(vis_stdout,"** ltl_mc error: error in opening file %s\n", debugOutName); 01686 FREE(debugOutName); 01687 LtlMcOptionFree(options); 01688 return NIL(LtlMcOption_t); 01689 } 01690 FREE(debugOutName); 01691 } 01692 01693 return options; 01694 01695 usage: 01696 (void) fprintf(vis_stderr, "usage: ltl_model_check [-a ltl2aut_algorithm][-b][-d dbg_level][-f dbg_file][-h][-i][-m][-s][-t period][-v verbosity_level][-A le_method][-D dc_level][-L lockstep_mode][-S schedule][-F][-X][-Y][-M] <ltl_file>\n"); 01697 (void) fprintf(vis_stderr, " -a <ltl2aut_algorithm>\n"); 01698 (void) fprintf(vis_stderr, " ltl2aut_algorithm = 0 => GPVW\n"); 01699 (void) fprintf(vis_stderr, " ltl2aut_algorithm = 1 => GPVW+\n"); 01700 (void) fprintf(vis_stderr, " ltl2aut_algorithm = 2 => LTL2AUT\n"); 01701 (void) fprintf(vis_stderr, " ltl2aut_algorithm = 3 => WRING (Default)\n"); 01702 (void) fprintf(vis_stderr, " -b \tUse boolean minimization in automaton generation\n"); 01703 (void) fprintf(vis_stderr, " -d <dbg_level>\n"); 01704 (void) fprintf(vis_stderr, " debug_level = 0 => no debugging (Default)\n"); 01705 (void) fprintf(vis_stderr, " debug_level = 1 => automatic debugging\n"); 01706 (void) fprintf(vis_stderr, " -f <dbg_out>\n"); 01707 (void) fprintf(vis_stderr, " write error trace to dbg_out\n"); 01708 (void) fprintf(vis_stderr, " -i \tPrint input values in debug traces.\n"); 01709 (void) fprintf(vis_stderr, " -m \tPipe debugger output through the UNIX utility more.\n"); 01710 (void) fprintf(vis_stderr, " -s \tWrite error trace in sim format.\n"); 01711 (void) fprintf(vis_stderr, " -v <verbosity_level>\n"); 01712 (void) fprintf(vis_stderr, " verbosity_level = 0 => no feedback (Default)\n"); 01713 (void) fprintf(vis_stderr, " verbosity_level = 1 => code status\n"); 01714 (void) fprintf(vis_stderr, " verbosity_level = 2 => code status and CPU usage profile\n"); 01715 (void) fprintf(vis_stderr, " -t <period> time out period\n"); 01716 (void) fprintf(vis_stderr, " -A <le_method>\n"); 01717 (void) fprintf(vis_stderr, " le_method = 0 => no use of Divide and Compose (Default)\n"); 01718 (void) fprintf(vis_stderr, " le_method = 1 => use Divide and Compose\n"); 01719 (void) fprintf(vis_stderr, " -D <dc_level>\n"); 01720 (void) fprintf(vis_stderr, " dc_level = 0 => no use of don't cares\n"); 01721 (void) fprintf(vis_stderr, " dc_level = 1 => use unreached states as don't cares (Default)\n"); 01722 (void) fprintf(vis_stderr, " dc_level = 2 => use unreached states as don't cares\n"); 01723 01724 (void) fprintf(vis_stderr, " and aggressive use of DC's to simplify MDD's\n"); 01725 (void) fprintf(vis_stderr, " dc_level = 3 => use over-approximate unreached states as don't cares\n"); 01726 (void) fprintf(vis_stderr, " and aggressive use of DC's to simplify MDD's\n"); 01727 (void) fprintf(vis_stderr, " -L <lockstep_mode>\n"); 01728 (void) fprintf(vis_stderr, " lockstep_mode is one of {off,on,all,n}\n"); 01729 (void) fprintf(vis_stderr, " -S <schedule>\n"); 01730 (void) fprintf(vis_stderr, " schedule is one of {EL,EL1,EL2,budget,random,off}\n"); 01731 (void) fprintf(vis_stderr, " -F \tUse forward analysis in fixpoint computation.\n"); 01732 (void) fprintf(vis_stderr, " -X \tDisable strength reduction (using different decision procedure \n"); 01733 (void) fprintf(vis_stderr, " \tfor strong, weak, terminal automaton).\n"); 01734 (void) fprintf(vis_stderr, " -Y \tDisable incremental partition of the composed system (M x A).\n"); 01735 (void) fprintf(vis_stderr, " -Z \tAdd arcs into the Buechi automaton by direct simulation relation.\n"); 01736 01737 (void) fprintf(vis_stderr, " -M \tAdd arcs to the automaton to reduce counter-example length.\n"); 01738 (void) fprintf(vis_stderr, " <ltl_file> The input file containing LTL formulae to be checked.\n"); 01739 (void) fprintf(vis_stderr, " -h \tPrints this usage message.\n"); 01740 01741 LtlMcOptionFree(options); 01742 return NIL(LtlMcOption_t); 01743 } 01744 01754 static LtlMcOption_t * 01755 ParseLtlTestOptions( 01756 int argc, 01757 char **argv) 01758 { 01759 LtlMcOption_t *options = LtlMcOptionAlloc(); 01760 char *ltlFileName = (char *)0; 01761 int c; 01762 01763 if (options == NIL(LtlMcOption_t)) 01764 return NIL(LtlMcOption_t); 01765 01766 /* 01767 * Parse command line options. 01768 */ 01769 util_getopt_reset(); 01770 while ((c = util_getopt(argc, argv, "wbpdMrif:m:v:o:t:h")) != EOF) { 01771 switch(c) { 01772 case 'w': 01773 options->rewriting = 1; 01774 break; 01775 case 'b': 01776 options->booleanmin = 1; 01777 break; 01778 case 'p': 01779 options->prunefair = 1; 01780 break; 01781 case 'd': 01782 options->directsim = 1; 01783 break; 01784 case 'M': 01785 options->directsimMaximize = 1; 01786 break; 01787 case 'r': 01788 options->reversesim = 1; 01789 break; 01790 case 'i': 01791 options->iocompatible = 1; 01792 break; 01793 case 'f': 01794 ltlFileName = util_strsav(util_optarg); 01795 break; 01796 case 'm': 01797 options->algorithm = (Ltl2AutAlgorithm) atoi(util_optarg); 01798 break; 01799 case 'v': 01800 options->verbosity = (Mc_VerbosityLevel) atoi(util_optarg); 01801 break; 01802 case 'o': 01803 options->outputfilename = util_strsav(util_optarg); 01804 break; 01805 case 't': 01806 options->outputformat = (Aut2FileType) atoi(util_optarg); 01807 break; 01808 case 'h': 01809 goto usage; 01810 default: 01811 goto usage; 01812 } 01813 } 01814 01815 /* 'Wring' is equivalent to 01816 * LTL2AUT + 01817 * rewriting + 01818 * prunefair + directsim + reversesim + iocompatible 01819 */ 01820 if (options->algorithm ==3) { 01821 options->rewriting = 1; 01822 options->prunefair = 1; 01823 options->directsim = 1; 01824 options->reversesim = 1; 01825 options->iocompatible = 1; 01826 } 01827 01828 /* Read LTL Formulae */ 01829 if (!ltlFileName) 01830 goto usage; 01831 01832 options->ltlFile = Cmd_FileOpen(ltlFileName, "r", NIL(char *), 0); 01833 FREE(ltlFileName); 01834 if (options->ltlFile == NIL(FILE)) { 01835 (void) fprintf(vis_stdout, "** ltl_to_aut error: error in opening file %s\n", ltlFileName); 01836 LtlMcOptionFree(options); 01837 return NIL(LtlMcOption_t); 01838 } 01839 01840 return options; 01841 01842 usage: 01843 (void) fprintf(vis_stderr, "usage: ltl_to_aut <-f ltl_file> [-m algorithm] [-o output_file] [-t output_format] [-w] [-b] [-p] [-d] [-r] [-i] [-M] [-v verbosity_level] [-h]\n"); 01844 (void) fprintf(vis_stderr, " -f <ltl_file>\n"); 01845 (void) fprintf(vis_stderr, " The input file containing LTL formulae\n"); 01846 (void) fprintf(vis_stderr, " -m <algorithm>\n"); 01847 (void) fprintf(vis_stderr, " algorithm = 0 => GPVW\n"); 01848 (void) fprintf(vis_stderr, " algorithm = 1 => GPVW+\n"); 01849 (void) fprintf(vis_stderr, " algorithm = 2 => LTL2AUT\n"); 01850 (void) fprintf(vis_stderr, " algorithm = 3 => Wring (default)\n"); 01851 (void) fprintf(vis_stderr, " -o <output_file>\n"); 01852 (void) fprintf(vis_stderr, " Write the automata to output_file\n"); 01853 (void) fprintf(vis_stderr, " -t <output_format>\n"); 01854 (void) fprintf(vis_stderr, " output_format = 0 => dot\n"); 01855 (void) fprintf(vis_stderr, " output_format = 1 => blif_mv\n"); 01856 (void) fprintf(vis_stderr, " output_format = 2 => verilog\n"); 01857 (void) fprintf(vis_stderr, " output_format = 3 => all (default)\n"); 01858 (void) fprintf(vis_stderr, " -w \tRewriting the formula\n"); 01859 (void) fprintf(vis_stderr, " -b \tBoolean minimization \n"); 01860 (void) fprintf(vis_stderr, " -p \tPruning the fairness\n"); 01861 (void) fprintf(vis_stderr, " -d \tDirect-simulation minimization\n"); 01862 (void) fprintf(vis_stderr, " -r \tReverse-simulation minimization\n"); 01863 (void) fprintf(vis_stderr, " -i \tI/O compatible minimization\n"); 01864 (void) fprintf(vis_stderr, " -M \tAdd arcs by direct-simulation to reduce the counter-example length\n"); 01865 (void) fprintf(vis_stderr, " -v <verbosity>\n"); 01866 (void) fprintf(vis_stderr, " \tVerbosity can be 0,1,2,3\n"); 01867 (void) fprintf(vis_stderr, " -h \tPrints this usage message.\n"); 01868 01869 LtlMcOptionFree(options); 01870 return NIL(LtlMcOption_t); 01871 } 01872 01873 01882 static boolean 01883 LtlMcAtomicFormulaCheckSemantics( 01884 Ctlsp_Formula_t *formula, 01885 Ntk_Network_t *network, 01886 boolean inputsAllowed) 01887 { 01888 char *nodeNameString = Ctlsp_FormulaReadVariableName( formula ); 01889 char *nodeValueString = Ctlsp_FormulaReadValueName( formula ); 01890 Ntk_Node_t *node = Ntk_NetworkFindNodeByName( network, nodeNameString ); 01891 01892 Var_Variable_t *nodeVar; 01893 int nodeValue; 01894 01895 if ( !node ) { 01896 error_append("Could not find node corresponding to the name\n\t- "); 01897 error_append( nodeNameString ); 01898 return FALSE; 01899 } 01900 01901 nodeVar = Ntk_NodeReadVariable( node ); 01902 if ( Var_VariableTestIsSymbolic( nodeVar ) ){ 01903 nodeValue = Var_VariableReadIndexFromSymbolicValue( nodeVar, nodeValueString ); 01904 if ( nodeValue == -1 ) { 01905 error_append("Value specified in RHS is not in domain of variable\n"); 01906 error_append( Ctlsp_FormulaReadVariableName( formula ) ); 01907 error_append("="); 01908 error_append( Ctlsp_FormulaReadValueName( formula ) ); 01909 return FALSE; 01910 } 01911 } 01912 else { 01913 int check; 01914 01915 check = Cmd_StringCheckIsInteger(nodeValueString, &nodeValue); 01916 if( check==0 ) { 01917 error_append("Value in the RHS is illegal\n"); 01918 error_append( Ctlsp_FormulaReadVariableName( formula ) ); 01919 error_append("="); 01920 error_append( Ctlsp_FormulaReadValueName( formula ) ); 01921 return FALSE; 01922 } 01923 if( check==1 ) { 01924 error_append("Value in the RHS is out of range of int\n"); 01925 error_append( Ctlsp_FormulaReadVariableName( formula ) ); 01926 error_append("="); 01927 error_append( Ctlsp_FormulaReadValueName( formula ) ); 01928 return FALSE; 01929 } 01930 if ( !(Var_VariableTestIsValueInRange( nodeVar, nodeValue ) ) ) { 01931 error_append("Value specified in RHS is not in domain of variable\n"); 01932 error_append( Ctlsp_FormulaReadVariableName( formula ) ); 01933 error_append("="); 01934 error_append( Ctlsp_FormulaReadValueName( formula ) ); 01935 return FALSE; 01936 } 01937 } 01938 01939 if(!inputsAllowed){ 01940 boolean coverSupport; 01941 lsGen tmpGen; 01942 Ntk_Node_t *tmpNode; 01943 st_table *supportNodes = st_init_table(st_ptrcmp, st_ptrhash); 01944 array_t *thisNodeArray = array_alloc( Ntk_Node_t *, 0); 01945 01946 array_insert_last( Ntk_Node_t *, thisNodeArray, node ); 01947 Ntk_NetworkForEachNode(network, tmpGen, tmpNode) { 01948 if (Ntk_NodeTestIsConstant(tmpNode) || Ntk_NodeTestIsLatch(tmpNode)) { 01949 st_insert(supportNodes, tmpNode, NIL(char)); 01950 } 01951 } 01952 01953 coverSupport = Ntk_NetworkTestLeavesCoverSupportOfRoots(network, 01954 thisNodeArray, 01955 supportNodes); 01956 array_free(thisNodeArray); 01957 st_free_table(supportNodes); 01958 01959 if ( coverSupport == FALSE ) { 01960 char *tmpString = 01961 util_strcat3( "\nNode ", nodeNameString, 01962 " is not driven only by latches and constants.\n"); 01963 error_append(tmpString); 01964 return FALSE; 01965 } 01966 } 01967 01968 return TRUE; 01969 } 01970 01983 static void 01984 TimeOutHandle(void) 01985 { 01986 longjmp(timeOutEnv, 1); 01987 } 01988 02001 static void 02002 ShuffleMddIdsToTop(mdd_manager *mddManager, array_t *mddIdArray) 02003 { 02004 array_t *mvar_list = mdd_ret_mvar_list(mddManager); 02005 int *invPermArray = ALLOC(int, bdd_num_vars(mddManager)); 02006 int invPermIndex, i, j, bvarId, mddId, result; 02007 st_table *stored = st_init_table(st_ptrcmp, st_ptrhash); 02008 mvar_type mvar; 02009 02010 /* put mddId on the top most */ 02011 invPermIndex = 0; 02012 arrayForEachItem(int, mddIdArray, j, mddId) { 02013 if (mddId == 0) continue; 02014 mvar = array_fetch(mvar_type, mvar_list, mddId); 02015 for (i = 0; i<mvar.encode_length; i++) { 02016 bvarId = mdd_ret_bvar_id(&mvar, i); 02017 invPermArray[invPermIndex++] = bvarId; 02018 st_insert(stored, (char *) (long) bvarId, (char *)0); 02019 } 02020 } 02021 /* shift every one else down */ 02022 for (i = 0; (unsigned) i< bdd_num_vars(mddManager); i++) { 02023 bvarId = bdd_get_id_from_level(mddManager, i); 02024 if (!st_is_member(stored, (char *) (long) bvarId)) { 02025 invPermArray[invPermIndex++] = bvarId; 02026 } 02027 } 02028 /* call bdd_shuffle */ 02029 result = bdd_shuffle_heap(mddManager, invPermArray); 02030 #ifdef DEBUG_LTLMC 02031 if (result) 02032 fprintf(vis_stdout, "\nShuffle automaton vars to the top: success!\n"); 02033 else 02034 fprintf(vis_stdout, "\nShuffle automaton vars to the top: failure!\n"); 02035 #endif 02036 02037 /* Clean up */ 02038 st_free_table(stored); 02039 FREE(invPermArray); 02040 }