You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1954 lines
48 KiB
1954 lines
48 KiB
/**CFile***********************************************************************
|
|
|
|
FileName [cuddBddPort.c]
|
|
|
|
PackageName [cudd]
|
|
|
|
Synopsis [SIS interface to the Decision Diagram Package of the
|
|
University of Colorado.]
|
|
|
|
Description [This file implements an interface between the functions in
|
|
the Berkeley BDD package and the functions provided by the CUDD (decision
|
|
diagram) package from the University of Colorado. The CUDD package is a
|
|
generic implementation of a decision diagram data structure. For the time
|
|
being, only Boole expansion is implemented and the leaves in the
|
|
in the nodes can be the constants zero, one or any arbitrary value.]
|
|
|
|
Author [Abelardo Pardo]
|
|
|
|
Copyright [Copyright (c) 1994-1996 The Univ. of Colorado.
|
|
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 COLORADO 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
|
|
COLORADO HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
THE UNIVERSITY OF COLORADO 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 COLORADO HAS NO OBLIGATION TO PROVIDE
|
|
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
|
|
|
|
******************************************************************************/
|
|
|
|
#include "util.h"
|
|
#include "array.h"
|
|
#include "st.h"
|
|
|
|
#ifdef EXTERN
|
|
#undef EXTERN
|
|
#endif
|
|
#define EXTERN
|
|
#include "cuddInt.h"
|
|
#include "cuddBdd.h"
|
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
/* Constant declarations */
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
/* Stucture declarations */
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
struct bdd_gen {
|
|
bdd_manager *manager;
|
|
DdGen *ddGen;
|
|
array_t *cube;
|
|
};
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
/* Type declarations */
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
/* Variable declarations */
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
#ifndef lint
|
|
static char rcsid[] DD_UNUSED = "$Id: cuddBddPort.c,v 1.11 1996/05/08 06:13:08 fabio Exp $";
|
|
#endif
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
/* Macro declarations */
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
|
|
/**AutomaticStart*************************************************************/
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
/* Static function prototypes */
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
static bdd_t * bdd_construct_bdd_t (DdManager *mgr, DdNode * fn);
|
|
|
|
/**AutomaticEnd***************************************************************/
|
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
/* Definition of exported functions */
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Terminates the bdd package.]
|
|
|
|
SideEffects []
|
|
|
|
******************************************************************************/
|
|
void
|
|
bdd_end(mgr)
|
|
bdd_manager *mgr;
|
|
{
|
|
if (mgr->hooks != NULL) FREE(mgr->hooks);
|
|
Cudd_Quit(mgr);
|
|
|
|
} /* end of bdd_end */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Initialize manager with the options given in mgr_init.]
|
|
|
|
SideEffects []
|
|
|
|
******************************************************************************/
|
|
void
|
|
bdd_set_mgr_init_dflts(mgr_init)
|
|
bdd_mgr_init *mgr_init;
|
|
{
|
|
fprintf(stderr,"CU DD Package: bdd_set_mgr_init_dflts translated to no-op\n");
|
|
return;
|
|
|
|
} /* end of bdd_set_mgr_init_dflts */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Starts the manager with nvariables variables.]
|
|
|
|
SideEffects []
|
|
|
|
******************************************************************************/
|
|
bdd_manager *
|
|
bdd_start(nvariables)
|
|
int nvariables;
|
|
{
|
|
DdManager *mgr;
|
|
bdd_external_hooks *hooks;
|
|
|
|
mgr = Cudd_Init((unsigned int)nvariables,0,CUDD_UNIQUE_SLOTS,
|
|
CUDD_CACHE_SLOTS,0);
|
|
|
|
hooks = ALLOC(bdd_external_hooks,1);
|
|
hooks->mdd = hooks->network = hooks->undef1 = (char *) 0;
|
|
mgr->hooks = (char *) hooks;
|
|
|
|
return (bdd_manager *)mgr;
|
|
|
|
} /* end of bdd_start */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Starts the manager with parameters.]
|
|
|
|
SideEffects []
|
|
|
|
******************************************************************************/
|
|
bdd_manager *
|
|
bdd_start_with_params(nvariables, mgr_init)
|
|
int nvariables;
|
|
bdd_mgr_init *mgr_init;
|
|
{
|
|
fprintf(stderr,"CU DD Package: bdd_start_with_parameters bypassed\n");
|
|
return (bdd_manager *)Cudd_Init((unsigned int)nvariables,0,
|
|
CUDD_UNIQUE_SLOTS,CUDD_CACHE_SLOTS,0);
|
|
|
|
} /* end of bdd_start_with_params */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Creates a new variable in the manager.]
|
|
|
|
SideEffects []
|
|
|
|
******************************************************************************/
|
|
bdd_t *
|
|
bdd_create_variable(mgr)
|
|
bdd_manager *mgr;
|
|
{
|
|
DdNode *var;
|
|
DdManager *dd = (DdManager *) mgr;
|
|
DdNode *one = DD_ONE(dd);
|
|
|
|
if (dd->size >= CUDD_MAXINDEX -1) return(NULL);
|
|
do {
|
|
dd->reordered = 0;
|
|
var = cuddUniqueInter(dd,dd->size,one,Cudd_Not(one));
|
|
} while (dd->reordered == 1);
|
|
|
|
if (var == NULL) return(NULL);
|
|
cuddRef(var);
|
|
return(bdd_construct_bdd_t(dd,var));
|
|
|
|
} /* end of bdd_create_variable */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Creates a new variable and positions it after the
|
|
variable with the specified index.]
|
|
|
|
SideEffects []
|
|
|
|
******************************************************************************/
|
|
bdd_t *
|
|
bdd_create_variable_after(mgr, after_id)
|
|
bdd_manager *mgr;
|
|
bdd_variableId after_id;
|
|
{
|
|
DdNode *var;
|
|
DdManager *dd = (DdManager *) mgr;
|
|
int level;
|
|
|
|
if (after_id >= dd->size) return(NULL);
|
|
level = 1 + dd->perm[after_id];
|
|
var = Cudd_bddNewVarAtLevel(dd,level);
|
|
if (var == NULL) return(NULL);
|
|
cuddRef(var);
|
|
return(bdd_construct_bdd_t(dd,var));
|
|
|
|
} /* end of bdd_create_variable_after */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Returns the BDD representing the variable with given ID.]
|
|
|
|
SideEffects []
|
|
|
|
******************************************************************************/
|
|
bdd_t *
|
|
bdd_get_variable(mgr, variable_ID)
|
|
bdd_manager *mgr;
|
|
bdd_variableId variable_ID; /* unsigned int */
|
|
{
|
|
DdNode *var;
|
|
DdManager *dd = (DdManager *) mgr;
|
|
DdNode *one = DD_ONE(dd);
|
|
|
|
if (variable_ID >= CUDD_MAXINDEX -1) return(NULL);
|
|
do {
|
|
dd->reordered = 0;
|
|
var = cuddUniqueInter(dd,(int)variable_ID,one,Cudd_Not(one));
|
|
} while (dd->reordered == 1);
|
|
|
|
if (var == NULL) return(NULL);
|
|
cuddRef(var);
|
|
return(bdd_construct_bdd_t(dd,var));
|
|
|
|
} /* end of bdd_get_variable */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Creates a copy of the BDD.]
|
|
|
|
SideEffects []
|
|
|
|
******************************************************************************/
|
|
bdd_t *
|
|
bdd_dup(f)
|
|
bdd_t *f;
|
|
{
|
|
cuddRef(f->node);
|
|
return(bdd_construct_bdd_t((DdManager *)f->mgr,f->node));
|
|
|
|
} /* end of bdd_dup */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Deletes the BDD of f.]
|
|
|
|
SideEffects []
|
|
|
|
******************************************************************************/
|
|
void
|
|
bdd_free(f)
|
|
bdd_t *f;
|
|
{
|
|
if (f == NULL) {
|
|
fail("bdd_free: trying to free a NULL bdd_t");
|
|
}
|
|
|
|
if (f->free == TRUE) {
|
|
fail("bdd_free: trying to free a freed bdd_t");
|
|
}
|
|
|
|
Cudd_RecursiveDeref((DdManager *)f->mgr,f->node);
|
|
/* This is a bit overconservative. */
|
|
f->node = 0;
|
|
f->mgr = 0;
|
|
f->free = 0;
|
|
FREE(f);
|
|
return;
|
|
|
|
} /* end of bdd_free */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [And of two BDDs.]
|
|
|
|
SideEffects []
|
|
|
|
******************************************************************************/
|
|
bdd_t *
|
|
bdd_and(f, g, f_phase, g_phase)
|
|
bdd_t *f;
|
|
bdd_t *g;
|
|
boolean f_phase;
|
|
boolean g_phase;
|
|
{
|
|
DdManager *dd;
|
|
DdNode *newf,*newg,*fandg;
|
|
bdd_t *result;
|
|
|
|
/* Make sure both BDDs belong to the same manager. */
|
|
assert(f->mgr == g->mgr);
|
|
|
|
/* Modify the phases of the operands according to the parameters. */
|
|
if (!f_phase) {
|
|
newf = Cudd_Not(f->node);
|
|
} else {
|
|
newf = f->node;
|
|
}
|
|
if (!g_phase) {
|
|
newg = Cudd_Not(g->node);
|
|
} else {
|
|
newg = g->node;
|
|
}
|
|
|
|
/* Perform the AND operation */
|
|
dd = (DdManager *)f->mgr;
|
|
fandg = Cudd_bddAnd((DdManager *)f->mgr,newf,newg);
|
|
if (fandg == NULL) return(NULL);
|
|
cuddRef(fandg);
|
|
result = bdd_construct_bdd_t(dd,fandg);
|
|
|
|
return(result);
|
|
|
|
} /* end of bdd_and */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Abstracts variables from the product of two BDDs.]
|
|
|
|
SideEffects []
|
|
|
|
******************************************************************************/
|
|
bdd_t *
|
|
bdd_and_smooth(f, g, smoothing_vars)
|
|
bdd_t *f;
|
|
bdd_t *g;
|
|
array_t *smoothing_vars; /* of bdd_t *'s */
|
|
{
|
|
int i;
|
|
bdd_t *variable;
|
|
DdNode *cube,*tmpDd,*result;
|
|
DdManager *mgr;
|
|
|
|
/* Make sure both operands belong to the same manager. */
|
|
assert(f->mgr == g->mgr);
|
|
|
|
/* The Boulder package needs the smothing variables passed as a cube.
|
|
** Therefore we must build that cube from the indices of variables
|
|
** in the array before calling the procedure.
|
|
*/
|
|
mgr = (DdManager *)f->mgr;
|
|
Cudd_Ref(cube = DD_ONE(mgr));
|
|
for (i = 0; i < array_n(smoothing_vars); i++) {
|
|
variable = array_fetch(bdd_t *,smoothing_vars,i);
|
|
|
|
/* Make sure the variable belongs to the same manager. */
|
|
assert(mgr == variable->mgr);
|
|
|
|
tmpDd = Cudd_bddAnd(mgr,cube,variable->node);
|
|
if (tmpDd == NULL) {
|
|
Cudd_RecursiveDeref(mgr,cube);
|
|
return(NULL);
|
|
}
|
|
cuddRef(tmpDd);
|
|
Cudd_RecursiveDeref(mgr, cube);
|
|
cube = tmpDd;
|
|
}
|
|
|
|
/* Perform the smoothing */
|
|
result = Cudd_bddAndAbstract(mgr,f->node,g->node,cube);
|
|
if (result == NULL) {
|
|
Cudd_RecursiveDeref(mgr, cube);
|
|
return(NULL);
|
|
}
|
|
cuddRef(result);
|
|
/* Get rid of temporary results. */
|
|
Cudd_RecursiveDeref(mgr, cube);
|
|
|
|
/* Build the bdd_t structure for the result */
|
|
return(bdd_construct_bdd_t(mgr,result));
|
|
|
|
} /* end of bdd_and_smooth */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Return a minimum size BDD between bounds.]
|
|
|
|
SideEffects []
|
|
|
|
******************************************************************************/
|
|
bdd_t *
|
|
bdd_between(f_min, f_max)
|
|
bdd_t *f_min;
|
|
bdd_t *f_max;
|
|
{
|
|
bdd_t *temp, *ret;
|
|
|
|
temp = bdd_or(f_min, f_max, 1, 0);
|
|
ret = bdd_minimize(f_min, temp);
|
|
bdd_free(temp);
|
|
return(ret);
|
|
|
|
} /* end of bdd_between */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Computes the cofactor of f with respect to g.]
|
|
|
|
SideEffects []
|
|
|
|
******************************************************************************/
|
|
bdd_t *
|
|
bdd_cofactor(f, g)
|
|
bdd_t *f;
|
|
bdd_t *g;
|
|
{
|
|
DdNode *result;
|
|
|
|
/* Make sure both operands belong to the same manager */
|
|
assert(f->mgr == g->mgr);
|
|
|
|
/* We use Cudd_bddConstrain instead of Cudd_Cofactor for generality. */
|
|
result = Cudd_bddConstrain((DdManager *)f->mgr,f->node,g->node);
|
|
if (result == NULL) return(NULL);
|
|
cuddRef(result);
|
|
return(bdd_construct_bdd_t((DdManager *)f->mgr,result));
|
|
|
|
} /* end of bdd_cofactor */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Functional composition of a function by a variable.]
|
|
|
|
SideEffects []
|
|
|
|
******************************************************************************/
|
|
bdd_t *
|
|
bdd_compose(f, v, g)
|
|
bdd_t *f;
|
|
bdd_t *v;
|
|
bdd_t *g;
|
|
{
|
|
DdNode *result;
|
|
|
|
/* Make sure all operands belong to the same manager. */
|
|
assert(f->mgr == g->mgr);
|
|
assert(f->mgr == v->mgr);
|
|
|
|
result = Cudd_bddCompose(f->mgr,f->node,g->node,(int)Cudd_Regular(v->node)->index);
|
|
if (result == NULL) return(NULL);
|
|
cuddRef(result);
|
|
return(bdd_construct_bdd_t(f->mgr,result));
|
|
|
|
} /* end of bdd_compose */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Universal Abstraction of Variables.]
|
|
|
|
SideEffects []
|
|
|
|
******************************************************************************/
|
|
bdd_t *
|
|
bdd_consensus(f, quantifying_vars)
|
|
bdd_t *f;
|
|
array_t *quantifying_vars; /* of bdd_t *'s */
|
|
{
|
|
int i;
|
|
bdd_t *variable;
|
|
DdNode *cube,*tmpDd,*result;
|
|
bdd_manager *mgr;
|
|
|
|
/* The Boulder package needs the smothing variables passed as a cube.
|
|
** Therefore we must build that cube from the indices of the variables
|
|
** in the array before calling the procedure.
|
|
*/
|
|
mgr = f->mgr;
|
|
Cudd_Ref(cube = DD_ONE(mgr));
|
|
for (i = 0; i < array_n(quantifying_vars); i++) {
|
|
variable = array_fetch(bdd_t *,quantifying_vars,i);
|
|
|
|
/* Make sure the variable belongs to the same manager */
|
|
assert(mgr == variable->mgr);
|
|
|
|
tmpDd = Cudd_bddAnd(mgr,cube,variable->node);
|
|
if (tmpDd == NULL) {
|
|
Cudd_RecursiveDeref(mgr, cube);
|
|
return(NULL);
|
|
}
|
|
cuddRef(tmpDd);
|
|
Cudd_RecursiveDeref(mgr, cube);
|
|
cube = tmpDd;
|
|
}
|
|
|
|
/* Perform the consensus */
|
|
result = Cudd_bddUnivAbstract(mgr,f->node,cube);
|
|
if (result == NULL) {
|
|
Cudd_RecursiveDeref(mgr, cube);
|
|
return(NULL);
|
|
}
|
|
cuddRef(result);
|
|
/* Get rid of temporary results */
|
|
Cudd_RecursiveDeref(mgr, cube);
|
|
|
|
/* Build the bdd_t structure for the result */
|
|
return(bdd_construct_bdd_t(mgr,result));
|
|
|
|
} /* end of bdd_consensus */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [The compatible projection function.]
|
|
|
|
Description [The compatible projection function. The reference minterm
|
|
is chosen based on the phases of the quantifying variables. If all
|
|
variables are in positive phase, the minterm 111...111 is used as
|
|
reference.]
|
|
|
|
SideEffects []
|
|
|
|
******************************************************************************/
|
|
bdd_t *
|
|
bdd_cproject(f, quantifying_vars)
|
|
bdd_t *f;
|
|
array_t *quantifying_vars; /* of bdd_t* */
|
|
{
|
|
DdManager *dd;
|
|
DdNode *cube;
|
|
DdNode *res;
|
|
bdd_t *fi;
|
|
int nvars, i;
|
|
|
|
if (f == NULL) {
|
|
fail ("bdd_cproject: invalid BDD");
|
|
}
|
|
|
|
nvars = array_n(quantifying_vars);
|
|
if (nvars <= 0) {
|
|
fail("bdd_cproject: no projection variables");
|
|
}
|
|
dd = f->mgr;
|
|
|
|
cube = DD_ONE(dd);
|
|
cuddRef(cube);
|
|
for (i = nvars - 1; i >= 0; i--) {
|
|
DdNode *tmpp;
|
|
fi = array_fetch(bdd_t *, quantifying_vars, i);
|
|
tmpp = Cudd_bddAnd(dd,fi->node,cube);
|
|
if (tmpp == NULL) {
|
|
Cudd_RecursiveDeref(dd,cube);
|
|
return(NULL);
|
|
}
|
|
cuddRef(tmpp);
|
|
Cudd_RecursiveDeref(dd,cube);
|
|
cube = tmpp;
|
|
}
|
|
|
|
res = Cudd_CProjection(dd,f->node,cube);
|
|
if (res == NULL) {
|
|
Cudd_RecursiveDeref(dd,cube);
|
|
return(NULL);
|
|
}
|
|
cuddRef(res);
|
|
Cudd_RecursiveDeref(dd,cube);
|
|
|
|
return(bdd_construct_bdd_t(dd,res));
|
|
|
|
} /* end of bdd_cproject */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [ITE.]
|
|
|
|
SideEffects []
|
|
|
|
******************************************************************************/
|
|
bdd_t *
|
|
bdd_ite(i, t, e, i_phase, t_phase, e_phase)
|
|
bdd_t *i;
|
|
bdd_t *t;
|
|
bdd_t *e;
|
|
boolean i_phase;
|
|
boolean t_phase;
|
|
boolean e_phase;
|
|
{
|
|
DdNode *newi,*newt,*newe,*ite;
|
|
|
|
/* Make sure both bdds belong to the same mngr */
|
|
assert(i->mgr == t->mgr);
|
|
assert(i->mgr == e->mgr);
|
|
|
|
/* Modify the phases of the operands according to the parameters */
|
|
if (!i_phase) {
|
|
newi = Cudd_Not(i->node);
|
|
} else {
|
|
newi = i->node;
|
|
}
|
|
if (!t_phase) {
|
|
newt = Cudd_Not(t->node);
|
|
} else {
|
|
newt = t->node;
|
|
}
|
|
if (!e_phase) {
|
|
newe = Cudd_Not(e->node);
|
|
} else {
|
|
newe = e->node;
|
|
}
|
|
|
|
/* Perform the ITE operation */
|
|
ite = Cudd_bddIte(i->mgr,newi,newt,newe);
|
|
if (ite == NULL) return(NULL);
|
|
cuddRef(ite);
|
|
return(bdd_construct_bdd_t(i->mgr,ite));
|
|
|
|
} /* end of bdd_ite */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Restric operator as described in Coudert et al. ICCAD90.]
|
|
|
|
SideEffects []
|
|
|
|
******************************************************************************/
|
|
bdd_t *
|
|
bdd_minimize(f, c)
|
|
bdd_t *f;
|
|
bdd_t *c;
|
|
{
|
|
DdNode *result;
|
|
|
|
/* Make sure both operands belong to the same manager. */
|
|
assert(f->mgr == c->mgr);
|
|
|
|
result = Cudd_bddRestrict(f->mgr,f->node,c->node);
|
|
if (result == NULL) return(NULL);
|
|
cuddRef(result);
|
|
|
|
return(bdd_construct_bdd_t(f->mgr,result));
|
|
|
|
} /* end of bdd_minimize */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Parametrized version of the Restrict operator.]
|
|
|
|
Description [Parametrized version of the Restrict operator. Currently
|
|
defaults to bdd_minimize.]
|
|
|
|
SideEffects []
|
|
|
|
******************************************************************************/
|
|
/*ARGSUSED*/
|
|
bdd_t *
|
|
bdd_minimize_with_params(f, c, match_type, compl, no_new_vars, return_min)
|
|
bdd_t *f;
|
|
bdd_t *c;
|
|
bdd_min_match_type_t match_type;
|
|
boolean compl;
|
|
boolean no_new_vars;
|
|
boolean return_min;
|
|
{
|
|
return(bdd_minimize(f,c));
|
|
|
|
} /* end of bdd_minimize_with_params */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Negation.]
|
|
|
|
SideEffects []
|
|
|
|
******************************************************************************/
|
|
bdd_t *
|
|
bdd_not(f)
|
|
bdd_t *f;
|
|
{
|
|
DdNode *result;
|
|
|
|
Cudd_Ref(result = Cudd_Not(f->node));
|
|
return(bdd_construct_bdd_t((DdManager *)f->mgr,result));
|
|
|
|
} /* end of bdd_not */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Returns the one BDD.]
|
|
|
|
SideEffects []
|
|
|
|
******************************************************************************/
|
|
bdd_t *
|
|
bdd_one(mgr)
|
|
bdd_manager *mgr;
|
|
{
|
|
DdNode *result;
|
|
|
|
Cudd_Ref(result = DD_ONE((DdManager *)mgr));
|
|
return(bdd_construct_bdd_t((DdManager *)mgr,result));
|
|
|
|
} /* end of bdd_one */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Or of two BDDs.]
|
|
|
|
SideEffects []
|
|
|
|
******************************************************************************/
|
|
bdd_t *
|
|
bdd_or(f, g, f_phase, g_phase)
|
|
bdd_t *f;
|
|
bdd_t *g;
|
|
boolean f_phase;
|
|
boolean g_phase;
|
|
{
|
|
DdNode *newf,*newg,*forg;
|
|
bdd_t *result;
|
|
|
|
/* Make sure both bdds belong to the same mngr */
|
|
assert(f->mgr == g->mgr);
|
|
|
|
/* Modify the phases of the operands according to the parameters */
|
|
if (f_phase) {
|
|
newf = Cudd_Not(f->node);
|
|
} else {
|
|
newf = f->node;
|
|
}
|
|
if (g_phase) {
|
|
newg = Cudd_Not(g->node);
|
|
} else {
|
|
newg = g->node;
|
|
}
|
|
|
|
/* Perform the OR operation */
|
|
forg = Cudd_bddAnd(f->mgr,newf,newg);
|
|
if (forg == NULL) return(NULL);
|
|
forg = Cudd_Not(forg);
|
|
cuddRef(forg);
|
|
result = bdd_construct_bdd_t(f->mgr,forg);
|
|
|
|
return(result);
|
|
|
|
} /* end of bdd_or */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Existential abstraction of variables.]
|
|
|
|
SideEffects []
|
|
|
|
******************************************************************************/
|
|
bdd_t *
|
|
bdd_smooth(f, smoothing_vars)
|
|
bdd_t *f;
|
|
array_t *smoothing_vars; /* of bdd_t *'s */
|
|
{
|
|
int i;
|
|
bdd_t *variable;
|
|
DdNode *cube,*tmpDd,*result;
|
|
bdd_manager *mgr;
|
|
|
|
/* The Boulder package needs the smothing variables passed as a cube.
|
|
** Therefore we must build that cube from the indices of the variables
|
|
** in the array before calling the procedure.
|
|
*/
|
|
mgr = f->mgr;
|
|
Cudd_Ref(cube = DD_ONE(mgr));
|
|
for (i = 0; i < array_n(smoothing_vars); i++) {
|
|
variable = array_fetch(bdd_t *,smoothing_vars,i);
|
|
|
|
/* Make sure the variable belongs to the same manager. */
|
|
assert(mgr == variable->mgr);
|
|
|
|
tmpDd = Cudd_bddAnd(mgr,cube,variable->node);
|
|
if (tmpDd == NULL) {
|
|
Cudd_RecursiveDeref(mgr, cube);
|
|
return(NULL);
|
|
}
|
|
cuddRef(tmpDd);
|
|
Cudd_RecursiveDeref(mgr, cube);
|
|
cube = tmpDd;
|
|
}
|
|
|
|
/* Perform the smoothing */
|
|
result = Cudd_bddExistAbstract(mgr,f->node,cube);
|
|
if (result == NULL) {
|
|
Cudd_RecursiveDeref(mgr, cube);
|
|
return(NULL);
|
|
}
|
|
cuddRef(result);
|
|
|
|
/* Get rid of temporary results */
|
|
Cudd_RecursiveDeref(mgr, cube);
|
|
|
|
/* Build the bdd_t structure for the result */
|
|
return(bdd_construct_bdd_t(mgr,result));
|
|
|
|
} /* end of bdd_smooth */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Permutes the variables.]
|
|
|
|
SideEffects []
|
|
|
|
******************************************************************************/
|
|
bdd_t *
|
|
bdd_substitute(f, old_array, new_array)
|
|
bdd_t *f;
|
|
array_t *old_array; /* of bdd_t *'s */
|
|
array_t *new_array; /* of bdd_t *'s */
|
|
{
|
|
int maxOld;
|
|
int i,varIndex,from,to;
|
|
int *permut;
|
|
bdd_t *variable;
|
|
DdNode *result;
|
|
|
|
/* Make sure both arrays have the same number of elements. */
|
|
assert(array_n(old_array) == array_n(new_array));
|
|
|
|
/* Detect what is the highest index of variable to rename. */
|
|
maxOld = 0;
|
|
for (i = 0; i < array_n(old_array); i++) {
|
|
variable = array_fetch(bdd_t *, old_array, i);
|
|
/* Make sure the variable belongs to this manager. */
|
|
assert(f->mgr == variable->mgr);
|
|
|
|
varIndex = Cudd_Regular(variable->node)->index;
|
|
if (varIndex > maxOld) {
|
|
maxOld = varIndex;
|
|
}
|
|
}
|
|
maxOld++;
|
|
|
|
/* Allocate and fill the array with the trivial permutation. */
|
|
permut = ALLOC(int, maxOld);
|
|
for (i = 0; i < maxOld; i++) permut[i] = i;
|
|
|
|
/* Modify the permutation by looking at both arrays old and new. */
|
|
for (i = 0; i < array_n(old_array); i++) {
|
|
variable = array_fetch(bdd_t *, old_array, i);
|
|
from = Cudd_Regular(variable->node)->index;
|
|
variable = array_fetch(bdd_t *, new_array, i);
|
|
/* Make sure the variable belongs to this manager. */
|
|
assert(f->mgr == variable->mgr);
|
|
|
|
to = Cudd_Regular(variable->node)->index;
|
|
permut[from] = to;
|
|
}
|
|
|
|
result = Cudd_bddPermute(f->mgr,f->node,permut);
|
|
FREE(permut);
|
|
if (result == NULL) return(NULL);
|
|
cuddRef(result);
|
|
return(bdd_construct_bdd_t(f->mgr,result));
|
|
|
|
} /* end of bdd_substitute */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Returns the Then branch of the BDD.]
|
|
|
|
SideEffects []
|
|
|
|
******************************************************************************/
|
|
bdd_t *
|
|
bdd_then(f)
|
|
bdd_t *f;
|
|
{
|
|
DdNode *result;
|
|
|
|
result = Cudd_T(f->node);
|
|
result = Cudd_NotCond(result,Cudd_IsComplement(f->node));
|
|
cuddRef(result);
|
|
return(bdd_construct_bdd_t(f->mgr,result));
|
|
|
|
} /* end of bdd_then */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Returns the else branch of a BDD.]
|
|
|
|
SideEffects []
|
|
|
|
******************************************************************************/
|
|
bdd_t *
|
|
bdd_else(f)
|
|
bdd_t *f;
|
|
{
|
|
DdNode *result;
|
|
|
|
result = Cudd_E(f->node);
|
|
result = Cudd_NotCond(result,Cudd_IsComplement(f->node));
|
|
cuddRef(result);
|
|
return(bdd_construct_bdd_t(f->mgr,result));
|
|
|
|
} /* end of bdd_else */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Returns the BDD of the top variable.]
|
|
|
|
Description [Returns the BDD of the top variable of the argument. If
|
|
the argument is constant, it returns the constant function itself.]
|
|
|
|
SideEffects []
|
|
|
|
******************************************************************************/
|
|
bdd_t *
|
|
bdd_top_var(f)
|
|
bdd_t *f;
|
|
{
|
|
DdNode *result;
|
|
|
|
if (Cudd_IsConstant(f->node)) {
|
|
result = f->node;
|
|
} else {
|
|
result = f->mgr->vars[Cudd_Regular(f->node)->index];
|
|
}
|
|
cuddRef(result);
|
|
return(bdd_construct_bdd_t(f->mgr,result));
|
|
|
|
} /* end of bdd_top_var */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Computes the exclusive nor of two BDDs.]
|
|
|
|
SideEffects []
|
|
|
|
******************************************************************************/
|
|
bdd_t *
|
|
bdd_xnor(f, g)
|
|
bdd_t *f;
|
|
bdd_t *g;
|
|
{
|
|
DdNode *result;
|
|
|
|
/* Make sure both operands belong to the same manager. */
|
|
assert(f->mgr == g->mgr);
|
|
|
|
result = Cudd_bddIte(f->mgr,f->node,g->node,Cudd_Not(g->node));
|
|
if (result == NULL) return(NULL);
|
|
cuddRef(result);
|
|
return(bdd_construct_bdd_t(f->mgr,result));
|
|
|
|
} /* end of bdd_xnor */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Computes the exclusive or of two BDDs.]
|
|
|
|
SideEffects []
|
|
|
|
******************************************************************************/
|
|
bdd_t *
|
|
bdd_xor(f, g)
|
|
bdd_t *f;
|
|
bdd_t *g;
|
|
{
|
|
DdNode *result;
|
|
|
|
/* Make sure both operands belong to the same manager. */
|
|
assert(f->mgr == g->mgr);
|
|
|
|
result = Cudd_bddIte(f->mgr,f->node,Cudd_Not(g->node),g->node);
|
|
if (result == NULL) return(NULL);
|
|
cuddRef(result);
|
|
return(bdd_construct_bdd_t(f->mgr,result));
|
|
|
|
} /* end of bdd_xor */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Returns the constant zero BDD.]
|
|
|
|
SideEffects []
|
|
|
|
******************************************************************************/
|
|
bdd_t *
|
|
bdd_zero(mgr)
|
|
bdd_manager *mgr;
|
|
{
|
|
DdNode *result;
|
|
|
|
Cudd_Ref(result = Cudd_Not(DD_ONE((mgr))));
|
|
return(bdd_construct_bdd_t(mgr,result));
|
|
|
|
} /* end of bdd_zero */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Equality check.]
|
|
|
|
SideEffects []
|
|
|
|
******************************************************************************/
|
|
boolean
|
|
bdd_equal(f, g)
|
|
bdd_t *f;
|
|
bdd_t *g;
|
|
{
|
|
return(f->node == g->node);
|
|
|
|
} /* end of bdd_equal */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Returns a BDD included in the intersection of f and g.]
|
|
|
|
SideEffects []
|
|
|
|
******************************************************************************/
|
|
bdd_t *
|
|
bdd_intersects(f, g)
|
|
bdd_t *f;
|
|
bdd_t *g;
|
|
{
|
|
DdNode *result;
|
|
|
|
/* Make sure both operands belong to the same manager. */
|
|
assert(f->mgr == g->mgr);
|
|
|
|
result = Cudd_bddIntersect(f->mgr,f->node,g->node);
|
|
if (result == NULL) return(NULL);
|
|
cuddRef(result);
|
|
return(bdd_construct_bdd_t(f->mgr,result));
|
|
|
|
} /* end of bdd_intersects */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Checks a BDD for tautology.]
|
|
|
|
SideEffects []
|
|
|
|
******************************************************************************/
|
|
boolean
|
|
bdd_is_tautology(f, phase)
|
|
bdd_t *f;
|
|
boolean phase;
|
|
{
|
|
if (phase) {
|
|
return(f->node == DD_ONE(f->mgr));
|
|
} else {
|
|
return(f->node == Cudd_Not(DD_ONE(f->mgr)));
|
|
}
|
|
|
|
} /* end of bdd_is_tautology */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Tests for containment of f in g.]
|
|
|
|
SideEffects []
|
|
|
|
******************************************************************************/
|
|
boolean
|
|
bdd_leq(f, g, f_phase, g_phase)
|
|
bdd_t *f;
|
|
bdd_t *g;
|
|
boolean f_phase;
|
|
boolean g_phase;
|
|
{
|
|
DdNode *newf, *newg;
|
|
|
|
/* Make sure both operands belong to the same manager. */
|
|
assert(f->mgr == g->mgr);
|
|
|
|
if (f_phase) {
|
|
newf = f->node;
|
|
} else {
|
|
newf = Cudd_Not(f->node);
|
|
}
|
|
if (g_phase) {
|
|
newg = g->node;
|
|
} else {
|
|
newg = Cudd_Not(g->node);
|
|
}
|
|
|
|
return(Cudd_bddLeq(f->mgr,newf,newg));
|
|
|
|
} /* end of bdd_leq */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Counts the number of minterms in the on set.]
|
|
|
|
SideEffects []
|
|
|
|
******************************************************************************/
|
|
double
|
|
bdd_count_onset(f, var_array)
|
|
bdd_t *f;
|
|
array_t *var_array; /* of bdd_t *'s */
|
|
{
|
|
return(Cudd_CountMinterm(f->mgr,f->node,array_n(var_array)));
|
|
|
|
} /* end of bdd_count_onset */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Obtains the manager of the BDD.]
|
|
|
|
SideEffects []
|
|
|
|
******************************************************************************/
|
|
bdd_manager *
|
|
bdd_get_manager(f)
|
|
bdd_t *f;
|
|
{
|
|
return(f->mgr);
|
|
|
|
} /* end of bdd_get_manager */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Returns the node of the BDD.]
|
|
|
|
SideEffects [Sets is_complemented.]
|
|
|
|
******************************************************************************/
|
|
bdd_node *
|
|
bdd_get_node(f, is_complemented)
|
|
bdd_t *f;
|
|
boolean *is_complemented; /* return */
|
|
{
|
|
if (Cudd_IsComplement(f->node)) {
|
|
*is_complemented = TRUE;
|
|
return(Cudd_Regular(f->node));
|
|
}
|
|
*is_complemented = FALSE;
|
|
return(f->node);
|
|
|
|
} /* end of bdd_get_node */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Returns the free field of the BDD.]
|
|
|
|
SideEffects []
|
|
|
|
******************************************************************************/
|
|
int
|
|
bdd_get_free(f)
|
|
bdd_t *f;
|
|
{
|
|
return (f->free);
|
|
|
|
} /* end of bdd_get_free */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Obtains some statistics of the BDD package.]
|
|
|
|
SideEffects [Sets stats.]
|
|
|
|
******************************************************************************/
|
|
/*ARGSUSED*/
|
|
void
|
|
bdd_get_stats(mgr, stats)
|
|
bdd_manager *mgr;
|
|
bdd_stats *stats; /* return */
|
|
{
|
|
stats->nodes.total = mgr->keys;
|
|
stats->nodes.used = mgr->keys - mgr->dead;
|
|
stats->nodes.unused = mgr->dead;
|
|
stats->cache.itetable.hits = (unsigned int) Cudd_ReadCacheHits(mgr);
|
|
stats->cache.itetable.misses = (unsigned int)
|
|
(Cudd_ReadCacheLookUps(mgr) - Cudd_ReadCacheHits(mgr));
|
|
stats->cache.itetable.collisions = mgr->cachecollisions;
|
|
stats->cache.itetable.inserts = mgr->cacheinserts;
|
|
stats->gc.times = Cudd_ReadGarbageCollections(mgr);
|
|
return;
|
|
|
|
} /* end of bdd_get_stats */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Obtains the support of the BDD.]
|
|
|
|
SideEffects []
|
|
|
|
******************************************************************************/
|
|
var_set_t *
|
|
bdd_get_support(f)
|
|
bdd_t *f;
|
|
{
|
|
DdNode *support, *scan;
|
|
var_set_t *result;
|
|
|
|
support = Cudd_Support(f->mgr,f->node);
|
|
if (support == NULL) return(NULL);
|
|
cuddRef(support);
|
|
|
|
result = var_set_new((int) f->mgr->size);
|
|
scan = support;
|
|
while (!cuddIsConstant(scan)) {
|
|
var_set_set_elt(result, scan->index);
|
|
scan = cuddT(scan);
|
|
}
|
|
Cudd_RecursiveDeref(f->mgr,support);
|
|
|
|
return(result);
|
|
|
|
} /* end of bdd_get_support */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Obtains the array of indices of an array of variables.]
|
|
|
|
SideEffects []
|
|
|
|
******************************************************************************/
|
|
array_t *
|
|
bdd_get_varids(var_array)
|
|
array_t *var_array;
|
|
{
|
|
int i;
|
|
int index;
|
|
bdd_t *var;
|
|
array_t *result = array_alloc(int,array_n(var_array));
|
|
|
|
for (i = 0; i < array_n(var_array); i++) {
|
|
var = array_fetch(bdd_t *, var_array, i);
|
|
index = Cudd_Regular(var->node)->index;
|
|
(void) array_insert_last(int, result, index);
|
|
}
|
|
return(result);
|
|
|
|
} /* end of bdd_get_varids */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Returns the number of variables in the manager.]
|
|
|
|
SideEffects []
|
|
|
|
******************************************************************************/
|
|
unsigned int
|
|
bdd_num_vars(mgr)
|
|
bdd_manager *mgr;
|
|
{
|
|
return(mgr->size);
|
|
|
|
} /* end of bdd_num_vars */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Prints the BDD.]
|
|
|
|
SideEffects []
|
|
|
|
******************************************************************************/
|
|
void
|
|
bdd_print(f)
|
|
bdd_t *f;
|
|
{
|
|
(void) cuddP(f->mgr,f->node);
|
|
|
|
} /* end of bdd_print */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Prints statistics about the package.]
|
|
|
|
SideEffects []
|
|
|
|
******************************************************************************/
|
|
void
|
|
bdd_print_stats(stats, file)
|
|
bdd_stats stats;
|
|
FILE *file;
|
|
{
|
|
#ifndef DD_STATS
|
|
fprintf(stderr,"CU DD package: bdd_print_stats: Statistics turned off. No output\n");
|
|
#else
|
|
fprintf(file,"CU DD Package Statistics\n");
|
|
fprintf(file," Cache hits : %d\n",stats.cache.itetable.hits);
|
|
fprintf(file," Cache misses : %d\n",stats.cache.itetable.misses);
|
|
fprintf(file," Cache collisions : %d\n",stats.cache.itetable.collisions);
|
|
fprintf(file," Cache inserts: %d\n",stats.cache.itetable.inserts);
|
|
#endif
|
|
return;
|
|
|
|
} /* end of bdd_print_stats */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Computes the number of nodes of a BDD.]
|
|
|
|
SideEffects []
|
|
|
|
******************************************************************************/
|
|
int
|
|
bdd_size(f)
|
|
bdd_t *f;
|
|
{
|
|
return(Cudd_DagSize(f->node));
|
|
|
|
} /* end of bdd_size */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Accesses the id of the top variable.]
|
|
|
|
SideEffects []
|
|
|
|
******************************************************************************/
|
|
bdd_variableId
|
|
bdd_top_var_id(f)
|
|
bdd_t *f;
|
|
{
|
|
return(Cudd_Regular(f->node)->index);
|
|
|
|
} /* end of bdd_top_var_id */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Accesses the external_hooks field of the manager.]
|
|
|
|
SideEffects []
|
|
|
|
******************************************************************************/
|
|
bdd_external_hooks *
|
|
bdd_get_external_hooks(mgr)
|
|
bdd_manager *mgr;
|
|
{
|
|
return((bdd_external_hooks *)(mgr->hooks));
|
|
|
|
} /* end of bdd_get_external_hooks */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Registers a new hook with the manager.]
|
|
|
|
SideEffects []
|
|
|
|
******************************************************************************/
|
|
/*ARGSUSED*/
|
|
void
|
|
bdd_register_daemon(mgr, daemon)
|
|
bdd_manager *mgr;
|
|
void (*daemon)();
|
|
{
|
|
fprintf(stderr,"CU DD Package: bdd_register_daemon translated to no-op.\n");
|
|
return;
|
|
|
|
} /* end of bdd_register_daemon */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Turns on or off garbage collection.]
|
|
|
|
SideEffects []
|
|
|
|
******************************************************************************/
|
|
void
|
|
bdd_set_gc_mode(mgr, no_gc)
|
|
bdd_manager *mgr;
|
|
boolean no_gc;
|
|
{
|
|
if (no_gc) {
|
|
Cudd_DisableGarbageCollection(mgr);
|
|
} else {
|
|
Cudd_EnableGarbageCollection(mgr);
|
|
}
|
|
return;
|
|
|
|
} /* end of bdd_set_gc_mode */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Reorders the BDD pool.]
|
|
|
|
SideEffects []
|
|
|
|
******************************************************************************/
|
|
void
|
|
bdd_dynamic_reordering(mgr, algorithm_type)
|
|
bdd_manager *mgr;
|
|
bdd_reorder_type_t algorithm_type;
|
|
{
|
|
switch (algorithm_type) {
|
|
case BDD_REORDER_SIFT:
|
|
mgr->autoMethod = CUDD_REORDER_SIFT;
|
|
mgr->autoDyn = 1;
|
|
break;
|
|
case BDD_REORDER_WINDOW:
|
|
case BDD_REORDER_WINDOW4:
|
|
mgr->autoMethod = CUDD_REORDER_WINDOW4;
|
|
mgr->autoDyn = 1;
|
|
break;
|
|
case BDD_REORDER_NONE:
|
|
mgr->autoDyn = 0;
|
|
break;
|
|
case BDD_REORDER_SAME:
|
|
mgr->autoDyn = 1;
|
|
break;
|
|
case BDD_REORDER_RANDOM:
|
|
mgr->autoMethod = CUDD_REORDER_RANDOM;
|
|
mgr->autoDyn = 1;
|
|
break;
|
|
case BDD_REORDER_RANDOM_PIVOT:
|
|
mgr->autoMethod = CUDD_REORDER_RANDOM_PIVOT;
|
|
mgr->autoDyn = 1;
|
|
break;
|
|
case BDD_REORDER_SIFT_CONVERGE:
|
|
mgr->autoMethod = CUDD_REORDER_SIFT_CONVERGE;
|
|
mgr->autoDyn = 1;
|
|
break;
|
|
case BDD_REORDER_SYMM_SIFT:
|
|
mgr->autoMethod = CUDD_REORDER_SYMM_SIFT;
|
|
mgr->autoDyn = 1;
|
|
break;
|
|
case BDD_REORDER_SYMM_SIFT_CONV:
|
|
mgr->autoMethod = CUDD_REORDER_SYMM_SIFT_CONV;
|
|
mgr->autoDyn = 1;
|
|
break;
|
|
case BDD_REORDER_WINDOW2:
|
|
mgr->autoMethod = CUDD_REORDER_WINDOW2;
|
|
mgr->autoDyn = 1;
|
|
break;
|
|
case BDD_REORDER_WINDOW3:
|
|
mgr->autoMethod = CUDD_REORDER_WINDOW3;
|
|
mgr->autoDyn = 1;
|
|
break;
|
|
case BDD_REORDER_WINDOW2_CONV:
|
|
mgr->autoMethod = CUDD_REORDER_WINDOW2_CONV;
|
|
mgr->autoDyn = 1;
|
|
break;
|
|
case BDD_REORDER_WINDOW3_CONV:
|
|
mgr->autoMethod = CUDD_REORDER_WINDOW3_CONV;
|
|
mgr->autoDyn = 1;
|
|
break;
|
|
case BDD_REORDER_WINDOW4_CONV:
|
|
mgr->autoMethod = CUDD_REORDER_WINDOW4_CONV;
|
|
mgr->autoDyn = 1;
|
|
break;
|
|
case BDD_REORDER_GROUP_SIFT:
|
|
mgr->autoMethod = CUDD_REORDER_GROUP_SIFT;
|
|
mgr->autoDyn = 1;
|
|
break;
|
|
case BDD_REORDER_GROUP_SIFT_CONV:
|
|
mgr->autoMethod = CUDD_REORDER_GROUP_SIFT_CONV;
|
|
mgr->autoDyn = 1;
|
|
break;
|
|
case BDD_REORDER_ANNEALING:
|
|
mgr->autoMethod = CUDD_REORDER_ANNEALING;
|
|
mgr->autoDyn = 1;
|
|
break;
|
|
case BDD_REORDER_GENETIC:
|
|
mgr->autoMethod = CUDD_REORDER_GENETIC;
|
|
mgr->autoDyn = 1;
|
|
break;
|
|
default:
|
|
fprintf(stderr,"CU DD Package: Reordering algorithm not considered\n");
|
|
}
|
|
|
|
} /* end of bdd_dynamic_reordering */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Calls reordering explicitly.]
|
|
|
|
SideEffects []
|
|
|
|
******************************************************************************/
|
|
void
|
|
bdd_reorder(mgr)
|
|
bdd_manager *mgr;
|
|
{
|
|
(void) Cudd_ReduceHeap(mgr,mgr->autoMethod,10); /* 10 = whatever (Verbatim from file ddTable.c) */
|
|
return;
|
|
|
|
} /* end of bdd_reorder */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Read the number of reorderings the package has performed
|
|
so far.]
|
|
|
|
SideEffects []
|
|
|
|
******************************************************************************/
|
|
int
|
|
bdd_read_reorderings(mgr)
|
|
bdd_manager *mgr;
|
|
{
|
|
return Cudd_ReadReorderings((DdManager *)mgr);
|
|
|
|
} /* end of bdd_read_reorderings */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Gets the id variable for one level in the BDD.]
|
|
|
|
SideEffects []
|
|
|
|
******************************************************************************/
|
|
bdd_variableId
|
|
bdd_get_id_from_level(mgr, level)
|
|
bdd_manager *mgr;
|
|
long level;
|
|
{
|
|
return(mgr->invperm[level]);
|
|
|
|
} /* end of bdd_get_id_from_level */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Gets the level of the top variable of the BDD.]
|
|
|
|
SideEffects []
|
|
|
|
******************************************************************************/
|
|
long
|
|
bdd_top_var_level(mgr, fn)
|
|
bdd_manager *mgr;
|
|
bdd_t *fn;
|
|
{
|
|
return((long) cuddI(mgr,Cudd_Regular(fn->node)->index));
|
|
|
|
} /* end of bdd_top_var_level */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Returns TRUE if the argument BDD is a cube; FALSE
|
|
otherwise.]
|
|
|
|
SideEffects []
|
|
|
|
******************************************************************************/
|
|
boolean
|
|
bdd_is_cube(f)
|
|
bdd_t *f;
|
|
{
|
|
struct DdManager *manager;
|
|
|
|
if (f == NULL) {
|
|
fail("bdd_is_cube: invalid BDD");
|
|
}
|
|
if (f->free) fail ("Freed BDD passed to bdd_is_cube");
|
|
manager = (DdManager *) f->mgr;
|
|
return((boolean)cuddCheckCube(manager,f->node));
|
|
|
|
} /* end of bdd_is_cube */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Calls the garbage collector explicitly.]
|
|
|
|
SideEffects []
|
|
|
|
******************************************************************************/
|
|
void
|
|
bdd_gc(mgr)
|
|
bdd_manager *mgr;
|
|
{
|
|
cuddGarbageCollect(mgr,1);
|
|
|
|
} /* end of bdd_gc */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Computes the shared size of an array of BDDs.]
|
|
|
|
Description [Computes the shared size of an array of BDDs. Returns
|
|
CUDD_OUT_OF_MEM in case of failure.]
|
|
|
|
SideEffects []
|
|
|
|
******************************************************************************/
|
|
long
|
|
bdd_size_multiple(bddArray)
|
|
array_t *bddArray;
|
|
{
|
|
DdNode **nodeArray;
|
|
bdd_t *bddUnit;
|
|
long result;
|
|
int i;
|
|
|
|
nodeArray = ALLOC(DdNode *, array_n(bddArray));
|
|
if (nodeArray == NULL) return(CUDD_OUT_OF_MEM);
|
|
for (i = 0; i < array_n(bddArray); i++) {
|
|
bddUnit = array_fetch(bdd_t *, bddArray, i);
|
|
nodeArray[i] = bddUnit->node;
|
|
}
|
|
|
|
result = Cudd_SharingSize(nodeArray,array_n(bddArray));
|
|
|
|
/* Clean up */
|
|
FREE(nodeArray);
|
|
|
|
return(result);
|
|
|
|
} /* end of bdd_size_multiple */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Returns the first cube of the function.
|
|
A generator is also returned, which will iterate over the rest.]
|
|
|
|
Description [Defines an iterator on the onset of a BDD. Two routines
|
|
are provided: bdd_first_cube, which extracts one cube from a BDD and
|
|
returns a bdd_gen structure containing the information necessary to
|
|
continue the enumeration; and bdd_next_cube, which returns 1 if
|
|
another cube was found, and 0 otherwise. A cube is represented as an
|
|
array of bdd_literal (which are integers in {0, 1, 2}), where 0
|
|
represents negated literal, 1 for literal, and 2 for don't care.
|
|
Returns a disjoint cover. A third routine is there to clean up.]
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso [bdd_next_cube bdd_gen_free]
|
|
|
|
******************************************************************************/
|
|
bdd_gen *
|
|
bdd_first_cube(fn, cube)
|
|
bdd_t *fn;
|
|
array_t **cube; /* of bdd_literal */
|
|
{
|
|
bdd_manager *manager;
|
|
bdd_gen *gen;
|
|
int i;
|
|
int *icube;
|
|
CUDD_VALUE_TYPE value;
|
|
|
|
/* Make sure we receive a valid bdd_t. (So to speak.) */
|
|
assert(fn != 0);
|
|
|
|
manager = fn->mgr;
|
|
|
|
/* Initialize the generator. */
|
|
gen = ALLOC(bdd_gen,1);
|
|
if (gen == NULL) return(NULL);
|
|
gen->manager = manager;
|
|
|
|
gen->cube = array_alloc(bdd_literal, manager->size);
|
|
if (gen->cube == NULL) {
|
|
fail("Bdd Package: Out of memory in bdd_first_cube");
|
|
}
|
|
|
|
gen->ddGen = Cudd_FirstCube(manager,fn->node,&icube,&value);
|
|
if (gen->ddGen == NULL) {
|
|
fail("Cudd Package: Out of memory in bdd_first_cube");
|
|
}
|
|
|
|
if (!Cudd_IsGenEmpty(gen->ddGen)) {
|
|
/* Copy icube to the array_t cube. */
|
|
for (i = 0; i < manager->size; i++) {
|
|
int myconst = icube[i];
|
|
array_insert(bdd_literal, gen->cube, i, myconst);
|
|
}
|
|
*cube = gen->cube;
|
|
}
|
|
|
|
return(gen);
|
|
|
|
} /* end of bdd_first_cube */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Gets the next cube on the generator. Returns {TRUE,
|
|
FALSE} when {more, no more}.]
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso [bdd_first_cube bdd_gen_free]
|
|
|
|
******************************************************************************/
|
|
boolean
|
|
bdd_next_cube(gen, cube)
|
|
bdd_gen *gen;
|
|
array_t **cube; /* of bdd_literal */
|
|
{
|
|
int retval;
|
|
int *icube;
|
|
CUDD_VALUE_TYPE value;
|
|
int i;
|
|
|
|
retval = Cudd_NextCube(gen->ddGen,&icube,&value);
|
|
if (!Cudd_IsGenEmpty(gen->ddGen)) {
|
|
/* Copy icube to the array_t cube. */
|
|
for (i = 0; i < gen->manager->size; i++) {
|
|
int myconst = icube[i];
|
|
array_insert(bdd_literal, gen->cube, i, myconst);
|
|
}
|
|
*cube = gen->cube;
|
|
}
|
|
|
|
return(retval);
|
|
|
|
} /* end of bdd_next_cube */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Gets the first node in the BDD and returns a generator.]
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso [bdd_next_node]
|
|
|
|
******************************************************************************/
|
|
bdd_gen *
|
|
bdd_first_node(fn, node)
|
|
bdd_t *fn;
|
|
bdd_node **node; /* return */
|
|
{
|
|
bdd_manager *manager;
|
|
bdd_gen *gen;
|
|
|
|
/* Make sure we receive a valid bdd_t. (So to speak.) */
|
|
assert(fn != 0);
|
|
|
|
manager = fn->mgr;
|
|
|
|
/* Initialize the generator. */
|
|
gen = ALLOC(bdd_gen,1);
|
|
if (gen == NULL) return(NULL);
|
|
gen->manager = manager;
|
|
gen->cube = NULL;
|
|
|
|
gen->ddGen = Cudd_FirstNode(manager,fn->node,node);
|
|
if (gen->ddGen == NULL) {
|
|
fail("Cudd Package: Out of memory in bdd_first_node");
|
|
}
|
|
|
|
return(gen);
|
|
|
|
} /* end of bdd_first_node */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Gets the next node in the BDD. Returns {TRUE, FALSE} when
|
|
{more, no more}.]
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso [bdd_first_node]
|
|
|
|
******************************************************************************/
|
|
boolean
|
|
bdd_next_node(gen, node)
|
|
bdd_gen *gen;
|
|
bdd_node **node; /* return */
|
|
{
|
|
return(Cudd_NextNode(gen->ddGen,node));
|
|
|
|
} /* end of bdd_next_node */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Frees up the space used by the generator. Returns an int
|
|
so that it is easier to fit in a foreach macro. Returns 0 (to make it
|
|
easy to put in expressions).]
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
******************************************************************************/
|
|
int
|
|
bdd_gen_free(gen)
|
|
bdd_gen *gen;
|
|
{
|
|
if (gen->cube != NULL) array_free(gen->cube);
|
|
Cudd_GenFree(gen->ddGen);
|
|
FREE(gen);
|
|
return(0);
|
|
|
|
} /* end of bdd_gen_free */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Queries the status of a generator.]
|
|
|
|
Description [Queries the status of a generator. Returns 1 if the
|
|
generator is empty or NULL; 0 otherswise.]
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso [bdd_first_cube bdd_next_cube bdd_first_node bdd_next_node
|
|
bdd_gen_free]
|
|
|
|
******************************************************************************/
|
|
boolean
|
|
bdd_is_gen_empty(gen)
|
|
bdd_gen *gen;
|
|
{
|
|
return(Cudd_IsGenEmpty(gen->ddGen));
|
|
|
|
} /* end of bdd_is_gen_empty */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Function that creates a variable of a given index.]
|
|
|
|
SideEffects []
|
|
|
|
******************************************************************************/
|
|
bdd_t *
|
|
bdd_var_with_index(manager, index)
|
|
bdd_manager *manager;
|
|
int index;
|
|
{
|
|
DdNode *var;
|
|
|
|
var = Cudd_bddIthVar(manager, index);
|
|
cuddRef(var);
|
|
return(bdd_construct_bdd_t(manager, var));
|
|
|
|
} /* end of bdd_var_with_index */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Temporary function that is empty.]
|
|
|
|
SideEffects []
|
|
|
|
******************************************************************************/
|
|
/*ARGSUSED*/
|
|
void
|
|
bdd_new_var_block(f, n)
|
|
bdd_t *f;
|
|
long n;
|
|
{
|
|
return;
|
|
|
|
} /* end of bdd_new_var_block */
|
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
/* Definition of internal functions */
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
/* Definition of static functions */
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Builds the bdd_t structure.]
|
|
|
|
Description [Builds the bdd_t structure from manager and node.
|
|
Assumes that the reference count of the node has already been
|
|
increased.]
|
|
|
|
SideEffects []
|
|
|
|
******************************************************************************/
|
|
static bdd_t *
|
|
bdd_construct_bdd_t(mgr,fn)
|
|
DdManager *mgr;
|
|
DdNode * fn;
|
|
{
|
|
bdd_t *result;
|
|
|
|
result = ALLOC(bdd_t, 1);
|
|
if (result == NULL) {
|
|
Cudd_RecursiveDeref(mgr,fn);
|
|
return(NULL);
|
|
}
|
|
result->mgr = mgr;
|
|
result->node = fn;
|
|
result->free = FALSE;
|
|
return(result);
|
|
|
|
} /* end of bdd_construct_bdd_t */
|