src/calPort/calPortIter.c File Reference

#include "calPortInt.h"
Include dependency graph for calPortIter.c:

Go to the source code of this file.

Data Structures

struct  CalBddGenStruct

Typedefs

typedef struct CalBddGenStruct CalBddGen_t

Enumerations

enum  bdd_gen_type { bdd_gen_cubes, bdd_gen_nodes, bdd_gen_cubes, bdd_gen_nodes }

Functions

static void pop_node_stack (CalBddGen_t *gen)
static void push_node_stack (Cal_Bdd_t f, CalBddGen_t *gen)
static void pop_cube_stack (CalBddGen_t *gen)
static void push_cube_stack (Cal_Bdd_t f, CalBddGen_t *gen)
bdd_gen_status bdd_gen_read_status (bdd_gen *gen)
bdd_genbdd_first_cube (bdd_t *fn, array_t **cube)
boolean bdd_next_cube (bdd_gen *gen_, array_t **cube)
bdd_genbdd_first_disjoint_cube (bdd_t *fn, array_t **cube)
boolean bdd_next_disjoint_cube (bdd_gen *gen_, array_t **cube)
bdd_genbdd_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_)

Typedef Documentation

typedef struct CalBddGenStruct CalBddGen_t

CFile***********************************************************************

FileName [calPortIter.c]

PackageName [calPort]

Synopsis [required]

Description [optional]

SeeAlso [optional]

Author [Rajeev K. Ranjan. Modified from the CMU port package written by Tom Shiple.]

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.]

Definition at line 46 of file calPortIter.c.


Enumeration Type Documentation

Enumerator:
bdd_gen_cubes 
bdd_gen_nodes 
bdd_gen_cubes 
bdd_gen_nodes 

Definition at line 51 of file calPortIter.c.

00051              {
00052     bdd_gen_cubes,
00053     bdd_gen_nodes
00054 } bdd_gen_type;


Function Documentation

bdd_gen* bdd_first_cube ( bdd_t fn,
array_t **  cube 
)

Function********************************************************************

Synopsis [required]

Description [bdd_first_cube - return the first cube of the function. A generator is returned that will iterate over the rest. Return the generator. ]

SideEffects [required]

SeeAlso [optional]

Definition at line 143 of file calPortIter.c.

00144 {
00145   Cal_BddManager_t *manager;
00146   CalBddGen_t *gen;
00147   int i;
00148   long numVars;
00149   Cal_Bdd function;
00150   Cal_Bdd_t calBdd;
00151   
00152   if (fn == NIL(bdd_t)) {
00153         CalBddFatalMessage("bdd_first_cube: invalid BDD");
00154   }
00155 
00156   manager = fn->bddManager;
00157   function = fn->calBdd;
00158   
00159   /*
00160    *    Allocate a new generator structure and fill it in; the stack and the 
00161    *    cube will be used, but the visited table and the node will not be used.
00162    */
00163   gen = ALLOC(CalBddGen_t, 1);
00164   
00165     /*
00166      *    first - init all the members to a rational value for cube iteration
00167      */
00168   gen->manager = manager;
00169   gen->status = bdd_EMPTY;
00170   gen->type = bdd_gen_cubes;
00171   gen->gen.cubes.cube = NIL(array_t);
00172   gen->stack.sp = 0;
00173   gen->stack.nodeStack = NIL(CalBddNode_t *);
00174   gen->stack.idStack = NIL(int);
00175   gen->node = NIL(CalBddNode_t);
00176   
00177   numVars = Cal_BddVars(manager);
00178   gen->gen.cubes.cube = array_alloc(bdd_literal, numVars);
00179     
00180   /*
00181    * Initialize each literal to 2 (don't care).
00182    */
00183   for (i = 0; i < numVars; i++) {
00184     array_insert(bdd_literal, gen->gen.cubes.cube, i, 2);
00185   }
00186   
00187   /*
00188    * The stack size will never exceed the number of variables in the BDD, since
00189    * the longest possible path from root to constant 1 is the number
00190    * of variables in the BDD.
00191    */
00192   gen->stack.sp = 0;
00193   gen->stack.nodeStack = ALLOC(CalBddNode_t *, numVars);
00194   gen->stack.idStack = ALLOC(int, numVars);
00195 
00196   /*
00197    * Clear out the stack so that in bdd_gen_free, we can decrement the
00198    * ref count of those nodes still on the stack.
00199    */
00200   for (i = 0; i < numVars; i++) {
00201         gen->stack.nodeStack[i] = NIL(CalBddNode_t);
00202         gen->stack.idStack[i] = -1;
00203   }
00204   
00205   if (Cal_BddIsBddZero(manager, function)){
00206         /*
00207          *    All done, for this was but the zero constant ...
00208          *    We are enumerating the onset, (which is vacuous).
00209      *    gen->status initialized to bdd_EMPTY above, so this
00210      *    appears to be redundant.
00211          */
00212         gen->status = bdd_EMPTY;
00213   } else {
00214         /*
00215          *    Get to work enumerating the onset.  Get the first cube.  Note that
00216      *    if fn is just the constant 1, push_cube_stack will properly
00217      *    handle this. 
00218          *    Get a new pointer to fn->node beforehand: this increments 
00219          *    the reference count of fn->node; this is necessary, because
00220      *    when fn->node 
00221          *    is popped from the stack at the very end, it's ref count is
00222      *    decremented. 
00223          */
00224         gen->status = bdd_NONEMPTY;
00225     calBdd = CalBddGetInternalBdd(manager, function);
00226     push_cube_stack(calBdd, gen);
00227   }
00228   *cube = gen->gen.cubes.cube;
00229   return (bdd_gen *)(gen);
00230 }

bdd_gen* bdd_first_disjoint_cube ( bdd_t fn,
array_t **  cube 
)

Definition at line 257 of file calPortIter.c.

00258 {
00259   return(bdd_first_cube(fn,cube));
00260 }

bdd_gen* bdd_first_node ( bdd_t fn,
bdd_node **  node 
)

Function********************************************************************

Synopsis [required]

Description [bdd_first_node - enumerates all bdd_node in fn. Return the generator.]

SideEffects [required]

SeeAlso [optional]

Definition at line 281 of file calPortIter.c.

00282 {
00283   Cal_BddManager_t *manager;
00284   CalBddGen_t *gen;
00285   long numVars;
00286   int i;
00287   Cal_Bdd_t calBdd;
00288   Cal_Bdd function;
00289   
00290   if (fn == NIL(bdd_t)) {
00291         CalBddFatalMessage("bdd_first_node: invalid BDD");
00292   }
00293   
00294   manager = fn->bddManager;
00295   function = fn->calBdd;
00296   
00297   /*
00298    *    Allocate a new generator structure and fill it in; the
00299    *    visited table will be used, as will the stack, but the
00300    *    cube array will not be used.
00301    */
00302   gen = ALLOC(CalBddGen_t, 1);
00303   
00304   /*
00305    *    first - init all the members to a rational value for node iteration.
00306    */
00307   gen->manager = manager;
00308   gen->status = bdd_NONEMPTY;
00309   gen->type = bdd_gen_nodes;
00310   gen->gen.nodes.visited = NIL(st_table);
00311   gen->stack.sp = 0;
00312   gen->stack.nodeStack = NIL(CalBddNode_t *);
00313   gen->stack.idStack = NIL(int);
00314   gen->node = NIL(CalBddNode_t);
00315   
00316   /* 
00317    * Set up the hash table for visited nodes.  Every time we visit a node,
00318    * we insert it into the table.
00319    */
00320   gen->gen.nodes.visited = st_init_table(st_ptrcmp, st_ptrhash);
00321   
00322   /*
00323    * The stack size will never exceed the number of variables in the BDD, since
00324    * the longest possible path from root to constant 1 is the number
00325    * of variables in the BDD.
00326    */
00327   gen->stack.sp = 0;
00328   numVars = Cal_BddVars(manager);
00329   gen->stack.nodeStack = ALLOC(CalBddNode_t *, numVars);
00330   gen->stack.idStack = ALLOC(int, numVars);
00331   /*
00332    * Clear out the stack so that in bdd_gen_free, we can decrement the
00333    * ref count of those nodes still on the stack.
00334    */
00335   for (i = 0; i < numVars; i++) {
00336         gen->stack.nodeStack[i] = NIL(CalBddNode_t);
00337         gen->stack.idStack[i] = -1;
00338   }
00339   
00340   /*
00341    * Get the first node.  Get a new pointer to fn->node beforehand:
00342    * this increments 
00343    * the reference count of fn->node; this is necessary, because when fn->node
00344    * is popped from the stack at the very end, it's ref count is decremented.
00345    */
00346   calBdd = CalBddGetInternalBdd(manager, function);
00347   push_node_stack(calBdd, gen);
00348   gen->status = bdd_NONEMPTY;
00349   
00350   *node = (bdd_node *)gen->node;        /* return the node */
00351   return (bdd_gen *)(gen);      /* and the new generator */
00352 }

int bdd_gen_free ( bdd_gen gen_  ) 

Function********************************************************************

Synopsis [required]

Description [bdd_gen_free - frees up the space used by the generator. Return an int so that it is easier to fit in a foreach macro. Return 0 (to make it easy to put in expressions). ]

SideEffects [required]

SeeAlso [optional]

Definition at line 392 of file calPortIter.c.

00393 {
00394   CalBddGen_t *gen = (CalBddGen_t *) gen_;
00395   st_table *visited_table;
00396 
00397   switch (gen->type) {
00398     case bdd_gen_cubes:
00399       array_free(gen->gen.cubes.cube);
00400       gen->gen.cubes.cube = NIL(array_t);
00401       break;
00402     case bdd_gen_nodes:
00403       visited_table = gen->gen.nodes.visited;
00404       st_free_table(visited_table);
00405       visited_table = NIL(st_table);
00406       break;
00407   }
00408   FREE(gen->stack.nodeStack);
00409   FREE(gen->stack.idStack);
00410   FREE(gen);
00411   return (0);   /* make it return some sort of an int */
00412 }

bdd_gen_status bdd_gen_read_status ( bdd_gen gen  ) 

AutomaticEnd

Definition at line 124 of file calPortIter.c.

00125 {
00126   return ((CalBddGen_t *)gen)->status;
00127 }

boolean bdd_next_cube ( bdd_gen gen_,
array_t **  cube 
)

Function********************************************************************

Synopsis [required]

Description [bdd_next_cube - get the next cube on the generator. Returns {TRUE, FALSE} when {more, no more}.]

SideEffects [required]

SeeAlso [optional]

Definition at line 245 of file calPortIter.c.

00246 {
00247   CalBddGen_t *gen = (CalBddGen_t *) gen_;
00248   pop_cube_stack(gen);
00249   if (gen->status == bdd_EMPTY) {
00250     return (FALSE);
00251   }
00252   *cube = gen->gen.cubes.cube;
00253   return (TRUE);
00254 }

boolean bdd_next_disjoint_cube ( bdd_gen gen_,
array_t **  cube 
)

Definition at line 263 of file calPortIter.c.

00264 {
00265   return(bdd_next_cube(gen_,cube));
00266 }

boolean bdd_next_node ( bdd_gen gen_,
bdd_node **  node 
)

Function********************************************************************

Synopsis [required]

Description [bdd_next_node - get the next node in the BDD. Return {TRUE, FALSE} when {more, no more}. ]

SideEffects [required]

SeeAlso [optional]

Definition at line 367 of file calPortIter.c.

00368 {
00369   CalBddGen_t *gen = (CalBddGen_t *) gen_;
00370   pop_node_stack(gen);
00371   if (gen->status == bdd_EMPTY) {
00372         return (FALSE);
00373   }
00374   *node = (bdd_node *) gen->node;
00375   return (TRUE);
00376 }

static void pop_cube_stack ( CalBddGen_t gen  )  [static]

Function********************************************************************

Synopsis [required]

Description [optional]

SideEffects [required]

SeeAlso [optional]

Definition at line 509 of file calPortIter.c.

00510 {
00511   CalBddNode_t *fNode;
00512   int fId, fIndex, i;
00513   Cal_Bdd_t f1, f;
00514   Cal_BddManager_t *manager;
00515   
00516   manager = gen->manager;
00517   if (gen->stack.sp == 0) {
00518     /*
00519      * Stack is empty.  Have already explored both the 0 and 1 branches of 
00520      * the root of the BDD.
00521      */
00522         gen->status = bdd_EMPTY;
00523   } else {
00524     /*
00525      * Explore the 1 branch of the node at the top of the stack (since it is
00526      * on the stack, this means we have already explored the 0 branch).  We 
00527      * permanently pop the top node, and bdd_free it, since there are
00528      * no more edges left to explore. 
00529      */
00530         fNode = gen->stack.nodeStack[--gen->stack.sp];
00531         fId = gen->stack.idStack[gen->stack.sp];
00532         gen->stack.nodeStack[gen->stack.sp] = NIL(CalBddNode_t); /* overwrite */
00533                                                          /* with NIL */
00534         gen->stack.idStack[gen->stack.sp] = -1;
00535         array_insert(bdd_literal, gen->gen.cubes.cube, fId-1, 1);
00536     fIndex = manager->idToIndex[fId];
00537         for (i = fIndex + 1; i < array_n(gen->gen.cubes.cube); i++) {
00538       array_insert(bdd_literal, gen->gen.cubes.cube,
00539                    manager->indexToId[i]-1, 2); 
00540         }
00541     f.bddNode = fNode;
00542     f.bddId = fId;
00543     CalBddGetThenBdd(f, f1);
00544         push_cube_stack(f1, gen);
00545   }
00546 }

static void pop_node_stack ( CalBddGen_t gen  )  [static]

AutomaticStart

Function********************************************************************

Synopsis [required]

Description [optional]

SideEffects [required]

SeeAlso [optional]

Definition at line 649 of file calPortIter.c.

00650 {
00651   CalBddNode_t *fNode;
00652   int fId;
00653   Cal_Bdd_t calBdd;
00654   
00655   if (gen->stack.sp == 0) {
00656     gen->status = bdd_EMPTY;
00657     return;
00658   }
00659   fNode = gen->stack.nodeStack[--gen->stack.sp]; 
00660   fId = gen->stack.idStack[gen->stack.sp];
00661   gen->stack.nodeStack[gen->stack.sp] = NIL(CalBddNode_t);
00662   gen->stack.idStack[gen->stack.sp] = -1;
00663   calBdd.bddNode = fNode;
00664   calBdd.bddId = fId;
00665   push_node_stack(calBdd, gen);
00666 }

static void push_cube_stack ( Cal_Bdd_t  f,
CalBddGen_t gen 
) [static]

Function********************************************************************

Synopsis [required]

Description [push_cube_stack - push a cube onto the stack to visit. Return nothing, just do it. The BDD is traversed using depth-first search, with the ELSE branch searched before the THEN branch. Caution: If you are creating new BDD's while iterating through the cubes, and a garbage collection happens to be performed during this process, then the BDD generator will get lost and an error will result. ]

SideEffects [required]

SeeAlso [optional]

Definition at line 448 of file calPortIter.c.

00449 {
00450   bdd_variableId topId;
00451   Cal_Bdd_t f0, f1;
00452   Cal_BddManager_t *manager;
00453 
00454   manager = gen->manager;
00455   
00456   if (CalBddIsBddOne(manager, f)){
00457     return;
00458   }
00459 
00460   topId = f.bddId-1;
00461   CalBddGetElseBdd(f, f0);
00462   CalBddGetThenBdd(f, f1);
00463 
00464   if (CalBddIsBddZero(manager, f1)){ 
00465 /*
00466  *    No choice: take the 0 branch.  Since there is only one branch to 
00467  *    explore from f, there is no need to push f onto the stack, because
00468  *    after exploring this branch we are done with f.  A consequence of 
00469  *    this is that there will be no f to pop either.  Same goes for the
00470  *    next case.  Decrement the ref count of f and of the branch leading
00471  *    to zero, since we will no longer need to access these nodes.
00472  */
00473     array_insert(bdd_literal, gen->gen.cubes.cube, topId, 0);
00474         push_cube_stack(f0, gen);
00475   }
00476   else if (CalBddIsBddZero(manager, f0)){
00477         /*
00478          *    No choice: take the 1 branch
00479          */
00480         array_insert(bdd_literal, gen->gen.cubes.cube, topId, 1);
00481         push_cube_stack(f1, gen);
00482   } else {
00483     /*
00484      * In this case, we must explore both branches of f.  We always choose
00485      * to explore the 0 branch first.  We must push f on the stack, so that
00486      * we can later pop it and explore its 1 branch. Decrement the ref count 
00487      * of f1 since we will no longer need to access this node.  Note that 
00488      * the parent of f1 was bdd_freed above or in pop_cube_stack.
00489      */
00490     gen->stack.nodeStack[gen->stack.sp] = f.bddNode;
00491     gen->stack.idStack[gen->stack.sp++] = f.bddId;
00492     array_insert(bdd_literal, gen->gen.cubes.cube, topId, 0);
00493     push_cube_stack(f0, gen);
00494   }
00495 }

static void push_node_stack ( Cal_Bdd_t  f,
CalBddGen_t gen 
) [static]

Function********************************************************************

Synopsis [required]

Description [push_node_stack - push a node onto the stack. The same as push_cube_stack but for enumerating nodes instead of cubes. The BDD is traversed using depth-first search, with the ELSE branch searched before the THEN branch, and a node returned only after its children have been returned. Note that the returned bdd_node pointer has the complement bit zeroed out. Caution: If you are creating new BDD's while iterating through the nodes, and a garbage collection happens to be performed during this process, then the BDD generator will get lost and an error will result. ]

SideEffects [required]

SeeAlso [optional]

Definition at line 568 of file calPortIter.c.

00569 {
00570   Cal_Bdd_t f0, f1;
00571   bdd_node *reg_f, *reg_f0, *reg_f1;
00572 
00573   reg_f = (CalBddNode_t *) CAL_BDD_POINTER(f.bddNode);  /* use of calInt.h */
00574   if (st_is_member(gen->gen.nodes.visited, (char *) reg_f)){
00575     /* 
00576      * Already been visited.
00577      */
00578         return;
00579   }
00580   
00581   if (CalBddIsBddConst(f)){
00582     /*
00583      * If f is the constant node and it has not been visited yet, then
00584      * put it in the visited table and set the gen->node pointer.
00585      * There is no need to put it in the stack because 
00586      * the constant node does not have any branches, and there is no
00587      * need to free f because constant nodes have a saturated
00588      * reference count. 
00589      */
00590         st_insert(gen->gen.nodes.visited, (char *) reg_f, NIL(char));
00591         gen->node = (CalBddNode_t *) reg_f;
00592   } else {
00593     /*
00594      * f has not been marked as visited.  We don't know yet if any of
00595      * its branches remain to be explored.  First get its branches.
00596      */
00597     CalBddGetElseBdd(f, f0);
00598     CalBddGetThenBdd(f, f1);
00599 
00600         reg_f0 = (CalBddNode_t *) CAL_BDD_POINTER(f0.bddNode);
00601         reg_f1 = (CalBddNode_t *) CAL_BDD_POINTER(f1.bddNode);
00602 
00603         if (st_is_member(gen->gen.nodes.visited, (char *) reg_f0) == 0){
00604       /* 
00605        * The 0 child has not been visited, so explore the 0 branch.
00606        * First push f on the stack.  Bdd_free f1 since we will not
00607        * need to access this exact pointer any more.
00608        */
00609       gen->stack.nodeStack[gen->stack.sp] = f.bddNode;
00610       gen->stack.idStack[gen->stack.sp++] = f.bddId;
00611       push_node_stack(f0, gen);
00612         } else{
00613       if (st_is_member(gen->gen.nodes.visited, (char *) reg_f1) == 0){
00614         /* 
00615          * The 0 child has been visited, but the 1 child has not been
00616          * visited, so explore the 1 branch.  First push f on the
00617          * stack. 
00618          */
00619         gen->stack.nodeStack[gen->stack.sp] = f.bddNode;
00620         gen->stack.idStack[gen->stack.sp++] = f.bddId;
00621         push_node_stack(f1, gen);
00622       } else {
00623         /*
00624          * Both the 0 and 1 children have been visited. Thus we are done
00625          * exploring from f.   
00626          * Mark f as visited (put it in the visited table), and set the
00627          * gen->node pointer. 
00628          */
00629         st_insert(gen->gen.nodes.visited, (char *) reg_f, NIL(char));
00630         gen->node = (CalBddNode_t *) reg_f;
00631       }
00632     }
00633   }
00634 }


Generated on Tue Jan 12 13:57:14 2010 for glu-2.2 by  doxygen 1.6.1