blob: d56365b0b7d770f2e01e31e9e8b5c2f51f2a012c [file] [log] [blame]
/**CFile****************************************************************
FileName [mfsInter.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [The good old minimization with complete don't-cares.]
Synopsis [Procedures for computing resub function by interpolation.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: mfsInter.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
#include "mfsInt.h"
#include "bool/kit/kit.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Adds constraints for the two-input AND-gate.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Abc_MfsSatAddXor( sat_solver * pSat, int iVarA, int iVarB, int iVarC )
{
lit Lits[3];
Lits[0] = toLitCond( iVarA, 1 );
Lits[1] = toLitCond( iVarB, 1 );
Lits[2] = toLitCond( iVarC, 1 );
if ( !sat_solver_addclause( pSat, Lits, Lits + 3 ) )
return 0;
Lits[0] = toLitCond( iVarA, 1 );
Lits[1] = toLitCond( iVarB, 0 );
Lits[2] = toLitCond( iVarC, 0 );
if ( !sat_solver_addclause( pSat, Lits, Lits + 3 ) )
return 0;
Lits[0] = toLitCond( iVarA, 0 );
Lits[1] = toLitCond( iVarB, 1 );
Lits[2] = toLitCond( iVarC, 0 );
if ( !sat_solver_addclause( pSat, Lits, Lits + 3 ) )
return 0;
Lits[0] = toLitCond( iVarA, 0 );
Lits[1] = toLitCond( iVarB, 0 );
Lits[2] = toLitCond( iVarC, 1 );
if ( !sat_solver_addclause( pSat, Lits, Lits + 3 ) )
return 0;
return 1;
}
/**Function*************************************************************
Synopsis [Creates miter for checking resubsitution.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
sat_solver * Abc_MfsCreateSolverResub( Mfs_Man_t * p, int * pCands, int nCands, int fInvert )
{
sat_solver * pSat;
Aig_Obj_t * pObjPo;
int Lits[2], status, iVar, i, c;
// get the literal for the output of F
pObjPo = Aig_ManCo( p->pAigWin, Aig_ManCoNum(p->pAigWin) - Vec_PtrSize(p->vDivs) - 1 );
Lits[0] = toLitCond( p->pCnf->pVarNums[pObjPo->Id], fInvert );
// collect the outputs of the divisors
Vec_IntClear( p->vProjVarsCnf );
Vec_PtrForEachEntryStart( Aig_Obj_t *, p->pAigWin->vCos, pObjPo, i, Aig_ManCoNum(p->pAigWin) - Vec_PtrSize(p->vDivs) )
{
assert( p->pCnf->pVarNums[pObjPo->Id] >= 0 );
Vec_IntPush( p->vProjVarsCnf, p->pCnf->pVarNums[pObjPo->Id] );
}
assert( Vec_IntSize(p->vProjVarsCnf) == Vec_PtrSize(p->vDivs) );
// start the solver
pSat = sat_solver_new();
sat_solver_setnvars( pSat, 2 * p->pCnf->nVars + Vec_PtrSize(p->vDivs) );
if ( pCands )
sat_solver_store_alloc( pSat );
// load the first copy of the clauses
for ( i = 0; i < p->pCnf->nClauses; i++ )
{
if ( !sat_solver_addclause( pSat, p->pCnf->pClauses[i], p->pCnf->pClauses[i+1] ) )
{
sat_solver_delete( pSat );
return NULL;
}
}
// add the clause for the first output of F
if ( !sat_solver_addclause( pSat, Lits, Lits+1 ) )
{
sat_solver_delete( pSat );
return NULL;
}
// add one-hotness constraints
if ( p->pPars->fOneHotness )
{
p->pSat = pSat;
if ( !Abc_NtkAddOneHotness( p ) )
return NULL;
p->pSat = NULL;
}
// bookmark the clauses of A
if ( pCands )
sat_solver_store_mark_clauses_a( pSat );
// transform the literals
for ( i = 0; i < p->pCnf->nLiterals; i++ )
p->pCnf->pClauses[0][i] += 2 * p->pCnf->nVars;
// load the second copy of the clauses
for ( i = 0; i < p->pCnf->nClauses; i++ )
{
if ( !sat_solver_addclause( pSat, p->pCnf->pClauses[i], p->pCnf->pClauses[i+1] ) )
{
sat_solver_delete( pSat );
return NULL;
}
}
// add one-hotness constraints
if ( p->pPars->fOneHotness )
{
p->pSat = pSat;
if ( !Abc_NtkAddOneHotness( p ) )
return NULL;
p->pSat = NULL;
}
// transform the literals
for ( i = 0; i < p->pCnf->nLiterals; i++ )
p->pCnf->pClauses[0][i] -= 2 * p->pCnf->nVars;
// add the clause for the second output of F
Lits[0] = 2 * p->pCnf->nVars + lit_neg( Lits[0] );
if ( !sat_solver_addclause( pSat, Lits, Lits+1 ) )
{
sat_solver_delete( pSat );
return NULL;
}
if ( pCands )
{
// add relevant clauses for EXOR gates
for ( c = 0; c < nCands; c++ )
{
// get the variable number of this divisor
i = lit_var( pCands[c] ) - 2 * p->pCnf->nVars;
// get the corresponding SAT variable
iVar = Vec_IntEntry( p->vProjVarsCnf, i );
// add the corresponding EXOR gate
if ( !Abc_MfsSatAddXor( pSat, iVar, iVar + p->pCnf->nVars, 2 * p->pCnf->nVars + i ) )
{
sat_solver_delete( pSat );
return NULL;
}
// add the corresponding clause
if ( !sat_solver_addclause( pSat, pCands + c, pCands + c + 1 ) )
{
sat_solver_delete( pSat );
return NULL;
}
}
// bookmark the roots
sat_solver_store_mark_roots( pSat );
}
else
{
// add the clauses for the EXOR gates - and remember their outputs
Vec_IntClear( p->vProjVarsSat );
Vec_IntForEachEntry( p->vProjVarsCnf, iVar, i )
{
if ( !Abc_MfsSatAddXor( pSat, iVar, iVar + p->pCnf->nVars, 2 * p->pCnf->nVars + i ) )
{
sat_solver_delete( pSat );
return NULL;
}
Vec_IntPush( p->vProjVarsSat, 2 * p->pCnf->nVars + i );
}
assert( Vec_IntSize(p->vProjVarsCnf) == Vec_IntSize(p->vProjVarsSat) );
// simplify the solver
status = sat_solver_simplify(pSat);
if ( status == 0 )
{
// printf( "Abc_MfsCreateSolverResub(): SAT solver construction has failed. Skipping node.\n" );
sat_solver_delete( pSat );
return NULL;
}
}
return pSat;
}
/**Function*************************************************************
Synopsis [Performs interpolation.]
Description [Derives the new function of the node.]
SideEffects []
SeeAlso []
***********************************************************************/
unsigned * Abc_NtkMfsInterplateTruth( Mfs_Man_t * p, int * pCands, int nCands, int fInvert )
{
sat_solver * pSat;
Sto_Man_t * pCnf = NULL;
unsigned * puTruth;
int nFanins, status;
int c, i, * pGloVars;
// derive the SAT solver for interpolation
pSat = Abc_MfsCreateSolverResub( p, pCands, nCands, fInvert );
// solve the problem
status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)p->pPars->nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
if ( status != l_False )
{
p->nTimeOuts++;
return NULL;
}
// get the learned clauses
pCnf = (Sto_Man_t *)sat_solver_store_release( pSat );
sat_solver_delete( pSat );
// set the global variables
pGloVars = Int_ManSetGlobalVars( p->pMan, nCands );
for ( c = 0; c < nCands; c++ )
{
// get the variable number of this divisor
i = lit_var( pCands[c] ) - 2 * p->pCnf->nVars;
// get the corresponding SAT variable
pGloVars[c] = Vec_IntEntry( p->vProjVarsCnf, i );
}
// derive the interpolant
nFanins = Int_ManInterpolate( p->pMan, pCnf, 0, &puTruth );
Sto_ManFree( pCnf );
assert( nFanins == nCands );
return puTruth;
}
/**Function*************************************************************
Synopsis [Performs interpolation.]
Description [Derives the new function of the node.]
SideEffects []
SeeAlso []
***********************************************************************/
int Abc_NtkMfsInterplateEval( Mfs_Man_t * p, int * pCands, int nCands )
{
unsigned * pTruth, uTruth0[2], uTruth1[2];
int nCounter;
pTruth = Abc_NtkMfsInterplateTruth( p, pCands, nCands, 0 );
if ( nCands == 6 )
{
uTruth1[0] = pTruth[0];
uTruth1[1] = pTruth[1];
}
else
{
uTruth1[0] = pTruth[0];
uTruth1[1] = pTruth[0];
}
pTruth = Abc_NtkMfsInterplateTruth( p, pCands, nCands, 1 );
if ( nCands == 6 )
{
uTruth0[0] = ~pTruth[0];
uTruth0[1] = ~pTruth[1];
}
else
{
uTruth0[0] = ~pTruth[0];
uTruth0[1] = ~pTruth[0];
}
nCounter = Extra_WordCountOnes( uTruth0[0] ^ uTruth1[0] );
nCounter += Extra_WordCountOnes( uTruth0[1] ^ uTruth1[1] );
// printf( "%d ", nCounter );
return nCounter;
}
/**Function*************************************************************
Synopsis [Performs interpolation.]
Description [Derives the new function of the node.]
SideEffects []
SeeAlso []
***********************************************************************/
Hop_Obj_t * Abc_NtkMfsInterplate( Mfs_Man_t * p, int * pCands, int nCands )
{
extern Hop_Obj_t * Kit_GraphToHop( Hop_Man_t * pMan, Kit_Graph_t * pGraph );
int fDumpFile = 0;
char FileName[32];
sat_solver * pSat;
Sto_Man_t * pCnf = NULL;
unsigned * puTruth;
Kit_Graph_t * pGraph;
Hop_Obj_t * pFunc;
int nFanins, status;
int c, i, * pGloVars;
// abctime clk = Abc_Clock();
// p->nDcMints += Abc_NtkMfsInterplateEval( p, pCands, nCands );
// derive the SAT solver for interpolation
pSat = Abc_MfsCreateSolverResub( p, pCands, nCands, 0 );
// dump CNF file (remember to uncomment two-lit clases in clause_create_new() in 'satSolver.c')
if ( fDumpFile )
{
static int Counter = 0;
sprintf( FileName, "cnf\\pj1_if6_mfs%03d.cnf", Counter++ );
Sat_SolverWriteDimacs( pSat, FileName, NULL, NULL, 1 );
}
// solve the problem
status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)p->pPars->nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
if ( fDumpFile )
printf( "File %s has UNSAT problem with %d conflicts.\n", FileName, (int)pSat->stats.conflicts );
if ( status != l_False )
{
p->nTimeOuts++;
return NULL;
}
//printf( "%d\n", pSat->stats.conflicts );
// ABC_PRT( "S", Abc_Clock() - clk );
// get the learned clauses
pCnf = (Sto_Man_t *)sat_solver_store_release( pSat );
sat_solver_delete( pSat );
// set the global variables
pGloVars = Int_ManSetGlobalVars( p->pMan, nCands );
for ( c = 0; c < nCands; c++ )
{
// get the variable number of this divisor
i = lit_var( pCands[c] ) - 2 * p->pCnf->nVars;
// get the corresponding SAT variable
pGloVars[c] = Vec_IntEntry( p->vProjVarsCnf, i );
}
// derive the interpolant
nFanins = Int_ManInterpolate( p->pMan, pCnf, 0, &puTruth );
Sto_ManFree( pCnf );
assert( nFanins == nCands );
// transform interpolant into AIG
pGraph = Kit_TruthToGraph( puTruth, nFanins, p->vMem );
pFunc = Kit_GraphToHop( (Hop_Man_t *)p->pNtk->pManFunc, pGraph );
Kit_GraphFree( pGraph );
return pFunc;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END