VIS

src/amc/amcAmc.c

Go to the documentation of this file.
00001 
00017 #include "amcInt.h" 
00018 #include "mcInt.h" 
00019 
00020 static char rcsid[] UNUSED = "$Id: amcAmc.c,v 1.57 2005/04/16 04:22:41 fabio Exp $";
00021 
00022 /*---------------------------------------------------------------------------*/
00023 /* Constant declarations                                                     */
00024 /*---------------------------------------------------------------------------*/
00025 
00026 
00027 /*---------------------------------------------------------------------------*/
00028 /* Type declarations                                                         */
00029 /*---------------------------------------------------------------------------*/
00030 
00031 
00032 /*---------------------------------------------------------------------------*/
00033 /* Structure declarations                                                    */
00034 /*---------------------------------------------------------------------------*/
00035 
00036 
00037 /*---------------------------------------------------------------------------*/
00038 /* Variable declarations                                                     */
00039 /*---------------------------------------------------------------------------*/
00040 
00041 
00042 /*---------------------------------------------------------------------------*/
00043 /* Macro declarations                                                        */
00044 /*---------------------------------------------------------------------------*/
00045 
00046 
00049 /*---------------------------------------------------------------------------*/
00050 /* Static function prototypes                                                */
00051 /*---------------------------------------------------------------------------*/
00052 static int stringCompare(const void *s1, const void *s2);
00053 
00057 /*---------------------------------------------------------------------------*/
00058 /* Definition of exported functions                                          */
00059 /*---------------------------------------------------------------------------*/
00060 
00093 void
00094 Amc_AmcEvaluateFormula(
00095   Ntk_Network_t         *network,
00096   Ctlp_Formula_t        *formula,
00097   int                   verbosity)
00098 {
00099   Amc_Info_t            *amcInfo;
00100   int                   levelOfLattice;
00101   char                  *flagValue;
00102 
00103   long initialTime = 0;
00104   long finalTime;
00105 
00106 
00107   /* 
00108    * If the partition was not created, get out.  We are assuming we were able to 
00109    * construct BDD for each combinational outputs.
00110    */
00111 
00112   graph_t       *partition = Part_NetworkReadPartition(network);
00113   if (partition == NIL(graph_t)) {
00114     error_append("** amc error: Network has no partition. Cannot apply approximate model checking.");
00115     return;
00116   }
00117 
00118 
00119   /*
00120    * Initialize data structures.
00121    */
00122   amcInfo = Amc_AmcInfoInitialize(network, formula, Amc_Default_c, verbosity);
00123 
00124 
00125 
00126   /* 
00127    * Check every possible environment variables that user may have set.
00128    * And give user some assurance by reporting the flag values.
00129    * Explanation of possible environment variables are discussed in the
00130    * man page of the package.
00131    */
00132   amcInfo->isMBM = 0;
00133 
00134   flagValue = Cmd_FlagReadByName("amc_prove_false");
00135   if (flagValue == NIL(char)){
00136     amcInfo->lowerBound = 0;
00137     fprintf(vis_stdout, "\n#AMC: Proving whether the formula is true.\n");
00138   }
00139   else {
00140     amcInfo->lowerBound = 1;
00141     fprintf(vis_stdout, "\n#AMC: Proving whether the formula is false.\n");
00142   }
00143 
00144   if(verbosity) {
00145     flagValue = Cmd_FlagReadByName("amc_grouping_method");
00146     if (flagValue == NIL(char)){
00147       amcInfo->groupingMethod = 0;
00148       fprintf(vis_stdout, "\n#AMC: No grouping method has been set."); 
00149     }
00150     else {
00151       amcInfo->groupingMethod = 1;
00152       fprintf(vis_stdout, "\n#AMC: Using latch dependency method for grouping latches into subsystems.");
00153     }
00154   }
00155 
00156 
00157 
00158   /*
00159    * The lattice of approximation algorithm.
00160    */
00161 
00162   levelOfLattice = array_n(amcInfo->subSystemArray);
00163   amcInfo->currentLevel = 1;
00164 
00165   while(levelOfLattice >= amcInfo->currentLevel) {
00166     if(verbosity) {
00167       (void)fprintf(vis_stdout, "\n\n##AMC: Entering level %d(%d) of the lattice of approximations\n", 
00168                                    amcInfo->currentLevel, levelOfLattice);
00169       fflush(vis_stdout);
00170     }
00171 
00172 
00173     initialTime = util_cpu_time();
00174 
00175     if( (!(*amcInfo->amcBoundProc)(amcInfo, formula, verbosity)) && !(amcInfo->isVerified) ) {
00176 
00177       /* Automatically switches to lattice of lowerbound approximations */
00178       if(verbosity)
00179         (void)fprintf(vis_stdout, "Abandoning upper bound approximations.\n");
00180 
00181       /* Free all */
00182       (*amcInfo->amcFreeProc)(amcInfo);
00183 
00184       amcInfo = Amc_AmcInfoInitialize(network, formula, Amc_Default_c, verbosity);
00185       amcInfo->lowerBound = TRUE;
00186       amcInfo->currentLevel = 0;
00187 
00188     }
00189     else if(amcInfo->isVerified) {
00190       finalTime = util_cpu_time();
00191       if(verbosity == Amc_VerbosityVomit_c) {
00192         (void) fprintf(vis_stdout, "\n%-20s%10ld\n", "analysis time =", 
00193                                     (finalTime - initialTime) / 1000);
00194       }
00195 
00196       if(amcInfo->amcAnswer == Amc_Verified_True_c) {
00197         (void) fprintf(vis_stdout, "\n# AMC: Verified formula TRUE at level %d of %d : ",
00198                        amcInfo->currentLevel, levelOfLattice);
00199       }else if(amcInfo->amcAnswer == Amc_Verified_False_c) {
00200         (void) fprintf(vis_stdout, "\n# AMC: Verified formula FALSE at level %d of %d : ",
00201                        amcInfo->currentLevel, levelOfLattice);
00202       }else{
00203         fprintf(vis_stdout, "\n# AMC: formula unknown --- ");
00204         Ctlp_FormulaPrint( vis_stdout, Ctlp_FormulaReadOriginalFormula( formula ) );
00205         (void) fprintf(vis_stdout, "\n# AMC: Verified formula UNKNOWN at level %d of %d : ",
00206                        amcInfo->currentLevel, levelOfLattice);
00207       }
00208       (void) fprintf(vis_stdout, "\n# AMC: ");
00209       Ctlp_FormulaPrint( vis_stdout, Ctlp_FormulaReadOriginalFormula( formula ) );
00210       AmcPrintOptimalSystem(vis_stdout, amcInfo);
00211       (*amcInfo->amcFreeProc)(amcInfo);
00212       return;
00213     } /* end of else if(amcInfo->isVerified) */
00214     
00215     amcInfo->currentLevel++;
00216   } /* end of while(levelOfLattice >= amcInfo->currentLevel) */
00217   
00218   finalTime = util_cpu_time();
00219   if(verbosity == Amc_VerbosityVomit_c) {
00220     (void) fprintf(vis_stdout, "\n%-20s%10ld\n", "analysis time =",
00221                    (finalTime - initialTime) / 1000);
00222   }
00223   
00224   /*
00225   ** Now, spec was not verified becase there was an error in computation.
00226   */ 
00227   (void) fprintf(vis_stdout, "\n# AMC: The spec was not able to be verified.\n# AMC: ");
00228   Ctlp_FormulaPrint( vis_stdout, Ctlp_FormulaReadOriginalFormula( formula ) );
00229   (*amcInfo->amcFreeProc)(amcInfo);
00230   
00231 }
00232 
00233 
00251 Amc_Info_t *
00252 Amc_AmcInfoInitialize(
00253   Ntk_Network_t         *network,
00254   Ctlp_Formula_t        *formula,
00255   Amc_MethodType        methodType,
00256   int                   verbosity)
00257 {
00258   Amc_Info_t            *amcInfo;
00259   char                  *userSpecifiedMethod;
00260 
00261   amcInfo = ALLOC(Amc_Info_t, 1);
00262   amcInfo->network = network;
00263 
00264   /*
00265    * AmcCreateSubsystems creates fsm for each subsystem and returns subSystemArray.
00266    */
00267   amcInfo->subSystemArray = AmcCreateSubsystemArray(network, formula);
00268 
00269 #ifdef AMC_DEBUG
00270 AmcCheckSupportAndOutputFunctions(amcInfo->subSystemArray);
00271 #endif
00272 
00273   /*
00274    * Initialize optimalSystem, isVerified; 
00275    */
00276   amcInfo->optimalSystem = NIL(Amc_SubsystemInfo_t);
00277   amcInfo->isVerified = 0;
00278   amcInfo->amcAnswer = Amc_Verified_Unknown_c;
00279 
00280   /*
00281    * If methodType is default, use user-specified method.
00282    */
00283   if (methodType == Amc_Default_c) {
00284     userSpecifiedMethod = Cmd_FlagReadByName("amc_method");
00285     if (userSpecifiedMethod == NIL(char)) {
00286       methodType = Amc_Block_c;
00287     }
00288     else {
00289       if (strcmp(userSpecifiedMethod, "block") == 0) {
00290         methodType = Amc_Block_c;
00291       }
00292       else if (strcmp(userSpecifiedMethod, "variable") == 0) {
00293         methodType = Amc_Variable_c;
00294       }
00295       else {
00296         (void) fprintf(vis_stderr, "** amc error: Unrecognized amc_method %s: using Block method.\n",
00297                        userSpecifiedMethod);
00298         methodType = Amc_Block_c;
00299       }
00300     }
00301   }
00302   
00303   amcInfo->methodType = methodType;
00304 
00305 
00306   /* 
00307    * Every subsystem shares identical initial states. 
00308    * We do not abstract the state space. Only the transition relation is over or
00309    * under approximated.
00310    */
00311   {
00312     mdd_t               *sampleInitialStates;
00313     Amc_SubsystemInfo_t *sampleSystem;
00314 
00315     /* 
00316      * Fsm routines always returns duplicate copy. 
00317      */
00318 
00319     sampleSystem = array_fetch(Amc_SubsystemInfo_t *, amcInfo->subSystemArray, 0);
00320     sampleInitialStates = Fsm_FsmComputeInitialStates(sampleSystem->fsm); 
00321     amcInfo->initialStates = sampleInitialStates;  
00322   }
00323 
00324 
00325   /* 
00326    * Fill in the rest of amcInfo according to methodType.
00327    */
00328   switch(methodType) {
00329     case Amc_Block_c:
00330       amcInfo->methodData = NIL(void);
00331       amcInfo->amcBoundProc = AmcBlockTearingProc;
00332       amcInfo->amcFreeProc  = AmcFreeBlock;
00333       break;
00334 /*
00335  ;;The variable tearing method has not been implemented yet;;
00336     case Amc_Variable_c:
00337       amcInfo->methodData = AmcInfoInitializeVariable(amcInfo);
00338       amcInfo->amcUpperBoundProc = AmcUpperBoundProcVariable;
00339       amcInfo->amcLowerBoundProc = AmcLowerBoundProcVariable;
00340       amcInfo->amcFreeProc = AmcFreeVariable;
00341       break;
00342 */
00343     default:
00344       fail("Invalid methodtype when initalizing amc method"); 
00345   }
00346 
00347   amcInfo->currentLevel = 0;
00348 
00349   return(amcInfo);
00350 }
00351 
00352 
00383 mdd_t *
00384 Amc_AmcExistentialQuantifySubsystem(
00385   Amc_SubsystemInfo_t   *subSystem,
00386   array_t               *quantifyVars,
00387 Amc_QuantificationMode  quantificationMode)
00388 {
00389   Fsm_Fsm_t     *subSystemFsm   = AmcSubsystemReadFsm(subSystem);       
00390   Ntk_Network_t *network        = Fsm_FsmReadNetwork(subSystemFsm);
00391   mdd_manager   *mddManager     = Ntk_NetworkReadMddManager(network);
00392   graph_t       *partition      = Part_NetworkReadPartition(network);
00393 
00394   mdd_t         *result;
00395 
00396   array_t       *transitionRelationArray = Amc_AmcSubsystemReadRelationArray(subSystem);
00397 
00398   if( transitionRelationArray == NIL(array_t) ) { 
00399     /* Build the transition relation of this subsystem. */
00400     st_table    *vertexTable    = AmcSubsystemReadVertexTable(subSystem);
00401     st_generator                *stGen;
00402     char                        *latchName;
00403 
00404     transitionRelationArray     = array_alloc(mdd_t *, 0);   
00405     st_foreach_item(vertexTable, stGen, &latchName, NIL(char *)) {
00406 
00407       Ntk_Node_t        *latch          = Ntk_NetworkFindNodeByName(network, latchName);
00408       int               functionMddId   = Ntk_NodeReadMddId(Ntk_NodeReadShadow(latch));
00409 
00410       char      *nameLatchDataInput     = Ntk_NodeReadName(Ntk_LatchReadDataInput(latch));
00411       vertex_t  *ptrVertex      = Part_PartitionFindVertexByName(partition, nameLatchDataInput);
00412 
00413       Mvf_Function_t    *nextStateFunction;
00414       mdd_t             *transitionRelation;
00415       nextStateFunction         = Part_VertexReadFunction(ptrVertex);
00416       transitionRelation        = Mvf_FunctionBuildRelationWithVariable(nextStateFunction,
00417                                                                 functionMddId);
00418 #ifdef AMC_DEBUG
00419     {
00420       int y, mddId; array_t *supportOfRelation;
00421       fprintf(vis_stdout, "\nThe transition relation of the output function of the node : %s", latchName);
00422       supportOfRelation = mdd_get_support(mddManager, transitionRelation);
00423       arrayForEachItem(int, supportOfRelation, y, mddId) {
00424         Ntk_Node_t *supportNode = Ntk_NetworkFindNodeByMddId(network, mddId);
00425         fprintf(vis_stdout, "\n\tThe node in the support : %s", 
00426                                        Ntk_NodeReadName(supportNode));
00427       }
00428     }
00429 #endif 
00430 
00431       if( nextStateFunction == NIL(Mvf_Function_t) ) {
00432          error_append("** amc error: Build partition before running approximate model checker.");
00433          return NIL(mdd_t);
00434       }
00435 
00436       array_insert_last(mdd_t *, transitionRelationArray, transitionRelation);
00437     } /* end of st_foreach_item */
00438 
00439     /* Cache the transition relation of the subsystem. */
00440     Amc_AmcSubsystemSetRelationArray(subSystem, transitionRelationArray);
00441 
00442   } /* end of transition relation construction. */
00443 
00444 
00445   /*
00446    * Notice : The present and next state variable of a subsystem is identical
00447    * to that of the original system. The subsystem carries the subset of the
00448    * output functions of the original system.
00449    */
00450   if( quantificationMode == Amc_User_c ) {
00451     /* result = Img_MultiwayLinearAndSmooth(mddManager, transitionRelationArray, quantifyVars,
00452                                          NIL(array_t)); */
00453     if( AmcSubsystemReadNextStateVarSmoothen(subSystem) == NIL(mdd_t) ) {
00454       result = Fsm_MddMultiwayAndSmooth(mddManager, transitionRelationArray, quantifyVars);
00455       AmcSubsystemSetNextStateVarSmoothen(subSystem, result);
00456     }
00457     else {
00458       result = AmcSubsystemReadNextStateVarSmoothen(subSystem);
00459     }
00460   }
00461   else if( quantificationMode == Amc_PresentVars_c ) {
00462     array_t     *presentVars    = Fsm_FsmReadPresentStateVars(subSystemFsm);
00463     result = Fsm_MddMultiwayAndSmooth(mddManager, transitionRelationArray, presentVars);
00464   }
00465   else if( quantificationMode == Amc_NextVars_c ) {
00466     array_t     *nextVars       = Fsm_FsmReadNextStateVars(subSystemFsm);
00467     result = Fsm_MddMultiwayAndSmooth(mddManager, transitionRelationArray, nextVars);
00468   }
00469   else if( quantificationMode == Amc_InputVars_c ) {
00470     array_t     *inputVars      = Fsm_FsmReadInputVars(subSystemFsm);
00471     result = Fsm_MddMultiwayAndSmooth(mddManager, transitionRelationArray, inputVars);
00472   }
00473   else {
00474     error_append("** amc error: Invalid quantification mode.");
00475     return NIL(mdd_t);
00476   }
00477 
00478 
00479   return(result);
00480 
00481 }
00482 
00517 array_t *
00518 Amc_AmcExistentialQuantifySubsystemArray(
00519   array_t                       *subSystemArray,
00520   Amc_SubsystemInfo_t           *currentSystem,
00521   array_t                       *quantifyVars,
00522   Amc_QuantificationMode        quantificationMode)
00523 {
00524   int i;
00525   Amc_SubsystemInfo_t   *subSystem; 
00526   mdd_t                 *quantifiedSystemMdd;
00527   array_t               *quantifiedSystemMddArray = array_alloc(mdd_t *, 0);
00528 
00529   if( (quantificationMode == Amc_User_c) && (quantifyVars == NIL(array_t)) ) {
00530     error_append("** amc error: Subsystem has no output functions.");
00531     return NIL(array_t);
00532   }
00533 
00534   arrayForEachItem(Amc_SubsystemInfo_t *, subSystemArray, i, subSystem) {
00535     if( (!subSystem->takenIntoOptimal) && (i != currentSystem->takenIntoOptimal) ) {
00536 
00537       quantifiedSystemMdd =
00538         Amc_AmcExistentialQuantifySubsystem(subSystem, quantifyVars, 
00539                                             quantificationMode);
00540       array_insert_last(mdd_t *, quantifiedSystemMddArray, quantifiedSystemMdd);
00541     }
00542   }
00543 
00544   return(quantifiedSystemMddArray);
00545 
00546 }
00547 
00548 
00558 Fsm_Fsm_t *
00559 Amc_AmcSubsystemReadFsm(
00560   Amc_SubsystemInfo_t *system)
00561 {
00562   return AmcSubsystemReadFsm(system);
00563 } /* End of Amc_AmcSubsystemReadFsm */
00564 
00574 void
00575 Amc_AmcSubsystemSetFsm(
00576   Amc_SubsystemInfo_t *system,
00577   Fsm_Fsm_t *info)
00578 {
00579   AmcSubsystemSetFsm(system, info);
00580 } /* End of Amc_AmcSubsystemReadFsm */
00581 
00582 
00593 array_t *
00594 Amc_AmcSubsystemReadRelationArray(
00595   Amc_SubsystemInfo_t *system)
00596 {
00597   return AmcSubsystemReadRelationArray(system);
00598 } /* End of Amc_AmcSubsystemReadTransitionRelation */
00599 
00610 void
00611 Amc_AmcSubsystemSetRelationArray(
00612   Amc_SubsystemInfo_t   *system,
00613   array_t               *info)
00614 {
00615   AmcSubsystemSetRelationArray(system, info);
00616 } /* End of Amc_AmcSubsystemSetTransitionRelation */
00617 
00618 
00632 mdd_t *
00633 Amc_AmcSubsystemReadNextStateVarSmoothen(
00634   Amc_SubsystemInfo_t *system)
00635 {
00636   return AmcSubsystemReadNextStateVarSmoothen(system);
00637 } /* End of Amc_AmcSubsystemReadNextStateVarSmooth */
00638 
00649 void
00650 Amc_AmcSubsystemSetNextStateVarSmoothen(
00651   Amc_SubsystemInfo_t   *system,
00652   mdd_t                 *info)
00653 {
00654   AmcSubsystemSetNextStateVarSmoothen(system, info);
00655 } /* End of Amc_AmcSubsystemSetNextStateVarSmooth */
00656 
00666 mdd_t *
00667 Amc_AmcSubsystemReadSatisfy(
00668   Amc_SubsystemInfo_t *system)
00669 {
00670   return AmcSubsystemReadSatisfy(system);
00671 } /* End of Amc_AmcSubsystemReadSatisfy */
00672 
00687 void
00688 Amc_AmcSubsystemSetSatisfy(
00689   Amc_SubsystemInfo_t *system,
00690   mdd_t *data)
00691 {
00692   AmcSubsystemSetSatisfy(system, data);
00693 } /* End of Amc_AmcSubsystemSetSatisfy */
00694 
00708 st_table *
00709 Amc_AmcSubsystemReadVertexTable(
00710   Amc_SubsystemInfo_t *system)
00711 {
00712   return AmcSubsystemReadVertexTable(system);
00713 } /* End of Amc_AmcSubsystemReadVertexTable */
00714 
00724 void
00725 Amc_AmcSubsystemSetVertexTable(
00726   Amc_SubsystemInfo_t *system,
00727   st_table *data)
00728 {
00729   AmcSubsystemSetVertexTable(system, data);
00730 } /* End of Amc_AmcSubsystemSetVertexTable */
00731 
00746 st_table *
00747 Amc_AmcSubsystemReadFanInTable(
00748   Amc_SubsystemInfo_t *system)
00749 {
00750   return AmcSubsystemReadFanInTable(system);
00751 } /* End of Amc_AmcSubsystemReadFanInTable */
00752 
00762 void
00763 Amc_AmcSubsystemSetFanInTable(
00764   Amc_SubsystemInfo_t *system,
00765   st_table *data)
00766 {
00767   AmcSubsystemSetFanInTable(system, data);
00768 } /* End of Amc_AmcSubsystemSetFanInTable */
00769 
00784 st_table *
00785 Amc_AmcSubsystemReadFanOutTable(
00786   Amc_SubsystemInfo_t *system)
00787 {
00788   return AmcSubsystemReadFanOutTable(system);
00789 } /* End of Amc_AmcSubsystemReadFanOutTable */
00790 
00800 void
00801 Amc_AmcSubsystemSetFanOutTable(
00802   Amc_SubsystemInfo_t *system,
00803   st_table *data)
00804 {
00805   AmcSubsystemSetFanOutTable(system, data);
00806 } /* End of Amc_AmcSubsystemSetFanOutTable */
00807 
00808 
00821 char *
00822 Amc_AmcSubsystemReadMethodSpecificData(
00823   Amc_SubsystemInfo_t *system)
00824 {
00825   return AmcSubsystemReadMethodSpecificData(system);
00826 } /* End of Amc_AmcSubsystemReadMethodSpecificData */
00827 
00837 void 
00838 Amc_AmcSubsystemSetMethodSpecificData(
00839   Amc_SubsystemInfo_t *system,
00840   char                *data)
00841 {
00842   AmcSubsystemSetMethodSpecificData(system, data);
00843 } /* End of Amc_AmcSubsystemSetMethodSpecificData */
00844 
00845 
00846 
00856 mdd_t *
00857 Amc_AmcReadInitialStates(
00858   Amc_Info_t *system)
00859 {
00860   return AmcReadInitialStates(system);
00861 } /* End of Amc_AmcReadInitialStates */
00862 
00872 void
00873 Amc_AmcSetInitialStates(
00874   Amc_Info_t    *system,
00875   mdd_t         *data)
00876 {
00877   AmcSetInitialStates(system, data);
00878 } /* End of Amc_AmcSetInitialStates */
00879 
00889 Amc_SubsystemInfo_t *
00890 Amc_AmcReadOptimalSystem(
00891   Amc_Info_t *system)
00892 {
00893   return AmcReadOptimalSystem(system);
00894 } /* End of Amc_AmcReadOptimalSystem */
00895 
00905 void
00906 Amc_AmcSetOptimalSystem(
00907   Amc_Info_t *system,
00908   Amc_SubsystemInfo_t    *data)
00909 {
00910   AmcSetOptimalSystem(system, data);
00911 } /* End of Amc_AmcSetOptimalSystem */
00912 
00922 void *
00923 Amc_AmcReadMethodData(
00924   Amc_Info_t *system)
00925 {
00926   return AmcReadMethodData(system);
00927 } /* End of Amc_AmcReadMethodData */
00928 
00938 void
00939 Amc_AmcSetMethodData(
00940   Amc_Info_t    *system,
00941   void          *data)
00942 {
00943   AmcSetMethodData(system, data);
00944 } /* End of Amc_AmcSetMethodData */
00945 
00946 
00947 
00957 Amc_SubsystemInfo_t *
00958 Amc_AmcSubsystemAllocate(void)
00959 {
00960   Amc_SubsystemInfo_t *result;
00961 
00962   result = ALLOC(Amc_SubsystemInfo_t, 1);
00963 
00964   return result;
00965 } /* End of Amc_SubsystemAllocate */
00966 
00967 
00979 Amc_SubsystemInfo_t *
00980 Amc_AmcSubsystemCreate(
00981   Fsm_Fsm_t             *fsm,
00982   mdd_t                 *satisfyStates,
00983   st_table              *vertexTable,
00984   st_table              *fanInTable,
00985   st_table              *fanOutTable)
00986 {
00987   Amc_SubsystemInfo_t *result;
00988 
00989   result                        = ALLOC(Amc_SubsystemInfo_t, 1);
00990   result->fsm                   = fsm;
00991   result->relationArray         = NIL(array_t);
00992   result->nextStateVarSmoothen  = NIL(mdd_t);
00993   result->satisfyStates         = satisfyStates;
00994   result->vertexTable           = vertexTable;
00995   result->fanInTable            = fanInTable;
00996   result->fanOutTable           = fanOutTable;
00997   result->takenIntoOptimal      = 0;  /* Initialize to 0 */
00998   result->methodSpecificData    = NIL(char);
00999 
01000   return result;
01001 } 
01002 
01012 Amc_SubsystemInfo_t *
01013 Amc_AmcSubsystemDuplicate(
01014   Ntk_Network_t       *network, 
01015   Amc_SubsystemInfo_t *subSystem)
01016 {
01017   Fsm_Fsm_t     *fsm;
01018   mdd_t         *satisfyStates  = NIL(mdd_t);
01019   st_table      *vertexTable    = NIL(st_table);
01020   st_table      *fanInTable     = NIL(st_table);
01021   st_table      *fanOutTable    = NIL(st_table);
01022   graph_t       *partition      = Part_NetworkReadPartition(network);
01023 
01024   if(subSystem->satisfyStates != NIL(mdd_t)) {
01025     satisfyStates = mdd_dup(subSystem->satisfyStates);
01026   }
01027   if(subSystem->vertexTable != NIL(st_table)) {
01028     vertexTable = st_copy(subSystem->vertexTable);
01029   }
01030   if(subSystem->fanInTable != NIL(st_table)) {
01031     fanInTable = st_copy(subSystem->fanInTable);
01032   }
01033   if(subSystem->fanOutTable != NIL(st_table)) {
01034     fanOutTable = st_copy(subSystem->fanOutTable);
01035   }
01036 
01037   fsm = Fsm_FsmCreateSubsystemFromNetwork(network, partition, vertexTable,
01038         FALSE, 0);
01039 
01040   return(Amc_AmcSubsystemCreate(fsm, satisfyStates, vertexTable, fanInTable, fanOutTable));
01041 }
01042 
01043 
01044 
01057 void
01058 Amc_AmcSubsystemFree(
01059   Amc_SubsystemInfo_t *subSystem)
01060 {
01061   st_table      *vertexTable;
01062   st_table      *fanInTable, *fanOutTable;
01063 
01064   /* Do not free partition associated to this fsm */
01065   if (AmcSubsystemReadFsm(subSystem) != NIL(Fsm_Fsm_t)) {
01066     Fsm_FsmSubsystemFree(AmcSubsystemReadFsm(subSystem));
01067   } 
01068 
01069   if (AmcSubsystemReadRelationArray(subSystem) != NIL(array_t)) {
01070     array_t *transitionRelationArray = AmcSubsystemReadRelationArray(subSystem);
01071     mdd_t   *transitionRelation;
01072     int         i;
01073     arrayForEachItem(mdd_t *, transitionRelationArray, i, transitionRelation) {
01074       mdd_free(transitionRelation); 
01075     } 
01076     array_free(transitionRelationArray);
01077   }
01078 
01079   if (AmcSubsystemReadNextStateVarSmoothen(subSystem) != NIL(mdd_t)) {
01080     mdd_free(AmcSubsystemReadNextStateVarSmoothen(subSystem));
01081   }
01082 
01083   if (AmcSubsystemReadSatisfy(subSystem) != NIL(mdd_t)) {
01084     mdd_free(AmcSubsystemReadSatisfy(subSystem));
01085   } 
01086 
01087   /* Do not free vertex!! */
01088   vertexTable = AmcSubsystemReadVertexTable(subSystem);
01089   if (vertexTable != NIL(st_table)) {
01090     st_free_table(vertexTable);
01091   }
01092 
01093   fanInTable = AmcSubsystemReadFanInTable(subSystem);
01094   if (fanInTable != NIL(st_table)) {
01095     st_free_table(fanInTable);
01096   }
01097 
01098   fanOutTable = AmcSubsystemReadFanOutTable(subSystem);
01099   if (fanOutTable != NIL(st_table)) {
01100     st_free_table(fanOutTable);
01101   }
01102 
01103 
01104   FREE(subSystem);
01105 } 
01106 
01118 void
01119 Amc_AmcSubsystemFreeAlsoPartition(
01120   Amc_SubsystemInfo_t *subSystem)
01121 {
01122   st_table      *vertexTable;
01123   st_table      *fanInTable, *fanOutTable;
01124 
01125   /* Do not free partition associated to this fsm */
01126   if (AmcSubsystemReadFsm(subSystem) != NIL(Fsm_Fsm_t)) {
01127     Fsm_FsmFree(AmcSubsystemReadFsm(subSystem));
01128   } 
01129 
01130   if (AmcSubsystemReadRelationArray(subSystem) != NIL(array_t)) {
01131     array_t *transitionRelationArray = AmcSubsystemReadRelationArray(subSystem);
01132     mdd_t   *transitionRelation;
01133     int         i;
01134     arrayForEachItem(mdd_t *, transitionRelationArray, i, transitionRelation) {
01135       mdd_free(transitionRelation); 
01136     } 
01137     array_free(transitionRelationArray);
01138   }
01139 
01140   if (AmcSubsystemReadNextStateVarSmoothen(subSystem) != NIL(mdd_t)) {
01141     mdd_free(AmcSubsystemReadNextStateVarSmoothen(subSystem));
01142   }
01143 
01144   if (AmcSubsystemReadSatisfy(subSystem) != NIL(mdd_t)) {
01145     mdd_free(AmcSubsystemReadSatisfy(subSystem));
01146   } 
01147 
01148   /* Do not free vertex!! */
01149   vertexTable = AmcSubsystemReadVertexTable(subSystem);
01150   if (vertexTable != NIL(st_table)) {
01151     st_free_table(vertexTable);
01152   }
01153 
01154   fanInTable = AmcSubsystemReadFanInTable(subSystem);
01155   if (fanInTable != NIL(st_table)) {
01156     st_free_table(fanInTable);
01157   }
01158 
01159   fanOutTable = AmcSubsystemReadFanOutTable(subSystem);
01160   if (fanOutTable != NIL(st_table)) {
01161     st_free_table(fanOutTable);
01162   }
01163 
01164 
01165   FREE(subSystem);
01166 } 
01167 
01168 
01169 
01170 
01186 Amc_SubsystemInfo_t *
01187 Amc_CombineSubsystems(
01188   Ntk_Network_t         *network,
01189   Amc_SubsystemInfo_t   *subSystem1,
01190   Amc_SubsystemInfo_t   *subSystem2)
01191 {
01192   Amc_SubsystemInfo_t   *subSystemInfo;
01193   Amc_SubsystemInfo_t   *subSystem;
01194   st_table              *vertexTable, *vertexTable1, *vertexTable2;
01195   st_table              *fanInTable = NIL(st_table);
01196   st_table              *fanOutTable = NIL(st_table);
01197   st_table              *fanInTable1, *fanInTable2;
01198   st_table              *fanOutTable1, *fanOutTable2;
01199   Ntk_Node_t            *latch;  
01200   graph_t               *partition = Part_NetworkReadPartition(network);
01201   Fsm_Fsm_t             *fsm;
01202   lsGen                 gen;
01203   st_generator          *stGen;
01204 
01205   /* If two subsystem are identical return error */
01206   if(subSystem1 == subSystem2) {
01207     error_append("** amc error: illegal subsystem combination");
01208     return NIL(Amc_SubsystemInfo_t);
01209   }
01210   /* If two subsystem are NIL return error */
01211   if( (subSystem1 == NIL(Amc_SubsystemInfo_t)) && 
01212       (subSystem2 == NIL(Amc_SubsystemInfo_t)) ) {
01213     error_append("** amc error: illegal subsystem combination");
01214     return NIL(Amc_SubsystemInfo_t);
01215   }
01216 
01217   /* If either of two subsystem is NIL return copy of the other */
01218   if(subSystem1 == NIL(Amc_SubsystemInfo_t)) {
01219     return Amc_AmcSubsystemDuplicate(network, subSystem2);
01220   }
01221   if(subSystem2 == NIL(Amc_SubsystemInfo_t)) {
01222     return Amc_AmcSubsystemDuplicate(network, subSystem1);
01223   }
01224 
01225   vertexTable  = st_init_table(strcmp, st_strhash); 
01226   vertexTable1 = AmcSubsystemReadVertexTable(subSystem1);
01227   vertexTable2 = AmcSubsystemReadVertexTable(subSystem2);
01228 
01229   Ntk_NetworkForEachLatch(network, gen, latch) {
01230     char *latchName = Ntk_NodeReadName(latch);
01231     if( st_lookup(vertexTable1, latchName, (char **)0) || 
01232         st_lookup(vertexTable2, latchName, (char **)0) ) {
01233 
01234       st_insert(vertexTable, latchName, (char *)0);
01235 
01236     }
01237   } /* end of Ntk_NetworkForEachLatch */
01238 
01239 
01240   fanInTable1 = AmcSubsystemReadFanInTable(subSystem1);
01241   fanInTable2 = AmcSubsystemReadFanInTable(subSystem2);
01242   if( (fanInTable1 != NIL(st_table)) && (fanInTable2 != NIL(st_table)) ) { 
01243 
01244     fanInTable  = st_init_table(st_ptrcmp, st_ptrhash); 
01245 
01246     st_foreach_item(fanInTable1, stGen, &subSystem, NIL(char *)) {
01247       st_insert(fanInTable, (char *)subSystem, (char *)0);
01248     }
01249     st_foreach_item(fanInTable2, stGen, &subSystem, NIL(char *)) {
01250       st_insert(fanInTable, (char *)subSystem, (char *)0);
01251     }
01252   }
01253 
01254 
01255   fanOutTable1 = AmcSubsystemReadFanOutTable(subSystem1);
01256   fanOutTable2 = AmcSubsystemReadFanOutTable(subSystem2);
01257 
01258   if( (fanOutTable1 != NIL(st_table)) && (fanOutTable2 != NIL(st_table)) ) { 
01259 
01260     fanOutTable  = st_init_table(st_ptrcmp, st_ptrhash); 
01261 
01262     st_foreach_item(fanInTable1, stGen, &subSystem, NIL(char *)) {
01263       st_insert(fanOutTable, subSystem, (char *)0);
01264     }
01265     st_foreach_item(fanInTable2, stGen, &subSystem, NIL(char *)) {
01266       st_insert(fanOutTable, subSystem, (char *)0);
01267     }
01268   }
01269 
01270 
01271   fsm = Fsm_FsmCreateSubsystemFromNetwork(network, partition, vertexTable,
01272         FALSE, 0);
01273 
01274   subSystemInfo = Amc_AmcSubsystemCreate(fsm, NIL(mdd_t), vertexTable, 
01275                                             fanInTable, fanOutTable);
01276 
01277   /* Does not free tables */
01278 
01279   return(subSystemInfo);
01280 }
01281 
01282 #ifdef AMC_DEBUG_
01283 
01295 Img_ImageInfo_t *
01296 Amc_AmcReadOrCreateImageInfo(
01297   Fsm_Fsm_t *fsm)
01298 {
01299   Img_ImageInfo_t *imageInfo;
01300   if( Fsm_FsmReadImageInfo(fsm) == NIL(Img_ImageInfo_t)) {
01301     array_t *dummyInputVars     = array_alloc(int, 0);
01302     imageInfo = Img_ImageInfoInitialize(Fsm_FsmReadPartition(fsm),
01303                                         Fsm_FsmReadNextStateFunctions(fsm),
01304                                         Fsm_FsmReadPresentStateVars(fsm),
01305                                         Fsm_FsmReadNextStateVars(fsm),
01306                                         dummyInputVars,
01307                                         Fsm_FsmReadNetwork(fsm),
01308                                         Img_Default_c, Img_Both_c);
01309     Fsm_FsmSetImageInfo(fsm, imageInfo);
01310     array_free(dummyInputVars);
01311   }
01312   return (imageInfo);
01313 }
01314 #endif
01315 
01327 mdd_t * 
01328 Amc_AmcEvaluateCTLFormula(
01329   Amc_SubsystemInfo_t   *subSystem,
01330   array_t               *subSystemArray,
01331   Ctlp_Formula_t        *ctlFormula, 
01332   mdd_t                 *fairStates, 
01333   Fsm_Fairness_t        *fairCondition, 
01334   mdd_t                 *modelCareStates,
01335   boolean               lowerBound,
01336   array_t               *quantifyVars,
01337   Mc_VerbosityLevel     verbosity,
01338   Mc_DcLevel            dcLevel )
01339 {
01340   Fsm_Fsm_t     *modelFsm = Amc_AmcSubsystemReadFsm(subSystem);
01341 
01342   mdd_t  *leftMdd  = NIL(mdd_t);
01343   mdd_t  *rightMdd = NIL(mdd_t);
01344   mdd_t  *result   = NIL(mdd_t);
01345   mdd_t  *tmpResult = NIL(mdd_t);
01346 
01347   mdd_t *ctlFormulaStates = Ctlp_FormulaObtainStates(ctlFormula );
01348   mdd_manager *mddMgr = Fsm_FsmReadMddManager(modelFsm);
01349   mdd_t *careStates = NIL(mdd_t);
01350   
01351 
01352   if (ctlFormulaStates) {
01353     return ctlFormulaStates;
01354   }
01355   
01356   { 
01357     Ctlp_Formula_t *leftChild = Ctlp_FormulaReadLeftChild(ctlFormula);
01358     if (leftChild) {
01359       leftMdd = Amc_AmcEvaluateCTLFormula(subSystem, subSystemArray, leftChild, fairStates, fairCondition, 
01360                                    modelCareStates, lowerBound, quantifyVars, verbosity, dcLevel); 
01361       if (!leftMdd) 
01362         return NIL(mdd_t);
01363     }
01364   }
01365 
01366   {
01367     Ctlp_Formula_t *rightChild = Ctlp_FormulaReadRightChild(ctlFormula);
01368     if (rightChild) {
01369       rightMdd = Amc_AmcEvaluateCTLFormula(subSystem, subSystemArray, rightChild, fairStates, fairCondition, 
01370                                     modelCareStates, lowerBound, quantifyVars, verbosity, dcLevel);
01371       if (!rightMdd ) 
01372         return NIL(mdd_t);
01373     }
01374   }
01375 
01376   careStates = (modelCareStates != NIL(mdd_t)) ?  mdd_dup(modelCareStates) : mdd_one(mddMgr);
01377   switch ( Ctlp_FormulaReadType( ctlFormula ) ) {
01378 
01379     case Ctlp_ID_c : tmpResult = AmcModelCheckAtomicFormula( modelFsm, ctlFormula ); 
01380 
01381        /* #AMC : Obtain lowerbound of the constraint set. */
01382       if(0 && lowerBound) { /*Chao: this is not correct! consider !EF(!p) */
01383         array_t *quantifyPresentVars     = array_fetch(array_t *, quantifyVars, 0);
01384         int     numOfPresentQuantifyVars = array_n(quantifyPresentVars);
01385         /* 
01386          * Currently VIS does not allow primary input as the variable of 
01387          * the atomic propositions. 
01388          */
01389         if(numOfPresentQuantifyVars > 0) {
01390            result = mdd_consensus(mddMgr, tmpResult, quantifyPresentVars);  
01391            mdd_free(tmpResult);
01392         }
01393         else
01394            result = tmpResult;
01395         }
01396       else
01397         result = tmpResult;
01398 
01399       break;
01400 
01401     case Ctlp_TRUE_c : result = mdd_one( mddMgr ); break;
01402     case Ctlp_FALSE_c : result = mdd_zero( mddMgr ); break;
01403 
01404     case Ctlp_NOT_c : result = mdd_not( leftMdd ); break;
01405     case Ctlp_EQ_c : result = mdd_xnor( leftMdd, rightMdd ); break;
01406     case Ctlp_XOR_c : result = mdd_xor( leftMdd, rightMdd ); break;
01407     case Ctlp_THEN_c : result = mdd_or( leftMdd, rightMdd, 0, 1 ); break;
01408     case Ctlp_AND_c: result = mdd_and( leftMdd, rightMdd, 1, 1 ); break;
01409     case Ctlp_OR_c: result = mdd_or( leftMdd, rightMdd, 1, 1 ); break;
01410 
01411     case Ctlp_EX_c: 
01412       result = Amc_AmcEvaluateEXFormula( modelFsm, subSystemArray, subSystem, leftMdd, fairStates, 
01413                                         careStates, lowerBound, quantifyVars, verbosity, dcLevel );
01414       break;
01415 
01416     case Ctlp_EU_c: {
01417       array_t *onionRings = array_alloc( mdd_t *, 0 );
01418       result = Amc_AmcEvaluateEUFormula( modelFsm, subSystemArray, subSystem, leftMdd, rightMdd, fairStates, 
01419                                     careStates, onionRings, lowerBound, quantifyVars, verbosity, dcLevel );
01420       Ctlp_FormulaSetDbgInfo( ctlFormula, (void *) onionRings, McFormulaFreeDebugData); 
01421       break;
01422     }
01423 
01424     case Ctlp_EG_c: {
01425       array_t *arrayOfOnionRings = array_alloc( array_t *, 0 );
01426       result = Amc_AmcEvaluateEGFormula( modelFsm, subSystemArray, subSystem, leftMdd, 
01427                                         fairStates, fairCondition, careStates, 
01428                                         arrayOfOnionRings, lowerBound, quantifyVars, verbosity, dcLevel );
01429       Ctlp_FormulaSetDbgInfo( ctlFormula, (void *) arrayOfOnionRings, McFormulaFreeDebugData); 
01430       break;
01431     }
01432 
01433     default: fail("Encountered unknown type of CTL formula\n");
01434   }
01435 
01436 
01437   Ctlp_FormulaSetStates( ctlFormula, result );
01438 
01439   mdd_free( careStates );
01440   return result;
01441 }
01442 
01473 mdd_t *
01474 Amc_AmcEvaluateEXFormula(
01475   Fsm_Fsm_t             *modelFsm,
01476   array_t               *subSystemArray, 
01477   Amc_SubsystemInfo_t   *subSystem,
01478   mdd_t                 *targetMdd,
01479   mdd_t                 *fairStates,
01480   mdd_t                 *careStates,
01481   boolean               lowerBound,
01482   array_t               *quantifyVars,
01483   Mc_VerbosityLevel     verbosity,
01484   Mc_DcLevel            dcLevel )
01485 {
01486   /* 
01487    * The care set consists of the passed careStates 
01488    */
01489   mdd_t *toCareSet = mdd_dup( careStates );
01490 
01491   mdd_t *fromLowerBound;
01492   mdd_t *fromUpperBound;
01493   mdd_t *result = NIL(mdd_t);
01494   mdd_t *tmpResult;
01495   mdd_manager *mddManager = Fsm_FsmReadMddManager( modelFsm );
01496   array_t *quantifyPresentVars = array_fetch(array_t *, quantifyVars, 0);
01497   
01498   Img_ImageInfo_t * imageInfo;
01499 
01500   assert(quantifyPresentVars != NIL(array_t));
01501 
01502   imageInfo = Fsm_FsmReadOrCreateImageInfo(modelFsm, 1, 1);
01503 
01504   if ( dcLevel == McDcLevelRchFrontier_c ) {
01505     /*
01506      * The lower bound is the conjunction of the fair states,
01507      * the target states, and the care states.
01508      */
01509     mdd_t *tmpMdd = mdd_and( targetMdd, fairStates, 1, 1 );
01510     fromLowerBound = mdd_and( tmpMdd, careStates, 1, 1 );
01511     mdd_free( tmpMdd );
01512     /* 
01513      * The upper bound is the OR of the lower bound with the 
01514      * complement of the care states.
01515      */
01516     fromUpperBound = mdd_or( fromLowerBound, careStates, 1, 0 );
01517   }
01518   else {
01519     /*
01520      * The lower bound is the conjunction of the fair states,
01521      * and the target states.
01522      */
01523     fromLowerBound = mdd_and( targetMdd, fairStates, 1, 1 );
01524     /*
01525      * The upper bound is the same as the lower bound.
01526      */
01527     fromUpperBound = mdd_dup( fromLowerBound );
01528   }
01529 
01530 
01531   /***************************************************************************
01532    * compute C1(s) =
01533    *    C(s)                         for upper-bound EX computation
01534    *    ( \forall (s_R) C(s) )       for lower-bound EX computation
01535    ***************************************************************************/
01536   if (lowerBound) {
01537       mdd_t *mdd1, *mdd2;
01538       mdd1 = fromLowerBound;
01539       mdd2 = fromUpperBound;
01540       if (array_n(quantifyPresentVars) > 0) {
01541         fromLowerBound = mdd_consensus(mddManager, fromLowerBound,
01542                                        quantifyPresentVars);
01543       } else {
01544         fromLowerBound = mdd_dup(fromLowerBound);
01545       }
01546       if (mdd_equal(mdd1, mdd2)) {
01547         fromUpperBound = mdd_dup(fromLowerBound);
01548       }else {
01549         if (array_n(quantifyPresentVars) > 0) {
01550           fromUpperBound = mdd_consensus(mddManager, fromUpperBound,
01551                                          quantifyPresentVars);
01552         } else {
01553           fromUpperBound = mdd_dup(fromUpperBound);
01554         }
01555       }
01556       mdd_free(mdd1);
01557       mdd_free(mdd2);
01558   }
01559 
01560   /***************************************************************************
01561    * Compute \exist (t,x) ( T_A(s,x,t_A) * C1(t) ), where
01562    *    C1(t) = C(t)                      for upper-bound EX
01563    *    C1(t) = (\forall (t_R) C(t) )     for lower-bound EX
01564    ***************************************************************************/
01565   tmpResult = Img_ImageInfoComputeBwdWithDomainVars( imageInfo,
01566                                                      fromLowerBound,
01567                                                      fromUpperBound,
01568                                                      toCareSet );
01569 
01570   /***************************************************************************
01571    * Compute the final result
01572    *    \exist  (s_R)  (tmpResult(s))      for upper-bound EX
01573    *    \forall (s_R)  (tmpResult(s))      for lower-bound EX
01574    **************************************************************************/
01575   if (lowerBound) {
01576     if (array_n(quantifyPresentVars) > 0) {
01577       result = mdd_consensus(mddManager, tmpResult, quantifyPresentVars);
01578     } else {
01579       result = mdd_dup(tmpResult);
01580     }
01581   }else {
01582     result = mdd_dup(tmpResult);
01583     /*  result = mdd_smooth(mddManager, tmpResult, quantifyPresentVars);*/
01584   } 
01585   mdd_free(tmpResult);
01586   
01587   mdd_free( fromLowerBound );
01588   mdd_free( fromUpperBound );
01589   mdd_free( toCareSet );
01590 
01591   if ( verbosity == McVerbosityMax_c ) {
01592     static int refCount = 0;
01593     mdd_manager *mddMgr = Fsm_FsmReadMddManager( modelFsm );
01594     array_t *psVars     = Fsm_FsmReadPresentStateVars( modelFsm );
01595     mdd_t *tmpMdd = careStates ? mdd_and( result, careStates, 1, 1 ) : mdd_dup( result );
01596     fprintf(vis_stdout, "--EX called %d (bdd_size - %d)\n", ++refCount, mdd_size( result ) );
01597     fprintf(vis_stdout, "--There are %.0f care states satisfying EX formula\n", 
01598             mdd_count_onset(  mddMgr, tmpMdd, psVars ) ); 
01599     mdd_free(tmpMdd);
01600   }
01601 
01602   return result;
01603 }
01604 
01605 #if 0
01606 /* this is the original (buggy) version */
01607 mdd_t *
01608 Amc_AmcEvaluateEXFormula_Old(
01609   Fsm_Fsm_t             *modelFsm,
01610   array_t               *subSystemArray, 
01611   Amc_SubsystemInfo_t   *subSystem,
01612   mdd_t                 *targetMdd,
01613   mdd_t                 *fairStates,
01614   mdd_t                 *careStates,
01615   boolean               lowerBound,
01616   array_t               *quantifyVars,
01617   Mc_VerbosityLevel     verbosity,
01618   Mc_DcLevel            dcLevel )
01619 {
01620   /* 
01621    * The care set consists of the passed careStates 
01622    */
01623   mdd_t *toCareSet = mdd_dup( careStates );
01624 
01625   mdd_t *fromLowerBound;
01626   mdd_t *fromUpperBound;
01627   mdd_t *result = NIL(mdd_t);
01628   mdd_t *tmpResult;
01629 
01630   Img_ImageInfo_t * imageInfo;
01631 
01632   imageInfo = Fsm_FsmReadOrCreateImageInfo(modelFsm, 1, 1);
01633 
01634   /*
01635    * this condition will never  be true; we didnt find it to be 
01636    * especially effective, are avoiding using it for now. later
01637    * we may add a McDcLevelMax+1 field which will allow us to use it
01638    *
01639    */
01640   if ( dcLevel > McDcLevelRchFrontier_c ) {
01641     /*
01642      * The lower bound is the conjunction of the fair states,
01643      * the target states, and the care states.
01644      */
01645     mdd_t *tmpMdd = mdd_and( targetMdd, fairStates, 1, 1 );
01646     fromLowerBound = mdd_and( tmpMdd, careStates, 1, 1 );
01647     mdd_free( tmpMdd );
01648     /* 
01649      * The upper bound is the OR of the lower bound with the 
01650      * complement of the care states.
01651      */
01652     fromUpperBound = mdd_or( fromLowerBound, careStates, 1, 0 );
01653   }
01654   else {
01655     /*
01656      * The lower bound is the conjunction of the fair states,
01657      * and the target states.
01658      */
01659     fromLowerBound = mdd_and( targetMdd, fairStates, 1, 1 );
01660     /*
01661      * The upper bound is the same as the lower bound.
01662      */
01663     fromUpperBound = mdd_dup( fromLowerBound );
01664   }
01665 
01666   /* #AMC : */
01667 #ifdef AMC_DEBUG
01668   if(lowerBound) {
01669     /* 
01670      * Sanity check. The set to compute a preimage from should only contain the present
01671      * state variables of the subsystem.
01672      */
01673     {
01674       mdd_manager       *mddManager     = Fsm_FsmReadMddManager( modelFsm );
01675       Ntk_Network_t     *network        = Fsm_FsmReadNetwork(modelFsm);
01676       array_t           *supportArray   = mdd_get_support(mddManager, fromLowerBound);
01677       st_table          *vertexTable    = Amc_AmcSubsystemReadVertexTable(subSystem);
01678       int               i, varId;
01679 
01680       fprintf(vis_stdout, "\n#AMC : Sanity check of the support of the constraint set");
01681       arrayForEachItem(int, supportArray, i, varId) {
01682         Ntk_Node_t  *node = Ntk_NetworkFindNodeByMddId(network, varId);
01683         char *latchName = Ntk_NodeReadName(node); 
01684         fprintf(vis_stdout, "\n#  fromLowerBound -- Node : %s", latchName);
01685       }
01686 
01687       arrayForEachItem(int, supportArray, i, varId) {
01688         char *latchName = Ntk_NodeReadName(Ntk_NetworkFindNodeByMddId(network, varId)); 
01689         if( !st_lookup(vertexTable, latchName, (char **)0 )) {
01690           fprintf(vis_stdout, "\n** amc error : Whoops!! Something's wrong in lowerbound routine.");
01691           fflush(vis_stdout); 
01692         }
01693       } /* end of arrayForEachItem */
01694     }
01695   } /* end of if(lowerBound) */
01696 #endif
01697 
01698   tmpResult = Img_ImageInfoComputeBwdWithDomainVars( imageInfo,
01699                                                      fromLowerBound,
01700                                                      fromUpperBound,
01701                                                      toCareSet );
01702 #ifdef AMC_DEBUG
01703     {
01704       Ntk_Network_t     *network        = Fsm_FsmReadNetwork(modelFsm);
01705       mdd_manager       *mddManager     = Fsm_FsmReadMddManager( modelFsm );
01706       array_t           *supportArray   = mdd_get_support(mddManager, tmpResult);
01707       int               i, varId;
01708 
01709       fprintf(vis_stdout, "\n#AMC : Sanity check of the support of the preimage");
01710       arrayForEachItem(int, supportArray, i, varId) {
01711         Ntk_Node_t  *node = Ntk_NetworkFindNodeByMddId(network, varId);
01712         char *latchName = Ntk_NodeReadName(node); 
01713         fprintf(vis_stdout, "\n## The preimage contains the node : %s", latchName);
01714         if( Ntk_NodeTestIsLatch(node) ) 
01715           fprintf(vis_stdout, "\n##  The node is a latch");
01716         else
01717           fprintf(vis_stdout, "\n##  The node is not a latch");
01718 
01719       } /* end of arrayForEachItem */
01720     }
01721 #endif
01722 
01723   /* #AMC : */
01724   if(lowerBound) {
01725     mdd_manager *mddManager       = Fsm_FsmReadMddManager( modelFsm );
01726     array_t     *quantifyNextVars = array_fetch(array_t *, quantifyVars, 1);
01727     array_t     *exQuantifiedSystemMddArray; 
01728 
01729     /* 
01730      * Existential abstraction of next state variables from subsystems that are
01731      * not currently in consideration. Each subsystem has disjoint next state
01732      * functions, hence we distribute existential abstraction over subsystems.
01733      */
01734 
01735     exQuantifiedSystemMddArray =
01736       Amc_AmcExistentialQuantifySubsystemArray(subSystemArray, subSystem,
01737                                                quantifyNextVars, Amc_User_c);
01738 
01739     /* 
01740      * Universal abstraction of present state and input variables from
01741      * subsystems that are not currently in consideration. 
01742      */
01743     {
01744       array_t   *quantifyPresentVars = array_fetch(array_t *, quantifyVars, 0);
01745       array_t   *quantifyInputVars   = array_fetch(array_t *, quantifyVars, 2);
01746       array_t   *consensusVarArray   = array_join(quantifyPresentVars,
01747                                                   quantifyInputVars);
01748       mdd_t     *interResult         = mdd_one( mddManager );
01749       mdd_t     *subMdd;
01750       int       i;
01751 
01752       array_insert_last(mdd_t *, exQuantifiedSystemMddArray, tmpResult);
01753       arrayForEachItem(mdd_t *, exQuantifiedSystemMddArray, i, subMdd) {
01754         mdd_t *cResult = mdd_consensus(mddManager, subMdd, consensusVarArray); 
01755         result = mdd_and(cResult, interResult, 1, 1); 
01756         mdd_free(cResult); mdd_free(interResult);
01757         interResult = result;
01758 
01759         if( mdd_is_tautology(result, 0) ) break;
01760       }
01761 
01762       mdd_free(tmpResult);
01763       /* Do not free Mdds. These are cached. */
01764       array_free(exQuantifiedSystemMddArray);
01765       array_free(consensusVarArray);
01766     }
01767 
01768 
01769   } /* end of if(lowerBound) */
01770   else {
01771    result = tmpResult;
01772   } /* end of #AMC insertion */
01773 
01774   mdd_free( fromLowerBound );
01775   mdd_free( fromUpperBound );
01776   mdd_free( toCareSet );
01777 
01778   if ( verbosity == McVerbosityMax_c ) {
01779     static int refCount = 0;
01780     mdd_manager *mddMgr = Fsm_FsmReadMddManager( modelFsm );
01781     array_t *psVars     = Fsm_FsmReadPresentStateVars( modelFsm );
01782     mdd_t *tmpMdd = careStates ? mdd_and( result, careStates, 1, 1 ) : mdd_dup( result );
01783     fprintf(vis_stdout, "--EX called %d (bdd_size - %d)\n", ++refCount, mdd_size( result ) );
01784     fprintf(vis_stdout, "--There are %.0f care states satisfying EX formula\n", 
01785             mdd_count_onset(  mddMgr, tmpMdd, psVars ) ); 
01786     mdd_free(tmpMdd);
01787   }
01788 
01789   return result;
01790 }
01791 #endif
01792 
01804 mdd_t *
01805 Amc_AmcEvaluateEUFormula( 
01806   Fsm_Fsm_t *modelFsm,
01807   array_t   *subSystemArray, 
01808   Amc_SubsystemInfo_t   *subSystem,
01809   mdd_t *invariantMdd,
01810   mdd_t *targetMdd,
01811   mdd_t *fairStates,
01812   mdd_t *careStates,
01813   array_t *onionRings,
01814   boolean lowerBound,
01815   array_t *quantifyVars,
01816   Mc_VerbosityLevel verbosity,
01817   Mc_DcLevel dcLevel )
01818 {
01819   mdd_t *aMdd;
01820   mdd_t *bMdd;
01821   mdd_t *cMdd;
01822   mdd_t *resultMdd = mdd_and( targetMdd, fairStates, 1, 1 );
01823   mdd_t *ringMdd   = mdd_dup( resultMdd ); 
01824 
01825   while (TRUE) { 
01826 
01827     if ( onionRings ) {
01828       array_insert_last( mdd_t *, onionRings, mdd_dup( resultMdd ) );
01829     }
01830 
01831     /*
01832      * When trying to use dont cares to the hilt, 
01833      * use a bdd between succ iterations -> ringMdd 
01834      */
01835     aMdd = Amc_AmcEvaluateEXFormula( modelFsm, subSystemArray, subSystem, ringMdd, fairStates, careStates,
01836                                     lowerBound, quantifyVars, verbosity, dcLevel );  
01837     mdd_free( ringMdd );
01838     bMdd = mdd_and( aMdd, invariantMdd, 1, 1 ); 
01839     cMdd = mdd_or( resultMdd, bMdd, 1, 1 ); 
01840 
01841     mdd_free( aMdd );
01842     mdd_free( bMdd );
01843 
01844     if ( mdd_equal_mod_care_set( cMdd, resultMdd, careStates ) ) {
01845       mdd_free( cMdd );
01846       break;
01847     }
01848 
01849     if ( dcLevel >= McDcLevelRchFrontier_c ) {
01850       mdd_t *tmpMdd = mdd_and( resultMdd, cMdd, 0, 1 );
01851       ringMdd = bdd_between( tmpMdd, cMdd );
01852       if ( verbosity == McVerbosityMax_c ) {
01853         fprintf(vis_stdout, "-- EU |A(n+1)-A(n)| = %d\t|A(n+1)| = %d\t|between-dc| = %d\n", 
01854                 mdd_size( tmpMdd ), mdd_size( resultMdd ), mdd_size( ringMdd ) );
01855       }
01856       mdd_free( tmpMdd );
01857     }
01858     else {
01859       ringMdd = mdd_dup( cMdd );
01860       if ( verbosity == McVerbosityMax_c ) {
01861         fprintf(vis_stdout, "-- EU |ringMdd| = %d\n", mdd_size( ringMdd ) );
01862       }
01863     }
01864 
01865     mdd_free( resultMdd );
01866     resultMdd = cMdd;
01867 
01868   }
01869 
01870   if ( ( verbosity == McVerbosityMax_c ) ) {
01871     static int refCount=0;
01872     mdd_manager *mddMgr = Fsm_FsmReadMddManager( modelFsm );
01873     array_t *psVars     = Fsm_FsmReadPresentStateVars( modelFsm );
01874     mdd_t *tmpMdd = careStates ? mdd_and( resultMdd, careStates, 1, 1 ) : mdd_dup( resultMdd );
01875     fprintf(vis_stdout, "--EU called %d (bdd_size - %d)\n", ++refCount, mdd_size( resultMdd ) );
01876     fprintf(vis_stdout, "--There are %.0f care states satisfying EU formula\n", 
01877             mdd_count_onset(  mddMgr, tmpMdd, psVars ) );
01878     mdd_free(tmpMdd);
01879   }
01880 
01881   return resultMdd;
01882 }
01883 
01894 mdd_t *
01895 Amc_AmcEvaluateEGFormula( 
01896   Fsm_Fsm_t *modelFsm,
01897   array_t   *subSystemArray,
01898   Amc_SubsystemInfo_t   *subSystem,
01899   mdd_t *invariantMdd,
01900   mdd_t *fairStates,
01901   Fsm_Fairness_t *modelFairness,
01902   mdd_t *careStates,
01903   array_t *onionRingsArrayForDbg,
01904   boolean lowerBound,
01905   array_t *quantifyVars,
01906   Mc_VerbosityLevel verbosity,
01907   Mc_DcLevel dcLevel )
01908 {
01909   int i;
01910   array_t *onionRings = NIL(array_t);
01911   array_t *tmpOnionRingsArrayForDbg = NIL(array_t);
01912   mdd_manager *mddManager = Fsm_FsmReadMddManager( modelFsm );
01913   mdd_t *mddOne = mdd_one( mddManager );
01914   mdd_t *Zmdd;
01915 
01916  
01917   array_t *buchiFairness = array_alloc( mdd_t *, 0 );
01918   if (modelFairness) {
01919     if ( !Fsm_FairnessTestIsBuchi( modelFairness ) ) {
01920       (void) fprintf(vis_stdout, "#** mc error: non Buchi fairness constraints not supported\n");
01921       return NIL(mdd_t);
01922     }
01923     else {
01924       int j;
01925       int numBuchi = Fsm_FairnessReadNumConjunctsOfDisjunct( modelFairness, 0 );
01926       array_t   *careStatesArray = array_alloc(mdd_t *, 0);
01927 
01928       array_insert(mdd_t *, careStatesArray, 0, careStates);
01929       for( j = 0 ; j < numBuchi; j++ ) {
01930         mdd_t *tmpMdd = Fsm_FairnessObtainFinallyInfMdd(modelFairness,
01931                                                         0, j, careStatesArray,
01932                                                         dcLevel);
01933         array_insert_last( mdd_t *, buchiFairness, tmpMdd );
01934       }
01935       array_free(careStatesArray);
01936     }
01937   }
01938   else {
01939     array_insert_last( mdd_t *, buchiFairness, mdd_one(mddManager) );
01940   }
01941 
01942   if ( onionRingsArrayForDbg !=NIL(array_t) ) {
01943     tmpOnionRingsArrayForDbg = array_alloc( array_t *, 0 );
01944   }
01945 
01946 
01947   Zmdd = mdd_dup( invariantMdd );
01948   while (TRUE) {
01949 
01950     mdd_t *ZprimeMdd = mdd_dup(Zmdd);
01951     mdd_t *conjunctsMdd = NIL(mdd_t);
01952     mdd_t *AAmdd = mdd_dup(Zmdd);
01953 
01954     for ( i = 0 ; i < array_n( buchiFairness ) ; i++ ) {
01955 
01956       mdd_t *aMdd, *bMdd, *cMdd;
01957       mdd_t *FiMdd = array_fetch( mdd_t *, buchiFairness, i );
01958 
01959       if ( tmpOnionRingsArrayForDbg ) {
01960         onionRings = array_alloc( mdd_t *, 0 );
01961         array_insert_last( array_t *, tmpOnionRingsArrayForDbg, onionRings );
01962       }
01963 
01964       /* aMdd = mdd_and( FiMdd, Zmdd, 1, 1); */
01965       aMdd = mdd_and( FiMdd, AAmdd, 1, 1);
01966 
01967       bMdd = Amc_AmcEvaluateEUFormula( modelFsm, subSystemArray, subSystem, AAmdd, aMdd, mddOne, careStates, 
01968                                       onionRings, lowerBound, quantifyVars, verbosity, dcLevel );
01969       mdd_free(aMdd);
01970       cMdd = Amc_AmcEvaluateEXFormula( modelFsm, subSystemArray, subSystem, bMdd, mddOne, careStates,
01971                                       lowerBound, quantifyVars, verbosity, dcLevel ); 
01972       mdd_free(bMdd);
01973 
01974       if ( conjunctsMdd == NIL(mdd_t) ) {
01975         conjunctsMdd = mdd_dup( cMdd );
01976         mdd_free( AAmdd ); AAmdd = mdd_and( conjunctsMdd, invariantMdd,1 ,1 ); 
01977       }
01978       else {
01979         mdd_t *tmpMdd = mdd_and( cMdd, conjunctsMdd, 1, 1 );
01980         mdd_free( conjunctsMdd );
01981         conjunctsMdd = tmpMdd;
01982         mdd_free( AAmdd ); AAmdd = mdd_and( conjunctsMdd, invariantMdd,1 ,1 );
01983       }
01984       mdd_free( cMdd );
01985     }
01986     mdd_free(AAmdd);
01987 
01988     mdd_free(ZprimeMdd);
01989     ZprimeMdd = mdd_and( invariantMdd, conjunctsMdd, 1, 1 );
01990     mdd_free( conjunctsMdd );
01991 
01992     if ( mdd_equal_mod_care_set( ZprimeMdd, Zmdd, careStates ) ) {
01993       mdd_free( ZprimeMdd );
01994       break;
01995     }
01996 
01997     mdd_free( Zmdd );
01998     Zmdd = ZprimeMdd;
01999 
02000     if ( tmpOnionRingsArrayForDbg ) {
02001       arrayForEachItem(array_t *, tmpOnionRingsArrayForDbg, i, onionRings ) {
02002         mdd_array_free( onionRings );
02003       }
02004       array_free( tmpOnionRingsArrayForDbg );
02005       tmpOnionRingsArrayForDbg = array_alloc( array_t *, 0 );
02006     }
02007   }
02008 
02009   if ( onionRingsArrayForDbg != NIL(array_t) ) {
02010     arrayForEachItem(array_t *, tmpOnionRingsArrayForDbg, i, onionRings ) {
02011       array_insert_last( array_t *, onionRingsArrayForDbg, onionRings );
02012     }
02013     array_free( tmpOnionRingsArrayForDbg );
02014   }
02015 
02016   if ( ( verbosity == McVerbositySome_c ) || ( verbosity == McVerbosityMax_c ) ) {
02017     { 
02018       for ( i = 0 ; i < array_n( onionRingsArrayForDbg ); i++ ) {
02019         int j;
02020         mdd_t *Fi = array_fetch( mdd_t *,  buchiFairness, i );
02021         array_t *onionRings = array_fetch( array_t *, onionRingsArrayForDbg, i );
02022         for( j = 0 ; j < array_n( onionRings ) ; j++ ) {
02023           mdd_t *ring = array_fetch( mdd_t *, onionRings, j );
02024           if ( j == 0 ) {
02025             if ( ! mdd_lequal( ring, Fi, 1, 1 ) ) {
02026               fprintf( vis_stderr, "Problem w/ dbg - inner most ring not in Fi\n");
02027             }
02028           }
02029           if ( ! mdd_lequal( ring, Zmdd, 1, 1 ) ) {
02030             fprintf( vis_stderr, "Problem w/ dbg - onion ring fails invariant\n");
02031           }
02032         }
02033       }
02034     }
02035 
02036     { 
02037       mdd_t *tmpMdd = careStates ? mdd_and( Zmdd, careStates, 1, 1 ) : mdd_dup( Zmdd );
02038       fprintf(vis_stdout, "--There are %.0f states satisfying EG formula\n", 
02039               mdd_count_onset(  Fsm_FsmReadMddManager( modelFsm ), tmpMdd,
02040                                 Fsm_FsmReadPresentStateVars( modelFsm ) ) );
02041       mdd_free( tmpMdd );
02042     }
02043   }
02044 
02045   mdd_array_free( buchiFairness );
02046   mdd_free( mddOne );
02047 
02048   return Zmdd;
02049 }
02050 
02051 
02052 /*---------------------------------------------------------------------------*/
02053 /* Definition of internal functions                                          */
02054 /*---------------------------------------------------------------------------*/
02055 
02072 array_t *
02073 AmcCreateSubsystemArray(
02074   Ntk_Network_t         *network,
02075   Ctlp_Formula_t        *formula)
02076 {
02077   array_t               *partitionArray, *subSystemArray;
02078   Part_Subsystem_t      *partitionSubsystem;
02079   Part_SubsystemInfo_t *subsystemInfo; 
02080   st_table              *vertexTable;
02081   array_t               *fanInIndexArray, *fanOutIndexArray;
02082   st_table              *fanInSystemTable, *fanOutSystemTable;
02083   Amc_SubsystemInfo_t   *subSystem; 
02084   graph_t               *partition = Part_NetworkReadPartition(network);
02085   int                   i, j;
02086   int                   fanInIndex, fanOutIndex, numOfVertex;
02087   Amc_SubsystemInfo_t   *fanInSubsystem, *fanOutSubsystem;
02088   char                  *flagValue, *numberOfVertexInGroup;
02089   array_t               *ctlArray;
02090 
02091   /* Obtain the size of the subsystem */
02092   numberOfVertexInGroup = Cmd_FlagReadByName("amc_sizeof_group");
02093   if(numberOfVertexInGroup != NIL(char)){
02094     numOfVertex = atoi(numberOfVertexInGroup); 
02095   }
02096   else{
02097     /* default value */
02098     numOfVertex = 8; 
02099   }
02100 
02101   /* 
02102    * Obtain subsystem partitioned as submachines. 
02103    */
02104   flagValue = Cmd_FlagReadByName("amc_grouping_method");
02105   if( (flagValue != NIL(char)) && 
02106            (strcmp(flagValue, "latch_dependency")) == 0){
02107 
02108     subsystemInfo = Part_PartitionSubsystemInfoInit(network);
02109     Part_PartitionSubsystemInfoSetBound(subsystemInfo, numOfVertex);
02110     partitionArray = Part_PartCreateSubsystems(subsystemInfo, NIL(array_t),
02111         NIL(array_t));
02112     
02113     Part_PartitionSubsystemInfoFree(subsystemInfo); 
02114 
02115   }
02116   else{
02117     /*
02118      * Latches which have dependency relation with given formulae
02119      * are computed and grouped into sub-systems.
02120      */
02121     lsGen  gen;
02122     Ntk_Node_t *node;
02123     char *name;
02124     array_t *arrayOfDataInputName;
02125     lsList latchInputList = lsCreate();
02126 
02127     if (latchInputList == (lsList)0){
02128       return NIL(array_t);
02129     }
02130 
02131     ctlArray = array_alloc(Ctlp_Formula_t *, 1);
02132     array_insert(Ctlp_Formula_t *, ctlArray, 0, formula);
02133 
02134     if (!Part_PartitionGetLatchInputListFromCTL(network, ctlArray,
02135                                                 NIL(array_t),
02136                                                 latchInputList)) {
02137       array_free(ctlArray);
02138       return NIL(array_t);
02139     }
02140     arrayOfDataInputName = array_alloc(Ntk_Node_t *, lsLength(latchInputList));
02141     lsForEachItem(latchInputList, gen, node){
02142       name = Ntk_NodeReadName(node);
02143       array_insert_last(char *, arrayOfDataInputName, name);
02144     }
02145     lsDestroy(latchInputList, (void (*)(lsGeneric))0);
02146     array_sort(arrayOfDataInputName, stringCompare);
02147 
02148     partitionArray = Part_PartGroupVeriticesBasedOnHierarchy(network,
02149                      arrayOfDataInputName);
02150     array_free(arrayOfDataInputName);
02151     array_free(ctlArray);
02152   }
02153 
02154   subSystemArray = array_alloc(Amc_SubsystemInfo_t *, array_n(partitionArray));
02155 
02156 
02157   /* 
02158    * For each partitioned submachines build an FSM. 
02159    */
02160   arrayForEachItem(Part_Subsystem_t *, partitionArray, i, partitionSubsystem) {
02161     Fsm_Fsm_t *fsm;
02162 
02163     vertexTable = Part_PartitionSubsystemReadVertexTable(partitionSubsystem);
02164     fanInIndexArray  = Part_PartitionSubsystemReadFanIn(partitionSubsystem);
02165     fanOutIndexArray = Part_PartitionSubsystemReadFanOut(partitionSubsystem); 
02166 
02167     FREE(partitionSubsystem);
02168 
02169     fsm = Fsm_FsmCreateSubsystemFromNetwork(network, partition, vertexTable,
02170         FALSE, 0);
02171 
02172     subSystem = Amc_AmcSubsystemCreate(fsm, NIL(mdd_t), vertexTable, 
02173                                     /*   NIL(st_table), NIL(st_table) ); */
02174                                        (st_table *)fanInIndexArray, 
02175                                        (st_table *)fanOutIndexArray); 
02176     array_insert_last(Amc_SubsystemInfo_t *, subSystemArray, subSystem);
02177   } /* end of arrayForEachItem(partitionArray) */
02178 
02179   array_free(partitionArray);
02180 
02181   /* 
02182    * Convert fanInIndexTable to fanInSystemTable
02183    * Convert fanOutIndexTable to fanOutSystemTable
02184    */
02185   arrayForEachItem(Amc_SubsystemInfo_t *, subSystemArray, i, subSystem) {
02186 
02187     fanInIndexArray = (array_t *) AmcSubsystemReadFanInTable(subSystem);
02188     fanInSystemTable = st_init_table(st_ptrcmp, st_ptrhash);
02189 
02190     if( fanInIndexArray != NIL(array_t) ) {
02191       arrayForEachItem(int, fanInIndexArray, j, fanInIndex) {
02192      
02193         fanInSubsystem = array_fetch(Amc_SubsystemInfo_t *, subSystemArray,
02194                                      fanInIndex);
02195         st_insert(fanInSystemTable, (char *)fanInSubsystem, NIL(char));
02196 
02197       }
02198       array_free(fanInIndexArray);
02199     }
02200 
02201     AmcSubsystemSetFanInTable(subSystem, fanInSystemTable);
02202 
02203 
02204     fanOutIndexArray = (array_t *) AmcSubsystemReadFanOutTable(subSystem);
02205     fanOutSystemTable = st_init_table(st_ptrcmp, st_ptrhash);
02206 
02207     if( fanOutIndexArray != NIL(array_t) ) {
02208       arrayForEachItem(int, fanOutIndexArray, j, fanOutIndex) {
02209      
02210         fanOutSubsystem = array_fetch(Amc_SubsystemInfo_t *, subSystemArray,
02211                                       fanOutIndex);
02212         st_insert(fanOutSystemTable, (char *)fanOutSubsystem, NIL(char));
02213 
02214       }
02215       array_free(fanOutIndexArray);
02216     }
02217 
02218     AmcSubsystemSetFanOutTable(subSystem, fanOutSystemTable);
02219 
02220   }
02221 
02222 
02223   return subSystemArray;
02224 }
02225 
02236 void
02237 AmcPrintOptimalSystem(
02238   FILE *fp,
02239   Amc_Info_t *amcInfo)
02240 {
02241   int i;
02242   Amc_SubsystemInfo_t *subSystem;
02243 
02244   fprintf(fp, "\nSubsystems in optimal path : ");
02245 
02246   arrayForEachItem(Amc_SubsystemInfo_t *, amcInfo->subSystemArray, i, subSystem) {
02247    
02248     if(subSystem->takenIntoOptimal)
02249       fprintf(fp, " %d ", i); 
02250   
02251   }
02252 
02253 }
02254 
02255 #ifdef AMC_DEBUG
02256 
02265 void
02266 AmcCheckSupportAndOutputFunctions(
02267   array_t *subSystemArray)
02268 {
02269   int i;
02270   Amc_SubsystemInfo_t *subSystem;
02271   arrayForEachItem(Amc_SubsystemInfo_t *, subSystemArray, i, subSystem) {
02272     Fsm_Fsm_t   *subSystemFsm   = AmcSubsystemReadFsm(subSystem);       
02273     Ntk_Network_t *network      = Fsm_FsmReadNetwork(subSystemFsm);
02274     mdd_manager *mddManager     = Ntk_NetworkReadMddManager(network);
02275     graph_t     *partition      = Part_NetworkReadPartition(network);
02276 
02277     st_table    *vertexTable    = AmcSubsystemReadVertexTable(subSystem);
02278     st_generator                *stGen;
02279     char                        *latchName;
02280 
02281     st_foreach_item(vertexTable, stGen, &latchName, NIL(char *)) {
02282 
02283       Ntk_Node_t        *latch          = Ntk_NetworkFindNodeByName(network, latchName);
02284       int               functionMddId   = Ntk_NodeReadMddId(Ntk_NodeReadShadow(latch));
02285 
02286       char      *nameLatchDataInput     = Ntk_NodeReadName(Ntk_LatchReadDataInput(latch));
02287       vertex_t  *ptrVertex      = Part_PartitionFindVertexByName(partition, nameLatchDataInput);
02288       Mvf_Function_t    *nextStateFunction;
02289       st_table          *supportTable;
02290 
02291       nextStateFunction = Part_VertexReadFunction(ptrVertex);
02292       supportTable      = AmcCreateFunctionSupportTable(nextStateFunction);
02293 
02294       /* print the name of the latch vars and its mddId in this subsystem*/
02295       fprintf(vis_stdout, "\nSubsystem %d : Has latch : %s MddId : %d", 
02296                                              i, latchName, Ntk_NodeReadMddId(latch));
02297       fprintf(vis_stdout, "\n\tIts corresponding next state var : %s MddId : %d", 
02298                                              Ntk_NodeReadName(Ntk_NodeReadShadow(latch)),
02299                                              Ntk_NodeReadMddId(Ntk_NodeReadShadow(latch)) );
02300 
02301       /* print the name of the output function and its mddId */
02302       {
02303         int outputMddId = Ntk_NodeReadMddId(Ntk_LatchReadDataInput(latch));
02304         fprintf(vis_stdout, "\n\tIts output function  Output Function : %s  MddId : %d", 
02305                                               nameLatchDataInput, outputMddId); 
02306       }
02307 
02308       /* print the support of its output function */
02309       {
02310         st_generator            *stGen2;
02311         long                    supportId;
02312         st_foreach_item(supportTable, stGen2, (char **)&supportId, NIL(char *)) {
02313           Ntk_Node_t  *supportNode = Ntk_NetworkFindNodeByMddId(network, (int) supportId);
02314           char          *supportName = Ntk_NodeReadName(supportNode);
02315           fprintf(vis_stdout, "\n\tOutput function's support : %s MddId : %d",
02316                                                 supportName, (int) supportId); 
02317           fflush(vis_stdout);
02318         } 
02319       }
02320 
02321 
02322     } /* end of st_foreach_item */
02323 
02324   } /* end of ArrayForEachItem */
02325 
02326 
02327   /* Print the name of the present state vars and its mddId */
02328   /* Print the name of the next state vars and its mddId */
02329   /* Print the input vars */
02330   {
02331     Amc_SubsystemInfo_t *subSystem = array_fetch(Amc_SubsystemInfo_t *, subSystemArray, 0);
02332     Fsm_Fsm_t   *subSystemFsm      = AmcSubsystemReadFsm(subSystem);
02333     Ntk_Network_t *network         = Fsm_FsmReadNetwork(subSystemFsm);
02334     lsGen gen; Ntk_Node_t *inputNode;
02335     Ntk_NetworkForEachPrimaryInput(network, gen, inputNode) {
02336       fprintf(vis_stdout, "\nPrimary Input : %s MddId : %d", 
02337                              Ntk_NodeReadName(inputNode), Ntk_NodeReadMddId(inputNode));
02338     }
02339   }
02340 
02341   /* Print the pseudo input vars */
02342   {
02343     Amc_SubsystemInfo_t *subSystem = array_fetch(Amc_SubsystemInfo_t *, subSystemArray, 0); 
02344     Fsm_Fsm_t   *subSystemFsm      = AmcSubsystemReadFsm(subSystem);
02345     Ntk_Network_t *network         = Fsm_FsmReadNetwork(subSystemFsm);
02346     lsGen gen; Ntk_Node_t *inputNode;
02347     Ntk_NetworkForEachPseudoInput(network, gen, inputNode) {
02348       fprintf(vis_stdout, "\nPseudo Input : %s MddId : %d", 
02349                              Ntk_NodeReadName(inputNode), Ntk_NodeReadMddId(inputNode));
02350       fflush(vis_stdout);
02351     }
02352   }
02353 
02354 }
02355 
02365 st_table *
02366 AmcCreateFunctionSupportTable(
02367   Mvf_Function_t *mvf)
02368 {
02369   mdd_manager  *mddManager;        /* Manager for the MDDs */
02370   array_t      *support;
02371   st_table     *mddSupport = st_init_table(st_numcmp, st_numhash);
02372   int          numComponents = Mvf_FunctionReadNumComponents(mvf);
02373   int          j, k;
02374   mdd_t        *unit;
02375 
02376   assert(numComponents!= 0);
02377   
02378   mddManager = Mvf_FunctionReadMddManager(mvf);
02379 
02380   /*
02381    * compute the support of an mdd as the union of supports of every
02382    * function component 
02383    */
02384   for(j = 0; j < numComponents; j++) {
02385     unit = Mvf_FunctionReadComponent(mvf, j);
02386     support = mdd_get_support(mddManager, unit);
02387     
02388     /* For every element of its support */
02389     for(k = 0; k < array_n(support); k++) {
02390       st_insert(mddSupport, (char *)(long)array_fetch(int, support, k), (char *)0);
02391     } /* End of for */
02392     array_free(support);
02393   } /* End of for */
02394 
02395   return mddSupport;
02396 } /* End of */
02397 #endif
02398 
02399 
02410 mdd_t *
02411 AmcModelCheckAtomicFormula( 
02412   Fsm_Fsm_t *modelFsm,
02413   Ctlp_Formula_t *ctlFormula)
02414 {
02415   mdd_t * resultMdd;
02416   mdd_t *tmpMdd;
02417   Ntk_Network_t *network = Fsm_FsmReadNetwork( modelFsm );
02418   char *nodeNameString = Ctlp_FormulaReadVariableName( ctlFormula );
02419   char *nodeValueString = Ctlp_FormulaReadValueName( ctlFormula );
02420   Ntk_Node_t *node = Ntk_NetworkFindNodeByName( network, nodeNameString );
02421 
02422   Var_Variable_t *nodeVar;
02423   int nodeValue;
02424 
02425   graph_t *modelPartition;
02426   vertex_t *partitionVertex;
02427   Mvf_Function_t *MVF;
02428 
02429   nodeVar = Ntk_NodeReadVariable( node );
02430   if ( Var_VariableTestIsSymbolic( nodeVar ) ){
02431     nodeValue = Var_VariableReadIndexFromSymbolicValue( nodeVar, nodeValueString );
02432   }
02433   else {
02434     nodeValue = atoi( nodeValueString );
02435   } 
02436 
02437   modelPartition = Part_NetworkReadPartition( network );
02438   if ( !( partitionVertex = Part_PartitionFindVertexByName( modelPartition,
02439                                                             nodeNameString ) )) { 
02440     lsGen tmpGen;
02441     Ntk_Node_t *tmpNode;
02442     array_t *mvfArray;
02443     array_t *tmpRoots = array_alloc( Ntk_Node_t *, 0 );
02444     st_table *tmpLeaves = st_init_table( st_ptrcmp, st_ptrhash );
02445     array_insert_last( Ntk_Node_t *, tmpRoots, node );
02446 
02447     Ntk_NetworkForEachCombInput( network, tmpGen, tmpNode ) {
02448       st_insert( tmpLeaves, (char *) tmpNode, (char *) NTM_UNUSED );
02449     }
02450 
02451     mvfArray =  Ntm_NetworkBuildMvfs( network, tmpRoots, tmpLeaves,
02452                                       NIL(mdd_t) );
02453     MVF = array_fetch( Mvf_Function_t *, mvfArray, 0 );
02454     array_free( tmpRoots );
02455     st_free_table( tmpLeaves );
02456     array_free( mvfArray );
02457 
02458     tmpMdd = Mvf_FunctionReadComponent( MVF, nodeValue );
02459     resultMdd = mdd_dup( tmpMdd );
02460     Mvf_FunctionFree( MVF );
02461     return resultMdd;
02462   }
02463   else {
02464     MVF = Part_VertexReadFunction( partitionVertex );
02465     tmpMdd = Mvf_FunctionReadComponent( MVF, nodeValue );
02466     resultMdd = mdd_dup( tmpMdd );
02467     return resultMdd;
02468   }
02469 }
02470 
02471 
02472 /*---------------------------------------------------------------------------*/
02473 /* Definition of static functions                                            */
02474 /*---------------------------------------------------------------------------*/
02482 static int
02483 stringCompare(
02484   const void * s1,
02485   const void * s2)
02486 {
02487   return(strcmp(*(char **)s1, *(char **)s2));
02488 }