blob: b20da8835e9b15cfaff2c2779855b065a7073d1d [file] [log] [blame]
/**CFile****************************************************************
FileName [giaIff.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Scalable AIG package.]
Synopsis [Hierarchical mapping of AIG with white boxes.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: giaIff.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
#include "gia.h"
#include "map/if/if.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
typedef struct Iff_Man_t_ Iff_Man_t;
struct Iff_Man_t_
{
Gia_Man_t * pGia; // mapped GIA
If_LibLut_t * pLib; // LUT library
int nLutSize; // LUT size
int nDegree; // degree
Vec_Flt_t * vTimes; // arrival times
Vec_Int_t * vMatch[4]; // matches
};
static inline float Iff_ObjTimeId( Iff_Man_t * p, int iObj ) { return Vec_FltEntry( p->vTimes, iObj ); }
static inline float Iff_ObjTime( Iff_Man_t * p, Gia_Obj_t * pObj ) { return Iff_ObjTimeId( p, Gia_ObjId(p->pGia, pObj) ); }
static inline void Iff_ObjSetTimeId( Iff_Man_t * p, int iObj, float Time ) { Vec_FltWriteEntry( p->vTimes, iObj, Time ); }
static inline void Iff_ObjSetTime( Iff_Man_t * p, Gia_Obj_t * pObj, float Time ) { Iff_ObjSetTimeId( p, Gia_ObjId(p->pGia, pObj), Time ); }
static inline int Iff_ObjMatchId( Iff_Man_t * p, int iObj, int Type ) { return Vec_IntEntry( p->vMatch[Type], iObj ); }
static inline int Iff_ObjMatch( Iff_Man_t * p, Gia_Obj_t * pObj, int Type ) { return Iff_ObjMatchId( p, Gia_ObjId(p->pGia, pObj), Type ); }
static inline void Iff_ObjSetMatchId( Iff_Man_t * p, int iObj, int Type, int Match ) { Vec_IntWriteEntry( p->vMatch[Type], iObj, Match ); }
static inline void Iff_ObjSetMatch( Iff_Man_t * p, Gia_Obj_t * pObj, int Type, int Match ) { Iff_ObjSetMatchId( p, Gia_ObjId(p->pGia, pObj), Type, Match );}
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Iff_Man_t * Gia_ManIffStart( Gia_Man_t * pGia )
{
Iff_Man_t * p = ABC_CALLOC( Iff_Man_t, 1 );
p->vTimes = Vec_FltStartFull( Gia_ManObjNum(pGia) );
p->vMatch[2] = Vec_IntStartFull( Gia_ManObjNum(pGia) );
p->vMatch[3] = Vec_IntStartFull( Gia_ManObjNum(pGia) );
return p;
}
void Gia_ManIffStop( Iff_Man_t * p )
{
Vec_FltFree( p->vTimes );
Vec_IntFree( p->vMatch[2] );
Vec_IntFree( p->vMatch[3] );
ABC_FREE( p );
}
/**Function*************************************************************
Synopsis [Count the number of unique fanins.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Gia_IffObjCount( Gia_Man_t * pGia, int iObj, int iFaninSkip2, int iFaninSkip3 )
{
int i, iFanin, Count = 0;
Gia_ManIncrementTravId( pGia );
Gia_LutForEachFanin( pGia, iObj, iFanin, i )
{
if ( iFanin == iFaninSkip2 || iFanin == iFaninSkip3 )
continue;
if ( Gia_ObjIsTravIdCurrentId( pGia, iFanin ) )
continue;
Gia_ObjSetTravIdCurrentId( pGia, iFanin );
Count++;
}
if ( iFaninSkip2 >= 0 )
{
Gia_LutForEachFanin( pGia, iFaninSkip2, iFanin, i )
{
if ( iFanin == iFaninSkip3 )
continue;
if ( Gia_ObjIsTravIdCurrentId( pGia, iFanin ) )
continue;
Gia_ObjSetTravIdCurrentId( pGia, iFanin );
Count++;
}
}
if ( iFaninSkip3 >= 0 )
{
Gia_LutForEachFanin( pGia, iFaninSkip3, iFanin, i )
{
if ( iFanin == iFaninSkip2 )
continue;
if ( Gia_ObjIsTravIdCurrentId( pGia, iFanin ) )
continue;
Gia_ObjSetTravIdCurrentId( pGia, iFanin );
Count++;
}
}
return Count;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
float Gia_IffObjTimeOne( Iff_Man_t * p, int iObj, int iFaninSkip2, int iFaninSkip3 )
{
int i, iFanin;
float DelayMax = -ABC_INFINITY;
Gia_LutForEachFanin( p->pGia, iObj, iFanin, i )
if ( iFanin != iFaninSkip2 && iFanin != iFaninSkip3 && DelayMax < Iff_ObjTimeId(p, iFanin) )
DelayMax = Iff_ObjTimeId(p, iFanin);
assert( i == Gia_ObjLutSize(p->pGia, iObj) );
if ( iFaninSkip2 == -1 )
return DelayMax;
Gia_LutForEachFanin( p->pGia, iFaninSkip2, iFanin, i )
if ( iFanin != iFaninSkip3 && DelayMax < Iff_ObjTimeId(p, iFanin) )
DelayMax = Iff_ObjTimeId(p, iFanin);
if ( iFaninSkip3 == -1 )
return DelayMax;
Gia_LutForEachFanin( p->pGia, iFaninSkip3, iFanin, i )
if ( iFanin != iFaninSkip2 && DelayMax < Iff_ObjTimeId(p, iFanin) )
DelayMax = Iff_ObjTimeId(p, iFanin);
assert( DelayMax >= 0 );
return DelayMax;
}
float Gia_IffObjTimeTwo( Iff_Man_t * p, int iObj, int * piFanin, float DelayMin )
{
int i, iFanin, nSize;
float This;
*piFanin = -1;
Gia_LutForEachFanin( p->pGia, iObj, iFanin, i )
{
if ( Gia_ObjIsCi(Gia_ManObj(p->pGia, iFanin)) )
continue;
This = Gia_IffObjTimeOne( p, iObj, iFanin, -1 );
nSize = Gia_IffObjCount( p->pGia, iObj, iFanin, -1 );
assert( nSize <= p->pLib->LutMax );
This += p->pLib->pLutDelays[nSize][0];
if ( DelayMin > This )
{
DelayMin = This;
*piFanin = iFanin;
}
}
return DelayMin;
}
float Gia_IffObjTimeThree( Iff_Man_t * p, int iObj, int * piFanin, int * piFanin2, float DelayMin )
{
int i, k, iFanin, iFanin2, nSize;
float This;
*piFanin = -1;
*piFanin2 = -1;
Gia_LutForEachFanin( p->pGia, iObj, iFanin, i )
Gia_LutForEachFanin( p->pGia, iObj, iFanin2, k )
{
if ( iFanin == iFanin2 )
continue;
if ( Gia_ObjIsCi(Gia_ManObj(p->pGia, iFanin)) )
continue;
if ( Gia_ObjIsCi(Gia_ManObj(p->pGia, iFanin2)) )
continue;
This = Gia_IffObjTimeOne( p, iObj, iFanin, iFanin2 );
nSize = Gia_IffObjCount( p->pGia, iObj, iFanin, iFanin2 );
assert( nSize <= p->pLib->LutMax );
This += p->pLib->pLutDelays[nSize][0];
if ( DelayMin > This )
{
DelayMin = This;
*piFanin = iFanin;
*piFanin2 = iFanin2;
}
}
return DelayMin;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Iff_Man_t * Gia_ManIffPerform( Gia_Man_t * pGia, If_LibLut_t * pLib, Tim_Man_t * pTime, int nLutSize, int nDegree )
{
Iff_Man_t * p;
Gia_Obj_t * pObj;
int iObj, iFanin, iFanin1, iFanin2;
int CountAll = 0, Count2 = 0, Count3 = 0;
float arrTime1, arrTime2, arrTime3, arrMax = -ABC_INFINITY;
assert( nDegree == 2 || nDegree == 3 );
// start the mapping manager and set its parameters
p = Gia_ManIffStart( pGia );
p->pGia = pGia;
p->pLib = pLib;
p->nLutSize = nLutSize;
p->nDegree = nDegree;
// compute arrival times of each node
Iff_ObjSetTimeId( p, 0, 0 );
Tim_ManIncrementTravId( pTime );
Gia_ManForEachObj1( pGia, pObj, iObj )
{
if ( Gia_ObjIsAnd(pObj) )
{
if ( !Gia_ObjIsLut(pGia, iObj) )
continue;
CountAll++;
// compute arrival times of LUT inputs
arrTime1 = Gia_IffObjTimeOne( p, iObj, -1, -1 );
arrTime1 += p->pLib->pLutDelays[Gia_ObjLutSize(pGia, iObj)][0];
// compute arrival times of LUT pairs
arrTime2 = Gia_IffObjTimeTwo( p, iObj, &iFanin, arrTime1 );
if ( nDegree == 2 )
{
// set arrival times
Iff_ObjSetTimeId( p, iObj, arrTime2 );
if ( arrTime2 < arrTime1 )
Iff_ObjSetMatchId( p, iObj, 2, iFanin ), Count2++;
}
else if ( nDegree == 3 )
{
// compute arrival times of LUT triples
arrTime3 = Gia_IffObjTimeThree( p, iObj, &iFanin1, &iFanin2, arrTime2 );
// set arrival times
Iff_ObjSetTimeId( p, iObj, arrTime3 );
if ( arrTime3 == arrTime1 )
continue;
if ( arrTime3 == arrTime2 )
Iff_ObjSetMatchId( p, iObj, 2, iFanin ), Count2++;
else
{
assert( arrTime3 < arrTime2 );
Iff_ObjSetMatchId( p, iObj, 2, iFanin1 );
Iff_ObjSetMatchId( p, iObj, 3, iFanin2 ), Count3++;
}
}
else assert( 0 );
}
else if ( Gia_ObjIsCi(pObj) )
{
arrTime1 = Tim_ManGetCiArrival( pTime, Gia_ObjCioId(pObj) );
Iff_ObjSetTime( p, pObj, arrTime1 );
}
else if ( Gia_ObjIsCo(pObj) )
{
arrTime1 = Iff_ObjTimeId( p, Gia_ObjFaninId0p(pGia, pObj) );
Tim_ManSetCoArrival( pTime, Gia_ObjCioId(pObj), arrTime1 );
Iff_ObjSetTime( p, pObj, arrTime1 );
arrMax = Abc_MaxFloat( arrMax, arrTime1 );
}
else assert( 0 );
}
printf( "Max delay = %.2f. Count1 = %d. Count2 = %d. Count3 = %d.\n",
arrMax, CountAll - Count2 - Count3, Count2, Count3 );
return p;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_ManIffSelect_rec( Iff_Man_t * p, int iObj, Vec_Int_t * vPacking )
{
int i, iFanin, iFaninSkip2, iFaninSkip3;
if ( Gia_ObjIsTravIdCurrentId( p->pGia, iObj ) )
return;
Gia_ObjSetTravIdCurrentId( p->pGia, iObj );
assert( Gia_ObjIsLut(p->pGia, iObj) );
iFaninSkip2 = Iff_ObjMatchId(p, iObj, 2);
iFaninSkip3 = Iff_ObjMatchId(p, iObj, 3);
if ( iFaninSkip2 == -1 )
{
assert( iFaninSkip3 == -1 );
Gia_LutForEachFanin( p->pGia, iObj, iFanin, i )
Gia_ManIffSelect_rec( p, iFanin, vPacking );
Vec_IntPush( vPacking, 1 );
Vec_IntPush( vPacking, iObj );
}
else if ( iFaninSkip3 == -1 )
{
assert( iFaninSkip2 > 0 );
Gia_LutForEachFanin( p->pGia, iObj, iFanin, i )
if ( iFanin != iFaninSkip2 )
Gia_ManIffSelect_rec( p, iFanin, vPacking );
Gia_LutForEachFanin( p->pGia, iFaninSkip2, iFanin, i )
Gia_ManIffSelect_rec( p, iFanin, vPacking );
Vec_IntPush( vPacking, 2 );
Vec_IntPush( vPacking, iFaninSkip2 );
Vec_IntPush( vPacking, iObj );
}
else
{
assert( iFaninSkip2 > 0 && iFaninSkip3 > 0 );
Gia_LutForEachFanin( p->pGia, iObj, iFanin, i )
if ( iFanin != iFaninSkip2 && iFanin != iFaninSkip3 )
Gia_ManIffSelect_rec( p, iFanin, vPacking );
Gia_LutForEachFanin( p->pGia, iFaninSkip2, iFanin, i )
if ( iFanin != iFaninSkip3 )
Gia_ManIffSelect_rec( p, iFanin, vPacking );
Gia_LutForEachFanin( p->pGia, iFaninSkip3, iFanin, i )
if ( iFanin != iFaninSkip2 )
Gia_ManIffSelect_rec( p, iFanin, vPacking );
Vec_IntPush( vPacking, 3 );
Vec_IntPush( vPacking, iFaninSkip2 );
Vec_IntPush( vPacking, iFaninSkip3 );
Vec_IntPush( vPacking, iObj );
}
Vec_IntAddToEntry( vPacking, 0, 1 );
}
Vec_Int_t * Gia_ManIffSelect( Iff_Man_t * p )
{
Vec_Int_t * vPacking;
Gia_Obj_t * pObj; int i;
vPacking = Vec_IntAlloc( Gia_ManObjNum(p->pGia) );
Vec_IntPush( vPacking, 0 );
// mark const0 and PIs
Gia_ManIncrementTravId( p->pGia );
Gia_ObjSetTravIdCurrentId( p->pGia, 0 );
Gia_ManForEachCi( p->pGia, pObj, i )
Gia_ObjSetTravIdCurrent( p->pGia, pObj );
// recursively collect internal nodes
Gia_ManForEachCo( p->pGia, pObj, i )
Gia_ManIffSelect_rec( p, Gia_ObjFaninId0p(p->pGia, pObj), vPacking );
return vPacking;
}
/**Function*************************************************************
Synopsis [This command performs hierarhical mapping.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_ManIffTest( Gia_Man_t * pGia, If_LibLut_t * pLib, int fVerbose )
{
Iff_Man_t * p;
Tim_Man_t * pTemp = NULL;
int nDegree = -1;
int nLutSize = Gia_ManLutSizeMax( pGia );
if ( nLutSize <= 4 )
{
nLutSize = 4;
if ( pLib->LutMax == 7 )
nDegree = 2;
else if ( pLib->LutMax == 10 )
nDegree = 3;
else
{ printf( "LUT library for packing 4-LUTs should have 7 or 10 inputs.\n" ); return; }
}
else if ( nLutSize <= 6 )
{
nLutSize = 6;
if ( pLib->LutMax == 11 )
nDegree = 2;
else if ( pLib->LutMax == 16 )
nDegree = 3;
else
{ printf( "LUT library for packing 6-LUTs should have 11 or 16 inputs.\n" ); return; }
}
else
{
printf( "The LUT size is more than 6.\n" );
return;
}
if ( fVerbose )
printf( "Performing %d-clustering with %d-LUTs:\n", nDegree, nLutSize );
// create timing manager
if ( pGia->pManTime == NULL )
pGia->pManTime = pTemp = Tim_ManStart( Gia_ManCiNum(pGia), Gia_ManCoNum(pGia) );
// perform timing computation
p = Gia_ManIffPerform( pGia, pLib, (Tim_Man_t *)pGia->pManTime, nLutSize, nDegree );
// remove timing manager
if ( pGia->pManTime == pTemp )
pGia->pManTime = NULL;
Tim_ManStopP( (Tim_Man_t **)&pTemp );
// derive clustering
Vec_IntFreeP( &pGia->vPacking );
pGia->vPacking = Gia_ManIffSelect( p );
Gia_ManIffStop( p );
// print statistics
if ( fVerbose )
Gia_ManPrintPackingStats( pGia );
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END