/**Function******************************************************************** Synopsis [Generates a BDD for the function x==y.] Description [This function generates a BDD for the function x==y. Both x and y are N-bit numbers, x\[0\] x\[1\] ... x\[N-1\] and y\[0\] y\[1\] ... y\[N-1\], with 0 the most significant bit. The BDD is built bottom-up. It has 3*N-1 internal nodes, if the variables are ordered as follows: x\[0\] y\[0\] x\[1\] y\[1\] ... x\[N-1\] y\[N-1\]. ] SideEffects [None] SeeAlso [Cudd_addXeqy] ******************************************************************************/ DdNode * Cudd_Xeqy( DdManager * dd /* DD manager */, int N /* number of x and y variables */, DdNode ** x /* array of x variables */, DdNode ** y /* array of y variables */) { DdNode *u, *v, *w; int i; /* Build bottom part of BDD outside loop. */ u = Cudd_bddIte(dd, x[N-1], y[N-1], Cudd_Not(y[N-1])); if (u == NULL) return(NULL); cuddRef(u); /* Loop to build the rest of the BDD. */ for (i = N-2; i >= 0; i--) { v = Cudd_bddAnd(dd, y[i], u); if (v == NULL) { Cudd_RecursiveDeref(dd, u); return(NULL); } cuddRef(v); w = Cudd_bddAnd(dd, Cudd_Not(y[i]), u); if (w == NULL) { Cudd_RecursiveDeref(dd, u); Cudd_RecursiveDeref(dd, v); return(NULL); } cuddRef(w); Cudd_RecursiveDeref(dd, u); u = Cudd_bddIte(dd, x[i], v, w); if (u == NULL) { Cudd_RecursiveDeref(dd, v); Cudd_RecursiveDeref(dd, w); return(NULL); } cuddRef(u); Cudd_RecursiveDeref(dd, v); Cudd_RecursiveDeref(dd, w); } cuddDeref(u); return(u); } /* end of Cudd_Xeqy */
/**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * dsdTreeGetPrimeFunction( DdManager * dd, Dsd_Node_t * pNode, int fRemap ) { DdNode * bCof0, * bCof1, * bCube0, * bCube1, * bNewFunc, * bTemp; int i; int fAllBuffs = 1; static int Permute[MAXINPUTS]; assert( pNode ); assert( !Dsd_IsComplement( pNode ) ); assert( pNode->Type == DT_PRIME ); // transform the function of this block to depend on inputs // corresponding to the formal inputs // first, substitute those inputs that have some blocks associated with them // second, remap the inputs to the top of the manager (then, it is easy to output them) // start the function bNewFunc = pNode->G; Cudd_Ref( bNewFunc ); // go over all primary inputs for ( i = 0; i < pNode->nDecs; i++ ) if ( pNode->pDecs[i]->Type != DT_BUF ) // remap only if it is not the buffer { bCube0 = Extra_bddFindOneCube( dd, Cudd_Not(pNode->pDecs[i]->G) ); Cudd_Ref( bCube0 ); bCof0 = Cudd_Cofactor( dd, bNewFunc, bCube0 ); Cudd_Ref( bCof0 ); Cudd_RecursiveDeref( dd, bCube0 ); bCube1 = Extra_bddFindOneCube( dd, pNode->pDecs[i]->G ); Cudd_Ref( bCube1 ); bCof1 = Cudd_Cofactor( dd, bNewFunc, bCube1 ); Cudd_Ref( bCof1 ); Cudd_RecursiveDeref( dd, bCube1 ); Cudd_RecursiveDeref( dd, bNewFunc ); // use the variable in the i-th level of the manager // bNewFunc = Cudd_bddIte( dd, dd->vars[dd->invperm[i]],bCof1,bCof0 ); Cudd_Ref( bNewFunc ); // use the first variale in the support of the component bNewFunc = Cudd_bddIte( dd, dd->vars[pNode->pDecs[i]->S->index],bCof1,bCof0 ); Cudd_Ref( bNewFunc ); Cudd_RecursiveDeref( dd, bCof0 ); Cudd_RecursiveDeref( dd, bCof1 ); } if ( fRemap ) { // remap the function to the top of the manager // remap the function to the first variables of the manager for ( i = 0; i < pNode->nDecs; i++ ) // Permute[ pNode->pDecs[i]->S->index ] = dd->invperm[i]; Permute[ pNode->pDecs[i]->S->index ] = i; bNewFunc = Cudd_bddPermute( dd, bTemp = bNewFunc, Permute ); Cudd_Ref( bNewFunc ); Cudd_RecursiveDeref( dd, bTemp ); } Cudd_Deref( bNewFunc ); return bNewFunc; }
/**Function******************************************************************** Synopsis [Computes the Hamming distance ADD.] Description [Computes the Hamming distance ADD. Returns an ADD that gives the Hamming distance between its two arguments if successful; NULL otherwise. The two vectors xVars and yVars identify the variables that form the two arguments.] SideEffects [None] SeeAlso [] ******************************************************************************/ DdNode * Cudd_addHamming( DdManager * dd, DdNode ** xVars, DdNode ** yVars, int nVars) { DdNode *result,*tempBdd; DdNode *tempAdd,*temp; int i; result = DD_ZERO(dd); cuddRef(result); for (i = 0; i < nVars; i++) { tempBdd = Cudd_bddIte(dd,xVars[i],Cudd_Not(yVars[i]),yVars[i]); if (tempBdd == NULL) { Cudd_RecursiveDeref(dd,result); return(NULL); } cuddRef(tempBdd); tempAdd = Cudd_BddToAdd(dd,tempBdd); if (tempAdd == NULL) { Cudd_RecursiveDeref(dd,tempBdd); Cudd_RecursiveDeref(dd,result); return(NULL); } cuddRef(tempAdd); Cudd_RecursiveDeref(dd,tempBdd); temp = Cudd_addApply(dd,Cudd_addPlus,tempAdd,result); if (temp == NULL) { Cudd_RecursiveDeref(dd,tempAdd); Cudd_RecursiveDeref(dd,result); return(NULL); } cuddRef(temp); Cudd_RecursiveDeref(dd,tempAdd); Cudd_RecursiveDeref(dd,result); result = temp; } cuddDeref(result); return(result); } /* end of Cudd_addHamming */
/**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Extra_dsdRemap( DdManager * dd, DdNode * bF, st_table * pCache, int * pVar2Form, int * pForm2Var, DdNode * pbCube0[], DdNode * pbCube1[] ) { DdNode * bFR, * bF0, * bF1; DdNode * bRes0, * bRes1, * bRes; int iForm; bFR = Cudd_Regular(bF); if ( cuddIsConstant(bFR) ) return bF; // check the hash-table if ( bFR->ref != 1 ) { if ( st_lookup( pCache, (char *)bF, (char **)&bRes ) ) return bRes; } // get the formal input iForm = pVar2Form[bFR->index]; // get the nodes pointed to by the cube bF0 = Extra_bddNodePointedByCube( dd, bF, pbCube0[iForm] ); bF1 = Extra_bddNodePointedByCube( dd, bF, pbCube1[iForm] ); // call recursively for these nodes bRes0 = Extra_dsdRemap( dd, bF0, pCache, pVar2Form, pForm2Var, pbCube0, pbCube1 ); Cudd_Ref( bRes0 ); bRes1 = Extra_dsdRemap( dd, bF1, pCache, pVar2Form, pForm2Var, pbCube0, pbCube1 ); Cudd_Ref( bRes1 ); // derive the result using ITE bRes = Cudd_bddIte( dd, dd->vars[ pForm2Var[iForm] ], bRes1, bRes0 ); Cudd_Ref( bRes ); Cudd_RecursiveDeref( dd, bRes0 ); Cudd_RecursiveDeref( dd, bRes1 ); // add to the hash table if ( bFR->ref != 1 ) st_insert( pCache, (char *)bF, (char *)bRes ); Cudd_Deref( bRes ); return bRes; }
/**Function******************************************************************** Synopsis [Generates a BDD for the function d(x,y) > d(y,z).] Description [This function generates a BDD for the function d(x,y) > d(y,z); x, y, and z are N-bit numbers, x\[0\] x\[1\] ... x\[N-1\], y\[0\] y\[1\] ... y\[N-1\], and z\[0\] z\[1\] ... z\[N-1\], with 0 the most significant bit. The distance d(x,y) is defined as: \sum_{i=0}^{N-1}(|x_i - y_i| \cdot 2^{N-i-1}). The BDD is built bottom-up. It has 7*N-3 internal nodes, if the variables are ordered as follows: x\[0\] y\[0\] z\[0\] x\[1\] y\[1\] z\[1\] ... x\[N-1\] y\[N-1\] z\[N-1\]. ] SideEffects [None] SeeAlso [Cudd_PrioritySelect Cudd_Dxygtdxz Cudd_Xgty Cudd_bddAdjPermuteX] ******************************************************************************/ DdNode * Cudd_Dxygtdyz( DdManager * dd /* DD manager */, int N /* number of x, y, and z variables */, DdNode ** x /* array of x variables */, DdNode ** y /* array of y variables */, DdNode ** z /* array of z variables */) { DdNode *one, *zero; DdNode *z1, *z2, *z3, *z4, *y1_, *y2, *x1; int i; one = DD_ONE(dd); zero = Cudd_Not(one); /* Build bottom part of BDD outside loop. */ y1_ = Cudd_bddIte(dd, y[N-1], one, z[N-1]); if (y1_ == NULL) return(NULL); cuddRef(y1_); y2 = Cudd_bddIte(dd, y[N-1], z[N-1], zero); if (y2 == NULL) { Cudd_RecursiveDeref(dd, y1_); return(NULL); } cuddRef(y2); x1 = Cudd_bddIte(dd, x[N-1], y1_, Cudd_Not(y2)); if (x1 == NULL) { Cudd_RecursiveDeref(dd, y1_); Cudd_RecursiveDeref(dd, y2); return(NULL); } cuddRef(x1); Cudd_RecursiveDeref(dd, y1_); Cudd_RecursiveDeref(dd, y2); /* Loop to build the rest of the BDD. */ for (i = N-2; i >= 0; i--) { z1 = Cudd_bddIte(dd, z[i], x1, zero); if (z1 == NULL) { Cudd_RecursiveDeref(dd, x1); return(NULL); } cuddRef(z1); z2 = Cudd_bddIte(dd, z[i], x1, one); if (z2 == NULL) { Cudd_RecursiveDeref(dd, x1); Cudd_RecursiveDeref(dd, z1); return(NULL); } cuddRef(z2); z3 = Cudd_bddIte(dd, z[i], one, x1); if (z3 == NULL) { Cudd_RecursiveDeref(dd, x1); Cudd_RecursiveDeref(dd, z1); Cudd_RecursiveDeref(dd, z2); return(NULL); } cuddRef(z3); z4 = Cudd_bddIte(dd, z[i], one, Cudd_Not(x1)); if (z4 == NULL) { Cudd_RecursiveDeref(dd, x1); Cudd_RecursiveDeref(dd, z1); Cudd_RecursiveDeref(dd, z2); Cudd_RecursiveDeref(dd, z3); return(NULL); } cuddRef(z4); Cudd_RecursiveDeref(dd, x1); y1_ = Cudd_bddIte(dd, y[i], z2, z1); if (y1_ == NULL) { Cudd_RecursiveDeref(dd, z1); Cudd_RecursiveDeref(dd, z2); Cudd_RecursiveDeref(dd, z3); Cudd_RecursiveDeref(dd, z4); return(NULL); } cuddRef(y1_); y2 = Cudd_bddIte(dd, y[i], z4, Cudd_Not(z3)); if (y2 == NULL) { Cudd_RecursiveDeref(dd, z1); Cudd_RecursiveDeref(dd, z2); Cudd_RecursiveDeref(dd, z3); Cudd_RecursiveDeref(dd, z4); Cudd_RecursiveDeref(dd, y1_); return(NULL); } cuddRef(y2); Cudd_RecursiveDeref(dd, z1); Cudd_RecursiveDeref(dd, z2); Cudd_RecursiveDeref(dd, z3); Cudd_RecursiveDeref(dd, z4); x1 = Cudd_bddIte(dd, x[i], y1_, Cudd_Not(y2)); if (x1 == NULL) { Cudd_RecursiveDeref(dd, y1_); Cudd_RecursiveDeref(dd, y2); return(NULL); } cuddRef(x1); Cudd_RecursiveDeref(dd, y1_); Cudd_RecursiveDeref(dd, y2); } cuddDeref(x1); return(Cudd_Not(x1)); } /* end of Cudd_Dxygtdyz */
void I_BDD_new_mutex_domain (DdManager *dd, DdNode *node[], unsigned int size) { unsigned int shbuf, vars, ctr; DdNode **ddVar, *one, *newnode, *oldnode, *bitnode; int i,j, extra; /* base cases */ if (size == 0) { return; } one = Cudd_ReadOne(dd); if (size == 1) { node[0] = one; Cudd_Ref (node[0]); return; } for(shbuf = size - 1, vars = 0; shbuf != 0; shbuf >>= 1, vars++); extra = (1 << vars) - size; ddVar = malloc(vars * sizeof(DdNode *)); for (j = 0; j < vars; j++) { ddVar[j] = bitnode = Cudd_bddNewVar (dd); Cudd_Ref (bitnode); } ctr = 0; for (i = 0; i < size; i++, ctr++) { newnode = one; Cudd_Ref (newnode); #ifdef I_BDD_MUTEX_DEBUG printf("i%d:", i); #endif for (j = (extra > 0); j < vars; j++) { bitnode = (ctr & (1 << j)) ? ddVar[j] : Cudd_Not(ddVar[j]); newnode = Cudd_bddAnd (dd, bitnode, oldnode = newnode); Cudd_Ref (newnode); Cudd_RecursiveDeref (dd, oldnode); #ifdef I_BDD_MUTEX_DEBUG if (ctr & (1 << j)) printf("+ v%d ", j); else printf("+ !v%d ", j); #endif } #ifdef I_BDD_MUTEX_DEBUG printf ("\n"); #endif node[i] = newnode; if (extra > 0) { extra--; ctr++; } } #ifdef I_BDD_MUTEX_TEST { DdNode *test, *old_test; int i; test = Cudd_ReadLogicZero(dd); Cudd_Ref (test); for (i = 0; i < size; i++) { if (Cudd_bddIte (dd, test, node[i], zero) != zero) I_punt("I_BDD_new_mutex_complex: not mutex!"); test = Cudd_bddIte(dd, node[i], one, old_test = test); Cudd_Ref (test); Cudd_RecursiveDeref (dd, old_test); } if (test != one) I_punt("I_BDD_new_mutex_complex: not exhaustive!"); Cudd_RecursiveDeref (dd, test); } #endif for (j = 0; j < vars; j++) Cudd_RecursiveDeref (dd, ddVar[j]); free (ddVar); return; }
ref_t shadow_ite(shadow_mgr mgr, ref_t iref, ref_t tref, ref_t eref) { DdNode *in = get_ddnode(mgr, iref); DdNode *tn = get_ddnode(mgr, tref); DdNode *en = get_ddnode(mgr, eref); DdNode *n = NULL; ref_t r = REF_INVALID; dd_type_t dtype = IS_BDD; if (mgr->do_local) { r = ref_ite(mgr->ref_mgr, iref, tref, eref); } if (mgr->do_dist) { ref_t rdist = dist_ite(mgr->ref_mgr, iref, tref, eref); if (mgr->do_local) { if (!check_refs(mgr, r, rdist)) { return REF_INVALID; } } else { r = rdist; } } if (mgr->do_cudd) { if (mgr->nzvars > 0) { bool zi = is_zdd(mgr, iref); bool zt = is_zdd(mgr, tref); bool ze = is_zdd(mgr, eref); if (zi || zt || ze) { dtype = IS_ZDD; if (is_add(mgr, iref) || is_add(mgr, tref) || is_add(mgr, eref)) { err(false, "Can't mix ADDs with ZDDs"); } if (!zi) { in = zconvert(mgr, in); } if (!zt) { tn = zconvert(mgr, tn); } if (!ze) { en = zconvert(mgr, en); } n = Cudd_zddIte(mgr->bdd_manager, in, tn, en); reference_dd(mgr, n); if (!zi) unreference_dd(mgr, in, IS_ZDD); if (!zt) unreference_dd(mgr, tn, IS_ZDD); if (!ze) unreference_dd(mgr, en, IS_ZDD); } } { bool ai = is_add(mgr, iref); bool at = is_add(mgr, tref); bool ae = is_add(mgr, eref); if (ai || at || ae) { dtype = IS_ADD; if (!ai) { in = aconvert(mgr, in); } if (!at) { tn = aconvert(mgr, tn); } if (!ae) { en = aconvert(mgr, en); } n = Cudd_addIte(mgr->bdd_manager, in, tn, en); reference_dd(mgr, n); if (!ai) unreference_dd(mgr, in, IS_ADD); if (!at) unreference_dd(mgr, tn, IS_ADD); if (!ae) unreference_dd(mgr, en, IS_ADD); } } if (dtype == IS_BDD) { n = Cudd_bddIte(mgr->bdd_manager, in, tn, en); reference_dd(mgr, n); } } else { n = ref2dd(mgr, r); } if (!do_ref(mgr)) r = dd2ref(n, dtype); add_ref(mgr, r, n); return r; }