blob: 19cdf9e6930806e3a9f862f70e7fa11c71b8861c [file] [log] [blame]
/**CFile****************************************************************
FileName [giaCCof.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Scalable AIG package.]
Synopsis [Backward reachability using circuit cofactoring.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: giaCCof.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
#include "gia.h"
#include "sat/bsat/satSolver.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
typedef struct Ccf_Man_t_ Ccf_Man_t; // manager
struct Ccf_Man_t_
{
// user data
Gia_Man_t * pGia; // single-output AIG manager
int nFrameMax; // maximum number of frames
int nConfMax; // maximum number of conflicts
int nTimeMax; // maximum runtime in seconds
int fVerbose; // verbose flag
// internal data
void * pUnr; // unrolling manager
Gia_Man_t * pFrames; // unrolled timeframes
Vec_Int_t * vCopies; // copy pointers of the AIG
sat_solver * pSat; // SAT solver
};
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Create manager.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Ccf_Man_t * Ccf_ManStart( Gia_Man_t * pGia, int nFrameMax, int nConfMax, int nTimeMax, int fVerbose )
{
static Gia_ParFra_t Pars, * pPars = &Pars;
Ccf_Man_t * p;
assert( nFrameMax > 0 );
p = ABC_CALLOC( Ccf_Man_t, 1 );
p->pGia = pGia;
p->nFrameMax = nFrameMax;
p->nConfMax = nConfMax;
p->nTimeMax = nTimeMax;
p->fVerbose = fVerbose;
// create unrolling manager
memset( pPars, 0, sizeof(Gia_ParFra_t) );
pPars->fVerbose = fVerbose;
pPars->nFrames = nFrameMax;
pPars->fSaveLastLit = 1;
p->pUnr = Gia_ManUnrollStart( pGia, pPars );
p->vCopies = Vec_IntAlloc( 1000 );
// internal data
p->pSat = sat_solver_new();
// sat_solver_setnvars( p->pSat, 10000 );
return p;
}
/**Function*************************************************************
Synopsis [Delete manager.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Ccf_ManStop( Ccf_Man_t * p )
{
Vec_IntFree( p->vCopies );
Gia_ManUnrollStop( p->pUnr );
sat_solver_delete( p->pSat );
Gia_ManStopP( &p->pFrames );
ABC_FREE( p );
}
/**Function*************************************************************
Synopsis [Extends the solver.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_ManCofExtendSolver( Ccf_Man_t * p )
{
Gia_Obj_t * pObj;
int i;
// add SAT clauses
for ( i = sat_solver_nvars(p->pSat); i < Gia_ManObjNum(p->pFrames); i++ )
{
pObj = Gia_ManObj( p->pFrames, i );
if ( Gia_ObjIsAnd(pObj) )
sat_solver_add_and( p->pSat, i,
Gia_ObjFaninId0(pObj, i),
Gia_ObjFaninId1(pObj, i),
Gia_ObjFaninC0(pObj),
Gia_ObjFaninC1(pObj), 0 );
}
sat_solver_setnvars( p->pSat, Gia_ManObjNum(p->pFrames) );
}
static inline int Gia_Obj0Copy( Vec_Int_t * vCopies, int Fan0, int fCompl0 )
{ return Abc_LitNotCond( Vec_IntEntry(vCopies, Fan0), fCompl0 ); }
static inline int Gia_Obj1Copy( Vec_Int_t * vCopies, int Fan1, int fCompl1 )
{ return Abc_LitNotCond( Vec_IntEntry(vCopies, Fan1), fCompl1 ); }
/**Function*************************************************************
Synopsis [Cofactor the circuit w.r.t. the given assignment.]
Description [Assumes that the solver has just returned SAT.]
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_ManCofOneDerive_rec( Ccf_Man_t * p, int Id )
{
Gia_Obj_t * pObj;
int Res;
if ( Vec_IntEntry(p->vCopies, Id) != -1 )
return;
pObj = Gia_ManObj(p->pFrames, Id);
assert( Gia_ObjIsCi(pObj) || Gia_ObjIsAnd(pObj) );
if ( Gia_ObjIsAnd(pObj) )
{
int fCompl0 = Gia_ObjFaninC0(pObj);
int fCompl1 = Gia_ObjFaninC1(pObj);
int Fan0 = Gia_ObjFaninId0p(p->pFrames, pObj);
int Fan1 = Gia_ObjFaninId1p(p->pFrames, pObj);
Gia_ManCofOneDerive_rec( p, Fan0 );
Gia_ManCofOneDerive_rec( p, Fan1 );
Res = Gia_ManHashAnd( p->pFrames,
Gia_Obj0Copy(p->vCopies, Fan0, fCompl0),
Gia_Obj1Copy(p->vCopies, Fan1, fCompl1) );
}
else if ( Gia_ObjCioId(pObj) >= Gia_ManRegNum(p->pGia) ) // PI
Res = sat_solver_var_value( p->pSat, Id );
else
Res = Abc_Var2Lit( Id, 0 );
Vec_IntWriteEntry( p->vCopies, Id, Res );
}
/**Function*************************************************************
Synopsis [Cofactor the circuit w.r.t. the given assignment.]
Description [Assumes that the solver has just returned SAT.]
SideEffects []
SeeAlso []
***********************************************************************/
int Gia_ManCofOneDerive( Ccf_Man_t * p, int LitProp )
{
int LitOut;
// derive the cofactor of the property node
Vec_IntFill( p->vCopies, Gia_ManObjNum(p->pFrames), -1 );
Gia_ManCofOneDerive_rec( p, Abc_Lit2Var(LitProp) );
LitOut = Vec_IntEntry( p->vCopies, Abc_Lit2Var(LitProp) );
LitOut = Abc_LitNotCond( LitOut, Abc_LitIsCompl(LitProp) );
// add new PO for the cofactor
Gia_ManAppendCo( p->pFrames, LitOut );
// add SAT clauses
Gia_ManCofExtendSolver( p );
// return negative literal of the cofactor
return Abc_LitNot(LitOut);
}
/**Function*************************************************************
Synopsis [Enumerates backward reachable states.]
Description [Return -1 if resource limit is reached. Returns 1
if computation converged (there is no more reachable states).
Returns 0 if no more states to enumerate.]
SideEffects []
SeeAlso []
***********************************************************************/
int Gia_ManCofGetReachable( Ccf_Man_t * p, int Lit )
{
int ObjPrev = 0, ConfPrev = 0;
int Count = 0, LitOut, RetValue;
abctime clk;
// try solving for the first time and quit if converged
RetValue = sat_solver_solve( p->pSat, &Lit, &Lit + 1, p->nConfMax, 0, 0, 0 );
if ( RetValue == l_False )
return 1;
// iterate circuit cofactoring
while ( RetValue == l_True )
{
clk = Abc_Clock();
// derive cofactor
LitOut = Gia_ManCofOneDerive( p, Lit );
// add the blocking clause
RetValue = sat_solver_addclause( p->pSat, &LitOut, &LitOut + 1 );
assert( RetValue );
// try solving again
RetValue = sat_solver_solve( p->pSat, &Lit, &Lit + 1, p->nConfMax, 0, 0, 0 );
// derive cofactors
if ( p->fVerbose )
{
printf( "%3d : AIG =%7d Conf =%7d. ", Count++,
Gia_ManObjNum(p->pFrames) - ObjPrev, sat_solver_nconflicts(p->pSat) - ConfPrev );
Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
ObjPrev = Gia_ManObjNum(p->pFrames);
ConfPrev = sat_solver_nconflicts(p->pSat);
}
}
if ( RetValue == l_Undef )
return -1;
return 0;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Gia_Man_t * Gia_ManCofTest( Gia_Man_t * pGia, int nFrameMax, int nConfMax, int nTimeMax, int fVerbose )
{
Gia_Man_t * pNew;
Ccf_Man_t * p;
Gia_Obj_t * pObj;
int f, i, Lit, RetValue = -1, fFailed = 0;
abctime nTimeToStop = Abc_Clock() + nTimeMax * CLOCKS_PER_SEC;
abctime clk = Abc_Clock();
assert( Gia_ManPoNum(pGia) == 1 );
// create reachability manager
p = Ccf_ManStart( pGia, nFrameMax, nConfMax, nTimeMax, fVerbose );
// set runtime limit
if ( nTimeMax )
sat_solver_set_runtime_limit( p->pSat, nTimeToStop );
// perform backward image computation
for ( f = 0; f < nFrameMax; f++ )
{
if ( fVerbose )
printf( "ITER %3d :\n", f );
// add to the mapping of nodes
p->pFrames = (Gia_Man_t *)Gia_ManUnrollAdd( p->pUnr, f+1 );
// add SAT clauses
Gia_ManCofExtendSolver( p );
// return output literal
Lit = Gia_ManUnrollLastLit( p->pUnr );
// derives cofactors of the property literal till all states are blocked
RetValue = Gia_ManCofGetReachable( p, Lit );
if ( RetValue )
break;
// check the property output
Gia_ManSetPhase( p->pFrames );
Gia_ManForEachPo( p->pFrames, pObj, i )
if ( pObj->fPhase )
{
printf( "Property failed in frame %d.\n", f );
fFailed = 1;
break;
}
if ( i < Gia_ManPoNum(p->pFrames) )
break;
}
// report the result
if ( nTimeToStop && Abc_Clock() > nTimeToStop )
printf( "Runtime limit (%d sec) is reached after %d frames. ", nTimeMax, f );
else if ( f == nFrameMax )
printf( "Completed %d frames without converging. ", f );
else if ( RetValue == 1 )
printf( "Backward reachability converged after %d iterations. ", f-1 );
else if ( RetValue == -1 )
printf( "Conflict limit or timeout is reached after %d frames. ", f-1 );
Abc_PrintTime( 1, "Runtime", Abc_Clock() - clk );
if ( !fFailed && RetValue == 1 )
printf( "Property holds.\n" );
else if ( !fFailed )
printf( "Property is undecided.\n" );
// get the resulting AIG manager
Gia_ManHashStop( p->pFrames );
pNew = p->pFrames; p->pFrames = NULL;
Ccf_ManStop( p );
// cleanup
// if ( fVerbose )
// Gia_ManPrintStats( pNew, 0 );
pNew = Gia_ManCleanup( pGia = pNew );
Gia_ManStop( pGia );
// if ( fVerbose )
// Gia_ManPrintStats( pNew, 0 );
return pNew;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END