[14] | 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 | |
---|