| 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);
|
|---|
| 67 | /*static*/ int ComputeNumberOfBinaryStateVariables(mdd_manager *mddManager, array_t *mddIdArray);
|
|---|
| 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 | ******************************************************************************/
|
|---|
| 1164 | /*static*/ int
|
|---|
| 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 */
|
|---|