summaryrefslogtreecommitdiffstats
path: root/src/proof/abs/absRefJ.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/proof/abs/absRefJ.c')
-rw-r--r--src/proof/abs/absRefJ.c916
1 files changed, 916 insertions, 0 deletions
diff --git a/src/proof/abs/absRefJ.c b/src/proof/abs/absRefJ.c
new file mode 100644
index 00000000..aa5ea7bb
--- /dev/null
+++ b/src/proof/abs/absRefJ.c
@@ -0,0 +1,916 @@
+/**CFile****************************************************************
+
+ FileName [absRef2.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Abstraction package.]
+
+ Synopsis [Refinement manager to compute all justifying subsets.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: absRef2.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "abs.h"
+#include "absRef2.h"
+
+ABC_NAMESPACE_IMPL_START
+
+/*
+ Description of the refinement manager
+
+ This refinement manager should be
+ * started by calling Rf2_ManStart()
+ this procedure takes one argument, the user's seq miter as a GIA manager
+ - the manager should have only one property output
+ - this manager should not change while the refinement manager is alive
+ - it cannot be used by external applications for any purpose
+ - when the refinement manager stop, GIA manager is the same as at the beginning
+ - in the meantime, it will have some data-structures attached to its nodes...
+ * stopped by calling Rf2_ManStop()
+ * between starting and stopping, refinements are obtained by calling Rf2_ManRefine()
+
+ Procedure Rf2_ManRefine() takes the following arguments:
+ * the refinement manager previously started by Rf2_ManStart()
+ * counter-example (CEX) obtained by abstracting some logic of GIA
+ * mapping (vMap) of inputs of the CEX into the object IDs of the GIA manager
+ - only PI, flop outputs, and internal AND nodes can be used in vMap
+ - the ordering of objects in vMap is not important
+ - however, the index of a non-PI object in vMap is used as its priority
+ (the smaller the index, the more likely this non-PI object apears in a refinement)
+ - only the logic between PO and the objects listed in vMap is traversed by the manager
+ (as a result, GIA can be arbitrarily large, but only objects used in the abstraction
+ and the pseudo-PI, that is, objects in the cut, will be visited by the manager)
+ * flag fPropFanout defines whether value propagation is done through the fanout
+ - it this flag is enabled, theoretically refinement should be better (the result smaller)
+ * flag fVerbose may print some statistics
+
+ The refinement manager returns a minimal-size array of integer IDs of GIA objects
+ which should be added to the abstraction to possibly prevent the given counter-example
+ - only flop output and internal AND nodes from vMap may appear in the resulting array
+ - if the resulting array is empty, the CEX is a true CEX
+ (in other words, non-PI objects are not needed to set the PO value to 1)
+
+ Verification of the selected refinement is performed by
+ - initializing all PI objects in vMap to value 0 or 1 they have in the CEX
+ - initializing all remaining objects in vMap to value X
+ - initializing objects used in the refiment to value 0 or 1 they have in the CEX
+ - simulating through as many timeframes as required by the CEX
+ - if the PO value in the last frame is 1, the refinement is correct
+ (however, the minimality of the refinement is not currently checked)
+
+*/
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Rf2_Obj_t_ Rf2_Obj_t; // refinement object
+struct Rf2_Obj_t_
+{
+ unsigned Value : 1; // binary value
+ unsigned fVisit : 1; // visited object
+ unsigned fPPi : 1; // PPI object
+ unsigned Prio : 24; // priority (0 - highest)
+};
+
+struct Rf2_Man_t_
+{
+ // user data
+ Gia_Man_t * pGia; // working AIG manager (it is completely owned by this package)
+ Abc_Cex_t * pCex; // counter-example
+ Vec_Int_t * vMap; // mapping of CEX inputs into objects (PI + PPI, in any order)
+ int fPropFanout; // propagate fanouts
+ int fVerbose; // verbose flag
+ // traversing data
+ Vec_Int_t * vObjs; // internal objects used in value propagation
+ Vec_Int_t * vFanins; // fanins of the PPI nodes
+ Vec_Int_t * pvVecs; // vectors of integers for each object
+ Vec_Vec_t * vGrp2Ppi; // for each node, the set of PPIs to include
+ int nMapWords;
+ // internal data
+ Rf2_Obj_t * pObjs; // refinement objects
+ int nObjs; // the number of used objects
+ int nObjsAlloc; // the number of allocated objects
+ int nObjsFrame; // the number of used objects in each frame
+ int nCalls; // total number of calls
+ int nRefines; // total refined objects
+ // statistics
+ clock_t timeFwd; // forward propagation
+ clock_t timeBwd; // backward propagation
+ clock_t timeVer; // ternary simulation
+ clock_t timeTotal; // other time
+};
+
+// accessing the refinement object
+static inline Rf2_Obj_t * Rf2_ManObj( Rf2_Man_t * p, Gia_Obj_t * pObj, int f )
+{
+ assert( Gia_ObjIsConst0(pObj) || pObj->Value );
+ assert( (int)pObj->Value < p->nObjsFrame );
+ assert( f >= 0 && f <= p->pCex->iFrame );
+ return p->pObjs + f * p->nObjsFrame + pObj->Value;
+}
+
+static inline Vec_Int_t * Rf2_ObjVec( Rf2_Man_t * p, Gia_Obj_t * pObj )
+{
+ return p->pvVecs + Gia_ObjId(p->pGia, pObj);
+}
+
+
+static inline unsigned * Rf2_ObjA( Rf2_Man_t * p, Gia_Obj_t * pObj )
+{
+ return (unsigned *)Vec_IntArray(Rf2_ObjVec(p, pObj));
+}
+static inline unsigned * Rf2_ObjN( Rf2_Man_t * p, Gia_Obj_t * pObj )
+{
+ return (unsigned *)Vec_IntArray(Rf2_ObjVec(p, pObj)) + p->nMapWords;
+}
+static inline void Rf2_ObjClear( Rf2_Man_t * p, Gia_Obj_t * pObj )
+{
+ Vec_IntFill( Rf2_ObjVec(p, pObj), 2*p->nMapWords, 0 );
+}
+static inline void Rf2_ObjStart( Rf2_Man_t * p, Gia_Obj_t * pObj, int i )
+{
+ Vec_Int_t * vVec = Rf2_ObjVec(p, pObj);
+ int w;
+ Vec_IntClear( vVec );
+ for ( w = 0; w < p->nMapWords; w++ )
+ Vec_IntPush( vVec, 0 );
+ for ( w = 0; w < p->nMapWords; w++ )
+ Vec_IntPush( vVec, ~0 );
+ Abc_InfoSetBit( Rf2_ObjA(p, pObj), i );
+ Abc_InfoXorBit( Rf2_ObjN(p, pObj), i );
+}
+static inline void Rf2_ObjCopy( Rf2_Man_t * p, Gia_Obj_t * pObj, Gia_Obj_t * pFanin )
+{
+ assert( Vec_IntSize(Rf2_ObjVec(p, pObj)) == 2*p->nMapWords );
+ memcpy( Rf2_ObjA(p, pObj), Rf2_ObjA(p, pFanin), sizeof(unsigned) * 2 * p->nMapWords );
+}
+static inline void Rf2_ObjDeriveAnd( Rf2_Man_t * p, Gia_Obj_t * pObj, int One )
+{
+ unsigned * pInfo, * pInfo0, * pInfo1;
+ int i;
+ assert( Gia_ObjIsAnd(pObj) );
+ assert( One == (int)pObj->fMark0 );
+ assert( One == (int)(Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj)) );
+ assert( One == (int)(Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj)) );
+ assert( Vec_IntSize(Rf2_ObjVec(p, pObj)) == 2*p->nMapWords );
+
+ pInfo = Rf2_ObjA( p, pObj );
+ pInfo0 = Rf2_ObjA( p, Gia_ObjFanin0(pObj) );
+ pInfo1 = Rf2_ObjA( p, Gia_ObjFanin1(pObj) );
+ for ( i = 0; i < p->nMapWords; i++ )
+ pInfo[i] = One ? (pInfo0[i] & pInfo1[i]) : (pInfo0[i] | pInfo1[i]);
+
+ pInfo = Rf2_ObjN( p, pObj );
+ pInfo0 = Rf2_ObjN( p, Gia_ObjFanin0(pObj) );
+ pInfo1 = Rf2_ObjN( p, Gia_ObjFanin1(pObj) );
+ for ( i = 0; i < p->nMapWords; i++ )
+ pInfo[i] = One ? (pInfo0[i] | pInfo1[i]) : (pInfo0[i] & pInfo1[i]);
+}
+static inline void Rf2_ObjPrint( Rf2_Man_t * p, Gia_Obj_t * pRoot )
+{
+ Gia_Obj_t * pObj;
+ unsigned * pInfo;
+ int i;
+ pInfo = Rf2_ObjA( p, pRoot );
+ Gia_ManForEachObjVec( p->vMap, p->pGia, pObj, i )
+ if ( !Gia_ObjIsPi(p->pGia, pObj) )
+ printf( "%d", Abc_InfoHasBit(pInfo, i) );
+ printf( "\n" );
+ pInfo = Rf2_ObjN( p, pRoot );
+ Gia_ManForEachObjVec( p->vMap, p->pGia, pObj, i )
+ if ( !Gia_ObjIsPi(p->pGia, pObj) )
+ printf( "%d", !Abc_InfoHasBit(pInfo, i) );
+ printf( "\n" );
+
+}
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Creates a new manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Rf2_Man_t * Rf2_ManStart( Gia_Man_t * pGia )
+{
+ Rf2_Man_t * p;
+ assert( Gia_ManPoNum(pGia) == 1 );
+ p = ABC_CALLOC( Rf2_Man_t, 1 );
+ p->pGia = pGia;
+ p->vObjs = Vec_IntAlloc( 1000 );
+ p->vFanins = Vec_IntAlloc( 1000 );
+ p->pvVecs = ABC_CALLOC( Vec_Int_t, Gia_ManObjNum(pGia) );
+ p->vGrp2Ppi = Vec_VecStart( 100 );
+ Gia_ManCleanMark0(pGia);
+ Gia_ManCleanMark1(pGia);
+ return p;
+}
+void Rf2_ManStop( Rf2_Man_t * p, int fProfile )
+{
+ if ( !p ) return;
+ // print runtime statistics
+ if ( fProfile && p->nCalls )
+ {
+ double MemGia = sizeof(Gia_Man_t) + sizeof(Gia_Obj_t) * p->pGia->nObjsAlloc + sizeof(int) * p->pGia->nTravIdsAlloc;
+ double MemOther = sizeof(Rf2_Man_t) + sizeof(Rf2_Obj_t) * p->nObjsAlloc + sizeof(int) * Vec_IntCap(p->vObjs);
+ clock_t timeOther = p->timeTotal - p->timeFwd - p->timeBwd - p->timeVer;
+ printf( "Abstraction refinement runtime statistics:\n" );
+ ABC_PRTP( "Sensetization", p->timeFwd, p->timeTotal );
+ ABC_PRTP( "Justification", p->timeBwd, p->timeTotal );
+ ABC_PRTP( "Verification ", p->timeVer, p->timeTotal );
+ ABC_PRTP( "Other ", timeOther, p->timeTotal );
+ ABC_PRTP( "TOTAL ", p->timeTotal, p->timeTotal );
+ printf( "Total calls = %d. Average refine = %.1f. GIA mem = %.3f MB. Other mem = %.3f MB.\n",
+ p->nCalls, 1.0*p->nRefines/p->nCalls, MemGia/(1<<20), MemOther/(1<<20) );
+ }
+ Vec_IntFree( p->vObjs );
+ Vec_IntFree( p->vFanins );
+ Vec_VecFree( p->vGrp2Ppi );
+ ABC_FREE( p->pvVecs );
+ ABC_FREE( p );
+}
+double Rf2_ManMemoryUsage( Rf2_Man_t * p )
+{
+ return (double)(sizeof(Rf2_Man_t) + sizeof(Vec_Int_t) * Gia_ManObjNum(p->pGia));
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Collect internal objects to be used in value propagation.]
+
+ Description [Resulting array vObjs contains RO, AND, PO/RI in a topo order.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Rf2_ManCollect_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vObjs )
+{
+ if ( Gia_ObjIsTravIdCurrent(p, pObj) )
+ return;
+ Gia_ObjSetTravIdCurrent(p, pObj);
+ if ( Gia_ObjIsCo(pObj) )
+ Rf2_ManCollect_rec( p, Gia_ObjFanin0(pObj), vObjs );
+ else if ( Gia_ObjIsAnd(pObj) )
+ {
+ Rf2_ManCollect_rec( p, Gia_ObjFanin0(pObj), vObjs );
+ Rf2_ManCollect_rec( p, Gia_ObjFanin1(pObj), vObjs );
+ }
+ else if ( !Gia_ObjIsRo(p, pObj) )
+ assert( 0 );
+ Vec_IntPush( vObjs, Gia_ObjId(p, pObj) );
+}
+void Rf2_ManCollect( Rf2_Man_t * p )
+{
+ Gia_Obj_t * pObj = NULL;
+ int i;
+ // mark const/PIs/PPIs
+ Gia_ManIncrementTravId( p->pGia );
+ Gia_ObjSetTravIdCurrent( p->pGia, Gia_ManConst0(p->pGia) );
+ Gia_ManForEachObjVec( p->vMap, p->pGia, pObj, i )
+ {
+ assert( Gia_ObjIsCi(pObj) || Gia_ObjIsAnd(pObj) );
+ Gia_ObjSetTravIdCurrent( p->pGia, pObj );
+ }
+ // collect objects
+ Vec_IntClear( p->vObjs );
+ Rf2_ManCollect_rec( p->pGia, Gia_ManPo(p->pGia, 0), p->vObjs );
+ Gia_ManForEachObjVec( p->vObjs, p->pGia, pObj, i )
+ if ( Gia_ObjIsRo(p->pGia, pObj) )
+ Rf2_ManCollect_rec( p->pGia, Gia_ObjRoToRi(p->pGia, pObj), p->vObjs );
+ // the last object should be a CO
+ assert( Gia_ObjIsCo(pObj) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs sensitization analysis.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Rf2_ManSensitize( Rf2_Man_t * p )
+{
+ Rf2_Obj_t * pRnm, * pRnm0, * pRnm1;
+ Gia_Obj_t * pObj;
+ int f, i, iBit = p->pCex->nRegs;
+ // const0 is initialized automatically in all timeframes
+ for ( f = 0; f <= p->pCex->iFrame; f++, iBit += p->pCex->nPis )
+ {
+ Gia_ManForEachObjVec( p->vMap, p->pGia, pObj, i )
+ {
+ assert( Gia_ObjIsCi(pObj) || Gia_ObjIsAnd(pObj) );
+ pRnm = Rf2_ManObj( p, pObj, f );
+ pRnm->Value = Abc_InfoHasBit( p->pCex->pData, iBit + i );
+ if ( !Gia_ObjIsPi(p->pGia, pObj) ) // this is PPI
+ {
+ assert( pObj->Value > 0 );
+ pRnm->Prio = pObj->Value;
+ pRnm->fPPi = 1;
+ }
+ }
+ Gia_ManForEachObjVec( p->vObjs, p->pGia, pObj, i )
+ {
+ assert( Gia_ObjIsRo(p->pGia, pObj) || Gia_ObjIsAnd(pObj) || Gia_ObjIsCo(pObj) );
+ pRnm = Rf2_ManObj( p, pObj, f );
+ assert( !pRnm->fPPi );
+ if ( Gia_ObjIsRo(p->pGia, pObj) )
+ {
+ if ( f == 0 )
+ continue;
+ pRnm0 = Rf2_ManObj( p, Gia_ObjRoToRi(p->pGia, pObj), f-1 );
+ pRnm->Value = pRnm0->Value;
+ pRnm->Prio = pRnm0->Prio;
+ continue;
+ }
+ if ( Gia_ObjIsCo(pObj) )
+ {
+ pRnm0 = Rf2_ManObj( p, Gia_ObjFanin0(pObj), f );
+ pRnm->Value = (pRnm0->Value ^ Gia_ObjFaninC0(pObj));
+ pRnm->Prio = pRnm0->Prio;
+ continue;
+ }
+ assert( Gia_ObjIsAnd(pObj) );
+ pRnm0 = Rf2_ManObj( p, Gia_ObjFanin0(pObj), f );
+ pRnm1 = Rf2_ManObj( p, Gia_ObjFanin1(pObj), f );
+ pRnm->Value = (pRnm0->Value ^ Gia_ObjFaninC0(pObj)) & (pRnm1->Value ^ Gia_ObjFaninC1(pObj));
+ if ( pRnm->Value == 1 )
+ pRnm->Prio = Abc_MaxInt( pRnm0->Prio, pRnm1->Prio );
+ else if ( (pRnm0->Value ^ Gia_ObjFaninC0(pObj)) == 0 && (pRnm1->Value ^ Gia_ObjFaninC1(pObj)) == 0 )
+ pRnm->Prio = Abc_MinInt( pRnm0->Prio, pRnm1->Prio ); // choice
+ else if ( (pRnm0->Value ^ Gia_ObjFaninC0(pObj)) == 0 )
+ pRnm->Prio = pRnm0->Prio;
+ else
+ pRnm->Prio = pRnm1->Prio;
+ }
+ }
+ assert( iBit == p->pCex->nBits );
+ pRnm = Rf2_ManObj( p, Gia_ManPo(p->pGia, 0), p->pCex->iFrame );
+ if ( pRnm->Value != 1 )
+ printf( "Output value is incorrect.\n" );
+ return pRnm->Prio;
+}
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Performs refinement.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Rf2_ManVerifyUsingTerSim( Gia_Man_t * p, Abc_Cex_t * pCex, Vec_Int_t * vMap, Vec_Int_t * vObjs, Vec_Int_t * vRes )
+{
+ Gia_Obj_t * pObj;
+ int i, f, iBit = pCex->nRegs;
+ Gia_ObjTerSimSet0( Gia_ManConst0(p) );
+ for ( f = 0; f <= pCex->iFrame; f++, iBit += pCex->nPis )
+ {
+ Gia_ManForEachObjVec( vMap, p, pObj, i )
+ {
+ pObj->Value = Abc_InfoHasBit( pCex->pData, iBit + i );
+ if ( !Gia_ObjIsPi(p, pObj) )
+ Gia_ObjTerSimSetX( pObj );
+ else if ( pObj->Value )
+ Gia_ObjTerSimSet1( pObj );
+ else
+ Gia_ObjTerSimSet0( pObj );
+ }
+ Gia_ManForEachObjVec( vRes, p, pObj, i ) // vRes is subset of vMap
+ {
+ if ( pObj->Value )
+ Gia_ObjTerSimSet1( pObj );
+ else
+ Gia_ObjTerSimSet0( pObj );
+ }
+ Gia_ManForEachObjVec( vObjs, p, pObj, i )
+ {
+ if ( Gia_ObjIsCo(pObj) )
+ Gia_ObjTerSimCo( pObj );
+ else if ( Gia_ObjIsAnd(pObj) )
+ Gia_ObjTerSimAnd( pObj );
+ else if ( f == 0 )
+ Gia_ObjTerSimSet0( pObj );
+ else
+ Gia_ObjTerSimRo( p, pObj );
+ }
+ }
+ Gia_ManForEachObjVec( vMap, p, pObj, i )
+ pObj->Value = 0;
+ pObj = Gia_ManPo( p, 0 );
+ if ( !Gia_ObjTerSimGet1(pObj) )
+ Abc_Print( 1, "\nRefinement verification has failed!!!\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the refinement for a given counter-example.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Rf2_ManGatherFanins_rec( Rf2_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vFanins, int Depth, int RootId, int fFirst )
+{
+ if ( Gia_ObjIsTravIdCurrent(p->pGia, pObj) )
+ return;
+ Gia_ObjSetTravIdCurrent(p->pGia, pObj);
+ if ( pObj->fPhase && !fFirst )
+ {
+ Vec_Int_t * vVec = Rf2_ObjVec( p, pObj );
+// if ( Vec_IntEntry( vVec, 0 ) == 0 )
+// return;
+ if ( Vec_IntSize(vVec) == 0 )
+ Vec_IntPush( vFanins, Gia_ObjId(p->pGia, pObj) );
+ Vec_IntPushUnique( vVec, RootId );
+ if ( Depth == 0 )
+ return;
+ }
+ if ( Gia_ObjIsPi(p->pGia, pObj) || Gia_ObjIsConst0(pObj) )
+ return;
+ if ( Gia_ObjIsRo(p->pGia, pObj) )
+ {
+ assert( pObj->fPhase );
+ pObj = Gia_ObjRoToRi(p->pGia, pObj);
+ Rf2_ManGatherFanins_rec( p, Gia_ObjFanin0(pObj), vFanins, Depth - 1, RootId, 0 );
+ }
+ else if ( Gia_ObjIsAnd(pObj) )
+ {
+ Rf2_ManGatherFanins_rec( p, Gia_ObjFanin0(pObj), vFanins, Depth - pObj->fPhase, RootId, 0 );
+ Rf2_ManGatherFanins_rec( p, Gia_ObjFanin1(pObj), vFanins, Depth - pObj->fPhase, RootId, 0 );
+ }
+ else assert( 0 );
+}
+void Rf2_ManGatherFanins( Rf2_Man_t * p, int Depth )
+{
+ Vec_Int_t * vUsed;
+ Vec_Int_t * vVec;
+ Gia_Obj_t * pObj;
+ int i, k, Entry;
+ // mark PPIs
+ Gia_ManForEachObjVec( p->vMap, p->pGia, pObj, i )
+ {
+ vVec = Rf2_ObjVec( p, pObj );
+ assert( Vec_IntSize(vVec) == 0 );
+ Vec_IntPush( vVec, 0 );
+ }
+ // collect internal
+ Vec_IntClear( p->vFanins );
+ Gia_ManForEachObjVec( p->vMap, p->pGia, pObj, i )
+ {
+ if ( Gia_ObjIsPi(p->pGia, pObj) )
+ continue;
+ Gia_ManIncrementTravId( p->pGia );
+ Rf2_ManGatherFanins_rec( p, pObj, p->vFanins, Depth, i, 1 );
+ }
+
+ vUsed = Vec_IntStart( Vec_IntSize(p->vMap) );
+
+ // evaluate collected
+ printf( "\nMap (%d): ", Vec_IntSize(p->vMap) );
+ Gia_ManForEachObjVec( p->vMap, p->pGia, pObj, i )
+ {
+ vVec = Rf2_ObjVec( p, pObj );
+ if ( Vec_IntSize(vVec) > 1 )
+ printf( "%d=%d ", i, Vec_IntSize(vVec) - 1 );
+ Vec_IntForEachEntryStart( vVec, Entry, k, 1 )
+ Vec_IntAddToEntry( vUsed, Entry, 1 );
+ Vec_IntClear( vVec );
+ }
+ printf( "\n" );
+ // evaluate internal
+ printf( "Int (%d): ", Vec_IntSize(p->vFanins) );
+ Gia_ManForEachObjVec( p->vFanins, p->pGia, pObj, i )
+ {
+ vVec = Rf2_ObjVec( p, pObj );
+ if ( Vec_IntSize(vVec) > 1 )
+ printf( "%d=%d ", i, Vec_IntSize(vVec) );
+ if ( Vec_IntSize(vVec) > 1 )
+ Vec_IntForEachEntry( vVec, Entry, k )
+ Vec_IntAddToEntry( vUsed, Entry, 1 );
+ Vec_IntClear( vVec );
+ }
+ printf( "\n" );
+ // evaluate PPIs
+ Vec_IntForEachEntry( vUsed, Entry, k )
+ printf( "%d ", Entry );
+ printf( "\n" );
+
+ Vec_IntFree( vUsed );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Sort, make dup- and containment-free, and filter.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Rf2_ManCountPpis( Rf2_Man_t * p )
+{
+ Gia_Obj_t * pObj;
+ int i, Counter = 0;
+ Gia_ManForEachObjVec( p->vMap, p->pGia, pObj, i )
+ if ( !Gia_ObjIsPi(p->pGia, pObj) ) // this is PPI
+ Counter++;
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sort, make dup- and containment-free, and filter.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Rf2_ManPrintVector( Vec_Int_t * p, int Num )
+{
+ int i, k, Entry;
+ Vec_IntForEachEntry( p, Entry, i )
+ {
+ for ( k = 0; k < Num; k++ )
+ printf( "%c", '0' + ((Entry>>k) & 1) );
+ printf( "\n" );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sort, make dup- and containment-free, and filter.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Rf2_ManProcessVector( Vec_Int_t * p, int Limit )
+{
+// int Start = Vec_IntSize(p);
+ int Start = 0;
+ int i, j, k, Entry, Entry2;
+// printf( "%d", Vec_IntSize(p) );
+ if ( Start > 5 )
+ {
+ printf( "Before: \n" );
+ Rf2_ManPrintVector( p, 31 );
+ }
+
+ k = 0;
+ Vec_IntForEachEntry( p, Entry, i )
+ if ( Gia_WordCountOnes((unsigned)Entry) <= Limit )
+ Vec_IntWriteEntry( p, k++, Entry );
+ Vec_IntShrink( p, k );
+ Vec_IntSort( p, 0 );
+ k = 0;
+ Vec_IntForEachEntry( p, Entry, i )
+ {
+ Vec_IntForEachEntryStop( p, Entry2, j, i )
+ if ( (Entry2 & Entry) == Entry2 ) // Entry2 is a subset of Entry
+ break;
+ if ( j == i ) // Entry is not contained in any Entry2
+ Vec_IntWriteEntry( p, k++, Entry );
+ }
+ Vec_IntShrink( p, k );
+// printf( "->%d ", Vec_IntSize(p) );
+ if ( Start > 5 )
+ {
+ printf( "After: \n" );
+ Rf2_ManPrintVector( p, 31 );
+ k = 0;
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Assigns a unique justifification ID for each PPI.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Rf2_ManAssignJustIds( Rf2_Man_t * p )
+{
+ Gia_Obj_t * pObj;
+ int nPpis = Rf2_ManCountPpis( p );
+ int nGroupSize = (nPpis / 30) + (nPpis % 30 > 0);
+ int i, k = 0;
+ Vec_VecClear( p->vGrp2Ppi );
+ Gia_ManForEachObjVec( p->vMap, p->pGia, pObj, i )
+ if ( !Gia_ObjIsPi(p->pGia, pObj) ) // this is PPI
+ Vec_VecPushInt( p->vGrp2Ppi, (k++ / nGroupSize), i );
+ printf( "Considering %d PPIs combined into %d groups of size %d.\n", k, (k-1)/nGroupSize+1, nGroupSize );
+ return (k-1)/nGroupSize+1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Sort, make dup- and containment-free, and filter.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Rf2_ManPrintVectorSpecial( Rf2_Man_t * p, Vec_Int_t * vVec )
+{
+ Gia_Obj_t * pObj;
+ int nPpis = Rf2_ManCountPpis( p );
+ int nGroupSize = (nPpis / 30) + (nPpis % 30 > 0);
+ int s, i, k, Entry, Counter;
+
+ Vec_IntForEachEntry( vVec, Entry, s )
+ {
+ k = 0;
+ Counter = 0;
+ Gia_ManForEachObjVec( p->vMap, p->pGia, pObj, i )
+ {
+ if ( !Gia_ObjIsPi(p->pGia, pObj) ) // this is PPI
+ {
+ if ( (Entry >> (k++ / nGroupSize)) & 1 )
+ printf( "1" ), Counter++;
+ else
+ printf( "0" );
+ }
+ else
+ printf( "-" );
+ }
+ printf( " %3d \n", Counter );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs justification propagation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Rf2_ManPropagate( Rf2_Man_t * p, int Limit )
+{
+ Vec_Int_t * vVec, * vVec0, * vVec1;
+ Gia_Obj_t * pObj;
+ int f, i, k, j, Entry, Entry2, iBit = p->pCex->nRegs;
+ // init constant
+ pObj = Gia_ManConst0(p->pGia);
+ pObj->fMark0 = 0;
+ Vec_IntFill( Rf2_ObjVec(p, pObj), 1, 0 );
+ // iterate through the timeframes
+ for ( f = 0; f <= p->pCex->iFrame; f++, iBit += p->pCex->nPis )
+ {
+ // initialize frontier values and init justification sets
+ Gia_ManForEachObjVec( p->vMap, p->pGia, pObj, i )
+ {
+ assert( Gia_ObjIsCi(pObj) || Gia_ObjIsAnd(pObj) );
+ pObj->fMark0 = Abc_InfoHasBit( p->pCex->pData, iBit + i );
+ Vec_IntFill( Rf2_ObjVec(p, pObj), 1, 0 );
+ }
+ // assign justification sets for PPis
+ Vec_VecForEachLevelInt( p->vGrp2Ppi, vVec, i )
+ Vec_IntForEachEntry( vVec, Entry, k )
+ {
+ assert( i < 31 );
+ pObj = Gia_ManObj( p->pGia, Vec_IntEntry(p->vMap, Entry) );
+ assert( Vec_IntSize(Rf2_ObjVec(p, pObj)) == 1 );
+ Vec_IntAddToEntry( Rf2_ObjVec(p, pObj), 0, (1 << i) );
+ }
+ // propagate internal nodes
+ Gia_ManForEachObjVec( p->vObjs, p->pGia, pObj, i )
+ {
+ pObj->fMark0 = 0;
+ vVec = Rf2_ObjVec(p, pObj);
+ Vec_IntClear( vVec );
+ if ( Gia_ObjIsRo(p->pGia, pObj) )
+ {
+ if ( f == 0 )
+ {
+ Vec_IntPush( vVec, 0 );
+ continue;
+ }
+ pObj->fMark0 = Gia_ObjRoToRi(p->pGia, pObj)->fMark0;
+ vVec0 = Rf2_ObjVec( p, Gia_ObjRoToRi(p->pGia, pObj) );
+ Vec_IntAppend( vVec, vVec0 );
+ continue;
+ }
+ if ( Gia_ObjIsCo(pObj) )
+ {
+ pObj->fMark0 = (Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj));
+ vVec0 = Rf2_ObjVec( p, Gia_ObjFanin0(pObj) );
+ Vec_IntAppend( vVec, vVec0 );
+ continue;
+ }
+ assert( Gia_ObjIsAnd(pObj) );
+ vVec0 = Rf2_ObjVec(p, Gia_ObjFanin0(pObj));
+ vVec1 = Rf2_ObjVec(p, Gia_ObjFanin1(pObj));
+ pObj->fMark0 = (Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj)) & (Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj));
+ if ( pObj->fMark0 == 1 )
+ {
+ Vec_IntForEachEntry( vVec0, Entry, k )
+ Vec_IntForEachEntry( vVec1, Entry2, j )
+ Vec_IntPush( vVec, Entry | Entry2 );
+ Rf2_ManProcessVector( vVec, Limit );
+ }
+ else if ( (Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj)) == 0 && (Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj)) == 0 )
+ {
+ Vec_IntAppend( vVec, vVec0 );
+ Vec_IntAppend( vVec, vVec1 );
+ Rf2_ManProcessVector( vVec, Limit );
+ }
+ else if ( (Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj)) == 0 )
+ Vec_IntAppend( vVec, vVec0 );
+ else
+ Vec_IntAppend( vVec, vVec1 );
+ }
+ }
+ assert( iBit == p->pCex->nBits );
+ if ( Gia_ManPo(p->pGia, 0)->fMark0 != 1 )
+ printf( "Output value is incorrect.\n" );
+ return Rf2_ObjVec(p, Gia_ManPo(p->pGia, 0));
+}
+
+/**Function*************************************************************
+
+ Synopsis [Performs justification propagation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Rf2_ManBounds( Rf2_Man_t * p )
+{
+ Gia_Obj_t * pObj;
+ int f, i, iBit = p->pCex->nRegs;
+ // init constant
+ pObj = Gia_ManConst0(p->pGia);
+ pObj->fMark0 = 0;
+ Rf2_ObjStart( p, pObj, Vec_IntSize(p->vMap) + Vec_IntSize(p->vObjs) );
+ // iterate through the timeframes
+ for ( f = 0; f <= p->pCex->iFrame; f++, iBit += p->pCex->nPis )
+ {
+ // initialize frontier values and init justification sets
+ Gia_ManForEachObjVec( p->vMap, p->pGia, pObj, i )
+ {
+ assert( Gia_ObjIsCi(pObj) || Gia_ObjIsAnd(pObj) );
+ pObj->fMark0 = Abc_InfoHasBit( p->pCex->pData, iBit + i );
+ Rf2_ObjStart( p, pObj, i );
+ }
+ // propagate internal nodes
+ Gia_ManForEachObjVec( p->vObjs, p->pGia, pObj, i )
+ {
+ pObj->fMark0 = 0;
+ Rf2_ObjClear( p, pObj );
+ if ( Gia_ObjIsRo(p->pGia, pObj) )
+ {
+ if ( f == 0 )
+ {
+ Rf2_ObjStart( p, pObj, Vec_IntSize(p->vMap) + i );
+ continue;
+ }
+ pObj->fMark0 = Gia_ObjRoToRi(p->pGia, pObj)->fMark0;
+ Rf2_ObjCopy( p, pObj, Gia_ObjRoToRi(p->pGia, pObj) );
+ continue;
+ }
+ if ( Gia_ObjIsCo(pObj) )
+ {
+ pObj->fMark0 = (Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj));
+ Rf2_ObjCopy( p, pObj, Gia_ObjFanin0(pObj) );
+ continue;
+ }
+ assert( Gia_ObjIsAnd(pObj) );
+ pObj->fMark0 = (Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj)) & (Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj));
+ if ( pObj->fMark0 == 1 )
+ Rf2_ObjDeriveAnd( p, pObj, 1 );
+ else if ( (Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj)) == 0 && (Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj)) == 0 )
+ Rf2_ObjDeriveAnd( p, pObj, 0 );
+ else if ( (Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj)) == 0 )
+ Rf2_ObjCopy( p, pObj, Gia_ObjFanin0(pObj) );
+ else
+ Rf2_ObjCopy( p, pObj, Gia_ObjFanin1(pObj) );
+ }
+ }
+ assert( iBit == p->pCex->nBits );
+ if ( Gia_ManPo(p->pGia, 0)->fMark0 != 1 )
+ printf( "Output value is incorrect.\n" );
+
+ printf( "Bounds: \n" );
+ Rf2_ObjPrint( p, Gia_ManPo(p->pGia, 0) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Computes the refinement for a given counter-example.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Rf2_ManRefine( Rf2_Man_t * p, Abc_Cex_t * pCex, Vec_Int_t * vMap, int fPropFanout, int fVerbose )
+{
+ Vec_Int_t * vJusts;
+// Vec_Int_t * vSelected = Vec_IntAlloc( 100 );
+ Vec_Int_t * vSelected = NULL;
+ clock_t clk, clk2 = clock();
+ int nGroups;
+ p->nCalls++;
+ // initialize
+ p->pCex = pCex;
+ p->vMap = vMap;
+ p->fPropFanout = fPropFanout;
+ p->fVerbose = fVerbose;
+ // collects used objects
+ Rf2_ManCollect( p );
+ // collect reconvergence points
+// Rf2_ManGatherFanins( p, 2 );
+ // propagate justification IDs
+ nGroups = Rf2_ManAssignJustIds( p );
+ vJusts = Rf2_ManPropagate( p, 32 );
+
+// printf( "\n" );
+// Rf2_ManPrintVector( vJusts, nGroups );
+ Rf2_ManPrintVectorSpecial( p, vJusts );
+ if ( Vec_IntSize(vJusts) == 0 )
+ {
+ printf( "Empty set of justifying subsets.\n" );
+ return NULL;
+ }
+
+// p->nMapWords = Abc_BitWordNum( Vec_IntSize(p->vMap) + Vec_IntSize(p->vObjs) + 1 ); // Map + Flops + Const
+// Rf2_ManBounds( p );
+
+ // select the result
+// Abc_PrintTime( 1, "Time", clock() - clk2 );
+
+ // verify (empty) refinement
+ clk = clock();
+// Rf2_ManVerifyUsingTerSim( p->pGia, p->pCex, p->vMap, p->vObjs, vSelected );
+// Vec_IntUniqify( vSelected );
+// Vec_IntReverseOrder( vSelected );
+ p->timeVer += clock() - clk;
+ p->timeTotal += clock() - clk2;
+// p->nRefines += Vec_IntSize(vSelected);
+ return vSelected;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+