blob: b1a5b66c45d336d33934ebed20b875d9dbc9b8d6 [file] [log] [blame]
/**CFile****************************************************************
FileName [pdrSat.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Property driven reachability.]
Synopsis [SAT solver procedures.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - November 20, 2010.]
Revision [$Id: pdrSat.c,v 1.00 2010/11/20 00:00:00 alanmi Exp $]
***********************************************************************/
#include "pdrInt.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Creates new SAT solver.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
sat_solver * Pdr_ManCreateSolver( Pdr_Man_t * p, int k )
{
sat_solver * pSat;
Aig_Obj_t * pObj;
int i;
assert( Vec_PtrSize(p->vSolvers) == k );
assert( Vec_VecSize(p->vClauses) == k );
assert( Vec_IntSize(p->vActVars) == k );
// create new solver
// pSat = sat_solver_new();
pSat = zsat_solver_new_seed(p->pPars->nRandomSeed);
pSat = Pdr_ManNewSolver( pSat, p, k, (int)(k == 0) );
Vec_PtrPush( p->vSolvers, pSat );
Vec_VecExpand( p->vClauses, k );
Vec_IntPush( p->vActVars, 0 );
// add property cone
Saig_ManForEachPo( p->pAig, pObj, i )
Pdr_ObjSatVar( p, k, 1, pObj );
return pSat;
}
/**Function*************************************************************
Synopsis [Returns old or restarted solver.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
sat_solver * Pdr_ManFetchSolver( Pdr_Man_t * p, int k )
{
sat_solver * pSat;
Vec_Ptr_t * vArrayK;
Pdr_Set_t * pCube;
int i, j;
pSat = Pdr_ManSolver(p, k);
if ( Vec_IntEntry(p->vActVars, k) < p->pPars->nRecycle )
return pSat;
assert( k < Vec_PtrSize(p->vSolvers) - 1 );
p->nStarts++;
// sat_solver_delete( pSat );
// pSat = sat_solver_new();
// sat_solver_restart( pSat );
zsat_solver_restart_seed( pSat, p->pPars->nRandomSeed );
// create new SAT solver
pSat = Pdr_ManNewSolver( pSat, p, k, (int)(k == 0) );
// write new SAT solver
Vec_PtrWriteEntry( p->vSolvers, k, pSat );
Vec_IntWriteEntry( p->vActVars, k, 0 );
// set the property output
Pdr_ManSetPropertyOutput( p, k );
// add the clauses
Vec_VecForEachLevelStart( p->vClauses, vArrayK, i, k )
Vec_PtrForEachEntry( Pdr_Set_t *, vArrayK, pCube, j )
Pdr_ManSolverAddClause( p, k, pCube );
return pSat;
}
/**Function*************************************************************
Synopsis [Converts SAT variables into register IDs.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Int_t * Pdr_ManLitsToCube( Pdr_Man_t * p, int k, int * pArray, int nArray )
{
int i, RegId;
Vec_IntClear( p->vLits );
for ( i = 0; i < nArray; i++ )
{
RegId = Pdr_ObjRegNum( p, k, Abc_Lit2Var(pArray[i]) );
if ( RegId == -1 )
continue;
assert( RegId >= 0 && RegId < Aig_ManRegNum(p->pAig) );
Vec_IntPush( p->vLits, Abc_Var2Lit(RegId, !Abc_LitIsCompl(pArray[i])) );
}
assert( Vec_IntSize(p->vLits) >= 0 && Vec_IntSize(p->vLits) <= nArray );
return p->vLits;
}
/**Function*************************************************************
Synopsis [Converts the cube in terms of RO numbers into array of CNF literals.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Int_t * Pdr_ManCubeToLits( Pdr_Man_t * p, int k, Pdr_Set_t * pCube, int fCompl, int fNext )
{
Aig_Obj_t * pObj;
int i, iVar, iVarMax = 0;
abctime clk = Abc_Clock();
Vec_IntClear( p->vLits );
// assert( !(fNext && fCompl) );
for ( i = 0; i < pCube->nLits; i++ )
{
if ( pCube->Lits[i] == -1 )
continue;
if ( fNext )
pObj = Saig_ManLi( p->pAig, Abc_Lit2Var(pCube->Lits[i]) );
else
pObj = Saig_ManLo( p->pAig, Abc_Lit2Var(pCube->Lits[i]) );
iVar = Pdr_ObjSatVar( p, k, fNext ? 2 - Abc_LitIsCompl(pCube->Lits[i]) : 3, pObj ); assert( iVar >= 0 );
iVarMax = Abc_MaxInt( iVarMax, iVar );
Vec_IntPush( p->vLits, Abc_Var2Lit( iVar, fCompl ^ Abc_LitIsCompl(pCube->Lits[i]) ) );
}
// sat_solver_setnvars( Pdr_ManSolver(p, k), iVarMax + 1 );
p->tCnf += Abc_Clock() - clk;
return p->vLits;
}
/**Function*************************************************************
Synopsis [Sets the property output to 0 (sat) forever.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Pdr_ManSetPropertyOutput( Pdr_Man_t * p, int k )
{
sat_solver * pSat;
Aig_Obj_t * pObj;
int Lit, RetValue, i;
if ( !p->pPars->fUsePropOut )
return;
pSat = Pdr_ManSolver(p, k);
Saig_ManForEachPo( p->pAig, pObj, i )
{
// skip solved outputs
if ( p->vCexes && Vec_PtrEntry(p->vCexes, i) )
continue;
// skip timedout outputs
if ( p->pPars->vOutMap && Vec_IntEntry(p->pPars->vOutMap, i) == -1 )
continue;
Lit = Abc_Var2Lit( Pdr_ObjSatVar(p, k, 1, pObj), 1 ); // neg literal
RetValue = sat_solver_addclause( pSat, &Lit, &Lit + 1 );
assert( RetValue == 1 );
}
sat_solver_compress( pSat );
}
/**Function*************************************************************
Synopsis [Adds one clause in terms of ROs to the k-th SAT solver.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Pdr_ManSolverAddClause( Pdr_Man_t * p, int k, Pdr_Set_t * pCube )
{
sat_solver * pSat;
Vec_Int_t * vLits;
int RetValue;
pSat = Pdr_ManSolver(p, k);
vLits = Pdr_ManCubeToLits( p, k, pCube, 1, 0 );
RetValue = sat_solver_addclause( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits) );
assert( RetValue == 1 );
sat_solver_compress( pSat );
}
/**Function*************************************************************
Synopsis [Collects values of the RO/RI variables in k-th SAT solver.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Pdr_ManCollectValues( Pdr_Man_t * p, int k, Vec_Int_t * vObjIds, Vec_Int_t * vValues )
{
sat_solver * pSat;
Aig_Obj_t * pObj;
int iVar, i;
Vec_IntClear( vValues );
pSat = Pdr_ManSolver(p, k);
Aig_ManForEachObjVec( vObjIds, p->pAig, pObj, i )
{
iVar = Pdr_ObjSatVar( p, k, 3, pObj ); assert( iVar >= 0 );
Vec_IntPush( vValues, sat_solver_var_value(pSat, iVar) );
}
}
/**Function*************************************************************
Synopsis [Checks if the cube holds (UNSAT) in the given timeframe.]
Description [Return 1/0 if cube or property are proved to hold/fail
in k-th timeframe. Returns the predecessor bad state in ppPred.]
SideEffects []
SeeAlso []
***********************************************************************/
int Pdr_ManCheckCubeCs( Pdr_Man_t * p, int k, Pdr_Set_t * pCube )
{
sat_solver * pSat;
Vec_Int_t * vLits;
abctime Limit;
int RetValue;
pSat = Pdr_ManFetchSolver( p, k );
vLits = Pdr_ManCubeToLits( p, k, pCube, 0, 0 );
Limit = sat_solver_set_runtime_limit( pSat, Pdr_ManTimeLimit(p) );
RetValue = sat_solver_solve( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits), 0, 0, 0, 0 );
sat_solver_set_runtime_limit( pSat, Limit );
if ( RetValue == l_Undef )
return -1;
return (RetValue == l_False);
}
/**Function*************************************************************
Synopsis [Checks if the cube holds (UNSAT) in the given timeframe.]
Description [Return 1/0 if cube or property are proved to hold/fail
in k-th timeframe. Returns the predecessor bad state in ppPred.]
SideEffects []
SeeAlso []
***********************************************************************/
int Pdr_ManCheckCube( Pdr_Man_t * p, int k, Pdr_Set_t * pCube, Pdr_Set_t ** ppPred, int nConfLimit, int fTryConf, int fUseLit )
{
//int fUseLit = 0;
int fLitUsed = 0;
sat_solver * pSat;
Vec_Int_t * vLits;
int Lit, RetValue;
abctime clk, Limit;
p->nCalls++;
pSat = Pdr_ManFetchSolver( p, k );
if ( pCube == NULL ) // solve the property
{
clk = Abc_Clock();
Lit = Abc_Var2Lit( Pdr_ObjSatVar(p, k, 2, Aig_ManCo(p->pAig, p->iOutCur)), 0 ); // pos literal (property fails)
Limit = sat_solver_set_runtime_limit( pSat, Pdr_ManTimeLimit(p) );
RetValue = sat_solver_solve( pSat, &Lit, &Lit + 1, nConfLimit, 0, 0, 0 );
sat_solver_set_runtime_limit( pSat, Limit );
if ( RetValue == l_Undef )
return -1;
}
else // check relative containment in terms of next states
{
if ( fUseLit )
{
fLitUsed = 1;
Vec_IntAddToEntry( p->vActVars, k, 1 );
// add the cube in terms of current state variables
vLits = Pdr_ManCubeToLits( p, k, pCube, 1, 0 );
// add activation literal
Lit = Abc_Var2Lit( Pdr_ManFreeVar(p, k), 0 );
// add activation literal
Vec_IntPush( vLits, Lit );
RetValue = sat_solver_addclause( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits) );
assert( RetValue == 1 );
sat_solver_compress( pSat );
// create assumptions
vLits = Pdr_ManCubeToLits( p, k, pCube, 0, 1 );
// add activation literal
Vec_IntPush( vLits, Abc_LitNot(Lit) );
}
else
vLits = Pdr_ManCubeToLits( p, k, pCube, 0, 1 );
// solve
clk = Abc_Clock();
Limit = sat_solver_set_runtime_limit( pSat, Pdr_ManTimeLimit(p) );
RetValue = sat_solver_solve( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits), fTryConf ? p->pPars->nConfGenLimit : nConfLimit, 0, 0, 0 );
sat_solver_set_runtime_limit( pSat, Limit );
if ( RetValue == l_Undef )
{
if ( fTryConf && p->pPars->nConfGenLimit )
RetValue = l_True;
else
return -1;
}
}
clk = Abc_Clock() - clk;
p->tSat += clk;
assert( RetValue != l_Undef );
if ( RetValue == l_False )
{
p->tSatUnsat += clk;
p->nCallsU++;
if ( ppPred )
*ppPred = NULL;
RetValue = 1;
}
else // if ( RetValue == l_True )
{
p->tSatSat += clk;
p->nCallsS++;
if ( ppPred )
{
abctime clk = Abc_Clock();
if ( p->pPars->fNewXSim )
*ppPred = Txs3_ManTernarySim( p->pTxs3, k, pCube );
else
*ppPred = Pdr_ManTernarySim( p, k, pCube );
p->tTsim += Abc_Clock() - clk;
p->nXsimLits += (*ppPred)->nLits;
p->nXsimRuns++;
}
RetValue = 0;
}
/* // for some reason, it does not work...
if ( fLitUsed )
{
int RetValue;
Lit = Abc_LitNot(Lit);
RetValue = sat_solver_addclause( pSat, &Lit, &Lit + 1 );
assert( RetValue == 1 );
sat_solver_compress( pSat );
}
*/
return RetValue;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END