VIS

src/amc/amcBlock.c

Go to the documentation of this file.
00001 
00017 #include "amcInt.h"
00018 #include "mcInt.h"
00019 
00020 static char rcsid[] UNUSED = "$Id: amcBlock.c,v 1.35 2005/04/25 20:24:53 fabio Exp $";
00021 
00022 /*---------------------------------------------------------------------------*/
00023 /* Constant declarations                                                     */
00024 /*---------------------------------------------------------------------------*/
00025 
00026 /*---------------------------------------------------------------------------*/
00027 /* Structure declarations                                                    */
00028 /*---------------------------------------------------------------------------*/
00029 
00037 struct BlockInfoStruct {
00038   Amc_SubsystemInfo_t   *optimalSystem; /* temporary storage for Block method */
00039   int                   bestSystem;     /* temporary storage for Block method */
00040 };
00041 
00042 struct BlockSubsystemInfoStruct {
00043   int           scheduledForRefinement;
00044 };
00045 
00046 
00047 /*---------------------------------------------------------------------------*/
00048 /* Type declarations                                                         */
00049 /*---------------------------------------------------------------------------*/
00050 typedef struct BlockInfoStruct BlockInfo_t;
00051 typedef struct BlockSubsystemInfoStruct BlockSubsystemInfo_t;
00052 
00053 /*---------------------------------------------------------------------------*/
00054 /* Variable declarations                                                     */
00055 /*---------------------------------------------------------------------------*/
00056 
00057 /*---------------------------------------------------------------------------*/
00058 /* Macro declarations                                                        */
00059 /*---------------------------------------------------------------------------*/
00060 
00063 /*---------------------------------------------------------------------------*/
00064 /* Static function prototypes                                                */
00065 /*---------------------------------------------------------------------------*/
00066 
00067 static BlockInfo_t * AmcObtainOptimalSystemUpperBound(Amc_Info_t *amcInfo, Ctlp_Formula_t *formula, BlockInfo_t *BlockInfo, int verbosity);
00068 static BlockInfo_t * AmcObtainOptimalSystemLowerBound(Amc_Info_t *amcInfo, Ctlp_Formula_t *formula, BlockInfo_t *BlockInfo, int verbosity);
00069 static void AmcInitializeDependency(array_t *subSystemArray, int isMBM);
00070 static void AmcInitializeSchedule(Amc_Info_t *amcInfo);
00071 static int AmcIsEverySubsystemRescheduled(Amc_Info_t *amcInfo);
00072 static void AmcPrintScheduleInformation(Amc_Info_t *amcInfo);
00073 #if 0
00074 static void AmcRescheduleForRefinement(st_table *fanOutSystemTable);
00075 static mdd_t * AmcRefineWithSatisfyStatesOfFanInSystem(Amc_SubsystemInfo_t *subSystem, mdd_t *careStates);
00076 #endif
00077 static array_t * AmcInitializeQuantifyVars(Amc_SubsystemInfo_t *subSystem);
00078 #if 0
00079 static void AmcFreeBlockInfo(BlockInfo_t *BlockInfo);
00080 #endif
00081 static int AmcBlockSubsystemReadScheduledForRefinement(BlockSubsystemInfo_t *system);
00082 static void AmcBlockSubsystemSetScheduledForRefinement(BlockSubsystemInfo_t *system, int data);
00083 #if 0
00084 static Amc_SubsystemInfo_t * AmcBlockReadOptimalSubsystem(BlockInfo_t *system);
00085 #endif
00086 static void AmcBlockSetOptimalSystem(BlockInfo_t *system, Amc_SubsystemInfo_t *data);
00087 #if 0
00088 static int AmcBlockReadBestSystem(BlockInfo_t *system);
00089 #endif
00090 static void AmcBlockSetBestSystem(BlockInfo_t *system, int data);
00091 #if 0
00092 static Amc_SubsystemInfo_t * AmcClearInputVarsFromFSM(Amc_SubsystemInfo_t *subSystem);
00093 #endif
00094 
00098 /*---------------------------------------------------------------------------*/
00099 /* Definition of exported functions                                          */
00100 /*---------------------------------------------------------------------------*/
00101 
00102 
00103 /*---------------------------------------------------------------------------*/
00104 /* Definition of internal functions                                          */
00105 /*---------------------------------------------------------------------------*/
00148 int
00149 AmcBlockTearingProc(
00150   Amc_Info_t     *amcInfo,
00151   Ctlp_Formula_t *formula,
00152   int            verbosity)
00153 {
00154   array_t               *subSystemArray = amcInfo->subSystemArray;
00155   Amc_SubsystemInfo_t   *subSystem;
00156   BlockInfo_t           BlockInfo;
00157 
00158 
00159   /*
00160    * Update fan-in subsystems and fan-out subsystems when machine by machine 
00161    * method is ON.
00162    * Update initial states in BlockInfo.
00163    * Reschedule every subsystem to be evaluated.
00164    */
00165 
00166   if( amcInfo->optimalSystem == NIL(Amc_SubsystemInfo_t) ) {
00167     AmcInitializeDependency(subSystemArray, amcInfo->isMBM);
00168   }
00169 
00170   AmcInitializeSchedule(amcInfo);
00171 
00172   /* BlockInfo is a temporary storage. optimal system is not freed */
00173   BlockInfo.optimalSystem = NIL(Amc_SubsystemInfo_t);
00174     
00175 
00176   /*
00177    * Outer loop until there's no scheduled subsystem.
00178    */
00179   while(AmcIsEverySubsystemRescheduled(amcInfo)) {
00180 
00181     if(verbosity == Amc_VerbosityNone_c)
00182       AmcPrintScheduleInformation(amcInfo);
00183 
00184 
00185     if( !amcInfo->lowerBound ) {
00186         AmcObtainOptimalSystemUpperBound(amcInfo, formula, &BlockInfo, 
00187                                          verbosity);
00188         /* AmcObtainOptimalSystemUpperBoundWithDI(amcInfo, formula, &BlockInfo,
00189                                                   verbosity); */
00190     }
00191     else {
00192         AmcObtainOptimalSystemLowerBound(amcInfo, formula, &BlockInfo, 
00193                                          verbosity);
00194         /* AmcObtainOptimalSystemLowerBoundWithMBM(amcInfo, formula, &BlockInfo,
00195                                                    verbosity); */
00196     }
00197 
00198     if(amcInfo->isVerified) {
00199 
00200         int best = BlockInfo.bestSystem;
00201         subSystem = array_fetch(Amc_SubsystemInfo_t *, amcInfo->subSystemArray,
00202                                 best);
00203         subSystem->takenIntoOptimal = 1;
00204 
00205       return 1;
00206     }
00207 
00208     if(!amcInfo->isMBM)
00209       break;
00210 
00211   } /* End of while() */
00212 
00213   if(verbosity == Amc_VerbosityNone_c)
00214     AmcPrintScheduleInformation(amcInfo);
00215 
00216 
00217   /* Update the subsystem that had been included in optimal system */
00218   {
00219     int best = BlockInfo.bestSystem;
00220     subSystem = array_fetch(Amc_SubsystemInfo_t *, amcInfo->subSystemArray, 
00221                             best);
00222     subSystem->takenIntoOptimal = 1;
00223   }
00224 
00225   /* Update amcInfo's optimal system */
00226   if(amcInfo->optimalSystem != NIL(Amc_SubsystemInfo_t)) {
00227 #ifdef AMC_DEBUG
00228     {
00229       Amc_SubsystemInfo_t *previousOpt = amcInfo->optimalSystem;
00230       Amc_SubsystemInfo_t *currentOpt  = BlockInfo.optimalSystem;
00231 
00232       if(!amcInfo->lowerBound) {
00233         if(mdd_lequal(previousOpt->satisfyStates, currentOpt->satisfyStates,
00234                       1, 1)) {
00235           fprintf(vis_stdout, "\n###AMC : We are ok.");
00236         }
00237         else {
00238           fprintf(vis_stdout, "\n** amc error: Somethings wrong.");
00239         }
00240       }
00241       else {
00242         if( mdd_lequal(currentOpt->satisfyStates, previousOpt->satisfyStates,
00243                        1, 1)) {
00244           fprintf(vis_stdout, "\n###AMC : We are ok.");
00245         }
00246         else {
00247           fprintf(vis_stdout, "\n** amc error: Somethings wrong.");
00248         }
00249       }
00250     }
00251 #endif 
00252     Amc_AmcSubsystemFree(amcInfo->optimalSystem);
00253   }
00254   AmcSetOptimalSystem(amcInfo, BlockInfo.optimalSystem);
00255 
00256   return 1;
00257 }
00258 
00266 void
00267 AmcFreeBlock(
00268   Amc_Info_t *amcInfo)
00269 {
00270   Amc_SubsystemInfo_t   *subSystem; 
00271   BlockSubsystemInfo_t  *BlockSubsystem;
00272   int i ;
00273 
00274   /* what if amc doesn't free partition */
00275   arrayForEachItem(Amc_SubsystemInfo_t *, amcInfo->subSystemArray, i, 
00276                    subSystem) {
00277     BlockSubsystem = (BlockSubsystemInfo_t *)AmcSubsystemReadMethodSpecificData(subSystem);
00278     if(BlockSubsystem != NIL(BlockSubsystemInfo_t))
00279       FREE(BlockSubsystem);
00280 
00281     Amc_AmcSubsystemFree(subSystem); 
00282   }
00283   array_free(amcInfo->subSystemArray);
00284 
00285   if(amcInfo->optimalSystem != NIL(Amc_SubsystemInfo_t)) {
00286     Amc_AmcSubsystemFree(amcInfo->optimalSystem);
00287     amcInfo->optimalSystem = NIL(Amc_SubsystemInfo_t);
00288   }
00289 
00290   if( amcInfo->initialStates != NIL(mdd_t)) {
00291     mdd_free(amcInfo->initialStates);
00292     amcInfo->initialStates = NIL(mdd_t);
00293   }
00294 
00295   FREE(amcInfo);
00296 
00297 }
00298 
00299 /*---------------------------------------------------------------------------*/
00300 /* Definition of static functions                                            */
00301 /*---------------------------------------------------------------------------*/
00302 
00303 
00304 
00350 static BlockInfo_t *
00351 AmcObtainOptimalSystemUpperBound(
00352 Amc_Info_t              *amcInfo,
00353 Ctlp_Formula_t          *formula,
00354 BlockInfo_t             *BlockInfo,
00355 int                     verbosity)
00356 {
00357   array_t               *subSystemArray = amcInfo->subSystemArray;
00358   Amc_SubsystemInfo_t   *subSystem, *bestCombinedSystem;
00359   mdd_t                 *initialStates;
00360   mdd_t                 *smallestStates, *currentErrorStates, *careStates;
00361   int                   i, best = 0;
00362   graph_t               *partition = Part_NetworkReadPartition(amcInfo->network);
00363   mdd_manager           *mddManager = Part_PartitionReadMddManager(partition);
00364   mdd_t                 *mddOne = mdd_one(mddManager);
00365   array_t               *quantifyVars;
00366   Mc_DcLevel            dcLevel;
00367   char  *flagValue;
00368 
00369 
00370   /* 
00371    * Initial states must be set before coming into this routine.
00372    */
00373   initialStates = amcInfo->initialStates;
00374   if( initialStates == NIL(mdd_t) ) {
00375     (void)fprintf(vis_stderr, "** amc error: \n");
00376     return(NIL(BlockInfo_t));
00377   }
00378  
00379   /* Read in the usage of don't care level */
00380   flagValue = Cmd_FlagReadByName("amc_DC_level");
00381   if(flagValue != NIL(char)){
00382     dcLevel = (Mc_DcLevel) atoi(flagValue); 
00383     if( dcLevel > McDcLevelRchFrontier_c ) dcLevel = McDcLevelRchFrontier_c;
00384   }
00385   else{
00386     /* default value set to McDcLevelNone_c. Mc's default is McDcLevelRch_c. */
00387     dcLevel = McDcLevelNone_c; 
00388   }
00389 
00390   /*
00391    * Update the set of states satisfying the formula for each sub-systems.
00392    * The process of "combining sub-systems" is equivalent of taking a 
00393    * "synchronous product" of multiple sub-subsystems.
00394    */
00395   smallestStates = NIL(mdd_t);
00396   bestCombinedSystem  = NIL(Amc_SubsystemInfo_t);
00397 
00398   arrayForEachItem(Amc_SubsystemInfo_t *, subSystemArray, i, subSystem) {
00399 
00400     mdd_t                       *reachableStates, *fairStates, *satisfyStates;
00401     Fsm_Fsm_t                   *combinedFsm;
00402     Fsm_Fairness_t              *fairCond;
00403     Amc_SubsystemInfo_t         *combinedSystem; 
00404 
00405     /* Proceed if the subsystem had not yet been taken into the optimal system. */
00406     if(!subSystem->takenIntoOptimal) {
00407 
00408       /* 
00409        * Combine subsystems. If optimal subsystem is NIL, duplicate the
00410        * subsystem.
00411        */  
00412       combinedSystem = Amc_CombineSubsystems(amcInfo->network,
00413                                              amcInfo->optimalSystem,
00414                                              subSystem);
00415       combinedFsm = AmcSubsystemReadFsm(combinedSystem);
00416 
00417       quantifyVars = AmcInitializeQuantifyVars(combinedSystem);
00418       
00419       /* 
00420        * Currently forced not to compute reachable states. This is to reduce
00421        * computational overhead of computing it when dealing with complex
00422        * examples.
00423        */
00424       reachableStates = mdd_one(mddManager);
00425       fairStates = mdd_one(mddManager);
00426       fairCond = Fsm_FsmReadFairnessConstraint(combinedFsm);
00427 
00428 
00429       /* Obtain new care set from fan-in systems */
00430       careStates = mdd_dup(reachableStates);
00431 
00432       Ctlp_FlushStates(formula);
00433       satisfyStates = mdd_dup(Amc_AmcEvaluateCTLFormula(combinedSystem,
00434                                                         subSystemArray, 
00435                                                         formula, fairStates,
00436                                                         fairCond,
00437                                                         careStates,
00438                                                         amcInfo->lowerBound, 
00439                                                         quantifyVars,
00440                                                         /*NIL(array_t),*/
00441                                                         (Mc_VerbosityLevel)
00442                                                         verbosity, dcLevel));
00443 
00444       {
00445         int x; array_t *quantifyStateVars;
00446         arrayForEachItem(array_t *, quantifyVars, x, quantifyStateVars) {
00447           array_free(quantifyStateVars); 
00448         }
00449         array_free(quantifyVars);
00450       }
00451       /* Free */
00452       mdd_free(careStates);
00453       mdd_free(reachableStates); mdd_free(fairStates); 
00454       
00455 
00456       /* 
00457        * Update the set of states satisfying the formula for each subsystems
00458        * when newly computed states are tighter than the one already stored.
00459        * Notice, "satisfySates" holds the set of states satisfying the formula
00460        * computed with the combined_system(optimal_system || current_subsystem). 
00461        * 
00462        */
00463       if( subSystem->satisfyStates != NIL(mdd_t) ) {
00464 
00465         if( !(mdd_equal(subSystem->satisfyStates, satisfyStates )) &&
00466             (mdd_lequal(subSystem->satisfyStates, satisfyStates, 1, 1)) ) {
00467           /* We got a tighter approximation. */
00468           mdd_free(subSystem->satisfyStates);
00469           AmcSubsystemSetSatisfy(subSystem, mdd_dup(satisfyStates));
00470         }
00471          
00472       }     
00473       else {
00474         /* We are in the first level of the lattice */
00475         AmcSubsystemSetSatisfy(subSystem, mdd_dup(satisfyStates));
00476 
00477       }
00478 
00479       /* Update the set of states satisfying the formula for the combined_system. */
00480       if( AmcSubsystemReadSatisfy(combinedSystem) != NIL(mdd_t) )
00481         mdd_free( AmcSubsystemReadSatisfy(combinedSystem) );
00482       AmcSubsystemSetSatisfy(combinedSystem, mdd_dup(satisfyStates));
00483 
00484 
00485       if( verbosity == Amc_VerbosityVomit_c) {
00486          mdd_manager *mddMgr = Fsm_FsmReadMddManager(combinedSystem->fsm);
00487          array_t     *psVars = Fsm_FsmReadPresentStateVars(combinedSystem->fsm);
00488 
00489          fprintf(vis_stdout, "\n#AMC STATUS: The states satisfying the formula : %10g",
00490                         mdd_count_onset(  mddMgr, combinedSystem->satisfyStates, psVars ) );
00491          fflush(vis_stdout);
00492        }
00493 
00494       /* 
00495        * Check whether the formula evaluates to TRUE. 
00496        */
00497       { 
00498         mdd_t *notSatisfyStates = mdd_not(satisfyStates);
00499         currentErrorStates = mdd_and(initialStates, notSatisfyStates, 1, 1);
00500         mdd_free(notSatisfyStates);
00501         mdd_free(satisfyStates);
00502       }
00503 
00504       if ( mdd_is_tautology(currentErrorStates, 0) ) { 
00505         /* The formula is verified TRUE!! */
00506 
00507         AmcBlockSetBestSystem(BlockInfo, i);
00508         amcInfo->isVerified = 1; 
00509         amcInfo->amcAnswer = Amc_Verified_True_c;
00510         fprintf(vis_stdout, "\n# AMC: formula passed --- ");
00511         Ctlp_FormulaPrint(vis_stdout, Ctlp_FormulaReadOriginalFormula(formula));
00512 
00513         if(currentErrorStates != NIL(mdd_t))
00514           mdd_free(currentErrorStates); 
00515         if(smallestStates != NIL(mdd_t))
00516           mdd_free(smallestStates);
00517         if( bestCombinedSystem != NIL(Amc_SubsystemInfo_t) )
00518           Amc_AmcSubsystemFree(bestCombinedSystem); 
00519 
00520         mdd_free(mddOne); Amc_AmcSubsystemFree(combinedSystem); 
00521         Ctlp_FlushStates(formula);
00522 
00523         return BlockInfo;
00524       } /* end of if */
00525       else if (amcInfo->currentLevel == array_n(amcInfo->subSystemArray)){
00526         /* The formula is verified FALSE!! */
00527         array_t *careStatesArray;
00528 
00529         AmcBlockSetBestSystem(BlockInfo, i);
00530         amcInfo->isVerified = 1;
00531         amcInfo->amcAnswer = Amc_Verified_False_c;
00532         fprintf(vis_stdout, "\n# AMC: formula failed --- ");
00533         Ctlp_FormulaPrint(vis_stdout, Ctlp_FormulaReadOriginalFormula(formula));
00534 
00535         if(currentErrorStates != NIL(mdd_t)) mdd_free(currentErrorStates);
00536         if(smallestStates != NIL(mdd_t))     mdd_free(smallestStates);
00537 
00538         if( bestCombinedSystem != NIL(Amc_SubsystemInfo_t) )
00539           Amc_AmcSubsystemFree(bestCombinedSystem);
00540 
00541         {
00542           /* Temporarily stay here until the damn thing becomes visible. */
00543           McOptions_t *mcOptions = ALLOC(McOptions_t, 1);
00544           mcOptions->useMore = FALSE;
00545           mcOptions->fwdBwd = McFwd_c;
00546           mcOptions->reduceFsm = FALSE;
00547           mcOptions->printInputs = FALSE;
00548           mcOptions->simFormat = FALSE;
00549           mcOptions->verbosityLevel = McVerbosityNone_c;
00550           mcOptions->dbgLevel = McDbgLevelMin_c;
00551           mcOptions->dcLevel   = McDcLevelNone_c;
00552           mcOptions->ctlFile = NIL(FILE);
00553           mcOptions->debugFile = NIL(FILE);
00554 
00555           careStatesArray = array_alloc(mdd_t *, 0);
00556           array_insert(mdd_t *, careStatesArray, 0, mddOne);
00557           fprintf(vis_stdout, "\n");
00558           McFsmDebugFormula((McOptions_t *)mcOptions, formula,
00559                             combinedSystem->fsm, careStatesArray);
00560           array_free(careStatesArray);
00561           FREE(mcOptions);
00562         }
00563         mdd_free(mddOne);
00564         Amc_AmcSubsystemFree(combinedSystem);
00565         Ctlp_FlushStates(formula);
00566 
00567         return BlockInfo;       
00568       }
00569 
00570       /* 
00571        * Get the locally optimal subsystem by choosing a subsystem that produces
00572        * smallest error states.
00573        */
00574       if( smallestStates == NIL(mdd_t) ||
00575          mdd_count_onset(mddManager, currentErrorStates, Fsm_FsmReadPresentStateVars(subSystem->fsm)) <=
00576          mdd_count_onset(mddManager, smallestStates, Fsm_FsmReadPresentStateVars(subSystem->fsm)) ) {
00577 
00578         if( smallestStates != NIL(mdd_t) )
00579           mdd_free(smallestStates);
00580 
00581         smallestStates = currentErrorStates;
00582 
00583         if(bestCombinedSystem != NIL(Amc_SubsystemInfo_t)) {
00584           Amc_AmcSubsystemFree(bestCombinedSystem);
00585           bestCombinedSystem = NIL(Amc_SubsystemInfo_t);
00586         }
00587         bestCombinedSystem = combinedSystem; 
00588         best = i;
00589       }
00590 
00591       else { /* Free combined system, current error states */
00592         Amc_AmcSubsystemFree(combinedSystem);
00593         combinedSystem = NIL(Amc_SubsystemInfo_t);
00594         mdd_free(currentErrorStates); 
00595       }
00596 
00597     
00598     } /* end of if(!takenIntoOptimal) */
00599 
00600   } /* end of arrayForEachItem(subSystemArray) */
00601 
00602 
00603   /* 
00604    * Flush the formula that was kept in last iteration.
00605    * Update Block Info.  
00606    */
00607   Ctlp_FlushStates(formula);
00608 
00609   /* Update the inital states */
00610   {
00611     mdd_t *initialStates;
00612     if((initialStates = AmcReadInitialStates(amcInfo)) != NIL(mdd_t))
00613       mdd_free(initialStates);
00614     AmcSetInitialStates(amcInfo, smallestStates);
00615   }
00616 
00617   if( verbosity == Amc_VerbositySpit_c ) {
00618     mdd_manager *mddMgr = Fsm_FsmReadMddManager(bestCombinedSystem->fsm);
00619     array_t     *psVars = Fsm_FsmReadPresentStateVars(bestCombinedSystem->fsm);
00620 
00621     fprintf(vis_stdout, "\n#AMC : The BDD size of the states satisfying the formula : %d", 
00622                                   mdd_size(bestCombinedSystem->satisfyStates) );
00623     fprintf(vis_stdout, "\n#AMC : The cardinality of the states satisfying the formula : %10g ",
00624                           mdd_count_onset(  mddMgr, bestCombinedSystem->satisfyStates, psVars ) );
00625     fprintf(vis_stdout, "\n#AMC : The BDD size of the states new initial states : %d",
00626                                   mdd_size(smallestStates) );
00627     fprintf(vis_stdout, "\n#AMC : The cardinality of the new initial states : %10g ",
00628                           mdd_count_onset(  mddMgr, smallestStates, psVars ) );
00629   }
00630 
00631 
00632   /* 
00633    * Update the optimal system BlockInfo->optimalSystem. BlockInfo is a temporary 
00634    * storage that survive through single level of the lattice.
00635    */
00636   if(BlockInfo->optimalSystem != NIL(Amc_SubsystemInfo_t)) {
00637     Amc_AmcSubsystemFree(BlockInfo->optimalSystem);
00638     AmcBlockSetOptimalSystem(BlockInfo, NIL(Amc_SubsystemInfo_t));
00639   }
00640   AmcSetOptimalSystem(BlockInfo, bestCombinedSystem);
00641 
00642   /* Set the best system. */
00643   AmcBlockSetBestSystem(BlockInfo, best);
00644 
00645   mdd_free(mddOne);
00646   
00647   return BlockInfo;
00648 
00649 }
00650 
00651 
00665 static BlockInfo_t *
00666 AmcObtainOptimalSystemLowerBound(
00667 Amc_Info_t              *amcInfo,
00668 Ctlp_Formula_t          *formula,
00669 BlockInfo_t             *BlockInfo,
00670 int                     verbosity)
00671 {
00672   array_t               *subSystemArray = amcInfo->subSystemArray;
00673   Amc_SubsystemInfo_t   *subSystem, *bestCombinedSystem;
00674   mdd_t                 *initialStates;
00675   mdd_t                 *smallestStates, *currentErrorStates, *careStates;
00676   int                   i, best = 0;
00677   graph_t               *partition = Part_NetworkReadPartition(amcInfo->network);
00678   mdd_manager           *mddManager = Part_PartitionReadMddManager(partition);
00679   mdd_t                 *mddOne = mdd_one(mddManager);
00680   array_t               *quantifyVars;
00681   Mc_DcLevel            dcLevel;
00682   char                  *flagValue;
00683   
00684   /* 
00685    * Initial states must be set before coming into this routine.
00686    */
00687   initialStates = amcInfo->initialStates;
00688   if( initialStates == NIL(mdd_t) ) {
00689     (void)fprintf(vis_stderr, "** amc error: \n");
00690     return(NIL(BlockInfo_t));
00691   }
00692 
00693   /* Read in the usage of don't care level. Do not want to pass parameters. */
00694   flagValue = Cmd_FlagReadByName("amc_DC_level");
00695   if(flagValue != NIL(char)){
00696     dcLevel = (Mc_DcLevel) atoi(flagValue);
00697     if( dcLevel > McDcLevelRchFrontier_c ) dcLevel = McDcLevelRchFrontier_c;
00698   }
00699   else{
00700     /* default value set to McDcLevelNone_c. Mc's default is McDcLevelRch_c. */
00701     dcLevel = McDcLevelNone_c;
00702   }
00703 
00704   /*
00705    * Update the set of states satisfying the formula for each subsystem.
00706    * The process of "combining sub-systems" is equivalent of taking a 
00707    * "synchronous product" of multiple subsystems.
00708    */
00709   smallestStates = NIL(mdd_t);
00710   bestCombinedSystem  = NIL(Amc_SubsystemInfo_t);
00711 
00712   arrayForEachItem(Amc_SubsystemInfo_t *, subSystemArray, i, subSystem) {
00713 
00714     mdd_t                       *reachableStates, *fairStates, *satisfyStates;
00715     Fsm_Fsm_t                   *combinedFsm;
00716     Fsm_Fairness_t              *fairCond;
00717     Amc_SubsystemInfo_t         *combinedSystem; 
00718 
00719     /* Proceed if the subsystem has not yet been taken into the optimal system. */
00720     if(!subSystem->takenIntoOptimal) {
00721 
00722       /* 
00723        * Combine subsystems. If optimal subsystem is NIL, duplicate the
00724        * subsystem.
00725        */
00726       combinedSystem = Amc_CombineSubsystems(amcInfo->network,
00727                                              amcInfo->optimalSystem,
00728                                              subSystem);
00729       /* Remove input variables from the FSM */
00730       /*      combinedSystem = AmcClearInputVarsFromFSM(combinedSystem);*/
00731       combinedFsm = AmcSubsystemReadFsm(combinedSystem);
00732 
00733       /*
00734        * Use takenIntoOptimal field for the purpose of excluding current block
00735        * when universally quantifying variables from transition relation. 
00736        * Obtain lower bound of transition relation by universal quantification.
00737        */
00738 
00739       quantifyVars = AmcInitializeQuantifyVars(combinedSystem);
00740       combinedSystem->takenIntoOptimal = i;
00741 
00742 
00743       /*
00744        * Currently forced not to compute reachable states. This is to reduce
00745        * computational burden of computing it when dealing with complex
00746        * examples.
00747        */
00748       reachableStates = mdd_one(mddManager);
00749       fairStates = mdd_one(mddManager);
00750       fairCond = Fsm_FsmReadFairnessConstraint(combinedFsm);
00751       careStates = mdd_dup(reachableStates);
00752 
00753       Ctlp_FlushStates(formula);
00754       satisfyStates = mdd_dup(Amc_AmcEvaluateCTLFormula(combinedSystem,
00755                                                         subSystemArray, 
00756                                                         formula, fairStates,
00757                                                         fairCond, careStates,
00758                                                         amcInfo->lowerBound, 
00759                                                         quantifyVars,
00760                                                         (Mc_VerbosityLevel)
00761                                                         verbosity, dcLevel));
00762       {
00763         int x; array_t *quantifyStateVars;
00764         arrayForEachItem(array_t *, quantifyVars, x, quantifyStateVars) {
00765           array_free(quantifyStateVars); 
00766         }
00767         array_free(quantifyVars);
00768       }
00769       mdd_free(careStates); mdd_free(reachableStates); mdd_free(fairStates); 
00770       
00771 
00772       /*
00773        */
00774       if( subSystem->satisfyStates != NIL(mdd_t) ) {
00775         if( !(mdd_equal(satisfyStates, subSystem->satisfyStates )) &&
00776              (mdd_lequal(satisfyStates, subSystem->satisfyStates, 1, 1)) ) {
00777           /* We got a tighter approximation. */
00778           mdd_free(subSystem->satisfyStates);
00779           AmcSubsystemSetSatisfy(subSystem, mdd_dup(satisfyStates));
00780         }
00781       }     /* end of if( subSystem->satisfyStates != NIL(mdd_t) ) */
00782       else {
00783         /* Update subsystem when we are in level 1 of the lattice */
00784         AmcSubsystemSetSatisfy(subSystem, mdd_dup(satisfyStates));
00785       }
00786 
00787       if( AmcSubsystemReadSatisfy(combinedSystem) != NIL(mdd_t) )
00788         mdd_free( AmcSubsystemReadSatisfy(combinedSystem) );
00789       AmcSubsystemSetSatisfy(combinedSystem, mdd_dup(satisfyStates));
00790 
00791 
00792       /* Test if the formula is verified */
00793       {
00794         mdd_t *notSatisfyStates = mdd_not(satisfyStates);
00795         currentErrorStates      = mdd_and(initialStates, notSatisfyStates, 1, 1);
00796         mdd_free(notSatisfyStates);
00797         mdd_free(satisfyStates);
00798       }
00799 
00800       if( verbosity == Amc_VerbosityVomit_c) {
00801         mdd_manager *mddMgr = Fsm_FsmReadMddManager(combinedSystem->fsm);
00802         array_t *psVars     = Fsm_FsmReadPresentStateVars(combinedSystem->fsm);
00803 
00804         fprintf(vis_stdout,
00805                 "\n#AMC STATUS: The states satisfying the formula : %10g",
00806                 mdd_count_onset(mddMgr, combinedSystem->satisfyStates, psVars ) );
00807         fflush(vis_stdout);
00808       }
00809 
00810       if ( !mdd_is_tautology(currentErrorStates, 0) ) {
00811         array_t *careStatesArray;
00812 
00813         /* Verified the formula FALSE!! */
00814         AmcBlockSetBestSystem(BlockInfo, i);
00815         amcInfo->isVerified = 1;
00816         amcInfo->amcAnswer = Amc_Verified_False_c;
00817         fprintf(vis_stdout, "\n# AMC: formula failed --- ");
00818         Ctlp_FormulaPrint(vis_stdout, Ctlp_FormulaReadOriginalFormula(formula));
00819 
00820 
00821         if(currentErrorStates != NIL(mdd_t)) mdd_free(currentErrorStates);
00822         if(smallestStates != NIL(mdd_t))     mdd_free(smallestStates);
00823 
00824         if( bestCombinedSystem != NIL(Amc_SubsystemInfo_t) )
00825           Amc_AmcSubsystemFree(bestCombinedSystem);
00826 
00827         {
00828           /* Temporarily stay here until the damn thing becomes visible. */
00829           McOptions_t *mcOptions = ALLOC(McOptions_t, 1);
00830           mcOptions->useMore = FALSE;
00831           mcOptions->fwdBwd = McFwd_c;
00832           mcOptions->reduceFsm = FALSE;
00833           mcOptions->printInputs = FALSE;
00834           mcOptions->simFormat = FALSE;
00835           mcOptions->verbosityLevel = McVerbosityNone_c;
00836           mcOptions->dbgLevel = McDbgLevelMinVerbose_c;
00837           mcOptions->dcLevel   = McDcLevelNone_c;
00838           mcOptions->ctlFile = NIL(FILE);
00839           mcOptions->debugFile = NIL(FILE);
00840 
00841           careStatesArray = array_alloc(mdd_t *, 0);
00842           array_insert(mdd_t *, careStatesArray, 0, mddOne);
00843           fprintf(vis_stdout, "\n");
00844           McFsmDebugFormula((McOptions_t *)mcOptions, formula,
00845                             combinedSystem->fsm, careStatesArray);
00846           array_free(careStatesArray);
00847           FREE(mcOptions);
00848         }
00849         mdd_free(mddOne);
00850         Amc_AmcSubsystemFree(combinedSystem);
00851         Ctlp_FlushStates(formula);
00852 
00853         return BlockInfo;
00854 
00855       }else if (amcInfo->currentLevel == array_n(amcInfo->subSystemArray)){
00856         /* The formula is verified true!! */
00857         AmcBlockSetBestSystem(BlockInfo, i);
00858         amcInfo->isVerified = 1; 
00859         amcInfo->amcAnswer = Amc_Verified_True_c;
00860         fprintf(vis_stdout, "\n# AMC: formula passed --- ");
00861         Ctlp_FormulaPrint(vis_stdout, Ctlp_FormulaReadOriginalFormula(formula));
00862 
00863 
00864         if(currentErrorStates != NIL(mdd_t))
00865           mdd_free(currentErrorStates); 
00866         if(smallestStates != NIL(mdd_t))
00867           mdd_free(smallestStates);
00868         if( bestCombinedSystem != NIL(Amc_SubsystemInfo_t) )
00869           Amc_AmcSubsystemFree(bestCombinedSystem); 
00870 
00871         mdd_free(mddOne); Amc_AmcSubsystemFree(combinedSystem); 
00872         Ctlp_FlushStates(formula);
00873 
00874         return BlockInfo;
00875       }
00876 
00877       mdd_free(currentErrorStates);
00878 
00879 
00880       /*
00881        * Choose a subsystem that produces smallest satisfying states.
00882        */
00883       if( smallestStates == NIL(mdd_t) ||
00884           mdd_count_onset(mddManager, subSystem->satisfyStates, Fsm_FsmReadPresentStateVars(subSystem->fsm)) <= 
00885           mdd_count_onset(mddManager, smallestStates, Fsm_FsmReadPresentStateVars(subSystem->fsm)) ) {
00886         /*
00887          * Found locally optimal subsystem. 
00888          * Free smallest-error-state, best combined system so far. 
00889          * Update smallest-error-states and best combined system. 
00890          */
00891         if( smallestStates != NIL(mdd_t) ) mdd_free(smallestStates);
00892 
00893         smallestStates = mdd_dup(subSystem->satisfyStates);
00894 
00895         if(bestCombinedSystem != NIL(Amc_SubsystemInfo_t)) {
00896           Amc_AmcSubsystemFree(bestCombinedSystem);
00897           bestCombinedSystem = NIL(Amc_SubsystemInfo_t);
00898         }
00899         bestCombinedSystem = combinedSystem; 
00900         best = i;
00901       }
00902 
00903       else { /* Free combined system, current error states */
00904         Amc_AmcSubsystemFree(combinedSystem); combinedSystem = NIL(Amc_SubsystemInfo_t);
00905       }
00906 
00907     } /* end of if(!takenIntoOptimal) */
00908 
00909   } /* end of arrayForEachItem(subSystemArray) */
00910 
00911   mdd_free(smallestStates);
00912 
00913   /* 
00914    * Flush formula that was kept in last iteration. Update Block Info.  
00915    */
00916   Ctlp_FlushStates(formula);
00917 
00918   /*
00919    * Update optimal system BlockInfo->optimalSystem. BlockInfo is a temporary 
00920    * storage that survive through single level of the lattice.
00921    */
00922   if(BlockInfo->optimalSystem != NIL(Amc_SubsystemInfo_t)) {
00923     Amc_AmcSubsystemFree(BlockInfo->optimalSystem);
00924     AmcBlockSetOptimalSystem(BlockInfo, NIL(Amc_SubsystemInfo_t));
00925   }
00926   AmcSetOptimalSystem(BlockInfo, bestCombinedSystem);
00927 
00928   /* Set best system. */
00929   AmcBlockSetBestSystem(BlockInfo, best);
00930   mdd_free(mddOne);
00931 
00932   return BlockInfo;
00933 
00934 }
00935 
00936 
00937 
00945 static void
00946 AmcInitializeDependency(
00947 array_t         *subSystemArray,
00948 int             isMBM)
00949 {
00950   Amc_SubsystemInfo_t   *subSystem;  
00951   BlockSubsystemInfo_t  *BlockSubsystem;
00952   int   i;
00953 
00954   if(!isMBM) {
00955     int i;
00956     arrayForEachItem(Amc_SubsystemInfo_t *, subSystemArray, i, subSystem) {
00957       AmcSubsystemSetMethodSpecificData(subSystem, NIL(BlockSubsystemInfo_t));
00958     }
00959     return;
00960   }
00961 
00962   arrayForEachItem(Amc_SubsystemInfo_t *, subSystemArray, i, subSystem) {
00963 
00964     BlockSubsystem = ALLOC(BlockSubsystemInfo_t, 1);
00965 
00966     AmcSubsystemSetMethodSpecificData(subSystem, BlockSubsystem);
00967 
00968   }
00969 
00970 }
00971 
00979 static void
00980 AmcInitializeSchedule(
00981 Amc_Info_t *amcInfo)
00982 {
00983   array_t                 *subSystemArray = amcInfo->subSystemArray;
00984   Amc_SubsystemInfo_t     *subSystem;  
00985   BlockSubsystemInfo_t    *BlockSubsystem;
00986   int i;
00987 
00988   /* If MBM flag is not set just return */
00989   if(!amcInfo->isMBM)
00990     return;
00991 
00992   arrayForEachItem(Amc_SubsystemInfo_t *, subSystemArray, i, subSystem) {
00993 
00994     BlockSubsystem = (BlockSubsystemInfo_t *) AmcSubsystemReadMethodSpecificData(subSystem);
00995     if(!subSystem->takenIntoOptimal)
00996       AmcBlockSubsystemSetScheduledForRefinement(BlockSubsystem, 1);
00997     
00998   }
00999 
01000 }
01001 
01002 
01010 static int
01011 AmcIsEverySubsystemRescheduled(
01012 Amc_Info_t *amcInfo)
01013 {
01014   array_t               *subSystemArray = amcInfo->subSystemArray;
01015   Amc_SubsystemInfo_t   *subSystem;  
01016   BlockSubsystemInfo_t  *BlockSubsystem;
01017   int i;
01018 
01019   /* If MBM flag is not set just return */
01020   if( !amcInfo->isMBM )
01021     return 1;
01022 
01023   arrayForEachItem(Amc_SubsystemInfo_t *, subSystemArray, i, subSystem) {
01024 
01025     BlockSubsystem = (BlockSubsystemInfo_t *) AmcSubsystemReadMethodSpecificData(subSystem);
01026     if( AmcBlockSubsystemReadScheduledForRefinement(BlockSubsystem) )
01027       return 1;
01028     
01029   }
01030   return 0;
01031 
01032 }
01033 
01041 static void
01042 AmcPrintScheduleInformation(
01043 Amc_Info_t *amcInfo)
01044 {
01045   array_t                 *subSystemArray = amcInfo->subSystemArray;
01046   Amc_SubsystemInfo_t     *subSystem;  
01047   BlockSubsystemInfo_t    *BlockSubsystem;
01048   int i;
01049 
01050   /* If MBM flag is not set just return */
01051   if(!amcInfo->isMBM)
01052     return;
01053 
01054   fprintf(vis_stdout, "\nSchedule information : ");
01055 
01056   arrayForEachItem(Amc_SubsystemInfo_t *, subSystemArray, i, subSystem) {
01057 
01058     BlockSubsystem = (BlockSubsystemInfo_t *) AmcSubsystemReadMethodSpecificData(subSystem);
01059     fprintf(vis_stdout, " %d ", AmcBlockSubsystemReadScheduledForRefinement(BlockSubsystem) );
01060     
01061   }
01062 
01063 }
01064 
01065 
01066 #if 0
01067 
01074 static void
01075 AmcRescheduleForRefinement(
01076 st_table        *fanOutSystemTable)
01077 {
01078   Amc_SubsystemInfo_t   *subSystem;
01079   BlockSubsystemInfo_t  *BlockSubsystem;
01080   st_generator *stGen;
01081 
01082   st_foreach_item(fanOutSystemTable, stGen, &subSystem, NIL(char *)) {
01083 
01084     /* reschedule only ones that are not taken */
01085     if(!subSystem->takenIntoOptimal) {
01086       BlockSubsystem = (BlockSubsystemInfo_t *) AmcSubsystemReadMethodSpecificData(subSystem);
01087       AmcBlockSubsystemSetScheduledForRefinement(BlockSubsystem, 1);
01088     }
01089 
01090   }
01091 
01092 }
01093 
01101 static mdd_t *
01102 AmcRefineWithSatisfyStatesOfFanInSystem(
01103 Amc_SubsystemInfo_t     *subSystem,
01104 mdd_t                   *careStates)
01105 {
01106   st_table              *fanInTable = AmcSubsystemReadFanInTable(subSystem);
01107   Amc_SubsystemInfo_t   *fanInSystem;
01108   st_generator          *stGen;
01109 
01110   mdd_t                 *oldCareStates = careStates;
01111   st_foreach_item(fanInTable, stGen, &fanInSystem, NIL(char *)) {
01112 
01113     if(fanInSystem->satisfyStates != NIL(mdd_t)) {
01114       mdd_t     *fanInSatisfyStates = mdd_dup(fanInSystem->satisfyStates);
01115       careStates = mdd_and(fanInSatisfyStates, oldCareStates, 1, 1);
01116       mdd_free(oldCareStates); mdd_free(fanInSatisfyStates);
01117       oldCareStates = careStates;
01118     }
01119 
01120   }
01121 
01122   return(careStates);
01123 } /* end of "machine by machine" refinement of the careset */
01124 #endif
01125 
01126 
01135 static array_t *
01136 AmcInitializeQuantifyVars(
01137 Amc_SubsystemInfo_t *subSystem)
01138 {
01139   array_t             *quantifyVars             = array_alloc(array_t *, 0);
01140   array_t             *quantifyPresentVars      = array_alloc(int, 0);
01141   array_t             *quantifyNextVars         = array_alloc(int, 0);
01142   array_t             *quantifyInputVars        = array_alloc(int, 0);
01143   Ntk_Network_t       *network = Fsm_FsmReadNetwork(AmcSubsystemReadFsm(subSystem));
01144   Ntk_Node_t          *latch;
01145   st_table            *vertexTable = AmcSubsystemReadVertexTable(subSystem);
01146   lsGen               gen;
01147     
01148   Ntk_NetworkForEachLatch(network, gen, latch) {
01149     char *latchName = Ntk_NodeReadName(latch); 
01150 #ifdef AMC_DEBUG
01151         fprintf(vis_stdout, "\nlatch name: %s", latchName);
01152         fprintf(vis_stdout, "\n latch id: %d", Ntk_NodeReadMddId(latch));
01153         fprintf(vis_stdout, "\n latch id: %d", Ntk_NodeReadMddId(Ntk_NodeReadShadow(latch)));
01154         fflush(vis_stdout);
01155 #endif
01156     if(!st_lookup(vertexTable, latchName, (char **)0)) {
01157     
01158       /* Next state variables. */
01159       array_insert_last(int, quantifyNextVars, Ntk_NodeReadMddId(Ntk_NodeReadShadow(latch)));
01160       /* Present state variables. */
01161       array_insert_last(int, quantifyPresentVars, Ntk_NodeReadMddId(latch));
01162 
01163     } /* end of if(st_lookup(vertexTable)) */
01164   } /* end of Ntk_NetworkForEachLatch */
01165 
01166 
01167   {
01168     st_table    *inputVarTable = st_init_table(st_numcmp, st_numhash);
01169     Ntk_Node_t  *primaryInput;
01170     /* Build the hash table of input vars of this subsystem. */
01171     /* arrayForEachItem(int, inputVarArray, i, inputVar) {
01172       st_insert(inputVarTable, (char *)(long)inputVar, (char *)0);
01173     } */
01174 
01175     Ntk_NetworkForEachInput(network, gen, primaryInput) {
01176       int       mddId = Ntk_NodeReadMddId(primaryInput);
01177 #ifdef AMC_DEBUG
01178       char *inputName = Ntk_NodeReadName(primaryInput); 
01179       int       testMddId = Ntk_NodeReadMddId(primaryInput);
01180       fprintf(vis_stdout, "\nprimary input name : %s", inputName);
01181       fprintf(vis_stdout, "\nprimary input mdd id : %d", testMddId);
01182       fflush(vis_stdout);
01183 #endif
01184       /* if(!st_lookup(inputVarTable, (char *)(long)mddId, (char **)0)) { */
01185         array_insert_last(int, quantifyInputVars, mddId);
01186       /* } */
01187     }
01188     st_free_table(inputVarTable);
01189   }
01190 
01191   array_insert_last(array_t *, quantifyVars, quantifyPresentVars); 
01192   array_insert_last(array_t *, quantifyVars, quantifyNextVars); 
01193   array_insert_last(array_t *, quantifyVars, quantifyInputVars); 
01194  
01195   return quantifyVars;
01196 
01197 }
01198 
01199 
01200 #if 0
01201 
01208 static void
01209 AmcFreeBlockInfo(
01210 BlockInfo_t     *BlockInfo)
01211 {
01212 
01213   if(BlockInfo->optimalSystem != NIL(Amc_SubsystemInfo_t)) {
01214     Amc_AmcSubsystemFree(BlockInfo->optimalSystem);
01215   }
01216 
01217 }
01218 #endif
01219 
01220 
01228 static int
01229 AmcBlockSubsystemReadScheduledForRefinement(
01230 BlockSubsystemInfo_t        *system)
01231 {
01232   return system->scheduledForRefinement;
01233 }
01234 
01242 static void
01243 AmcBlockSubsystemSetScheduledForRefinement(
01244 BlockSubsystemInfo_t        *system,
01245 int                   data)
01246 {
01247   system->scheduledForRefinement = data;
01248 }
01249 
01250 
01251 #if 0
01252 
01259 static Amc_SubsystemInfo_t *
01260 AmcBlockReadOptimalSubsystem(
01261 BlockInfo_t        *system)
01262 {
01263   return system->optimalSystem;
01264 }
01265 #endif
01266 
01274 static void
01275 AmcBlockSetOptimalSystem(
01276 BlockInfo_t                  *system,
01277 Amc_SubsystemInfo_t  *data)
01278 {
01279   system->optimalSystem = data;
01280 }
01281 
01282 #if 0
01283 
01290 static int
01291 AmcBlockReadBestSystem(
01292 BlockInfo_t        *system)
01293 {
01294   return system->bestSystem;
01295 }
01296 #endif
01297 
01305 static void
01306 AmcBlockSetBestSystem(
01307 BlockInfo_t                *system,
01308 int                  data)
01309 {
01310   system->bestSystem = data;
01311 }
01312 
01313 #if 0
01314 
01325 static Amc_SubsystemInfo_t *
01326 AmcClearInputVarsFromFSM(
01327 Amc_SubsystemInfo_t   *subSystem)
01328 {
01329   Fsm_Fsm_t     *fsm = subSystem->fsm;
01330   array_t       *inputVarArray = Fsm_FsmReadInputVars(fsm);
01331   array_t       *newInputVarArray = array_alloc(int, 0);
01332 
01333   array_free(inputVarArray);
01334   (void) Fsm_FsmSetInputVars(fsm, newInputVarArray);
01335 
01336   return(subSystem);
01337 }
01338 #endif