/**Function************************************************************* Synopsis [Starts the monolithic image computation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Extra_ImageTree2_t * Extra_bddImageStart2( DdManager * dd, DdNode * bCare, int nParts, DdNode ** pbParts, int nVars, DdNode ** pbVars, int fVerbose ) { Extra_ImageTree2_t * pTree; DdNode * bCubeAll, * bCubeNot, * bTemp; int i; pTree = ABC_ALLOC( Extra_ImageTree2_t, 1 ); pTree->dd = dd; pTree->bImage = NULL; bCubeAll = Extra_bddComputeCube( dd, dd->vars, dd->size ); Cudd_Ref( bCubeAll ); bCubeNot = Extra_bddComputeCube( dd, pbVars, nVars ); Cudd_Ref( bCubeNot ); pTree->bCube = Cudd_bddExistAbstract( dd, bCubeAll, bCubeNot ); Cudd_Ref( pTree->bCube ); Cudd_RecursiveDeref( dd, bCubeAll ); Cudd_RecursiveDeref( dd, bCubeNot ); // derive the monolithic relation pTree->bRel = b1; Cudd_Ref( pTree->bRel ); for ( i = 0; i < nParts; i++ ) { pTree->bRel = Cudd_bddAnd( dd, bTemp = pTree->bRel, pbParts[i] ); Cudd_Ref( pTree->bRel ); Cudd_RecursiveDeref( dd, bTemp ); } Extra_bddImageCompute2( pTree, bCare ); return pTree; }
static keyvalue_table_ptr cudd_equant(shadow_mgr mgr, set_ptr roots, set_ptr vars) { DdNode *cube = cudd_lit_cube(mgr, vars); keyvalue_table_ptr etable = word_keyvalue_new(); word_t w; set_iterstart(roots); while (set_iternext(roots, &w)) { ref_t r = (ref_t) w; DdNode *n = get_ddnode(mgr, r); DdNode *nr = Cudd_bddExistAbstract(mgr->bdd_manager, n, cube); reference_dd(mgr, nr); keyvalue_insert(etable, w, (word_t) nr); } unreference_dd(mgr, cube, IS_BDD); return etable; }
/**Function************************************************************* Synopsis [Recompute the image.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Extra_bddImageCompute_rec( Extra_ImageTree_t * pTree, Extra_ImageNode_t * pNode ) { DdManager * dd = pNode->dd; DdNode * bTemp; int nNodes; // trivial case if ( pNode->pNode1 == NULL ) { if ( pNode->bCube ) { pNode->bImage = Cudd_bddExistAbstract( dd, bTemp = pNode->bImage, pNode->bCube ); Cudd_Ref( pNode->bImage ); Cudd_RecursiveDeref( dd, bTemp ); } return; } // compute the children if ( pNode->pNode1 ) Extra_bddImageCompute_rec( pTree, pNode->pNode1 ); if ( pNode->pNode2 ) Extra_bddImageCompute_rec( pTree, pNode->pNode2 ); // clean the old image if ( pNode->bImage ) Cudd_RecursiveDeref( dd, pNode->bImage ); pNode->bImage = NULL; // compute the new image if ( pNode->bCube ) pNode->bImage = Cudd_bddAndAbstract( dd, pNode->pNode1->bImage, pNode->pNode2->bImage, pNode->bCube ); else pNode->bImage = Cudd_bddAnd( dd, pNode->pNode1->bImage, pNode->pNode2->bImage ); Cudd_Ref( pNode->bImage ); if ( pTree->fVerbose ) { nNodes = Cudd_DagSize( pNode->bImage ); if ( pTree->nNodesMax < nNodes ) pTree->nNodesMax = nNodes; } }
/**Function************************************************************* Synopsis [Compute the image.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Extra_bddImageCompute( Extra_ImageTree_t * pTree, DdNode * bCare ) { DdManager * dd = pTree->pCare->dd; DdNode * bSupp, * bRem; pTree->nIter++; // make sure the supports are okay bSupp = Cudd_Support( dd, bCare ); Cudd_Ref( bSupp ); if ( bSupp != pTree->bCareSupp ) { bRem = Cudd_bddExistAbstract( dd, bSupp, pTree->bCareSupp ); Cudd_Ref( bRem ); if ( bRem != b1 ) { printf( "Original care set support: " ); ABC_PRB( dd, pTree->bCareSupp ); printf( "Current care set support: " ); ABC_PRB( dd, bSupp ); Cudd_RecursiveDeref( dd, bSupp ); Cudd_RecursiveDeref( dd, bRem ); printf( "The care set depends on some vars that were not in the care set during scheduling.\n" ); return NULL; } Cudd_RecursiveDeref( dd, bRem ); } Cudd_RecursiveDeref( dd, bSupp ); // remove the previous image Cudd_RecursiveDeref( dd, pTree->pCare->bImage ); pTree->pCare->bImage = bCare; Cudd_Ref( bCare ); // compute the image pTree->nNodesMax = 0; Extra_bddImageCompute_rec( pTree, pTree->pRoot ); if ( pTree->nNodesMaxT < pTree->nNodesMax ) pTree->nNodesMaxT = pTree->nNodesMax; // if ( pTree->fVerbose ) // printf( "Iter %2d : Max nodes = %5d.\n", pTree->nIter, pTree->nNodesMax ); return pTree->pRoot->bImage; }
Abc_NtkForEachLatch( pNtk, pNode, i ) { bVar = Cudd_bddIthVar( dd, Abc_NtkCiNum(pNtk) + i ); // bProd = Cudd_bddXnor( dd, bVar, pNtk->vFuncsGlob->pArray[i] ); Cudd_Ref( bProd ); bProd = Cudd_bddXnor( dd, bVar, Abc_ObjGlobalBdd(Abc_ObjFanin0(pNode)) ); Cudd_Ref( bProd ); bRel = Cudd_bddAnd( dd, bTemp = bRel, bProd ); Cudd_Ref( bRel ); Cudd_RecursiveDeref( dd, bTemp ); Cudd_RecursiveDeref( dd, bProd ); } // free the global BDDs // Abc_NtkFreeGlobalBdds( pNtk ); Abc_NtkFreeGlobalBdds( pNtk, 0 ); // quantify the PI variables bInputs = Extra_bddComputeRangeCube( dd, 0, Abc_NtkPiNum(pNtk) ); Cudd_Ref( bInputs ); bRel = Cudd_bddExistAbstract( dd, bTemp = bRel, bInputs ); Cudd_Ref( bRel ); Cudd_RecursiveDeref( dd, bTemp ); Cudd_RecursiveDeref( dd, bInputs ); // reorder and disable reordering if ( fReorder ) { if ( fVerbose ) fprintf( stdout, "BDD nodes in the transition relation before reordering %d.\n", Cudd_DagSize(bRel) ); Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 ); Cudd_AutodynDisable( dd ); if ( fVerbose ) fprintf( stdout, "BDD nodes in the transition relation after reordering %d.\n", Cudd_DagSize(bRel) ); } Cudd_Deref( bRel ); return bRel;
/**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 */
/**Function************************************************************* Synopsis [Builds the tree.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Extra_BuildTreeNode( DdManager * dd, int nNodes, Extra_ImageNode_t ** pNodes, int nVars, Extra_ImageVar_t ** pVars ) { Extra_ImageNode_t * pNode1, * pNode2; Extra_ImageVar_t * pVar; Extra_ImageNode_t * pNode; DdNode * bCube, * bTemp, * bSuppTemp, * bParts; int iNode1, iNode2; int iVarBest, nSupp, v; // find the best variable iVarBest = Extra_FindBestVariable( dd, nNodes, pNodes, nVars, pVars ); if ( iVarBest == -1 ) return 0; pVar = pVars[iVarBest]; // this var cannot appear in one partition only nSupp = Extra_bddSuppSize( dd, pVar->bParts ); assert( nSupp == pVar->nParts ); assert( nSupp != 1 ); // if it appears in only two partitions, quantify it if ( pVar->nParts == 2 ) { // get the nodes iNode1 = pVar->bParts->index; iNode2 = cuddT(pVar->bParts)->index; pNode1 = pNodes[iNode1]; pNode2 = pNodes[iNode2]; // get the quantification cube bCube = dd->vars[pVar->iNum]; Cudd_Ref( bCube ); // add the variables that appear only in these partitions for ( v = 0; v < nVars; v++ ) if ( pVars[v] && v != iVarBest && pVars[v]->bParts == pVars[iVarBest]->bParts ) { // add this var bCube = Cudd_bddAnd( dd, bTemp = bCube, dd->vars[pVars[v]->iNum] ); Cudd_Ref( bCube ); Cudd_RecursiveDeref( dd, bTemp ); // clean this var Cudd_RecursiveDeref( dd, pVars[v]->bParts ); ABC_FREE( pVars[v] ); } // clean the best var Cudd_RecursiveDeref( dd, pVars[iVarBest]->bParts ); ABC_FREE( pVars[iVarBest] ); // combines two nodes pNode = Extra_CombineTwoNodes( dd, bCube, pNode1, pNode2 ); Cudd_RecursiveDeref( dd, bCube ); } else // if ( pVar->nParts > 2 ) { // find two smallest BDDs that have this var Extra_FindBestPartitions( dd, pVar->bParts, nNodes, pNodes, &iNode1, &iNode2 ); pNode1 = pNodes[iNode1]; pNode2 = pNodes[iNode2]; // it is not possible that a var appears only in these two // otherwise, it would have a different cost bParts = Cudd_bddAnd( dd, dd->vars[iNode1], dd->vars[iNode2] ); Cudd_Ref( bParts ); for ( v = 0; v < nVars; v++ ) if ( pVars[v] && pVars[v]->bParts == bParts ) assert( 0 ); Cudd_RecursiveDeref( dd, bParts ); // combines two nodes pNode = Extra_CombineTwoNodes( dd, b1, pNode1, pNode2 ); } // clean the old nodes pNodes[iNode1] = pNode; pNodes[iNode2] = NULL; // update the variables that appear in pNode[iNode2] for ( bSuppTemp = pNode2->pPart->bSupp; bSuppTemp != b1; bSuppTemp = cuddT(bSuppTemp) ) { pVar = pVars[bSuppTemp->index]; if ( pVar == NULL ) // this variable is not be quantified continue; // quantify this var assert( Cudd_bddLeq( dd, pVar->bParts, dd->vars[iNode2] ) ); pVar->bParts = Cudd_bddExistAbstract( dd, bTemp = pVar->bParts, dd->vars[iNode2] ); Cudd_Ref( pVar->bParts ); Cudd_RecursiveDeref( dd, bTemp ); // add the new var pVar->bParts = Cudd_bddAnd( dd, bTemp = pVar->bParts, dd->vars[iNode1] ); Cudd_Ref( pVar->bParts ); Cudd_RecursiveDeref( dd, bTemp ); // update the score pVar->nParts = Extra_bddSuppSize( dd, pVar->bParts ); } return 1; }