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