#include "cmuPortInt.h"
Go to the source code of this file.
Data Structures | |
struct | cmu_bdd_gen |
Enumerations | |
enum | bdd_gen_type { bdd_gen_cubes, bdd_gen_nodes, bdd_gen_cubes, bdd_gen_nodes } |
Functions | |
static void | pop_cube_stack (cmu_bdd_gen *gen) |
static void | pop_node_stack (cmu_bdd_gen *gen) |
static void | push_cube_stack (bdd_node *f, cmu_bdd_gen *gen) |
static void | push_node_stack (bdd_node *f, cmu_bdd_gen *gen) |
bdd_gen_status | bdd_gen_read_status (bdd_gen *gen) |
bdd_gen * | bdd_first_cube (bdd_t *fn, array_t **cube) |
boolean | bdd_next_cube (bdd_gen *gen_, array_t **cube) |
bdd_gen * | bdd_first_disjoint_cube (bdd_t *fn, array_t **cube) |
boolean | bdd_next_disjoint_cube (bdd_gen *gen_, array_t **cube) |
bdd_gen * | bdd_first_node (bdd_t *fn, bdd_node **node) |
boolean | bdd_next_node (bdd_gen *gen_, bdd_node **node) |
int | bdd_gen_free (bdd_gen *gen_) |
enum bdd_gen_type |
CFile***********************************************************************
FileName [cmuPort.c]
PackageName [cmu_port]
Synopsis [Port routines for CMU package.]
Description [optional]
SeeAlso [optional]
Author [Thomas R. Shiple. Some changes by Rajeev K. Ranjan.]
Copyright [Copyright (c) 1994-1996 The Regents of the Univ. of California. All rights reserved.
Permission is hereby granted, without written agreement and without license or royalty fees, to use, copy, modify, and distribute this software and its documentation for any purpose, provided that the above copyright notice and the following two paragraphs appear in all copies of this software.
IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
Revision [
]
Definition at line 51 of file cmuPortIter.c.
00051 { 00052 bdd_gen_cubes, 00053 bdd_gen_nodes 00054 } bdd_gen_type;
Definition at line 132 of file cmuPortIter.c.
00133 { 00134 struct bdd_manager_ *manager; 00135 cmu_bdd_gen *gen; 00136 int i; 00137 long num_vars; 00138 bdd_node *f; 00139 00140 if (fn == NIL(bdd_t)) { 00141 cmu_bdd_fatal("bdd_first_cube: invalid BDD"); 00142 } 00143 00144 manager = fn->mgr; 00145 00146 /* 00147 * Allocate a new generator structure and fill it in; the stack and the 00148 * cube will be used, but the visited table and the node will not be used. 00149 */ 00150 gen = ALLOC(cmu_bdd_gen, 1); 00151 if (gen == NIL(cmu_bdd_gen)) { 00152 cmu_bdd_fatal("bdd_first_cube: failed on memory allocation, location 1"); 00153 } 00154 00155 /* 00156 * first - init all the members to a rational value for cube iteration 00157 */ 00158 gen->manager = manager; 00159 gen->status = bdd_EMPTY; 00160 gen->type = bdd_gen_cubes; 00161 gen->gen.cubes.cube = NIL(array_t); 00162 gen->stack.sp = 0; 00163 gen->stack.stack = NIL(bdd_node *); 00164 gen->node = NIL(bdd_node); 00165 00166 num_vars = cmu_bdd_vars(manager); 00167 gen->gen.cubes.cube = array_alloc(bdd_literal, num_vars); 00168 if (gen->gen.cubes.cube == NIL(array_t)) { 00169 cmu_bdd_fatal("bdd_first_cube: failed on memory allocation, location 2"); 00170 } 00171 00172 /* 00173 * Initialize each literal to 2 (don't care). 00174 */ 00175 for (i = 0; i < num_vars; i++) { 00176 array_insert(bdd_literal, gen->gen.cubes.cube, i, 2); 00177 } 00178 00179 /* 00180 * The stack size will never exceed the number of variables in the BDD, since 00181 * the longest possible path from root to constant 1 is the number of variables 00182 * in the BDD. 00183 */ 00184 gen->stack.sp = 0; 00185 gen->stack.stack = ALLOC(bdd_node *, num_vars); 00186 if (gen->stack.stack == NIL(bdd_node *)) { 00187 cmu_bdd_fatal("bdd_first_cube: failed on memory allocation, location 3"); 00188 } 00189 /* 00190 * Clear out the stack so that in bdd_gen_free, we can decrement the ref count 00191 * of those nodes still on the stack. 00192 */ 00193 for (i = 0; i < num_vars; i++) { 00194 gen->stack.stack[i] = NIL(bdd_node); 00195 } 00196 00197 if (bdd_is_tautology(fn, 0)) { 00198 /* 00199 * All done, for this was but the zero constant ... 00200 * We are enumerating the onset, (which is vacuous). 00201 * gen->status initialized to bdd_EMPTY above, so this 00202 * appears to be redundant. 00203 */ 00204 gen->status = bdd_EMPTY; 00205 } else { 00206 /* 00207 * Get to work enumerating the onset. Get the first cube. Note that 00208 * if fn is just the constant 1, push_cube_stack will properly handle this. 00209 * Get a new pointer to fn->node beforehand: this increments 00210 * the reference count of fn->node; this is necessary, because when fn->node 00211 * is popped from the stack at the very end, it's ref count is decremented. 00212 */ 00213 gen->status = bdd_NONEMPTY; 00214 f = cmu_bdd_identity(manager, fn->node); 00215 push_cube_stack(f, gen); 00216 } 00217 00218 *cube = gen->gen.cubes.cube; 00219 return (bdd_gen *)(gen); 00220 }
Definition at line 239 of file cmuPortIter.c.
00240 { 00241 return(bdd_first_cube(fn,cube)); 00242 }
Definition at line 255 of file cmuPortIter.c.
00256 { 00257 struct bdd_manager_ *manager; 00258 cmu_bdd_gen *gen; 00259 long num_vars; 00260 bdd_node *f; 00261 int i; 00262 00263 if (fn == NIL(bdd_t)) { 00264 cmu_bdd_fatal("bdd_first_node: invalid BDD"); 00265 } 00266 00267 manager = fn->mgr; 00268 00269 /* 00270 * Allocate a new generator structure and fill it in; the 00271 * visited table will be used, as will the stack, but the 00272 * cube array will not be used. 00273 */ 00274 gen = ALLOC(cmu_bdd_gen, 1); 00275 if (gen == NIL(bdd_gen)) { 00276 cmu_bdd_fatal("bdd_first_node: failed on memory allocation, location 1"); 00277 } 00278 00279 /* 00280 * first - init all the members to a rational value for node iteration. 00281 */ 00282 gen->manager = manager; 00283 gen->status = bdd_NONEMPTY; 00284 gen->type = bdd_gen_nodes; 00285 gen->gen.nodes.visited = NIL(st_table); 00286 gen->stack.sp = 0; 00287 gen->stack.stack = NIL(bdd_node *); 00288 gen->node = NIL(bdd_node); 00289 00290 /* 00291 * Set up the hash table for visited nodes. Every time we visit a node, 00292 * we insert it into the table. 00293 */ 00294 gen->gen.nodes.visited = st_init_table(st_ptrcmp, st_ptrhash); 00295 if (gen->gen.nodes.visited == NIL(st_table)) { 00296 cmu_bdd_fatal("bdd_first_node: failed on memory allocation, location 2"); 00297 } 00298 00299 /* 00300 * The stack size will never exceed the number of variables in the BDD, since 00301 * the longest possible path from root to constant 1 is the number of variables 00302 * in the BDD. 00303 */ 00304 gen->stack.sp = 0; 00305 num_vars = cmu_bdd_vars(manager); 00306 gen->stack.stack = ALLOC(bdd_node *, num_vars); 00307 if (gen->stack.stack == NIL(bdd_node *)) { 00308 cmu_bdd_fatal("bdd_first_node: failed on memory allocation, location 3"); 00309 } 00310 /* 00311 * Clear out the stack so that in bdd_gen_free, we can decrement the ref count 00312 * of those nodes still on the stack. 00313 */ 00314 for (i = 0; i < num_vars; i++) { 00315 gen->stack.stack[i] = NIL(bdd_node); 00316 } 00317 00318 /* 00319 * Get the first node. Get a new pointer to fn->node beforehand: this increments 00320 * the reference count of fn->node; this is necessary, because when fn->node 00321 * is popped from the stack at the very end, it's ref count is decremented. 00322 */ 00323 f = cmu_bdd_identity(manager, fn->node); 00324 push_node_stack(f, gen); 00325 gen->status = bdd_NONEMPTY; 00326 00327 *node = gen->node; /* return the node */ 00328 return (bdd_gen *) (gen); /* and the new generator */ 00329 }
int bdd_gen_free | ( | bdd_gen * | gen_ | ) |
Definition at line 354 of file cmuPortIter.c.
00355 { 00356 long num_vars; 00357 int i; 00358 struct bdd_manager_ *mgr; 00359 bdd_node *f; 00360 st_table *visited_table; 00361 st_generator *visited_gen; 00362 cmu_bdd_gen *gen = (cmu_bdd_gen *) gen_; 00363 00364 mgr = gen->manager; 00365 00366 switch (gen->type) { 00367 case bdd_gen_cubes: 00368 array_free(gen->gen.cubes.cube); 00369 gen->gen.cubes.cube = NIL(array_t); 00370 break; 00371 case bdd_gen_nodes: 00372 visited_table = gen->gen.nodes.visited; 00373 st_foreach_item(visited_table, visited_gen, &f, NIL(refany)) { 00374 cmu_bdd_free(mgr, (bdd) f); 00375 } 00376 st_free_table(visited_table); 00377 visited_table = NIL(st_table); 00378 break; 00379 } 00380 00381 /* 00382 * Free the data associated with this generator. If there are any nodes remaining 00383 * on the stack, we must free them, to get their ref counts back to what they were before. 00384 */ 00385 num_vars = cmu_bdd_vars(mgr); 00386 for (i = 0; i < num_vars; i++) { 00387 f = gen->stack.stack[i]; 00388 if (f != NIL(bdd_node)) { 00389 cmu_bdd_free(mgr, (bdd) f); 00390 } 00391 } 00392 FREE(gen->stack.stack); 00393 00394 FREE(gen); 00395 00396 return (0); /* make it return some sort of an int */ 00397 }
bdd_gen_status bdd_gen_read_status | ( | bdd_gen * | gen | ) |
AutomaticEnd
Definition at line 110 of file cmuPortIter.c.
00111 { 00112 return ((cmu_bdd_gen *)gen)->status; 00113 }
Definition at line 227 of file cmuPortIter.c.
00228 { 00229 cmu_bdd_gen *gen = (cmu_bdd_gen *) gen_; 00230 pop_cube_stack(gen); 00231 if (gen->status == bdd_EMPTY) { 00232 return (FALSE); 00233 } 00234 *cube = gen->gen.cubes.cube; 00235 return (TRUE); 00236 }
Definition at line 245 of file cmuPortIter.c.
00246 { 00247 return(bdd_next_cube(gen_,cube)); 00248 }
Definition at line 336 of file cmuPortIter.c.
00337 { 00338 cmu_bdd_gen *gen = (cmu_bdd_gen *) gen_; 00339 00340 pop_node_stack(gen); 00341 if (gen->status == bdd_EMPTY) { 00342 return (FALSE); 00343 } 00344 *node = gen->node; 00345 return (TRUE); 00346 }
static void pop_cube_stack | ( | cmu_bdd_gen * | gen | ) | [static] |
AutomaticStart
Definition at line 486 of file cmuPortIter.c.
00487 { 00488 bdd_variableId topf_id, level_i_id; 00489 bdd_node *branch_f; 00490 bdd_node *f1; 00491 int i; 00492 long topf_level; 00493 struct bdd_manager_ *mgr; 00494 struct bdd_ *var_bdd; 00495 00496 mgr = gen->manager; 00497 00498 if (gen->stack.sp == 0) { 00499 /* 00500 * Stack is empty. Have already explored both the 0 and 1 branches of 00501 * the root of the BDD. 00502 */ 00503 gen->status = bdd_EMPTY; 00504 } else { 00505 /* 00506 * Explore the 1 branch of the node at the top of the stack (since it is 00507 * on the stack, this means we have already explored the 0 branch). We 00508 * permanently pop the top node, and bdd_free it, since there are no more edges left to 00509 * explore. 00510 */ 00511 branch_f = gen->stack.stack[--gen->stack.sp]; 00512 gen->stack.stack[gen->stack.sp] = NIL(bdd_node); /* overwrite with NIL */ 00513 topf_id = (bdd_variableId) (cmu_bdd_if_id(mgr, (bdd) branch_f) - 1); 00514 array_insert(bdd_literal, gen->gen.cubes.cube, topf_id, 1); 00515 00516 /* 00517 * We must set the variables with levels greater than the level of branch_f, 00518 * back to 2 (don't care). This is because these variables are not 00519 * on the current path, and thus there values are don't care. 00520 * 00521 * Note the following correspondence: 00522 * CMU UCB 00523 * index level (both start at zero) 00524 * indexindex id (CMU has id 0 for constant, thus really start numbering at 1; 00525 * UCB starts numbering at 0) 00526 */ 00527 topf_level = cmu_bdd_if_index(mgr, (bdd) branch_f); 00528 for (i = topf_level + 1; i < array_n(gen->gen.cubes.cube); i++) { 00529 var_bdd = cmu_bdd_var_with_index(mgr, i); 00530 level_i_id = (bdd_variableId) (cmu_bdd_if_id(mgr, var_bdd) - 1); 00531 /* 00532 * No need to free var_bdd, since single variable BDDs are never garbage collected. 00533 * Note that level_i_id is just (mgr->indexindexes[i] - 1); however, wanted 00534 * to avoid using CMU internals. 00535 */ 00536 array_insert(bdd_literal, gen->gen.cubes.cube, level_i_id, 2); 00537 } 00538 f1 = cmu_bdd_then(mgr, (bdd) branch_f); 00539 push_cube_stack(f1, gen); 00540 cmu_bdd_free(mgr, (bdd) branch_f); 00541 } 00542 }
static void pop_node_stack | ( | cmu_bdd_gen * | gen | ) | [static] |
Definition at line 630 of file cmuPortIter.c.
00631 { 00632 bdd_node *branch_f; 00633 00634 if (gen->stack.sp == 0) { 00635 gen->status = bdd_EMPTY; 00636 } else { 00637 branch_f = gen->stack.stack[--gen->stack.sp]; /* overwrite with NIL */ 00638 gen->stack.stack[gen->stack.sp] = NIL(bdd_node); 00639 push_node_stack(branch_f, gen); 00640 } 00641 }
static void push_cube_stack | ( | bdd_node * | f, | |
cmu_bdd_gen * | gen | |||
) | [static] |
Definition at line 428 of file cmuPortIter.c.
00429 { 00430 bdd_variableId topf_id; 00431 bdd_node *f0, *f1; 00432 struct bdd_manager_ *mgr; 00433 00434 mgr = gen->manager; 00435 00436 if (f == cmu_bdd_one(mgr)) { 00437 return; 00438 } 00439 00440 topf_id = (bdd_variableId) (cmu_bdd_if_id(mgr, (bdd) f) - 1); 00441 00442 /* 00443 * Get the then and else branches of f. Note that cmu_bdd_then and cmu_bdd_else 00444 * automatically take care of inverted pointers. 00445 */ 00446 f0 = cmu_bdd_else(mgr, (bdd) f); 00447 f1 = cmu_bdd_then(mgr, (bdd) f); 00448 00449 if (f1 == cmu_bdd_zero(mgr)) { 00450 /* 00451 * No choice: take the 0 branch. Since there is only one branch to 00452 * explore from f, there is no need to push f onto the stack, because 00453 * after exploring this branch we are done with f. A consequence of 00454 * this is that there will be no f to pop either. Same goes for the 00455 * next case. Decrement the ref count of f and of the branch leading 00456 * to zero, since we will no longer need to access these nodes. 00457 */ 00458 array_insert(bdd_literal, gen->gen.cubes.cube, topf_id, 0); 00459 push_cube_stack(f0, gen); 00460 cmu_bdd_free(mgr, (bdd) f1); 00461 cmu_bdd_free(mgr, (bdd) f); 00462 } else if (f0 == cmu_bdd_zero(mgr)) { 00463 /* 00464 * No choice: take the 1 branch 00465 */ 00466 array_insert(bdd_literal, gen->gen.cubes.cube, topf_id, 1); 00467 push_cube_stack(f1, gen); 00468 cmu_bdd_free(mgr, (bdd) f0); 00469 cmu_bdd_free(mgr, (bdd) f); 00470 } else { 00471 /* 00472 * In this case, we must explore both branches of f. We always choose 00473 * to explore the 0 branch first. We must push f on the stack, so that 00474 * we can later pop it and explore its 1 branch. Decrement the ref count 00475 * of f1 since we will no longer need to access this node. Note that 00476 * the parent of f1 was bdd_freed above or in pop_cube_stack. 00477 */ 00478 gen->stack.stack[gen->stack.sp++] = f; 00479 array_insert(bdd_literal, gen->gen.cubes.cube, topf_id, 0); 00480 push_cube_stack(f0, gen); 00481 cmu_bdd_free(mgr, (bdd) f1); 00482 } 00483 }
static void push_node_stack | ( | bdd_node * | f, | |
cmu_bdd_gen * | gen | |||
) | [static] |
Definition at line 560 of file cmuPortIter.c.
00561 { 00562 bdd_node *f0, *f1; 00563 bdd_node *reg_f, *reg_f0, *reg_f1; 00564 struct bdd_manager_ *mgr; 00565 00566 mgr = gen->manager; 00567 00568 reg_f = (bdd_node *) BDD_POINTER(f); /* use of bddint.h */ 00569 if (st_lookup(gen->gen.nodes.visited, (refany) reg_f, NIL(refany))) { 00570 /* 00571 * Already been visited. 00572 */ 00573 return; 00574 } 00575 00576 if (f == cmu_bdd_one(mgr) || f == cmu_bdd_zero(mgr)) { 00577 /* 00578 * If f is the constant node and it has not been visited yet, then put it in the visited table 00579 * and set the gen->node pointer. There is no need to put it in the stack because 00580 * the constant node does not have any branches, and there is no need to free f because 00581 * constant nodes have a saturated reference count. 00582 */ 00583 st_insert(gen->gen.nodes.visited, (refany) reg_f, NIL(any)); 00584 gen->node = reg_f; 00585 } else { 00586 /* 00587 * f has not been marked as visited. We don't know yet if any of its branches 00588 * remain to be explored. First get its branches. Note that cmu_bdd_then and 00589 * cmu_bdd_else automatically take care of inverted pointers. 00590 */ 00591 f0 = cmu_bdd_else(mgr, (bdd) f); 00592 f1 = cmu_bdd_then(mgr, (bdd) f); 00593 00594 reg_f0 = (bdd_node *) BDD_POINTER(f0); /* use of bddint.h */ 00595 reg_f1 = (bdd_node *) BDD_POINTER(f1); 00596 if (! st_lookup(gen->gen.nodes.visited, (refany) reg_f0, NIL(refany))) { 00597 /* 00598 * The 0 child has not been visited, so explore the 0 branch. First push f on 00599 * the stack. Bdd_free f1 since we will not need to access this exact pointer 00600 * any more. 00601 */ 00602 gen->stack.stack[gen->stack.sp++] = f; 00603 push_node_stack(f0, gen); 00604 cmu_bdd_free(mgr, (bdd) f1); 00605 } else if (! st_lookup(gen->gen.nodes.visited, (refany) reg_f1, NIL(refany))) { 00606 /* 00607 * The 0 child has been visited, but the 1 child has not been visited, so 00608 * explore the 1 branch. First push f on the stack. We are done with f0, 00609 * so bdd_free it. 00610 */ 00611 gen->stack.stack[gen->stack.sp++] = f; 00612 push_node_stack(f1, gen); 00613 cmu_bdd_free(mgr, (bdd) f0); 00614 } else { 00615 /* 00616 * Both the 0 and 1 children have been visited. Thus we are done exploring from f. 00617 * Mark f as visited (put it in the visited table), and set the gen->node pointer. 00618 * We will no longer need to refer to f0 and f1, so bdd_free them. f will be 00619 * bdd_freed when the visited table is freed. 00620 */ 00621 st_insert(gen->gen.nodes.visited, (refany) reg_f, NIL(any)); 00622 gen->node = reg_f; 00623 cmu_bdd_free(mgr, (bdd) f0); 00624 cmu_bdd_free(mgr, (bdd) f1); 00625 } 00626 } 00627 }