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