/**CFile**************************************************************** FileName [cecSim.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Combinational equivalence checking.] Synopsis [Simulation.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: cecSim.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "cecInt.h" #include "aig/gia/giaAig.h" #include "misc/util/utilTruth.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #define SIM_RANDS 113 typedef struct Cec_ManS_t_ Cec_ManS_t; struct Cec_ManS_t_ { int nWords; int nLevelMax; int nLevelMin; int iRand; Gia_Man_t * pAig; Vec_Int_t * vInputs; Vec_Wec_t * vLevels; Vec_Wrd_t * vSims; word * pTemp[4]; word Rands[SIM_RANDS]; int nSkipped; int nVisited; int nCexes; abctime clkSat; abctime clkUnsat; }; static inline word * Cec_ManSSim( Cec_ManS_t * p, int iNode, int Value ) { return Vec_WrdEntryP(p->vSims, p->nWords*(iNode+iNode+Value)); } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Cec_ManS_t * Cec_ManSStart( Gia_Man_t * pAig, int nWords ) { Cec_ManS_t * p; int i; p = ABC_ALLOC( Cec_ManS_t, 1 ); memset( p, 0, sizeof(Cec_ManS_t) ); p->nWords = nWords; p->pAig = pAig; p->vInputs = Vec_IntAlloc( 100 ); p->vLevels = Vec_WecStart( Gia_ManLevelNum(pAig) + 1 ); p->vSims = Vec_WrdStart( Gia_ManObjNum(pAig) * nWords * 2 ); p->pTemp[0] = ABC_ALLOC( word, 4*nWords ); for ( i = 1; i < 4; i++ ) p->pTemp[i] = p->pTemp[i-1] + nWords; for ( i = 0; i < SIM_RANDS; i++ ) p->Rands[i] = Gia_ManRandomW(0); return p; } void Cec_ManSStop( Cec_ManS_t * p ) { Vec_IntFree( p->vInputs ); Vec_WecFree( p->vLevels ); Vec_WrdFree( p->vSims ); ABC_FREE( p->pTemp[0] ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Verify counter-example.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Cec_ManSVerify_rec( Gia_Man_t * p, int iObj ) { int Value0, Value1; Gia_Obj_t * pObj = Gia_ManObj( p, iObj ); if ( iObj == 0 ) return 0; if ( Gia_ObjIsTravIdCurrentId(p, iObj) ) return pObj->fMark1; Gia_ObjSetTravIdCurrentId(p, iObj); if ( Gia_ObjIsCi(pObj) ) return pObj->fMark1; assert( Gia_ObjIsAnd(pObj) ); Value0 = Cec_ManSVerify_rec( p, Gia_ObjFaninId0(pObj, iObj) ) ^ Gia_ObjFaninC0(pObj); Value1 = Cec_ManSVerify_rec( p, Gia_ObjFaninId1(pObj, iObj) ) ^ Gia_ObjFaninC1(pObj); return pObj->fMark1 = Gia_ObjIsXor(pObj) ? Value0 ^ Value1 : Value0 & Value1; } void Cec_ManSVerifyTwo( Gia_Man_t * p, int iObj0, int iObj1 ) { int Value0, Value1; Gia_ManIncrementTravId( p ); Value0 = Cec_ManSVerify_rec( p, iObj0 ); Value1 = Cec_ManSVerify_rec( p, iObj1 ); if ( (Value0 ^ Value1) == Gia_ObjPhaseDiff(p, iObj0, iObj1) ) printf( "CEX verification FAILED for obj %d and obj %d.\n", iObj0, iObj1 ); // else // printf( "CEX verification succeeded for obj %d and obj %d.\n", iObj0, iObj1 );; } void Cec_ManSVerify( Cec_ManS_t * p, int iObj0, int iObj1 ) { int fDoVerify = 0; int w, i, iObj, nCares; word * pCare = Vec_WrdArray(p->vSims); if ( Vec_IntSize(p->vInputs) == 0 ) { printf( "No primary inputs.\n" ); return; } Vec_IntForEachEntry( p->vInputs, iObj, i ) { word * pSim_0 = Cec_ManSSim( p, iObj, 0 ); word * pSim_1 = Cec_ManSSim( p, iObj, 1 ); if ( p->nWords == 1 ) pCare[0] |= pSim_0[0] & pSim_1[0]; else Abc_TtOrAnd( pCare, pSim_0, pSim_1, p->nWords ); } nCares = Abc_TtCountOnesVec( pCare, p->nWords ); if ( nCares == 64*p->nWords ) { printf( "No CEXes.\n" ); return; } assert( Vec_IntSize(p->vInputs) > 0 ); for ( w = 0; w < 64*p->nWords; w++ ) { if ( Abc_TtGetBit(pCare, w) ) continue; if ( !fDoVerify ) continue; Vec_IntForEachEntry( p->vInputs, iObj, i ) Gia_ManObj(p->pAig, iObj)->fMark1 = Abc_TtGetBit( Cec_ManSSim(p, iObj, 1), w ); Cec_ManSVerifyTwo( p->pAig, iObj0, iObj1 ); } printf( "Considered %d CEXes of nodes %d and %d.\n", 64*p->nWords - nCares, iObj0, iObj1 ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cec_ManSRunImply( Cec_ManS_t * p, int iNode ) { Gia_Obj_t * pNode = Gia_ManObj( p->pAig, iNode ); if ( Gia_ObjIsAnd(pNode) ) { int iFan0 = Gia_ObjFaninId0( pNode, iNode ); int iFan1 = Gia_ObjFaninId1( pNode, iNode ); word * pSim__ = Cec_ManSSim( p, 0, 0 ); word * pSim_0 = Cec_ManSSim( p, iNode, 0 ); word * pSim_1 = Cec_ManSSim( p, iNode, 1 ); word * pSim00 = Cec_ManSSim( p, iFan0, Gia_ObjFaninC0(pNode) ); word * pSim01 = Cec_ManSSim( p, iFan0, !Gia_ObjFaninC0(pNode) ); word * pSim10 = Cec_ManSSim( p, iFan1, Gia_ObjFaninC1(pNode) ); word * pSim11 = Cec_ManSSim( p, iFan1, !Gia_ObjFaninC1(pNode) ); if ( p->nWords == 1 ) { pSim_0[0] |= pSim00[0] | pSim10[0]; pSim_1[0] |= pSim01[0] & pSim11[0]; pSim__[0] |= pSim_0[0] & pSim_1[0]; pSim_0[0] &= ~pSim__[0]; pSim_1[0] &= ~pSim__[0]; } else { Abc_TtOr( pSim_0, pSim_0, pSim00, p->nWords ); Abc_TtOr( pSim_0, pSim_0, pSim10, p->nWords ); Abc_TtOrAnd( pSim_1, pSim01, pSim11, p->nWords ); Abc_TtOrAnd( pSim__, pSim_0, pSim_1, p->nWords ); Abc_TtAndSharp( pSim_0, pSim_0, pSim__, p->nWords, 1 ); Abc_TtAndSharp( pSim_1, pSim_1, pSim__, p->nWords, 1 ); } } } int Cec_ManSRunPropagate( Cec_ManS_t * p, int iNode ) { Gia_Obj_t * pNode = Gia_ManObj( p->pAig, iNode ); int iFan0 = Gia_ObjFaninId0( pNode, iNode ); int iFan1 = Gia_ObjFaninId1( pNode, iNode ); word * pSim_0 = Cec_ManSSim( p, iNode, 0 ); word * pSim_1 = Cec_ManSSim( p, iNode, 1 ); if ( Abc_TtIsConst0(pSim_0, p->nWords) && Abc_TtIsConst0(pSim_1, p->nWords) ) { p->nSkipped++; return 0; } p->nVisited++; //Cec_ManSRunImply( p, iFan0 ); //Cec_ManSRunImply( p, iFan1 ); { word * pSim__ = Cec_ManSSim( p, 0, 0 ); word * pSim00 = Cec_ManSSim( p, iFan0, Gia_ObjFaninC0(pNode) ); word * pSim01 = Cec_ManSSim( p, iFan0, !Gia_ObjFaninC0(pNode) ); word * pSim10 = Cec_ManSSim( p, iFan1, Gia_ObjFaninC1(pNode) ); word * pSim11 = Cec_ManSSim( p, iFan1, !Gia_ObjFaninC1(pNode) ); p->iRand = p->iRand == SIM_RANDS-1 ? 0 : p->iRand + 1; if ( p->nWords == 1 ) { pSim01[0] |= pSim_1[0]; pSim11[0] |= pSim_1[0]; pSim00[0] |= pSim_0[0] & (pSim11[0] | ~p->Rands[p->iRand]); pSim10[0] |= pSim_0[0] & (pSim01[0] | p->Rands[p->iRand]); pSim__[0] |= pSim00[0] & pSim01[0]; pSim__[0] |= pSim10[0] & pSim11[0]; pSim00[0] &= ~pSim__[0]; pSim01[0] &= ~pSim__[0]; pSim10[0] &= ~pSim__[0]; pSim11[0] &= ~pSim__[0]; } else { int w; for ( w = 0; w < p->nWords; w++ ) p->pTemp[0][w] = ~p->Rands[(p->iRand + w) % SIM_RANDS]; Abc_TtOr( pSim01, pSim01, pSim_1, p->nWords ); Abc_TtOr( pSim11, pSim11, pSim_1, p->nWords ); Abc_TtOr( p->pTemp[1], pSim11, p->pTemp[0], p->nWords ); Abc_TtOrAnd( pSim00, pSim_0, p->pTemp[1], p->nWords ); Abc_TtNot( p->pTemp[0], p->nWords ); Abc_TtOr( p->pTemp[1], pSim01, p->pTemp[0], p->nWords ); Abc_TtOrAnd( pSim10, pSim_0, p->pTemp[1], p->nWords ); Abc_TtOrAnd( pSim__, pSim00, pSim01, p->nWords ); Abc_TtOrAnd( pSim__, pSim10, pSim11, p->nWords ); Abc_TtAndSharp( pSim00, pSim00, pSim__, p->nWords, 1 ); Abc_TtAndSharp( pSim01, pSim01, pSim__, p->nWords, 1 ); Abc_TtAndSharp( pSim10, pSim10, pSim__, p->nWords, 1 ); Abc_TtAndSharp( pSim11, pSim11, pSim__, p->nWords, 1 ); } } return 1; } void Cec_ManSInsert( Cec_ManS_t * p, int iNode ) { Gia_Obj_t * pNode; int Level; assert( iNode > 0 ); if ( Gia_ObjIsTravIdCurrentId(p->pAig, iNode) ) return; Gia_ObjSetTravIdCurrentId(p->pAig, iNode); pNode = Gia_ManObj( p->pAig, iNode ); if ( Gia_ObjIsCi(pNode) ) { Vec_IntPush( p->vInputs, iNode ); return; } assert( Gia_ObjIsAnd(pNode) ); Level = Gia_ObjLevelId( p->pAig, iNode ); assert( Level > 0 ); Vec_WecPush( p->vLevels, Level, iNode ); p->nLevelMax = Abc_MaxInt( p->nLevelMax, Level ); p->nLevelMin = Abc_MinInt( p->nLevelMin, Level ); assert( p->nLevelMin <= p->nLevelMax ); } int Cec_ManSRunSimInt( Cec_ManS_t * p ) { Vec_Int_t * vLevel; int i, k, iNode, fSolved = 0; Vec_WecForEachLevelReverseStartStop( p->vLevels, vLevel, i, p->nLevelMax+1, p->nLevelMin ) { Vec_IntForEachEntry( vLevel, iNode, k ) { Gia_Obj_t * pNode = Gia_ManObj( p->pAig, iNode ); if ( !fSolved && Cec_ManSRunPropagate( p, iNode ) ) { Cec_ManSInsert( p, Gia_ObjFaninId0(pNode, iNode) ); Cec_ManSInsert( p, Gia_ObjFaninId1(pNode, iNode) ); if ( Abc_TtIsConst1(Vec_WrdArray(p->vSims), p->nWords) ) fSolved = 1; } Abc_TtClear( Cec_ManSSim(p, iNode, 0), 2*p->nWords ); } Vec_IntClear( vLevel ); } //Vec_WecForEachLevel( p->vLevels, vLevel, i ) // assert( Vec_IntSize(vLevel) == 0 ); return fSolved; } int Cec_ManSRunSim( Cec_ManS_t * p, int iNode0, int iNode1 ) { abctime clk = Abc_Clock(); //Vec_Int_t * vLevel; //int pNodes[2] = { iNode0, iNode1 }; int i, iNode, Status, fDiff = Gia_ObjPhaseDiff( p->pAig, iNode0, iNode1 ); word * pSim00 = Cec_ManSSim( p, iNode0, 0 ); word * pSim01 = Cec_ManSSim( p, iNode0, 1 ); word * pSim10 = Cec_ManSSim( p, iNode1, fDiff ); word * pSim11 = Cec_ManSSim( p, iNode1, !fDiff ); Abc_TtClear( Vec_WrdArray(p->vSims), p->nWords ); //for ( i = 0; i < Vec_WrdSize(p->vSims); i++ ) // assert( p->vSims->pArray[i] == 0 ); assert( Vec_IntSize(p->vInputs) == 0 ); if ( iNode0 == 0 ) Abc_TtFill( pSim11, p->nWords ); else { if ( p->nWords == 1 ) { pSim00[0] = (word)0xFFFFFFFF; pSim11[0] = (word)0xFFFFFFFF; pSim01[0] = pSim00[0] << 32; pSim10[0] = pSim11[0] << 32; } else { assert( p->nWords % 2 == 0 ); Abc_TtFill( pSim00, p->nWords/2 ); Abc_TtFill( pSim11, p->nWords/2 ); Abc_TtFill( pSim01 + p->nWords/2, p->nWords/2 ); Abc_TtFill( pSim10 + p->nWords/2, p->nWords/2 ); } } p->nLevelMin = ABC_INFINITY; p->nLevelMax = 0; Gia_ManIncrementTravId( p->pAig ); if ( iNode0 ) Cec_ManSInsert( p, iNode0 ); Cec_ManSInsert( p, iNode1 ); p->nSkipped = p->nVisited = 0; Status = Cec_ManSRunSimInt( p ); if ( Status == 0 ) p->clkSat += Abc_Clock() - clk; else p->clkUnsat += Abc_Clock() - clk; // if ( Status == 0 ) // printf( "Solving %6d and %6d. Skipped = %6d. Visited = %6d. Cone = %6d. Min = %3d. Max = %3d.\n", // iNode0, iNode1, p->nSkipped, p->nVisited, Gia_ManConeSize(p->pAig, pNodes, 2), p->nLevelMin, p->nLevelMax ); if ( Status == 0 ) Cec_ManSVerify( p, iNode0, iNode1 ), p->nCexes++; Vec_IntForEachEntry( p->vInputs, iNode, i ) Abc_TtClear( Cec_ManSSim(p, iNode, 0), 2*p->nWords ); Vec_IntClear( p->vInputs ); return Status; } void Cec_ManSRunTest( Gia_Man_t * pAig ) { abctime clk = Abc_Clock(); Cec_ManS_t * p; int i, k, nWords = 1; Gia_ManRandomW( 1 ); p = Cec_ManSStart( pAig, nWords ); Gia_ManForEachClass0( p->pAig, i ) Gia_ClassForEachObj1( p->pAig, i, k ) Cec_ManSRunSim( p, i, k ); printf( "Detected %d CEXes. ", p->nCexes ); Abc_PrintTime( 1, "Time ", Abc_Clock() - clk ); Abc_PrintTime( 1, "Sat ", p->clkSat ); Abc_PrintTime( 1, "Unsat", p->clkUnsat ); Cec_ManSStop( p ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END