mirror of https://github.com/YosysHQ/abc.git
378 lines
12 KiB
C
378 lines
12 KiB
C
/**CFile****************************************************************
|
|
|
|
FileName [bmcBmc.c]
|
|
|
|
SystemName [ABC: Logic synthesis and verification system.]
|
|
|
|
PackageName [SAT-based bounded model checking.]
|
|
|
|
Synopsis [Simple BMC package.]
|
|
|
|
Author [Alan Mishchenko]
|
|
|
|
Affiliation [UC Berkeley]
|
|
|
|
Date [Ver. 1.0. Started - June 20, 2005.]
|
|
|
|
Revision [$Id: bmcBmc.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
|
|
|
|
***********************************************************************/
|
|
|
|
#include "proof/fra/fra.h"
|
|
#include "sat/cnf/cnf.h"
|
|
#include "sat/bsat/satStore.h"
|
|
#include "sat/satoko/satoko.h"
|
|
#include "bmc.h"
|
|
|
|
ABC_NAMESPACE_IMPL_START
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// DECLARATIONS ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// FUNCTION DEFINITIONS ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Create timeframes of the manager for BMC.]
|
|
|
|
Description [The resulting manager is combinational. POs correspond to \
|
|
the property outputs in each time-frame.]
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
Aig_Man_t * Saig_ManFramesBmc( Aig_Man_t * pAig, int nFrames )
|
|
{
|
|
Aig_Man_t * pFrames;
|
|
Aig_Obj_t * pObj, * pObjLi, * pObjLo;
|
|
int i, f;
|
|
assert( Saig_ManRegNum(pAig) > 0 );
|
|
pFrames = Aig_ManStart( Aig_ManNodeNum(pAig) * nFrames );
|
|
// map the constant node
|
|
Aig_ManConst1(pAig)->pData = Aig_ManConst1( pFrames );
|
|
// create variables for register outputs
|
|
Saig_ManForEachLo( pAig, pObj, i )
|
|
pObj->pData = Aig_ManConst0( pFrames );
|
|
// add timeframes
|
|
for ( f = 0; f < nFrames; f++ )
|
|
{
|
|
// create PI nodes for this frame
|
|
Saig_ManForEachPi( pAig, pObj, i )
|
|
pObj->pData = Aig_ObjCreateCi( pFrames );
|
|
// add internal nodes of this frame
|
|
Aig_ManForEachNode( pAig, pObj, i )
|
|
pObj->pData = Aig_And( pFrames, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
|
|
// create POs for this frame
|
|
Saig_ManForEachPo( pAig, pObj, i )
|
|
Aig_ObjCreateCo( pFrames, Aig_ObjChild0Copy(pObj) );
|
|
if ( f == nFrames - 1 )
|
|
break;
|
|
// save register inputs
|
|
Saig_ManForEachLi( pAig, pObj, i )
|
|
pObj->pData = Aig_ObjChild0Copy(pObj);
|
|
// transfer to register outputs
|
|
Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i )
|
|
pObjLo->pData = pObjLi->pData;
|
|
}
|
|
Aig_ManCleanup( pFrames );
|
|
return pFrames;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Returns the number of internal nodes that are not counted yet.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
int Saig_ManFramesCount_rec( Aig_Man_t * p, Aig_Obj_t * pObj )
|
|
{
|
|
if ( !Aig_ObjIsNode(pObj) )
|
|
return 0;
|
|
if ( Aig_ObjIsTravIdCurrent(p, pObj) )
|
|
return 0;
|
|
Aig_ObjSetTravIdCurrent(p, pObj);
|
|
return 1 + Saig_ManFramesCount_rec( p, Aig_ObjFanin0(pObj) ) +
|
|
Saig_ManFramesCount_rec( p, Aig_ObjFanin1(pObj) );
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Create timeframes of the manager for BMC.]
|
|
|
|
Description [The resulting manager is combinational. POs correspond to
|
|
the property outputs in each time-frame.
|
|
The unrolling is stopped as soon as the number of nodes in the frames
|
|
exceeds the given maximum size.]
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
Aig_Man_t * Saig_ManFramesBmcLimit( Aig_Man_t * pAig, int nFrames, int nSizeMax )
|
|
{
|
|
Aig_Man_t * pFrames;
|
|
Aig_Obj_t * pObj, * pObjLi, * pObjLo, * pObjPo;
|
|
int i, f, Counter = 0;
|
|
assert( Saig_ManRegNum(pAig) > 0 );
|
|
pFrames = Aig_ManStart( nSizeMax );
|
|
Aig_ManIncrementTravId( pFrames );
|
|
// map the constant node
|
|
Aig_ManConst1(pAig)->pData = Aig_ManConst1( pFrames );
|
|
// create variables for register outputs
|
|
Saig_ManForEachLo( pAig, pObj, i )
|
|
pObj->pData = Aig_ManConst0( pFrames );
|
|
// add timeframes
|
|
Counter = 0;
|
|
for ( f = 0; f < nFrames; f++ )
|
|
{
|
|
// create PI nodes for this frame
|
|
Saig_ManForEachPi( pAig, pObj, i )
|
|
pObj->pData = Aig_ObjCreateCi( pFrames );
|
|
// add internal nodes of this frame
|
|
Aig_ManForEachNode( pAig, pObj, i )
|
|
pObj->pData = Aig_And( pFrames, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
|
|
// create POs for this frame
|
|
Saig_ManForEachPo( pAig, pObj, i )
|
|
{
|
|
pObjPo = Aig_ObjCreateCo( pFrames, Aig_ObjChild0Copy(pObj) );
|
|
Counter += Saig_ManFramesCount_rec( pFrames, Aig_ObjFanin0(pObjPo) );
|
|
}
|
|
if ( Counter >= nSizeMax )
|
|
{
|
|
Aig_ManCleanup( pFrames );
|
|
return pFrames;
|
|
}
|
|
if ( f == nFrames - 1 )
|
|
break;
|
|
// save register inputs
|
|
Saig_ManForEachLi( pAig, pObj, i )
|
|
pObj->pData = Aig_ObjChild0Copy(pObj);
|
|
// transfer to register outputs
|
|
Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i )
|
|
pObjLo->pData = pObjLi->pData;
|
|
}
|
|
Aig_ManCleanup( pFrames );
|
|
return pFrames;
|
|
}
|
|
|
|
ABC_NAMESPACE_IMPL_END
|
|
|
|
#include "misc/util/utilMem.h"
|
|
|
|
ABC_NAMESPACE_IMPL_START
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Returns a counter-example.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
int * Sat2_SolverGetModel( satoko_t * p, int * pVars, int nVars )
|
|
{
|
|
int * pModel;
|
|
int i;
|
|
pModel = ABC_CALLOC( int, nVars+1 );
|
|
for ( i = 0; i < nVars; i++ )
|
|
pModel[i] = satoko_read_cex_varvalue(p, pVars[i]);
|
|
return pModel;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Performs BMC for the given AIG.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
int Saig_ManBmcSimple( Aig_Man_t * pAig, int nFrames, int nSizeMax, int nConfLimit, int fRewrite, int fVerbose, int * piFrame, int nCofFanLit, int fUseSatoko )
|
|
{
|
|
extern Aig_Man_t * Gia_ManCofactorAig( Aig_Man_t * p, int nFrames, int nCofFanLit );
|
|
sat_solver * pSat = NULL;
|
|
satoko_t * pSat2 = NULL;
|
|
Cnf_Dat_t * pCnf;
|
|
Aig_Man_t * pFrames, * pAigTemp;
|
|
Aig_Obj_t * pObj;
|
|
int status, Lit, i, RetValue = -1;
|
|
abctime clk;
|
|
|
|
// derive the timeframes
|
|
clk = Abc_Clock();
|
|
if ( nCofFanLit )
|
|
{
|
|
pFrames = Gia_ManCofactorAig( pAig, nFrames, nCofFanLit );
|
|
if ( pFrames == NULL )
|
|
return -1;
|
|
}
|
|
else if ( nSizeMax > 0 )
|
|
{
|
|
pFrames = Saig_ManFramesBmcLimit( pAig, nFrames, nSizeMax );
|
|
nFrames = Aig_ManCoNum(pFrames) / Saig_ManPoNum(pAig) + ((Aig_ManCoNum(pFrames) % Saig_ManPoNum(pAig)) > 0);
|
|
}
|
|
else
|
|
pFrames = Saig_ManFramesBmc( pAig, nFrames );
|
|
if ( piFrame )
|
|
*piFrame = nFrames;
|
|
if ( fVerbose )
|
|
{
|
|
printf( "Running \"bmc\". AIG: PI/PO/Reg = %d/%d/%d. Node = %6d. Lev = %5d.\n",
|
|
Saig_ManPiNum(pAig), Saig_ManPoNum(pAig), Saig_ManRegNum(pAig),
|
|
Aig_ManNodeNum(pAig), Aig_ManLevelNum(pAig) );
|
|
printf( "Time-frames (%d): PI/PO = %d/%d. Node = %6d. Lev = %5d. ",
|
|
nFrames, Aig_ManCiNum(pFrames), Aig_ManCoNum(pFrames),
|
|
Aig_ManNodeNum(pFrames), Aig_ManLevelNum(pFrames) );
|
|
ABC_PRT( "Time", Abc_Clock() - clk );
|
|
fflush( stdout );
|
|
}
|
|
// rewrite the timeframes
|
|
if ( fRewrite )
|
|
{
|
|
clk = Abc_Clock();
|
|
// pFrames = Dar_ManBalance( pAigTemp = pFrames, 0 );
|
|
pFrames = Dar_ManRwsat( pAigTemp = pFrames, 1, 0 );
|
|
Aig_ManStop( pAigTemp );
|
|
if ( fVerbose )
|
|
{
|
|
printf( "Time-frames after rewriting: Node = %6d. Lev = %5d. ",
|
|
Aig_ManNodeNum(pFrames), Aig_ManLevelNum(pFrames) );
|
|
ABC_PRT( "Time", Abc_Clock() - clk );
|
|
fflush( stdout );
|
|
}
|
|
}
|
|
// create the SAT solver
|
|
clk = Abc_Clock();
|
|
pCnf = Cnf_Derive( pFrames, Aig_ManCoNum(pFrames) );
|
|
//if ( s_fInterrupt )
|
|
//return -1;
|
|
if ( fUseSatoko )
|
|
{
|
|
satoko_opts_t opts;
|
|
satoko_default_opts(&opts);
|
|
opts.conf_limit = nConfLimit;
|
|
pSat2 = satoko_create();
|
|
satoko_configure(pSat2, &opts);
|
|
satoko_setnvars(pSat2, pCnf->nVars);
|
|
for ( i = 0; i < pCnf->nClauses; i++ )
|
|
if ( !satoko_add_clause( pSat2, pCnf->pClauses[i], pCnf->pClauses[i+1]-pCnf->pClauses[i] ) )
|
|
assert( 0 );
|
|
}
|
|
else
|
|
{
|
|
pSat = sat_solver_new();
|
|
sat_solver_setnvars( pSat, pCnf->nVars );
|
|
for ( i = 0; i < pCnf->nClauses; i++ )
|
|
if ( !sat_solver_addclause( pSat, pCnf->pClauses[i], pCnf->pClauses[i+1] ) )
|
|
assert( 0 );
|
|
}
|
|
if ( fVerbose )
|
|
{
|
|
printf( "CNF: Variables = %6d. Clauses = %7d. Literals = %8d. ", pCnf->nVars, pCnf->nClauses, pCnf->nLiterals );
|
|
ABC_PRT( "Time", Abc_Clock() - clk );
|
|
fflush( stdout );
|
|
}
|
|
status = pSat ? sat_solver_simplify(pSat) : 1;
|
|
if ( status == 0 )
|
|
{
|
|
if ( fVerbose )
|
|
{
|
|
printf( "The BMC problem is trivially UNSAT\n" );
|
|
fflush( stdout );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
abctime clkPart = Abc_Clock();
|
|
Aig_ManForEachCo( pFrames, pObj, i )
|
|
{
|
|
Lit = toLitCond( pCnf->pVarNums[pObj->Id], 0 );
|
|
if ( fVerbose )
|
|
{
|
|
printf( "Solving output %2d of frame %3d ... \r",
|
|
i % Saig_ManPoNum(pAig), i / Saig_ManPoNum(pAig) );
|
|
}
|
|
clk = Abc_Clock();
|
|
if ( pSat2 )
|
|
status = satoko_solve_assumptions_limit( pSat2, &Lit, 1, nConfLimit );
|
|
else
|
|
status = sat_solver_solve( pSat, &Lit, &Lit + 1, (ABC_INT64_T)nConfLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
|
|
if ( fVerbose && (i % Saig_ManPoNum(pAig) == Saig_ManPoNum(pAig) - 1) )
|
|
{
|
|
printf( "Solved %2d outputs of frame %3d. ",
|
|
Saig_ManPoNum(pAig), i / Saig_ManPoNum(pAig) );
|
|
printf( "Conf =%8.0f. Imp =%11.0f. ",
|
|
(double)(pSat ? pSat->stats.conflicts : satoko_conflictnum(pSat2)),
|
|
(double)(pSat ? pSat->stats.propagations : satoko_stats(pSat2)->n_propagations) );
|
|
ABC_PRT( "T", Abc_Clock() - clkPart );
|
|
clkPart = Abc_Clock();
|
|
fflush( stdout );
|
|
}
|
|
if ( status == l_False )
|
|
{
|
|
/*
|
|
Lit = lit_neg( Lit );
|
|
RetValue = sat_solver_addclause( pSat, &Lit, &Lit + 1 );
|
|
assert( RetValue );
|
|
if ( pSat->qtail != pSat->qhead )
|
|
{
|
|
RetValue = sat_solver_simplify(pSat);
|
|
assert( RetValue );
|
|
}
|
|
*/
|
|
}
|
|
else if ( status == l_True )
|
|
{
|
|
Vec_Int_t * vCiIds = Cnf_DataCollectPiSatNums( pCnf, pFrames );
|
|
int * pModel = pSat2 ? Sat2_SolverGetModel(pSat2, vCiIds->pArray, vCiIds->nSize) : Sat_SolverGetModel(pSat, vCiIds->pArray, vCiIds->nSize);
|
|
pModel[Aig_ManCiNum(pFrames)] = pObj->Id;
|
|
pAig->pSeqModel = Fra_SmlCopyCounterExample( pAig, pFrames, pModel );
|
|
ABC_FREE( pModel );
|
|
Vec_IntFree( vCiIds );
|
|
|
|
if ( piFrame )
|
|
*piFrame = i / Saig_ManPoNum(pAig);
|
|
RetValue = 0;
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
if ( piFrame )
|
|
*piFrame = i / Saig_ManPoNum(pAig);
|
|
RetValue = -1;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if ( pSat ) sat_solver_delete( pSat );
|
|
if ( pSat2 ) satoko_destroy( pSat2 );
|
|
Cnf_DataFree( pCnf );
|
|
Aig_ManStop( pFrames );
|
|
return RetValue;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// END OF FILE ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
ABC_NAMESPACE_IMPL_END
|
|
|