[14] | 1 | /**CFile*********************************************************************** |
---|
| 2 | |
---|
| 3 | FileName [bmcAutUtil.c] |
---|
| 4 | |
---|
| 5 | PackageName [bmc] |
---|
| 6 | |
---|
| 7 | Synopsis [Utility file for BMC_Automaton] |
---|
| 8 | |
---|
| 9 | Author [Mohammad Awedh] |
---|
| 10 | |
---|
| 11 | Copyright [This file was created at the University of Colorado at |
---|
| 12 | Boulder. The University of Colorado at Boulder makes no warranty |
---|
| 13 | about the suitability of this software for any purpose. It is |
---|
| 14 | presented on an AS IS basis.] |
---|
| 15 | ******************************************************************************/ |
---|
| 16 | |
---|
| 17 | #include "bmc.h" |
---|
| 18 | #include "bmcInt.h" |
---|
| 19 | |
---|
| 20 | static char rcsid[] UNUSED = "$Id: bmcAutUtil.c,v 1.18 2005/05/18 18:11:52 jinh Exp $"; |
---|
| 21 | |
---|
| 22 | /*---------------------------------------------------------------------------*/ |
---|
| 23 | /* Constant declarations */ |
---|
| 24 | /*---------------------------------------------------------------------------*/ |
---|
| 25 | |
---|
| 26 | /*---------------------------------------------------------------------------*/ |
---|
| 27 | /* Type declarations */ |
---|
| 28 | /*---------------------------------------------------------------------------*/ |
---|
| 29 | |
---|
| 30 | |
---|
| 31 | /*---------------------------------------------------------------------------*/ |
---|
| 32 | /* Structure declarations */ |
---|
| 33 | /*---------------------------------------------------------------------------*/ |
---|
| 34 | |
---|
| 35 | |
---|
| 36 | /*---------------------------------------------------------------------------*/ |
---|
| 37 | /* Variable declarations */ |
---|
| 38 | /*---------------------------------------------------------------------------*/ |
---|
| 39 | |
---|
| 40 | |
---|
| 41 | /**AutomaticStart*************************************************************/ |
---|
| 42 | |
---|
| 43 | /*---------------------------------------------------------------------------*/ |
---|
| 44 | /* Static function prototypes */ |
---|
| 45 | /*---------------------------------------------------------------------------*/ |
---|
| 46 | |
---|
| 47 | static st_table * AutomatonVertexGetImg(graph_t *G, vertex_t *vtx); |
---|
| 48 | static st_table * AutomatonVertexGetPreImg(graph_t *G, vertex_t *vtx); |
---|
| 49 | static int stIntersect(st_table *tbl1, st_table *tbl2); |
---|
| 50 | static int NoOfBitEncode(int n); |
---|
| 51 | static bdd_t * encodeOfInteger(mdd_manager *manager, array_t *varArray, int val); |
---|
| 52 | |
---|
| 53 | /**AutomaticEnd***************************************************************/ |
---|
| 54 | |
---|
| 55 | |
---|
| 56 | /*---------------------------------------------------------------------------*/ |
---|
| 57 | /* Definition of exported functions */ |
---|
| 58 | /*---------------------------------------------------------------------------*/ |
---|
| 59 | |
---|
| 60 | |
---|
| 61 | /*---------------------------------------------------------------------------*/ |
---|
| 62 | /* Definition of internal functions */ |
---|
| 63 | /*---------------------------------------------------------------------------*/ |
---|
| 64 | |
---|
| 65 | /**Function******************************************************************** |
---|
| 66 | |
---|
| 67 | Synopsis [Encode the states of the Automaton.] |
---|
| 68 | |
---|
| 69 | Description [] |
---|
| 70 | |
---|
| 71 | SideEffects [] |
---|
| 72 | |
---|
| 73 | SeeAlso [] |
---|
| 74 | |
---|
| 75 | ******************************************************************************/ |
---|
| 76 | void |
---|
| 77 | BmcAutEncodeAutomatonStates( |
---|
| 78 | Ntk_Network_t *network, |
---|
| 79 | Ltl_Automaton_t *automaton) |
---|
| 80 | { |
---|
| 81 | mdd_manager *manager = Ntk_NetworkReadMddManager(network); |
---|
| 82 | lsGen lsGen, lsGen1; |
---|
| 83 | vertex_t *vtx; |
---|
| 84 | Ltl_AutomatonNode_t *node, *node1; |
---|
| 85 | Ctlsp_Formula_t *F; |
---|
| 86 | mdd_t *label; |
---|
| 87 | |
---|
| 88 | int i; |
---|
| 89 | |
---|
| 90 | /* |
---|
| 91 | Build the mdd of the labels of each automaton node |
---|
| 92 | */ |
---|
| 93 | foreach_vertex(automaton->G, lsGen, vtx) { |
---|
| 94 | node = (Ltl_AutomatonNode_t *) vtx->user_data; |
---|
| 95 | if (node->Labels) { |
---|
| 96 | label = mdd_one(manager); |
---|
| 97 | for (i=0; i<array_n(automaton->labelTable); i++) { |
---|
| 98 | if (LtlSetGetElt(node->Labels, i)) { |
---|
| 99 | F = array_fetch(Ctlsp_Formula_t *, automaton->labelTable, i); |
---|
| 100 | label = mdd_and(label, BmcAutBuildMddForPropositionalFormula(network, automaton, F), 1, 1); |
---|
| 101 | } |
---|
| 102 | } |
---|
| 103 | node->Encode = label; |
---|
| 104 | } |
---|
| 105 | } |
---|
| 106 | /* |
---|
| 107 | Encode automaton labels |
---|
| 108 | */ |
---|
| 109 | foreach_vertex(automaton->G, lsGen, vtx) { |
---|
| 110 | bdd_t *newVar = NULL; |
---|
| 111 | |
---|
| 112 | node = (Ltl_AutomatonNode_t *) vtx->user_data; |
---|
| 113 | foreach_vertex(automaton->G, lsGen1, vtx) { |
---|
| 114 | node1 = (Ltl_AutomatonNode_t *) vtx->user_data; |
---|
| 115 | if(node != node1){ |
---|
| 116 | if(newVar == NULL){ |
---|
| 117 | newVar = bdd_create_variable(manager); |
---|
| 118 | node->Encode = bdd_and(node->Encode, newVar, 1, 1); |
---|
| 119 | } |
---|
| 120 | node1->Encode = bdd_and(node1->Encode, bdd_not(newVar), 1, 1); |
---|
| 121 | } |
---|
| 122 | } |
---|
| 123 | } |
---|
| 124 | } /* BmcAutEncodeAutomatonStates() */ |
---|
| 125 | |
---|
| 126 | |
---|
| 127 | /**Function******************************************************************** |
---|
| 128 | |
---|
| 129 | Synopsis [Encode the states of the Automaton.] |
---|
| 130 | |
---|
| 131 | Description [The labels of each node in the automaton are |
---|
| 132 | propositional and are asserted by state variables in the original |
---|
| 133 | model. So, we uses these labels as part of the state encoding of the |
---|
| 134 | automaton. If two nodes cannot be uniquely specified, then we use |
---|
| 135 | new variables] |
---|
| 136 | |
---|
| 137 | SideEffects [] |
---|
| 138 | |
---|
| 139 | SeeAlso [] |
---|
| 140 | |
---|
| 141 | ******************************************************************************/ |
---|
| 142 | void |
---|
| 143 | BmcAutEncodeAutomatonStates2( |
---|
| 144 | Ntk_Network_t *network, |
---|
| 145 | Ltl_Automaton_t *automaton) |
---|
| 146 | { |
---|
| 147 | mdd_manager *manager = Ntk_NetworkReadMddManager(network); |
---|
| 148 | lsGen lsGen, lsGen1; |
---|
| 149 | vertex_t *vtx; |
---|
| 150 | Ltl_AutomatonNode_t *node, *node1; |
---|
| 151 | Ctlsp_Formula_t *F; |
---|
| 152 | mdd_t *label; |
---|
| 153 | |
---|
| 154 | int i; |
---|
| 155 | |
---|
| 156 | /* |
---|
| 157 | Build the mdd for the labels of each automaton node. |
---|
| 158 | */ |
---|
| 159 | foreach_vertex(automaton->G, lsGen, vtx) { |
---|
| 160 | node = (Ltl_AutomatonNode_t *) vtx->user_data; |
---|
| 161 | if (node->Labels) { |
---|
| 162 | label = mdd_one(manager); |
---|
| 163 | for (i=0; i<array_n(automaton->labelTable); i++) { |
---|
| 164 | if (LtlSetGetElt(node->Labels, i)) { |
---|
| 165 | F = array_fetch(Ctlsp_Formula_t *, automaton->labelTable, i); |
---|
| 166 | label = mdd_and(label, BmcAutBuildMddForPropositionalFormula(network, automaton, F), 1, 1); |
---|
| 167 | } |
---|
| 168 | } |
---|
| 169 | node->Encode = label; |
---|
| 170 | } |
---|
| 171 | } |
---|
| 172 | /* |
---|
| 173 | Three cases: |
---|
| 174 | 1- node and node1 are both = 1 |
---|
| 175 | 2- node1 = 1 |
---|
| 176 | 3- neither node nor nod1 equal to 1 |
---|
| 177 | */ |
---|
| 178 | foreach_vertex(automaton->G, lsGen, vtx) { |
---|
| 179 | bdd_t *newVar = NULL; |
---|
| 180 | st_table *preState, *preState1; |
---|
| 181 | |
---|
| 182 | node = (Ltl_AutomatonNode_t *) vtx->user_data; |
---|
| 183 | preState = AutomatonVertexGetPreImg(automaton->G, vtx); |
---|
| 184 | |
---|
| 185 | foreach_vertex(automaton->G, lsGen1, vtx) { |
---|
| 186 | node1 = (Ltl_AutomatonNode_t *) vtx->user_data; |
---|
| 187 | if(node != node1){ |
---|
| 188 | if (!mdd_is_tautology(mdd_and(node->Encode, node1->Encode, 1,1),0)){ |
---|
| 189 | preState1 = AutomatonVertexGetPreImg(automaton->G, vtx); |
---|
| 190 | if (stIntersect(preState, preState1)){ |
---|
| 191 | if(mdd_equal(node->Encode, mdd_one(manager)) && !mdd_equal(node1->Encode, mdd_one(manager))){ |
---|
| 192 | node->Encode = bdd_not(node1->Encode); |
---|
| 193 | } else |
---|
| 194 | if(mdd_equal(node1->Encode, mdd_one(manager)) && !mdd_equal(node->Encode, mdd_one(manager))){ |
---|
| 195 | node1->Encode = bdd_not(node->Encode); |
---|
| 196 | } else { |
---|
| 197 | if(newVar == NULL){ |
---|
| 198 | newVar = bdd_create_variable(manager); |
---|
| 199 | } |
---|
| 200 | node1->Encode = bdd_and(node1->Encode, bdd_not(newVar), 1, 1); |
---|
| 201 | node->Encode = bdd_and(node->Encode, bdd_not(node1->Encode), 1, 1); |
---|
| 202 | } |
---|
| 203 | } else { |
---|
| 204 | if(newVar == NULL){ |
---|
| 205 | newVar = bdd_create_variable(manager); |
---|
| 206 | node->Encode = bdd_and(node->Encode, newVar, 1, 1); |
---|
| 207 | } |
---|
| 208 | node1->Encode = bdd_and(node1->Encode, bdd_not(newVar), 1, 1); |
---|
| 209 | } |
---|
| 210 | } |
---|
| 211 | } |
---|
| 212 | } |
---|
| 213 | } |
---|
| 214 | |
---|
| 215 | #if 0 |
---|
| 216 | /* |
---|
| 217 | Encode the automaton labels |
---|
| 218 | */ |
---|
| 219 | foreach_vertex(automaton->G, lsGen, vtx) { |
---|
| 220 | bdd_t *newVar = NULL; |
---|
| 221 | st_table *nextStates; |
---|
| 222 | Ltl_AutomatonNode_t *nextState; |
---|
| 223 | st_generator *stGen; |
---|
| 224 | |
---|
| 225 | node = (Ltl_AutomatonNode_t *) vtx->user_data; |
---|
| 226 | nextStates = AutomatonVertexGetImg(automaton->G, vtx); |
---|
| 227 | |
---|
| 228 | st_foreach_item(nextStates, stGen, (char **)&vtx, NIL(char *)) { |
---|
| 229 | nextState = (Ltl_AutomatonNode_t *) vtx->user_data; |
---|
| 230 | |
---|
| 231 | if(node != nextState){ |
---|
| 232 | if (!mdd_is_tautology(mdd_and(node->Encode, nextState->Encode, 1,1),0)){ |
---|
| 233 | printf("n%d intersects n%d\n", node->index, nextState->index); |
---|
| 234 | if(newVar == NULL){ |
---|
| 235 | newVar = bdd_create_variable(manager); |
---|
| 236 | /*node->Encode = bdd_and(node->Encode, newVar, 1, 1);*/ |
---|
| 237 | } |
---|
| 238 | nextState->Encode = bdd_and(nextState->Encode, bdd_not(newVar), 1, 1); |
---|
| 239 | node->Encode = bdd_and(node->Encode, bdd_not(nextState->Encode), 1, 1); |
---|
| 240 | } |
---|
| 241 | } |
---|
| 242 | } |
---|
| 243 | } |
---|
| 244 | #endif |
---|
| 245 | |
---|
| 246 | } /* BmcAutEncodeAutomatonStates2() */ |
---|
| 247 | |
---|
| 248 | /**Function******************************************************************** |
---|
| 249 | |
---|
| 250 | Synopsis [Encode the states of the Automaton.] |
---|
| 251 | |
---|
| 252 | Description [The labels of each node in the automaton are |
---|
| 253 | propositional and are asserted by state variables in the original |
---|
| 254 | model. So, we uses these labels as part of the state encoding of the |
---|
| 255 | automaton. If two nodes cannot be uniquely specified, then we use |
---|
| 256 | new variables] |
---|
| 257 | |
---|
| 258 | SideEffects [] |
---|
| 259 | |
---|
| 260 | SeeAlso [] |
---|
| 261 | |
---|
| 262 | ******************************************************************************/ |
---|
| 263 | void |
---|
| 264 | BmcAutEncodeAutomatonStates3( |
---|
| 265 | Ntk_Network_t *network, |
---|
| 266 | Ltl_Automaton_t *automaton) |
---|
| 267 | { |
---|
| 268 | mdd_manager *manager = Ntk_NetworkReadMddManager(network); |
---|
| 269 | lsGen lsGen; |
---|
| 270 | st_generator *stGen, *stGen1; |
---|
| 271 | vertex_t *vtx, *vtx1; |
---|
| 272 | Ltl_AutomatonNode_t *node, *node1; |
---|
| 273 | Ctlsp_Formula_t *F; |
---|
| 274 | bdd_t *label; |
---|
| 275 | |
---|
| 276 | int i; |
---|
| 277 | int noOfStates=0; |
---|
| 278 | int noOfBits; |
---|
| 279 | array_t *varArray = array_alloc(bdd_t*,0); |
---|
| 280 | |
---|
| 281 | /* |
---|
| 282 | Build the bdd for the labels of each automaton node. |
---|
| 283 | */ |
---|
| 284 | foreach_vertex(automaton->G, lsGen, vtx) { |
---|
| 285 | node = (Ltl_AutomatonNode_t *) vtx->user_data; |
---|
| 286 | if (node->Labels) { |
---|
| 287 | noOfStates++; |
---|
| 288 | label = bdd_one(manager); |
---|
| 289 | for (i=0; i<array_n(automaton->labelTable); i++) { |
---|
| 290 | if (LtlSetGetElt(node->Labels, i)) { |
---|
| 291 | F = array_fetch(Ctlsp_Formula_t *, automaton->labelTable, i); |
---|
| 292 | label = bdd_and(label, BmcAutBuildMddForPropositionalFormula(network, automaton, F), 1, 1); |
---|
| 293 | } |
---|
| 294 | } |
---|
| 295 | node->Encode = label; |
---|
| 296 | } |
---|
| 297 | } |
---|
| 298 | |
---|
| 299 | st_foreach_item(automaton->Init, stGen, &vtx, NULL) { |
---|
| 300 | node = (Ltl_AutomatonNode_t *) vtx->user_data; |
---|
| 301 | st_foreach_item(automaton->Init, stGen1, &vtx1, NULL) { |
---|
| 302 | node1 = (Ltl_AutomatonNode_t *) vtx1->user_data; |
---|
| 303 | if(node != node1){ |
---|
| 304 | if(mdd_equal(node->Encode, mdd_one(manager)) && !mdd_equal(node1->Encode, mdd_one(manager))){ |
---|
| 305 | node->Encode = bdd_not(node1->Encode); |
---|
| 306 | } else |
---|
| 307 | if(mdd_equal(node1->Encode, mdd_one(manager)) && !mdd_equal(node->Encode, mdd_one(manager))){ |
---|
| 308 | node1->Encode = bdd_not(node->Encode); |
---|
| 309 | } |
---|
| 310 | } |
---|
| 311 | } |
---|
| 312 | } |
---|
| 313 | |
---|
| 314 | noOfBits = NoOfBitEncode(noOfStates); |
---|
| 315 | for(i=0; i< noOfBits; i++){ |
---|
| 316 | array_insert_last(bdd_t*, varArray, bdd_create_variable(manager)); |
---|
| 317 | } |
---|
| 318 | i=0; |
---|
| 319 | foreach_vertex(automaton->G, lsGen, vtx) { |
---|
| 320 | node = (Ltl_AutomatonNode_t *) vtx->user_data; |
---|
| 321 | if (node->Labels) { |
---|
| 322 | node->Encode = bdd_and(node->Encode, encodeOfInteger(manager, varArray, i), 1, 1); |
---|
| 323 | i++; |
---|
| 324 | } |
---|
| 325 | } |
---|
| 326 | } /* BmcAutEncodeAutomatonStates3() */ |
---|
| 327 | |
---|
| 328 | |
---|
| 329 | /**Function******************************************************************** |
---|
| 330 | |
---|
| 331 | Synopsis [Build BDD of the transition relation of the Automaton.] |
---|
| 332 | |
---|
| 333 | Description [] |
---|
| 334 | |
---|
| 335 | SideEffects [] |
---|
| 336 | |
---|
| 337 | SeeAlso [] |
---|
| 338 | |
---|
| 339 | ******************************************************************************/ |
---|
| 340 | void |
---|
| 341 | BmcAutBuildTransitionRelation( |
---|
| 342 | Ntk_Network_t *network, |
---|
| 343 | Ltl_Automaton_t *automaton) |
---|
| 344 | { |
---|
| 345 | mdd_manager *manager = Ntk_NetworkReadMddManager(network); |
---|
| 346 | lsGen lsGen; |
---|
| 347 | st_generator *stGen; |
---|
| 348 | vertex_t *vtx, *vtx1; |
---|
| 349 | Ltl_AutomatonNode_t *state, *nextState; |
---|
| 350 | |
---|
| 351 | |
---|
| 352 | |
---|
| 353 | bdd_t *nextStateBdd, *transitionRelation; |
---|
| 354 | bdd_t *initialState, *fairSet, *fairState; |
---|
| 355 | int i; |
---|
| 356 | bdd_t *bddVar; |
---|
| 357 | st_table *nextStates; |
---|
| 358 | var_set_t *psSupport, *nsSupport; |
---|
| 359 | st_table *FairSet = 0; |
---|
| 360 | array_t *fairSetArray; |
---|
| 361 | |
---|
| 362 | /* |
---|
| 363 | psNsTable (Bdd Id, bdd_t*) |
---|
| 364 | */ |
---|
| 365 | st_table *psNsTable = st_init_table(st_numcmp, st_numhash); |
---|
| 366 | /* |
---|
| 367 | nsPsTable (BDD Id, BDD Id) |
---|
| 368 | */ |
---|
| 369 | st_table *nsPsTable = st_init_table(st_numcmp, st_numhash); |
---|
| 370 | |
---|
| 371 | boolean isComplemented; |
---|
| 372 | int nodeIndex; |
---|
| 373 | |
---|
| 374 | /* |
---|
| 375 | Initialization |
---|
| 376 | */ |
---|
| 377 | transitionRelation = bdd_zero(manager); |
---|
| 378 | |
---|
| 379 | /* |
---|
| 380 | Build the transition relation |
---|
| 381 | */ |
---|
| 382 | foreach_vertex(automaton->G, lsGen, vtx) { |
---|
| 383 | state = (Ltl_AutomatonNode_t *) vtx->user_data; |
---|
| 384 | /* |
---|
| 385 | support is the set of the bddId of the bdd node in the support of the bdd function. |
---|
| 386 | */ |
---|
| 387 | psSupport = bdd_get_support(state->Encode); |
---|
| 388 | for(i=0; i<psSupport->n_elts; i++) { |
---|
| 389 | if (var_set_get_elt(psSupport, i) == 1) { |
---|
| 390 | /* |
---|
| 391 | i is the bdd Id of the variable in the support of the function. |
---|
| 392 | */ |
---|
| 393 | if (!st_lookup(psNsTable, (char *)(long) i, NULL)){ |
---|
| 394 | bddVar = bdd_create_variable(manager); |
---|
| 395 | nodeIndex = bdd_node_read_index(bdd_get_node(bddVar, &isComplemented)); |
---|
| 396 | st_insert(psNsTable, (char *) (long) i, (char *) bddVar); |
---|
| 397 | st_insert(nsPsTable, (char *) (long) nodeIndex, (char *) (long)i); |
---|
| 398 | } |
---|
| 399 | } |
---|
| 400 | } |
---|
| 401 | /* |
---|
| 402 | Get the next states. |
---|
| 403 | */ |
---|
| 404 | nextStates = AutomatonVertexGetImg(automaton->G, vtx); |
---|
| 405 | st_foreach_item(nextStates, stGen, &vtx1, NULL) { |
---|
| 406 | nextState = (Ltl_AutomatonNode_t *) vtx1->user_data; |
---|
| 407 | |
---|
| 408 | nextStateBdd = bdd_dup(nextState->Encode); |
---|
| 409 | nsSupport = bdd_get_support(nextStateBdd); |
---|
| 410 | for(i=0; i<nsSupport->n_elts; i++) { |
---|
| 411 | if (var_set_get_elt(nsSupport, i) == 1) { |
---|
| 412 | bdd_t *tmp; |
---|
| 413 | |
---|
| 414 | if (!st_lookup(psNsTable, (char *)(long)i, &bddVar)){ |
---|
| 415 | bddVar = bdd_create_variable(manager); |
---|
| 416 | nodeIndex = bdd_node_read_index(bdd_get_node(bddVar, &isComplemented)); |
---|
| 417 | st_insert(psNsTable, (char *) (long) i, (char *) bddVar); |
---|
| 418 | st_insert(nsPsTable, (char *) (long) nodeIndex, (char *) (long)i); |
---|
| 419 | } |
---|
| 420 | tmp = nextStateBdd; |
---|
| 421 | nextStateBdd = bdd_compose(nextStateBdd, bdd_get_variable(manager, i), bddVar); |
---|
| 422 | bdd_free(tmp); |
---|
| 423 | } |
---|
| 424 | } |
---|
| 425 | transitionRelation = bdd_or(transitionRelation, bdd_and(state->Encode, nextStateBdd,1 ,1) ,1 ,1); |
---|
| 426 | |
---|
| 427 | } /* for each next states*/ |
---|
| 428 | } /* for each present state */ |
---|
| 429 | |
---|
| 430 | fairSetArray = array_alloc(bdd_t*, 0); |
---|
| 431 | fairSet = 0; |
---|
| 432 | if (lsLength(automaton->Fair) != 0) { |
---|
| 433 | fairSet = bdd_zero(manager); |
---|
| 434 | lsForEachItem(automaton->Fair, lsGen, FairSet) { |
---|
| 435 | fairState = bdd_zero(manager); |
---|
| 436 | st_foreach_item(FairSet, stGen, &vtx, NULL) { |
---|
| 437 | state = (Ltl_AutomatonNode_t *) vtx->user_data; |
---|
| 438 | fairState = bdd_or(fairState, state->Encode,1,1); |
---|
| 439 | } |
---|
| 440 | array_insert_last(bdd_t*, fairSetArray, fairState); |
---|
| 441 | fairSet = bdd_or(fairSet, fairState,1,1); |
---|
| 442 | } |
---|
| 443 | } |
---|
| 444 | initialState = bdd_zero(manager); |
---|
| 445 | st_foreach_item(automaton->Init, stGen, &vtx, NULL) { |
---|
| 446 | state = (Ltl_AutomatonNode_t *) vtx->user_data; |
---|
| 447 | initialState = bdd_or(initialState, state->Encode, 1, 1); |
---|
| 448 | } |
---|
| 449 | automaton->transitionRelation = transitionRelation; |
---|
| 450 | automaton->initialStates = initialState; |
---|
| 451 | automaton->fairSets = fairSet; |
---|
| 452 | automaton->psNsTable = psNsTable; |
---|
| 453 | automaton->nsPsTable = nsPsTable; |
---|
| 454 | automaton->fairSetArray = fairSetArray; |
---|
| 455 | |
---|
| 456 | } /* BmcAutBuildTransitionRelation() */ |
---|
| 457 | |
---|
| 458 | |
---|
| 459 | /**Function******************************************************************** |
---|
| 460 | |
---|
| 461 | Synopsis [Build MDD for a propositional formula.] |
---|
| 462 | |
---|
| 463 | Description [Build MDD for a propositional formula. Returns NIL if the conversion |
---|
| 464 | fails. The calling application is responsible for freeing the returned MDD.] |
---|
| 465 | |
---|
| 466 | SideEffects [] |
---|
| 467 | |
---|
| 468 | SeeAlso [] |
---|
| 469 | |
---|
| 470 | ******************************************************************************/ |
---|
| 471 | mdd_t * |
---|
| 472 | BmcAutBuildMddForPropositionalFormula( |
---|
| 473 | Ntk_Network_t *network, |
---|
| 474 | Ltl_Automaton_t *automaton, |
---|
| 475 | Ctlsp_Formula_t *formula) |
---|
| 476 | { |
---|
| 477 | mdd_manager *manager = Ntk_NetworkReadMddManager(network); |
---|
| 478 | mdd_t *left, *right, *result; |
---|
| 479 | |
---|
| 480 | |
---|
| 481 | if (formula == NIL(Ctlsp_Formula_t)) { |
---|
| 482 | return NIL(mdd_t); |
---|
| 483 | } |
---|
| 484 | if (formula->type == Ctlsp_TRUE_c){ |
---|
| 485 | return bdd_one(manager); |
---|
| 486 | } |
---|
| 487 | if (formula->type == Ctlsp_FALSE_c){ |
---|
| 488 | return mdd_zero(manager); |
---|
| 489 | } |
---|
| 490 | |
---|
| 491 | if (!Ctlsp_isPropositionalFormula(formula)) { |
---|
| 492 | (void) fprintf(vis_stderr, "bmc error: Only propositional formula can be converted to bdd \n"); |
---|
| 493 | fprintf(vis_stdout, "\nFormula: "); |
---|
| 494 | Ctlsp_FormulaPrint(vis_stdout, formula); |
---|
| 495 | fprintf(vis_stdout, "\n"); |
---|
| 496 | return NIL(mdd_t); |
---|
| 497 | } |
---|
| 498 | /* |
---|
| 499 | Atomic proposition. |
---|
| 500 | */ |
---|
| 501 | if (formula->type == Ctlsp_ID_c){ |
---|
| 502 | int is_complemented; |
---|
| 503 | bdd_node *funcNode; |
---|
| 504 | |
---|
| 505 | result = BmcModelCheckAtomicFormula(Fsm_NetworkReadOrCreateFsm(network), formula); |
---|
| 506 | funcNode = bdd_get_node(result, &is_complemented); |
---|
| 507 | if(is_complemented){ |
---|
| 508 | funcNode = bdd_not_bdd_node(funcNode); |
---|
| 509 | } |
---|
| 510 | return result; |
---|
| 511 | } |
---|
| 512 | /* |
---|
| 513 | right can be NIL(mdd_t) for unery operators, but left can't be NIL(mdd_t) |
---|
| 514 | */ |
---|
| 515 | left = BmcAutBuildMddForPropositionalFormula(network, automaton, formula->left); |
---|
| 516 | if (left == NIL(mdd_t)){ |
---|
| 517 | return NIL(mdd_t); |
---|
| 518 | } |
---|
| 519 | right = BmcAutBuildMddForPropositionalFormula(network, automaton, formula->right); |
---|
| 520 | /*assert(right != NIL(mdd_t)); */ |
---|
| 521 | switch(formula->type) { |
---|
| 522 | case Ctlsp_NOT_c: |
---|
| 523 | result = mdd_not(left); |
---|
| 524 | break; |
---|
| 525 | case Ctlsp_OR_c: |
---|
| 526 | result = mdd_or(left, right, 1, 1); |
---|
| 527 | break; |
---|
| 528 | case Ctlsp_AND_c: |
---|
| 529 | result = mdd_and(left, right, 1, 1); |
---|
| 530 | break; |
---|
| 531 | case Ctlsp_THEN_c: |
---|
| 532 | result = mdd_or(left, right, 0, 1); |
---|
| 533 | break; |
---|
| 534 | case Ctlsp_EQ_c: |
---|
| 535 | result = mdd_xnor(left, right); |
---|
| 536 | break; |
---|
| 537 | case Ctlsp_XOR_c: |
---|
| 538 | result = mdd_xor(left, right); |
---|
| 539 | break; |
---|
| 540 | default: |
---|
| 541 | /* |
---|
| 542 | return NIL(mdd_t) if the type is not supported |
---|
| 543 | */ |
---|
| 544 | fail("Unexpected type"); |
---|
| 545 | } |
---|
| 546 | return result; |
---|
| 547 | } |
---|
| 548 | |
---|
| 549 | /**Function******************************************************************** |
---|
| 550 | |
---|
| 551 | Synopsis [Generate CNF for a given BDD function.] |
---|
| 552 | |
---|
| 553 | Description [Generate CNF for a BDD function. This function first |
---|
| 554 | negates the BDD function, and then generates the CNF corresponding |
---|
| 555 | to the OFF-set of the negated function. If the BDD node is a next |
---|
| 556 | state variable, we use the BDD index of the present state variable |
---|
| 557 | corresponding to this variable. We could do this by searching the |
---|
| 558 | nsPSTable. If trans ==1, this function generates a CNF for a |
---|
| 559 | transition from current state to next state, otherwise it generates |
---|
| 560 | CNF for NO transition. |
---|
| 561 | |
---|
| 562 | The function calling this function must add a unit clause to set the |
---|
| 563 | returned value to positive (for function to be true) or negative |
---|
| 564 | (for function to be false). |
---|
| 565 | |
---|
| 566 | ] |
---|
| 567 | |
---|
| 568 | SideEffects [] |
---|
| 569 | |
---|
| 570 | SeeAlso [] |
---|
| 571 | |
---|
| 572 | ******************************************************************************/ |
---|
| 573 | int |
---|
| 574 | BmcAutGenerateCnfForBddOffSet( |
---|
| 575 | bdd_t *function, |
---|
| 576 | int current, |
---|
| 577 | int next, |
---|
| 578 | BmcCnfClauses_t *cnfClauses, |
---|
| 579 | st_table *nsPsTable) |
---|
| 580 | { |
---|
| 581 | bdd_manager *bddManager = bdd_get_manager(function); |
---|
| 582 | bdd_node *node, *funcNode; |
---|
| 583 | int is_complemented; |
---|
| 584 | bdd_gen *gen; |
---|
| 585 | int varIndex; |
---|
| 586 | array_t *tmpClause; |
---|
| 587 | array_t *cube; |
---|
| 588 | int i, value; |
---|
| 589 | int state = current; |
---|
| 590 | bdd_t *bddFunction; |
---|
| 591 | bdd_t *newVar; |
---|
| 592 | |
---|
| 593 | int total=0, ndc=0; |
---|
| 594 | float per; |
---|
| 595 | |
---|
| 596 | if (function == NULL){ |
---|
| 597 | return 0; |
---|
| 598 | } |
---|
| 599 | |
---|
| 600 | funcNode = bdd_get_node(function, &is_complemented); |
---|
| 601 | |
---|
| 602 | if (bdd_is_constant(funcNode)){ |
---|
| 603 | if (is_complemented){ |
---|
| 604 | /* add an empty clause to indicate FALSE (un-satisfiable)*/ |
---|
| 605 | BmcAddEmptyClause(cnfClauses); |
---|
| 606 | } |
---|
| 607 | /*bdd_free(bddFunction); |
---|
| 608 | bdd_free(newVar);*/ |
---|
| 609 | return 0; |
---|
| 610 | } |
---|
| 611 | |
---|
| 612 | newVar = bdd_create_variable(bddManager); |
---|
| 613 | bddFunction = bdd_xnor(newVar, function); |
---|
| 614 | bddFunction = bdd_not(bddFunction); |
---|
| 615 | |
---|
| 616 | foreach_bdd_cube(bddFunction, gen, cube){ |
---|
| 617 | tmpClause = array_alloc(int,0); |
---|
| 618 | arrayForEachItem(int, cube, i, value) { |
---|
| 619 | total++; |
---|
| 620 | if (value != 2){ |
---|
| 621 | int j; |
---|
| 622 | |
---|
| 623 | ndc++; |
---|
| 624 | /* |
---|
| 625 | If the BDD varaible is a next state varaible, we use the corresponding |
---|
| 626 | current state varaible but with next state index. |
---|
| 627 | */ |
---|
| 628 | |
---|
| 629 | if (nsPsTable && st_lookup_int(nsPsTable, (char *)(long)i, &j)){ |
---|
| 630 | node = bdd_bdd_ith_var(bddManager, j); |
---|
| 631 | state = next; |
---|
| 632 | } else { |
---|
| 633 | node = bdd_bdd_ith_var(bddManager, i); |
---|
| 634 | state = current; |
---|
| 635 | } |
---|
| 636 | varIndex = BmcGetCnfVarIndexForBddNode(bddManager, bdd_regular(node), state, cnfClauses); |
---|
| 637 | if (value == 1){ |
---|
| 638 | varIndex = -varIndex; |
---|
| 639 | } |
---|
| 640 | array_insert_last(int, tmpClause, varIndex); |
---|
| 641 | } |
---|
| 642 | } |
---|
| 643 | BmcCnfInsertClause(cnfClauses, tmpClause); |
---|
| 644 | array_free(tmpClause); |
---|
| 645 | }/* foreach_bdd_cube() */ |
---|
| 646 | varIndex = BmcGetCnfVarIndexForBddNode(bddManager, |
---|
| 647 | bdd_regular(bdd_get_node(newVar, &is_complemented)), |
---|
| 648 | current, cnfClauses); |
---|
| 649 | per = ((float) ((float)ndc/(float)total))*100; |
---|
| 650 | return (varIndex); |
---|
| 651 | } /* BmcAutGenerateCnfForBddOffSet() */ |
---|
| 652 | |
---|
| 653 | |
---|
| 654 | /**Function******************************************************************** |
---|
| 655 | |
---|
| 656 | Synopsis [Alloc Memory for BmcCheckForTermination_t] |
---|
| 657 | |
---|
| 658 | SideEffects [] |
---|
| 659 | |
---|
| 660 | SeeAlso [] |
---|
| 661 | ******************************************************************************/ |
---|
| 662 | BmcCheckForTermination_t * |
---|
| 663 | BmcAutTerminationAlloc( |
---|
| 664 | Ntk_Network_t *network, |
---|
| 665 | Ctlsp_Formula_t *ltlFormula, |
---|
| 666 | array_t *constraintArray) |
---|
| 667 | { |
---|
| 668 | BmcCheckForTermination_t *result = ALLOC(BmcCheckForTermination_t, 1); |
---|
| 669 | Ltl_Automaton_t *automaton; |
---|
| 670 | LtlMcOption_t *ltlOptions = LtlMcOptionAlloc(); |
---|
| 671 | |
---|
| 672 | if (!result){ |
---|
| 673 | return result; |
---|
| 674 | } |
---|
| 675 | /* |
---|
| 676 | Build the Buechi Automaton for the negation of the LTL formula. |
---|
| 677 | */ |
---|
| 678 | ltlOptions->algorithm = Ltl2Aut_WRING_c; |
---|
| 679 | ltlOptions->rewriting = TRUE; |
---|
| 680 | ltlOptions->prunefair = TRUE; |
---|
| 681 | ltlOptions->iocompatible = TRUE; |
---|
| 682 | ltlOptions->directsim = TRUE; |
---|
| 683 | ltlOptions->reversesim = TRUE; |
---|
| 684 | ltlOptions->verbosity = McVerbosityNone_c; |
---|
| 685 | ltlOptions->noStrengthReduction = 1; |
---|
| 686 | |
---|
| 687 | automaton = LtlMcFormulaToAutomaton(network, ltlFormula, ltlOptions, 0); |
---|
| 688 | assert(automaton != NIL(Ltl_Automaton_t)); |
---|
| 689 | |
---|
| 690 | /*BmcAutEncodeAutomatonStates(network, automaton); */ |
---|
| 691 | /*mcAutEncodeAutomatonStates2(network, automaton);*/ |
---|
| 692 | BmcAutEncodeAutomatonStates3(network, automaton); |
---|
| 693 | BmcAutBuildTransitionRelation(network, automaton); |
---|
| 694 | |
---|
| 695 | LtlMcOptionFree(ltlOptions); |
---|
| 696 | |
---|
| 697 | result->k = 0; |
---|
| 698 | result->m = -1; |
---|
| 699 | result->n = -1; |
---|
| 700 | result->checkLevel = 0; |
---|
| 701 | result->action = 0; |
---|
| 702 | result->automaton = automaton; |
---|
| 703 | |
---|
| 704 | result->externalConstraints = NIL(Ctlsp_Formula_t); |
---|
| 705 | if(constraintArray != NIL(array_t)){ |
---|
| 706 | Ctlsp_Formula_t *formula1, *formula2; |
---|
| 707 | int j; |
---|
| 708 | |
---|
| 709 | formula1 = NIL(Ctlsp_Formula_t); |
---|
| 710 | arrayForEachItem(Ctlsp_Formula_t *, constraintArray, j, formula2) { |
---|
| 711 | formula2 = Ctlsp_FormulaDup(formula2); |
---|
| 712 | if(formula1 == NIL(Ctlsp_Formula_t)) { |
---|
| 713 | formula1 = formula2; |
---|
| 714 | } else { |
---|
| 715 | formula1 = Ctlsp_FormulaCreate(Ctlsp_OR_c, formula1, formula2); |
---|
| 716 | } |
---|
| 717 | } |
---|
| 718 | result->externalConstraints = formula1; |
---|
| 719 | } |
---|
| 720 | result->internalConstraints = automaton->fairSets; |
---|
| 721 | return result; |
---|
| 722 | } |
---|
| 723 | |
---|
| 724 | /**Function******************************************************************** |
---|
| 725 | |
---|
| 726 | Synopsis [Convert LTL to Automaton] |
---|
| 727 | |
---|
| 728 | Description [] |
---|
| 729 | SideEffects [] |
---|
| 730 | |
---|
| 731 | SeeAlso [] |
---|
| 732 | ******************************************************************************/ |
---|
| 733 | Ltl_Automaton_t * |
---|
| 734 | BmcAutLtlToAutomaton( |
---|
| 735 | Ntk_Network_t *network, |
---|
| 736 | Ctlsp_Formula_t *ltlFormula) |
---|
| 737 | { |
---|
| 738 | Ltl_Automaton_t *automaton; |
---|
| 739 | LtlMcOption_t *ltlOptions = LtlMcOptionAlloc(); |
---|
| 740 | |
---|
| 741 | /* |
---|
| 742 | Build the Buechi Automaton for the negation of the LTL formula. |
---|
| 743 | */ |
---|
| 744 | ltlOptions->algorithm = Ltl2Aut_WRING_c; |
---|
| 745 | ltlOptions->rewriting = TRUE; |
---|
| 746 | ltlOptions->prunefair = TRUE; |
---|
| 747 | ltlOptions->iocompatible = TRUE; |
---|
| 748 | ltlOptions->directsim = TRUE; |
---|
| 749 | ltlOptions->reversesim = TRUE; |
---|
| 750 | ltlOptions->verbosity = McVerbosityNone_c; |
---|
| 751 | ltlOptions->noStrengthReduction = 1; |
---|
| 752 | |
---|
| 753 | automaton = LtlMcFormulaToAutomaton(network, ltlFormula, ltlOptions, 0); |
---|
| 754 | assert(automaton != NIL(Ltl_Automaton_t)); |
---|
| 755 | |
---|
| 756 | return automaton; |
---|
| 757 | } |
---|
| 758 | |
---|
| 759 | |
---|
| 760 | /**Function******************************************************************** |
---|
| 761 | |
---|
| 762 | Synopsis [Free BmcCheckForTermination_t.] |
---|
| 763 | |
---|
| 764 | SideEffects [] |
---|
| 765 | |
---|
| 766 | SeeAlso [] |
---|
| 767 | ******************************************************************************/ |
---|
| 768 | void |
---|
| 769 | BmcAutTerminationFree( |
---|
| 770 | BmcCheckForTermination_t *result) |
---|
| 771 | { |
---|
| 772 | LtlTableau_t *tableau; |
---|
| 773 | Ltl_Automaton_t *automaton = result->automaton; |
---|
| 774 | |
---|
| 775 | tableau = automaton->tableau; |
---|
| 776 | Ltl_AutomatonFree((gGeneric) automaton); |
---|
| 777 | LtlTableauFree(tableau); |
---|
| 778 | if(result->externalConstraints != NIL(Ctlsp_Formula_t)){ |
---|
| 779 | Ctlsp_FormulaFree(result->externalConstraints); |
---|
| 780 | } |
---|
| 781 | |
---|
| 782 | FREE(result); |
---|
| 783 | } |
---|
| 784 | |
---|
| 785 | |
---|
| 786 | /*---------------------------------------------------------------------------*/ |
---|
| 787 | /* Definition of static functions */ |
---|
| 788 | /*---------------------------------------------------------------------------*/ |
---|
| 789 | |
---|
| 790 | /**Function******************************************************************** |
---|
| 791 | |
---|
| 792 | Synopsis [Return the image of the given vertex in the hash table.] |
---|
| 793 | |
---|
| 794 | SideEffects [Result should be freed by the caller.] |
---|
| 795 | |
---|
| 796 | ******************************************************************************/ |
---|
| 797 | static st_table * |
---|
| 798 | AutomatonVertexGetImg( |
---|
| 799 | graph_t *G, |
---|
| 800 | vertex_t *vtx) |
---|
| 801 | { |
---|
| 802 | lsList Img; |
---|
| 803 | lsGen lsgen; |
---|
| 804 | edge_t *e; |
---|
| 805 | vertex_t *s; |
---|
| 806 | st_table *uTable; |
---|
| 807 | |
---|
| 808 | Img = g_get_out_edges(vtx); |
---|
| 809 | |
---|
| 810 | uTable = st_init_table(st_ptrcmp, st_ptrhash); |
---|
| 811 | lsForEachItem(Img, lsgen, e) { |
---|
| 812 | s = g_e_dest(e); |
---|
| 813 | st_insert(uTable, (char *) s, (char *) s); |
---|
| 814 | } |
---|
| 815 | |
---|
| 816 | return uTable; |
---|
| 817 | } |
---|
| 818 | |
---|
| 819 | /**Function******************************************************************** |
---|
| 820 | |
---|
| 821 | Synopsis [Return the pre-image of the given vertex in the hash table.] |
---|
| 822 | |
---|
| 823 | SideEffects [Result should be freed by the caller.] |
---|
| 824 | |
---|
| 825 | ******************************************************************************/ |
---|
| 826 | static st_table * |
---|
| 827 | AutomatonVertexGetPreImg( |
---|
| 828 | graph_t *G, |
---|
| 829 | vertex_t *vtx) |
---|
| 830 | { |
---|
| 831 | lsList preImg; |
---|
| 832 | lsGen lsgen; |
---|
| 833 | edge_t *e; |
---|
| 834 | vertex_t *s; |
---|
| 835 | st_table *uTable; |
---|
| 836 | |
---|
| 837 | preImg = g_get_in_edges(vtx); |
---|
| 838 | |
---|
| 839 | uTable = st_init_table(st_ptrcmp, st_ptrhash); |
---|
| 840 | lsForEachItem(preImg, lsgen, e) { |
---|
| 841 | s = g_e_source(e); |
---|
| 842 | st_insert(uTable, (char *) s, (char *) s); |
---|
| 843 | } |
---|
| 844 | |
---|
| 845 | return uTable; |
---|
| 846 | } |
---|
| 847 | |
---|
| 848 | /**Function******************************************************************** |
---|
| 849 | |
---|
| 850 | Synopsis [Return 1 if tbl1 and tbl2 two intersects.] |
---|
| 851 | |
---|
| 852 | SideEffects [] |
---|
| 853 | |
---|
| 854 | ******************************************************************************/ |
---|
| 855 | static int |
---|
| 856 | stIntersect( |
---|
| 857 | st_table *tbl1, |
---|
| 858 | st_table *tbl2) |
---|
| 859 | { |
---|
| 860 | st_generator *stgen; |
---|
| 861 | vertex_t *vtx; |
---|
| 862 | |
---|
| 863 | st_foreach_item(tbl1, stgen, &vtx, NULL) { |
---|
| 864 | if (st_is_member(tbl2,(char *)vtx)) { |
---|
| 865 | st_free_gen(stgen); |
---|
| 866 | return 1; |
---|
| 867 | } |
---|
| 868 | } |
---|
| 869 | return 0; |
---|
| 870 | } |
---|
| 871 | |
---|
| 872 | /**Function******************************************************************** |
---|
| 873 | |
---|
| 874 | Synopsis [Returns no. of Bit encoding needed for n] |
---|
| 875 | |
---|
| 876 | Description [] |
---|
| 877 | |
---|
| 878 | SideEffects [] |
---|
| 879 | |
---|
| 880 | SeeAlso [] |
---|
| 881 | |
---|
| 882 | ******************************************************************************/ |
---|
| 883 | static int |
---|
| 884 | NoOfBitEncode( |
---|
| 885 | int n) |
---|
| 886 | { |
---|
| 887 | int i = 0; |
---|
| 888 | int j = 1; |
---|
| 889 | |
---|
| 890 | if (n < 2) return 1; /* Takes care of value <= 1 */ |
---|
| 891 | |
---|
| 892 | while (j < n) { |
---|
| 893 | j = j * 2; |
---|
| 894 | i++; |
---|
| 895 | } |
---|
| 896 | return i; |
---|
| 897 | } |
---|
| 898 | |
---|
| 899 | /**Function******************************************************************** |
---|
| 900 | |
---|
| 901 | Synopsis [Returns no. of Bit encoding needed for n] |
---|
| 902 | |
---|
| 903 | Description [] |
---|
| 904 | |
---|
| 905 | SideEffects [] |
---|
| 906 | |
---|
| 907 | SeeAlso [] |
---|
| 908 | |
---|
| 909 | ******************************************************************************/ |
---|
| 910 | static bdd_t * |
---|
| 911 | encodeOfInteger( |
---|
| 912 | mdd_manager *manager, |
---|
| 913 | array_t *varArray, |
---|
| 914 | int val) |
---|
| 915 | { |
---|
| 916 | int i; |
---|
| 917 | bdd_t *returnValue = mdd_one(manager); |
---|
| 918 | int tmp = val; |
---|
| 919 | bdd_t *var; |
---|
| 920 | |
---|
| 921 | for(i=0; i< array_n(varArray); i++){ |
---|
| 922 | var = array_fetch(bdd_t*, varArray, i); |
---|
| 923 | if(tmp%2 == 0){ |
---|
| 924 | returnValue = bdd_and(returnValue, var, 1, 0); |
---|
| 925 | } else { |
---|
| 926 | returnValue = bdd_and(returnValue, var, 1, 1); |
---|
| 927 | } |
---|
| 928 | tmp = tmp / 2; |
---|
| 929 | } |
---|
| 930 | return returnValue; |
---|
| 931 | } |
---|
| 932 | |
---|