blob: 552b53e9d3b01551db69485a3e87e5f5427ec266 [file] [log] [blame]
/**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