VIS

src/ltl/ltl.c

Go to the documentation of this file.
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 }