/**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