1 | /**CFile*********************************************************************** |
---|
2 | |
---|
3 | FileName [mcDnC.c] |
---|
4 | |
---|
5 | PackageName [mc] |
---|
6 | |
---|
7 | Synopsis [The Divide and Compose (D'n'C) Approach of SCC Enumeration.] |
---|
8 | |
---|
9 | Description [This file contains the functions to compute the fair |
---|
10 | Strongly Connected Components (SCCs) of the state translation graph |
---|
11 | of an FSM by Divide and Compose. Knowledge of the fair SCCs can be |
---|
12 | used to decide language emptiness. For more information, please |
---|
13 | check the CONCUR'01 paper of Wang et al., "Divide and Compose: SCC |
---|
14 | refinement for language emptiness." Other applications are also |
---|
15 | possible.] |
---|
16 | |
---|
17 | SeeAlso [] |
---|
18 | |
---|
19 | Author [Chao Wang] |
---|
20 | |
---|
21 | Copyright [Copyright (c) 2004 The Regents of the Univ. of Colorado. |
---|
22 | All rights reserved. |
---|
23 | |
---|
24 | Permission is hereby granted, without written agreement and without |
---|
25 | license or royalty fees, to use, copy, modify, and distribute this |
---|
26 | software and its documentation for any purpose, provided that the |
---|
27 | above copyright notice and the following two paragraphs appear in |
---|
28 | all copies of this software.] |
---|
29 | |
---|
30 | ******************************************************************************/ |
---|
31 | #include "mcInt.h" |
---|
32 | |
---|
33 | static char rcsid[] UNUSED = "$Id: mcDnC.c,v 1.9 2005/05/18 18:12:00 jinh Exp $"; |
---|
34 | |
---|
35 | /*---------------------------------------------------------------------------*/ |
---|
36 | /* Constant declarations */ |
---|
37 | /*---------------------------------------------------------------------------*/ |
---|
38 | |
---|
39 | /*---------------------------------------------------------------------------*/ |
---|
40 | /* Structure declarations */ |
---|
41 | /*---------------------------------------------------------------------------*/ |
---|
42 | |
---|
43 | /*---------------------------------------------------------------------------*/ |
---|
44 | /* Type declarations */ |
---|
45 | /*---------------------------------------------------------------------------*/ |
---|
46 | |
---|
47 | /*---------------------------------------------------------------------------*/ |
---|
48 | /* Variable declarations */ |
---|
49 | /*---------------------------------------------------------------------------*/ |
---|
50 | |
---|
51 | /*---------------------------------------------------------------------------*/ |
---|
52 | /* Macro declarations */ |
---|
53 | /*---------------------------------------------------------------------------*/ |
---|
54 | |
---|
55 | /**AutomaticStart*************************************************************/ |
---|
56 | |
---|
57 | /*---------------------------------------------------------------------------*/ |
---|
58 | /* Static function prototypes */ |
---|
59 | /*---------------------------------------------------------------------------*/ |
---|
60 | static int SccIsStrong(mdd_manager *mddMgr, array_t *buechiFairness, mdd_t *SCC); |
---|
61 | static array_t * SortMddArrayBySize(Fsm_Fsm_t *fsm, array_t *mddArray); |
---|
62 | static int stringCompare(const void * s1, const void * s2); |
---|
63 | /**AutomaticEnd***************************************************************/ |
---|
64 | |
---|
65 | |
---|
66 | /*---------------------------------------------------------------------------*/ |
---|
67 | /* Definition of exported functions */ |
---|
68 | /*---------------------------------------------------------------------------*/ |
---|
69 | |
---|
70 | /**Function******************************************************************** |
---|
71 | |
---|
72 | Synopsis [Compute all the states that lead to a fair cycle by |
---|
73 | Compositional SCC analysis (DnC -- Divide and Compose).] |
---|
74 | |
---|
75 | Comment [Used by LE/LTL/CTL* model checking. The Divide and Compose |
---|
76 | (D'n'C) approach is used for the symbolic SCC enumeration, which |
---|
77 | first creates SCC-closed sets on an abstract model and then |
---|
78 | successively refines these sets on the refined abstract models, |
---|
79 | until either no fair SCC exists or the concrete (original) model is |
---|
80 | reached. |
---|
81 | |
---|
82 | Strength reduction is also applied during the process -- as soon as |
---|
83 | the SCC-closed sets become weak/terminal, special decision |
---|
84 | procedures will be used to determine their language emptiness. |
---|
85 | |
---|
86 | For more information, please check the CONCUR'01 paper of Wang et |
---|
87 | al., "Divide and Compose: SCC refinement for language emptiness." |
---|
88 | |
---|
89 | Debugging information will be print out if dbgLevel is non-zero. |
---|
90 | |
---|
91 | Return the set of initial states from where fair paths exist.] |
---|
92 | |
---|
93 | SideEffects [] |
---|
94 | |
---|
95 | ******************************************************************************/ |
---|
96 | mdd_t * |
---|
97 | Mc_FsmCheckLanguageEmptinessByDnC( |
---|
98 | Fsm_Fsm_t *modelFsm, |
---|
99 | array_t *modelCareStates, |
---|
100 | Mc_AutStrength_t automatonStrength, |
---|
101 | int dcLevel, |
---|
102 | int dbgLevel, |
---|
103 | int printInputs, |
---|
104 | int verbosity, |
---|
105 | Mc_GSHScheduleType GSHschedule, |
---|
106 | Mc_FwdBwdAnalysis GSHdirection, |
---|
107 | int lockstep, |
---|
108 | FILE *dbgFile, |
---|
109 | int UseMore, |
---|
110 | int SimValue, |
---|
111 | char *driverName) |
---|
112 | { |
---|
113 | Ntk_Network_t *network = Fsm_FsmReadNetwork(modelFsm); |
---|
114 | mdd_manager *mddManager = Fsm_FsmReadMddManager(modelFsm); |
---|
115 | Fsm_Fairness_t *modelFairness = NIL(Fsm_Fairness_t); |
---|
116 | array_t *buechiFairness = NIL(array_t); |
---|
117 | int isExactReachableStatesAvailable = 0; |
---|
118 | mdd_t *reachableStates, *initialStates = NIL(mdd_t); |
---|
119 | mdd_t *fairStates, *fairInitialStates = NIL(mdd_t); |
---|
120 | array_t *onionRings = NIL(array_t); |
---|
121 | array_t *strongSccClosedSets = NIL(array_t); |
---|
122 | array_t *absLatchNameTableArray = NIL(array_t); |
---|
123 | int numOfAbstractModels, iter, i, exitFlag; |
---|
124 | array_t *arrayOfOnionRings = NIL(array_t); |
---|
125 | array_t *ctlArray = array_alloc(Ctlp_Formula_t *, 0); |
---|
126 | array_t *modelCareStatesArray = mdd_array_duplicate(modelCareStates); |
---|
127 | Mc_SccGen_t *sccgen; |
---|
128 | int composeIncSize, numOfLatches, maxLatchesToCompose; |
---|
129 | |
---|
130 | int maxComposePercentage = 30; |
---|
131 | int maxSccsToEnum = 100; |
---|
132 | |
---|
133 | |
---|
134 | /* |
---|
135 | * Read fairness constraints. |
---|
136 | */ |
---|
137 | modelFairness = Fsm_FsmReadFairnessConstraint(modelFsm); |
---|
138 | buechiFairness = array_alloc(mdd_t *, 0); |
---|
139 | if (modelFairness != NIL(Fsm_Fairness_t)) { |
---|
140 | if (!Fsm_FairnessTestIsBuchi(modelFairness)) { |
---|
141 | (void) fprintf(vis_stdout, |
---|
142 | "** non-Buechi fairness constraints not supported\n"); |
---|
143 | array_free(buechiFairness); |
---|
144 | assert(0); |
---|
145 | } else { |
---|
146 | int j; |
---|
147 | int numBuchi = Fsm_FairnessReadNumConjunctsOfDisjunct(modelFairness, 0); |
---|
148 | for (j = 0; j < numBuchi; j++) { |
---|
149 | Ctlp_Formula_t *tmpFormula; |
---|
150 | mdd_t *tempMdd; |
---|
151 | tmpFormula = Fsm_FairnessReadFinallyInfFormula(modelFairness, 0, j ); |
---|
152 | tempMdd = Fsm_FairnessObtainFinallyInfMdd(modelFairness, 0, j, |
---|
153 | modelCareStatesArray, |
---|
154 | (Mc_DcLevel) dcLevel); |
---|
155 | array_insert_last(mdd_t *, buechiFairness, tempMdd); |
---|
156 | array_insert_last( Ctlp_Formula_t *, ctlArray, |
---|
157 | Ctlp_FormulaDup(tmpFormula)); |
---|
158 | #if 1 |
---|
159 | fprintf(vis_stdout,"\nFairness[%d]:",j); |
---|
160 | Ctlp_FormulaPrint(vis_stdout, tmpFormula); |
---|
161 | fprintf(vis_stdout,"\n"); |
---|
162 | #endif |
---|
163 | } |
---|
164 | } |
---|
165 | } else { |
---|
166 | array_insert_last(mdd_t *, buechiFairness, mdd_one(mddManager)); |
---|
167 | } |
---|
168 | |
---|
169 | /* |
---|
170 | * If we need debugging information, arrayOfOnionRings != NIL(array_t), |
---|
171 | */ |
---|
172 | if (dbgLevel != McDbgLevelNone_c) |
---|
173 | arrayOfOnionRings = array_alloc(array_t *, 0); |
---|
174 | else |
---|
175 | arrayOfOnionRings = NIL(array_t); |
---|
176 | |
---|
177 | /* |
---|
178 | * If exact/approximate reachable states are available, use them. |
---|
179 | */ |
---|
180 | initialStates = Fsm_FsmComputeInitialStates(modelFsm); |
---|
181 | reachableStates = Fsm_FsmReadReachableStates(modelFsm); |
---|
182 | isExactReachableStatesAvailable = (reachableStates != NIL(mdd_t)); |
---|
183 | if (!isExactReachableStatesAvailable) |
---|
184 | reachableStates = McMddArrayAnd(modelCareStatesArray); |
---|
185 | else |
---|
186 | reachableStates = mdd_dup(reachableStates); |
---|
187 | onionRings = Fsm_FsmReadReachabilityOnionRings(modelFsm); |
---|
188 | if (onionRings == NIL(array_t)) { |
---|
189 | onionRings = array_alloc(mdd_t *, 0); |
---|
190 | array_insert(mdd_t *, onionRings, 0, mdd_dup(reachableStates)); |
---|
191 | }else |
---|
192 | onionRings = mdd_array_duplicate(onionRings); |
---|
193 | |
---|
194 | strongSccClosedSets = array_alloc(mdd_t *, 0); |
---|
195 | array_insert(mdd_t *, strongSccClosedSets, 0, mdd_dup(reachableStates)); |
---|
196 | |
---|
197 | /* |
---|
198 | * Compute a series of over-approximated abstract models |
---|
199 | */ |
---|
200 | numOfLatches = array_n(Fsm_FsmReadPresentStateVars(modelFsm)); |
---|
201 | maxLatchesToCompose = (numOfLatches * maxComposePercentage/100); |
---|
202 | maxLatchesToCompose = (maxLatchesToCompose > 20)? maxLatchesToCompose:20; |
---|
203 | composeIncSize = maxLatchesToCompose/10; |
---|
204 | composeIncSize = (composeIncSize > 4)? composeIncSize:4; |
---|
205 | |
---|
206 | absLatchNameTableArray = |
---|
207 | Mc_CreateStaticRefinementScheduleArray(network, |
---|
208 | ctlArray, |
---|
209 | NIL(array_t), |
---|
210 | NIL(array_t), |
---|
211 | FALSE, |
---|
212 | FALSE, |
---|
213 | ((verbosity<McVerbosityMax_c)? |
---|
214 | 0:McVerbositySome_c), |
---|
215 | composeIncSize, |
---|
216 | Part_CorrelationWithSupport); |
---|
217 | numOfAbstractModels = (array_n(absLatchNameTableArray) - 1); |
---|
218 | if (verbosity >= McVerbosityLittle_c) { |
---|
219 | fprintf(vis_stdout, |
---|
220 | "-- DnC: scheduled total %d abs models with %d latches\n", |
---|
221 | numOfAbstractModels, numOfLatches); |
---|
222 | } |
---|
223 | |
---|
224 | if (verbosity >= McVerbositySome_c) { |
---|
225 | fprintf(vis_stdout, "-- DnC:\n"); |
---|
226 | fprintf(vis_stdout, |
---|
227 | "-- DnC: maxComposePercentage = %d\n", maxComposePercentage); |
---|
228 | fprintf(vis_stdout, |
---|
229 | "-- DnC: numOfLatches = %d\n", numOfLatches); |
---|
230 | fprintf(vis_stdout, |
---|
231 | "-- DnC: composeIncSize = %d\n", composeIncSize); |
---|
232 | fprintf(vis_stdout, |
---|
233 | "-- DnC: numOfAbstractModels = %d\n", numOfAbstractModels); |
---|
234 | fprintf(vis_stdout, |
---|
235 | "-- DnC: maxLatchesToCompose = %d\n", maxLatchesToCompose); |
---|
236 | fprintf(vis_stdout, |
---|
237 | "-- DnC: maxSccsToEnum = %d\n", maxSccsToEnum); |
---|
238 | fprintf(vis_stdout, "-- Dnc: \n"); |
---|
239 | } |
---|
240 | |
---|
241 | exitFlag = 0; |
---|
242 | for (iter=0; iter<numOfAbstractModels; iter++) { |
---|
243 | Fsm_Fsm_t *absFsm = NIL(Fsm_Fsm_t); |
---|
244 | st_table *absLatchNameTable = NIL(st_table); |
---|
245 | array_t *absOnionRings; |
---|
246 | array_t *tempArray = NIL(array_t); |
---|
247 | mdd_t *sccClosedSet = NIL(mdd_t); |
---|
248 | mdd_t *tempMdd = NIL(mdd_t); |
---|
249 | mdd_t *absReachableStates = NIL(mdd_t); |
---|
250 | |
---|
251 | absLatchNameTable = array_fetch(st_table *, absLatchNameTableArray, iter); |
---|
252 | absFsm = Fsm_FsmCreateSubsystemFromNetwork(network, NIL(graph_t), |
---|
253 | absLatchNameTable, TRUE, 1); |
---|
254 | |
---|
255 | if (!isExactReachableStatesAvailable) { |
---|
256 | absReachableStates = Fsm_FsmComputeReachableStates(absFsm, 0, 0, 0, 0, |
---|
257 | 1, 0, 0, |
---|
258 | Fsm_Rch_Default_c, |
---|
259 | 0, 0, |
---|
260 | NIL(array_t), FALSE, |
---|
261 | NIL(array_t)); |
---|
262 | absOnionRings = Fsm_FsmReadReachabilityOnionRings(absFsm); |
---|
263 | assert(absOnionRings); |
---|
264 | absOnionRings = mdd_array_duplicate(absOnionRings); |
---|
265 | }else { |
---|
266 | absReachableStates = McComputeAbstractStates(absFsm, reachableStates); |
---|
267 | absOnionRings = array_alloc(mdd_t *, array_n(onionRings)); |
---|
268 | arrayForEachItem(mdd_t *, onionRings, i, tempMdd) { |
---|
269 | array_insert(mdd_t *, absOnionRings, i, |
---|
270 | McComputeAbstractStates(absFsm, tempMdd) ); |
---|
271 | } |
---|
272 | } |
---|
273 | |
---|
274 | tempArray = strongSccClosedSets; |
---|
275 | strongSccClosedSets = array_alloc(mdd_t *, 0); |
---|
276 | arrayForEachItem(mdd_t *, tempArray, i, sccClosedSet) { |
---|
277 | sccClosedSet = (iter == 0)? |
---|
278 | McComputeAbstractStates(absFsm, sccClosedSet): mdd_dup(sccClosedSet); |
---|
279 | tempMdd = mdd_and(sccClosedSet, absReachableStates, 1, 1); |
---|
280 | if (mdd_is_tautology(tempMdd, 0)) |
---|
281 | mdd_free(tempMdd); |
---|
282 | else |
---|
283 | array_insert_last(mdd_t *, strongSccClosedSets, tempMdd); |
---|
284 | mdd_free(sccClosedSet); |
---|
285 | } |
---|
286 | mdd_array_free(tempArray); |
---|
287 | |
---|
288 | /* Refine SCC-closed sets, but up to a certain number */ |
---|
289 | tempArray = strongSccClosedSets; |
---|
290 | strongSccClosedSets = array_alloc(mdd_t *, 0); |
---|
291 | Mc_FsmForEachFairScc(absFsm, sccgen, sccClosedSet, tempArray, |
---|
292 | strongSccClosedSets, /* new scc-closed sets */ |
---|
293 | buechiFairness, absOnionRings, FALSE, |
---|
294 | ((verbosity<McVerbosityMax_c)? |
---|
295 | McVerbosityNone_c:McVerbositySome_c), |
---|
296 | (Mc_DcLevel) dcLevel) { |
---|
297 | if (SccIsStrong(mddManager, buechiFairness, sccClosedSet)) { |
---|
298 | array_insert_last(mdd_t *, strongSccClosedSets, sccClosedSet); |
---|
299 | if (maxSccsToEnum>0 && array_n(strongSccClosedSets)>maxSccsToEnum) { |
---|
300 | Mc_FsmSccGenFree(sccgen, strongSccClosedSets); |
---|
301 | break; |
---|
302 | } |
---|
303 | |
---|
304 | }else { |
---|
305 | array_t *newCareStatesArray; |
---|
306 | newCareStatesArray = mdd_array_duplicate(modelCareStatesArray); |
---|
307 | if (!isExactReachableStatesAvailable) |
---|
308 | array_insert_last(mdd_t *, newCareStatesArray, absReachableStates); |
---|
309 | |
---|
310 | if (verbosity >= McVerbositySome_c) |
---|
311 | fprintf(vis_stdout, "-- DnC: search in a weak SCC-closed set\n"); |
---|
312 | |
---|
313 | fairStates = McFsmRefineWeakFairSCCs(modelFsm, sccClosedSet, |
---|
314 | newCareStatesArray, |
---|
315 | arrayOfOnionRings, FALSE, |
---|
316 | dcLevel, |
---|
317 | ((verbosity<McVerbosityMax_c)? 0:McVerbositySome_c) ); |
---|
318 | fairInitialStates = mdd_and(initialStates, fairStates, 1, 1); |
---|
319 | mdd_free(fairStates); |
---|
320 | if (!mdd_is_tautology(fairInitialStates, 0)) { |
---|
321 | /* Done, find a reachable fair cycle */ |
---|
322 | exitFlag = 2; |
---|
323 | if (verbosity >= McVerbosityLittle_c) |
---|
324 | fprintf(vis_stdout, "-- DnC: find a weak SCC!\n"); |
---|
325 | Mc_FsmSccGenFree(sccgen, NIL(array_t)); |
---|
326 | break; |
---|
327 | }else { |
---|
328 | mdd_free(fairInitialStates); |
---|
329 | } |
---|
330 | } |
---|
331 | |
---|
332 | }/*Mc_FsmForEachFairScc( ) {*/ |
---|
333 | mdd_array_free(tempArray); |
---|
334 | |
---|
335 | SortMddArrayBySize(absFsm, strongSccClosedSets); |
---|
336 | |
---|
337 | if (verbosity >= McVerbosityLittle_c && exitFlag != 2) { |
---|
338 | fprintf(vis_stdout, |
---|
339 | "-- DnC: found %d SCC-closed sets in abs model %d with %d latches\n", |
---|
340 | array_n(strongSccClosedSets), iter+1, |
---|
341 | st_count(absLatchNameTable)); |
---|
342 | if (verbosity >= McVerbositySome_c) { |
---|
343 | array_t *absPSvars = Fsm_FsmReadPresentStateVars(absFsm); |
---|
344 | array_t *PSvars = Fsm_FsmReadPresentStateVars(modelFsm); |
---|
345 | arrayForEachItem(mdd_t *, strongSccClosedSets, i, tempMdd) { |
---|
346 | fprintf(vis_stdout, "-- An SCC-closed set with %5g abs (%5g concrete) states\n", |
---|
347 | mdd_count_onset(mddManager, tempMdd, absPSvars), |
---|
348 | mdd_count_onset(mddManager, tempMdd, PSvars) |
---|
349 | ); |
---|
350 | } |
---|
351 | } |
---|
352 | } |
---|
353 | |
---|
354 | if(exitFlag == 0 && array_n(strongSccClosedSets) == 0) { |
---|
355 | /* Done, no reachable fair cycle exists */ |
---|
356 | exitFlag = 1; |
---|
357 | } |
---|
358 | |
---|
359 | mdd_array_free(absOnionRings); |
---|
360 | Fsm_FsmFree(absFsm); |
---|
361 | |
---|
362 | /* existFlag: 0 --> unknown; 1 --> no fair SCC; 2 --> find a fair SCC */ |
---|
363 | if ( exitFlag != 0 || st_count(absLatchNameTable) > maxLatchesToCompose ) { |
---|
364 | if (!isExactReachableStatesAvailable) { |
---|
365 | array_insert_last(mdd_t *, modelCareStatesArray, absReachableStates); |
---|
366 | tempMdd = reachableStates; |
---|
367 | reachableStates = mdd_and(reachableStates, absReachableStates,1,1); |
---|
368 | mdd_free(tempMdd); |
---|
369 | } |
---|
370 | break; |
---|
371 | } |
---|
372 | |
---|
373 | mdd_free(absReachableStates); |
---|
374 | |
---|
375 | }/*for (iter=0; iter<numOfAbstractModels; iter++) {*/ |
---|
376 | |
---|
377 | for (i=0; i<array_n(absLatchNameTableArray); i++) { |
---|
378 | st_free_table( array_fetch(st_table *, absLatchNameTableArray, i) ); |
---|
379 | } |
---|
380 | array_free(absLatchNameTableArray); |
---|
381 | |
---|
382 | |
---|
383 | /* |
---|
384 | * Compute fair SCCs on the concrete model if necessary |
---|
385 | */ |
---|
386 | if (exitFlag == 0) { |
---|
387 | array_t *tempArray; |
---|
388 | mdd_t *sccClosedSet = NIL(mdd_t); |
---|
389 | mdd_t *tempMdd = NIL(mdd_t); |
---|
390 | |
---|
391 | if (verbosity >= McVerbosityLittle_c) |
---|
392 | fprintf(vis_stdout, "-- DnC: check the concrete model\n"); |
---|
393 | |
---|
394 | tempArray = strongSccClosedSets; |
---|
395 | strongSccClosedSets = array_alloc(mdd_t *, 0); |
---|
396 | arrayForEachItem(mdd_t *, tempArray, i, sccClosedSet) { |
---|
397 | tempMdd = mdd_and(sccClosedSet, reachableStates, 1, 1); |
---|
398 | if (mdd_is_tautology(tempMdd, 0)) |
---|
399 | mdd_free(tempMdd); |
---|
400 | else |
---|
401 | array_insert_last(mdd_t *, strongSccClosedSets, tempMdd); |
---|
402 | mdd_free(sccClosedSet); |
---|
403 | } |
---|
404 | array_free(tempArray); |
---|
405 | |
---|
406 | if (lockstep != MC_LOCKSTEP_OFF) { |
---|
407 | tempArray = array_alloc(mdd_t *, 0); |
---|
408 | fairStates = McFsmRefineFairSCCsByLockStep(modelFsm, lockstep, |
---|
409 | tempArray, |
---|
410 | strongSccClosedSets, |
---|
411 | NIL(array_t), |
---|
412 | arrayOfOnionRings, |
---|
413 | (Mc_VerbosityLevel) verbosity, |
---|
414 | (Mc_DcLevel) dcLevel); |
---|
415 | mdd_array_free(tempArray); |
---|
416 | }else{ |
---|
417 | mdd_t *fairStates0, *sccClosedSet; |
---|
418 | array_t *EUonionRings; |
---|
419 | mdd_t *mddOne = mdd_one(mddManager); |
---|
420 | Mc_EarlyTermination_t *earlyTermination; |
---|
421 | |
---|
422 | sccClosedSet = McMddArrayOr(strongSccClosedSets); |
---|
423 | fairStates0 = Mc_FsmEvaluateEGFormula(modelFsm, sccClosedSet, |
---|
424 | NIL(mdd_t), mddOne, |
---|
425 | modelFairness, |
---|
426 | modelCareStatesArray, |
---|
427 | MC_NO_EARLY_TERMINATION, |
---|
428 | NIL(array_t), |
---|
429 | Mc_None_c, |
---|
430 | &arrayOfOnionRings, |
---|
431 | (Mc_VerbosityLevel) verbosity, |
---|
432 | (Mc_DcLevel) dcLevel, |
---|
433 | NIL(boolean), |
---|
434 | GSHschedule); |
---|
435 | mdd_free(sccClosedSet); |
---|
436 | |
---|
437 | EUonionRings = ( (arrayOfOnionRings == NIL(array_t))? |
---|
438 | NIL(array_t):array_alloc(mdd_t *,0) ); |
---|
439 | |
---|
440 | earlyTermination = Mc_EarlyTerminationAlloc(McSome_c, initialStates); |
---|
441 | fairStates = Mc_FsmEvaluateEUFormula(modelFsm, mddOne, |
---|
442 | fairStates0, NIL(mdd_t), mddOne, |
---|
443 | modelCareStatesArray, |
---|
444 | earlyTermination, |
---|
445 | NIL(array_t), Mc_None_c, |
---|
446 | EUonionRings, |
---|
447 | (Mc_VerbosityLevel) verbosity, |
---|
448 | (Mc_DcLevel) dcLevel, |
---|
449 | NIL(boolean)); |
---|
450 | mdd_free(fairStates0); |
---|
451 | mdd_free(mddOne); |
---|
452 | Mc_EarlyTerminationFree(earlyTermination); |
---|
453 | |
---|
454 | if (arrayOfOnionRings != NIL(array_t)) { |
---|
455 | int j; |
---|
456 | arrayForEachItem(array_t *, arrayOfOnionRings, i, tempArray) { |
---|
457 | #ifndef NDEBUG |
---|
458 | mdd_t *mdd1 = array_fetch_last(mdd_t *, tempArray); |
---|
459 | #endif |
---|
460 | arrayForEachItem(mdd_t *, EUonionRings, j, tempMdd) { |
---|
461 | if (j != 0) |
---|
462 | array_insert_last(mdd_t *, tempArray, mdd_dup(tempMdd)); |
---|
463 | else |
---|
464 | assert( mdd_equal(tempMdd, mdd1) ); |
---|
465 | } |
---|
466 | } |
---|
467 | mdd_array_free(EUonionRings); |
---|
468 | } |
---|
469 | } |
---|
470 | |
---|
471 | fairInitialStates = mdd_and(initialStates, fairStates, 1, 1); |
---|
472 | mdd_free(fairStates); |
---|
473 | exitFlag = mdd_is_tautology(fairInitialStates, 0)? 1:2; |
---|
474 | } |
---|
475 | |
---|
476 | /* Clean-Ups */ |
---|
477 | mdd_array_free(modelCareStatesArray); |
---|
478 | mdd_array_free(strongSccClosedSets); |
---|
479 | mdd_array_free(onionRings); |
---|
480 | mdd_free(reachableStates); |
---|
481 | mdd_free(initialStates); |
---|
482 | |
---|
483 | /* |
---|
484 | * Print out the verification result (pass/fail, empty/non-empty) |
---|
485 | */ |
---|
486 | if (exitFlag == 1) { |
---|
487 | if (strcmp(driverName, "LE") == 0) |
---|
488 | fprintf(vis_stdout, "# LE: language emptiness check passes\n"); |
---|
489 | else |
---|
490 | fprintf(vis_stdout, "# %s: formula passed\n", driverName); |
---|
491 | if (arrayOfOnionRings != NIL(array_t)) |
---|
492 | mdd_array_array_free(arrayOfOnionRings); |
---|
493 | return fairInitialStates; |
---|
494 | |
---|
495 | }else if (exitFlag == 2) { |
---|
496 | if (strcmp(driverName, "LE") == 0) |
---|
497 | fprintf(vis_stdout, "# LE: language is not empty\n"); |
---|
498 | else |
---|
499 | fprintf(vis_stdout, "# %s: formula failed\n", driverName); |
---|
500 | |
---|
501 | }else { |
---|
502 | fprintf(vis_stderr, "* DnC error, result is unknown!\n"); |
---|
503 | assert(0); |
---|
504 | } |
---|
505 | |
---|
506 | /* |
---|
507 | * Print out the debugging information if requested |
---|
508 | */ |
---|
509 | if (dbgLevel == McDbgLevelNone_c) { |
---|
510 | if (arrayOfOnionRings != NIL(array_t)) |
---|
511 | mdd_array_array_free(arrayOfOnionRings); |
---|
512 | return fairInitialStates; |
---|
513 | |
---|
514 | }else { |
---|
515 | mdd_t *badStates, *aBadState, *mddOne; |
---|
516 | McPath_t *fairPath, *normalPath; |
---|
517 | array_t *stemArray, *cycleArray; |
---|
518 | FILE *tmpFile = vis_stdout; |
---|
519 | extern FILE *vis_stdpipe; |
---|
520 | fprintf(vis_stdout, "# %s: generating path to fair cycle\n", driverName); |
---|
521 | |
---|
522 | /* Generate witness. */ |
---|
523 | badStates = mdd_dup(fairInitialStates); |
---|
524 | aBadState = Mc_ComputeAState(badStates, modelFsm); |
---|
525 | mdd_free(badStates); |
---|
526 | |
---|
527 | mddOne = mdd_one(mddManager); |
---|
528 | fairPath = McBuildFairPath(aBadState, mddOne, arrayOfOnionRings, modelFsm, |
---|
529 | modelCareStates, |
---|
530 | (Mc_VerbosityLevel) verbosity, |
---|
531 | (Mc_DcLevel) dcLevel, |
---|
532 | McFwd_c); |
---|
533 | mdd_free(mddOne); |
---|
534 | mdd_free(aBadState); |
---|
535 | mdd_array_array_free(arrayOfOnionRings); |
---|
536 | |
---|
537 | /* Print witness. */ |
---|
538 | normalPath = McPathNormalize(fairPath); |
---|
539 | McPathFree(fairPath); |
---|
540 | |
---|
541 | stemArray = McPathReadStemArray(normalPath); |
---|
542 | cycleArray = McPathReadCycleArray(normalPath); |
---|
543 | |
---|
544 | /* we should pass dbgFile/UseMore as parameters |
---|
545 | dbgFile = McOptionsReadDebugFile(options);*/ |
---|
546 | if (dbgFile != NIL(FILE)) { |
---|
547 | vis_stdpipe = dbgFile; |
---|
548 | } else if (UseMore == TRUE) { |
---|
549 | vis_stdpipe = popen("more","w"); |
---|
550 | } else { |
---|
551 | vis_stdpipe = vis_stdout; |
---|
552 | } |
---|
553 | vis_stdout = vis_stdpipe; |
---|
554 | |
---|
555 | /* We should also pass SimValue as a parameter */ |
---|
556 | if (SimValue == FALSE) { |
---|
557 | (void) fprintf(vis_stdout, "# %s: path to fair cycle:\n\n", driverName); |
---|
558 | Mc_PrintPath(stemArray, modelFsm, printInputs); |
---|
559 | fprintf (vis_stdout, "\n"); |
---|
560 | |
---|
561 | (void) fprintf(vis_stdout, "# %s: fair cycle:\n\n", driverName); |
---|
562 | Mc_PrintPath(cycleArray, modelFsm, printInputs); |
---|
563 | fprintf (vis_stdout, "\n"); |
---|
564 | }else { |
---|
565 | array_t *completePath = McCreateMergedPath(stemArray, cycleArray); |
---|
566 | (void) fprintf(vis_stdout, "# %s: counter-example\n", driverName); |
---|
567 | McPrintSimPath(vis_stdout, completePath, modelFsm); |
---|
568 | mdd_array_free(completePath); |
---|
569 | } |
---|
570 | |
---|
571 | if (dbgFile == NIL(FILE) && UseMore == TRUE) { |
---|
572 | (void) pclose(vis_stdpipe); |
---|
573 | } |
---|
574 | vis_stdout = tmpFile; |
---|
575 | |
---|
576 | McPathFree(normalPath); |
---|
577 | } |
---|
578 | |
---|
579 | return fairInitialStates; |
---|
580 | } |
---|
581 | |
---|
582 | /**Function******************************************************************** |
---|
583 | |
---|
584 | Synopsis [Create a refinement schedule array.] |
---|
585 | |
---|
586 | Description [If dynamicIncrease is true, the first element of return |
---|
587 | array includes varibales appeared in formula. The size of the first |
---|
588 | element should be less than or equal to incrementalSize. The second |
---|
589 | element includes all variables in formula's cone of influence. When |
---|
590 | dynamicIncrease is false, all variables in formula's cone of |
---|
591 | influence (let's say n variables) are partitioned into |
---|
592 | ceil(n/incrementalSize) elements. Then one more element which |
---|
593 | includes all n variables are added to return array.] |
---|
594 | |
---|
595 | SideEffects [] |
---|
596 | |
---|
597 | SeeAlso [Part_SubsystemInfo_t] |
---|
598 | |
---|
599 | ******************************************************************************/ |
---|
600 | array_t * |
---|
601 | Mc_CreateStaticRefinementScheduleArray( |
---|
602 | Ntk_Network_t *network, |
---|
603 | array_t *ctlArray, |
---|
604 | array_t *ltlArray, |
---|
605 | array_t *fairArray, |
---|
606 | boolean dynamicIncrease, |
---|
607 | boolean isLatchNameSort, |
---|
608 | int verbosity, |
---|
609 | int incrementalSize, |
---|
610 | Part_CMethod correlationMethod) |
---|
611 | { |
---|
612 | array_t *partitionArray; |
---|
613 | Part_Subsystem_t *partitionSubsystem; |
---|
614 | Part_SubsystemInfo_t *subsystemInfo; |
---|
615 | st_table *latchNameTable; |
---|
616 | st_table *latchNameTableSum, *latchNameTableSumCopy; |
---|
617 | char *flagValue; |
---|
618 | st_generator *stGen; |
---|
619 | char *name; |
---|
620 | double affinityFactor; |
---|
621 | array_t *scheduleArray; |
---|
622 | boolean dynamicAndDependency = isLatchNameSort; |
---|
623 | array_t *tempArray, *tempArray2; |
---|
624 | int i, count; |
---|
625 | |
---|
626 | /* affinity factor to decompose state space */ |
---|
627 | flagValue = Cmd_FlagReadByName("part_group_affinity_factor"); |
---|
628 | if(flagValue != NIL(char)){ |
---|
629 | affinityFactor = atof(flagValue); |
---|
630 | } |
---|
631 | else{ |
---|
632 | /* default value */ |
---|
633 | affinityFactor = 0.5; |
---|
634 | } |
---|
635 | |
---|
636 | /* |
---|
637 | * Obtain submachines as array: The first sub-system includes |
---|
638 | * variables in CTL/LTL/fair formulas and other latches are grouped |
---|
639 | * in the same way as Part_PartCreateSubsystems() |
---|
640 | */ |
---|
641 | subsystemInfo = Part_PartitionSubsystemInfoInit(network); |
---|
642 | Part_PartitionSubsystemInfoSetBound(subsystemInfo, incrementalSize); |
---|
643 | Part_PartitionSubsystemInfoSetVerbosity(subsystemInfo, verbosity); |
---|
644 | Part_PartitionSubsystemInfoSetCorrelationMethod(subsystemInfo, |
---|
645 | correlationMethod); |
---|
646 | Part_PartitionSubsystemInfoSetAffinityFactor(subsystemInfo, affinityFactor); |
---|
647 | partitionArray = Part_PartCreateSubsystemsWithCtlAndLtl(subsystemInfo, |
---|
648 | ctlArray, ltlArray, fairArray, |
---|
649 | dynamicIncrease,dynamicAndDependency,FALSE); |
---|
650 | Part_PartitionSubsystemInfoFree(subsystemInfo); |
---|
651 | |
---|
652 | scheduleArray = array_alloc(st_table *, 0); |
---|
653 | |
---|
654 | |
---|
655 | /* |
---|
656 | * For each partitioned submachines build an FSM. |
---|
657 | */ |
---|
658 | latchNameTableSum = st_init_table(strcmp, st_strhash); |
---|
659 | if (!dynamicAndDependency){ |
---|
660 | for (i=0;i<array_n(partitionArray);i++){ |
---|
661 | partitionSubsystem = array_fetch(Part_Subsystem_t *, partitionArray, i); |
---|
662 | if (partitionSubsystem != NIL(Part_Subsystem_t)) { |
---|
663 | latchNameTable = Part_PartitionSubsystemReadVertexTable(partitionSubsystem); |
---|
664 | st_foreach_item(latchNameTable, stGen, &name, NIL(char *)) { |
---|
665 | if (!st_lookup(latchNameTableSum, name, NIL(char *))){ |
---|
666 | st_insert(latchNameTableSum, name, NIL(char)); |
---|
667 | } |
---|
668 | } |
---|
669 | Part_PartitionSubsystemFree(partitionSubsystem); |
---|
670 | } |
---|
671 | latchNameTableSumCopy = st_copy(latchNameTableSum); |
---|
672 | array_insert_last(st_table *, scheduleArray, latchNameTableSumCopy); |
---|
673 | } |
---|
674 | }else{ |
---|
675 | partitionSubsystem = array_fetch(Part_Subsystem_t *, partitionArray, 0); |
---|
676 | latchNameTable = Part_PartitionSubsystemReadVertexTable(partitionSubsystem); |
---|
677 | st_foreach_item(latchNameTable, stGen, &name, NIL(char *)) { |
---|
678 | st_insert(latchNameTableSum, name, NIL(char)); |
---|
679 | } |
---|
680 | latchNameTableSumCopy = st_copy(latchNameTableSum); |
---|
681 | array_insert_last(st_table *, scheduleArray, latchNameTableSumCopy); |
---|
682 | Part_PartitionSubsystemFree(partitionSubsystem); |
---|
683 | |
---|
684 | partitionSubsystem = array_fetch(Part_Subsystem_t *, partitionArray, 1); |
---|
685 | tempArray = array_alloc(char *, 0); |
---|
686 | if (partitionSubsystem != NIL(Part_Subsystem_t)){ |
---|
687 | latchNameTable = Part_PartitionSubsystemReadVertexTable(partitionSubsystem); |
---|
688 | st_foreach_item(latchNameTable, stGen, &name, NIL(char *)) { |
---|
689 | array_insert_last(char *, tempArray, name); |
---|
690 | } |
---|
691 | array_sort(tempArray, stringCompare); |
---|
692 | Part_PartitionSubsystemFree(partitionSubsystem); |
---|
693 | } |
---|
694 | |
---|
695 | partitionSubsystem = array_fetch(Part_Subsystem_t *, partitionArray, 2); |
---|
696 | tempArray2 = array_alloc(char *, 0); |
---|
697 | if (partitionSubsystem != NIL(Part_Subsystem_t)) { |
---|
698 | latchNameTable = Part_PartitionSubsystemReadVertexTable(partitionSubsystem); |
---|
699 | st_foreach_item(latchNameTable, stGen, &name, NIL(char *)) { |
---|
700 | array_insert_last(char *, tempArray2, name); |
---|
701 | } |
---|
702 | array_sort(tempArray2, stringCompare); |
---|
703 | Part_PartitionSubsystemFree(partitionSubsystem); |
---|
704 | } |
---|
705 | |
---|
706 | array_append(tempArray, tempArray2); |
---|
707 | array_free(tempArray2); |
---|
708 | |
---|
709 | count = 0; |
---|
710 | arrayForEachItem(char *, tempArray, i, name){ |
---|
711 | if (!st_lookup(latchNameTableSum, name, NIL(char *))){ |
---|
712 | st_insert(latchNameTableSum, (char *)name, (char *)0); |
---|
713 | count++; |
---|
714 | } |
---|
715 | if ((count == incrementalSize) && (i < array_n(tempArray)-1)){ |
---|
716 | latchNameTableSumCopy = st_copy(latchNameTableSum); |
---|
717 | array_insert_last(st_table *, scheduleArray, latchNameTableSumCopy); |
---|
718 | count = 0; |
---|
719 | } |
---|
720 | } |
---|
721 | array_free(tempArray); |
---|
722 | latchNameTableSumCopy = st_copy(latchNameTableSum); |
---|
723 | array_insert_last(st_table *, scheduleArray, latchNameTableSumCopy); |
---|
724 | } |
---|
725 | |
---|
726 | array_free(partitionArray); |
---|
727 | st_free_table(latchNameTableSum); |
---|
728 | |
---|
729 | return (scheduleArray); |
---|
730 | } |
---|
731 | |
---|
732 | |
---|
733 | /*---------------------------------------------------------------------------*/ |
---|
734 | /* Definition of internal functions */ |
---|
735 | /*---------------------------------------------------------------------------*/ |
---|
736 | |
---|
737 | /**Function******************************************************************** |
---|
738 | |
---|
739 | Synopsis [Compute the fair SCCs within the given weak SCC-closed |
---|
740 | set.] |
---|
741 | |
---|
742 | Description [Used by the Divide and Compose (D'n'C) approach for |
---|
743 | language emptiness checking. Because it's a weak SCC-closed set, |
---|
744 | fair states can be computed through the evaluation of EF EG |
---|
745 | (sccClosedSet). |
---|
746 | |
---|
747 | Debugging information will be returned if arrayOfOnionRings is not NIL. |
---|
748 | |
---|
749 | Return the fair states leading to a fair cycle within the given |
---|
750 | SCC-closed set.] |
---|
751 | |
---|
752 | SideEffects [arrayOfOnionRings will be changed if it is not NIL and |
---|
753 | the initial states intersect the fair states.] |
---|
754 | |
---|
755 | ******************************************************************************/ |
---|
756 | mdd_t * |
---|
757 | McFsmRefineWeakFairSCCs( |
---|
758 | Fsm_Fsm_t *modelFsm, |
---|
759 | mdd_t *sccClosedSet, |
---|
760 | array_t *modelCareStatesArray, |
---|
761 | array_t *arrayOfOnionRings, |
---|
762 | boolean isSccTerminal, |
---|
763 | int dcLevel, |
---|
764 | int verbosity) |
---|
765 | { |
---|
766 | mdd_manager *mddManager = Fsm_FsmReadMddManager(modelFsm); |
---|
767 | mdd_t *initialStates; |
---|
768 | mdd_t *mddOne, *mddEgFair, *mddEfEgFair, *fairInitStates, *mdd1; |
---|
769 | array_t *EFonionRings, *EGArrayOfOnionRings, *EGonionRings; |
---|
770 | array_t *newOnionRings; |
---|
771 | int i, j; |
---|
772 | Mc_EarlyTermination_t *earlyTermination; |
---|
773 | |
---|
774 | initialStates = Fsm_FsmComputeInitialStates(modelFsm); |
---|
775 | mddOne = mdd_one(mddManager); |
---|
776 | |
---|
777 | /* if debugging information is requested, arrayOfOnionRings!=NIL(array_t) */ |
---|
778 | if (arrayOfOnionRings != NIL(array_t)) { |
---|
779 | EGArrayOfOnionRings = array_alloc(array_t *, 0); |
---|
780 | EFonionRings = array_alloc(mdd_t *, 0); |
---|
781 | }else { |
---|
782 | EGArrayOfOnionRings = NIL(array_t); |
---|
783 | EFonionRings = NIL(array_t); |
---|
784 | } |
---|
785 | |
---|
786 | if (isSccTerminal) |
---|
787 | mddEgFair = mdd_dup(sccClosedSet); |
---|
788 | else |
---|
789 | mddEgFair = Mc_FsmEvaluateEGFormula(modelFsm, sccClosedSet, |
---|
790 | NIL(mdd_t), mddOne, |
---|
791 | NIL(Fsm_Fairness_t), |
---|
792 | modelCareStatesArray, |
---|
793 | NIL(Mc_EarlyTermination_t), |
---|
794 | NIL(array_t), Mc_None_c, |
---|
795 | &EGArrayOfOnionRings, |
---|
796 | (Mc_VerbosityLevel) verbosity, |
---|
797 | (Mc_DcLevel) dcLevel, |
---|
798 | NIL(boolean), McGSH_EL_c); |
---|
799 | |
---|
800 | earlyTermination = Mc_EarlyTerminationAlloc(McSome_c, initialStates); |
---|
801 | mddEfEgFair = Mc_FsmEvaluateEUFormula(modelFsm, mddOne, |
---|
802 | mddEgFair, NIL(mdd_t), mddOne, |
---|
803 | modelCareStatesArray, |
---|
804 | earlyTermination, |
---|
805 | NIL(array_t), Mc_None_c, |
---|
806 | EFonionRings, |
---|
807 | (Mc_VerbosityLevel) verbosity, |
---|
808 | (Mc_DcLevel) dcLevel, |
---|
809 | NIL(boolean)); |
---|
810 | mdd_free(mddEgFair); |
---|
811 | Mc_EarlyTerminationFree(earlyTermination); |
---|
812 | |
---|
813 | fairInitStates = mdd_and(mddEfEgFair, initialStates, 1, 1); |
---|
814 | |
---|
815 | /* create the arrayOfOnionRings */ |
---|
816 | if (arrayOfOnionRings!=NIL(array_t) && !mdd_is_tautology(fairInitStates,0)) { |
---|
817 | if (isSccTerminal) |
---|
818 | array_insert_last(array_t *, |
---|
819 | arrayOfOnionRings, mdd_array_duplicate(EFonionRings)); |
---|
820 | else { |
---|
821 | arrayForEachItem(array_t *, EGArrayOfOnionRings, i, EGonionRings) { |
---|
822 | newOnionRings = mdd_array_duplicate(EGonionRings); |
---|
823 | arrayForEachItem(mdd_t *, EFonionRings, j, mdd1) { |
---|
824 | if (j != 0) |
---|
825 | array_insert_last(mdd_t *, newOnionRings, mdd_dup(mdd1)); |
---|
826 | } |
---|
827 | array_insert_last(array_t *, arrayOfOnionRings, newOnionRings); |
---|
828 | } |
---|
829 | } |
---|
830 | } |
---|
831 | mdd_free(fairInitStates); |
---|
832 | |
---|
833 | if (arrayOfOnionRings != NIL(array_t)) { |
---|
834 | mdd_array_free(EFonionRings); |
---|
835 | mdd_array_array_free(EGArrayOfOnionRings); |
---|
836 | } |
---|
837 | |
---|
838 | mdd_free(initialStates); |
---|
839 | mdd_free(mddOne); |
---|
840 | |
---|
841 | return mddEfEgFair; |
---|
842 | } |
---|
843 | |
---|
844 | |
---|
845 | /**Function******************************************************************** |
---|
846 | |
---|
847 | Synopsis [Compute the abstract states from the concrete states.] |
---|
848 | |
---|
849 | Description [By existentially quantify out the invisible |
---|
850 | variables. Invisible variables are those state variables (or |
---|
851 | latches) that are not in the supports of the abstract states---they |
---|
852 | have been abstracted away.] |
---|
853 | |
---|
854 | SideEffects [] |
---|
855 | |
---|
856 | ******************************************************************************/ |
---|
857 | mdd_t * |
---|
858 | McComputeAbstractStates( |
---|
859 | Fsm_Fsm_t *absFsm, |
---|
860 | mdd_t *states) |
---|
861 | { |
---|
862 | mdd_t *result; |
---|
863 | mdd_manager *mddManager = Fsm_FsmReadMddManager(absFsm); |
---|
864 | array_t *psVars = Fsm_FsmReadPresentStateVars(absFsm); |
---|
865 | array_t *supportVars; |
---|
866 | array_t *invisibleVars = array_alloc(long, 0); |
---|
867 | st_table *psVarTable = st_init_table(st_numcmp, st_numhash); |
---|
868 | int i; |
---|
869 | long mddId; |
---|
870 | |
---|
871 | arrayForEachItem(long, psVars, i, mddId) { |
---|
872 | st_insert(psVarTable, (char *)mddId, NIL(char)); |
---|
873 | } |
---|
874 | |
---|
875 | supportVars = mdd_get_support(mddManager, states); |
---|
876 | arrayForEachItem(long, supportVars, i, mddId) { |
---|
877 | if (!st_is_member(psVarTable, (char *)mddId)) |
---|
878 | array_insert_last(long, invisibleVars, mddId); |
---|
879 | } |
---|
880 | array_free(supportVars); |
---|
881 | st_free_table(psVarTable); |
---|
882 | |
---|
883 | result = mdd_smooth(mddManager, states, invisibleVars); |
---|
884 | |
---|
885 | array_free(invisibleVars); |
---|
886 | |
---|
887 | return result; |
---|
888 | } |
---|
889 | |
---|
890 | |
---|
891 | /**Function******************************************************************** |
---|
892 | |
---|
893 | Synopsis [Return true if the Divide and Compose (D'n'C) approach for |
---|
894 | language emptiness checking is enabled.] |
---|
895 | |
---|
896 | Description [Return true if the D'n'C approach for language emptiness |
---|
897 | is enabled.] |
---|
898 | |
---|
899 | SideEffects [] |
---|
900 | |
---|
901 | ******************************************************************************/ |
---|
902 | boolean |
---|
903 | McGetDncEnabled(void) |
---|
904 | { |
---|
905 | char *flagValue; |
---|
906 | boolean result = FALSE; |
---|
907 | |
---|
908 | flagValue = Cmd_FlagReadByName("divide_and_compose"); |
---|
909 | if (flagValue != NIL(char)) { |
---|
910 | if (strcmp(flagValue, "true") == 0) |
---|
911 | result = TRUE; |
---|
912 | else if (strcmp(flagValue, "false") == 0) |
---|
913 | result = FALSE; |
---|
914 | else { |
---|
915 | fprintf(vis_stderr, "** dnc error: invalid dnc_enable flag %s, dnc is disabled. \n", flagValue); |
---|
916 | } |
---|
917 | } |
---|
918 | |
---|
919 | return result; |
---|
920 | } |
---|
921 | |
---|
922 | |
---|
923 | /*---------------------------------------------------------------------------*/ |
---|
924 | /* Definition of static functions */ |
---|
925 | /*---------------------------------------------------------------------------*/ |
---|
926 | |
---|
927 | /**Function******************************************************************** |
---|
928 | |
---|
929 | Synopsis [Return true if the given SCC is strong.] |
---|
930 | |
---|
931 | Description [Return true if the given SCC is strong. Note that the |
---|
932 | check is conservative -- for the purpose of efficiency -- When it |
---|
933 | returns false, the SCC is definitely weak; when it returns true, the |
---|
934 | SCC may be still be weak. For the language emptiness checking, this |
---|
935 | is not going to hurt us.] |
---|
936 | |
---|
937 | SideEffects [] |
---|
938 | |
---|
939 | ******************************************************************************/ |
---|
940 | static boolean |
---|
941 | SccIsStrong(mdd_manager *mddMgr, array_t *buechiFairness, mdd_t *SCC) |
---|
942 | { |
---|
943 | boolean strength; |
---|
944 | mdd_t *LabeledAllFairness = mdd_dup(SCC); |
---|
945 | mdd_t *NotLabeledAllFairness; |
---|
946 | mdd_t *fairSet; |
---|
947 | int i; |
---|
948 | |
---|
949 | /* |
---|
950 | * check whether SCC intersects all the fairness constraints |
---|
951 | * if yes, WEAK |
---|
952 | * if no, WEAK or STRONG |
---|
953 | */ |
---|
954 | arrayForEachItem(mdd_t *, buechiFairness, i, fairSet) { |
---|
955 | mdd_t *tmpMdd = LabeledAllFairness; |
---|
956 | LabeledAllFairness = mdd_and(LabeledAllFairness, fairSet, 1,1 ); |
---|
957 | mdd_free( tmpMdd ); |
---|
958 | } |
---|
959 | NotLabeledAllFairness = mdd_and(SCC, LabeledAllFairness, 1, 0); |
---|
960 | mdd_free(LabeledAllFairness); |
---|
961 | |
---|
962 | if(mdd_is_tautology(NotLabeledAllFairness, 0)) { |
---|
963 | mdd_free(NotLabeledAllFairness); |
---|
964 | strength = FALSE; /* WEAK*/ |
---|
965 | } |
---|
966 | else { |
---|
967 | mdd_free(NotLabeledAllFairness); |
---|
968 | strength = TRUE; |
---|
969 | } |
---|
970 | |
---|
971 | return strength; |
---|
972 | } |
---|
973 | |
---|
974 | /**Function******************************************************************** |
---|
975 | |
---|
976 | Synopsis [Compare the size of two mdds.] |
---|
977 | |
---|
978 | Description [Used to sort the array of mdds by their number of minterms.] |
---|
979 | |
---|
980 | SideEffects [SortMddArrayBySize] |
---|
981 | |
---|
982 | ******************************************************************************/ |
---|
983 | static st_table *array_mdd_compare_table = NIL(st_table); |
---|
984 | static int |
---|
985 | array_mdd_compare_size( |
---|
986 | const void *obj1, |
---|
987 | const void *obj2) |
---|
988 | { |
---|
989 | double *val1, *val2; |
---|
990 | int flag1, flag2; |
---|
991 | |
---|
992 | flag1 = st_lookup(array_mdd_compare_table, *((char **)obj1), &val1); |
---|
993 | flag2 = st_lookup(array_mdd_compare_table, *((char **)obj2), &val2); |
---|
994 | assert(flag1 && flag2); |
---|
995 | |
---|
996 | if (*val1 < *val2) |
---|
997 | return -1; |
---|
998 | else if (*val1> *val2) |
---|
999 | return +1; |
---|
1000 | else |
---|
1001 | return 0; |
---|
1002 | } |
---|
1003 | |
---|
1004 | /**Function******************************************************************** |
---|
1005 | |
---|
1006 | Synopsis [Sort the array of mdds by their number of minterms.] |
---|
1007 | |
---|
1008 | Description [Sort the array of mdds by their number of minterms. The |
---|
1009 | present state variables of the given FSM is used to count the |
---|
1010 | minterms. The sorting will be skipped if the number of present state |
---|
1011 | variables is larger than 1024.] |
---|
1012 | |
---|
1013 | SideEffects [array_mdd_compare_size] |
---|
1014 | |
---|
1015 | ******************************************************************************/ |
---|
1016 | static array_t * |
---|
1017 | SortMddArrayBySize(Fsm_Fsm_t *fsm, array_t *mddArray) |
---|
1018 | { |
---|
1019 | mdd_manager *mddManager = Fsm_FsmReadMddManager(fsm); |
---|
1020 | array_t *psVars = Fsm_FsmReadPresentStateVars(fsm); |
---|
1021 | |
---|
1022 | if (array_n(psVars) < 1024) { |
---|
1023 | st_table *mddToSizeTable =st_init_table(st_ptrcmp, st_ptrhash); |
---|
1024 | double *sizes = ALLOC(double, array_n(mddArray)); |
---|
1025 | mdd_t *mdd1; |
---|
1026 | int i; |
---|
1027 | |
---|
1028 | arrayForEachItem(mdd_t *, mddArray, i, mdd1) { |
---|
1029 | *(sizes+i) = mdd_count_onset(mddManager, mdd1, psVars); |
---|
1030 | st_insert(mddToSizeTable, (char *)mdd1, (char *)(sizes+i)); |
---|
1031 | } |
---|
1032 | |
---|
1033 | array_mdd_compare_table = mddToSizeTable; |
---|
1034 | array_sort(mddArray, array_mdd_compare_size); |
---|
1035 | |
---|
1036 | FREE(sizes); |
---|
1037 | st_free_table(mddToSizeTable); |
---|
1038 | } |
---|
1039 | |
---|
1040 | return mddArray; |
---|
1041 | } |
---|
1042 | |
---|
1043 | |
---|
1044 | /**Function******************************************************************** |
---|
1045 | |
---|
1046 | Synopsis [Compare two strings] |
---|
1047 | |
---|
1048 | SideEffects [] |
---|
1049 | |
---|
1050 | ******************************************************************************/ |
---|
1051 | static int |
---|
1052 | stringCompare( |
---|
1053 | const void * s1, |
---|
1054 | const void * s2) |
---|
1055 | { |
---|
1056 | return(strcmp(*(char **)s1, *(char **)s2)); |
---|
1057 | } |
---|
1058 | |
---|
1059 | |
---|