blob: f9d65bbb1aa33bf705016a449149605926e8f737 [file] [log] [blame]
/**CFile****************************************************************
FileName [bmcBmc2.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [SAT-based bounded model checking.]
Synopsis [Simple BMC package.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: bmcBmc2.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
#include "sat/cnf/cnf.h"
#include "sat/bsat/satStore.h"
#include "sat/satoko/satoko.h"
#include "proof/ssw/ssw.h"
#include "bmc.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
//#define AIG_VISITED ((Aig_Obj_t *)(ABC_PTRUINT_T)1)
typedef struct Saig_Bmc_t_ Saig_Bmc_t;
struct Saig_Bmc_t_
{
// parameters
int nFramesMax; // the max number of timeframes to consider
int nNodesMax; // the max number of nodes to add
int nConfMaxOne; // the max number of conflicts at a target
int nConfMaxAll; // the max number of conflicts for all targets
int fVerbose; // enables verbose output
// AIG managers
Aig_Man_t * pAig; // the user's AIG manager
Aig_Man_t * pFrm; // Frames manager
Vec_Int_t * vVisited; // nodes visited in Frames
// node mapping
int nObjs; // the largest number of an AIG object
Vec_Ptr_t * vAig2Frm; // mapping of AIG nodees into Frames nodes
// SAT solver
sat_solver * pSat; // SAT solver
satoko_t * pSat2; // SAT solver
int nSatVars; // the number of used SAT variables
Vec_Int_t * vObj2Var; // mapping of frames objects in CNF variables
int nStitchVars;
// subproblems
Vec_Ptr_t * vTargets; // targets to be solved in this interval
int iFramePrev; // previous frame
int iFrameLast; // last frame
int iOutputLast; // last output
int iFrameFail; // failed frame
int iOutputFail; // failed output
};
static inline Aig_Obj_t * Saig_BmcObjFrame( Saig_Bmc_t * p, Aig_Obj_t * pObj, int i )
{
// return (Aig_Obj_t *)Vec_PtrGetEntry( p->vAig2Frm, p->nObjs*i+pObj->Id );
Aig_Obj_t * pRes;
Vec_Int_t * vFrame = (Vec_Int_t *)Vec_PtrEntry( p->vAig2Frm, i );
int iObjLit = Vec_IntEntry( vFrame, Aig_ObjId(pObj) );
if ( iObjLit == -1 )
return NULL;
pRes = Aig_ManObj( p->pFrm, Abc_Lit2Var(iObjLit) );
if ( pRes == NULL )
Vec_IntWriteEntry( vFrame, Aig_ObjId(pObj), -1 );
else
pRes = Aig_NotCond( pRes, Abc_LitIsCompl(iObjLit) );
return pRes;
}
static inline void Saig_BmcObjSetFrame( Saig_Bmc_t * p, Aig_Obj_t * pObj, int i, Aig_Obj_t * pNode )
{
// Vec_PtrSetEntry( p->vAig2Frm, p->nObjs*i+pObj->Id, pNode );
Vec_Int_t * vFrame;
int iObjLit;
if ( i == Vec_PtrSize(p->vAig2Frm) )
Vec_PtrPush( p->vAig2Frm, Vec_IntStartFull(p->nObjs) );
assert( i < Vec_PtrSize(p->vAig2Frm) );
vFrame = (Vec_Int_t *)Vec_PtrEntry( p->vAig2Frm, i );
if ( pNode == NULL )
iObjLit = -1;
else
iObjLit = Abc_Var2Lit( Aig_ObjId(Aig_Regular(pNode)), Aig_IsComplement(pNode) );
Vec_IntWriteEntry( vFrame, Aig_ObjId(pObj), iObjLit );
}
static inline Aig_Obj_t * Saig_BmcObjChild0( Saig_Bmc_t * p, Aig_Obj_t * pObj, int i ) { assert( !Aig_IsComplement(pObj) ); return Aig_NotCond(Saig_BmcObjFrame(p, Aig_ObjFanin0(pObj), i), Aig_ObjFaninC0(pObj)); }
static inline Aig_Obj_t * Saig_BmcObjChild1( Saig_Bmc_t * p, Aig_Obj_t * pObj, int i ) { assert( !Aig_IsComplement(pObj) ); return Aig_NotCond(Saig_BmcObjFrame(p, Aig_ObjFanin1(pObj), i), Aig_ObjFaninC1(pObj)); }
static inline int Saig_BmcSatNum( Saig_Bmc_t * p, Aig_Obj_t * pObj ) { return Vec_IntGetEntry( p->vObj2Var, pObj->Id ); }
static inline void Saig_BmcSetSatNum( Saig_Bmc_t * p, Aig_Obj_t * pObj, int Num ) { Vec_IntSetEntry(p->vObj2Var, pObj->Id, Num); }
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
#define ABS_ZER 1
#define ABS_ONE 2
#define ABS_UND 3
static inline int Abs_ManSimInfoNot( int Value )
{
if ( Value == ABS_ZER )
return ABS_ONE;
if ( Value == ABS_ONE )
return ABS_ZER;
return ABS_UND;
}
static inline int Abs_ManSimInfoAnd( int Value0, int Value1 )
{
if ( Value0 == ABS_ZER || Value1 == ABS_ZER )
return ABS_ZER;
if ( Value0 == ABS_ONE && Value1 == ABS_ONE )
return ABS_ONE;
return ABS_UND;
}
static inline int Abs_ManSimInfoGet( Vec_Ptr_t * vSimInfo, Aig_Obj_t * pObj, int iFrame )
{
unsigned * pInfo = (unsigned *)Vec_PtrEntry( vSimInfo, iFrame );
return 3 & (pInfo[Aig_ObjId(pObj) >> 4] >> ((Aig_ObjId(pObj) & 15) << 1));
}
static inline void Abs_ManSimInfoSet( Vec_Ptr_t * vSimInfo, Aig_Obj_t * pObj, int iFrame, int Value )
{
unsigned * pInfo = (unsigned *)Vec_PtrEntry( vSimInfo, iFrame );
assert( Value >= ABS_ZER && Value <= ABS_UND );
Value ^= Abs_ManSimInfoGet( vSimInfo, pObj, iFrame );
pInfo[Aig_ObjId(pObj) >> 4] ^= (Value << ((Aig_ObjId(pObj) & 15) << 1));
}
/**Function*************************************************************
Synopsis [Performs ternary simulation for one node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Abs_ManExtendOneEval_rec( Vec_Ptr_t * vSimInfo, Aig_Man_t * p, Aig_Obj_t * pObj, int iFrame )
{
int Value0, Value1, Value;
Value = Abs_ManSimInfoGet( vSimInfo, pObj, iFrame );
if ( Value )
return Value;
if ( Aig_ObjIsCi(pObj) )
{
assert( Saig_ObjIsLo(p, pObj) );
Value = Abs_ManExtendOneEval_rec( vSimInfo, p, Saig_ObjLoToLi(p, pObj), iFrame-1 );
Abs_ManSimInfoSet( vSimInfo, pObj, iFrame, Value );
return Value;
}
Value0 = Abs_ManExtendOneEval_rec( vSimInfo, p, Aig_ObjFanin0(pObj), iFrame );
if ( Aig_ObjFaninC0(pObj) )
Value0 = Abs_ManSimInfoNot( Value0 );
if ( Aig_ObjIsCo(pObj) )
{
Abs_ManSimInfoSet( vSimInfo, pObj, iFrame, Value0 );
return Value0;
}
assert( Aig_ObjIsNode(pObj) );
if ( Value0 == ABS_ZER )
Value = ABS_ZER;
else
{
Value1 = Abs_ManExtendOneEval_rec( vSimInfo, p, Aig_ObjFanin1(pObj), iFrame );
if ( Aig_ObjFaninC1(pObj) )
Value1 = Abs_ManSimInfoNot( Value1 );
Value = Abs_ManSimInfoAnd( Value0, Value1 );
}
Abs_ManSimInfoSet( vSimInfo, pObj, iFrame, Value );
assert( Value );
return Value;
}
/**Function*************************************************************
Synopsis [Performs ternary simulation for one design.]
Description [The returned array contains the result of ternary
simulation for all the frames where the output could be proved 0.]
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Ptr_t * Abs_ManTernarySimulate( Aig_Man_t * p, int nFramesMax, int fVerbose )
{
Vec_Ptr_t * vSimInfo;
Aig_Obj_t * pObj;
int i, f, nFramesLimit, nFrameWords;
abctime clk = Abc_Clock();
assert( Aig_ManRegNum(p) > 0 );
// the maximum number of frames will be determined to use at most 200Mb of RAM
nFramesLimit = 1 + (200000000 * 4)/Aig_ManObjNum(p);
nFramesLimit = Abc_MinInt( nFramesLimit, nFramesMax );
nFrameWords = Abc_BitWordNum( 2 * Aig_ManObjNum(p) );
// allocate simulation info
vSimInfo = Vec_PtrAlloc( nFramesLimit );
for ( f = 0; f < nFramesLimit; f++ )
{
Vec_PtrPush( vSimInfo, ABC_CALLOC(unsigned, nFrameWords) );
if ( f == 0 )
{
Saig_ManForEachLo( p, pObj, i )
Abs_ManSimInfoSet( vSimInfo, pObj, 0, ABS_ZER );
}
Abs_ManSimInfoSet( vSimInfo, Aig_ManConst1(p), f, ABS_ONE );
Saig_ManForEachPi( p, pObj, i )
Abs_ManSimInfoSet( vSimInfo, pObj, f, ABS_UND );
Saig_ManForEachPo( p, pObj, i )
Abs_ManExtendOneEval_rec( vSimInfo, p, pObj, f );
// check if simulation has derived at least one fail or unknown
Saig_ManForEachPo( p, pObj, i )
if ( Abs_ManSimInfoGet(vSimInfo, pObj, f) != ABS_ZER )
{
if ( fVerbose )
{
printf( "Ternary sim found non-zero output in frame %d. Used %5.2f MB. ",
f, 0.25 * (f+1) * Aig_ManObjNum(p) / (1<<20) );
ABC_PRT( "Time", Abc_Clock() - clk );
}
return vSimInfo;
}
}
if ( fVerbose )
{
printf( "Ternary sim proved all outputs in the first %d frames. Used %5.2f MB. ",
nFramesLimit, 0.25 * nFramesLimit * Aig_ManObjNum(p) / (1<<20) );
ABC_PRT( "Time", Abc_Clock() - clk );
}
return vSimInfo;
}
/**Function*************************************************************
Synopsis [Free the array of simulation info.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abs_ManFreeAray( Vec_Ptr_t * p )
{
void * pTemp;
int i;
Vec_PtrForEachEntry( void *, p, pTemp, i )
ABC_FREE( pTemp );
Vec_PtrFree( p );
}
/**Function*************************************************************
Synopsis [Create manager.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Saig_Bmc_t * Saig_BmcManStart( Aig_Man_t * pAig, int nFramesMax, int nNodesMax, int nConfMaxOne, int nConfMaxAll, int fVerbose, int fUseSatoko )
{
Saig_Bmc_t * p;
Aig_Obj_t * pObj;
int i, Lit;
// assert( Aig_ManRegNum(pAig) > 0 );
p = (Saig_Bmc_t *)ABC_ALLOC( char, sizeof(Saig_Bmc_t) );
memset( p, 0, sizeof(Saig_Bmc_t) );
// set parameters
p->nFramesMax = nFramesMax;
p->nNodesMax = nNodesMax;
p->nConfMaxOne = nConfMaxOne;
p->nConfMaxAll = nConfMaxAll;
p->fVerbose = fVerbose;
p->pAig = pAig;
p->nObjs = Aig_ManObjNumMax(pAig);
// create node and variable mappings
p->vAig2Frm = Vec_PtrAlloc( 100 );
p->vObj2Var = Vec_IntAlloc( 0 );
Vec_IntFill( p->vObj2Var, p->nObjs, 0 );
// start the AIG manager and map primary inputs
p->pFrm = Aig_ManStart( p->nObjs );
Saig_ManForEachLo( pAig, pObj, i )
Saig_BmcObjSetFrame( p, pObj, 0, Aig_ManConst0(p->pFrm) );
// create SAT solver
p->nSatVars = 1;
Lit = toLit( p->nSatVars );
if ( fUseSatoko )
{
satoko_opts_t opts;
satoko_default_opts(&opts);
opts.conf_limit = nConfMaxOne;
p->pSat2 = satoko_create();
satoko_configure(p->pSat2, &opts);
satoko_setnvars(p->pSat2, 2000);
satoko_add_clause( p->pSat2, &Lit, 1 );
}
else
{
p->pSat = sat_solver_new();
p->pSat->nLearntStart = 10000;//p->pPars->nLearnedStart;
p->pSat->nLearntDelta = 5000;//p->pPars->nLearnedDelta;
p->pSat->nLearntRatio = 75;//p->pPars->nLearnedPerce;
p->pSat->nLearntMax = p->pSat->nLearntStart;
sat_solver_setnvars( p->pSat, 2000 );
sat_solver_addclause( p->pSat, &Lit, &Lit + 1 );
}
Saig_BmcSetSatNum( p, Aig_ManConst1(p->pFrm), p->nSatVars++ );
// other data structures
p->vTargets = Vec_PtrAlloc( 1000 );
p->vVisited = Vec_IntAlloc( 1000 );
p->iOutputFail = -1;
p->iFrameFail = -1;
return p;
}
/**Function*************************************************************
Synopsis [Delete manager.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Saig_BmcManStop( Saig_Bmc_t * p )
{
Aig_ManStop( p->pFrm );
Vec_VecFree( (Vec_Vec_t *)p->vAig2Frm );
Vec_IntFree( p->vObj2Var );
if ( p->pSat ) sat_solver_delete( p->pSat );
if ( p->pSat2 ) satoko_destroy( p->pSat2 );
Vec_PtrFree( p->vTargets );
Vec_IntFree( p->vVisited );
ABC_FREE( p );
}
/**Function*************************************************************
Synopsis [Explores the possibility of constructing the output.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
/*
Aig_Obj_t * Saig_BmcIntervalExplore_rec( Saig_Bmc_t * p, Aig_Obj_t * pObj, int i )
{
Aig_Obj_t * pRes, * p0, * p1, * pConst1 = Aig_ManConst1(p->pAig);
pRes = Saig_BmcObjFrame( p, pObj, i );
if ( pRes != NULL )
return pRes;
if ( Saig_ObjIsPi( p->pAig, pObj ) )
pRes = AIG_VISITED;
else if ( Saig_ObjIsLo( p->pAig, pObj ) )
pRes = Saig_BmcIntervalExplore_rec( p, Saig_ObjLoToLi(p->pAig, pObj), i-1 );
else if ( Aig_ObjIsCo( pObj ) )
{
pRes = Saig_BmcIntervalExplore_rec( p, Aig_ObjFanin0(pObj), i );
if ( pRes != AIG_VISITED )
pRes = Saig_BmcObjChild0( p, pObj, i );
}
else
{
p0 = Saig_BmcIntervalExplore_rec( p, Aig_ObjFanin0(pObj), i );
if ( p0 != AIG_VISITED )
p0 = Saig_BmcObjChild0( p, pObj, i );
p1 = Saig_BmcIntervalExplore_rec( p, Aig_ObjFanin1(pObj), i );
if ( p1 != AIG_VISITED )
p1 = Saig_BmcObjChild1( p, pObj, i );
if ( p0 == Aig_Not(p1) )
pRes = Aig_ManConst0(p->pFrm);
else if ( Aig_Regular(p0) == pConst1 )
pRes = (p0 == pConst1) ? p1 : Aig_ManConst0(p->pFrm);
else if ( Aig_Regular(p1) == pConst1 )
pRes = (p1 == pConst1) ? p0 : Aig_ManConst0(p->pFrm);
else
pRes = AIG_VISITED;
if ( pRes != AIG_VISITED && !Aig_ObjIsConst1(Aig_Regular(pRes)) )
pRes = AIG_VISITED;
}
Saig_BmcObjSetFrame( p, pObj, i, pRes );
return pRes;
}
*/
/**Function*************************************************************
Synopsis [Performs the actual construction of the output.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Aig_Obj_t * Saig_BmcIntervalConstruct_rec( Saig_Bmc_t * p, Aig_Obj_t * pObj, int i, Vec_Int_t * vVisited )
{
Aig_Obj_t * pRes;
pRes = Saig_BmcObjFrame( p, pObj, i );
if ( pRes != NULL )
return pRes;
if ( Saig_ObjIsPi( p->pAig, pObj ) )
pRes = Aig_ObjCreateCi(p->pFrm);
else if ( Saig_ObjIsLo( p->pAig, pObj ) )
pRes = Saig_BmcIntervalConstruct_rec( p, Saig_ObjLoToLi(p->pAig, pObj), i-1, vVisited );
else if ( Aig_ObjIsCo( pObj ) )
{
Saig_BmcIntervalConstruct_rec( p, Aig_ObjFanin0(pObj), i, vVisited );
pRes = Saig_BmcObjChild0( p, pObj, i );
}
else
{
Saig_BmcIntervalConstruct_rec( p, Aig_ObjFanin0(pObj), i, vVisited );
if ( Saig_BmcObjChild0(p, pObj, i) == Aig_ManConst0(p->pFrm) )
pRes = Aig_ManConst0(p->pFrm);
else
{
Saig_BmcIntervalConstruct_rec( p, Aig_ObjFanin1(pObj), i, vVisited );
pRes = Aig_And( p->pFrm, Saig_BmcObjChild0(p, pObj, i), Saig_BmcObjChild1(p, pObj, i) );
}
}
assert( pRes != NULL );
Saig_BmcObjSetFrame( p, pObj, i, pRes );
Vec_IntPush( vVisited, Aig_ObjId(pObj) );
Vec_IntPush( vVisited, i );
return pRes;
}
/**Function*************************************************************
Synopsis [Adds new AIG nodes to the frames.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Saig_BmcInterval( Saig_Bmc_t * p )
{
Aig_Obj_t * pTarget;
int i, iObj, iFrame;
int nNodes = Aig_ManObjNum( p->pFrm );
Vec_PtrClear( p->vTargets );
p->iFramePrev = p->iFrameLast;
for ( ; p->iFrameLast < p->nFramesMax; p->iFrameLast++, p->iOutputLast = 0 )
{
if ( p->iOutputLast == 0 )
{
Saig_BmcObjSetFrame( p, Aig_ManConst1(p->pAig), p->iFrameLast, Aig_ManConst1(p->pFrm) );
}
for ( ; p->iOutputLast < Saig_ManPoNum(p->pAig); p->iOutputLast++ )
{
if ( Aig_ManObjNum(p->pFrm) >= nNodes + p->nNodesMax )
return;
// Saig_BmcIntervalExplore_rec( p, Aig_ManCo(p->pAig, p->iOutputLast), p->iFrameLast );
Vec_IntClear( p->vVisited );
pTarget = Saig_BmcIntervalConstruct_rec( p, Aig_ManCo(p->pAig, p->iOutputLast), p->iFrameLast, p->vVisited );
Vec_PtrPush( p->vTargets, pTarget );
Aig_ObjCreateCo( p->pFrm, pTarget );
Aig_ManCleanup( p->pFrm ); // it is not efficient to cleanup the whole manager!!!
// check if the node is gone
Vec_IntForEachEntryDouble( p->vVisited, iObj, iFrame, i )
Saig_BmcObjFrame( p, Aig_ManObj(p->pAig, iObj), iFrame );
// it is not efficient to remove nodes, which may be used later!!!
}
}
}
/**Function*************************************************************
Synopsis [Performs the actual construction of the output.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Aig_Obj_t * Saig_BmcIntervalToAig_rec( Saig_Bmc_t * p, Aig_Man_t * pNew, Aig_Obj_t * pObj )
{
if ( pObj->pData )
return (Aig_Obj_t *)pObj->pData;
Vec_IntPush( p->vVisited, Aig_ObjId(pObj) );
if ( Saig_BmcSatNum(p, pObj) || Aig_ObjIsCi(pObj) )
{
p->nStitchVars += !Aig_ObjIsCi(pObj);
return (Aig_Obj_t *)(pObj->pData = Aig_ObjCreateCi(pNew));
}
Saig_BmcIntervalToAig_rec( p, pNew, Aig_ObjFanin0(pObj) );
Saig_BmcIntervalToAig_rec( p, pNew, Aig_ObjFanin1(pObj) );
assert( pObj->pData == NULL );
return (Aig_Obj_t *)(pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ));
}
/**Function*************************************************************
Synopsis [Creates AIG of the newly added nodes.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Aig_Man_t * Saig_BmcIntervalToAig( Saig_Bmc_t * p )
{
Aig_Man_t * pNew;
Aig_Obj_t * pObj, * pObjNew;
int i;
Aig_ManForEachObj( p->pFrm, pObj, i )
assert( pObj->pData == NULL );
pNew = Aig_ManStart( p->nNodesMax );
Aig_ManConst1(p->pFrm)->pData = Aig_ManConst1(pNew);
Vec_IntClear( p->vVisited );
Vec_IntPush( p->vVisited, Aig_ObjId(Aig_ManConst1(p->pFrm)) );
Vec_PtrForEachEntry( Aig_Obj_t *, p->vTargets, pObj, i )
{
// assert( !Aig_ObjIsConst1(Aig_Regular(pObj)) );
pObjNew = Saig_BmcIntervalToAig_rec( p, pNew, Aig_Regular(pObj) );
assert( !Aig_IsComplement(pObjNew) );
Aig_ObjCreateCo( pNew, pObjNew );
}
return pNew;
}
/**Function*************************************************************
Synopsis [Derives CNF for the newly added nodes.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Saig_BmcLoadCnf( Saig_Bmc_t * p, Cnf_Dat_t * pCnf )
{
Aig_Obj_t * pObj, * pObjNew;
int i, Lits[2], VarNumOld, VarNumNew;
Aig_ManForEachObjVec( p->vVisited, p->pFrm, pObj, i )
{
// get the new variable of this node
pObjNew = (Aig_Obj_t *)pObj->pData;
pObj->pData = NULL;
VarNumNew = pCnf->pVarNums[ pObjNew->Id ];
if ( VarNumNew == -1 )
continue;
// get the old variable of this node
VarNumOld = Saig_BmcSatNum( p, pObj );
if ( VarNumOld == 0 )
{
Saig_BmcSetSatNum( p, pObj, VarNumNew );
continue;
}
// add clauses connecting existing variables
Lits[0] = toLitCond( VarNumOld, 0 );
Lits[1] = toLitCond( VarNumNew, 1 );
if ( p->pSat2 )
{
if ( !satoko_add_clause( p->pSat2, Lits, 2 ) )
assert( 0 );
}
else
{
if ( !sat_solver_addclause( p->pSat, Lits, Lits+2 ) )
assert( 0 );
}
Lits[0] = toLitCond( VarNumOld, 1 );
Lits[1] = toLitCond( VarNumNew, 0 );
if ( p->pSat2 )
{
if ( !satoko_add_clause( p->pSat2, Lits, 2 ) )
assert( 0 );
}
else
{
if ( !sat_solver_addclause( p->pSat, Lits, Lits+2 ) )
assert( 0 );
}
}
// add CNF to the SAT solver
if ( p->pSat2 )
{
for ( i = 0; i < pCnf->nClauses; i++ )
if ( !satoko_add_clause( p->pSat2, pCnf->pClauses[i], pCnf->pClauses[i+1]-pCnf->pClauses[i] ) )
break;
}
else
{
for ( i = 0; i < pCnf->nClauses; i++ )
if ( !sat_solver_addclause( p->pSat, pCnf->pClauses[i], pCnf->pClauses[i+1] ) )
break;
}
if ( i < pCnf->nClauses )
printf( "SAT solver became UNSAT after adding clauses.\n" );
}
/**Function*************************************************************
Synopsis [Solves targets with the given resource limit.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Saig_BmcDeriveFailed( Saig_Bmc_t * p, int iTargetFail )
{
int k;
p->iOutputFail = p->iOutputLast;
p->iFrameFail = p->iFrameLast;
for ( k = Vec_PtrSize(p->vTargets); k > iTargetFail; k-- )
{
if ( p->iOutputFail == 0 )
{
p->iOutputFail = Saig_ManPoNum(p->pAig);
p->iFrameFail--;
}
p->iOutputFail--;
}
}
/**Function*************************************************************
Synopsis [Solves targets with the given resource limit.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Abc_Cex_t * Saig_BmcGenerateCounterExample( Saig_Bmc_t * p )
{
Abc_Cex_t * pCex;
Aig_Obj_t * pObj, * pObjFrm;
int i, f, iVarNum;
// start the counter-example
pCex = Abc_CexAlloc( Aig_ManRegNum(p->pAig), Saig_ManPiNum(p->pAig), p->iFrameFail+1 );
pCex->iFrame = p->iFrameFail;
pCex->iPo = p->iOutputFail;
// copy the bit data
for ( f = 0; f <= p->iFrameFail; f++ )
{
Saig_ManForEachPi( p->pAig, pObj, i )
{
pObjFrm = Saig_BmcObjFrame( p, pObj, f );
if ( pObjFrm == NULL )
continue;
iVarNum = Saig_BmcSatNum( p, pObjFrm );
if ( iVarNum == 0 )
continue;
if ( p->pSat2 ? satoko_read_cex_varvalue(p->pSat2, iVarNum) : sat_solver_var_value(p->pSat, iVarNum) )
Abc_InfoSetBit( pCex->pData, pCex->nRegs + Saig_ManPiNum(p->pAig) * f + i );
}
}
// verify the counter example
if ( !Saig_ManVerifyCex( p->pAig, pCex ) )
{
printf( "Saig_BmcGenerateCounterExample(): Counter-example is invalid.\n" );
Abc_CexFree( pCex );
pCex = NULL;
}
return pCex;
}
/**Function*************************************************************
Synopsis [Solves targets with the given resource limit.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Saig_BmcSolveTargets( Saig_Bmc_t * p, int nStart, int * pnOutsSolved )
{
Aig_Obj_t * pObj;
int i, k, VarNum, Lit, status, RetValue;
assert( Vec_PtrSize(p->vTargets) > 0 );
if ( p->pSat && p->pSat->qtail != p->pSat->qhead )
{
RetValue = sat_solver_simplify(p->pSat);
assert( RetValue != 0 );
}
Vec_PtrForEachEntry( Aig_Obj_t *, p->vTargets, pObj, i )
{
if ( ((*pnOutsSolved)++ / Saig_ManPoNum(p->pAig)) < nStart )
continue;
if ( p->nConfMaxAll && (p->pSat ? p->pSat->stats.conflicts : satoko_conflictnum(p->pSat2)) > p->nConfMaxAll )
return l_Undef;
VarNum = Saig_BmcSatNum( p, Aig_Regular(pObj) );
Lit = toLitCond( VarNum, Aig_IsComplement(pObj) );
if ( p->pSat2 )
RetValue = satoko_solve_assumptions_limit( p->pSat2, &Lit, 1, p->nConfMaxOne );
else
RetValue = sat_solver_solve( p->pSat, &Lit, &Lit + 1, (ABC_INT64_T)p->nConfMaxOne, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
if ( RetValue == l_False ) // unsat
{
// add final unit clause
Lit = lit_neg( Lit );
if ( p->pSat2 )
status = satoko_add_clause( p->pSat2, &Lit, 1 );
else
status = sat_solver_addclause( p->pSat, &Lit, &Lit + 1 );
assert( status );
if ( p->pSat )
{
// add learned units
for ( k = 0; k < veci_size(&p->pSat->unit_lits); k++ )
{
Lit = veci_begin(&p->pSat->unit_lits)[k];
status = sat_solver_addclause( p->pSat, &Lit, &Lit + 1 );
assert( status );
}
veci_resize(&p->pSat->unit_lits, 0);
// propagate units
sat_solver_compress( p->pSat );
}
continue;
}
if ( RetValue == l_Undef ) // undecided
return l_Undef;
// generate counter-example
Saig_BmcDeriveFailed( p, i );
p->pAig->pSeqModel = Saig_BmcGenerateCounterExample( p );
{
// extern Vec_Int_t * Saig_ManExtendCounterExampleTest( Aig_Man_t * p, int iFirstPi, void * pCex );
// Saig_ManExtendCounterExampleTest( p->pAig, 0, p->pAig->pSeqModel );
}
return l_True;
}
return l_False;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Saig_BmcAddTargetsAsPos( Saig_Bmc_t * p )
{
Aig_Obj_t * pObj;
int i;
Vec_PtrForEachEntry( Aig_Obj_t *, p->vTargets, pObj, i )
Aig_ObjCreateCo( p->pFrm, pObj );
Aig_ManPrintStats( p->pFrm );
Aig_ManCleanup( p->pFrm );
Aig_ManPrintStats( p->pFrm );
}
/**Function*************************************************************
Synopsis [Performs BMC with the given parameters.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Saig_BmcPerform( Aig_Man_t * pAig, int nStart, int nFramesMax, int nNodesMax, int nTimeOut, int nConfMaxOne, int nConfMaxAll, int fVerbose, int fVerbOverwrite, int * piFrames, int fSilent, int fUseSatoko )
{
Saig_Bmc_t * p;
Aig_Man_t * pNew;
Cnf_Dat_t * pCnf;
int nOutsSolved = 0;
int Iter, RetValue = -1;
abctime nTimeToStop = nTimeOut ? nTimeOut * CLOCKS_PER_SEC + Abc_Clock(): 0;
abctime clk = Abc_Clock(), clk2, clkTotal = Abc_Clock();
int Status = -1;
/*
Vec_Ptr_t * vSimInfo;
vSimInfo = Abs_ManTernarySimulate( pAig, nFramesMax, fVerbose );
Abs_ManFreeAray( vSimInfo );
*/
if ( fVerbose )
{
printf( "Running \"bmc2\". AIG: PI/PO/Reg = %d/%d/%d. Node = %6d. Lev = %5d.\n",
Saig_ManPiNum(pAig), Saig_ManPoNum(pAig), Saig_ManRegNum(pAig),
Aig_ManNodeNum(pAig), Aig_ManLevelNum(pAig) );
printf( "Params: FramesMax = %d. NodesDelta = %d. ConfMaxOne = %d. ConfMaxAll = %d.\n",
nFramesMax, nNodesMax, nConfMaxOne, nConfMaxAll );
}
nFramesMax = nFramesMax ? nFramesMax : ABC_INFINITY;
p = Saig_BmcManStart( pAig, nFramesMax, nNodesMax, nConfMaxOne, nConfMaxAll, fVerbose, fUseSatoko );
// set runtime limit
if ( nTimeOut )
{
if ( p->pSat2 )
satoko_set_runtime_limit( p->pSat2, nTimeToStop );
else
sat_solver_set_runtime_limit( p->pSat, nTimeToStop );
}
for ( Iter = 0; ; Iter++ )
{
clk2 = Abc_Clock();
// add new logic interval to frames
Saig_BmcInterval( p );
// Saig_BmcAddTargetsAsPos( p );
if ( Vec_PtrSize(p->vTargets) == 0 )
break;
// convert logic slice into new AIG
pNew = Saig_BmcIntervalToAig( p );
//printf( "StitchVars = %d.\n", p->nStitchVars );
// derive CNF for the new AIG
pCnf = Cnf_Derive( pNew, Aig_ManCoNum(pNew) );
Cnf_DataLift( pCnf, p->nSatVars );
p->nSatVars += pCnf->nVars;
// add this CNF to the solver
Saig_BmcLoadCnf( p, pCnf );
Cnf_DataFree( pCnf );
Aig_ManStop( pNew );
// solve the targets
RetValue = Saig_BmcSolveTargets( p, nStart, &nOutsSolved );
if ( fVerbose )
{
printf( "%4d : F =%5d. O =%4d. And =%8d. Var =%8d. Conf =%7d. ",
Iter, p->iFrameLast, p->iOutputLast, Aig_ManNodeNum(p->pFrm), p->nSatVars,
p->pSat ? (int)p->pSat->stats.conflicts : satoko_conflictnum(p->pSat2) );
printf( "%4.0f MB", 4.0*(p->iFrameLast+1)*p->nObjs/(1<<20) );
printf( "%9.2f sec", (float)(Abc_Clock() - clkTotal)/(float)(CLOCKS_PER_SEC) );
printf( "\n" );
fflush( stdout );
}
if ( RetValue != l_False )
break;
// check the timeout
if ( nTimeOut && Abc_Clock() > nTimeToStop )
{
if ( !fSilent )
printf( "Reached timeout (%d seconds).\n", nTimeOut );
if ( piFrames )
*piFrames = p->iFrameLast-1;
Saig_BmcManStop( p );
return Status;
}
}
if ( RetValue == l_True )
{
assert( p->iFrameFail * Saig_ManPoNum(p->pAig) + p->iOutputFail + 1 == nOutsSolved );
if ( !fSilent )
Abc_Print( 1, "Output %d of miter \"%s\" was asserted in frame %d. ",
p->iOutputFail, p->pAig->pName, p->iFrameFail );
Status = 0;
if ( piFrames )
*piFrames = p->iFrameFail - 1;
}
else // if ( RetValue == l_False || RetValue == l_Undef )
{
if ( !fSilent )
Abc_Print( 1, "No output failed in %d frames. ", Abc_MaxInt(p->iFramePrev-1, 0) );
if ( piFrames )
{
if ( p->iOutputLast > 0 )
*piFrames = p->iFramePrev - 2;
else
*piFrames = p->iFramePrev - 1;
}
}
if ( !fSilent )
{
if ( fVerbOverwrite )
{
ABC_PRTr( "Time", Abc_Clock() - clk );
}
else
{
ABC_PRT( "Time", Abc_Clock() - clk );
}
if ( RetValue != l_True )
{
if ( p->iFrameLast >= p->nFramesMax )
printf( "Reached limit on the number of timeframes (%d).\n", p->nFramesMax );
else if ( p->nConfMaxAll && (p->pSat ? (int)p->pSat->stats.conflicts : satoko_conflictnum(p->pSat2)) > p->nConfMaxAll )
printf( "Reached global conflict limit (%d).\n", p->nConfMaxAll );
else if ( nTimeOut && Abc_Clock() > nTimeToStop )
printf( "Reached timeout (%d seconds).\n", nTimeOut );
else
printf( "Reached local conflict limit (%d).\n", p->nConfMaxOne );
}
}
Saig_BmcManStop( p );
fflush( stdout );
return Status;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END