blob: d6fb5f5eb13130744105d85cddf8aebc0cba7d24 [file] [log] [blame]
/**CFile****************************************************************
FileName [resSat.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Resynthesis package.]
Synopsis [Interface with the SAT solver.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - January 15, 2007.]
Revision [$Id: resSat.c,v 1.00 2007/01/15 00:00:00 alanmi Exp $]
***********************************************************************/
#include "base/abc/abc.h"
#include "resInt.h"
#include "aig/hop/hop.h"
#include "sat/bsat/satSolver.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
extern int Res_SatAddConst1( sat_solver * pSat, int iVar, int fCompl );
extern int Res_SatAddEqual( sat_solver * pSat, int iVar0, int iVar1, int fCompl );
extern int Res_SatAddAnd( sat_solver * pSat, int iVar, int iVar0, int iVar1, int fCompl0, int fCompl1 );
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Loads AIG into the SAT solver for checking resubstitution.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void * Res_SatProveUnsat( Abc_Ntk_t * pAig, Vec_Ptr_t * vFanins )
{
void * pCnf = NULL;
sat_solver * pSat;
Vec_Ptr_t * vNodes;
Abc_Obj_t * pObj;
int i, nNodes, status;
// make sure fanins contain POs of the AIG
pObj = (Abc_Obj_t *)Vec_PtrEntry( vFanins, 0 );
assert( pObj->pNtk == pAig && Abc_ObjIsPo(pObj) );
// collect reachable nodes
vNodes = Abc_NtkDfsNodes( pAig, (Abc_Obj_t **)vFanins->pArray, vFanins->nSize );
// assign unique numbers to each node
nNodes = 0;
Abc_AigConst1(pAig)->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)nNodes++;
Abc_NtkForEachPi( pAig, pObj, i )
pObj->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)nNodes++;
Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
pObj->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)nNodes++;
Vec_PtrForEachEntry( Abc_Obj_t *, vFanins, pObj, i ) // useful POs
pObj->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)nNodes++;
// start the solver
pSat = sat_solver_new();
sat_solver_store_alloc( pSat );
// add clause for the constant node
Res_SatAddConst1( pSat, (int)(ABC_PTRUINT_T)Abc_AigConst1(pAig)->pCopy, 0 );
// add clauses for AND gates
Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
Res_SatAddAnd( pSat, (int)(ABC_PTRUINT_T)pObj->pCopy,
(int)(ABC_PTRUINT_T)Abc_ObjFanin0(pObj)->pCopy, (int)(ABC_PTRUINT_T)Abc_ObjFanin1(pObj)->pCopy, Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj) );
Vec_PtrFree( vNodes );
// add clauses for POs
Vec_PtrForEachEntry( Abc_Obj_t *, vFanins, pObj, i )
Res_SatAddEqual( pSat, (int)(ABC_PTRUINT_T)pObj->pCopy,
(int)(ABC_PTRUINT_T)Abc_ObjFanin0(pObj)->pCopy, Abc_ObjFaninC0(pObj) );
// add trivial clauses
pObj = (Abc_Obj_t *)Vec_PtrEntry(vFanins, 0);
Res_SatAddConst1( pSat, (int)(ABC_PTRUINT_T)pObj->pCopy, 0 ); // care-set
pObj = (Abc_Obj_t *)Vec_PtrEntry(vFanins, 1);
Res_SatAddConst1( pSat, (int)(ABC_PTRUINT_T)pObj->pCopy, 0 ); // on-set
// bookmark the clauses of A
sat_solver_store_mark_clauses_a( pSat );
// duplicate the clauses
pObj = (Abc_Obj_t *)Vec_PtrEntry(vFanins, 1);
Sat_SolverDoubleClauses( pSat, (int)(ABC_PTRUINT_T)pObj->pCopy );
// add the equality constraints
Vec_PtrForEachEntryStart( Abc_Obj_t *, vFanins, pObj, i, 2 )
Res_SatAddEqual( pSat, (int)(ABC_PTRUINT_T)pObj->pCopy, ((int)(ABC_PTRUINT_T)pObj->pCopy) + nNodes, 0 );
// bookmark the roots
sat_solver_store_mark_roots( pSat );
// solve the problem
status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)10000, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
if ( status == l_False )
{
pCnf = sat_solver_store_release( pSat );
// printf( "unsat\n" );
}
else if ( status == l_True )
{
// printf( "sat\n" );
}
else
{
// printf( "undef\n" );
}
sat_solver_delete( pSat );
return pCnf;
}
/**Function*************************************************************
Synopsis [Loads AIG into the SAT solver for constrained simulation.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void * Res_SatSimulateConstr( Abc_Ntk_t * pAig, int fOnSet )
{
sat_solver * pSat;
Vec_Ptr_t * vFanins;
Vec_Ptr_t * vNodes;
Abc_Obj_t * pObj;
int i, nNodes;
// start the array
vFanins = Vec_PtrAlloc( 2 );
pObj = Abc_NtkPo( pAig, 0 );
Vec_PtrPush( vFanins, pObj );
pObj = Abc_NtkPo( pAig, 1 );
Vec_PtrPush( vFanins, pObj );
// collect reachable nodes
vNodes = Abc_NtkDfsNodes( pAig, (Abc_Obj_t **)vFanins->pArray, vFanins->nSize );
// assign unique numbers to each node
nNodes = 0;
Abc_AigConst1(pAig)->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)nNodes++;
Abc_NtkForEachPi( pAig, pObj, i )
pObj->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)nNodes++;
Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
pObj->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)nNodes++;
Vec_PtrForEachEntry( Abc_Obj_t *, vFanins, pObj, i ) // useful POs
pObj->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)nNodes++;
// start the solver
pSat = sat_solver_new();
// add clause for the constant node
Res_SatAddConst1( pSat, (int)(ABC_PTRUINT_T)Abc_AigConst1(pAig)->pCopy, 0 );
// add clauses for AND gates
Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
Res_SatAddAnd( pSat, (int)(ABC_PTRUINT_T)pObj->pCopy,
(int)(ABC_PTRUINT_T)Abc_ObjFanin0(pObj)->pCopy, (int)(ABC_PTRUINT_T)Abc_ObjFanin1(pObj)->pCopy, Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj) );
Vec_PtrFree( vNodes );
// add clauses for the first PO
pObj = Abc_NtkPo( pAig, 0 );
Res_SatAddEqual( pSat, (int)(ABC_PTRUINT_T)pObj->pCopy,
(int)(ABC_PTRUINT_T)Abc_ObjFanin0(pObj)->pCopy, Abc_ObjFaninC0(pObj) );
// add clauses for the second PO
pObj = Abc_NtkPo( pAig, 1 );
Res_SatAddEqual( pSat, (int)(ABC_PTRUINT_T)pObj->pCopy,
(int)(ABC_PTRUINT_T)Abc_ObjFanin0(pObj)->pCopy, Abc_ObjFaninC0(pObj) );
// add trivial clauses
pObj = Abc_NtkPo( pAig, 0 );
Res_SatAddConst1( pSat, (int)(ABC_PTRUINT_T)pObj->pCopy, 0 ); // care-set
pObj = Abc_NtkPo( pAig, 1 );
Res_SatAddConst1( pSat, (int)(ABC_PTRUINT_T)pObj->pCopy, !fOnSet ); // on-set
Vec_PtrFree( vFanins );
return pSat;
}
/**Function*************************************************************
Synopsis [Loads AIG into the SAT solver for constrained simulation.]
Description [Returns 1 if the required number of patterns are found.
Returns 0 if the solver ran out of time or proved a constant.
In the latter, case one of the flags, fConst0 or fConst1, are set to 1.]
SideEffects []
SeeAlso []
***********************************************************************/
int Res_SatSimulate( Res_Sim_t * p, int nPatsLimit, int fOnSet )
{
Vec_Int_t * vLits;
Vec_Ptr_t * vPats;
sat_solver * pSat;
int RetValue = -1; // Suppress "might be used uninitialized"
int i, k, value, status, Lit, Var, iPat;
abctime clk = Abc_Clock();
//printf( "Looking for %s: ", fOnSet? "onset " : "offset" );
// decide what problem should be solved
Lit = toLitCond( (int)(ABC_PTRUINT_T)Abc_NtkPo(p->pAig,1)->pCopy, !fOnSet );
if ( fOnSet )
{
iPat = p->nPats1;
vPats = p->vPats1;
}
else
{
iPat = p->nPats0;
vPats = p->vPats0;
}
assert( iPat < nPatsLimit );
// derive the SAT solver
pSat = (sat_solver *)Res_SatSimulateConstr( p->pAig, fOnSet );
pSat->fSkipSimplify = 1;
status = sat_solver_simplify( pSat );
if ( status == 0 )
{
if ( iPat == 0 )
{
// if ( fOnSet )
// p->fConst0 = 1;
// else
// p->fConst1 = 1;
RetValue = 0;
}
goto finish;
}
// enumerate through the SAT assignments
RetValue = 1;
vLits = Vec_IntAlloc( 32 );
for ( k = iPat; k < nPatsLimit; k++ )
{
// solve with the assumption
// status = sat_solver_solve( pSat, &Lit, &Lit + 1, (ABC_INT64_T)10000, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)10000, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
if ( status == l_False )
{
//printf( "Const %d\n", !fOnSet );
if ( k == 0 )
{
if ( fOnSet )
p->fConst0 = 1;
else
p->fConst1 = 1;
RetValue = 0;
}
break;
}
else if ( status == l_True )
{
// save the pattern
Vec_IntClear( vLits );
for ( i = 0; i < p->nTruePis; i++ )
{
Var = (int)(ABC_PTRUINT_T)Abc_NtkPi(p->pAig,i)->pCopy;
// value = (int)(pSat->model.ptr[Var] == l_True);
value = sat_solver_var_value(pSat, Var);
if ( value )
Abc_InfoSetBit( (unsigned *)Vec_PtrEntry(vPats, i), k );
Lit = toLitCond( Var, value );
Vec_IntPush( vLits, Lit );
// printf( "%d", value );
}
// printf( "\n" );
status = sat_solver_addclause( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits) );
if ( status == 0 )
{
k++;
RetValue = 1;
break;
}
}
else
{
//printf( "Undecided\n" );
if ( k == 0 )
RetValue = 0;
else
RetValue = 1;
break;
}
}
Vec_IntFree( vLits );
//printf( "Found %d patterns\n", k - iPat );
// set the new number of patterns
if ( fOnSet )
p->nPats1 = k;
else
p->nPats0 = k;
finish:
sat_solver_delete( pSat );
p->timeSat += Abc_Clock() - clk;
return RetValue;
}
/**Function*************************************************************
Synopsis [Asserts equality of the variable to a constant.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Res_SatAddConst1( 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 [Asserts equality of two variables.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Res_SatAddEqual( 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 constraints for the two-input AND-gate.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Res_SatAddAnd( 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;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END