blob: cb41dc5ef9ba16a9f6633efa5a750079ea38561c [file] [log] [blame]
/**CFile****************************************************************
FileName [fraClaus.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [New FRAIG package.]
Synopsis [Induction with clause strengthening.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 30, 2007.]
Revision [$Id: fraClau.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $]
***********************************************************************/
#include "fra.h"
#include "sat/cnf/cnf.h"
#include "sat/bsat/satSolver.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
typedef struct Clu_Man_t_ Clu_Man_t;
struct Clu_Man_t_
{
// parameters
int nFrames; // the K of the K-step induction
int nPref; // the number of timeframes to skip
int nClausesMax; // the max number of 4-clauses to consider
int nLutSize; // the max cut size
int nLevels; // the number of levels for cut computation
int nCutsMax; // the maximum number of cuts to compute at a node
int nBatches; // the number of clause batches to use
int fStepUp; // increase cut size for each batch
int fTarget; // tries to prove the property
int fVerbose;
int fVeryVerbose;
// internal parameters
int nSimWords; // the number of simulation words
int nSimWordsPref; // the number of simulation words in the prefix
int nSimFrames; // the number of frames to simulate
int nBTLimit; // the largest number of backtracks (0 = infinite)
// the network
Aig_Man_t * pAig;
// SAT solvers
sat_solver * pSatMain;
sat_solver * pSatBmc;
// CNF for the test solver
Cnf_Dat_t * pCnf;
int fFail;
int fFiltering;
int fNothingNew;
// clauses
Vec_Int_t * vLits;
Vec_Int_t * vClauses;
Vec_Int_t * vCosts;
int nClauses;
int nCuts;
int nOneHots;
int nOneHotsProven;
// clauses proven
Vec_Int_t * vLitsProven;
Vec_Int_t * vClausesProven;
// counter-examples
Vec_Ptr_t * vCexes;
int nCexes;
int nCexesAlloc;
};
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Runs the SAT solver on the problem.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Fra_ClausRunBmc( Clu_Man_t * p )
{
Aig_Obj_t * pObj;
int Lits[2], nLitsTot, RetValue, i;
// set the output literals
nLitsTot = 2 * p->pCnf->nVars;
pObj = Aig_ManCo(p->pAig, 0);
for ( i = 0; i < p->nPref + p->nFrames; i++ )
{
Lits[0] = i * nLitsTot + toLitCond( p->pCnf->pVarNums[pObj->Id], 0 );
RetValue = sat_solver_solve( p->pSatBmc, Lits, Lits + 1, (ABC_INT64_T)p->nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
if ( RetValue != l_False )
return 0;
}
return 1;
}
/**Function*************************************************************
Synopsis [Runs the SAT solver on the problem.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Fra_ClausRunSat( Clu_Man_t * p )
{
Aig_Obj_t * pObj;
int * pLits;
int i, RetValue;
pLits = ABC_ALLOC( int, p->nFrames + 1 );
// set the output literals
pObj = Aig_ManCo(p->pAig, 0);
for ( i = 0; i <= p->nFrames; i++ )
pLits[i] = i * 2 * p->pCnf->nVars + toLitCond( p->pCnf->pVarNums[pObj->Id], i != p->nFrames );
// try to solve the problem
RetValue = sat_solver_solve( p->pSatMain, pLits, pLits + p->nFrames + 1, (ABC_INT64_T)p->nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
ABC_FREE( pLits );
if ( RetValue == l_False )
return 1;
// get the counter-example
assert( RetValue == l_True );
return 0;
}
/**Function*************************************************************
Synopsis [Runs the SAT solver on the problem.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Fra_ClausRunSat0( Clu_Man_t * p )
{
Aig_Obj_t * pObj;
int Lits[2], RetValue;
pObj = Aig_ManCo(p->pAig, 0);
Lits[0] = toLitCond( p->pCnf->pVarNums[pObj->Id], 0 );
RetValue = sat_solver_solve( p->pSatMain, Lits, Lits + 1, (ABC_INT64_T)p->nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
if ( RetValue == l_False )
return 1;
return 0;
}
/**Function*************************************************************
Synopsis [Return combinations appearing in the cut.]
Description [This procedure is taken from "Hacker's Delight" by H.S.Warren.]
SideEffects []
SeeAlso []
***********************************************************************/
void transpose32a( unsigned a[32] )
{
int j, k;
unsigned long m, t;
for ( j = 16, m = 0x0000FFFF; j; j >>= 1, m ^= m << j )
{
for ( k = 0; k < 32; k = ((k | j) + 1) & ~j )
{
t = (a[k] ^ (a[k|j] >> j)) & m;
a[k] ^= t;
a[k|j] ^= (t << j);
}
}
}
/**Function*************************************************************
Synopsis [Return combinations appearing in the cut.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Fra_ClausProcessClausesCut( Clu_Man_t * p, Fra_Sml_t * pSimMan, Dar_Cut_t * pCut, int * pScores )
{
unsigned Matrix[32];
unsigned * pSims[16], uWord;
int nSeries, i, k, j;
int nWordsForSim = pSimMan->nWordsTotal - p->nSimWordsPref;
// compute parameters
assert( pCut->nLeaves > 1 && pCut->nLeaves < 5 );
assert( nWordsForSim % 8 == 0 );
// get parameters
for ( i = 0; i < (int)pCut->nLeaves; i++ )
pSims[i] = Fra_ObjSim( pSimMan, pCut->pLeaves[i] ) + p->nSimWordsPref;
// add combinational patterns
memset( pScores, 0, sizeof(int) * 16 );
nSeries = nWordsForSim / 8;
for ( i = 0; i < nSeries; i++ )
{
memset( Matrix, 0, sizeof(unsigned) * 32 );
for ( k = 0; k < 8; k++ )
for ( j = 0; j < (int)pCut->nLeaves; j++ )
Matrix[31-(k*4+j)] = pSims[j][i*8+k];
transpose32a( Matrix );
for ( k = 0; k < 32; k++ )
for ( j = 0, uWord = Matrix[k]; j < 8; j++, uWord >>= 4 )
pScores[uWord & 0xF]++;
}
// collect patterns
uWord = 0;
for ( i = 0; i < 16; i++ )
if ( pScores[i] )
uWord |= (1 << i);
// Extra_PrintBinary( stdout, &uWord, 16 ); printf( "\n" );
return (int)uWord;
}
/**Function*************************************************************
Synopsis [Return combinations appearing in the cut.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Fra_ClausProcessClausesCut2( Clu_Man_t * p, Fra_Sml_t * pSimMan, Dar_Cut_t * pCut, int * pScores )
{
unsigned * pSims[16], uWord;
int iMint, i, k, b;
int nWordsForSim = pSimMan->nWordsTotal - p->nSimWordsPref;
// compute parameters
assert( pCut->nLeaves > 1 && pCut->nLeaves < 5 );
assert( nWordsForSim % 8 == 0 );
// get parameters
for ( i = 0; i < (int)pCut->nLeaves; i++ )
pSims[i] = Fra_ObjSim( pSimMan, pCut->pLeaves[i] ) + p->nSimWordsPref;
// add combinational patterns
memset( pScores, 0, sizeof(int) * 16 );
for ( i = 0; i < nWordsForSim; i++ )
for ( k = 0; k < 32; k++ )
{
iMint = 0;
for ( b = 0; b < (int)pCut->nLeaves; b++ )
if ( pSims[b][i] & (1 << k) )
iMint |= (1 << b);
pScores[iMint]++;
}
// collect patterns
uWord = 0;
for ( i = 0; i < 16; i++ )
if ( pScores[i] )
uWord |= (1 << i);
// Extra_PrintBinary( stdout, &uWord, 16 ); printf( "\n" );
return (int)uWord;
}
/**Function*************************************************************
Synopsis [Return the number of combinations appearing in the cut.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Fra_ClausProcessClausesCut3( Clu_Man_t * p, Fra_Sml_t * pSimMan, Aig_Cut_t * pCut, int * pScores )
{
unsigned Matrix[32];
unsigned * pSims[16], uWord;
int iMint, i, j, k, b, nMints, nSeries;
int nWordsForSim = pSimMan->nWordsTotal - p->nSimWordsPref;
// compute parameters
assert( pCut->nFanins > 1 && pCut->nFanins < 17 );
assert( nWordsForSim % 8 == 0 );
// get parameters
for ( i = 0; i < (int)pCut->nFanins; i++ )
pSims[i] = Fra_ObjSim( pSimMan, pCut->pFanins[i] ) + p->nSimWordsPref;
// add combinational patterns
nMints = (1 << pCut->nFanins);
memset( pScores, 0, sizeof(int) * nMints );
if ( pCut->nLeafMax == 4 )
{
// convert the simulation patterns
nSeries = nWordsForSim / 8;
for ( i = 0; i < nSeries; i++ )
{
memset( Matrix, 0, sizeof(unsigned) * 32 );
for ( k = 0; k < 8; k++ )
for ( j = 0; j < (int)pCut->nFanins; j++ )
Matrix[31-(k*4+j)] = pSims[j][i*8+k];
transpose32a( Matrix );
for ( k = 0; k < 32; k++ )
for ( j = 0, uWord = Matrix[k]; j < 8; j++, uWord >>= 4 )
pScores[uWord & 0xF]++;
}
}
else
{
// go through the simulation patterns
for ( i = 0; i < nWordsForSim; i++ )
for ( k = 0; k < 32; k++ )
{
iMint = 0;
for ( b = 0; b < (int)pCut->nFanins; b++ )
if ( pSims[b][i] & (1 << k) )
iMint |= (1 << b);
pScores[iMint]++;
}
}
}
/**Function*************************************************************
Synopsis [Returns the cut-off cost.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Fra_ClausSelectClauses( Clu_Man_t * p )
{
int * pCostCount, nClauCount, Cost, CostMax, i, c;
assert( Vec_IntSize(p->vClauses) > p->nClausesMax );
// count how many implications have each cost
CostMax = p->nSimWords * 32 + 1;
pCostCount = ABC_ALLOC( int, CostMax );
memset( pCostCount, 0, sizeof(int) * CostMax );
Vec_IntForEachEntry( p->vCosts, Cost, i )
{
if ( Cost == -1 )
continue;
assert( Cost < CostMax );
pCostCount[ Cost ]++;
}
assert( pCostCount[0] == 0 );
// select the bound on the cost (above this bound, implication will be included)
nClauCount = 0;
for ( c = CostMax - 1; c > 0; c-- )
{
assert( pCostCount[c] >= 0 );
nClauCount += pCostCount[c];
if ( nClauCount >= p->nClausesMax )
break;
}
// collect implications with the given costs
nClauCount = 0;
Vec_IntForEachEntry( p->vCosts, Cost, i )
{
if ( Cost >= c && nClauCount < p->nClausesMax )
{
nClauCount++;
continue;
}
Vec_IntWriteEntry( p->vCosts, i, -1 );
}
ABC_FREE( pCostCount );
p->nClauses = nClauCount;
if ( p->fVerbose )
printf( "Selected %d clauses. Cost range: [%d < %d < %d]\n", nClauCount, 1, c, CostMax );
return c;
}
/**Function*************************************************************
Synopsis [Processes the clauses.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Fra_ClausRecordClause( Clu_Man_t * p, Dar_Cut_t * pCut, int iMint, int Cost )
{
int i;
for ( i = 0; i < (int)pCut->nLeaves; i++ )
Vec_IntPush( p->vLits, toLitCond( p->pCnf->pVarNums[pCut->pLeaves[i]], (iMint&(1<<i)) ) );
Vec_IntPush( p->vClauses, Vec_IntSize(p->vLits) );
Vec_IntPush( p->vCosts, Cost );
}
/**Function*************************************************************
Synopsis [Processes the clauses.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Fra_ClausRecordClause2( Clu_Man_t * p, Aig_Cut_t * pCut, int iMint, int Cost )
{
int i;
for ( i = 0; i < (int)pCut->nFanins; i++ )
Vec_IntPush( p->vLits, toLitCond( p->pCnf->pVarNums[pCut->pFanins[i]], (iMint&(1<<i)) ) );
Vec_IntPush( p->vClauses, Vec_IntSize(p->vLits) );
Vec_IntPush( p->vCosts, Cost );
}
/**Function*************************************************************
Synopsis [Returns 1 if simulation info is composed of all zeros.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Fra_ClausSmlNodeIsConst( Fra_Sml_t * pSeq, Aig_Obj_t * pObj )
{
unsigned * pSims;
int i;
pSims = Fra_ObjSim(pSeq, pObj->Id);
for ( i = pSeq->nWordsPref; i < pSeq->nWordsTotal; i++ )
if ( pSims[i] )
return 0;
return 1;
}
/**Function*************************************************************
Synopsis [Returns 1 if implications holds.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Fra_ClausSmlNodesAreImp( Fra_Sml_t * pSeq, Aig_Obj_t * pObj1, Aig_Obj_t * pObj2 )
{
unsigned * pSimL, * pSimR;
int k;
pSimL = Fra_ObjSim(pSeq, pObj1->Id);
pSimR = Fra_ObjSim(pSeq, pObj2->Id);
for ( k = pSeq->nWordsPref; k < pSeq->nWordsTotal; k++ )
if ( pSimL[k] & ~pSimR[k] ) // !(Obj1 -> Obj2)
return 0;
return 1;
}
/**Function*************************************************************
Synopsis [Returns 1 if implications holds.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Fra_ClausSmlNodesAreImpC( Fra_Sml_t * pSeq, Aig_Obj_t * pObj1, Aig_Obj_t * pObj2 )
{
unsigned * pSimL, * pSimR;
int k;
pSimL = Fra_ObjSim(pSeq, pObj1->Id);
pSimR = Fra_ObjSim(pSeq, pObj2->Id);
for ( k = pSeq->nWordsPref; k < pSeq->nWordsTotal; k++ )
if ( pSimL[k] & pSimR[k] )
return 0;
return 1;
}
/**Function*************************************************************
Synopsis [Processes the clauses.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Fra_ClausCollectLatchClauses( Clu_Man_t * p, Fra_Sml_t * pSeq )
{
Aig_Obj_t * pObj1, * pObj2;
unsigned * pSims1, * pSims2;
int CostMax, i, k, nCountConst, nCountImps;
nCountConst = nCountImps = 0;
CostMax = p->nSimWords * 32;
/*
// add the property
{
Aig_Obj_t * pObj;
int Lits[1];
pObj = Aig_ManCo( p->pAig, 0 );
Lits[0] = toLitCond( p->pCnf->pVarNums[pObj->Id], 1 );
Vec_IntPush( p->vLits, Lits[0] );
Vec_IntPush( p->vClauses, Vec_IntSize(p->vLits) );
Vec_IntPush( p->vCosts, CostMax );
nCountConst++;
// printf( "Added the target property to the set of clauses to be inductively checked.\n" );
}
*/
pSeq->nWordsPref = p->nSimWordsPref;
Aig_ManForEachLoSeq( p->pAig, pObj1, i )
{
pSims1 = Fra_ObjSim( pSeq, pObj1->Id );
if ( Fra_ClausSmlNodeIsConst( pSeq, pObj1 ) )
{
Vec_IntPush( p->vLits, toLitCond( p->pCnf->pVarNums[pObj1->Id], 1 ) );
Vec_IntPush( p->vClauses, Vec_IntSize(p->vLits) );
Vec_IntPush( p->vCosts, CostMax );
nCountConst++;
continue;
}
Aig_ManForEachLoSeq( p->pAig, pObj2, k )
{
pSims2 = Fra_ObjSim( pSeq, pObj2->Id );
if ( Fra_ClausSmlNodesAreImp( pSeq, pObj1, pObj2 ) )
{
Vec_IntPush( p->vLits, toLitCond( p->pCnf->pVarNums[pObj1->Id], 1 ) );
Vec_IntPush( p->vLits, toLitCond( p->pCnf->pVarNums[pObj2->Id], 0 ) );
Vec_IntPush( p->vClauses, Vec_IntSize(p->vLits) );
Vec_IntPush( p->vCosts, CostMax );
nCountImps++;
continue;
}
if ( Fra_ClausSmlNodesAreImp( pSeq, pObj2, pObj1 ) )
{
Vec_IntPush( p->vLits, toLitCond( p->pCnf->pVarNums[pObj2->Id], 1 ) );
Vec_IntPush( p->vLits, toLitCond( p->pCnf->pVarNums[pObj1->Id], 0 ) );
Vec_IntPush( p->vClauses, Vec_IntSize(p->vLits) );
Vec_IntPush( p->vCosts, CostMax );
nCountImps++;
continue;
}
if ( Fra_ClausSmlNodesAreImpC( pSeq, pObj1, pObj2 ) )
{
Vec_IntPush( p->vLits, toLitCond( p->pCnf->pVarNums[pObj1->Id], 1 ) );
Vec_IntPush( p->vLits, toLitCond( p->pCnf->pVarNums[pObj2->Id], 1 ) );
Vec_IntPush( p->vClauses, Vec_IntSize(p->vLits) );
Vec_IntPush( p->vCosts, CostMax );
nCountImps++;
continue;
}
}
if ( nCountConst + nCountImps > p->nClausesMax / 2 )
break;
}
pSeq->nWordsPref = 0;
if ( p->fVerbose )
printf( "Collected %d register constants and %d one-hotness implications.\n", nCountConst, nCountImps );
p->nOneHots = nCountConst + nCountImps;
p->nOneHotsProven = 0;
return 0;
}
/**Function*************************************************************
Synopsis [Processes the clauses.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Fra_ClausProcessClauses( Clu_Man_t * p, int fRefs )
{
Aig_MmFixed_t * pMemCuts;
// Aig_ManCut_t * pManCut;
Fra_Sml_t * pComb, * pSeq;
Aig_Obj_t * pObj;
Dar_Cut_t * pCut;
int Scores[16], uScores, i, k, j, nCuts = 0;
abctime clk;
// simulate the AIG
clk = Abc_Clock();
// srand( 0xAABBAABB );
Aig_ManRandom(1);
pSeq = Fra_SmlSimulateSeq( p->pAig, 0, p->nPref + p->nSimFrames, p->nSimWords/p->nSimFrames, 1 );
if ( p->fTarget && pSeq->fNonConstOut )
{
printf( "Property failed after sequential simulation!\n" );
Fra_SmlStop( pSeq );
return 0;
}
if ( p->fVerbose )
{
ABC_PRT( "Sim-seq", Abc_Clock() - clk );
}
clk = Abc_Clock();
if ( fRefs )
{
Fra_ClausCollectLatchClauses( p, pSeq );
if ( p->fVerbose )
{
ABC_PRT( "Lat-cla", Abc_Clock() - clk );
}
}
// generate cuts for all nodes, assign cost, and find best cuts
clk = Abc_Clock();
pMemCuts = Dar_ManComputeCuts( p->pAig, 10, 0, 1 );
// pManCut = Aig_ComputeCuts( p->pAig, 10, 4, 0, 1 );
if ( p->fVerbose )
{
ABC_PRT( "Cuts ", Abc_Clock() - clk );
}
// collect sequential info for each cut
clk = Abc_Clock();
Aig_ManForEachNode( p->pAig, pObj, i )
Dar_ObjForEachCut( pObj, pCut, k )
if ( pCut->nLeaves > 1 )
{
pCut->uTruth = Fra_ClausProcessClausesCut( p, pSeq, pCut, Scores );
// uScores = Fra_ClausProcessClausesCut2( p, pSeq, pCut, Scores );
// if ( uScores != pCut->uTruth )
// {
// int x = 0;
// }
}
if ( p->fVerbose )
{
ABC_PRT( "Infoseq", Abc_Clock() - clk );
}
Fra_SmlStop( pSeq );
// perform combinational simulation
clk = Abc_Clock();
// srand( 0xAABBAABB );
Aig_ManRandom(1);
pComb = Fra_SmlSimulateComb( p->pAig, p->nSimWords + p->nSimWordsPref, 0 );
if ( p->fVerbose )
{
ABC_PRT( "Sim-cmb", Abc_Clock() - clk );
}
// collect combinational info for each cut
clk = Abc_Clock();
Aig_ManForEachNode( p->pAig, pObj, i )
Dar_ObjForEachCut( pObj, pCut, k )
if ( pCut->nLeaves > 1 )
{
nCuts++;
uScores = Fra_ClausProcessClausesCut( p, pComb, pCut, Scores );
uScores &= ~pCut->uTruth; pCut->uTruth = 0;
if ( uScores == 0 )
continue;
// write the clauses
for ( j = 0; j < (1<<pCut->nLeaves); j++ )
if ( uScores & (1 << j) )
Fra_ClausRecordClause( p, pCut, j, Scores[j] );
}
Fra_SmlStop( pComb );
Aig_MmFixedStop( pMemCuts, 0 );
// Aig_ManCutStop( pManCut );
if ( p->fVerbose )
{
ABC_PRT( "Infocmb", Abc_Clock() - clk );
}
if ( p->fVerbose )
printf( "Node = %5d. Non-triv cuts = %7d. Clauses = %6d. Clause per cut = %6.2f.\n",
Aig_ManNodeNum(p->pAig), nCuts, Vec_IntSize(p->vClauses), 1.0*Vec_IntSize(p->vClauses)/nCuts );
if ( Vec_IntSize(p->vClauses) > p->nClausesMax )
Fra_ClausSelectClauses( p );
else
p->nClauses = Vec_IntSize( p->vClauses );
return 1;
}
/**Function*************************************************************
Synopsis [Processes the clauses.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Fra_ClausProcessClauses2( Clu_Man_t * p, int fRefs )
{
// Aig_MmFixed_t * pMemCuts;
Aig_ManCut_t * pManCut;
Fra_Sml_t * pComb, * pSeq;
Aig_Obj_t * pObj;
Aig_Cut_t * pCut;
int i, k, j, nCuts = 0;
abctime clk;
int ScoresSeq[1<<12], ScoresComb[1<<12];
assert( p->nLutSize < 13 );
// simulate the AIG
clk = Abc_Clock();
// srand( 0xAABBAABB );
Aig_ManRandom(1);
pSeq = Fra_SmlSimulateSeq( p->pAig, 0, p->nPref + p->nSimFrames, p->nSimWords/p->nSimFrames, 1 );
if ( p->fTarget && pSeq->fNonConstOut )
{
printf( "Property failed after sequential simulation!\n" );
Fra_SmlStop( pSeq );
return 0;
}
if ( p->fVerbose )
{
//ABC_PRT( "Sim-seq", Abc_Clock() - clk );
}
// perform combinational simulation
clk = Abc_Clock();
// srand( 0xAABBAABB );
Aig_ManRandom(1);
pComb = Fra_SmlSimulateComb( p->pAig, p->nSimWords + p->nSimWordsPref, 0 );
if ( p->fVerbose )
{
//ABC_PRT( "Sim-cmb", Abc_Clock() - clk );
}
clk = Abc_Clock();
if ( fRefs )
{
Fra_ClausCollectLatchClauses( p, pSeq );
if ( p->fVerbose )
{
//ABC_PRT( "Lat-cla", Abc_Clock() - clk );
}
}
// generate cuts for all nodes, assign cost, and find best cuts
clk = Abc_Clock();
// pMemCuts = Dar_ManComputeCuts( p->pAig, 10, 0, 1 );
pManCut = Aig_ComputeCuts( p->pAig, p->nCutsMax, p->nLutSize, 0, p->fVerbose );
if ( p->fVerbose )
{
//ABC_PRT( "Cuts ", Abc_Clock() - clk );
}
// collect combinational info for each cut
clk = Abc_Clock();
Aig_ManForEachNode( p->pAig, pObj, i )
{
if ( pObj->Level > (unsigned)p->nLevels )
continue;
Aig_ObjForEachCut( pManCut, pObj, pCut, k )
if ( pCut->nFanins > 1 )
{
nCuts++;
Fra_ClausProcessClausesCut3( p, pSeq, pCut, ScoresSeq );
Fra_ClausProcessClausesCut3( p, pComb, pCut, ScoresComb );
// write the clauses
for ( j = 0; j < (1<<pCut->nFanins); j++ )
if ( ScoresComb[j] != 0 && ScoresSeq[j] == 0 )
Fra_ClausRecordClause2( p, pCut, j, ScoresComb[j] );
}
}
Fra_SmlStop( pSeq );
Fra_SmlStop( pComb );
p->nCuts = nCuts;
// Aig_MmFixedStop( pMemCuts, 0 );
Aig_ManCutStop( pManCut );
p->pAig->pManCuts = NULL;
if ( p->fVerbose )
{
printf( "Node = %5d. Cuts = %7d. Clauses = %6d. Clause/cut = %6.2f.\n",
Aig_ManNodeNum(p->pAig), nCuts, Vec_IntSize(p->vClauses), 1.0*Vec_IntSize(p->vClauses)/nCuts );
ABC_PRT( "Processing sim-info to find candidate clauses (unoptimized)", Abc_Clock() - clk );
}
// filter out clauses that are contained in the already proven clauses
assert( p->nClauses == 0 );
p->nClauses = Vec_IntSize( p->vClauses );
if ( Vec_IntSize( p->vClausesProven ) > 0 )
{
int RetValue, k, Beg;
int End = -1; // Suppress "might be used uninitialized"
int * pStart;
// reset the solver
if ( p->pSatMain ) sat_solver_delete( p->pSatMain );
p->pSatMain = (sat_solver *)Cnf_DataWriteIntoSolver( p->pCnf, 1, 0 );
if ( p->pSatMain == NULL )
{
printf( "Error: Main solver is unsat.\n" );
return -1;
}
// add the proven clauses
Beg = 0;
pStart = Vec_IntArray(p->vLitsProven);
Vec_IntForEachEntry( p->vClausesProven, End, i )
{
assert( End - Beg <= p->nLutSize );
// add the clause to all timeframes
RetValue = sat_solver_addclause( p->pSatMain, pStart + Beg, pStart + End );
if ( RetValue == 0 )
{
printf( "Error: Solver is UNSAT after adding assumption clauses.\n" );
return -1;
}
Beg = End;
}
assert( End == Vec_IntSize(p->vLitsProven) );
// check the clauses
Beg = 0;
pStart = Vec_IntArray(p->vLits);
Vec_IntForEachEntry( p->vClauses, End, i )
{
assert( Vec_IntEntry( p->vCosts, i ) >= 0 );
assert( End - Beg <= p->nLutSize );
// check the clause
for ( k = Beg; k < End; k++ )
pStart[k] = lit_neg( pStart[k] );
RetValue = sat_solver_solve( p->pSatMain, pStart + Beg, pStart + End, (ABC_INT64_T)p->nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
for ( k = Beg; k < End; k++ )
pStart[k] = lit_neg( pStart[k] );
// the clause holds
if ( RetValue == l_False )
{
Vec_IntWriteEntry( p->vCosts, i, -1 );
p->nClauses--;
}
Beg = End;
}
assert( End == Vec_IntSize(p->vLits) );
if ( p->fVerbose )
printf( "Already proved clauses filtered out %d candidate clauses (out of %d).\n",
Vec_IntSize(p->vClauses) - p->nClauses, Vec_IntSize(p->vClauses) );
}
p->fFiltering = 0;
if ( p->nClauses > p->nClausesMax )
{
Fra_ClausSelectClauses( p );
p->fFiltering = 1;
}
return 1;
}
/**Function*************************************************************
Synopsis [Converts AIG into the SAT solver.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Fra_ClausBmcClauses( Clu_Man_t * p )
{
int * pStart, nLitsTot, RetValue, Beg, End, Counter, i, k, f;
/*
for ( i = 0; i < Vec_IntSize(p->vLits); i++ )
printf( "%d ", p->vLits->pArray[i] );
printf( "\n" );
*/
// add the clauses
Counter = 0;
// skip through the prefix variables
if ( p->nPref )
{
nLitsTot = p->nPref * 2 * p->pCnf->nVars;
for ( i = 0; i < Vec_IntSize(p->vLits); i++ )
p->vLits->pArray[i] += nLitsTot;
}
// go through the timeframes
nLitsTot = 2 * p->pCnf->nVars;
pStart = Vec_IntArray(p->vLits);
for ( f = 0; f < p->nFrames; f++ )
{
Beg = 0;
Vec_IntForEachEntry( p->vClauses, End, i )
{
if ( Vec_IntEntry( p->vCosts, i ) == -1 )
{
Beg = End;
continue;
}
assert( Vec_IntEntry( p->vCosts, i ) > 0 );
assert( End - Beg <= p->nLutSize );
for ( k = Beg; k < End; k++ )
pStart[k] = lit_neg( pStart[k] );
RetValue = sat_solver_solve( p->pSatBmc, pStart + Beg, pStart + End, (ABC_INT64_T)p->nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
for ( k = Beg; k < End; k++ )
pStart[k] = lit_neg( pStart[k] );
if ( RetValue != l_False )
{
Beg = End;
Vec_IntWriteEntry( p->vCosts, i, -1 );
Counter++;
continue;
}
/*
// add the clause
RetValue = sat_solver_addclause( p->pSatBmc, pStart + Beg, pStart + End );
// assert( RetValue == 1 );
if ( RetValue == 0 )
{
printf( "Error: Solver is UNSAT after adding BMC clauses.\n" );
return -1;
}
*/
Beg = End;
// simplify the solver
if ( p->pSatBmc->qtail != p->pSatBmc->qhead )
{
RetValue = sat_solver_simplify(p->pSatBmc);
assert( RetValue != 0 );
assert( p->pSatBmc->qtail == p->pSatBmc->qhead );
}
}
// increment literals
for ( i = 0; i < Vec_IntSize(p->vLits); i++ )
p->vLits->pArray[i] += nLitsTot;
}
// return clauses back to normal
nLitsTot = (p->nPref + p->nFrames) * nLitsTot;
for ( i = 0; i < Vec_IntSize(p->vLits); i++ )
p->vLits->pArray[i] -= nLitsTot;
/*
for ( i = 0; i < Vec_IntSize(p->vLits); i++ )
printf( "%d ", p->vLits->pArray[i] );
printf( "\n" );
*/
return Counter;
}
/**Function*************************************************************
Synopsis [Cleans simulation info.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Fra_ClausSimInfoClean( Clu_Man_t * p )
{
assert( p->pCnf->nVars <= Vec_PtrSize(p->vCexes) );
Vec_PtrCleanSimInfo( p->vCexes, 0, p->nCexesAlloc/32 );
p->nCexes = 0;
}
/**Function*************************************************************
Synopsis [Reallocs simulation info.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Fra_ClausSimInfoRealloc( Clu_Man_t * p )
{
assert( p->nCexes == p->nCexesAlloc );
Vec_PtrReallocSimInfo( p->vCexes );
Vec_PtrCleanSimInfo( p->vCexes, p->nCexesAlloc/32, 2 * p->nCexesAlloc/32 );
p->nCexesAlloc *= 2;
}
/**Function*************************************************************
Synopsis [Records simulation info.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Fra_ClausSimInfoRecord( Clu_Man_t * p, int * pModel )
{
int i;
if ( p->nCexes == p->nCexesAlloc )
Fra_ClausSimInfoRealloc( p );
assert( p->nCexes < p->nCexesAlloc );
for ( i = 0; i < p->pCnf->nVars; i++ )
{
if ( pModel[i] == l_True )
{
assert( Abc_InfoHasBit( (unsigned *)Vec_PtrEntry(p->vCexes, i), p->nCexes ) == 0 );
Abc_InfoSetBit( (unsigned *)Vec_PtrEntry(p->vCexes, i), p->nCexes );
}
}
p->nCexes++;
}
/**Function*************************************************************
Synopsis [Uses the simulation info.]
Description [Returns 1 if the simulation info disproved the clause.]
SideEffects []
SeeAlso []
***********************************************************************/
int Fra_ClausSimInfoCheck( Clu_Man_t * p, int * pLits, int nLits )
{
unsigned * pSims[16], uWord;
int nWords, iVar, i, w;
for ( i = 0; i < nLits; i++ )
{
iVar = lit_var(pLits[i]) - p->nFrames * p->pCnf->nVars;
assert( iVar > 0 && iVar < p->pCnf->nVars );
pSims[i] = (unsigned *)Vec_PtrEntry( p->vCexes, iVar );
}
nWords = p->nCexes / 32;
for ( w = 0; w < nWords; w++ )
{
uWord = ~(unsigned)0;
for ( i = 0; i < nLits; i++ )
uWord &= (lit_sign(pLits[i])? pSims[i][w] : ~pSims[i][w]);
if ( uWord )
return 1;
}
if ( p->nCexes % 32 )
{
uWord = ~(unsigned)0;
for ( i = 0; i < nLits; i++ )
uWord &= (lit_sign(pLits[i])? pSims[i][w] : ~pSims[i][w]);
if ( uWord & Abc_InfoMask( p->nCexes % 32 ) )
return 1;
}
return 0;
}
/**Function*************************************************************
Synopsis [Converts AIG into the SAT solver.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Fra_ClausInductiveClauses( Clu_Man_t * p )
{
// Aig_Obj_t * pObjLi, * pObjLo;
int * pStart, nLitsTot, RetValue, Beg, End, Counter, i, k, f, fFlag;//, Lits[2];
p->fFail = 0;
// reset the solver
if ( p->pSatMain ) sat_solver_delete( p->pSatMain );
p->pSatMain = (sat_solver *)Cnf_DataWriteIntoSolver( p->pCnf, p->nFrames+1, 0 );
if ( p->pSatMain == NULL )
{
printf( "Error: Main solver is unsat.\n" );
return -1;
}
Fra_ClausSimInfoClean( p );
/*
// check if the property holds
if ( Fra_ClausRunSat0( p ) )
printf( "Property holds without strengthening.\n" );
else
printf( "Property does not hold without strengthening.\n" );
*/
/*
// add constant registers
Aig_ManForEachLiLoSeq( p->pAig, pObjLi, pObjLo, i )
if ( Aig_ObjFanin0(pObjLi) == Aig_ManConst1(p->pAig) )
{
for ( k = 0; k < p->nFrames; k++ )
{
Lits[0] = k * 2 * p->pCnf->nVars + toLitCond( p->pCnf->pVarNums[pObjLo->Id], Aig_ObjFaninC0(pObjLi) );
RetValue = sat_solver_addclause( p->pSatMain, Lits, Lits + 1 );
if ( RetValue == 0 )
{
printf( "Error: Solver is UNSAT after adding constant-register clauses.\n" );
return -1;
}
}
}
*/
// add the proven clauses
nLitsTot = 2 * p->pCnf->nVars;
pStart = Vec_IntArray(p->vLitsProven);
for ( f = 0; f < p->nFrames; f++ )
{
Beg = 0;
Vec_IntForEachEntry( p->vClausesProven, End, i )
{
assert( End - Beg <= p->nLutSize );
// add the clause to all timeframes
RetValue = sat_solver_addclause( p->pSatMain, pStart + Beg, pStart + End );
if ( RetValue == 0 )
{
printf( "Error: Solver is UNSAT after adding assumption clauses.\n" );
return -1;
}
Beg = End;
}
// increment literals
for ( i = 0; i < Vec_IntSize(p->vLitsProven); i++ )
p->vLitsProven->pArray[i] += nLitsTot;
}
// return clauses back to normal
nLitsTot = (p->nFrames) * nLitsTot;
for ( i = 0; i < Vec_IntSize(p->vLitsProven); i++ )
p->vLitsProven->pArray[i] -= nLitsTot;
/*
// add the proven clauses
nLitsTot = 2 * p->pCnf->nVars;
pStart = Vec_IntArray(p->vLitsProven);
Beg = 0;
Vec_IntForEachEntry( p->vClausesProven, End, i )
{
assert( End - Beg <= p->nLutSize );
// add the clause to all timeframes
RetValue = sat_solver_addclause( p->pSatMain, pStart + Beg, pStart + End );
if ( RetValue == 0 )
{
printf( "Error: Solver is UNSAT after adding assumption clauses.\n" );
return -1;
}
Beg = End;
}
*/
// add the clauses
nLitsTot = 2 * p->pCnf->nVars;
pStart = Vec_IntArray(p->vLits);
for ( f = 0; f < p->nFrames; f++ )
{
Beg = 0;
Vec_IntForEachEntry( p->vClauses, End, i )
{
if ( Vec_IntEntry( p->vCosts, i ) == -1 )
{
Beg = End;
continue;
}
assert( Vec_IntEntry( p->vCosts, i ) > 0 );
assert( End - Beg <= p->nLutSize );
// add the clause to all timeframes
RetValue = sat_solver_addclause( p->pSatMain, pStart + Beg, pStart + End );
if ( RetValue == 0 )
{
printf( "Error: Solver is UNSAT after adding assumption clauses.\n" );
return -1;
}
Beg = End;
}
// increment literals
for ( i = 0; i < Vec_IntSize(p->vLits); i++ )
p->vLits->pArray[i] += nLitsTot;
}
// simplify the solver
if ( p->pSatMain->qtail != p->pSatMain->qhead )
{
RetValue = sat_solver_simplify(p->pSatMain);
assert( RetValue != 0 );
assert( p->pSatMain->qtail == p->pSatMain->qhead );
}
// check if the property holds
if ( p->fTarget )
{
if ( Fra_ClausRunSat0( p ) )
{
if ( p->fVerbose )
printf( " Property holds. " );
}
else
{
if ( p->fVerbose )
printf( " Property fails. " );
// return -2;
p->fFail = 1;
}
}
/*
// add the property for the first K frames
for ( i = 0; i < p->nFrames; i++ )
{
Aig_Obj_t * pObj;
int Lits[2];
// set the output literals
pObj = Aig_ManCo(p->pAig, 0);
Lits[0] = i * nLitsTot + toLitCond( p->pCnf->pVarNums[pObj->Id], 1 );
// add the clause
RetValue = sat_solver_addclause( p->pSatMain, Lits, Lits + 1 );
// assert( RetValue == 1 );
if ( RetValue == 0 )
{
printf( "Error: Solver is UNSAT after adding property for the first K frames.\n" );
return -1;
}
}
*/
// simplify the solver
if ( p->pSatMain->qtail != p->pSatMain->qhead )
{
RetValue = sat_solver_simplify(p->pSatMain);
assert( RetValue != 0 );
assert( p->pSatMain->qtail == p->pSatMain->qhead );
}
// check the clause in the last timeframe
Beg = 0;
Counter = 0;
Vec_IntForEachEntry( p->vClauses, End, i )
{
if ( Vec_IntEntry( p->vCosts, i ) == -1 )
{
Beg = End;
continue;
}
assert( Vec_IntEntry( p->vCosts, i ) > 0 );
assert( End - Beg <= p->nLutSize );
if ( Fra_ClausSimInfoCheck(p, pStart + Beg, End - Beg) )
{
fFlag = 1;
// printf( "s-" );
Beg = End;
Vec_IntWriteEntry( p->vCosts, i, -1 );
Counter++;
continue;
}
else
{
fFlag = 0;
// printf( "s?" );
}
for ( k = Beg; k < End; k++ )
pStart[k] = lit_neg( pStart[k] );
RetValue = sat_solver_solve( p->pSatMain, pStart + Beg, pStart + End, (ABC_INT64_T)p->nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
for ( k = Beg; k < End; k++ )
pStart[k] = lit_neg( pStart[k] );
// the problem is not solved
if ( RetValue != l_False )
{
// printf( "S- " );
// Fra_ClausSimInfoRecord( p, (int*)p->pSatMain->model.ptr + p->nFrames * p->pCnf->nVars );
Fra_ClausSimInfoRecord( p, (int*)p->pSatMain->model + p->nFrames * p->pCnf->nVars );
// RetValue = Fra_ClausSimInfoCheck(p, pStart + Beg, End - Beg);
// assert( RetValue );
Beg = End;
Vec_IntWriteEntry( p->vCosts, i, -1 );
Counter++;
continue;
}
// printf( "S+ " );
// assert( !fFlag );
/*
// add the clause
RetValue = sat_solver_addclause( p->pSatMain, pStart + Beg, pStart + End );
// assert( RetValue == 1 );
if ( RetValue == 0 )
{
printf( "Error: Solver is UNSAT after adding proved clauses.\n" );
return -1;
}
*/
Beg = End;
// simplify the solver
if ( p->pSatMain->qtail != p->pSatMain->qhead )
{
RetValue = sat_solver_simplify(p->pSatMain);
assert( RetValue != 0 );
assert( p->pSatMain->qtail == p->pSatMain->qhead );
}
}
// return clauses back to normal
nLitsTot = p->nFrames * nLitsTot;
for ( i = 0; i < Vec_IntSize(p->vLits); i++ )
p->vLits->pArray[i] -= nLitsTot;
// if ( fFail )
// return -2;
return Counter;
}
/**Function*************************************************************
Synopsis [Converts AIG into the SAT solver.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Clu_Man_t * Fra_ClausAlloc( Aig_Man_t * pAig, int nFrames, int nPref, int nClausesMax, int nLutSize, int nLevels, int nCutsMax, int nBatches, int fStepUp, int fTarget, int fVerbose, int fVeryVerbose )
{
Clu_Man_t * p;
p = ABC_ALLOC( Clu_Man_t, 1 );
memset( p, 0, sizeof(Clu_Man_t) );
p->pAig = pAig;
p->nFrames = nFrames;
p->nPref = nPref;
p->nClausesMax = nClausesMax;
p->nLutSize = nLutSize;
p->nLevels = nLevels;
p->nCutsMax = nCutsMax;
p->nBatches = nBatches;
p->fStepUp = fStepUp;
p->fTarget = fTarget;
p->fVerbose = fVerbose;
p->fVeryVerbose = fVeryVerbose;
p->nSimWords = 512;//1024;//64;
p->nSimFrames = 32;//8;//32;
p->nSimWordsPref = p->nPref*p->nSimWords/p->nSimFrames;
p->vLits = Vec_IntAlloc( 1<<14 );
p->vClauses = Vec_IntAlloc( 1<<12 );
p->vCosts = Vec_IntAlloc( 1<<12 );
p->vLitsProven = Vec_IntAlloc( 1<<14 );
p->vClausesProven= Vec_IntAlloc( 1<<12 );
p->nCexesAlloc = 1024;
p->vCexes = Vec_PtrAllocSimInfo( Aig_ManObjNumMax(p->pAig)+1, p->nCexesAlloc/32 );
Vec_PtrCleanSimInfo( p->vCexes, 0, p->nCexesAlloc/32 );
return p;
}
/**Function*************************************************************
Synopsis [Converts AIG into the SAT solver.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Fra_ClausFree( Clu_Man_t * p )
{
if ( p->vCexes ) Vec_PtrFree( p->vCexes );
if ( p->vLits ) Vec_IntFree( p->vLits );
if ( p->vClauses ) Vec_IntFree( p->vClauses );
if ( p->vLitsProven ) Vec_IntFree( p->vLitsProven );
if ( p->vClausesProven ) Vec_IntFree( p->vClausesProven );
if ( p->vCosts ) Vec_IntFree( p->vCosts );
if ( p->pCnf ) Cnf_DataFree( p->pCnf );
if ( p->pSatMain ) sat_solver_delete( p->pSatMain );
if ( p->pSatBmc ) sat_solver_delete( p->pSatBmc );
ABC_FREE( p );
}
/**Function*************************************************************
Synopsis [Converts AIG into the SAT solver.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Fra_ClausAddToStorage( Clu_Man_t * p )
{
int * pStart;
int Beg, End, Counter, i, k;
Beg = 0;
Counter = 0;
pStart = Vec_IntArray( p->vLits );
Vec_IntForEachEntry( p->vClauses, End, i )
{
if ( Vec_IntEntry( p->vCosts, i ) == -1 )
{
Beg = End;
continue;
}
assert( Vec_IntEntry( p->vCosts, i ) > 0 );
assert( End - Beg <= p->nLutSize );
for ( k = Beg; k < End; k++ )
Vec_IntPush( p->vLitsProven, pStart[k] );
Vec_IntPush( p->vClausesProven, Vec_IntSize(p->vLitsProven) );
Beg = End;
Counter++;
if ( i < p->nOneHots )
p->nOneHotsProven++;
}
if ( p->fVerbose )
printf( "Added to storage %d proved clauses (including %d one-hot clauses)\n", Counter, p->nOneHotsProven );
Vec_IntClear( p->vClauses );
Vec_IntClear( p->vLits );
Vec_IntClear( p->vCosts );
p->nClauses = 0;
p->fNothingNew = (int)(Counter == 0);
}
/**Function*************************************************************
Synopsis [Converts AIG into the SAT solver.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Fra_ClausPrintIndClauses( Clu_Man_t * p )
{
int Counters[9] = {0};
int * pStart;
int Beg, End, i;
Beg = 0;
pStart = Vec_IntArray( p->vLitsProven );
Vec_IntForEachEntry( p->vClausesProven, End, i )
{
if ( End - Beg >= 8 )
Counters[8]++;
else
Counters[End - Beg]++;
//printf( "%d ", End-Beg );
Beg = End;
}
printf( "SUMMARY: Total proved clauses = %d. ", Vec_IntSize(p->vClausesProven) );
printf( "Clause per lit: " );
for ( i = 0; i < 8; i++ )
if ( Counters[i] )
printf( "%d=%d ", i, Counters[i] );
if ( Counters[8] )
printf( ">7=%d ", Counters[8] );
printf( "\n" );
}
/**Function*************************************************************
Synopsis [Writes the clauses into an AIGER file.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Aig_Obj_t * Fra_ClausGetLiteral( Clu_Man_t * p, int * pVar2Id, int Lit )
{
Aig_Obj_t * pLiteral;
int NodeId = pVar2Id[ lit_var(Lit) ];
assert( NodeId >= 0 );
pLiteral = (Aig_Obj_t *)Aig_ManObj( p->pAig, NodeId )->pData;
return Aig_NotCond( pLiteral, lit_sign(Lit) );
}
/**Function*************************************************************
Synopsis [Writes the clauses into an AIGER file.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Fra_ClausWriteIndClauses( Clu_Man_t * p )
{
extern void Ioa_WriteAiger( Aig_Man_t * pMan, char * pFileName, int fWriteSymbols, int fCompact );
Aig_Man_t * pNew;
Aig_Obj_t * pClause, * pLiteral;
char * pName;
int * pStart, * pVar2Id;
int Beg, End, i, k;
// create mapping from SAT vars to node IDs
pVar2Id = ABC_ALLOC( int, p->pCnf->nVars );
memset( pVar2Id, 0xFF, sizeof(int) * p->pCnf->nVars );
for ( i = 0; i < Aig_ManObjNumMax(p->pAig); i++ )
if ( p->pCnf->pVarNums[i] >= 0 )
{
assert( p->pCnf->pVarNums[i] < p->pCnf->nVars );
pVar2Id[ p->pCnf->pVarNums[i] ] = i;
}
// start the manager
pNew = Aig_ManDupWithoutPos( p->pAig );
// add the clauses
Beg = 0;
pStart = Vec_IntArray( p->vLitsProven );
Vec_IntForEachEntry( p->vClausesProven, End, i )
{
pClause = Fra_ClausGetLiteral( p, pVar2Id, pStart[Beg] );
for ( k = Beg + 1; k < End; k++ )
{
pLiteral = Fra_ClausGetLiteral( p, pVar2Id, pStart[k] );
pClause = Aig_Or( pNew, pClause, pLiteral );
}
Aig_ObjCreateCo( pNew, pClause );
Beg = End;
}
ABC_FREE( pVar2Id );
Aig_ManCleanup( pNew );
pName = Ioa_FileNameGenericAppend( p->pAig->pName, "_care.aig" );
printf( "Care one-hotness clauses will be written into file \"%s\".\n", pName );
Ioa_WriteAiger( pNew, pName, 0, 1 );
Aig_ManStop( pNew );
}
/**Function*************************************************************
Synopsis [Checks if the clause holds using the given simulation info.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Fra_ClausEstimateCoverageOne( Fra_Sml_t * pSim, int * pLits, int nLits, int * pVar2Id, unsigned * pResult )
{
unsigned * pSims[16];
int iVar, i, w;
for ( i = 0; i < nLits; i++ )
{
iVar = lit_var(pLits[i]);
pSims[i] = Fra_ObjSim( pSim, pVar2Id[iVar] );
}
for ( w = 0; w < pSim->nWordsTotal; w++ )
{
pResult[w] = ~(unsigned)0;
for ( i = 0; i < nLits; i++ )
pResult[w] &= (lit_sign(pLits[i])? pSims[i][w] : ~pSims[i][w]);
}
}
/**Function*************************************************************
Synopsis [Estimates the coverage of state space by clauses.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Fra_ClausEstimateCoverage( Clu_Man_t * p )
{
int nCombSimWords = (1<<11);
Fra_Sml_t * pComb;
unsigned * pResultTot, * pResultOne;
int nCovered, Beg, End, i, w;
int * pStart, * pVar2Id;
abctime clk = Abc_Clock();
// simulate the circuit with nCombSimWords * 32 = 64K patterns
// srand( 0xAABBAABB );
Aig_ManRandom(1);
pComb = Fra_SmlSimulateComb( p->pAig, nCombSimWords, 0 );
// create mapping from SAT vars to node IDs
pVar2Id = ABC_ALLOC( int, p->pCnf->nVars );
memset( pVar2Id, 0, sizeof(int) * p->pCnf->nVars );
for ( i = 0; i < Aig_ManObjNumMax(p->pAig); i++ )
if ( p->pCnf->pVarNums[i] >= 0 )
{
assert( p->pCnf->pVarNums[i] < p->pCnf->nVars );
pVar2Id[ p->pCnf->pVarNums[i] ] = i;
}
// get storage for one assignment and all assignments
assert( Aig_ManCoNum(p->pAig) > 2 );
pResultOne = Fra_ObjSim( pComb, Aig_ManCo(p->pAig, 0)->Id );
pResultTot = Fra_ObjSim( pComb, Aig_ManCo(p->pAig, 1)->Id );
// start the OR of don't-cares
for ( w = 0; w < nCombSimWords; w++ )
pResultTot[w] = 0;
// check clauses
Beg = 0;
pStart = Vec_IntArray( p->vLitsProven );
Vec_IntForEachEntry( p->vClausesProven, End, i )
{
Fra_ClausEstimateCoverageOne( pComb, pStart + Beg, End-Beg, pVar2Id, pResultOne );
Beg = End;
for ( w = 0; w < nCombSimWords; w++ )
pResultTot[w] |= pResultOne[w];
}
// count the total number of patterns contained in the don't-care
nCovered = 0;
for ( w = 0; w < nCombSimWords; w++ )
nCovered += Aig_WordCountOnes( pResultTot[w] );
Fra_SmlStop( pComb );
ABC_FREE( pVar2Id );
// print the result
printf( "Care states ratio = %f. ", 1.0 * (nCombSimWords * 32 - nCovered) / (nCombSimWords * 32) );
printf( "(%d out of %d patterns) ", nCombSimWords * 32 - nCovered, nCombSimWords * 32 );
ABC_PRT( "Time", Abc_Clock() - clk );
}
/**Function*************************************************************
Synopsis [Converts AIG into the SAT solver.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Fra_Claus( Aig_Man_t * pAig, int nFrames, int nPref, int nClausesMax, int nLutSize, int nLevels, int nCutsMax, int nBatches, int fStepUp, int fBmc, int fRefs, int fTarget, int fVerbose, int fVeryVerbose )
{
Clu_Man_t * p;
abctime clk, clkTotal = Abc_Clock(), clkInd;
int b, Iter, Counter, nPrefOld;
int nClausesBeg = 0;
// create the manager
p = Fra_ClausAlloc( pAig, nFrames, nPref, nClausesMax, nLutSize, nLevels, nCutsMax, nBatches, fStepUp, fTarget, fVerbose, fVeryVerbose );
if ( p->fVerbose )
{
printf( "PARAMETERS: Frames = %d. Pref = %d. Clauses max = %d. Cut size = %d.\n", nFrames, nPref, nClausesMax, nLutSize );
printf( "Level max = %d. Cuts max = %d. Batches = %d. Increment cut size = %s.\n", nLevels, nCutsMax, nBatches, fStepUp? "yes":"no" );
//ABC_PRT( "Sim-seq", Abc_Clock() - clk );
}
assert( !p->fTarget || Aig_ManCoNum(pAig) - Aig_ManRegNum(pAig) == 1 );
clk = Abc_Clock();
// derive CNF
// if ( p->fTarget )
// p->pAig->nRegs++;
p->pCnf = Cnf_DeriveSimple( p->pAig, Aig_ManCoNum(p->pAig) );
// if ( p->fTarget )
// p->pAig->nRegs--;
if ( fVerbose )
{
//ABC_PRT( "CNF ", Abc_Clock() - clk );
}
// check BMC
clk = Abc_Clock();
p->pSatBmc = (sat_solver *)Cnf_DataWriteIntoSolver( p->pCnf, p->nPref + p->nFrames, 1 );
if ( p->pSatBmc == NULL )
{
printf( "Error: BMC solver is unsat.\n" );
Fra_ClausFree( p );
return 1;
}
if ( p->fTarget && !Fra_ClausRunBmc( p ) )
{
printf( "Problem fails the base case after %d frame expansion.\n", p->nPref + p->nFrames );
Fra_ClausFree( p );
return 1;
}
if ( fVerbose )
{
//ABC_PRT( "SAT-bmc", Abc_Clock() - clk );
}
// start the SAT solver
clk = Abc_Clock();
p->pSatMain = (sat_solver *)Cnf_DataWriteIntoSolver( p->pCnf, p->nFrames+1, 0 );
if ( p->pSatMain == NULL )
{
printf( "Error: Main solver is unsat.\n" );
Fra_ClausFree( p );
return 1;
}
for ( b = 0; b < p->nBatches; b++ )
{
// if ( fVerbose )
printf( "*** BATCH %d: ", b+1 );
if ( b && p->nLutSize < 12 && (!p->fFiltering || p->fNothingNew || p->fStepUp) )
p->nLutSize++;
printf( "Using %d-cuts.\n", p->nLutSize );
// try solving without additional clauses
if ( p->fTarget && Fra_ClausRunSat( p ) )
{
printf( "Problem is inductive without strengthening.\n" );
Fra_ClausFree( p );
return 1;
}
if ( fVerbose )
{
// ABC_PRT( "SAT-ind", Abc_Clock() - clk );
}
// collect the candidate inductive clauses using 4-cuts
clk = Abc_Clock();
nPrefOld = p->nPref; p->nPref = 0; p->nSimWordsPref = 0;
// Fra_ClausProcessClauses( p, fRefs );
Fra_ClausProcessClauses2( p, fRefs );
p->nPref = nPrefOld;
p->nSimWordsPref = p->nPref*p->nSimWords/p->nSimFrames;
nClausesBeg = p->nClauses;
//ABC_PRT( "Clauses", Abc_Clock() - clk );
// check clauses using BMC
if ( fBmc )
{
clk = Abc_Clock();
Counter = Fra_ClausBmcClauses( p );
p->nClauses -= Counter;
if ( fVerbose )
{
printf( "BMC disproved %d clauses. ", Counter );
ABC_PRT( "Time", Abc_Clock() - clk );
}
}
// prove clauses inductively
clkInd = clk = Abc_Clock();
Counter = 1;
for ( Iter = 0; Counter > 0; Iter++ )
{
if ( fVerbose )
printf( "Iter %3d : Begin = %5d. ", Iter, p->nClauses );
Counter = Fra_ClausInductiveClauses( p );
if ( Counter > 0 )
p->nClauses -= Counter;
if ( fVerbose )
{
printf( "End = %5d. Exs = %5d. ", p->nClauses, p->nCexes );
// printf( "\n" );
ABC_PRT( "Time", Abc_Clock() - clk );
}
clk = Abc_Clock();
}
// add proved clauses to storage
Fra_ClausAddToStorage( p );
// report the results
if ( p->fTarget )
{
if ( Counter == -1 )
printf( "Fra_Claus(): Internal error. " );
else if ( p->fFail )
printf( "Property FAILS during refinement. " );
else
printf( "Property HOLDS inductively after strengthening. " );
ABC_PRT( "Time ", Abc_Clock() - clkTotal );
if ( !p->fFail )
break;
}
else
{
printf( "Finished proving inductive clauses. " );
ABC_PRT( "Time ", Abc_Clock() - clkTotal );
}
}
// verify the computed interpolant
Fra_InvariantVerify( pAig, nFrames, p->vClausesProven, p->vLitsProven );
// printf( "THIS COMMAND IS KNOWN TO HAVE A BUG!\n" );
// if ( !p->fTarget && p->fVerbose )
if ( p->fVerbose )
{
Fra_ClausPrintIndClauses( p );
Fra_ClausEstimateCoverage( p );
}
if ( !p->fTarget )
{
Fra_ClausWriteIndClauses( p );
}
/*
// print the statistic into a file
{
FILE * pTable;
assert( p->nBatches == 1 );
pTable = fopen( "stats.txt", "a+" );
fprintf( pTable, "%s ", pAig->pName );
fprintf( pTable, "%d ", Aig_ManCiNum(pAig)-Aig_ManRegNum(pAig) );
fprintf( pTable, "%d ", Aig_ManCoNum(pAig)-Aig_ManRegNum(pAig) );
fprintf( pTable, "%d ", Aig_ManRegNum(pAig) );
fprintf( pTable, "%d ", Aig_ManNodeNum(pAig) );
fprintf( pTable, "%d ", p->nCuts );
fprintf( pTable, "%d ", nClausesBeg );
fprintf( pTable, "%d ", p->nClauses );
fprintf( pTable, "%d ", Iter );
fprintf( pTable, "%.2f ", (float)(clkInd-clkTotal)/(float)(CLOCKS_PER_SEC) );
fprintf( pTable, "%.2f ", (float)(Abc_Clock()-clkInd)/(float)(CLOCKS_PER_SEC) );
fprintf( pTable, "%.2f ", (float)(Abc_Clock()-clkTotal)/(float)(CLOCKS_PER_SEC) );
fprintf( pTable, "\n" );
fclose( pTable );
}
*/
// clean the manager
Fra_ClausFree( p );
return 1;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END