/**CFile**************************************************************** FileName [dsdLocal.c] PackageName [DSD: Disjoint-support decomposition package.] Synopsis [Deriving the local function of the DSD node.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 8.0. Started - September 22, 2003.] Revision [$Id: dsdLocal.c,v 1.0 2002/22/09 00:00:00 alanmi Exp $] ***********************************************************************/ #include "dsdInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// STATIC VARIABLES /// //////////////////////////////////////////////////////////////////////// static DdNode * Extra_dsdRemap( DdManager * dd, DdNode * bFunc, st__table * pCache, int * pVar2Form, int * pForm2Var, DdNode * pbCube0[], DdNode * pbCube1[] ); static DdNode * Extra_bddNodePointedByCube( DdManager * dd, DdNode * bF, DdNode * bC ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Returns the local function of the DSD node. ] Description [The local function is computed using the global function of the node and the global functions of the formal inputs. The resulting local function is mapped using the topmost N variables of the manager. The number of variables N is equal to the number of formal inputs.] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Dsd_TreeGetPrimeFunction( DdManager * dd, Dsd_Node_t * pNode ) { int * pForm2Var; // the mapping of each formal input into its first var int * pVar2Form; // the mapping of each var into its formal inputs int i, iVar, iLev, * pPermute; DdNode ** pbCube0, ** pbCube1; DdNode * bFunc, * bRes, * bTemp; st__table * pCache; pPermute = ABC_ALLOC( int, dd->size ); pVar2Form = ABC_ALLOC( int, dd->size ); pForm2Var = ABC_ALLOC( int, dd->size ); pbCube0 = ABC_ALLOC( DdNode *, dd->size ); pbCube1 = ABC_ALLOC( DdNode *, dd->size ); // remap the global function in such a way that // the support variables of each formal input are adjacent iLev = 0; for ( i = 0; i < pNode->nDecs; i++ ) { pForm2Var[i] = dd->invperm[i]; for ( bTemp = pNode->pDecs[i]->S; bTemp != b1; bTemp = cuddT(bTemp) ) { iVar = dd->invperm[iLev]; pPermute[bTemp->index] = iVar; pVar2Form[iVar] = i; iLev++; } // collect the cubes representing each assignment pbCube0[i] = Extra_bddGetOneCube( dd, Cudd_Not(pNode->pDecs[i]->G) ); Cudd_Ref( pbCube0[i] ); pbCube1[i] = Extra_bddGetOneCube( dd, pNode->pDecs[i]->G ); Cudd_Ref( pbCube1[i] ); } // remap the function bFunc = Cudd_bddPermute( dd, pNode->G, pPermute ); Cudd_Ref( bFunc ); // remap the cube for ( i = 0; i < pNode->nDecs; i++ ) { pbCube0[i] = Cudd_bddPermute( dd, bTemp = pbCube0[i], pPermute ); Cudd_Ref( pbCube0[i] ); Cudd_RecursiveDeref( dd, bTemp ); pbCube1[i] = Cudd_bddPermute( dd, bTemp = pbCube1[i], pPermute ); Cudd_Ref( pbCube1[i] ); Cudd_RecursiveDeref( dd, bTemp ); } // remap the function pCache = st__init_table( st__ptrcmp, st__ptrhash);; bRes = Extra_dsdRemap( dd, bFunc, pCache, pVar2Form, pForm2Var, pbCube0, pbCube1 ); Cudd_Ref( bRes ); st__free_table( pCache ); Cudd_RecursiveDeref( dd, bFunc ); for ( i = 0; i < pNode->nDecs; i++ ) { Cudd_RecursiveDeref( dd, pbCube0[i] ); Cudd_RecursiveDeref( dd, pbCube1[i] ); } /* //////////// // permute the function once again // in such a way that i-th var stood for i-th formal input for ( i = 0; i < dd->size; i++ ) pPermute[i] = -1; for ( i = 0; i < pNode->nDecs; i++ ) pPermute[dd->invperm[i]] = i; bRes = Cudd_bddPermute( dd, bTemp = bRes, pPermute ); Cudd_Ref( bRes ); Cudd_RecursiveDeref( dd, bTemp ); //////////// */ ABC_FREE(pPermute); ABC_FREE(pVar2Form); ABC_FREE(pForm2Var); ABC_FREE(pbCube0); ABC_FREE(pbCube1); Cudd_Deref( bRes ); return bRes; } /**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 [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Extra_bddNodePointedByCube( DdManager * dd, DdNode * bF, DdNode * bC ) { DdNode * bFR, * bCR; DdNode * bF0, * bF1; DdNode * bC0, * bC1; int LevelF, LevelC; assert( bC != b0 ); if ( bC == b1 ) return bF; // bRes = cuddCacheLookup2( dd, Extra_bddNodePointedByCube, bF, bC ); // if ( bRes ) // return bRes; // there is no need for caching because this operation is very fast // there will no gain reusing the results of this operations // instead, it will flush CUDD cache of other useful entries bFR = Cudd_Regular( bF ); bCR = Cudd_Regular( bC ); assert( !cuddIsConstant( bFR ) ); LevelF = dd->perm[bFR->index]; LevelC = dd->perm[bCR->index]; if ( LevelF <= LevelC ) { if ( bFR != bF ) { bF0 = Cudd_Not( cuddE(bFR) ); bF1 = Cudd_Not( cuddT(bFR) ); } else { bF0 = cuddE(bFR); bF1 = cuddT(bFR); } } else { bF0 = bF1 = bF; } if ( LevelC <= LevelF ) { if ( bCR != bC ) { bC0 = Cudd_Not( cuddE(bCR) ); bC1 = Cudd_Not( cuddT(bCR) ); } else { bC0 = cuddE(bCR); bC1 = cuddT(bCR); } } else { bC0 = bC1 = bC; } assert( bC0 == b0 || bC1 == b0 ); if ( bC0 == b0 ) return Extra_bddNodePointedByCube( dd, bF1, bC1 ); return Extra_bddNodePointedByCube( dd, bF0, bC0 ); } #if 0 /**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; } #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END