[14] | 1 | /**CFile*********************************************************************** |
---|
| 2 | |
---|
| 3 | FileName [grabUtil.c] |
---|
| 4 | |
---|
| 5 | PackageName [grab] |
---|
| 6 | |
---|
| 7 | Synopsis [The utility functions for abstraction refinement.] |
---|
| 8 | |
---|
| 9 | Description [This file contains the functions to check invariant |
---|
| 10 | properties by the GRAB abstraction refinement algorithm. GRAB stands |
---|
| 11 | for "Generational Refinement of Ariadne's Bundle," in which the |
---|
| 12 | automatic refinement is guided by all shortest abstract |
---|
| 13 | counter-examples. For more information, please check the ICCAD'03 |
---|
| 14 | paper of Wang et al., "Improving Ariadne's Bundle by Following |
---|
| 15 | Multiple Counter-Examples in Abstraction Refinement." ] |
---|
| 16 | |
---|
| 17 | Author [Chao Wang] |
---|
| 18 | |
---|
| 19 | Copyright [Copyright (c) 2004 The Regents of the Univ. of Colorado. |
---|
| 20 | All rights reserved. |
---|
| 21 | |
---|
| 22 | Permission is hereby granted, without written agreement and without |
---|
| 23 | license or royalty fees, to use, copy, modify, and distribute this |
---|
| 24 | software and its documentation for any purpose, provided that the |
---|
| 25 | above copyright notice and the following two paragraphs appear in |
---|
| 26 | all copies of this software.] |
---|
| 27 | |
---|
| 28 | ******************************************************************************/ |
---|
| 29 | |
---|
| 30 | #include "grabInt.h" |
---|
| 31 | |
---|
| 32 | /*---------------------------------------------------------------------------*/ |
---|
| 33 | /* Constant declarations */ |
---|
| 34 | /*---------------------------------------------------------------------------*/ |
---|
| 35 | |
---|
| 36 | /*---------------------------------------------------------------------------*/ |
---|
| 37 | /* Structure declarations */ |
---|
| 38 | /*---------------------------------------------------------------------------*/ |
---|
| 39 | |
---|
| 40 | /*---------------------------------------------------------------------------*/ |
---|
| 41 | /* Type declarations */ |
---|
| 42 | /*---------------------------------------------------------------------------*/ |
---|
| 43 | |
---|
| 44 | /*---------------------------------------------------------------------------*/ |
---|
| 45 | /* Variable declarations */ |
---|
| 46 | /*---------------------------------------------------------------------------*/ |
---|
| 47 | |
---|
| 48 | /*---------------------------------------------------------------------------*/ |
---|
| 49 | /* Macro declarations */ |
---|
| 50 | /*---------------------------------------------------------------------------*/ |
---|
| 51 | |
---|
| 52 | /**AutomaticStart*************************************************************/ |
---|
| 53 | |
---|
| 54 | /*---------------------------------------------------------------------------*/ |
---|
| 55 | /* Static function prototypes */ |
---|
| 56 | /*---------------------------------------------------------------------------*/ |
---|
| 57 | |
---|
| 58 | static void GetFormulaNodes(Ntk_Network_t *network, Ctlp_Formula_t *F, array_t *formulaNodes); |
---|
| 59 | static void GetFaninLatches(Ntk_Node_t *node, st_table *visited, st_table *absVarTable); |
---|
| 60 | static void NodeTableAddCtlFormulaNodes(Ntk_Network_t *network, Ctlp_Formula_t *formula, st_table * nodesTable); |
---|
| 61 | |
---|
| 62 | /**AutomaticEnd***************************************************************/ |
---|
| 63 | |
---|
| 64 | /*---------------------------------------------------------------------------*/ |
---|
| 65 | /* Definition of internal functions */ |
---|
| 66 | /*---------------------------------------------------------------------------*/ |
---|
| 67 | |
---|
| 68 | /**Function******************************************************************** |
---|
| 69 | |
---|
| 70 | Synopsis [Compute the Cone-Of-Influence abstract model.] |
---|
| 71 | |
---|
| 72 | Description [Compute the Cone-Of-Influence abstraction, which |
---|
| 73 | consists of latches in the transitive supprot of the property.] |
---|
| 74 | |
---|
| 75 | SideEffects [] |
---|
| 76 | |
---|
| 77 | ******************************************************************************/ |
---|
| 78 | st_table * |
---|
| 79 | GrabComputeCOIAbstraction( |
---|
| 80 | Ntk_Network_t *network, |
---|
| 81 | Ctlp_Formula_t *invFormula) |
---|
| 82 | { |
---|
| 83 | st_table *formulaNodes; |
---|
| 84 | array_t *formulaCombNodes; |
---|
| 85 | Ntk_Node_t *node; |
---|
| 86 | array_t *nodeArray; |
---|
| 87 | int i; |
---|
| 88 | st_generator *stGen; |
---|
| 89 | st_table *absVarTable; |
---|
| 90 | |
---|
| 91 | /* find network nodes in the immediate support of the property */ |
---|
| 92 | formulaNodes = st_init_table(st_ptrcmp, st_ptrhash); |
---|
| 93 | NodeTableAddCtlFormulaNodes(network, invFormula, formulaNodes); |
---|
| 94 | |
---|
| 95 | /* find network nodes in the transitive fan-in */ |
---|
| 96 | nodeArray = array_alloc(Ntk_Node_t *, 0); |
---|
| 97 | st_foreach_item(formulaNodes, stGen, & node, NIL(char *)) { |
---|
| 98 | array_insert_last( Ntk_Node_t *, nodeArray, node); |
---|
| 99 | } |
---|
| 100 | st_free_table(formulaNodes); |
---|
| 101 | formulaCombNodes = Ntk_NodeComputeTransitiveFaninNodes(network, nodeArray, |
---|
| 102 | FALSE, TRUE); |
---|
| 103 | array_free(nodeArray); |
---|
| 104 | |
---|
| 105 | /* extract all the latches */ |
---|
| 106 | absVarTable = st_init_table(st_ptrcmp, st_ptrhash); |
---|
| 107 | arrayForEachItem(Ntk_Node_t *, formulaCombNodes, i, node) { |
---|
| 108 | if (Ntk_NodeTestIsLatch(node) == TRUE) { |
---|
| 109 | st_insert(absVarTable, node, (char *)0); |
---|
| 110 | } |
---|
| 111 | } |
---|
| 112 | array_free(formulaCombNodes); |
---|
| 113 | |
---|
| 114 | return absVarTable; |
---|
| 115 | } |
---|
| 116 | |
---|
| 117 | /**Function******************************************************************** |
---|
| 118 | |
---|
| 119 | Synopsis [Compute the initial abstract model.] |
---|
| 120 | |
---|
| 121 | Description [Compute the he initial abstraction, which consists of |
---|
| 122 | latches in the immediate supprot of the property.] |
---|
| 123 | |
---|
| 124 | SideEffects [] |
---|
| 125 | |
---|
| 126 | ******************************************************************************/ |
---|
| 127 | st_table * |
---|
| 128 | GrabComputeInitialAbstraction( |
---|
| 129 | Ntk_Network_t *network, |
---|
| 130 | Ctlp_Formula_t *invFormula) |
---|
| 131 | { |
---|
| 132 | array_t *formulaNodes = array_alloc(Ntk_Node_t *, 0); |
---|
| 133 | Ntk_Node_t *node; |
---|
| 134 | int i; |
---|
| 135 | st_table *absVarTable, *visited; |
---|
| 136 | |
---|
| 137 | GetFormulaNodes(network, invFormula, formulaNodes); |
---|
| 138 | |
---|
| 139 | absVarTable = st_init_table(st_ptrcmp, st_ptrhash); |
---|
| 140 | visited = st_init_table(st_ptrcmp, st_ptrhash); |
---|
| 141 | arrayForEachItem(Ntk_Node_t *, formulaNodes, i, node) { |
---|
| 142 | GetFaninLatches(node, visited, absVarTable); |
---|
| 143 | } |
---|
| 144 | |
---|
| 145 | st_free_table(visited); |
---|
| 146 | array_free(formulaNodes); |
---|
| 147 | |
---|
| 148 | return absVarTable; |
---|
| 149 | } |
---|
| 150 | |
---|
| 151 | /**Function******************************************************************** |
---|
| 152 | |
---|
| 153 | Synopsis [Build or update partition for the current abstract model.] |
---|
| 154 | |
---|
| 155 | Description [Build or update partition for the current abstract |
---|
| 156 | model. It is a two-phase process, in which the first phase generated |
---|
| 157 | the Bnvs---intermediate variables that should be created; while the |
---|
| 158 | second phase actually create the BDDs. |
---|
| 159 | |
---|
| 160 | When a non-empty hash table 'absBnvTable' is given, BNVs not in this |
---|
| 161 | table should be treated as inputs---they should not appear in the |
---|
| 162 | partition either. |
---|
| 163 | |
---|
| 164 | When 'absBnvTable' is not provided (e.g. when fine-grain abstraction |
---|
| 165 | is disabled), all relevant BNVs should appear in the partition.] |
---|
| 166 | |
---|
| 167 | SideEffects [] |
---|
| 168 | |
---|
| 169 | ******************************************************************************/ |
---|
| 170 | void |
---|
| 171 | GrabUpdateAbstractPartition( |
---|
| 172 | Ntk_Network_t *network, |
---|
| 173 | st_table *coiBnvTable, |
---|
| 174 | st_table *absVarTable, |
---|
| 175 | st_table *absBnvTable, |
---|
| 176 | int partitionFlag) |
---|
| 177 | { |
---|
| 178 | graph_t *newPart; |
---|
| 179 | st_table *useAbsBnvTable = absBnvTable? absBnvTable:coiBnvTable; |
---|
| 180 | |
---|
| 181 | if (partitionFlag == GRAB_PARTITION_BUILD) { |
---|
| 182 | |
---|
| 183 | /* free the existing partition */ |
---|
| 184 | Ntk_NetworkFreeApplInfo(network, PART_NETWORK_APPL_KEY); |
---|
| 185 | |
---|
| 186 | /* insert bnvs whenever necessary. Note that when the current |
---|
| 187 | * partition is not available, this function will create new bnvs |
---|
| 188 | * and put them into the coiBnvTable. Otherwise, it retrieves |
---|
| 189 | * existing bnvs from the current partiton */ |
---|
| 190 | Part_PartitionReadOrCreateBnvs(network, absVarTable, coiBnvTable); |
---|
| 191 | |
---|
| 192 | /* create the new partition */ |
---|
| 193 | newPart = g_alloc(); |
---|
| 194 | newPart->user_data = (gGeneric)PartPartitionInfoCreate("default", |
---|
| 195 | Ntk_NetworkReadMddManager(network), |
---|
| 196 | Part_Frontier_c); |
---|
| 197 | Part_PartitionWithExistingBnvs(network, newPart, coiBnvTable, |
---|
| 198 | absVarTable, useAbsBnvTable); |
---|
| 199 | Ntk_NetworkAddApplInfo(network, PART_NETWORK_APPL_KEY, |
---|
| 200 | (Ntk_ApplInfoFreeFn) Part_PartitionFreeCallback, |
---|
| 201 | (void *) newPart); |
---|
| 202 | |
---|
| 203 | }else if (partitionFlag == GRAB_PARTITION_UPDATE) { |
---|
| 204 | fprintf(vis_stdout, |
---|
| 205 | "\n ** grab error: GRAB_PARTITION_UPDATE not implemented\n"); |
---|
| 206 | assert(0); |
---|
| 207 | } |
---|
| 208 | |
---|
| 209 | } |
---|
| 210 | |
---|
| 211 | /**Function******************************************************************** |
---|
| 212 | |
---|
| 213 | Synopsis [Create the abstract FSM.] |
---|
| 214 | |
---|
| 215 | Description [Create the abstract FSM. Table 'coiBnvTable' contains |
---|
| 216 | all the BNVs (i.e. intermediate variables), while Table |
---|
| 217 | 'absBnvTable' contains all the visible BNVs. BNVs not in absBnvTable |
---|
| 218 | should be treated as inputs. |
---|
| 219 | |
---|
| 220 | When absBnvTable is NULL (e.g. fine-grain abstraction is disabled), |
---|
| 221 | no BNV is treated as input. |
---|
| 222 | |
---|
| 223 | If independentFlag is TRUE, invisible latches are regarded as |
---|
| 224 | inputs; otherwise, they are regarded as latches.] |
---|
| 225 | |
---|
| 226 | SideEffects [] |
---|
| 227 | |
---|
| 228 | ******************************************************************************/ |
---|
| 229 | Fsm_Fsm_t * |
---|
| 230 | GrabCreateAbstractFsm( |
---|
| 231 | Ntk_Network_t *network, |
---|
| 232 | st_table *coiBnvTable, |
---|
| 233 | st_table *absVarTable, |
---|
| 234 | st_table *absBnvTable, |
---|
| 235 | int partitionFlag, |
---|
| 236 | int independentFlag) |
---|
| 237 | { |
---|
| 238 | Fsm_Fsm_t *fsm; |
---|
| 239 | array_t *absLatches = array_alloc(Ntk_Node_t *, 0); |
---|
| 240 | array_t *invisibleVars = array_alloc(Ntk_Node_t *, 0); |
---|
| 241 | array_t *absInputs = array_alloc(Ntk_Node_t *, 0); |
---|
| 242 | array_t *rootNodesArray = array_alloc(Ntk_Node_t *, 0); |
---|
| 243 | st_table *rawLeafNodesTable = st_init_table(st_ptrcmp, st_ptrhash); |
---|
| 244 | lsList topologicalNodeList; |
---|
| 245 | lsGen lsgen; |
---|
| 246 | st_generator *stgen; |
---|
| 247 | Ntk_Node_t *node; |
---|
| 248 | |
---|
| 249 | GrabUpdateAbstractPartition(network, coiBnvTable, absVarTable, absBnvTable, |
---|
| 250 | partitionFlag); |
---|
| 251 | |
---|
| 252 | /* first, compute the absLatches, invisibleVars, and absInputs: |
---|
| 253 | * absLatches includes all the visible latch variables; |
---|
| 254 | * invisibleVars includes all the invisible latches variables; |
---|
| 255 | * absInputs includes all the primary and pseudo inputs. |
---|
| 256 | */ |
---|
| 257 | st_foreach_item(absVarTable, stgen, &node, NIL(char *)) { |
---|
| 258 | array_insert_last(Ntk_Node_t *, absLatches, node); |
---|
| 259 | array_insert_last(Ntk_Node_t *, rootNodesArray, |
---|
| 260 | Ntk_LatchReadDataInput(node)); |
---|
| 261 | array_insert_last(Ntk_Node_t *, rootNodesArray, |
---|
| 262 | Ntk_LatchReadInitialInput(node)); |
---|
| 263 | } |
---|
| 264 | |
---|
| 265 | Ntk_NetworkForEachCombInput(network, lsgen, node) { |
---|
| 266 | st_insert(rawLeafNodesTable, node, (char *) (long) (-1) ); |
---|
| 267 | } |
---|
| 268 | st_foreach_item(coiBnvTable, stgen, &node, NIL(char *)) { |
---|
| 269 | /* unless it blongs to the current Abstract Model */ |
---|
| 270 | if (absBnvTable && !st_is_member(absBnvTable, node)) |
---|
| 271 | st_insert(rawLeafNodesTable, node, (char *) (long) (-1) ); |
---|
| 272 | } |
---|
| 273 | |
---|
| 274 | topologicalNodeList = Ntk_NetworkComputeTopologicalOrder(network, |
---|
| 275 | rootNodesArray, |
---|
| 276 | rawLeafNodesTable); |
---|
| 277 | lsForEachItem(topologicalNodeList, lsgen, node){ |
---|
| 278 | if (st_is_member(rawLeafNodesTable, node) && |
---|
| 279 | !st_is_member(absVarTable, node) ) { |
---|
| 280 | /*if (Ntk_NodeTestIsLatch(node) || |
---|
| 281 | coiBnvTable && st_is_member(coiBnvTable, node))*/ |
---|
| 282 | if (Ntk_NodeTestIsLatch(node) || |
---|
| 283 | (coiBnvTable && st_is_member(coiBnvTable, node))) |
---|
| 284 | array_insert_last(Ntk_Node_t *, invisibleVars, node); |
---|
| 285 | else |
---|
| 286 | array_insert_last(Ntk_Node_t *, absInputs, node); |
---|
| 287 | } |
---|
| 288 | } |
---|
| 289 | |
---|
| 290 | lsDestroy(topologicalNodeList, (void (*)(lsGeneric))0); |
---|
| 291 | st_free_table(rawLeafNodesTable); |
---|
| 292 | array_free(rootNodesArray); |
---|
| 293 | |
---|
| 294 | |
---|
| 295 | /* now, create the abstract Fsm according to the value of |
---|
| 296 | * independentFlag when independentFlag is TRUE, the present state |
---|
| 297 | * varaibles are absLatches; otherwise, they contain both absLatches |
---|
| 298 | * and invisibleVars (with such a FSM, preimages may contain |
---|
| 299 | * invisible vars in their supports) |
---|
| 300 | */ |
---|
| 301 | fsm = Fsm_FsmCreateAbstractFsm(network, NIL(graph_t), |
---|
| 302 | absLatches, invisibleVars, absInputs, |
---|
| 303 | NIL(array_t), independentFlag); |
---|
| 304 | |
---|
| 305 | #if 0 |
---|
| 306 | /* for debugging */ |
---|
| 307 | if (partitionFlag == GRAB_PARTITION_NOCHANGE) { |
---|
| 308 | GrabPrintNodeArray("absLatches", absLatches); |
---|
| 309 | GrabPrintNodeArray("invisibleVars", invisibleVars); |
---|
| 310 | GrabPrintNodeArray("absInputs", absInputs); |
---|
| 311 | } |
---|
| 312 | #endif |
---|
| 313 | |
---|
| 314 | array_free(invisibleVars); |
---|
| 315 | array_free(absInputs); |
---|
| 316 | array_free(absLatches); |
---|
| 317 | |
---|
| 318 | |
---|
| 319 | return fsm; |
---|
| 320 | } |
---|
| 321 | |
---|
| 322 | /**Function******************************************************************** |
---|
| 323 | |
---|
| 324 | Synopsis [Computes the set of initial states of set of latches.] |
---|
| 325 | |
---|
| 326 | Description [Computes the set of initial states of a set of latches. |
---|
| 327 | The nodes driving the initial inputs of the latches, called the |
---|
| 328 | initial nodes, must not have latches in their support. If an |
---|
| 329 | initial node is found that has a latch in its transitive fanin, then |
---|
| 330 | a NULL MDD is returned, and a message is written to the |
---|
| 331 | error_string.<p> |
---|
| 332 | |
---|
| 333 | The initial states are computed as follows. For each latch i, the relation |
---|
| 334 | (x_i = g_i(u)) is built, where x_i is the present state variable of latch i, |
---|
| 335 | and g_i(u) is the multi-valued initialization function of latch i, in terms |
---|
| 336 | of the input variables u. These relations are then conjuncted, and the |
---|
| 337 | input variables are existentially quantified from the result |
---|
| 338 | (i.e. init_states(x) = \exists u \[\prod (x_i = g_i(u))\]).] |
---|
| 339 | |
---|
| 340 | SideEffects [The result of the initial state computation is stored with |
---|
| 341 | the FSM.] |
---|
| 342 | |
---|
| 343 | SeeAlso [Fsm_FsmComputeReachableStates] |
---|
| 344 | |
---|
| 345 | ******************************************************************************/ |
---|
| 346 | mdd_t * |
---|
| 347 | GrabComputeInitialStates( |
---|
| 348 | Ntk_Network_t *network, |
---|
| 349 | array_t *psVars) |
---|
| 350 | { |
---|
| 351 | int i = 0; |
---|
| 352 | mdd_t *initStates; |
---|
| 353 | Ntk_Node_t *node; |
---|
| 354 | array_t *initRelnArray; |
---|
| 355 | array_t *initMvfs; |
---|
| 356 | array_t *initNodes; |
---|
| 357 | array_t *initVertices; |
---|
| 358 | array_t *latchMddIds; |
---|
| 359 | array_t *inputVars = array_alloc(int, 0); |
---|
| 360 | array_t *combArray; |
---|
| 361 | st_table *supportNodes; |
---|
| 362 | st_table *supportVertices; |
---|
| 363 | mdd_manager *mddManager = Ntk_NetworkReadMddManager(network); |
---|
| 364 | graph_t *partition = |
---|
| 365 | (graph_t *) Ntk_NetworkReadApplInfo(network, PART_NETWORK_APPL_KEY); |
---|
| 366 | int numLatches; |
---|
| 367 | Img_MethodType imageMethod; |
---|
| 368 | |
---|
| 369 | numLatches = array_n(psVars); |
---|
| 370 | |
---|
| 371 | /* Get the array of initial nodes, both as network nodes and as |
---|
| 372 | * partition vertices. |
---|
| 373 | */ |
---|
| 374 | initNodes = array_alloc(Ntk_Node_t *, numLatches); |
---|
| 375 | initVertices = array_alloc(vertex_t *, numLatches); |
---|
| 376 | latchMddIds = array_alloc(int, numLatches); |
---|
| 377 | for (i=0; i<numLatches; i++){ |
---|
| 378 | int latchMddId = array_fetch(int, psVars, i); |
---|
| 379 | Ntk_Node_t *latch = Ntk_NetworkFindNodeByMddId(network, latchMddId); |
---|
| 380 | Ntk_Node_t *initNode = Ntk_LatchReadInitialInput(latch); |
---|
| 381 | vertex_t *initVertex = Part_PartitionFindVertexByName(partition, |
---|
| 382 | Ntk_NodeReadName(initNode)); |
---|
| 383 | array_insert(Ntk_Node_t *, initNodes, i, initNode); |
---|
| 384 | array_insert(vertex_t *, initVertices, i, initVertex); |
---|
| 385 | array_insert(int, latchMddIds, i, Ntk_NodeReadMddId(latch)); |
---|
| 386 | } |
---|
| 387 | |
---|
| 388 | /* Get the table of legal support nodes, both as network nodes and |
---|
| 389 | * as partition vertices. Inputs (both primary and pseudo) and |
---|
| 390 | * constants constitute the legal support nodes. |
---|
| 391 | */ |
---|
| 392 | supportNodes = st_init_table(st_ptrcmp, st_ptrhash); |
---|
| 393 | supportVertices = st_init_table(st_ptrcmp, st_ptrhash); |
---|
| 394 | combArray = Ntk_NodeComputeTransitiveFaninNodes(network, initNodes, TRUE, |
---|
| 395 | TRUE); |
---|
| 396 | arrayForEachItem(Ntk_Node_t *, combArray, i, node) { |
---|
| 397 | vertex_t *vertex = Part_PartitionFindVertexByName(partition, |
---|
| 398 | Ntk_NodeReadName(node)); |
---|
| 399 | if (Ntk_NodeTestIsConstant(node) || Ntk_NodeTestIsInput(node)) { |
---|
| 400 | st_insert(supportNodes, node, NIL(char)); |
---|
| 401 | st_insert(supportVertices, vertex, NIL(char)); |
---|
| 402 | } |
---|
| 403 | if (Ntk_NodeTestIsInput(node)) { |
---|
| 404 | assert(Ntk_NodeReadMddId(node) != -1); |
---|
| 405 | array_insert_last(int, inputVars, Ntk_NodeReadMddId(node)); |
---|
| 406 | } |
---|
| 407 | } |
---|
| 408 | array_free(combArray); |
---|
| 409 | array_free(initNodes); |
---|
| 410 | st_free_table(supportNodes); |
---|
| 411 | |
---|
| 412 | /* Compute the initial states |
---|
| 413 | */ |
---|
| 414 | initMvfs = Part_PartitionCollapse(partition, initVertices, |
---|
| 415 | supportVertices, NIL(mdd_t)); |
---|
| 416 | array_free(initVertices); |
---|
| 417 | st_free_table(supportVertices); |
---|
| 418 | |
---|
| 419 | /* Compute the relation (x_i = g_i(u)) for each latch. */ |
---|
| 420 | initRelnArray = array_alloc(mdd_t*, numLatches); |
---|
| 421 | for (i = 0; i < numLatches; i++) { |
---|
| 422 | int latchMddId = array_fetch(int, latchMddIds, i); |
---|
| 423 | Mvf_Function_t *initMvf = array_fetch(Mvf_Function_t *, initMvfs, i); |
---|
| 424 | mdd_t *initLatchReln = Mvf_FunctionBuildRelationWithVariable(initMvf, |
---|
| 425 | latchMddId); |
---|
| 426 | array_insert(mdd_t *, initRelnArray, i, initLatchReln); |
---|
| 427 | } |
---|
| 428 | |
---|
| 429 | array_free(latchMddIds); |
---|
| 430 | Mvf_FunctionArrayFree(initMvfs); |
---|
| 431 | |
---|
| 432 | imageMethod = Img_UserSpecifiedMethod(); |
---|
| 433 | if (imageMethod != Img_Iwls95_c && imageMethod != Img_Mlp_c) |
---|
| 434 | imageMethod = Img_Iwls95_c; |
---|
| 435 | |
---|
| 436 | initStates = Img_MultiwayLinearAndSmooth(mddManager, initRelnArray, |
---|
| 437 | inputVars, psVars, |
---|
| 438 | imageMethod, Img_Forward_c); |
---|
| 439 | |
---|
| 440 | mdd_array_free(initRelnArray); |
---|
| 441 | |
---|
| 442 | array_free(inputVars); |
---|
| 443 | |
---|
| 444 | return (initStates); |
---|
| 445 | } |
---|
| 446 | |
---|
| 447 | /**Function******************************************************************** |
---|
| 448 | |
---|
| 449 | Synopsis [Compute the reachable states of the abstract model.] |
---|
| 450 | |
---|
| 451 | Description [Compute the reachable states of the abstract model.] |
---|
| 452 | |
---|
| 453 | SideEffects [] |
---|
| 454 | |
---|
| 455 | ******************************************************************************/ |
---|
| 456 | mdd_t * |
---|
| 457 | GrabFsmComputeReachableStates( |
---|
| 458 | Fsm_Fsm_t *absFsm, |
---|
| 459 | st_table *absVarTable, |
---|
| 460 | st_table *absBnvTable, |
---|
| 461 | array_t *invStatesArray, |
---|
| 462 | int verbose) |
---|
| 463 | { |
---|
| 464 | mdd_manager *mddManager = Fsm_FsmReadMddManager(absFsm); |
---|
| 465 | Img_ImageInfo_t *imageInfo; |
---|
| 466 | array_t *fwdOnionRings; |
---|
| 467 | mdd_t *initStates, *mdd1, *mddOne, *rchStates, *frontier; |
---|
| 468 | |
---|
| 469 | imageInfo = Fsm_FsmReadOrCreateImageInfo(absFsm, 0, 1); |
---|
| 470 | |
---|
| 471 | fwdOnionRings = array_alloc(mdd_t *, 0); |
---|
| 472 | mddOne = mdd_one(mddManager); |
---|
| 473 | initStates = Fsm_FsmComputeInitialStates(absFsm); |
---|
| 474 | array_insert_last(mdd_t *, fwdOnionRings, initStates); |
---|
| 475 | rchStates = mdd_dup(initStates); |
---|
| 476 | |
---|
| 477 | frontier = initStates; |
---|
| 478 | while(TRUE) { |
---|
| 479 | mdd1 = Img_ImageInfoComputeFwdWithDomainVars(imageInfo, frontier, |
---|
| 480 | rchStates, mddOne); |
---|
| 481 | frontier = mdd_and(mdd1, rchStates, 1, 0); |
---|
| 482 | mdd_free(mdd1); |
---|
| 483 | |
---|
| 484 | mdd1 = rchStates; |
---|
| 485 | rchStates = mdd_or(rchStates, frontier, 1, 1); |
---|
| 486 | mdd_free(mdd1); |
---|
| 487 | |
---|
| 488 | if (mdd_is_tautology(frontier, 0)) { |
---|
| 489 | mdd_free(frontier); |
---|
| 490 | break; |
---|
| 491 | } |
---|
| 492 | array_insert_last(mdd_t *, fwdOnionRings, frontier); |
---|
| 493 | |
---|
| 494 | /* if this happens, the invariant is voilated */ |
---|
| 495 | if (!mdd_lequal_array(frontier, invStatesArray, 1, 1)) |
---|
| 496 | break; |
---|
| 497 | } |
---|
| 498 | |
---|
| 499 | mdd_free(mddOne); |
---|
| 500 | |
---|
| 501 | FsmSetReachabilityOnionRings(absFsm, fwdOnionRings); |
---|
| 502 | |
---|
| 503 | return rchStates; |
---|
| 504 | } |
---|
| 505 | |
---|
| 506 | /**Function******************************************************************** |
---|
| 507 | |
---|
| 508 | Synopsis [Compute the reachable states inside the SORs.] |
---|
| 509 | |
---|
| 510 | Description [Compute the reachable states inside the SORs.] |
---|
| 511 | |
---|
| 512 | SideEffects [] |
---|
| 513 | |
---|
| 514 | ******************************************************************************/ |
---|
| 515 | mdd_t * |
---|
| 516 | GrabFsmComputeConstrainedReachableStates( |
---|
| 517 | Fsm_Fsm_t *absFsm, |
---|
| 518 | st_table *absVarTable, |
---|
| 519 | st_table *absBnvTable, |
---|
| 520 | array_t *SORs, |
---|
| 521 | int verbose) |
---|
| 522 | { |
---|
| 523 | mdd_manager *mddManager = Fsm_FsmReadMddManager(absFsm); |
---|
| 524 | Img_ImageInfo_t *imageInfo; |
---|
| 525 | array_t *rchOnionRings; |
---|
| 526 | mdd_t *mdd1, *mdd2, *mdd3, *mdd4; |
---|
| 527 | mdd_t *mddOne, *initStates, *rchStates; |
---|
| 528 | int i; |
---|
| 529 | |
---|
| 530 | assert (SORs != NIL(array_t)); |
---|
| 531 | |
---|
| 532 | imageInfo = Fsm_FsmReadOrCreateImageInfo(absFsm, 0, 1); |
---|
| 533 | |
---|
| 534 | rchOnionRings = array_alloc(mdd_t *, 0); |
---|
| 535 | mddOne = mdd_one(mddManager); |
---|
| 536 | |
---|
| 537 | /* the new initial states */ |
---|
| 538 | mdd2 = array_fetch(mdd_t *, SORs, 0); |
---|
| 539 | mdd1 = Fsm_FsmComputeInitialStates(absFsm); |
---|
| 540 | initStates = mdd_and(mdd1, mdd2, 1, 1); |
---|
| 541 | mdd_free(mdd1); |
---|
| 542 | array_insert(mdd_t *, rchOnionRings, 0, initStates); |
---|
| 543 | |
---|
| 544 | /* compute the reachable states inside the previous SORs */ |
---|
| 545 | rchStates = mdd_dup(initStates); |
---|
| 546 | for (i=0; i<array_n(SORs)-1; i++) { |
---|
| 547 | mdd1 = array_fetch(mdd_t *, rchOnionRings, i); |
---|
| 548 | mdd2 = Img_ImageInfoComputeFwdWithDomainVars(imageInfo, |
---|
| 549 | mdd1, |
---|
| 550 | rchStates, |
---|
| 551 | mddOne); |
---|
| 552 | |
---|
| 553 | mdd3 = array_fetch(mdd_t *, SORs, i+1); |
---|
| 554 | mdd4 = mdd_and(mdd2, mdd3, 1, 1); |
---|
| 555 | mdd_free(mdd2); |
---|
| 556 | |
---|
| 557 | /* if this happens, the last ring is no longer reachable */ |
---|
| 558 | if (mdd_is_tautology(mdd4, 0)) { |
---|
| 559 | mdd_free(mdd4); |
---|
| 560 | break; |
---|
| 561 | } |
---|
| 562 | array_insert(mdd_t *, rchOnionRings, i+1, mdd4); |
---|
| 563 | |
---|
| 564 | mdd1 = rchStates; |
---|
| 565 | rchStates = mdd_or(rchStates, mdd4, 1, 1); |
---|
| 566 | mdd_free(mdd1); |
---|
| 567 | } |
---|
| 568 | |
---|
| 569 | mdd_free(mddOne); |
---|
| 570 | |
---|
| 571 | FsmSetReachabilityOnionRings(absFsm, rchOnionRings); |
---|
| 572 | |
---|
| 573 | return rchStates; |
---|
| 574 | } |
---|
| 575 | |
---|
| 576 | /**Function******************************************************************** |
---|
| 577 | |
---|
| 578 | Synopsis [Compute the Synchronous Onion Rings (SORs).] |
---|
| 579 | |
---|
| 580 | Description [Compute the Synchronous Onion Rings (SORs) with |
---|
| 581 | backward reachability analysis. The SORs capture all the shortest |
---|
| 582 | counter-examples to an invariant property. If the forward |
---|
| 583 | reachability onion rings is not provided (as oldRings), it will be |
---|
| 584 | retrived from absFsm. |
---|
| 585 | |
---|
| 586 | cexType controls the type of the counter-example envelope: |
---|
| 587 | GRAB_CEX_MINTERM, a single-state path, |
---|
| 588 | GRAB_CEX_CUBE, a cube-states path, |
---|
| 589 | GRAB_CEX_SOR, the SORs. |
---|
| 590 | ] |
---|
| 591 | |
---|
| 592 | SideEffects [] |
---|
| 593 | |
---|
| 594 | ******************************************************************************/ |
---|
| 595 | array_t * |
---|
| 596 | GrabFsmComputeSynchronousOnionRings( |
---|
| 597 | Fsm_Fsm_t *absFsm, |
---|
| 598 | st_table *absVarTable, |
---|
| 599 | st_table *absBnvTable, |
---|
| 600 | array_t *oldRings, |
---|
| 601 | mdd_t *inv_states, |
---|
| 602 | int cexType, |
---|
| 603 | int verbose) |
---|
| 604 | { |
---|
| 605 | mdd_manager *mddManager = Fsm_FsmReadMddManager(absFsm); |
---|
| 606 | Img_ImageInfo_t *imageInfo; |
---|
| 607 | array_t *onionRings, *synOnionRings; |
---|
| 608 | array_t *allPSVars; |
---|
| 609 | mdd_t *mddOne, *ring; |
---|
| 610 | mdd_t *mdd1, *mdd2, *mdd3, *mdd4; |
---|
| 611 | int j; |
---|
| 612 | |
---|
| 613 | imageInfo = Fsm_FsmReadOrCreateImageInfo(absFsm, 1, 0); |
---|
| 614 | |
---|
| 615 | /* get the forward reachability onion rings */ |
---|
| 616 | onionRings = oldRings; |
---|
| 617 | if (onionRings == NIL(array_t)) |
---|
| 618 | onionRings = Fsm_FsmReadReachabilityOnionRings(absFsm); |
---|
| 619 | assert(onionRings); |
---|
| 620 | |
---|
| 621 | synOnionRings = array_alloc(mdd_t *, array_n(onionRings)); |
---|
| 622 | |
---|
| 623 | mddOne = mdd_one(mddManager); |
---|
| 624 | allPSVars = Fsm_FsmReadPresentStateVars(absFsm); |
---|
| 625 | |
---|
| 626 | /* the last ring */ |
---|
| 627 | mdd2 = array_fetch_last(mdd_t *, onionRings); |
---|
| 628 | mdd1 = mdd_and(mdd2, inv_states, 1, 0); |
---|
| 629 | if (cexType == GRAB_CEX_MINTERM) |
---|
| 630 | ring = Mc_ComputeAMinterm(mdd1, allPSVars, mddManager); |
---|
| 631 | else if (cexType == GRAB_CEX_CUBE) { |
---|
| 632 | array_t *bddIds = mdd_get_bdd_support_ids(mddManager, mdd1); |
---|
| 633 | int nvars = array_n(bddIds); |
---|
| 634 | array_free(bddIds); |
---|
| 635 | ring = bdd_approx_remap_ua(mdd1, (bdd_approx_dir_t)BDD_UNDER_APPROX, |
---|
| 636 | nvars, 1024, 1); |
---|
| 637 | if (ring == NIL(mdd_t)) |
---|
| 638 | ring = mdd_dup(mdd1); |
---|
| 639 | }else |
---|
| 640 | ring = mdd_dup(mdd1); |
---|
| 641 | mdd_free(mdd1); |
---|
| 642 | array_insert(mdd_t *, synOnionRings, array_n(onionRings)-1, ring); |
---|
| 643 | |
---|
| 644 | /* the rest rings */ |
---|
| 645 | for (j=array_n(onionRings)-2; j>=0; j--) { |
---|
| 646 | mdd1 = array_fetch(mdd_t *, synOnionRings, j+1); |
---|
| 647 | mdd2 = Img_ImageInfoComputeBwdWithDomainVars(imageInfo, |
---|
| 648 | mdd1, |
---|
| 649 | mdd1, |
---|
| 650 | mddOne); |
---|
| 651 | |
---|
| 652 | mdd3 = array_fetch(mdd_t *, onionRings, j); |
---|
| 653 | mdd4 = mdd_and(mdd2, mdd3, 1, 1); |
---|
| 654 | mdd_free(mdd2); |
---|
| 655 | |
---|
| 656 | if (cexType == GRAB_CEX_MINTERM) |
---|
| 657 | ring = Mc_ComputeAMinterm(mdd4, allPSVars, mddManager); |
---|
| 658 | else if (cexType == GRAB_CEX_CUBE) { |
---|
| 659 | array_t *bddIds = mdd_get_bdd_support_ids(mddManager, mdd4); |
---|
| 660 | int nvars = array_n(bddIds); |
---|
| 661 | array_free(bddIds); |
---|
| 662 | ring = bdd_approx_remap_ua(mdd4, (bdd_approx_dir_t)BDD_UNDER_APPROX, |
---|
| 663 | nvars, 1024, 1); |
---|
| 664 | if (ring == NIL(mdd_t)) |
---|
| 665 | ring = mdd_dup(mdd4); |
---|
| 666 | }else |
---|
| 667 | ring = mdd_dup(mdd4); |
---|
| 668 | mdd_free(mdd4); |
---|
| 669 | array_insert(mdd_t *, synOnionRings, j, ring); |
---|
| 670 | } |
---|
| 671 | |
---|
| 672 | mdd_free(mddOne); |
---|
| 673 | |
---|
| 674 | return synOnionRings; |
---|
| 675 | } |
---|
| 676 | |
---|
| 677 | /**Function******************************************************************** |
---|
| 678 | |
---|
| 679 | Synopsis [Get the visible variable mddIds of the current abstraction.] |
---|
| 680 | |
---|
| 681 | Description [Get the visible variable mddIds of the current |
---|
| 682 | abstraction. Note that they are the state variables.] |
---|
| 683 | |
---|
| 684 | SideEffects [] |
---|
| 685 | |
---|
| 686 | ******************************************************************************/ |
---|
| 687 | array_t * |
---|
| 688 | GrabGetVisibleVarMddIds ( |
---|
| 689 | Fsm_Fsm_t *absFsm, |
---|
| 690 | st_table *absVarTable) |
---|
| 691 | { |
---|
| 692 | array_t *visibleVarMddIds = array_alloc(int, 0); |
---|
| 693 | st_generator *stgen; |
---|
| 694 | Ntk_Node_t *node; |
---|
| 695 | int mddId; |
---|
| 696 | |
---|
| 697 | st_foreach_item(absVarTable, stgen, &node, NIL(char *)) { |
---|
| 698 | mddId = Ntk_NodeReadMddId(node); |
---|
| 699 | array_insert_last(int, visibleVarMddIds, mddId); |
---|
| 700 | } |
---|
| 701 | |
---|
| 702 | return visibleVarMddIds; |
---|
| 703 | } |
---|
| 704 | |
---|
| 705 | |
---|
| 706 | /**Function******************************************************************** |
---|
| 707 | |
---|
| 708 | Synopsis [Get the invisible variable mddIds of the current abstraction.] |
---|
| 709 | |
---|
| 710 | Description [Get the invisible variable mddIds of the current |
---|
| 711 | abstraction. Note that they include both state variables and boolean |
---|
| 712 | network variables.] |
---|
| 713 | |
---|
| 714 | SideEffects [] |
---|
| 715 | |
---|
| 716 | ******************************************************************************/ |
---|
| 717 | array_t * |
---|
| 718 | GrabGetInvisibleVarMddIds( |
---|
| 719 | Fsm_Fsm_t *absFsm, |
---|
| 720 | st_table *absVarTable, |
---|
| 721 | st_table *absBnvTable) |
---|
| 722 | { |
---|
| 723 | Ntk_Network_t *network = Fsm_FsmReadNetwork(absFsm); |
---|
| 724 | array_t *inputVars = Fsm_FsmReadInputVars(absFsm); |
---|
| 725 | array_t *invisibleVarMddIds = array_alloc(int, 0); |
---|
| 726 | Ntk_Node_t *node; |
---|
| 727 | int i, mddId; |
---|
| 728 | |
---|
| 729 | arrayForEachItem(int, inputVars, i, mddId) { |
---|
| 730 | node = Ntk_NetworkFindNodeByMddId(network, mddId); |
---|
| 731 | if ( !Ntk_NodeTestIsInput(node) && |
---|
| 732 | !st_is_member(absVarTable, node) ) { |
---|
| 733 | if (absBnvTable != NIL(st_table)) { |
---|
| 734 | if (!st_is_member(absBnvTable, node)) { |
---|
| 735 | array_insert_last(int, invisibleVarMddIds, mddId); |
---|
| 736 | } |
---|
| 737 | }else |
---|
| 738 | array_insert_last(int, invisibleVarMddIds, mddId); |
---|
| 739 | } |
---|
| 740 | } |
---|
| 741 | |
---|
| 742 | return invisibleVarMddIds; |
---|
| 743 | } |
---|
| 744 | |
---|
| 745 | /**Function******************************************************************** |
---|
| 746 | |
---|
| 747 | Synopsis [Test whether the refinement set of latches is sufficient.] |
---|
| 748 | |
---|
| 749 | Description [Test whether the refinement set of latches is sufficient.] |
---|
| 750 | |
---|
| 751 | SideEffects [] |
---|
| 752 | |
---|
| 753 | ******************************************************************************/ |
---|
| 754 | int |
---|
| 755 | GrabTestRefinementSetSufficient( |
---|
| 756 | Ntk_Network_t *network, |
---|
| 757 | array_t *SORs, |
---|
| 758 | st_table *absVarTable, |
---|
| 759 | int verbose) |
---|
| 760 | { |
---|
| 761 | int is_sufficient; |
---|
| 762 | |
---|
| 763 | is_sufficient = !Bmc_AbstractCheckAbstractTraces(network, |
---|
| 764 | SORs, |
---|
| 765 | absVarTable, |
---|
| 766 | 0, 0, 0); |
---|
| 767 | return is_sufficient; |
---|
| 768 | } |
---|
| 769 | |
---|
| 770 | /**Function******************************************************************** |
---|
| 771 | |
---|
| 772 | Synopsis [Test whether the refinement set of BNVs is sufficient.] |
---|
| 773 | |
---|
| 774 | Description [Test whether the refinement set of BNVs is sufficient.] |
---|
| 775 | |
---|
| 776 | SideEffects [] |
---|
| 777 | |
---|
| 778 | ******************************************************************************/ |
---|
| 779 | int |
---|
| 780 | GrabTestRefinementBnvSetSufficient( |
---|
| 781 | Ntk_Network_t *network, |
---|
| 782 | st_table *coiBnvTable, |
---|
| 783 | array_t *SORs, |
---|
| 784 | st_table *absVarTable, |
---|
| 785 | st_table *absBnvTable, |
---|
| 786 | int verbose) |
---|
| 787 | { |
---|
| 788 | int is_sufficient; |
---|
| 789 | |
---|
| 790 | assert(absBnvTable && coiBnvTable); |
---|
| 791 | |
---|
| 792 | is_sufficient = |
---|
| 793 | !Bmc_AbstractCheckAbstractTracesWithFineGrain(network, |
---|
| 794 | coiBnvTable, |
---|
| 795 | SORs, |
---|
| 796 | absVarTable, |
---|
| 797 | absBnvTable); |
---|
| 798 | return is_sufficient; |
---|
| 799 | } |
---|
| 800 | |
---|
| 801 | /**Function******************************************************************** |
---|
| 802 | |
---|
| 803 | Synopsis [Minimize the refinement set of latch variable.] |
---|
| 804 | |
---|
| 805 | Description [Minimize the refinement set of latch variable. After |
---|
| 806 | that, also prune away the boolean network variables that are no |
---|
| 807 | longer in the transitive fan-in.] |
---|
| 808 | |
---|
| 809 | SideEffects [] |
---|
| 810 | |
---|
| 811 | ******************************************************************************/ |
---|
| 812 | void |
---|
| 813 | GrabMinimizeLatchRefinementSet( |
---|
| 814 | Ntk_Network_t *network, |
---|
| 815 | st_table **absVarTable, |
---|
| 816 | st_table **absBnvTable, |
---|
| 817 | array_t *newlyAddedLatches, |
---|
| 818 | array_t **newlyAddedBnvs, |
---|
| 819 | array_t *SORs, |
---|
| 820 | int verbose) |
---|
| 821 | { |
---|
| 822 | st_table *newVertexTable, *oldBnvTable, *transFaninTable; |
---|
| 823 | array_t *rootArray, *transFanins, *oldNewlyAddedBnvs; |
---|
| 824 | st_generator *stgen; |
---|
| 825 | Ntk_Node_t *node; |
---|
| 826 | int i, flag, n_size, mddId; |
---|
| 827 | |
---|
| 828 | n_size = array_n(newlyAddedLatches); |
---|
| 829 | |
---|
| 830 | if (verbose >= 3) |
---|
| 831 | fprintf(vis_stdout, |
---|
| 832 | "-- grab: minimize latch refinement set: previous size is %d\n", |
---|
| 833 | n_size); |
---|
| 834 | |
---|
| 835 | arrayForEachItem(int, newlyAddedLatches, i, mddId) { |
---|
| 836 | node = Ntk_NetworkFindNodeByMddId(network, mddId); |
---|
| 837 | /* first, try to drop it */ |
---|
| 838 | newVertexTable = st_copy(*absVarTable); |
---|
| 839 | flag = st_delete(newVertexTable, &node, NIL(char *)); |
---|
| 840 | assert(flag); |
---|
| 841 | /* if the counter-example does not come back, drop it officially */ |
---|
| 842 | flag = Bmc_AbstractCheckAbstractTraces(network,SORs, |
---|
| 843 | newVertexTable, 0, 0, 0); |
---|
| 844 | if (!flag) { |
---|
| 845 | st_free_table(*absVarTable); |
---|
| 846 | *absVarTable = newVertexTable; |
---|
| 847 | n_size--; |
---|
| 848 | }else { |
---|
| 849 | st_free_table(newVertexTable); |
---|
| 850 | if (verbose >= 3) |
---|
| 851 | fprintf(vis_stdout," add back %s (latch)\n", |
---|
| 852 | Ntk_NodeReadName(node)); |
---|
| 853 | } |
---|
| 854 | } |
---|
| 855 | |
---|
| 856 | if (verbose >= 3) |
---|
| 857 | fprintf(vis_stdout, |
---|
| 858 | "-- grab: minimize latch refinement set: current size is %d\n", |
---|
| 859 | n_size); |
---|
| 860 | |
---|
| 861 | /* prune away irrelevant BNVs */ |
---|
| 862 | if (*absBnvTable != NIL(st_table) && st_count(*absBnvTable)>0) { |
---|
| 863 | |
---|
| 864 | rootArray = array_alloc(Ntk_Node_t *, 0); |
---|
| 865 | st_foreach_item(*absVarTable, stgen, &node, NIL(char *)) { |
---|
| 866 | array_insert_last(Ntk_Node_t *, rootArray, Ntk_LatchReadDataInput(node)); |
---|
| 867 | array_insert_last(Ntk_Node_t *, rootArray, |
---|
| 868 | Ntk_LatchReadInitialInput(node)); |
---|
| 869 | } |
---|
| 870 | transFanins = Ntk_NodeComputeTransitiveFaninNodes(network, rootArray, |
---|
| 871 | TRUE, /*stopAtLatch*/ |
---|
| 872 | FALSE /*combInputsOnly*/ |
---|
| 873 | ); |
---|
| 874 | array_free(rootArray); |
---|
| 875 | |
---|
| 876 | transFaninTable = st_init_table(st_ptrcmp, st_ptrhash); |
---|
| 877 | arrayForEachItem(Ntk_Node_t *, transFanins, i, node) { |
---|
| 878 | st_insert(transFaninTable, node, NIL(char)); |
---|
| 879 | } |
---|
| 880 | array_free(transFanins); |
---|
| 881 | |
---|
| 882 | oldBnvTable = *absBnvTable; |
---|
| 883 | oldNewlyAddedBnvs = *newlyAddedBnvs; |
---|
| 884 | *absBnvTable = st_init_table(st_ptrcmp, st_ptrhash); |
---|
| 885 | *newlyAddedBnvs = array_alloc(int, 0); |
---|
| 886 | st_foreach_item(oldBnvTable, stgen, &node, NIL(char *)) { |
---|
| 887 | if (st_is_member(transFaninTable, node)) |
---|
| 888 | st_insert(*absBnvTable, node, NIL(char)); |
---|
| 889 | } |
---|
| 890 | arrayForEachItem(int, oldNewlyAddedBnvs, i, mddId) { |
---|
| 891 | node = Ntk_NetworkFindNodeByMddId(network, mddId); |
---|
| 892 | if (st_is_member(transFaninTable, node)) |
---|
| 893 | array_insert_last(int, *newlyAddedBnvs, mddId); |
---|
| 894 | } |
---|
| 895 | st_free_table(transFaninTable); |
---|
| 896 | |
---|
| 897 | if (verbose >= 5) { |
---|
| 898 | st_foreach_item(oldBnvTable, stgen, &node, NIL(char *)) { |
---|
| 899 | if (!st_is_member(*absBnvTable, node)) |
---|
| 900 | fprintf(vis_stdout, " prune away BNV %s\n", Ntk_NodeReadName(node)); |
---|
| 901 | } |
---|
| 902 | } |
---|
| 903 | |
---|
| 904 | array_free(oldNewlyAddedBnvs); |
---|
| 905 | st_free_table(oldBnvTable); |
---|
| 906 | } |
---|
| 907 | |
---|
| 908 | } |
---|
| 909 | |
---|
| 910 | |
---|
| 911 | /**Function******************************************************************** |
---|
| 912 | |
---|
| 913 | Synopsis [Minimize the refinement set of latch variable.] |
---|
| 914 | |
---|
| 915 | Description [Minimize the refinement set of latch variable. After |
---|
| 916 | that, also prune away the boolean network variables that are no |
---|
| 917 | longer in the transitive fan-in.] |
---|
| 918 | |
---|
| 919 | SideEffects [] |
---|
| 920 | |
---|
| 921 | ******************************************************************************/ |
---|
| 922 | void |
---|
| 923 | GrabMinimizeBnvRefinementSet( |
---|
| 924 | Ntk_Network_t *network, |
---|
| 925 | st_table *coiBnvTable, |
---|
| 926 | st_table *absVarTable, |
---|
| 927 | st_table **absBnvTable, |
---|
| 928 | array_t *newlyAddedBnvs, |
---|
| 929 | array_t *SORs, |
---|
| 930 | int verbose) |
---|
| 931 | { |
---|
| 932 | st_table *newBnvTable; |
---|
| 933 | Ntk_Node_t *node; |
---|
| 934 | int i, flag, n_size, mddId; |
---|
| 935 | |
---|
| 936 | n_size = array_n(newlyAddedBnvs); |
---|
| 937 | |
---|
| 938 | if (verbose >= 3) |
---|
| 939 | fprintf(vis_stdout, |
---|
| 940 | "-- grab: minimize bnv refinement set: previous size is %d\n", |
---|
| 941 | n_size); |
---|
| 942 | |
---|
| 943 | arrayForEachItem(int, newlyAddedBnvs, i, mddId) { |
---|
| 944 | node = Ntk_NetworkFindNodeByMddId(network, mddId); |
---|
| 945 | /* first, try to drop it */ |
---|
| 946 | newBnvTable = st_copy(*absBnvTable); |
---|
| 947 | flag = st_delete(newBnvTable, &node, NIL(char *)); |
---|
| 948 | assert(flag); |
---|
| 949 | /* if the counter-example does not come back, drop it officially */ |
---|
| 950 | flag = Bmc_AbstractCheckAbstractTracesWithFineGrain(network, |
---|
| 951 | coiBnvTable, |
---|
| 952 | SORs, |
---|
| 953 | absVarTable, |
---|
| 954 | newBnvTable); |
---|
| 955 | if (!flag) { |
---|
| 956 | st_free_table(*absBnvTable); |
---|
| 957 | *absBnvTable = newBnvTable; |
---|
| 958 | n_size--; |
---|
| 959 | }else { |
---|
| 960 | st_free_table(newBnvTable); |
---|
| 961 | if (verbose >= 3) |
---|
| 962 | fprintf(vis_stdout," add back %s (BNV)\n", |
---|
| 963 | Ntk_NodeReadName(node)); |
---|
| 964 | } |
---|
| 965 | } |
---|
| 966 | |
---|
| 967 | if (verbose >= 3) |
---|
| 968 | fprintf(vis_stdout, |
---|
| 969 | "-- grab: minimize bnv refinement set: current size is %d\n", |
---|
| 970 | n_size); |
---|
| 971 | } |
---|
| 972 | |
---|
| 973 | /**Function******************************************************************** |
---|
| 974 | |
---|
| 975 | Synopsis [Clear the fields of mddId for all network nodes.] |
---|
| 976 | |
---|
| 977 | Description [Clear the fields of mddId for all network nodes.] |
---|
| 978 | |
---|
| 979 | SideEffects [] |
---|
| 980 | |
---|
| 981 | ******************************************************************************/ |
---|
| 982 | void |
---|
| 983 | GrabNtkClearAllMddIds( |
---|
| 984 | Ntk_Network_t *network) |
---|
| 985 | { |
---|
| 986 | #ifndef NDEBUG |
---|
| 987 | mdd_manager *mddManager = Ntk_NetworkReadMddManager(network); |
---|
| 988 | #endif |
---|
| 989 | Ntk_Node_t *node; |
---|
| 990 | lsGen lsgen; |
---|
| 991 | |
---|
| 992 | assert(mddManager == NIL(mdd_manager)); |
---|
| 993 | |
---|
| 994 | Ntk_NetworkForEachNode(network, lsgen, node) { |
---|
| 995 | Ntk_NodeSetMddId(node, NTK_UNASSIGNED_MDD_ID); |
---|
| 996 | } |
---|
| 997 | } |
---|
| 998 | |
---|
| 999 | /**Function******************************************************************** |
---|
| 1000 | |
---|
| 1001 | Synopsis [Print an array of network nodes.] |
---|
| 1002 | |
---|
| 1003 | Description [Print an array of network nodes.] |
---|
| 1004 | |
---|
| 1005 | SideEffects [] |
---|
| 1006 | |
---|
| 1007 | ******************************************************************************/ |
---|
| 1008 | void |
---|
| 1009 | GrabPrintNodeArray( |
---|
| 1010 | char *caption, |
---|
| 1011 | array_t *theArray) |
---|
| 1012 | { |
---|
| 1013 | Ntk_Node_t *node; |
---|
| 1014 | char string[32]; |
---|
| 1015 | int i; |
---|
| 1016 | |
---|
| 1017 | fprintf(vis_stdout, "\n%s[%d] =\n", caption, theArray?array_n(theArray):0); |
---|
| 1018 | |
---|
| 1019 | if (!theArray) return; |
---|
| 1020 | |
---|
| 1021 | arrayForEachItem(Ntk_Node_t *, theArray, i, node) { |
---|
| 1022 | if (Ntk_NodeTestIsLatch(node)) |
---|
| 1023 | strcpy(string, "latch"); |
---|
| 1024 | else if (Ntk_NodeTestIsInput(node)) |
---|
| 1025 | strcpy(string, "input"); |
---|
| 1026 | else if (Ntk_NodeTestIsLatchDataInput(node)) |
---|
| 1027 | strcpy(string, "latchDataIn"); |
---|
| 1028 | else if (Ntk_NodeTestIsLatchInitialInput(node)) |
---|
| 1029 | strcpy(string, "latchInitIn"); |
---|
| 1030 | else if (Ntk_NodeTestIsConstant(node)) |
---|
| 1031 | strcpy(string, "const"); |
---|
| 1032 | else |
---|
| 1033 | strcpy(string, "BNV"); |
---|
| 1034 | |
---|
| 1035 | fprintf(vis_stdout, "%s\t(%s)\n", Ntk_NodeReadName(node), string); |
---|
| 1036 | } |
---|
| 1037 | } |
---|
| 1038 | |
---|
| 1039 | /**Function******************************************************************** |
---|
| 1040 | |
---|
| 1041 | Synopsis [Print an array of network nodes.] |
---|
| 1042 | |
---|
| 1043 | Description [Print an array of network nodes.] |
---|
| 1044 | |
---|
| 1045 | SideEffects [] |
---|
| 1046 | |
---|
| 1047 | ******************************************************************************/ |
---|
| 1048 | void |
---|
| 1049 | GrabPrintMddIdArray( |
---|
| 1050 | Ntk_Network_t *network, |
---|
| 1051 | char *caption, |
---|
| 1052 | array_t *mddIdArray) |
---|
| 1053 | { |
---|
| 1054 | Ntk_Node_t *node; |
---|
| 1055 | array_t *theArray = array_alloc(Ntk_Node_t *, array_n(mddIdArray)); |
---|
| 1056 | int i, mddId; |
---|
| 1057 | |
---|
| 1058 | arrayForEachItem(int, mddIdArray, i, mddId) { |
---|
| 1059 | node = Ntk_NetworkFindNodeByMddId(network, mddId); |
---|
| 1060 | array_insert(Ntk_Node_t *, theArray, i, node); |
---|
| 1061 | } |
---|
| 1062 | |
---|
| 1063 | GrabPrintNodeArray(caption, theArray); |
---|
| 1064 | |
---|
| 1065 | array_free(theArray); |
---|
| 1066 | |
---|
| 1067 | } |
---|
| 1068 | |
---|
| 1069 | /**Function******************************************************************** |
---|
| 1070 | |
---|
| 1071 | Synopsis [Print a list of network nodes.] |
---|
| 1072 | |
---|
| 1073 | Description [Print a list of network nodes.] |
---|
| 1074 | |
---|
| 1075 | SideEffects [] |
---|
| 1076 | |
---|
| 1077 | ******************************************************************************/ |
---|
| 1078 | void |
---|
| 1079 | GrabPrintNodeList( |
---|
| 1080 | char *caption, |
---|
| 1081 | lsList theList) |
---|
| 1082 | { |
---|
| 1083 | Ntk_Node_t *node; |
---|
| 1084 | char string[32]; |
---|
| 1085 | lsGen lsgen; |
---|
| 1086 | |
---|
| 1087 | fprintf(vis_stdout, "\n%s[%d] =\n", caption, theList?lsLength(theList):0); |
---|
| 1088 | |
---|
| 1089 | if (!theList) return; |
---|
| 1090 | |
---|
| 1091 | lsForEachItem(theList, lsgen, node) { |
---|
| 1092 | if (Ntk_NodeTestIsLatch(node)) |
---|
| 1093 | strcpy(string, "latch"); |
---|
| 1094 | else if (Ntk_NodeTestIsInput(node)) |
---|
| 1095 | strcpy(string, "input"); |
---|
| 1096 | else if (Ntk_NodeTestIsLatchDataInput(node)) |
---|
| 1097 | strcpy(string, "latchDataIn"); |
---|
| 1098 | else if (Ntk_NodeTestIsLatchInitialInput(node)) |
---|
| 1099 | strcpy(string, "latchInitIn"); |
---|
| 1100 | else if (Ntk_NodeTestIsConstant(node)) |
---|
| 1101 | strcpy(string, "const"); |
---|
| 1102 | else |
---|
| 1103 | strcpy(string, "BNV"); |
---|
| 1104 | |
---|
| 1105 | fprintf(vis_stdout, " %s\t %s\n", string, Ntk_NodeReadName(node)); |
---|
| 1106 | } |
---|
| 1107 | } |
---|
| 1108 | |
---|
| 1109 | /**Function******************************************************************** |
---|
| 1110 | |
---|
| 1111 | Synopsis [Print a hash table of network nodes.] |
---|
| 1112 | |
---|
| 1113 | Description [Print a hash table of network nodes.] |
---|
| 1114 | |
---|
| 1115 | SideEffects [] |
---|
| 1116 | |
---|
| 1117 | ******************************************************************************/ |
---|
| 1118 | void |
---|
| 1119 | GrabPrintNodeHashTable( |
---|
| 1120 | char *caption, |
---|
| 1121 | st_table *theTable) |
---|
| 1122 | { |
---|
| 1123 | Ntk_Node_t *node; |
---|
| 1124 | char string[32]; |
---|
| 1125 | long value; |
---|
| 1126 | st_generator *stgen; |
---|
| 1127 | |
---|
| 1128 | fprintf(vis_stdout, "\n%s[%d] =\n", caption, theTable?st_count(theTable):0); |
---|
| 1129 | |
---|
| 1130 | if (!theTable) return; |
---|
| 1131 | |
---|
| 1132 | st_foreach_item(theTable, stgen, &node, &value) { |
---|
| 1133 | if (Ntk_NodeTestIsLatch(node)) |
---|
| 1134 | strcpy(string, "latch"); |
---|
| 1135 | else if (Ntk_NodeTestIsInput(node)) |
---|
| 1136 | strcpy(string, "input"); |
---|
| 1137 | else if (Ntk_NodeTestIsLatchDataInput(node)) |
---|
| 1138 | strcpy(string, "latchDataIn"); |
---|
| 1139 | else if (Ntk_NodeTestIsLatchInitialInput(node)) |
---|
| 1140 | strcpy(string, "latchInitIn"); |
---|
| 1141 | else if (Ntk_NodeTestIsConstant(node)) |
---|
| 1142 | strcpy(string, "const"); |
---|
| 1143 | else |
---|
| 1144 | strcpy(string, "BNV"); |
---|
| 1145 | |
---|
| 1146 | if (value != 0) |
---|
| 1147 | fprintf(vis_stdout, " %s\t %s\t %ld\n", string, Ntk_NodeReadName(node), |
---|
| 1148 | value); |
---|
| 1149 | else |
---|
| 1150 | fprintf(vis_stdout, " %s\t %s \n", string, Ntk_NodeReadName(node)); |
---|
| 1151 | } |
---|
| 1152 | } |
---|
| 1153 | |
---|
| 1154 | /*---------------------------------------------------------------------------*/ |
---|
| 1155 | /* Definition of static functions */ |
---|
| 1156 | /*---------------------------------------------------------------------------*/ |
---|
| 1157 | |
---|
| 1158 | /**Function******************************************************************** |
---|
| 1159 | |
---|
| 1160 | Synopsis [Get network nodes that are mentioned by the formula.] |
---|
| 1161 | |
---|
| 1162 | Description [Get network nodes that are mentioned by the formula.] |
---|
| 1163 | |
---|
| 1164 | SideEffects [] |
---|
| 1165 | |
---|
| 1166 | ******************************************************************************/ |
---|
| 1167 | static void |
---|
| 1168 | GetFormulaNodes( |
---|
| 1169 | Ntk_Network_t *network, |
---|
| 1170 | Ctlp_Formula_t *F, |
---|
| 1171 | array_t *formulaNodes) |
---|
| 1172 | { |
---|
| 1173 | |
---|
| 1174 | if (F == NIL(Ctlp_Formula_t)) |
---|
| 1175 | return; |
---|
| 1176 | |
---|
| 1177 | if (Ctlp_FormulaReadType(F) == Ctlp_ID_c) { |
---|
| 1178 | char *nodeNameString = Ctlp_FormulaReadVariableName(F); |
---|
| 1179 | Ntk_Node_t *node = Ntk_NetworkFindNodeByName(network, nodeNameString); |
---|
| 1180 | assert(node); |
---|
| 1181 | array_insert_last(Ntk_Node_t *, formulaNodes, node); |
---|
| 1182 | return; |
---|
| 1183 | } |
---|
| 1184 | |
---|
| 1185 | GetFormulaNodes(network, Ctlp_FormulaReadRightChild(F), formulaNodes); |
---|
| 1186 | GetFormulaNodes(network, Ctlp_FormulaReadLeftChild(F), formulaNodes); |
---|
| 1187 | } |
---|
| 1188 | |
---|
| 1189 | |
---|
| 1190 | /**Function******************************************************************** |
---|
| 1191 | |
---|
| 1192 | Synopsis [Get the fan-in latches of those already in the table.] |
---|
| 1193 | |
---|
| 1194 | Description [Get the fan-in latches of those already in the table.] |
---|
| 1195 | |
---|
| 1196 | SideEffects [] |
---|
| 1197 | |
---|
| 1198 | ******************************************************************************/ |
---|
| 1199 | static void |
---|
| 1200 | GetFaninLatches( |
---|
| 1201 | Ntk_Node_t *node, |
---|
| 1202 | st_table *visited, |
---|
| 1203 | st_table *absVarTable) |
---|
| 1204 | { |
---|
| 1205 | if (st_is_member(visited, node)) |
---|
| 1206 | return; |
---|
| 1207 | |
---|
| 1208 | st_insert(visited, node, (char *)0); |
---|
| 1209 | |
---|
| 1210 | if (Ntk_NodeTestIsLatch(node)) |
---|
| 1211 | st_insert(absVarTable, node, (char *)0); |
---|
| 1212 | else { |
---|
| 1213 | int i; |
---|
| 1214 | Ntk_Node_t *fanin; |
---|
| 1215 | Ntk_NodeForEachFanin(node, i, fanin) { |
---|
| 1216 | GetFaninLatches(fanin, visited, absVarTable); |
---|
| 1217 | } |
---|
| 1218 | } |
---|
| 1219 | } |
---|
| 1220 | |
---|
| 1221 | /**Function******************************************************************** |
---|
| 1222 | |
---|
| 1223 | Synopsis [Add nodes for wires referred to in formula to nodesTable.] |
---|
| 1224 | |
---|
| 1225 | SideEffects [] |
---|
| 1226 | |
---|
| 1227 | ******************************************************************************/ |
---|
| 1228 | static void |
---|
| 1229 | NodeTableAddCtlFormulaNodes( |
---|
| 1230 | Ntk_Network_t *network, |
---|
| 1231 | Ctlp_Formula_t *formula, |
---|
| 1232 | st_table * nodesTable ) |
---|
| 1233 | { |
---|
| 1234 | if (formula == NIL(Ctlp_Formula_t)) |
---|
| 1235 | return; |
---|
| 1236 | |
---|
| 1237 | if ( Ctlp_FormulaReadType( formula ) == Ctlp_ID_c ) { |
---|
| 1238 | char *nodeNameString = Ctlp_FormulaReadVariableName( formula ); |
---|
| 1239 | Ntk_Node_t *node = Ntk_NetworkFindNodeByName( network, nodeNameString ); |
---|
| 1240 | if( node ) |
---|
| 1241 | st_insert( nodesTable, ( char *) node, NIL(char) ); |
---|
| 1242 | return; |
---|
| 1243 | } |
---|
| 1244 | |
---|
| 1245 | NodeTableAddCtlFormulaNodes( network, Ctlp_FormulaReadRightChild( formula ), nodesTable ); |
---|
| 1246 | NodeTableAddCtlFormulaNodes( network, Ctlp_FormulaReadLeftChild( formula ), nodesTable ); |
---|
| 1247 | } |
---|
| 1248 | |
---|
| 1249 | |
---|