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 */ |
---|