/**CFile**************************************************************** FileName [giaResub.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Scalable AIG package.] Synopsis [Resubstitution.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: giaResub.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "gia.h" #include "misc/vec/vecWec.h" #include "misc/vec/vecQue.h" #include "misc/vec/vecHsh.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Computes MFFCs of all qualifying nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ObjCheckMffc_rec( Gia_Man_t * p,Gia_Obj_t * pObj, int Limit, Vec_Int_t * vNodes ) { int iFanin; if ( Gia_ObjIsCi(pObj) ) return 1; assert( Gia_ObjIsAnd(pObj) ); iFanin = Gia_ObjFaninId0p(p, pObj); Vec_IntPush( vNodes, iFanin ); if ( !Gia_ObjRefDecId(p, iFanin) && (Vec_IntSize(vNodes) > Limit || !Gia_ObjCheckMffc_rec(p, Gia_ObjFanin0(pObj), Limit, vNodes)) ) return 0; iFanin = Gia_ObjFaninId1p(p, pObj); Vec_IntPush( vNodes, iFanin ); if ( !Gia_ObjRefDecId(p, iFanin) && (Vec_IntSize(vNodes) > Limit || !Gia_ObjCheckMffc_rec(p, Gia_ObjFanin1(pObj), Limit, vNodes)) ) return 0; if ( !Gia_ObjIsMux(p, pObj) ) return 1; iFanin = Gia_ObjFaninId2p(p, pObj); Vec_IntPush( vNodes, iFanin ); if ( !Gia_ObjRefDecId(p, iFanin) && (Vec_IntSize(vNodes) > Limit || !Gia_ObjCheckMffc_rec(p, Gia_ObjFanin2(p, pObj), Limit, vNodes)) ) return 0; return 1; } static inline int Gia_ObjCheckMffc( Gia_Man_t * p, Gia_Obj_t * pRoot, int Limit, Vec_Int_t * vNodes, Vec_Int_t * vLeaves, Vec_Int_t * vInners ) { int RetValue, iObj, i; Vec_IntClear( vNodes ); RetValue = Gia_ObjCheckMffc_rec( p, pRoot, Limit, vNodes ); if ( RetValue ) { Vec_IntClear( vLeaves ); Vec_IntClear( vInners ); Vec_IntSort( vNodes, 0 ); Vec_IntForEachEntry( vNodes, iObj, i ) if ( Gia_ObjRefNumId(p, iObj) > 0 || Gia_ObjIsCi(Gia_ManObj(p, iObj)) ) { if ( !Vec_IntSize(vLeaves) || Vec_IntEntryLast(vLeaves) != iObj ) Vec_IntPush( vLeaves, iObj ); } else { if ( !Vec_IntSize(vInners) || Vec_IntEntryLast(vInners) != iObj ) Vec_IntPush( vInners, iObj ); } Vec_IntPush( vInners, Gia_ObjId(p, pRoot) ); } Vec_IntForEachEntry( vNodes, iObj, i ) Gia_ObjRefIncId( p, iObj ); return RetValue; } Vec_Wec_t * Gia_ManComputeMffcs( Gia_Man_t * p, int LimitMin, int LimitMax, int SuppMax, int RatioBest ) { Gia_Obj_t * pObj; Vec_Wec_t * vMffcs; Vec_Int_t * vNodes, * vLeaves, * vInners, * vMffc; int i, iPivot; assert( p->pMuxes ); vNodes = Vec_IntAlloc( 2 * LimitMax ); vLeaves = Vec_IntAlloc( 2 * LimitMax ); vInners = Vec_IntAlloc( 2 * LimitMax ); vMffcs = Vec_WecAlloc( 1000 ); Gia_ManCreateRefs( p ); Gia_ManForEachAnd( p, pObj, i ) { if ( !Gia_ObjRefNum(p, pObj) ) continue; if ( !Gia_ObjCheckMffc(p, pObj, LimitMax, vNodes, vLeaves, vInners) ) continue; if ( Vec_IntSize(vInners) < LimitMin ) continue; if ( Vec_IntSize(vLeaves) > SuppMax ) continue; // improve cut // collect cut vMffc = Vec_WecPushLevel( vMffcs ); Vec_IntGrow( vMffc, Vec_IntSize(vLeaves) + Vec_IntSize(vInners) + 20 ); Vec_IntPush( vMffc, i ); Vec_IntPush( vMffc, Vec_IntSize(vLeaves) ); Vec_IntPush( vMffc, Vec_IntSize(vInners) ); Vec_IntAppend( vMffc, vLeaves ); // Vec_IntAppend( vMffc, vInners ); // add last entry equal to the ratio Vec_IntPush( vMffc, 1000 * Vec_IntSize(vInners) / Vec_IntSize(vLeaves) ); } Vec_IntFree( vNodes ); Vec_IntFree( vLeaves ); Vec_IntFree( vInners ); // sort MFFCs by their inner/leaf ratio Vec_WecSortByLastInt( vMffcs, 1 ); Vec_WecForEachLevel( vMffcs, vMffc, i ) Vec_IntPop( vMffc ); // remove those whose ratio is not good iPivot = RatioBest * Vec_WecSize(vMffcs) / 100; Vec_WecForEachLevelStart( vMffcs, vMffc, i, iPivot ) Vec_IntErase( vMffc ); assert( iPivot <= Vec_WecSize(vMffcs) ); Vec_WecShrink( vMffcs, iPivot ); return vMffcs; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManPrintDivStats( Gia_Man_t * p, Vec_Wec_t * vMffcs, Vec_Wec_t * vPivots ) { int fVerbose = 0; Vec_Int_t * vMffc; int i, nDivs, nDivsAll = 0, nDivs0 = 0; Vec_WecForEachLevel( vMffcs, vMffc, i ) { nDivs = Vec_IntSize(vMffc) - 3 - Vec_IntEntry(vMffc, 1) - Vec_IntEntry(vMffc, 2); nDivs0 += (nDivs == 0); nDivsAll += nDivs; if ( !fVerbose ) continue; printf( "%6d : ", Vec_IntEntry(vMffc, 0) ); printf( "Leaf =%3d ", Vec_IntEntry(vMffc, 1) ); printf( "Mffc =%4d ", Vec_IntEntry(vMffc, 2) ); printf( "Divs =%4d ", nDivs ); printf( "\n" ); } printf( "Collected %d (%.1f %%) MFFCs and %d (%.1f %%) have no divisors (div ave for others is %.2f).\n", Vec_WecSize(vMffcs), 100.0 * Vec_WecSize(vMffcs) / Gia_ManAndNum(p), nDivs0, 100.0 * nDivs0 / Gia_ManAndNum(p), 1.0*nDivsAll/Abc_MaxInt(1, Vec_WecSize(vMffcs) - nDivs0) ); printf( "Using %.2f MB for MFFCs and %.2f MB for pivots. ", Vec_WecMemory(vMffcs)/(1<<20), Vec_WecMemory(vPivots)/(1<<20) ); } /**Function************************************************************* Synopsis [Compute divisors and Boolean functions for the nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManAddDivisors( Gia_Man_t * p, Vec_Wec_t * vMffcs ) { Vec_Wec_t * vPivots; Vec_Int_t * vMffc, * vPivot, * vPivot0, * vPivot1; Vec_Int_t * vCommon, * vCommon2, * vMap; Gia_Obj_t * pObj; int i, k, iObj, iPivot, iMffc; //abctime clkStart = Abc_Clock(); // initialize pivots (mapping of nodes into MFFCs whose leaves they are) vMap = Vec_IntStartFull( Gia_ManObjNum(p) ); vPivots = Vec_WecStart( Gia_ManObjNum(p) ); Vec_WecForEachLevel( vMffcs, vMffc, i ) { assert( Vec_IntSize(vMffc) == 3 + Vec_IntEntry(vMffc, 1) ); iPivot = Vec_IntEntry( vMffc, 0 ); Vec_IntWriteEntry( vMap, iPivot, i ); // iterate through the MFFC leaves Vec_IntForEachEntryStart( vMffc, iObj, k, 3 ) { vPivot = Vec_WecEntry( vPivots, iObj ); if ( Vec_IntSize(vPivot) == 0 ) Vec_IntGrow(vPivot, 4); Vec_IntPush( vPivot, iPivot ); } } Vec_WecForEachLevel( vPivots, vPivot, i ) Vec_IntSort( vPivot, 0 ); // create pivots for internal nodes while growing MFFCs vCommon = Vec_IntAlloc( 100 ); vCommon2 = Vec_IntAlloc( 100 ); Gia_ManForEachAnd( p, pObj, i ) { // find commont pivots // the slow down happens because some PIs have very large sets of pivots vPivot0 = Vec_WecEntry( vPivots, Gia_ObjFaninId0(pObj, i) ); vPivot1 = Vec_WecEntry( vPivots, Gia_ObjFaninId1(pObj, i) ); Vec_IntTwoFindCommon( vPivot0, vPivot1, vCommon ); if ( Gia_ObjIsMuxId(p, i) ) { vPivot = Vec_WecEntry( vPivots, Gia_ObjFaninId2(p, i) ); Vec_IntTwoFindCommon( vPivot, vCommon, vCommon2 ); ABC_SWAP( Vec_Int_t *, vCommon, vCommon2 ); } if ( Vec_IntSize(vCommon) == 0 ) continue; // add new pivots (this trick increased memory used in vPivots) vPivot = Vec_WecEntry( vPivots, i ); Vec_IntTwoMerge2( vPivot, vCommon, vCommon2 ); ABC_SWAP( Vec_Int_t, *vPivot, *vCommon2 ); // grow MFFCs Vec_IntForEachEntry( vCommon, iObj, k ) { iMffc = Vec_IntEntry( vMap, iObj ); assert( iMffc != -1 ); vMffc = Vec_WecEntry( vMffcs, iMffc ); Vec_IntPush( vMffc, i ); } } //Abc_PrintTime( 1, "Time", Abc_Clock() - clkStart ); Vec_IntFree( vCommon ); Vec_IntFree( vCommon2 ); Vec_IntFree( vMap ); Gia_ManPrintDivStats( p, vMffcs, vPivots ); Vec_WecFree( vPivots ); // returns the modified array of MFFCs } void Gia_ManResubTest( Gia_Man_t * p ) { Vec_Wec_t * vMffcs; Gia_Man_t * pNew = Gia_ManDupMuxes( p, 2 ); abctime clkStart = Abc_Clock(); vMffcs = Gia_ManComputeMffcs( pNew, 4, 100, 8, 100 ); Gia_ManAddDivisors( pNew, vMffcs ); Vec_WecFree( vMffcs ); Abc_PrintTime( 1, "Time", Abc_Clock() - clkStart ); Gia_ManStop( pNew ); } /**Function************************************************************* Synopsis [Perform resubstitution.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END