blob: 904a2d7f06b6233786fd010b3d68720962b73630 [file] [log] [blame]
/**CFile****************************************************************
FileName [bmcBmc3.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [SAT-based bounded model checking.]
Synopsis [Simple BMC package.]
Author [Alan Mishchenko in collaboration with Niklas Een.]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: bmcBmc3.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
#include "proof/fra/fra.h"
#include "sat/cnf/cnf.h"
#include "sat/bsat/satStore.h"
#include "sat/satoko/satoko.h"
#include "sat/glucose/AbcGlucose.h"
#include "misc/vec/vecHsh.h"
#include "misc/vec/vecWec.h"
#include "bmc.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
typedef struct Gia_ManBmc_t_ Gia_ManBmc_t;
struct Gia_ManBmc_t_
{
// input/output data
Saig_ParBmc_t * pPars; // parameters
Aig_Man_t * pAig; // user AIG
Vec_Ptr_t * vCexes; // counter-examples
// intermediate data
Vec_Int_t * vMapping; // mapping
Vec_Int_t * vMapRefs; // mapping references
// Vec_Vec_t * vSects; // sections
Vec_Int_t * vId2Num; // number of each node
Vec_Ptr_t * vTerInfo; // ternary information
Vec_Ptr_t * vId2Var; // SAT vars for each object
Vec_Wec_t * vVisited; // visited nodes
abctime * pTime4Outs; // timeout per output
// hash table
Vec_Int_t * vData; // storage for cuts
Hsh_IntMan_t * vHash; // hash table
Vec_Int_t * vId2Lit; // mapping cuts into literals
int nHashHit; // hash table hits
int nHashMiss; // hash table misses
int nBufNum; // the number of simple nodes
int nDupNum; // the number of simple nodes
int nUniProps; // propagating learned clause values
int nLitUsed; // used literals
int nLitUseless; // useless literals
// SAT solver
sat_solver * pSat; // SAT solver
satoko_t * pSat2; // SAT solver
bmcg_sat_solver * pSat3; // SAT solver
int nSatVars; // SAT variables
int nObjNums; // SAT objects
int nWordNum; // unsigned words for ternary simulation
char * pSopSizes, ** pSops; // CNF representation
};
extern int Gia_ManToBridgeResult( FILE * pFile, int Result, Abc_Cex_t * pCex, int iPoProved );
void Gia_ManReportProgress( FILE * pFile, int prop_no, int depth )
{
extern int Gia_ManToBridgeProgress( FILE * pFile, int Size, unsigned char * pBuffer );
char buf[100];
sprintf(buf, "property: safe<%d>\nbug-free-depth: %d\n", prop_no, depth);
Gia_ManToBridgeProgress(pFile, strlen(buf), (unsigned char *)buf);
}
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
#define SAIG_TER_NON 0
#define SAIG_TER_ZER 1
#define SAIG_TER_ONE 2
#define SAIG_TER_UND 3
static inline int Saig_ManBmcSimInfoNot( int Value )
{
if ( Value == SAIG_TER_ZER )
return SAIG_TER_ONE;
if ( Value == SAIG_TER_ONE )
return SAIG_TER_ZER;
return SAIG_TER_UND;
}
static inline int Saig_ManBmcSimInfoAnd( int Value0, int Value1 )
{
if ( Value0 == SAIG_TER_ZER || Value1 == SAIG_TER_ZER )
return SAIG_TER_ZER;
if ( Value0 == SAIG_TER_ONE && Value1 == SAIG_TER_ONE )
return SAIG_TER_ONE;
return SAIG_TER_UND;
}
static inline int Saig_ManBmcSimInfoGet( unsigned * pInfo, Aig_Obj_t * pObj )
{
return 3 & (pInfo[Aig_ObjId(pObj) >> 4] >> ((Aig_ObjId(pObj) & 15) << 1));
}
static inline void Saig_ManBmcSimInfoSet( unsigned * pInfo, Aig_Obj_t * pObj, int Value )
{
assert( Value >= SAIG_TER_ZER && Value <= SAIG_TER_UND );
Value ^= Saig_ManBmcSimInfoGet( pInfo, pObj );
pInfo[Aig_ObjId(pObj) >> 4] ^= (Value << ((Aig_ObjId(pObj) & 15) << 1));
}
static inline int Saig_ManBmcSimInfoClear( unsigned * pInfo, Aig_Obj_t * pObj )
{
int Value = Saig_ManBmcSimInfoGet( pInfo, pObj );
pInfo[Aig_ObjId(pObj) >> 4] ^= (Value << ((Aig_ObjId(pObj) & 15) << 1));
return Value;
}
/**Function*************************************************************
Synopsis [Returns the number of LIs with binary ternary info.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Saig_ManBmcTerSimCount01( Aig_Man_t * p, unsigned * pInfo )
{
Aig_Obj_t * pObj;
int i, Counter = 0;
if ( pInfo == NULL )
return Saig_ManRegNum(p);
Saig_ManForEachLi( p, pObj, i )
if ( !Aig_ObjIsConst1(Aig_ObjFanin0(pObj)) )
Counter += (Saig_ManBmcSimInfoGet(pInfo, pObj) != SAIG_TER_UND);
return Counter;
}
/**Function*************************************************************
Synopsis [Performs ternary simulation of one frame.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
unsigned * Saig_ManBmcTerSimOne( Aig_Man_t * p, unsigned * pPrev )
{
Aig_Obj_t * pObj, * pObjLi;
unsigned * pInfo;
int i, Val0, Val1;
pInfo = ABC_CALLOC( unsigned, Abc_BitWordNum(2 * Aig_ManObjNumMax(p)) );
Saig_ManBmcSimInfoSet( pInfo, Aig_ManConst1(p), SAIG_TER_ONE );
Saig_ManForEachPi( p, pObj, i )
Saig_ManBmcSimInfoSet( pInfo, pObj, SAIG_TER_UND );
if ( pPrev == NULL )
{
Saig_ManForEachLo( p, pObj, i )
Saig_ManBmcSimInfoSet( pInfo, pObj, SAIG_TER_ZER );
}
else
{
Saig_ManForEachLiLo( p, pObjLi, pObj, i )
Saig_ManBmcSimInfoSet( pInfo, pObj, Saig_ManBmcSimInfoGet(pPrev, pObjLi) );
}
Aig_ManForEachNode( p, pObj, i )
{
Val0 = Saig_ManBmcSimInfoGet( pInfo, Aig_ObjFanin0(pObj) );
Val1 = Saig_ManBmcSimInfoGet( pInfo, Aig_ObjFanin1(pObj) );
if ( Aig_ObjFaninC0(pObj) )
Val0 = Saig_ManBmcSimInfoNot( Val0 );
if ( Aig_ObjFaninC1(pObj) )
Val1 = Saig_ManBmcSimInfoNot( Val1 );
Saig_ManBmcSimInfoSet( pInfo, pObj, Saig_ManBmcSimInfoAnd(Val0, Val1) );
}
Aig_ManForEachCo( p, pObj, i )
{
Val0 = Saig_ManBmcSimInfoGet( pInfo, Aig_ObjFanin0(pObj) );
if ( Aig_ObjFaninC0(pObj) )
Val0 = Saig_ManBmcSimInfoNot( Val0 );
Saig_ManBmcSimInfoSet( pInfo, pObj, Val0 );
}
return pInfo;
}
/**Function*************************************************************
Synopsis [Collects internal nodes and PIs in the DFS order.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Ptr_t * Saig_ManBmcTerSim( Aig_Man_t * p )
{
Vec_Ptr_t * vInfos;
unsigned * pInfo = NULL;
int i, TerPrev = ABC_INFINITY, TerCur, CountIncrease = 0;
vInfos = Vec_PtrAlloc( 100 );
for ( i = 0; i < 1000 && CountIncrease < 5 && TerPrev > 0; i++ )
{
TerCur = Saig_ManBmcTerSimCount01( p, pInfo );
if ( TerCur >= TerPrev )
CountIncrease++;
TerPrev = TerCur;
pInfo = Saig_ManBmcTerSimOne( p, pInfo );
Vec_PtrPush( vInfos, pInfo );
}
return vInfos;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Saig_ManBmcTerSimTest( Aig_Man_t * p )
{
Vec_Ptr_t * vInfos;
unsigned * pInfo;
int i;
vInfos = Saig_ManBmcTerSim( p );
Vec_PtrForEachEntry( unsigned *, vInfos, pInfo, i )
Abc_Print( 1, "%d=%d ", i, Saig_ManBmcTerSimCount01(p, pInfo) );
Abc_Print( 1, "\n" );
Vec_PtrFreeFree( vInfos );
}
/**Function*************************************************************
Synopsis [Count the number of non-ternary per frame.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Saig_ManBmcCountNonternary_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vInfos, unsigned * pInfo, int f, int * pCounter )
{
int Value = Saig_ManBmcSimInfoClear( pInfo, pObj );
if ( Value == SAIG_TER_NON )
return 0;
assert( f >= 0 );
pCounter[f] += (Value == SAIG_TER_UND);
if ( Saig_ObjIsPi(p, pObj) || (f == 0 && Saig_ObjIsLo(p, pObj)) || Aig_ObjIsConst1(pObj) )
return 0;
if ( Saig_ObjIsLi(p, pObj) )
return Saig_ManBmcCountNonternary_rec( p, Aig_ObjFanin0(pObj), vInfos, pInfo, f, pCounter );
if ( Saig_ObjIsLo(p, pObj) )
return Saig_ManBmcCountNonternary_rec( p, Saig_ObjLoToLi(p, pObj), vInfos, (unsigned *)Vec_PtrEntry(vInfos, f-1), f-1, pCounter );
assert( Aig_ObjIsNode(pObj) );
Saig_ManBmcCountNonternary_rec( p, Aig_ObjFanin0(pObj), vInfos, pInfo, f, pCounter );
Saig_ManBmcCountNonternary_rec( p, Aig_ObjFanin1(pObj), vInfos, pInfo, f, pCounter );
return 0;
}
void Saig_ManBmcCountNonternary( Aig_Man_t * p, Vec_Ptr_t * vInfos, int iFrame )
{
int i, * pCounters = ABC_CALLOC( int, iFrame + 1 );
unsigned * pInfo = (unsigned *)Vec_PtrEntry(vInfos, iFrame);
assert( Saig_ManBmcSimInfoGet( pInfo, Aig_ManCo(p, 0) ) == SAIG_TER_UND );
Saig_ManBmcCountNonternary_rec( p, Aig_ObjFanin0(Aig_ManCo(p, 0)), vInfos, pInfo, iFrame, pCounters );
for ( i = 0; i <= iFrame; i++ )
Abc_Print( 1, "%d=%d ", i, pCounters[i] );
Abc_Print( 1, "\n" );
ABC_FREE( pCounters );
}
/**Function*************************************************************
Synopsis [Returns the number of POs with binary ternary info.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Saig_ManBmcTerSimCount01Po( Aig_Man_t * p, unsigned * pInfo )
{
Aig_Obj_t * pObj;
int i, Counter = 0;
Saig_ManForEachPo( p, pObj, i )
Counter += (Saig_ManBmcSimInfoGet(pInfo, pObj) != SAIG_TER_UND);
return Counter;
}
Vec_Ptr_t * Saig_ManBmcTerSimPo( Aig_Man_t * p )
{
Vec_Ptr_t * vInfos;
unsigned * pInfo = NULL;
int i, nPoBin;
vInfos = Vec_PtrAlloc( 100 );
for ( i = 0; ; i++ )
{
if ( i % 100 == 0 )
Abc_Print( 1, "Frame %5d\n", i );
pInfo = Saig_ManBmcTerSimOne( p, pInfo );
Vec_PtrPush( vInfos, pInfo );
nPoBin = Saig_ManBmcTerSimCount01Po( p, pInfo );
if ( nPoBin < Saig_ManPoNum(p) )
break;
}
Abc_Print( 1, "Detected terminary PO in frame %d.\n", i );
Saig_ManBmcCountNonternary( p, vInfos, i );
return vInfos;
}
void Saig_ManBmcTerSimTestPo( Aig_Man_t * p )
{
Vec_Ptr_t * vInfos;
vInfos = Saig_ManBmcTerSimPo( p );
Vec_PtrFreeFree( vInfos );
}
/**Function*************************************************************
Synopsis [Collects internal nodes in the DFS order.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Saig_ManBmcDfs_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes )
{
assert( !Aig_IsComplement(pObj) );
if ( Aig_ObjIsTravIdCurrent(p, pObj) )
return;
Aig_ObjSetTravIdCurrent(p, pObj);
if ( Aig_ObjIsNode(pObj) )
{
Saig_ManBmcDfs_rec( p, Aig_ObjFanin0(pObj), vNodes );
Saig_ManBmcDfs_rec( p, Aig_ObjFanin1(pObj), vNodes );
}
Vec_PtrPush( vNodes, pObj );
}
/**Function*************************************************************
Synopsis [Collects internal nodes and PIs in the DFS order.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Ptr_t * Saig_ManBmcDfsNodes( Aig_Man_t * p, Vec_Ptr_t * vRoots )
{
Vec_Ptr_t * vNodes;
Aig_Obj_t * pObj;
int i;
vNodes = Vec_PtrAlloc( 100 );
Vec_PtrForEachEntry( Aig_Obj_t *, vRoots, pObj, i )
Saig_ManBmcDfs_rec( p, Aig_ObjFanin0(pObj), vNodes );
return vNodes;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Vec_t * Saig_ManBmcSections( Aig_Man_t * p )
{
Vec_Ptr_t * vSects, * vRoots, * vCone;
Aig_Obj_t * pObj, * pObjPo;
int i;
Aig_ManIncrementTravId( p );
Aig_ObjSetTravIdCurrent( p, Aig_ManConst1(p) );
// start the roots
vRoots = Vec_PtrAlloc( 1000 );
Saig_ManForEachPo( p, pObjPo, i )
{
Aig_ObjSetTravIdCurrent( p, pObjPo );
Vec_PtrPush( vRoots, pObjPo );
}
// compute the cones
vSects = Vec_PtrAlloc( 20 );
while ( Vec_PtrSize(vRoots) > 0 )
{
vCone = Saig_ManBmcDfsNodes( p, vRoots );
Vec_PtrPush( vSects, vCone );
// get the next set of roots
Vec_PtrClear( vRoots );
Vec_PtrForEachEntry( Aig_Obj_t *, vCone, pObj, i )
{
if ( !Saig_ObjIsLo(p, pObj) )
continue;
pObjPo = Saig_ObjLoToLi( p, pObj );
if ( Aig_ObjIsTravIdCurrent(p, pObjPo) )
continue;
Aig_ObjSetTravIdCurrent( p, pObjPo );
Vec_PtrPush( vRoots, pObjPo );
}
}
Vec_PtrFree( vRoots );
return (Vec_Vec_t *)vSects;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Saig_ManBmcSectionsTest( Aig_Man_t * p )
{
Vec_Vec_t * vSects;
Vec_Ptr_t * vOne;
int i;
vSects = Saig_ManBmcSections( p );
Vec_VecForEachLevel( vSects, vOne, i )
Abc_Print( 1, "%d=%d ", i, Vec_PtrSize(vOne) );
Abc_Print( 1, "\n" );
Vec_VecFree( vSects );
}
/**Function*************************************************************
Synopsis [Collects the supergate.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Saig_ManBmcSupergate_rec( Aig_Obj_t * pObj, Vec_Ptr_t * vSuper )
{
// if the new node is complemented or a PI, another gate begins
if ( Aig_IsComplement(pObj) || Aig_ObjIsCi(pObj) ) // || (Aig_ObjRefs(pObj) > 1) )
{
Vec_PtrPushUnique( vSuper, Aig_Regular(pObj) );
return;
}
// go through the branches
Saig_ManBmcSupergate_rec( Aig_ObjChild0(pObj), vSuper );
Saig_ManBmcSupergate_rec( Aig_ObjChild1(pObj), vSuper );
}
/**Function*************************************************************
Synopsis [Collect the topmost supergate.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Ptr_t * Saig_ManBmcSupergate( Aig_Man_t * p, int iPo )
{
Vec_Ptr_t * vSuper;
Aig_Obj_t * pObj;
vSuper = Vec_PtrAlloc( 10 );
pObj = Aig_ManCo( p, iPo );
pObj = Aig_ObjChild0( pObj );
if ( !Aig_IsComplement(pObj) )
{
Vec_PtrPush( vSuper, pObj );
return vSuper;
}
pObj = Aig_Regular( pObj );
if ( !Aig_ObjIsNode(pObj) )
{
Vec_PtrPush( vSuper, pObj );
return vSuper;
}
Saig_ManBmcSupergate_rec( Aig_ObjChild0(pObj), vSuper );
Saig_ManBmcSupergate_rec( Aig_ObjChild1(pObj), vSuper );
return vSuper;
}
/**Function*************************************************************
Synopsis [Returns the number of nodes with ref counter more than 1.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Saig_ManBmcCountRefed( Aig_Man_t * p, Vec_Ptr_t * vSuper )
{
Aig_Obj_t * pObj;
int i, Counter = 0;
Vec_PtrForEachEntry( Aig_Obj_t *, vSuper, pObj, i )
{
assert( !Aig_IsComplement(pObj) );
Counter += (Aig_ObjRefs(pObj) > 1);
}
return Counter;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Saig_ManBmcSupergateTest( Aig_Man_t * p )
{
Vec_Ptr_t * vSuper;
Aig_Obj_t * pObj;
int i;
Abc_Print( 1, "Supergates: " );
Saig_ManForEachPo( p, pObj, i )
{
vSuper = Saig_ManBmcSupergate( p, i );
Abc_Print( 1, "%d=%d(%d) ", i, Vec_PtrSize(vSuper), Saig_ManBmcCountRefed(p, vSuper) );
Vec_PtrFree( vSuper );
}
Abc_Print( 1, "\n" );
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Saig_ManBmcWriteBlif( Aig_Man_t * p, Vec_Int_t * vMapping, char * pFileName )
{
FILE * pFile;
char * pSopSizes, ** pSops;
Aig_Obj_t * pObj;
char Vals[4];
int i, k, b, iFan, iTruth, * pData;
pFile = fopen( pFileName, "w" );
if ( pFile == NULL )
{
Abc_Print( 1, "Cannot open file %s\n", pFileName );
return;
}
fprintf( pFile, ".model test\n" );
fprintf( pFile, ".inputs" );
Aig_ManForEachCi( p, pObj, i )
fprintf( pFile, " n%d", Aig_ObjId(pObj) );
fprintf( pFile, "\n" );
fprintf( pFile, ".outputs" );
Aig_ManForEachCo( p, pObj, i )
fprintf( pFile, " n%d", Aig_ObjId(pObj) );
fprintf( pFile, "\n" );
fprintf( pFile, ".names" );
fprintf( pFile, " n%d\n", Aig_ObjId(Aig_ManConst1(p)) );
fprintf( pFile, " 1\n" );
Cnf_ReadMsops( &pSopSizes, &pSops );
Aig_ManForEachNode( p, pObj, i )
{
if ( Vec_IntEntry(vMapping, i) == 0 )
continue;
pData = Vec_IntEntryP( vMapping, Vec_IntEntry(vMapping, i) );
fprintf( pFile, ".names" );
for ( iFan = 0; iFan < 4; iFan++ )
if ( pData[iFan+1] >= 0 )
fprintf( pFile, " n%d", pData[iFan+1] );
else
break;
fprintf( pFile, " n%d\n", i );
// write SOP
iTruth = pData[0] & 0xffff;
for ( k = 0; k < pSopSizes[iTruth]; k++ )
{
int Lit = pSops[iTruth][k];
for ( b = 3; b >= 0; b-- )
{
if ( Lit % 3 == 0 )
Vals[b] = '0';
else if ( Lit % 3 == 1 )
Vals[b] = '1';
else
Vals[b] = '-';
Lit = Lit / 3;
}
for ( b = 0; b < iFan; b++ )
fprintf( pFile, "%c", Vals[b] );
fprintf( pFile, " 1\n" );
}
}
free( pSopSizes );
free( pSops[1] );
free( pSops );
Aig_ManForEachCo( p, pObj, i )
{
fprintf( pFile, ".names" );
fprintf( pFile, " n%d", Aig_ObjId(Aig_ObjFanin0(pObj)) );
fprintf( pFile, " n%d\n", Aig_ObjId(pObj) );
fprintf( pFile, "%d 1\n", !Aig_ObjFaninC0(pObj) );
}
fprintf( pFile, ".end\n" );
fclose( pFile );
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Saig_ManBmcMappingTest( Aig_Man_t * p )
{
Vec_Int_t * vMapping;
vMapping = Cnf_DeriveMappingArray( p );
Saig_ManBmcWriteBlif( p, vMapping, "test.blif" );
Vec_IntFree( vMapping );
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Int_t * Saig_ManBmcComputeMappingRefs( Aig_Man_t * p, Vec_Int_t * vMap )
{
Vec_Int_t * vRefs;
Aig_Obj_t * pObj;
int i, iFan, * pData;
vRefs = Vec_IntStart( Aig_ManObjNumMax(p) );
Aig_ManForEachCo( p, pObj, i )
Vec_IntAddToEntry( vRefs, Aig_ObjFaninId0(pObj), 1 );
Aig_ManForEachNode( p, pObj, i )
{
if ( Vec_IntEntry(vMap, i) == 0 )
continue;
pData = Vec_IntEntryP( vMap, Vec_IntEntry(vMap, i) );
for ( iFan = 0; iFan < 4; iFan++ )
if ( pData[iFan+1] >= 0 )
Vec_IntAddToEntry( vRefs, pData[iFan+1], 1 );
}
return vRefs;
}
/**Function*************************************************************
Synopsis [Create manager.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Gia_ManBmc_t * Saig_Bmc3ManStart( Aig_Man_t * pAig, int nTimeOutOne, int nConfLimit, int fUseSatoko, int fUseGlucose )
{
Gia_ManBmc_t * p;
Aig_Obj_t * pObj;
int i;
// assert( Aig_ManRegNum(pAig) > 0 );
p = ABC_CALLOC( Gia_ManBmc_t, 1 );
p->pAig = pAig;
// create mapping
p->vMapping = Cnf_DeriveMappingArray( pAig );
p->vMapRefs = Saig_ManBmcComputeMappingRefs( pAig, p->vMapping );
// create sections
// p->vSects = Saig_ManBmcSections( pAig );
// map object IDs into their numbers and section numbers
p->nObjNums = 0;
p->vId2Num = Vec_IntStartFull( Aig_ManObjNumMax(pAig) );
Vec_IntWriteEntry( p->vId2Num, Aig_ObjId(Aig_ManConst1(pAig)), p->nObjNums++ );
Aig_ManForEachCi( pAig, pObj, i )
Vec_IntWriteEntry( p->vId2Num, Aig_ObjId(pObj), p->nObjNums++ );
Aig_ManForEachNode( pAig, pObj, i )
if ( Vec_IntEntry(p->vMapping, Aig_ObjId(pObj)) > 0 )
Vec_IntWriteEntry( p->vId2Num, Aig_ObjId(pObj), p->nObjNums++ );
Aig_ManForEachCo( pAig, pObj, i )
Vec_IntWriteEntry( p->vId2Num, Aig_ObjId(pObj), p->nObjNums++ );
p->vId2Var = Vec_PtrAlloc( 100 );
p->vTerInfo = Vec_PtrAlloc( 100 );
p->vVisited = Vec_WecAlloc( 100 );
// create solver
p->nSatVars = 1;
if ( fUseSatoko )
{
satoko_opts_t opts;
satoko_default_opts(&opts);
opts.conf_limit = nConfLimit;
p->pSat2 = satoko_create();
satoko_configure(p->pSat2, &opts);
satoko_setnvars(p->pSat2, 1000);
}
else if ( fUseGlucose )
{
//opts.conf_limit = nConfLimit;
p->pSat3 = bmcg_sat_solver_start();
for ( i = 0; i < 1000; i++ )
bmcg_sat_solver_addvar( p->pSat3 );
}
else
{
p->pSat = sat_solver_new();
sat_solver_setnvars(p->pSat, 1000);
}
Cnf_ReadMsops( &p->pSopSizes, &p->pSops );
// terminary simulation
p->nWordNum = Abc_BitWordNum( 2 * Aig_ManObjNumMax(pAig) );
// hash table
p->vData = Vec_IntAlloc( 5 * 10000 );
p->vHash = Hsh_IntManStart( p->vData, 5, 10000 );
p->vId2Lit = Vec_IntAlloc( 10000 );
// time spent on each outputs
if ( nTimeOutOne )
{
p->pTime4Outs = ABC_ALLOC( abctime, Saig_ManPoNum(pAig) );
for ( i = 0; i < Saig_ManPoNum(pAig); i++ )
p->pTime4Outs[i] = nTimeOutOne * CLOCKS_PER_SEC / 1000 + 1;
}
return p;
}
/**Function*************************************************************
Synopsis [Delete manager.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Saig_Bmc3ManStop( Gia_ManBmc_t * p )
{
if ( p->pPars->fVerbose )
{
int nUsedVars = p->pSat ? sat_solver_count_usedvars(p->pSat) : 0;
Abc_Print( 1, "LStart(P) = %d LDelta(Q) = %d LRatio(R) = %d ReduceDB = %d Vars = %d Used = %d (%.2f %%)\n",
p->pSat ? p->pSat->nLearntStart : 0,
p->pSat ? p->pSat->nLearntDelta : 0,
p->pSat ? p->pSat->nLearntRatio : 0,
p->pSat ? p->pSat->nDBreduces : 0,
p->pSat ? sat_solver_nvars(p->pSat) : p->pSat3 ? bmcg_sat_solver_varnum(p->pSat3) : satoko_varnum(p->pSat2),
nUsedVars,
100.0*nUsedVars/(p->pSat ? sat_solver_nvars(p->pSat) : p->pSat3 ? bmcg_sat_solver_varnum(p->pSat3) : satoko_varnum(p->pSat2)) );
Abc_Print( 1, "Buffs = %d. Dups = %d. Hash hits = %d. Hash misses = %d. UniProps = %d.\n",
p->nBufNum, p->nDupNum, p->nHashHit, p->nHashMiss, p->nUniProps );
}
// Aig_ManCleanMarkA( p->pAig );
if ( p->vCexes )
{
assert( p->pAig->vSeqModelVec == NULL );
p->pAig->vSeqModelVec = p->vCexes;
p->vCexes = NULL;
}
// Vec_PtrFreeFree( p->vCexes );
Vec_WecFree( p->vVisited );
Vec_IntFree( p->vMapping );
Vec_IntFree( p->vMapRefs );
// Vec_VecFree( p->vSects );
Vec_IntFree( p->vId2Num );
Vec_VecFree( (Vec_Vec_t *)p->vId2Var );
Vec_PtrFreeFree( p->vTerInfo );
if ( p->pSat ) sat_solver_delete( p->pSat );
if ( p->pSat2 ) satoko_destroy( p->pSat2 );
if ( p->pSat3 ) bmcg_sat_solver_stop( p->pSat3 );
ABC_FREE( p->pTime4Outs );
Vec_IntFree( p->vData );
Hsh_IntManStop( p->vHash );
Vec_IntFree( p->vId2Lit );
ABC_FREE( p->pSopSizes );
ABC_FREE( p->pSops[1] );
ABC_FREE( p->pSops );
ABC_FREE( p );
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline int * Saig_ManBmcMapping( Gia_ManBmc_t * p, Aig_Obj_t * pObj )
{
if ( Vec_IntEntry(p->vMapping, Aig_ObjId(pObj)) == 0 )
return NULL;
return Vec_IntEntryP( p->vMapping, Vec_IntEntry(p->vMapping, Aig_ObjId(pObj)) );
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Saig_ManBmcLiteral( Gia_ManBmc_t * p, Aig_Obj_t * pObj, int iFrame )
{
Vec_Int_t * vFrame;
int ObjNum;
assert( !Aig_ObjIsNode(pObj) || Saig_ManBmcMapping(p, pObj) );
ObjNum = Vec_IntEntry( p->vId2Num, Aig_ObjId(pObj) );
assert( ObjNum >= 0 );
vFrame = (Vec_Int_t *)Vec_PtrEntry( p->vId2Var, iFrame );
assert( vFrame != NULL );
return Vec_IntEntry( vFrame, ObjNum );
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Saig_ManBmcSetLiteral( Gia_ManBmc_t * p, Aig_Obj_t * pObj, int iFrame, int iLit )
{
Vec_Int_t * vFrame;
int ObjNum;
assert( !Aig_ObjIsNode(pObj) || Saig_ManBmcMapping(p, pObj) );
ObjNum = Vec_IntEntry( p->vId2Num, Aig_ObjId(pObj) );
vFrame = (Vec_Int_t *)Vec_PtrEntry( p->vId2Var, iFrame );
Vec_IntWriteEntry( vFrame, ObjNum, iLit );
/*
if ( Vec_IntEntry( p->vMapRefs, Aig_ObjId(pObj) ) > 1 )
p->nLitUsed++;
else
p->nLitUseless++;
*/
return iLit;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Saig_ManBmcCof0( int t, int v )
{
static int s_Truth[4] = { 0xAAAA, 0xCCCC, 0xF0F0, 0xFF00 };
return 0xffff & ((t & ~s_Truth[v]) | ((t & ~s_Truth[v]) << (1<<v)));
}
static inline int Saig_ManBmcCof1( int t, int v )
{
static int s_Truth[4] = { 0xAAAA, 0xCCCC, 0xF0F0, 0xFF00 };
return 0xffff & ((t & s_Truth[v]) | ((t & s_Truth[v]) >> (1<<v)));
}
static inline int Saig_ManBmcCofEqual( int t, int v )
{
assert( v >= 0 && v <= 3 );
if ( v == 0 )
return ((t & 0xAAAA) >> 1) == (t & 0x5555);
if ( v == 1 )
return ((t & 0xCCCC) >> 2) == (t & 0x3333);
if ( v == 2 )
return ((t & 0xF0F0) >> 4) == (t & 0x0F0F);
if ( v == 3 )
return ((t & 0xFF00) >> 8) == (t & 0x00FF);
return -1;
}
/**Function*************************************************************
Synopsis [Derives CNF for one node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Saig_ManBmcReduceTruth( int uTruth, int Lits[] )
{
int v;
for ( v = 0; v < 4; v++ )
if ( Lits[v] == 0 )
{
uTruth = Saig_ManBmcCof0(uTruth, v);
Lits[v] = -1;
}
else if ( Lits[v] == 1 )
{
uTruth = Saig_ManBmcCof1(uTruth, v);
Lits[v] = -1;
}
for ( v = 0; v < 4; v++ )
if ( Lits[v] == -1 )
assert( Saig_ManBmcCofEqual(uTruth, v) );
else if ( Saig_ManBmcCofEqual(uTruth, v) )
Lits[v] = -1;
return uTruth;
}
/**Function*************************************************************
Synopsis [Derives CNF for one node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Saig_ManBmcAddClauses( Gia_ManBmc_t * p, int uTruth, int Lits[], int iLitOut )
{
int i, k, b, CutLit, nClaLits, ClaLits[5];
assert( uTruth > 0 && uTruth < 0xffff );
// write positive/negative polarity
for ( i = 0; i < 2; i++ )
{
if ( i )
uTruth = 0xffff & ~uTruth;
// Extra_PrintBinary( stdout, &uTruth, 16 ); Abc_Print( 1, "\n" );
for ( k = 0; k < p->pSopSizes[uTruth]; k++ )
{
nClaLits = 0;
ClaLits[nClaLits++] = i ? lit_neg(iLitOut) : iLitOut;
CutLit = p->pSops[uTruth][k];
for ( b = 3; b >= 0; b-- )
{
if ( CutLit % 3 == 0 ) // value 0 --> write positive literal
{
assert( Lits[b] > 1 );
ClaLits[nClaLits++] = Lits[b];
}
else if ( CutLit % 3 == 1 ) // value 1 --> write negative literal
{
assert( Lits[b] > 1 );
ClaLits[nClaLits++] = lit_neg(Lits[b]);
}
CutLit = CutLit / 3;
}
if ( p->pSat2 )
{
if ( !satoko_add_clause( p->pSat2, ClaLits, nClaLits ) )
assert( 0 );
}
else if ( p->pSat3 )
{
if ( !bmcg_sat_solver_addclause( p->pSat3, ClaLits, nClaLits ) )
assert( 0 );
}
else
{
if ( !sat_solver_addclause( p->pSat, ClaLits, ClaLits+nClaLits ) )
assert( 0 );
}
}
}
}
/**Function*************************************************************
Synopsis [Derives CNF for one node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Saig_ManBmcCreateCnf_rec( Gia_ManBmc_t * p, Aig_Obj_t * pObj, int iFrame )
{
extern unsigned Dar_CutSortVars( unsigned uTruth, int * pVars );
int * pMapping, i, iLit, Lits[5], uTruth;
iLit = Saig_ManBmcLiteral( p, pObj, iFrame );
if ( iLit != ~0 )
return iLit;
assert( iFrame >= 0 );
if ( Aig_ObjIsCi(pObj) )
{
if ( Saig_ObjIsPi(p->pAig, pObj) )
iLit = toLit( p->nSatVars++ );
else
iLit = Saig_ManBmcCreateCnf_rec( p, Saig_ObjLoToLi(p->pAig, pObj), iFrame-1 );
return Saig_ManBmcSetLiteral( p, pObj, iFrame, iLit );
}
if ( Aig_ObjIsCo(pObj) )
{
iLit = Saig_ManBmcCreateCnf_rec( p, Aig_ObjFanin0(pObj), iFrame );
if ( Aig_ObjFaninC0(pObj) )
iLit = lit_neg(iLit);
return Saig_ManBmcSetLiteral( p, pObj, iFrame, iLit );
}
assert( Aig_ObjIsNode(pObj) );
pMapping = Saig_ManBmcMapping( p, pObj );
for ( i = 0; i < 4; i++ )
if ( pMapping[i+1] == -1 )
Lits[i] = -1;
else
Lits[i] = Saig_ManBmcCreateCnf_rec( p, Aig_ManObj(p->pAig, pMapping[i+1]), iFrame );
uTruth = 0xffff & (unsigned)pMapping[0];
// propagate constants
uTruth = Saig_ManBmcReduceTruth( uTruth, Lits );
if ( uTruth == 0 || uTruth == 0xffff )
{
iLit = (uTruth == 0xffff);
return Saig_ManBmcSetLiteral( p, pObj, iFrame, iLit );
}
// canonicize inputs
uTruth = Dar_CutSortVars( uTruth, Lits );
assert( uTruth != 0 && uTruth != 0xffff );
if ( uTruth == 0xAAAA || uTruth == 0x5555 )
{
iLit = Abc_LitNotCond( Lits[0], uTruth == 0x5555 );
p->nBufNum++;
}
else
{
int iEntry, iRes;
int fCompl = (uTruth & 1);
Lits[4] = (uTruth & 1) ? 0xffff & ~uTruth : uTruth;
iEntry = Vec_IntSize(p->vData) / 5;
assert( iEntry * 5 == Vec_IntSize(p->vData) );
for ( i = 0; i < 5; i++ )
Vec_IntPush( p->vData, Lits[i] );
iRes = Hsh_IntManAdd( p->vHash, iEntry );
if ( iRes == iEntry )
{
iLit = toLit( p->nSatVars++ );
Saig_ManBmcAddClauses( p, Lits[4], Lits, iLit );
assert( iEntry == Vec_IntSize(p->vId2Lit) );
Vec_IntPush( p->vId2Lit, iLit );
p->nHashMiss++;
}
else
{
iLit = Vec_IntEntry( p->vId2Lit, iRes );
Vec_IntShrink( p->vData, Vec_IntSize(p->vData) - 5 );
p->nHashHit++;
}
iLit = Abc_LitNotCond( iLit, fCompl );
}
return Saig_ManBmcSetLiteral( p, pObj, iFrame, iLit );
}
/**Function*************************************************************
Synopsis [Derives CNF for one node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Saig_ManBmcCreateCnf_iter( Gia_ManBmc_t * p, Aig_Obj_t * pObj, int iFrame, Vec_Int_t * vVisit )
{
if ( Saig_ManBmcLiteral( p, pObj, iFrame ) != ~0 )
return;
if ( Aig_ObjIsTravIdCurrent(p->pAig, pObj) )
return;
Aig_ObjSetTravIdCurrent(p->pAig, pObj);
if ( Aig_ObjIsCi(pObj) )
{
if ( Saig_ObjIsLo(p->pAig, pObj) )
Vec_IntPush( vVisit, Saig_ObjLoToLi(p->pAig, pObj)->Id );
return;
}
if ( Aig_ObjIsCo(pObj) )
{
Saig_ManBmcCreateCnf_iter( p, Aig_ObjFanin0(pObj), iFrame, vVisit );
return;
}
else
{
int * pMapping, i;
assert( Aig_ObjIsNode(pObj) );
pMapping = Saig_ManBmcMapping( p, pObj );
for ( i = 0; i < 4; i++ )
if ( pMapping[i+1] != -1 )
Saig_ManBmcCreateCnf_iter( p, Aig_ManObj(p->pAig, pMapping[i+1]), iFrame, vVisit );
}
}
/**Function*************************************************************
Synopsis [Recursively performs terminary simulation.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Saig_ManBmcRunTerSim_rec( Gia_ManBmc_t * p, Aig_Obj_t * pObj, int iFrame )
{
unsigned * pInfo = (unsigned *)Vec_PtrEntry( p->vTerInfo, iFrame );
int Val0, Val1, Value = Saig_ManBmcSimInfoGet( pInfo, pObj );
if ( Value != SAIG_TER_NON )
{
/*
// check the value of this literal in the SAT solver
if ( Value == SAIG_TER_UND && Saig_ManBmcMapping(p, pObj) )
{
int Lit = Saig_ManBmcLiteral( p, pObj, iFrame );
if ( Lit >= 0 )
{
assert( Lit >= 2 );
if ( p->pSat->assigns[Abc_Lit2Var(Lit)] < 2 )
{
p->nUniProps++;
if ( Abc_LitIsCompl(Lit) ^ (p->pSat->assigns[Abc_Lit2Var(Lit)] == 0) )
Value = SAIG_TER_ONE;
else
Value = SAIG_TER_ZER;
// Value = SAIG_TER_UND; // disable!
// use the new value
Saig_ManBmcSimInfoSet( pInfo, pObj, Value );
// transfer to the unrolling
if ( Value != SAIG_TER_UND )
Saig_ManBmcSetLiteral( p, pObj, iFrame, (int)(Value == SAIG_TER_ONE) );
}
}
}
*/
return Value;
}
if ( Aig_ObjIsCo(pObj) )
{
Value = Saig_ManBmcRunTerSim_rec( p, Aig_ObjFanin0(pObj), iFrame );
if ( Aig_ObjFaninC0(pObj) )
Value = Saig_ManBmcSimInfoNot( Value );
}
else if ( Saig_ObjIsLo(p->pAig, pObj) )
{
assert( iFrame > 0 );
Value = Saig_ManBmcRunTerSim_rec( p, Saig_ObjLoToLi(p->pAig, pObj), iFrame - 1 );
}
else if ( Aig_ObjIsNode(pObj) )
{
Val0 = Saig_ManBmcRunTerSim_rec( p, Aig_ObjFanin0(pObj), iFrame );
Val1 = Saig_ManBmcRunTerSim_rec( p, Aig_ObjFanin1(pObj), iFrame );
if ( Aig_ObjFaninC0(pObj) )
Val0 = Saig_ManBmcSimInfoNot( Val0 );
if ( Aig_ObjFaninC1(pObj) )
Val1 = Saig_ManBmcSimInfoNot( Val1 );
Value = Saig_ManBmcSimInfoAnd( Val0, Val1 );
}
else assert( 0 );
Saig_ManBmcSimInfoSet( pInfo, pObj, Value );
// transfer to the unrolling
if ( Saig_ManBmcMapping(p, pObj) && Value != SAIG_TER_UND )
Saig_ManBmcSetLiteral( p, pObj, iFrame, (int)(Value == SAIG_TER_ONE) );
return Value;
}
/**Function*************************************************************
Synopsis [Derives CNF for one node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Saig_ManBmcCreateCnf( Gia_ManBmc_t * p, Aig_Obj_t * pObj, int iFrame )
{
Vec_Int_t * vVisit, * vVisit2;
Aig_Obj_t * pTemp;
int Lit, f, i;
// perform ternary simulation
int Value = Saig_ManBmcRunTerSim_rec( p, pObj, iFrame );
if ( Value != SAIG_TER_UND )
return (int)(Value == SAIG_TER_ONE);
// construct CNF if value is ternary
// Lit = Saig_ManBmcCreateCnf_rec( p, pObj, iFrame );
Vec_WecClear( p->vVisited );
vVisit = Vec_WecPushLevel( p->vVisited );
Vec_IntPush( vVisit, Aig_ObjId(pObj) );
for ( f = iFrame; f >= 0; f-- )
{
Aig_ManIncrementTravId( p->pAig );
vVisit2 = Vec_WecPushLevel( p->vVisited );
vVisit = Vec_WecEntry( p->vVisited, Vec_WecSize(p->vVisited)-2 );
Aig_ManForEachObjVec( vVisit, p->pAig, pTemp, i )
Saig_ManBmcCreateCnf_iter( p, pTemp, f, vVisit2 );
if ( Vec_IntSize(vVisit2) == 0 )
break;
}
Vec_WecForEachLevelReverse( p->vVisited, vVisit, f )
Aig_ManForEachObjVec( vVisit, p->pAig, pTemp, i )
Saig_ManBmcCreateCnf_rec( p, pTemp, iFrame-f );
Lit = Saig_ManBmcLiteral( p, pObj, iFrame );
// extend the SAT solver
if ( p->pSat2 )
satoko_setnvars( p->pSat2, p->nSatVars );
else if ( p->pSat3 )
{
for ( i = bmcg_sat_solver_varnum(p->pSat3); i < p->nSatVars; i++ )
bmcg_sat_solver_addvar( p->pSat3 );
}
else
sat_solver_setnvars( p->pSat, p->nSatVars );
return Lit;
}
/**Function*************************************************************
Synopsis [Procedure used for sorting the nodes in decreasing order of levels.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Aig_NodeCompareRefsIncrease( Aig_Obj_t ** pp1, Aig_Obj_t ** pp2 )
{
int Diff = Aig_ObjRefs(*pp1) - Aig_ObjRefs(*pp2);
if ( Diff < 0 )
return -1;
if ( Diff > 0 )
return 1;
Diff = Aig_ObjId(*pp1) - Aig_ObjId(*pp2);
if ( Diff < 0 )
return -1;
if ( Diff > 0 )
return 1;
return 0;
}
/**Function*************************************************************
Synopsis [This procedure sets default parameters.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Saig_ParBmcSetDefaultParams( Saig_ParBmc_t * p )
{
memset( p, 0, sizeof(Saig_ParBmc_t) );
p->nStart = 0; // maximum number of timeframes
p->nFramesMax = 0; // maximum number of timeframes
p->nConfLimit = 0; // maximum number of conflicts at a node
p->nConfLimitJump = 0; // maximum number of conflicts after jumping
p->nFramesJump = 0; // the number of tiemframes to jump
p->nTimeOut = 0; // approximate timeout in seconds
p->nTimeOutGap = 0; // time since the last CEX found
p->nPisAbstract = 0; // the number of PIs to abstract
p->fSolveAll = 0; // stops on the first SAT instance
p->fDropSatOuts = 0; // replace sat outputs by constant 0
p->nLearnedStart = 10000; // starting learned clause limit
p->nLearnedDelta = 2000; // delta of learned clause limit
p->nLearnedPerce = 80; // ratio of learned clause limit
p->fVerbose = 0; // verbose
p->fNotVerbose = 0; // skip line-by-line print-out
p->iFrame = -1; // explored up to this frame
p->nFailOuts = 0; // the number of failed outputs
p->nDropOuts = 0; // the number of timed out outputs
p->timeLastSolved = 0; // time when the last one was solved
}
/**Function*************************************************************
Synopsis [Returns time to stop.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
abctime Saig_ManBmcTimeToStop( Saig_ParBmc_t * pPars, abctime nTimeToStopNG )
{
abctime nTimeToStopGap = pPars->nTimeOutGap ? pPars->nTimeOutGap * CLOCKS_PER_SEC + Abc_Clock(): 0;
abctime nTimeToStop = 0;
if ( nTimeToStopNG && nTimeToStopGap )
nTimeToStop = nTimeToStopNG < nTimeToStopGap ? nTimeToStopNG : nTimeToStopGap;
else if ( nTimeToStopNG )
nTimeToStop = nTimeToStopNG;
else if ( nTimeToStopGap )
nTimeToStop = nTimeToStopGap;
return nTimeToStop;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Abc_Cex_t * Saig_ManGenerateCex( Gia_ManBmc_t * p, int f, int i )
{
Aig_Obj_t * pObjPi;
Abc_Cex_t * pCex = Abc_CexMakeTriv( Aig_ManRegNum(p->pAig), Saig_ManPiNum(p->pAig), Saig_ManPoNum(p->pAig), f*Saig_ManPoNum(p->pAig)+i );
int j, k, iBit = Saig_ManRegNum(p->pAig);
for ( j = 0; j <= f; j++, iBit += Saig_ManPiNum(p->pAig) )
Saig_ManForEachPi( p->pAig, pObjPi, k )
{
int iLit = Saig_ManBmcLiteral( p, pObjPi, j );
if ( p->pSat2 )
{
if ( iLit != ~0 && satoko_read_cex_varvalue(p->pSat2, lit_var(iLit)) )
Abc_InfoSetBit( pCex->pData, iBit + k );
}
else if ( p->pSat3 )
{
if ( iLit != ~0 && bmcg_sat_solver_read_cex_varvalue(p->pSat3, lit_var(iLit)) )
Abc_InfoSetBit( pCex->pData, iBit + k );
}
else
{
if ( iLit != ~0 && sat_solver_var_value(p->pSat, lit_var(iLit)) )
Abc_InfoSetBit( pCex->pData, iBit + k );
}
}
return pCex;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Saig_ManCallSolver( Gia_ManBmc_t * p, int Lit )
{
if ( Lit == 0 )
return l_False;
if ( Lit == 1 )
return l_True;
if ( p->pSat2 )
return satoko_solve_assumptions_limit( p->pSat2, &Lit, 1, p->pPars->nConfLimit );
else if ( p->pSat3 )
{
bmcg_sat_solver_set_conflict_budget( p->pSat3, p->pPars->nConfLimit );
return bmcg_sat_solver_solve( p->pSat3, &Lit, 1 );
}
else
return sat_solver_solve( p->pSat, &Lit, &Lit + 1, (ABC_INT64_T)p->pPars->nConfLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
}
/**Function*************************************************************
Synopsis [Bounded model checking engine.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Saig_ManBmcScalable( Aig_Man_t * pAig, Saig_ParBmc_t * pPars )
{
Gia_ManBmc_t * p;
Aig_Obj_t * pObj;
Abc_Cex_t * pCexNew, * pCexNew0;
FILE * pLogFile = NULL;
unsigned * pInfo;
int RetValue = -1, fFirst = 1, nJumpFrame = 0, fUnfinished = 0;
int nOutDigits = Abc_Base10Log( Saig_ManPoNum(pAig) );
int i, f, k, Lit, status;
abctime clk, clk2, clkSatRun, clkOther = 0, clkTotal = Abc_Clock();
abctime nTimeUnsat = 0, nTimeSat = 0, nTimeUndec = 0, clkOne = 0;
abctime nTimeToStopNG, nTimeToStop;
if ( pPars->pLogFileName )
pLogFile = fopen( pPars->pLogFileName, "wb" );
if ( pPars->nTimeOutOne && pPars->nTimeOut == 0 )
pPars->nTimeOut = pPars->nTimeOutOne * Saig_ManPoNum(pAig) / 1000 + 1;
if ( pPars->nTimeOutOne && !pPars->fSolveAll )
pPars->nTimeOutOne = 0;
nTimeToStopNG = pPars->nTimeOut ? pPars->nTimeOut * CLOCKS_PER_SEC + Abc_Clock(): 0;
nTimeToStop = Saig_ManBmcTimeToStop( pPars, nTimeToStopNG );
// create BMC manager
p = Saig_Bmc3ManStart( pAig, pPars->nTimeOutOne, pPars->nConfLimit, pPars->fUseSatoko, pPars->fUseGlucose );
p->pPars = pPars;
if ( p->pSat )
{
p->pSat->nLearntStart = p->pPars->nLearnedStart;
p->pSat->nLearntDelta = p->pPars->nLearnedDelta;
p->pSat->nLearntRatio = p->pPars->nLearnedPerce;
p->pSat->nLearntMax = p->pSat->nLearntStart;
p->pSat->fNoRestarts = p->pPars->fNoRestarts;
p->pSat->RunId = p->pPars->RunId;
p->pSat->pFuncStop = p->pPars->pFuncStop;
}
else if ( p->pSat3 )
{
// satoko_set_runid(p->pSat3, p->pPars->RunId);
// satoko_set_stop_func(p->pSat3, p->pPars->pFuncStop);
}
else
{
satoko_set_runid(p->pSat2, p->pPars->RunId);
satoko_set_stop_func(p->pSat2, p->pPars->pFuncStop);
}
if ( pPars->fSolveAll && p->vCexes == NULL )
p->vCexes = Vec_PtrStart( Saig_ManPoNum(pAig) );
if ( pPars->fVerbose )
{
Abc_Print( 1, "Running \"bmc3\". PI/PO/Reg = %d/%d/%d. And =%7d. Lev =%6d. ObjNums =%6d.\n",// Sect =%3d.\n",
Saig_ManPiNum(pAig), Saig_ManPoNum(pAig), Saig_ManRegNum(pAig),
Aig_ManNodeNum(pAig), Aig_ManLevelNum(pAig), p->nObjNums );//, Vec_VecSize(p->vSects) );
Abc_Print( 1, "Params: FramesMax = %d. Start = %d. ConfLimit = %d. TimeOut = %d. SolveAll = %d.\n",
pPars->nFramesMax, pPars->nStart, pPars->nConfLimit, pPars->nTimeOut, pPars->fSolveAll );
}
pPars->nFramesMax = pPars->nFramesMax ? pPars->nFramesMax : ABC_INFINITY;
// set runtime limit
if ( nTimeToStop )
{
if ( p->pSat2 )
satoko_set_runtime_limit( p->pSat2, nTimeToStop );
else if ( p->pSat3 )
bmcg_sat_solver_set_runtime_limit( p->pSat3, nTimeToStop );
else
sat_solver_set_runtime_limit( p->pSat, nTimeToStop );
}
// perform frames
Aig_ManRandom( 1 );
pPars->timeLastSolved = Abc_Clock();
for ( f = 0; f < pPars->nFramesMax; f++ )
{
// stop BMC after exploring all reachable states
if ( !pPars->nFramesJump && Aig_ManRegNum(pAig) < 30 && f == (1 << Aig_ManRegNum(pAig)) )
{
Abc_Print( 1, "Stopping BMC because all 2^%d reachable states are visited.\n", Aig_ManRegNum(pAig) );
if ( p->pPars->fUseBridge )
Saig_ManForEachPo( pAig, pObj, i )
if ( !(p->vCexes && Vec_PtrEntry(p->vCexes, i)) && !(p->pTime4Outs && p->pTime4Outs[i] == 0) ) // not SAT and not timed out
Gia_ManToBridgeResult( stdout, 1, NULL, i );
RetValue = pPars->nFailOuts ? 0 : 1;
goto finish;
}
// stop BMC if all targets are solved
if ( pPars->fSolveAll && pPars->nFailOuts + pPars->nDropOuts >= Saig_ManPoNum(pAig) )
{
Abc_Print( 1, "Stopping BMC because all targets are disproved or timed out.\n" );
RetValue = pPars->nFailOuts ? 0 : 1;
goto finish;
}
// consider the next timeframe
if ( (RetValue == -1 || pPars->fSolveAll) && pPars->nStart == 0 && !nJumpFrame )
pPars->iFrame = f-1;
// map nodes of this section
Vec_PtrPush( p->vId2Var, Vec_IntStartFull(p->nObjNums) );
Vec_PtrPush( p->vTerInfo, (pInfo = ABC_CALLOC(unsigned, p->nWordNum)) );
/*
// cannot remove mapping of frame values for any timeframes
// because with constant propagation they may be needed arbitrarily far
if ( f > 2*Vec_VecSize(p->vSects) )
{
int iFrameOld = f - 2*Vec_VecSize( p->vSects );
void * pMemory = Vec_IntReleaseArray( Vec_PtrEntry(p->vId2Var, iFrameOld) );
ABC_FREE( pMemory );
}
*/
// prepare some nodes
Saig_ManBmcSetLiteral( p, Aig_ManConst1(pAig), f, 1 );
Saig_ManBmcSimInfoSet( pInfo, Aig_ManConst1(pAig), SAIG_TER_ONE );
Saig_ManForEachPi( pAig, pObj, i )
Saig_ManBmcSimInfoSet( pInfo, pObj, SAIG_TER_UND );
if ( f == 0 )
{
Saig_ManForEachLo( p->pAig, pObj, i )
{
Saig_ManBmcSetLiteral( p, pObj, 0, 0 );
Saig_ManBmcSimInfoSet( pInfo, pObj, SAIG_TER_ZER );
}
}
if ( (pPars->nStart && f < pPars->nStart) || (nJumpFrame && f < nJumpFrame) )
continue;
// create CNF upfront
if ( pPars->fSolveAll )
{
Saig_ManForEachPo( pAig, pObj, i )
{
if ( i >= Saig_ManPoNum(pAig) )
break;
// check for timeout
if ( pPars->nTimeOutGap && pPars->timeLastSolved && Abc_Clock() > pPars->timeLastSolved + pPars->nTimeOutGap * CLOCKS_PER_SEC )
{
Abc_Print( 1, "Reached gap timeout (%d seconds).\n", pPars->nTimeOutGap );
goto finish;
}
if ( nTimeToStop && Abc_Clock() > nTimeToStop )
{
if ( !pPars->fSilent )
Abc_Print( 1, "Reached timeout (%d seconds).\n", pPars->nTimeOut );
goto finish;
}
// skip solved outputs
if ( p->vCexes && Vec_PtrEntry(p->vCexes, i) )
continue;
// skip output whose time has run out
if ( p->pTime4Outs && p->pTime4Outs[i] == 0 )
continue;
// add constraints for this output
clk2 = Abc_Clock();
Saig_ManBmcCreateCnf( p, pObj, f );
clkOther += Abc_Clock() - clk2;
}
}
// solve SAT
clk = Abc_Clock();
Saig_ManForEachPo( pAig, pObj, i )
{
if ( i >= Saig_ManPoNum(pAig) )
break;
// check for timeout
if ( pPars->nTimeOutGap && pPars->timeLastSolved && Abc_Clock() > pPars->timeLastSolved + pPars->nTimeOutGap * CLOCKS_PER_SEC )
{
Abc_Print( 1, "Reached gap timeout (%d seconds).\n", pPars->nTimeOutGap );
goto finish;
}
if ( nTimeToStop && Abc_Clock() > nTimeToStop )
{
if ( !pPars->fSilent )
Abc_Print( 1, "Reached timeout (%d seconds).\n", pPars->nTimeOut );
goto finish;
}
if ( p->pPars->pFuncStop && p->pPars->pFuncStop(p->pPars->RunId) )
{
if ( !pPars->fSilent )
Abc_Print( 1, "Bmc3 got callbacks.\n" );
goto finish;
}
// skip solved outputs
if ( p->vCexes && Vec_PtrEntry(p->vCexes, i) )
continue;
// skip output whose time has run out
if ( p->pTime4Outs && p->pTime4Outs[i] == 0 )
continue;
// add constraints for this output
clk2 = Abc_Clock();
Lit = Saig_ManBmcCreateCnf( p, pObj, f );
clkOther += Abc_Clock() - clk2;
// solve this output
fUnfinished = 0;
if ( p->pSat ) sat_solver_compress( p->pSat );
if ( p->pTime4Outs )
{
assert( p->pTime4Outs[i] > 0 );
clkOne = Abc_Clock();
if ( p->pSat2 )
satoko_set_runtime_limit( p->pSat2, p->pTime4Outs[i] + Abc_Clock() );
else if ( p->pSat3 )
bmcg_sat_solver_set_runtime_limit( p->pSat3, p->pTime4Outs[i] + Abc_Clock() );
else
sat_solver_set_runtime_limit( p->pSat, p->pTime4Outs[i] + Abc_Clock() );
}
clk2 = Abc_Clock();
status = Saig_ManCallSolver( p, Lit );
clkSatRun = Abc_Clock() - clk2;
if ( pLogFile )
fprintf( pLogFile, "Frame %5d Output %5d Time(ms) %8d %8d\n", f, i,
Lit < 2 ? 0 : (int)(clkSatRun * 1000 / CLOCKS_PER_SEC),
Lit < 2 ? 0 : Abc_MaxInt(0, Abc_MinInt(pPars->nTimeOutOne, pPars->nTimeOutOne - (int)((p->pTime4Outs[i] - clkSatRun) * 1000 / CLOCKS_PER_SEC))) );
if ( p->pTime4Outs )
{
abctime timeSince = Abc_Clock() - clkOne;
assert( p->pTime4Outs[i] > 0 );
p->pTime4Outs[i] = (p->pTime4Outs[i] > timeSince) ? p->pTime4Outs[i] - timeSince : 0;
if ( p->pTime4Outs[i] == 0 && status != l_True )
pPars->nDropOuts++;
}
if ( status == l_False )
{
nTimeUnsat += clkSatRun;
if ( Lit != 0 )
{
// add final unit clause
Lit = lit_neg( Lit );
if ( p->pSat2 )
status = satoko_add_clause( p->pSat2, &Lit, 1 );
else if ( p->pSat3 )
status = bmcg_sat_solver_addclause( p->pSat3, &Lit, 1 );
else
status = sat_solver_addclause( p->pSat, &Lit, &Lit + 1 );
assert( status );
// add learned units
if ( p->pSat )
{
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 );
}
}
if ( p->pPars->fUseBridge )
Gia_ManReportProgress( stdout, i, f );
}
else if ( status == l_True )
{
nTimeSat += clkSatRun;
RetValue = 0;
fFirst = 0;
if ( !pPars->fSolveAll )
{
if ( pPars->fVerbose )
{
Abc_Print( 1, "%4d %s : ", f, fUnfinished ? "-" : "+" );
Abc_Print( 1, "Var =%8.0f. ", (double)p->nSatVars );
Abc_Print( 1, "Cla =%9.0f. ", (double)(p->pSat ? p->pSat->stats.clauses : p->pSat3 ? bmcg_sat_solver_clausenum(p->pSat3) : satoko_clausenum(p->pSat2)) );
Abc_Print( 1, "Conf =%7.0f. ", (double)(p->pSat ? p->pSat->stats.conflicts : p->pSat3 ? bmcg_sat_solver_conflictnum(p->pSat3) : satoko_conflictnum(p->pSat2)) );
// Abc_Print( 1, "Imp =%10.0f. ", (double)p->pSat->stats.propagations );
// Abc_Print( 1, "Uni =%7.0f. ",(double)(p->pSat ? sat_solver_count_assigned(p->pSat) : 0) );
// ABC_PRT( "Time", Abc_Clock() - clk );
Abc_Print( 1, "Learn =%7.0f. ", (double)(p->pSat ? p->pSat->stats.learnts : p->pSat3 ? bmcg_sat_solver_learntnum(p->pSat3) : satoko_learntnum(p->pSat2)) );
Abc_Print( 1, "%4.0f MB", 4.25*(f+1)*p->nObjNums /(1<<20) );
Abc_Print( 1, "%4.0f MB", 1.0*(p->pSat ? sat_solver_memory(p->pSat) : 0)/(1<<20) );
Abc_Print( 1, "%9.2f sec ", (float)(Abc_Clock() - clkTotal)/(float)(CLOCKS_PER_SEC) );
// Abc_Print( 1, "\n" );
// ABC_PRMn( "Id2Var", (f+1)*p->nObjNums*4 );
// ABC_PRMn( "SAT", 42 * p->pSat->size + 16 * (int)p->pSat->stats.clauses + 4 * (int)p->pSat->stats.clauses_literals );
// Abc_Print( 1, "S =%6d. ", p->nBufNum );
// Abc_Print( 1, "D =%6d. ", p->nDupNum );
Abc_Print( 1, "\n" );
fflush( stdout );
}
ABC_FREE( pAig->pSeqModel );
pAig->pSeqModel = Saig_ManGenerateCex( p, f, i );
goto finish;
}
pPars->nFailOuts++;
if ( !pPars->fNotVerbose )
Abc_Print( 1, "Output %*d was asserted in frame %2d (solved %*d out of %*d outputs).\n",
nOutDigits, i, f, nOutDigits, pPars->nFailOuts, nOutDigits, Saig_ManPoNum(pAig) );
if ( p->vCexes == NULL )
p->vCexes = Vec_PtrStart( Saig_ManPoNum(pAig) );
pCexNew = (p->pPars->fUseBridge || pPars->fStoreCex) ? Saig_ManGenerateCex( p, f, i ) : (Abc_Cex_t *)(ABC_PTRINT_T)1;
pCexNew0 = NULL;
if ( p->pPars->fUseBridge )
{
Gia_ManToBridgeResult( stdout, 0, pCexNew, pCexNew->iPo );
//Abc_CexFree( pCexNew );
pCexNew0 = pCexNew;
pCexNew = (Abc_Cex_t *)(ABC_PTRINT_T)1;
}
Vec_PtrWriteEntry( p->vCexes, i, Abc_CexDup(pCexNew, Saig_ManRegNum(pAig)) );
if ( pPars->pFuncOnFail && pPars->pFuncOnFail(i, pPars->fStoreCex ? (Abc_Cex_t *)Vec_PtrEntry(p->vCexes, i) : NULL) )
{
Abc_CexFreeP( &pCexNew0 );
Abc_Print( 1, "Quitting due to callback on fail.\n" );
goto finish;
}
// reset the timeout
pPars->timeLastSolved = Abc_Clock();
nTimeToStop = Saig_ManBmcTimeToStop( pPars, nTimeToStopNG );
if ( nTimeToStop )
{
if ( p->pSat2 )
satoko_set_runtime_limit( p->pSat2, nTimeToStop );
else if ( p->pSat3 )
bmcg_sat_solver_set_runtime_limit( p->pSat3, nTimeToStop );
else
sat_solver_set_runtime_limit( p->pSat, nTimeToStop );
}
// check if other outputs failed under the same counter-example
Saig_ManForEachPo( pAig, pObj, k )
{
if ( k >= Saig_ManPoNum(pAig) )
break;
// skip solved outputs
if ( p->vCexes && Vec_PtrEntry(p->vCexes, k) )
continue;
// check if this output is solved
Lit = Saig_ManBmcCreateCnf( p, pObj, f );
if ( p->pSat2 )
{
if ( satoko_read_cex_varvalue(p->pSat2, lit_var(Lit)) == Abc_LitIsCompl(Lit) )
continue;
}
else if ( p->pSat3 )
{
if ( bmcg_sat_solver_read_cex_varvalue(p->pSat3, lit_var(Lit)) == Abc_LitIsCompl(Lit) )
continue;
}
else
{
if ( sat_solver_var_value(p->pSat, lit_var(Lit)) == Abc_LitIsCompl(Lit) )
continue;
}
// write entry
pPars->nFailOuts++;
if ( !pPars->fNotVerbose )
Abc_Print( 1, "Output %*d was asserted in frame %2d (solved %*d out of %*d outputs).\n",
nOutDigits, k, f, nOutDigits, pPars->nFailOuts, nOutDigits, Saig_ManPoNum(pAig) );
// report to the bridge
if ( p->pPars->fUseBridge )
{
// set the output number
pCexNew0->iPo = k;
Gia_ManToBridgeResult( stdout, 0, pCexNew0, pCexNew0->iPo );
}
// remember solved output
Vec_PtrWriteEntry( p->vCexes, k, Abc_CexDup(pCexNew, Saig_ManRegNum(pAig)) );
}
Abc_CexFreeP( &pCexNew0 );
Abc_CexFree( pCexNew );
}
else
{
nTimeUndec += clkSatRun;
assert( status == l_Undef );
if ( pPars->nFramesJump )
{
pPars->nConfLimit = pPars->nConfLimitJump;
nJumpFrame = f + pPars->nFramesJump;
fUnfinished = 1;
break;
}
if ( p->pTime4Outs == NULL )
goto finish;
}
}
if ( pPars->fVerbose )
{
if ( fFirst == 1 && f > 0 && (p->pSat ? p->pSat->stats.conflicts : p->pSat3 ? bmcg_sat_solver_conflictnum(p->pSat3) : satoko_conflictnum(p->pSat2)) > 1 )
{
fFirst = 0;
// Abc_Print( 1, "Outputs of frames up to %d are trivially UNSAT.\n", f );
}
Abc_Print( 1, "%4d %s : ", f, fUnfinished ? "-" : "+" );
Abc_Print( 1, "Var =%8.0f. ", (double)p->nSatVars );
// Abc_Print( 1, "Used =%8.0f. ", (double)sat_solver_count_usedvars(p->pSat) );
Abc_Print( 1, "Cla =%9.0f. ", (double)(p->pSat ? p->pSat->stats.clauses : p->pSat3 ? bmcg_sat_solver_clausenum(p->pSat3) : satoko_clausenum(p->pSat2)) );
Abc_Print( 1, "Conf =%7.0f. ",(double)(p->pSat ? p->pSat->stats.conflicts : p->pSat3 ? bmcg_sat_solver_conflictnum(p->pSat3) : satoko_conflictnum(p->pSat2)) );
// Abc_Print( 1, "Imp =%10.0f. ", (double)p->pSat->stats.propagations );
// Abc_Print( 1, "Uni =%7.0f. ", (double)(p->pSat ? sat_solver_count_assigned(p->pSat) : 0) );
Abc_Print( 1, "Learn =%7.0f. ", (double)(p->pSat ? p->pSat->stats.learnts : p->pSat3 ? bmcg_sat_solver_learntnum(p->pSat3) : satoko_learntnum(p->pSat2)) );
if ( pPars->fSolveAll )
Abc_Print( 1, "CEX =%5d. ", pPars->nFailOuts );
if ( pPars->nTimeOutOne )
Abc_Print( 1, "T/O =%4d. ", pPars->nDropOuts );
// ABC_PRT( "Time", Abc_Clock() - clk );
// Abc_Print( 1, "%4.0f MB", 4.0*Vec_IntSize(p->vVisited) /(1<<20) );
Abc_Print( 1, "%4.0f MB", 4.0*(f+1)*p->nObjNums /(1<<20) );
Abc_Print( 1, "%4.0f MB", 1.0*(p->pSat ? sat_solver_memory(p->pSat) : 0)/(1<<20) );
// Abc_Print( 1, " %6d %6d ", p->nLitUsed, p->nLitUseless );
Abc_Print( 1, "%9.2f sec ", 1.0*(Abc_Clock() - clkTotal)/CLOCKS_PER_SEC );
// Abc_Print( 1, "\n" );
// ABC_PRMn( "Id2Var", (f+1)*p->nObjNums*4 );
// ABC_PRMn( "SAT", 42 * p->pSat->size + 16 * (int)p->pSat->stats.clauses + 4 * (int)p->pSat->stats.clauses_literals );
// Abc_Print( 1, "Simples = %6d. ", p->nBufNum );
// Abc_Print( 1, "Dups = %6d. ", p->nDupNum );
Abc_Print( 1, "\n" );
fflush( stdout );
}
}
// consider the next timeframe
if ( nJumpFrame && pPars->nStart == 0 )
pPars->iFrame = nJumpFrame - pPars->nFramesJump;
else if ( RetValue == -1 && pPars->nStart == 0 )
pPars->iFrame = f-1;
//ABC_PRT( "CNF generation runtime", clkOther );
finish:
if ( pPars->fVerbose )
{
Abc_Print( 1, "Runtime: " );
Abc_Print( 1, "CNF = %.1f sec (%.1f %%) ", 1.0*clkOther/CLOCKS_PER_SEC, 100.0*clkOther/(Abc_Clock() - clkTotal) );
Abc_Print( 1, "UNSAT = %.1f sec (%.1f %%) ", 1.0*nTimeUnsat/CLOCKS_PER_SEC, 100.0*nTimeUnsat/(Abc_Clock() - clkTotal) );
Abc_Print( 1, "SAT = %.1f sec (%.1f %%) ", 1.0*nTimeSat/CLOCKS_PER_SEC, 100.0*nTimeSat/(Abc_Clock() - clkTotal) );
Abc_Print( 1, "UNDEC = %.1f sec (%.1f %%)", 1.0*nTimeUndec/CLOCKS_PER_SEC, 100.0*nTimeUndec/(Abc_Clock() - clkTotal) );
Abc_Print( 1, "\n" );
}
Saig_Bmc3ManStop( p );
fflush( stdout );
if ( pLogFile )
fclose( pLogFile );
return RetValue;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END