Esempio n. 1
0
DdNode*
cuddauxAddGuardOfNodeRecur(DdManager* manager, DdNode* f, DdNode* h)
{
  DdNode *one, *res, *T, *E;
  int topf, toph;

  /* Handle terminal cases */
  one = DD_ONE(manager);
  if (f==h){
    return(one);
  }
  topf = cuddI(manager,f->index);
  toph = cuddI(manager,h->index);
  if (topf >= toph){
    return Cudd_Not(one);
  }

  /* Look in the cache */
  res = cuddCacheLookup2(manager,Cuddaux_addGuardOfNode,f,h);
  if (res != NULL)
    return(res);

  T = cuddauxAddGuardOfNodeRecur(manager,cuddT(f),h);
  if (T == NULL)
    return(NULL);
  cuddRef(T);
  E = cuddauxAddGuardOfNodeRecur(manager,cuddE(f),h);
  if (E == NULL){
    Cudd_IterDerefBdd(manager, T);
    return(NULL);
  }
  cuddRef(E);
  if (T == E){
    res = T;
  }
  else {
    if (Cudd_IsComplement(T)){
      res = cuddUniqueInter(manager,f->index,Cudd_Not(T),Cudd_Not(E));
      if (res == NULL) {
	Cudd_IterDerefBdd(manager, T);
	Cudd_IterDerefBdd(manager, E);
	return(NULL);
      }
      res = Cudd_Not(res);
    }
    else {
      res = cuddUniqueInter(manager,f->index,T,E);
      if (res == NULL) {
	Cudd_IterDerefBdd(manager, T);
	Cudd_IterDerefBdd(manager, E);
	return(NULL);
      }
    }
  }
  cuddDeref(T);
  cuddDeref(E);
  cuddCacheInsert2(manager,Cuddaux_addGuardOfNode,f,h,res);
  return(res);
}
Esempio n. 2
0
/**Function********************************************************************

  Synopsis    [Implements the recursive step of Cudd_bddVarMap.]

  Description [Implements the recursive step of Cudd_bddVarMap.
  Returns a pointer to the result if successful; NULL otherwise.]

  SideEffects [None]

  SeeAlso     [Cudd_bddVarMap]

******************************************************************************/
static DdNode *
cuddBddVarMapRecur(
  DdManager *manager /* DD manager */,
  DdNode *f /* BDD to be remapped */)
{
    DdNode	*F, *T, *E;
    DdNode	*res;
    int		index;

    statLine(manager);
    F = Cudd_Regular(f);

    /* Check for terminal case of constant node. */
    if (cuddIsConstant(F)) {
	return(f);
    }

    /* If problem already solved, look up answer and return. */
    if (F->ref != 1 &&
	(res = cuddCacheLookup1(manager,Cudd_bddVarMap,F)) != NULL) {
	return(Cudd_NotCond(res,F != f));
    }

    /* Split and recur on children of this node. */
    T = cuddBddVarMapRecur(manager,cuddT(F));
    if (T == NULL) return(NULL);
    cuddRef(T);
    E = cuddBddVarMapRecur(manager,cuddE(F));
    if (E == NULL) {
	Cudd_IterDerefBdd(manager, T);
	return(NULL);
    }
    cuddRef(E);

    /* Move variable that should be in this position to this position
    ** by retrieving the single var BDD for that variable, and calling
    ** cuddBddIteRecur with the T and E we just created.
    */
    index = manager->map[F->index];
    res = cuddBddIteRecur(manager,manager->vars[index],T,E);
    if (res == NULL) {
	Cudd_IterDerefBdd(manager, T);
	Cudd_IterDerefBdd(manager, E);
	return(NULL);
    }
    cuddRef(res);
    Cudd_IterDerefBdd(manager, T);
    Cudd_IterDerefBdd(manager, E);

    /* Do not keep the result if the reference count is only 1, since
    ** it will not be visited again.
    */
    if (F->ref != 1) {
	cuddCacheInsert1(manager,Cudd_bddVarMap,F,res);
    }
    cuddDeref(res);
    return(Cudd_NotCond(res,F != f));

} /* end of cuddBddVarMapRecur */
Esempio n. 3
0
/**Function********************************************************************

  Synopsis    [Performs the recursive steps of Cudd_bddBoleanDiff.]

  Description [Performs the recursive steps of Cudd_bddBoleanDiff.
  Returns the BDD obtained by XORing the cofactors of f with respect to
  var if successful; NULL otherwise. Exploits the fact that dF/dx =
  dF'/dx.]

  SideEffects [None]

  SeeAlso     []

******************************************************************************/
DdNode *
cuddBddBooleanDiffRecur(
  DdManager * manager,
  DdNode * f,
  DdNode * var)
{
    DdNode *T, *E, *res, *res1, *res2;

    statLine(manager);
    if (cuddI(manager,f->index) > manager->perm[var->index]) {
	/* f does not depend on var. */
	return(Cudd_Not(DD_ONE(manager)));
    }

    /* From now on, f is non-constant. */

    /* If the two indices are the same, so are their levels. */
    if (f->index == var->index) {
	res = cuddBddXorRecur(manager, cuddT(f), cuddE(f));
        return(res);
    }

    /* From now on, cuddI(manager,f->index) < cuddI(manager,cube->index). */

    /* Check the cache. */
    res = cuddCacheLookup2(manager, cuddBddBooleanDiffRecur, f, var);
    if (res != NULL) {
	return(res);
    }

    /* Compute the cofactors of f. */
    T = cuddT(f); E = cuddE(f);

    res1 = cuddBddBooleanDiffRecur(manager, T, var);
    if (res1 == NULL) return(NULL);
    cuddRef(res1);
    res2 = cuddBddBooleanDiffRecur(manager, Cudd_Regular(E), var);
    if (res2 == NULL) {
	Cudd_IterDerefBdd(manager, res1);
	return(NULL);
    }
    cuddRef(res2);
    /* ITE takes care of possible complementation of res1 and of the
    ** case in which res1 == res2. */
    res = cuddBddIteRecur(manager, manager->vars[f->index], res1, res2);
    if (res == NULL) {
	Cudd_IterDerefBdd(manager, res1);
	Cudd_IterDerefBdd(manager, res2);
	return(NULL);
    }
    cuddDeref(res1);
    cuddDeref(res2);
    cuddCacheInsert2(manager, cuddBddBooleanDiffRecur, f, var, res);
    return(res);

} /* end of cuddBddBooleanDiffRecur */
Esempio n. 4
0
/**Function********************************************************************

  Synopsis    [Performs the recursive step of Cuddaux_Support.]

  Description [Performs the recursive step of Cuddaux_Support.]

  SideEffects [None]

  SeeAlso     []

******************************************************************************/
DdNode*
cuddauxSupportRecur(DdManager* dd,
		    DdNode * f)
{
  DdNode *one, *fv, *fvn, *T,*E, *res, *res1;

  one = DD_ONE(dd);
  if (cuddIsConstant(f)) {
    return one;
  }
  fv = cuddT(f);
  fvn = Cudd_Regular(cuddE(f));
  if (cuddIsConstant(fv) && cuddIsConstant(fvn)){
    return dd->vars[f->index];
  }
  /* Look in the cache */
  res = cuddCacheLookup1(dd,Cuddaux_Support,f);
  if (res != NULL)
    return(res);

  T = cuddIsConstant(fv) ? one : cuddauxSupportRecur(dd,fv);
  if (T == NULL)
    return(NULL);
  cuddRef(T);
  E = cuddIsConstant(fvn) ? one : cuddauxSupportRecur(dd,fvn);
  if (E == NULL){
    Cudd_IterDerefBdd(dd,T);
    return(NULL);
  }
  if (T==E){
    res = cuddUniqueInter(dd,f->index,T,Cudd_Not(one));
    if (res == NULL){
      Cudd_IterDerefBdd(dd,T);
      return NULL;
    }
    cuddDeref(T);
  }
  else {
    cuddRef(E);
    res1 = cuddBddAndRecur(dd,T,E);
    if (res1 == NULL){
      Cudd_IterDerefBdd(dd,T);
      Cudd_IterDerefBdd(dd,E);
      return(NULL);
    }
    cuddRef(res1);
    Cudd_IterDerefBdd(dd,T);
    Cudd_IterDerefBdd(dd,E);
    res = cuddUniqueInter(dd,f->index,res1,Cudd_Not(one));
    if (res == NULL){
      Cudd_IterDerefBdd(dd,T);
      Cudd_IterDerefBdd(dd,E);
      Cudd_IterDerefBdd(dd,res1);
      return(NULL);
    }
    cuddDeref(res1);
  }
  cuddCacheInsert1(dd,Cuddaux_Support,f,res);
  return(res);
} /* end of cuddauxSupportRecur */
Esempio n. 5
0
/**Function********************************************************************

  Synopsis    [Finds the number of variables on which a DD depends, using Cuddaux_Support.]

  Description []

  SideEffects [None]

  SeeAlso     [Cudd_SupportSize]

******************************************************************************/
int Cuddaux_SupportSize(DdManager* dd, DdNode* f)
{
  DdNode* res;
  int size;
  res = Cuddaux_Support(dd,f);
  cuddRef(res);
  size = Cudd_DagSize(res) - 1;
  assert(size>=0);
  Cudd_IterDerefBdd(dd,res);
  return size;
}
Esempio n. 6
0
/**Function********************************************************************

  Synopsis    [Classifies the variables in the support of two DDs.]

  Description [Classifies the variables in the support of two DDs
  <code>f</code> and <code>g</code>, depending on whther they appear
  in both DDs, only in <code>f</code>, or only in <code>g</code>.
  Returns 1 if successful; 0 otherwise.]

  SideEffects [The cubes of the three classes of variables are
  returned as side effects.]

  SeeAlso     []

******************************************************************************/
int
Cuddaux_ClassifySupport(
			DdManager * dd /* manager */,
			DdNode * f /* first DD */,
			DdNode * g /* second DD */,
			DdNode ** common /* cube of shared variables */,
			DdNode ** onlyF /* cube of variables only in f */,
			DdNode ** onlyG /* cube of variables only in g */)
{
  DdNode *suppF, *suppG;

  suppF = suppG = *common = *onlyF = *onlyG = NULL;

  suppF = Cuddaux_Support(dd,f);
  if (suppF == NULL) goto Cuddaux_ClassifySupport_error;
  cuddRef(suppF);

  suppG = Cuddaux_Support(dd,g);
  if (suppG == NULL) goto Cuddaux_ClassifySupport_error;
  cuddRef(suppG);

  *common = Cudd_bddLiteralSetIntersection(dd,suppF,suppG);
  if (*common == NULL) goto Cuddaux_ClassifySupport_error;
  cuddRef(*common);

  *onlyF = Cudd_Cofactor(dd,suppF,*common);
  if (*onlyF == NULL) goto Cuddaux_ClassifySupport_error;
  cuddRef(*onlyF);

  *onlyG = Cudd_Cofactor(dd,suppG,*common);
  if (*onlyG == NULL) goto Cuddaux_ClassifySupport_error;
  cuddRef(*onlyG);
  Cudd_IterDerefBdd(dd,suppF);
  Cudd_IterDerefBdd(dd,suppG);
  cuddDeref(*common);
  cuddDeref(*onlyF);
  cuddDeref(*onlyG);
  return 1;
 Cuddaux_ClassifySupport_error:
  if (suppF) Cudd_IterDerefBdd(dd,suppF);
  if (suppG) Cudd_IterDerefBdd(dd,suppG);
  if (*common){
    Cudd_IterDerefBdd(dd,*common);
    *common = NULL;
  }
  if (*onlyF){
    Cudd_IterDerefBdd(dd,*onlyF);
    *onlyF = NULL;
  }
  if (*onlyG){
    Cudd_IterDerefBdd(dd,*onlyG);
    *onlyG = NULL;
  }
  dd->errorCode = CUDD_MEMORY_OUT;
  return(0);
} /* end of Cuddaux_ClassifySupport */
Esempio n. 7
0
/**Function********************************************************************

  Synopsis    [Clears the death row.]

  Description []

  SideEffects [None]

  SeeAlso     [Cudd_DelayedDerefBdd Cudd_IterDerefBdd Cudd_CheckZeroRef
  cuddGarbageCollect]

******************************************************************************/
void
cuddClearDeathRow(
  DdManager *table)
{
#ifndef DD_NO_DEATH_ROW
    int i;

    for (i = 0; i < table->deathRowDepth; i++) {
        if (table->deathRow[i] == NULL) break;
        Cudd_IterDerefBdd(table,table->deathRow[i]);
        table->deathRow[i] = NULL;
    }
#ifdef DD_DEBUG
    for (; i < table->deathRowDepth; i++) {
        assert(table->deathRow[i] == NULL);
    }
#endif
    table->nextDead = 0;
#endif

} /* end of cuddClearDeathRow */
Esempio n. 8
0
/**Function********************************************************************

  Synopsis    [Shrinks the death row.]

  Description [Shrinks the death row by a factor of four.]

  SideEffects [None]

  SeeAlso     [cuddClearDeathRow]

******************************************************************************/
void
cuddShrinkDeathRow(
  DdManager *table)
{
#ifndef DD_NO_DEATH_ROW
    int i;

    if (table->deathRowDepth > 3) {
        for (i = table->deathRowDepth/4; i < table->deathRowDepth; i++) {
            if (table->deathRow[i] == NULL) break;
            Cudd_IterDerefBdd(table,table->deathRow[i]);
            table->deathRow[i] = NULL;
        }
        table->deathRowDepth /= 4;
        table->deadMask = table->deathRowDepth - 1;
        if ((unsigned) table->nextDead > table->deadMask) {
            table->nextDead = 0;
        }
        table->deathRow = ABC_REALLOC(DdNodePtr, table->deathRow,
                                   table->deathRowDepth);
    }
#endif

} /* end of cuddShrinkDeathRow */
Esempio n. 9
0
/**Function********************************************************************

  Synopsis [Implements the recursive step of Cudd_bddAnd.]

  Description [Implements the recursive step of Cudd_bddAnd by taking
  the conjunction of two BDDs.  Returns a pointer to the result is
  successful; NULL otherwise.]

  SideEffects [None]

  SeeAlso     [Cudd_bddAnd]

******************************************************************************/
DdNode *
cuddBddAndRecur(
  DdManager * manager,
  DdNode * f,
  DdNode * g)
{
    DdNode *F, *fv, *fnv, *G, *gv, *gnv;
    DdNode *one, *r, *t, *e;
    unsigned int topf, topg, index;

    statLine(manager);
    one = DD_ONE(manager);

    /* Terminal cases. */
    F = Cudd_Regular(f);
    G = Cudd_Regular(g);
    if (F == G) {
        if (f == g) return(f);
        else return(Cudd_Not(one));
    }
    if (F == one) {
        if (f == one) return(g);
        else return(f);
    }
    if (G == one) {
        if (g == one) return(f);
        else return(g);
    }

    /* At this point f and g are not constant. */
    if (cuddF2L(f) > cuddF2L(g)) { /* Try to increase cache efficiency. */
        DdNode *tmp = f;
        f = g;
        g = tmp;
        F = Cudd_Regular(f);
        G = Cudd_Regular(g);
    }

    /* Check cache. */
    if (F->ref != 1 || G->ref != 1) {
        r = cuddCacheLookup2(manager, Cudd_bddAnd, f, g);
        if (r != NULL) return(r);
    }

    if ( manager->TimeStop && Abc_Clock() > manager->TimeStop )
        return NULL;

    /* Here we can skip the use of cuddI, because the operands are known
    ** to be non-constant.
    */
    topf = manager->perm[F->index];
    topg = manager->perm[G->index];

    /* Compute cofactors. */
    if (topf <= topg) {
        index = F->index;
        fv = cuddT(F);
        fnv = cuddE(F);
        if (Cudd_IsComplement(f)) {
            fv = Cudd_Not(fv);
            fnv = Cudd_Not(fnv);
        }
    } else {
        index = G->index;
        fv = fnv = f;
    }

    if (topg <= topf) {
        gv = cuddT(G);
        gnv = cuddE(G);
        if (Cudd_IsComplement(g)) {
            gv = Cudd_Not(gv);
            gnv = Cudd_Not(gnv);
        }
    } else {
        gv = gnv = g;
    }

    t = cuddBddAndRecur(manager, fv, gv);
    if (t == NULL) return(NULL);
    cuddRef(t);

    e = cuddBddAndRecur(manager, fnv, gnv);
    if (e == NULL) {
        Cudd_IterDerefBdd(manager, t);
        return(NULL);
    }
    cuddRef(e);

    if (t == e) {
        r = t;
    } else {
        if (Cudd_IsComplement(t)) {
            r = cuddUniqueInter(manager,(int)index,Cudd_Not(t),Cudd_Not(e));
            if (r == NULL) {
                Cudd_IterDerefBdd(manager, t);
                Cudd_IterDerefBdd(manager, e);
                return(NULL);
            }
            r = Cudd_Not(r);
        } else {
            r = cuddUniqueInter(manager,(int)index,t,e);
            if (r == NULL) {
                Cudd_IterDerefBdd(manager, t);
                Cudd_IterDerefBdd(manager, e);
                return(NULL);
            }
        }
    }
    cuddDeref(e);
    cuddDeref(t);
    if (F->ref != 1 || G->ref != 1)
        cuddCacheInsert2(manager, Cudd_bddAnd, f, g, r);
    return(r);

} /* end of cuddBddAndRecur */
Esempio n. 10
0
/**Function********************************************************************

  Synopsis    [Implements the recursive step of Cudd_bddIntersect.]

  Description []

  SideEffects [None]

  SeeAlso     [Cudd_bddIntersect]

******************************************************************************/
DdNode *
cuddBddIntersectRecur(
  DdManager * dd,
  DdNode * f,
  DdNode * g)
{
    DdNode *res;
    DdNode *F, *G, *t, *e;
    DdNode *fv, *fnv, *gv, *gnv;
    DdNode *one, *zero;
    unsigned int index, topf, topg;

    statLine(dd);
    one = DD_ONE(dd);
    zero = Cudd_Not(one);

    /* Terminal cases. */
    if (f == zero || g == zero || f == Cudd_Not(g)) return(zero);
    if (f == g || g == one) return(f);
    if (f == one) return(g);

    /* At this point f and g are not constant. */
    if (cuddF2L(f) > cuddF2L(g)) { DdNode *tmp = f; f = g; g = tmp; }
    res = cuddCacheLookup2(dd,Cudd_bddIntersect,f,g);
    if (res != NULL) return(res);

    /* Find splitting variable. Here we can skip the use of cuddI,
    ** because the operands are known to be non-constant.
    */
    F = Cudd_Regular(f);
    topf = dd->perm[F->index];
    G = Cudd_Regular(g);
    topg = dd->perm[G->index];

    /* Compute cofactors. */
    if (topf <= topg) {
        index = F->index;
        fv = cuddT(F);
        fnv = cuddE(F);
        if (Cudd_IsComplement(f)) {
            fv = Cudd_Not(fv);
            fnv = Cudd_Not(fnv);
        }
    } else {
        index = G->index;
        fv = fnv = f;
    }

    if (topg <= topf) {
        gv = cuddT(G);
        gnv = cuddE(G);
        if (Cudd_IsComplement(g)) {
            gv = Cudd_Not(gv);
            gnv = Cudd_Not(gnv);
        }
    } else {
        gv = gnv = g;
    }

    /* Compute partial results. */
    t = cuddBddIntersectRecur(dd,fv,gv);
    if (t == NULL) return(NULL);
    cuddRef(t);
    if (t != zero) {
        e = zero;
    } else {
        e = cuddBddIntersectRecur(dd,fnv,gnv);
        if (e == NULL) {
            Cudd_IterDerefBdd(dd, t);
            return(NULL);
        }
    }
    cuddRef(e);

    if (t == e) { /* both equal zero */
        res = t;
    } else if (Cudd_IsComplement(t)) {
        res = cuddUniqueInter(dd,(int)index,Cudd_Not(t),Cudd_Not(e));
        if (res == NULL) {
            Cudd_IterDerefBdd(dd, t);
            Cudd_IterDerefBdd(dd, e);
            return(NULL);
        }
        res = Cudd_Not(res);
    } else {
        res = cuddUniqueInter(dd,(int)index,t,e);
        if (res == NULL) {
            Cudd_IterDerefBdd(dd, t);
            Cudd_IterDerefBdd(dd, e);
            return(NULL);
        }
    }
    cuddDeref(e);
    cuddDeref(t);

    cuddCacheInsert2(dd,Cudd_bddIntersect,f,g,res);

    return(res);

} /* end of cuddBddIntersectRecur */
Esempio n. 11
0
/**Function********************************************************************

  Synopsis    [Implements the recursive step of Cudd_bddIte.]

  Description [Implements the recursive step of Cudd_bddIte. Returns a
  pointer to the resulting BDD. NULL if the intermediate result blows
  up or if reordering occurs.]

  SideEffects [None]

  SeeAlso     []

******************************************************************************/
DdNode *
cuddBddIteRecur(
  DdManager * dd,
  DdNode * f,
  DdNode * g,
  DdNode * h)
{
    DdNode       *one, *zero, *res;
    DdNode       *r, *Fv, *Fnv, *Gv, *Gnv, *H, *Hv, *Hnv, *t, *e;
    unsigned int topf, topg, toph, v;
    int          index = -1;
    int          comple;

    statLine(dd);
    /* Terminal cases. */

    /* One variable cases. */
    if (f == (one = DD_ONE(dd)))        /* ITE(1,G,H) = G */
        return(g);
    
    if (f == (zero = Cudd_Not(one)))    /* ITE(0,G,H) = H */
        return(h);
    
    /* From now on, f is known not to be a constant. */
    if (g == one || f == g) {   /* ITE(F,F,H) = ITE(F,1,H) = F + H */
        if (h == zero) {        /* ITE(F,1,0) = F */
            return(f);
        } else {
            res = cuddBddAndRecur(dd,Cudd_Not(f),Cudd_Not(h));
            return(Cudd_NotCond(res,res != NULL));
        }
    } else if (g == zero || f == Cudd_Not(g)) { /* ITE(F,!F,H) = ITE(F,0,H) = !F * H */
        if (h == one) {         /* ITE(F,0,1) = !F */
            return(Cudd_Not(f));
        } else {
            res = cuddBddAndRecur(dd,Cudd_Not(f),h);
            return(res);
        }
    }
    if (h == zero || f == h) {    /* ITE(F,G,F) = ITE(F,G,0) = F * G */
        res = cuddBddAndRecur(dd,f,g);
        return(res);
    } else if (h == one || f == Cudd_Not(h)) { /* ITE(F,G,!F) = ITE(F,G,1) = !F + G */
        res = cuddBddAndRecur(dd,f,Cudd_Not(g));
        return(Cudd_NotCond(res,res != NULL));
    }

    /* Check remaining one variable case. */
    if (g == h) {               /* ITE(F,G,G) = G */
        return(g);
    } else if (g == Cudd_Not(h)) { /* ITE(F,G,!G) = F <-> G */
        res = cuddBddXorRecur(dd,f,h);
        return(res);
    }
    
    /* From here, there are no constants. */
    comple = bddVarToCanonicalSimple(dd, &f, &g, &h, &topf, &topg, &toph);

    /* f & g are now regular pointers */

    v = ddMin(topg, toph);

    /* A shortcut: ITE(F,G,H) = (v,G,H) if F = (v,1,0), v < top(G,H). */
    if (topf < v && cuddT(f) == one && cuddE(f) == zero) {
        r = cuddUniqueInter(dd, (int) f->index, g, h);
        return(Cudd_NotCond(r,comple && r != NULL));
    }

    /* Check cache. */
    r = cuddCacheLookup(dd, DD_BDD_ITE_TAG, f, g, h);
    if (r != NULL) {
        return(Cudd_NotCond(r,comple));
    }

    /* Compute cofactors. */
    if (topf <= v) {
        v = ddMin(topf, v);     /* v = top_var(F,G,H) */
        index = f->index;
        Fv = cuddT(f); Fnv = cuddE(f);
    } else {
        Fv = Fnv = f;
    }
    if (topg == v) {
        index = g->index;
        Gv = cuddT(g); Gnv = cuddE(g);
    } else {
        Gv = Gnv = g;
    }
    if (toph == v) {
        H = Cudd_Regular(h);
        index = H->index;
        Hv = cuddT(H); Hnv = cuddE(H);
        if (Cudd_IsComplement(h)) {
            Hv = Cudd_Not(Hv);
            Hnv = Cudd_Not(Hnv);
        }
    } else {
        Hv = Hnv = h;
    }

    /* Recursive step. */
    t = cuddBddIteRecur(dd,Fv,Gv,Hv);
    if (t == NULL) return(NULL);
    cuddRef(t);

    e = cuddBddIteRecur(dd,Fnv,Gnv,Hnv);
    if (e == NULL) {
        Cudd_IterDerefBdd(dd,t);
        return(NULL);
    }
    cuddRef(e);

    r = (t == e) ? t : cuddUniqueInter(dd,index,t,e);
    if (r == NULL) {
        Cudd_IterDerefBdd(dd,t);
        Cudd_IterDerefBdd(dd,e);
        return(NULL);
    }
    cuddDeref(t);
    cuddDeref(e);

    cuddCacheInsert(dd, DD_BDD_ITE_TAG, f, g, h, r);
    return(Cudd_NotCond(r,comple));

} /* end of cuddBddIteRecur */
Esempio n. 12
0
/**Function********************************************************************

  Synopsis [Implements the recursive step of Cudd_bddXor.]

  Description [Implements the recursive step of Cudd_bddXor by taking
  the exclusive OR of two BDDs.  Returns a pointer to the result is
  successful; NULL otherwise.]

  SideEffects [None]

  SeeAlso     [Cudd_bddXor]

******************************************************************************/
DdNode *
cuddBddXorRecur(
  DdManager * manager,
  DdNode * f,
  DdNode * g)
{
    DdNode *fv, *fnv, *G, *gv, *gnv;
    DdNode *one, *zero, *r, *t, *e;
    unsigned int topf, topg, index;

    statLine(manager);
    one = DD_ONE(manager);
    zero = Cudd_Not(one);

    /* Terminal cases. */
    if (f == g) return(zero);
    if (f == Cudd_Not(g)) return(one);
    if (cuddF2L(f) > cuddF2L(g)) { /* Try to increase cache efficiency and simplify tests. */
        DdNode *tmp = f;
        f = g;
        g = tmp;
    }
    if (g == zero) return(f);
    if (g == one) return(Cudd_Not(f));
    if (Cudd_IsComplement(f)) {
        f = Cudd_Not(f);
        g = Cudd_Not(g);
    }
    /* Now the first argument is regular. */
    if (f == one) return(Cudd_Not(g));

    /* At this point f and g are not constant. */

    /* Check cache. */
    r = cuddCacheLookup2(manager, Cudd_bddXor, f, g);
    if (r != NULL) return(r);

    /* Here we can skip the use of cuddI, because the operands are known
    ** to be non-constant.
    */
    topf = manager->perm[f->index];
    G = Cudd_Regular(g);
    topg = manager->perm[G->index];

    /* Compute cofactors. */
    if (topf <= topg) {
        index = f->index;
        fv = cuddT(f);
        fnv = cuddE(f);
    } else {
        index = G->index;
        fv = fnv = f;
    }

    if (topg <= topf) {
        gv = cuddT(G);
        gnv = cuddE(G);
        if (Cudd_IsComplement(g)) {
            gv = Cudd_Not(gv);
            gnv = Cudd_Not(gnv);
        }
    } else {
        gv = gnv = g;
    }

    t = cuddBddXorRecur(manager, fv, gv);
    if (t == NULL) return(NULL);
    cuddRef(t);

    e = cuddBddXorRecur(manager, fnv, gnv);
    if (e == NULL) {
        Cudd_IterDerefBdd(manager, t);
        return(NULL);
    }
    cuddRef(e);

    if (t == e) {
        r = t;
    } else {
        if (Cudd_IsComplement(t)) {
            r = cuddUniqueInter(manager,(int)index,Cudd_Not(t),Cudd_Not(e));
            if (r == NULL) {
                Cudd_IterDerefBdd(manager, t);
                Cudd_IterDerefBdd(manager, e);
                return(NULL);
            }
            r = Cudd_Not(r);
        } else {
            r = cuddUniqueInter(manager,(int)index,t,e);
            if (r == NULL) {
                Cudd_IterDerefBdd(manager, t);
                Cudd_IterDerefBdd(manager, e);
                return(NULL);
            }
        }
    }
    cuddDeref(e);
    cuddDeref(t);
    cuddCacheInsert2(manager, Cudd_bddXor, f, g, r);
    return(r);

} /* end of cuddBddXorRecur */
Esempio n. 13
0
/**Function********************************************************************

  Synopsis    [Performs the recursive step of Cudd_bddVectorCompose.]

  Description []

  SideEffects [None]

  SeeAlso     []

******************************************************************************/
static DdNode *
cuddBddVectorComposeRecur(
  DdManager * dd /* DD manager */,
  DdHashTable * table /* computed table */,
  DdNode * f /* BDD in which to compose */,
  DdNode ** vector /* functions to be composed */,
  int deepest /* depth of the deepest substitution */)
{
    DdNode	*F,*T,*E;
    DdNode	*res;

    statLine(dd);
    F = Cudd_Regular(f);

    /* If we are past the deepest substitution, return f. */
    if (cuddI(dd,F->index) > deepest) {
	return(f);
    }

    /* If problem already solved, look up answer and return. */
    if ((res = cuddHashTableLookup1(table,F)) != NULL) {
#ifdef DD_DEBUG
	bddVectorComposeHits++;
#endif
	return(Cudd_NotCond(res,F != f));
    }

    /* Split and recur on children of this node. */
    T = cuddBddVectorComposeRecur(dd,table,cuddT(F),vector, deepest);
    if (T == NULL) return(NULL);
    cuddRef(T);
    E = cuddBddVectorComposeRecur(dd,table,cuddE(F),vector, deepest);
    if (E == NULL) {
	Cudd_IterDerefBdd(dd, T);
	return(NULL);
    }
    cuddRef(E);

    /* Call cuddBddIteRecur with the BDD that replaces the current top
    ** variable and the T and E we just created.
    */
    res = cuddBddIteRecur(dd,vector[F->index],T,E);
    if (res == NULL) {
	Cudd_IterDerefBdd(dd, T);
	Cudd_IterDerefBdd(dd, E);
	return(NULL);
    }
    cuddRef(res);
    Cudd_IterDerefBdd(dd, T);
    Cudd_IterDerefBdd(dd, E);	

    /* Do not keep the result if the reference count is only 1, since
    ** it will not be visited again.
    */
    if (F->ref != 1) {
	ptrint fanout = (ptrint) F->ref;
	cuddSatDec(fanout);
	if (!cuddHashTableInsert1(table,F,res,fanout)) {
	    Cudd_IterDerefBdd(dd, res);
	    return(NULL);
	}
    }
    cuddDeref(res);
    return(Cudd_NotCond(res,F != f));

} /* end of cuddBddVectorComposeRecur */
Esempio n. 14
0
/**Function********************************************************************

  Synopsis    [Implements the recursive step of Cudd_bddPermute.]

  Description [ Recursively puts the BDD in the order given in the array permut.
  Checks for trivial cases to terminate recursion, then splits on the
  children of this node.  Once the solutions for the children are
  obtained, it puts into the current position the node from the rest of
  the BDD that should be here. Then returns this BDD.
  The key here is that the node being visited is NOT put in its proper
  place by this instance, but rather is switched when its proper position
  is reached in the recursion tree.<p>
  The DdNode * that is returned is the same BDD as passed in as node,
  but in the new order.]

  SideEffects [None]

  SeeAlso     [Cudd_bddPermute cuddAddPermuteRecur]

******************************************************************************/
static DdNode *
cuddBddPermuteRecur(
  DdManager * manager /* DD manager */,
  DdHashTable * table /* computed table */,
  DdNode * node /* BDD to be reordered */,
  int * permut /* permutation array */)
{
    DdNode	*N,*T,*E;
    DdNode	*res;
    int		index;

    statLine(manager);
    N = Cudd_Regular(node);

    /* Check for terminal case of constant node. */
    if (cuddIsConstant(N)) {
	return(node);
    }

    /* If problem already solved, look up answer and return. */
    if (N->ref != 1 && (res = cuddHashTableLookup1(table,N)) != NULL) {
#ifdef DD_DEBUG
	bddPermuteRecurHits++;
#endif
	return(Cudd_NotCond(res,N != node));
    }

    /* Split and recur on children of this node. */
    T = cuddBddPermuteRecur(manager,table,cuddT(N),permut);
    if (T == NULL) return(NULL);
    cuddRef(T);
    E = cuddBddPermuteRecur(manager,table,cuddE(N),permut);
    if (E == NULL) {
	Cudd_IterDerefBdd(manager, T);
	return(NULL);
    }
    cuddRef(E);

    /* Move variable that should be in this position to this position
    ** by retrieving the single var BDD for that variable, and calling
    ** cuddBddIteRecur with the T and E we just created.
    */
    index = permut[N->index];
    res = cuddBddIteRecur(manager,manager->vars[index],T,E);
    if (res == NULL) {
	Cudd_IterDerefBdd(manager, T);
	Cudd_IterDerefBdd(manager, E);
	return(NULL);
    }
    cuddRef(res);
    Cudd_IterDerefBdd(manager, T);
    Cudd_IterDerefBdd(manager, E);

    /* Do not keep the result if the reference count is only 1, since
    ** it will not be visited again.
    */
    if (N->ref != 1) {
	ptrint fanout = (ptrint) N->ref;
	cuddSatDec(fanout);
	if (!cuddHashTableInsert1(table,N,res,fanout)) {
	    Cudd_IterDerefBdd(manager, res);
	    return(NULL);
	}
    }
    cuddDeref(res);
    return(Cudd_NotCond(res,N != node));

} /* end of cuddBddPermuteRecur */
Esempio n. 15
0
/**Function********************************************************************

  Synopsis    [Performs the recursive steps of Cudd_bddExistAbstract.]

  Description [Performs the recursive steps of Cudd_bddExistAbstract.
  Returns the BDD obtained by abstracting the variables
  of cube from f if successful; NULL otherwise. It is also used by
  Cudd_bddUnivAbstract.]

  SideEffects [None]

  SeeAlso     [Cudd_bddExistAbstract Cudd_bddUnivAbstract]

******************************************************************************/
DdNode *
cuddBddExistAbstractRecur(
  DdManager * manager,
  DdNode * f,
  DdNode * cube)
{
    DdNode	*F, *T, *E, *res, *res1, *res2, *one;

    statLine(manager);
    one = DD_ONE(manager);
    F = Cudd_Regular(f);

    /* Cube is guaranteed to be a cube at this point. */	
    if (cube == one || F == one) {  
        return(f);
    }
    /* From now on, f and cube are non-constant. */

    /* Abstract a variable that does not appear in f. */
    while (manager->perm[F->index] > manager->perm[cube->index]) {
	cube = cuddT(cube);
	if (cube == one) return(f);
    }

    /* Check the cache. */
    if (F->ref != 1 && (res = cuddCacheLookup2(manager, Cudd_bddExistAbstract, f, cube)) != NULL) {
	return(res);
    }

    /* Compute the cofactors of f. */
    T = cuddT(F); E = cuddE(F);
    if (f != F) {
	T = Cudd_Not(T); E = Cudd_Not(E);
    }

    /* If the two indices are the same, so are their levels. */
    if (F->index == cube->index) {
	if (T == one || E == one || T == Cudd_Not(E)) {
	    return(one);
	}
	res1 = cuddBddExistAbstractRecur(manager, T, cuddT(cube));
	if (res1 == NULL) return(NULL);
	if (res1 == one) {
	    if (F->ref != 1)
		cuddCacheInsert2(manager, Cudd_bddExistAbstract, f, cube, one);
	    return(one);
	}
        cuddRef(res1);
	res2 = cuddBddExistAbstractRecur(manager, E, cuddT(cube));
	if (res2 == NULL) {
	    Cudd_IterDerefBdd(manager,res1);
	    return(NULL);
	}
        cuddRef(res2);
	res = cuddBddAndRecur(manager, Cudd_Not(res1), Cudd_Not(res2));
	if (res == NULL) {
	    Cudd_IterDerefBdd(manager, res1);
	    Cudd_IterDerefBdd(manager, res2);
	    return(NULL);
	}
	res = Cudd_Not(res);
	cuddRef(res);
	Cudd_IterDerefBdd(manager, res1);
	Cudd_IterDerefBdd(manager, res2);
	if (F->ref != 1)
	    cuddCacheInsert2(manager, Cudd_bddExistAbstract, f, cube, res);
	cuddDeref(res);
        return(res);
    } else { /* if (cuddI(manager,F->index) < cuddI(manager,cube->index)) */
	res1 = cuddBddExistAbstractRecur(manager, T, cube);
	if (res1 == NULL) return(NULL);
        cuddRef(res1);
	res2 = cuddBddExistAbstractRecur(manager, E, cube);
	if (res2 == NULL) {
	    Cudd_IterDerefBdd(manager, res1);
	    return(NULL);
	}
        cuddRef(res2);
	/* ITE takes care of possible complementation of res1 and of the
        ** case in which res1 == res2. */
	res = cuddBddIteRecur(manager, manager->vars[F->index], res1, res2);
	if (res == NULL) {
	    Cudd_IterDerefBdd(manager, res1);
	    Cudd_IterDerefBdd(manager, res2);
	    return(NULL);
	}
	cuddDeref(res1);
	cuddDeref(res2);
	if (F->ref != 1)
	    cuddCacheInsert2(manager, Cudd_bddExistAbstract, f, cube, res);
        return(res);
    }	    

} /* end of cuddBddExistAbstractRecur */
Esempio n. 16
0
/**Function********************************************************************

  Synopsis [Takes the exclusive OR of two BDDs and simultaneously abstracts the
  variables in cube.]

  Description [Takes the exclusive OR of two BDDs and simultaneously abstracts
  the variables in cube. The variables are existentially abstracted.  Returns a
  pointer to the result is successful; NULL otherwise.]

  SideEffects [None]

  SeeAlso     [Cudd_bddAndAbstract]

******************************************************************************/
DdNode *
cuddBddXorExistAbstractRecur(
  DdManager * manager,
  DdNode * f,
  DdNode * g,
  DdNode * cube)
{
    DdNode *F, *fv, *fnv, *G, *gv, *gnv;
    DdNode *one, *zero, *r, *t, *e, *Cube;
    unsigned int topf, topg, topcube, top, index;

    statLine(manager);
    one = DD_ONE(manager);
    zero = Cudd_Not(one);

    /* Terminal cases. */
    if (f == g) {
	return(zero);
    }
    if (f == Cudd_Not(g)) {
	return(one);
    }
    if (cube == one) {
	return(cuddBddXorRecur(manager, f, g));
    }
    if (f == one) {
	return(cuddBddExistAbstractRecur(manager, Cudd_Not(g), cube));
    }
    if (g == one) {
	return(cuddBddExistAbstractRecur(manager, Cudd_Not(f), cube));
    }
    if (f == zero) {
	return(cuddBddExistAbstractRecur(manager, g, cube));
    }
    if (g == zero) {
	return(cuddBddExistAbstractRecur(manager, f, cube));
    }

    /* At this point f, g, and cube are not constant. */

    if (f > g) { /* Try to increase cache efficiency. */
	DdNode *tmp = f;
	f = g;
	g = tmp;
    }

    /* Check cache. */
    r = cuddCacheLookup(manager, DD_BDD_XOR_EXIST_ABSTRACT_TAG, f, g, cube);
    if (r != NULL) {
	return(r);
    }

    /* Here we can skip the use of cuddI, because the operands are known
    ** to be non-constant.
    */
    F = Cudd_Regular(f);
    topf = manager->perm[F->index];
    G = Cudd_Regular(g);
    topg = manager->perm[G->index];
    top = ddMin(topf, topg);
    topcube = manager->perm[cube->index];

    if (topcube < top) {
	return(cuddBddXorExistAbstractRecur(manager, f, g, cuddT(cube)));
    }
    /* Now, topcube >= top. */

    if (topf == top) {
	index = F->index;
	fv = cuddT(F);
	fnv = cuddE(F);
	if (Cudd_IsComplement(f)) {
	    fv = Cudd_Not(fv);
	    fnv = Cudd_Not(fnv);
	}
    } else {
	index = G->index;
	fv = fnv = f;
    }

    if (topg == top) {
	gv = cuddT(G);
	gnv = cuddE(G);
	if (Cudd_IsComplement(g)) {
	    gv = Cudd_Not(gv);
	    gnv = Cudd_Not(gnv);
	}
    } else {
	gv = gnv = g;
    }

    if (topcube == top) {
	Cube = cuddT(cube);
    } else {
	Cube = cube;
    }

    t = cuddBddXorExistAbstractRecur(manager, fv, gv, Cube);
    if (t == NULL) return(NULL);

    /* Special case: 1 OR anything = 1. Hence, no need to compute
    ** the else branch if t is 1.
    */
    if (t == one && topcube == top) {
	cuddCacheInsert(manager, DD_BDD_XOR_EXIST_ABSTRACT_TAG, f, g, cube, one);
	return(one);
    }
    cuddRef(t);

    e = cuddBddXorExistAbstractRecur(manager, fnv, gnv, Cube);
    if (e == NULL) {
	Cudd_IterDerefBdd(manager, t);
	return(NULL);
    }
    cuddRef(e);

    if (topcube == top) {	/* abstract */
	r = cuddBddAndRecur(manager, Cudd_Not(t), Cudd_Not(e));
	if (r == NULL) {
	    Cudd_IterDerefBdd(manager, t);
	    Cudd_IterDerefBdd(manager, e);
	    return(NULL);
	}
	r = Cudd_Not(r);
	cuddRef(r);
	Cudd_IterDerefBdd(manager, t);
	Cudd_IterDerefBdd(manager, e);
	cuddDeref(r);
    } else if (t == e) {
	r = t;
	cuddDeref(t);
	cuddDeref(e);
    } else {
	if (Cudd_IsComplement(t)) {
	    r = cuddUniqueInter(manager,(int)index,Cudd_Not(t),Cudd_Not(e));
	    if (r == NULL) {
		Cudd_IterDerefBdd(manager, t);
		Cudd_IterDerefBdd(manager, e);
		return(NULL);
	    }
	    r = Cudd_Not(r);
	} else {
	    r = cuddUniqueInter(manager,(int)index,t,e);
	    if (r == NULL) {
		Cudd_IterDerefBdd(manager, t);
		Cudd_IterDerefBdd(manager, e);
		return(NULL);
	    }
	}
	cuddDeref(e);
	cuddDeref(t);
    }
    cuddCacheInsert(manager, DD_BDD_XOR_EXIST_ABSTRACT_TAG, f, g, cube, r);
    return (r);

} /* end of cuddBddXorExistAbstractRecur */
Esempio n. 17
0
/**Function********************************************************************

  Synopsis    [Performs the recursive step of Cudd_bddCompose.]

  Description [Performs the recursive step of Cudd_bddCompose.
  Exploits the fact that the composition of f' with g
  produces the complement of the composition of f with g to better
  utilize the cache.  Returns the composed BDD if successful; NULL
  otherwise.]

  SideEffects [None]

  SeeAlso     [Cudd_bddCompose]

******************************************************************************/
DdNode *
cuddBddComposeRecur(
  DdManager * dd,
  DdNode * f,
  DdNode * g,
  DdNode * proj)
{
    DdNode	*F, *G, *f1, *f0, *g1, *g0, *r, *t, *e;
    unsigned int v, topf, topg, topindex;
    int		comple;

    statLine(dd);
    v = dd->perm[proj->index];
    F = Cudd_Regular(f);
    topf = cuddI(dd,F->index);

    /* Terminal case. Subsumes the test for constant f. */
    if (topf > v) return(f);

    /* We solve the problem for a regular pointer, and then complement
    ** the result if the pointer was originally complemented.
    */
    comple = Cudd_IsComplement(f);

    /* Check cache. */
    r = cuddCacheLookup(dd,DD_BDD_COMPOSE_RECUR_TAG,F,g,proj);
    if (r != NULL) {
	return(Cudd_NotCond(r,comple));
    }

    if (topf == v) {
	/* Compose. */
	f1 = cuddT(F);
	f0 = cuddE(F);
	r = cuddBddIteRecur(dd, g, f1, f0);
	if (r == NULL) return(NULL);
    } else {
	/* Compute cofactors of f and g. Remember the index of the top
	** variable.
	*/
	G = Cudd_Regular(g);
	topg = cuddI(dd,G->index);
	if (topf > topg) {
	    topindex = G->index;
	    f1 = f0 = F;
	} else {
	    topindex = F->index;
	    f1 = cuddT(F);
	    f0 = cuddE(F);
	}
	if (topg > topf) {
	    g1 = g0 = g;
	} else {
	    g1 = cuddT(G);
	    g0 = cuddE(G);
	    if (g != G) {
		g1 = Cudd_Not(g1);
		g0 = Cudd_Not(g0);
	    }
	}
	/* Recursive step. */
	t = cuddBddComposeRecur(dd, f1, g1, proj);
	if (t == NULL) return(NULL);
	cuddRef(t);
	e = cuddBddComposeRecur(dd, f0, g0, proj);
	if (e == NULL) {
	    Cudd_IterDerefBdd(dd, t);
	    return(NULL);
	}
	cuddRef(e);

	r = cuddBddIteRecur(dd, dd->vars[topindex], t, e);
	if (r == NULL) {
	    Cudd_IterDerefBdd(dd, t);
	    Cudd_IterDerefBdd(dd, e);
	    return(NULL);
	}
	cuddRef(r);
	Cudd_IterDerefBdd(dd, t); /* t & e not necessarily part of r */
	Cudd_IterDerefBdd(dd, e);
	cuddDeref(r);
    }

    cuddCacheInsert(dd,DD_BDD_COMPOSE_RECUR_TAG,F,g,proj,r);

    return(Cudd_NotCond(r,comple));

} /* end of cuddBddComposeRecur */
Esempio n. 18
0
/**Function********************************************************************

  Synopsis [Takes the AND of two BDDs and simultaneously abstracts the
  variables in cube.]

  Description [Takes the AND of two BDDs and simultaneously abstracts
  the variables in cube. The variables are existentially abstracted.
  Returns a pointer to the result is successful; NULL otherwise.]

  SideEffects [None]

  SeeAlso     [Cudd_bddAndAbstract]

******************************************************************************/
DdNode *
cuddBddAndAbstractRecur(
  DdManager * manager,
  DdNode * f,
  DdNode * g,
  DdNode * cube)
{
    DdNode *F, *ft, *fe, *G, *gt, *ge;
    DdNode *one, *zero, *r, *t, *e;
    unsigned int topf, topg, topcube, top, index;

    statLine(manager);
    one = DD_ONE(manager);
    zero = Cudd_Not(one);

    /* Terminal cases. */
    if (f == zero || g == zero || f == Cudd_Not(g)) return(zero);
    if (f == one && g == one)   return(one);

    if (cube == one) {
        return(cuddBddAndRecur(manager, f, g));
    }
    if (f == one || f == g) {
        return(cuddBddExistAbstractRecur(manager, g, cube));
    }
    if (g == one) {
        return(cuddBddExistAbstractRecur(manager, f, cube));
    }
    /* At this point f, g, and cube are not constant. */

    if (f > g) { /* Try to increase cache efficiency. */
        DdNode *tmp = f;
        f = g;
        g = tmp;
    }

    /* Here we can skip the use of cuddI, because the operands are known
    ** to be non-constant.
    */
    F = Cudd_Regular(f);
    G = Cudd_Regular(g);
    topf = manager->perm[F->index];
    topg = manager->perm[G->index];
    top = ddMin(topf, topg);
    topcube = manager->perm[cube->index];

    while (topcube < top) {
        cube = cuddT(cube);
        if (cube == one) {
            return(cuddBddAndRecur(manager, f, g));
        }
        topcube = manager->perm[cube->index];
    }
    /* Now, topcube >= top. */

    /* Check cache. */
    if (F->ref != 1 || G->ref != 1) {
        r = cuddCacheLookup(manager, DD_BDD_AND_ABSTRACT_TAG, f, g, cube);
        if (r != NULL) {
            return(r);
        }
    }

    if ( manager->TimeStop && manager->TimeStop < clock() )
        return NULL;

    if (topf == top) {
        index = F->index;
        ft = cuddT(F);
        fe = cuddE(F);
        if (Cudd_IsComplement(f)) {
            ft = Cudd_Not(ft);
            fe = Cudd_Not(fe);
        }
    } else {
        index = G->index;
        ft = fe = f;
    }

    if (topg == top) {
        gt = cuddT(G);
        ge = cuddE(G);
        if (Cudd_IsComplement(g)) {
            gt = Cudd_Not(gt);
            ge = Cudd_Not(ge);
        }
    } else {
        gt = ge = g;
    }

    if (topcube == top) {       /* quantify */
        DdNode *Cube = cuddT(cube);
        t = cuddBddAndAbstractRecur(manager, ft, gt, Cube);
        if (t == NULL) return(NULL);
        /* Special case: 1 OR anything = 1. Hence, no need to compute
        ** the else branch if t is 1. Likewise t + t * anything == t.
        ** Notice that t == fe implies that fe does not depend on the
        ** variables in Cube. Likewise for t == ge.
        */
        if (t == one || t == fe || t == ge) {
            if (F->ref != 1 || G->ref != 1)
                cuddCacheInsert(manager, DD_BDD_AND_ABSTRACT_TAG,
                                f, g, cube, t);
            return(t);
        }
        cuddRef(t);
        /* Special case: t + !t * anything == t + anything. */
        if (t == Cudd_Not(fe)) {
            e = cuddBddExistAbstractRecur(manager, ge, Cube);
        } else if (t == Cudd_Not(ge)) {
            e = cuddBddExistAbstractRecur(manager, fe, Cube);
        } else {
            e = cuddBddAndAbstractRecur(manager, fe, ge, Cube);
        }
        if (e == NULL) {
            Cudd_IterDerefBdd(manager, t);
            return(NULL);
        }
        if (t == e) {
            r = t;
            cuddDeref(t);
        } else {
            cuddRef(e);
            r = cuddBddAndRecur(manager, Cudd_Not(t), Cudd_Not(e));
            if (r == NULL) {
                Cudd_IterDerefBdd(manager, t);
                Cudd_IterDerefBdd(manager, e);
                return(NULL);
            }
            r = Cudd_Not(r);
            cuddRef(r);
            Cudd_DelayedDerefBdd(manager, t);
            Cudd_DelayedDerefBdd(manager, e);
            cuddDeref(r);
        }
    } else {
        t = cuddBddAndAbstractRecur(manager, ft, gt, cube);
        if (t == NULL) return(NULL);
        cuddRef(t);
        e = cuddBddAndAbstractRecur(manager, fe, ge, cube);
        if (e == NULL) {
            Cudd_IterDerefBdd(manager, t);
            return(NULL);
        }
        if (t == e) {
            r = t;
            cuddDeref(t);
        } else {
            cuddRef(e);
            if (Cudd_IsComplement(t)) {
                r = cuddUniqueInter(manager, (int) index,
                                    Cudd_Not(t), Cudd_Not(e));
                if (r == NULL) {
                    Cudd_IterDerefBdd(manager, t);
                    Cudd_IterDerefBdd(manager, e);
                    return(NULL);
                }
                r = Cudd_Not(r);
            } else {
                r = cuddUniqueInter(manager,(int)index,t,e);
                if (r == NULL) {
                    Cudd_IterDerefBdd(manager, t);
                    Cudd_IterDerefBdd(manager, e);
                    return(NULL);
                }
            }
            cuddDeref(e);
            cuddDeref(t);
        }
    }

    if (F->ref != 1 || G->ref != 1)
        cuddCacheInsert(manager, DD_BDD_AND_ABSTRACT_TAG, f, g, cube, r);
    return (r);

} /* end of cuddBddAndAbstractRecur */
Esempio n. 19
0
/**Function********************************************************************

  Synopsis    [Performs the recursive step of Cuddaux_addRestrict.]

  Description [Performs the recursive step of Cuddaux_addRestrict.
  Returns the restricted ADD if successful; otherwise NULL.]

  SideEffects [None]

  SeeAlso     [Cudd_addRestrict]

******************************************************************************/
DdNode *
cuddauxAddRestrictRecur(
  DdManager * dd,
  DdNode * f,
  DdNode * c)
{
  DdNode	 *Fv, *Fnv, *Cv, *Cnv, *t, *e, *res, *one, *zero;
  unsigned int topf, topc;
  int		 index;

  one = DD_ONE(dd);
  zero = Cudd_Not(one);

  /* Trivial cases */
  if (c == one)		return(f);
  if (c == zero){
    fprintf(stderr,"CuddauxAddRestrictRecur: warning: false careset\n");
    return(DD_BACKGROUND(dd));
  }
  if (Cudd_IsConstant(f)) return(f);

  /* Now f and c are non-constant. */

  /* Check the cache. */
  res = cuddCacheLookup2(dd, Cuddaux_addRestrict, f, c);
  if (res != NULL) {
    return(res);
  }

  topf = dd->perm[f->index];
  topc = dd->perm[Cudd_Regular(c)->index];

  if (topc < topf) {	/* abstract top variable from c */
    DdNode *d, *s1, *s2;

    /* Take the OR by applying DeMorgan. */
    /* Find complements of cofactors of c. */
    if (Cudd_IsComplement(c)) {
      s1 = cuddT(Cudd_Regular(c));
      s2 = cuddE(Cudd_Regular(c));
    } else {
      s1 = Cudd_Not(cuddT(c));
      s2 = Cudd_Not(cuddE(c));
    }
    /* Take the AND and negate */
    d = cuddBddAndRecur(dd, s1, s2);
    if (d == NULL) return(NULL);
    d = Cudd_Not(d);
    cuddRef(d);

    res = cuddauxAddRestrictRecur(dd, f, d);
    if (res == NULL) {
      Cudd_IterDerefBdd(dd, d);
      return(NULL);
    }
    cuddRef(res);
    Cudd_IterDerefBdd(dd, d);
    cuddDeref(res);
    cuddCacheInsert2(dd, Cuddaux_addRestrict, f, c, res);
    return(res);
  }

  /* Recursive step. Here topf <= topc. */
  index = f->index;
  Fv = cuddT(f); Fnv = cuddE(f);
  if (topc == topf) {
    Cv = Cudd_T(c); Cnv = Cudd_E(c);
    if (Cudd_IsComplement(c)) {
      Cv = Cudd_Not(Cv); Cnv = Cudd_Not(Cnv);
    }
  } else {
    Cv = Cnv = c;
  }

  if (!Cudd_IsConstant(Cv)) {
    t = cuddauxAddRestrictRecur(dd, Fv, Cv);
    if (t == NULL) return(NULL);
  } 
  else if (Cv == one) {
    t = Fv;
  } 
  else {		/* Cv == zero: return(Fnv @ Cnv) */
    if (Cnv == one) {
      res = Fnv;
    } 
    else {
      res = cuddauxAddRestrictRecur(dd, Fnv, Cnv);
      if (res == NULL) return(NULL);
    }
    return(res);
  }
  cuddRef(t);

  if (!Cudd_IsConstant(Cnv)) {
    e = cuddauxAddRestrictRecur(dd, Fnv, Cnv);
    if (e == NULL) {
      Cudd_RecursiveDeref(dd, t);
      return(NULL);
    }
  } else if (Cnv == one) {
    e = Fnv;
  } else {		/* Cnv == zero: return (Fv @ Cv) previously computed */
    cuddDeref(t);
    return(t);
  }
  cuddRef(e);

  res = (t == e) ? t : cuddUniqueInter(dd, index, t, e);
  if (res == NULL) {
    Cudd_RecursiveDeref(dd, e);
    Cudd_RecursiveDeref(dd, t);
    return(NULL);
  }
  cuddDeref(t);
  cuddDeref(e);

  cuddCacheInsert2(dd, Cuddaux_addRestrict, f, c, res);
  return(res);

} /* end of cuddauxAddRestrictRecur */
Esempio n. 20
0
/**Function********************************************************************

  Synopsis [BDD restrict according to Coudert and Madre's algorithm
  (ICCAD90).]

  Description [BDD restrict according to Coudert and Madre's algorithm
  (ICCAD90). Returns the restricted BDD if successful; otherwise NULL.]

  SideEffects [None]

  SeeAlso     [Cudd_bddRestrict]

******************************************************************************/
DdNode*
Cuddaux_bddRestrict(DdManager * dd, DdNode * f, DdNode * c)
{
  DdNode *one,*zero;
  DdNode *suppF, *suppC, *commonSupp, *onlyC;
  DdNode *cplus, *res;
  int retval;
  
  one = DD_ONE(dd);
  zero = Cudd_Not(one);
  /* Check terminal cases here to avoid computing supports in trivial cases.
  ** This also allows us notto check later for the case c == 0, in which
  ** there is no common support. */
  if (c == one) return(f);
  if (c == zero){
    fprintf(stderr,"Cuddaux_bddRestrict: warning: false careset\n");
    return(zero);
  }
  if (Cudd_IsConstant(f)) return(f);
  if (f == c) return(one);
  if (f == Cudd_Not(c)) return(zero);
  
  /* Check if supports intersect. */
  suppF = Cuddaux_Support(dd,f);
  if (suppF==NULL) return(NULL);
  cuddRef(suppF);

  suppC = Cuddaux_Support(dd,c);
  if (suppC==NULL){
    Cudd_IterDerefBdd(dd,suppF);
    return(NULL);
  }
  cuddRef(suppC);

  commonSupp = Cudd_bddLiteralSetIntersection(dd,suppF,suppC);
  if (commonSupp==NULL){
    Cudd_IterDerefBdd(dd,suppF);
    Cudd_IterDerefBdd(dd,suppC); 
    return(NULL);
  }
  if (commonSupp == one) {
    Cudd_IterDerefBdd(dd,suppF);
    Cudd_IterDerefBdd(dd,suppC); 
    return(f);
  }
  cuddRef(commonSupp);

  Cudd_IterDerefBdd(dd,suppF);
  /* Abstract from c the variables that do not appear in f. */
  onlyC = Cudd_Cofactor(dd,suppC,commonSupp);
  if (onlyC == NULL) {
    Cudd_IterDerefBdd(dd,suppC); 
    Cudd_IterDerefBdd(dd,commonSupp); 
    return(NULL);
  }
  cuddRef(onlyC);
  Cudd_IterDerefBdd(dd,suppC); 
  Cudd_IterDerefBdd(dd,commonSupp); 
  cplus = Cudd_bddExistAbstract(dd, c, onlyC);
  if (cplus == NULL) {
    Cudd_IterDerefBdd(dd,onlyC); 
    return(NULL);
  }
  cuddRef(cplus);
  Cudd_IterDerefBdd(dd,onlyC);
  
  do {
    dd->reordered = 0;
    res = cuddBddRestrictRecur(dd, f, cplus);
  } while (dd->reordered == 1);
  if (res == NULL) {
    Cudd_IterDerefBdd(dd,cplus);
    return(NULL);
  }
  cuddRef(res);
  Cudd_IterDerefBdd(dd,cplus);
  cuddDeref(res);
  return(res);
} /* end of Cuddaux_bddRestrict */
Esempio n. 21
0
/**Function********************************************************************

  Synopsis    [Main program for ntr.]

  Description [Main program for ntr. Performs initialization. Reads command
  line options and network(s). Builds BDDs with reordering, and optionally
  does reachability analysis. Prints stats.]

  SideEffects [None]

  SeeAlso     []

******************************************************************************/
int
main(
  int  argc,
  char ** argv)
{
    NtrOptions	*option;	/* options */
    FILE	*fp1;		/* first network file pointer */
    BnetNetwork	*net1 = NULL;	/* first network */
    FILE	*fp2;		/* second network file pointer */
    BnetNetwork	*net2 = NULL;	/* second network */
    DdManager	*dd;		/* pointer to DD manager */
    int		exitval;	/* return value of Cudd_CheckZeroRef */
    int		ok;		/* overall return value from main() */
    int		result;		/* stores the return value of functions */
    BnetNode	*node;		/* auxiliary pointer to network node */
    int		i;		/* loop index */
    int		j;		/* loop index */
    double	*signatures;	/* array of signatures */
    int		pr;		/* verbosity level */
    int		reencoded;	/* linear transformations attempted */

    /* Initialize. */
    option = mainInit();
    ntrReadOptions(argc,argv,option);
    pr = option->verb;
    reencoded = option->reordering == CUDD_REORDER_LINEAR ||
		option->reordering == CUDD_REORDER_LINEAR_CONVERGE ||
		option->autoMethod == CUDD_REORDER_LINEAR ||
		option->autoMethod == CUDD_REORDER_LINEAR_CONVERGE;
    /* Currently traversal requires global BDDs. Override whatever
    ** was specified for locGlob.
    */
    if (option->traverse == TRUE || option->envelope == TRUE ||
	option->scc == TRUE) {
	option->locGlob = BNET_GLOBAL_DD;
    }

    /* Read the first network... */
    fp1 = open_file(option->file1, "r");
    net1 = Bnet_ReadNetwork(fp1,pr);
    (void) fclose(fp1);
    if (net1 == NULL) {
	(void) fprintf(stderr,"Syntax error in %s.\n",option->file1);
	exit(2);
    }
    /* ... and optionally echo it to the standard output. */
    if (pr > 2) {
	Bnet_PrintNetwork(net1);
    }

    /* Read the second network... */
    if (option->verify == TRUE || option->second == TRUE ||
	option->clip > 0.0 || option->dontcares) {
	fp2 = open_file(option->file2, "r");
	net2 = Bnet_ReadNetwork(fp2,pr);
	(void) fclose(fp2);
	if (net2 == NULL) {
	    (void) fprintf(stderr,"Syntax error in %s.\n",option->file2);
	    exit(2);
	}
	/* ... and optionally echo it to the standard output. */
	if (pr > 2) {
	    Bnet_PrintNetwork(net2);
	}
    }

    /* Initialize manager. We start with 0 variables, because
    ** Ntr_buildDDs will create new variables rather than using
    ** whatever already exists.
    */
    dd = startCudd(option,net1->ninputs);
    if (dd == NULL) { exit(2); }

    /* Build the BDDs for the nodes of the first network. */
    result = Ntr_buildDDs(net1,dd,option,NULL);
    if (result == 0) { exit(2); }

    /* Build the BDDs for the nodes of the second network if requested. */
    if (option->verify == TRUE || option->second == TRUE ||
	option->clip > 0.0 || option->dontcares == TRUE) {
	char *nodesave = option->node;
	option->node = NULL;
	result = Ntr_buildDDs(net2,dd,option,net1);
	option->node = nodesave;
	if (result == 0) { exit(2); }
    }

    if (option->noBuild == TRUE) {
	Bnet_FreeNetwork(net1);
	if (option->verify == TRUE || option->second == TRUE ||
	    option->clip > 0.0) {
	    Bnet_FreeNetwork(net2);
	}
	freeOption(option);
	exit(0);
    }
    if (option->locGlob != BNET_LOCAL_DD) {
	/* Print the order before the final reordering. */
	(void) printf("Order before final reordering\n");
	result = Bnet_PrintOrder(net1,dd);
	if (result == 0) exit(2);
    }

    /* Perform final reordering */
    if (option->zddtest == FALSE) {
	result = reorder(net1,dd,option);
	if (result == 0) exit(2);

	/* Print final order. */
	if ((option->reordering != CUDD_REORDER_NONE || option->gaOnOff) &&
	    option->locGlob != BNET_LOCAL_DD) {
	    (void) printf("New order\n");
	    result = Bnet_PrintOrder(net1,dd);
	    if (result == 0) exit(2);
	}

	/* Print the re-encoded inputs. */
	if (pr >= 1 && reencoded == 1) {
	    for (i = 0; i < net1->npis; i++) {
		if (!st_lookup(net1->hash,net1->inputs[i],&node)) {
		    exit(2);
		}
		(void) fprintf(stdout,"%s:",node->name);
		Cudd_PrintDebug(dd,node->dd,Cudd_ReadSize(dd),pr);
	    }
	    for (i = 0; i < net1->nlatches; i++) {
		if (!st_lookup(net1->hash,net1->latches[i][1],&node)) {
		    exit(2);
		}
		(void) fprintf(stdout,"%s:",node->name);
		Cudd_PrintDebug(dd,node->dd,Cudd_ReadSize(dd),pr);
	    }
	    if (pr >= 3) {
		result = Cudd_PrintLinear(dd);
		if (result == 0) exit(2);
	    }
	}
    }

    /* Verify (combinational) equivalence. */
    if (option->verify == TRUE) {
	result = Ntr_VerifyEquivalence(dd,net1,net2,option);
	if (result == 0) {
	    (void) printf("Verification abnormally terminated\n");
	    exit(2);
	} else if (result == -1) {
	    (void) printf("Combinational verification failed\n");
	} else {
	    (void) printf("Verification succeeded\n");
	}
    }

    /* Traverse if requested and if the circuit is sequential. */
    result = Ntr_Trav(dd,net1,option);
    if (result == 0) exit(2);

    /* Traverse with trasitive closure. */
    result = Ntr_ClosureTrav(dd,net1,option);
    if (result == 0) exit(2);

    /* Compute outer envelope if requested and if the circuit is sequential. */
    if (option->envelope == TRUE && net1->nlatches > 0) {
	NtrPartTR *T;
	T = Ntr_buildTR(dd,net1,option,option->image);
	result = Ntr_Envelope(dd,T,NULL,option);
	Ntr_freeTR(dd,T);
    }

    /* Compute SCCs if requested and if the circuit is sequential. */
    result = Ntr_SCC(dd,net1,option);
    if (result == 0) exit(2);

    /* Test Constrain Decomposition. */
    if (option->partition == TRUE && net1->nlatches > 0) {
	NtrPartTR *T;
	DdNode *product;
	DdNode **decomp;
	int sharingSize;
	T = Ntr_buildTR(dd,net1,option,NTR_IMAGE_MONO);
	decomp = Cudd_bddConstrainDecomp(dd,T->part[0]);
	if (decomp == NULL) exit(2);
	sharingSize = Cudd_SharingSize(decomp, Cudd_ReadSize(dd));
	(void) fprintf(stdout, "Decomposition Size: %d components %d nodes\n",
		       Cudd_ReadSize(dd), sharingSize);
	product = Cudd_ReadOne(dd);
	Cudd_Ref(product);
	for (i = 0; i < Cudd_ReadSize(dd); i++) {
	    DdNode *intermediate = Cudd_bddAnd(dd, product, decomp[i]);
	    if (intermediate == NULL) {
		exit(2);
	    }
	    Cudd_Ref(intermediate);
	    Cudd_IterDerefBdd(dd, product);
	    product = intermediate;
	}
	if (product != T->part[0])
	    exit(2);
	Cudd_IterDerefBdd(dd, product);
	for (i = 0; i < Cudd_ReadSize(dd); i++) {
	    Cudd_IterDerefBdd(dd, decomp[i]);
	}
	FREE(decomp);
	Ntr_freeTR(dd,T);
    }

    /* Test char-to-vect conversion. */
    result = Ntr_TestCharToVect(dd,net1,option);
    if (result == 0) exit(2);

    /* Test extraction of two-literal clauses. */
    result = Ntr_TestTwoLiteralClauses(dd,net1,option);
    if (result == 0) exit(2);

    /* Test BDD minimization functions. */
    result = Ntr_TestMinimization(dd,net1,net2,option);
    if (result == 0) exit(2);

    /* Test density-related functions. */
    result = Ntr_TestDensity(dd,net1,option);
    if (result == 0) exit(2);

    /* Test decomposition functions. */
    result = Ntr_TestDecomp(dd,net1,option);
    if (result == 0) exit(2);

    /* Test cofactor estimation functions. */
    result = Ntr_TestCofactorEstimate(dd,net1,option);
    if (result == 0) exit(2);

    /* Test BDD clipping functions. */
    result = Ntr_TestClipping(dd,net1,net2,option);
    if (result == 0) exit(2);

    /* Test BDD equivalence and containment under DC functions. */
    result = Ntr_TestEquivAndContain(dd,net1,net2,option);
    if (result == 0) exit(2);

    /* Test BDD Cudd_bddClosestCube. */
    result = Ntr_TestClosestCube(dd,net1,option);
    if (result == 0) exit(2);

    /* Test ZDDs if requested. */
    if (option->stateOnly == FALSE && option->zddtest == TRUE) {
	result = Ntr_testZDD(dd,net1,option);
	if (result == 0)
	    (void) fprintf(stdout,"ZDD test failed.\n");
	result = Ntr_testISOP(dd,net1,option);
	if (result == 0)
	    (void) fprintf(stdout,"ISOP test failed.\n");
    }

    /* Compute maximum flow if requested and if the circuit is sequential. */
    if (option->maxflow == TRUE && net1->nlatches > 0) {
	result = Ntr_maxflow(dd,net1,option);
	if (result == 0)
	    (void) fprintf(stdout,"Maxflow computation failed.\n");
    }

    /* Compute shortest paths if requested and if the circuit is sequential. */
    if (option->shortPath != NTR_SHORT_NONE && net1->nlatches > 0) {
	result = Ntr_ShortestPaths(dd,net1,option);
	if (result == 0)
	    (void) fprintf(stdout,"Shortest paths computation failed.\n");
    }

    /* Compute output signatures if so requested. */
    if (option->signatures) {
	(void) printf("Positive cofactor measures\n");
	for (i = 0; i < net1->noutputs; i++) {
	    if (!st_lookup(net1->hash,net1->outputs[i],&node)) {
		exit(2);
	    }
	    signatures = Cudd_CofMinterm(dd, node->dd);
	    if (signatures) {
		(void) printf("%s:\n", node->name);
		for (j = 0; j < Cudd_ReadSize(dd); j++) {
		    if((j%5 == 0)&&i) (void) printf("\n");
		    (void) printf("%5d: %-#8.4g ", j, signatures[j]);
		}
		(void) printf("\n");
		FREE(signatures);
	    } else {
		(void) printf("Signature computation failed.\n");
	    }
	}
    }

    /* Dump BDDs if so requested. */
    if (option->bdddump && option->second == FALSE &&
	option->density == FALSE && option->decomp == FALSE &&
	option->cofest == FALSE && option->clip < 0.0 &&
	option->scc == FALSE) {
	(void) printf("Dumping BDDs to %s\n", option->dumpfile);
	if (option->node != NULL) {
	    if (!st_lookup(net1->hash,option->node,&node)) {
		exit(2);
	    }
	    result = Bnet_bddArrayDump(dd,net1,option->dumpfile,&(node->dd),
				       &(node->name),1,option->dumpFmt);
	} else {
	    result = Bnet_bddDump(dd, net1, option->dumpfile,
				  option->dumpFmt, reencoded);
	}
	if (result != 1) {
	    (void) printf("BDD dump failed.\n");
	}
    }

    /* Print stats and clean up. */
    if (pr >= 0) {
	result = Cudd_PrintInfo(dd,stdout);
	if (result != 1) {
	    (void) printf("Cudd_PrintInfo failed.\n");
	}
    }

#if defined(DD_DEBUG) && !defined(DD_NO_DEATH_ROW)
    (void) fprintf(dd->err,"%d empty slots in death row\n",
    cuddTimesInDeathRow(dd,NULL));
#endif
    (void) printf("Final size: %ld\n", Cudd_ReadNodeCount(dd));

    /* Dispose of node BDDs. */
    node = net1->nodes;
    while (node != NULL) {
	if (node->dd != NULL &&
	node->type != BNET_INPUT_NODE &&
	node->type != BNET_PRESENT_STATE_NODE) {
	    Cudd_IterDerefBdd(dd,node->dd);
	}
	node = node->next;
    }
    /* Dispose of network. */
    Bnet_FreeNetwork(net1);
    /* Do the same cleanup for the second network if it was created. */
    if (option->verify == TRUE || option->second == TRUE ||
	option->clip > 0.0 || option->dontcares == TRUE) {
	node = net2->nodes;
	while (node != NULL) {
	    if (node->dd != NULL &&
		node->type != BNET_INPUT_NODE &&
		node->type != BNET_PRESENT_STATE_NODE) {
		Cudd_IterDerefBdd(dd,node->dd);
	    }
	    node = node->next;
	}
	Bnet_FreeNetwork(net2);
    }

    /* Check reference counts: At this point we should have dereferenced
    ** everything we had, except in the case of re-encoding.
    */
    exitval = Cudd_CheckZeroRef(dd);
    ok = exitval != 0;  /* ok == 0 means O.K. */
    if (exitval != 0) {
	(void) fflush(stdout);
	(void) fprintf(stderr,
	    "%d non-zero DD reference counts after dereferencing\n", exitval);
    }

#ifdef DD_DEBUG
    Cudd_CheckKeys(dd);
#endif

    Cudd_Quit(dd);

    if (pr >= 0) (void) printf("total time = %s\n",
	    util_print_time(util_cpu_time() - option->initialTime));
    freeOption(option);
    if (pr >= 0) util_print_cpu_stats(stdout);

#ifdef MNEMOSYNE
    mnem_writestats();
#endif

    exit(ok);
    /* NOTREACHED */

} /* end of main */