blob: 5bc0d3d63ca100c3f28b72712853c5120aa82e3f [file] [log] [blame]
/**CFile****************************************************************
FileName [pdrTsim.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Property driven reachability.]
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_ObjIsCi(pObj) )
{
Vec_IntPush( vCiObjs, Aig_ObjId(pObj) );
return;
}
Pdr_ManCollectCone_rec( pAig, Aig_ObjFanin0(pObj), vCiObjs, vNodes );
if ( Aig_ObjIsCo(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_ManForEachObjVec( vCoObjs, pAig, 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_ObjIsCo(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_ManForEachObjVec( vCiObjs, pAig, pObj, i )
Pdr_ManSimInfoSet( pAig, pObj, (Vec_IntEntry(vCiVals, i)?PDR_ONE:PDR_ZER) );
// set the FOs to remove
if ( vCi2Rem != NULL )
Aig_ManForEachObjVec( vCi2Rem, pAig, pObj, i )
Pdr_ManSimInfoSet( pAig, pObj, PDR_UND );
// perform ternary simulation
Aig_ManForEachObjVec( vNodes, pAig, pObj, i )
Pdr_ManExtendOneEval( pAig, pObj );
// transfer results to the output
Aig_ManForEachObjVec( vCoObjs, pAig, pObj, i )
Pdr_ManExtendOneEval( pAig, pObj );
// check the results
Aig_ManForEachObjVec( vCoObjs, pAig, 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 = -1, 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_ManForEachObjVec( vVis, pAig, 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_ObjIsCo(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_ManForEachObjVec( vUndo, pAig, 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_ManForEachObjVec( vCi2Rem, pAig, 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_ManForEachObjVec( vCiObjs, pAig, pObj, i )
{
if ( Saig_ObjIsPi(pAig, pObj) )
{
Lit = Abc_Var2Lit( Aig_ObjCioId(pObj), (Vec_IntEntry(vCiVals, i) == 0) );
Vec_IntPush( vPiLits, Lit );
continue;
}
assert( Saig_ObjIsLo(pAig, pObj) );
if ( Aig_ObjIsTravIdCurrent(pAig, pObj) )
continue;
Lit = Abc_Var2Lit( Aig_ObjCioId(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_ManCiNum(pAig)+1 );
for ( i = 0; i < Aig_ManCiNum(pAig); i++ )
pBuff[i] = '-';
pBuff[i] = 0;
Aig_ManForEachObjVec( vCiObjs, pAig, pObj, i )
pBuff[Aig_ObjCioId(pObj)] = (Vec_IntEntry(vCiVals, i)? '1':'0');
if ( vCi2Rem )
Aig_ManForEachObjVec( vCi2Rem, pAig, pObj, i )
pBuff[Aig_ObjCioId(pObj)] = 'x';
Abc_Print( 1, "%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 )
{
Pdr_Set_t * pRes;
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;
//abctime clk = Abc_Clock();
// collect CO objects
Vec_IntClear( vCoObjs );
if ( pCube == NULL ) // the target is the property output
{
// Vec_IntPush( vCoObjs, Aig_ObjId(Aig_ManCo(p->pAig, (p->pPars->iOutput==-1)?0:p->pPars->iOutput)) );
Vec_IntPush( vCoObjs, Aig_ObjId(Aig_ManCo(p->pAig, p->iOutCur)) );
}
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 )
{
Abc_Print( 1, "Trying to justify cube " );
if ( pCube )
Pdr_SetPrint( stdout, pCube, Aig_ManRegNum(p->pAig), NULL );
else
Abc_Print( 1, "<prop=fail>" );
Abc_Print( 1, " 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 );
// iteratively remove flops
if ( p->pPars->fFlopPrio )
{
// collect flops and sort them by priority
Vec_IntClear( vRes );
Aig_ManForEachObjVec( vCiObjs, p->pAig, pObj, i )
{
if ( !Saig_ObjIsLo( p->pAig, pObj ) )
continue;
Entry = Aig_ObjCioId(pObj) - Saig_ManPiNum(p->pAig);
Vec_IntPush( vRes, Entry );
}
Vec_IntSelectSortCost( Vec_IntArray(vRes), Vec_IntSize(vRes), vPrio );
// try removing flops starting from low-priority to high-priority
Vec_IntClear( vCi2Rem );
Vec_IntForEachEntry( vRes, Entry, i )
{
pObj = Aig_ManCi( p->pAig, Saig_ManPiNum(p->pAig) + Entry );
assert( Saig_ObjIsLo( p->pAig, pObj ) );
Vec_IntClear( vUndo );
if ( Pdr_ManExtendOne( p->pAig, pObj, vUndo, vVisits ) )
Vec_IntPush( vCi2Rem, Aig_ObjId(pObj) );
else
Pdr_ManExtendUndo( p->pAig, vUndo );
}
}
else
{
// try removing low-priority flops first
Vec_IntClear( vCi2Rem );
Aig_ManForEachObjVec( vCiObjs, p->pAig, pObj, i )
{
if ( !Saig_ObjIsLo( p->pAig, pObj ) )
continue;
Entry = Aig_ObjCioId(pObj) - Saig_ManPiNum(p->pAig);
if ( Vec_IntEntry(vPrio, Entry) )
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 high-priority flops next
Aig_ManForEachObjVec( vCiObjs, p->pAig, pObj, i )
{
if ( !Saig_ObjIsLo( p->pAig, pObj ) )
continue;
Entry = Aig_ObjCioId(pObj) - Saig_ManPiNum(p->pAig);
if ( !Vec_IntEntry(vPrio, Entry) )
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 += Abc_Clock() - clk;
// move abstracted literals from flops to inputs
if ( p->pPars->fUseAbs && p->vAbsFlops )
{
int i, iLit, k = 0;
Vec_IntForEachEntry( vRes, iLit, i )
{
if ( Vec_IntEntry(p->vAbsFlops, Abc_Lit2Var(iLit)) ) // used flop
Vec_IntWriteEntry( vRes, k++, iLit );
else
Vec_IntPush( vPiLits, 2*Saig_ManPiNum(p->pAig) + iLit );
}
Vec_IntShrink( vRes, k );
}
pRes = Pdr_SetCreate( vRes, vPiLits );
//ZH: Disabled assertion because this invariant doesn't hold with down
//because of the join operation which can bring in initial states
//assert( k == 0 || !Pdr_SetIsInit(pRes, -1) );
return pRes;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END