Commit 624af674 by Alan Mishchenko

New code since Dec 2010.

parent ab80b015
/**CFile****************************************************************
FileName [giaSim.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Scalable AIG package.]
Synopsis [Fast sequential simulator.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: giaSim.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
#include "gia.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
typedef struct Gia_Sim2_t_ Gia_Sim2_t;
struct Gia_Sim2_t_
{
Gia_Man_t * pAig;
Gia_ParSim_t * pPars;
int nWords;
unsigned * pDataSim;
Vec_Int_t * vClassOld;
Vec_Int_t * vClassNew;
};
static inline unsigned * Gia_Sim2Data( Gia_Sim2_t * p, int i ) { return p->pDataSim + i * p->nWords; }
extern void Gia_ManResetRandom( Gia_ParSim_t * pPars );
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_Sim2Delete( Gia_Sim2_t * p )
{
Vec_IntFreeP( &p->vClassOld );
Vec_IntFreeP( &p->vClassNew );
ABC_FREE( p->pDataSim );
ABC_FREE( p );
}
/**Function*************************************************************
Synopsis [Creates fast simulation manager.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Gia_Sim2_t * Gia_Sim2Create( Gia_Man_t * pAig, Gia_ParSim_t * pPars )
{
Gia_Sim2_t * p;
Gia_Obj_t * pObj;
int i;
p = ABC_CALLOC( Gia_Sim2_t, 1 );
p->pAig = pAig;
p->pPars = pPars;
p->nWords = pPars->nWords;
p->pDataSim = ABC_ALLOC( unsigned, p->nWords * Gia_ManObjNum(p->pAig) );
if ( !p->pDataSim )
{
Abc_Print( 1, "Simulator could not allocate %.2f Gb for simulation info.\n",
4.0 * p->nWords * Gia_ManObjNum(p->pAig) / (1<<30) );
Gia_Sim2Delete( p );
return NULL;
}
p->vClassOld = Vec_IntAlloc( 100 );
p->vClassNew = Vec_IntAlloc( 100 );
if ( pPars->fVerbose )
Abc_Print( 1, "Memory: AIG = %7.2f Mb. SimInfo = %7.2f Mb.\n",
12.0*Gia_ManObjNum(p->pAig)/(1<<20), 4.0*p->nWords*Gia_ManObjNum(p->pAig)/(1<<20) );
// prepare AIG
Gia_ManSetPhase( pAig );
Gia_ManForEachObj( pAig, pObj, i )
pObj->Value = i;
return p;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Gia_Sim2InfoRandom( Gia_Sim2_t * p, unsigned * pInfo )
{
int w;
for ( w = p->nWords-1; w >= 0; w-- )
pInfo[w] = Gia_ManRandom( 0 );
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Gia_Sim2InfoZero( Gia_Sim2_t * p, unsigned * pInfo )
{
int w;
for ( w = p->nWords-1; w >= 0; w-- )
pInfo[w] = 0;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Gia_Sim2InfoOne( Gia_Sim2_t * p, unsigned * pInfo )
{
int w;
for ( w = p->nWords-1; w >= 0; w-- )
pInfo[w] = ~0;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Gia_Sim2InfoCopy( Gia_Sim2_t * p, unsigned * pInfo, unsigned * pInfo0 )
{
int w;
for ( w = p->nWords-1; w >= 0; w-- )
pInfo[w] = pInfo0[w];
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Gia_Sim2SimulateCo( Gia_Sim2_t * p, Gia_Obj_t * pObj )
{
unsigned * pInfo = Gia_Sim2Data( p, Gia_ObjValue(pObj) );
unsigned * pInfo0 = Gia_Sim2Data( p, Gia_ObjFaninId0(pObj, Gia_ObjValue(pObj)) );
int w;
if ( Gia_ObjFaninC0(pObj) )
for ( w = p->nWords-1; w >= 0; w-- )
pInfo[w] = ~pInfo0[w];
else
for ( w = p->nWords-1; w >= 0; w-- )
pInfo[w] = pInfo0[w];
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Gia_Sim2SimulateNode( Gia_Sim2_t * p, Gia_Obj_t * pObj )
{
unsigned * pInfo = Gia_Sim2Data( p, Gia_ObjValue(pObj) );
unsigned * pInfo0 = Gia_Sim2Data( p, Gia_ObjFaninId0(pObj, Gia_ObjValue(pObj)) );
unsigned * pInfo1 = Gia_Sim2Data( p, Gia_ObjFaninId1(pObj, Gia_ObjValue(pObj)) );
int w;
if ( Gia_ObjFaninC0(pObj) )
{
if ( Gia_ObjFaninC1(pObj) )
for ( w = p->nWords-1; w >= 0; w-- )
pInfo[w] = ~(pInfo0[w] | pInfo1[w]);
else
for ( w = p->nWords-1; w >= 0; w-- )
pInfo[w] = ~pInfo0[w] & pInfo1[w];
}
else
{
if ( Gia_ObjFaninC1(pObj) )
for ( w = p->nWords-1; w >= 0; w-- )
pInfo[w] = pInfo0[w] & ~pInfo1[w];
else
for ( w = p->nWords-1; w >= 0; w-- )
pInfo[w] = pInfo0[w] & pInfo1[w];
}
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Gia_Sim2InfoTransfer( Gia_Sim2_t * p )
{
Gia_Obj_t * pObjRo, * pObjRi;
unsigned * pInfo0, * pInfo1;
int i;
Gia_ManForEachRiRo( p->pAig, pObjRi, pObjRo, i )
{
pInfo0 = Gia_Sim2Data( p, Gia_ObjValue(pObjRo) );
pInfo1 = Gia_Sim2Data( p, Gia_ObjValue(pObjRi) );
Gia_Sim2InfoCopy( p, pInfo0, pInfo1 );
}
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Gia_Sim2SimulateRound( Gia_Sim2_t * p )
{
Gia_Obj_t * pObj;
int i;
pObj = Gia_ManConst0(p->pAig);
assert( Gia_ObjValue(pObj) == 0 );
Gia_Sim2InfoZero( p, Gia_Sim2Data(p, Gia_ObjValue(pObj)) );
Gia_ManForEachPi( p->pAig, pObj, i )
Gia_Sim2InfoRandom( p, Gia_Sim2Data(p, Gia_ObjValue(pObj)) );
Gia_ManForEachAnd( p->pAig, pObj, i )
{
assert( Gia_ObjValue(pObj) == i );
Gia_Sim2SimulateNode( p, pObj );
}
Gia_ManForEachCo( p->pAig, pObj, i )
Gia_Sim2SimulateCo( p, pObj );
}
/**Function*************************************************************
Synopsis [Compares simulation info of two nodes.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Gia_Sim2CompareEqual( unsigned * p0, unsigned * p1, int nWords, int fCompl )
{
int w;
if ( !fCompl )
{
for ( w = 0; w < nWords; w++ )
if ( p0[w] != p1[w] )
return 0;
return 1;
}
else
{
for ( w = 0; w < nWords; w++ )
if ( p0[w] != ~p1[w] )
return 0;
return 1;
}
}
/**Function*************************************************************
Synopsis [Compares simulation info of one node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Gia_Sim2CompareZero( unsigned * p0, int nWords, int fCompl )
{
int w;
if ( !fCompl )
{
for ( w = 0; w < nWords; w++ )
if ( p0[w] != 0 )
return 0;
return 1;
}
else
{
for ( w = 0; w < nWords; w++ )
if ( p0[w] != ~0 )
return 0;
return 1;
}
}
/**Function*************************************************************
Synopsis [Creates equivalence class.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_Sim2ClassCreate( Gia_Man_t * p, Vec_Int_t * vClass )
{
int Repr = GIA_VOID, EntPrev = -1, Ent, i;
assert( Vec_IntSize(vClass) > 0 );
Vec_IntForEachEntry( vClass, Ent, i )
{
if ( i == 0 )
{
Repr = Ent;
Gia_ObjSetRepr( p, Ent, GIA_VOID );
EntPrev = Ent;
}
else
{
assert( Repr < Ent );
Gia_ObjSetRepr( p, Ent, Repr );
Gia_ObjSetNext( p, EntPrev, Ent );
EntPrev = Ent;
}
}
Gia_ObjSetNext( p, EntPrev, 0 );
}
/**Function*************************************************************
Synopsis [Refines one equivalence class.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Gia_Sim2ClassRefineOne( Gia_Sim2_t * p, int i )
{
Gia_Obj_t * pObj0, * pObj1;
unsigned * pSim0, * pSim1;
int Ent;
Vec_IntClear( p->vClassOld );
Vec_IntClear( p->vClassNew );
Vec_IntPush( p->vClassOld, i );
pObj0 = Gia_ManObj( p->pAig, i );
pSim0 = Gia_Sim2Data( p, i );
Gia_ClassForEachObj1( p->pAig, i, Ent )
{
pObj1 = Gia_ManObj( p->pAig, Ent );
pSim1 = Gia_Sim2Data( p, Ent );
if ( Gia_Sim2CompareEqual( pSim0, pSim1, p->nWords, Gia_ObjPhase(pObj0) ^ Gia_ObjPhase(pObj1) ) )
Vec_IntPush( p->vClassOld, Ent );
else
Vec_IntPush( p->vClassNew, Ent );
}
if ( Vec_IntSize( p->vClassNew ) == 0 )
return 0;
Gia_Sim2ClassCreate( p->pAig, p->vClassOld );
Gia_Sim2ClassCreate( p->pAig, p->vClassNew );
if ( Vec_IntSize(p->vClassNew) > 1 )
return 1 + Gia_Sim2ClassRefineOne( p, Vec_IntEntry(p->vClassNew,0) );
return 1;
}
/**Function*************************************************************
Synopsis [Computes hash key of the simuation info.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Gia_Sim2HashKey( unsigned * pSim, int nWords, int nTableSize )
{
static int s_Primes[16] = {
1291, 1699, 1999, 2357, 2953, 3313, 3907, 4177,
4831, 5147, 5647, 6343, 6899, 7103, 7873, 8147 };
unsigned uHash = 0;
int i;
if ( pSim[0] & 1 )
for ( i = 0; i < nWords; i++ )
uHash ^= ~pSim[i] * s_Primes[i & 0xf];
else
for ( i = 0; i < nWords; i++ )
uHash ^= pSim[i] * s_Primes[i & 0xf];
return (int)(uHash % nTableSize);
}
/**Function*************************************************************
Synopsis [Refines nodes belonging to candidate constant class.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_Sim2ProcessRefined( Gia_Sim2_t * p, Vec_Int_t * vRefined )
{
unsigned * pSim;
int * pTable, nTableSize, i, k, Key;
if ( Vec_IntSize(vRefined) == 0 )
return;
nTableSize = Gia_PrimeCudd( 1000 + Vec_IntSize(vRefined) / 3 );
pTable = ABC_CALLOC( int, nTableSize );
Vec_IntForEachEntry( vRefined, i, k )
{
pSim = Gia_Sim2Data( p, i );
Key = Gia_Sim2HashKey( pSim, p->nWords, nTableSize );
if ( pTable[Key] == 0 )
{
assert( Gia_ObjRepr(p->pAig, i) == 0 );
assert( Gia_ObjNext(p->pAig, i) == 0 );
Gia_ObjSetRepr( p->pAig, i, GIA_VOID );
}
else
{
Gia_ObjSetNext( p->pAig, pTable[Key], i );
Gia_ObjSetRepr( p->pAig, i, Gia_ObjRepr(p->pAig, pTable[Key]) );
if ( Gia_ObjRepr(p->pAig, i) == GIA_VOID )
Gia_ObjSetRepr( p->pAig, i, pTable[Key] );
assert( Gia_ObjRepr(p->pAig, i) > 0 );
}
pTable[Key] = i;
}
/*
Vec_IntForEachEntry( vRefined, i, k )
{
if ( Gia_ObjIsHead( p->pAig, i ) )
Gia_Sim2ClassRefineOne( p, i );
}
*/
ABC_FREE( pTable );
}
/**Function*************************************************************
Synopsis [Refines equivalences after one simulation round.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_Sim2InfoRefineEquivs( Gia_Sim2_t * p )
{
Vec_Int_t * vRefined;
Gia_Obj_t * pObj;
unsigned * pSim;
int i, Count = 0;
// process constant candidates
vRefined = Vec_IntAlloc( 100 );
Gia_ManForEachObj1( p->pAig, pObj, i )
{
if ( !Gia_ObjIsConst(p->pAig, i) )
continue;
pSim = Gia_Sim2Data( p, i );
//Extra_PrintBinary( stdout, pSim, 32 * p->nWords ); printf( "\n" );
if ( !Gia_Sim2CompareZero( pSim, p->nWords, Gia_ObjPhase(pObj) ) )
{
Vec_IntPush( vRefined, i );
Count++;
}
}
Gia_Sim2ProcessRefined( p, vRefined );
Vec_IntFree( vRefined );
// process other classes
Gia_ManForEachClass( p->pAig, i )
Count += Gia_Sim2ClassRefineOne( p, i );
// if ( Count )
// printf( "Refined %d times.\n", Count );
}
/**Function*************************************************************
Synopsis [Returns index of the first pattern that failed.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Gia_Sim2InfoIsZero( Gia_Sim2_t * p, unsigned * pInfo )
{
int w;
for ( w = 0; w < p->nWords; w++ )
if ( pInfo[w] )
return 32*w + Gia_WordFindFirstBit( pInfo[w] );
return -1;
}
/**Function*************************************************************
Synopsis [Returns index of the PO and pattern that failed it.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Gia_Sim2CheckPos( Gia_Sim2_t * p, int * piPo, int * piPat )
{
Gia_Obj_t * pObj;
int i, iPat;
Gia_ManForEachPo( p->pAig, pObj, i )
{
iPat = Gia_Sim2InfoIsZero( p, Gia_Sim2Data( p, Gia_ObjValue(pObj) ) );
if ( iPat >= 0 )
{
*piPo = i;
*piPat = iPat;
return 1;
}
}
return 0;
}
/**Function*************************************************************
Synopsis [Returns the counter-example.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Abc_Cex_t * Gia_Sim2GenerateCounter( Gia_Man_t * pAig, int iFrame, int iOut, int nWords, int iPat )
{
Abc_Cex_t * p;
unsigned * pData;
int f, i, w, Counter;
p = Gia_ManAllocCounterExample( Gia_ManRegNum(pAig), Gia_ManPiNum(pAig), iFrame+1 );
p->iFrame = iFrame;
p->iPo = iOut;
// fill in the binary data
Counter = p->nRegs;
pData = ABC_ALLOC( unsigned, nWords );
for ( f = 0; f <= iFrame; f++, Counter += p->nPis )
for ( i = 0; i < Gia_ManPiNum(pAig); i++ )
{
for ( w = nWords-1; w >= 0; w-- )
pData[w] = Gia_ManRandom( 0 );
if ( Gia_InfoHasBit( pData, iPat ) )
Gia_InfoSetBit( p->pData, Counter + i );
}
ABC_FREE( pData );
return p;
}
/**Function*************************************************************
Synopsis [Performs simulation to refine equivalence classes.]
Description [Returns 1 if counter-example is detected.]
SideEffects []
SeeAlso []
***********************************************************************/
int Gia_ManSimSimulateEquiv( Gia_Man_t * pAig, Gia_ParSim_t * pPars )
{
Gia_Sim2_t * p;
Gia_Obj_t * pObj;
int i, clkTotal = clock();
int RetValue = 0, iOut, iPat;
assert( pAig->pReprs && pAig->pNexts );
ABC_FREE( pAig->pCexSeq );
p = Gia_Sim2Create( pAig, pPars );
Gia_ManResetRandom( pPars );
Gia_ManForEachRo( p->pAig, pObj, i )
Gia_Sim2InfoZero( p, Gia_Sim2Data(p, Gia_ObjValue(pObj)) );
for ( i = 0; i < pPars->nIters; i++ )
{
Gia_Sim2SimulateRound( p );
if ( pPars->fVerbose )
{
Abc_Print( 1, "Frame %4d out of %4d and timeout %3d sec. ", i+1, pPars->nIters, pPars->TimeLimit );
if ( pAig->pReprs && pAig->pNexts )
Abc_Print( 1, "Lits = %4d. ", Gia_ManEquivCountLitsAll(pAig) );
Abc_Print( 1, "Time = %7.2f sec\r", (1.0*clock()-clkTotal)/CLOCKS_PER_SEC );
}
if ( pPars->fCheckMiter && Gia_Sim2CheckPos( p, &iOut, &iPat ) )
{
Gia_ManResetRandom( pPars );
pPars->iOutFail = iOut;
pAig->pCexSeq = Gia_Sim2GenerateCounter( pAig, i, iOut, p->nWords, iPat );
Abc_Print( 1, "Networks are NOT EQUIVALENT. Output %d was asserted in frame %d. ", iOut, i );
if ( !Gia_ManVerifyCounterExample( pAig, pAig->pCexSeq, 0 ) )
{
// Abc_Print( 1, "\n" );
Abc_Print( 1, "\nGenerated counter-example is INVALID. " );
// Abc_Print( 1, "\n" );
}
else
{
// Abc_Print( 1, "\n" );
// if ( pPars->fVerbose )
// Abc_Print( 1, "\nGenerated counter-example is verified correctly. " );
// Abc_Print( 1, "\n" );
}
RetValue = 1;
break;
}
if ( pAig->pReprs && pAig->pNexts )
Gia_Sim2InfoRefineEquivs( p );
if ( (clock() - clkTotal)/CLOCKS_PER_SEC >= pPars->TimeLimit )
{
i++;
break;
}
if ( i < pPars->nIters - 1 )
Gia_Sim2InfoTransfer( p );
}
Gia_Sim2Delete( p );
if ( pAig->pCexSeq == NULL )
Abc_Print( 1, "No bug detected after simulating %d frames with %d words. ", i, pPars->nWords );
Abc_PrintTime( 1, "Time", clock() - clkTotal );
return RetValue;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END
/**CFile****************************************************************
FileName [saigTempor.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Sequential AIG package.]
Synopsis [Temporal decomposition.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: saigTempor.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
#include "saig.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Creates initialized timeframes for temporal decomposition.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Aig_Man_t * Saig_ManTemporFrames( Aig_Man_t * pAig, int nFrames )
{
Aig_Man_t * pFrames;
Aig_Obj_t * pObj, * pObjLi, * pObjLo;
int i, f;
// start the frames package
Aig_ManCleanData( pAig );
pFrames = Aig_ManStart( Aig_ManObjNumMax(pAig) * nFrames );
pFrames->pName = Aig_UtilStrsav( pAig->pName );
// initiliaze the flops
Saig_ManForEachLo( pAig, pObj, i )
pObj->pData = Aig_ManConst0(pFrames);
// for each timeframe
for ( f = 0; f < nFrames; f++ )
{
Aig_ManConst1(pAig)->pData = Aig_ManConst1(pFrames);
Saig_ManForEachPi( pAig, pObj, i )
pObj->pData = Aig_ObjCreatePi(pFrames);
Aig_ManForEachNode( pAig, pObj, i )
pObj->pData = Aig_And( pFrames, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
Aig_ManForEachPo( pAig, pObj, i )
pObj->pData = Aig_ObjChild0Copy(pObj);
Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i )
pObjLo->pData = pObjLi->pData;
}
// create POs for the flop inputs
Saig_ManForEachLi( pAig, pObj, i )
Aig_ObjCreatePo( pFrames, pObj->pData );
Aig_ManCleanup( pFrames );
return pFrames;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Aig_Man_t * Saig_ManTemporDecompose( Aig_Man_t * pAig, int nFrames )
{
Aig_Man_t * pAigNew, * pFrames;
Aig_Obj_t * pObj, * pReset;
int i;
if ( pAig->nConstrs > 0 )
{
printf( "The AIG manager should have no constraints.\n" );
return NULL;
}
// create initialized timeframes
pFrames = Saig_ManTemporFrames( pAig, nFrames );
assert( Aig_ManPoNum(pFrames) == Aig_ManRegNum(pAig) );
// start the new manager
Aig_ManCleanData( pAig );
pAigNew = Aig_ManStart( Aig_ManNodeNum(pAig) );
pAigNew->pName = Aig_UtilStrsav( pAig->pName );
// map the constant node and primary inputs
Aig_ManConst1(pAig)->pData = Aig_ManConst1( pAigNew );
Saig_ManForEachPi( pAig, pObj, i )
pObj->pData = Aig_ObjCreatePi( pAigNew );
// insert initialization logic
Aig_ManConst1(pFrames)->pData = Aig_ManConst1( pAigNew );
Aig_ManForEachPi( pFrames, pObj, i )
pObj->pData = Aig_ObjCreatePi( pAigNew );
Aig_ManForEachNode( pFrames, pObj, i )
pObj->pData = Aig_And( pAigNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
Aig_ManForEachPo( pFrames, pObj, i )
pObj->pData = Aig_ObjChild0Copy(pObj);
// create reset latch (the first one among the latches)
pReset = Aig_ObjCreatePi( pAigNew );
// create flop output values
Saig_ManForEachLo( pAig, pObj, i )
pObj->pData = Aig_Mux( pAigNew, pReset, Aig_ObjCreatePi(pAigNew), Aig_ManPo(pFrames, i)->pData );
Aig_ManStop( pFrames );
// add internal nodes of this frame
Aig_ManForEachNode( pAig, pObj, i )
pObj->pData = Aig_And( pAigNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
// create primary outputs
Saig_ManForEachPo( pAig, pObj, i )
Aig_ObjCreatePo( pAigNew, Aig_ObjChild0Copy(pObj) );
// create reset latch (the first one among the latches)
Aig_ObjCreatePo( pAigNew, Aig_ManConst1(pAigNew) );
// create latch inputs
Saig_ManForEachLi( pAig, pObj, i )
Aig_ObjCreatePo( pAigNew, Aig_ObjChild0Copy(pObj) );
// finalize
Aig_ManCleanup( pAigNew );
Aig_ManSetRegNum( pAigNew, Aig_ManRegNum(pAig)+1 ); // + reset latch (011111...)
return pAigNew;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Aig_Man_t * Saig_ManTempor( Aig_Man_t * pAig, int nFrames, int TimeOut, int nConfLimit, int fUseBmc, int fVerbose, int fVeryVerbose )
{
extern int Saig_ManPhasePrefixLength( Aig_Man_t * p, int fVerbose, int fVeryVerbose );
int RetValue, nFramesFinished = -1;
assert( nFrames >= 0 );
if ( nFrames == 0 )
{
nFrames = Saig_ManPhasePrefixLength( pAig, fVerbose, fVeryVerbose );
if ( nFrames == 1 )
{
printf( "The leading sequence has length 1. Temporal decomposition is not performed.\n" );
return NULL;
}
Abc_Print( 1, "Using computed frame number (%d).\n", nFrames );
}
else
Abc_Print( 1, "Using user-given frame number (%d).\n", nFrames );
// run BMC2
if ( fUseBmc )
{
RetValue = Saig_BmcPerform( pAig, 0, nFrames, 5000, TimeOut, nConfLimit, 0, fVerbose, 0, &nFramesFinished );
if ( RetValue == 0 )
{
printf( "A cex found in the first %d frames.\n", nFrames );
return NULL;
}
if ( nFramesFinished < nFrames )
{
printf( "BMC for %d frames could not be completed. A cex may exist!\n", nFrames );
return NULL;
}
}
return Saig_ManTemporDecompose( pAig, nFrames );
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END
SRC += src/sat/pdr/pdr.c \
src/sat/pdr/pdrCnf.c \
src/sat/pdr/pdrCore.c \
src/sat/pdr/pdrInv.c \
src/sat/pdr/pdrMan.c \
src/sat/pdr/pdrSat.c \
src/sat/pdr/pdrTsim.c \
src/sat/pdr/pdrUtil.c
/**CFile****************************************************************
FileName [pdr.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Netlist representation.]
Synopsis []
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - November 20, 2010.]
Revision [$Id: pdr.c,v 1.00 2010/11/20 00:00:00 alanmi Exp $]
***********************************************************************/
#include "pdrInt.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END
/**CFile****************************************************************
FileName [pdr.h]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Netlist representation.]
Synopsis [External declarations.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - November 20, 2010.]
Revision [$Id: pdr.h,v 1.00 2010/11/20 00:00:00 alanmi Exp $]
***********************************************************************/
#ifndef __PDR_H__
#define __PDR_H__
ABC_NAMESPACE_HEADER_START
////////////////////////////////////////////////////////////////////////
/// INCLUDES ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// PARAMETERS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// BASIC TYPES ///
////////////////////////////////////////////////////////////////////////
typedef struct Pdr_Par_t_ Pdr_Par_t;
struct Pdr_Par_t_
{
int iOutput; // zero-based number of primary output to solve
int nRecycle; // limit on vars for recycling
int nFrameMax; // limit on frame count
int nConfLimit; // limit on SAT solver conflicts
int nTimeOut; // timeout in seconds
int fTwoRounds; // use two rounds for generalization
int fMonoCnf; // monolythic CNF
int fDumpInv; // dump inductive invariant
int fShortest; // forces bug traces to be shortest
int fVerbose; // verbose output
int fVeryVerbose; // very verbose output
};
////////////////////////////////////////////////////////////////////////
/// MACRO DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// FUNCTION DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
/*=== pdrCore.c ==========================================================*/
extern void Pdr_ManSetDefaultParams( Pdr_Par_t * pPars );
extern int Pdr_ManSolve( Aig_Man_t * p, Pdr_Par_t * pPars, Abc_Cex_t ** ppCex );
ABC_NAMESPACE_HEADER_END
#endif
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
/**CFile****************************************************************
FileName [pdrClass.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Netlist representation.]
Synopsis [Equivalence classes of register outputs.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - November 20, 2010.]
Revision [$Id: pdrClass.c,v 1.00 2010/11/20 00:00:00 alanmi Exp $]
***********************************************************************/
#include "pdrInt.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Performs duplication with the variable map.]
Description [Var map contains -1 if const0 and <reg_num> otherwise.]
SideEffects []
SeeAlso []
***********************************************************************/
Aig_Man_t * Pdr_ManRehashWithMap( Aig_Man_t * pAig, Vec_Int_t * vMap )
{
Aig_Man_t * pFrames;
Aig_Obj_t * pObj;
int i, iReg;
assert( Vec_IntSize(vMap) == Aig_ManRegNum(pAig) );
// start the fraig package
pFrames = Aig_ManStart( Aig_ManObjNumMax(pAig) );
pFrames->pName = Aig_UtilStrsav( pAig->pName );
pFrames->pSpec = Aig_UtilStrsav( pAig->pSpec );
// create CI mapping
Aig_ManCleanData( pAig );
Aig_ManConst1(pAig)->pData = Aig_ManConst1(pFrames);
Aig_ManForEachPi( pAig, pObj, i )
pObj->pData = Aig_ObjCreatePi(pFrames);
Saig_ManForEachLo( pAig, pObj, i )
{
iReg = Vec_IntEntry(vMap, i);
if ( iReg == -1 )
pObj->pData = Aig_ManConst0(pFrames);
else
pObj->pData = Saig_ManLo(pAig, iReg)->pData;
}
// add internal nodes of this frame
Aig_ManForEachNode( pAig, pObj, i )
pObj->pData = Aig_And( pFrames, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
// add output nodes
Aig_ManForEachPo( pAig, pObj, i )
pObj->pData = Aig_ObjCreatePo( pFrames, Aig_ObjChild0Copy(pObj) );
// finish off
Aig_ManCleanup( pFrames );
Aig_ManSetRegNum( pFrames, Aig_ManRegNum(pAig) );
return pFrames;
}
/**Function*************************************************************
Synopsis [Creates mapping of registers.]
Description [Var map contains -1 if const0 and <reg_num> otherwise.]
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Int_t * Pdr_ManCreateMap( Aig_Man_t * p )
{
Aig_Obj_t * pObj;
Vec_Int_t * vMap;
int * pLit2Id, Lit, i;
pLit2Id = ABC_ALLOC( int, Aig_ManObjNumMax(p) * 2 );
for ( i = 0; i < Aig_ManObjNumMax(p) * 2; i++ )
pLit2Id[i] = -1;
vMap = Vec_IntAlloc( Aig_ManRegNum(p) );
Saig_ManForEachLi( p, pObj, i )
{
if ( Aig_ObjChild0(pObj) == Aig_ManConst0(p) )
{
Vec_IntPush( vMap, -1 );
continue;
}
Lit = 2 * Aig_ObjFaninId0(pObj) + Aig_ObjFaninC0(pObj);
if ( pLit2Id[Lit] < 0 ) // the first time
pLit2Id[Lit] = i;
Vec_IntPush( vMap, pLit2Id[Lit] );
}
ABC_FREE( pLit2Id );
return vMap;
}
/**Function*************************************************************
Synopsis [Counts reduced registers.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Pdr_ManCountMap( Vec_Int_t * vMap )
{
int i, Entry, Counter = 0;
Vec_IntForEachEntry( vMap, Entry, i )
if ( Entry != i )
Counter++;
return Counter;
}
/**Function*************************************************************
Synopsis [Counts reduced registers.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Pdr_ManPrintMap( Vec_Int_t * vMap )
{
Vec_Int_t * vMarks;
int f, i, iClass, Entry, Counter = 0;
printf( " Consts: " );
Vec_IntForEachEntry( vMap, Entry, i )
if ( Entry == -1 )
printf( "%d ", i );
printf( "\n" );
vMarks = Vec_IntAlloc( 100 );
Vec_IntForEachEntry( vMap, iClass, f )
{
if ( iClass == -1 )
continue;
if ( iClass == f )
continue;
// check previous classes
if ( Vec_IntFind( vMarks, iClass ) >= 0 )
continue;
Vec_IntPush( vMarks, iClass );
// print class
printf( " Class %d : ", iClass );
Vec_IntForEachEntry( vMap, Entry, i )
if ( Entry == iClass )
printf( "%d ", i );
printf( "\n" );
}
Vec_IntFree( vMarks );
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Pdr_ManEquivClasses( Aig_Man_t * pAig )
{
Vec_Int_t * vMap;
Aig_Man_t * pTemp;
int f, nFrames = 100;
assert( Saig_ManRegNum(pAig) > 0 );
// start the map
vMap = Vec_IntAlloc( 0 );
Vec_IntFill( vMap, Aig_ManRegNum(pAig), -1 );
// iterate and print changes
for ( f = 0; f < nFrames; f++ )
{
// implement variable map
pTemp = Pdr_ManRehashWithMap( pAig, vMap );
// report the result
printf( "F =%4d : Total = %6d. Nodes = %6d. RedRegs = %6d. Prop = %s\n",
f+1, Aig_ManNodeNum(pAig), Aig_ManNodeNum(pTemp), Pdr_ManCountMap(vMap),
Aig_ObjChild0(Aig_ManPo(pTemp,0)) == Aig_ManConst0(pTemp) ? "proof" : "unknown" );
// recreate the map
Pdr_ManPrintMap( vMap );
Vec_IntFree( vMap );
vMap = Pdr_ManCreateMap( pTemp );
Aig_ManStop( pTemp );
if ( Pdr_ManCountMap(vMap) == 0 )
break;
}
Vec_IntFree( vMap );
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END
/**CFile****************************************************************
FileName [pdrCnf.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Netlist representation.]
Synopsis [CNF computation on demand.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - November 20, 2010.]
Revision [$Id: pdrCnf.c,v 1.00 2010/11/20 00:00:00 alanmi Exp $]
***********************************************************************/
#include "pdrInt.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
/*
The CNF (p->pCnf2) is expressed in terms of object IDs.
Each node in the CNF is marked if it has clauses (p->pCnf2->pObj2Count[Id] > 0).
Each node in the CNF has the first clause (p->pCnf2->pObj2Clause)
and the number of clauses (p->pCnf2->pObj2Count).
Each node used in a CNF of any timeframe has its SAT var recorded.
Each frame has a reserve mapping of SAT variables into ObjIds.
*/
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Returns SAT variable of the given object.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Pdr_ObjSatVar1( Pdr_Man_t * p, int k, Aig_Obj_t * pObj )
{
return p->pCnf1->pVarNums[ Aig_ObjId(pObj) ];
}
/**Function*************************************************************
Synopsis [Returns SAT variable of the given object.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Pdr_ObjSatVar2FindOrAdd( Pdr_Man_t * p, int k, Aig_Obj_t * pObj )
{
assert( p->pCnf2->pObj2Count[Aig_ObjId(pObj)] >= 0 );
if ( p->pvId2Vars[Aig_ObjId(pObj)] == NULL )
p->pvId2Vars[Aig_ObjId(pObj)] = Vec_IntStart( 16 );
if ( Vec_IntGetEntry( p->pvId2Vars[Aig_ObjId(pObj)], k ) == 0 )
{
sat_solver * pSat = Pdr_ManSolver(p, k);
Vec_Int_t * vVar2Ids = (Vec_Int_t *)Vec_PtrEntry(p->vVar2Ids, k);
int iVarNew = Vec_IntSize( vVar2Ids );
assert( iVarNew > 0 );
Vec_IntPush( vVar2Ids, Aig_ObjId(pObj) );
Vec_IntWriteEntry( p->pvId2Vars[Aig_ObjId(pObj)], k, iVarNew );
sat_solver_setnvars( pSat, iVarNew + 1 );
if ( k == 0 && Saig_ObjIsLo(p->pAig, pObj) ) // initialize the register output
{
int Lit = toLitCond( iVarNew, 1 );
int RetValue = sat_solver_addclause( pSat, &Lit, &Lit + 1 );
assert( RetValue == 1 );
sat_solver_compress( pSat );
}
}
return Vec_IntEntry( p->pvId2Vars[Aig_ObjId(pObj)], k );
}
/**Function*************************************************************
Synopsis [Recursively adds CNF for the given object.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Pdr_ObjSatVar2( Pdr_Man_t * p, int k, Aig_Obj_t * pObj )
{
sat_solver * pSat;
Vec_Int_t * vLits;
Vec_Int_t * vVar2Ids = (Vec_Int_t *)Vec_PtrEntry(p->vVar2Ids, k);
int nVarCount = Vec_IntSize(vVar2Ids);
int iVarThis = Pdr_ObjSatVar2FindOrAdd( p, k, pObj );
int * pLit, i, iVar, nClauses, iFirstClause, RetValue;
if ( nVarCount == Vec_IntSize(vVar2Ids) )
return iVarThis;
assert( nVarCount + 1 == Vec_IntSize(vVar2Ids) );
if ( Aig_ObjIsPi(pObj) )
return iVarThis;
nClauses = p->pCnf2->pObj2Count[Aig_ObjId(pObj)];
iFirstClause = p->pCnf2->pObj2Clause[Aig_ObjId(pObj)];
assert( nClauses > 0 );
pSat = Pdr_ManSolver(p, k);
vLits = Vec_IntAlloc( 16 );
for ( i = iFirstClause; i < iFirstClause + nClauses; i++ )
{
Vec_IntClear( vLits );
for ( pLit = p->pCnf2->pClauses[i]; pLit < p->pCnf2->pClauses[i+1]; pLit++ )
{
iVar = Pdr_ObjSatVar2( p, k, Aig_ManObj(p->pAig, lit_var(*pLit)) );
Vec_IntPush( vLits, toLitCond( iVar, lit_sign(*pLit) ) );
}
RetValue = sat_solver_addclause( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits)+Vec_IntSize(vLits) );
assert( RetValue );
}
Vec_IntFree( vLits );
return iVarThis;
}
/**Function*************************************************************
Synopsis [Returns SAT variable of the given object.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Pdr_ObjSatVar( Pdr_Man_t * p, int k, Aig_Obj_t * pObj )
{
if ( p->pPars->fMonoCnf )
return Pdr_ObjSatVar1( p, k, pObj );
else
return Pdr_ObjSatVar2( p, k, pObj );
}
/**Function*************************************************************
Synopsis [Returns register number for the given SAT variable.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Pdr_ObjRegNum1( Pdr_Man_t * p, int k, int iSatVar )
{
int RegId;
assert( iSatVar >= 0 );
// consider the case of auxiliary variable
if ( iSatVar >= p->pCnf1->nVars )
return -1;
// consider the case of register output
RegId = Vec_IntEntry( p->vVar2Reg, iSatVar );
assert( RegId >= 0 && RegId < Aig_ManRegNum(p->pAig) );
return RegId;
}
/**Function*************************************************************
Synopsis [Returns register number for the given SAT variable.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Pdr_ObjRegNum2( Pdr_Man_t * p, int k, int iSatVar )
{
Aig_Obj_t * pObj;
int ObjId;
Vec_Int_t * vVar2Ids = (Vec_Int_t *)Vec_PtrEntry(p->vVar2Ids, k);
assert( iSatVar > 0 && iSatVar < Vec_IntSize(vVar2Ids) );
ObjId = Vec_IntEntry( vVar2Ids, iSatVar );
if ( ObjId == -1 ) // activation variable
return -1;
pObj = Aig_ManObj( p->pAig, ObjId );
if ( Saig_ObjIsLi( p->pAig, pObj ) )
return Aig_ObjPioNum(pObj)-Saig_ManPoNum(p->pAig);
assert( 0 ); // should be called for register inputs only
return -1;
}
/**Function*************************************************************
Synopsis [Returns register number for the given SAT variable.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Pdr_ObjRegNum( Pdr_Man_t * p, int k, int iSatVar )
{
if ( p->pPars->fMonoCnf )
return Pdr_ObjRegNum1( p, k, iSatVar );
else
return Pdr_ObjRegNum2( p, k, iSatVar );
}
/**Function*************************************************************
Synopsis [Returns the index of unused SAT variable.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Pdr_ManFreeVar( Pdr_Man_t * p, int k )
{
if ( p->pPars->fMonoCnf )
return sat_solver_nvars( Pdr_ManSolver(p, k) );
else
{
Vec_Int_t * vVar2Ids = (Vec_Int_t *)Vec_PtrEntry( p->vVar2Ids, k );
Vec_IntPush( vVar2Ids, -1 );
return Vec_IntSize( vVar2Ids ) - 1;
}
}
/**Function*************************************************************
Synopsis [Creates SAT solver.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline sat_solver * Pdr_ManNewSolver1( Pdr_Man_t * p, int k, int fInit )
{
sat_solver * pSat;
Aig_Obj_t * pObj;
int i;
if ( p->pCnf1 == NULL )
{
int nRegs = p->pAig->nRegs;
p->pAig->nRegs = Aig_ManPoNum(p->pAig);
p->pCnf1 = Cnf_Derive( p->pAig, Aig_ManPoNum(p->pAig) );
p->pAig->nRegs = nRegs;
assert( p->vVar2Reg == NULL );
p->vVar2Reg = Vec_IntStartFull( p->pCnf1->nVars );
Saig_ManForEachLi( p->pAig, pObj, i )
Vec_IntWriteEntry( p->vVar2Reg, Pdr_ObjSatVar(p, k, pObj), i );
}
pSat = (sat_solver *)Cnf_DataWriteIntoSolver( p->pCnf1, 1, fInit );
return pSat;
}
/**Function*************************************************************
Synopsis [Creates SAT solver.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline sat_solver * Pdr_ManNewSolver2( Pdr_Man_t * p, int k, int fInit )
{
sat_solver * pSat;
Vec_Int_t * vVar2Ids;
int i, Entry;
if ( p->pCnf2 == NULL )
{
p->pCnf2 = Cnf_DeriveOther( p->pAig );
p->pvId2Vars = ABC_CALLOC( Vec_Int_t *, Aig_ManObjNumMax(p->pAig) );
p->vVar2Ids = Vec_PtrAlloc( 256 );
}
// update the variable mapping
vVar2Ids = (Vec_Int_t *)Vec_PtrGetEntry( p->vVar2Ids, k );
if ( vVar2Ids == NULL )
{
vVar2Ids = Vec_IntAlloc( 500 );
Vec_PtrWriteEntry( p->vVar2Ids, k, vVar2Ids );
}
Vec_IntForEachEntry( vVar2Ids, Entry, i )
{
if ( Entry == -1 )
continue;
assert( Vec_IntEntry( p->pvId2Vars[Entry], k ) > 0 );
Vec_IntWriteEntry( p->pvId2Vars[Entry], k, 0 );
}
Vec_IntClear( vVar2Ids );
Vec_IntPush( vVar2Ids, -1 );
// start the SAT solver
pSat = sat_solver_new();
sat_solver_setnvars( pSat, 500 );
return pSat;
}
/**Function*************************************************************
Synopsis [Creates SAT solver.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
sat_solver * Pdr_ManNewSolver( Pdr_Man_t * p, int k, int fInit )
{
if ( p->pPars->fMonoCnf )
return Pdr_ManNewSolver1( p, k, fInit );
else
return Pdr_ManNewSolver2( p, k, fInit );
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END
/**CFile****************************************************************
FileName [pdrCore.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Netlist representation.]
Synopsis [Core procedures.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - November 20, 2010.]
Revision [$Id: pdrCore.c,v 1.00 2010/11/20 00:00:00 alanmi Exp $]
***********************************************************************/
#include "pdrInt.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Returns 1 if the state could be blocked.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Pdr_ManSetDefaultParams( Pdr_Par_t * pPars )
{
memset( pPars, 0, sizeof(Pdr_Par_t) );
pPars->iOutput = -1; // zero-based output number
pPars->nRecycle = 300; // limit on vars for recycling
pPars->nFrameMax = 5000; // limit on number of timeframes
pPars->nTimeOut = 0; // timeout in seconds
pPars->nConfLimit = 100000; // limit on SAT solver conflicts
pPars->fTwoRounds = 0; // use two rounds for generalization
pPars->fMonoCnf = 0; // monolythic CNF
pPars->fDumpInv = 0; // dump inductive invariant
pPars->fShortest = 0; // forces bug traces to be shortest
pPars->fVerbose = 0; // verbose output
pPars->fVeryVerbose = 0; // very verbose output
}
/**Function*************************************************************
Synopsis [Reduces clause using analyzeFinal.]
Description [Assumes that the SAT solver just terminated an UNSAT call.]
SideEffects []
SeeAlso []
***********************************************************************/
Pdr_Set_t * Pdr_ManReduceClause( Pdr_Man_t * p, int k, Pdr_Set_t * pCube )
{
Pdr_Set_t * pCubeMin;
Vec_Int_t * vLits;
int i, Entry, nCoreLits, * pCoreLits;
// get relevant SAT literals
nCoreLits = sat_solver_final(Pdr_ManSolver(p, k), &pCoreLits);
// translate them into register literals and remove auxiliary
vLits = Pdr_ManLitsToCube( p, k, pCoreLits, nCoreLits );
// skip if there is no improvement
if ( Vec_IntSize(vLits) == pCube->nLits )
return NULL;
assert( Vec_IntSize(vLits) < pCube->nLits );
// if the cube overlaps with init, add any literal
Vec_IntForEachEntry( vLits, Entry, i )
if ( lit_sign(Entry) == 0 ) // positive literal
break;
if ( i == Vec_IntSize(vLits) ) // only negative literals
{
// add the first positive literal
for ( i = 0; i < pCube->nLits; i++ )
if ( lit_sign(pCube->Lits[i]) == 0 ) // positive literal
{
Vec_IntPush( vLits, pCube->Lits[i] );
break;
}
assert( i < pCube->nLits );
}
// generate a starting cube
pCubeMin = Pdr_SetCreateSubset( pCube, Vec_IntArray(vLits), Vec_IntSize(vLits) );
assert( !Pdr_SetIsInit(pCubeMin, -1) );
/*
// make sure the cube works
{
int RetValue;
RetValue = Pdr_ManCheckCube( p, k, pCubeMin, NULL, 0 );
assert( RetValue );
}
*/
return pCubeMin;
}
/**Function*************************************************************
Synopsis [Returns 1 if the state could be blocked.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Pdr_ManPushClauses( Pdr_Man_t * p )
{
Pdr_Set_t * pTemp, * pCubeK, * pCubeK1;
Vec_Ptr_t * vArrayK, * vArrayK1;
int i, j, k, m, RetValue = 0, kMax = Vec_PtrSize(p->vSolvers)-1;
int Counter = 0;
int clk = clock();
Vec_VecForEachLevelStartStop( p->vClauses, vArrayK, k, 1, kMax-1 )
{
Vec_PtrSort( vArrayK, (int (*)(void))Pdr_SetCompare );
vArrayK1 = (Vec_Ptr_t *)Vec_VecEntry( p->vClauses, k+1 );
Vec_PtrForEachEntry( Pdr_Set_t *, vArrayK, pCubeK, j )
{
Counter++;
// remove cubes in the same frame that are contained by pCubeK
Vec_PtrForEachEntryStart( Pdr_Set_t *, vArrayK, pTemp, m, j+1 )
{
if ( !Pdr_SetContains( pTemp, pCubeK ) ) // pCubeK contains pTemp
continue;
Pdr_SetDeref( pTemp );
Vec_PtrWriteEntry( vArrayK, m, Vec_PtrEntryLast(vArrayK) );
Vec_PtrPop(vArrayK);
m--;
}
// check if the clause can be moved to the next frame
if ( !Pdr_ManCheckCube( p, k, pCubeK, NULL, 0 ) )
continue;
{
Pdr_Set_t * pCubeMin;
pCubeMin = Pdr_ManReduceClause( p, k, pCubeK );
if ( pCubeMin != NULL )
{
// printf( "%d ", pCubeK->nLits - pCubeMin->nLits );
Pdr_SetDeref( pCubeK );
pCubeK = pCubeMin;
}
}
// if it can be moved, add it to the next frame
Pdr_ManSolverAddClause( p, k+1, pCubeK );
// check if the clause subsumes others
Vec_PtrForEachEntry( Pdr_Set_t *, vArrayK1, pCubeK1, i )
{
if ( !Pdr_SetContains( pCubeK1, pCubeK ) ) // pCubeK contains pCubeK1
continue;
Pdr_SetDeref( pCubeK1 );
Vec_PtrWriteEntry( vArrayK1, i, Vec_PtrEntryLast(vArrayK1) );
Vec_PtrPop(vArrayK1);
i--;
}
// add the last clause
Vec_PtrPush( vArrayK1, pCubeK );
Vec_PtrWriteEntry( vArrayK, j, Vec_PtrEntryLast(vArrayK) );
Vec_PtrPop(vArrayK);
j--;
}
if ( Vec_PtrSize(vArrayK) == 0 )
RetValue = 1;
}
// clean up the last one
vArrayK = (Vec_Ptr_t *)Vec_VecEntry( p->vClauses, kMax );
Vec_PtrSort( vArrayK, (int (*)(void))Pdr_SetCompare );
Vec_PtrForEachEntry( Pdr_Set_t *, vArrayK, pCubeK, j )
{
// remove cubes in the same frame that are contained by pCubeK
Vec_PtrForEachEntryStart( Pdr_Set_t *, vArrayK, pTemp, m, j+1 )
{
if ( !Pdr_SetContains( pTemp, pCubeK ) ) // pCubeK contains pTemp
continue;
/*
printf( "===\n" );
Pdr_SetPrint( stdout, pCubeK, Aig_ManRegNum(p->pAig), NULL );
printf( "\n" );
Pdr_SetPrint( stdout, pTemp, Aig_ManRegNum(p->pAig), NULL );
printf( "\n" );
*/
Pdr_SetDeref( pTemp );
Vec_PtrWriteEntry( vArrayK, m, Vec_PtrEntryLast(vArrayK) );
Vec_PtrPop(vArrayK);
m--;
}
}
p->tPush += clock() - clk;
return RetValue;
}
/**Function*************************************************************
Synopsis [Returns 1 if the clause is contained in higher clauses.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Pdr_ManCheckContainment( Pdr_Man_t * p, int k, Pdr_Set_t * pSet )
{
Pdr_Set_t * pThis;
Vec_Ptr_t * vArrayK;
int i, j, kMax = Vec_PtrSize(p->vSolvers)-1;
Vec_VecForEachLevelStartStop( p->vClauses, vArrayK, i, k, kMax )
Vec_PtrForEachEntry( Pdr_Set_t *, vArrayK, pThis, j )
if ( Pdr_SetContains( pSet, pThis ) )
return 1;
return 0;
}
/**Function*************************************************************
Synopsis [Sorts literals by priority.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int * Pdr_ManSortByPriority( Pdr_Man_t * p, Pdr_Set_t * pCube )
{
int * pPrios = Vec_IntArray(p->vPrio);
int * pArray = p->pOrder;
int temp, i, j, best_i, nSize = pCube->nLits;
// initialize variable order
for ( i = 0; i < nSize; i++ )
pArray[i] = i;
for ( i = 0; i < nSize-1; i++ )
{
best_i = i;
for ( j = i+1; j < nSize; j++ )
// if ( pArray[j] < pArray[best_i] )
if ( pPrios[pCube->Lits[pArray[j]]>>1] < pPrios[pCube->Lits[pArray[best_i]]>>1] )
best_i = j;
temp = pArray[i];
pArray[i] = pArray[best_i];
pArray[best_i] = temp;
}
/*
for ( i = 0; i < pCube->nLits; i++ )
printf( "%2d : %5d %5d %5d\n", i, pArray[i], pCube->Lits[pArray[i]]>>1, pPrios[pCube->Lits[pArray[i]]>>1] );
printf( "\n" );
*/
return pArray;
}
/**Function*************************************************************
Synopsis [Returns 1 if the state could be blocked.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Pdr_ManGeneralize( Pdr_Man_t * p, int k, Pdr_Set_t * pCube, Pdr_Set_t ** ppPred, Pdr_Set_t ** ppCubeMin )
{
Pdr_Set_t * pCubeMin, * pCubeTmp = NULL;
int i, j, n, Lit, RetValue, clk = clock();
int * pOrder;
// if there is no induction, return
*ppCubeMin = NULL;
RetValue = Pdr_ManCheckCube( p, k, pCube, ppPred, p->pPars->nConfLimit );
if ( RetValue == -1 )
return -1;
if ( RetValue == 0 )
{
p->tGeneral += clock() - clk;
return 0;
}
// reduce clause using assumptions
// pCubeMin = Pdr_SetDup( pCube );
pCubeMin = Pdr_ManReduceClause( p, k, pCube );
if ( pCubeMin == NULL )
pCubeMin = Pdr_SetDup( pCube );
// sort literals by their occurences
pOrder = Pdr_ManSortByPriority( p, pCubeMin );
// try removing literals
for ( j = 0; j < pCubeMin->nLits; j++ )
{
// use ordering
// i = j;
i = pOrder[j];
// check init state
assert( pCubeMin->Lits[i] != -1 );
if ( Pdr_SetIsInit(pCubeMin, i) )
continue;
// try removing this literal
Lit = pCubeMin->Lits[i]; pCubeMin->Lits[i] = -1;
RetValue = Pdr_ManCheckCube( p, k, pCubeMin, NULL, p->pPars->nConfLimit );
if ( RetValue == -1 )
{
Pdr_SetDeref( pCubeMin );
return -1;
}
pCubeMin->Lits[i] = Lit;
if ( RetValue == 0 )
continue;
// remove j-th entry
for ( n = j; n < pCubeMin->nLits-1; n++ )
pOrder[n] = pOrder[n+1];
j--;
// success - update the cube
pCubeMin = Pdr_SetCreateFrom( pCubeTmp = pCubeMin, i );
Pdr_SetDeref( pCubeTmp );
assert( pCubeMin->nLits > 0 );
i--;
// get the ordering by decreasing priorit
pOrder = Pdr_ManSortByPriority( p, pCubeMin );
}
if ( p->pPars->fTwoRounds )
for ( j = 0; j < pCubeMin->nLits; j++ )
{
// use ordering
// i = j;
i = pOrder[j];
// check init state
assert( pCubeMin->Lits[i] != -1 );
if ( Pdr_SetIsInit(pCubeMin, i) )
continue;
// try removing this literal
Lit = pCubeMin->Lits[i]; pCubeMin->Lits[i] = -1;
RetValue = Pdr_ManCheckCube( p, k, pCubeMin, NULL, p->pPars->nConfLimit );
if ( RetValue == -1 )
{
Pdr_SetDeref( pCubeMin );
return -1;
}
pCubeMin->Lits[i] = Lit;
if ( RetValue == 0 )
continue;
// remove j-th entry
for ( n = j; n < pCubeMin->nLits-1; n++ )
pOrder[n] = pOrder[n+1];
j--;
// success - update the cube
pCubeMin = Pdr_SetCreateFrom( pCubeTmp = pCubeMin, i );
Pdr_SetDeref( pCubeTmp );
assert( pCubeMin->nLits > 0 );
i--;
// get the ordering by decreasing priorit
pOrder = Pdr_ManSortByPriority( p, pCubeMin );
}
assert( ppCubeMin != NULL );
*ppCubeMin = pCubeMin;
p->tGeneral += clock() - clk;
return 1;
}
/**Function*************************************************************
Synopsis [Returns 1 if the state could be blocked.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Pdr_ManBlockCube( Pdr_Man_t * p, Pdr_Set_t * pCube )
{
Pdr_Obl_t * pThis;
Pdr_Set_t * pPred, * pCubeMin;
int i, k, RetValue, Prio = ABC_INFINITY, Counter = 0;
int kMax = Vec_PtrSize(p->vSolvers)-1, clk;
p->nBlocks++;
// create first proof obligation
assert( p->pQueue == NULL );
pThis = Pdr_OblStart( kMax, Prio--, pCube, NULL ); // consume ref
Pdr_QueuePush( p, pThis );
// try to solve it recursively
while ( !Pdr_QueueIsEmpty(p) )
{
Counter++;
pThis = Pdr_QueueHead( p );
if ( pThis->iFrame == 0 )
return 0; // SAT
pThis = Pdr_QueuePop( p );
assert( pThis->iFrame > 0 );
assert( !Pdr_SetIsInit(pThis->pState, -1) );
clk = clock();
if ( Pdr_ManCheckContainment( p, pThis->iFrame, pThis->pState ) )
{
p->tContain += clock() - clk;
Pdr_OblDeref( pThis );
continue;
}
p->tContain += clock() - clk;
// check if the cube is already contained
if ( Pdr_ManCheckCubeCs( p, pThis->iFrame, pThis->pState ) ) // cube is blocked by clauses in this frame
{
Pdr_OblDeref( pThis );
continue;
}
// check if the cube holds with relative induction
pCubeMin = NULL;
RetValue = Pdr_ManGeneralize( p, pThis->iFrame-1, pThis->pState, &pPred, &pCubeMin );
if ( RetValue == -1 )
{
Pdr_OblDeref( pThis );
return -1;
}
if ( RetValue ) // cube is blocked inductively in this frame
{
assert( pCubeMin != NULL );
// k is the last frame where pCubeMin holds
k = pThis->iFrame;
// check other frames
assert( pPred == NULL );
for ( k = pThis->iFrame; k < kMax; k++ )
if ( !Pdr_ManCheckCube( p, k, pCubeMin, NULL, 0 ) )
break;
// add new clause
if ( p->pPars->fVeryVerbose )
{
printf( "Adding cube " );
Pdr_SetPrint( stdout, pCubeMin, Aig_ManRegNum(p->pAig), NULL );
printf( " to frame %d.\n", k );
}
// set priority flops
for ( i = 0; i < pCubeMin->nLits; i++ )
{
assert( pCubeMin->Lits[i] >= 0 );
assert( (pCubeMin->Lits[i] / 2) < Aig_ManRegNum(p->pAig) );
Vec_IntAddToEntry( p->vPrio, pCubeMin->Lits[i] / 2, 1 );
}
Vec_VecPush( p->vClauses, k, pCubeMin ); // consume ref
p->nCubes++;
// add clause
for ( i = 1; i <= k; i++ )
Pdr_ManSolverAddClause( p, i, pCubeMin );
// schedule proof obligation
if ( k < kMax && !p->pPars->fShortest )
{
pThis->iFrame = k+1;
pThis->prio = Prio--;
Pdr_QueuePush( p, pThis );
}
else
{
Pdr_OblDeref( pThis );
}
}
else
{
assert( pCubeMin == NULL );
assert( pPred != NULL );
pThis->prio = Prio--;
Pdr_QueuePush( p, pThis );
pThis = Pdr_OblStart( pThis->iFrame-1, Prio--, pPred, Pdr_OblRef(pThis) );
Pdr_QueuePush( p, pThis );
}
// check the timeout
if ( p->timeToStop && clock() >= p->timeToStop )
return -1;
}
return 1;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Pdr_ManSolveInt( Pdr_Man_t * p )
{
int fPrintClauses = 0;
Pdr_Set_t * pCube;
int k, RetValue = -1;
int clkTotal = clock();
int clkStart = clock();
p->timeToStop = (p->pPars->nTimeOut == 0) ? 0 : clock() + (CLOCKS_PER_SEC * p->pPars->nTimeOut);
assert( Vec_PtrSize(p->vSolvers) == 0 );
// create the first timeframe
Pdr_ManCreateSolver( p, (k = 0) );
while ( 1 )
{
p->nFrames = k;
assert( k == Vec_PtrSize(p->vSolvers)-1 );
RetValue = Pdr_ManCheckCube( p, k, NULL, &pCube, p->pPars->nConfLimit );
if ( RetValue == -1 )
{
if ( p->pPars->fVerbose )
Pdr_ManPrintProgress( p, 1, clock() - clkStart );
printf( "Reached conflict limit (%d).\n", p->pPars->nConfLimit );
return -1;
}
if ( RetValue == 0 )
{
RetValue = Pdr_ManBlockCube( p, pCube );
if ( RetValue == -1 )
{
if ( p->pPars->fVerbose )
Pdr_ManPrintProgress( p, 1, clock() - clkStart );
printf( "Reached conflict limit (%d).\n", p->pPars->nConfLimit );
return -1;
}
if ( RetValue == 0 )
{
if ( fPrintClauses )
{
printf( "*** Clauses after frame %d:\n", k );
Pdr_ManPrintClauses( p, 0 );
}
if ( p->pPars->fVerbose )
Pdr_ManPrintProgress( p, 1, clock() - clkStart );
return 0; // SAT
}
}
else
{
// open a new timeframe
assert( pCube == NULL );
Pdr_ManSetPropertyOutput( p, k );
Pdr_ManCreateSolver( p, ++k );
if ( fPrintClauses )
{
printf( "*** Clauses after frame %d:\n", k );
Pdr_ManPrintClauses( p, 0 );
}
if ( p->pPars->fVerbose )
Pdr_ManPrintProgress( p, 0, clock() - clkStart );
// push clauses into this timeframe
if ( Pdr_ManPushClauses( p ) )
{
if ( p->pPars->fVerbose )
Pdr_ManPrintProgress( p, 1, clock() - clkStart );
Pdr_ManReportInvariant( p );
Pdr_ManVerifyInvariant( p );
if ( p->pPars->fDumpInv )
Pdr_ManDumpClauses( p, (char *)"inv.pla" );
return 1; // UNSAT
}
if ( p->pPars->fVerbose )
Pdr_ManPrintProgress( p, 1, clock() - clkStart );
clkStart = clock();
}
// check the timeout
if ( p->timeToStop && clock() >= p->timeToStop )
{
if ( fPrintClauses )
{
printf( "*** Clauses after frame %d:\n", k );
Pdr_ManPrintClauses( p, 0 );
}
if ( p->pPars->fVerbose )
Pdr_ManPrintProgress( p, 1, clock() - clkStart );
printf( "Reached timeout (%d seconds).\n", p->pPars->nTimeOut );
return -1;
}
if ( p->pPars->nFrameMax && k >= p->pPars->nFrameMax )
{
if ( p->pPars->fVerbose )
Pdr_ManPrintProgress( p, 1, clock() - clkStart );
printf( "Reached limit on the number of timeframes (%d).\n", p->pPars->nFrameMax );
return -1;
}
}
return RetValue;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Pdr_ManSolve_( Aig_Man_t * pAig, Pdr_Par_t * pPars, Vec_Int_t ** pvPrioInit, Abc_Cex_t ** ppCex )
{
Pdr_Man_t * p;
int RetValue;
int clk = clock();
p = Pdr_ManStart( pAig, pPars, pvPrioInit? *pvPrioInit : NULL );
RetValue = Pdr_ManSolveInt( p );
*ppCex = RetValue ? NULL : Pdr_ManDeriveCex( p );
// if ( *ppCex && pPars->fVerbose )
// printf( "Found counter-example in frame %d after exploring %d frames.\n",
// (*ppCex)->iFrame, p->nFrames );
p->tTotal += clock() - clk;
if ( pvPrioInit )
{
*pvPrioInit = p->vPrio;
p->vPrio = NULL;
}
Pdr_ManStop( p );
return RetValue;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Pdr_ManSolve( Aig_Man_t * pAig, Pdr_Par_t * pPars, Abc_Cex_t ** ppCex )
{
/*
Vec_Int_t * vPrioInit = NULL;
int RetValue, nTimeOut;
if ( pPars->nTimeOut > 0 )
return Pdr_ManSolve_( pAig, pPars, NULL, ppCex );
nTimeOut = pPars->nTimeOut;
pPars->nTimeOut = 10;
RetValue = Pdr_ManSolve_( pAig, pPars, &vPrioInit, ppCex );
pPars->nTimeOut = nTimeOut;
if ( RetValue == -1 )
RetValue = Pdr_ManSolve_( pAig, pPars, &vPrioInit, ppCex );
Vec_IntFree( vPrioInit );
return RetValue;
*/
return Pdr_ManSolve_( pAig, pPars, NULL, ppCex );
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END
/**CFile****************************************************************
FileName [pdrInt.h]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Netlist representation.]
Synopsis [Internal declarations.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - November 20, 2010.]
Revision [$Id: pdrInt.h,v 1.00 2010/11/20 00:00:00 alanmi Exp $]
***********************************************************************/
#ifndef __PDR_INT_H__
#define __PDR_INT_H__
////////////////////////////////////////////////////////////////////////
/// INCLUDES ///
////////////////////////////////////////////////////////////////////////
#include "saig.h"
#include "cnf.h"
#include "satSolver.h"
#include "pdr.h"
ABC_NAMESPACE_HEADER_START
////////////////////////////////////////////////////////////////////////
/// PARAMETERS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// BASIC TYPES ///
////////////////////////////////////////////////////////////////////////
typedef struct Pdr_Set_t_ Pdr_Set_t;
struct Pdr_Set_t_
{
word Sign; // signature
int nRefs; // ref counter
short nTotal; // total literals
short nLits; // num flop literals
int Lits[0];
};
typedef struct Pdr_Obl_t_ Pdr_Obl_t;
struct Pdr_Obl_t_
{
int iFrame; // time frame
int prio; // priority
int nRefs; // reference counter
Pdr_Set_t * pState; // state cube
Pdr_Obl_t * pNext; // next one
Pdr_Obl_t * pLink; // queue link
};
typedef struct Pdr_Man_t_ Pdr_Man_t;
struct Pdr_Man_t_
{
// input problem
Pdr_Par_t * pPars; // parameters
Aig_Man_t * pAig; // user's AIG
// static CNF representation
Cnf_Dat_t * pCnf1; // CNF for this AIG
Vec_Int_t * vVar2Reg; // mapping of SAT var into registers
// dynamic CNF representation
Cnf_Dat_t * pCnf2; // CNF for this AIG
Vec_Int_t** pvId2Vars; // for each used ObjId, maps frame into SAT var
Vec_Ptr_t * vVar2Ids; // for each used frame, maps SAT var into ObjId
// data representation
Vec_Ptr_t * vSolvers; // SAT solvers
Vec_Vec_t * vClauses; // clauses by timeframe
Pdr_Obl_t * pQueue; // proof obligations
int * pOrder; // ordering of the lits
Vec_Int_t * vActVars; // the counter of activation variables
// internal use
Vec_Int_t * vPrio; // priority flops
Vec_Int_t * vLits; // array of literals
Vec_Int_t * vCiObjs; // cone leaves
Vec_Int_t * vCoObjs; // cone roots
Vec_Int_t * vCiVals; // cone leaf values
Vec_Int_t * vCoVals; // cone root values
Vec_Int_t * vNodes; // cone nodes
Vec_Int_t * vUndo; // cone undos
Vec_Int_t * vVisits; // intermediate
Vec_Int_t * vCi2Rem; // CIs to be removed
Vec_Int_t * vRes; // final result
// statistics
int nBlocks; // the number of times blockState was called
int nObligs; // the number of proof obligations derived
int nCubes; // the number of cubes derived
int nCalls; // the number of SAT calls
int nCallsS; // the number of SAT calls (sat)
int nCallsU; // the number of SAT calls (unsat)
int nStarts; // the number of SAT solver restarts
int nFrames; // frames explored
// runtime
int timeStart;
int timeToStop;
// time stats
int tSat;
int tSatSat;
int tSatUnsat;
int tGeneral;
int tPush;
int tTsim;
int tContain;
int tCnf;
int tTotal;
};
////////////////////////////////////////////////////////////////////////
/// MACRO DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
static inline sat_solver * Pdr_ManSolver( Pdr_Man_t * p, int k ) { return (sat_solver *)Vec_PtrEntry(p->vSolvers, k); }
////////////////////////////////////////////////////////////////////////
/// FUNCTION DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
/*=== pdrCex.c ==========================================================*/
extern Abc_Cex_t * Pdr_ManDeriveCex( Pdr_Man_t * p );
/*=== pdrCnf.c ==========================================================*/
extern int Pdr_ObjSatVar( Pdr_Man_t * p, int k, Aig_Obj_t * pObj );
extern int Pdr_ObjRegNum( Pdr_Man_t * p, int k, int iSatVar );
extern int Pdr_ManFreeVar( Pdr_Man_t * p, int k );
extern sat_solver * Pdr_ManNewSolver( Pdr_Man_t * p, int k, int fInit );
/*=== pdrInv.c ==========================================================*/
extern void Pdr_ManPrintProgress( Pdr_Man_t * p, int fClose, int Time );
extern void Pdr_ManPrintClauses( Pdr_Man_t * p, int kStart );
extern void Pdr_ManDumpClauses( Pdr_Man_t * p, char * pFileName );
extern void Pdr_ManReportInvariant( Pdr_Man_t * p );
extern void Pdr_ManVerifyInvariant( Pdr_Man_t * p );
/*=== pdrMan.c ==========================================================*/
extern Pdr_Man_t * Pdr_ManStart( Aig_Man_t * pAig, Pdr_Par_t * pPars, Vec_Int_t * vPrioInit );
extern void Pdr_ManStop( Pdr_Man_t * p );
extern Abc_Cex_t * Pdr_ManDeriveCex( Pdr_Man_t * p );
/*=== pdrSat.c ==========================================================*/
extern sat_solver * Pdr_ManCreateSolver( Pdr_Man_t * p, int k );
extern sat_solver * Pdr_ManFetchSolver( Pdr_Man_t * p, int k );
extern void Pdr_ManSetPropertyOutput( Pdr_Man_t * p, int k );
extern Vec_Int_t * Pdr_ManCubeToLits( Pdr_Man_t * p, int k, Pdr_Set_t * pCube, int fCompl, int fNext );
extern Vec_Int_t * Pdr_ManLitsToCube( Pdr_Man_t * p, int k, int * pArray, int nArray );
extern void Pdr_ManSolverAddClause( Pdr_Man_t * p, int k, Pdr_Set_t * pCube );
extern void Pdr_ManCollectValues( Pdr_Man_t * p, int k, Vec_Int_t * vObjIds, Vec_Int_t * vValues );
extern int Pdr_ManCheckCubeCs( Pdr_Man_t * p, int k, Pdr_Set_t * pCube );
extern int Pdr_ManCheckCube( Pdr_Man_t * p, int k, Pdr_Set_t * pCube, Pdr_Set_t ** ppPred, int nConfLimit );
/*=== pdrTsim.c ==========================================================*/
extern Pdr_Set_t * Pdr_ManTernarySim( Pdr_Man_t * p, int k, Pdr_Set_t * pCube );
/*=== pdrUtil.c ==========================================================*/
extern Pdr_Set_t * Pdr_SetCreate( Vec_Int_t * vLits, Vec_Int_t * vPiLits );
extern Pdr_Set_t * Pdr_SetCreateFrom( Pdr_Set_t * pSet, int iRemove );
extern Pdr_Set_t * Pdr_SetCreateSubset( Pdr_Set_t * pSet, int * pLits, int nLits );
extern Pdr_Set_t * Pdr_SetDup( Pdr_Set_t * pSet );
extern Pdr_Set_t * Pdr_SetRef( Pdr_Set_t * p );
extern void Pdr_SetDeref( Pdr_Set_t * p );
extern int Pdr_SetContains( Pdr_Set_t * pOld, Pdr_Set_t * pNew );
extern int Pdr_SetIsInit( Pdr_Set_t * p, int iRemove );
extern void Pdr_SetPrint( FILE * pFile, Pdr_Set_t * p, int nRegs, Vec_Int_t * vFlopCounts );
extern int Pdr_SetCompare( Pdr_Set_t ** pp1, Pdr_Set_t ** pp2 );
extern Pdr_Obl_t * Pdr_OblStart( int k, int prio, Pdr_Set_t * pState, Pdr_Obl_t * pNext );
extern Pdr_Obl_t * Pdr_OblRef( Pdr_Obl_t * p );
extern void Pdr_OblDeref( Pdr_Obl_t * p );
extern int Pdr_QueueIsEmpty( Pdr_Man_t * p );
extern Pdr_Obl_t * Pdr_QueueHead( Pdr_Man_t * p );
extern Pdr_Obl_t * Pdr_QueuePop( Pdr_Man_t * p );
extern void Pdr_QueuePush( Pdr_Man_t * p, Pdr_Obl_t * pObl );
extern void Pdr_QueuePrint( Pdr_Man_t * p );
extern void Pdr_QueueStop( Pdr_Man_t * p );
ABC_NAMESPACE_HEADER_END
#endif
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
/**CFile****************************************************************
FileName [pdrInv.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Netlist representation.]
Synopsis [Invariant computation, printing, verification.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - November 20, 2010.]
Revision [$Id: pdrInv.c,v 1.00 2010/11/20 00:00:00 alanmi Exp $]
***********************************************************************/
#include "pdrInt.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Pdr_ManPrintProgress( Pdr_Man_t * p, int fClose, int Time )
{
extern int Extra_Base10Log( unsigned int Num );
static int PastSize;
Vec_Ptr_t * vVec;
int i, ThisSize, Length, LengthStart;
if ( Vec_PtrSize(p->vSolvers) < 2 )
return;
// count the total length of the printout
Length = 0;
Vec_VecForEachLevel( p->vClauses, vVec, i )
Length += 1 + Extra_Base10Log(Vec_PtrSize(vVec)+1);
// determine the starting point
LengthStart = ABC_MAX( 0, Length - 70 );
printf( "%3d :", Vec_PtrSize(p->vSolvers)-1 );
ThisSize = 6;
if ( LengthStart > 0 )
{
printf( " ..." );
ThisSize += 4;
}
Length = 0;
Vec_VecForEachLevel( p->vClauses, vVec, i )
{
if ( Length < LengthStart )
{
Length += 1 + Extra_Base10Log(Vec_PtrSize(vVec)+1);
continue;
}
printf( " %d", Vec_PtrSize(vVec) );
Length += 1 + Extra_Base10Log(Vec_PtrSize(vVec)+1);
ThisSize += 1 + Extra_Base10Log(Vec_PtrSize(vVec)+1);
}
if ( fClose )
{
for ( i = 0; i < PastSize - ThisSize; i++ )
printf( " " );
printf( "\n" );
}
else
{
printf( "\r" );
PastSize = ThisSize;
}
// printf(" %.2f sec", (float)(Time)/(float)(CLOCKS_PER_SEC));
}
/**Function*************************************************************
Synopsis [Counts how many times each flop appears in the set of cubes.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Int_t * Pdr_ManCountFlops( Pdr_Man_t * p, Vec_Ptr_t * vCubes )
{
Vec_Int_t * vFlopCount;
Pdr_Set_t * pCube;
int i, n;
vFlopCount = Vec_IntStart( Aig_ManRegNum(p->pAig) );
Vec_PtrForEachEntry( Pdr_Set_t *, vCubes, pCube, i )
for ( n = 0; n < pCube->nLits; n++ )
{
assert( pCube->Lits[n] >= 0 && pCube->Lits[n] < 2*Aig_ManRegNum(p->pAig) );
Vec_IntAddToEntry( vFlopCount, pCube->Lits[n] >> 1, 1 );
}
return vFlopCount;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Pdr_ManFindInvariantStart( Pdr_Man_t * p )
{
Vec_Ptr_t * vArrayK;
int k, kMax = Vec_PtrSize(p->vSolvers)-1;
Vec_VecForEachLevelStartStop( p->vClauses, vArrayK, k, 1, kMax )
if ( Vec_PtrSize(vArrayK) == 0 )
return k;
return -1;
}
/**Function*************************************************************
Synopsis [Counts the number of variables used in the clauses.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Ptr_t * Pdr_ManCollectCubes( Pdr_Man_t * p, int kStart )
{
Vec_Ptr_t * vResult;
Vec_Ptr_t * vArrayK;
Pdr_Set_t * pSet;
int i, j;
vResult = Vec_PtrAlloc( 100 );
Vec_VecForEachLevelStart( p->vClauses, vArrayK, i, kStart )
Vec_PtrForEachEntry( Pdr_Set_t *, vArrayK, pSet, j )
Vec_PtrPush( vResult, pSet );
return vResult;
}
/**Function*************************************************************
Synopsis [Counts the number of variables used in the clauses.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Pdr_ManCountVariables( Pdr_Man_t * p, int kStart )
{
Vec_Int_t * vFlopCounts;
Vec_Ptr_t * vCubes;
int i, Entry, Counter = 0;
vCubes = Pdr_ManCollectCubes( p, kStart );
vFlopCounts = Pdr_ManCountFlops( p, vCubes );
Vec_IntForEachEntry( vFlopCounts, Entry, i )
Counter += (Entry > 0);
Vec_IntFreeP( &vFlopCounts );
Vec_PtrFree( vCubes );
return Counter;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Pdr_ManPrintClauses( Pdr_Man_t * p, int kStart )
{
Vec_Ptr_t * vArrayK;
Pdr_Set_t * pCube;
int i, k, Counter = 0;
Vec_VecForEachLevelStart( p->vClauses, vArrayK, k, kStart )
{
Vec_PtrSort( vArrayK, (int (*)(void))Pdr_SetCompare );
Vec_PtrForEachEntry( Pdr_Set_t *, vArrayK, pCube, i )
{
printf( "C=%4d. F=%4d ", Counter++, k );
Pdr_SetPrint( stdout, pCube, Aig_ManRegNum(p->pAig), NULL );
printf( "\n" );
}
}
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Pdr_ManDumpClauses( Pdr_Man_t * p, char * pFileName )
{
int fUseSupp = 1;
FILE * pFile;
Vec_Int_t * vFlopCounts;
Vec_Ptr_t * vCubes;
Pdr_Set_t * pCube;
int i, kStart;
// create file
pFile = fopen( pFileName, "w" );
if ( pFile == NULL )
{
printf( "Cannot open file \"%s\" for writing invariant.\n", pFileName );
return;
}
// collect cubes
kStart = Pdr_ManFindInvariantStart( p );
vCubes = Pdr_ManCollectCubes( p, kStart );
Vec_PtrSort( vCubes, (int (*)(void))Pdr_SetCompare );
// collect variable appearances
vFlopCounts = fUseSupp ? Pdr_ManCountFlops( p, vCubes ) : NULL;
// output the header
fprintf( pFile, "# Inductive invariant for \"%s\"\n", p->pAig->pName );
fprintf( pFile, "# generated by PDR in ABC on %s\n", Aig_TimeStamp() );
fprintf( pFile, ".i %d\n", fUseSupp ? Pdr_ManCountVariables(p, kStart) : Aig_ManRegNum(p->pAig) );
fprintf( pFile, ".o 1\n" );
fprintf( pFile, ".p %d\n", Vec_PtrSize(vCubes) );
// output cubes
Vec_PtrForEachEntry( Pdr_Set_t *, vCubes, pCube, i )
{
Pdr_SetPrint( pFile, pCube, Aig_ManRegNum(p->pAig), vFlopCounts );
fprintf( pFile, " 1\n" );
}
fprintf( pFile, ".e\n\n" );
fclose( pFile );
Vec_IntFreeP( &vFlopCounts );
Vec_PtrFree( vCubes );
printf( "Inductive invariant was written into file \"%s\".\n", pFileName );
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Pdr_ManReportInvariant( Pdr_Man_t * p )
{
Vec_Ptr_t * vCubes;
int kStart = Pdr_ManFindInvariantStart( p );
vCubes = Pdr_ManCollectCubes( p, kStart );
printf( "Invariant F[%d] : %d clauses with %d flops (out of %d)\n",
kStart, Vec_PtrSize(vCubes), Pdr_ManCountVariables(p, kStart), Aig_ManRegNum(p->pAig) );
Vec_PtrFree( vCubes );
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Pdr_ManVerifyInvariant( Pdr_Man_t * p )
{
sat_solver * pSat;
Vec_Int_t * vLits;
Vec_Ptr_t * vCubes;
Pdr_Set_t * pCube;
int i, kStart, kThis, RetValue, Counter = 0, clk = clock();
// collect cubes used in the inductive invariant
kStart = Pdr_ManFindInvariantStart( p );
vCubes = Pdr_ManCollectCubes( p, kStart );
// create solver with the cubes
kThis = Vec_PtrSize(p->vSolvers);
pSat = Pdr_ManCreateSolver( p, kThis );
// add the property output
Pdr_ManSetPropertyOutput( p, kThis );
// add the clauses
Vec_PtrForEachEntry( Pdr_Set_t *, vCubes, pCube, i )
{
vLits = Pdr_ManCubeToLits( p, kThis, pCube, 1, 0 );
RetValue = sat_solver_addclause( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits) );
assert( RetValue );
sat_solver_compress( pSat );
}
// check each clause
Vec_PtrForEachEntry( Pdr_Set_t *, vCubes, pCube, i )
{
vLits = Pdr_ManCubeToLits( p, kThis, pCube, 0, 1 );
RetValue = sat_solver_solve( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits), 0, 0, 0, 0 );
if ( RetValue != l_False )
{
printf( "Verification of clause %d failed.\n", i );
Counter++;
}
}
if ( Counter )
printf( "Verification of %d clauses has failed.\n", Counter );
else
{
printf( "Verification of invariant with %d clauses was successful. ", Vec_PtrSize(vCubes) );
Abc_PrintTime( 1, "Time", clock() - clk );
}
// sat_solver_delete( pSat );
Vec_PtrFree( vCubes );
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END
/**CFile****************************************************************
FileName [pdr.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Netlist representation.]
Synopsis [Manager procedures.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - November 20, 2010.]
Revision [$Id: pdr.c,v 1.00 2010/11/20 00:00:00 alanmi Exp $]
***********************************************************************/
#include "pdrInt.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Creates manager.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Pdr_Man_t * Pdr_ManStart( Aig_Man_t * pAig, Pdr_Par_t * pPars, Vec_Int_t * vPrioInit )
{
Pdr_Man_t * p;
p = ABC_CALLOC( Pdr_Man_t, 1 );
p->pPars = pPars;
p->pAig = pAig;
p->vSolvers = Vec_PtrAlloc( 0 );
p->vClauses = Vec_VecAlloc( 0 );
p->pQueue = NULL;
p->pOrder = ABC_ALLOC( int, Aig_ManRegNum(pAig) );
p->vActVars = Vec_IntAlloc( 256 );
// internal use
p->vPrio = vPrioInit ? vPrioInit : Vec_IntStart( Aig_ManRegNum(pAig) ); // priority flops
p->vLits = Vec_IntAlloc( 100 ); // array of literals
p->vCiObjs = Vec_IntAlloc( 100 ); // cone leaves
p->vCoObjs = Vec_IntAlloc( 100 ); // cone roots
p->vCiVals = Vec_IntAlloc( 100 ); // cone leaf values
p->vCoVals = Vec_IntAlloc( 100 ); // cone root values
p->vNodes = Vec_IntAlloc( 100 ); // cone nodes
p->vUndo = Vec_IntAlloc( 100 ); // cone undos
p->vVisits = Vec_IntAlloc( 100 ); // intermediate
p->vCi2Rem = Vec_IntAlloc( 100 ); // CIs to be removed
p->vRes = Vec_IntAlloc( 100 ); // final result
// additional AIG data-members
if ( pAig->pFanData == NULL )
Aig_ManFanoutStart( pAig );
if ( pAig->pTerSimData == NULL )
pAig->pTerSimData = ABC_CALLOC( unsigned, 1 + (Aig_ManObjNumMax(pAig) / 16) );
p->timeStart = clock();
return p;
}
/**Function*************************************************************
Synopsis [Frees manager.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Pdr_ManStop( Pdr_Man_t * p )
{
Pdr_Set_t * pCla;
sat_solver * pSat;
int i, k;
if ( p->pPars->fVerbose )
{
printf( "Block =%5d Oblig =%6d Clause =%6d Call =%6d (sat=%.1f%%) Start =%4d\n",
p->nBlocks, p->nObligs, p->nCubes, p->nCalls, 100.0 * p->nCallsS / p->nCalls, p->nStarts );
ABC_PRTP( "SAT solving", p->tSat, p->tTotal );
ABC_PRTP( " unsat ", p->tSatUnsat, p->tTotal );
ABC_PRTP( " sat ", p->tSatSat, p->tTotal );
ABC_PRTP( "Generalize ", p->tGeneral, p->tTotal );
ABC_PRTP( "Push clause", p->tPush, p->tTotal );
ABC_PRTP( "Ternary sim", p->tTsim, p->tTotal );
ABC_PRTP( "Containment", p->tContain, p->tTotal );
ABC_PRTP( "CNF compute", p->tCnf, p->tTotal );
ABC_PRTP( "TOTAL ", p->tTotal, p->tTotal );
}
Vec_PtrForEachEntry( sat_solver *, p->vSolvers, pSat, i )
sat_solver_delete( pSat );
Vec_PtrFree( p->vSolvers );
Vec_VecForEachEntry( Pdr_Set_t *, p->vClauses, pCla, i, k )
Pdr_SetDeref( pCla );
Vec_VecFree( p->vClauses );
Pdr_QueueStop( p );
ABC_FREE( p->pOrder );
Vec_IntFree( p->vActVars );
// static CNF
Cnf_DataFree( p->pCnf1 );
Vec_IntFreeP( &p->vVar2Reg );
// dynamic CNF
Cnf_DataFree( p->pCnf2 );
if ( p->pvId2Vars )
for ( i = 0; i < Aig_ManObjNumMax(p->pAig); i++ )
Vec_IntFreeP( &p->pvId2Vars[i] );
ABC_FREE( p->pvId2Vars );
Vec_VecFreeP( (Vec_Vec_t **)&p->vVar2Ids );
// internal use
Vec_IntFreeP( &p->vPrio ); // priority flops
Vec_IntFree( p->vLits ); // array of literals
Vec_IntFree( p->vCiObjs ); // cone leaves
Vec_IntFree( p->vCoObjs ); // cone roots
Vec_IntFree( p->vCiVals ); // cone leaf values
Vec_IntFree( p->vCoVals ); // cone root values
Vec_IntFree( p->vNodes ); // cone nodes
Vec_IntFree( p->vUndo ); // cone undos
Vec_IntFree( p->vVisits ); // intermediate
Vec_IntFree( p->vCi2Rem ); // CIs to be removed
Vec_IntFree( p->vRes ); // final result
// additional AIG data-members
if ( p->pAig->pFanData != NULL )
Aig_ManFanoutStop( p->pAig );
if ( p->pAig->pTerSimData != NULL )
ABC_FREE( p->pAig->pTerSimData );
ABC_FREE( p );
}
/**Function*************************************************************
Synopsis [Derives counter-example.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Abc_Cex_t * Pdr_ManDeriveCex( Pdr_Man_t * p )
{
extern Abc_Cex_t * Gia_ManAllocCounterExample( int nRegs, int nRealPis, int nFrames );
Abc_Cex_t * pCex;
Pdr_Obl_t * pObl;
int i, f, Lit, nFrames = 0;
// count the number of frames
for ( pObl = p->pQueue; pObl; pObl = pObl->pNext )
nFrames++;
// create the counter-example
pCex = Gia_ManAllocCounterExample( Aig_ManRegNum(p->pAig), Saig_ManPiNum(p->pAig), nFrames );
pCex->iPo = (p->pPars->iOutput==-1)? 0 : p->pPars->iOutput;
pCex->iFrame = nFrames-1;
for ( pObl = p->pQueue, f = 0; pObl; pObl = pObl->pNext, f++ )
for ( i = pObl->pState->nLits; i < pObl->pState->nTotal; i++ )
{
Lit = pObl->pState->Lits[i];
if ( lit_sign(Lit) )
continue;
assert( lit_var(Lit) < pCex->nPis );
Aig_InfoSetBit( pCex->pData, pCex->nRegs + f * pCex->nPis + lit_var(Lit) );
}
assert( f == nFrames );
return pCex;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END
/**CFile****************************************************************
FileName [pdrSat.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Netlist representation.]
Synopsis [SAT solver procedures.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - November 20, 2010.]
Revision [$Id: pdrSat.c,v 1.00 2010/11/20 00:00:00 alanmi Exp $]
***********************************************************************/
#include "pdrInt.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Creates new SAT solver.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
sat_solver * Pdr_ManCreateSolver( Pdr_Man_t * p, int k )
{
sat_solver * pSat;
assert( Vec_PtrSize(p->vSolvers) == k );
assert( Vec_VecSize(p->vClauses) == k );
assert( Vec_IntSize(p->vActVars) == k );
// create new solver
pSat = Pdr_ManNewSolver( p, k, (int)(k == 0) );
Vec_PtrPush( p->vSolvers, pSat );
Vec_VecExpand( p->vClauses, k );
Vec_IntPush( p->vActVars, 0 );
// add property cone
Pdr_ObjSatVar( p, k, Aig_ManPo(p->pAig, (p->pPars->iOutput==-1)?0:p->pPars->iOutput ) );
return pSat;
}
/**Function*************************************************************
Synopsis [Returns old or restarted solver.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
sat_solver * Pdr_ManFetchSolver( Pdr_Man_t * p, int k )
{
sat_solver * pSat;
Vec_Ptr_t * vArrayK;
Pdr_Set_t * pCube;
int i, j;
pSat = Pdr_ManSolver(p, k);
if ( Vec_IntEntry(p->vActVars, k) < p->pPars->nRecycle )
return pSat;
assert( k < Vec_PtrSize(p->vSolvers) - 1 );
p->nStarts++;
sat_solver_delete( pSat );
// create new SAT solver
pSat = Pdr_ManNewSolver( p, k, (int)(k == 0) );
// write new SAT solver
Vec_PtrWriteEntry( p->vSolvers, k, pSat );
Vec_IntWriteEntry( p->vActVars, k, 0 );
// set the property output
Pdr_ManSetPropertyOutput( p, k );
// add the clauses
Vec_VecForEachLevelStart( p->vClauses, vArrayK, i, k )
Vec_PtrForEachEntry( Pdr_Set_t *, vArrayK, pCube, j )
Pdr_ManSolverAddClause( p, k, pCube );
return pSat;
}
/**Function*************************************************************
Synopsis [Converts SAT variables into register IDs.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Int_t * Pdr_ManLitsToCube( Pdr_Man_t * p, int k, int * pArray, int nArray )
{
int i, RegId;
Vec_IntClear( p->vLits );
for ( i = 0; i < nArray; i++ )
{
RegId = Pdr_ObjRegNum( p, k, lit_var(pArray[i]) );
if ( RegId == -1 )
continue;
assert( RegId >= 0 && RegId < Aig_ManRegNum(p->pAig) );
Vec_IntPush( p->vLits, toLitCond(RegId, !lit_sign(pArray[i])) );
}
assert( Vec_IntSize(p->vLits) >= 0 && Vec_IntSize(p->vLits) <= nArray );
return p->vLits;
}
/**Function*************************************************************
Synopsis [Converts the cube in terms of RO numbers into array of CNF literals.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Int_t * Pdr_ManCubeToLits( Pdr_Man_t * p, int k, Pdr_Set_t * pCube, int fCompl, int fNext )
{
Aig_Obj_t * pObj;
int i, iVar, iVarMax = 0;
int clk = clock();
Vec_IntClear( p->vLits );
for ( i = 0; i < pCube->nLits; i++ )
{
if ( pCube->Lits[i] == -1 )
continue;
if ( fNext )
pObj = Saig_ManLi( p->pAig, lit_var(pCube->Lits[i]) );
else
pObj = Saig_ManLo( p->pAig, lit_var(pCube->Lits[i]) );
iVar = Pdr_ObjSatVar( p, k, pObj ); assert( iVar >= 0 );
iVarMax = ABC_MAX( iVarMax, iVar );
Vec_IntPush( p->vLits, toLitCond( iVar, fCompl ^ lit_sign(pCube->Lits[i]) ) );
}
// sat_solver_setnvars( Pdr_ManSolver(p, k), iVarMax + 1 );
p->tCnf += clock() - clk;
return p->vLits;
}
/**Function*************************************************************
Synopsis [Sets the property output to 0 (sat) forever.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Pdr_ManSetPropertyOutput( Pdr_Man_t * p, int k )
{
sat_solver * pSat;
int Lit, RetValue;
pSat = Pdr_ManSolver(p, k);
Lit = toLitCond( Pdr_ObjSatVar(p, k, Aig_ManPo(p->pAig, (p->pPars->iOutput==-1)?0:p->pPars->iOutput)), 1 ); // neg literal
RetValue = sat_solver_addclause( pSat, &Lit, &Lit + 1 );
assert( RetValue == 1 );
sat_solver_compress( pSat );
}
/**Function*************************************************************
Synopsis [Adds one clause in terms of ROs to the k-th SAT solver.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Pdr_ManSolverAddClause( Pdr_Man_t * p, int k, Pdr_Set_t * pCube )
{
sat_solver * pSat;
Vec_Int_t * vLits;
int RetValue;
pSat = Pdr_ManSolver(p, k);
vLits = Pdr_ManCubeToLits( p, k, pCube, 1, 0 );
RetValue = sat_solver_addclause( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits) );
assert( RetValue == 1 );
sat_solver_compress( pSat );
}
/**Function*************************************************************
Synopsis [Collects values of the RO/RI variables in k-th SAT solver.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Pdr_ManCollectValues( Pdr_Man_t * p, int k, Vec_Int_t * vObjIds, Vec_Int_t * vValues )
{
sat_solver * pSat;
Aig_Obj_t * pObj;
int iVar, i;
Vec_IntClear( vValues );
pSat = Pdr_ManSolver(p, k);
Aig_ManForEachNodeVec( p->pAig, vObjIds, pObj, i )
{
iVar = Pdr_ObjSatVar( p, k, pObj ); assert( iVar >= 0 );
Vec_IntPush( vValues, sat_solver_var_value(pSat, iVar) );
}
}
/**Function*************************************************************
Synopsis [Checks if the cube holds (UNSAT) in the given timeframe.]
Description [Return 1/0 if cube or property are proved to hold/fail
in k-th timeframe. Returns the predecessor bad state in ppPred.]
SideEffects []
SeeAlso []
***********************************************************************/
int Pdr_ManCheckCubeCs( Pdr_Man_t * p, int k, Pdr_Set_t * pCube )
{
sat_solver * pSat;
Vec_Int_t * vLits;
int RetValue;
pSat = Pdr_ManFetchSolver( p, k );
vLits = Pdr_ManCubeToLits( p, k, pCube, 0, 0 );
RetValue = sat_solver_solve( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits), 0, 0, 0, 0 );
assert( RetValue != l_Undef );
return (RetValue == l_False);
}
/**Function*************************************************************
Synopsis [Checks if the cube holds (UNSAT) in the given timeframe.]
Description [Return 1/0 if cube or property are proved to hold/fail
in k-th timeframe. Returns the predecessor bad state in ppPred.]
SideEffects []
SeeAlso []
***********************************************************************/
int Pdr_ManCheckCube( Pdr_Man_t * p, int k, Pdr_Set_t * pCube, Pdr_Set_t ** ppPred, int nConfLimit )
{
int fUseLit = 1;
int fLitUsed = 0;
sat_solver * pSat;
Vec_Int_t * vLits;
int Lit, RetValue, clk;
p->nCalls++;
pSat = Pdr_ManFetchSolver( p, k );
if ( pCube == NULL ) // solve the property
{
clk = clock();
Lit = toLit( Pdr_ObjSatVar(p, k, Aig_ManPo(p->pAig, (p->pPars->iOutput==-1)?0:p->pPars->iOutput)) ); // pos literal (property fails)
RetValue = sat_solver_solve( pSat, &Lit, &Lit + 1, nConfLimit, 0, 0, 0 );
if ( RetValue == l_Undef )
return -1;
}
else // check relative containment in terms of next states
{
if ( fUseLit )
{
fLitUsed = 1;
Vec_IntAddToEntry( p->vActVars, k, 1 );
// add the cube in terms of current state variables
vLits = Pdr_ManCubeToLits( p, k, pCube, 1, 0 );
// add activation literal
Lit = toLit( Pdr_ManFreeVar(p, k) );
// add activation literal
Vec_IntPush( vLits, Lit );
RetValue = sat_solver_addclause( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits) );
assert( RetValue == 1 );
sat_solver_compress( pSat );
// create assumptions
vLits = Pdr_ManCubeToLits( p, k, pCube, 0, 1 );
// add activation literal
Vec_IntPush( vLits, lit_neg(Lit) );
}
else
vLits = Pdr_ManCubeToLits( p, k, pCube, 0, 1 );
// solve
clk = clock();
RetValue = sat_solver_solve( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits), nConfLimit, 0, 0, 0 );
if ( RetValue == l_Undef )
return -1;
}
clk = clock() - clk;
p->tSat += clk;
assert( RetValue != l_Undef );
if ( RetValue == l_False )
{
p->tSatUnsat += clk;
p->nCallsU++;
if ( ppPred )
*ppPred = NULL;
RetValue = 1;
}
else // if ( RetValue == l_True )
{
p->tSatSat += clk;
p->nCallsS++;
if ( ppPred )
*ppPred = Pdr_ManTernarySim( p, k, pCube );
RetValue = 0;
}
/* // for some reason, it does not work...
if ( fLitUsed )
{
int RetValue;
Lit = lit_neg(Lit);
RetValue = sat_solver_addclause( pSat, &Lit, &Lit + 1 );
assert( RetValue == 1 );
sat_solver_compress( pSat );
}
*/
return RetValue;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END
/**CFile****************************************************************
FileName [pdrTsim.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Netlist representation.]
Synopsis [Ternary simulation.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - November 20, 2010.]
Revision [$Id: pdrTsim.c,v 1.00 2010/11/20 00:00:00 alanmi Exp $]
***********************************************************************/
#include "pdrInt.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
#define PDR_ZER 1
#define PDR_ONE 2
#define PDR_UND 3
static inline int Pdr_ManSimInfoNot( int Value )
{
if ( Value == PDR_ZER )
return PDR_ONE;
if ( Value == PDR_ONE )
return PDR_ZER;
return PDR_UND;
}
static inline int Pdr_ManSimInfoAnd( int Value0, int Value1 )
{
if ( Value0 == PDR_ZER || Value1 == PDR_ZER )
return PDR_ZER;
if ( Value0 == PDR_ONE && Value1 == PDR_ONE )
return PDR_ONE;
return PDR_UND;
}
static inline int Pdr_ManSimInfoGet( Aig_Man_t * p, Aig_Obj_t * pObj )
{
return 3 & (p->pTerSimData[Aig_ObjId(pObj) >> 4] >> ((Aig_ObjId(pObj) & 15) << 1));
}
static inline void Pdr_ManSimInfoSet( Aig_Man_t * p, Aig_Obj_t * pObj, int Value )
{
assert( Value >= PDR_ZER && Value <= PDR_UND );
Value ^= Pdr_ManSimInfoGet( p, pObj );
p->pTerSimData[Aig_ObjId(pObj) >> 4] ^= (Value << ((Aig_ObjId(pObj) & 15) << 1));
}
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Marks the TFI cone and collects CIs and nodes.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Pdr_ManCollectCone_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Int_t * vCiObjs, Vec_Int_t * vNodes )
{
assert( !Aig_IsComplement(pObj) );
if ( Aig_ObjIsTravIdCurrent(pAig, pObj) )
return;
Aig_ObjSetTravIdCurrent(pAig, pObj);
if ( Aig_ObjIsPi(pObj) )
{
Vec_IntPush( vCiObjs, Aig_ObjId(pObj) );
return;
}
Pdr_ManCollectCone_rec( pAig, Aig_ObjFanin0(pObj), vCiObjs, vNodes );
if ( Aig_ObjIsPo(pObj) )
return;
Pdr_ManCollectCone_rec( pAig, Aig_ObjFanin1(pObj), vCiObjs, vNodes );
Vec_IntPush( vNodes, Aig_ObjId(pObj) );
}
/**Function*************************************************************
Synopsis [Marks the TFI cone and collects CIs and nodes.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Pdr_ManCollectCone( Aig_Man_t * pAig, Vec_Int_t * vCoObjs, Vec_Int_t * vCiObjs, Vec_Int_t * vNodes )
{
Aig_Obj_t * pObj;
int i;
Vec_IntClear( vCiObjs );
Vec_IntClear( vNodes );
Aig_ManIncrementTravId( pAig );
Aig_ObjSetTravIdCurrent( pAig, Aig_ManConst1(pAig) );
Aig_ManForEachNodeVec( pAig, vCoObjs, pObj, i )
Pdr_ManCollectCone_rec( pAig, pObj, vCiObjs, vNodes );
}
/**Function*************************************************************
Synopsis [Performs ternary simulation for one node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Pdr_ManExtendOneEval( Aig_Man_t * pAig, Aig_Obj_t * pObj )
{
int Value0, Value1, Value;
Value0 = Pdr_ManSimInfoGet( pAig, Aig_ObjFanin0(pObj) );
if ( Aig_ObjFaninC0(pObj) )
Value0 = Pdr_ManSimInfoNot( Value0 );
if ( Aig_ObjIsPo(pObj) )
{
Pdr_ManSimInfoSet( pAig, pObj, Value0 );
return Value0;
}
assert( Aig_ObjIsNode(pObj) );
Value1 = Pdr_ManSimInfoGet( pAig, Aig_ObjFanin1(pObj) );
if ( Aig_ObjFaninC1(pObj) )
Value1 = Pdr_ManSimInfoNot( Value1 );
Value = Pdr_ManSimInfoAnd( Value0, Value1 );
Pdr_ManSimInfoSet( pAig, pObj, Value );
return Value;
}
/**Function*************************************************************
Synopsis [Performs ternary simulation for one design.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Pdr_ManSimDataInit( Aig_Man_t * pAig,
Vec_Int_t * vCiObjs, Vec_Int_t * vCiVals, Vec_Int_t * vNodes,
Vec_Int_t * vCoObjs, Vec_Int_t * vCoVals, Vec_Int_t * vCi2Rem )
{
Aig_Obj_t * pObj;
int i;
// set the CI values
Pdr_ManSimInfoSet( pAig, Aig_ManConst1(pAig), PDR_ONE );
Aig_ManForEachNodeVec( pAig, vCiObjs, pObj, i )
Pdr_ManSimInfoSet( pAig, pObj, (Vec_IntEntry(vCiVals, i)?PDR_ONE:PDR_ZER) );
// set the FOs to remove
if ( vCi2Rem != NULL )
Aig_ManForEachNodeVec( pAig, vCi2Rem, pObj, i )
Pdr_ManSimInfoSet( pAig, pObj, PDR_UND );
// perform ternary simulation
Aig_ManForEachNodeVec( pAig, vNodes, pObj, i )
Pdr_ManExtendOneEval( pAig, pObj );
// transfer results to the output
Aig_ManForEachNodeVec( pAig, vCoObjs, pObj, i )
Pdr_ManExtendOneEval( pAig, pObj );
// check the results
Aig_ManForEachNodeVec( pAig, vCoObjs, pObj, i )
if ( Pdr_ManSimInfoGet( pAig, pObj ) != (Vec_IntEntry(vCoVals, i)?PDR_ONE:PDR_ZER) )
return 0;
return 1;
}
/**Function*************************************************************
Synopsis [Tries to assign ternary value to one of the CIs.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Pdr_ManExtendOne( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Int_t * vUndo, Vec_Int_t * vVis )
{
Aig_Obj_t * pFanout;
int i, k, iFanout, Value, Value2;
assert( Saig_ObjIsLo(pAig, pObj) );
assert( Aig_ObjIsTravIdCurrent(pAig, pObj) );
// save original value
Value = Pdr_ManSimInfoGet( pAig, pObj );
assert( Value == PDR_ZER || Value == PDR_ONE );
Vec_IntPush( vUndo, Aig_ObjId(pObj) );
Vec_IntPush( vUndo, Value );
// update original value
Pdr_ManSimInfoSet( pAig, pObj, PDR_UND );
// traverse
Vec_IntClear( vVis );
Vec_IntPush( vVis, Aig_ObjId(pObj) );
Aig_ManForEachNodeVec( pAig, vVis, pObj, i )
{
Aig_ObjForEachFanout( pAig, pObj, pFanout, iFanout, k )
{
if ( !Aig_ObjIsTravIdCurrent(pAig, pFanout) )
continue;
assert( Aig_ObjId(pObj) < Aig_ObjId(pFanout) );
Value = Pdr_ManSimInfoGet( pAig, pFanout );
if ( Value == PDR_UND )
continue;
Value2 = Pdr_ManExtendOneEval( pAig, pFanout );
if ( Value2 == Value )
continue;
assert( Value2 == PDR_UND );
Vec_IntPush( vUndo, Aig_ObjId(pFanout) );
Vec_IntPush( vUndo, Value );
if ( Aig_ObjIsPo(pFanout) )
return 0;
assert( Aig_ObjIsNode(pFanout) );
Vec_IntPushOrder( vVis, Aig_ObjId(pFanout) );
}
}
return 1;
}
/**Function*************************************************************
Synopsis [Undoes the partial results of ternary simulation.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Pdr_ManExtendUndo( Aig_Man_t * pAig, Vec_Int_t * vUndo )
{
Aig_Obj_t * pObj;
int i, Value;
Aig_ManForEachNodeVec( pAig, vUndo, pObj, i )
{
Value = Vec_IntEntry(vUndo, ++i);
assert( Pdr_ManSimInfoGet(pAig, pObj) == PDR_UND );
Pdr_ManSimInfoSet( pAig, pObj, Value );
}
}
/**Function*************************************************************
Synopsis [Derives the resulting cube.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Pdr_ManDeriveResult( Aig_Man_t * pAig, Vec_Int_t * vCiObjs, Vec_Int_t * vCiVals, Vec_Int_t * vCi2Rem, Vec_Int_t * vRes, Vec_Int_t * vPiLits )
{
Aig_Obj_t * pObj;
int i, Lit;
// mark removed flop outputs
Aig_ManIncrementTravId( pAig );
Aig_ManForEachNodeVec( pAig, vCi2Rem, pObj, i )
{
assert( Saig_ObjIsLo( pAig, pObj ) );
Aig_ObjSetTravIdCurrent(pAig, pObj);
}
// collect flop outputs that are not marked
Vec_IntClear( vRes );
Vec_IntClear( vPiLits );
Aig_ManForEachNodeVec( pAig, vCiObjs, pObj, i )
{
if ( Saig_ObjIsPi(pAig, pObj) )
{
Lit = toLitCond( Aig_ObjPioNum(pObj), (Vec_IntEntry(vCiVals, i) == 0) );
Vec_IntPush( vPiLits, Lit );
continue;
}
assert( Saig_ObjIsLo(pAig, pObj) );
if ( Aig_ObjIsTravIdCurrent(pAig, pObj) )
continue;
Lit = toLitCond( Aig_ObjPioNum(pObj) - Saig_ManPiNum(pAig), (Vec_IntEntry(vCiVals, i) == 0) );
Vec_IntPush( vRes, Lit );
}
if ( Vec_IntSize(vRes) == 0 )
Vec_IntPush(vRes, 0);
}
/**Function*************************************************************
Synopsis [Derives the resulting cube.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Pdr_ManPrintCex( Aig_Man_t * pAig, Vec_Int_t * vCiObjs, Vec_Int_t * vCiVals, Vec_Int_t * vCi2Rem )
{
Aig_Obj_t * pObj;
int i;
char * pBuff = ABC_ALLOC( char, Aig_ManPiNum(pAig)+1 );
for ( i = 0; i < Aig_ManPiNum(pAig); i++ )
pBuff[i] = '-';
pBuff[i] = 0;
Aig_ManForEachNodeVec( pAig, vCiObjs, pObj, i )
pBuff[Aig_ObjPioNum(pObj)] = (Vec_IntEntry(vCiVals, i)? '1':'0');
if ( vCi2Rem )
Aig_ManForEachNodeVec( pAig, vCi2Rem, pObj, i )
pBuff[Aig_ObjPioNum(pObj)] = 'x';
printf( "%s\n", pBuff );
ABC_FREE( pBuff );
}
/**Function*************************************************************
Synopsis [Shrinks values using ternary simulation.]
Description [The cube contains the set of flop index literals which,
when converted into a clause and applied to the combinational outputs,
led to a satisfiable SAT run in frame k (values stored in the SAT solver).
If the cube is NULL, it is assumed that the first property output was
asserted and failed.
The resulting array is a set of flop index literals that asserts the COs.
Priority contains 0 for i-th entry if the i-th FF is desirable to remove.]
SideEffects []
SeeAlso []
***********************************************************************/
Pdr_Set_t * Pdr_ManTernarySim( Pdr_Man_t * p, int k, Pdr_Set_t * pCube )
{
Vec_Int_t * vPrio = p->vPrio; // priority flops (flop indices)
Vec_Int_t * vPiLits = p->vLits; // array of literals (0/1 PI values)
Vec_Int_t * vCiObjs = p->vCiObjs; // cone leaves (CI obj IDs)
Vec_Int_t * vCoObjs = p->vCoObjs; // cone roots (CO obj IDs)
Vec_Int_t * vCiVals = p->vCiVals; // cone leaf values (0/1 CI values)
Vec_Int_t * vCoVals = p->vCoVals; // cone root values (0/1 CO values)
Vec_Int_t * vNodes = p->vNodes; // cone nodes (node obj IDs)
Vec_Int_t * vUndo = p->vUndo; // cone undos (node obj IDs)
Vec_Int_t * vVisits = p->vVisits; // intermediate (obj IDs)
Vec_Int_t * vCi2Rem = p->vCi2Rem; // CIs to be removed (CI obj IDs)
Vec_Int_t * vRes = p->vRes; // final result (flop literals)
Aig_Obj_t * pObj;
int i, Entry, RetValue;
int clk = clock();
// collect CO objects
Vec_IntClear( vCoObjs );
if ( pCube == NULL ) // the target is the property output
Vec_IntPush( vCoObjs, Aig_ObjId(Aig_ManPo(p->pAig, (p->pPars->iOutput==-1)?0:p->pPars->iOutput)) );
else // the target is the cube
{
for ( i = 0; i < pCube->nLits; i++ )
{
if ( pCube->Lits[i] == -1 )
continue;
pObj = Saig_ManLi(p->pAig, (pCube->Lits[i] >> 1));
Vec_IntPush( vCoObjs, Aig_ObjId(pObj) );
}
}
if ( p->pPars->fVeryVerbose )
{
printf( "Trying to justify cube " );
if ( pCube )
Pdr_SetPrint( stdout, pCube, Aig_ManRegNum(p->pAig), NULL );
else
printf( "<prop=fail>" );
printf( " in frame %d.\n", k );
}
// collect CI objects
Pdr_ManCollectCone( p->pAig, vCoObjs, vCiObjs, vNodes );
// collect values
Pdr_ManCollectValues( p, k, vCiObjs, vCiVals );
Pdr_ManCollectValues( p, k, vCoObjs, vCoVals );
// simulate for the first time
if ( p->pPars->fVeryVerbose )
Pdr_ManPrintCex( p->pAig, vCiObjs, vCiVals, NULL );
RetValue = Pdr_ManSimDataInit( p->pAig, vCiObjs, vCiVals, vNodes, vCoObjs, vCoVals, NULL );
assert( RetValue );
// try removing high-priority flops
Vec_IntClear( vCi2Rem );
Aig_ManForEachNodeVec( p->pAig, vCiObjs, pObj, i )
{
if ( !Saig_ObjIsLo( p->pAig, pObj ) )
continue;
Entry = Aig_ObjPioNum(pObj) - Saig_ManPiNum(p->pAig);
if ( vPrio != NULL && Vec_IntEntry( vPrio, Entry ) != 0 )
continue;
Vec_IntClear( vUndo );
if ( Pdr_ManExtendOne( p->pAig, pObj, vUndo, vVisits ) )
Vec_IntPush( vCi2Rem, Aig_ObjId(pObj) );
else
Pdr_ManExtendUndo( p->pAig, vUndo );
}
// try removing low-priority flops
Aig_ManForEachNodeVec( p->pAig, vCiObjs, pObj, i )
{
if ( !Saig_ObjIsLo( p->pAig, pObj ) )
continue;
Entry = Aig_ObjPioNum(pObj) - Saig_ManPiNum(p->pAig);
if ( vPrio == NULL || Vec_IntEntry( vPrio, Entry ) == 0 )
continue;
Vec_IntClear( vUndo );
if ( Pdr_ManExtendOne( p->pAig, pObj, vUndo, vVisits ) )
Vec_IntPush( vCi2Rem, Aig_ObjId(pObj) );
else
Pdr_ManExtendUndo( p->pAig, vUndo );
}
if ( p->pPars->fVeryVerbose )
Pdr_ManPrintCex( p->pAig, vCiObjs, vCiVals, vCi2Rem );
RetValue = Pdr_ManSimDataInit( p->pAig, vCiObjs, vCiVals, vNodes, vCoObjs, vCoVals, vCi2Rem );
assert( RetValue );
// derive the set of resulting registers
Pdr_ManDeriveResult( p->pAig, vCiObjs, vCiVals, vCi2Rem, vRes, vPiLits );
assert( Vec_IntSize(vRes) > 0 );
p->tTsim += clock() - clk;
return Pdr_SetCreate( vRes, vPiLits );
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END
/**CFile****************************************************************
FileName [pdrUtil.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Netlist representation.]
Synopsis [Various utilities.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - November 20, 2010.]
Revision [$Id: pdrUtil.c,v 1.00 2010/11/20 00:00:00 alanmi Exp $]
***********************************************************************/
#include "pdrInt.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Performs fast mapping for one node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Vec_IntSelectSort( int * pArray, int nSize )
{
int temp, i, j, best_i;
for ( i = 0; i < nSize-1; i++ )
{
best_i = i;
for ( j = i+1; j < nSize; j++ )
if ( pArray[j] < pArray[best_i] )
best_i = j;
temp = pArray[i];
pArray[i] = pArray[best_i];
pArray[best_i] = temp;
}
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Pdr_Set_t * Pdr_SetCreate( Vec_Int_t * vLits, Vec_Int_t * vPiLits )
{
Pdr_Set_t * p;
int i;
assert( Vec_IntSize(vLits) + Vec_IntSize(vPiLits) < (1<<15) );
p = (Pdr_Set_t *)ABC_ALLOC( char, sizeof(Pdr_Set_t) + (Vec_IntSize(vLits) + Vec_IntSize(vPiLits)) * sizeof(int) );
p->nLits = Vec_IntSize(vLits);
p->nTotal = Vec_IntSize(vLits) + Vec_IntSize(vPiLits);
p->nRefs = 1;
p->Sign = 0;
for ( i = 0; i < p->nLits; i++ )
{
p->Lits[i] = Vec_IntEntry(vLits, i);
p->Sign |= ((word)1 << (p->Lits[i] % 63));
}
Vec_IntSelectSort( p->Lits, p->nLits );
/*
for ( i = 0; i < p->nLits; i++ )
printf( "%d ", p->Lits[i] );
printf( "\n" );
*/
// remember PI literals
for ( i = p->nLits; i < p->nTotal; i++ )
p->Lits[i] = Vec_IntEntry(vPiLits, i-p->nLits);
return p;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Pdr_Set_t * Pdr_SetCreateFrom( Pdr_Set_t * pSet, int iRemove )
{
Pdr_Set_t * p;
int i, k = 0;
assert( iRemove >= 0 && iRemove < pSet->nLits );
p = (Pdr_Set_t *)ABC_ALLOC( char, sizeof(Pdr_Set_t) + (pSet->nTotal - 1) * sizeof(int) );
p->nLits = pSet->nLits - 1;
p->nTotal = pSet->nTotal - 1;
p->nRefs = 1;
p->Sign = 0;
for ( i = 0; i < pSet->nTotal; i++ )
{
if ( i == iRemove )
continue;
p->Lits[k++] = pSet->Lits[i];
if ( i >= pSet->nLits )
continue;
p->Sign |= ((word)1 << (pSet->Lits[i] % 63));
}
assert( k == p->nTotal );
return p;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Pdr_Set_t * Pdr_SetCreateSubset( Pdr_Set_t * pSet, int * pLits, int nLits )
{
Pdr_Set_t * p;
int i, k = 0;
assert( nLits >= 0 && nLits <= pSet->nLits );
p = (Pdr_Set_t *)ABC_ALLOC( char, sizeof(Pdr_Set_t) + (nLits + pSet->nTotal - pSet->nLits) * sizeof(int) );
p->nLits = nLits;
p->nTotal = nLits + pSet->nTotal - pSet->nLits;
p->nRefs = 1;
p->Sign = 0;
for ( i = 0; i < nLits; i++ )
{
assert( pLits[i] >= 0 );
p->Lits[k++] = pLits[i];
p->Sign |= ((word)1 << (pLits[i] % 63));
}
Vec_IntSelectSort( p->Lits, p->nLits );
for ( i = pSet->nLits; i < pSet->nTotal; i++ )
p->Lits[k++] = pSet->Lits[i];
assert( k == p->nTotal );
return p;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Pdr_Set_t * Pdr_SetDup( Pdr_Set_t * pSet )
{
Pdr_Set_t * p;
int i;
p = (Pdr_Set_t *)ABC_ALLOC( char, sizeof(Pdr_Set_t) + pSet->nTotal * sizeof(int) );
p->nLits = pSet->nLits;
p->nTotal = pSet->nTotal;
p->nRefs = 1;
p->Sign = pSet->Sign;
for ( i = 0; i < pSet->nTotal; i++ )
p->Lits[i] = pSet->Lits[i];
return p;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Pdr_Set_t * Pdr_SetRef( Pdr_Set_t * p )
{
p->nRefs++;
return p;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Pdr_SetDeref( Pdr_Set_t * p )
{
if ( --p->nRefs == 0 )
ABC_FREE( p );
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Pdr_SetPrint( FILE * pFile, Pdr_Set_t * p, int nRegs, Vec_Int_t * vFlopCounts )
{
char * pBuff;
int i, k, Entry;
pBuff = ABC_ALLOC( char, nRegs + 1 );
for ( i = 0; i < nRegs; i++ )
pBuff[i] = '-';
pBuff[i] = 0;
for ( i = 0; i < p->nLits; i++ )
{
if ( p->Lits[i] == -1 )
continue;
pBuff[lit_var(p->Lits[i])] = (lit_sign(p->Lits[i])? '0':'1');
}
if ( vFlopCounts )
{
// skip some literals
k = 0;
Vec_IntForEachEntry( vFlopCounts, Entry, i )
if ( Entry )
pBuff[k++] = pBuff[i];
pBuff[k] = 0;
}
fprintf( pFile, "%s", pBuff );
ABC_FREE( pBuff );
}
/**Function*************************************************************
Synopsis [Return 1 if pOld set-theoretically contains pNew.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Pdr_SetContains( Pdr_Set_t * pOld, Pdr_Set_t * pNew )
{
int * pOldInt, * pNewInt;
assert( pOld->nLits > 0 );
assert( pNew->nLits > 0 );
if ( pOld->nLits < pNew->nLits )
return 0;
if ( (pOld->Sign & pNew->Sign) != pNew->Sign )
return 0;
pOldInt = pOld->Lits + pOld->nLits - 1;
pNewInt = pNew->Lits + pNew->nLits - 1;
while ( pNew->Lits <= pNewInt )
{
if ( pOld->Lits > pOldInt )
return 0;
assert( *pNewInt != -1 );
assert( *pOldInt != -1 );
if ( *pNewInt == *pOldInt )
pNewInt--, pOldInt--;
else if ( *pNewInt < *pOldInt )
pOldInt--;
else
return 0;
}
return 1;
}
/**Function*************************************************************
Synopsis [Return 1 if the state cube contains init state (000...0).]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Pdr_SetIsInit( Pdr_Set_t * pCube, int iRemove )
{
int i;
for ( i = 0; i < pCube->nLits; i++ )
{
assert( pCube->Lits[i] != -1 );
if ( i == iRemove )
continue;
if ( lit_sign( pCube->Lits[i] ) == 0 )
return 0;
}
return 1;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Pdr_SetCompare( Pdr_Set_t ** pp1, Pdr_Set_t ** pp2 )
{
Pdr_Set_t * p1 = *pp1;
Pdr_Set_t * p2 = *pp2;
int i;
for ( i = 0; i < p1->nLits && i < p2->nLits; i++ )
{
if ( p1->Lits[i] > p2->Lits[i] )
return -1;
if ( p1->Lits[i] < p2->Lits[i] )
return 1;
}
if ( i == p1->nLits && i < p2->nLits )
return -1;
if ( i < p1->nLits && i == p2->nLits )
return 1;
return 0;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Pdr_Obl_t * Pdr_OblStart( int k, int prio, Pdr_Set_t * pState, Pdr_Obl_t * pNext )
{
Pdr_Obl_t * p;
p = ABC_ALLOC( Pdr_Obl_t, 1 );
p->iFrame = k;
p->prio = prio;
p->nRefs = 1;
p->pState = pState;
p->pNext = pNext;
p->pLink = NULL;
return p;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Pdr_Obl_t * Pdr_OblRef( Pdr_Obl_t * p )
{
p->nRefs++;
return p;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Pdr_OblDeref( Pdr_Obl_t * p )
{
if ( --p->nRefs == 0 )
{
if ( p->pNext )
Pdr_OblDeref( p->pNext );
Pdr_SetDeref( p->pState );
ABC_FREE( p );
}
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Pdr_QueueIsEmpty( Pdr_Man_t * p )
{
return p->pQueue == NULL;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Pdr_Obl_t * Pdr_QueueHead( Pdr_Man_t * p )
{
return p->pQueue;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Pdr_Obl_t * Pdr_QueuePop( Pdr_Man_t * p )
{
Pdr_Obl_t * pRes = p->pQueue;
if ( p->pQueue == NULL )
return NULL;
p->pQueue = p->pQueue->pLink;
Pdr_OblDeref( pRes );
return pRes;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Pdr_QueuePush( Pdr_Man_t * p, Pdr_Obl_t * pObl )
{
Pdr_Obl_t * pTemp, ** ppPrev;
p->nObligs++;
Pdr_OblRef( pObl );
if ( p->pQueue == NULL )
{
p->pQueue = pObl;
return;
}
for ( ppPrev = &p->pQueue, pTemp = p->pQueue; pTemp; ppPrev = &pTemp->pLink, pTemp = pTemp->pLink )
if ( pTemp->iFrame > pObl->iFrame || (pTemp->iFrame == pObl->iFrame && pTemp->prio > pObl->prio) )
break;
*ppPrev = pObl;
pObl->pLink = pTemp;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Pdr_QueuePrint( Pdr_Man_t * p )
{
Pdr_Obl_t * pObl;
for ( pObl = p->pQueue; pObl; pObl = pObl->pLink )
printf( "Frame = %2d. Prio = %8d.\n", pObl->iFrame, pObl->prio );
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Pdr_QueueStop( Pdr_Man_t * p )
{
Pdr_Obl_t * pObl;
while ( !Pdr_QueueIsEmpty(p) )
{
pObl = Pdr_QueuePop(p);
Pdr_OblDeref( pObl );
}
p->pQueue = NULL;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment