blob: b4a8be74d433e6d1f8f87d8f607a1def4af1e05e [file] [log] [blame]
/**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