blob: c6ccb7d1fc58f269417bc1394dd8be6def3ff4df [file] [log] [blame]
/**CFile****************************************************************
FileName [giaCof.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Scalable AIG package.]
Synopsis [Cofactor estimation procedures.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: giaCof.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
#include <math.h>
#include "gia.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
typedef struct Cof_Fan_t_ Cof_Fan_t;
struct Cof_Fan_t_
{
unsigned iFan : 31; // ID of the fanin/fanout
unsigned fCompl : 1; // complemented attribute
};
typedef struct Cof_Obj_t_ Cof_Obj_t;
struct Cof_Obj_t_
{
unsigned fTerm : 1; // terminal node (CI/CO)
unsigned fPhase : 1; // value under 000 pattern
unsigned fMark0 : 1; // first user-controlled mark
unsigned fMark1 : 1; // second user-controlled mark
unsigned nFanins : 4; // the number of fanins
unsigned nFanouts : 24; // total number of fanouts
unsigned nFanoutsM; // total number of MUX ctrl fanouts
unsigned Value; // application specific data
int Id; // ID of the node
int iNext; // next one in the linked list
int iLit; // literal of the node after rehashing
Cof_Fan_t Fanios[0]; // the array of fanins/fanouts
};
typedef struct Cof_Man_t_ Cof_Man_t;
struct Cof_Man_t_
{
Gia_Man_t * pGia; // the original AIG manager
Vec_Int_t * vCis; // the vector of CIs (PIs + LOs)
Vec_Int_t * vCos; // the vector of COs (POs + LIs)
int nObjs; // the number of objects
int nNodes; // the number of nodes
int nTravIds; // traversal ID of the network
int * pObjData; // the logic network defined for the AIG
int nObjData; // the size of array to store the logic network
int * pLevels; // the linked lists of levels
int nLevels; // the max number of logic levels
};
static inline unsigned Gia_ObjHandle( Gia_Obj_t * pObj ) { return pObj->Value; }
static inline int Cof_ObjLevel( Cof_Man_t * p, Cof_Obj_t * pObj ) { return Gia_ObjLevel(p->pGia, Gia_ManObj(p->pGia,pObj->Id)); }
static inline unsigned Cof_ObjHandle( Cof_Man_t * p, Cof_Obj_t * pObj ) { return (unsigned)(((int *)pObj) - p->pObjData); }
static inline unsigned Cof_ObjHandleDiff( Cof_Obj_t * pObj, Cof_Obj_t * pFanin ) { return (unsigned)(((int *)pObj) - ((int *)pFanin)); }
static inline int Cof_ObjIsTerm( Cof_Obj_t * pObj ) { return pObj->fTerm; }
static inline int Cof_ObjIsCi( Cof_Obj_t * pObj ) { return pObj->fTerm && pObj->nFanins == 0; }
static inline int Cof_ObjIsCo( Cof_Obj_t * pObj ) { return pObj->fTerm && pObj->nFanins == 1; }
static inline int Cof_ObjIsNode( Cof_Obj_t * pObj ) { return!pObj->fTerm && pObj->nFanins > 0; }
static inline int Cof_ObjIsConst0( Cof_Obj_t * pObj ) { return!pObj->fTerm && pObj->nFanins == 0; }
static inline int Cof_ObjFaninNum( Cof_Obj_t * pObj ) { return pObj->nFanins; }
static inline int Cof_ObjFanoutNum( Cof_Obj_t * pObj ) { return pObj->nFanouts; }
static inline int Cof_ObjSize( Cof_Obj_t * pObj ) { return sizeof(Cof_Obj_t) / 4 + pObj->nFanins + pObj->nFanouts; }
static inline Cof_Obj_t * Cof_ManObj( Cof_Man_t * p, unsigned iHandle ) { return (Cof_Obj_t *)(p->pObjData + iHandle); }
static inline Cof_Obj_t * Cof_ObjFanin( Cof_Obj_t * pObj, int i ) { return (Cof_Obj_t *)(((int *)pObj) - pObj->Fanios[i].iFan); }
static inline Cof_Obj_t * Cof_ObjFanout( Cof_Obj_t * pObj, int i ) { return (Cof_Obj_t *)(((int *)pObj) + pObj->Fanios[pObj->nFanins+i].iFan); }
static inline int Cof_ManObjNum( Cof_Man_t * p ) { return p->nObjs; }
static inline int Cof_ManNodeNum( Cof_Man_t * p ) { return p->nNodes; }
static inline void Cof_ManResetTravId( Cof_Man_t * p ) { extern void Cof_ManCleanValue( Cof_Man_t * p ); Cof_ManCleanValue( p ); p->nTravIds = 1; }
static inline void Cof_ManIncrementTravId( Cof_Man_t * p ) { p->nTravIds++; }
static inline void Cof_ObjSetTravId( Cof_Obj_t * pObj, int TravId ) { pObj->Value = TravId; }
static inline void Cof_ObjSetTravIdCurrent( Cof_Man_t * p, Cof_Obj_t * pObj ) { pObj->Value = p->nTravIds; }
static inline void Cof_ObjSetTravIdPrevious( Cof_Man_t * p, Cof_Obj_t * pObj ) { pObj->Value = p->nTravIds - 1; }
static inline int Cof_ObjIsTravIdCurrent( Cof_Man_t * p, Cof_Obj_t * pObj ) { return ((int)pObj->Value == p->nTravIds); }
static inline int Cof_ObjIsTravIdPrevious( Cof_Man_t * p, Cof_Obj_t * pObj ) { return ((int)pObj->Value == p->nTravIds - 1); }
#define Cof_ManForEachObj( p, pObj, i ) \
for ( i = 0; (i < p->nObjData) && (pObj = Cof_ManObj(p,i)); i += Cof_ObjSize(pObj) )
#define Cof_ManForEachNode( p, pObj, i ) \
for ( i = 0; (i < p->nObjData) && (pObj = Cof_ManObj(p,i)); i += Cof_ObjSize(pObj) ) if ( Cof_ObjIsTerm(pObj) ) {} else
#define Cof_ObjForEachFanin( pObj, pNext, i ) \
for ( i = 0; (i < (int)pObj->nFanins) && (pNext = Cof_ObjFanin(pObj,i)); i++ )
#define Cof_ObjForEachFanout( pObj, pNext, i ) \
for ( i = 0; (i < (int)pObj->nFanouts) && (pNext = Cof_ObjFanout(pObj,i)); i++ )
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Creates logic network isomorphic to the given AIG.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Cof_Man_t * Cof_ManCreateLogicSimple( Gia_Man_t * pGia )
{
Cof_Man_t * p;
Cof_Obj_t * pObjLog, * pFanLog;
Gia_Obj_t * pObj;
int * pMuxRefs;
int i, iHandle = 0;
p = ABC_CALLOC( Cof_Man_t, 1 );
p->pGia = pGia;
p->vCis = Vec_IntAlloc( Gia_ManCiNum(pGia) );
p->vCos = Vec_IntAlloc( Gia_ManCoNum(pGia) );
p->nObjData = (sizeof(Cof_Obj_t) / 4) * Gia_ManObjNum(pGia) + 4 * Gia_ManAndNum(pGia) + 2 * Gia_ManCoNum(pGia);
p->pObjData = ABC_CALLOC( int, p->nObjData );
ABC_FREE( pGia->pRefs );
Gia_ManCreateRefs( pGia );
Gia_ManForEachObj( pGia, pObj, i )
{
pObj->Value = iHandle;
pObjLog = Cof_ManObj( p, iHandle );
pObjLog->nFanins = 0;
pObjLog->nFanouts = Gia_ObjRefNum( pGia, pObj );
pObjLog->Id = i;
pObjLog->Value = 0;
if ( Gia_ObjIsAnd(pObj) )
{
pFanLog = Cof_ManObj( p, Gia_ObjHandle(Gia_ObjFanin0(pObj)) );
pFanLog->Fanios[pFanLog->nFanins + pFanLog->Value++].iFan =
pObjLog->Fanios[pObjLog->nFanins].iFan = Cof_ObjHandleDiff( pObjLog, pFanLog );
pObjLog->Fanios[pObjLog->nFanins++].fCompl = Gia_ObjFaninC0(pObj);
pFanLog = Cof_ManObj( p, Gia_ObjHandle(Gia_ObjFanin1(pObj)) );
pFanLog->Fanios[pFanLog->nFanins + pFanLog->Value++].iFan =
pObjLog->Fanios[pObjLog->nFanins].iFan = Cof_ObjHandleDiff( pObjLog, pFanLog );
pObjLog->Fanios[pObjLog->nFanins++].fCompl = Gia_ObjFaninC1(pObj);
p->nNodes++;
}
else if ( Gia_ObjIsCo(pObj) )
{
pFanLog = Cof_ManObj( p, Gia_ObjHandle(Gia_ObjFanin0(pObj)) );
pFanLog->Fanios[pFanLog->nFanins + pFanLog->Value++].iFan =
pObjLog->Fanios[pObjLog->nFanins].iFan = Cof_ObjHandleDiff( pObjLog, pFanLog );
pObjLog->Fanios[pObjLog->nFanins++].fCompl = Gia_ObjFaninC0(pObj);
pObjLog->fTerm = 1;
Vec_IntPush( p->vCos, iHandle );
}
else if ( Gia_ObjIsCi(pObj) )
{
pObjLog->fTerm = 1;
Vec_IntPush( p->vCis, iHandle );
}
iHandle += Cof_ObjSize( pObjLog );
p->nObjs++;
}
assert( iHandle == p->nObjData );
pMuxRefs = Gia_ManCreateMuxRefs( pGia );
Gia_ManForEachObj( pGia, pObj, i )
{
pObjLog = Cof_ManObj( p, Gia_ObjHandle(pObj) );
assert( pObjLog->nFanouts == pObjLog->Value );
pObjLog->nFanoutsM = pMuxRefs[i];
}
ABC_FREE( pMuxRefs );
return p;
}
/**Function*************************************************************
Synopsis [Creates logic network isomorphic to the given AIG.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Cof_ManStop( Cof_Man_t * p )
{
Vec_IntFree( p->vCis );
Vec_IntFree( p->vCos );
ABC_FREE( p->pObjData );
ABC_FREE( p->pLevels );
ABC_FREE( p );
}
/**Function*************************************************************
Synopsis [Collects support nodes.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Cof_ManTfoSize_rec( Cof_Man_t * p, Cof_Obj_t * pObj )
{
Cof_Obj_t * pNext;
unsigned i, Counter = 0;
if ( Cof_ObjIsTravIdCurrent(p, pObj) )
return 0;
Cof_ObjSetTravIdCurrent(p, pObj);
if ( Cof_ObjIsCo(pObj) )
return 0;
assert( Cof_ObjIsCi(pObj) || Cof_ObjIsNode(pObj) );
Cof_ObjForEachFanout( pObj, pNext, i )
Counter += Cof_ManTfoSize_rec( p, pNext );
return 1 + Counter;
}
/**Function*************************************************************
Synopsis [Collects support nodes.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Cof_ManTfoSize( Cof_Man_t * p, Cof_Obj_t ** ppObjs, int nObjs )
{
int i, Counter = 0;
Cof_ManIncrementTravId( p );
for ( i = 0; i < nObjs; i++ )
Counter += Cof_ManTfoSize_rec( p, ppObjs[i] ) - 1;
return Counter;
}
/**Function*************************************************************
Synopsis [Collects support nodes.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Cof_ManTfiSize_rec( Cof_Man_t * p, Cof_Obj_t * pObj )
{
Cof_Obj_t * pNext;
unsigned i, Counter = 0;
if ( Cof_ObjIsTravIdCurrent(p, pObj) )
return 0;
Cof_ObjSetTravIdCurrent(p, pObj);
if ( Cof_ObjIsCi(pObj) )
return 0;
assert( Cof_ObjIsNode(pObj) );
Cof_ObjForEachFanin( pObj, pNext, i )
Counter += Cof_ManTfiSize_rec( p, pNext );
return 1 + Counter;
}
/**Function*************************************************************
Synopsis [Collects support nodes.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Cof_ManTfiSize( Cof_Man_t * p, Cof_Obj_t ** ppObjs, int nObjs )
{
int i, Counter = 0;
Cof_ManIncrementTravId( p );
for ( i = 0; i < nObjs; i++ )
if ( Cof_ObjIsCo(ppObjs[i]) )
Counter += Cof_ManTfiSize_rec( p, Cof_ObjFanin(ppObjs[i],0) );
else
Counter += Cof_ManTfiSize_rec( p, ppObjs[i] );
return Counter;
}
/**Function*************************************************************
Synopsis [Collects support nodes.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Cof_ManSuppSize_rec( Cof_Man_t * p, Cof_Obj_t * pObj )
{
Cof_Obj_t * pNext;
unsigned i, Counter = 0;
if ( Cof_ObjIsTravIdCurrent(p, pObj) )
return 0;
Cof_ObjSetTravIdCurrent(p, pObj);
if ( Cof_ObjIsCi(pObj) )
return 1;
assert( Cof_ObjIsNode(pObj) );
Cof_ObjForEachFanin( pObj, pNext, i )
Counter += Cof_ManSuppSize_rec( p, pNext );
return Counter;
}
/**Function*************************************************************
Synopsis [Collects support nodes.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Cof_ManSuppSize( Cof_Man_t * p, Cof_Obj_t ** ppObjs, int nObjs )
{
int i, Counter = 0;
Cof_ManIncrementTravId( p );
for ( i = 0; i < nObjs; i++ )
if ( Cof_ObjIsCo(ppObjs[i]) )
Counter += Cof_ManSuppSize_rec( p, Cof_ObjFanin(ppObjs[i],0) );
else
Counter += Cof_ManSuppSize_rec( p, ppObjs[i] );
return Counter;
}
/**Function*************************************************************
Synopsis [Cleans the value.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Cof_ManCleanValue( Cof_Man_t * p )
{
Cof_Obj_t * pObj;
int i;
Cof_ManForEachObj( p, pObj, i )
pObj->Value = 0;
}
/**Function*************************************************************
Synopsis [Returns sorted array of node handles with largest fanout.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Cof_ManInsertEntry_rec( Vec_Ptr_t * vNodes, Cof_Obj_t * pNode, int nNodeMax )
{
Cof_Obj_t * pLast;
if ( Vec_PtrSize(vNodes) == 0 )
{
Vec_PtrPush(vNodes, pNode);
return;
}
pLast = (Cof_Obj_t *)Vec_PtrPop(vNodes);
if ( Cof_ObjFanoutNum(pLast) < Cof_ObjFanoutNum(pNode) )
{
Cof_ManInsertEntry_rec( vNodes, pNode, nNodeMax );
if ( Vec_PtrSize(vNodes) < nNodeMax )
Vec_PtrPush( vNodes, pLast );
}
else
{
Vec_PtrPush( vNodes, pLast );
if ( Vec_PtrSize(vNodes) < nNodeMax )
Vec_PtrPush( vNodes, pNode );
}
}
/**Function*************************************************************
Synopsis [Returns sorted array of node handles with largest fanout.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Ptr_t * Cof_ManCollectHighFanout( Cof_Man_t * p, int nNodes )
{
Vec_Ptr_t * vNodes;
Cof_Obj_t * pObj;
int i;
vNodes = Vec_PtrAlloc( nNodes );
Cof_ManForEachObj( p, pObj, i )
if ( Cof_ObjIsCi(pObj) || Cof_ObjIsNode(pObj) )
Cof_ManInsertEntry_rec( vNodes, pObj, nNodes );
return vNodes;
}
/**Function*************************************************************
Synopsis [Returns sorted array of node handles with largest fanout.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Cof_ManCountRemoved( Cof_Man_t * p, Cof_Obj_t * pRoot, int fConst1 )
{
Gia_Obj_t * pNextGia;
Cof_Obj_t * pTemp, * pNext, * pFanin0, * pFanin1;
int Counter = 0, LevelStart, LevelNext;
int i, k, iHandle, iLit0, iLit1, iNextNew;
// restart the trav ids
Cof_ManIncrementTravId( p );
Cof_ObjSetTravIdCurrent( p, pRoot );
// add the node to the queue
LevelStart = Cof_ObjLevel(p, pRoot);
assert( p->pLevels[LevelStart] == 0 );
pRoot->iNext = 0;
p->pLevels[LevelStart] = Cof_ObjHandle( p, pRoot );
// set the new literal
pRoot->iLit = Abc_Var2Lit( 0, fConst1 );
// process nodes in the levelized order
for ( i = LevelStart; i < p->nLevels; i++ )
{
for ( iHandle = p->pLevels[i];
iHandle && (pTemp = Cof_ManObj(p, iHandle));
iHandle = pTemp->iNext )
{
assert( pTemp->Id != Abc_Lit2Var(pTemp->iLit) );
Cof_ObjForEachFanout( pTemp, pNext, k )
{
if ( Cof_ObjIsCo(pNext) )
continue;
if ( Cof_ObjIsTravIdCurrent(p, pNext) )
continue;
pFanin0 = Cof_ObjFanin( pNext, 0 );
pFanin1 = Cof_ObjFanin( pNext, 1 );
assert( pFanin0 == pTemp || pFanin1 == pTemp );
pNextGia = Gia_ManObj( p->pGia, pNext->Id );
if ( Cof_ObjIsTravIdCurrent(p, pFanin0) )
iLit0 = Abc_LitNotCond( pFanin0->iLit, Gia_ObjFaninC0(pNextGia) );
else
iLit0 = Gia_ObjFaninLit0( pNextGia, pNext->Id );
if ( Cof_ObjIsTravIdCurrent(p, pFanin1) )
iLit1 = Abc_LitNotCond( pFanin1->iLit, Gia_ObjFaninC1(pNextGia) );
else
iLit1 = Gia_ObjFaninLit1( pNextGia, pNext->Id );
iNextNew = Gia_ManHashAndTry( p->pGia, iLit0, iLit1 );
if ( iNextNew == -1 )
continue;
Cof_ObjSetTravIdCurrent(p, pNext);
// set the new literal
pNext->iLit = iNextNew;
// add it to be processed
LevelNext = Cof_ObjLevel( p, pNext );
assert( LevelNext > i && LevelNext < p->nLevels );
pNext->iNext = p->pLevels[LevelNext];
p->pLevels[LevelNext] = Cof_ObjHandle( p, pNext );
Counter++;
}
}
p->pLevels[i] = 0;
}
return Counter;
}
/**Function*************************************************************
Synopsis [Returns sorted array of node handles with largest fanout.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Cof_ManPrintHighFanoutOne( Cof_Man_t * p, Cof_Obj_t * pObj )
{
printf( "%7d : ", pObj->Id );
printf( "i/o/c =%2d %5d %5d ", Cof_ObjFaninNum(pObj), Cof_ObjFanoutNum(pObj), 2*pObj->nFanoutsM );
printf( "l =%4d ", Cof_ObjLevel(p, pObj) );
printf( "s =%5d ", Cof_ManSuppSize(p, &pObj, 1) );
printf( "TFI =%7d ", Cof_ManTfiSize(p, &pObj, 1) );
printf( "TFO =%7d ", Cof_ManTfoSize(p, &pObj, 1) );
printf( "C0 =%6d ", Cof_ManCountRemoved(p, pObj, 0) );
printf( "C1 =%6d", Cof_ManCountRemoved(p, pObj, 1) );
printf( "\n" );
}
/**Function*************************************************************
Synopsis [Returns sorted array of node handles with largest fanout.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Cof_ManPrintHighFanout( Cof_Man_t * p, int nNodes )
{
Vec_Ptr_t * vNodes;
Cof_Obj_t * pObj;
int i;
vNodes = Cof_ManCollectHighFanout( p, nNodes );
Vec_PtrForEachEntry( Cof_Obj_t *, vNodes, pObj, i )
Cof_ManPrintHighFanoutOne( p, pObj );
Vec_PtrFree( vNodes );
}
/**Function*************************************************************
Synopsis [Compute MFFC size of the node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Cof_NodeDeref_rec( Cof_Obj_t * pNode )
{
if ( pNode->nFanins == 0 )
return 0;
if ( --pNode->nFanouts > 0 )
return 0;
return 1 + Cof_NodeDeref_rec( Cof_ObjFanin(pNode, 0) )
+ Cof_NodeDeref_rec( Cof_ObjFanin(pNode, 1) );
}
int Cof_NodeRef_rec( Cof_Obj_t * pNode )
{
if ( pNode->nFanins == 0 )
return 0;
if ( pNode->nFanouts++ > 0 )
return 0;
return 1 + Cof_NodeRef_rec( Cof_ObjFanin(pNode, 0) )
+ Cof_NodeRef_rec( Cof_ObjFanin(pNode, 1) );
}
static inline int Cof_ObjMffcSize( Cof_Obj_t * pNode )
{
int Count1, Count2, nFanout;
nFanout = pNode->nFanouts;
pNode->nFanouts = 1;
Count1 = Cof_NodeDeref_rec( pNode );
Count2 = Cof_NodeRef_rec( pNode );
pNode->nFanouts = nFanout;
assert( Count1 == Count2 );
return Count1;
}
/**Function*************************************************************
Synopsis [Prints the distribution of fanins/fanouts in the network.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Cof_ManPrintFanio( Cof_Man_t * p )
{
char Buffer[100];
Cof_Obj_t * pNode;
Vec_Int_t * vFanins, * vFanouts, * vMffcs;
int nFanins, nFanouts, nMffcs, nFaninsMax, nFanoutsMax, nMffcsMax, nFaninsAll, nFanoutsAll, nMffcsAll;
int i, k, nSizeMax, nMffcNodes = 0;
// determine the largest fanin and fanout
nFaninsMax = nFanoutsMax = nMffcsMax = 0;
nFaninsAll = nFanoutsAll = nMffcsAll = 0;
Cof_ManForEachNode( p, pNode, i )
{
if ( i == 0 ) continue;
nFanins = Cof_ObjFaninNum(pNode);
nFanouts = Cof_ObjFanoutNum(pNode);
nMffcs = pNode->nFanouts > 1 ? Cof_ObjMffcSize(pNode) : 0;
nFaninsAll += nFanins;
nFanoutsAll += nFanouts;
nMffcsAll += nMffcs;
nFaninsMax = Abc_MaxInt( nFaninsMax, nFanins );
nFanoutsMax = Abc_MaxInt( nFanoutsMax, nFanouts );
nMffcsMax = Abc_MaxInt( nMffcsMax, nMffcs );
}
// allocate storage for fanin/fanout numbers
nSizeMax = Abc_MaxInt( 10 * (Abc_Base10Log(nFaninsMax) + 1), 10 * (Abc_Base10Log(nFanoutsMax) + 1) );
nSizeMax = Abc_MaxInt( 10 * (Abc_Base10Log(nMffcsMax) + 1), nSizeMax );
vFanins = Vec_IntStart( nSizeMax );
vFanouts = Vec_IntStart( nSizeMax );
vMffcs = Vec_IntStart( nSizeMax );
// count the number of fanins and fanouts
Cof_ManForEachNode( p, pNode, i )
{
if ( i == 0 ) continue;
nFanins = Cof_ObjFaninNum(pNode);
nFanouts = Cof_ObjFanoutNum(pNode);
nMffcs = pNode->nFanouts > 1 ? Cof_ObjMffcSize(pNode) : 0;
if ( nFanins < 10 )
Vec_IntAddToEntry( vFanins, nFanins, 1 );
else if ( nFanins < 100 )
Vec_IntAddToEntry( vFanins, 10 + nFanins/10, 1 );
else if ( nFanins < 1000 )
Vec_IntAddToEntry( vFanins, 20 + nFanins/100, 1 );
else if ( nFanins < 10000 )
Vec_IntAddToEntry( vFanins, 30 + nFanins/1000, 1 );
else if ( nFanins < 100000 )
Vec_IntAddToEntry( vFanins, 40 + nFanins/10000, 1 );
else if ( nFanins < 1000000 )
Vec_IntAddToEntry( vFanins, 50 + nFanins/100000, 1 );
else if ( nFanins < 10000000 )
Vec_IntAddToEntry( vFanins, 60 + nFanins/1000000, 1 );
if ( nFanouts < 10 )
Vec_IntAddToEntry( vFanouts, nFanouts, 1 );
else if ( nFanouts < 100 )
Vec_IntAddToEntry( vFanouts, 10 + nFanouts/10, 1 );
else if ( nFanouts < 1000 )
Vec_IntAddToEntry( vFanouts, 20 + nFanouts/100, 1 );
else if ( nFanouts < 10000 )
Vec_IntAddToEntry( vFanouts, 30 + nFanouts/1000, 1 );
else if ( nFanouts < 100000 )
Vec_IntAddToEntry( vFanouts, 40 + nFanouts/10000, 1 );
else if ( nFanouts < 1000000 )
Vec_IntAddToEntry( vFanouts, 50 + nFanouts/100000, 1 );
else if ( nFanouts < 10000000 )
Vec_IntAddToEntry( vFanouts, 60 + nFanouts/1000000, 1 );
if ( nMffcs == 0 )
continue;
nMffcNodes++;
if ( nMffcs < 10 )
Vec_IntAddToEntry( vMffcs, nMffcs, 1 );
else if ( nMffcs < 100 )
Vec_IntAddToEntry( vMffcs, 10 + nMffcs/10, 1 );
else if ( nMffcs < 1000 )
Vec_IntAddToEntry( vMffcs, 20 + nMffcs/100, 1 );
else if ( nMffcs < 10000 )
Vec_IntAddToEntry( vMffcs, 30 + nMffcs/1000, 1 );
else if ( nMffcs < 100000 )
Vec_IntAddToEntry( vMffcs, 40 + nMffcs/10000, 1 );
else if ( nMffcs < 1000000 )
Vec_IntAddToEntry( vMffcs, 50 + nMffcs/100000, 1 );
else if ( nMffcs < 10000000 )
Vec_IntAddToEntry( vMffcs, 60 + nMffcs/1000000, 1 );
}
printf( "The distribution of fanins, fanouts. and MFFCs in the network:\n" );
printf( " Number Nodes with fanin Nodes with fanout Nodes with MFFC\n" );
for ( k = 0; k < nSizeMax; k++ )
{
if ( vFanins->pArray[k] == 0 && vFanouts->pArray[k] == 0 && vMffcs->pArray[k] == 0 )
continue;
if ( k < 10 )
printf( "%15d : ", k );
else
{
sprintf( Buffer, "%d - %d", (int)pow((double)10, k/10) * (k%10), (int)pow((double)10, k/10) * (k%10+1) - 1 );
printf( "%15s : ", Buffer );
}
if ( vFanins->pArray[k] == 0 )
printf( " " );
else
printf( "%11d ", vFanins->pArray[k] );
printf( " " );
if ( vFanouts->pArray[k] == 0 )
printf( " " );
else
printf( "%12d ", vFanouts->pArray[k] );
printf( " " );
if ( vMffcs->pArray[k] == 0 )
printf( " " );
else
printf( " %12d ", vMffcs->pArray[k] );
printf( "\n" );
}
Vec_IntFree( vFanins );
Vec_IntFree( vFanouts );
Vec_IntFree( vMffcs );
printf( "Fanins: Max = %d. Ave = %.2f. Fanouts: Max = %d. Ave = %.2f. MFFCs: Max = %d. Ave = %.2f.\n",
nFaninsMax, 1.0*nFaninsAll /Cof_ManNodeNum(p),
nFanoutsMax, 1.0*nFanoutsAll/Cof_ManNodeNum(p),
nMffcsMax, 1.0*nMffcsAll /nMffcNodes );
}
/**Function*************************************************************
Synopsis [Returns sorted array of node handles with largest fanout.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_ManPrintFanio( Gia_Man_t * pGia, int nNodes )
{
Cof_Man_t * p;
abctime clk = Abc_Clock();
p = Cof_ManCreateLogicSimple( pGia );
p->nLevels = 1 + Gia_ManLevelNum( pGia );
p->pLevels = ABC_CALLOC( int, p->nLevels );
Cof_ManPrintFanio( p );
if ( nNodes > 0 )
{
Cof_ManResetTravId( p );
Gia_ManHashStart( pGia );
Cof_ManPrintHighFanout( p, nNodes );
Gia_ManHashStop( pGia );
ABC_PRMn( "Memory for logic network", 4*p->nObjData );
ABC_PRT( "Time", Abc_Clock() - clk );
}
Cof_ManStop( p );
}
/**Function*************************************************************
Synopsis [Duplicates AIG in the DFS order while putting CIs first.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Gia_Man_t * Gia_ManDupCofInt( Gia_Man_t * p, int iVar )
{
Gia_Man_t * pNew;
Gia_Obj_t * pObj, * pPivot;
int i, iCofVar = -1;
if ( !(iVar > 0 && iVar < Gia_ManObjNum(p)) )
{
printf( "Gia_ManDupCof(): Variable %d is out of range (%d; %d).\n", iVar, 0, Gia_ManObjNum(p) );
return NULL;
}
// find the cofactoring variable
pPivot = Gia_ManObj( p, iVar );
if ( !Gia_ObjIsCand(pPivot) )
{
printf( "Gia_ManDupCof(): Variable %d should be a CI or an AND node.\n", iVar );
return NULL;
}
pNew = Gia_ManStart( Gia_ManObjNum(p) );
pNew->pName = Abc_UtilStrsav( p->pName );
pNew->pSpec = Abc_UtilStrsav( p->pSpec );
Gia_ManHashAlloc( pNew );
Gia_ManFillValue( p );
Gia_ManConst0(p)->Value = 0;
// compute negative cofactor
Gia_ManForEachCi( p, pObj, i )
{
pObj->Value = Gia_ManAppendCi(pNew);
if ( pObj == pPivot )
{
iCofVar = pObj->Value;
pObj->Value = Abc_Var2Lit( 0, 0 );
}
}
Gia_ManForEachAnd( p, pObj, i )
{
pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
if ( pObj == pPivot )
{
iCofVar = pObj->Value;
pObj->Value = Abc_Var2Lit( 0, 0 );
}
}
Gia_ManForEachCo( p, pObj, i )
pObj->Value = Gia_ObjFanin0Copy(pObj);
// compute the positive cofactor
Gia_ManForEachCi( p, pObj, i )
{
pObj->Value = Abc_Var2Lit( Gia_ObjId(pNew, Gia_ManCi(pNew, i)), 0 );
if ( pObj == pPivot )
pObj->Value = Abc_Var2Lit( 0, 1 );
}
Gia_ManForEachAnd( p, pObj, i )
{
pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
if ( pObj == pPivot )
pObj->Value = Abc_Var2Lit( 0, 1 );
}
// create MUXes
assert( iCofVar > 0 );
Gia_ManForEachCo( p, pObj, i )
{
if ( pObj->Value == (unsigned)Gia_ObjFanin0Copy(pObj) )
pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
else
pObj->Value = Gia_ManAppendCo( pNew, Gia_ManHashMux(pNew, iCofVar, Gia_ObjFanin0Copy(pObj), pObj->Value) );
}
Gia_ManHashStop( pNew );
Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) );
return pNew;
}
/**Function*************************************************************
Synopsis [Duplicates AIG in the DFS order while putting CIs first.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Gia_Man_t * Gia_ManDupCof( Gia_Man_t * p, int iVar )
{
Gia_Man_t * pNew, * pTemp;
pNew = Gia_ManDupCofInt( p, iVar );
pNew = Gia_ManCleanup( pTemp = pNew );
Gia_ManStop( pTemp );
return pNew;
}
/**Function*************************************************************
Synopsis [Determines variables whose fanout count is higher than this.]
Description [Variables are returned in a reverse topological order.]
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Int_t * Gia_ManCofVars( Gia_Man_t * p, int nFanLim )
{
Vec_Int_t * vVars;
Gia_Obj_t * pObj;
int i;
ABC_FREE( p->pRefs );
Gia_ManCreateRefs( p );
vVars = Vec_IntAlloc( 100 );
Gia_ManForEachObj( p, pObj, i )
if ( Gia_ObjIsCand(pObj) && Gia_ObjRefNum(p, pObj) >= nFanLim )
Vec_IntPush( vVars, i );
ABC_FREE( p->pRefs );
return vVars;
}
/**Function*************************************************************
Synopsis [Transfers attributes from the original one to the final one.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Int_t * Gia_ManTransfer( Gia_Man_t * pAig, Gia_Man_t * pCof, Gia_Man_t * pNew, Vec_Int_t * vSigs )
{
Vec_Int_t * vSigsNew;
Gia_Obj_t * pObj, * pObjF;
int i;
vSigsNew = Vec_IntAlloc( 100 );
Gia_ManForEachObjVec( vSigs, pAig, pObj, i )
{
assert( Gia_ObjIsCand(pObj) );
pObjF = Gia_ManObj( pCof, Abc_Lit2Var(pObj->Value) );
if ( pObjF->Value && ~pObjF->Value )
Vec_IntPushUnique( vSigsNew, Abc_Lit2Var(pObjF->Value) );
}
return vSigsNew;
}
/**Function*************************************************************
Synopsis [Cofactors selected variables (should be in reverse topo order).]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Gia_Man_t * Gia_ManDupCofAllInt( Gia_Man_t * p, Vec_Int_t * vSigs, int fVerbose )
{
Vec_Int_t * vSigsNew, * vTemp;
Gia_Man_t * pAig, * pCof, * pNew;
int iVar;
if ( fVerbose )
{
printf( "Cofactoring %d signals.\n", Vec_IntSize(vSigs) );
Gia_ManPrintStats( p, NULL );
}
if ( Vec_IntSize( vSigs ) > 200 )
{
printf( "Too many signals to cofactor.\n" );
return NULL;
}
pAig = Gia_ManDup( p );
vSigsNew = Vec_IntDup( vSigs );
while ( Vec_IntSize(vSigsNew) > 0 )
{
Vec_IntSort( vSigsNew, 0 );
iVar = Vec_IntPop( vSigsNew );
// Gia_ManCreateRefs( pAig );
// printf( "ref count = %d\n", Gia_ObjRefNum( pAig, Gia_ManObj(pAig, iVar) ) );
// ABC_FREE( pAig->pRefs );
pCof = Gia_ManDupCofInt( pAig, iVar );
pNew = Gia_ManCleanup( pCof );
vSigsNew = Gia_ManTransfer( pAig, pCof, pNew, vTemp = vSigsNew );
Vec_IntFree( vTemp );
Gia_ManStop( pAig );
Gia_ManStop( pCof );
pAig = pNew;
if ( fVerbose )
printf( "Cofactored variable %d.\n", iVar );
if ( fVerbose )
Gia_ManPrintStats( pAig, NULL );
}
Vec_IntFree( vSigsNew );
return pAig;
}
/**Function*************************************************************
Synopsis [Cofactors all variables whose fanout is higher than this.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Gia_Man_t * Gia_ManDupCofAll( Gia_Man_t * p, int nFanLim, int fVerbose )
{
Gia_Man_t * pNew;
Vec_Int_t * vSigs = Gia_ManCofVars( p, nFanLim );
pNew = Gia_ManDupCofAllInt( p, vSigs, fVerbose );
Vec_IntFree( vSigs );
return pNew;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END