blob: 0d5bbca23a7e7ceeb38c4007330bf79e285544e3 [file] [log] [blame]
/**CFile****************************************************************
FileName [sfmSat.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [SAT-based optimization using internal don't-cares.]
Synopsis [SAT-based procedures.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: sfmSat.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
#include "sfmInt.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
static word s_Truths6[6] = {
ABC_CONST(0xAAAAAAAAAAAAAAAA),
ABC_CONST(0xCCCCCCCCCCCCCCCC),
ABC_CONST(0xF0F0F0F0F0F0F0F0),
ABC_CONST(0xFF00FF00FF00FF00),
ABC_CONST(0xFFFF0000FFFF0000),
ABC_CONST(0xFFFFFFFF00000000)
};
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Converts a window into a SAT solver.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Sfm_NtkWindowToSolver( Sfm_Ntk_t * p )
{
// p->vOrder contains all variables in the window in a good order
// p->vDivs is a subset of nodes in p->vOrder used as divisor candidates
// p->vTfo contains TFO of the node (does not include node)
// p->vRoots contains roots of the TFO of the node (may include node)
Vec_Int_t * vClause;
int RetValue, iNode = -1, iFanin, i, k;
abctime clk = Abc_Clock();
// if ( p->pSat )
// printf( "%d ", p->pSat->stats.learnts );
sat_solver_restart( p->pSat );
sat_solver_setnvars( p->pSat, 1 + Vec_IntSize(p->vOrder) + Vec_IntSize(p->vTfo) + Vec_IntSize(p->vRoots) + 10 );
// create SAT variables
Sfm_NtkCleanVars( p );
p->nSatVars = 1;
Vec_IntForEachEntry( p->vOrder, iNode, i )
Sfm_ObjSetSatVar( p, iNode, p->nSatVars++ );
// collect divisor variables
Vec_IntClear( p->vDivVars );
Vec_IntForEachEntry( p->vDivs, iNode, i )
Vec_IntPush( p->vDivVars, Sfm_ObjSatVar(p, iNode) );
// add CNF clauses for the TFI
Vec_IntForEachEntry( p->vOrder, iNode, i )
{
if ( Sfm_ObjIsPi(p, iNode) )
continue;
// collect fanin variables
Vec_IntClear( p->vFaninMap );
Sfm_ObjForEachFanin( p, iNode, iFanin, k )
Vec_IntPush( p->vFaninMap, Sfm_ObjSatVar(p, iFanin) );
Vec_IntPush( p->vFaninMap, Sfm_ObjSatVar(p, iNode) );
// generate CNF
Sfm_TranslateCnf( p->vClauses, (Vec_Str_t *)Vec_WecEntry(p->vCnfs, iNode), p->vFaninMap, -1 );
// add clauses
Vec_WecForEachLevel( p->vClauses, vClause, k )
{
if ( Vec_IntSize(vClause) == 0 )
break;
RetValue = sat_solver_addclause( p->pSat, Vec_IntArray(vClause), Vec_IntArray(vClause) + Vec_IntSize(vClause) );
if ( RetValue == 0 )
return 0;
}
}
if ( Vec_IntSize(p->vTfo) > 0 )
{
assert( p->pPars->nTfoLevMax > 0 );
assert( Vec_IntSize(p->vRoots) > 0 );
assert( Vec_IntEntry(p->vTfo, 0) != p->iPivotNode );
// collect variables of root nodes
Vec_IntClear( p->vLits );
Vec_IntForEachEntry( p->vRoots, iNode, i )
Vec_IntPush( p->vLits, Sfm_ObjSatVar(p, iNode) );
// assign new variables to the TFO nodes
Vec_IntForEachEntry( p->vTfo, iNode, i )
{
Sfm_ObjCleanSatVar( p, Sfm_ObjSatVar(p, iNode) );
Sfm_ObjSetSatVar( p, iNode, p->nSatVars++ );
}
// add CNF clauses for the TFO
Vec_IntForEachEntry( p->vTfo, iNode, i )
{
assert( Sfm_ObjIsNode(p, iNode) );
// collect fanin variables
Vec_IntClear( p->vFaninMap );
Sfm_ObjForEachFanin( p, iNode, iFanin, k )
Vec_IntPush( p->vFaninMap, Sfm_ObjSatVar(p, iFanin) );
Vec_IntPush( p->vFaninMap, Sfm_ObjSatVar(p, iNode) );
// generate CNF
Sfm_TranslateCnf( p->vClauses, (Vec_Str_t *)Vec_WecEntry(p->vCnfs, iNode), p->vFaninMap, Sfm_ObjSatVar(p, p->iPivotNode) );
// add clauses
Vec_WecForEachLevel( p->vClauses, vClause, k )
{
if ( Vec_IntSize(vClause) == 0 )
break;
RetValue = sat_solver_addclause( p->pSat, Vec_IntArray(vClause), Vec_IntArray(vClause) + Vec_IntSize(vClause) );
if ( RetValue == 0 )
return 0;
}
}
// create XOR clauses for the roots
Vec_IntForEachEntry( p->vRoots, iNode, i )
{
sat_solver_add_xor( p->pSat, Vec_IntEntry(p->vLits, i), Sfm_ObjSatVar(p, iNode), p->nSatVars++, 0 );
Vec_IntWriteEntry( p->vLits, i, Abc_Var2Lit(p->nSatVars-1, 0) );
}
// make OR clause for the last nRoots variables
RetValue = sat_solver_addclause( p->pSat, Vec_IntArray(p->vLits), Vec_IntArray(p->vLits) + Vec_IntSize(p->vLits) );
if ( RetValue == 0 )
return 0;
}
// finalize
RetValue = sat_solver_simplify( p->pSat );
p->timeCnf += Abc_Clock() - clk;
return RetValue;
}
/**Function*************************************************************
Synopsis [Takes SAT solver and returns interpolant.]
Description [If interpolant does not exist, records difference variables.]
SideEffects []
SeeAlso []
***********************************************************************/
word Sfm_ComputeInterpolant( Sfm_Ntk_t * p )
{
word * pSign, uCube, uTruth = 0;
int status, i, Div, iVar, nFinal, * pFinal, nIter = 0;
int pLits[2], nVars = sat_solver_nvars( p->pSat );
sat_solver_setnvars( p->pSat, nVars + 1 );
pLits[0] = Abc_Var2Lit( Sfm_ObjSatVar(p, p->iPivotNode), 0 ); // F = 1
pLits[1] = Abc_Var2Lit( nVars, 0 ); // iNewLit
while ( 1 )
{
// find onset minterm
p->nSatCalls++;
status = sat_solver_solve( p->pSat, pLits, pLits + 2, p->pPars->nBTLimit, 0, 0, 0 );
if ( status == l_Undef )
return SFM_SAT_UNDEC;
if ( status == l_False )
return uTruth;
assert( status == l_True );
// remember variable values
Vec_IntClear( p->vValues );
Vec_IntForEachEntry( p->vDivVars, iVar, i )
Vec_IntPush( p->vValues, sat_solver_var_value(p->pSat, iVar) );
// collect divisor literals
Vec_IntClear( p->vLits );
Vec_IntPush( p->vLits, Abc_LitNot(pLits[0]) ); // F = 0
Vec_IntForEachEntry( p->vDivIds, Div, i )
Vec_IntPush( p->vLits, sat_solver_var_literal(p->pSat, Div) );
// check against offset
p->nSatCalls++;
status = sat_solver_solve( p->pSat, Vec_IntArray(p->vLits), Vec_IntArray(p->vLits) + Vec_IntSize(p->vLits), p->pPars->nBTLimit, 0, 0, 0 );
if ( status == l_Undef )
return SFM_SAT_UNDEC;
if ( status == l_True )
break;
assert( status == l_False );
// compute cube and add clause
nFinal = sat_solver_final( p->pSat, &pFinal );
uCube = ~(word)0;
Vec_IntClear( p->vLits );
Vec_IntPush( p->vLits, Abc_LitNot(pLits[1]) ); // NOT(iNewLit)
for ( i = 0; i < nFinal; i++ )
{
if ( pFinal[i] == pLits[0] )
continue;
Vec_IntPush( p->vLits, pFinal[i] );
iVar = Vec_IntFind( p->vDivIds, Abc_Lit2Var(pFinal[i]) ); assert( iVar >= 0 );
uCube &= Abc_LitIsCompl(pFinal[i]) ? s_Truths6[iVar] : ~s_Truths6[iVar];
}
uTruth |= uCube;
status = sat_solver_addclause( p->pSat, Vec_IntArray(p->vLits), Vec_IntArray(p->vLits) + Vec_IntSize(p->vLits) );
assert( status );
nIter++;
}
assert( status == l_True );
// store the counter-example
Vec_IntForEachEntry( p->vDivVars, iVar, i )
if ( Vec_IntEntry(p->vValues, i) ^ sat_solver_var_value(p->pSat, iVar) ) // insert 1
{
pSign = Vec_WrdEntryP( p->vDivCexes, i );
assert( !Abc_InfoHasBit( (unsigned *)pSign, p->nCexes) );
Abc_InfoXorBit( (unsigned *)pSign, p->nCexes );
}
p->nCexes++;
return SFM_SAT_SAT;
}
/**Function*************************************************************
Synopsis [Checks resubstitution.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Sfm_ComputeInterpolantCheck( Sfm_Ntk_t * p )
{
int iNode = 3;
int iDiv0 = 6;
int iDiv1 = 7;
word uTruth;
// int i;
// Sfm_NtkForEachNode( p, i )
{
Sfm_NtkCreateWindow( p, iNode, 1 );
Sfm_NtkWindowToSolver( p );
// collect SAT variables of divisors
Vec_IntClear( p->vDivIds );
Vec_IntPush( p->vDivIds, Sfm_ObjSatVar(p, iDiv0) );
Vec_IntPush( p->vDivIds, Sfm_ObjSatVar(p, iDiv1) );
uTruth = Sfm_ComputeInterpolant( p );
if ( uTruth == SFM_SAT_SAT )
printf( "The problem is SAT.\n" );
else if ( uTruth == SFM_SAT_UNDEC )
printf( "The problem is UNDEC.\n" );
else
Kit_DsdPrintFromTruth( (unsigned *)&uTruth, 2 ); printf( "\n" );
}
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END