blob: 0b3003a82ea599e363b7ea34ed817ea988bc8775 [file] [log] [blame]
/**CFile****************************************************************
FileName [gia.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Scalable AIG package.]
Synopsis []
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: gia.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
#include "gia.h"
ABC_NAMESPACE_IMPL_START
/*
The code is based on the paper by F. A. Aloul, I. L. Markov, and K. A. Sakallah.
"FORCE: A Fast and Easy-To-Implement Variable-Ordering Heuristic", Proc. GLSVLSI�03.
http://www.eecs.umich.edu/~imarkov/pubs/conf/glsvlsi03-force.pdf
*/
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
typedef struct Frc_Obj_t_ Frc_Obj_t;
struct Frc_Obj_t_
{
unsigned fCi : 1; // terminal node CI
unsigned fCo : 1; // terminal node CO
unsigned fMark0 : 1; // first user-controlled mark
unsigned fMark1 : 1; // second user-controlled mark
unsigned nFanins : 28; // the number of fanins
unsigned nFanouts; // the number of fanouts
unsigned iFanout; // the current number of fanouts
int hHandle; // the handle of the node
int pPlace; // the placement of each node
union {
float fEdgeCenter; // center-of-gravity of the edge
unsigned iFanin;
};
int Fanios[0]; // the array of fanins/fanouts
};
typedef struct Frc_Man_t_ Frc_Man_t;
struct Frc_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 nRegs; // the number of registers
int * pObjData; // the array containing data for objects
int nObjData; // the size of array to store the logic network
int fVerbose; // verbose output flag
int nCutCur; // current cut
int nCutMax; // max cut seen
};
static inline int Frc_ManRegNum( Frc_Man_t * p ) { return p->nRegs; }
static inline int Frc_ManCiNum( Frc_Man_t * p ) { return Vec_IntSize(p->vCis); }
static inline int Frc_ManCoNum( Frc_Man_t * p ) { return Vec_IntSize(p->vCos); }
static inline int Frc_ManPiNum( Frc_Man_t * p ) { return Vec_IntSize(p->vCis) - p->nRegs; }
static inline int Frc_ManPoNum( Frc_Man_t * p ) { return Vec_IntSize(p->vCos) - p->nRegs; }
static inline int Frc_ManObjNum( Frc_Man_t * p ) { return p->nObjs; }
static inline int Frc_ManNodeNum( Frc_Man_t * p ) { return p->nObjs - Vec_IntSize(p->vCis) - Vec_IntSize(p->vCos); }
static inline Frc_Obj_t * Frc_ManObj( Frc_Man_t * p, int hHandle ) { return (Frc_Obj_t *)(p->pObjData + hHandle); }
static inline Frc_Obj_t * Frc_ManCi( Frc_Man_t * p, int i ) { return Frc_ManObj( p, Vec_IntEntry(p->vCis,i) ); }
static inline Frc_Obj_t * Frc_ManCo( Frc_Man_t * p, int i ) { return Frc_ManObj( p, Vec_IntEntry(p->vCos,i) ); }
static inline int Frc_ObjIsTerm( Frc_Obj_t * pObj ) { return pObj->fCi || pObj->fCo; }
static inline int Frc_ObjIsCi( Frc_Obj_t * pObj ) { return pObj->fCi; }
static inline int Frc_ObjIsCo( Frc_Obj_t * pObj ) { return pObj->fCo; }
static inline int Frc_ObjIsPi( Frc_Obj_t * pObj ) { return pObj->fCi && pObj->nFanins == 0; }
static inline int Frc_ObjIsPo( Frc_Obj_t * pObj ) { return pObj->fCo && pObj->nFanouts == 0; }
static inline int Frc_ObjIsNode( Frc_Obj_t * pObj ) { return!Frc_ObjIsTerm(pObj) && pObj->nFanins > 0; }
static inline int Frc_ObjIsConst0( Frc_Obj_t * pObj ) { return!Frc_ObjIsTerm(pObj) && pObj->nFanins == 0; }
static inline int Frc_ObjSize( Frc_Obj_t * pObj ) { return sizeof(Frc_Obj_t) / 4 + pObj->nFanins + pObj->nFanouts; }
static inline int Frc_ObjFaninNum( Frc_Obj_t * pObj ) { return pObj->nFanins; }
static inline int Frc_ObjFanoutNum( Frc_Obj_t * pObj ) { return pObj->nFanouts; }
static inline Frc_Obj_t * Frc_ObjFanin( Frc_Obj_t * pObj, int i ) { return (Frc_Obj_t *)(((int *)pObj) - pObj->Fanios[i]); }
static inline Frc_Obj_t * Frc_ObjFanout( Frc_Obj_t * pObj, int i ) { return (Frc_Obj_t *)(((int *)pObj) + pObj->Fanios[pObj->nFanins+i]); }
#define Frc_ManForEachObj( p, pObj, i ) \
for ( i = 0; (i < p->nObjData) && (pObj = Frc_ManObj(p,i)); i += Frc_ObjSize(pObj) )
#define Frc_ManForEachObjVec( vVec, p, pObj, i ) \
for ( i = 0; (i < Vec_IntSize(vVec)) && ((pObj) = Frc_ManObj(p, Vec_IntEntry(vVec,i))); i++ )
#define Frc_ManForEachNode( p, pObj, i ) \
for ( i = 0; (i < p->nObjData) && (pObj = Frc_ManObj(p,i)); i += Frc_ObjSize(pObj) ) if ( Frc_ObjIsTerm(pObj) ) {} else
#define Frc_ManForEachCi( p, pObj, i ) \
for ( i = 0; (i < Vec_IntSize(p->vCis)) && (pObj = Frc_ManObj(p,Vec_IntEntry(p->vCis,i))); i++ )
#define Frc_ManForEachCo( p, pObj, i ) \
for ( i = 0; (i < Vec_IntSize(p->vCos)) && (pObj = Frc_ManObj(p,Vec_IntEntry(p->vCos,i))); i++ )
#define Frc_ObjForEachFanin( pObj, pNext, i ) \
for ( i = 0; (i < (int)pObj->nFanins) && (pNext = Frc_ObjFanin(pObj,i)); i++ )
#define Frc_ObjForEachFaninReverse( pObj, pNext, i ) \
for ( i = (int)pObj->nFanins - 1; (i >= 0) && (pNext = Frc_ObjFanin(pObj,i)); i-- )
#define Frc_ObjForEachFanout( pObj, pNext, i ) \
for ( i = 0; (i < (int)pObj->nFanouts) && (pNext = Frc_ObjFanout(pObj,i)); i++ )
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Creates fanin/fanout pair.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Frc_ObjAddFanin( Frc_Obj_t * pObj, Frc_Obj_t * pFanin )
{
assert( pObj->iFanin < pObj->nFanins );
assert( pFanin->iFanout < pFanin->nFanouts );
pFanin->Fanios[pFanin->nFanins + pFanin->iFanout++] =
pObj->Fanios[pObj->iFanin++] = pObj->hHandle - pFanin->hHandle;
}
/**Function*************************************************************
Synopsis [Creates logic network isomorphic to the given AIG.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Frc_Man_t * Frc_ManStartSimple( Gia_Man_t * pGia )
{
Frc_Man_t * p;
Frc_Obj_t * pObjLog, * pFanLog;
Gia_Obj_t * pObj;//, * pObjRi, * pObjRo;
int i, nNodes, hHandle = 0;
// prepare the AIG
Gia_ManCreateRefs( pGia );
// create logic network
p = ABC_CALLOC( Frc_Man_t, 1 );
p->pGia = pGia;
p->nRegs = Gia_ManRegNum(pGia);
p->vCis = Vec_IntAlloc( Gia_ManCiNum(pGia) );
p->vCos = Vec_IntAlloc( Gia_ManCoNum(pGia) );
p->nObjData = (sizeof(Frc_Obj_t) / 4) * Gia_ManObjNum(pGia) + 2 * (2 * Gia_ManAndNum(pGia) + Gia_ManCoNum(pGia));
p->pObjData = ABC_CALLOC( int, p->nObjData );
// create constant node
Gia_ManConst0(pGia)->Value = hHandle;
pObjLog = Frc_ManObj( p, hHandle );
pObjLog->hHandle = hHandle;
pObjLog->nFanins = 0;
pObjLog->nFanouts = Gia_ObjRefNum( pGia, Gia_ManConst0(pGia) );
// count objects
hHandle += Frc_ObjSize( pObjLog );
nNodes = 1;
p->nObjs++;
// create the PIs
Gia_ManForEachCi( pGia, pObj, i )
{
// create PI object
pObj->Value = hHandle;
Vec_IntPush( p->vCis, hHandle );
pObjLog = Frc_ManObj( p, hHandle );
pObjLog->hHandle = hHandle;
pObjLog->nFanins = 0;
pObjLog->nFanouts = Gia_ObjRefNum( pGia, pObj );
pObjLog->fCi = 0;
// count objects
hHandle += Frc_ObjSize( pObjLog );
p->nObjs++;
}
// create internal nodes
Gia_ManForEachAnd( pGia, pObj, i )
{
assert( Gia_ObjRefNum( pGia, pObj ) > 0 );
// create node object
pObj->Value = hHandle;
pObjLog = Frc_ManObj( p, hHandle );
pObjLog->hHandle = hHandle;
pObjLog->nFanins = 2;
pObjLog->nFanouts = Gia_ObjRefNum( pGia, pObj );
// add fanins
pFanLog = Frc_ManObj( p, Gia_ObjValue(Gia_ObjFanin0(pObj)) );
Frc_ObjAddFanin( pObjLog, pFanLog );
pFanLog = Frc_ManObj( p, Gia_ObjValue(Gia_ObjFanin1(pObj)) );
Frc_ObjAddFanin( pObjLog, pFanLog );
// count objects
hHandle += Frc_ObjSize( pObjLog );
nNodes++;
p->nObjs++;
}
// create the POs
Gia_ManForEachCo( pGia, pObj, i )
{
// create PO object
pObj->Value = hHandle;
Vec_IntPush( p->vCos, hHandle );
pObjLog = Frc_ManObj( p, hHandle );
pObjLog->hHandle = hHandle;
pObjLog->nFanins = 1;
pObjLog->nFanouts = 0;
pObjLog->fCo = 1;
// add fanins
pFanLog = Frc_ManObj( p, Gia_ObjValue(Gia_ObjFanin0(pObj)) );
Frc_ObjAddFanin( pObjLog, pFanLog );
// count objects
hHandle += Frc_ObjSize( pObjLog );
p->nObjs++;
}
// connect registers
// Gia_ManForEachRiRo( pGia, pObjRi, pObjRo, i )
// Frc_ObjAddFanin( Frc_ManObj(p,Gia_ObjValue(pObjRo)), Frc_ManObj(p,Gia_ObjValue(pObjRi)) );
assert( nNodes == Frc_ManNodeNum(p) );
assert( hHandle == p->nObjData );
if ( hHandle != p->nObjData )
printf( "Frc_ManStartSimple(): Fatal error in internal representation.\n" );
// make sure the fanin/fanout counters are correct
Gia_ManForEachObj( pGia, pObj, i )
{
if ( !~Gia_ObjValue(pObj) )
continue;
pObjLog = Frc_ManObj( p, Gia_ObjValue(pObj) );
assert( pObjLog->nFanins == pObjLog->iFanin );
assert( pObjLog->nFanouts == pObjLog->iFanout );
pObjLog->iFanin = pObjLog->iFanout = 0;
}
ABC_FREE( pGia->pRefs );
return p;
}
/**Function*************************************************************
Synopsis [Collect the fanin IDs.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Frc_ManCollectSuper_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vSuper, Vec_Int_t * vVisit )
{
if ( pObj->fMark1 )
return;
pObj->fMark1 = 1;
Vec_IntPush( vVisit, Gia_ObjId(p, pObj) );
if ( pObj->fMark0 )
{
Vec_IntPush( vSuper, Gia_ObjId(p, pObj) );
return;
}
assert( Gia_ObjIsAnd(pObj) );
Frc_ManCollectSuper_rec( p, Gia_ObjFanin0(pObj), vSuper, vVisit );
Frc_ManCollectSuper_rec( p, Gia_ObjFanin1(pObj), vSuper, vVisit );
}
/**Function*************************************************************
Synopsis [Collect the fanin IDs.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Frc_ManCollectSuper( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vSuper, Vec_Int_t * vVisit )
{
int Entry, i;
Vec_IntClear( vSuper );
Vec_IntClear( vVisit );
assert( pObj->fMark0 == 1 );
pObj->fMark0 = 0;
Frc_ManCollectSuper_rec( p, pObj, vSuper, vVisit );
pObj->fMark0 = 1;
Vec_IntForEachEntry( vVisit, Entry, i )
Gia_ManObj(p, Entry)->fMark1 = 0;
}
/**Function*************************************************************
Synopsis [Assigns references while removing the MUX/XOR ones.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Frc_ManCreateRefsSpecial( Gia_Man_t * p )
{
Gia_Obj_t * pObj, * pFan0, * pFan1;
Gia_Obj_t * pObjC, * pObjD0, * pObjD1;
int i;
assert( p->pRefs == NULL );
Gia_ManCleanMark0( p );
Gia_ManCreateRefs( p );
Gia_ManForEachAnd( p, pObj, i )
{
assert( pObj->fMark0 == 0 );
pFan0 = Gia_ObjFanin0(pObj);
pFan1 = Gia_ObjFanin1(pObj);
// skip nodes whose fanins are PIs or are already marked
if ( Gia_ObjIsCi(pFan0) || pFan0->fMark0 ||
Gia_ObjIsCi(pFan1) || pFan1->fMark0 )
continue;
// skip nodes that are not MUX type
if ( !Gia_ObjIsMuxType(pObj) )
continue;
// the node is MUX type, mark it and its fanins
pObj->fMark0 = 1;
pFan0->fMark0 = 1;
pFan1->fMark0 = 1;
// deref the control
pObjC = Gia_ObjRecognizeMux( pObj, &pObjD1, &pObjD0 );
Gia_ObjRefDec( p, Gia_Regular(pObjC) );
if ( Gia_Regular(pObjD0) == Gia_Regular(pObjD1) )
Gia_ObjRefDec( p, Gia_Regular(pObjD0) );
}
Gia_ManForEachAnd( p, pObj, i )
assert( Gia_ObjRefNum(p, pObj) > 0 );
Gia_ManCleanMark0( p );
}
/**Function*************************************************************
Synopsis [Assigns references while removing the MUX/XOR ones.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Frc_ManTransformRefs( Gia_Man_t * p, int * pnObjs, int * pnFanios )
{
Vec_Int_t * vSuper, * vVisit;
Gia_Obj_t * pObj, * pFanin;
int i, k, Counter;
assert( p->pRefs != NULL );
// mark nodes to be used in the logic network
Gia_ManCleanMark0( p );
Gia_ManConst0(p)->fMark0 = 1;
// mark the inputs
Gia_ManForEachCi( p, pObj, i )
pObj->fMark0 = 1;
// mark those nodes that have ref count more than 1
Gia_ManForEachAnd( p, pObj, i )
pObj->fMark0 = (Gia_ObjRefNum(p, pObj) > 1);
// mark the output drivers
Gia_ManForEachCoDriver( p, pObj, i )
pObj->fMark0 = 1;
// count the number of nodes
Counter = 0;
Gia_ManForEachObj( p, pObj, i )
Counter += pObj->fMark0;
*pnObjs = Counter + Gia_ManCoNum(p);
// reset the references
ABC_FREE( p->pRefs );
p->pRefs = ABC_CALLOC( int, Gia_ManObjNum(p) );
// reference from internal nodes
Counter = 0;
vSuper = Vec_IntAlloc( 100 );
vVisit = Vec_IntAlloc( 100 );
Gia_ManCleanMark1( p );
Gia_ManForEachAnd( p, pObj, i )
{
if ( pObj->fMark0 == 0 )
continue;
Frc_ManCollectSuper( p, pObj, vSuper, vVisit );
Gia_ManForEachObjVec( vSuper, p, pFanin, k )
{
assert( pFanin->fMark0 );
Gia_ObjRefInc( p, pFanin );
}
Counter += Vec_IntSize( vSuper );
}
Gia_ManCheckMark1( p );
Vec_IntFree( vSuper );
Vec_IntFree( vVisit );
// reference from outputs
Gia_ManForEachCoDriver( p, pObj, i )
{
assert( pObj->fMark0 );
Gia_ObjRefInc( p, pObj );
}
*pnFanios = Counter + Gia_ManCoNum(p);
}
/**Function*************************************************************
Synopsis [Creates logic network isomorphic to the given AIG.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Frc_Man_t * Frc_ManStart( Gia_Man_t * pGia )
{
Frc_Man_t * p;
Frc_Obj_t * pObjLog, * pFanLog;
Gia_Obj_t * pObj, * pFanin;//, * pObjRi, * pObjRo;
Vec_Int_t * vSuper, * vVisit;
int nObjs, nFanios, nNodes = 0;
int i, k, hHandle = 0;
// prepare the AIG
// Gia_ManCreateRefs( pGia );
Frc_ManCreateRefsSpecial( pGia );
Frc_ManTransformRefs( pGia, &nObjs, &nFanios );
Gia_ManFillValue( pGia );
// create logic network
p = ABC_CALLOC( Frc_Man_t, 1 );
p->pGia = pGia;
p->nRegs = Gia_ManRegNum(pGia);
p->vCis = Vec_IntAlloc( Gia_ManCiNum(pGia) );
p->vCos = Vec_IntAlloc( Gia_ManCoNum(pGia) );
p->nObjData = (sizeof(Frc_Obj_t) / 4) * nObjs + 2 * nFanios;
p->pObjData = ABC_CALLOC( int, p->nObjData );
// create constant node
Gia_ManConst0(pGia)->Value = hHandle;
pObjLog = Frc_ManObj( p, hHandle );
pObjLog->hHandle = hHandle;
pObjLog->nFanins = 0;
pObjLog->nFanouts = Gia_ObjRefNum( pGia, Gia_ManConst0(pGia) );
// count objects
hHandle += Frc_ObjSize( pObjLog );
nNodes++;
p->nObjs++;
// create the PIs
Gia_ManForEachCi( pGia, pObj, i )
{
// create PI object
pObj->Value = hHandle;
Vec_IntPush( p->vCis, hHandle );
pObjLog = Frc_ManObj( p, hHandle );
pObjLog->hHandle = hHandle;
pObjLog->nFanins = 0;
pObjLog->nFanouts = Gia_ObjRefNum( pGia, pObj );
pObjLog->fCi = 1;
// count objects
hHandle += Frc_ObjSize( pObjLog );
p->nObjs++;
}
// create internal nodes
vSuper = Vec_IntAlloc( 100 );
vVisit = Vec_IntAlloc( 100 );
Gia_ManForEachAnd( pGia, pObj, i )
{
if ( pObj->fMark0 == 0 )
{
assert( Gia_ObjRefNum( pGia, pObj ) == 0 );
continue;
}
assert( Gia_ObjRefNum( pGia, pObj ) > 0 );
Frc_ManCollectSuper( pGia, pObj, vSuper, vVisit );
// create node object
pObj->Value = hHandle;
pObjLog = Frc_ManObj( p, hHandle );
pObjLog->hHandle = hHandle;
pObjLog->nFanins = Vec_IntSize( vSuper );
pObjLog->nFanouts = Gia_ObjRefNum( pGia, pObj );
// add fanins
Gia_ManForEachObjVec( vSuper, pGia, pFanin, k )
{
pFanLog = Frc_ManObj( p, Gia_ObjValue(pFanin) );
Frc_ObjAddFanin( pObjLog, pFanLog );
}
// count objects
hHandle += Frc_ObjSize( pObjLog );
nNodes++;
p->nObjs++;
}
Vec_IntFree( vSuper );
Vec_IntFree( vVisit );
// create the POs
Gia_ManForEachCo( pGia, pObj, i )
{
// create PO object
pObj->Value = hHandle;
Vec_IntPush( p->vCos, hHandle );
pObjLog = Frc_ManObj( p, hHandle );
pObjLog->hHandle = hHandle;
pObjLog->nFanins = 1;
pObjLog->nFanouts = 0;
pObjLog->fCo = 1;
// add fanins
pFanLog = Frc_ManObj( p, Gia_ObjValue(Gia_ObjFanin0(pObj)) );
Frc_ObjAddFanin( pObjLog, pFanLog );
// count objects
hHandle += Frc_ObjSize( pObjLog );
p->nObjs++;
}
// connect registers
// Gia_ManForEachRiRo( pGia, pObjRi, pObjRo, i )
// Frc_ObjAddFanin( Frc_ManObj(p,Gia_ObjValue(pObjRo)), Frc_ManObj(p,Gia_ObjValue(pObjRi)) );
Gia_ManCleanMark0( pGia );
assert( nNodes == Frc_ManNodeNum(p) );
assert( nObjs == p->nObjs );
assert( hHandle == p->nObjData );
if ( hHandle != p->nObjData )
printf( "Frc_ManStart(): Fatal error in internal representation.\n" );
// make sure the fanin/fanout counters are correct
Gia_ManForEachObj( pGia, pObj, i )
{
if ( !~Gia_ObjValue(pObj) )
continue;
pObjLog = Frc_ManObj( p, Gia_ObjValue(pObj) );
assert( pObjLog->nFanins == pObjLog->iFanin );
assert( pObjLog->nFanouts == pObjLog->iFanout );
pObjLog->iFanin = pObjLog->iFanout = 0;
}
ABC_FREE( pGia->pRefs );
return p;
}
/**Function*************************************************************
Synopsis [Creates logic network isomorphic to the given AIG.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Frc_ManPrintStats( Frc_Man_t * p )
{
// if ( p->pName )
// printf( "%8s : ", p->pName );
printf( "i/o =%7d/%7d ", Frc_ManPiNum(p), Frc_ManPoNum(p) );
if ( Frc_ManRegNum(p) )
printf( "ff =%7d ", Frc_ManRegNum(p) );
printf( "node =%8d ", Frc_ManNodeNum(p) );
printf( "obj =%8d ", Frc_ManObjNum(p) );
// printf( "lev =%5d ", Frc_ManLevelNum(p) );
// printf( "cut =%5d ", Frc_ManCrossCut(p) );
printf( "mem =%5.2f MB", 4.0*p->nObjData/(1<<20) );
// printf( "obj =%5d ", Frc_ManObjNum(p) );
printf( "\n" );
}
/**Function*************************************************************
Synopsis [Creates logic network isomorphic to the given AIG.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Frc_ManStop( Frc_Man_t * p )
{
Vec_IntFree( p->vCis );
Vec_IntFree( p->vCos );
ABC_FREE( p->pObjData );
ABC_FREE( p );
}
/**Function*************************************************************
Synopsis [Computes cross cut size for the given order of POs.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Frc_ManCrossCut_rec( Frc_Man_t * p, Frc_Obj_t * pObj )
{
assert( pObj->iFanout > 0 );
if ( pObj->iFanout-- == pObj->nFanouts )
{
Frc_Obj_t * pFanin;
int i;
p->nCutCur++;
p->nCutMax = Abc_MaxInt( p->nCutMax, p->nCutCur );
if ( !Frc_ObjIsCi(pObj) )
Frc_ObjForEachFanin( pObj, pFanin, i )
p->nCutCur -= Frc_ManCrossCut_rec( p, pFanin );
}
return pObj->iFanout == 0;
}
/**Function*************************************************************
Synopsis [Computes cross cut size for the given order of POs.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Frc_ManCrossCut2_rec( Frc_Man_t * p, Frc_Obj_t * pObj )
{
assert( pObj->iFanout > 0 );
if ( pObj->iFanout-- == pObj->nFanouts )
{
Frc_Obj_t * pFanin;
int i;
p->nCutCur++;
p->nCutMax = Abc_MaxInt( p->nCutMax, p->nCutCur );
if ( !Frc_ObjIsCi(pObj) )
Frc_ObjForEachFaninReverse( pObj, pFanin, i )
p->nCutCur -= Frc_ManCrossCut2_rec( p, pFanin );
}
return pObj->iFanout == 0;
}
/**Function*************************************************************
Synopsis [Computes cross cut size for the given order of POs.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Frc_ManCrossCut( Frc_Man_t * p, Vec_Int_t * vOrder, int fReverse )
{
Frc_Obj_t * pObj;
int i;
assert( Vec_IntSize(vOrder) == Frc_ManCoNum(p) );
p->nCutCur = 0;
p->nCutMax = 0;
Frc_ManForEachObj( p, pObj, i )
pObj->iFanout = pObj->nFanouts;
Frc_ManForEachObjVec( vOrder, p, pObj, i )
{
assert( Frc_ObjIsCo(pObj) );
if ( fReverse )
p->nCutCur -= Frc_ManCrossCut2_rec( p, Frc_ObjFanin(pObj,0) );
else
p->nCutCur -= Frc_ManCrossCut_rec( p, Frc_ObjFanin(pObj,0) );
}
assert( p->nCutCur == 0 );
// Frc_ManForEachObj( p, pObj, i )
// assert( pObj->iFanout == 0 );
return p->nCutMax;
}
/**Function*************************************************************
Synopsis [Collects CO handles.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Int_t * Frc_ManCollectCos( Frc_Man_t * p )
{
Vec_Int_t * vCoOrder;
Frc_Obj_t * pObj;
int i;
vCoOrder = Vec_IntAlloc( Frc_ManCoNum(p) );
Frc_ManForEachCo( p, pObj, i )
Vec_IntPush( vCoOrder, pObj->hHandle );
return vCoOrder;
}
/**Function*************************************************************
Synopsis [Computes cross cut size for the given order of POs.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Frc_ManCrossCutTest( Frc_Man_t * p, Vec_Int_t * vOrderInit )
{
Vec_Int_t * vOrder;
// abctime clk = Abc_Clock();
vOrder = vOrderInit? vOrderInit : Frc_ManCollectCos( p );
printf( "CrossCut = %6d\n", Frc_ManCrossCut( p, vOrder, 0 ) );
printf( "CrossCut = %6d\n", Frc_ManCrossCut( p, vOrder, 1 ) );
Vec_IntReverseOrder( vOrder );
printf( "CrossCut = %6d\n", Frc_ManCrossCut( p, vOrder, 0 ) );
printf( "CrossCut = %6d\n", Frc_ManCrossCut( p, vOrder, 1 ) );
Vec_IntReverseOrder( vOrder );
if ( vOrder != vOrderInit )
Vec_IntFree( vOrder );
// ABC_PRT( "Time", Abc_Clock() - clk );
}
/**Function*************************************************************
Synopsis [Generates random placement.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Frc_ManPlaceRandom( Frc_Man_t * p )
{
Frc_Obj_t * pThis;
int * pPlacement;
int i, h, Temp, iNext, Counter;
pPlacement = ABC_ALLOC( int, p->nObjs );
for ( i = 0; i < p->nObjs; i++ )
pPlacement[i] = i;
for ( i = 0; i < p->nObjs; i++ )
{
iNext = Gia_ManRandom( 0 ) % p->nObjs;
Temp = pPlacement[i];
pPlacement[i] = pPlacement[iNext];
pPlacement[iNext] = Temp;
}
Counter = 0;
Frc_ManForEachObj( p, pThis, h )
pThis->pPlace = pPlacement[Counter++];
ABC_FREE( pPlacement );
}
/**Function*************************************************************
Synopsis [Shuffles array of random integers.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Frc_ManArrayShuffle( Vec_Int_t * vArray )
{
int i, iNext, Temp;
for ( i = 0; i < vArray->nSize; i++ )
{
iNext = Gia_ManRandom( 0 ) % vArray->nSize;
Temp = vArray->pArray[i];
vArray->pArray[i] = vArray->pArray[iNext];
vArray->pArray[iNext] = Temp;
}
}
/**Function*************************************************************
Synopsis [Computes cross cut size for the given order of POs.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Frc_ManPlaceDfs_rec( Frc_Man_t * p, Frc_Obj_t * pObj, int * piPlace )
{
assert( pObj->iFanout > 0 );
if ( pObj->iFanout-- == pObj->nFanouts )
{
Frc_Obj_t * pFanin;
int i;
if ( !Frc_ObjIsCi(pObj) )
Frc_ObjForEachFanin( pObj, pFanin, i )
Frc_ManPlaceDfs_rec( p, pFanin, piPlace );
pObj->pPlace = (*piPlace)++;
}
}
/**Function*************************************************************
Synopsis [Generates DFS placement.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Frc_ManPlaceDfs( Frc_Man_t * p, Vec_Int_t * vCoOrder )
{
Frc_Obj_t * pObj;
int i, nPlaces = 0;
Frc_ManForEachObj( p, pObj, i )
{
pObj->iFanout = pObj->nFanouts;
if ( pObj->nFanouts == 0 && !Frc_ObjIsCo(pObj) )
pObj->pPlace = nPlaces++;
}
Frc_ManForEachObjVec( vCoOrder, p, pObj, i )
{
assert( Frc_ObjIsCo(pObj) );
Frc_ManPlaceDfs_rec( p, Frc_ObjFanin(pObj,0), &nPlaces );
pObj->pPlace = nPlaces++;
}
assert( nPlaces == p->nObjs );
}
/**Function*************************************************************
Synopsis [Generates DFS placement by trying both orders.]
Description [Returns the cross cut size of the best order. ]
SideEffects []
SeeAlso []
***********************************************************************/
int Frc_ManPlaceDfsBoth( Frc_Man_t * p, Vec_Int_t * vCoOrder, int * piCutSize2 )
{
int nCutStart1, nCutStart2;
nCutStart1 = Frc_ManCrossCut( p, vCoOrder, 0 );
Vec_IntReverseOrder( vCoOrder );
nCutStart2 = Frc_ManCrossCut( p, vCoOrder, 0 );
if ( nCutStart1 <= nCutStart2 )
{
Vec_IntReverseOrder( vCoOrder ); // undo
Frc_ManPlaceDfs( p, vCoOrder );
*piCutSize2 = nCutStart2;
return nCutStart1;
}
else
{
Frc_ManPlaceDfs( p, vCoOrder );
Vec_IntReverseOrder( vCoOrder ); // undo
*piCutSize2 = nCutStart1;
return nCutStart2;
}
}
/**Function*************************************************************
Synopsis [Performs iterative refinement of the given placement.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Frc_ManPlacementRefine( Frc_Man_t * p, int nIters, int fVerbose )
{
int fRandomize = 0;
Vec_Int_t * vCoOrder;
Frc_Obj_t * pThis, * pNext;
double CostThis, CostPrev;
float * pVertX, VertX;
int * pPermX, * pHandles;
int k, h, Iter, iMinX, iMaxX, Counter, nCutStart, nCutCur, nCutCur2, nCutPrev;
abctime clk = Abc_Clock(), clk2, clk2Total = 0;
// create starting one-dimensional placement
vCoOrder = Frc_ManCollectCos( p );
if ( fRandomize )
Frc_ManArrayShuffle( vCoOrder );
nCutStart = Frc_ManPlaceDfsBoth( p, vCoOrder, &nCutCur2 );
// refine placement
CostPrev = 0.0;
nCutPrev = nCutStart;
pHandles = ABC_ALLOC( int, p->nObjs );
pVertX = ABC_ALLOC( float, p->nObjs );
for ( Iter = 0; Iter < nIters; Iter++ )
{
// compute centers of hyperedges
CostThis = 0.0;
Frc_ManForEachObj( p, pThis, h )
{
iMinX = iMaxX = pThis->pPlace;
Frc_ObjForEachFanout( pThis, pNext, k )
{
iMinX = Abc_MinInt( iMinX, pNext->pPlace );
iMaxX = Abc_MaxInt( iMaxX, pNext->pPlace );
}
pThis->fEdgeCenter = 0.5 * (iMaxX + iMinX);
CostThis += (iMaxX - iMinX);
}
// compute new centers of objects
Counter = 0;
Frc_ManForEachObj( p, pThis, h )
{
VertX = pThis->fEdgeCenter;
Frc_ObjForEachFanin( pThis, pNext, k )
VertX += pNext->fEdgeCenter;
pVertX[Counter] = VertX / (Frc_ObjFaninNum(pThis) + 1);
pHandles[Counter++] = h;
}
assert( Counter == Frc_ManObjNum(p) );
// sort these numbers
clk2 = Abc_Clock();
pPermX = Gia_SortFloats( pVertX, pHandles, p->nObjs );
clk2Total += Abc_Clock() - clk2;
assert( pPermX == pHandles );
Vec_IntClear( vCoOrder );
for ( k = 0; k < p->nObjs; k++ )
{
pThis = Frc_ManObj( p, pPermX[k] );
pThis->pPlace = k;
if ( Frc_ObjIsCo(pThis) )
Vec_IntPush( vCoOrder, pThis->hHandle );
}
/*
printf( "Ordering of PIs:\n" );
Frc_ManForEachCi( p, pThis, k )
printf( "PI number = %7d. Object handle = %7d, Coordinate = %7d.\n",
k, pThis->hHandle, pThis->pPlace );
*/
nCutCur = Frc_ManPlaceDfsBoth( p, vCoOrder, &nCutCur2 );
// evaluate cost
if ( fVerbose )
{
printf( "%2d : Span = %e ", Iter+1, CostThis );
printf( "Cut = %6d (%5.2f %%) CutR = %6d ", nCutCur, 100.0*(nCutStart-nCutCur)/nCutStart, nCutCur2 );
ABC_PRTn( "Total", Abc_Clock() - clk );
ABC_PRT( "Sort", clk2Total );
// Frc_ManCrossCutTest( p, vCoOrder );
}
// if ( 1.0 * nCutPrev / nCutCur < 1.001 )
// break;
nCutPrev = nCutCur;
}
ABC_FREE( pHandles );
ABC_FREE( pVertX );
Vec_IntFree( vCoOrder );
}
/**Function*************************************************************
Synopsis [Returns 1 if all fanouts are COsw.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Frc_ObjFanoutsAreCos( Frc_Obj_t * pThis )
{
Frc_Obj_t * pNext;
int i;
Frc_ObjForEachFanout( pThis, pNext, i )
if ( !Frc_ObjIsCo(pNext) )
return 0;
return 1;
}
/**Function*************************************************************
Synopsis [Computes the distances from the given set of objects.]
Description [Returns one of the most distant objects.]
SideEffects []
SeeAlso []
***********************************************************************/
void Frc_DumpGraphIntoFile( Frc_Man_t * p )
{
FILE * pFile;
Frc_Obj_t * pThis, * pNext;
int i, k, Counter = 0;
// assign numbers to CIs and internal nodes
Frc_ManForEachObj( p, pThis, i )
{
if ( i && ((Frc_ObjIsCi(pThis) && !Frc_ObjFanoutsAreCos(pThis)) || Frc_ObjIsNode(pThis)) )
pThis->iFanin = Counter++;
else
pThis->iFanin = ~0;
}
// assign numbers to all other nodes
pFile = fopen( "x\\large\\aig\\dg1.g", "w" );
Frc_ManForEachObj( p, pThis, i )
{
Frc_ObjForEachFanout( pThis, pNext, k )
{
if ( ~pThis->iFanin && ~pNext->iFanin )
fprintf( pFile, "%d %d\n", pThis->iFanin, pNext->iFanin );
}
}
fclose( pFile );
}
/**Function*************************************************************
Synopsis [Experiment with the FORCE algorithm.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void For_ManExperiment( Gia_Man_t * pGia, int nIters, int fClustered, int fVerbose )
{
Frc_Man_t * p;
Gia_ManRandom( 1 );
if ( fClustered )
p = Frc_ManStart( pGia );
else
p = Frc_ManStartSimple( pGia );
// Frc_DumpGraphIntoFile( p );
if ( fVerbose )
Frc_ManPrintStats( p );
// Frc_ManCrossCutTest( p, NULL );
Frc_ManPlacementRefine( p, nIters, fVerbose );
Frc_ManStop( p );
}
/**Function*************************************************************
Synopsis [Experiment with the FORCE algorithm.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void For_ManFileExperiment()
{
FILE * pFile;
int * pBuffer;
int i, Size, Exp = 25;
abctime clk = Abc_Clock();
int RetValue;
Size = (1 << Exp);
printf( "2^%d machine words (%d bytes).\n", Exp, (int)sizeof(int) * Size );
pBuffer = ABC_ALLOC( int, Size );
for ( i = 0; i < Size; i++ )
pBuffer[i] = i;
ABC_PRT( "Fillup", Abc_Clock() - clk );
clk = Abc_Clock();
pFile = fopen( "test.txt", "rb" );
RetValue = fread( pBuffer, 1, sizeof(int) * Size, pFile );
fclose( pFile );
ABC_PRT( "Read ", Abc_Clock() - clk );
clk = Abc_Clock();
pFile = fopen( "test.txt", "wb" );
fwrite( pBuffer, 1, sizeof(int) * Size, pFile );
fclose( pFile );
ABC_PRT( "Write ", Abc_Clock() - clk );
/*
2^25 machine words (134217728 bytes).
Fillup = 0.06 sec
Read = 0.08 sec
Write = 1.81 sec
*/
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END