| /**CFile**************************************************************** | |
| FileName [sbdCut2.c] | |
| SystemName [ABC: Logic synthesis and verification system.] | |
| PackageName [SAT-based optimization using internal don't-cares.] | |
| Synopsis [Cut computation.] | |
| Author [Alan Mishchenko] | |
| Affiliation [UC Berkeley] | |
| Date [Ver. 1.0. Started - June 20, 2005.] | |
| Revision [$Id: sbdCut2.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] | |
| ***********************************************************************/ | |
| #include "sbdInt.h" | |
| ABC_NAMESPACE_IMPL_START | |
| //////////////////////////////////////////////////////////////////////// | |
| /// DECLARATIONS /// | |
| //////////////////////////////////////////////////////////////////////// | |
| #define SBD_MAX_CUTSIZE 10 | |
| #define SBD_MAX_CUTNUM 501 | |
| #define SBD_CUT_NO_LEAF 0xF | |
| typedef struct Sbd_Cut_t_ Sbd_Cut_t; | |
| struct Sbd_Cut_t_ | |
| { | |
| word Sign; // signature | |
| int iFunc; // functionality | |
| int Cost; // cut cost | |
| int CostLev; // cut cost | |
| unsigned nTreeLeaves : 9; // tree leaves | |
| unsigned nSlowLeaves : 9; // slow leaves | |
| unsigned nTopLeaves : 10; // top leaves | |
| unsigned nLeaves : 4; // leaf count | |
| int pLeaves[SBD_MAX_CUTSIZE]; // leaves | |
| }; | |
| struct Sbd_Srv_t_ | |
| { | |
| int nLutSize; | |
| int nCutSize; | |
| int nCutNum; | |
| int fVerbose; | |
| Gia_Man_t * pGia; // user's AIG manager (will be modified by adding nodes) | |
| Vec_Int_t * vMirrors; // mirrors for each node | |
| Vec_Int_t * vLutLevs; // delays for each node | |
| Vec_Int_t * vLevs; // levels for each node | |
| Vec_Int_t * vRefs; // refs for each node | |
| Sbd_Cut_t pCuts[SBD_MAX_CUTNUM]; // temporary cuts | |
| Sbd_Cut_t * ppCuts[SBD_MAX_CUTNUM]; // temporary cut pointers | |
| abctime clkStart; // starting time | |
| Vec_Int_t * vCut0; // current cut | |
| Vec_Int_t * vCut; // current cut | |
| Vec_Int_t * vCutTop; // current cut | |
| Vec_Int_t * vCutBot; // current cut | |
| }; | |
| //////////////////////////////////////////////////////////////////////// | |
| /// FUNCTION DEFINITIONS /// | |
| //////////////////////////////////////////////////////////////////////// | |
| /**Function************************************************************* | |
| Synopsis [] | |
| Description [] | |
| SideEffects [] | |
| SeeAlso [] | |
| ***********************************************************************/ | |
| Sbd_Srv_t * Sbd_ManCutServerStart( Gia_Man_t * pGia, Vec_Int_t * vMirrors, | |
| Vec_Int_t * vLutLevs, Vec_Int_t * vLevs, Vec_Int_t * vRefs, | |
| int nLutSize, int nCutSize, int nCutNum, int fVerbose ) | |
| { | |
| Sbd_Srv_t * p; | |
| assert( nLutSize <= nCutSize ); | |
| assert( nCutSize < SBD_CUT_NO_LEAF ); | |
| assert( nCutSize > 1 && nCutSize <= SBD_MAX_CUTSIZE ); | |
| assert( nCutNum > 1 && nCutNum < SBD_MAX_CUTNUM ); | |
| p = ABC_CALLOC( Sbd_Srv_t, 1 ); | |
| p->clkStart = Abc_Clock(); | |
| p->nLutSize = nLutSize; | |
| p->nCutSize = nCutSize; | |
| p->nCutNum = nCutNum; | |
| p->fVerbose = fVerbose; | |
| p->pGia = pGia; | |
| p->vMirrors = vMirrors; | |
| p->vLutLevs = vLutLevs; | |
| p->vLevs = vLevs; | |
| p->vRefs = vRefs; | |
| p->vCut0 = Vec_IntAlloc( 100 ); | |
| p->vCut = Vec_IntAlloc( 100 ); | |
| p->vCutTop = Vec_IntAlloc( 100 ); | |
| p->vCutBot = Vec_IntAlloc( 100 ); | |
| return p; | |
| } | |
| void Sbd_ManCutServerStop( Sbd_Srv_t * p ) | |
| { | |
| Vec_IntFree( p->vCut0 ); | |
| Vec_IntFree( p->vCut ); | |
| Vec_IntFree( p->vCutTop ); | |
| Vec_IntFree( p->vCutBot ); | |
| ABC_FREE( p ); | |
| } | |
| /**Function************************************************************* | |
| Synopsis [] | |
| Description [] | |
| SideEffects [] | |
| SeeAlso [] | |
| ***********************************************************************/ | |
| int Sbd_ManCutIsTopo_rec( Gia_Man_t * p, Vec_Int_t * vMirrors, int iObj ) | |
| { | |
| Gia_Obj_t * pObj; | |
| int Ret0, Ret1; | |
| if ( Vec_IntEntry(vMirrors, iObj) >= 0 ) | |
| iObj = Abc_Lit2Var(Vec_IntEntry(vMirrors, iObj)); | |
| if ( !iObj || Gia_ObjIsTravIdCurrentId(p, iObj) ) | |
| return 1; | |
| Gia_ObjSetTravIdCurrentId(p, iObj); | |
| pObj = Gia_ManObj( p, iObj ); | |
| if ( Gia_ObjIsCi(pObj) ) | |
| return 0; | |
| assert( Gia_ObjIsAnd(pObj) ); | |
| Ret0 = Sbd_ManCutIsTopo_rec( p, vMirrors, Gia_ObjFaninId0(pObj, iObj) ); | |
| Ret1 = Sbd_ManCutIsTopo_rec( p, vMirrors, Gia_ObjFaninId1(pObj, iObj) ); | |
| return Ret0 && Ret1; | |
| } | |
| int Sbd_ManCutIsTopo( Gia_Man_t * p, Vec_Int_t * vMirrors, Vec_Int_t * vCut, int iObj ) | |
| { | |
| int i, Entry, RetValue; | |
| Gia_ManIncrementTravId( p ); | |
| Vec_IntForEachEntry( vCut, Entry, i ) | |
| Gia_ObjSetTravIdCurrentId( p, Entry ); | |
| RetValue = Sbd_ManCutIsTopo_rec( p, vMirrors, iObj ); | |
| if ( RetValue == 0 ) | |
| printf( "Cut of node %d is not tological\n", iObj ); | |
| assert( RetValue ); | |
| return RetValue; | |
| } | |
| /**Function************************************************************* | |
| Synopsis [] | |
| Description [] | |
| SideEffects [] | |
| SeeAlso [] | |
| ***********************************************************************/ | |
| static inline int Sbd_ManCutExpandOne( Gia_Man_t * p, Vec_Int_t * vMirrors, Vec_Int_t * vLutLevs, Vec_Int_t * vCut, int iThis, int iObj ) | |
| { | |
| int Lit0m, Lit1m, Fan0, Fan1, iPlace0, iPlace1; | |
| int LutLev = Vec_IntEntry( vLutLevs, iObj ); | |
| Gia_Obj_t * pObj = Gia_ManObj(p, iObj); | |
| if ( Gia_ObjIsCi(pObj) ) | |
| return 0; | |
| assert( Gia_ObjIsAnd(pObj) ); | |
| Lit0m = Vec_IntEntry( vMirrors, Gia_ObjFaninId0(pObj, iObj) ); | |
| Lit1m = Vec_IntEntry( vMirrors, Gia_ObjFaninId1(pObj, iObj) ); | |
| Fan0 = Lit0m >= 0 ? Abc_Lit2Var(Lit0m) : Gia_ObjFaninId0(pObj, iObj); | |
| Fan1 = Lit1m >= 0 ? Abc_Lit2Var(Lit1m) : Gia_ObjFaninId1(pObj, iObj); | |
| iPlace0 = Vec_IntFind( vCut, Fan0 ); | |
| iPlace1 = Vec_IntFind( vCut, Fan1 ); | |
| if ( iPlace0 == -1 && iPlace1 == -1 ) | |
| return 0; | |
| if ( Vec_IntEntry(vLutLevs, Fan0) > LutLev || Vec_IntEntry(vLutLevs, Fan1) > LutLev ) | |
| return 0; | |
| Vec_IntDrop( vCut, iThis ); | |
| if ( iPlace0 == -1 && Fan0 ) | |
| Vec_IntPushOrder( vCut, Fan0 ); | |
| if ( iPlace1 == -1 && Fan1 ) | |
| Vec_IntPushOrder( vCut, Fan1 ); | |
| return 1; | |
| } | |
| void Vec_IntIsOrdered( Vec_Int_t * vCut ) | |
| { | |
| int i, Prev, Entry; | |
| Prev = Vec_IntEntry( vCut, 0 ); | |
| Vec_IntForEachEntryStart( vCut, Entry, i, 1 ) | |
| { | |
| assert( Prev < Entry ); | |
| Prev = Entry; | |
| } | |
| } | |
| void Sbd_ManCutExpand( Gia_Man_t * p, Vec_Int_t * vMirrors, Vec_Int_t * vLutLevs, Vec_Int_t * vCut ) | |
| { | |
| int i, Entry; | |
| do | |
| { | |
| Vec_IntForEachEntry( vCut, Entry, i ) | |
| if ( Sbd_ManCutExpandOne( p, vMirrors, vLutLevs, vCut, i, Entry ) ) | |
| break; | |
| } | |
| while ( i < Vec_IntSize(vCut) ); | |
| } | |
| void Sbd_ManCutReload( Vec_Int_t * vMirrors, Vec_Int_t * vLutLevs, int LevStop, Vec_Int_t * vCut, Vec_Int_t * vCutTop, Vec_Int_t * vCutBot ) | |
| { | |
| int i, Entry; | |
| Vec_IntClear( vCutTop ); | |
| Vec_IntClear( vCutBot ); | |
| Vec_IntForEachEntry( vCut, Entry, i ) | |
| { | |
| assert( Entry ); | |
| assert( Vec_IntEntry(vMirrors, Entry) == -1 ); | |
| assert( Vec_IntEntry(vLutLevs, Entry) <= LevStop ); | |
| if ( Vec_IntEntry(vLutLevs, Entry) == LevStop ) | |
| Vec_IntPush( vCutTop, Entry ); | |
| else | |
| Vec_IntPush( vCutBot, Entry ); | |
| } | |
| Vec_IntIsOrdered( vCut ); | |
| } | |
| int Sbd_ManCutCollect_rec( Gia_Man_t * p, Vec_Int_t * vMirrors, int iObj, int LevStop, Vec_Int_t * vLutLevs, Vec_Int_t * vCut ) | |
| { | |
| Gia_Obj_t * pObj; | |
| int Ret0, Ret1; | |
| if ( Vec_IntEntry(vMirrors, iObj) >= 0 ) | |
| iObj = Abc_Lit2Var(Vec_IntEntry(vMirrors, iObj)); | |
| if ( !iObj || Gia_ObjIsTravIdCurrentId(p, iObj) ) | |
| return 1; | |
| Gia_ObjSetTravIdCurrentId(p, iObj); | |
| pObj = Gia_ManObj( p, iObj ); | |
| if ( Gia_ObjIsCi(pObj) || Vec_IntEntry(vLutLevs, iObj) <= LevStop ) | |
| { | |
| Vec_IntPush( vCut, iObj ); | |
| return Vec_IntEntry(vLutLevs, iObj) <= LevStop; | |
| } | |
| assert( Gia_ObjIsAnd(pObj) ); | |
| Ret0 = Sbd_ManCutCollect_rec( p, vMirrors, Gia_ObjFaninId0(pObj, iObj), LevStop, vLutLevs, vCut ); | |
| Ret1 = Sbd_ManCutCollect_rec( p, vMirrors, Gia_ObjFaninId1(pObj, iObj), LevStop, vLutLevs, vCut ); | |
| return Ret0 && Ret1; | |
| } | |
| /**Function************************************************************* | |
| Synopsis [] | |
| Description [] | |
| SideEffects [] | |
| SeeAlso [] | |
| ***********************************************************************/ | |
| int Sbd_ManCutReduceTop( Gia_Man_t * p, Vec_Int_t * vMirrors, int iObj, Vec_Int_t * vLutLevs, Vec_Int_t * vCut, Vec_Int_t * vCutTop, int nCutSize ) | |
| { | |
| int i, Entry, Lit0m, Lit1m, Fan0, Fan1; | |
| int LevStop = Vec_IntEntry(vLutLevs, iObj) - 2; | |
| Vec_IntIsOrdered( vCut ); | |
| Vec_IntForEachEntryReverse( vCutTop, Entry, i ) | |
| { | |
| Gia_Obj_t * pObj = Gia_ManObj( p, Entry ); | |
| if ( Gia_ObjIsCi(pObj) ) | |
| continue; | |
| assert( Gia_ObjIsAnd(pObj) ); | |
| assert( Vec_IntEntry(vLutLevs, Entry) == LevStop ); | |
| Lit0m = Vec_IntEntry( vMirrors, Gia_ObjFaninId0(pObj, Entry) ); | |
| Lit1m = Vec_IntEntry( vMirrors, Gia_ObjFaninId1(pObj, Entry) ); | |
| Fan0 = Lit0m >= 0 ? Abc_Lit2Var(Lit0m) : Gia_ObjFaninId0(pObj, Entry); | |
| Fan1 = Lit1m >= 0 ? Abc_Lit2Var(Lit1m) : Gia_ObjFaninId1(pObj, Entry); | |
| if ( Vec_IntEntry(vLutLevs, Fan0) > LevStop || Vec_IntEntry(vLutLevs, Fan1) > LevStop ) | |
| continue; | |
| assert( Vec_IntEntry(vLutLevs, Fan0) <= LevStop ); | |
| assert( Vec_IntEntry(vLutLevs, Fan1) <= LevStop ); | |
| if ( Vec_IntEntry(vLutLevs, Fan0) == LevStop && Vec_IntEntry(vLutLevs, Fan1) == LevStop ) | |
| continue; | |
| Vec_IntRemove( vCut, Entry ); | |
| if ( Fan0 ) Vec_IntPushUniqueOrder( vCut, Fan0 ); | |
| if ( Fan1 ) Vec_IntPushUniqueOrder( vCut, Fan1 ); | |
| //Sbd_ManCutIsTopo( p, vMirrors, vCut, iObj ); | |
| return 1; | |
| } | |
| return 0; | |
| } | |
| /**Function************************************************************* | |
| Synopsis [] | |
| Description [] | |
| SideEffects [] | |
| SeeAlso [] | |
| ***********************************************************************/ | |
| int Sbd_ManCutServerFirst( Sbd_Srv_t * p, int iObj, int * pLeaves ) | |
| { | |
| int RetValue, LevStop = Vec_IntEntry(p->vLutLevs, iObj) - 2; | |
| Vec_IntClear( p->vCut ); | |
| Gia_ManIncrementTravId( p->pGia ); | |
| RetValue = Sbd_ManCutCollect_rec( p->pGia, p->vMirrors, iObj, LevStop, p->vLutLevs, p->vCut ); | |
| if ( RetValue == 0 ) // cannot build delay-improving cut | |
| return -1; | |
| // check if the current cut is good | |
| Vec_IntSort( p->vCut, 0 ); | |
| /* | |
| Sbd_ManCutReload( p->vMirrors, p->vLutLevs, LevStop, p->vCut, p->vCutTop, p->vCutBot ); | |
| if ( Vec_IntSize(p->vCut) <= p->nCutSize && Vec_IntSize(p->vCutTop) <= p->nLutSize-1 ) | |
| { | |
| //printf( "%d ", Vec_IntSize(p->vCut) ); | |
| memcpy( pLeaves, Vec_IntArray(p->vCut), sizeof(int) * Vec_IntSize(p->vCut) ); | |
| return Vec_IntSize(p->vCut); | |
| } | |
| */ | |
| // try to expand the cut | |
| Sbd_ManCutExpand( p->pGia, p->vMirrors, p->vLutLevs, p->vCut ); | |
| Sbd_ManCutReload( p->vMirrors, p->vLutLevs, LevStop, p->vCut, p->vCutTop, p->vCutBot ); | |
| if ( Vec_IntSize(p->vCut) <= p->nCutSize && Vec_IntSize(p->vCutTop) <= p->nLutSize-1 ) | |
| { | |
| //printf( "1=(%d,%d) ", Vec_IntSize(p->vCutTop), Vec_IntSize(p->vCutBot) ); | |
| //printf( "%d ", Vec_IntSize(p->vCut) ); | |
| memcpy( pLeaves, Vec_IntArray(p->vCut), sizeof(int) * Vec_IntSize(p->vCut) ); | |
| return Vec_IntSize(p->vCut); | |
| } | |
| // try to reduce the topmost | |
| Vec_IntClear( p->vCut0 ); | |
| Vec_IntAppend( p->vCut0, p->vCut ); | |
| if ( Vec_IntSize(p->vCut) < p->nCutSize && Sbd_ManCutReduceTop( p->pGia, p->vMirrors, iObj, p->vLutLevs, p->vCut, p->vCutTop, p->nCutSize ) ) | |
| { | |
| Sbd_ManCutExpand( p->pGia, p->vMirrors, p->vLutLevs, p->vCut ); | |
| Sbd_ManCutReload( p->vMirrors, p->vLutLevs, LevStop, p->vCut, p->vCutTop, p->vCutBot ); | |
| assert( Vec_IntSize(p->vCut) <= p->nCutSize ); | |
| if ( Vec_IntSize(p->vCutTop) <= p->nLutSize-1 ) | |
| { | |
| //printf( "%d -> %d (%d + %d)\n", Vec_IntSize(p->vCut0), Vec_IntSize(p->vCut), Vec_IntSize(p->vCutTop), Vec_IntSize(p->vCutBot) ); | |
| memcpy( pLeaves, Vec_IntArray(p->vCut), sizeof(int) * Vec_IntSize(p->vCut) ); | |
| return Vec_IntSize(p->vCut); | |
| } | |
| // try again | |
| if ( Vec_IntSize(p->vCut) < p->nCutSize && Sbd_ManCutReduceTop( p->pGia, p->vMirrors, iObj, p->vLutLevs, p->vCut, p->vCutTop, p->nCutSize ) ) | |
| { | |
| Sbd_ManCutExpand( p->pGia, p->vMirrors, p->vLutLevs, p->vCut ); | |
| Sbd_ManCutReload( p->vMirrors, p->vLutLevs, LevStop, p->vCut, p->vCutTop, p->vCutBot ); | |
| assert( Vec_IntSize(p->vCut) <= p->nCutSize ); | |
| if ( Vec_IntSize(p->vCutTop) <= p->nLutSize-1 ) | |
| { | |
| //printf( "* %d -> %d (%d + %d)\n", Vec_IntSize(p->vCut0), Vec_IntSize(p->vCut), Vec_IntSize(p->vCutTop), Vec_IntSize(p->vCutBot) ); | |
| memcpy( pLeaves, Vec_IntArray(p->vCut), sizeof(int) * Vec_IntSize(p->vCut) ); | |
| return Vec_IntSize(p->vCut); | |
| } | |
| // try again | |
| if ( Vec_IntSize(p->vCut) < p->nCutSize && Sbd_ManCutReduceTop( p->pGia, p->vMirrors, iObj, p->vLutLevs, p->vCut, p->vCutTop, p->nCutSize ) ) | |
| { | |
| Sbd_ManCutExpand( p->pGia, p->vMirrors, p->vLutLevs, p->vCut ); | |
| Sbd_ManCutReload( p->vMirrors, p->vLutLevs, LevStop, p->vCut, p->vCutTop, p->vCutBot ); | |
| assert( Vec_IntSize(p->vCut) <= p->nCutSize ); | |
| if ( Vec_IntSize(p->vCutTop) <= p->nLutSize-1 ) | |
| { | |
| //printf( "** %d -> %d (%d + %d)\n", Vec_IntSize(p->vCut0), Vec_IntSize(p->vCut), Vec_IntSize(p->vCutTop), Vec_IntSize(p->vCutBot) ); | |
| memcpy( pLeaves, Vec_IntArray(p->vCut), sizeof(int) * Vec_IntSize(p->vCut) ); | |
| return Vec_IntSize(p->vCut); | |
| } | |
| // try again | |
| if ( Vec_IntSize(p->vCut) < p->nCutSize && Sbd_ManCutReduceTop( p->pGia, p->vMirrors, iObj, p->vLutLevs, p->vCut, p->vCutTop, p->nCutSize ) ) | |
| { | |
| Sbd_ManCutExpand( p->pGia, p->vMirrors, p->vLutLevs, p->vCut ); | |
| Sbd_ManCutReload( p->vMirrors, p->vLutLevs, LevStop, p->vCut, p->vCutTop, p->vCutBot ); | |
| assert( Vec_IntSize(p->vCut) <= p->nCutSize ); | |
| if ( Vec_IntSize(p->vCutTop) <= p->nLutSize-1 ) | |
| { | |
| //printf( "*** %d -> %d (%d + %d)\n", Vec_IntSize(p->vCut0), Vec_IntSize(p->vCut), Vec_IntSize(p->vCutTop), Vec_IntSize(p->vCutBot) ); | |
| memcpy( pLeaves, Vec_IntArray(p->vCut), sizeof(int) * Vec_IntSize(p->vCut) ); | |
| return Vec_IntSize(p->vCut); | |
| } | |
| } | |
| } | |
| } | |
| } | |
| // recompute the cut | |
| Vec_IntClear( p->vCut ); | |
| Gia_ManIncrementTravId( p->pGia ); | |
| RetValue = Sbd_ManCutCollect_rec( p->pGia, p->vMirrors, iObj, LevStop-1, p->vLutLevs, p->vCut ); | |
| if ( RetValue == 0 ) // cannot build delay-improving cut | |
| return -1; | |
| // check if the current cut is good | |
| Vec_IntSort( p->vCut, 0 ); | |
| /* | |
| Sbd_ManCutReload( p->vMirrors, p->vLutLevs, LevStop, p->vCut, p->vCutTop, p->vCutBot ); | |
| if ( Vec_IntSize(p->vCut) <= p->nCutSize && Vec_IntSize(p->vCutTop) <= p->nLutSize-1 ) | |
| { | |
| //printf( "%d ", Vec_IntSize(p->vCut) ); | |
| memcpy( pLeaves, Vec_IntArray(p->vCut), sizeof(int) * Vec_IntSize(p->vCut) ); | |
| return Vec_IntSize(p->vCut); | |
| } | |
| */ | |
| // try to expand the cut | |
| Sbd_ManCutExpand( p->pGia, p->vMirrors, p->vLutLevs, p->vCut ); | |
| Sbd_ManCutReload( p->vMirrors, p->vLutLevs, LevStop, p->vCut, p->vCutTop, p->vCutBot ); | |
| if ( Vec_IntSize(p->vCut) <= p->nCutSize && Vec_IntSize(p->vCutTop) <= p->nLutSize-1 ) | |
| { | |
| //printf( "2=(%d,%d) ", Vec_IntSize(p->vCutTop), Vec_IntSize(p->vCutBot) ); | |
| //printf( "%d ", Vec_IntSize(p->vCut) ); | |
| memcpy( pLeaves, Vec_IntArray(p->vCut), sizeof(int) * Vec_IntSize(p->vCut) ); | |
| return Vec_IntSize(p->vCut); | |
| } | |
| return -1; | |
| } | |
| //////////////////////////////////////////////////////////////////////// | |
| /// END OF FILE /// | |
| //////////////////////////////////////////////////////////////////////// | |
| ABC_NAMESPACE_IMPL_END | |