blob: 4c807cdebc1df95fd31ddf5ef15c6cb21229d1a5 [file] [log] [blame]
/**CFile****************************************************************
FileName [giaBidec.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Scalable AIG package.]
Synopsis [Application of bi-decomposition to AIG minimization.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: giaBidec.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
#include "gia.h"
#include "bool/bdc/bdc.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Computes truth table of the cut.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
unsigned * Gia_ManConvertAigToTruth_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vTruth, int nWords, Vec_Int_t * vVisited )
{
unsigned * pTruth, * pTruth0, * pTruth1;
int i;
assert( !Gia_IsComplement(pObj) );
if ( Vec_IntGetEntry(p->vTruths, Gia_ObjId(p, pObj)) != -1 )
return (unsigned *)Vec_IntEntryP( vTruth, nWords * Vec_IntGetEntry(p->vTruths, Gia_ObjId(p, pObj)) );
// compute the truth tables of the fanins
pTruth0 = Gia_ManConvertAigToTruth_rec( p, Gia_ObjFanin0(pObj), vTruth, nWords, vVisited );
pTruth1 = Gia_ManConvertAigToTruth_rec( p, Gia_ObjFanin1(pObj), vTruth, nWords, vVisited );
// get room for the truth table
pTruth = Vec_IntFetch( vTruth, nWords );
// create the truth table of the node
if ( !Gia_ObjFaninC0(pObj) && !Gia_ObjFaninC1(pObj) )
for ( i = 0; i < nWords; i++ )
pTruth[i] = pTruth0[i] & pTruth1[i];
else if ( !Gia_ObjFaninC0(pObj) && Gia_ObjFaninC1(pObj) )
for ( i = 0; i < nWords; i++ )
pTruth[i] = pTruth0[i] & ~pTruth1[i];
else if ( Gia_ObjFaninC0(pObj) && !Gia_ObjFaninC1(pObj) )
for ( i = 0; i < nWords; i++ )
pTruth[i] = ~pTruth0[i] & pTruth1[i];
else // if ( Gia_ObjFaninC0(pObj) && Gia_ObjFaninC1(pObj) )
for ( i = 0; i < nWords; i++ )
pTruth[i] = ~pTruth0[i] & ~pTruth1[i];
// save the visited node
Vec_IntSetEntry( p->vTruths, Gia_ObjId(p, pObj), Vec_IntSize(vVisited) );
Vec_IntPush( vVisited, Gia_ObjId(p, pObj) );
return pTruth;
}
/**Function*************************************************************
Synopsis [Computes truth table of the node.]
Description [Assumes that the structural support is no more than 8 inputs.
Uses array vTruth to store temporary truth tables. The returned pointer should
be used immediately.]
SideEffects []
SeeAlso []
***********************************************************************/
unsigned * Gia_ManConvertAigToTruth( Gia_Man_t * p, Gia_Obj_t * pRoot, Vec_Int_t * vLeaves, Vec_Int_t * vTruth, Vec_Int_t * vVisited )
{
static unsigned uTruths[8][8] = { // elementary truth tables
{ 0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA },
{ 0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC },
{ 0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0 },
{ 0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00 },
{ 0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000 },
{ 0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF },
{ 0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF,0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF },
{ 0x00000000,0x00000000,0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF }
};
Gia_Obj_t * pObj;
Vec_Ptr_t * vTtElems = NULL;
unsigned * pTruth;//, * pTruth2;
int i, nWords, nVars;
// get the number of variables and words
nVars = Vec_IntSize( vLeaves );
nWords = Abc_TruthWordNum( nVars );
// check the case of a constant
if ( Gia_ObjIsConst0( Gia_Regular(pRoot) ) )
{
Vec_IntClear( vTruth );
// get room for the truth table
pTruth = Vec_IntFetch( vTruth, nWords );
if ( !Gia_IsComplement(pRoot) )
Gia_ManTruthClear( pTruth, nVars );
else
Gia_ManTruthFill( pTruth, nVars );
return pTruth;
}
// if the number of variables is more than 8, allocate truth tables
if ( nVars > 8 )
vTtElems = Vec_PtrAllocTruthTables( nVars );
// assign elementary truth tables
Vec_IntClear( vTruth );
Vec_IntClear( vVisited );
Gia_ManForEachObjVec( vLeaves, p, pObj, i )
{
// get room for the truth table
pTruth = Vec_IntFetch( vTruth, nWords );
// assign elementary variable
if ( vTtElems )
Gia_ManTruthCopy( pTruth, (unsigned *)Vec_PtrEntry(vTtElems, i), nVars );
else
Gia_ManTruthCopy( pTruth, uTruths[i], nVars );
// save the visited node
Vec_IntSetEntry( p->vTruths, Gia_ObjId(p, pObj), Vec_IntSize(vVisited) );
Vec_IntPush( vVisited, Gia_ObjId(p, pObj) );
}
if ( vTtElems )
Vec_PtrFree( vTtElems );
// clear the marks and compute the truth table
// pTruth2 = Gia_ManConvertAigToTruth_rec( p, Gia_Regular(pRoot), vTruth, nWords, vVisited );
pTruth = Gia_ManConvertAigToTruth_rec( p, Gia_Regular(pRoot), vTruth, nWords, vVisited );
// copy the result
// Gia_ManTruthCopy( pTruth, pTruth2, nVars );
if ( Gia_IsComplement(pRoot) )
Gia_ManTruthNot( pTruth, pTruth, nVars );
// clean truth tables
Gia_ManForEachObjVec( vVisited, p, pObj, i )
Vec_IntSetEntry( p->vTruths, Gia_ObjId(p, pObj), -1 );
return pTruth;
}
/**Function*************************************************************
Synopsis [Resynthesizes nodes using bi-decomposition.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Gia_ObjPerformBidec( Bdc_Man_t * pManDec,
Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pRoot,
Vec_Int_t * vLeaves, Vec_Int_t * vTruth, Vec_Int_t * vVisited )
{
unsigned * pTruth;
Bdc_Fun_t * pFunc;
Gia_Obj_t * pFanin;
int i, iFan, nVars, nNodes;
// collect leaves of this gate
Vec_IntClear( vLeaves );
Gia_LutForEachFanin( p, Gia_ObjId(p, pRoot), iFan, i )
Vec_IntPush( vLeaves, iFan );
nVars = Vec_IntSize( vLeaves );
assert( nVars < 16 );
// derive truth table
pTruth = Gia_ManConvertAigToTruth( p, pRoot, vLeaves, vTruth, vVisited );
//Extra_PrintBinary( stdout, pTruth, (1<<nVars) ); printf( "\n" );
if ( Gia_ManTruthIsConst0(pTruth, nVars) )
{
//printf( "Node %d is const0\n", Gia_ObjId(p, pRoot) );
return 0;
}
if ( Gia_ManTruthIsConst1(pTruth, nVars) )
{
//printf( "Node %d is const1\n", Gia_ObjId(p, pRoot) );
return 1;
}
// decompose truth table
Bdc_ManDecompose( pManDec, pTruth, NULL, nVars, NULL, 1000 );
/*
if ( Bdc_ManNodeNum(pManDec) == 0 )
printf( "Node %d has 0 bidec nodes\n", Gia_ObjId(p, pRoot) );
if ( Kit_TruthSupportSize(pTruth, nVars) != nVars )
{
printf( "Node %d has %d fanins and %d supp size\n", Gia_ObjId(p, pRoot), nVars, Kit_TruthSupportSize(pTruth, nVars) );
Gia_LutForEachFanin( p, Gia_ObjId(p, pRoot), iFan, i )
{
printf( "%d ", Kit_TruthVarInSupport(pTruth, nVars, i) );
Gia_ObjPrint( p, Gia_ManObj(p, iFan) );
}
// Gia_ManPrintStats( p, 0 );
}
*/
// convert back into HOP
Bdc_FuncSetCopy( Bdc_ManFunc( pManDec, 0 ), Gia_ManConst1(pNew) );
Gia_ManForEachObjVec( vLeaves, p, pFanin, i )
Bdc_FuncSetCopyInt( Bdc_ManFunc( pManDec, i+1 ), Gia_ObjValue(pFanin) );
nNodes = Bdc_ManNodeNum( pManDec );
for ( i = nVars + 1; i < nNodes; i++ )
{
pFunc = Bdc_ManFunc( pManDec, i );
Bdc_FuncSetCopyInt( pFunc, Gia_ManHashAnd( pNew, Bdc_FunFanin0Copy(pFunc), Bdc_FunFanin1Copy(pFunc) ) );
}
return Bdc_FunObjCopy( Bdc_ManRoot(pManDec) );
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Gia_Man_t * Gia_ManPerformBidec( Gia_Man_t * p, int fVerbose )
{
Bdc_Man_t * pManDec;
Bdc_Par_t Pars = {0}, * pPars = &Pars;
Vec_Int_t * vLeaves, * vTruth, * vVisited;
Gia_Man_t * pNew, * pTemp;
Gia_Obj_t * pObj;
int i;//, clk = Abc_Clock();
pPars->nVarsMax = Gia_ManLutSizeMax( p );
pPars->fVerbose = fVerbose;
if ( pPars->nVarsMax < 2 )
{
printf( "Resynthesis is not performed when nodes have less than 2 inputs.\n" );
return NULL;
}
if ( pPars->nVarsMax > 15 )
{
printf( "Resynthesis is not performed when nodes have more than 15 inputs.\n" );
return NULL;
}
vLeaves = Vec_IntAlloc( 0 );
vTruth = Vec_IntAlloc( (1<<16) );
vVisited = Vec_IntAlloc( 0 );
// clean the old manager
Gia_ManCleanTruth( p );
Gia_ManFillValue( p );
Gia_ManConst0(p)->Value = 0;
// start the new manager
pNew = Gia_ManStart( Gia_ManObjNum(p) );
pNew->pName = Abc_UtilStrsav( p->pName );
pNew->pSpec = Abc_UtilStrsav( p->pSpec );
Gia_ManHashAlloc( pNew );
// Gia_ManCleanLevels( pNew, Gia_ManObjNum(p) );
pManDec = Bdc_ManAlloc( pPars );
Gia_ManForEachObj1( p, pObj, i )
{
if ( Gia_ObjIsCi(pObj) ) // transfer the CI level (is it needed?)
pObj->Value = Gia_ManAppendCi( pNew );
else if ( Gia_ObjIsCo(pObj) )
pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
else if ( Gia_ObjIsLut(p, i) )
pObj->Value = Gia_ObjPerformBidec( pManDec, pNew, p, pObj, vLeaves, vTruth, vVisited );
}
Bdc_ManFree( pManDec );
// cleanup the AIG
Gia_ManHashStop( pNew );
// check the presence of dangling nodes
if ( Gia_ManHasDangling(pNew) )
{
pNew = Gia_ManCleanup( pTemp = pNew );
if ( Gia_ManAndNum(pNew) != Gia_ManAndNum(pTemp) )
printf( "Gia_ManPerformBidec() node count before and after: %6d and %6d.\n", Gia_ManAndNum(pNew), Gia_ManAndNum(pTemp) );
Gia_ManStop( pTemp );
}
Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) );
Vec_IntFree( vLeaves );
Vec_IntFree( vTruth );
Vec_IntFree( vVisited );
if ( fVerbose )
{
// printf( "Total gain in AIG nodes = %d. ", Gia_ManObjNum(p)-Gia_ManObjNum(pNew) );
// ABC_PRT( "Total runtime", Abc_Clock() - clk );
}
return pNew;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END