OpenFPGA/abc/src/opt/sbd/sbdCore.c

2230 lines
81 KiB
C

/**CFile****************************************************************
FileName [sbdCore.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [SAT-based optimization using internal don't-cares.]
Synopsis [Core procedures.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: sbdCore.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
#include "sbdInt.h"
#include "opt/dau/dau.h"
#include "misc/tim/tim.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
#define SBD_MAX_LUTSIZE 6
typedef struct Sbd_Man_t_ Sbd_Man_t;
struct Sbd_Man_t_
{
Sbd_Par_t * pPars; // user's parameters
Gia_Man_t * pGia; // user's AIG manager (will be modified by adding nodes)
Vec_Wec_t * vTfos; // TFO for each node (roots are marked) (windowing)
Vec_Int_t * vLutLevs; // LUT level for each node after resynthesis
Vec_Int_t * vLutCuts; // LUT cut for each nodes after resynthesis
Vec_Int_t * vLutCuts2; // LUT cut for each nodes after resynthesis
Vec_Int_t * vMirrors; // alternative node
Vec_Wrd_t * vSims[4]; // simulation information (main, backup, controlability)
Vec_Int_t * vCover; // temporary
Vec_Int_t * vLits; // temporary
Vec_Int_t * vLits2; // temporary
int nLuts[6]; // 0=const, 1=1lut, 2=2lut, 3=3lut
int nTried;
int nUsed;
abctime timeWin;
abctime timeCut;
abctime timeCov;
abctime timeCnf;
abctime timeSat;
abctime timeQbf;
abctime timeNew;
abctime timeOther;
abctime timeTotal;
Sbd_Sto_t * pSto;
Sbd_Srv_t * pSrv;
// target node
int Pivot; // target node
int DivCutoff; // the place where D-2 divisors begin
Vec_Int_t * vTfo; // TFO (excludes node, includes roots) - precomputed
Vec_Int_t * vRoots; // TFO root nodes
Vec_Int_t * vWinObjs; // TFI + Pivot + sideTFI + TFO (including roots)
Vec_Int_t * vObj2Var; // SAT variables for the window (indexes of objects in vWinObjs)
Vec_Int_t * vDivSet; // divisor variables
Vec_Int_t * vDivVars; // divisor variables
Vec_Int_t * vDivValues; // SAT variables values for the divisor variables
Vec_Wec_t * vDivLevels; // divisors collected by levels
Vec_Int_t * vCounts[2]; // counters of zeros and ones
Vec_Wrd_t * vMatrix; // covering matrix
sat_solver * pSat; // SAT solver
};
static inline int * Sbd_ObjCut( Sbd_Man_t * p, int i ) { return Vec_IntEntryP( p->vLutCuts, (p->pPars->nLutSize + 1) * i ); }
static inline int * Sbd_ObjCut2( Sbd_Man_t * p, int i ) { return Vec_IntEntryP( p->vLutCuts2, (p->pPars->nLutSize + 1) * i ); }
static inline word * Sbd_ObjSim0( Sbd_Man_t * p, int i ) { return Vec_WrdEntryP( p->vSims[0], p->pPars->nWords * i ); }
static inline word * Sbd_ObjSim1( Sbd_Man_t * p, int i ) { return Vec_WrdEntryP( p->vSims[1], p->pPars->nWords * i ); }
static inline word * Sbd_ObjSim2( Sbd_Man_t * p, int i ) { return Vec_WrdEntryP( p->vSims[2], p->pPars->nWords * i ); }
static inline word * Sbd_ObjSim3( Sbd_Man_t * p, int i ) { return Vec_WrdEntryP( p->vSims[3], p->pPars->nWords * i ); }
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Sbd_ParSetDefault( Sbd_Par_t * pPars )
{
memset( pPars, 0, sizeof(Sbd_Par_t) );
pPars->nLutSize = 4; // target LUT size
pPars->nLutNum = 3; // target LUT count
pPars->nCutSize = (pPars->nLutSize - 1) * pPars->nLutNum + 1; // target cut size
pPars->nCutNum = 128; // target cut count
pPars->nTfoLevels = 5; // the number of TFO levels (windowing)
pPars->nTfoFanMax = 4; // the max number of fanouts (windowing)
pPars->nWinSizeMax = 2000; // maximum window size (windowing)
pPars->nBTLimit = 0; // maximum number of SAT conflicts
pPars->nWords = 1; // simulation word count
pPars->fMapping = 1; // generate mapping
pPars->fMoreCuts = 0; // use several cuts
pPars->fFindDivs = 0; // perform divisor search
pPars->fUsePath = 0; // optimize only critical path
pPars->fArea = 0; // area-oriented optimization
pPars->fCover = 0; // use complete cover procedure
pPars->fVerbose = 0; // verbose flag
pPars->fVeryVerbose = 0; // verbose flag
}
/**Function*************************************************************
Synopsis [Computes TFO and window roots for all nodes.]
Description [TFO does not include the node itself. If TFO is empty,
it means that the node itself is its own root, which may happen if
the node is pointed by a PO or if it has too many fanouts.]
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Wec_t * Sbd_ManWindowRoots( Gia_Man_t * p, int nTfoLevels, int nTfoFanMax )
{
Vec_Wec_t * vTfos = Vec_WecStart( Gia_ManObjNum(p) ); // TFO nodes with roots marked
Vec_Wec_t * vTemp = Vec_WecStart( Gia_ManObjNum(p) ); // storage
Vec_Int_t * vNodes, * vNodes0, * vNodes1;
Vec_Bit_t * vPoDrivers = Vec_BitStart( Gia_ManObjNum(p) );
int i, k, k2, Id, Fan;
Gia_ManLevelNum( p );
Gia_ManCreateRefs( p );
Gia_ManCleanMark0( p );
Gia_ManForEachCiId( p, Id, i )
{
vNodes = Vec_WecEntry( vTemp, Id );
Vec_IntGrow( vNodes, 1 );
Vec_IntPush( vNodes, Id );
}
Gia_ManForEachCoDriverId( p, Id, i )
Vec_BitWriteEntry( vPoDrivers, Id, 1 );
Gia_ManForEachAndId( p, Id )
{
int fAlwaysRoot = Vec_BitEntry(vPoDrivers, Id) || (Gia_ObjRefNumId(p, Id) >= nTfoFanMax);
vNodes0 = Vec_WecEntry( vTemp, Gia_ObjFaninId0(Gia_ManObj(p, Id), Id) );
vNodes1 = Vec_WecEntry( vTemp, Gia_ObjFaninId1(Gia_ManObj(p, Id), Id) );
vNodes = Vec_WecEntry( vTemp, Id );
Vec_IntTwoMerge2( vNodes0, vNodes1, vNodes );
k2 = 0;
Vec_IntForEachEntry( vNodes, Fan, k )
{
int fRoot = fAlwaysRoot || (Gia_ObjLevelId(p, Id) - Gia_ObjLevelId(p, Fan) >= nTfoLevels);
Vec_WecPush( vTfos, Fan, Abc_Var2Lit(Id, fRoot) );
if ( !fRoot ) Vec_IntWriteEntry( vNodes, k2++, Fan );
}
Vec_IntShrink( vNodes, k2 );
if ( !fAlwaysRoot )
Vec_IntPush( vNodes, Id );
}
Vec_WecFree( vTemp );
Vec_BitFree( vPoDrivers );
// print the results
if ( 0 )
Vec_WecForEachLevel( vTfos, vNodes, i )
{
if ( !Gia_ObjIsAnd(Gia_ManObj(p, i)) )
continue;
printf( "Node %3d : ", i );
Vec_IntForEachEntry( vNodes, Fan, k )
printf( "%d%s ", Abc_Lit2Var(Fan), Abc_LitIsCompl(Fan)? "*":"" );
printf( "\n" );
}
return vTfos;
}
/**Function*************************************************************
Synopsis [Manager manipulation.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Sbd_Man_t * Sbd_ManStart( Gia_Man_t * pGia, Sbd_Par_t * pPars )
{
int i, w, Id;
Sbd_Man_t * p = ABC_CALLOC( Sbd_Man_t, 1 );
p->timeTotal = Abc_Clock();
p->pPars = pPars;
p->pGia = pGia;
p->vTfos = Sbd_ManWindowRoots( pGia, pPars->nTfoLevels, pPars->nTfoFanMax );
p->vLutLevs = Vec_IntStart( Gia_ManObjNum(pGia) );
p->vLutCuts = Vec_IntStart( Gia_ManObjNum(pGia) * (p->pPars->nLutSize + 1) );
p->vMirrors = Vec_IntStartFull( Gia_ManObjNum(pGia) );
for ( i = 0; i < 4; i++ )
p->vSims[i] = Vec_WrdStart( Gia_ManObjNum(pGia) * p->pPars->nWords );
// target node
p->vCover = Vec_IntAlloc( 100 );
p->vLits = Vec_IntAlloc( 100 );
p->vLits2 = Vec_IntAlloc( 100 );
p->vRoots = Vec_IntAlloc( 100 );
p->vWinObjs = Vec_IntAlloc( Gia_ManObjNum(pGia) );
p->vObj2Var = Vec_IntStart( Gia_ManObjNum(pGia) );
p->vDivSet = Vec_IntAlloc( 100 );
p->vDivVars = Vec_IntAlloc( 100 );
p->vDivValues = Vec_IntAlloc( 100 );
p->vDivLevels = Vec_WecAlloc( 100 );
p->vCounts[0] = Vec_IntAlloc( 100 );
p->vCounts[1] = Vec_IntAlloc( 100 );
p->vMatrix = Vec_WrdAlloc( 100 );
// start input cuts
Gia_ManForEachCiId( pGia, Id, i )
{
int * pCut = Sbd_ObjCut( p, Id );
pCut[0] = 1;
pCut[1] = Id;
}
// generate random input
Gia_ManRandom( 1 );
Gia_ManForEachCiId( pGia, Id, i )
for ( w = 0; w < p->pPars->nWords; w++ )
Sbd_ObjSim0(p, Id)[w] = Gia_ManRandomW( 0 );
// cut enumeration
if ( pPars->fMoreCuts )
p->pSto = Sbd_StoAlloc( pGia, p->vMirrors, pPars->nLutSize, pPars->nCutSize, pPars->nCutNum, !pPars->fMapping, 1 );
else
{
p->pSto = Sbd_StoAlloc( pGia, p->vMirrors, pPars->nLutSize, pPars->nLutSize, pPars->nCutNum, !pPars->fMapping, 1 );
p->pSrv = Sbd_ManCutServerStart( pGia, p->vMirrors, p->vLutLevs, NULL, NULL, pPars->nLutSize, pPars->nCutSize, pPars->nCutNum, 0 );
}
return p;
}
void Sbd_ManStop( Sbd_Man_t * p )
{
int i;
Vec_WecFree( p->vTfos );
Vec_IntFree( p->vLutLevs );
Vec_IntFree( p->vLutCuts );
Vec_IntFree( p->vMirrors );
for ( i = 0; i < 4; i++ )
Vec_WrdFree( p->vSims[i] );
Vec_IntFree( p->vCover );
Vec_IntFree( p->vLits );
Vec_IntFree( p->vLits2 );
Vec_IntFree( p->vRoots );
Vec_IntFree( p->vWinObjs );
Vec_IntFree( p->vObj2Var );
Vec_IntFree( p->vDivSet );
Vec_IntFree( p->vDivVars );
Vec_IntFree( p->vDivValues );
Vec_WecFree( p->vDivLevels );
Vec_IntFree( p->vCounts[0] );
Vec_IntFree( p->vCounts[1] );
Vec_WrdFree( p->vMatrix );
sat_solver_delete_p( &p->pSat );
if ( p->pSto ) Sbd_StoFree( p->pSto );
if ( p->pSrv ) Sbd_ManCutServerStop( p->pSrv );
ABC_FREE( p );
}
/**Function*************************************************************
Synopsis [Constructing window.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Sbd_ManPropagateControlOne( Sbd_Man_t * p, int Node )
{
Gia_Obj_t * pNode = Gia_ManObj(p->pGia, Node); int w;
int iObj0 = Gia_ObjFaninId0(pNode, Node);
int iObj1 = Gia_ObjFaninId1(pNode, Node);
// word * pSims = Sbd_ObjSim0(p, Node);
// word * pSims0 = Sbd_ObjSim0(p, iObj0);
// word * pSims1 = Sbd_ObjSim0(p, iObj1);
word * pCtrl = Sbd_ObjSim2(p, Node);
word * pCtrl0 = Sbd_ObjSim2(p, iObj0);
word * pCtrl1 = Sbd_ObjSim2(p, iObj1);
word * pDtrl = Sbd_ObjSim3(p, Node);
word * pDtrl0 = Sbd_ObjSim3(p, iObj0);
word * pDtrl1 = Sbd_ObjSim3(p, iObj1);
// Gia_ObjPrint( p->pGia, pNode );
// printf( "Node %2d : %d %d\n\n", Node, (int)(pSims[0] & 1), (int)(pCtrl[0] & 1) );
for ( w = 0; w < p->pPars->nWords; w++ )
{
// word Sim0 = Gia_ObjFaninC0(pNode) ? ~pSims0[w] : pSims0[w];
// word Sim1 = Gia_ObjFaninC1(pNode) ? ~pSims1[w] : pSims1[w];
pCtrl0[w] |= pCtrl[w];// & (pSims[w] | Sim1 | (~Sim0 & ~Sim1));
pCtrl1[w] |= pCtrl[w];// & (pSims[w] | Sim0 | (~Sim0 & ~Sim1));
pDtrl0[w] |= pDtrl[w];// & (pSims[w] | Sim1 | (~Sim0 & ~Sim1));
pDtrl1[w] |= pDtrl[w];// & (pSims[w] | Sim0 | (~Sim0 & ~Sim1));
}
}
void Sbd_ManPropagateControl( Sbd_Man_t * p, int Pivot )
{
abctime clk = Abc_Clock();
int i, Node;
Abc_TtCopy( Sbd_ObjSim3(p, Pivot), Sbd_ObjSim2(p, Pivot), p->pPars->nWords, 0 );
// clean controlability
for ( i = 0; i < Vec_IntEntry(p->vObj2Var, Pivot) && ((Node = Vec_IntEntry(p->vWinObjs, i)), 1); i++ )
{
Abc_TtClear( Sbd_ObjSim2(p, Node), p->pPars->nWords );
Abc_TtClear( Sbd_ObjSim3(p, Node), p->pPars->nWords );
//printf( "Clearing node %d.\n", Node );
}
// propagate controlability to fanins for the TFI nodes starting from the pivot
for ( i = Vec_IntEntry(p->vObj2Var, Pivot); i >= 0 && ((Node = Vec_IntEntry(p->vWinObjs, i)), 1); i-- )
if ( Gia_ObjIsAnd(Gia_ManObj(p->pGia, Node)) )
Sbd_ManPropagateControlOne( p, Node );
p->timeWin += Abc_Clock() - clk;
}
void Sbd_ManUpdateOrder( Sbd_Man_t * p, int Pivot )
{
int i, k, Node;
Vec_Int_t * vLevel;
int nTimeValidDivs = 0;
// collect divisors by logic level
int LevelMax = Vec_IntEntry(p->vLutLevs, Pivot);
Vec_WecClear( p->vDivLevels );
Vec_WecInit( p->vDivLevels, LevelMax + 1 );
Vec_IntForEachEntry( p->vWinObjs, Node, i )
Vec_WecPush( p->vDivLevels, Vec_IntEntry(p->vLutLevs, Node), Node );
// reload divisors
Vec_IntClear( p->vWinObjs );
Vec_WecForEachLevel( p->vDivLevels, vLevel, i )
{
Vec_IntSort( vLevel, 0 );
Vec_IntForEachEntry( vLevel, Node, k )
{
Vec_IntWriteEntry( p->vObj2Var, Node, Vec_IntSize(p->vWinObjs) );
Vec_IntPush( p->vWinObjs, Node );
}
// remember divisor cutoff
if ( i == LevelMax - 2 )
nTimeValidDivs = Vec_IntSize(p->vWinObjs);
}
assert( nTimeValidDivs > 0 );
Vec_IntClear( p->vDivVars );
p->DivCutoff = -1;
Vec_IntForEachEntryStartStop( p->vWinObjs, Node, i, Abc_MaxInt(0, nTimeValidDivs-63), nTimeValidDivs )
{
if ( p->DivCutoff == -1 && Vec_IntEntry(p->vLutLevs, Node) == LevelMax - 2 )
p->DivCutoff = Vec_IntSize(p->vDivVars);
Vec_IntPush( p->vDivVars, i );
}
if ( p->DivCutoff == -1 )
p->DivCutoff = 0;
// verify
/*
assert( Vec_IntSize(p->vDivVars) < 64 );
Vec_IntForEachEntryStart( p->vDivVars, Node, i, p->DivCutoff )
assert( Vec_IntEntry(p->vLutLevs, Vec_IntEntry(p->vWinObjs, Node)) == LevelMax - 2 );
Vec_IntForEachEntryStop( p->vDivVars, Node, i, p->DivCutoff )
assert( Vec_IntEntry(p->vLutLevs, Vec_IntEntry(p->vWinObjs, Node)) < LevelMax - 2 );
*/
Vec_IntFill( p->vDivValues, Vec_IntSize(p->vDivVars), 0 );
//printf( "%d ", Vec_IntSize(p->vDivVars) );
// printf( "Node %4d : Win = %5d. Divs = %5d. D1 = %5d. D2 = %5d.\n",
// Pivot, Vec_IntSize(p->vWinObjs), Vec_IntSize(p->vDivVars), Vec_IntSize(p->vDivVars)-p->DivCutoff, p->DivCutoff );
}
void Sbd_ManWindowSim_rec( Sbd_Man_t * p, int NodeInit )
{
Gia_Obj_t * pObj;
int Node = NodeInit;
if ( Vec_IntEntry(p->vMirrors, Node) >= 0 )
Node = Abc_Lit2Var( Vec_IntEntry(p->vMirrors, Node) );
if ( Gia_ObjIsTravIdCurrentId(p->pGia, Node) )
return;
Gia_ObjSetTravIdCurrentId(p->pGia, Node);
pObj = Gia_ManObj( p->pGia, Node );
if ( Gia_ObjIsAnd(pObj) )
{
Sbd_ManWindowSim_rec( p, Gia_ObjFaninId0(pObj, Node) );
Sbd_ManWindowSim_rec( p, Gia_ObjFaninId1(pObj, Node) );
}
if ( !pObj->fMark0 )
{
Vec_IntWriteEntry( p->vObj2Var, Node, Vec_IntSize(p->vWinObjs) );
Vec_IntPush( p->vWinObjs, Node );
}
if ( Gia_ObjIsCi(pObj) )
return;
// simulate
assert( Gia_ObjIsAnd(pObj) );
if ( Gia_ObjIsXor(pObj) )
{
Abc_TtXor( Sbd_ObjSim0(p, Node),
Sbd_ObjSim0(p, Gia_ObjFaninId0(pObj, Node)),
Sbd_ObjSim0(p, Gia_ObjFaninId1(pObj, Node)),
p->pPars->nWords,
Gia_ObjFaninC0(pObj) ^ Gia_ObjFaninC1(pObj) );
if ( pObj->fMark0 )
Abc_TtXor( Sbd_ObjSim1(p, Node),
Gia_ObjFanin0(pObj)->fMark0 ? Sbd_ObjSim1(p, Gia_ObjFaninId0(pObj, Node)) : Sbd_ObjSim0(p, Gia_ObjFaninId0(pObj, Node)),
Gia_ObjFanin1(pObj)->fMark0 ? Sbd_ObjSim1(p, Gia_ObjFaninId1(pObj, Node)) : Sbd_ObjSim0(p, Gia_ObjFaninId1(pObj, Node)),
p->pPars->nWords,
Gia_ObjFaninC0(pObj) ^ Gia_ObjFaninC1(pObj) );
}
else
{
Abc_TtAndCompl( Sbd_ObjSim0(p, Node),
Sbd_ObjSim0(p, Gia_ObjFaninId0(pObj, Node)), Gia_ObjFaninC0(pObj),
Sbd_ObjSim0(p, Gia_ObjFaninId1(pObj, Node)), Gia_ObjFaninC1(pObj),
p->pPars->nWords );
if ( pObj->fMark0 )
Abc_TtAndCompl( Sbd_ObjSim1(p, Node),
Gia_ObjFanin0(pObj)->fMark0 ? Sbd_ObjSim1(p, Gia_ObjFaninId0(pObj, Node)) : Sbd_ObjSim0(p, Gia_ObjFaninId0(pObj, Node)), Gia_ObjFaninC0(pObj),
Gia_ObjFanin1(pObj)->fMark0 ? Sbd_ObjSim1(p, Gia_ObjFaninId1(pObj, Node)) : Sbd_ObjSim0(p, Gia_ObjFaninId1(pObj, Node)), Gia_ObjFaninC1(pObj),
p->pPars->nWords );
}
if ( Node != NodeInit )
Abc_TtCopy( Sbd_ObjSim0(p, NodeInit), Sbd_ObjSim0(p, Node), p->pPars->nWords, Abc_LitIsCompl(Vec_IntEntry(p->vMirrors, NodeInit)) );
}
int Sbd_ManWindow( Sbd_Man_t * p, int Pivot )
{
abctime clk = Abc_Clock();
int i, Node;
// assign pivot and TFO (assume siminfo is assigned at the PIs)
p->Pivot = Pivot;
p->vTfo = Vec_WecEntry( p->vTfos, Pivot );
// add constant node
Vec_IntClear( p->vWinObjs );
Vec_IntWriteEntry( p->vObj2Var, 0, Vec_IntSize(p->vWinObjs) );
Vec_IntPush( p->vWinObjs, 0 );
// simulate TFI cone
Gia_ManIncrementTravId( p->pGia );
Gia_ObjSetTravIdCurrentId(p->pGia, 0);
Sbd_ManWindowSim_rec( p, Pivot );
if ( p->pPars->nWinSizeMax && Vec_IntSize(p->vWinObjs) > p->pPars->nWinSizeMax )
{
p->timeWin += Abc_Clock() - clk;
return 0;
}
Sbd_ManUpdateOrder( p, Pivot );
assert( Vec_IntSize(p->vDivVars) == Vec_IntSize(p->vDivValues) );
assert( Vec_IntSize(p->vDivVars) < Vec_IntSize(p->vWinObjs) );
// simulate node
Gia_ManObj(p->pGia, Pivot)->fMark0 = 1;
Abc_TtCopy( Sbd_ObjSim1(p, Pivot), Sbd_ObjSim0(p, Pivot), p->pPars->nWords, 1 );
// mark TFO and simulate extended TFI without adding TFO nodes
Vec_IntClear( p->vRoots );
Vec_IntForEachEntry( p->vTfo, Node, i )
{
Gia_ManObj(p->pGia, Abc_Lit2Var(Node))->fMark0 = 1;
if ( !Abc_LitIsCompl(Node) )
continue;
Sbd_ManWindowSim_rec( p, Abc_Lit2Var(Node) );
Vec_IntPush( p->vRoots, Abc_Lit2Var(Node) );
}
// add TFO nodes and remove marks
Gia_ManObj(p->pGia, Pivot)->fMark0 = 0;
Vec_IntForEachEntry( p->vTfo, Node, i )
{
Gia_ManObj(p->pGia, Abc_Lit2Var(Node))->fMark0 = 0;
Vec_IntWriteEntry( p->vObj2Var, Abc_Lit2Var(Node), Vec_IntSize(p->vWinObjs) );
Vec_IntPush( p->vWinObjs, Abc_Lit2Var(Node) );
}
if ( p->pPars->nWinSizeMax && Vec_IntSize(p->vWinObjs) > p->pPars->nWinSizeMax )
{
p->timeWin += Abc_Clock() - clk;
return 0;
}
// compute controlability for node
if ( Vec_IntSize(p->vTfo) == 0 )
Abc_TtFill( Sbd_ObjSim2(p, Pivot), p->pPars->nWords );
else
Abc_TtClear( Sbd_ObjSim2(p, Pivot), p->pPars->nWords );
Vec_IntForEachEntry( p->vTfo, Node, i )
if ( Abc_LitIsCompl(Node) ) // root
Abc_TtOrXor( Sbd_ObjSim2(p, Pivot), Sbd_ObjSim0(p, Abc_Lit2Var(Node)), Sbd_ObjSim1(p, Abc_Lit2Var(Node)), p->pPars->nWords );
p->timeWin += Abc_Clock() - clk;
// propagate controlability to fanins for the TFI nodes starting from the pivot
Sbd_ManPropagateControl( p, Pivot );
assert( Vec_IntSize(p->vDivValues) <= 64 );
return (int)(Vec_IntSize(p->vDivValues) <= 64);
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Sbd_ManCheckConst( Sbd_Man_t * p, int Pivot )
{
int nMintCount = 1;
Vec_Ptr_t * vSims;
word * pSims = Sbd_ObjSim0( p, Pivot );
word * pCtrl = Sbd_ObjSim2( p, Pivot );
int PivotVar = Vec_IntEntry(p->vObj2Var, Pivot);
int RetValue, i, iObj, Ind, fFindOnset, nCares[2] = {0};
abctime clk = Abc_Clock();
p->pSat = Sbd_ManSatSolver( p->pSat, p->pGia, p->vMirrors, Pivot, p->vWinObjs, p->vObj2Var, p->vTfo, p->vRoots, 0 );
p->timeCnf += Abc_Clock() - clk;
if ( p->pSat == NULL )
{
//if ( p->pPars->fVerbose )
// printf( "Found stuck-at-%d node %d.\n", 0, Pivot );
Vec_IntWriteEntry( p->vLutLevs, Pivot, 0 );
p->nLuts[0]++;
return 0;
}
//return -1;
//Sbd_ManPrintObj( p, Pivot );
// count the number of on-set and off-set care-set minterms
Vec_IntClear( p->vLits );
for ( i = 0; i < 64; i++ )
if ( Abc_TtGetBit(pCtrl, i) )
nCares[Abc_TtGetBit(pSims, i)]++;
else
Vec_IntPush( p->vLits, i );
fFindOnset = (int)(nCares[0] < nCares[1]);
if ( nCares[0] >= nMintCount && nCares[1] >= nMintCount )
return -1;
// find how many do we need
nCares[0] = nCares[0] < nMintCount ? nMintCount - nCares[0] : 0;
nCares[1] = nCares[1] < nMintCount ? nMintCount - nCares[1] : 0;
if ( p->pPars->fVeryVerbose )
printf( "Computing %d offset and %d onset minterms for node %d.\n", nCares[0], nCares[1], Pivot );
if ( Vec_IntSize(p->vLits) >= nCares[0] + nCares[1] )
Vec_IntShrink( p->vLits, nCares[0] + nCares[1] );
else
{
// collect places to insert new minterms
for ( i = 0; i < 64 && Vec_IntSize(p->vLits) < nCares[0] + nCares[1]; i++ )
if ( fFindOnset == Abc_TtGetBit(pSims, i) )
Vec_IntPush( p->vLits, i );
}
// collect simulation pointers
vSims = Vec_PtrAlloc( PivotVar + 1 );
Vec_IntForEachEntry( p->vWinObjs, iObj, i )
{
Vec_PtrPush( vSims, Sbd_ObjSim0(p, iObj) );
if ( iObj == Pivot )
break;
}
assert( i == PivotVar );
// compute patterns
RetValue = Sbd_ManCollectConstants( p->pSat, nCares, PivotVar, (word **)Vec_PtrArray(vSims), p->vLits );
// print computed miterms
if ( 0 && RetValue < 0 )
{
Vec_Int_t * vPis = Vec_WecEntry(p->vDivLevels, 0);
int i, k, Ind;
printf( "Additional minterms:\n" );
Vec_IntForEachEntry( p->vLits, Ind, k )
{
for ( i = 0; i < Vec_IntSize(vPis); i++ )
printf( "%d", Abc_TtGetBit( (word *)Vec_PtrEntry(vSims, Vec_IntEntry(p->vWinObjs, i)), Ind ) );
printf( "\n" );
}
}
Vec_PtrFree( vSims );
if ( RetValue >= 0 )
{
if ( p->pPars->fVeryVerbose )
printf( "Found stuck-at-%d node %d.\n", RetValue, Pivot );
Vec_IntWriteEntry( p->vLutLevs, Pivot, 0 );
p->nLuts[0]++;
return RetValue;
}
// set controlability of these minterms
Vec_IntForEachEntry( p->vLits, Ind, i )
Abc_TtSetBit( pCtrl, Ind );
// propagate controlability to fanins for the TFI nodes starting from the pivot
Sbd_ManPropagateControl( p, Pivot );
// double check that we now have enough minterms
for ( i = 0; i < 64; i++ )
if ( Abc_TtGetBit(pCtrl, i) )
nCares[Abc_TtGetBit(pSims, i)]++;
assert( nCares[0] >= nMintCount && nCares[1] >= nMintCount );
return -1;
}
/**Function*************************************************************
Synopsis [Transposing 64-bit matrix.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Sbd_TransposeMatrix64( word A[64] )
{
int j, k;
word t, m = 0x00000000FFFFFFFF;
for ( j = 32; j != 0; j = j >> 1, m = m ^ (m << j) )
{
for ( k = 0; k < 64; k = (k + j + 1) & ~j )
{
t = (A[k] ^ (A[k+j] >> j)) & m;
A[k] = A[k] ^ t;
A[k+j] = A[k+j] ^ (t << j);
}
}
}
static inline void Sbd_PrintMatrix64( word A[64] )
{
int j, k;
for ( j = 0; j < 64; j++, printf("\n") )
for ( k = 0; k < 64; k++ )
printf( "%d", (int)((A[j] >> k) & 1) );
printf( "\n" );
}
/**Function*************************************************************
Synopsis [Profiling divisor candidates.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Sbd_ManPrintObj( Sbd_Man_t * p, int Pivot )
{
int nDivs = Vec_IntEntry(p->vObj2Var, Pivot) + 1;
int i, k, k0, k1, Id, Bit0, Bit1;
Vec_IntForEachEntryStop( p->vWinObjs, Id, i, nDivs )
printf( "%3d : ", Id ), Extra_PrintBinary( stdout, (unsigned *)Sbd_ObjSim0(p, Id), 64 ), printf( "\n" );
assert( p->Pivot == Pivot );
Vec_IntClear( p->vCounts[0] );
Vec_IntClear( p->vCounts[1] );
printf( "Node %d. Useful divisors = %d.\n", Pivot, Vec_IntSize(p->vDivValues) );
printf( "Lev : " );
Vec_IntForEachEntryStop( p->vWinObjs, Id, i, nDivs )
{
if ( i == nDivs-1 )
printf( " " );
printf( "%d", Vec_IntEntry(p->vLutLevs, Id) );
}
printf( "\n" );
printf( "\n" );
if ( nDivs > 99 )
{
printf( " : " );
Vec_IntForEachEntryStop( p->vWinObjs, Id, i, nDivs )
{
if ( i == nDivs-1 )
printf( " " );
printf( "%d", Id / 100 );
}
printf( "\n" );
}
if ( nDivs > 9 )
{
printf( " : " );
Vec_IntForEachEntryStop( p->vWinObjs, Id, i, nDivs )
{
if ( i == nDivs-1 )
printf( " " );
printf( "%d", (Id % 100) / 10 );
}
printf( "\n" );
}
if ( nDivs > 0 )
{
printf( " : " );
Vec_IntForEachEntryStop( p->vWinObjs, Id, i, nDivs )
{
if ( i == nDivs-1 )
printf( " " );
printf( "%d", Id % 10 );
}
printf( "\n" );
printf( "\n" );
}
// sampling matrix
for ( k = 0; k < p->pPars->nWords * 64; k++ )
{
if ( !Abc_TtGetBit(Sbd_ObjSim2(p, Pivot), k) )
continue;
printf( "%3d : ", k );
Vec_IntForEachEntryStop( p->vWinObjs, Id, i, nDivs )
{
word * pSims = Sbd_ObjSim0( p, Id );
word * pCtrl = Sbd_ObjSim2( p, Id );
if ( i == nDivs-1 )
{
if ( Abc_TtGetBit(pCtrl, k) )
Vec_IntPush( p->vCounts[Abc_TtGetBit(pSims, k)], k );
printf( " " );
}
printf( "%c", Abc_TtGetBit(pCtrl, k) ? '0' + Abc_TtGetBit(pSims, k) : '.' );
}
printf( "\n" );
printf( "%3d : ", k );
Vec_IntForEachEntryStop( p->vWinObjs, Id, i, nDivs )
{
word * pSims = Sbd_ObjSim0( p, Id );
word * pCtrl = Sbd_ObjSim3( p, Id );
if ( i == nDivs-1 )
{
if ( Abc_TtGetBit(pCtrl, k) )
Vec_IntPush( p->vCounts[Abc_TtGetBit(pSims, k)], k );
printf( " " );
}
printf( "%c", Abc_TtGetBit(pCtrl, k) ? '0' + Abc_TtGetBit(pSims, k) : '.' );
}
printf( "\n" );
printf( "Sims: " );
Vec_IntForEachEntryStop( p->vWinObjs, Id, i, nDivs )
{
word * pSims = Sbd_ObjSim0( p, Id );
//word * pCtrl = Sbd_ObjSim2( p, Id );
if ( i == nDivs-1 )
printf( " " );
printf( "%c", '0' + Abc_TtGetBit(pSims, k) );
}
printf( "\n" );
printf( "Ctrl: " );
Vec_IntForEachEntryStop( p->vWinObjs, Id, i, nDivs )
{
//word * pSims = Sbd_ObjSim0( p, Id );
word * pCtrl = Sbd_ObjSim2( p, Id );
if ( i == nDivs-1 )
printf( " " );
printf( "%c", '0' + Abc_TtGetBit(pCtrl, k) );
}
printf( "\n" );
printf( "\n" );
}
// covering table
printf( "Exploring %d x %d covering table.\n", Vec_IntSize(p->vCounts[0]), Vec_IntSize(p->vCounts[1]) );
/*
Vec_IntForEachEntryStop( p->vCounts[0], Bit0, k0, Abc_MinInt(Vec_IntSize(p->vCounts[0]), 8) )
Vec_IntForEachEntryStop( p->vCounts[1], Bit1, k1, Abc_MinInt(Vec_IntSize(p->vCounts[1]), 8) )
{
printf( "%3d %3d : ", Bit0, Bit1 );
Vec_IntForEachEntryStop( p->vWinObjs, Id, i, nDivs )
{
word * pSims = Sbd_ObjSim0( p, Id );
word * pCtrl = Sbd_ObjSim2( p, Id );
if ( i == nDivs-1 )
printf( " " );
printf( "%c", (Abc_TtGetBit(pCtrl, Bit0) && Abc_TtGetBit(pCtrl, Bit1) && Abc_TtGetBit(pSims, Bit0) != Abc_TtGetBit(pSims, Bit1)) ? '1' : '.' );
}
printf( "\n" );
}
*/
Vec_WrdClear( p->vMatrix );
Vec_IntForEachEntryStop( p->vCounts[0], Bit0, k0, Abc_MinInt(Vec_IntSize(p->vCounts[0]), 64) )
Vec_IntForEachEntryStop( p->vCounts[1], Bit1, k1, Abc_MinInt(Vec_IntSize(p->vCounts[1]), 64) )
{
word Row = 0;
Vec_IntForEachEntryStop( p->vWinObjs, Id, i, nDivs )
{
word * pSims = Sbd_ObjSim0( p, Id );
word * pCtrl = Sbd_ObjSim2( p, Id );
if ( Abc_TtGetBit(pCtrl, Bit0) && Abc_TtGetBit(pCtrl, Bit1) && Abc_TtGetBit(pSims, Bit0) != Abc_TtGetBit(pSims, Bit1) )
Abc_TtXorBit( &Row, i );
}
if ( Vec_WrdPushUnique( p->vMatrix, Row ) )
continue;
for ( i = 0; i < nDivs; i++ )
printf( "%d", (int)((Row >> i) & 1) );
printf( "\n" );
}
}
void Sbd_ManMatrPrint( Sbd_Man_t * p, word Cover[], int nCol, int nRows )
{
int i, k;
for ( i = 0; i <= nCol; i++ )
{
printf( "%2d : ", i );
printf( "%d ", i == nCol ? Vec_IntEntry(p->vLutLevs, p->Pivot) : Vec_IntEntry(p->vLutLevs, Vec_IntEntry(p->vWinObjs, Vec_IntEntry(p->vDivVars, i))) );
for ( k = 0; k < nRows; k++ )
printf( "%d", (int)((Cover[i] >> k) & 1) );
printf( "\n");
}
printf( "\n");
}
static inline void Sbd_ManCoverReverseOrder( word Cover[64] )
{
int i;
for ( i = 0; i < 32; i++ )
{
word Cube = Cover[i];
Cover[i] = Cover[63-i];
Cover[63-i] = Cube;
}
}
static inline int Sbd_ManAddCube1( int nRowLimit, word Cover[], int nRows, word Cube )
{
int n, m;
if ( 0 )
{
printf( "Adding cube: " );
for ( n = 0; n < nRowLimit; n++ )
printf( "%d", (int)((Cube >> n) & 1) );
printf( "\n" );
}
// do not add contained Cube
assert( nRows <= nRowLimit );
for ( n = 0; n < nRows; n++ )
if ( (Cover[n] & Cube) == Cover[n] ) // Cube is contained
return nRows;
// remove rows contained by Cube
for ( n = m = 0; n < nRows; n++ )
if ( (Cover[n] & Cube) != Cube ) // Cover[n] is not contained
Cover[m++] = Cover[n];
if ( m < nRowLimit )
Cover[m++] = Cube;
for ( n = m; n < nRows; n++ )
Cover[n] = 0;
nRows = m;
return nRows;
}
static inline int Sbd_ManAddCube2( word Cover[2][64], int nRows, word Cube[2] )
{
int n, m;
// do not add contained Cube
assert( nRows <= 64 );
for ( n = 0; n < nRows; n++ )
if ( (Cover[0][n] & Cube[0]) == Cover[0][n] && (Cover[1][n] & Cube[1]) == Cover[1][n] ) // Cube is contained
return nRows;
// remove rows contained by Cube
for ( n = m = 0; n < nRows; n++ )
if ( (Cover[0][n] & Cube[0]) != Cube[0] || (Cover[1][n] & Cube[1]) != Cube[1] ) // Cover[n] is not contained
{
Cover[0][m] = Cover[0][n];
Cover[1][m] = Cover[1][n];
m++;
}
if ( m < 64 )
{
Cover[0][m] = Cube[0];
Cover[1][m] = Cube[1];
m++;
}
for ( n = m; n < nRows; n++ )
Cover[0][n] = Cover[1][n] = 0;
nRows = m;
return nRows;
}
static inline int Sbd_ManFindCandsSimple( Sbd_Man_t * p, word Cover[], int nDivs )
{
int c0, c1, c2, c3;
word Target = Cover[nDivs];
Vec_IntClear( p->vDivSet );
for ( c0 = 0; c0 < nDivs; c0++ )
if ( Cover[c0] == Target )
{
Vec_IntPush( p->vDivSet, c0 );
return 1;
}
for ( c0 = 0; c0 < nDivs; c0++ )
for ( c1 = c0+1; c1 < nDivs; c1++ )
if ( (Cover[c0] | Cover[c1]) == Target )
{
Vec_IntPush( p->vDivSet, c0 );
Vec_IntPush( p->vDivSet, c1 );
return 1;
}
for ( c0 = 0; c0 < nDivs; c0++ )
for ( c1 = c0+1; c1 < nDivs; c1++ )
for ( c2 = c1+1; c2 < nDivs; c2++ )
if ( (Cover[c0] | Cover[c1] | Cover[c2]) == Target )
{
Vec_IntPush( p->vDivSet, c0 );
Vec_IntPush( p->vDivSet, c1 );
Vec_IntPush( p->vDivSet, c2 );
return 1;
}
for ( c0 = 0; c0 < nDivs; c0++ )
for ( c1 = c0+1; c1 < nDivs; c1++ )
for ( c2 = c1+1; c2 < nDivs; c2++ )
for ( c3 = c2+1; c3 < nDivs; c3++ )
{
if ( (Cover[c0] | Cover[c1] | Cover[c2] | Cover[c3]) == Target )
{
Vec_IntPush( p->vDivSet, c0 );
Vec_IntPush( p->vDivSet, c1 );
Vec_IntPush( p->vDivSet, c2 );
Vec_IntPush( p->vDivSet, c3 );
return 1;
}
}
return 0;
}
static inline int Sbd_ManFindCands( Sbd_Man_t * p, word Cover[64], int nDivs )
{
int Ones[64], Order[64];
int Limits[4] = { nDivs/4+1, nDivs/3+2, nDivs/2+3, nDivs };
int c0, c1, c2, c3;
word Target = Cover[nDivs];
if ( nDivs < 8 || p->pPars->fCover )
return Sbd_ManFindCandsSimple( p, Cover, nDivs );
Vec_IntClear( p->vDivSet );
for ( c0 = 0; c0 < nDivs; c0++ )
if ( Cover[c0] == Target )
{
Vec_IntPush( p->vDivSet, c0 );
return 1;
}
for ( c0 = 0; c0 < nDivs; c0++ )
for ( c1 = c0+1; c1 < nDivs; c1++ )
if ( (Cover[c0] | Cover[c1]) == Target )
{
Vec_IntPush( p->vDivSet, c0 );
Vec_IntPush( p->vDivSet, c1 );
return 1;
}
// count ones
for ( c0 = 0; c0 < nDivs; c0++ )
Ones[c0] = Abc_TtCountOnes( Cover[c0] );
// sort by the number of ones
for ( c0 = 0; c0 < nDivs; c0++ )
Order[c0] = c0;
Vec_IntSelectSortCost2Reverse( Order, nDivs, Ones );
// sort with limits
for ( c0 = 0; c0 < Limits[0]; c0++ )
for ( c1 = c0+1; c1 < Limits[1]; c1++ )
for ( c2 = c1+1; c2 < Limits[2]; c2++ )
if ( (Cover[Order[c0]] | Cover[Order[c1]] | Cover[Order[c2]]) == Target )
{
Vec_IntPush( p->vDivSet, Order[c0] );
Vec_IntPush( p->vDivSet, Order[c1] );
Vec_IntPush( p->vDivSet, Order[c2] );
return 1;
}
for ( c0 = 0; c0 < Limits[0]; c0++ )
for ( c1 = c0+1; c1 < Limits[1]; c1++ )
for ( c2 = c1+1; c2 < Limits[2]; c2++ )
for ( c3 = c2+1; c3 < Limits[3]; c3++ )
{
if ( (Cover[Order[c0]] | Cover[Order[c1]] | Cover[Order[c2]] | Cover[Order[c3]]) == Target )
{
Vec_IntPush( p->vDivSet, Order[c0] );
Vec_IntPush( p->vDivSet, Order[c1] );
Vec_IntPush( p->vDivSet, Order[c2] );
Vec_IntPush( p->vDivSet, Order[c3] );
return 1;
}
}
return 0;
}
int Sbd_ManExplore( Sbd_Man_t * p, int Pivot, word * pTruth )
{
int fVerbose = 0;
abctime clk;
int nIters, nItersMax = 32;
word MatrS[64] = {0}, MatrC[2][64] = {{0}}, Cubes[2][2][64] = {{{0}}}, Cover[64] = {0}, Cube, CubeNew[2];
int i, k, n, Node, Index, nCubes[2] = {0}, nRows = 0, nRowsOld;
int nDivs = Vec_IntSize(p->vDivValues);
int PivotVar = Vec_IntEntry(p->vObj2Var, Pivot);
int FreeVar = Vec_IntSize(p->vWinObjs) + Vec_IntSize(p->vTfo) + Vec_IntSize(p->vRoots);
int RetValue = 0;
if ( p->pPars->fVerbose )
printf( "Node %d. Useful divisors = %d.\n", Pivot, nDivs );
if ( fVerbose )
Sbd_ManPrintObj( p, Pivot );
// collect bit-matrices
Vec_IntForEachEntry( p->vDivVars, Node, i )
{
MatrS[63-i] = *Sbd_ObjSim0( p, Vec_IntEntry(p->vWinObjs, Node) );
MatrC[0][63-i] = *Sbd_ObjSim2( p, Vec_IntEntry(p->vWinObjs, Node) );
MatrC[1][63-i] = *Sbd_ObjSim3( p, Vec_IntEntry(p->vWinObjs, Node) );
}
MatrS[63-i] = *Sbd_ObjSim0( p, Pivot );
MatrC[0][63-i] = *Sbd_ObjSim2( p, Pivot );
MatrC[1][63-i] = *Sbd_ObjSim3( p, Pivot );
//Sbd_PrintMatrix64( MatrS );
Sbd_TransposeMatrix64( MatrS );
Sbd_TransposeMatrix64( MatrC[0] );
Sbd_TransposeMatrix64( MatrC[1] );
//Sbd_PrintMatrix64( MatrS );
// collect cubes
for ( i = 0; i < 64; i++ )
{
assert( Abc_TtGetBit(&MatrC[0][i], nDivs) == Abc_TtGetBit(&MatrC[1][i], nDivs) );
if ( !Abc_TtGetBit(&MatrC[0][i], nDivs) )
continue;
Index = Abc_TtGetBit(&MatrS[i], nDivs); // Index==0 offset; Index==1 onset
for ( n = 0; n < 2; n++ )
{
if ( n && MatrC[0][i] == MatrC[1][i] )
continue;
assert( MatrC[n][i] );
CubeNew[0] = ~MatrS[i] & MatrC[n][i];
CubeNew[1] = MatrS[i] & MatrC[n][i];
assert( CubeNew[0] || CubeNew[1] );
nCubes[Index] = Sbd_ManAddCube2( Cubes[Index], nCubes[Index], CubeNew );
}
}
if ( p->pPars->fVerbose )
printf( "Generated matrix with %d x %d entries.\n", nCubes[0], nCubes[1] );
if ( p->pPars->fVerbose )
for ( n = 0; n < 2; n++ )
{
printf( "%s:\n", n ? "Onset" : "Offset" );
for ( i = 0; i < nCubes[n]; i++, printf( "\n" ) )
for ( k = 0; k < 64; k++ )
if ( Abc_TtGetBit(&Cubes[n][0][i], k) )
printf( "0" );
else if ( Abc_TtGetBit(&Cubes[n][1][i], k) )
printf( "1" );
else
printf( "." );
printf( "\n" );
}
// create covering table
nRows = 0;
for ( i = 0; i < nCubes[0] && nRows < 32; i++ )
for ( k = 0; k < nCubes[1] && nRows < 32; k++ )
{
Cube = (Cubes[0][1][i] & Cubes[1][0][k]) | (Cubes[0][0][i] & Cubes[1][1][k]);
assert( Cube );
nRows = Sbd_ManAddCube1( 64, Cover, nRows, Cube );
}
Sbd_ManCoverReverseOrder( Cover );
if ( p->pPars->fVerbose )
printf( "Generated cover with %d entries.\n", nRows );
//if ( p->pPars->fVerbose )
//Sbd_PrintMatrix64( Cover );
Sbd_TransposeMatrix64( Cover );
//if ( p->pPars->fVerbose )
//Sbd_PrintMatrix64( Cover );
Sbd_ManCoverReverseOrder( Cover );
nRowsOld = nRows;
for ( nIters = 0; nIters < nItersMax && nRows < 64; nIters++ )
{
if ( p->pPars->fVerbose )
Sbd_ManMatrPrint( p, Cover, nDivs, nRows );
clk = Abc_Clock();
if ( !Sbd_ManFindCands( p, Cover, nDivs ) )
{
if ( p->pPars->fVerbose )
printf( "Cannot find a feasible cover.\n" );
p->timeCov += Abc_Clock() - clk;
return RetValue;
}
p->timeCov += Abc_Clock() - clk;
if ( p->pPars->fVerbose )
printf( "Candidate support: " ),
Vec_IntPrint( p->vDivSet );
clk = Abc_Clock();
*pTruth = Sbd_ManSolve( p->pSat, PivotVar, FreeVar+nIters, p->vDivSet, p->vDivVars, p->vDivValues, p->vLits );
p->timeSat += Abc_Clock() - clk;
if ( *pTruth == SBD_SAT_UNDEC )
printf( "Node %d: Undecided.\n", Pivot );
else if ( *pTruth == SBD_SAT_SAT )
{
if ( p->pPars->fVerbose )
{
int i;
printf( "Node %d: SAT.\n", Pivot );
for ( i = 0; i < nDivs; i++ )
printf( "%d", i % 10 );
printf( "\n" );
for ( i = 0; i < nDivs; i++ )
printf( "%c", (Vec_IntEntry(p->vDivValues, i) & 0x4) ? '0' + (Vec_IntEntry(p->vDivValues, i) & 1) : 'x' );
printf( "\n" );
for ( i = 0; i < nDivs; i++ )
printf( "%c", (Vec_IntEntry(p->vDivValues, i) & 0x8) ? '0' + ((Vec_IntEntry(p->vDivValues, i) >> 1) & 1) : 'x' );
printf( "\n" );
}
// add row to the covering table
for ( i = 0; i < nDivs; i++ )
if ( Vec_IntEntry(p->vDivValues, i) == 0xE || Vec_IntEntry(p->vDivValues, i) == 0xD )
Cover[i] |= ((word)1 << nRows);
Cover[nDivs] |= ((word)1 << nRows);
nRows++;
}
else
{
if ( p->pPars->fVerbose )
{
printf( "Node %d: UNSAT.\n", Pivot );
Extra_PrintBinary( stdout, (unsigned *)pTruth, 1 << Vec_IntSize(p->vDivSet) ), printf( "\n" );
}
RetValue = 1;
break;
}
//break;
}
return RetValue;
}
int Sbd_ManExplore2( Sbd_Man_t * p, int Pivot, word * pTruth )
{
abctime clk;
word Onset[64] = {0}, Offset[64] = {0}, Cube;
word CoverRows[64] = {0}, CoverCols[64] = {0};
int nIters, nItersMax = 32;
int i, k, nRows = 0;
int PivotVar = Vec_IntEntry(p->vObj2Var, Pivot);
int FreeVar = Vec_IntSize(p->vWinObjs) + Vec_IntSize(p->vTfo) + Vec_IntSize(p->vRoots);
int nDivs = Vec_IntSize( p->vDivVars );
int nConsts = 4;
int RetValue;
clk = Abc_Clock();
//sat_solver_delete_p( &p->pSat );
p->pSat = Sbd_ManSatSolver( p->pSat, p->pGia, p->vMirrors, Pivot, p->vWinObjs, p->vObj2Var, p->vTfo, p->vRoots, 0 );
p->timeCnf += Abc_Clock() - clk;
assert( nConsts <= 8 );
clk = Abc_Clock();
RetValue = Sbd_ManCollectConstantsNew( p->pSat, p->vDivVars, nConsts, PivotVar, Onset, Offset );
p->timeSat += Abc_Clock() - clk;
if ( RetValue >= 0 )
{
if ( p->pPars->fVeryVerbose )
printf( "Found stuck-at-%d node %d.\n", RetValue, Pivot );
Vec_IntWriteEntry( p->vLutLevs, Pivot, 0 );
p->nLuts[0]++;
return RetValue;
}
RetValue = 0;
// create rows of the table
nRows = 0;
for ( i = 0; i < nConsts; i++ )
for ( k = 0; k < nConsts; k++ )
{
Cube = Onset[i] ^ Offset[k];
assert( Cube );
nRows = Sbd_ManAddCube1( 256, CoverRows, nRows, Cube );
}
assert( nRows <= 64 );
// create columns of the table
for ( i = 0; i < nRows; i++ )
for ( k = 0; k <= nDivs; k++ )
if ( (CoverRows[i] >> k) & 1 )
Abc_TtXorBit(&CoverCols[k], i);
// solve the covering problem
for ( nIters = 0; nIters < nItersMax && nRows < 64; nIters++ )
{
if ( p->pPars->fVeryVerbose )
Sbd_ManMatrPrint( p, CoverCols, nDivs, nRows );
clk = Abc_Clock();
if ( !Sbd_ManFindCands( p, CoverCols, nDivs ) )
{
if ( p->pPars->fVeryVerbose )
printf( "Cannot find a feasible cover.\n" );
p->timeCov += Abc_Clock() - clk;
return 0;
}
p->timeCov += Abc_Clock() - clk;
if ( p->pPars->fVeryVerbose )
printf( "Candidate support: " ),
Vec_IntPrint( p->vDivSet );
clk = Abc_Clock();
*pTruth = Sbd_ManSolve( p->pSat, PivotVar, FreeVar+nIters, p->vDivSet, p->vDivVars, p->vDivValues, p->vLits );
p->timeSat += Abc_Clock() - clk;
if ( *pTruth == SBD_SAT_UNDEC )
printf( "Node %d: Undecided.\n", Pivot );
else if ( *pTruth == SBD_SAT_SAT )
{
if ( p->pPars->fVeryVerbose )
{
int i;
printf( "Node %d: SAT.\n", Pivot );
for ( i = 0; i < nDivs; i++ )
printf( "%d", Vec_IntEntry(p->vLutLevs, Vec_IntEntry(p->vWinObjs, Vec_IntEntry(p->vDivVars, i))) );
printf( "\n" );
for ( i = 0; i < nDivs; i++ )
printf( "%d", i % 10 );
printf( "\n" );
for ( i = 0; i < nDivs; i++ )
printf( "%c", (Vec_IntEntry(p->vDivValues, i) & 0x4) ? '0' + (Vec_IntEntry(p->vDivValues, i) & 1) : 'x' );
printf( "\n" );
for ( i = 0; i < nDivs; i++ )
printf( "%c", (Vec_IntEntry(p->vDivValues, i) & 0x8) ? '0' + ((Vec_IntEntry(p->vDivValues, i) >> 1) & 1) : 'x' );
printf( "\n" );
}
// add row to the covering table
for ( i = 0; i < nDivs; i++ )
if ( Vec_IntEntry(p->vDivValues, i) == 0xE || Vec_IntEntry(p->vDivValues, i) == 0xD )
CoverCols[i] |= ((word)1 << nRows);
CoverCols[nDivs] |= ((word)1 << nRows);
nRows++;
}
else
{
if ( p->pPars->fVeryVerbose )
{
printf( "Node %d: UNSAT. ", Pivot );
Extra_PrintBinary( stdout, (unsigned *)pTruth, 1 << Vec_IntSize(p->vDivSet) ), printf( "\n" );
}
p->nLuts[1]++;
RetValue = 1;
break;
}
}
return RetValue;
}
int Sbd_ManExploreCut( Sbd_Man_t * p, int Pivot, int nLeaves, int * pLeaves, int * pnStrs, Sbd_Str_t * Strs, int * pFreeVar )
{
abctime clk = Abc_Clock();
int PivotVar = Vec_IntEntry(p->vObj2Var, Pivot);
int Delay = Vec_IntEntry( p->vLutLevs, Pivot );
int pNodesTop[SBD_DIV_MAX], pNodesBot[SBD_DIV_MAX], pNodesBot1[SBD_DIV_MAX], pNodesBot2[SBD_DIV_MAX];
int nNodesTop = 0, nNodesBot = 0, nNodesBot1 = 0, nNodesBot2 = 0, nNodesDiff = 0, nNodesDiff1 = 0, nNodesDiff2 = 0;
int i, k, iObj, nIters, RetValue = 0;
// try to remove fanins
for ( nIters = 0; nIters < nLeaves; nIters++ )
{
word Truth;
// try to remove one variable from divisors
Vec_IntClear( p->vDivSet );
for ( i = 0; i < nLeaves; i++ )
if ( i != nLeaves-1-nIters && pLeaves[i] != -1 )
Vec_IntPush( p->vDivSet, Vec_IntEntry(p->vObj2Var, pLeaves[i]) );
assert( Vec_IntSize(p->vDivSet) < nLeaves );
// compute truth table
clk = Abc_Clock();
Truth = Sbd_ManSolve( p->pSat, PivotVar, (*pFreeVar)++, p->vDivSet, p->vDivVars, p->vDivValues, p->vLits );
p->timeSat += Abc_Clock() - clk;
if ( Truth == SBD_SAT_UNDEC )
printf( "Node %d: Undecided.\n", Pivot );
else if ( Truth == SBD_SAT_SAT )
{
int DelayDiff = Vec_IntEntry(p->vLutLevs, pLeaves[nLeaves-1-nIters]) - Delay;
if ( DelayDiff > -2 )
return 0;
}
else
pLeaves[nLeaves-1-nIters] = -1;
}
Vec_IntClear( p->vDivSet );
for ( i = 0; i < nLeaves; i++ )
if ( pLeaves[i] != -1 )
Vec_IntPush( p->vDivSet, pLeaves[i] );
//printf( "Reduced %d -> %d\n", nLeaves, Vec_IntSize(p->vDivSet) );
if ( Vec_IntSize(p->vDivSet) <= p->pPars->nLutSize )
{
word Truth;
*pnStrs = 1;
// remap divisors
Vec_IntForEachEntry( p->vDivSet, iObj, i )
Vec_IntWriteEntry( p->vDivSet, i, Vec_IntEntry(p->vObj2Var, iObj) );
// compute truth table
clk = Abc_Clock();
Truth = Sbd_ManSolve( p->pSat, PivotVar, (*pFreeVar)++, p->vDivSet, p->vDivVars, p->vDivValues, p->vLits );
p->timeSat += Abc_Clock() - clk;
if ( Truth == SBD_SAT_SAT )
{
printf( "The cut at node %d is not topological.\n", p->Pivot );
return 0;
}
assert( Truth != SBD_SAT_UNDEC && Truth != SBD_SAT_SAT );
// create structure
Strs->fLut = 1;
Strs->nVarIns = Vec_IntSize( p->vDivSet );
for ( i = 0; i < Strs->nVarIns; i++ )
Strs->VarIns[i] = i;
Strs->Res = Truth;
p->nLuts[1]++;
//Extra_PrintBinary( stdout, (unsigned *)&Truth, 1 << Strs->nVarIns ), printf( "\n" );
return 1;
}
assert( Vec_IntSize(p->vDivSet) > p->pPars->nLutSize );
// count number of nodes on each level
nNodesTop = nNodesBot = nNodesBot1 = nNodesBot2 = 0;
Vec_IntForEachEntry( p->vDivSet, iObj, i )
{
int DelayDiff = Vec_IntEntry(p->vLutLevs, iObj) - Delay;
if ( DelayDiff > -2 )
break;
if ( DelayDiff == -2 )
pNodesTop[nNodesTop++] = i;
else // if ( DelayDiff < -2 )
{
pNodesBot[nNodesBot++] = i;
if ( DelayDiff == -3 )
pNodesBot1[nNodesBot1++] = i;
else // if ( DelayDiff < -3 )
pNodesBot2[nNodesBot2++] = i;
}
Vec_IntWriteEntry( p->vDivSet, i, Vec_IntEntry(p->vObj2Var, iObj) );
}
assert( nNodesBot == nNodesBot1 + nNodesBot2 );
if ( i < Vec_IntSize(p->vDivSet) )
return 0;
if ( nNodesTop > p->pPars->nLutSize-1 )
return 0;
// try 44
if ( Vec_IntSize(p->vDivSet) <= 2*p->pPars->nLutSize-1 )
{
int nMoved = 0;
if ( nNodesBot > p->pPars->nLutSize ) // need to move bottom left-over to the top
{
while ( nNodesBot > p->pPars->nLutSize )
pNodesTop[nNodesTop++] = pNodesBot[--nNodesBot], nMoved++;
assert( nNodesBot == p->pPars->nLutSize );
}
assert( nNodesBot <= p->pPars->nLutSize );
assert( nNodesTop <= p->pPars->nLutSize-1 );
Strs[0].fLut = 1;
Strs[0].nVarIns = p->pPars->nLutSize;
for ( i = 0; i < nNodesTop; i++ )
Strs[0].VarIns[i] = pNodesTop[i];
for ( ; i < p->pPars->nLutSize; i++ )
Strs[0].VarIns[i] = Vec_IntSize(p->vDivSet)+1 + i-nNodesTop;
Strs[0].Res = 0;
Strs[1].fLut = 1;
Strs[1].nVarIns = nNodesBot;
for ( i = 0; i < nNodesBot; i++ )
Strs[1].VarIns[i] = pNodesBot[i];
Strs[1].Res = 0;
nNodesDiff = p->pPars->nLutSize-1 - nNodesTop;
assert( nNodesDiff >= 0 && nNodesDiff <= 3 );
for ( k = 0; k < nNodesDiff; k++ )
{
Strs[2+k].fLut = 0;
Strs[2+k].nVarIns = nNodesBot;
for ( i = 0; i < nNodesBot; i++ )
Strs[2+k].VarIns[i] = pNodesBot[i];
Strs[2+k].Res = 0;
}
*pnStrs = 2 + nNodesDiff;
clk = Abc_Clock();
RetValue = Sbd_ProblemSolve( p->pGia, p->vMirrors, Pivot, p->vWinObjs, p->vObj2Var, p->vTfo, p->vRoots, p->vDivSet, *pnStrs, Strs );
p->timeQbf += Abc_Clock() - clk;
if ( RetValue )
p->nLuts[2]++;
while ( nMoved-- )
pNodesBot[nNodesBot++] = pNodesTop[--nNodesTop];
}
if ( RetValue )
return RetValue;
if ( p->pPars->nLutNum < 3 )
return 0;
if ( Vec_IntSize(p->vDivSet) < 2*p->pPars->nLutSize-1 )
return 0;
// try 444 -- LUT(LUT, LUT)
if ( nNodesTop <= p->pPars->nLutSize-2 )
{
int nMoved = 0;
if ( nNodesBot > 2*p->pPars->nLutSize ) // need to move bottom left-over to the top
{
while ( nNodesBot > 2*p->pPars->nLutSize )
pNodesTop[nNodesTop++] = pNodesBot[--nNodesBot], nMoved++;
assert( nNodesBot == 2*p->pPars->nLutSize );
}
assert( nNodesBot > p->pPars->nLutSize );
assert( nNodesBot <= 2*p->pPars->nLutSize );
assert( nNodesTop <= p->pPars->nLutSize-2 );
Strs[0].fLut = 1;
Strs[0].nVarIns = p->pPars->nLutSize;
for ( i = 0; i < nNodesTop; i++ )
Strs[0].VarIns[i] = pNodesTop[i];
for ( ; i < p->pPars->nLutSize; i++ )
Strs[0].VarIns[i] = Vec_IntSize(p->vDivSet)+1 + i-nNodesTop;
Strs[0].Res = 0;
Strs[1].fLut = 1;
Strs[1].nVarIns = p->pPars->nLutSize;
for ( i = 0; i < Strs[1].nVarIns; i++ )
Strs[1].VarIns[i] = pNodesBot[i];
Strs[1].Res = 0;
Strs[2].fLut = 1;
Strs[2].nVarIns = p->pPars->nLutSize;
for ( i = 0; i < Strs[2].nVarIns; i++ )
Strs[2].VarIns[i] = pNodesBot[nNodesBot-p->pPars->nLutSize+i];
Strs[2].Res = 0;
nNodesDiff = p->pPars->nLutSize-2 - nNodesTop;
assert( nNodesDiff >= 0 && nNodesDiff <= 2 );
for ( k = 0; k < nNodesDiff; k++ )
{
Strs[3+k].fLut = 0;
Strs[3+k].nVarIns = nNodesBot;
for ( i = 0; i < nNodesBot; i++ )
Strs[3+k].VarIns[i] = pNodesBot[i];
Strs[3+k].Res = 0;
}
*pnStrs = 3 + nNodesDiff;
clk = Abc_Clock();
RetValue = Sbd_ProblemSolve( p->pGia, p->vMirrors, Pivot, p->vWinObjs, p->vObj2Var, p->vTfo, p->vRoots, p->vDivSet, *pnStrs, Strs );
p->timeQbf += Abc_Clock() - clk;
if ( RetValue )
p->nLuts[3]++;
while ( nMoved-- )
pNodesBot[nNodesBot++] = pNodesTop[--nNodesTop];
}
if ( RetValue )
return RetValue;
// try 444 -- LUT(LUT(LUT))
if ( nNodesBot1 + nNodesTop <= 2*p->pPars->nLutSize-2 )
{
if ( nNodesBot2 > p->pPars->nLutSize ) // need to move bottom left-over to the top
{
while ( nNodesBot2 > p->pPars->nLutSize )
pNodesBot1[nNodesBot1++] = pNodesBot2[--nNodesBot2];
assert( nNodesBot2 == p->pPars->nLutSize );
}
if ( nNodesBot1 > p->pPars->nLutSize-1 ) // need to move bottom left-over to the top
{
while ( nNodesBot1 > p->pPars->nLutSize-1 )
pNodesTop[nNodesTop++] = pNodesBot1[--nNodesBot1];
assert( nNodesBot1 == p->pPars->nLutSize-1 );
}
assert( nNodesBot2 <= p->pPars->nLutSize );
assert( nNodesBot1 <= p->pPars->nLutSize-1 );
assert( nNodesTop <= p->pPars->nLutSize-1 );
Strs[0].fLut = 1;
Strs[0].nVarIns = p->pPars->nLutSize;
for ( i = 0; i < nNodesTop; i++ )
Strs[0].VarIns[i] = pNodesTop[i];
Strs[0].VarIns[i++] = Vec_IntSize(p->vDivSet)+1;
for ( ; i < p->pPars->nLutSize; i++ )
Strs[0].VarIns[i] = Vec_IntSize(p->vDivSet)+2 + i-nNodesTop;
Strs[0].Res = 0;
nNodesDiff1 = p->pPars->nLutSize-1 - nNodesTop;
Strs[1].fLut = 1;
Strs[1].nVarIns = p->pPars->nLutSize;
for ( i = 0; i < nNodesBot1; i++ )
Strs[1].VarIns[i] = pNodesBot1[i];
Strs[1].VarIns[i++] = Vec_IntSize(p->vDivSet)+2;
for ( ; i < p->pPars->nLutSize; i++ )
Strs[1].VarIns[i] = Vec_IntSize(p->vDivSet)+2+nNodesDiff1 + i-nNodesBot1;
Strs[1].Res = 0;
nNodesDiff2 = p->pPars->nLutSize-1 - nNodesBot1;
Strs[2].fLut = 1;
Strs[2].nVarIns = nNodesBot2;
for ( i = 0; i < Strs[2].nVarIns; i++ )
Strs[2].VarIns[i] = pNodesBot2[i];
Strs[2].Res = 0;
nNodesDiff = nNodesDiff1 + nNodesDiff2;
assert( nNodesDiff >= 0 && nNodesDiff <= 3 );
for ( k = 0; k < nNodesDiff; k++ )
{
Strs[3+k].fLut = 0;
Strs[3+k].nVarIns = nNodesBot2;
for ( i = 0; i < nNodesBot2; i++ )
Strs[3+k].VarIns[i] = pNodesBot2[i];
Strs[3+k].Res = 0;
if ( k >= nNodesDiff1 )
continue;
Strs[3+k].nVarIns += nNodesBot1;
for ( i = 0; i < nNodesBot1; i++ )
Strs[3+k].VarIns[nNodesBot2 + i] = pNodesBot1[i];
}
*pnStrs = 3 + nNodesDiff;
clk = Abc_Clock();
RetValue = Sbd_ProblemSolve( p->pGia, p->vMirrors, Pivot, p->vWinObjs, p->vObj2Var, p->vTfo, p->vRoots, p->vDivSet, *pnStrs, Strs );
p->timeQbf += Abc_Clock() - clk;
if ( RetValue )
p->nLuts[4]++;
}
return RetValue;
}
int Sbd_ManExplore3( Sbd_Man_t * p, int Pivot, int * pnStrs, Sbd_Str_t * Strs )
{
int FreeVar = Vec_IntSize(p->vWinObjs) + Vec_IntSize(p->vTfo) + Vec_IntSize(p->vRoots);
int FreeVarStart = FreeVar;
int nSize, nLeaves, pLeaves[SBD_DIV_MAX];
//sat_solver_delete_p( &p->pSat );
abctime clk = Abc_Clock();
p->pSat = Sbd_ManSatSolver( p->pSat, p->pGia, p->vMirrors, Pivot, p->vWinObjs, p->vObj2Var, p->vTfo, p->vRoots, 0 );
p->timeCnf += Abc_Clock() - clk;
// extract one cut
if ( p->pSrv )
{
nLeaves = Sbd_ManCutServerFirst( p->pSrv, Pivot, pLeaves );
if ( nLeaves == -1 )
return 0;
assert( nLeaves <= p->pPars->nCutSize );
if ( Sbd_ManExploreCut( p, Pivot, nLeaves, pLeaves, pnStrs, Strs, &FreeVar ) )
return 1;
return 0;
}
// extract one cut
for ( nSize = p->pPars->nLutSize + 1; nSize <= p->pPars->nCutSize; nSize++ )
{
nLeaves = Sbd_StoObjBestCut( p->pSto, Pivot, nSize, pLeaves );
if ( nLeaves == -1 )
continue;
assert( nLeaves == nSize );
if ( Sbd_ManExploreCut( p, Pivot, nLeaves, pLeaves, pnStrs, Strs, &FreeVar ) )
return 1;
}
assert( FreeVar - FreeVarStart <= SBD_FVAR_MAX );
return 0;
}
/**Function*************************************************************
Synopsis [Computes delay-oriented k-feasible cut at the node.]
Description [Return 1 if node's LUT level does not exceed those of the fanins.]
SideEffects []
SeeAlso []
***********************************************************************/
int Sbd_CutMergeSimple( Sbd_Man_t * p, int * pCut1, int * pCut2, int * pCut )
{
int * pBeg = pCut + 1;
int * pBeg1 = pCut1 + 1;
int * pBeg2 = pCut2 + 1;
int * pEnd1 = pCut1 + 1 + pCut1[0];
int * pEnd2 = pCut2 + 1 + pCut2[0];
while ( pBeg1 < pEnd1 && pBeg2 < pEnd2 )
{
if ( *pBeg1 == *pBeg2 )
*pBeg++ = *pBeg1++, pBeg2++;
else if ( *pBeg1 < *pBeg2 )
*pBeg++ = *pBeg1++;
else
*pBeg++ = *pBeg2++;
}
while ( pBeg1 < pEnd1 )
*pBeg++ = *pBeg1++;
while ( pBeg2 < pEnd2 )
*pBeg++ = *pBeg2++;
return (pCut[0] = pBeg - pCut - 1);
}
/*
int Sbd_ManMergeCuts( Sbd_Man_t * p, int Node )
{
int Result = 1; // no need to resynthesize
int pCut[2*SBD_MAX_LUTSIZE+1];
int iFan0 = Gia_ObjFaninId0( Gia_ManObj(p->pGia, Node), Node );
int iFan1 = Gia_ObjFaninId1( Gia_ManObj(p->pGia, Node), Node );
int Level0 = Vec_IntEntry( p->vLutLevs, iFan0 );
int Level1 = Vec_IntEntry( p->vLutLevs, iFan1 );
int LevMax = (Level0 || Level1) ? Abc_MaxInt(Level0, Level1) : 1;
int * pCut0 = Sbd_ObjCut( p, iFan0 );
int * pCut1 = Sbd_ObjCut( p, iFan1 );
int nSize = Sbd_CutMergeSimple( p, pCut0, pCut1, pCut );
if ( nSize > p->pPars->nLutSize )
{
if ( Level0 != Level1 )
{
int Cut0[2] = {1, iFan0}, * pCut0Temp = Level0 < LevMax ? Cut0 : pCut0;
int Cut1[2] = {1, iFan1}, * pCut1Temp = Level1 < LevMax ? Cut1 : pCut1;
nSize = Sbd_CutMergeSimple( p, pCut0Temp, pCut1Temp, pCut );
}
if ( nSize > p->pPars->nLutSize )
{
pCut[0] = 2;
pCut[1] = iFan0 < iFan1 ? iFan0 : iFan1;
pCut[2] = iFan0 < iFan1 ? iFan1 : iFan0;
Result = LevMax ? 0 : 1;
LevMax++;
}
}
assert( iFan0 != iFan1 );
assert( Vec_IntEntry(p->vLutLevs, Node) == 0 );
Vec_IntWriteEntry( p->vLutLevs, Node, LevMax );
memcpy( Sbd_ObjCut(p, Node), pCut, sizeof(int) * (pCut[0] + 1) );
//printf( "Setting node %d with delay %d (result = %d).\n", Node, LevMax, Result );
return Result;
}
*/
int Sbd_ManMergeCuts( Sbd_Man_t * p, int Node )
{
int pCut11[2*SBD_MAX_LUTSIZE+1];
int pCut01[2*SBD_MAX_LUTSIZE+1];
int pCut10[2*SBD_MAX_LUTSIZE+1];
int pCut00[2*SBD_MAX_LUTSIZE+1];
int iFan0 = Gia_ObjFaninId0( Gia_ManObj(p->pGia, Node), Node );
int iFan1 = Gia_ObjFaninId1( Gia_ManObj(p->pGia, Node), Node );
int Level0 = Vec_IntEntry( p->vLutLevs, iFan0 ) ? Vec_IntEntry( p->vLutLevs, iFan0 ) : 1;
int Level1 = Vec_IntEntry( p->vLutLevs, iFan1 ) ? Vec_IntEntry( p->vLutLevs, iFan1 ) : 1;
int * pCut0 = Sbd_ObjCut( p, iFan0 );
int * pCut1 = Sbd_ObjCut( p, iFan1 );
int Cut0[2] = {1, iFan0};
int Cut1[2] = {1, iFan1};
int nSize11 = Sbd_CutMergeSimple( p, pCut0, pCut1, pCut11 );
int nSize01 = Sbd_CutMergeSimple( p, Cut0, pCut1, pCut01 );
int nSize10 = Sbd_CutMergeSimple( p, pCut0, Cut1, pCut10 );
int nSize00 = Sbd_CutMergeSimple( p, Cut0, Cut1, pCut00 );
int Lev11 = nSize11 <= p->pPars->nLutSize ? Abc_MaxInt(Level0, Level1) : ABC_INFINITY;
int Lev01 = nSize01 <= p->pPars->nLutSize ? Abc_MaxInt(Level0+1, Level1) : ABC_INFINITY;
int Lev10 = nSize10 <= p->pPars->nLutSize ? Abc_MaxInt(Level0, Level1+1) : ABC_INFINITY;
int Lev00 = nSize00 <= p->pPars->nLutSize ? Abc_MaxInt(Level0+1, Level1+1) : ABC_INFINITY;
int * pCutRes = pCut11;
int LevCur = Lev11;
if ( Lev01 < LevCur || (Lev01 == LevCur && pCut01[0] < pCutRes[0]) )
{
pCutRes = pCut01;
LevCur = Lev01;
}
if ( Lev10 < LevCur || (Lev10 == LevCur && pCut10[0] < pCutRes[0]) )
{
pCutRes = pCut10;
LevCur = Lev10;
}
if ( Lev00 < LevCur || (Lev00 == LevCur && pCut00[0] < pCutRes[0]) )
{
pCutRes = pCut00;
LevCur = Lev00;
}
assert( iFan0 != iFan1 );
assert( Vec_IntEntry(p->vLutLevs, Node) == 0 );
Vec_IntWriteEntry( p->vLutLevs, Node, LevCur );
//Vec_IntWriteEntry( p->vLevs, Node, 1+Abc_MaxInt(Vec_IntEntry(p->vLevs, iFan0), Vec_IntEntry(p->vLevs, iFan1)) );
assert( pCutRes[0] <= p->pPars->nLutSize );
memcpy( Sbd_ObjCut(p, Node), pCutRes, sizeof(int) * (pCutRes[0] + 1) );
//printf( "Setting node %d with delay %d.\n", Node, LevCur );
return LevCur == 1; // LevCur == Abc_MaxInt(Level0, Level1);
}
int Sbd_ManDelay( Sbd_Man_t * p )
{
int i, Id, Delay = 0;
Gia_ManForEachCoDriverId( p->pGia, Id, i )
Delay = Abc_MaxInt( Delay, Vec_IntEntry(p->vLutLevs, Id) );
return Delay;
}
void Sbd_ManMergeTest( Sbd_Man_t * p )
{
int Node;
Gia_ManForEachAndId( p->pGia, Node )
Sbd_ManMergeCuts( p, Node );
printf( "Delay %d.\n", Sbd_ManDelay(p) );
}
void Sbd_ManFindCut_rec( Gia_Man_t * p, Gia_Obj_t * pObj )
{
if ( pObj->fMark1 )
return;
pObj->fMark1 = 1;
if ( pObj->fMark0 )
return;
assert( Gia_ObjIsAnd(pObj) );
Sbd_ManFindCut_rec( p, Gia_ObjFanin0(pObj) );
Sbd_ManFindCut_rec( p, Gia_ObjFanin1(pObj) );
}
void Sbd_ManFindCutUnmark_rec( Gia_Man_t * p, Gia_Obj_t * pObj )
{
if ( !pObj->fMark1 )
return;
pObj->fMark1 = 0;
if ( pObj->fMark0 )
return;
assert( Gia_ObjIsAnd(pObj) );
Sbd_ManFindCutUnmark_rec( p, Gia_ObjFanin0(pObj) );
Sbd_ManFindCutUnmark_rec( p, Gia_ObjFanin1(pObj) );
}
void Sbd_ManFindCut( Sbd_Man_t * p, int Node, Vec_Int_t * vCutLits )
{
int pCut[SBD_MAX_LUTSIZE+1];
int i, LevelMax = 0;
// label reachable nodes
Gia_Obj_t * pTemp, * pObj = Gia_ManObj(p->pGia, Node);
Sbd_ManFindCut_rec( p->pGia, pObj );
// collect
pCut[0] = 0;
Gia_ManForEachObjVec( vCutLits, p->pGia, pTemp, i )
if ( pTemp->fMark1 )
{
LevelMax = Abc_MaxInt( LevelMax, Vec_IntEntry(p->vLutLevs, Gia_ObjId(p->pGia, pTemp)) );
pCut[1+pCut[0]++] = Gia_ObjId(p->pGia, pTemp);
}
assert( pCut[0] <= p->pPars->nLutSize );
// unlabel reachable nodes
Sbd_ManFindCutUnmark_rec( p->pGia, pObj );
// create cut
assert( Vec_IntEntry(p->vLutLevs, Node) == 0 );
Vec_IntWriteEntry( p->vLutLevs, Node, LevelMax+1 );
//Vec_IntWriteEntry( p->vLevs, Node, 1+Abc_MaxInt(Vec_IntEntry(p->vLevs, Gia_ObjFaninId0(pObj, Node)), Vec_IntEntry(p->vLevs, Gia_ObjFaninId1(pObj, Node))) );
memcpy( Sbd_ObjCut(p, Node), pCut, sizeof(int) * (pCut[0] + 1) );
}
int Sbd_ManImplement( Sbd_Man_t * p, int Pivot, word Truth )
{
Gia_Obj_t * pObj;
int i, k, w, iLit, Entry, Node;
int iObjLast = Gia_ManObjNum(p->pGia);
int iCurLev = Vec_IntEntry(p->vLutLevs, Pivot);
int iNewLev;
// collect leaf literals
Vec_IntClear( p->vLits );
Vec_IntForEachEntry( p->vDivSet, Node, i )
{
Node = Vec_IntEntry( p->vWinObjs, Node );
if ( Vec_IntEntry(p->vMirrors, Node) >= 0 )
Vec_IntPush( p->vLits, Vec_IntEntry(p->vMirrors, Node) );
else
Vec_IntPush( p->vLits, Abc_Var2Lit(Node, 0) );
}
// pretend to have MUXes
// assert( p->pGia->pMuxes == NULL );
if ( p->pGia->nXors && p->pGia->pMuxes == NULL )
p->pGia->pMuxes = (unsigned *)p;
// derive new function of the node
iLit = Dsm_ManTruthToGia( p->pGia, &Truth, p->vLits, p->vCover );
if ( p->pGia->pMuxes == (unsigned *)p )
p->pGia->pMuxes = NULL;
// remember this function
assert( Vec_IntEntry(p->vMirrors, Pivot) == -1 );
Vec_IntWriteEntry( p->vMirrors, Pivot, iLit );
if ( p->pPars->fVerbose )
printf( "Replacing node %d by literal %d.\n", Pivot, iLit );
// translate literals into variables
Vec_IntForEachEntry( p->vLits, Entry, i )
Vec_IntWriteEntry( p->vLits, i, Abc_Lit2Var(Entry) );
// label inputs
Gia_ManForEachObjVec( p->vLits, p->pGia, pObj, i )
pObj->fMark0 = 1;
// extend data-structure to accommodate new nodes
assert( Vec_IntSize(p->vLutLevs) == iObjLast );
for ( i = iObjLast; i < Gia_ManObjNum(p->pGia); i++ )
{
Vec_IntPush( p->vLutLevs, 0 );
Vec_IntPush( p->vObj2Var, 0 );
Vec_IntPush( p->vMirrors, -1 );
Vec_IntFillExtra( p->vLutCuts, Vec_IntSize(p->vLutCuts) + p->pPars->nLutSize + 1, 0 );
Sbd_ManFindCut( p, i, p->vLits );
for ( k = 0; k < 4; k++ )
for ( w = 0; w < p->pPars->nWords; w++ )
Vec_WrdPush( p->vSims[k], 0 );
}
// unlabel inputs
Gia_ManForEachObjVec( p->vLits, p->pGia, pObj, i )
pObj->fMark0 = 0;
// make sure delay reduction is achieved
iNewLev = Vec_IntEntry( p->vLutLevs, Abc_Lit2Var(iLit) );
assert( iNewLev < iCurLev );
// update delay of the initial node
assert( Vec_IntEntry(p->vLutLevs, Pivot) == iCurLev );
Vec_IntWriteEntry( p->vLutLevs, Pivot, iNewLev );
//Vec_IntWriteEntry( p->vLevs, Pivot, 1+Abc_MaxInt(Vec_IntEntry(p->vLevs, Gia_ObjFaninId0(pObj, Pivot)), Vec_IntEntry(p->vLevs, Gia_ObjFaninId1(pObj, Pivot))) );
return 0;
}
int Sbd_ManImplement2( Sbd_Man_t * p, int Pivot, int nStrs, Sbd_Str_t * pStrs )
{
//Gia_Obj_t * pObj = NULL;
int i, k, w, iLit, Node;
int iObjLast = Gia_ManObjNum(p->pGia);
int iCurLev = Vec_IntEntry(p->vLutLevs, Pivot);
int iNewLev;
// collect leaf literals
Vec_IntClear( p->vLits );
Vec_IntForEachEntry( p->vDivSet, Node, i )
{
Node = Vec_IntEntry( p->vWinObjs, Node );
if ( Vec_IntEntry(p->vMirrors, Node) >= 0 )
Vec_IntPush( p->vLits, Vec_IntEntry(p->vMirrors, Node) );
else
Vec_IntPush( p->vLits, Abc_Var2Lit(Node, 0) );
}
// collect structure nodes
for ( i = 0; i < nStrs; i++ )
Vec_IntPush( p->vLits, -1 );
// implement structures
for ( i = nStrs-1; i >= 0; i-- )
{
if ( pStrs[i].fLut )
{
// collect local literals
Vec_IntClear( p->vLits2 );
for ( k = 0; k < (int)pStrs[i].nVarIns; k++ )
Vec_IntPush( p->vLits2, Vec_IntEntry(p->vLits, pStrs[i].VarIns[k]) );
// pretend to have MUXes
// assert( p->pGia->pMuxes == NULL );
if ( p->pGia->nXors && p->pGia->pMuxes == NULL )
p->pGia->pMuxes = (unsigned *)p;
// derive new function of the node
iLit = Dsm_ManTruthToGia( p->pGia, &pStrs[i].Res, p->vLits2, p->vCover );
if ( p->pGia->pMuxes == (unsigned *)p )
p->pGia->pMuxes = NULL;
}
else
{
iLit = Vec_IntEntry( p->vLits, (int)pStrs[i].Res );
assert( iLit > 0 );
}
// update literal
assert( Vec_IntEntry(p->vLits, Vec_IntSize(p->vLits)-nStrs+i) == -1 );
Vec_IntWriteEntry( p->vLits, Vec_IntSize(p->vLits)-nStrs+i, iLit );
}
iLit = Vec_IntEntry( p->vLits, Vec_IntSize(p->vDivSet) );
//assert( iObjLast == Gia_ManObjNum(p->pGia) || Abc_Lit2Var(iLit) == Gia_ManObjNum(p->pGia)-1 );
// remember this function
assert( Vec_IntEntry(p->vMirrors, Pivot) == -1 );
Vec_IntWriteEntry( p->vMirrors, Pivot, iLit );
if ( p->pPars->fVeryVerbose )
printf( "Replacing node %d by literal %d.\n", Pivot, iLit );
// extend data-structure to accommodate new nodes
assert( Vec_IntSize(p->vLutLevs) == iObjLast );
for ( i = iObjLast; i < Gia_ManObjNum(p->pGia); i++ )
{
assert( i == Vec_IntSize(p->vMirrors) );
Vec_IntPush( p->vMirrors, -1 );
Sbd_StoRefObj( p->pSto, i, i == Gia_ManObjNum(p->pGia)-1 ? Pivot : -1 );
}
Sbd_StoDerefObj( p->pSto, Pivot );
for ( i = iObjLast; i < Gia_ManObjNum(p->pGia); i++ )
{
//Gia_Obj_t * pObjI = Gia_ManObj( p->pGia, i );
abctime clk = Abc_Clock();
int Delay = Sbd_StoComputeCutsNode( p->pSto, i );
p->timeCut += Abc_Clock() - clk;
assert( i == Vec_IntSize(p->vLutLevs) );
Vec_IntPush( p->vLutLevs, Delay );
//Vec_IntPush( p->vLevs, 1+Abc_MaxInt(Vec_IntEntry(p->vLevs, Gia_ObjFaninId0(pObjI, i)), Vec_IntEntry(p->vLevs, Gia_ObjFaninId1(pObjI, i))) );
Vec_IntPush( p->vObj2Var, 0 );
Vec_IntFillExtra( p->vLutCuts, Vec_IntSize(p->vLutCuts) + p->pPars->nLutSize + 1, 0 );
Sbd_StoSaveBestDelayCut( p->pSto, i, Sbd_ObjCut(p, i) );
//Sbd_ManFindCut( p, i, p->vLits );
for ( k = 0; k < 4; k++ )
for ( w = 0; w < p->pPars->nWords; w++ )
Vec_WrdPush( p->vSims[k], 0 );
}
// make sure delay reduction is achieved
iNewLev = Vec_IntEntry( p->vLutLevs, Abc_Lit2Var(iLit) );
assert( !iNewLev || iNewLev < iCurLev );
// update delay of the initial node
//pObj = Gia_ManObj( p->pGia, Pivot );
assert( Vec_IntEntry(p->vLutLevs, Pivot) == iCurLev );
Vec_IntWriteEntry( p->vLutLevs, Pivot, iNewLev );
//Vec_IntWriteEntry( p->vLevs, Pivot, Pivot ? 1+Abc_MaxInt(Vec_IntEntry(p->vLevs, Gia_ObjFaninId0(pObj, Pivot)), Vec_IntEntry(p->vLevs, Gia_ObjFaninId1(pObj, Pivot))) : 0 );
return 0;
}
/**Function*************************************************************
Synopsis [Derives new AIG after resynthesis.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Sbd_ManDeriveMapping_rec( Sbd_Man_t * p, Gia_Man_t * pNew, int iObj )
{
Gia_Obj_t * pObj; int k, * pCut;
if ( !iObj || Gia_ObjIsTravIdCurrentId(pNew, iObj) )
return;
Gia_ObjSetTravIdCurrentId(pNew, iObj);
pObj = Gia_ManObj( pNew, iObj );
if ( Gia_ObjIsCi(pObj) )
return;
assert( Gia_ObjIsAnd(pObj) );
pCut = Sbd_ObjCut2( p, iObj );
for ( k = 1; k <= pCut[0]; k++ )
Sbd_ManDeriveMapping_rec( p, pNew, pCut[k] );
// add mapping
Vec_IntWriteEntry( pNew->vMapping, iObj, Vec_IntSize(pNew->vMapping) );
for ( k = 0; k <= pCut[0]; k++ )
Vec_IntPush( pNew->vMapping, pCut[k] );
Vec_IntPush( pNew->vMapping, iObj );
}
void Sbd_ManDeriveMapping( Sbd_Man_t * p, Gia_Man_t * pNew )
{
Gia_Obj_t * pObj, * pFan;
int i, k, iFan, iObjNew, iFanNew, * pCut, * pCutNew;
Vec_Int_t * vLeaves = Vec_IntAlloc( 100 );
// derive cuts for the new manager
p->vLutCuts2 = Vec_IntStart( Gia_ManObjNum(pNew) * (p->pPars->nLutSize + 1) );
Gia_ManForEachAnd( p->pGia, pObj, i )
{
if ( Vec_IntEntry(p->vMirrors, i) >= 0 )
continue;
if ( pObj->Value == ~0 )
continue;
iObjNew = Abc_Lit2Var( pObj->Value );
if ( !Gia_ObjIsAnd(Gia_ManObj(pNew, iObjNew)) )
continue;
pCutNew = Sbd_ObjCut2( p, iObjNew );
pCut = Sbd_ObjCut( p, i );
Vec_IntClear( vLeaves );
for ( k = 1; k <= pCut[0]; k++ )
{
iFan = Vec_IntEntry(p->vMirrors, pCut[k]) >= 0 ? Abc_Lit2Var(Vec_IntEntry(p->vMirrors, pCut[k])) : pCut[k];
pFan = Gia_ManObj( p->pGia, iFan );
if ( pFan->Value == ~0 )
continue;
iFanNew = Abc_Lit2Var( pFan->Value );
if ( iFanNew == 0 || iFanNew == iObjNew )
continue;
Vec_IntPushUniqueOrder( vLeaves, iFanNew );
}
assert( Vec_IntSize(vLeaves) <= p->pPars->nLutSize );
//assert( Vec_IntSize(vLeaves) > 1 );
pCutNew[0] = Vec_IntSize(vLeaves);
memcpy( pCutNew+1, Vec_IntArray(vLeaves), sizeof(int) * Vec_IntSize(vLeaves) );
}
Vec_IntFree( vLeaves );
// create new mapping
Vec_IntFreeP( &pNew->vMapping );
pNew->vMapping = Vec_IntAlloc( (p->pPars->nLutSize + 2) * Gia_ManObjNum(pNew) );
Vec_IntFill( pNew->vMapping, Gia_ManObjNum(pNew), 0 );
Gia_ManIncrementTravId( pNew );
Gia_ManForEachCo( pNew, pObj, i )
Sbd_ManDeriveMapping_rec( p, pNew, Gia_ObjFaninId0p(pNew, pObj) );
Vec_IntFreeP( &p->vLutCuts2 );
}
void Sbd_ManDerive_rec( Gia_Man_t * pNew, Gia_Man_t * p, int Node, Vec_Int_t * vMirrors )
{
Gia_Obj_t * pObj;
int Obj = Node;
if ( Vec_IntEntry(vMirrors, Node) >= 0 )
Obj = Abc_Lit2Var( Vec_IntEntry(vMirrors, Node) );
pObj = Gia_ManObj( p, Obj );
if ( !~pObj->Value )
{
assert( Gia_ObjIsAnd(pObj) );
Sbd_ManDerive_rec( pNew, p, Gia_ObjFaninId0(pObj, Obj), vMirrors );
Sbd_ManDerive_rec( pNew, p, Gia_ObjFaninId1(pObj, Obj), vMirrors );
if ( Gia_ObjIsXor(pObj) )
pObj->Value = Gia_ManHashXorReal( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
else
pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
}
// set the original node as well
if ( Obj != Node )
Gia_ManObj(p, Node)->Value = Abc_LitNotCond( pObj->Value, Abc_LitIsCompl(Vec_IntEntry(vMirrors, Node)) );
}
Gia_Man_t * Sbd_ManDerive( Sbd_Man_t * pMan, Gia_Man_t * p, Vec_Int_t * vMirrors )
{
Gia_Man_t * pNew, * pTemp;
Gia_Obj_t * pObj;
int i;
Gia_ManFillValue( p );
pNew = Gia_ManStart( Gia_ManObjNum(p) );
pNew->pName = Abc_UtilStrsav( p->pName );
pNew->pSpec = Abc_UtilStrsav( p->pSpec );
if ( p->pMuxes )
pNew->pMuxes = ABC_CALLOC( unsigned, Gia_ManObjNum(p) );
Gia_ManConst0(p)->Value = 0;
Gia_ManHashAlloc( pNew );
Gia_ManForEachCi( p, pObj, i )
pObj->Value = Gia_ManAppendCi(pNew);
Gia_ManForEachCo( p, pObj, i )
Sbd_ManDerive_rec( pNew, p, Gia_ObjFaninId0p(p, pObj), vMirrors );
Gia_ManForEachCo( p, pObj, i )
pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
Gia_ManHashStop( pNew );
Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) );
Gia_ManTransferTiming( pNew, p );
if ( pMan->pPars->fMapping )
Sbd_ManDeriveMapping( pMan, pNew );
// remove dangling nodes
pNew = Gia_ManCleanup( pTemp = pNew );
Gia_ManTransferTiming( pNew, pTemp );
Gia_ManTransferMapping( pNew, pTemp );
Gia_ManStop( pTemp );
return pNew;
}
/**Function*************************************************************
Synopsis [Performs delay optimization for the given LUT size.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Sbd_NtkPerformOne( Sbd_Man_t * p, int Pivot )
{
Sbd_Str_t Strs[SBD_DIV_MAX]; word Truth = 0;
int RetValue, nStrs = 0;
if ( !p->pSto && Sbd_ManMergeCuts( p, Pivot ) )
return;
if ( !Sbd_ManWindow( p, Pivot ) )
return;
//if ( Vec_IntSize(p->vWinObjs) > 100 )
// printf( "Obj %d : Win = %d TFO = %d. Roots = %d.\n", Pivot, Vec_IntSize(p->vWinObjs), Vec_IntSize(p->vTfo), Vec_IntSize(p->vRoots) );
p->nTried++;
p->nUsed++;
RetValue = Sbd_ManCheckConst( p, Pivot );
if ( RetValue >= 0 )
{
Vec_IntWriteEntry( p->vMirrors, Pivot, RetValue );
//if ( p->pPars->fVerbose ) printf( "Node %5d: Detected constant %d.\n", Pivot, RetValue );
}
else if ( p->pPars->fFindDivs && p->pPars->nLutNum >= 1 && Sbd_ManExplore2( p, Pivot, &Truth ) )
{
int i;
Strs->fLut = 1;
Strs->nVarIns = Vec_IntSize( p->vDivSet );
for ( i = 0; i < Strs->nVarIns; i++ )
Strs->VarIns[i] = i;
Strs->Res = Truth;
Sbd_ManImplement2( p, Pivot, 1, Strs );
//if ( p->pPars->fVerbose ) printf( "Node %5d: Detected LUT%d\n", Pivot, p->pPars->nLutSize );
}
else if ( p->pPars->nLutNum >= 2 && Sbd_ManExplore3( p, Pivot, &nStrs, Strs ) )
{
Sbd_ManImplement2( p, Pivot, nStrs, Strs );
if ( !p->pPars->fVerbose )
return;
//if ( Vec_IntSize(p->vDivSet) <= 4 )
// printf( "Node %5d: Detected %d\n", Pivot, p->pPars->nLutSize );
//else if ( Vec_IntSize(p->vDivSet) <= 6 || (Vec_IntSize(p->vDivSet) == 7 && nStrs == 2) )
// printf( "Node %5d: Detected %d%d\n", Pivot, p->pPars->nLutSize, p->pPars->nLutSize );
//else
// printf( "Node %5d: Detected %d%d%d\n", Pivot, p->pPars->nLutSize, p->pPars->nLutSize, p->pPars->nLutSize );
}
else
p->nUsed--;
}
Gia_Man_t * Sbd_NtkPerform( Gia_Man_t * pGia, Sbd_Par_t * pPars )
{
Gia_Man_t * pNew;
Gia_Obj_t * pObj;
Vec_Bit_t * vPath;
Sbd_Man_t * p = Sbd_ManStart( pGia, pPars );
int nNodesOld = Gia_ManObjNum(pGia);
int k, Pivot;
assert( pPars->nLutSize <= 6 );
// prepare references
Gia_ManForEachObj( p->pGia, pObj, Pivot )
Sbd_StoRefObj( p->pSto, Pivot, -1 );
//return NULL;
vPath = (pPars->fUsePath && Gia_ManHasMapping(pGia)) ? Sbc_ManCriticalPath(pGia) : NULL;
if ( pGia->pManTime != NULL && Tim_ManBoxNum((Tim_Man_t*)pGia->pManTime) )
{
Vec_Int_t * vNodes = Gia_ManOrderWithBoxes( pGia );
Tim_Man_t * pTimOld = (Tim_Man_t *)pGia->pManTime;
pGia->pManTime = Tim_ManDup( pTimOld, 1 );
//Tim_ManPrint( pGia->pManTime );
Tim_ManIncrementTravId( (Tim_Man_t *)pGia->pManTime );
Gia_ManForEachObjVec( vNodes, pGia, pObj, k )
{
Pivot = Gia_ObjId( pGia, pObj );
if ( Pivot >= nNodesOld )
break;
if ( Gia_ObjIsAnd(pObj) )
{
abctime clk = Abc_Clock();
int Delay = Sbd_StoComputeCutsNode( p->pSto, Pivot );
Sbd_StoSaveBestDelayCut( p->pSto, Pivot, Sbd_ObjCut(p, Pivot) );
p->timeCut += Abc_Clock() - clk;
Vec_IntWriteEntry( p->vLutLevs, Pivot, Delay );
if ( Delay > 1 && (!vPath || Vec_BitEntry(vPath, Pivot)) )
Sbd_NtkPerformOne( p, Pivot );
}
else if ( Gia_ObjIsCi(pObj) )
{
int arrTime = Tim_ManGetCiArrival( (Tim_Man_t*)pGia->pManTime, Gia_ObjCioId(pObj) );
Vec_IntWriteEntry( p->vLutLevs, Pivot, arrTime );
Sbd_StoComputeCutsCi( p->pSto, Pivot, arrTime, arrTime );
}
else if ( Gia_ObjIsCo(pObj) )
{
int arrTime = Vec_IntEntry( p->vLutLevs, Gia_ObjFaninId0(pObj, Pivot) );
Tim_ManSetCoArrival( (Tim_Man_t*)pGia->pManTime, Gia_ObjCioId(pObj), arrTime );
}
else if ( Gia_ObjIsConst0(pObj) )
Sbd_StoComputeCutsConst0( p->pSto, 0 );
else assert( 0 );
}
Tim_ManStop( (Tim_Man_t *)pGia->pManTime );
pGia->pManTime = pTimOld;
Vec_IntFree( vNodes );
}
else
{
Sbd_StoComputeCutsConst0( p->pSto, 0 );
Gia_ManForEachObj( pGia, pObj, Pivot )
{
if ( Pivot >= nNodesOld )
break;
if ( Gia_ObjIsCi(pObj) )
Sbd_StoComputeCutsCi( p->pSto, Pivot, 0, 0 );
else if ( Gia_ObjIsAnd(pObj) )
{
abctime clk = Abc_Clock();
int Delay = Sbd_StoComputeCutsNode( p->pSto, Pivot );
Sbd_StoSaveBestDelayCut( p->pSto, Pivot, Sbd_ObjCut(p, Pivot) );
p->timeCut += Abc_Clock() - clk;
Vec_IntWriteEntry( p->vLutLevs, Pivot, Delay );
if ( Delay > 1 && (!vPath || Vec_BitEntry(vPath, Pivot)) )
Sbd_NtkPerformOne( p, Pivot );
}
//if ( nNodesOld != Gia_ManObjNum(pGia) )
// break;
}
}
Vec_BitFreeP( &vPath );
p->timeTotal = Abc_Clock() - p->timeTotal;
if ( p->pPars->fVerbose )
{
printf( "K = %d. S = %d. N = %d. P = %d. ",
p->pPars->nLutSize, p->pPars->nLutNum, p->pPars->nCutSize, p->pPars->nCutNum );
printf( "Try = %d. Use = %d. C = %d. 1 = %d. 2 = %d. 3a = %d. 3b = %d. Lev = %d. ",
p->nTried, p->nUsed, p->nLuts[0], p->nLuts[1], p->nLuts[2], p->nLuts[3], p->nLuts[4], Sbd_ManDelay(p) );
Abc_PrintTime( 1, "Time", p->timeTotal );
}
pNew = Sbd_ManDerive( p, pGia, p->vMirrors );
// print runtime statistics
p->timeOther = p->timeTotal - p->timeWin - p->timeCut - p->timeCov - p->timeCnf - p->timeSat - p->timeQbf;
if ( p->pPars->fVerbose )
{
ABC_PRTP( "Win", p->timeWin , p->timeTotal );
ABC_PRTP( "Cut", p->timeCut , p->timeTotal );
ABC_PRTP( "Cov", p->timeCov , p->timeTotal );
ABC_PRTP( "Cnf", p->timeCnf , p->timeTotal );
ABC_PRTP( "Sat", p->timeSat , p->timeTotal );
ABC_PRTP( "Qbf", p->timeQbf , p->timeTotal );
ABC_PRTP( "Oth", p->timeOther, p->timeTotal );
ABC_PRTP( "ALL", p->timeTotal, p->timeTotal );
}
Sbd_ManStop( p );
return pNew;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END