blob: 162795b0e945f02604856e3781275f304733b589 [file] [log] [blame]
/**CFile****************************************************************
FileName [saigGlaCba.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Sequential AIG package.]
Synopsis [Gate level abstraction.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: saigGlaCba.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
#include "saig.h"
#include "sat/bsat/satSolver.h"
#include "sat/cnf/cnf.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
typedef struct Aig_Gla1Man_t_ Aig_Gla1Man_t;
struct Aig_Gla1Man_t_
{
// user data
Aig_Man_t * pAig;
int nConfLimit;
int nFramesMax;
int fVerbose;
// unrolling
int nFrames;
Vec_Int_t * vObj2Vec; // maps obj ID into its vec ID
Vec_Int_t * vVec2Var; // maps vec ID into its sat Var (nFrames per vec ID)
Vec_Int_t * vVar2Inf; // maps sat Var into its frame and obj ID
// abstraction
Vec_Int_t * vAssigned; // collects objects whose SAT variables have been created
Vec_Int_t * vIncluded; // maps obj ID into its status (0=unused; 1=included in abstraction)
// components
Vec_Int_t * vPis; // primary inputs
Vec_Int_t * vPPis; // pseudo primary inputs
Vec_Int_t * vFlops; // flops
Vec_Int_t * vNodes; // nodes
// CNF computation
Vec_Ptr_t * vLeaves;
Vec_Ptr_t * vVolume;
Vec_Int_t * vCover;
Vec_Ptr_t * vObj2Cnf;
Vec_Int_t * vLits;
// SAT solver
sat_solver * pSat;
// statistics
clock_t timeSat;
clock_t timeRef;
clock_t timeTotal;
};
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Adds constant to the solver.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Aig_Gla1AddConst( sat_solver * pSat, int iVar, int fCompl )
{
lit Lit = toLitCond( iVar, fCompl );
if ( !sat_solver_addclause( pSat, &Lit, &Lit + 1 ) )
return 0;
return 1;
}
/**Function*************************************************************
Synopsis [Adds buffer to the solver.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Aig_Gla1AddBuffer( sat_solver * pSat, int iVar0, int iVar1, int fCompl )
{
lit Lits[2];
Lits[0] = toLitCond( iVar0, 0 );
Lits[1] = toLitCond( iVar1, !fCompl );
if ( !sat_solver_addclause( pSat, Lits, Lits + 2 ) )
return 0;
Lits[0] = toLitCond( iVar0, 1 );
Lits[1] = toLitCond( iVar1, fCompl );
if ( !sat_solver_addclause( pSat, Lits, Lits + 2 ) )
return 0;
return 1;
}
/**Function*************************************************************
Synopsis [Adds buffer to the solver.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Aig_Gla1AddNode( sat_solver * pSat, int iVar, int iVar0, int iVar1, int fCompl0, int fCompl1 )
{
lit Lits[3];
Lits[0] = toLitCond( iVar, 1 );
Lits[1] = toLitCond( iVar0, fCompl0 );
if ( !sat_solver_addclause( pSat, Lits, Lits + 2 ) )
return 0;
Lits[0] = toLitCond( iVar, 1 );
Lits[1] = toLitCond( iVar1, fCompl1 );
if ( !sat_solver_addclause( pSat, Lits, Lits + 2 ) )
return 0;
Lits[0] = toLitCond( iVar, 0 );
Lits[1] = toLitCond( iVar0, !fCompl0 );
Lits[2] = toLitCond( iVar1, !fCompl1 );
if ( !sat_solver_addclause( pSat, Lits, Lits + 3 ) )
return 0;
return 1;
}
/**Function*************************************************************
Synopsis [Derives abstraction components (PIs, PPIs, flops, nodes).]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Aig_Gla1CollectAbstr( Aig_Gla1Man_t * p )
{
Aig_Obj_t * pObj;
int i, Entry;
/*
// make sure every neighbor of included objects is assigned a variable
Vec_IntForEachEntry( p->vIncluded, Entry, i )
{
if ( Entry == 0 )
continue;
assert( Entry == 1 );
pObj = Aig_ManObj( p->pAig, i );
if ( Vec_IntFind( p->vAssigned, Aig_ObjId(pObj) ) == -1 )
printf( "Aig_Gla1CollectAbstr(): Object not found\n" );
if ( Aig_ObjIsNode(pObj) )
{
if ( Vec_IntFind( p->vAssigned, Aig_ObjFaninId0(pObj) ) == -1 )
printf( "Aig_Gla1CollectAbstr(): Node's fanin is not found\n" );
if ( Vec_IntFind( p->vAssigned, Aig_ObjFaninId1(pObj) ) == -1 )
printf( "Aig_Gla1CollectAbstr(): Node's fanin is not found\n" );
}
else if ( Saig_ObjIsLo(p->pAig, pObj) )
{
Aig_Obj_t * pObjLi;
pObjLi = Saig_ObjLoToLi(p->pAig, pObj);
if ( Vec_IntFind( p->vAssigned, Aig_ObjFaninId0(pObjLi) ) == -1 )
printf( "Aig_Gla1CollectAbstr(): Flop's fanin is not found\n" );
}
else assert( Aig_ObjIsConst1(pObj) );
}
*/
Vec_IntClear( p->vPis );
Vec_IntClear( p->vPPis );
Vec_IntClear( p->vFlops );
Vec_IntClear( p->vNodes );
Vec_IntForEachEntryReverse( p->vAssigned, Entry, i )
{
pObj = Aig_ManObj( p->pAig, Entry );
if ( Saig_ObjIsPi(p->pAig, pObj) )
Vec_IntPush( p->vPis, Aig_ObjId(pObj) );
else if ( !Vec_IntEntry(p->vIncluded, Aig_ObjId(pObj)) )
Vec_IntPush( p->vPPis, Aig_ObjId(pObj) );
else if ( Aig_ObjIsNode(pObj) )
Vec_IntPush( p->vNodes, Aig_ObjId(pObj) );
else if ( Saig_ObjIsLo(p->pAig, pObj) )
Vec_IntPush( p->vFlops, Aig_ObjId(pObj) );
else assert( Aig_ObjIsConst1(pObj) );
}
}
/**Function*************************************************************
Synopsis [Duplicates the AIG manager recursively.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Aig_Gla1DeriveAbs_rec( Aig_Man_t * pNew, Aig_Obj_t * pObj )
{
if ( pObj->pData )
return;
assert( Aig_ObjIsNode(pObj) );
Aig_Gla1DeriveAbs_rec( pNew, Aig_ObjFanin0(pObj) );
Aig_Gla1DeriveAbs_rec( pNew, Aig_ObjFanin1(pObj) );
pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
}
/**Function*************************************************************
Synopsis [Derives abstraction.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Aig_Man_t * Aig_Gla1DeriveAbs( Aig_Gla1Man_t * p )
{
Aig_Man_t * pNew;
Aig_Obj_t * pObj;
int i, RetValue;
assert( Saig_ManPoNum(p->pAig) == 1 );
// start the new manager
pNew = Aig_ManStart( 5000 );
pNew->pName = Abc_UtilStrsav( p->pAig->pName );
// create constant
Aig_ManCleanData( p->pAig );
Aig_ManConst1(p->pAig)->pData = Aig_ManConst1(pNew);
// create PIs
Aig_ManForEachObjVec( p->vPis, p->pAig, pObj, i )
pObj->pData = Aig_ObjCreateCi(pNew);
// create additional PIs
Aig_ManForEachObjVec( p->vPPis, p->pAig, pObj, i )
pObj->pData = Aig_ObjCreateCi(pNew);
// create ROs
Aig_ManForEachObjVec( p->vFlops, p->pAig, pObj, i )
pObj->pData = Aig_ObjCreateCi(pNew);
// create internal nodes
Aig_ManForEachObjVec( p->vNodes, p->pAig, pObj, i )
// pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
Aig_Gla1DeriveAbs_rec( pNew, pObj );
// create PO
Saig_ManForEachPo( p->pAig, pObj, i )
pObj->pData = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) );
// create RIs
Aig_ManForEachObjVec( p->vFlops, p->pAig, pObj, i )
{
assert( Saig_ObjIsLo(p->pAig, pObj) );
pObj = Saig_ObjLoToLi( p->pAig, pObj );
pObj->pData = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) );
}
Aig_ManSetRegNum( pNew, Vec_IntSize(p->vFlops) );
// clean up
RetValue = Aig_ManCleanup( pNew );
if ( RetValue > 0 )
printf( "Aig_Gla1DeriveAbs(): Internal error! Object count mismatch.\n" );
assert( RetValue == 0 );
return pNew;
}
/**Function*************************************************************
Synopsis [Finds existing SAT variable or creates a new one.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Aig_Gla1FetchVecId( Aig_Gla1Man_t * p, Aig_Obj_t * pObj )
{
int i, iVecId;
iVecId = Vec_IntEntry( p->vObj2Vec, Aig_ObjId(pObj) );
if ( iVecId == 0 )
{
iVecId = Vec_IntSize( p->vVec2Var ) / p->nFrames;
for ( i = 0; i < p->nFrames; i++ )
Vec_IntPush( p->vVec2Var, 0 );
Vec_IntWriteEntry( p->vObj2Vec, Aig_ObjId(pObj), iVecId );
Vec_IntPushOrderReverse( p->vAssigned, Aig_ObjId(pObj) );
}
return iVecId;
}
/**Function*************************************************************
Synopsis [Finds existing SAT variable or creates a new one.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Aig_Gla1FetchVar( Aig_Gla1Man_t * p, Aig_Obj_t * pObj, int k )
{
int iVecId, iSatVar;
assert( k < p->nFrames );
iVecId = Aig_Gla1FetchVecId( p, pObj );
iSatVar = Vec_IntEntry( p->vVec2Var, iVecId * p->nFrames + k );
if ( iSatVar == 0 )
{
iSatVar = Vec_IntSize( p->vVar2Inf ) / 2;
Vec_IntPush( p->vVar2Inf, Aig_ObjId(pObj) );
Vec_IntPush( p->vVar2Inf, k );
Vec_IntWriteEntry( p->vVec2Var, iVecId * p->nFrames + k, iSatVar );
sat_solver_setnvars( p->pSat, iSatVar + 1 );
}
return iSatVar;
}
/**Function*************************************************************
Synopsis [Adds CNF for the given object in the given frame.]
Description [Returns 0, if the solver becames UNSAT.]
SideEffects []
SeeAlso []
***********************************************************************/
int Aig_Gla1ObjAddToSolver( Aig_Gla1Man_t * p, Aig_Obj_t * pObj, int k )
{
if ( k == p->nFrames )
{
int i, j, nVecIds = Vec_IntSize( p->vVec2Var ) / p->nFrames;
Vec_Int_t * vVec2VarNew = Vec_IntAlloc( 4 * nVecIds * p->nFrames );
for ( i = 0; i < nVecIds; i++ )
{
for ( j = 0; j < p->nFrames; j++ )
Vec_IntPush( vVec2VarNew, Vec_IntEntry( p->vVec2Var, i * p->nFrames + j ) );
for ( j = 0; j < p->nFrames; j++ )
Vec_IntPush( vVec2VarNew, i ? 0 : -1 );
}
Vec_IntFree( p->vVec2Var );
p->vVec2Var = vVec2VarNew;
p->nFrames *= 2;
}
assert( k < p->nFrames );
assert( Vec_IntEntry(p->vIncluded, Aig_ObjId(pObj)) );
if ( Aig_ObjIsConst1(pObj) )
return Aig_Gla1AddConst( p->pSat, Aig_Gla1FetchVar(p, pObj, k), 0 );
if ( Saig_ObjIsLo(p->pAig, pObj) )
{
Aig_Obj_t * pObjLi = Saig_ObjLoToLi(p->pAig, pObj);
if ( k == 0 )
{
Aig_Gla1FetchVecId( p, Aig_ObjFanin0(pObjLi) );
return Aig_Gla1AddConst( p->pSat, Aig_Gla1FetchVar(p, pObj, k), 1 );
}
return Aig_Gla1AddBuffer( p->pSat, Aig_Gla1FetchVar(p, pObj, k),
Aig_Gla1FetchVar(p, Aig_ObjFanin0(pObjLi), k-1),
Aig_ObjFaninC0(pObjLi) );
}
else
{
Vec_Int_t * vClauses;
int i, Entry;
assert( Aig_ObjIsNode(pObj) );
if ( p->vObj2Cnf == NULL )
return Aig_Gla1AddNode( p->pSat, Aig_Gla1FetchVar(p, pObj, k),
Aig_Gla1FetchVar(p, Aig_ObjFanin0(pObj), k),
Aig_Gla1FetchVar(p, Aig_ObjFanin1(pObj), k),
Aig_ObjFaninC0(pObj), Aig_ObjFaninC1(pObj) );
// derive clauses
assert( pObj->fMarkA );
vClauses = (Vec_Int_t *)Vec_PtrEntry( p->vObj2Cnf, Aig_ObjId(pObj) );
if ( vClauses == NULL )
{
Vec_PtrWriteEntry( p->vObj2Cnf, Aig_ObjId(pObj), (vClauses = Vec_IntAlloc(16)) );
Cnf_ComputeClauses( p->pAig, pObj, p->vLeaves, p->vVolume, NULL, p->vCover, vClauses );
}
// derive variables
Cnf_CollectLeaves( pObj, p->vLeaves, 0 );
Vec_PtrForEachEntry( Aig_Obj_t *, p->vLeaves, pObj, i )
Aig_Gla1FetchVar( p, pObj, k );
// translate clauses
assert( Vec_IntSize(vClauses) >= 2 );
assert( Vec_IntEntry(vClauses, 0) == 0 );
Vec_IntForEachEntry( vClauses, Entry, i )
{
if ( Entry == 0 )
{
Vec_IntClear( p->vLits );
continue;
}
Vec_IntPush( p->vLits, (Entry & 1) ^ (2 * Aig_Gla1FetchVar(p, Aig_ManObj(p->pAig, Entry >> 1), k)) );
if ( i == Vec_IntSize(vClauses) - 1 || Vec_IntEntry(vClauses, i+1) == 0 )
{
if ( !sat_solver_addclause( p->pSat, Vec_IntArray(p->vLits), Vec_IntArray(p->vLits)+Vec_IntSize(p->vLits) ) )
return 0;
}
}
return 1;
}
}
/**Function*************************************************************
Synopsis [Returns the array of neighbors.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Aig_Gla1CollectAssigned( Aig_Gla1Man_t * p, Vec_Int_t * vGateClasses )
{
Aig_Obj_t * pObj;
int i, Entry;
Vec_IntForEachEntryReverse( vGateClasses, Entry, i )
{
if ( Entry == 0 )
continue;
assert( Entry == 1 );
pObj = Aig_ManObj( p->pAig, i );
Aig_Gla1FetchVecId( p, pObj );
if ( Aig_ObjIsNode(pObj) )
{
Aig_Gla1FetchVecId( p, Aig_ObjFanin0(pObj) );
Aig_Gla1FetchVecId( p, Aig_ObjFanin1(pObj) );
}
else if ( Saig_ObjIsLo(p->pAig, pObj) )
Aig_Gla1FetchVecId( p, Aig_ObjFanin0(Saig_ObjLoToLi(p->pAig, pObj)) );
else assert( Aig_ObjIsConst1(pObj) );
}
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Aig_Gla1Man_t * Aig_Gla1ManStart( Aig_Man_t * pAig, Vec_Int_t * vGateClassesOld, int fNaiveCnf )
{
Aig_Gla1Man_t * p;
int i;
p = ABC_CALLOC( Aig_Gla1Man_t, 1 );
p->pAig = pAig;
p->nFrames = 32;
// unrolling
p->vObj2Vec = Vec_IntStart( Aig_ManObjNumMax(pAig) );
p->vVec2Var = Vec_IntAlloc( 1 << 20 );
p->vVar2Inf = Vec_IntAlloc( 1 << 20 );
// skip first vector ID
for ( i = 0; i < p->nFrames; i++ )
Vec_IntPush( p->vVec2Var, -1 );
// skip first SAT variable
Vec_IntPush( p->vVar2Inf, -1 );
Vec_IntPush( p->vVar2Inf, -1 );
// abstraction
p->vAssigned = Vec_IntAlloc( 1000 );
if ( vGateClassesOld )
{
p->vIncluded = Vec_IntDup( vGateClassesOld );
Aig_Gla1CollectAssigned( p, vGateClassesOld );
assert( fNaiveCnf );
}
else
p->vIncluded = Vec_IntStart( Aig_ManObjNumMax(pAig) );
// components
p->vPis = Vec_IntAlloc( 1000 );
p->vPPis = Vec_IntAlloc( 1000 );
p->vFlops = Vec_IntAlloc( 1000 );
p->vNodes = Vec_IntAlloc( 1000 );
// CNF computation
if ( !fNaiveCnf )
{
p->vLeaves = Vec_PtrAlloc( 100 );
p->vVolume = Vec_PtrAlloc( 100 );
p->vCover = Vec_IntAlloc( 1 << 16 );
p->vObj2Cnf = Vec_PtrStart( Aig_ManObjNumMax(pAig) );
p->vLits = Vec_IntAlloc( 100 );
Cnf_DeriveFastMark( pAig );
}
// start the SAT solver
p->pSat = sat_solver_new();
sat_solver_setnvars( p->pSat, 256 );
return p;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Aig_Gla1ManStop( Aig_Gla1Man_t * p )
{
Vec_IntFreeP( &p->vObj2Vec );
Vec_IntFreeP( &p->vVec2Var );
Vec_IntFreeP( &p->vVar2Inf );
Vec_IntFreeP( &p->vAssigned );
Vec_IntFreeP( &p->vIncluded );
Vec_IntFreeP( &p->vPis );
Vec_IntFreeP( &p->vPPis );
Vec_IntFreeP( &p->vFlops );
Vec_IntFreeP( &p->vNodes );
if ( p->vObj2Cnf )
{
Vec_PtrFreeP( &p->vLeaves );
Vec_PtrFreeP( &p->vVolume );
Vec_IntFreeP( &p->vCover );
Vec_VecFreeP( (Vec_Vec_t **)&p->vObj2Cnf );
Vec_IntFreeP( &p->vLits );
Aig_ManCleanMarkA( p->pAig );
}
if ( p->pSat )
sat_solver_delete( p->pSat );
ABC_FREE( p );
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Abc_Cex_t * Aig_Gla1DeriveCex( Aig_Gla1Man_t * p, int iFrame )
{
Abc_Cex_t * pCex;
Aig_Obj_t * pObj;
int i, f, iVecId, iSatId;
pCex = Abc_CexAlloc( Vec_IntSize(p->vFlops), Vec_IntSize(p->vPis) + Vec_IntSize(p->vPPis), iFrame+1 );
pCex->iFrame = iFrame;
Aig_ManForEachObjVec( p->vPis, p->pAig, pObj, i )
{
iVecId = Vec_IntEntry( p->vObj2Vec, Aig_ObjId(pObj) );
assert( iVecId > 0 );
for ( f = 0; f <= iFrame; f++ )
{
iSatId = Vec_IntEntry( p->vVec2Var, iVecId * p->nFrames + f );
if ( iSatId == 0 )
continue;
assert( iSatId > 0 );
if ( sat_solver_var_value(p->pSat, iSatId) )
Abc_InfoSetBit( pCex->pData, pCex->nRegs + f * pCex->nPis + i );
}
}
Aig_ManForEachObjVec( p->vPPis, p->pAig, pObj, i )
{
iVecId = Vec_IntEntry( p->vObj2Vec, Aig_ObjId(pObj) );
assert( iVecId > 0 );
for ( f = 0; f <= iFrame; f++ )
{
iSatId = Vec_IntEntry( p->vVec2Var, iVecId * p->nFrames + f );
if ( iSatId == 0 )
continue;
assert( iSatId > 0 );
if ( sat_solver_var_value(p->pSat, iSatId) )
Abc_InfoSetBit( pCex->pData, pCex->nRegs + f * pCex->nPis + Vec_IntSize(p->vPis) + i );
}
}
return pCex;
}
/**Function*************************************************************
Synopsis [Prints current abstraction statistics.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Aig_Gla1PrintAbstr( Aig_Gla1Man_t * p, int f, int r, int v, int c )
{
if ( r == 0 )
printf( "== %3d ==", f );
else
printf( " " );
printf( " %4d PI =%6d PPI =%6d FF =%6d Node =%6d Var =%7d Conf =%6d\n",
r, Vec_IntSize(p->vPis), Vec_IntSize(p->vPPis), Vec_IntSize(p->vFlops), Vec_IntSize(p->vNodes), v, c );
}
/**Function*************************************************************
Synopsis [Prints current abstraction statistics.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Aig_Gla1ExtendIncluded( Aig_Gla1Man_t * p )
{
Aig_Obj_t * pObj;
int i, k;
Aig_ManForEachNode( p->pAig, pObj, i )
{
if ( !Vec_IntEntry( p->vIncluded, i ) )
continue;
Cnf_ComputeClauses( p->pAig, pObj, p->vLeaves, p->vVolume, NULL, p->vCover, p->vNodes );
Vec_PtrForEachEntry( Aig_Obj_t *, p->vVolume, pObj, k )
{
assert( Aig_ObjId(pObj) <= i );
Vec_IntWriteEntry( p->vIncluded, Aig_ObjId(pObj), 1 );
}
}
}
/**Function*************************************************************
Synopsis [Performs gate-level localization abstraction.]
Description [Returns array of objects included in the abstraction. This array
may contain only const1, flop outputs, and internal nodes, that is, objects
that should have clauses added to the SAT solver.]
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Int_t * Aig_Gla1ManPerform( Aig_Man_t * pAig, Vec_Int_t * vGateClassesOld, int nStart, int nFramesMax, int nConfLimit, int TimeLimit, int fNaiveCnf, int fVerbose, int * piFrame )
{
Vec_Int_t * vResult = NULL;
Aig_Gla1Man_t * p;
Aig_Man_t * pAbs;
Aig_Obj_t * pObj;
Abc_Cex_t * pCex;
Vec_Int_t * vPPiRefine;
int f, g, r, i, iSatVar, Lit, Entry, RetValue;
int nConfBef, nConfAft;
clock_t clk, clkTotal = clock();
clock_t nTimeToStop = TimeLimit ? TimeLimit * CLOCKS_PER_SEC + clock(): 0;
assert( Saig_ManPoNum(pAig) == 1 );
if ( nFramesMax == 0 )
nFramesMax = ABC_INFINITY;
if ( fVerbose )
{
if ( TimeLimit )
printf( "Abstracting from frame %d to frame %d with timeout %d sec.\n", nStart, nFramesMax, TimeLimit );
else
printf( "Abstracting from frame %d to frame %d with no timeout.\n", nStart, nFramesMax );
}
// start the solver
p = Aig_Gla1ManStart( pAig, vGateClassesOld, fNaiveCnf );
p->nFramesMax = nFramesMax;
p->nConfLimit = nConfLimit;
p->fVerbose = fVerbose;
// include constant node
Vec_IntWriteEntry( p->vIncluded, 0, 1 );
Aig_Gla1FetchVecId( p, Aig_ManConst1(pAig) );
// set runtime limit
if ( TimeLimit )
sat_solver_set_runtime_limit( p->pSat, nTimeToStop );
// iterate over the timeframes
for ( f = 0; f < nFramesMax; f++ )
{
// initialize abstraction in this timeframe
Aig_ManForEachObjVec( p->vAssigned, pAig, pObj, i )
if ( Vec_IntEntry(p->vIncluded, Aig_ObjId(pObj)) )
if ( !Aig_Gla1ObjAddToSolver( p, pObj, f ) )
printf( "Error! SAT solver became UNSAT.\n" );
// skip checking if we are not supposed to
if ( f < nStart )
continue;
// create output literal to represent property failure
pObj = Aig_ManCo( pAig, 0 );
iSatVar = Aig_Gla1FetchVar( p, Aig_ObjFanin0(pObj), f );
Lit = toLitCond( iSatVar, Aig_ObjFaninC0(pObj) );
// try solving the abstraction
Aig_Gla1CollectAbstr( p );
for ( r = 0; r < ABC_INFINITY; r++ )
{
// try to find a counter-example
clk = clock();
nConfBef = p->pSat->stats.conflicts;
RetValue = sat_solver_solve( p->pSat, &Lit, &Lit + 1,
(ABC_INT64_T)nConfLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
nConfAft = p->pSat->stats.conflicts;
p->timeSat += clock() - clk;
if ( RetValue != l_True )
{
if ( fVerbose )
{
if ( r == 0 )
printf( "== %3d ==", f );
else
printf( " " );
if ( TimeLimit && clock() > nTimeToStop )
printf( " SAT solver timed out after %d seconds.\n", TimeLimit );
else if ( RetValue != l_False )
printf( " SAT solver returned UNDECIDED after %5d conflicts.\n", nConfAft - nConfBef );
else
{
printf( " SAT solver returned UNSAT after %5d conflicts. ", nConfAft - nConfBef );
Abc_PrintTime( 1, "Total time", clock() - clkTotal );
}
}
break;
}
clk = clock();
// derive abstraction
pAbs = Aig_Gla1DeriveAbs( p );
// derive counter-example
pCex = Aig_Gla1DeriveCex( p, f );
// verify the counter-example
RetValue = Saig_ManVerifyCex( pAbs, pCex );
if ( RetValue == 0 )
printf( "Error! CEX is invalid.\n" );
// perform refinement
vPPiRefine = Saig_ManCbaFilterInputs( pAbs, Vec_IntSize(p->vPis), pCex, 0 );
Vec_IntForEachEntry( vPPiRefine, Entry, i )
{
pObj = Aig_ManObj( pAig, Vec_IntEntry(p->vPPis, Entry) );
assert( Aig_ObjIsNode(pObj) || Saig_ObjIsLo(p->pAig, pObj) );
assert( Vec_IntEntry( p->vIncluded, Aig_ObjId(pObj) ) == 0 );
Vec_IntWriteEntry( p->vIncluded, Aig_ObjId(pObj), 1 );
for ( g = 0; g <= f; g++ )
if ( !Aig_Gla1ObjAddToSolver( p, pObj, g ) )
printf( "Error! SAT solver became UNSAT.\n" );
}
if ( Vec_IntSize(vPPiRefine) == 0 )
{
Vec_IntFreeP( &p->vIncluded );
Vec_IntFree( vPPiRefine );
Aig_ManStop( pAbs );
Abc_CexFree( pCex );
break;
}
Vec_IntFree( vPPiRefine );
Aig_ManStop( pAbs );
Abc_CexFree( pCex );
p->timeRef += clock() - clk;
// prepare abstraction
Aig_Gla1CollectAbstr( p );
if ( fVerbose )
Aig_Gla1PrintAbstr( p, f, r, p->pSat->size, nConfAft - nConfBef );
}
if ( RetValue != l_False )
break;
}
p->timeTotal = clock() - clkTotal;
if ( f == nFramesMax )
printf( "Finished %d frames without exceeding conflict limit (%d).\n", f, nConfLimit );
else if ( p->vIncluded == NULL )
printf( "The problem is SAT in frame %d. The CEX is currently not produced.\n", f );
else
printf( "Ran out of conflict limit (%d) at frame %d.\n", nConfLimit, f );
*piFrame = f;
// print stats
if ( fVerbose )
{
ABC_PRTP( "Sat ", p->timeSat, p->timeTotal );
ABC_PRTP( "Ref ", p->timeRef, p->timeTotal );
ABC_PRTP( "Total ", p->timeTotal, p->timeTotal );
}
// prepare return value
if ( !fNaiveCnf && p->vIncluded )
Aig_Gla1ExtendIncluded( p );
vResult = p->vIncluded; p->vIncluded = NULL;
Aig_Gla1ManStop( p );
return vResult;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END