blob: 23af0e387aa078c19482dece435a88cea3a64097 [file] [log] [blame]
/**CFile****************************************************************
FileName [ivyMulti.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [And-Inverter Graph package.]
Synopsis [Constructing multi-input AND/EXOR gates.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - May 11, 2006.]
Revision [$Id: ivyMulti.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $]
***********************************************************************/
#include "ivy.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
typedef struct Ivy_Eval_t_ Ivy_Eval_t;
struct Ivy_Eval_t_
{
unsigned Mask : 5; // the mask of covered nodes
unsigned Weight : 3; // the number of covered nodes
unsigned Cost : 4; // the number of overlapping nodes
unsigned Level : 12; // the level of this node
unsigned Fan0 : 4; // the first fanin
unsigned Fan1 : 4; // the second fanin
};
static Ivy_Obj_t * Ivy_MultiBuild_rec( Ivy_Eval_t * pEvals, int iNum, Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type );
static void Ivy_MultiSort( Ivy_Obj_t ** pArgs, int nArgs );
static int Ivy_MultiPushUniqueOrderByLevel( Ivy_Obj_t ** pArray, int nArgs, Ivy_Obj_t * pNode );
static Ivy_Obj_t * Ivy_MultiEval( Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type );
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Constructs the well-balanced tree of gates.]
Description [Disregards levels and possible logic sharing.]
SideEffects []
SeeAlso []
***********************************************************************/
Ivy_Obj_t * Ivy_Multi_rec( Ivy_Obj_t ** ppObjs, int nObjs, Ivy_Type_t Type )
{
Ivy_Obj_t * pObj1, * pObj2;
if ( nObjs == 1 )
return ppObjs[0];
pObj1 = Ivy_Multi_rec( ppObjs, nObjs/2, Type );
pObj2 = Ivy_Multi_rec( ppObjs + nObjs/2, nObjs - nObjs/2, Type );
return Ivy_Oper( pObj1, pObj2, Type );
}
/**Function*************************************************************
Synopsis [Constructs a balanced tree while taking sharing into account.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Ivy_Obj_t * Ivy_Multi( Ivy_Obj_t ** pArgsInit, int nArgs, Ivy_Type_t Type )
{
static char NumBits[32] = {0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5};
static Ivy_Eval_t pEvals[15+15*14/2];
static Ivy_Obj_t * pArgs[16];
Ivy_Eval_t * pEva, * pEvaBest;
int nArgsNew, nEvals, i, k;
Ivy_Obj_t * pTemp;
// consider the case of one argument
assert( nArgs > 0 );
if ( nArgs == 1 )
return pArgsInit[0];
// consider the case of two arguments
if ( nArgs == 2 )
return Ivy_Oper( pArgsInit[0], pArgsInit[1], Type );
//Ivy_MultiEval( pArgsInit, nArgs, Type ); printf( "\n" );
// set the initial ones
for ( i = 0; i < nArgs; i++ )
{
pArgs[i] = pArgsInit[i];
pEva = pEvals + i;
pEva->Mask = (1 << i);
pEva->Weight = 1;
pEva->Cost = 0;
pEva->Level = Ivy_Regular(pArgs[i])->Level;
pEva->Fan0 = 0;
pEva->Fan1 = 0;
}
// find the available nodes
pEvaBest = pEvals;
nArgsNew = nArgs;
for ( i = 1; i < nArgsNew; i++ )
for ( k = 0; k < i; k++ )
if ( pTemp = Ivy_TableLookup(Ivy_ObjCreateGhost(pArgs[k], pArgs[i], Type, IVY_INIT_NONE)) )
{
pEva = pEvals + nArgsNew;
pEva->Mask = pEvals[k].Mask | pEvals[i].Mask;
pEva->Weight = NumBits[pEva->Mask];
pEva->Cost = pEvals[k].Cost + pEvals[i].Cost + NumBits[pEvals[k].Mask & pEvals[i].Mask];
pEva->Level = 1 + IVY_MAX(pEvals[k].Level, pEvals[i].Level);
pEva->Fan0 = k;
pEva->Fan1 = i;
// assert( pEva->Level == (unsigned)Ivy_ObjLevel(pTemp) );
// compare
if ( pEvaBest->Weight < pEva->Weight ||
pEvaBest->Weight == pEva->Weight && pEvaBest->Cost > pEva->Cost ||
pEvaBest->Weight == pEva->Weight && pEvaBest->Cost == pEva->Cost && pEvaBest->Level > pEva->Level )
pEvaBest = pEva;
// save the argument
pArgs[nArgsNew++] = pTemp;
if ( nArgsNew == 15 )
goto Outside;
}
Outside:
// printf( "Best = %d.\n", pEvaBest - pEvals );
// the case of no common nodes
if ( nArgsNew == nArgs )
{
Ivy_MultiSort( pArgs, nArgs );
return Ivy_MultiBalance_rec( pArgs, nArgs, Type );
}
// the case of one common node
if ( nArgsNew == nArgs + 1 )
{
assert( pEvaBest - pEvals == nArgs );
k = 0;
for ( i = 0; i < nArgs; i++ )
if ( i != (int)pEvaBest->Fan0 && i != (int)pEvaBest->Fan1 )
pArgs[k++] = pArgs[i];
pArgs[k++] = pArgs[nArgs];
assert( k == nArgs - 1 );
nArgs = k;
Ivy_MultiSort( pArgs, nArgs );
return Ivy_MultiBalance_rec( pArgs, nArgs, Type );
}
// the case when there is a node that covers everything
if ( (int)pEvaBest->Mask == ((1 << nArgs) - 1) )
return Ivy_MultiBuild_rec( pEvals, pEvaBest - pEvals, pArgs, nArgsNew, Type );
// evaluate node pairs
nEvals = nArgsNew;
for ( i = 1; i < nArgsNew; i++ )
for ( k = 0; k < i; k++ )
{
pEva = pEvals + nEvals;
pEva->Mask = pEvals[k].Mask | pEvals[i].Mask;
pEva->Weight = NumBits[pEva->Mask];
pEva->Cost = pEvals[k].Cost + pEvals[i].Cost + NumBits[pEvals[k].Mask & pEvals[i].Mask];
pEva->Level = 1 + IVY_MAX(pEvals[k].Level, pEvals[i].Level);
pEva->Fan0 = k;
pEva->Fan1 = i;
// compare
if ( pEvaBest->Weight < pEva->Weight ||
pEvaBest->Weight == pEva->Weight && pEvaBest->Cost > pEva->Cost ||
pEvaBest->Weight == pEva->Weight && pEvaBest->Cost == pEva->Cost && pEvaBest->Level > pEva->Level )
pEvaBest = pEva;
// save the argument
nEvals++;
}
assert( pEvaBest - pEvals >= nArgsNew );
// printf( "Used (%d, %d).\n", pEvaBest->Fan0, pEvaBest->Fan1 );
// get the best implementation
pTemp = Ivy_MultiBuild_rec( pEvals, pEvaBest - pEvals, pArgs, nArgsNew, Type );
// collect those not covered by EvaBest
k = 0;
for ( i = 0; i < nArgs; i++ )
if ( (pEvaBest->Mask & (1 << i)) == 0 )
pArgs[k++] = pArgs[i];
pArgs[k++] = pTemp;
assert( k == nArgs - (int)pEvaBest->Weight + 1 );
nArgs = k;
Ivy_MultiSort( pArgs, nArgs );
return Ivy_MultiBalance_rec( pArgs, nArgs, Type );
}
/**Function*************************************************************
Synopsis [Implements multi-input AND/EXOR operation.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Ivy_Obj_t * Ivy_MultiBuild_rec( Ivy_Eval_t * pEvals, int iNum, Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type )
{
Ivy_Obj_t * pNode0, * pNode1;
if ( iNum < nArgs )
return pArgs[iNum];
pNode0 = Ivy_MultiBuild_rec( pEvals, pEvals[iNum].Fan0, pArgs, nArgs, Type );
pNode1 = Ivy_MultiBuild_rec( pEvals, pEvals[iNum].Fan1, pArgs, nArgs, Type );
return Ivy_Oper( pNode0, pNode1, Type );
}
/**Function*************************************************************
Synopsis [Selection-sorts the nodes in the decreasing over of level.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Ivy_MultiSort( Ivy_Obj_t ** pArgs, int nArgs )
{
Ivy_Obj_t * pTemp;
int i, j, iBest;
for ( i = 0; i < nArgs-1; i++ )
{
iBest = i;
for ( j = i+1; j < nArgs; j++ )
if ( Ivy_Regular(pArgs[j])->Level > Ivy_Regular(pArgs[iBest])->Level )
iBest = j;
pTemp = pArgs[i];
pArgs[i] = pArgs[iBest];
pArgs[iBest] = pTemp;
}
}
/**Function*************************************************************
Synopsis [Inserts a new node in the order by levels.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Ivy_MultiPushUniqueOrderByLevel( Ivy_Obj_t ** pArray, int nArgs, Ivy_Obj_t * pNode )
{
Ivy_Obj_t * pNode1, * pNode2;
int i;
// try to find the node in the array
for ( i = 0; i < nArgs; i++ )
if ( pArray[i] == pNode )
return nArgs;
// put the node last
pArray[nArgs++] = pNode;
// find the place to put the new node
for ( i = nArgs-1; i > 0; i-- )
{
pNode1 = pArray[i ];
pNode2 = pArray[i-1];
if ( Ivy_Regular(pNode1)->Level <= Ivy_Regular(pNode2)->Level )
break;
pArray[i ] = pNode2;
pArray[i-1] = pNode1;
}
return nArgs;
}
/**Function*************************************************************
Synopsis [Balances the array recursively.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Ivy_Obj_t * Ivy_MultiBalance_rec( Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type )
{
Ivy_Obj_t * pNodeNew;
// consider the case of one argument
assert( nArgs > 0 );
if ( nArgs == 1 )
return pArgs[0];
// consider the case of two arguments
if ( nArgs == 2 )
return Ivy_Oper( pArgs[0], pArgs[1], Type );
// get the last two nodes
pNodeNew = Ivy_Oper( pArgs[nArgs-1], pArgs[nArgs-2], Type );
// add the new node
nArgs = Ivy_MultiPushUniqueOrderByLevel( pArgs, nArgs - 2, pNodeNew );
return Ivy_MultiBalance_rec( pArgs, nArgs, Type );
}
/**Function*************************************************************
Synopsis [Implements multi-input AND/EXOR operation.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Ivy_Obj_t * Ivy_MultiEval( Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type )
{
Ivy_Obj_t * pTemp;
int i, k;
int nArgsOld = nArgs;
for ( i = 0; i < nArgs; i++ )
printf( "%d[%d] ", i, Ivy_Regular(pArgs[i])->Level );
for ( i = 1; i < nArgs; i++ )
for ( k = 0; k < i; k++ )
{
pTemp = Ivy_TableLookup(Ivy_ObjCreateGhost(pArgs[k], pArgs[i], Type, IVY_INIT_NONE));
if ( pTemp != NULL )
{
printf( "%d[%d]=(%d,%d) ", nArgs, Ivy_Regular(pTemp)->Level, k, i );
pArgs[nArgs++] = pTemp;
}
}
printf( " ((%d/%d)) ", nArgsOld, nArgs-nArgsOld );
return NULL;
}
/**Function*************************************************************
Synopsis [Old code.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Ivy_Obj_t * Ivy_Multi1( Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type )
{
Ivy_Obj_t * pArgsRef[5], * pTemp;
int i, k, m, nArgsNew, Counter = 0;
//Ivy_MultiEval( pArgs, nArgs, Type ); printf( "\n" );
assert( Type == IVY_AND || Type == IVY_EXOR );
assert( nArgs > 0 );
if ( nArgs == 1 )
return pArgs[0];
// find the nodes with more than one fanout
nArgsNew = 0;
for ( i = 0; i < nArgs; i++ )
if ( Ivy_ObjRefs( Ivy_Regular(pArgs[i]) ) > 0 )
pArgsRef[nArgsNew++] = pArgs[i];
// go through pairs
if ( nArgsNew >= 2 )
for ( i = 0; i < nArgsNew; i++ )
for ( k = i + 1; k < nArgsNew; k++ )
if ( pTemp = Ivy_TableLookup(Ivy_ObjCreateGhost(pArgsRef[i], pArgsRef[k], Type, IVY_INIT_NONE)) )
Counter++;
// printf( "%d", Counter );
// go through pairs
if ( nArgsNew >= 2 )
for ( i = 0; i < nArgsNew; i++ )
for ( k = i + 1; k < nArgsNew; k++ )
if ( pTemp = Ivy_TableLookup(Ivy_ObjCreateGhost(pArgsRef[i], pArgsRef[k], Type, IVY_INIT_NONE)) )
{
nArgsNew = 0;
for ( m = 0; m < nArgs; m++ )
if ( pArgs[m] != pArgsRef[i] && pArgs[m] != pArgsRef[k] )
pArgs[nArgsNew++] = pArgs[m];
pArgs[nArgsNew++] = pTemp;
assert( nArgsNew == nArgs - 1 );
return Ivy_Multi1( pArgs, nArgsNew, Type );
}
return Ivy_Multi_rec( pArgs, nArgs, Type );
}
/**Function*************************************************************
Synopsis [Old code.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Ivy_Obj_t * Ivy_Multi2( Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type )
{
assert( Type == IVY_AND || Type == IVY_EXOR );
assert( nArgs > 0 );
return Ivy_Multi_rec( pArgs, nArgs, Type );
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END