[14] | 1 | /**CFile*********************************************************************** |
---|
| 2 | |
---|
| 3 | FileName [fsmReach.c] |
---|
| 4 | |
---|
| 5 | PackageName [fsm] |
---|
| 6 | |
---|
| 7 | Synopsis [Routines to perform reachability on the FSM structure.] |
---|
| 8 | |
---|
| 9 | Author [Rajeev K. Ranjan, In-Ho Moon, Kavita Ravi] |
---|
| 10 | |
---|
| 11 | Copyright [Copyright (c) 1994-1996 The Regents of the Univ. of California. |
---|
| 12 | All rights reserved. |
---|
| 13 | |
---|
| 14 | Permission is hereby granted, without written agreement and without license |
---|
| 15 | or royalty fees, to use, copy, modify, and distribute this software and its |
---|
| 16 | documentation for any purpose, provided that the above copyright notice and |
---|
| 17 | the following two paragraphs appear in all copies of this software. |
---|
| 18 | |
---|
| 19 | IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR |
---|
| 20 | DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT |
---|
| 21 | OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF |
---|
| 22 | CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
---|
| 23 | |
---|
| 24 | THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, |
---|
| 25 | INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND |
---|
| 26 | FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN |
---|
| 27 | "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE |
---|
| 28 | MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.] |
---|
| 29 | |
---|
| 30 | ******************************************************************************/ |
---|
| 31 | |
---|
| 32 | #include "fsmInt.h" |
---|
| 33 | #include "bdd.h" |
---|
| 34 | #include "ntm.h" |
---|
| 35 | #include "img.h" |
---|
| 36 | #include "sim.h" |
---|
| 37 | |
---|
| 38 | static char rcsid[] UNUSED = "$Id: fsmReach.c,v 1.102 2009/04/11 01:40:54 fabio Exp $"; |
---|
| 39 | |
---|
| 40 | /*---------------------------------------------------------------------------*/ |
---|
| 41 | /* Constant declarations */ |
---|
| 42 | /*---------------------------------------------------------------------------*/ |
---|
| 43 | /* HD constants */ |
---|
| 44 | #define FSM_HD_NONGREEDY 0 /* flag to indicate non-greedy computation at |
---|
| 45 | dead-ends */ |
---|
| 46 | #define FSM_HD_GREEDY 1 /* flag to indicate greedy computation at dead-ends */ |
---|
| 47 | #define FSM_HD_LARGE_SIZE 100000 /* size considered large for reached */ |
---|
| 48 | #define FSM_HD_MID_SIZE 50000 /* size considered medium for reached*/ |
---|
| 49 | #define FSM_HD_MINT_GROWTH 0.5 /* factor measuring minterm jump of reached*/ |
---|
| 50 | #define FSM_HD_GROWTH_RATE 0.04 /* Growth rate for reached in measuring slow |
---|
| 51 | * growth. */ |
---|
| 52 | #define FSM_MDD_DONT_FREE 0 /* flag to indicate that bdd should not be freed. */ |
---|
| 53 | #define FSM_MDD_FREE 1 /* flag to indicate that bdd should be freed.*/ |
---|
| 54 | #define FSM_HD_NUM_SLOW_GROWTHS 5 /* number of iterations of allowed |
---|
| 55 | * slow growth of reached. */ |
---|
| 56 | /*---------------------------------------------------------------------------*/ |
---|
| 57 | /* Structure declarations */ |
---|
| 58 | /*---------------------------------------------------------------------------*/ |
---|
| 59 | |
---|
| 60 | /**AutomaticStart*************************************************************/ |
---|
| 61 | |
---|
| 62 | /*---------------------------------------------------------------------------*/ |
---|
| 63 | /* Static function prototypes */ |
---|
| 64 | /*---------------------------------------------------------------------------*/ |
---|
| 65 | |
---|
| 66 | static int CheckImageValidity(mdd_manager *mddManager, mdd_t *image, array_t *domainVarMddIdArray, array_t *quantifyVarMddIdArray); |
---|
[15] | 67 | /*static*/ int ComputeNumberOfBinaryStateVariables(mdd_manager *mddManager, array_t *mddIdArray); |
---|
[14] | 68 | static mdd_t * AddStates(mdd_t *a, mdd_t *b, int freeA, int freeB); |
---|
| 69 | static void RandomSimulation(int simNVec, Fsm_Fsm_t *fsm, Fsm_RchType_t approxFlag, mdd_t *initialStates, mdd_t **reachableStates, mdd_t **fromLowerBound, FsmHdStruct_t *hdInfo); |
---|
| 70 | static void PrintStatsPerIteration(Fsm_RchType_t approxFlag, int nvars, int depth, FsmHdStruct_t *hdInfo, mdd_manager *mddManager, mdd_t *reachableStates, mdd_t *fromLowerBound, array_t *mintermVarArray); |
---|
| 71 | static void HdInduceFullDeadEndIfNecessary(mdd_manager *mddManager, Img_ImageInfo_t *imageInfo, mdd_t **fromLowerBound, mdd_t **fromUpperBound, mdd_t **reachableStates, mdd_t **image, FsmHdStruct_t *hdInfo, int *depth, int shellFlag, array_t *onionRings, array_t *mintermVarArray, int oldSize, double oldMint, int verbosityLevel); |
---|
| 72 | static mdd_t * ComputeInitialStates(Fsm_Fsm_t *fsm, int shellFlag, boolean printWarning); |
---|
| 73 | static int CheckStatesContainedInInvariant(mdd_t *reachableStates, array_t *invarStates); |
---|
| 74 | static void HdComputeReachabilityParameters(mdd_manager *mddManager, Img_ImageInfo_t *imageInfo, mdd_t **reachableStates, mdd_t **fromUpperBound, mdd_t **fromLowerBound, mdd_t **image, FsmHdStruct_t *hdInfo, mdd_t *initialStates, array_t *mintermVarArray, int *depth, int printStep, int shellFlag, array_t *onionRings, int verbosityLevel); |
---|
| 75 | static int InitializeIncrementalParameters(Fsm_Fsm_t *fsm, Ntk_Network_t *network, array_t **arrayOfRoots, st_table **tableOfLeaves); |
---|
| 76 | static mdd_t * IncrementalImageCompute(Ntk_Network_t *network, Fsm_Fsm_t *fsm, mdd_manager *mddManager, mdd_t *fromLowerBound, mdd_t *fromUpperBound, mdd_t *toCareSet, array_t *arrayOfRoots, st_table *tableOfLeaves, array_t *smoothVarArray, array_t *relationArray, int numLatch); |
---|
| 77 | static void PrintOnionRings(Fsm_Fsm_t *fsm, int printStep, Fsm_RchType_t approxFlag, int nvars); |
---|
| 78 | static array_t * GenerateGuidedSearchSequenceArray(array_t *guideArray); |
---|
| 79 | static void ComputeReachabilityParameters(mdd_manager *mddManager, Img_ImageInfo_t *imageInfo, Fsm_RchType_t approxFlag, mdd_t **reachableStates, mdd_t **fromUpperBound, mdd_t **fromLowerBound, mdd_t **image, FsmHdStruct_t *hdInfo, mdd_t *initialStates, array_t *mintermVarArray, int *depth, int printStep, int shellFlag, array_t *onionRings, int verbosityLevel, boolean guidedSearchMode, mdd_t *hint, int *hintDepth, boolean *notConverged); |
---|
| 80 | |
---|
| 81 | /**AutomaticEnd***************************************************************/ |
---|
| 82 | |
---|
| 83 | |
---|
| 84 | /*---------------------------------------------------------------------------*/ |
---|
| 85 | /* Definition of exported functions */ |
---|
| 86 | /*---------------------------------------------------------------------------*/ |
---|
| 87 | /**Function******************************************************************** |
---|
| 88 | |
---|
| 89 | Synopsis [Computes the set of reachable states of an FSM.] |
---|
| 90 | |
---|
| 91 | Description [Computes the set of reachable states of an FSM. If |
---|
| 92 | this set has already been computed, then just returns the result of |
---|
| 93 | the previous computation. The recomputation is done anyway if onion |
---|
| 94 | rings are required and have not been previously computed. The |
---|
| 95 | calling application is responsible for freeing the returned MDD in |
---|
| 96 | all cases. If verbosityLevel is greater than 1, then information is |
---|
| 97 | printed after every k steps of reachability, where k is defined by |
---|
| 98 | the -s option in the compute_reach command (the default for k is |
---|
| 99 | 1). If reorderFlag is set, then dynamic reordering is invoked once |
---|
| 100 | when the size of the reachable state set reaches the threshold given |
---|
| 101 | by reorderThreshold. This is independent of the |
---|
| 102 | dynamic_variable_reordering command. The shell flag indicates that |
---|
| 103 | the onion rings of frontier states should be stored. The default |
---|
| 104 | does not store the onion rings. The default value for approxFlag is |
---|
| 105 | Fsm_Rch_Default_c. See fsm.h for values. |
---|
| 106 | |
---|
| 107 | The procedure offers the following variations of reachability |
---|
| 108 | analysis: 1. Exact Reachability analysis by breadth-first search |
---|
| 109 | (default). 2. Reachability Analysis (HD) . 3. Reachability Analysis |
---|
| 110 | (upper bound by overapproximate FSM traversal). 4 ARDC-accelerated |
---|
| 111 | Reachability Analysis. 5. Invariant checking with early termination. |
---|
| 112 | |
---|
| 113 | A lower bound (specified by depthValue) on the reachable states may |
---|
| 114 | be obtained by performing a specified number of iterations |
---|
| 115 | (depthValue argument). It updates a field in the |
---|
| 116 | fsm.reachabilityInfo signalling that the reachable states are an |
---|
| 117 | under approximation. The default for the depthValue argument is 0 |
---|
| 118 | which indicates that reachability analysis computation should |
---|
| 119 | proceed to a fixpoint. If a depthValue is specified after the |
---|
| 120 | computation of reachable states, the reachable states is returned, |
---|
| 121 | else depthValue number of computations are performed. Every non-zero |
---|
| 122 | depthValue is interpreted as the number of iterations (image |
---|
| 123 | computations) to be performed from the current state (not from the |
---|
| 124 | initial state). |
---|
| 125 | |
---|
| 126 | Reachability Analysis (HD) is requested as approxFlag = Fsm_Rch_Hd_c. |
---|
| 127 | HD provides an exact set of reachable states with memory efficiency or |
---|
| 128 | a lower bound if reachability analysis does not complete. |
---|
| 129 | HD Principles: 1. compute image of small BDDs. 2. compute partial |
---|
| 130 | image if necessary 3. When no new states are generated (dead-end), |
---|
| 131 | compute new states from image of reached in a decomposed form. Allow |
---|
| 132 | no partial image. 4. When there is a big jump in the size of |
---|
| 133 | reached, compute its entire image. 5. store states that will |
---|
| 134 | produce no new successors (interior states) |
---|
| 135 | |
---|
| 136 | The algorithm is implemented as follows |
---|
| 137 | from = init; reached = init; |
---|
| 138 | while (reached != 1 && from != 0) { |
---|
| 139 | Allow partial image; |
---|
| 140 | image = Image(from); |
---|
| 141 | Check if partial image; |
---|
| 142 | from = image - reached; |
---|
| 143 | if (!partial image) interior_states_candidate = from; |
---|
| 144 | if (from == 0 || slow growth of Reached for 5 iterations) { |
---|
| 145 | Dead-end computation(greedy): find new states from image of reached; |
---|
| 146 | } |
---|
| 147 | if (from != 0 and (reached+from) size has a big jump) { |
---|
| 148 | Dead-end computation(non-greedy): find the entire image of reached; |
---|
| 149 | } |
---|
| 150 | if (from != 0) { |
---|
| 151 | Compute dense subset of from with at least 1 new state; |
---|
| 152 | if subset contains from (i.e., all new states) |
---|
| 153 | interior states += interior states candidate; |
---|
| 154 | reached = reached + from/subset; |
---|
| 155 | } |
---|
| 156 | } |
---|
| 157 | |
---|
| 158 | Legend: fromLowerBound = from; initialStates = init; |
---|
| 159 | reachableStates = reached |
---|
| 160 | fromUpperBound = reachableStates (BFS)/fromLowerBound(HD) |
---|
| 161 | interiorStates = states with no new successors |
---|
| 162 | interiorStateCandidates = states that may be interior |
---|
| 163 | states depending on whether all of them are added to |
---|
| 164 | reachableStates. |
---|
| 165 | |
---|
| 166 | Currently, this does not support the incrementalFlag = 1 option. |
---|
| 167 | |
---|
| 168 | Reachability Analysis (upper bound by overapproximate FSM traversal) |
---|
| 169 | gives an upper bound of exact reachable states by overapproximation. |
---|
| 170 | It is requested as approxFlag = Fsm_Rch_Oa_c. To do this, first, it |
---|
| 171 | groups latch variables by using SSD(State Space Decomposition in the |
---|
| 172 | paper Cho et.al, TCAD96-DEC) algorithm, then computes the reachable |
---|
| 173 | states of each submachines until convergence, then the product of |
---|
| 174 | reachable states of all submachines is an overapproximate reachable |
---|
| 175 | states. In this case, depthValue and shellFlag and incrementalFlag |
---|
| 176 | are incompatible with this option. |
---|
| 177 | |
---|
| 178 | ARDC-accelerated Reachability Analysis may allow faster and smaller |
---|
| 179 | memory usage reachability analysis. First, it computes |
---|
| 180 | overapproximated reachable states (if already computed, just use it). |
---|
| 181 | Reachability Analysis is then performed (any value of approxFlag is |
---|
| 182 | applicable) with a transition relation minimized with the complement |
---|
| 183 | of overapproximate reachable states as don't cares (called |
---|
| 184 | ARDC). This option is requested as ardc = 1. |
---|
| 185 | |
---|
| 186 | invarStates is a set of invariant states that can be specified. The |
---|
| 187 | reachable states must satisfy all invariants. The default value is |
---|
| 188 | NULL. Any invalid invariant must also be set to NULL in the |
---|
| 189 | invarStaes array. This option is used by the check_invariant |
---|
| 190 | command. When an array of invariant states is provided, reachability |
---|
| 191 | analysis is done until an invariant is violated or when reachability |
---|
| 192 | finishes, whichever is earlier. If an approximation of the reachable |
---|
| 193 | states exists, then each invariant is checked for violation. If none |
---|
| 194 | are violated, the set of reachable states is returned. It is the |
---|
| 195 | caller's resposibility to remove the violating invariant from the |
---|
| 196 | invarStates array to continue checking the remaining |
---|
| 197 | invariants. The presence of invarStates takes precedence over a |
---|
| 198 | non-zero depthValue. |
---|
| 199 | |
---|
| 200 | In general, the reachable states may not be consistent with the |
---|
| 201 | onion rings i.e., sum of onion rings is always contained in the |
---|
| 202 | reachable states. When the shell flag is specified and onion rings |
---|
| 203 | exist, the initial states are set to the sum of the onion ring |
---|
| 204 | states instead of the default initial states of the fsm or |
---|
| 205 | previously computed reachable states. |
---|
| 206 | |
---|
| 207 | Some random simulation of the reachable states can be done prior to |
---|
| 208 | reachability analysis. This is turned on using the rch_simulate |
---|
| 209 | flag. A number should be specifed in the command : set sim_reach |
---|
| 210 | <number>, which specifies the number of vectors to be simulated. |
---|
| 211 | The initial states are then set to the simulated set of states. If |
---|
| 212 | HD is specified, a subset may be taken. |
---|
| 213 | |
---|
| 214 | The recompute flag asks for an explicit recomputation. This means |
---|
| 215 | that even reachable states have been computed, they will be |
---|
| 216 | recomputed. |
---|
| 217 | |
---|
| 218 | On consecutive calls, recomputation is avoided as much as |
---|
| 219 | possible. The specific cases are when |
---|
| 220 | Case a. No shell Flag: Recomputation is avoided when reachability is |
---|
| 221 | done, when an underapproximation exists and it violates an |
---|
| 222 | invariant, an overapproximation exists and all invariants pass. |
---|
| 223 | |
---|
| 224 | Case b. With shell flag: Recomputation is avoided when onion rings |
---|
| 225 | are up-to-date and reachability is done or when onion rings are |
---|
| 226 | up-to-date, an underapproximation exists and an invariant fails. |
---|
| 227 | |
---|
| 228 | Update of fsm.reachabiltiyInfo fields are also based on minimum |
---|
| 229 | recomputation. The reachability field is updated only if the current |
---|
| 230 | set of reachable states are larger than the previous set. |
---|
| 231 | |
---|
| 232 | printWarning flag turns is used to turn on/off the warning message |
---|
| 233 | printed when the previously computed reachable states are used to |
---|
| 234 | proceed with computation. The default is TRUE. ] |
---|
| 235 | |
---|
| 236 | SideEffects [The result of the reachable state computation is stored |
---|
| 237 | with the FSM. i.e., depth, reachable set, underapprox flag. ] |
---|
| 238 | |
---|
| 239 | SeeAlso [Fsm_FsmComputeInitialStates |
---|
| 240 | Fsm_ArdcComputeOverApproximateReachableStates] |
---|
| 241 | |
---|
| 242 | ******************************************************************************/ |
---|
| 243 | mdd_t * |
---|
| 244 | Fsm_FsmComputeReachableStates( |
---|
| 245 | Fsm_Fsm_t *fsm, |
---|
| 246 | int incrementalFlag, |
---|
| 247 | int verbosityLevel, |
---|
| 248 | int printStep, |
---|
| 249 | int depthValue, |
---|
| 250 | int shellFlag, |
---|
| 251 | int reorderFlag, |
---|
| 252 | int reorderThreshold, |
---|
| 253 | Fsm_RchType_t approxFlag, |
---|
| 254 | int ardc, |
---|
| 255 | int recompute, |
---|
| 256 | array_t *invarStates, |
---|
| 257 | boolean printWarning, |
---|
| 258 | array_t *guideArray) |
---|
| 259 | { |
---|
| 260 | /* BFS variables */ |
---|
| 261 | Img_ImageInfo_t *imageInfo = NIL(Img_ImageInfo_t); /* image info structure*/ |
---|
| 262 | Img_ImageInfo_t *oldImageInfo = NIL(Img_ImageInfo_t); |
---|
| 263 | mdd_t *reachableStates;/* reachable states */ |
---|
| 264 | mdd_t *unreachableStates; |
---|
| 265 | mdd_t *fromLowerBound; /* new states in each iteration */ |
---|
| 266 | mdd_t *fromUpperBound; /* set to reachable states */ |
---|
| 267 | mdd_t *image, *newImage;/* image computed at each iteration */ |
---|
| 268 | mdd_t *initialStates; /* initial states */ |
---|
| 269 | mdd_t *toCareSet; /* the complement of the reached set */ |
---|
| 270 | int depth = 0; /* depth upto which the computation is |
---|
| 271 | * performed. |
---|
| 272 | */ |
---|
| 273 | graph_t *partition, *oldPartition; |
---|
| 274 | mdd_manager *mddManager = Fsm_FsmReadMddManager(fsm); /* mdd manager */ |
---|
| 275 | Ntk_Network_t *network = fsm->network; /* network */ |
---|
| 276 | bdd_reorder_type_t currentMethod = |
---|
| 277 | Ntk_NetworkReadDynamicVarOrderingMethod(network); /* current reordering |
---|
| 278 | * method */ |
---|
| 279 | int firstTimeFlag = TRUE, firstReorderFlag = FALSE; |
---|
| 280 | /* a flag to indicate the start of the computation */ |
---|
| 281 | Fsm_RchStatus_t rchStatus = Fsm_Rch_Under_c; |
---|
| 282 | /* under approximation of the reached set computed */ |
---|
| 283 | int reachableStateSetSize; /* bdd size of the reached set */ |
---|
| 284 | array_t *mintermVarArray; /* array of present state variables */ |
---|
| 285 | array_t *onionRings = NIL(array_t); |
---|
| 286 | /* onionringarray for shellFlag computation */ |
---|
| 287 | |
---|
| 288 | /* Incremental flag variables */ |
---|
| 289 | array_t *arrayOfRoots = NIL(array_t); |
---|
| 290 | st_table *tableOfLeaves = NIL(st_table); |
---|
| 291 | int numLatch = 0; |
---|
| 292 | array_t *relationArray = NIL(array_t), *smoothVarArray = NIL(array_t); |
---|
| 293 | |
---|
| 294 | boolean notConverged = FALSE; /* flag that says that the fixpoint procedure |
---|
| 295 | did not converge. */ |
---|
| 296 | /* HD variables */ |
---|
| 297 | FsmHdStruct_t *hdInfo = NULL; |
---|
| 298 | int nvars; /* number of present state variables */ |
---|
| 299 | |
---|
| 300 | |
---|
| 301 | /* Simulation variables */ |
---|
| 302 | int simNVec = 0; /* number of simulation vectors. */ |
---|
| 303 | char *simString = Cmd_FlagReadByName("rch_simulate"); |
---|
| 304 | |
---|
| 305 | /* Guided Search */ |
---|
| 306 | array_t *hintDepthArray = NIL(array_t); |
---|
| 307 | int hintDepth = -1; |
---|
| 308 | mdd_t *hint = NIL(mdd_t); /* iterates over guide array */ |
---|
| 309 | int hintnr; /* idem */ |
---|
| 310 | boolean guidedSearchMode = FALSE; |
---|
| 311 | boolean guideArrayAllocated = FALSE; |
---|
| 312 | |
---|
| 313 | boolean invariantFailed = FALSE; |
---|
| 314 | |
---|
| 315 | /* initializations */ |
---|
| 316 | /* if fsm is a submachine, takes realPsVars to count minterm correctly. */ |
---|
| 317 | mintermVarArray = Fsm_FsmReadPresentStateVars(fsm); |
---|
| 318 | |
---|
| 319 | /* compute number of present state variables */ |
---|
| 320 | nvars = ComputeNumberOfBinaryStateVariables(mddManager, mintermVarArray); |
---|
| 321 | assert(nvars > 0); |
---|
| 322 | |
---|
| 323 | /* initializations */ |
---|
| 324 | if (recompute) { |
---|
| 325 | if (incrementalFlag && |
---|
| 326 | ((approxFlag == Fsm_Rch_Hd_c) || (approxFlag == Fsm_Rch_Oa_c))) { |
---|
| 327 | fprintf(vis_stdout, |
---|
| 328 | "** rch error: Incremental flag and HD computation are not compatible\n"); |
---|
| 329 | return NIL(mdd_t); |
---|
| 330 | } |
---|
| 331 | FsmResetReachabilityFields(fsm, approxFlag); |
---|
| 332 | } else if ((!shellFlag) || Fsm_FsmTestReachabilityOnionRingsUpToDate(fsm)) { |
---|
| 333 | /* If already computed and exact , just return a copy. */ |
---|
| 334 | reachableStates = Fsm_FsmReadReachableStates(fsm); |
---|
| 335 | if (reachableStates != NIL(mdd_t)){ |
---|
| 336 | if (printWarning) { |
---|
| 337 | fprintf(vis_stdout, "** rch info: Reachable states have been previously computed.\n"); |
---|
| 338 | fprintf(vis_stdout, "** rch info: Not recomputing reachable states.\n"); |
---|
| 339 | fprintf(vis_stdout, "** rch info: Use compute_reach -F to recompute if necessary.\n"); |
---|
| 340 | } |
---|
| 341 | if (!shellFlag) { |
---|
| 342 | if (printWarning) { |
---|
| 343 | if (FsmReadReachabilityComputationMode(fsm) == Fsm_Rch_Bfs_c) { |
---|
| 344 | fprintf(vis_stdout, "** rch info: All previous computations done using BFS (-A 0 option).\n"); |
---|
| 345 | } else { |
---|
| 346 | fprintf(vis_stdout, "** rch info: Some previous computations done using BFS/DFS mode (-A 1 or -g option).\n"); |
---|
| 347 | } |
---|
| 348 | } |
---|
| 349 | return (mdd_dup(reachableStates)); |
---|
| 350 | } else if (Fsm_FsmReadReachabilityOnionRings(fsm)) { |
---|
| 351 | /* if onion rings exist, since they are up-to-date, return the |
---|
| 352 | * reachable states |
---|
| 353 | */ |
---|
| 354 | if (printWarning) { |
---|
| 355 | if (Fsm_FsmReadReachabilityOnionRingsMode(fsm) == Fsm_Rch_Bfs_c) { |
---|
| 356 | fprintf(vis_stdout, "** rch info: Onion rings have been computed using BFS (-A 0 option)\n"); |
---|
| 357 | } else { |
---|
| 358 | fprintf(vis_stdout, "** rch info: Some onion rings have been computed using BFS/DFS (-A 1 or -g option)\n"); |
---|
| 359 | } |
---|
| 360 | } |
---|
| 361 | if (printStep) |
---|
| 362 | PrintOnionRings(fsm, printStep, approxFlag, nvars); |
---|
| 363 | return (mdd_dup(reachableStates)); |
---|
| 364 | } |
---|
| 365 | } |
---|
| 366 | |
---|
| 367 | /* if some computed states exist and they violate an invariant, |
---|
| 368 | return the current set of reachable states */ |
---|
| 369 | reachableStates = Fsm_FsmReadCurrentReachableStates(fsm); |
---|
| 370 | if (reachableStates != NIL(mdd_t)) { |
---|
| 371 | if (!shellFlag) { |
---|
| 372 | /* if an underApprox exists, check invariant, if any */ |
---|
| 373 | if (invarStates != NIL(array_t)) { |
---|
| 374 | if (!CheckStatesContainedInInvariant(reachableStates, invarStates)) { |
---|
| 375 | if (printWarning) { |
---|
| 376 | fprintf(vis_stdout, "** rch info: Invariant violation using previously computed states\n"); |
---|
| 377 | } |
---|
| 378 | /* return violating reachable states */ |
---|
| 379 | return (mdd_dup(reachableStates)); |
---|
| 380 | } |
---|
| 381 | } |
---|
| 382 | } else if (Fsm_FsmReadReachabilityOnionRings(fsm)) { |
---|
| 383 | /* an invariant fails. */ |
---|
| 384 | if (invarStates != NIL(array_t)) { |
---|
| 385 | if (!CheckStatesContainedInInvariant(reachableStates, invarStates)) { |
---|
| 386 | if (printWarning) { |
---|
| 387 | fprintf(vis_stdout, "** rch info: Invariant violation using previously computed states\n"); |
---|
| 388 | if (Fsm_FsmReadReachabilityOnionRingsMode(fsm) == Fsm_Rch_Bfs_c) { |
---|
| 389 | fprintf(vis_stdout, "** rch info: Previous onion rings computed in BFS (-A 0 option).\n"); |
---|
| 390 | } else { |
---|
| 391 | fprintf(vis_stdout, "** rch info: Some set of onion rings have been computed using BFS/DFS (-A 1 or -g option)\n"); |
---|
| 392 | } |
---|
| 393 | fprintf(vis_stdout, "** rch info: Use compute_reach -F to recompute if necessary.\n"); |
---|
| 394 | } |
---|
| 395 | if (printStep) { |
---|
| 396 | PrintOnionRings(fsm, printStep, approxFlag, nvars); |
---|
| 397 | } |
---|
| 398 | return (mdd_dup(reachableStates)); |
---|
| 399 | } |
---|
| 400 | } |
---|
| 401 | } |
---|
| 402 | } |
---|
| 403 | /* if an over approx exists, check invariant, if any */ |
---|
| 404 | if ((invarStates != NIL(array_t)) && (!shellFlag) && (!depthValue) && |
---|
| 405 | (Fsm_FsmReadOverApproximateReachableStates(fsm) |
---|
| 406 | != NIL(array_t))) { |
---|
| 407 | if (FsmArdcCheckInvariant(fsm, invarStates)) { |
---|
| 408 | fprintf(vis_stdout, "** rch info: Over approximation exists, using over approximation for invariant checking.\n"); |
---|
| 409 | return(Fsm_ArdcGetMddOfOverApproximateReachableStates(fsm)); |
---|
| 410 | } |
---|
| 411 | } |
---|
| 412 | |
---|
| 413 | if (incrementalFlag && |
---|
| 414 | ((approxFlag == Fsm_Rch_Hd_c) || (approxFlag == Fsm_Rch_Oa_c))) { |
---|
| 415 | fprintf(vis_stdout, |
---|
| 416 | "** rch error: Incremental flag and HD computation are not compatible\n"); |
---|
| 417 | |
---|
| 418 | return NIL(mdd_t); |
---|
| 419 | } |
---|
| 420 | } |
---|
| 421 | /* onion rings make no sense with Over approx */ |
---|
| 422 | if (shellFlag && (approxFlag == Fsm_Rch_Oa_c)) { |
---|
| 423 | fprintf(vis_stdout, "** rch error: Can't generate onion rings with over approx\n"); |
---|
| 424 | return NIL(mdd_t); |
---|
| 425 | } |
---|
| 426 | |
---|
| 427 | /* depth value makes no sense with over approximation */ |
---|
| 428 | if (depthValue && (approxFlag == Fsm_Rch_Oa_c)) { |
---|
| 429 | fprintf(vis_stdout, "** rch error: Can't generate over approx with depth Value\n"); |
---|
| 430 | return NIL(mdd_t); |
---|
| 431 | } |
---|
| 432 | |
---|
| 433 | /* guided search cannot be done with Over approximation */ |
---|
| 434 | if ((guideArray != NIL(array_t)) && (approxFlag == Fsm_Rch_Oa_c)) { |
---|
| 435 | fprintf(vis_stdout, "Guided search is not implemented with Over approximations\n"); |
---|
| 436 | return NIL(mdd_t); |
---|
| 437 | } |
---|
| 438 | |
---|
| 439 | /* initializations */ |
---|
| 440 | reachableStateSetSize = 0; |
---|
| 441 | if ((approxFlag == Fsm_Rch_Hd_c) || (guideArray != NIL(array_t))) { |
---|
| 442 | /* this structure is needed for HD and guidedSearch */ |
---|
| 443 | hdInfo = FsmHdStructAlloc(nvars); |
---|
| 444 | } |
---|
| 445 | |
---|
| 446 | simNVec = 0; |
---|
| 447 | if (simString != NIL(char)) { |
---|
| 448 | simNVec = strtol(simString, NULL, 10); |
---|
| 449 | if (simNVec <= 0) simNVec = 0; |
---|
| 450 | } |
---|
| 451 | /* initialize onion ring array */ |
---|
| 452 | if (shellFlag) { |
---|
| 453 | if (Fsm_FsmReadReachabilityOnionRings(fsm) == NIL(array_t)) { |
---|
| 454 | onionRings = array_alloc(mdd_t *, 0); |
---|
| 455 | } else { |
---|
| 456 | onionRings = Fsm_FsmReadReachabilityOnionRings(fsm); |
---|
| 457 | } |
---|
| 458 | } |
---|
| 459 | |
---|
| 460 | /* Computes ARDCs, and overapproximation by SSD traversal, if required. */ |
---|
| 461 | if (approxFlag == Fsm_Rch_Oa_c || ardc) { |
---|
| 462 | long initialTime = 0; |
---|
| 463 | long finalTime; |
---|
| 464 | |
---|
| 465 | assert(!incrementalFlag); |
---|
| 466 | |
---|
| 467 | if (verbosityLevel > 0) |
---|
| 468 | initialTime = util_cpu_time(); |
---|
| 469 | |
---|
| 470 | (void)Fsm_FsmComputeOverApproximateReachableStates(fsm, incrementalFlag, |
---|
| 471 | verbosityLevel, printStep, depthValue, shellFlag, reorderFlag, |
---|
| 472 | reorderThreshold, recompute); |
---|
| 473 | |
---|
| 474 | if (approxFlag == Fsm_Rch_Oa_c) { |
---|
| 475 | if (hdInfo != NIL(FsmHdStruct_t)) FsmHdStructFree(hdInfo); |
---|
| 476 | return(Fsm_ArdcGetMddOfOverApproximateReachableStates(fsm)); |
---|
| 477 | } |
---|
| 478 | |
---|
| 479 | if (verbosityLevel > 0) { |
---|
| 480 | finalTime = util_cpu_time(); |
---|
| 481 | Fsm_ArdcPrintReachabilityResults(fsm, finalTime-initialTime); |
---|
| 482 | } |
---|
| 483 | } |
---|
| 484 | |
---|
| 485 | if(Cmd_FlagReadByName("linear_compute_range")) { |
---|
| 486 | partition = Part_NetworkCreatePartition(network, 0, "temp", (lsList)0, |
---|
| 487 | (lsList)0, NIL(mdd_t), Part_Fine_c, 0, 0, 0, 0); |
---|
| 488 | oldPartition = fsm->partition; |
---|
| 489 | oldImageInfo = fsm->imageInfo; |
---|
| 490 | fsm->imageInfo = 0; |
---|
| 491 | imageInfo = Fsm_FsmReadOrCreateImageInfoForComputingRange(fsm, 0, 1); |
---|
| 492 | unreachableStates = Img_ImageGetUnreachableStates(imageInfo); |
---|
| 493 | fprintf(vis_stdout, "%-20s%10g\n", "reachable states =", |
---|
| 494 | mdd_count_onset(mddManager, unreachableStates, |
---|
| 495 | fsm->fsmData.presentStateVars)); |
---|
| 496 | fflush(vis_stdout); |
---|
| 497 | /* get unreachable states */ |
---|
| 498 | Img_ImageInfoFree(imageInfo); |
---|
| 499 | fsm->imageInfo = oldImageInfo; |
---|
| 500 | fsm->partition = oldPartition; |
---|
| 501 | Part_PartitionFree(partition); |
---|
| 502 | exit(0); |
---|
| 503 | } |
---|
| 504 | /* Compute the set of initial states. Start with the |
---|
| 505 | * underapproximation of Reached states if it exists or sum of |
---|
| 506 | * onion rings if shell flag is specified or the initial states of |
---|
| 507 | * the fsm. |
---|
| 508 | */ |
---|
| 509 | initialStates = ComputeInitialStates(fsm, shellFlag, printWarning); |
---|
| 510 | if (initialStates == NIL(mdd_t)) { |
---|
| 511 | fprintf(vis_stdout, "** rch error: No initial states computed."); |
---|
| 512 | fprintf(vis_stdout, " No reachability will be performed.\n"); |
---|
| 513 | if (hdInfo != NIL(FsmHdStruct_t)) FsmHdStructFree(hdInfo); |
---|
| 514 | return NIL(mdd_t); |
---|
| 515 | } |
---|
| 516 | |
---|
| 517 | if (incrementalFlag){ |
---|
| 518 | /* Note: if incrementalflag is set, no imageinfo is created! */ |
---|
| 519 | numLatch = InitializeIncrementalParameters(fsm, network, &arrayOfRoots, |
---|
| 520 | &tableOfLeaves); |
---|
| 521 | smoothVarArray = array_join(fsm->fsmData.presentStateVars, |
---|
| 522 | fsm->fsmData.inputVars); |
---|
| 523 | relationArray = array_alloc(mdd_t *, numLatch+1); |
---|
| 524 | } else { |
---|
| 525 | /* Create an imageInfo for image computations, if not already created. */ |
---|
| 526 | imageInfo = Fsm_FsmReadOrCreateImageInfo(fsm, 0, 1); |
---|
| 527 | if (ardc) { |
---|
| 528 | Fsm_ArdcMinimizeTransitionRelation(fsm, Img_Forward_c); |
---|
| 529 | } |
---|
| 530 | } |
---|
| 531 | |
---|
| 532 | /* Get approximate traversal options */ |
---|
| 533 | if ((!incrementalFlag) && (approxFlag == Fsm_Rch_Hd_c)) { |
---|
| 534 | /* only partial image allowed. No approximation of frontier set */ |
---|
| 535 | hdInfo->onlyPartialImage = Fsm_FsmHdOptionReadOnlyPartialImage(hdInfo->options); |
---|
| 536 | /* states which can produce no new successors. */ |
---|
| 537 | hdInfo->interiorStates = bdd_zero(mddManager); |
---|
| 538 | } |
---|
| 539 | |
---|
| 540 | /* pertaining to simulation */ |
---|
| 541 | if (simNVec > 0) { |
---|
| 542 | RandomSimulation(simNVec, fsm, approxFlag, initialStates, |
---|
| 543 | &reachableStates, &fromLowerBound, hdInfo); |
---|
| 544 | } else { |
---|
| 545 | /* start reached set with initial states */ |
---|
| 546 | reachableStates = mdd_dup(initialStates); |
---|
| 547 | fromLowerBound = mdd_dup(reachableStates); |
---|
| 548 | } |
---|
| 549 | |
---|
| 550 | /* initialize variables to print */ |
---|
| 551 | if ((!incrementalFlag) && (approxFlag == Fsm_Rch_Hd_c)) { |
---|
| 552 | |
---|
| 553 | FsmHdStatsComputeSizeAndMinterms(mddManager, reachableStates, |
---|
| 554 | mintermVarArray, nvars, |
---|
| 555 | Fsm_Hd_Reached, hdInfo->stats); |
---|
| 556 | FsmHdStatsComputeSizeAndMinterms(mddManager, fromLowerBound, |
---|
| 557 | mintermVarArray, nvars, |
---|
| 558 | Fsm_Hd_From, hdInfo->stats); |
---|
| 559 | FsmHdStatsSetMintermFromSubset(hdInfo->stats, FsmHdStatsReadMintermFrom(hdInfo->stats)); |
---|
| 560 | FsmHdStatsSetSizeFromSubset(hdInfo->stats, FsmHdStatsReadSizeFrom(hdInfo->stats)); |
---|
| 561 | } |
---|
| 562 | |
---|
| 563 | if (printStep && ((depth % printStep) == 0) && (approxFlag == Fsm_Rch_Hd_c)){ |
---|
| 564 | fprintf(vis_stdout, "\nIndex: R = Reached; I = Image, F = Frontier, FA = Approximation of Frontier\n"); |
---|
| 565 | fprintf(vis_stdout, " f = Minterms in f; |f| = Bdd nodes in f\n\n"); |
---|
| 566 | } |
---|
| 567 | /* initialize for the first iteration */ |
---|
| 568 | fromUpperBound = reachableStates; |
---|
| 569 | |
---|
| 570 | /* hint array */ |
---|
| 571 | if (guideArray == NIL(array_t)) { |
---|
| 572 | guideArray = array_alloc(mdd_t *, 0); |
---|
| 573 | guideArrayAllocated = TRUE; |
---|
| 574 | } |
---|
| 575 | /* pad with 1 when no hints are provided */ |
---|
| 576 | if (array_n(guideArray) == 0) { |
---|
| 577 | array_insert_last(mdd_t *, guideArray, bdd_one(mddManager)); |
---|
| 578 | } |
---|
| 579 | /* depth sequence for hints. 1-to-1 correspondence with guidearray */ |
---|
| 580 | /* -1 implies apply hint to convergence. */ |
---|
| 581 | hintDepthArray = GenerateGuidedSearchSequenceArray(guideArray); |
---|
| 582 | |
---|
| 583 | assert(array_n(hintDepthArray) == array_n(guideArray)); |
---|
| 584 | |
---|
| 585 | if (array_n(guideArray) == 0) hint = mdd_one(mddManager); |
---|
| 586 | |
---|
| 587 | arrayForEachItem(mdd_t *, guideArray, hintnr, hint){ |
---|
| 588 | |
---|
| 589 | /* check the depth for which this hint is to be applied. */ |
---|
| 590 | hintDepth = array_fetch(int, hintDepthArray, hintnr); |
---|
| 591 | |
---|
| 592 | if(hintnr == 0 && mdd_is_tautology(hint, 1) && array_n(guideArray) == 1){ |
---|
| 593 | assert(hintDepth == -1); |
---|
| 594 | } else { |
---|
| 595 | assert(!incrementalFlag); |
---|
| 596 | guidedSearchMode = TRUE; |
---|
| 597 | Fsm_InstantiateHint(fsm, hint, 1, 0, Ctlp_Underapprox_c, |
---|
| 598 | verbosityLevel > 1); |
---|
| 599 | if (hintnr < (array_n(guideArray)-1)) |
---|
| 600 | fprintf(vis_stdout, "**GS info: Instantiating hint number %d\n", hintnr+1); |
---|
| 601 | else |
---|
| 602 | fprintf(vis_stdout, "**GS info: Restoring original transition relation\n"); |
---|
| 603 | |
---|
| 604 | if (approxFlag == Fsm_Rch_Hd_c) { |
---|
| 605 | /* clean up all the invalid state information */ |
---|
| 606 | if (hdInfo->interiorStates != NIL(mdd_t)) |
---|
| 607 | mdd_free(hdInfo->interiorStates); |
---|
| 608 | hdInfo->interiorStates = NIL(mdd_t); /* for every new hint, this is invalid. */ |
---|
| 609 | if (hdInfo->interiorStateCandidate != NIL(mdd_t)) |
---|
| 610 | mdd_free(hdInfo->interiorStateCandidate); |
---|
| 611 | hdInfo->interiorStateCandidate = NIL(mdd_t); /* for every new hint, this is invalid */ |
---|
| 612 | hdInfo->imageOfReachedComputed = FALSE; /* since it doesn't matter for every new hint */ |
---|
| 613 | if (hdInfo->deadEndResidue != NIL(mdd_t)) |
---|
| 614 | mdd_free(hdInfo->deadEndResidue); |
---|
| 615 | hdInfo->deadEndResidue = NIL(mdd_t); |
---|
| 616 | } |
---|
| 617 | /* generate a frontier by doing a dead-end computation if the |
---|
| 618 | frontier is empty. This is non-greedy for BFS and greedy for |
---|
| 619 | HD. */ |
---|
| 620 | if (mdd_is_tautology(fromLowerBound, 0)) { |
---|
| 621 | ComputeReachabilityParameters(mddManager, imageInfo, approxFlag, |
---|
| 622 | &reachableStates, &fromUpperBound, |
---|
| 623 | &fromLowerBound, &image, hdInfo, |
---|
| 624 | initialStates, |
---|
| 625 | mintermVarArray, |
---|
| 626 | &depth, printStep, |
---|
| 627 | shellFlag, onionRings, |
---|
| 628 | verbosityLevel, |
---|
| 629 | guidedSearchMode, hint, &hintDepth, |
---|
| 630 | ¬Converged); |
---|
| 631 | } |
---|
| 632 | } |
---|
| 633 | /* initialize */ |
---|
| 634 | notConverged = FALSE; |
---|
| 635 | if (!incrementalFlag) |
---|
| 636 | Img_ImageInfoResetUseOptimizedRelationFlag(imageInfo); |
---|
| 637 | /* Main loop of reachability computation. */ |
---|
| 638 | /* Iterate until fromLowerBound is empty or all states are reached. */ |
---|
| 639 | while (!mdd_is_tautology(fromLowerBound, 0)) { |
---|
| 640 | if(depth > 0 && !incrementalFlag) |
---|
| 641 | Img_ImageInfoSetUseOptimizedRelationFlag(imageInfo); |
---|
| 642 | /* fromLowerBound is the "onion shell" of states just reached. */ |
---|
| 643 | if ((shellFlag && (approxFlag != Fsm_Rch_Hd_c) && |
---|
| 644 | (!firstTimeFlag || |
---|
| 645 | (Fsm_FsmReadReachabilityOnionRings(fsm) == NIL(array_t)))) || |
---|
| 646 | (shellFlag && (approxFlag == Fsm_Rch_Hd_c) && |
---|
| 647 | (Fsm_FsmReadReachabilityOnionRings(fsm) == NIL(array_t)) && |
---|
| 648 | firstTimeFlag)) { |
---|
| 649 | array_insert_last(mdd_t*, onionRings, mdd_dup(fromLowerBound)); |
---|
| 650 | } |
---|
| 651 | |
---|
| 652 | /* if it is the print step, print out the iteration and the */ |
---|
| 653 | if (printStep && ((depth % printStep) == 0)) { |
---|
| 654 | int step; |
---|
| 655 | /* for BFS, preserve earlier format of printing */ |
---|
| 656 | step = (shellFlag) ? array_n(onionRings) : Fsm_FsmGetReachableDepth(fsm)+depth; |
---|
| 657 | PrintStatsPerIteration(approxFlag, |
---|
| 658 | nvars, |
---|
| 659 | step, |
---|
| 660 | hdInfo, |
---|
| 661 | mddManager, |
---|
| 662 | reachableStates, |
---|
| 663 | fromLowerBound, |
---|
| 664 | mintermVarArray); |
---|
| 665 | } |
---|
| 666 | |
---|
| 667 | /* Check if invariant contains the new states. In case of HD |
---|
| 668 | * computation, check the containment of the entire reached set. |
---|
| 669 | */ |
---|
| 670 | if (invarStates != NIL(array_t)) { |
---|
| 671 | mdd_t *temp; |
---|
| 672 | temp = (approxFlag == Fsm_Rch_Hd_c) ? reachableStates : fromLowerBound; |
---|
| 673 | if (!CheckStatesContainedInInvariant(temp, invarStates)) { |
---|
| 674 | notConverged = TRUE; |
---|
| 675 | invariantFailed = TRUE; /* flag used for early termination */ |
---|
| 676 | break; |
---|
| 677 | } |
---|
| 678 | } |
---|
| 679 | |
---|
| 680 | if (mdd_is_tautology(reachableStates, 1)) { |
---|
| 681 | break; |
---|
| 682 | } |
---|
| 683 | |
---|
| 684 | if ((depthValue && (depth == depthValue)) || |
---|
| 685 | /* limited depth hint is implemented this way */ |
---|
| 686 | (hintDepth == 0)) { |
---|
| 687 | /* No more steps */ |
---|
| 688 | notConverged = TRUE; |
---|
| 689 | break; |
---|
| 690 | } |
---|
| 691 | |
---|
| 692 | if (reorderFlag && !firstReorderFlag && |
---|
| 693 | (reachableStateSetSize >= reorderThreshold )){ |
---|
| 694 | firstReorderFlag = TRUE; |
---|
| 695 | (void) fprintf(vis_stdout, "Dynamic variable ordering forced "); |
---|
| 696 | (void) fprintf(vis_stdout, "with method sift\n"); |
---|
| 697 | Ntk_NetworkSetDynamicVarOrderingMethod(network, |
---|
| 698 | BDD_REORDER_SIFT, |
---|
| 699 | BDD_REORDER_VERBOSITY_DEFAULT); |
---|
| 700 | bdd_reorder(Ntk_NetworkReadMddManager(network)); |
---|
| 701 | Ntk_NetworkSetDynamicVarOrderingMethod(network, currentMethod, |
---|
| 702 | BDD_REORDER_VERBOSITY_DEFAULT); |
---|
| 703 | } |
---|
| 704 | |
---|
| 705 | firstTimeFlag = FALSE; |
---|
| 706 | /* careSet for image computation is the set of all states not reached |
---|
| 707 | * so far. |
---|
| 708 | */ |
---|
| 709 | toCareSet = mdd_not(reachableStates); |
---|
| 710 | |
---|
| 711 | /* |
---|
| 712 | * Image of some set between lower and upper, where we care |
---|
| 713 | * about the image only on unreached states. |
---|
| 714 | */ |
---|
| 715 | if (incrementalFlag){ |
---|
| 716 | image = IncrementalImageCompute(network, fsm, mddManager, |
---|
| 717 | fromLowerBound, |
---|
| 718 | fromUpperBound, toCareSet, |
---|
| 719 | arrayOfRoots, tableOfLeaves, |
---|
| 720 | smoothVarArray, relationArray, |
---|
| 721 | numLatch); |
---|
| 722 | } else{ |
---|
| 723 | assert(!incrementalFlag); |
---|
| 724 | |
---|
| 725 | if (approxFlag == Fsm_Rch_Hd_c) { |
---|
| 726 | /* allow partial image computation */ |
---|
| 727 | Img_ImageAllowPartialImage(imageInfo, TRUE); |
---|
| 728 | } |
---|
| 729 | |
---|
| 730 | /* compute the image of this iteration */ |
---|
| 731 | image = Img_ImageInfoComputeFwdWithDomainVars(imageInfo, |
---|
| 732 | fromLowerBound, |
---|
| 733 | fromUpperBound, |
---|
| 734 | toCareSet); |
---|
| 735 | |
---|
| 736 | |
---|
| 737 | |
---|
| 738 | /* record if partial image or not */ |
---|
| 739 | if (approxFlag == Fsm_Rch_Hd_c) { |
---|
| 740 | /* Check if partial image computation, disallow partial image |
---|
| 741 | * computation. |
---|
| 742 | */ |
---|
| 743 | hdInfo->partialImage = Img_ImageWasPartial(imageInfo); |
---|
| 744 | /* record this to prevent dead-end computation. */ |
---|
| 745 | hdInfo->imageOfReachedComputed = (!hdInfo->partialImage) && |
---|
| 746 | mdd_equal(reachableStates, fromLowerBound); |
---|
| 747 | /* potential candidates for interior states (only if not a |
---|
| 748 | * partial image) |
---|
| 749 | */ |
---|
| 750 | if (!hdInfo->partialImage) hdInfo->interiorStateCandidate = mdd_dup(fromLowerBound); |
---|
| 751 | } |
---|
| 752 | } |
---|
| 753 | |
---|
| 754 | /* free the used bdds */ |
---|
| 755 | mdd_free(toCareSet); |
---|
| 756 | |
---|
| 757 | /* New lower bound is the states just reached. */ |
---|
| 758 | mdd_free(fromLowerBound); |
---|
| 759 | fromLowerBound = mdd_and(image, reachableStates, 1, 0); |
---|
| 760 | depth++; |
---|
| 761 | hintDepth--; |
---|
| 762 | |
---|
| 763 | |
---|
| 764 | if ((!incrementalFlag) && (approxFlag == Fsm_Rch_Hd_c)) { |
---|
| 765 | FsmHdStatsComputeSizeAndMinterms(mddManager, image, |
---|
| 766 | mintermVarArray, nvars, |
---|
| 767 | Fsm_Hd_To, hdInfo->stats); |
---|
| 768 | } |
---|
| 769 | |
---|
| 770 | /* need image only if HD and not dead-end */ |
---|
| 771 | if (approxFlag != Fsm_Rch_Hd_c) { |
---|
| 772 | mdd_free(image); |
---|
| 773 | image = NULL; |
---|
| 774 | } else { |
---|
| 775 | if (hdInfo->imageOfReachedComputed || hdInfo->onlyPartialImage || |
---|
| 776 | (hdInfo->slowGrowth >= FSM_HD_NUM_SLOW_GROWTHS) || |
---|
| 777 | mdd_is_tautology(fromLowerBound, 0)) { |
---|
| 778 | mdd_free(image); |
---|
| 779 | image = NULL; |
---|
| 780 | } |
---|
| 781 | } |
---|
| 782 | |
---|
| 783 | /* computes reachable states, fromlowerBound and fromupperbound |
---|
| 784 | * for BFS. For HD it computes the above as well as interior |
---|
| 785 | * statess, dead-end residue, etc. All the other parameteres are |
---|
| 786 | * updated. For guided search, this call does not perform a |
---|
| 787 | * non-greedy dead-end computation, even if the frontier is 0. */ |
---|
| 788 | ComputeReachabilityParameters(mddManager, imageInfo, approxFlag, |
---|
| 789 | &reachableStates, |
---|
| 790 | &fromUpperBound, |
---|
| 791 | &fromLowerBound, |
---|
| 792 | &image, |
---|
| 793 | hdInfo, |
---|
| 794 | initialStates, |
---|
| 795 | mintermVarArray, |
---|
| 796 | &depth, printStep, |
---|
| 797 | shellFlag, onionRings, |
---|
| 798 | verbosityLevel, FALSE, hint, |
---|
| 799 | &hintDepth, |
---|
| 800 | ¬Converged); |
---|
| 801 | |
---|
| 802 | |
---|
| 803 | if (mdd_is_tautology(fromLowerBound, 0) && |
---|
| 804 | (approxFlag == Fsm_Rch_Bfs_c) && |
---|
| 805 | (!guidedSearchMode) && (!depthValue)) |
---|
| 806 | depth--; |
---|
| 807 | |
---|
| 808 | } /* end of main while loop (while frontier != 0) */ |
---|
| 809 | |
---|
| 810 | /* stop iterating over hint if invariants are violated or all |
---|
| 811 | states are reachable or limited depth value has been |
---|
| 812 | reached. */ |
---|
| 813 | if (invariantFailed) break; |
---|
| 814 | if (mdd_is_tautology(reachableStates, 1)) { |
---|
| 815 | break; |
---|
| 816 | } |
---|
| 817 | if (depthValue && (depth == depthValue)) { |
---|
| 818 | /* No more steps */ |
---|
| 819 | break; |
---|
| 820 | } |
---|
| 821 | |
---|
| 822 | }/* for each hint */ |
---|
| 823 | |
---|
| 824 | |
---|
| 825 | if(!incrementalFlag && |
---|
| 826 | Img_ImageInfoObtainMethodType(imageInfo) == Img_Linear_c && |
---|
| 827 | Img_ImageInfoObtainOptimizeType(imageInfo) == Opt_NS && |
---|
| 828 | Img_IsTransitionRelationOptimized(imageInfo)) { |
---|
| 829 | Img_ImageInfoResetUseOptimizedRelationFlag(imageInfo); |
---|
| 830 | fprintf(vis_stdout, "%-20s%10g\n", "reachable states =", |
---|
| 831 | mdd_count_onset(mddManager, reachableStates, |
---|
| 832 | fsm->fsmData.presentStateVars)); |
---|
| 833 | fromLowerBound = mdd_dup(reachableStates); |
---|
| 834 | fromUpperBound = reachableStates; |
---|
| 835 | while (1) { |
---|
| 836 | toCareSet = mdd_dup(reachableStates); |
---|
| 837 | image = Img_ImageInfoComputeFwdWithDomainVars(imageInfo, |
---|
| 838 | fromLowerBound, |
---|
| 839 | fromUpperBound, |
---|
| 840 | toCareSet); |
---|
| 841 | newImage = bdd_or(image, initialStates, 1, 1); |
---|
| 842 | bdd_free(image); |
---|
| 843 | image = newImage; |
---|
| 844 | if(mdd_equal(fromLowerBound, image)) { |
---|
| 845 | mdd_free(toCareSet); |
---|
| 846 | mdd_free(fromLowerBound); |
---|
| 847 | mdd_free(reachableStates); |
---|
| 848 | fromLowerBound = image; |
---|
| 849 | reachableStates = mdd_dup(fromLowerBound); |
---|
| 850 | fromUpperBound = reachableStates; |
---|
| 851 | fprintf(vis_stdout, "%-20s%10g\n", "reachable states =", |
---|
| 852 | mdd_count_onset(mddManager, reachableStates, |
---|
| 853 | fsm->fsmData.presentStateVars)); |
---|
| 854 | break; |
---|
| 855 | } |
---|
| 856 | mdd_free(toCareSet); |
---|
| 857 | mdd_free(fromLowerBound); |
---|
| 858 | mdd_free(reachableStates); |
---|
| 859 | fromLowerBound = image; |
---|
| 860 | reachableStates = mdd_dup(fromLowerBound); |
---|
| 861 | fromUpperBound = reachableStates; |
---|
| 862 | |
---|
| 863 | fprintf(vis_stdout, "%-20s%10g\n", "reachable states =", |
---|
| 864 | mdd_count_onset(mddManager, reachableStates, |
---|
| 865 | fsm->fsmData.presentStateVars)); |
---|
| 866 | } |
---|
| 867 | } |
---|
| 868 | |
---|
| 869 | |
---|
| 870 | /* clean up for Guided search mainly, only if needed */ |
---|
| 871 | /* we rely on the fact that the variable hint is set to the last hint from |
---|
| 872 | * the previous loop. |
---|
| 873 | */ |
---|
| 874 | if (guidedSearchMode && !mdd_is_tautology(hint, 1)) |
---|
| 875 | Fsm_CleanUpHints(fsm, 1, 0, printStep); |
---|
| 876 | array_free(hintDepthArray); |
---|
| 877 | |
---|
| 878 | /* If (1) all states are reachable, or (2) not limited depth computation |
---|
| 879 | and not a converge with a hint, or (3) limited depth and not |
---|
| 880 | guided search mode and BFS and frontier = 0, or (4) in guided |
---|
| 881 | search, if limited depth and frontier = 0 then one full dead-end |
---|
| 882 | should have occured */ |
---|
| 883 | if(mdd_is_tautology(reachableStates, 1) || |
---|
| 884 | ((notConverged == FALSE) && mdd_is_tautology(hint, 1)) || |
---|
| 885 | (!guidedSearchMode && (notConverged == TRUE) && |
---|
| 886 | mdd_is_tautology(fromLowerBound, 0) && (approxFlag == Fsm_Rch_Bfs_c)) || |
---|
| 887 | (guidedSearchMode && hdInfo->deadEndWithOriginalTR && |
---|
| 888 | mdd_is_tautology(fromLowerBound, 0) && (approxFlag == Fsm_Rch_Bfs_c))) { |
---|
| 889 | |
---|
| 890 | rchStatus = Fsm_Rch_Exact_c; |
---|
| 891 | if (mdd_is_tautology(reachableStates, 1) && |
---|
| 892 | !mdd_is_tautology(fromLowerBound, 0) && |
---|
| 893 | printStep && ((depth % printStep) == 0) ) { |
---|
| 894 | int step; |
---|
| 895 | /* for BFS, preserve earlier format of printing */ |
---|
| 896 | step = (shellFlag) ? |
---|
| 897 | array_n(onionRings) : |
---|
| 898 | Fsm_FsmGetReachableDepth(fsm)+depth; |
---|
| 899 | PrintStatsPerIteration(approxFlag, nvars, step, hdInfo, |
---|
| 900 | mddManager, reachableStates, |
---|
| 901 | fromLowerBound, mintermVarArray); |
---|
| 902 | } |
---|
| 903 | } |
---|
| 904 | |
---|
| 905 | /* clean up the hints if allocated here */ |
---|
| 906 | if (guideArrayAllocated) mdd_array_free(guideArray); |
---|
| 907 | |
---|
| 908 | if (hdInfo != NIL(FsmHdStruct_t)) { |
---|
| 909 | FsmHdStructFree(hdInfo); |
---|
| 910 | } |
---|
| 911 | |
---|
| 912 | mdd_free(fromLowerBound); |
---|
| 913 | mdd_free(initialStates); |
---|
| 914 | |
---|
| 915 | /* Update FSM reahcability fields */ |
---|
| 916 | |
---|
| 917 | /* indicate whether the shells are consistent with the reachable states */ |
---|
| 918 | if (!shellFlag) { |
---|
| 919 | /* if any states were added from a previous computation, shells |
---|
| 920 | are not up-to-date */ |
---|
| 921 | if (Fsm_FsmReadCurrentReachableStates(fsm) != NIL(mdd_t)) { |
---|
| 922 | if (!mdd_lequal(reachableStates, Fsm_FsmReadCurrentReachableStates(fsm), 1, 1)) { |
---|
| 923 | FsmSetReachabilityOnionRingsUpToDateFlag(fsm, FALSE); |
---|
| 924 | } /* otherwise the previous iteration was computed with onion |
---|
| 925 | rings, in which case it is still up-to-date or the previous |
---|
| 926 | iteration was computed without onion rings and it was set to not |
---|
| 927 | up-to-date in the previous iteration */ |
---|
| 928 | } else { |
---|
| 929 | assert(Fsm_FsmReadReachabilityOnionRings(fsm) == NIL(array_t)); |
---|
| 930 | /* not up-to-date because no onion rings */ |
---|
| 931 | FsmSetReachabilityOnionRingsUpToDateFlag(fsm, FALSE); |
---|
| 932 | } |
---|
| 933 | |
---|
| 934 | } else { |
---|
| 935 | /* shells are up to date only if current set adds upto previously |
---|
| 936 | computed states or more */ |
---|
| 937 | if (Fsm_FsmReadCurrentReachableStates(fsm)) { |
---|
| 938 | if (!mdd_lequal(Fsm_FsmReadCurrentReachableStates(fsm), |
---|
| 939 | reachableStates, 1, 1)) { |
---|
| 940 | FsmSetReachabilityOnionRingsUpToDateFlag(fsm, FALSE); |
---|
| 941 | } else { |
---|
| 942 | FsmSetReachabilityOnionRingsUpToDateFlag(fsm, TRUE); |
---|
| 943 | } |
---|
| 944 | |
---|
| 945 | } else FsmSetReachabilityOnionRingsUpToDateFlag(fsm, TRUE); |
---|
| 946 | |
---|
| 947 | /* Onion rings are not BFS, i.e., HD or Guided search. */ |
---|
| 948 | if ((approxFlag == Fsm_Rch_Hd_c) || |
---|
| 949 | (Fsm_FsmReadReachabilityOnionRingsMode(fsm) == Fsm_Rch_Hd_c) || |
---|
| 950 | guidedSearchMode) |
---|
| 951 | FsmSetReachabilityOnionRingsMode(fsm, Fsm_Rch_Hd_c); |
---|
| 952 | |
---|
| 953 | if (array_n(onionRings) == 0) { |
---|
| 954 | array_free(onionRings); |
---|
| 955 | onionRings = NIL(array_t); |
---|
| 956 | } |
---|
| 957 | FsmSetReachabilityOnionRings(fsm, onionRings); |
---|
| 958 | } |
---|
| 959 | |
---|
| 960 | /* update fsm structure */ |
---|
| 961 | /* record depth of traversal, depth is consistent with reachable |
---|
| 962 | states, hence may not be consistent with the onion rings */ |
---|
| 963 | /* replace reachable states if only more states have been computed now */ |
---|
| 964 | if (Fsm_FsmReadCurrentReachableStates(fsm) != NIL(mdd_t)) { |
---|
| 965 | if (!mdd_lequal(reachableStates, Fsm_FsmReadCurrentReachableStates(fsm), 1, 1)) { |
---|
| 966 | Fsm_FsmFreeReachableStates(fsm); |
---|
| 967 | fsm->reachabilityInfo.reachableStates = mdd_dup(reachableStates); |
---|
| 968 | if (!shellFlag) fsm->reachabilityInfo.depth = Fsm_FsmGetReachableDepth(fsm) + depth; |
---|
| 969 | else if (Fsm_FsmReadReachabilityOnionRings(fsm)) |
---|
| 970 | fsm->reachabilityInfo.depth = array_n(Fsm_FsmReadReachabilityOnionRings(fsm)); |
---|
| 971 | /* set computation mode as HD if HD or Guided search, basically to indicate not BFS */ |
---|
| 972 | if ((approxFlag == Fsm_Rch_Hd_c) || |
---|
| 973 | (FsmReadReachabilityComputationMode(fsm) == Fsm_Rch_Hd_c) || |
---|
| 974 | guidedSearchMode) { |
---|
| 975 | FsmSetReachabilityComputationMode(fsm, Fsm_Rch_Hd_c); |
---|
| 976 | } |
---|
| 977 | } |
---|
| 978 | } else { |
---|
| 979 | fsm->reachabilityInfo.reachableStates = mdd_dup(reachableStates); |
---|
| 980 | if (!shellFlag) fsm->reachabilityInfo.depth = depth; |
---|
| 981 | else if (Fsm_FsmReadReachabilityOnionRings(fsm)) |
---|
| 982 | fsm->reachabilityInfo.depth = array_n(Fsm_FsmReadReachabilityOnionRings(fsm)); |
---|
| 983 | /* set computation mode as HD if HD or Guided search, basically to indicate not BFS */ |
---|
| 984 | if ((approxFlag == Fsm_Rch_Hd_c) || guidedSearchMode) { |
---|
| 985 | FsmSetReachabilityComputationMode(fsm, Fsm_Rch_Hd_c); |
---|
| 986 | } else { |
---|
| 987 | FsmSetReachabilityComputationMode(fsm, Fsm_Rch_Bfs_c); |
---|
| 988 | } |
---|
| 989 | |
---|
| 990 | } |
---|
| 991 | /* indicate whether reachability analysis is completed or not */ |
---|
| 992 | FsmSetReachabilityApproxComputationStatus(fsm, rchStatus); |
---|
| 993 | |
---|
| 994 | if (incrementalFlag){ |
---|
| 995 | array_free(relationArray); |
---|
| 996 | array_free(arrayOfRoots); |
---|
| 997 | st_free_table(tableOfLeaves); |
---|
| 998 | array_free(smoothVarArray); |
---|
| 999 | /* Need to put in next state function data for the partition */ |
---|
| 1000 | } |
---|
| 1001 | |
---|
| 1002 | return reachableStates; |
---|
| 1003 | } /* end of Fsm_FsmComputeReachableStates */ |
---|
| 1004 | |
---|
| 1005 | |
---|
| 1006 | |
---|
| 1007 | /**Function******************************************************************** |
---|
| 1008 | |
---|
| 1009 | Synopsis [Existentially quantifies variables from an implicit product.] |
---|
| 1010 | |
---|
| 1011 | Description [Existentially quantifies the smoothing variables from the |
---|
| 1012 | product of the MDDs in mddArray, and returns the result. SmoothingVars is an |
---|
| 1013 | array of MDD ids. For now, uses the simplistic approach of conjunction all |
---|
| 1014 | the MDDs, and then quantifying the smoothing variables.] |
---|
| 1015 | |
---|
| 1016 | SideEffects [] |
---|
| 1017 | |
---|
| 1018 | ******************************************************************************/ |
---|
| 1019 | mdd_t * |
---|
| 1020 | Fsm_MddMultiwayAndSmooth(mdd_manager *mddManager, array_t *mddArray, |
---|
| 1021 | array_t *smoothingVars) |
---|
| 1022 | { |
---|
| 1023 | int i; |
---|
| 1024 | mdd_t *resultMdd; |
---|
| 1025 | mdd_t *product = mdd_one(mddManager); |
---|
| 1026 | |
---|
| 1027 | for (i = 0; i<array_n(mddArray); i++){ |
---|
| 1028 | mdd_t *mdd = array_fetch(mdd_t*, mddArray, i); |
---|
| 1029 | mdd_t *tempProduct = mdd_and(product, mdd, 1, 1); |
---|
| 1030 | mdd_free(product); |
---|
| 1031 | product = tempProduct; |
---|
| 1032 | } |
---|
| 1033 | |
---|
| 1034 | if (array_n(smoothingVars) == 0) { |
---|
| 1035 | resultMdd = mdd_dup(product); |
---|
| 1036 | } |
---|
| 1037 | else{ |
---|
| 1038 | resultMdd = mdd_smooth(mddManager, product, smoothingVars); |
---|
| 1039 | } |
---|
| 1040 | |
---|
| 1041 | mdd_free(product); |
---|
| 1042 | return resultMdd; |
---|
| 1043 | } |
---|
| 1044 | |
---|
| 1045 | /**Function******************************************************************** |
---|
| 1046 | |
---|
| 1047 | Synopsis [Prints the results of reachability analysis.] |
---|
| 1048 | |
---|
| 1049 | Description [Prints the results of reachability analysis.] |
---|
| 1050 | |
---|
| 1051 | SideEffects [] |
---|
| 1052 | |
---|
| 1053 | SeeAlso [] |
---|
| 1054 | |
---|
| 1055 | ******************************************************************************/ |
---|
| 1056 | void |
---|
| 1057 | Fsm_FsmReachabilityPrintResults( |
---|
| 1058 | Fsm_Fsm_t *fsm, |
---|
| 1059 | long elapseTime, |
---|
| 1060 | int approxFlag) |
---|
| 1061 | { |
---|
| 1062 | mdd_manager *mddManager = Fsm_FsmReadMddManager(fsm); |
---|
| 1063 | mdd_t *reachableStates = fsm->reachabilityInfo.reachableStates; |
---|
| 1064 | array_t *psVarsArray; |
---|
| 1065 | int nvars; |
---|
| 1066 | |
---|
| 1067 | if (!reachableStates) |
---|
| 1068 | return; |
---|
| 1069 | |
---|
| 1070 | psVarsArray = Fsm_FsmReadPresentStateVars(fsm); |
---|
| 1071 | /* compute number of present state variables */ |
---|
| 1072 | nvars = ComputeNumberOfBinaryStateVariables(mddManager, psVarsArray); |
---|
| 1073 | |
---|
| 1074 | (void) fprintf(vis_stdout,"********************************\n"); |
---|
| 1075 | (void) fprintf(vis_stdout,"Reachability analysis results:\n"); |
---|
| 1076 | if ((FsmReadReachabilityComputationMode(fsm) == Fsm_Rch_Bfs_c) && |
---|
| 1077 | (Fsm_FsmReadReachableStates(fsm) != NIL(mdd_t))) { |
---|
| 1078 | (void) fprintf(vis_stdout, "%-20s%10d\n", "FSM depth =", |
---|
| 1079 | fsm->reachabilityInfo.depth); |
---|
| 1080 | } else { |
---|
| 1081 | (void) fprintf(vis_stdout, "%-20s%10d\n", "computation depth =", |
---|
| 1082 | fsm->reachabilityInfo.depth); |
---|
| 1083 | } |
---|
| 1084 | if (nvars <= 1023) { |
---|
| 1085 | (void) fprintf(vis_stdout, "%-20s%10g\n", "reachable states =", |
---|
| 1086 | mdd_count_onset(mddManager, reachableStates, |
---|
| 1087 | fsm->fsmData.presentStateVars)); |
---|
| 1088 | } else { |
---|
| 1089 | /* |
---|
| 1090 | (void) fprintf(vis_stdout, "%-20s", "reachable states = "); |
---|
| 1091 | bdd_print_apa_minterm(vis_stdout, reachableStates, nvars, (long)6); |
---|
| 1092 | */ |
---|
| 1093 | EpDouble epd; |
---|
| 1094 | char strValue[20]; |
---|
| 1095 | |
---|
| 1096 | mdd_epd_count_onset(mddManager, reachableStates, |
---|
| 1097 | fsm->fsmData.presentStateVars, &epd); |
---|
| 1098 | EpdGetString(&epd, strValue); |
---|
| 1099 | (void) fprintf(vis_stdout, "%-20s%10s\n", "reachable states =", strValue); |
---|
| 1100 | } |
---|
| 1101 | (void) fprintf(vis_stdout, "%-20s%10d\n", "BDD size =", |
---|
| 1102 | mdd_size(reachableStates)); |
---|
| 1103 | (void) fprintf(vis_stdout, "%-20s%10g\n", "analysis time =", |
---|
| 1104 | (double)elapseTime/1000.0); |
---|
| 1105 | if (Fsm_FsmReadReachableStates(fsm) != NIL(mdd_t)) { |
---|
| 1106 | (void) fprintf(vis_stdout, "%-20s%10s\n", "reachability analysis = ", "complete"); |
---|
| 1107 | } else { |
---|
| 1108 | (void) fprintf(vis_stdout, "%-20s%10s\n", "reachability analysis = ", "incomplete"); |
---|
| 1109 | } |
---|
| 1110 | } |
---|
| 1111 | |
---|
| 1112 | |
---|
| 1113 | /*---------------------------------------------------------------------------*/ |
---|
| 1114 | /* Definition of static functions */ |
---|
| 1115 | /*---------------------------------------------------------------------------*/ |
---|
| 1116 | |
---|
| 1117 | /**Function******************************************************************** |
---|
| 1118 | |
---|
| 1119 | Synopsis [Checks the validity of image] |
---|
| 1120 | |
---|
| 1121 | Description [In a properly formed image, there should not be any |
---|
| 1122 | domain or quantify variables in its support. This function checks |
---|
| 1123 | for that fact.] |
---|
| 1124 | |
---|
| 1125 | SideEffects [] |
---|
| 1126 | |
---|
| 1127 | ******************************************************************************/ |
---|
| 1128 | static int |
---|
| 1129 | CheckImageValidity(mdd_manager *mddManager, mdd_t *image, array_t |
---|
| 1130 | *domainVarMddIdArray, array_t *quantifyVarMddIdArray) |
---|
| 1131 | { |
---|
| 1132 | int i; |
---|
| 1133 | array_t *imageSupportArray = mdd_get_support(mddManager, image); |
---|
| 1134 | st_table *imageSupportTable = st_init_table(st_numcmp, st_numhash); |
---|
| 1135 | for (i=0; i<array_n(imageSupportArray); i++){ |
---|
| 1136 | int mddId = array_fetch(int, imageSupportArray, i); |
---|
| 1137 | (void) st_insert(imageSupportTable, (char *) (long) mddId, NIL(char)); |
---|
| 1138 | } |
---|
| 1139 | for (i=0; i<array_n(domainVarMddIdArray); i++){ |
---|
| 1140 | int domainVarId; |
---|
| 1141 | domainVarId = array_fetch(int, domainVarMddIdArray, i); |
---|
| 1142 | assert(st_is_member(imageSupportTable, (char *)(long)domainVarId) == 0); |
---|
| 1143 | } |
---|
| 1144 | for (i=0; i<array_n(quantifyVarMddIdArray); i++){ |
---|
| 1145 | int quantifyVarId; |
---|
| 1146 | quantifyVarId = array_fetch(int, quantifyVarMddIdArray, i); |
---|
| 1147 | assert(st_is_member(imageSupportTable, (char *)(long)quantifyVarId) == 0); |
---|
| 1148 | } |
---|
| 1149 | st_free_table(imageSupportTable); |
---|
| 1150 | array_free(imageSupportArray); |
---|
| 1151 | return 1; |
---|
| 1152 | } |
---|
| 1153 | |
---|
| 1154 | /**Function******************************************************************** |
---|
| 1155 | |
---|
| 1156 | Synopsis [Counts the number of Bdd variables for the given Mdd id array]. |
---|
| 1157 | |
---|
| 1158 | Description [Counts the number of Bdd variables for the given Mdd id array] |
---|
| 1159 | |
---|
| 1160 | |
---|
| 1161 | SideEffects [] |
---|
| 1162 | |
---|
| 1163 | ******************************************************************************/ |
---|
[15] | 1164 | /*static*/ int |
---|
[14] | 1165 | ComputeNumberOfBinaryStateVariables(mdd_manager *mddManager, |
---|
| 1166 | array_t *mddIdArray) |
---|
| 1167 | { |
---|
| 1168 | int mddId, i; |
---|
| 1169 | mvar_type mddVar; |
---|
| 1170 | int numEncodingBits, count = 0; |
---|
| 1171 | array_t *mvar_list = mdd_ret_mvar_list(mddManager); |
---|
| 1172 | |
---|
| 1173 | arrayForEachItem(int, mddIdArray, i, mddId) { |
---|
| 1174 | mddVar = array_fetch(mvar_type, mvar_list, mddId); |
---|
| 1175 | numEncodingBits = mddVar.encode_length; |
---|
| 1176 | count += numEncodingBits; |
---|
| 1177 | } |
---|
| 1178 | return count; |
---|
| 1179 | } /* end of ComputeNumberOfBinaryStateVariables */ |
---|
| 1180 | |
---|
| 1181 | |
---|
| 1182 | /**Function******************************************************************** |
---|
| 1183 | |
---|
| 1184 | Synopsis [Add states.] |
---|
| 1185 | |
---|
| 1186 | Description [Add States.] |
---|
| 1187 | |
---|
| 1188 | SideEffects [ Free the original parts] |
---|
| 1189 | |
---|
| 1190 | ******************************************************************************/ |
---|
| 1191 | static mdd_t * |
---|
| 1192 | AddStates(mdd_t *a, mdd_t *b, int freeA, int freeB) |
---|
| 1193 | { |
---|
| 1194 | mdd_t *result; |
---|
| 1195 | if ((a != NULL) && (b != NULL)) { |
---|
| 1196 | result = mdd_or(a, b, 1, 1); |
---|
| 1197 | } else if ((a == NULL) && (b == NULL)) { |
---|
| 1198 | result = a; |
---|
| 1199 | } else if (a == NULL) { |
---|
| 1200 | result = mdd_dup(b); |
---|
| 1201 | } else { |
---|
| 1202 | result = mdd_dup(a); |
---|
| 1203 | } |
---|
| 1204 | if ((freeA == FSM_MDD_FREE) && (a != NULL)) mdd_free(a); |
---|
| 1205 | if ((freeB == FSM_MDD_FREE) && (b != NULL)) mdd_free(b); |
---|
| 1206 | return result; |
---|
| 1207 | } /* end of AddStates */ |
---|
| 1208 | |
---|
| 1209 | |
---|
| 1210 | /**Function******************************************************************** |
---|
| 1211 | |
---|
| 1212 | Synopsis [Simulates randomly specified number of states.] |
---|
| 1213 | |
---|
| 1214 | Description [Simulates randomly specified number of states.] |
---|
| 1215 | |
---|
| 1216 | SideEffects [] |
---|
| 1217 | |
---|
| 1218 | ******************************************************************************/ |
---|
| 1219 | static void |
---|
| 1220 | RandomSimulation(int simNVec, |
---|
| 1221 | Fsm_Fsm_t *fsm, |
---|
| 1222 | Fsm_RchType_t approxFlag, |
---|
| 1223 | mdd_t *initialStates, |
---|
| 1224 | mdd_t **reachableStates, |
---|
| 1225 | mdd_t **fromLowerBound, |
---|
| 1226 | FsmHdStruct_t *hdInfo) |
---|
| 1227 | { |
---|
| 1228 | Ntk_Network_t *network = fsm->network; |
---|
| 1229 | |
---|
| 1230 | /* Compute specified number of simulated states. */ |
---|
| 1231 | *reachableStates = Sim_RandomSimulate(network, simNVec, 0); |
---|
| 1232 | *reachableStates = AddStates(*reachableStates, initialStates, FSM_MDD_FREE, FSM_MDD_DONT_FREE); |
---|
| 1233 | *fromLowerBound = mdd_dup(*reachableStates); |
---|
| 1234 | |
---|
| 1235 | if (approxFlag == Fsm_Rch_Hd_c) { |
---|
| 1236 | if (mdd_size(*fromLowerBound) > |
---|
| 1237 | Fsm_FsmHdOptionReadFrontierApproxThreshold(hdInfo->options)) { |
---|
| 1238 | /* Reset frontier if too large. */ |
---|
| 1239 | mdd_free(*fromLowerBound); |
---|
| 1240 | *fromLowerBound = bdd_between(initialStates, *reachableStates); |
---|
| 1241 | if (!mdd_equal(*fromLowerBound, *reachableStates)) { |
---|
| 1242 | hdInfo->firstSubset = FALSE; |
---|
| 1243 | hdInfo->deadEndResidue = mdd_and(*reachableStates, |
---|
| 1244 | *fromLowerBound, 1, 0); |
---|
| 1245 | } |
---|
| 1246 | } |
---|
| 1247 | } |
---|
| 1248 | return; |
---|
| 1249 | } /* end of RandomSimulation */ |
---|
| 1250 | |
---|
| 1251 | |
---|
| 1252 | /**Function******************************************************************** |
---|
| 1253 | |
---|
| 1254 | Synopsis [Prints stats per iteration] |
---|
| 1255 | |
---|
| 1256 | Description [Prints stats per iteration] |
---|
| 1257 | |
---|
| 1258 | SideEffects [] |
---|
| 1259 | |
---|
| 1260 | ******************************************************************************/ |
---|
| 1261 | static void |
---|
| 1262 | PrintStatsPerIteration(Fsm_RchType_t approxFlag, |
---|
| 1263 | int nvars, |
---|
| 1264 | int depth, |
---|
| 1265 | FsmHdStruct_t *hdInfo, |
---|
| 1266 | mdd_manager *mddManager, |
---|
| 1267 | mdd_t *reachableStates, |
---|
| 1268 | mdd_t *fromLowerBound, |
---|
| 1269 | array_t *mintermVarArray) |
---|
| 1270 | { |
---|
| 1271 | if (approxFlag != Fsm_Rch_Hd_c) { |
---|
| 1272 | int reachableStateSetSize = mdd_size(reachableStates); |
---|
| 1273 | if (nvars <= 1023) { |
---|
| 1274 | (void)fprintf(vis_stdout, "BFS step = %d\t|states| = %8g\tBdd size = %8ld\n", |
---|
| 1275 | depth, mdd_count_onset(mddManager, reachableStates, |
---|
| 1276 | mintermVarArray), |
---|
| 1277 | (long)reachableStateSetSize); |
---|
| 1278 | /* bdd_print_minterm(reachableStates); */ |
---|
| 1279 | } else { |
---|
| 1280 | (void)fprintf(vis_stdout, "BFS step = %d\tBdd size = %8d\t|states| = ", |
---|
| 1281 | depth, reachableStateSetSize); |
---|
| 1282 | (void) bdd_print_apa_minterm(vis_stdout, reachableStates, nvars, (long)6); |
---|
| 1283 | } |
---|
| 1284 | |
---|
| 1285 | } else { /* HD */ |
---|
| 1286 | |
---|
| 1287 | if (nvars <= 1023) { |
---|
| 1288 | (void)fprintf(vis_stdout, "Step = %d, R = %8g, |R| = %8d, I = %8g, |I| = %8d\n", |
---|
| 1289 | depth, FsmHdStatsReadMintermReached(hdInfo->stats), |
---|
| 1290 | FsmHdStatsReadSizeReached(hdInfo->stats), FsmHdStatsReadMintermTo(hdInfo->stats) , |
---|
| 1291 | FsmHdStatsReadSizeTo(hdInfo->stats)); |
---|
| 1292 | (void)fprintf(vis_stdout, "Completed iteration %d at %g seconds\n", |
---|
| 1293 | depth, (util_cpu_time()/1000.0)); |
---|
| 1294 | |
---|
| 1295 | (void)fprintf(vis_stdout, "Step = %d, F = %8g, |F| = %8d, FA = %8g, |FA| = %8d\n", |
---|
| 1296 | depth+1, FsmHdStatsReadMintermFrom(hdInfo->stats), |
---|
| 1297 | FsmHdStatsReadSizeFrom(hdInfo->stats), |
---|
| 1298 | FsmHdStatsReadMintermFromSubset(hdInfo->stats), |
---|
| 1299 | FsmHdStatsReadSizeFromSubset(hdInfo->stats)); |
---|
| 1300 | } else { |
---|
| 1301 | int status; |
---|
| 1302 | (void)fprintf(vis_stdout, "Step = %d, |R| = %8d, R = ", |
---|
| 1303 | depth, FsmHdStatsReadSizeReached(hdInfo->stats)); |
---|
| 1304 | status = bdd_print_apa_minterm(vis_stdout, reachableStates, nvars, (long)6); |
---|
| 1305 | if (!status) { |
---|
| 1306 | error_append("** rch error: Error in printing arbitrary precision minterm count of Reached"); |
---|
| 1307 | } |
---|
| 1308 | |
---|
| 1309 | (void)fprintf(vis_stdout, "Completed iteration %d at %g seconds\n", |
---|
| 1310 | depth, (util_cpu_time()/1000.0)); |
---|
| 1311 | (void)fprintf(vis_stdout, "Step = %d, |F| = %8d, F = %8g, |FA| = %8d, FA = ", |
---|
| 1312 | depth, FsmHdStatsReadSizeFrom(hdInfo->stats), 0.0, |
---|
| 1313 | FsmHdStatsReadSizeFromSubset(hdInfo->stats) ); |
---|
| 1314 | status = bdd_print_apa_minterm(vis_stdout, fromLowerBound, nvars, 6); |
---|
| 1315 | if (!status) { |
---|
| 1316 | error_append("** rch error: Error in printing arbitrary precision minterm count of From"); |
---|
| 1317 | } |
---|
| 1318 | } |
---|
| 1319 | } |
---|
| 1320 | return; |
---|
| 1321 | } /* end of PrintStatsPerIteration */ |
---|
| 1322 | |
---|
| 1323 | /**Function******************************************************************** |
---|
| 1324 | |
---|
| 1325 | Synopsis [Induce full dead-end if there is a big jump in Reached |
---|
| 1326 | size] |
---|
| 1327 | |
---|
| 1328 | Description [Induce full dead-end if there is a big jump in Reached |
---|
| 1329 | size and not enough increase in minterms of Reached. So throw away |
---|
| 1330 | the new large-sized Reached and compute its entire image. Use the |
---|
| 1331 | dead-end computation for this and use the non-greedy flag. This is a |
---|
| 1332 | recovery mechanism to combat fragmentation of the state space.] |
---|
| 1333 | |
---|
| 1334 | SideEffects [Other quantities are adjusted accordingly. Now the Reached |
---|
| 1335 | set before the dead-end computation will be added to the interior states.] |
---|
| 1336 | |
---|
| 1337 | ******************************************************************************/ |
---|
| 1338 | static void |
---|
| 1339 | HdInduceFullDeadEndIfNecessary(mdd_manager *mddManager, |
---|
| 1340 | Img_ImageInfo_t *imageInfo, |
---|
| 1341 | mdd_t **fromLowerBound, |
---|
| 1342 | mdd_t **fromUpperBound, |
---|
| 1343 | mdd_t **reachableStates, |
---|
| 1344 | mdd_t **image, |
---|
| 1345 | FsmHdStruct_t *hdInfo, |
---|
| 1346 | int *depth, |
---|
| 1347 | int shellFlag, |
---|
| 1348 | array_t *onionRings, |
---|
| 1349 | array_t *mintermVarArray, |
---|
| 1350 | int oldSize, |
---|
| 1351 | double oldMint, |
---|
| 1352 | int verbosityLevel) |
---|
| 1353 | { |
---|
| 1354 | int nvars = Fsm_FsmHdOptionReadNumVars(hdInfo->options); |
---|
| 1355 | /* |
---|
| 1356 | * Compute a full (non-greedy) dead-end when a dead-end computation |
---|
| 1357 | * hasn't occurred, and the jump in minterms is lower than MINT_GROWTH and |
---|
| 1358 | * either the old reached size is between MID_SIZE and LARGE_SIZE and the |
---|
| 1359 | * jump is MID_SIZE or the new size is larger than LARGE_SIZE and the jump |
---|
| 1360 | * is LARGE_SIZE. |
---|
| 1361 | */ |
---|
| 1362 | if ((hdInfo->deadEndComputation == FALSE) && |
---|
| 1363 | ((FsmHdStatsReadMintermReached(hdInfo->stats) - oldMint)/oldMint < FSM_HD_MINT_GROWTH) && |
---|
| 1364 | (((FsmHdStatsReadSizeReached(hdInfo->stats) > FSM_HD_MID_SIZE) && |
---|
| 1365 | (FsmHdStatsReadSizeReached(hdInfo->stats) - oldSize > FSM_HD_MID_SIZE) && |
---|
| 1366 | (oldSize > FSM_HD_MID_SIZE) && (oldSize < FSM_HD_LARGE_SIZE)) || |
---|
| 1367 | ((FsmHdStatsReadSizeReached(hdInfo->stats) > FSM_HD_LARGE_SIZE) && |
---|
| 1368 | (FsmHdStatsReadSizeReached(hdInfo->stats) - oldSize > FSM_HD_LARGE_SIZE)))) { |
---|
| 1369 | if (verbosityLevel >= 2) { |
---|
| 1370 | fprintf(vis_stdout, "Full Dead End: New Reached = %d, Minterms = %g\n", |
---|
| 1371 | FsmHdStatsReadSizeReached(hdInfo->stats), FsmHdStatsReadMintermReached(hdInfo->stats)); |
---|
| 1372 | } |
---|
| 1373 | |
---|
| 1374 | if (*image != NULL) { |
---|
| 1375 | mdd_free(*image); |
---|
| 1376 | *image = NULL; |
---|
| 1377 | } |
---|
| 1378 | /* throw away the reached with the jump in size */ |
---|
| 1379 | mdd_free(*reachableStates); |
---|
| 1380 | if (shellFlag && onionRings) { |
---|
| 1381 | mdd_free(array_fetch(mdd_t *, onionRings, array_n(onionRings)-1)); |
---|
| 1382 | array_insert(mdd_t *, onionRings, array_n(onionRings)-1, NIL(mdd_t)); |
---|
| 1383 | } |
---|
| 1384 | |
---|
| 1385 | *reachableStates = *fromUpperBound; |
---|
| 1386 | /* throw away interior state candidates since we just threw away |
---|
| 1387 | * the new states |
---|
| 1388 | */ |
---|
| 1389 | if (hdInfo->interiorStateCandidate != NIL(mdd_t)) { |
---|
| 1390 | mdd_free(hdInfo->interiorStateCandidate); |
---|
| 1391 | hdInfo->interiorStateCandidate = NIL(mdd_t); |
---|
| 1392 | } |
---|
| 1393 | |
---|
| 1394 | if (verbosityLevel >= 2) { |
---|
| 1395 | /* record number of dead ends */ |
---|
| 1396 | (hdInfo->numDeadEnds)++; |
---|
| 1397 | fprintf(vis_stdout, "Dead-End %d at %g seconds - FULL\n", |
---|
| 1398 | hdInfo->numDeadEnds, (util_cpu_time()/1000.0)); |
---|
| 1399 | } |
---|
| 1400 | |
---|
| 1401 | /* perform a full non-greedy dead-end computation */ |
---|
| 1402 | *fromLowerBound = FsmHdDeadEnd(mddManager, imageInfo, *reachableStates, |
---|
| 1403 | hdInfo, |
---|
| 1404 | mintermVarArray, |
---|
| 1405 | FSM_HD_NONGREEDY, verbosityLevel); |
---|
| 1406 | (*depth)++; |
---|
| 1407 | /* update reached since a new set of seeds have been found */ |
---|
| 1408 | assert (!mdd_is_tautology(*fromLowerBound, 0)); |
---|
| 1409 | if (shellFlag && onionRings) { |
---|
| 1410 | mdd_t *temp = mdd_and(*fromLowerBound, *reachableStates, 1, 0); |
---|
| 1411 | if (!mdd_is_tautology(temp, 0)) |
---|
| 1412 | array_insert(mdd_t *, onionRings, array_n(onionRings)-1, temp); |
---|
| 1413 | else |
---|
| 1414 | mdd_free(temp); |
---|
| 1415 | } |
---|
| 1416 | *fromUpperBound = *reachableStates; |
---|
| 1417 | *reachableStates = mdd_or(*fromLowerBound, *fromUpperBound, 1, 1); |
---|
| 1418 | FsmHdStatsComputeSizeAndMinterms(mddManager, *reachableStates, |
---|
| 1419 | mintermVarArray, nvars, |
---|
| 1420 | Fsm_Hd_Reached, hdInfo->stats); |
---|
| 1421 | } /* end of if jump in Reached */ |
---|
| 1422 | } /* end of HdInduceFullDeadEndIfNecessary */ |
---|
| 1423 | |
---|
| 1424 | |
---|
| 1425 | /**Function******************************************************************** |
---|
| 1426 | |
---|
| 1427 | Synopsis [Compute initial states.] |
---|
| 1428 | |
---|
| 1429 | Description [Compute initial states. Return fsm initial states if no |
---|
| 1430 | previously computed states are found. If shell flag, compute union |
---|
| 1431 | of rings. If not shell flag, return previously computed states.] |
---|
| 1432 | |
---|
| 1433 | SideEffects [] |
---|
| 1434 | |
---|
| 1435 | ******************************************************************************/ |
---|
| 1436 | static mdd_t * |
---|
| 1437 | ComputeInitialStates(Fsm_Fsm_t *fsm, int shellFlag, boolean printWarning) |
---|
| 1438 | { |
---|
| 1439 | mdd_t *initialStates = NIL(mdd_t); |
---|
| 1440 | boolean rings = FALSE; |
---|
| 1441 | array_t *mintermVarArray = Fsm_FsmReadPresentStateVars(fsm); |
---|
| 1442 | |
---|
| 1443 | if (Fsm_FsmReadCurrentReachableStates(fsm) == NIL(mdd_t)) { |
---|
| 1444 | initialStates = Fsm_FsmComputeInitialStates(fsm); |
---|
| 1445 | return (initialStates); |
---|
| 1446 | } else if (shellFlag) { |
---|
| 1447 | (void) Fsm_FsmReachabilityOnionRingsStates(fsm, &initialStates); |
---|
| 1448 | if (initialStates == NIL(mdd_t)) { |
---|
| 1449 | initialStates = Fsm_FsmComputeInitialStates(fsm); |
---|
| 1450 | return (initialStates); |
---|
| 1451 | } else if (mdd_is_tautology(initialStates, 0)) { |
---|
| 1452 | initialStates = Fsm_FsmComputeInitialStates(fsm); |
---|
| 1453 | return (initialStates); |
---|
| 1454 | } |
---|
| 1455 | /* some states are found in the onion rings */ |
---|
| 1456 | rings = TRUE; |
---|
| 1457 | } else { |
---|
| 1458 | /* use previously computed states */ |
---|
| 1459 | initialStates = mdd_dup(Fsm_FsmReadCurrentReachableStates(fsm)); |
---|
| 1460 | } |
---|
| 1461 | if (printWarning) { |
---|
| 1462 | fprintf(vis_stdout, "** rch warning: Starting reachability analysis from previously computed states.\n"); |
---|
| 1463 | fprintf(vis_stdout, "** rch warning: Use compute_reach -F to recompute if necessary.\n"); |
---|
| 1464 | fprintf(vis_stdout, "** rch warning: Previously computed states = %g, Size = %d, computation depth = 0-%d\n", mdd_count_onset(Fsm_FsmReadMddManager(fsm), initialStates, mintermVarArray), mdd_size(initialStates), fsm->reachabilityInfo.depth); |
---|
| 1465 | if (!rings) { |
---|
| 1466 | if (FsmReadReachabilityComputationMode(fsm) == Fsm_Rch_Bfs_c) { |
---|
| 1467 | fprintf(vis_stdout, "** rch warning: Previous computation done with BFS (-A 0 option)\n"); |
---|
| 1468 | } else if (FsmReadReachabilityComputationMode(fsm) == Fsm_Rch_Hd_c) { |
---|
| 1469 | fprintf(vis_stdout, "** rch warning: Some previous computations done using BFS/DFS mode (-A 1 or -g option)\n"); |
---|
| 1470 | } |
---|
| 1471 | } else { |
---|
| 1472 | if (Fsm_FsmReadReachabilityOnionRingsMode(fsm) == Fsm_Rch_Bfs_c) { |
---|
| 1473 | fprintf(vis_stdout, "** rch warning: Previous onion rings computed with BFS (-A 0 option)\n"); |
---|
| 1474 | } else if (Fsm_FsmReadReachabilityOnionRingsMode(fsm) == Fsm_Rch_Hd_c) { |
---|
| 1475 | fprintf(vis_stdout, "** rch warning: Some set of onion rings have been computed using BFS/DFS (-A 1 or -g option)\n"); |
---|
| 1476 | } |
---|
| 1477 | } |
---|
| 1478 | } |
---|
| 1479 | return (initialStates); |
---|
| 1480 | } /* end of ComputeInitialStates */ |
---|
| 1481 | |
---|
| 1482 | |
---|
| 1483 | /**Function******************************************************************** |
---|
| 1484 | |
---|
| 1485 | Synopsis [Checks if the reachable states are contained in each |
---|
| 1486 | element of an array of invariants.] |
---|
| 1487 | |
---|
| 1488 | Description [Checks if the reachable states are contained in each |
---|
| 1489 | element of an array of invariants. Returns 0 as soon as a violation |
---|
| 1490 | is found.] |
---|
| 1491 | |
---|
| 1492 | SideEffects [] |
---|
| 1493 | |
---|
| 1494 | ******************************************************************************/ |
---|
| 1495 | static int |
---|
| 1496 | CheckStatesContainedInInvariant(mdd_t *reachableStates, |
---|
| 1497 | array_t *invarStates) |
---|
| 1498 | { |
---|
| 1499 | int i; |
---|
| 1500 | mdd_t *invariant; |
---|
| 1501 | |
---|
| 1502 | arrayForEachItem(mdd_t *, invarStates, i, invariant) { |
---|
| 1503 | if (invariant == NIL(mdd_t)) continue; |
---|
| 1504 | if (!mdd_lequal(reachableStates, invariant, 1, 1)) { |
---|
| 1505 | return 0; |
---|
| 1506 | } |
---|
| 1507 | } |
---|
| 1508 | return 1; |
---|
| 1509 | } |
---|
| 1510 | |
---|
| 1511 | /**Function******************************************************************** |
---|
| 1512 | |
---|
| 1513 | Synopsis [Computes the reachable states, fromLowerBound and |
---|
| 1514 | fromUpperBound for HD Traversal.] |
---|
| 1515 | |
---|
| 1516 | Description [Computes the reachable states, fromLowerBound and |
---|
| 1517 | fromUpperBound for HD Traversal. Updates all other arguments such as |
---|
| 1518 | interiorStates, deadEndResidue . There are 3 major operations in |
---|
| 1519 | this procedure. 1. Induce (if slow growth in reached) and compute a |
---|
| 1520 | dead-end if necessary. 2. Compute the image of Reached if there is a |
---|
| 1521 | big jump in its size. 3. Compute a dense subset of states to be used |
---|
| 1522 | as a frontier in the next iteration. |
---|
| 1523 | |
---|
| 1524 | 1. A dead-end is the situation where no new states have been |
---|
| 1525 | produced (fromLowerBound = 0), It is induced if the rate of growth |
---|
| 1526 | of Reached is slow. If the image of the Entire Reached set has been |
---|
| 1527 | computed in the previous iteration, then pretend this is a dead-end. |
---|
| 1528 | |
---|
| 1529 | 2. If the jump in Reached is large, compute its entire image to |
---|
| 1530 | recover from fragmentation. |
---|
| 1531 | |
---|
| 1532 | 3. A dense subset of the frontier set is computed to be used as the |
---|
| 1533 | frontier set in the next iteration. The update of reached is |
---|
| 1534 | performed in this step (may not add scrap states if |
---|
| 1535 | specified.). If a dead-end has just been performed, the new states |
---|
| 1536 | are always added to Reached. Growth rate monitors are also |
---|
| 1537 | updated. ] |
---|
| 1538 | |
---|
| 1539 | SideEffects [] |
---|
| 1540 | |
---|
| 1541 | ******************************************************************************/ |
---|
| 1542 | static void |
---|
| 1543 | HdComputeReachabilityParameters(mdd_manager *mddManager, |
---|
| 1544 | Img_ImageInfo_t *imageInfo, |
---|
| 1545 | mdd_t **reachableStates, |
---|
| 1546 | mdd_t **fromUpperBound, |
---|
| 1547 | mdd_t **fromLowerBound, |
---|
| 1548 | mdd_t **image, |
---|
| 1549 | FsmHdStruct_t *hdInfo, |
---|
| 1550 | mdd_t *initialStates, |
---|
| 1551 | array_t *mintermVarArray, |
---|
| 1552 | int *depth, |
---|
| 1553 | int printStep, |
---|
| 1554 | int shellFlag, |
---|
| 1555 | array_t *onionRings, |
---|
| 1556 | int verbosityLevel) |
---|
| 1557 | { |
---|
| 1558 | float growth; |
---|
| 1559 | boolean scrapStates; |
---|
| 1560 | int nvars = Fsm_FsmHdOptionReadNumVars(hdInfo->options); |
---|
| 1561 | int oldSize; |
---|
| 1562 | double oldMint; |
---|
| 1563 | int sizeOfOnionRings = 0; |
---|
| 1564 | if (shellFlag && onionRings) { |
---|
| 1565 | sizeOfOnionRings = array_n(onionRings); |
---|
| 1566 | } |
---|
| 1567 | |
---|
| 1568 | verbosityLevel = (printStep && (((*depth) % printStep) == 0)) ? verbosityLevel : 0; |
---|
| 1569 | |
---|
| 1570 | /* keep image if small, record size of the image */ |
---|
| 1571 | oldSize = FsmHdStatsReadSizeReached(hdInfo->stats); |
---|
| 1572 | oldMint = FsmHdStatsReadMintermReached(hdInfo->stats); |
---|
| 1573 | FsmHdStatsReset(hdInfo->stats, Fsm_Hd_Reached); |
---|
| 1574 | FsmHdStatsReset(hdInfo->stats, Fsm_Hd_FromSubset); |
---|
| 1575 | FsmHdStatsReset(hdInfo->stats, Fsm_Hd_From); |
---|
| 1576 | |
---|
| 1577 | scrapStates = Fsm_FsmHdOptionReadScrapStates(hdInfo->options); |
---|
| 1578 | hdInfo->onlyPartialImage = Fsm_FsmHdOptionReadOnlyPartialImage(hdInfo->options); |
---|
| 1579 | |
---|
| 1580 | /* Step 1: Check comments at the top of this function */ |
---|
| 1581 | /* Check if this is a dead end */ |
---|
| 1582 | /* if growth rate of reached is really small, induce a dead-end */ |
---|
| 1583 | hdInfo->deadEndComputation = FALSE; |
---|
| 1584 | if ((hdInfo->imageOfReachedComputed) || |
---|
| 1585 | (mdd_is_tautology(*fromLowerBound, 0)) || |
---|
| 1586 | (hdInfo->slowGrowth >= 5)) { |
---|
| 1587 | /* |
---|
| 1588 | * if image of reached is computed, add to the dead states. |
---|
| 1589 | * Set dead-end computation flag and add all new states to Reached. |
---|
| 1590 | */ |
---|
| 1591 | |
---|
| 1592 | /* add to interior states */ |
---|
| 1593 | hdInfo->interiorStates = AddStates(hdInfo->interiorStates, |
---|
| 1594 | hdInfo->interiorStateCandidate, |
---|
| 1595 | FSM_MDD_FREE, FSM_MDD_FREE); |
---|
| 1596 | hdInfo->interiorStateCandidate = NIL(mdd_t); |
---|
| 1597 | if ((verbosityLevel >= 2) && (hdInfo->interiorStates != NIL(mdd_t))) { |
---|
| 1598 | fprintf(vis_stdout, "Interior states added, Size = %d, Minterms = %g\n", |
---|
| 1599 | mdd_size(hdInfo->interiorStates), mdd_count_onset(mddManager, |
---|
| 1600 | hdInfo->interiorStates, mintermVarArray)); |
---|
| 1601 | } |
---|
| 1602 | |
---|
| 1603 | hdInfo->deadEndComputation = TRUE; |
---|
| 1604 | hdInfo->firstSubset = FALSE; |
---|
| 1605 | hdInfo->slowGrowth = 0; |
---|
| 1606 | hdInfo->lastIter = *depth; |
---|
| 1607 | |
---|
| 1608 | if (!hdInfo->imageOfReachedComputed) { |
---|
| 1609 | /* Either slow growth or real dead-end */ |
---|
| 1610 | if (verbosityLevel >= 2) { |
---|
| 1611 | if (!mdd_is_tautology(*fromLowerBound, 0)) |
---|
| 1612 | fprintf(vis_stdout, "Dead-End triggered by slow growth\n"); |
---|
| 1613 | /* record number of dead ends */ |
---|
| 1614 | (hdInfo->numDeadEnds)++; |
---|
| 1615 | fprintf(vis_stdout, "Dead-End %d at %g seconds\n", hdInfo->numDeadEnds, |
---|
| 1616 | (util_cpu_time()/1000.0)); |
---|
| 1617 | } |
---|
| 1618 | |
---|
| 1619 | /* add another onion ring. */ |
---|
| 1620 | if (shellFlag && onionRings && !mdd_is_tautology(*fromLowerBound, 0)) { |
---|
| 1621 | mdd_t *temp = mdd_and(*fromLowerBound, *reachableStates, 1, 0); |
---|
| 1622 | if (!mdd_is_tautology(temp, 0)) |
---|
| 1623 | array_insert_last(mdd_t *, onionRings, temp); |
---|
| 1624 | else |
---|
| 1625 | mdd_free(temp); |
---|
| 1626 | } |
---|
| 1627 | *reachableStates = AddStates(*fromLowerBound, *reachableStates, |
---|
| 1628 | FSM_MDD_FREE, FSM_MDD_FREE); |
---|
| 1629 | *fromUpperBound = *reachableStates; |
---|
| 1630 | |
---|
| 1631 | /* perform a dead-end computation */ |
---|
| 1632 | *fromLowerBound = FsmHdDeadEnd(mddManager, imageInfo, *reachableStates, |
---|
| 1633 | hdInfo, |
---|
| 1634 | mintermVarArray, |
---|
| 1635 | FSM_HD_GREEDY, verbosityLevel); |
---|
| 1636 | |
---|
| 1637 | (*depth)++; |
---|
| 1638 | } |
---|
| 1639 | } /* end of if dead-end computation */ |
---|
| 1640 | |
---|
| 1641 | /* Step 2: Check comments at the top of this function */ |
---|
| 1642 | if (!mdd_is_tautology(*fromLowerBound, 0)) { |
---|
| 1643 | /* add another onion ring. */ |
---|
| 1644 | if (shellFlag && onionRings) { |
---|
| 1645 | mdd_t *temp = mdd_and(*fromLowerBound, *reachableStates, 1, 0); |
---|
| 1646 | if (!mdd_is_tautology(temp, 0)) |
---|
| 1647 | array_insert_last(mdd_t *, onionRings, temp); |
---|
| 1648 | else |
---|
| 1649 | mdd_free(temp); |
---|
| 1650 | } |
---|
| 1651 | /* compute reachable states with new states */ |
---|
| 1652 | *fromUpperBound = *reachableStates; |
---|
| 1653 | *reachableStates = mdd_or(*fromLowerBound, *fromUpperBound, 1, 1); |
---|
| 1654 | FsmHdStatsComputeSizeAndMinterms(mddManager, *reachableStates, |
---|
| 1655 | mintermVarArray, nvars, |
---|
| 1656 | Fsm_Hd_Reached, hdInfo->stats); |
---|
| 1657 | |
---|
| 1658 | |
---|
| 1659 | /* |
---|
| 1660 | * induce a full dead-end computation if jump in size of Reached is |
---|
| 1661 | * large. But when the image of Reached has been computed or a dead-end |
---|
| 1662 | * computation was just done, this is not done because deadEndComputation |
---|
| 1663 | * has been set to 1. |
---|
| 1664 | */ |
---|
| 1665 | HdInduceFullDeadEndIfNecessary(mddManager, imageInfo, fromLowerBound, |
---|
| 1666 | fromUpperBound, reachableStates, image, |
---|
| 1667 | hdInfo, depth, shellFlag, onionRings, |
---|
| 1668 | mintermVarArray, oldSize, |
---|
| 1669 | oldMint, verbosityLevel); |
---|
| 1670 | } /* end of if (!mdd_is_tautology(fromLowerBound, 0)) */ |
---|
| 1671 | |
---|
| 1672 | /* Step 3: Check comments at the top of this function */ |
---|
| 1673 | /* Create subset if necessary */ |
---|
| 1674 | if (!mdd_is_tautology(*fromLowerBound, 0)) { |
---|
| 1675 | if (!hdInfo->onlyPartialImage) { |
---|
| 1676 | mdd_t *newStates; |
---|
| 1677 | /* |
---|
| 1678 | * Now fromUpperBound has the old reached states, reachableStates |
---|
| 1679 | * has the new set of states. |
---|
| 1680 | */ |
---|
| 1681 | newStates = mdd_dup(*fromLowerBound); |
---|
| 1682 | FsmHdFromComputeDenseSubset(mddManager, fromLowerBound, |
---|
| 1683 | fromUpperBound, reachableStates, |
---|
| 1684 | image, initialStates, hdInfo, |
---|
| 1685 | shellFlag, onionRings, sizeOfOnionRings, |
---|
| 1686 | mintermVarArray); |
---|
| 1687 | |
---|
| 1688 | /* if all new states are chosen from the previous iteration and |
---|
| 1689 | * all these states have been added then add to interior states. |
---|
| 1690 | * All new states are sometimes not added when |
---|
| 1691 | * hdInfo->options->scrapStates is 0. Dead-end computations need not be |
---|
| 1692 | * considered here since the interior states were already added then. |
---|
| 1693 | */ |
---|
| 1694 | if ((hdInfo->interiorStateCandidate != NIL(mdd_t)) && |
---|
| 1695 | ((mdd_lequal(newStates, *fromLowerBound, 1, 1)) || |
---|
| 1696 | (scrapStates == TRUE))) { |
---|
| 1697 | hdInfo->interiorStates = AddStates(hdInfo->interiorStates, hdInfo->interiorStateCandidate, |
---|
| 1698 | FSM_MDD_FREE, FSM_MDD_FREE); |
---|
| 1699 | hdInfo->interiorStateCandidate = NIL(mdd_t); |
---|
| 1700 | if (verbosityLevel >= 2) { |
---|
| 1701 | fprintf(vis_stdout, |
---|
| 1702 | "Interior states added, Size = %d, Minterms = %g\n", |
---|
| 1703 | mdd_size(hdInfo->interiorStates), |
---|
| 1704 | mdd_count_onset(mddManager, hdInfo->interiorStates, |
---|
| 1705 | mintermVarArray)); |
---|
| 1706 | } |
---|
| 1707 | } |
---|
| 1708 | mdd_free(newStates); |
---|
| 1709 | |
---|
| 1710 | /* end of if fromLowerbound == 0 && subset Flag*/ |
---|
| 1711 | } else { |
---|
| 1712 | mdd_free(*fromUpperBound); |
---|
| 1713 | if (printStep && ((*depth) % printStep == 0)) { |
---|
| 1714 | FsmHdStatsComputeSizeAndMinterms(mddManager, *fromLowerBound, |
---|
| 1715 | mintermVarArray, nvars, Fsm_Hd_From, hdInfo->stats); |
---|
| 1716 | FsmHdStatsSetMintermFromSubset(hdInfo->stats, 0.0); |
---|
| 1717 | FsmHdStatsSetSizeFromSubset(hdInfo->stats, 0); |
---|
| 1718 | } |
---|
| 1719 | *fromUpperBound = *reachableStates; |
---|
| 1720 | } |
---|
| 1721 | } /* end of if fromLowerBound == 0 */ |
---|
| 1722 | if (hdInfo->interiorStateCandidate != NIL(mdd_t)) { |
---|
| 1723 | mdd_free(hdInfo->interiorStateCandidate); |
---|
| 1724 | hdInfo->interiorStateCandidate = NIL(mdd_t); |
---|
| 1725 | } |
---|
| 1726 | |
---|
| 1727 | /* monitor growth rate of reached, record if slow growth in consecutive |
---|
| 1728 | * iterations |
---|
| 1729 | */ |
---|
| 1730 | if (!mdd_is_tautology(*fromLowerBound, 0)) { |
---|
| 1731 | FsmHdStatsComputeSizeAndMinterms(mddManager, *reachableStates, |
---|
| 1732 | mintermVarArray, nvars, Fsm_Hd_Reached, hdInfo->stats); |
---|
| 1733 | growth = (float)(FsmHdStatsReadMintermReached(hdInfo->stats) - oldMint)/ |
---|
| 1734 | (float)oldMint; |
---|
| 1735 | if ((growth < FSM_HD_GROWTH_RATE) && |
---|
| 1736 | (((hdInfo->slowGrowth) && ((*depth) == (hdInfo->lastIter) + 1)) || (!(hdInfo->slowGrowth)))) { |
---|
| 1737 | if (verbosityLevel >= 2) { |
---|
| 1738 | fprintf(vis_stdout, "Growth rate = %f\n", growth); |
---|
| 1739 | } |
---|
| 1740 | (hdInfo->slowGrowth)++; |
---|
| 1741 | hdInfo->lastIter = *depth; |
---|
| 1742 | } else { |
---|
| 1743 | /* reset value */ |
---|
| 1744 | hdInfo->slowGrowth = 0; |
---|
| 1745 | } |
---|
| 1746 | } |
---|
| 1747 | return; |
---|
| 1748 | } /* end of HdComputeReachabilityParameters */ |
---|
| 1749 | |
---|
| 1750 | /**Function******************************************************************** |
---|
| 1751 | |
---|
| 1752 | Synopsis [Initializes parameters for incremental computation.] |
---|
| 1753 | |
---|
| 1754 | Description [Initializes parameters for incremental computation. |
---|
| 1755 | Instantiates arrayOfRoots and tableOfLeafs, and returns the number of latches |
---|
| 1756 | in the sytstem. Upon return, arrayOfRoots is an array of Ntk_Node_t *, and |
---|
| 1757 | tableOfLeaves is an st_table of Ntk_Node_t *.] |
---|
| 1758 | |
---|
| 1759 | SideEffects [] |
---|
| 1760 | |
---|
| 1761 | ******************************************************************************/ |
---|
| 1762 | static int |
---|
| 1763 | InitializeIncrementalParameters( |
---|
| 1764 | Fsm_Fsm_t *fsm, |
---|
| 1765 | Ntk_Network_t *network, |
---|
| 1766 | array_t **arrayOfRoots, |
---|
| 1767 | st_table **tableOfLeaves) |
---|
| 1768 | { |
---|
| 1769 | int numLatch; |
---|
| 1770 | Ntk_Node_t *node; |
---|
| 1771 | lsGen gen; |
---|
| 1772 | int i, mddId; /* iterate over the nextStateVars of the fsm */ |
---|
| 1773 | |
---|
| 1774 | numLatch = Ntk_NetworkReadNumLatches(network); |
---|
| 1775 | |
---|
| 1776 | /* This changed to fix a bug. Instead of reading the roots using |
---|
| 1777 | Ntk_NetworkForEachCombOutput, we now get them from |
---|
| 1778 | fsm->fsdData.nextStateVars, which means that the order is consistent with |
---|
| 1779 | the latter field, as required later on in the incremental reachability |
---|
| 1780 | code |
---|
| 1781 | |
---|
| 1782 | old code: |
---|
| 1783 | *arrayOfRoots = array_alloc(Ntk_Node_t *, numLatch); |
---|
| 1784 | Ntk_NetworkForEachCombOutput(network, gen, node) { |
---|
| 1785 | if(Ntk_NodeTestIsLatchDataInput(node)){ |
---|
| 1786 | array_insert_last(Ntk_Node_t *, *arrayOfRoots, node); |
---|
| 1787 | } |
---|
| 1788 | } |
---|
| 1789 | */ |
---|
| 1790 | |
---|
| 1791 | assert(numLatch == array_n(fsm->fsmData.nextStateVars)); |
---|
| 1792 | *arrayOfRoots = array_alloc(Ntk_Node_t *, numLatch); |
---|
| 1793 | |
---|
| 1794 | arrayForEachItem(int, fsm->fsmData.nextStateVars, i, mddId){ |
---|
| 1795 | Ntk_Node_t *shadow; |
---|
| 1796 | Ntk_Node_t *latch; |
---|
| 1797 | Ntk_Node_t *dataInput; |
---|
| 1798 | |
---|
| 1799 | shadow = Ntk_NetworkFindNodeByMddId(network, mddId); |
---|
| 1800 | assert(Ntk_NodeTestIsShadow(shadow)); |
---|
| 1801 | latch = Ntk_ShadowReadOrigin(shadow); |
---|
| 1802 | assert(Ntk_NodeTestIsLatch(latch)); |
---|
| 1803 | dataInput = Ntk_LatchReadDataInput(latch); |
---|
| 1804 | assert(dataInput != NIL(Ntk_Node_t)); |
---|
| 1805 | |
---|
| 1806 | array_insert(Ntk_Node_t *, *arrayOfRoots, i, dataInput); |
---|
| 1807 | } |
---|
| 1808 | |
---|
| 1809 | *tableOfLeaves = st_init_table(st_ptrcmp, st_ptrhash); |
---|
| 1810 | Ntk_NetworkForEachCombInput(network, gen, node) { |
---|
| 1811 | st_insert(*tableOfLeaves, (char *)node, (char *) (long) (-1) ); |
---|
| 1812 | } |
---|
| 1813 | return (numLatch); |
---|
| 1814 | } |
---|
| 1815 | |
---|
| 1816 | |
---|
| 1817 | /**Function******************************************************************** |
---|
| 1818 | |
---|
| 1819 | Synopsis [Computes image for incremental computation.] |
---|
| 1820 | |
---|
| 1821 | Description [Computes image for incremental computation.] |
---|
| 1822 | |
---|
| 1823 | SideEffects [] |
---|
| 1824 | |
---|
| 1825 | ******************************************************************************/ |
---|
| 1826 | static mdd_t * |
---|
| 1827 | IncrementalImageCompute(Ntk_Network_t *network, |
---|
| 1828 | Fsm_Fsm_t *fsm, |
---|
| 1829 | mdd_manager *mddManager, |
---|
| 1830 | mdd_t *fromLowerBound, |
---|
| 1831 | mdd_t *fromUpperBound, |
---|
| 1832 | mdd_t *toCareSet, |
---|
| 1833 | array_t *arrayOfRoots, |
---|
| 1834 | st_table *tableOfLeaves, |
---|
| 1835 | array_t *smoothVarArray, |
---|
| 1836 | array_t *relationArray, |
---|
| 1837 | int numLatch) |
---|
| 1838 | { |
---|
| 1839 | Mvf_Function_t *function; |
---|
| 1840 | mdd_t *relation, *optimizedRelation, *toCareSetRV, *imageRV; |
---|
| 1841 | mdd_t *subOptimizedRelation, *image; |
---|
| 1842 | int mddId, i; |
---|
| 1843 | array_t *arrayOfMvf; |
---|
| 1844 | mdd_t *frontierSet; |
---|
| 1845 | |
---|
| 1846 | frontierSet = bdd_between(fromLowerBound, fromUpperBound); |
---|
| 1847 | /* Create the array of transition relations */ |
---|
| 1848 | toCareSetRV = mdd_substitute(mddManager, toCareSet, |
---|
| 1849 | fsm->fsmData.presentStateVars, |
---|
| 1850 | fsm->fsmData.nextStateVars); |
---|
| 1851 | |
---|
| 1852 | arrayOfMvf = Ntm_NetworkBuildMvfs(network, arrayOfRoots, |
---|
| 1853 | tableOfLeaves, frontierSet); |
---|
| 1854 | for (i=0; i < numLatch; i++){ |
---|
| 1855 | function = array_fetch(Mvf_Function_t *, arrayOfMvf, i); |
---|
| 1856 | mddId = array_fetch(int, fsm->fsmData.nextStateVars, i); |
---|
| 1857 | /* Since both arrayOfMvf and fsmData have been obtained from */ |
---|
| 1858 | /* the same generator */ |
---|
| 1859 | relation = Mvf_FunctionBuildRelationWithVariable(function, |
---|
| 1860 | mddId); |
---|
| 1861 | subOptimizedRelation = bdd_cofactor(relation, toCareSetRV); |
---|
| 1862 | mdd_free(relation); |
---|
| 1863 | optimizedRelation = bdd_cofactor(subOptimizedRelation, frontierSet); |
---|
| 1864 | mdd_free(subOptimizedRelation); |
---|
| 1865 | array_insert(mdd_t *, relationArray, i, optimizedRelation); |
---|
| 1866 | } |
---|
| 1867 | Mvf_FunctionArrayFree(arrayOfMvf); |
---|
| 1868 | mdd_free(toCareSetRV); |
---|
| 1869 | array_insert(mdd_t *, relationArray, numLatch, frontierSet); |
---|
| 1870 | imageRV = Fsm_MddMultiwayAndSmooth(mddManager, relationArray, |
---|
| 1871 | smoothVarArray); |
---|
| 1872 | /* |
---|
| 1873 | ** The above call can be substituted by more sophisticated |
---|
| 1874 | ** Img_MultiwayLinearAndSmooth. However, that will have its |
---|
| 1875 | ** associated overhead, and could offset any advantage. We |
---|
| 1876 | ** expect that individual transition relation relations should |
---|
| 1877 | ** be small and monolithic way to handle them would be ok. |
---|
| 1878 | ** However, a good strategy would be find the quantification |
---|
| 1879 | ** schedule which does not change with the computation of |
---|
| 1880 | ** incremental transition relations. |
---|
| 1881 | */ |
---|
| 1882 | for (i = 0; i <= numLatch; i++){ |
---|
| 1883 | mdd_free(array_fetch(mdd_t*, relationArray, i)); |
---|
| 1884 | } |
---|
| 1885 | assert(CheckImageValidity(mddManager, imageRV, |
---|
| 1886 | fsm->fsmData.presentStateVars, |
---|
| 1887 | fsm->fsmData.inputVars)); |
---|
| 1888 | image = mdd_substitute(mddManager, imageRV, |
---|
| 1889 | fsm->fsmData.nextStateVars, |
---|
| 1890 | fsm->fsmData.presentStateVars); |
---|
| 1891 | mdd_free(imageRV); |
---|
| 1892 | assert(CheckImageValidity(mddManager, image, |
---|
| 1893 | fsm->fsmData.nextStateVars, |
---|
| 1894 | fsm->fsmData.inputVars)); |
---|
| 1895 | return image; |
---|
| 1896 | } |
---|
| 1897 | |
---|
| 1898 | /**Function******************************************************************** |
---|
| 1899 | |
---|
| 1900 | Synopsis [Prints information about onion rings] |
---|
| 1901 | |
---|
| 1902 | Description [Prints information about onion rings.] |
---|
| 1903 | |
---|
| 1904 | SideEffects [] |
---|
| 1905 | |
---|
| 1906 | ******************************************************************************/ |
---|
| 1907 | static void |
---|
| 1908 | PrintOnionRings(Fsm_Fsm_t *fsm, int printStep, |
---|
| 1909 | Fsm_RchType_t approxFlag, int nvars) |
---|
| 1910 | { |
---|
| 1911 | int i; |
---|
| 1912 | mdd_t *reachableStates; |
---|
| 1913 | mdd_manager *mddManager = Fsm_FsmReadMddManager(fsm); |
---|
| 1914 | array_t *mintermVarArray = Fsm_FsmReadPresentStateVars(fsm); |
---|
| 1915 | |
---|
| 1916 | fprintf(vis_stdout, "** rch warning: Not possible to compute size of reachable states at every iteration\n"); |
---|
| 1917 | if (Fsm_FsmReadReachabilityOnionRings(fsm) != NIL(array_t)) { |
---|
| 1918 | arrayForEachItem(mdd_t *, Fsm_FsmReadReachabilityOnionRings(fsm), |
---|
| 1919 | i, reachableStates) { |
---|
| 1920 | if (printStep && (i % printStep == 0)) { |
---|
| 1921 | if (approxFlag != Fsm_Rch_Hd_c) { |
---|
| 1922 | if (nvars <= 1023) { |
---|
| 1923 | (void)fprintf(vis_stdout, "BFS step = %d\t|onion ring states| = %8g", |
---|
| 1924 | i, mdd_count_onset(mddManager, reachableStates, |
---|
| 1925 | mintermVarArray)); |
---|
| 1926 | if (i != array_n(Fsm_FsmReadReachabilityOnionRings(fsm))-1) { |
---|
| 1927 | fprintf(vis_stdout, "\n"); |
---|
| 1928 | } else { |
---|
| 1929 | fprintf(vis_stdout, "\tSize = %d\n", mdd_size(reachableStates)); |
---|
| 1930 | } |
---|
| 1931 | |
---|
| 1932 | } else { |
---|
| 1933 | (void)fprintf(vis_stdout, "BFS step = %d\t|onion ring states| = ", |
---|
| 1934 | i); |
---|
| 1935 | (void) bdd_print_apa_minterm(vis_stdout, reachableStates, nvars, (long)6); |
---|
| 1936 | if (i != array_n(Fsm_FsmReadReachabilityOnionRings(fsm))-1) { |
---|
| 1937 | fprintf(vis_stdout, "Final Size = %d\n", mdd_size(reachableStates)); |
---|
| 1938 | } |
---|
| 1939 | } |
---|
| 1940 | } else { |
---|
| 1941 | |
---|
| 1942 | if (nvars <= 1023) { |
---|
| 1943 | (void)fprintf(vis_stdout, "Step = %d\t|onion ring states| = %8g", |
---|
| 1944 | i, mdd_count_onset(mddManager, reachableStates, |
---|
| 1945 | mintermVarArray)); |
---|
| 1946 | if (i != array_n(Fsm_FsmReadReachabilityOnionRings(fsm))-1) { |
---|
| 1947 | fprintf(vis_stdout, "\n"); |
---|
| 1948 | } else { |
---|
| 1949 | fprintf(vis_stdout, "\tSize = %d\n", mdd_size(reachableStates)); |
---|
| 1950 | } |
---|
| 1951 | } else { |
---|
| 1952 | (void)fprintf(vis_stdout, "Step = %d\t|onion ring states| = ", |
---|
| 1953 | i); |
---|
| 1954 | (void) bdd_print_apa_minterm(vis_stdout, reachableStates, nvars, (long)6); |
---|
| 1955 | if (i != array_n(Fsm_FsmReadReachabilityOnionRings(fsm))-1) { |
---|
| 1956 | fprintf(vis_stdout, "Final Size = %d\n", mdd_size(reachableStates)); |
---|
| 1957 | } |
---|
| 1958 | } |
---|
| 1959 | } |
---|
| 1960 | } |
---|
| 1961 | } |
---|
| 1962 | } |
---|
| 1963 | return; |
---|
| 1964 | }/* printonionrings */ |
---|
| 1965 | |
---|
| 1966 | /**Function******************************************************************** |
---|
| 1967 | |
---|
| 1968 | Synopsis [Reads in a sequence of integers separated by commas and |
---|
| 1969 | stores them in an array.] |
---|
| 1970 | |
---|
| 1971 | Description [Reads in a sequence of integers separated by commas from the |
---|
| 1972 | environment variable guided_search_sequence. It stores them in an array that |
---|
| 1973 | it returns. Alpha characters and 0 integers are replaced by |
---|
| 1974 | -1. Pads the remaining entries corresponding to the guide array with -1. |
---|
| 1975 | Every number indicates the number of times the corresponding (in sequence) |
---|
| 1976 | hint should be used. The value -1 means `to convergence'.] |
---|
| 1977 | |
---|
| 1978 | |
---|
| 1979 | SideEffects [] |
---|
| 1980 | |
---|
| 1981 | ******************************************************************************/ |
---|
| 1982 | static array_t * |
---|
| 1983 | GenerateGuidedSearchSequenceArray(array_t *guideArray) |
---|
| 1984 | { |
---|
| 1985 | char *seqStr = Cmd_FlagReadByName("guided_search_sequence"); |
---|
| 1986 | char *preStr; |
---|
| 1987 | int intEntry; |
---|
| 1988 | array_t *depthArray = array_alloc(int, 0); |
---|
| 1989 | int i; |
---|
| 1990 | |
---|
| 1991 | /* Skip parsing if we have no guided search sequence */ |
---|
| 1992 | if (seqStr != NIL(char) && strcmp(seqStr, "") != 0){ |
---|
| 1993 | preStr = strtok(seqStr, ","); |
---|
| 1994 | |
---|
| 1995 | while(preStr != NIL(char)){ |
---|
| 1996 | intEntry = strtol(preStr, (char **) NULL, 10); |
---|
| 1997 | array_insert_last(int, depthArray, (intEntry == 0 ? -1 : intEntry)); |
---|
| 1998 | preStr = strtok(NIL(char), ","); |
---|
| 1999 | } |
---|
| 2000 | } |
---|
| 2001 | |
---|
| 2002 | if(array_n(depthArray) > array_n(guideArray)){ |
---|
| 2003 | fprintf(vis_stdout, "** rch warning: guided_search_sequence has more entries\n"); |
---|
| 2004 | fprintf(vis_stdout,"than there are hints. Extra entires will be ignored\n"); |
---|
| 2005 | } |
---|
| 2006 | |
---|
| 2007 | /* pad with -1s */ |
---|
| 2008 | for (i = array_n(depthArray); i < array_n(guideArray); i++) { |
---|
| 2009 | array_insert_last(int, depthArray, -1); |
---|
| 2010 | } |
---|
| 2011 | |
---|
| 2012 | assert(array_n(depthArray) >= array_n(guideArray)); |
---|
| 2013 | |
---|
| 2014 | return depthArray; |
---|
| 2015 | } |
---|
| 2016 | |
---|
| 2017 | |
---|
| 2018 | /**Function******************************************************************** |
---|
| 2019 | |
---|
| 2020 | Synopsis [Computes the reachable states, frontier and fromUpperBound.] |
---|
| 2021 | |
---|
| 2022 | Description [Computes the reachable states, frontier and |
---|
| 2023 | fromUpperBound. For HD it also generates interior states, interior |
---|
| 2024 | state candidates, dead-end residue, number of dead-ends, residue |
---|
| 2025 | count, etc. For guided search, this procedure also generates a |
---|
| 2026 | dead-end if the frontier is 0. Also this procedure keeps track of |
---|
| 2027 | convergence and whether a dead-end is required at the end.] |
---|
| 2028 | |
---|
| 2029 | SideEffects [All arguments are updated.] |
---|
| 2030 | |
---|
| 2031 | SeeAlso [HdComputeReachabilityParameters FsmHdDeadEnd] |
---|
| 2032 | |
---|
| 2033 | ******************************************************************************/ |
---|
| 2034 | static void |
---|
| 2035 | ComputeReachabilityParameters(mdd_manager *mddManager, |
---|
| 2036 | Img_ImageInfo_t *imageInfo, |
---|
| 2037 | Fsm_RchType_t approxFlag, |
---|
| 2038 | mdd_t **reachableStates, |
---|
| 2039 | mdd_t **fromUpperBound, |
---|
| 2040 | mdd_t **fromLowerBound, |
---|
| 2041 | mdd_t **image, |
---|
| 2042 | FsmHdStruct_t *hdInfo, |
---|
| 2043 | mdd_t *initialStates, |
---|
| 2044 | array_t *mintermVarArray, |
---|
| 2045 | int *depth, |
---|
| 2046 | int printStep, |
---|
| 2047 | int shellFlag, |
---|
| 2048 | array_t *onionRings, |
---|
| 2049 | int verbosityLevel, |
---|
| 2050 | boolean guidedSearchMode, |
---|
| 2051 | mdd_t *hint, |
---|
| 2052 | int *hintDepth, |
---|
| 2053 | boolean *notConverged) |
---|
| 2054 | { |
---|
| 2055 | if (approxFlag == Fsm_Rch_Bfs_c) { |
---|
| 2056 | /* New set of reachable states is old set plus new states in image. */ |
---|
| 2057 | *reachableStates = AddStates(*fromLowerBound, *reachableStates, |
---|
| 2058 | FSM_MDD_DONT_FREE, FSM_MDD_FREE); |
---|
| 2059 | *fromUpperBound = *reachableStates; |
---|
| 2060 | |
---|
| 2061 | /* in guided search, if the mode is to convergence or the |
---|
| 2062 | limited depth has not been reached, and the frontier is empty, |
---|
| 2063 | then generate a frontier in BFS mode (that is a full dead-end). */ |
---|
| 2064 | if (guidedSearchMode && |
---|
| 2065 | mdd_is_tautology(*fromLowerBound, 0) /* no frontier */ && |
---|
| 2066 | (hdInfo->deadEndWithOriginalTR == FALSE) /* and guided search */ ) { |
---|
| 2067 | assert(imageInfo != NIL(Img_ImageInfo_t)); |
---|
| 2068 | if (*hintDepth != 0) { |
---|
| 2069 | /* add another onion ring. */ |
---|
| 2070 | if (shellFlag && onionRings) { |
---|
| 2071 | mdd_t *temp = mdd_and(*fromLowerBound, *reachableStates, 1, 0); |
---|
| 2072 | if (!mdd_is_tautology(temp, 0)) |
---|
| 2073 | array_insert_last(mdd_t *, onionRings, temp); |
---|
| 2074 | else |
---|
| 2075 | mdd_free(temp); |
---|
| 2076 | } |
---|
| 2077 | /* do a full dead-end (non-greedy), compute all the frontier states */ |
---|
| 2078 | mdd_free(*fromLowerBound); |
---|
| 2079 | *fromLowerBound = FsmHdDeadEnd(mddManager, imageInfo, *reachableStates, |
---|
| 2080 | hdInfo, |
---|
| 2081 | mintermVarArray, |
---|
| 2082 | FSM_HD_NONGREEDY, verbosityLevel); |
---|
| 2083 | mdd_free(hdInfo->interiorStates); |
---|
| 2084 | hdInfo->interiorStates = NIL(mdd_t); |
---|
| 2085 | *reachableStates = AddStates(*fromLowerBound, *reachableStates, |
---|
| 2086 | FSM_MDD_DONT_FREE, FSM_MDD_FREE); |
---|
| 2087 | *fromUpperBound = *reachableStates; |
---|
| 2088 | (*hintDepth)--; |
---|
| 2089 | (*depth)++; |
---|
| 2090 | if (mdd_is_tautology(hint, 1)) hdInfo->deadEndWithOriginalTR = TRUE; |
---|
| 2091 | } else { |
---|
| 2092 | *notConverged = TRUE; |
---|
| 2093 | /* set this flag for correct detection of convergence |
---|
| 2094 | Corner case: when limited depth and frontier = 0 */ |
---|
| 2095 | } |
---|
| 2096 | } |
---|
| 2097 | } else if (approxFlag == Fsm_Rch_Hd_c) { |
---|
| 2098 | assert(imageInfo != NIL(Img_ImageInfo_t)); |
---|
| 2099 | if (!guidedSearchMode || (*hintDepth != 0)) { |
---|
| 2100 | /* computes reachable states, fromLowerBound and fromUpperBound. |
---|
| 2101 | * Updates all other quantities such as interiorStates, |
---|
| 2102 | * deadEndResidue. */ |
---|
| 2103 | HdComputeReachabilityParameters(mddManager, imageInfo, |
---|
| 2104 | reachableStates, |
---|
| 2105 | fromUpperBound, |
---|
| 2106 | fromLowerBound, |
---|
| 2107 | image, |
---|
| 2108 | hdInfo, |
---|
| 2109 | initialStates, |
---|
| 2110 | mintermVarArray, |
---|
| 2111 | depth, printStep, |
---|
| 2112 | shellFlag, onionRings, |
---|
| 2113 | verbosityLevel); |
---|
| 2114 | if (guidedSearchMode) (*hintDepth)--; |
---|
| 2115 | |
---|
| 2116 | } else { /* guidedSearchMode and hint depth is 0 */ |
---|
| 2117 | if (mdd_is_tautology(*fromLowerBound, 0)) { |
---|
| 2118 | *notConverged = TRUE; |
---|
| 2119 | /* set this flag for correct detection of convergence |
---|
| 2120 | Corner case: when limited depth and frontier = 0 */ |
---|
| 2121 | } |
---|
| 2122 | /* add another onion ring. */ |
---|
| 2123 | if (shellFlag && onionRings) { |
---|
| 2124 | mdd_t *temp = mdd_and(*fromLowerBound, *reachableStates, 1, 0); |
---|
| 2125 | if (!mdd_is_tautology(temp, 0)) |
---|
| 2126 | array_insert_last(mdd_t *, onionRings, temp); |
---|
| 2127 | else |
---|
| 2128 | mdd_free(temp); |
---|
| 2129 | } |
---|
| 2130 | |
---|
| 2131 | } |
---|
| 2132 | } |
---|
| 2133 | return; |
---|
| 2134 | } /* End of ComputeReachabilityParameters */ |
---|