blob: 2687e9c1c09c98235c1c7717c3b38645024bc595 [file] [log] [blame]
/**CFile****************************************************************
FileName [sswSweep.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Inductive prover with constraints.]
Synopsis [One round of SAT sweeping.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - September 1, 2008.]
Revision [$Id: sswSweep.c,v 1.00 2008/09/01 00:00:00 alanmi Exp $]
***********************************************************************/
#include "sswInt.h"
#include "misc/bar/bar.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Retrives value of the PI in the original AIG.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Ssw_ManGetSatVarValue( Ssw_Man_t * p, Aig_Obj_t * pObj, int f )
{
int fUseNoBoundary = 0;
Aig_Obj_t * pObjFraig;
int Value;
// assert( Aig_ObjIsCi(pObj) );
pObjFraig = Ssw_ObjFrame( p, pObj, f );
if ( fUseNoBoundary )
{
Value = Ssw_CnfGetNodeValue( p->pMSat, Aig_Regular(pObjFraig) );
Value ^= Aig_IsComplement(pObjFraig);
}
else
{
int nVarNum = Ssw_ObjSatNum( p->pMSat, Aig_Regular(pObjFraig) );
Value = (!nVarNum)? 0 : (Aig_IsComplement(pObjFraig) ^ sat_solver_var_value( p->pMSat->pSat, nVarNum ));
}
// Value = (Aig_IsComplement(pObjFraig) ^ ((!nVarNum)? 0 : sat_solver_var_value( p->pSat, nVarNum )));
// Value = (!nVarNum)? Aig_ManRandom(0) & 1 : (Aig_IsComplement(pObjFraig) ^ sat_solver_var_value( p->pSat, nVarNum ));
if ( p->pPars->fPolarFlip )
{
if ( Aig_Regular(pObjFraig)->fPhase ) Value ^= 1;
}
return Value;
}
/**Function*************************************************************
Synopsis [Performs fraiging for the internal nodes.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Ssw_CheckConstraints( Ssw_Man_t * p )
{
Aig_Obj_t * pObj, * pObj2;
int nConstrPairs, i;
int Counter = 0;
nConstrPairs = Aig_ManCoNum(p->pFrames)-Aig_ManRegNum(p->pAig);
assert( (nConstrPairs & 1) == 0 );
for ( i = 0; i < nConstrPairs; i += 2 )
{
pObj = Aig_ManCo( p->pFrames, i );
pObj2 = Aig_ManCo( p->pFrames, i+1 );
if ( Ssw_NodesAreEquiv( p, Aig_ObjFanin0(pObj), Aig_ObjFanin0(pObj2) ) != 1 )
{
Ssw_NodesAreConstrained( p, Aig_ObjChild0(pObj), Aig_ObjChild0(pObj2) );
Counter++;
}
}
Abc_Print( 1, "Total constraints = %d. Added constraints = %d.\n", nConstrPairs/2, Counter );
}
/**Function*************************************************************
Synopsis [Copy pattern from the solver into the internal storage.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Ssw_SmlSavePatternAigPhase( Ssw_Man_t * p, int f )
{
Aig_Obj_t * pObj;
int i;
memset( p->pPatWords, 0, sizeof(unsigned) * p->nPatWords );
Aig_ManForEachCi( p->pAig, pObj, i )
if ( Aig_ObjPhaseReal( Ssw_ObjFrame(p, pObj, f) ) )
Abc_InfoSetBit( p->pPatWords, i );
}
/**Function*************************************************************
Synopsis [Copy pattern from the solver into the internal storage.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Ssw_SmlSavePatternAig( Ssw_Man_t * p, int f )
{
Aig_Obj_t * pObj;
int i;
memset( p->pPatWords, 0, sizeof(unsigned) * p->nPatWords );
Aig_ManForEachCi( p->pAig, pObj, i )
if ( Ssw_ManGetSatVarValue( p, pObj, f ) )
Abc_InfoSetBit( p->pPatWords, i );
}
/**Function*************************************************************
Synopsis [Saves one counter-example into internal storage.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Ssw_SmlAddPatternDyn( Ssw_Man_t * p )
{
Aig_Obj_t * pObj;
unsigned * pInfo;
int i, nVarNum;
// iterate through the PIs of the frames
Vec_PtrForEachEntry( Aig_Obj_t *, p->pMSat->vUsedPis, pObj, i )
{
assert( Aig_ObjIsCi(pObj) );
nVarNum = Ssw_ObjSatNum( p->pMSat, pObj );
assert( nVarNum > 0 );
if ( sat_solver_var_value( p->pMSat->pSat, nVarNum ) )
{
pInfo = (unsigned *)Vec_PtrEntry( p->vSimInfo, Aig_ObjCioId(pObj) );
Abc_InfoSetBit( pInfo, p->nPatterns );
}
}
}
/**Function*************************************************************
Synopsis [Performs fraiging for one node.]
Description [Returns the fraiged node.]
SideEffects []
SeeAlso []
***********************************************************************/
int Ssw_ManSweepNode( Ssw_Man_t * p, Aig_Obj_t * pObj, int f, int fBmc, Vec_Int_t * vPairs )
{
Aig_Obj_t * pObjRepr, * pObjFraig, * pObjFraig2, * pObjReprFraig;
int RetValue;
abctime clk;
// get representative of this class
pObjRepr = Aig_ObjRepr( p->pAig, pObj );
if ( pObjRepr == NULL )
return 0;
// get the fraiged node
pObjFraig = Ssw_ObjFrame( p, pObj, f );
// get the fraiged representative
pObjReprFraig = Ssw_ObjFrame( p, pObjRepr, f );
// check if constant 0 pattern distinquishes these nodes
assert( pObjFraig != NULL && pObjReprFraig != NULL );
assert( (pObj->fPhase == pObjRepr->fPhase) == (Aig_ObjPhaseReal(pObjFraig) == Aig_ObjPhaseReal(pObjReprFraig)) );
// if the fraiged nodes are the same, return
if ( Aig_Regular(pObjFraig) == Aig_Regular(pObjReprFraig) )
return 0;
// add constraints on demand
if ( !fBmc && p->pPars->fDynamic )
{
clk = Abc_Clock();
Ssw_ManLoadSolver( p, pObjRepr, pObj );
p->nRecycleCalls++;
p->timeMarkCones += Abc_Clock() - clk;
}
// call equivalence checking
if ( Aig_Regular(pObjFraig) != Aig_ManConst1(p->pFrames) )
RetValue = Ssw_NodesAreEquiv( p, Aig_Regular(pObjReprFraig), Aig_Regular(pObjFraig) );
else
RetValue = Ssw_NodesAreEquiv( p, Aig_Regular(pObjFraig), Aig_Regular(pObjReprFraig) );
if ( RetValue == 1 ) // proved equivalent
{
pObjFraig2 = Aig_NotCond( pObjReprFraig, pObj->fPhase ^ pObjRepr->fPhase );
Ssw_ObjSetFrame( p, pObj, f, pObjFraig2 );
if ( p->pPars->fEquivDump2 && vPairs )
{
Vec_IntPush( vPairs, pObjRepr->Id );
Vec_IntPush( vPairs, pObj->Id );
}
return 0;
}
if ( p->pPars->fEquivDump && vPairs )
{
Vec_IntPush( vPairs, pObjRepr->Id );
Vec_IntPush( vPairs, pObj->Id );
}
if ( RetValue == -1 ) // timed out
{
Ssw_ClassesRemoveNode( p->ppClasses, pObj );
return 1;
}
// disproved the equivalence
if ( !fBmc && p->pPars->fDynamic )
{
Ssw_SmlAddPatternDyn( p );
p->nPatterns++;
return 1;
}
else
Ssw_SmlSavePatternAig( p, f );
if ( !p->pPars->fConstrs )
Ssw_ManResimulateWord( p, pObj, pObjRepr, f );
else
Ssw_ManResimulateBit( p, pObj, pObjRepr );
assert( Aig_ObjRepr( p->pAig, pObj ) != pObjRepr );
if ( Aig_ObjRepr( p->pAig, pObj ) == pObjRepr )
{
Abc_Print( 1, "Ssw_ManSweepNode(): Failed to refine representative.\n" );
}
return 1;
}
/**Function*************************************************************
Synopsis [Performs fraiging for the internal nodes.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Ssw_ManSweepBmc( Ssw_Man_t * p )
{
Bar_Progress_t * pProgress = NULL;
Aig_Obj_t * pObj, * pObjNew, * pObjLi, * pObjLo;
int i, f;
abctime clk;
clk = Abc_Clock();
// start initialized timeframes
p->pFrames = Aig_ManStart( Aig_ManObjNumMax(p->pAig) * p->pPars->nFramesK );
Saig_ManForEachLo( p->pAig, pObj, i )
Ssw_ObjSetFrame( p, pObj, 0, Aig_ManConst0(p->pFrames) );
// sweep internal nodes
p->fRefined = 0;
if ( p->pPars->fVerbose )
pProgress = Bar_ProgressStart( stdout, Aig_ManObjNumMax(p->pAig) * p->pPars->nFramesK );
for ( f = 0; f < p->pPars->nFramesK; f++ )
{
// map constants and PIs
Ssw_ObjSetFrame( p, Aig_ManConst1(p->pAig), f, Aig_ManConst1(p->pFrames) );
Saig_ManForEachPi( p->pAig, pObj, i )
Ssw_ObjSetFrame( p, pObj, f, Aig_ObjCreateCi(p->pFrames) );
// sweep flops
Saig_ManForEachLo( p->pAig, pObj, i )
p->fRefined |= Ssw_ManSweepNode( p, pObj, f, 1, NULL );
// sweep internal nodes
Aig_ManForEachNode( p->pAig, pObj, i )
{
if ( p->pPars->fVerbose )
Bar_ProgressUpdate( pProgress, Aig_ManObjNumMax(p->pAig) * f + i, NULL );
pObjNew = Aig_And( p->pFrames, Ssw_ObjChild0Fra(p, pObj, f), Ssw_ObjChild1Fra(p, pObj, f) );
Ssw_ObjSetFrame( p, pObj, f, pObjNew );
p->fRefined |= Ssw_ManSweepNode( p, pObj, f, 1, NULL );
}
// quit if this is the last timeframe
if ( f == p->pPars->nFramesK - 1 )
break;
// transfer latch input to the latch outputs
Aig_ManForEachCo( p->pAig, pObj, i )
Ssw_ObjSetFrame( p, pObj, f, Ssw_ObjChild0Fra(p, pObj, f) );
// build logic cones for register outputs
Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i )
{
pObjNew = Ssw_ObjFrame( p, pObjLi, f );
Ssw_ObjSetFrame( p, pObjLo, f+1, pObjNew );
Ssw_CnfNodeAddToSolver( p->pMSat, Aig_Regular(pObjNew) );//
}
}
if ( p->pPars->fVerbose )
Bar_ProgressStop( pProgress );
// cleanup
// Ssw_ClassesCheck( p->ppClasses );
p->timeBmc += Abc_Clock() - clk;
return p->fRefined;
}
/**Function*************************************************************
Synopsis [Generates AIG with the following nodes put into seq miters.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Ssw_ManDumpEquivMiter( Aig_Man_t * p, Vec_Int_t * vPairs, int Num, int fAddOuts )
{
FILE * pFile;
char pBuffer[16];
Aig_Man_t * pNew;
sprintf( pBuffer, "equiv%03d.aig", Num );
pFile = fopen( pBuffer, "w" );
if ( pFile == NULL )
{
Abc_Print( 1, "Cannot open file %s for writing.\n", pBuffer );
return;
}
fclose( pFile );
pNew = Saig_ManCreateEquivMiter( p, vPairs, fAddOuts );
Ioa_WriteAiger( pNew, pBuffer, 0, 0 );
Aig_ManStop( pNew );
Abc_Print( 1, "AIG with %4d disproved equivs is dumped into file \"%s\".\n", Vec_IntSize(vPairs)/2, pBuffer );
}
/**Function*************************************************************
Synopsis [Performs fraiging for the internal nodes.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Ssw_ManSweep( Ssw_Man_t * p )
{
static int Counter;
Bar_Progress_t * pProgress = NULL;
Aig_Obj_t * pObj, * pObj2, * pObjNew;
int nConstrPairs, i, f;
abctime clk;
Vec_Int_t * vObjPairs;
// perform speculative reduction
clk = Abc_Clock();
// create timeframes
p->pFrames = Ssw_FramesWithClasses( p );
// add constants
nConstrPairs = Aig_ManCoNum(p->pFrames)-Aig_ManRegNum(p->pAig);
assert( (nConstrPairs & 1) == 0 );
for ( i = 0; i < nConstrPairs; i += 2 )
{
pObj = Aig_ManCo( p->pFrames, i );
pObj2 = Aig_ManCo( p->pFrames, i+1 );
Ssw_NodesAreConstrained( p, Aig_ObjChild0(pObj), Aig_ObjChild0(pObj2) );
}
// build logic cones for register inputs
for ( i = 0; i < Aig_ManRegNum(p->pAig); i++ )
{
pObj = Aig_ManCo( p->pFrames, nConstrPairs + i );
Ssw_CnfNodeAddToSolver( p->pMSat, Aig_ObjFanin0(pObj) );//
}
sat_solver_simplify( p->pMSat->pSat );
// map constants and PIs of the last frame
f = p->pPars->nFramesK;
Ssw_ObjSetFrame( p, Aig_ManConst1(p->pAig), f, Aig_ManConst1(p->pFrames) );
Saig_ManForEachPi( p->pAig, pObj, i )
Ssw_ObjSetFrame( p, pObj, f, Aig_ObjCreateCi(p->pFrames) );
p->timeReduce += Abc_Clock() - clk;
// sweep internal nodes
p->fRefined = 0;
Ssw_ClassesClearRefined( p->ppClasses );
if ( p->pPars->fVerbose )
pProgress = Bar_ProgressStart( stdout, Aig_ManObjNumMax(p->pAig) );
vObjPairs = (p->pPars->fEquivDump || p->pPars->fEquivDump2)? Vec_IntAlloc(1000) : NULL;
Aig_ManForEachObj( p->pAig, pObj, i )
{
if ( p->pPars->fVerbose )
Bar_ProgressUpdate( pProgress, i, NULL );
if ( Saig_ObjIsLo(p->pAig, pObj) )
p->fRefined |= Ssw_ManSweepNode( p, pObj, f, 0, vObjPairs );
else if ( Aig_ObjIsNode(pObj) )
{
pObjNew = Aig_And( p->pFrames, Ssw_ObjChild0Fra(p, pObj, f), Ssw_ObjChild1Fra(p, pObj, f) );
Ssw_ObjSetFrame( p, pObj, f, pObjNew );
p->fRefined |= Ssw_ManSweepNode( p, pObj, f, 0, vObjPairs );
}
}
if ( p->pPars->fVerbose )
Bar_ProgressStop( pProgress );
// cleanup
// Ssw_ClassesCheck( p->ppClasses );
if ( p->pPars->fEquivDump )
Ssw_ManDumpEquivMiter( p->pAig, vObjPairs, Counter++, 1 );
if ( p->pPars->fEquivDump2 && !p->fRefined )
Ssw_ManDumpEquivMiter( p->pAig, vObjPairs, 0, 0 );
Vec_IntFreeP( &vObjPairs );
return p->fRefined;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END