blob: 6cdaa24887299bf8b4babd309ae1313b799e052e [file] [log] [blame]
/**CFile****************************************************************
FileName [fraCec.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [New FRAIG package.]
Synopsis [CEC engined based on fraiging.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 30, 2007.]
Revision [$Id: fraCec.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $]
***********************************************************************/
#include "fra.h"
#include "sat/cnf/cnf.h"
#include "sat/bsat/satSolver2.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Fra_FraigSat( Aig_Man_t * pMan, ABC_INT64_T nConfLimit, ABC_INT64_T nInsLimit, int nLearnedStart, int nLearnedDelta, int nLearnedPerce, int fFlipBits, int fAndOuts, int fNewSolver, int fVerbose )
{
if ( fNewSolver )
{
extern void * Cnf_DataWriteIntoSolver2( Cnf_Dat_t * p, int nFrames, int fInit );
extern int Cnf_DataWriteOrClause2( void * pSat, Cnf_Dat_t * pCnf );
sat_solver2 * pSat;
Cnf_Dat_t * pCnf;
int status, RetValue = 0;
abctime clk = Abc_Clock();
Vec_Int_t * vCiIds;
assert( Aig_ManRegNum(pMan) == 0 );
pMan->pData = NULL;
// derive CNF
pCnf = Cnf_Derive( pMan, Aig_ManCoNum(pMan) );
// pCnf = Cnf_DeriveSimple( pMan, Aig_ManCoNum(pMan) );
if ( fFlipBits )
Cnf_DataTranformPolarity( pCnf, 0 );
if ( fVerbose )
{
printf( "CNF stats: Vars = %6d. Clauses = %7d. Literals = %8d. ", pCnf->nVars, pCnf->nClauses, pCnf->nLiterals );
Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
}
// convert into SAT solver
pSat = (sat_solver2 *)Cnf_DataWriteIntoSolver2( pCnf, 1, 0 );
if ( pSat == NULL )
{
Cnf_DataFree( pCnf );
return 1;
}
if ( fAndOuts )
{
// assert each output independently
if ( !Cnf_DataWriteAndClauses( pSat, pCnf ) )
{
sat_solver2_delete( pSat );
Cnf_DataFree( pCnf );
return 1;
}
}
else
{
// add the OR clause for the outputs
if ( !Cnf_DataWriteOrClause2( pSat, pCnf ) )
{
sat_solver2_delete( pSat );
Cnf_DataFree( pCnf );
return 1;
}
}
vCiIds = Cnf_DataCollectPiSatNums( pCnf, pMan );
Cnf_DataFree( pCnf );
printf( "Created SAT problem with %d variable and %d clauses. ", sat_solver2_nvars(pSat), sat_solver2_nclauses(pSat) );
ABC_PRT( "Time", Abc_Clock() - clk );
// simplify the problem
clk = Abc_Clock();
status = sat_solver2_simplify(pSat);
// printf( "Simplified the problem to %d variables and %d clauses. ", sat_solver2_nvars(pSat), sat_solver2_nclauses(pSat) );
// ABC_PRT( "Time", Abc_Clock() - clk );
if ( status == 0 )
{
Vec_IntFree( vCiIds );
sat_solver2_delete( pSat );
// printf( "The problem is UNSATISFIABLE after simplification.\n" );
return 1;
}
// solve the miter
clk = Abc_Clock();
if ( fVerbose )
pSat->verbosity = 1;
status = sat_solver2_solve( pSat, NULL, NULL, (ABC_INT64_T)nConfLimit, (ABC_INT64_T)nInsLimit, (ABC_INT64_T)0, (ABC_INT64_T)0 );
if ( status == l_Undef )
{
// printf( "The problem timed out.\n" );
RetValue = -1;
}
else if ( status == l_True )
{
// printf( "The problem is SATISFIABLE.\n" );
RetValue = 0;
}
else if ( status == l_False )
{
// printf( "The problem is UNSATISFIABLE.\n" );
RetValue = 1;
}
else
assert( 0 );
// Abc_Print( 1, "The number of conflicts = %6d. ", (int)pSat->stats.conflicts );
// Abc_PrintTime( 1, "Solving time", Abc_Clock() - clk );
// if the problem is SAT, get the counterexample
if ( status == l_True )
{
pMan->pData = Sat_Solver2GetModel( pSat, vCiIds->pArray, vCiIds->nSize );
}
// free the sat_solver2
if ( fVerbose )
Sat_Solver2PrintStats( stdout, pSat );
//sat_solver2_store_write( pSat, "trace.cnf" );
//sat_solver2_store_free( pSat );
sat_solver2_delete( pSat );
Vec_IntFree( vCiIds );
return RetValue;
}
else
{
sat_solver * pSat;
Cnf_Dat_t * pCnf;
int status, RetValue = 0;
abctime clk = Abc_Clock();
Vec_Int_t * vCiIds;
assert( Aig_ManRegNum(pMan) == 0 );
pMan->pData = NULL;
// derive CNF
pCnf = Cnf_Derive( pMan, Aig_ManCoNum(pMan) );
// pCnf = Cnf_DeriveSimple( pMan, Aig_ManCoNum(pMan) );
if ( fFlipBits )
Cnf_DataTranformPolarity( pCnf, 0 );
if ( fVerbose )
{
printf( "CNF stats: Vars = %6d. Clauses = %7d. Literals = %8d. ", pCnf->nVars, pCnf->nClauses, pCnf->nLiterals );
Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
}
// convert into SAT solver
pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 );
if ( pSat == NULL )
{
Cnf_DataFree( pCnf );
return 1;
}
if ( nLearnedStart )
pSat->nLearntStart = pSat->nLearntMax = nLearnedStart;
if ( nLearnedDelta )
pSat->nLearntDelta = nLearnedDelta;
if ( nLearnedPerce )
pSat->nLearntRatio = nLearnedPerce;
if ( fVerbose )
pSat->fVerbose = fVerbose;
if ( fAndOuts )
{
// assert each output independently
if ( !Cnf_DataWriteAndClauses( pSat, pCnf ) )
{
sat_solver_delete( pSat );
Cnf_DataFree( pCnf );
return 1;
}
}
else
{
// add the OR clause for the outputs
if ( !Cnf_DataWriteOrClause( pSat, pCnf ) )
{
sat_solver_delete( pSat );
Cnf_DataFree( pCnf );
return 1;
}
}
vCiIds = Cnf_DataCollectPiSatNums( pCnf, pMan );
Cnf_DataFree( pCnf );
// printf( "Created SAT problem with %d variable and %d clauses. ", sat_solver_nvars(pSat), sat_solver_nclauses(pSat) );
// ABC_PRT( "Time", Abc_Clock() - clk );
// simplify the problem
clk = Abc_Clock();
status = sat_solver_simplify(pSat);
// printf( "Simplified the problem to %d variables and %d clauses. ", sat_solver_nvars(pSat), sat_solver_nclauses(pSat) );
// ABC_PRT( "Time", Abc_Clock() - clk );
if ( status == 0 )
{
Vec_IntFree( vCiIds );
sat_solver_delete( pSat );
// printf( "The problem is UNSATISFIABLE after simplification.\n" );
return 1;
}
// solve the miter
clk = Abc_Clock();
// if ( fVerbose )
// pSat->verbosity = 1;
status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)nConfLimit, (ABC_INT64_T)nInsLimit, (ABC_INT64_T)0, (ABC_INT64_T)0 );
if ( status == l_Undef )
{
// printf( "The problem timed out.\n" );
RetValue = -1;
}
else if ( status == l_True )
{
// printf( "The problem is SATISFIABLE.\n" );
RetValue = 0;
}
else if ( status == l_False )
{
// printf( "The problem is UNSATISFIABLE.\n" );
RetValue = 1;
}
else
assert( 0 );
// Abc_Print( 1, "The number of conflicts = %6d. ", (int)pSat->stats.conflicts );
// Abc_PrintTime( 1, "Solving time", Abc_Clock() - clk );
// if the problem is SAT, get the counterexample
if ( status == l_True )
{
pMan->pData = Sat_SolverGetModel( pSat, vCiIds->pArray, vCiIds->nSize );
}
// free the sat_solver
if ( fVerbose )
Sat_SolverPrintStats( stdout, pSat );
//sat_solver_store_write( pSat, "trace.cnf" );
//sat_solver_store_free( pSat );
sat_solver_delete( pSat );
Vec_IntFree( vCiIds );
return RetValue;
}
}
/**Function*************************************************************
Synopsis [Recognizes what nodes are inputs of the EXOR.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Aig_ManCountXors( Aig_Man_t * p )
{
Aig_Obj_t * pObj, * pFan0, * pFan1;
int i, Counter = 0;
Aig_ManForEachNode( p, pObj, i )
if ( Aig_ObjIsMuxType(pObj) && Aig_ObjRecognizeExor(pObj, &pFan0, &pFan1) )
Counter++;
return Counter;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Fra_FraigCec( Aig_Man_t ** ppAig, int nConfLimit, int fVerbose )
{
int nBTLimitStart = 300; // starting SAT run
int nBTLimitFirst = 2; // first fraiging iteration
int nBTLimitLast = nConfLimit; // the last-gasp SAT run
Fra_Par_t Params, * pParams = &Params;
Aig_Man_t * pAig = *ppAig, * pTemp;
int i, RetValue;
abctime clk;
// report the original miter
if ( fVerbose )
{
printf( "Original miter: Nodes = %6d.\n", Aig_ManNodeNum(pAig) );
}
RetValue = Fra_FraigMiterStatus( pAig );
// assert( RetValue == -1 );
if ( RetValue == 0 )
{
pAig->pData = ABC_ALLOC( int, Aig_ManCiNum(pAig) );
memset( pAig->pData, 0, sizeof(int) * Aig_ManCiNum(pAig) );
return RetValue;
}
// if SAT only, solve without iteration
clk = Abc_Clock();
RetValue = Fra_FraigSat( pAig, (ABC_INT64_T)2*nBTLimitStart, (ABC_INT64_T)0, 0, 0, 0, 1, 0, 0, 0 );
if ( fVerbose )
{
printf( "Initial SAT: Nodes = %6d. ", Aig_ManNodeNum(pAig) );
ABC_PRT( "Time", Abc_Clock() - clk );
}
if ( RetValue >= 0 )
return RetValue;
// duplicate the AIG
clk = Abc_Clock();
pAig = Dar_ManRwsat( pTemp = pAig, 1, 0 );
Aig_ManStop( pTemp );
if ( fVerbose )
{
printf( "Rewriting: Nodes = %6d. ", Aig_ManNodeNum(pAig) );
ABC_PRT( "Time", Abc_Clock() - clk );
}
// perform the loop
Fra_ParamsDefault( pParams );
pParams->nBTLimitNode = nBTLimitFirst;
pParams->nBTLimitMiter = nBTLimitStart;
pParams->fDontShowBar = 1;
pParams->fProve = 1;
for ( i = 0; i < 6; i++ )
{
//printf( "Running fraiging with %d BTnode and %d BTmiter.\n", pParams->nBTLimitNode, pParams->nBTLimitMiter );
// try XOR balancing
if ( Aig_ManCountXors(pAig) * 30 > Aig_ManNodeNum(pAig) + 300 )
{
clk = Abc_Clock();
pAig = Dar_ManBalanceXor( pTemp = pAig, 1, 0, 0 );
Aig_ManStop( pTemp );
if ( fVerbose )
{
printf( "Balance-X: Nodes = %6d. ", Aig_ManNodeNum(pAig) );
ABC_PRT( "Time", Abc_Clock() - clk );
}
}
// run fraiging
clk = Abc_Clock();
pAig = Fra_FraigPerform( pTemp = pAig, pParams );
Aig_ManStop( pTemp );
if ( fVerbose )
{
printf( "Fraiging (i=%d): Nodes = %6d. ", i+1, Aig_ManNodeNum(pAig) );
ABC_PRT( "Time", Abc_Clock() - clk );
}
// check the miter status
RetValue = Fra_FraigMiterStatus( pAig );
if ( RetValue >= 0 )
break;
// perform rewriting
clk = Abc_Clock();
pAig = Dar_ManRewriteDefault( pTemp = pAig );
Aig_ManStop( pTemp );
if ( fVerbose )
{
printf( "Rewriting: Nodes = %6d. ", Aig_ManNodeNum(pAig) );
ABC_PRT( "Time", Abc_Clock() - clk );
}
// check the miter status
RetValue = Fra_FraigMiterStatus( pAig );
if ( RetValue >= 0 )
break;
// try simulation
// set the parameters for the next run
pParams->nBTLimitNode = 8 * pParams->nBTLimitNode;
pParams->nBTLimitMiter = 2 * pParams->nBTLimitMiter;
}
// if still unsolved try last gasp
if ( RetValue == -1 )
{
clk = Abc_Clock();
RetValue = Fra_FraigSat( pAig, (ABC_INT64_T)nBTLimitLast, (ABC_INT64_T)0, 0, 0, 0, 1, 0, 0, 0 );
if ( fVerbose )
{
printf( "Final SAT: Nodes = %6d. ", Aig_ManNodeNum(pAig) );
ABC_PRT( "Time", Abc_Clock() - clk );
}
}
*ppAig = pAig;
return RetValue;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Fra_FraigCecPartitioned( Aig_Man_t * pMan1, Aig_Man_t * pMan2, int nConfLimit, int nPartSize, int fSmart, int fVerbose )
{
Aig_Man_t * pAig;
Vec_Ptr_t * vParts;
int i, RetValue = 1, nOutputs;
// create partitions
vParts = Aig_ManMiterPartitioned( pMan1, pMan2, nPartSize, fSmart );
// solve the partitions
nOutputs = -1;
Vec_PtrForEachEntry( Aig_Man_t *, vParts, pAig, i )
{
nOutputs++;
if ( fVerbose )
{
printf( "Verifying part %4d (out of %4d) PI = %5d. PO = %5d. And = %6d. Lev = %4d.\r",
i+1, Vec_PtrSize(vParts), Aig_ManCiNum(pAig), Aig_ManCoNum(pAig),
Aig_ManNodeNum(pAig), Aig_ManLevelNum(pAig) );
fflush( stdout );
}
RetValue = Fra_FraigMiterStatus( pAig );
if ( RetValue == 1 )
continue;
if ( RetValue == 0 )
break;
RetValue = Fra_FraigCec( &pAig, nConfLimit, 0 );
Vec_PtrWriteEntry( vParts, i, pAig );
if ( RetValue == 1 )
continue;
if ( RetValue == 0 )
break;
break;
}
// clear the result
if ( fVerbose )
{
printf( " \r" );
fflush( stdout );
}
// report the timeout
if ( RetValue == -1 )
{
printf( "Timed out after verifying %d partitions (out of %d).\n", nOutputs, Vec_PtrSize(vParts) );
fflush( stdout );
}
// free intermediate results
Vec_PtrForEachEntry( Aig_Man_t *, vParts, pAig, i )
Aig_ManStop( pAig );
Vec_PtrFree( vParts );
return RetValue;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Fra_FraigCecTop( Aig_Man_t * pMan1, Aig_Man_t * pMan2, int nConfLimit, int nPartSize, int fSmart, int fVerbose )
{
Aig_Man_t * pTemp;
//Abc_NtkDarCec( pNtk1, pNtk2, fPartition, fVerbose );
int RetValue;
abctime clkTotal = Abc_Clock();
if ( Aig_ManCiNum(pMan1) != Aig_ManCiNum(pMan1) )
{
printf( "Abc_CommandAbc8Cec(): Miters have different number of PIs.\n" );
return 0;
}
if ( Aig_ManCoNum(pMan1) != Aig_ManCoNum(pMan1) )
{
printf( "Abc_CommandAbc8Cec(): Miters have different number of POs.\n" );
return 0;
}
assert( Aig_ManCiNum(pMan1) == Aig_ManCiNum(pMan1) );
assert( Aig_ManCoNum(pMan1) == Aig_ManCoNum(pMan1) );
// make sure that the first miter has more nodes
if ( Aig_ManNodeNum(pMan1) < Aig_ManNodeNum(pMan2) )
{
pTemp = pMan1;
pMan1 = pMan2;
pMan2 = pTemp;
}
assert( Aig_ManNodeNum(pMan1) >= Aig_ManNodeNum(pMan2) );
if ( nPartSize )
RetValue = Fra_FraigCecPartitioned( pMan1, pMan2, nConfLimit, nPartSize, fSmart, fVerbose );
else // no partitioning
RetValue = Fra_FraigCecPartitioned( pMan1, pMan2, nConfLimit, Aig_ManCoNum(pMan1), 0, fVerbose );
// report the miter
if ( RetValue == 1 )
{
printf( "Networks are equivalent. " );
ABC_PRT( "Time", Abc_Clock() - clkTotal );
}
else if ( RetValue == 0 )
{
printf( "Networks are NOT EQUIVALENT. " );
ABC_PRT( "Time", Abc_Clock() - clkTotal );
}
else
{
printf( "Networks are UNDECIDED. " );
ABC_PRT( "Time", Abc_Clock() - clkTotal );
}
fflush( stdout );
return RetValue;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END