| /**CFile**************************************************************** |
| |
| FileName [ivyFraig.c] |
| |
| SystemName [ABC: Logic synthesis and verification system.] |
| |
| PackageName [And-Inverter Graph package.] |
| |
| Synopsis [Functional reduction of AIGs] |
| |
| Author [Alan Mishchenko] |
| |
| Affiliation [UC Berkeley] |
| |
| Date [Ver. 1.0. Started - May 11, 2006.] |
| |
| Revision [$Id: ivyFraig.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] |
| |
| ***********************************************************************/ |
| |
| #include <math.h> |
| |
| #include "sat/bsat/satSolver.h" |
| #include "misc/extra/extra.h" |
| #include "ivy.h" |
| |
| ABC_NAMESPACE_IMPL_START |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// DECLARATIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| typedef struct Ivy_FraigMan_t_ Ivy_FraigMan_t; |
| typedef struct Ivy_FraigSim_t_ Ivy_FraigSim_t; |
| typedef struct Ivy_FraigList_t_ Ivy_FraigList_t; |
| |
| struct Ivy_FraigList_t_ |
| { |
| Ivy_Obj_t * pHead; |
| Ivy_Obj_t * pTail; |
| int nItems; |
| }; |
| |
| struct Ivy_FraigSim_t_ |
| { |
| int Type; |
| Ivy_FraigSim_t * pNext; |
| Ivy_FraigSim_t * pFanin0; |
| Ivy_FraigSim_t * pFanin1; |
| unsigned pData[0]; |
| }; |
| |
| struct Ivy_FraigMan_t_ |
| { |
| // general info |
| Ivy_FraigParams_t * pParams; // various parameters |
| // temporary backtrack limits because "ABC_INT64_T" cannot be defined in Ivy_FraigParams_t ... |
| ABC_INT64_T nBTLimitGlobal; // global limit on the number of backtracks |
| ABC_INT64_T nInsLimitGlobal;// global limit on the number of clause inspects |
| // AIG manager |
| Ivy_Man_t * pManAig; // the starting AIG manager |
| Ivy_Man_t * pManFraig; // the final AIG manager |
| // simulation information |
| int nSimWords; // the number of words |
| char * pSimWords; // the simulation info |
| Ivy_FraigSim_t * pSimStart; // the list of simulation info for internal nodes |
| // counter example storage |
| int nPatWords; // the number of words in the counter example |
| unsigned * pPatWords; // the counter example |
| int * pPatScores; // the scores of each pattern |
| // equivalence classes |
| Ivy_FraigList_t lClasses; // equivalence classes |
| Ivy_FraigList_t lCand; // candidatates |
| int nPairs; // the number of pairs of nodes |
| // equivalence checking |
| sat_solver * pSat; // SAT solver |
| int nSatVars; // the number of variables currently used |
| Vec_Ptr_t * vPiVars; // the PIs of the cone used |
| // other |
| ProgressBar * pProgress; |
| // statistics |
| int nSimRounds; |
| int nNodesMiter; |
| int nClassesZero; |
| int nClassesBeg; |
| int nClassesEnd; |
| int nPairsBeg; |
| int nPairsEnd; |
| int nSatCalls; |
| int nSatCallsSat; |
| int nSatCallsUnsat; |
| int nSatProof; |
| int nSatFails; |
| int nSatFailsReal; |
| // runtime |
| abctime timeSim; |
| abctime timeTrav; |
| abctime timeSat; |
| abctime timeSatUnsat; |
| abctime timeSatSat; |
| abctime timeSatFail; |
| abctime timeRef; |
| abctime timeTotal; |
| abctime time1; |
| abctime time2; |
| }; |
| |
| typedef struct Prove_ParamsStruct_t_ Prove_Params_t; |
| struct Prove_ParamsStruct_t_ |
| { |
| // general parameters |
| int fUseFraiging; // enables fraiging |
| int fUseRewriting; // enables rewriting |
| int fUseBdds; // enables BDD construction when other methods fail |
| int fVerbose; // prints verbose stats |
| // iterations |
| int nItersMax; // the number of iterations |
| // mitering |
| int nMiteringLimitStart; // starting mitering limit |
| float nMiteringLimitMulti; // multiplicative coefficient to increase the limit in each iteration |
| // rewriting |
| int nRewritingLimitStart; // the number of rewriting iterations |
| float nRewritingLimitMulti; // multiplicative coefficient to increase the limit in each iteration |
| // fraiging |
| int nFraigingLimitStart; // starting backtrack(conflict) limit |
| float nFraigingLimitMulti; // multiplicative coefficient to increase the limit in each iteration |
| // last-gasp BDD construction |
| int nBddSizeLimit; // the number of BDD nodes when construction is aborted |
| int fBddReorder; // enables dynamic BDD variable reordering |
| // last-gasp mitering |
| int nMiteringLimitLast; // final mitering limit |
| // global SAT solver limits |
| ABC_INT64_T nTotalBacktrackLimit; // global limit on the number of backtracks |
| ABC_INT64_T nTotalInspectLimit; // global limit on the number of clause inspects |
| // global resources applied |
| ABC_INT64_T nTotalBacktracksMade; // the total number of backtracks made |
| ABC_INT64_T nTotalInspectsMade; // the total number of inspects made |
| }; |
| |
| static inline Ivy_FraigSim_t * Ivy_ObjSim( Ivy_Obj_t * pObj ) { return (Ivy_FraigSim_t *)pObj->pFanout; } |
| static inline Ivy_Obj_t * Ivy_ObjClassNodeLast( Ivy_Obj_t * pObj ) { return pObj->pNextFan0; } |
| static inline Ivy_Obj_t * Ivy_ObjClassNodeRepr( Ivy_Obj_t * pObj ) { return pObj->pNextFan0; } |
| static inline Ivy_Obj_t * Ivy_ObjClassNodeNext( Ivy_Obj_t * pObj ) { return pObj->pNextFan1; } |
| static inline Ivy_Obj_t * Ivy_ObjNodeHashNext( Ivy_Obj_t * pObj ) { return pObj->pPrevFan0; } |
| static inline Ivy_Obj_t * Ivy_ObjEquivListNext( Ivy_Obj_t * pObj ) { return pObj->pPrevFan0; } |
| static inline Ivy_Obj_t * Ivy_ObjEquivListPrev( Ivy_Obj_t * pObj ) { return pObj->pPrevFan1; } |
| static inline Ivy_Obj_t * Ivy_ObjFraig( Ivy_Obj_t * pObj ) { return pObj->pEquiv; } |
| static inline int Ivy_ObjSatNum( Ivy_Obj_t * pObj ) { return (int)(ABC_PTRUINT_T)pObj->pNextFan0; } |
| static inline Vec_Ptr_t * Ivy_ObjFaninVec( Ivy_Obj_t * pObj ) { return (Vec_Ptr_t *)pObj->pNextFan1; } |
| |
| static inline void Ivy_ObjSetSim( Ivy_Obj_t * pObj, Ivy_FraigSim_t * pSim ) { pObj->pFanout = (Ivy_Obj_t *)pSim; } |
| static inline void Ivy_ObjSetClassNodeLast( Ivy_Obj_t * pObj, Ivy_Obj_t * pLast ) { pObj->pNextFan0 = pLast; } |
| static inline void Ivy_ObjSetClassNodeRepr( Ivy_Obj_t * pObj, Ivy_Obj_t * pRepr ) { pObj->pNextFan0 = pRepr; } |
| static inline void Ivy_ObjSetClassNodeNext( Ivy_Obj_t * pObj, Ivy_Obj_t * pNext ) { pObj->pNextFan1 = pNext; } |
| static inline void Ivy_ObjSetNodeHashNext( Ivy_Obj_t * pObj, Ivy_Obj_t * pNext ) { pObj->pPrevFan0 = pNext; } |
| static inline void Ivy_ObjSetEquivListNext( Ivy_Obj_t * pObj, Ivy_Obj_t * pNext ) { pObj->pPrevFan0 = pNext; } |
| static inline void Ivy_ObjSetEquivListPrev( Ivy_Obj_t * pObj, Ivy_Obj_t * pPrev ) { pObj->pPrevFan1 = pPrev; } |
| static inline void Ivy_ObjSetFraig( Ivy_Obj_t * pObj, Ivy_Obj_t * pNode ) { pObj->pEquiv = pNode; } |
| static inline void Ivy_ObjSetSatNum( Ivy_Obj_t * pObj, int Num ) { pObj->pNextFan0 = (Ivy_Obj_t *)(ABC_PTRUINT_T)Num; } |
| static inline void Ivy_ObjSetFaninVec( Ivy_Obj_t * pObj, Vec_Ptr_t * vFanins ) { pObj->pNextFan1 = (Ivy_Obj_t *)vFanins; } |
| |
| static inline unsigned Ivy_ObjRandomSim() { return (rand() << 24) ^ (rand() << 12) ^ rand(); } |
| |
| // iterate through equivalence classes |
| #define Ivy_FraigForEachEquivClass( pList, pEnt ) \ |
| for ( pEnt = pList; \ |
| pEnt; \ |
| pEnt = Ivy_ObjEquivListNext(pEnt) ) |
| #define Ivy_FraigForEachEquivClassSafe( pList, pEnt, pEnt2 ) \ |
| for ( pEnt = pList, \ |
| pEnt2 = pEnt? Ivy_ObjEquivListNext(pEnt): NULL; \ |
| pEnt; \ |
| pEnt = pEnt2, \ |
| pEnt2 = pEnt? Ivy_ObjEquivListNext(pEnt): NULL ) |
| // iterate through nodes in one class |
| #define Ivy_FraigForEachClassNode( pClass, pEnt ) \ |
| for ( pEnt = pClass; \ |
| pEnt; \ |
| pEnt = Ivy_ObjClassNodeNext(pEnt) ) |
| // iterate through nodes in the hash table |
| #define Ivy_FraigForEachBinNode( pBin, pEnt ) \ |
| for ( pEnt = pBin; \ |
| pEnt; \ |
| pEnt = Ivy_ObjNodeHashNext(pEnt) ) |
| |
| static Ivy_FraigMan_t * Ivy_FraigStart( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams ); |
| static Ivy_FraigMan_t * Ivy_FraigStartSimple( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams ); |
| static Ivy_Man_t * Ivy_FraigPerform_int( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams, ABC_INT64_T nBTLimitGlobal, ABC_INT64_T nInsLimitGlobal, ABC_INT64_T * pnSatConfs, ABC_INT64_T * pnSatInspects ); |
| static void Ivy_FraigPrint( Ivy_FraigMan_t * p ); |
| static void Ivy_FraigStop( Ivy_FraigMan_t * p ); |
| static void Ivy_FraigSimulate( Ivy_FraigMan_t * p ); |
| static void Ivy_FraigSweep( Ivy_FraigMan_t * p ); |
| static Ivy_Obj_t * Ivy_FraigAnd( Ivy_FraigMan_t * p, Ivy_Obj_t * pObjOld ); |
| static int Ivy_FraigNodesAreEquiv( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj0, Ivy_Obj_t * pObj1 ); |
| static int Ivy_FraigNodeIsConst( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj ); |
| static void Ivy_FraigNodeAddToSolver( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj0, Ivy_Obj_t * pObj1 ); |
| static int Ivy_FraigSetActivityFactors( Ivy_FraigMan_t * p, Ivy_Obj_t * pOld, Ivy_Obj_t * pNew ); |
| static void Ivy_FraigAddToPatScores( Ivy_FraigMan_t * p, Ivy_Obj_t * pClass, Ivy_Obj_t * pClassNew ); |
| static int Ivy_FraigMiterStatus( Ivy_Man_t * pMan ); |
| static void Ivy_FraigMiterProve( Ivy_FraigMan_t * p ); |
| static void Ivy_FraigMiterPrint( Ivy_Man_t * pNtk, char * pString, abctime clk, int fVerbose ); |
| static int * Ivy_FraigCreateModel( Ivy_FraigMan_t * p ); |
| |
| static int Ivy_FraigNodesAreEquivBdd( Ivy_Obj_t * pObj1, Ivy_Obj_t * pObj2 ); |
| static int Ivy_FraigCheckCone( Ivy_FraigMan_t * pGlo, Ivy_Man_t * p, Ivy_Obj_t * pObj1, Ivy_Obj_t * pObj2, int nConfLimit ); |
| |
| static ABC_INT64_T s_nBTLimitGlobal = 0; |
| static ABC_INT64_T s_nInsLimitGlobal = 0; |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// FUNCTION DEFINITIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| /**Function************************************************************* |
| |
| Synopsis [Sets the default solving parameters.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Ivy_FraigParamsDefault( Ivy_FraigParams_t * pParams ) |
| { |
| memset( pParams, 0, sizeof(Ivy_FraigParams_t) ); |
| pParams->nSimWords = 32; // the number of words in the simulation info |
| pParams->dSimSatur = 0.005; // the ratio of refined classes when saturation is reached |
| pParams->fPatScores = 0; // enables simulation pattern scoring |
| pParams->MaxScore = 25; // max score after which resimulation is used |
| pParams->fDoSparse = 1; // skips sparse functions |
| // pParams->dActConeRatio = 0.05; // the ratio of cone to be bumped |
| // pParams->dActConeBumpMax = 5.0; // the largest bump of activity |
| pParams->dActConeRatio = 0.3; // the ratio of cone to be bumped |
| pParams->dActConeBumpMax = 10.0; // the largest bump of activity |
| |
| pParams->nBTLimitNode = 100; // conflict limit at a node |
| pParams->nBTLimitMiter = 500000; // conflict limit at an output |
| // pParams->nBTLimitGlobal = 0; // conflict limit global |
| // pParams->nInsLimitGlobal = 0; // inspection limit global |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Performs combinational equivalence checking for the miter.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Ivy_FraigProve( Ivy_Man_t ** ppManAig, void * pPars ) |
| { |
| Prove_Params_t * pParams = (Prove_Params_t *)pPars; |
| Ivy_FraigParams_t Params, * pIvyParams = &Params; |
| Ivy_Man_t * pManAig, * pManTemp; |
| int RetValue, nIter; |
| abctime clk;//, Counter; |
| ABC_INT64_T nSatConfs = 0, nSatInspects = 0; |
| |
| // start the network and parameters |
| pManAig = *ppManAig; |
| Ivy_FraigParamsDefault( pIvyParams ); |
| pIvyParams->fVerbose = pParams->fVerbose; |
| pIvyParams->fProve = 1; |
| |
| if ( pParams->fVerbose ) |
| { |
| printf( "RESOURCE LIMITS: Iterations = %d. Rewriting = %s. Fraiging = %s.\n", |
| pParams->nItersMax, pParams->fUseRewriting? "yes":"no", pParams->fUseFraiging? "yes":"no" ); |
| printf( "Miter = %d (%3.1f). Rwr = %d (%3.1f). Fraig = %d (%3.1f). Last = %d.\n", |
| pParams->nMiteringLimitStart, pParams->nMiteringLimitMulti, |
| pParams->nRewritingLimitStart, pParams->nRewritingLimitMulti, |
| pParams->nFraigingLimitStart, pParams->nFraigingLimitMulti, pParams->nMiteringLimitLast ); |
| } |
| |
| // if SAT only, solve without iteration |
| if ( !pParams->fUseRewriting && !pParams->fUseFraiging ) |
| { |
| clk = Abc_Clock(); |
| pIvyParams->nBTLimitMiter = pParams->nMiteringLimitLast / Ivy_ManPoNum(pManAig); |
| pManAig = Ivy_FraigMiter( pManTemp = pManAig, pIvyParams ); Ivy_ManStop( pManTemp ); |
| RetValue = Ivy_FraigMiterStatus( pManAig ); |
| Ivy_FraigMiterPrint( pManAig, "SAT solving", clk, pParams->fVerbose ); |
| *ppManAig = pManAig; |
| return RetValue; |
| } |
| |
| if ( Ivy_ManNodeNum(pManAig) < 500 ) |
| { |
| // run the first mitering |
| clk = Abc_Clock(); |
| pIvyParams->nBTLimitMiter = pParams->nMiteringLimitStart / Ivy_ManPoNum(pManAig); |
| pManAig = Ivy_FraigMiter( pManTemp = pManAig, pIvyParams ); Ivy_ManStop( pManTemp ); |
| RetValue = Ivy_FraigMiterStatus( pManAig ); |
| Ivy_FraigMiterPrint( pManAig, "SAT solving", clk, pParams->fVerbose ); |
| if ( RetValue >= 0 ) |
| { |
| *ppManAig = pManAig; |
| return RetValue; |
| } |
| } |
| |
| // check the current resource limits |
| RetValue = -1; |
| for ( nIter = 0; nIter < pParams->nItersMax; nIter++ ) |
| { |
| if ( pParams->fVerbose ) |
| { |
| printf( "ITERATION %2d : Confs = %6d. FraigBTL = %3d. \n", nIter+1, |
| (int)(pParams->nMiteringLimitStart * pow(pParams->nMiteringLimitMulti,nIter)), |
| (int)(pParams->nFraigingLimitStart * pow(pParams->nFraigingLimitMulti,nIter)) ); |
| fflush( stdout ); |
| } |
| |
| // try rewriting |
| if ( pParams->fUseRewriting ) |
| { // bug in Ivy_NodeFindCutsAll() when leaves are identical! |
| /* |
| clk = Abc_Clock(); |
| Counter = (int)(pParams->nRewritingLimitStart * pow(pParams->nRewritingLimitMulti,nIter)); |
| pManAig = Ivy_ManRwsat( pManAig, 0 ); |
| RetValue = Ivy_FraigMiterStatus( pManAig ); |
| Ivy_FraigMiterPrint( pManAig, "Rewriting ", clk, pParams->fVerbose ); |
| */ |
| } |
| if ( RetValue >= 0 ) |
| break; |
| |
| // catch the situation when ref pattern detects the bug |
| RetValue = Ivy_FraigMiterStatus( pManAig ); |
| if ( RetValue >= 0 ) |
| break; |
| |
| // try fraiging followed by mitering |
| if ( pParams->fUseFraiging ) |
| { |
| clk = Abc_Clock(); |
| pIvyParams->nBTLimitNode = (int)(pParams->nFraigingLimitStart * pow(pParams->nFraigingLimitMulti,nIter)); |
| pIvyParams->nBTLimitMiter = 1 + (int)(pParams->nMiteringLimitStart * pow(pParams->nMiteringLimitMulti,nIter)) / Ivy_ManPoNum(pManAig); |
| pManAig = Ivy_FraigPerform_int( pManTemp = pManAig, pIvyParams, pParams->nTotalBacktrackLimit, pParams->nTotalInspectLimit, &nSatConfs, &nSatInspects ); Ivy_ManStop( pManTemp ); |
| RetValue = Ivy_FraigMiterStatus( pManAig ); |
| Ivy_FraigMiterPrint( pManAig, "Fraiging ", clk, pParams->fVerbose ); |
| } |
| if ( RetValue >= 0 ) |
| break; |
| |
| // add to the number of backtracks and inspects |
| pParams->nTotalBacktracksMade += nSatConfs; |
| pParams->nTotalInspectsMade += nSatInspects; |
| // check if global resource limit is reached |
| if ( (pParams->nTotalBacktrackLimit && pParams->nTotalBacktracksMade >= pParams->nTotalBacktrackLimit) || |
| (pParams->nTotalInspectLimit && pParams->nTotalInspectsMade >= pParams->nTotalInspectLimit) ) |
| { |
| printf( "Reached global limit on conflicts/inspects. Quitting.\n" ); |
| *ppManAig = pManAig; |
| return -1; |
| } |
| } |
| /* |
| if ( RetValue < 0 ) |
| { |
| if ( pParams->fVerbose ) |
| { |
| printf( "Attempting SAT with conflict limit %d ...\n", pParams->nMiteringLimitLast ); |
| fflush( stdout ); |
| } |
| clk = Abc_Clock(); |
| pIvyParams->nBTLimitMiter = pParams->nMiteringLimitLast / Ivy_ManPoNum(pManAig); |
| if ( pParams->nTotalBacktrackLimit ) |
| s_nBTLimitGlobal = pParams->nTotalBacktrackLimit - pParams->nTotalBacktracksMade; |
| if ( pParams->nTotalInspectLimit ) |
| s_nInsLimitGlobal = pParams->nTotalInspectLimit - pParams->nTotalInspectsMade; |
| pManAig = Ivy_FraigMiter( pManTemp = pManAig, pIvyParams ); Ivy_ManStop( pManTemp ); |
| s_nBTLimitGlobal = 0; |
| s_nInsLimitGlobal = 0; |
| RetValue = Ivy_FraigMiterStatus( pManAig ); |
| Ivy_FraigMiterPrint( pManAig, "SAT solving", clk, pParams->fVerbose ); |
| // make sure that the sover never returns "undecided" when infinite resource limits are set |
| if( RetValue == -1 && pParams->nTotalInspectLimit == 0 && |
| pParams->nTotalBacktrackLimit == 0 ) |
| { |
| extern void Prove_ParamsPrint( Prove_Params_t * pParams ); |
| Prove_ParamsPrint( pParams ); |
| printf("ERROR: ABC has returned \"undecided\" in spite of no limits...\n"); |
| exit(1); |
| } |
| } |
| */ |
| // assign the model if it was proved by rewriting (const 1 miter) |
| if ( RetValue == 0 && pManAig->pData == NULL ) |
| { |
| pManAig->pData = ABC_ALLOC( int, Ivy_ManPiNum(pManAig) ); |
| memset( pManAig->pData, 0, sizeof(int) * Ivy_ManPiNum(pManAig) ); |
| } |
| *ppManAig = pManAig; |
| return RetValue; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Performs fraiging of the AIG.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Ivy_Man_t * Ivy_FraigPerform_int( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams, ABC_INT64_T nBTLimitGlobal, ABC_INT64_T nInsLimitGlobal, ABC_INT64_T * pnSatConfs, ABC_INT64_T * pnSatInspects ) |
| { |
| Ivy_FraigMan_t * p; |
| Ivy_Man_t * pManAigNew; |
| abctime clk; |
| if ( Ivy_ManNodeNum(pManAig) == 0 ) |
| return Ivy_ManDup(pManAig); |
| clk = Abc_Clock(); |
| assert( Ivy_ManLatchNum(pManAig) == 0 ); |
| p = Ivy_FraigStart( pManAig, pParams ); |
| // set global limits |
| p->nBTLimitGlobal = nBTLimitGlobal; |
| p->nInsLimitGlobal = nInsLimitGlobal; |
| |
| Ivy_FraigSimulate( p ); |
| Ivy_FraigSweep( p ); |
| pManAigNew = p->pManFraig; |
| p->timeTotal = Abc_Clock() - clk; |
| if ( pnSatConfs ) |
| *pnSatConfs = p->pSat? p->pSat->stats.conflicts : 0; |
| if ( pnSatInspects ) |
| *pnSatInspects = p->pSat? p->pSat->stats.inspects : 0; |
| Ivy_FraigStop( p ); |
| return pManAigNew; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Performs fraiging of the AIG.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Ivy_Man_t * Ivy_FraigPerform( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams ) |
| { |
| Ivy_FraigMan_t * p; |
| Ivy_Man_t * pManAigNew; |
| abctime clk; |
| if ( Ivy_ManNodeNum(pManAig) == 0 ) |
| return Ivy_ManDup(pManAig); |
| clk = Abc_Clock(); |
| assert( Ivy_ManLatchNum(pManAig) == 0 ); |
| p = Ivy_FraigStart( pManAig, pParams ); |
| Ivy_FraigSimulate( p ); |
| Ivy_FraigSweep( p ); |
| pManAigNew = p->pManFraig; |
| p->timeTotal = Abc_Clock() - clk; |
| Ivy_FraigStop( p ); |
| return pManAigNew; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Applies brute-force SAT to the miter.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Ivy_Man_t * Ivy_FraigMiter( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams ) |
| { |
| Ivy_FraigMan_t * p; |
| Ivy_Man_t * pManAigNew; |
| Ivy_Obj_t * pObj; |
| int i; |
| abctime clk; |
| clk = Abc_Clock(); |
| assert( Ivy_ManLatchNum(pManAig) == 0 ); |
| p = Ivy_FraigStartSimple( pManAig, pParams ); |
| // set global limits |
| p->nBTLimitGlobal = s_nBTLimitGlobal; |
| p->nInsLimitGlobal = s_nInsLimitGlobal; |
| // duplicate internal nodes |
| Ivy_ManForEachNode( p->pManAig, pObj, i ) |
| pObj->pEquiv = Ivy_And( p->pManFraig, Ivy_ObjChild0Equiv(pObj), Ivy_ObjChild1Equiv(pObj) ); |
| // try to prove each output of the miter |
| Ivy_FraigMiterProve( p ); |
| // add the POs |
| Ivy_ManForEachPo( p->pManAig, pObj, i ) |
| Ivy_ObjCreatePo( p->pManFraig, Ivy_ObjChild0Equiv(pObj) ); |
| // clean the new manager |
| Ivy_ManForEachObj( p->pManFraig, pObj, i ) |
| { |
| if ( Ivy_ObjFaninVec(pObj) ) |
| Vec_PtrFree( Ivy_ObjFaninVec(pObj) ); |
| pObj->pNextFan0 = pObj->pNextFan1 = NULL; |
| } |
| // remove dangling nodes |
| Ivy_ManCleanup( p->pManFraig ); |
| pManAigNew = p->pManFraig; |
| p->timeTotal = Abc_Clock() - clk; |
| |
| //printf( "Final nodes = %6d. ", Ivy_ManNodeNum(pManAigNew) ); |
| //ABC_PRT( "Time", p->timeTotal ); |
| Ivy_FraigStop( p ); |
| return pManAigNew; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Starts the fraiging manager without simulation info.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Ivy_FraigMan_t * Ivy_FraigStartSimple( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams ) |
| { |
| Ivy_FraigMan_t * p; |
| // allocat the fraiging manager |
| p = ABC_ALLOC( Ivy_FraigMan_t, 1 ); |
| memset( p, 0, sizeof(Ivy_FraigMan_t) ); |
| p->pParams = pParams; |
| p->pManAig = pManAig; |
| p->pManFraig = Ivy_ManStartFrom( pManAig ); |
| p->vPiVars = Vec_PtrAlloc( 100 ); |
| return p; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Starts the fraiging manager.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Ivy_FraigMan_t * Ivy_FraigStart( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams ) |
| { |
| Ivy_FraigMan_t * p; |
| Ivy_FraigSim_t * pSims; |
| Ivy_Obj_t * pObj; |
| int i, k, EntrySize; |
| // clean the fanout representation |
| Ivy_ManForEachObj( pManAig, pObj, i ) |
| // pObj->pEquiv = pObj->pFanout = pObj->pNextFan0 = pObj->pNextFan1 = pObj->pPrevFan0 = pObj->pPrevFan1 = NULL; |
| assert( !pObj->pEquiv && !pObj->pFanout ); |
| // allocat the fraiging manager |
| p = ABC_ALLOC( Ivy_FraigMan_t, 1 ); |
| memset( p, 0, sizeof(Ivy_FraigMan_t) ); |
| p->pParams = pParams; |
| p->pManAig = pManAig; |
| p->pManFraig = Ivy_ManStartFrom( pManAig ); |
| // allocate simulation info |
| p->nSimWords = pParams->nSimWords; |
| // p->pSimWords = ABC_ALLOC( unsigned, Ivy_ManObjNum(pManAig) * p->nSimWords ); |
| EntrySize = sizeof(Ivy_FraigSim_t) + sizeof(unsigned) * p->nSimWords; |
| p->pSimWords = (char *)ABC_ALLOC( char, Ivy_ManObjNum(pManAig) * EntrySize ); |
| memset( p->pSimWords, 0, EntrySize ); |
| k = 0; |
| Ivy_ManForEachObj( pManAig, pObj, i ) |
| { |
| pSims = (Ivy_FraigSim_t *)(p->pSimWords + EntrySize * k++); |
| pSims->pNext = NULL; |
| if ( Ivy_ObjIsNode(pObj) ) |
| { |
| if ( p->pSimStart == NULL ) |
| p->pSimStart = pSims; |
| else |
| ((Ivy_FraigSim_t *)(p->pSimWords + EntrySize * (k-2)))->pNext = pSims; |
| pSims->pFanin0 = Ivy_ObjSim( Ivy_ObjFanin0(pObj) ); |
| pSims->pFanin1 = Ivy_ObjSim( Ivy_ObjFanin1(pObj) ); |
| pSims->Type = (Ivy_ObjFaninPhase(Ivy_ObjChild0(pObj)) << 2) | (Ivy_ObjFaninPhase(Ivy_ObjChild1(pObj)) << 1) | pObj->fPhase; |
| } |
| else |
| { |
| pSims->pFanin0 = NULL; |
| pSims->pFanin1 = NULL; |
| pSims->Type = 0; |
| } |
| Ivy_ObjSetSim( pObj, pSims ); |
| } |
| assert( k == Ivy_ManObjNum(pManAig) ); |
| // allocate storage for sim pattern |
| p->nPatWords = Ivy_BitWordNum( Ivy_ManPiNum(pManAig) ); |
| p->pPatWords = ABC_ALLOC( unsigned, p->nPatWords ); |
| p->pPatScores = ABC_ALLOC( int, 32 * p->nSimWords ); |
| p->vPiVars = Vec_PtrAlloc( 100 ); |
| // set random number generator |
| srand( 0xABCABC ); |
| return p; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Stops the fraiging manager.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Ivy_FraigStop( Ivy_FraigMan_t * p ) |
| { |
| if ( p->pParams->fVerbose ) |
| Ivy_FraigPrint( p ); |
| if ( p->vPiVars ) Vec_PtrFree( p->vPiVars ); |
| if ( p->pSat ) sat_solver_delete( p->pSat ); |
| ABC_FREE( p->pPatScores ); |
| ABC_FREE( p->pPatWords ); |
| ABC_FREE( p->pSimWords ); |
| ABC_FREE( p ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Prints stats for the fraiging manager.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Ivy_FraigPrint( Ivy_FraigMan_t * p ) |
| { |
| double nMemory; |
| nMemory = (double)Ivy_ManObjNum(p->pManAig)*p->nSimWords*sizeof(unsigned)/(1<<20); |
| printf( "SimWords = %d. Rounds = %d. Mem = %0.2f MB. ", p->nSimWords, p->nSimRounds, nMemory ); |
| printf( "Classes: Beg = %d. End = %d.\n", p->nClassesBeg, p->nClassesEnd ); |
| // printf( "Limits: BTNode = %d. BTMiter = %d.\n", p->pParams->nBTLimitNode, p->pParams->nBTLimitMiter ); |
| printf( "Proof = %d. Counter-example = %d. Fail = %d. FailReal = %d. Zero = %d.\n", |
| p->nSatProof, p->nSatCallsSat, p->nSatFails, p->nSatFailsReal, p->nClassesZero ); |
| printf( "Final = %d. Miter = %d. Total = %d. Mux = %d. (Exor = %d.) SatVars = %d.\n", |
| Ivy_ManNodeNum(p->pManFraig), p->nNodesMiter, Ivy_ManNodeNum(p->pManAig), 0, 0, p->nSatVars ); |
| if ( p->pSat ) Sat_SolverPrintStats( stdout, p->pSat ); |
| ABC_PRT( "AIG simulation ", p->timeSim ); |
| ABC_PRT( "AIG traversal ", p->timeTrav ); |
| ABC_PRT( "SAT solving ", p->timeSat ); |
| ABC_PRT( " Unsat ", p->timeSatUnsat ); |
| ABC_PRT( " Sat ", p->timeSatSat ); |
| ABC_PRT( " Fail ", p->timeSatFail ); |
| ABC_PRT( "Class refining ", p->timeRef ); |
| ABC_PRT( "TOTAL RUNTIME ", p->timeTotal ); |
| if ( p->time1 ) { ABC_PRT( "time1 ", p->time1 ); } |
| } |
| |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [Assigns random patterns to the PI node.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Ivy_NodeAssignRandom( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj ) |
| { |
| Ivy_FraigSim_t * pSims; |
| int i; |
| assert( Ivy_ObjIsPi(pObj) ); |
| pSims = Ivy_ObjSim(pObj); |
| for ( i = 0; i < p->nSimWords; i++ ) |
| pSims->pData[i] = Ivy_ObjRandomSim(); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Assigns constant patterns to the PI node.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Ivy_NodeAssignConst( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj, int fConst1 ) |
| { |
| Ivy_FraigSim_t * pSims; |
| int i; |
| assert( Ivy_ObjIsPi(pObj) ); |
| pSims = Ivy_ObjSim(pObj); |
| for ( i = 0; i < p->nSimWords; i++ ) |
| pSims->pData[i] = fConst1? ~(unsigned)0 : 0; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Assings random simulation info for the PIs.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Ivy_FraigAssignRandom( Ivy_FraigMan_t * p ) |
| { |
| Ivy_Obj_t * pObj; |
| int i; |
| Ivy_ManForEachPi( p->pManAig, pObj, i ) |
| Ivy_NodeAssignRandom( p, pObj ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Assings distance-1 simulation info for the PIs.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Ivy_FraigAssignDist1( Ivy_FraigMan_t * p, unsigned * pPat ) |
| { |
| Ivy_Obj_t * pObj; |
| int i, Limit; |
| Ivy_ManForEachPi( p->pManAig, pObj, i ) |
| { |
| Ivy_NodeAssignConst( p, pObj, Ivy_InfoHasBit(pPat, i) ); |
| // printf( "%d", Ivy_InfoHasBit(pPat, i) ); |
| } |
| // printf( "\n" ); |
| |
| Limit = IVY_MIN( Ivy_ManPiNum(p->pManAig), p->nSimWords * 32 - 1 ); |
| for ( i = 0; i < Limit; i++ ) |
| Ivy_InfoXorBit( Ivy_ObjSim( Ivy_ManPi(p->pManAig,i) )->pData, i+1 ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Returns 1 if simulation info is composed of all zeros.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Ivy_NodeHasZeroSim( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj ) |
| { |
| Ivy_FraigSim_t * pSims; |
| int i; |
| pSims = Ivy_ObjSim(pObj); |
| for ( i = 0; i < p->nSimWords; i++ ) |
| if ( pSims->pData[i] ) |
| return 0; |
| return 1; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Returns 1 if simulation info is composed of all zeros.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Ivy_NodeComplementSim( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj ) |
| { |
| Ivy_FraigSim_t * pSims; |
| int i; |
| pSims = Ivy_ObjSim(pObj); |
| for ( i = 0; i < p->nSimWords; i++ ) |
| pSims->pData[i] = ~pSims->pData[i]; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Returns 1 if simulation infos are equal.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Ivy_NodeCompareSims( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj0, Ivy_Obj_t * pObj1 ) |
| { |
| Ivy_FraigSim_t * pSims0, * pSims1; |
| int i; |
| pSims0 = Ivy_ObjSim(pObj0); |
| pSims1 = Ivy_ObjSim(pObj1); |
| for ( i = 0; i < p->nSimWords; i++ ) |
| if ( pSims0->pData[i] != pSims1->pData[i] ) |
| return 0; |
| return 1; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Simulates one node.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Ivy_NodeSimulateSim( Ivy_FraigMan_t * p, Ivy_FraigSim_t * pSims ) |
| { |
| unsigned * pData, * pData0, * pData1; |
| int i; |
| pData = pSims->pData; |
| pData0 = pSims->pFanin0->pData; |
| pData1 = pSims->pFanin1->pData; |
| switch( pSims->Type ) |
| { |
| case 0: |
| for ( i = 0; i < p->nSimWords; i++ ) |
| pData[i] = (pData0[i] & pData1[i]); |
| break; |
| case 1: |
| for ( i = 0; i < p->nSimWords; i++ ) |
| pData[i] = ~(pData0[i] & pData1[i]); |
| break; |
| case 2: |
| for ( i = 0; i < p->nSimWords; i++ ) |
| pData[i] = (pData0[i] & ~pData1[i]); |
| break; |
| case 3: |
| for ( i = 0; i < p->nSimWords; i++ ) |
| pData[i] = (~pData0[i] | pData1[i]); |
| break; |
| case 4: |
| for ( i = 0; i < p->nSimWords; i++ ) |
| pData[i] = (~pData0[i] & pData1[i]); |
| break; |
| case 5: |
| for ( i = 0; i < p->nSimWords; i++ ) |
| pData[i] = (pData0[i] | ~pData1[i]); |
| break; |
| case 6: |
| for ( i = 0; i < p->nSimWords; i++ ) |
| pData[i] = ~(pData0[i] | pData1[i]); |
| break; |
| case 7: |
| for ( i = 0; i < p->nSimWords; i++ ) |
| pData[i] = (pData0[i] | pData1[i]); |
| break; |
| } |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Simulates one node.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Ivy_NodeSimulate( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj ) |
| { |
| Ivy_FraigSim_t * pSims, * pSims0, * pSims1; |
| int fCompl, fCompl0, fCompl1, i; |
| assert( !Ivy_IsComplement(pObj) ); |
| // get hold of the simulation information |
| pSims = Ivy_ObjSim(pObj); |
| pSims0 = Ivy_ObjSim(Ivy_ObjFanin0(pObj)); |
| pSims1 = Ivy_ObjSim(Ivy_ObjFanin1(pObj)); |
| // get complemented attributes of the children using their random info |
| fCompl = pObj->fPhase; |
| fCompl0 = Ivy_ObjFaninPhase(Ivy_ObjChild0(pObj)); |
| fCompl1 = Ivy_ObjFaninPhase(Ivy_ObjChild1(pObj)); |
| // simulate |
| if ( fCompl0 && fCompl1 ) |
| { |
| if ( fCompl ) |
| for ( i = 0; i < p->nSimWords; i++ ) |
| pSims->pData[i] = (pSims0->pData[i] | pSims1->pData[i]); |
| else |
| for ( i = 0; i < p->nSimWords; i++ ) |
| pSims->pData[i] = ~(pSims0->pData[i] | pSims1->pData[i]); |
| } |
| else if ( fCompl0 && !fCompl1 ) |
| { |
| if ( fCompl ) |
| for ( i = 0; i < p->nSimWords; i++ ) |
| pSims->pData[i] = (pSims0->pData[i] | ~pSims1->pData[i]); |
| else |
| for ( i = 0; i < p->nSimWords; i++ ) |
| pSims->pData[i] = (~pSims0->pData[i] & pSims1->pData[i]); |
| } |
| else if ( !fCompl0 && fCompl1 ) |
| { |
| if ( fCompl ) |
| for ( i = 0; i < p->nSimWords; i++ ) |
| pSims->pData[i] = (~pSims0->pData[i] | pSims1->pData[i]); |
| else |
| for ( i = 0; i < p->nSimWords; i++ ) |
| pSims->pData[i] = (pSims0->pData[i] & ~pSims1->pData[i]); |
| } |
| else // if ( !fCompl0 && !fCompl1 ) |
| { |
| if ( fCompl ) |
| for ( i = 0; i < p->nSimWords; i++ ) |
| pSims->pData[i] = ~(pSims0->pData[i] & pSims1->pData[i]); |
| else |
| for ( i = 0; i < p->nSimWords; i++ ) |
| pSims->pData[i] = (pSims0->pData[i] & pSims1->pData[i]); |
| } |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Computes hash value using simulation info.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| unsigned Ivy_NodeHash( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj ) |
| { |
| static int s_FPrimes[128] = { |
| 1009, 1049, 1093, 1151, 1201, 1249, 1297, 1361, 1427, 1459, |
| 1499, 1559, 1607, 1657, 1709, 1759, 1823, 1877, 1933, 1997, |
| 2039, 2089, 2141, 2213, 2269, 2311, 2371, 2411, 2467, 2543, |
| 2609, 2663, 2699, 2741, 2797, 2851, 2909, 2969, 3037, 3089, |
| 3169, 3221, 3299, 3331, 3389, 3461, 3517, 3557, 3613, 3671, |
| 3719, 3779, 3847, 3907, 3943, 4013, 4073, 4129, 4201, 4243, |
| 4289, 4363, 4441, 4493, 4549, 4621, 4663, 4729, 4793, 4871, |
| 4933, 4973, 5021, 5087, 5153, 5227, 5281, 5351, 5417, 5471, |
| 5519, 5573, 5651, 5693, 5749, 5821, 5861, 5923, 6011, 6073, |
| 6131, 6199, 6257, 6301, 6353, 6397, 6481, 6563, 6619, 6689, |
| 6737, 6803, 6863, 6917, 6977, 7027, 7109, 7187, 7237, 7309, |
| 7393, 7477, 7523, 7561, 7607, 7681, 7727, 7817, 7877, 7933, |
| 8011, 8039, 8059, 8081, 8093, 8111, 8123, 8147 |
| }; |
| Ivy_FraigSim_t * pSims; |
| unsigned uHash; |
| int i; |
| assert( p->nSimWords <= 128 ); |
| uHash = 0; |
| pSims = Ivy_ObjSim(pObj); |
| for ( i = 0; i < p->nSimWords; i++ ) |
| uHash ^= pSims->pData[i] * s_FPrimes[i]; |
| return uHash; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Simulates AIG manager.] |
| |
| Description [Assumes that the PI simulation info is attached.] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Ivy_FraigSimulateOne( Ivy_FraigMan_t * p ) |
| { |
| Ivy_Obj_t * pObj; |
| int i; |
| abctime clk; |
| clk = Abc_Clock(); |
| Ivy_ManForEachNode( p->pManAig, pObj, i ) |
| { |
| Ivy_NodeSimulate( p, pObj ); |
| /* |
| if ( Ivy_ObjFraig(pObj) == NULL ) |
| printf( "%3d --- -- %d : ", pObj->Id, pObj->fPhase ); |
| else |
| printf( "%3d %3d %2d %d : ", pObj->Id, Ivy_Regular(Ivy_ObjFraig(pObj))->Id, Ivy_ObjSatNum(Ivy_Regular(Ivy_ObjFraig(pObj))), pObj->fPhase ); |
| Extra_PrintBinary( stdout, Ivy_ObjSim(pObj), 30 ); |
| printf( "\n" ); |
| */ |
| } |
| p->timeSim += Abc_Clock() - clk; |
| p->nSimRounds++; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Simulates AIG manager.] |
| |
| Description [Assumes that the PI simulation info is attached.] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Ivy_FraigSimulateOneSim( Ivy_FraigMan_t * p ) |
| { |
| Ivy_FraigSim_t * pSims; |
| abctime clk; |
| clk = Abc_Clock(); |
| for ( pSims = p->pSimStart; pSims; pSims = pSims->pNext ) |
| Ivy_NodeSimulateSim( p, pSims ); |
| p->timeSim += Abc_Clock() - clk; |
| p->nSimRounds++; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Adds one node to the equivalence class.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Ivy_NodeAddToClass( Ivy_Obj_t * pClass, Ivy_Obj_t * pObj ) |
| { |
| if ( Ivy_ObjClassNodeNext(pClass) == NULL ) |
| Ivy_ObjSetClassNodeNext( pClass, pObj ); |
| else |
| Ivy_ObjSetClassNodeNext( Ivy_ObjClassNodeLast(pClass), pObj ); |
| Ivy_ObjSetClassNodeLast( pClass, pObj ); |
| Ivy_ObjSetClassNodeRepr( pObj, pClass ); |
| Ivy_ObjSetClassNodeNext( pObj, NULL ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Adds equivalence class to the list of classes.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Ivy_FraigAddClass( Ivy_FraigList_t * pList, Ivy_Obj_t * pClass ) |
| { |
| if ( pList->pHead == NULL ) |
| { |
| pList->pHead = pClass; |
| pList->pTail = pClass; |
| Ivy_ObjSetEquivListPrev( pClass, NULL ); |
| Ivy_ObjSetEquivListNext( pClass, NULL ); |
| } |
| else |
| { |
| Ivy_ObjSetEquivListNext( pList->pTail, pClass ); |
| Ivy_ObjSetEquivListPrev( pClass, pList->pTail ); |
| Ivy_ObjSetEquivListNext( pClass, NULL ); |
| pList->pTail = pClass; |
| } |
| pList->nItems++; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Updates the list of classes after base class has split.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Ivy_FraigInsertClass( Ivy_FraigList_t * pList, Ivy_Obj_t * pBase, Ivy_Obj_t * pClass ) |
| { |
| Ivy_ObjSetEquivListPrev( pClass, pBase ); |
| Ivy_ObjSetEquivListNext( pClass, Ivy_ObjEquivListNext(pBase) ); |
| if ( Ivy_ObjEquivListNext(pBase) ) |
| Ivy_ObjSetEquivListPrev( Ivy_ObjEquivListNext(pBase), pClass ); |
| Ivy_ObjSetEquivListNext( pBase, pClass ); |
| if ( pList->pTail == pBase ) |
| pList->pTail = pClass; |
| pList->nItems++; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Removes equivalence class from the list of classes.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Ivy_FraigRemoveClass( Ivy_FraigList_t * pList, Ivy_Obj_t * pClass ) |
| { |
| if ( pList->pHead == pClass ) |
| pList->pHead = Ivy_ObjEquivListNext(pClass); |
| if ( pList->pTail == pClass ) |
| pList->pTail = Ivy_ObjEquivListPrev(pClass); |
| if ( Ivy_ObjEquivListPrev(pClass) ) |
| Ivy_ObjSetEquivListNext( Ivy_ObjEquivListPrev(pClass), Ivy_ObjEquivListNext(pClass) ); |
| if ( Ivy_ObjEquivListNext(pClass) ) |
| Ivy_ObjSetEquivListPrev( Ivy_ObjEquivListNext(pClass), Ivy_ObjEquivListPrev(pClass) ); |
| Ivy_ObjSetEquivListNext( pClass, NULL ); |
| Ivy_ObjSetEquivListPrev( pClass, NULL ); |
| pClass->fMarkA = 0; |
| pList->nItems--; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Count the number of pairs.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Ivy_FraigCountPairsClasses( Ivy_FraigMan_t * p ) |
| { |
| Ivy_Obj_t * pClass, * pNode; |
| int nPairs = 0, nNodes; |
| return nPairs; |
| |
| Ivy_FraigForEachEquivClass( p->lClasses.pHead, pClass ) |
| { |
| nNodes = 0; |
| Ivy_FraigForEachClassNode( pClass, pNode ) |
| nNodes++; |
| nPairs += nNodes * (nNodes - 1) / 2; |
| } |
| return nPairs; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Creates initial simulation classes.] |
| |
| Description [Assumes that simulation info is assigned.] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Ivy_FraigCreateClasses( Ivy_FraigMan_t * p ) |
| { |
| Ivy_Obj_t ** pTable; |
| Ivy_Obj_t * pObj, * pConst1, * pBin, * pEntry; |
| int i, nTableSize; |
| unsigned Hash; |
| pConst1 = Ivy_ManConst1(p->pManAig); |
| // allocate the table |
| nTableSize = Ivy_ManObjNum(p->pManAig) / 2 + 13; |
| pTable = ABC_ALLOC( Ivy_Obj_t *, nTableSize ); |
| memset( pTable, 0, sizeof(Ivy_Obj_t *) * nTableSize ); |
| // collect nodes into the table |
| Ivy_ManForEachObj( p->pManAig, pObj, i ) |
| { |
| if ( !Ivy_ObjIsPi(pObj) && !Ivy_ObjIsNode(pObj) ) |
| continue; |
| Hash = Ivy_NodeHash( p, pObj ); |
| if ( Hash == 0 && Ivy_NodeHasZeroSim( p, pObj ) ) |
| { |
| Ivy_NodeAddToClass( pConst1, pObj ); |
| continue; |
| } |
| // add the node to the table |
| pBin = pTable[Hash % nTableSize]; |
| Ivy_FraigForEachBinNode( pBin, pEntry ) |
| if ( Ivy_NodeCompareSims( p, pEntry, pObj ) ) |
| { |
| Ivy_NodeAddToClass( pEntry, pObj ); |
| break; |
| } |
| // check if the entry was added |
| if ( pEntry ) |
| continue; |
| Ivy_ObjSetNodeHashNext( pObj, pBin ); |
| pTable[Hash % nTableSize] = pObj; |
| } |
| // collect non-trivial classes |
| assert( p->lClasses.pHead == NULL ); |
| Ivy_ManForEachObj( p->pManAig, pObj, i ) |
| { |
| if ( !Ivy_ObjIsConst1(pObj) && !Ivy_ObjIsPi(pObj) && !Ivy_ObjIsNode(pObj) ) |
| continue; |
| Ivy_ObjSetNodeHashNext( pObj, NULL ); |
| if ( Ivy_ObjClassNodeRepr(pObj) == NULL ) |
| { |
| assert( Ivy_ObjClassNodeNext(pObj) == NULL ); |
| continue; |
| } |
| // recognize the head of the class |
| if ( Ivy_ObjClassNodeNext( Ivy_ObjClassNodeRepr(pObj) ) != NULL ) |
| continue; |
| // clean the class representative and add it to the list |
| Ivy_ObjSetClassNodeRepr( pObj, NULL ); |
| Ivy_FraigAddClass( &p->lClasses, pObj ); |
| } |
| // free the table |
| ABC_FREE( pTable ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Recursively refines the class after simulation.] |
| |
| Description [Returns 1 if the class has changed.] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Ivy_FraigRefineClass_rec( Ivy_FraigMan_t * p, Ivy_Obj_t * pClass ) |
| { |
| Ivy_Obj_t * pClassNew, * pListOld, * pListNew, * pNode; |
| int RetValue = 0; |
| // check if there is refinement |
| pListOld = pClass; |
| Ivy_FraigForEachClassNode( Ivy_ObjClassNodeNext(pClass), pClassNew ) |
| { |
| if ( !Ivy_NodeCompareSims(p, pClass, pClassNew) ) |
| { |
| if ( p->pParams->fPatScores ) |
| Ivy_FraigAddToPatScores( p, pClass, pClassNew ); |
| break; |
| } |
| pListOld = pClassNew; |
| } |
| if ( pClassNew == NULL ) |
| return 0; |
| // set representative of the new class |
| Ivy_ObjSetClassNodeRepr( pClassNew, NULL ); |
| // start the new list |
| pListNew = pClassNew; |
| // go through the remaining nodes and sort them into two groups: |
| // (1) matches of the old node; (2) non-matches of the old node |
| Ivy_FraigForEachClassNode( Ivy_ObjClassNodeNext(pClassNew), pNode ) |
| if ( Ivy_NodeCompareSims( p, pClass, pNode ) ) |
| { |
| Ivy_ObjSetClassNodeNext( pListOld, pNode ); |
| pListOld = pNode; |
| } |
| else |
| { |
| Ivy_ObjSetClassNodeNext( pListNew, pNode ); |
| Ivy_ObjSetClassNodeRepr( pNode, pClassNew ); |
| pListNew = pNode; |
| } |
| // finish both lists |
| Ivy_ObjSetClassNodeNext( pListNew, NULL ); |
| Ivy_ObjSetClassNodeNext( pListOld, NULL ); |
| // update the list of classes |
| Ivy_FraigInsertClass( &p->lClasses, pClass, pClassNew ); |
| // if the old class is trivial, remove it |
| if ( Ivy_ObjClassNodeNext(pClass) == NULL ) |
| Ivy_FraigRemoveClass( &p->lClasses, pClass ); |
| // if the new class is trivial, remove it; otherwise, try to refine it |
| if ( Ivy_ObjClassNodeNext(pClassNew) == NULL ) |
| Ivy_FraigRemoveClass( &p->lClasses, pClassNew ); |
| else |
| RetValue = Ivy_FraigRefineClass_rec( p, pClassNew ); |
| return RetValue + 1; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Creates the counter-example from the successful pattern.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Ivy_FraigCheckOutputSimsSavePattern( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj ) |
| { |
| Ivy_FraigSim_t * pSims; |
| int i, k, BestPat, * pModel; |
| // find the word of the pattern |
| pSims = Ivy_ObjSim(pObj); |
| for ( i = 0; i < p->nSimWords; i++ ) |
| if ( pSims->pData[i] ) |
| break; |
| assert( i < p->nSimWords ); |
| // find the bit of the pattern |
| for ( k = 0; k < 32; k++ ) |
| if ( pSims->pData[i] & (1 << k) ) |
| break; |
| assert( k < 32 ); |
| // determine the best pattern |
| BestPat = i * 32 + k; |
| // fill in the counter-example data |
| pModel = ABC_ALLOC( int, Ivy_ManPiNum(p->pManFraig) ); |
| Ivy_ManForEachPi( p->pManAig, pObj, i ) |
| { |
| pModel[i] = Ivy_InfoHasBit(Ivy_ObjSim(pObj)->pData, BestPat); |
| // printf( "%d", pModel[i] ); |
| } |
| // printf( "\n" ); |
| // set the model |
| assert( p->pManFraig->pData == NULL ); |
| p->pManFraig->pData = pModel; |
| return; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Returns 1 if the one of the output is already non-constant 0.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Ivy_FraigCheckOutputSims( Ivy_FraigMan_t * p ) |
| { |
| Ivy_Obj_t * pObj; |
| int i; |
| // make sure the reference simulation pattern does not detect the bug |
| // pObj = Ivy_ManPo( p->pManAig, 0 ); |
| Ivy_ManForEachPo( p->pManAig, pObj, i ) |
| { |
| assert( Ivy_ObjFanin0(pObj)->fPhase == (unsigned)Ivy_ObjFaninC0(pObj) ); // Ivy_ObjFaninPhase(Ivy_ObjChild0(pObj)) == 0 |
| // complement simulation info |
| // if ( Ivy_ObjFanin0(pObj)->fPhase ^ Ivy_ObjFaninC0(pObj) ) // Ivy_ObjFaninPhase(Ivy_ObjChild0(pObj)) |
| // Ivy_NodeComplementSim( p, Ivy_ObjFanin0(pObj) ); |
| // check |
| if ( !Ivy_NodeHasZeroSim( p, Ivy_ObjFanin0(pObj) ) ) |
| { |
| // create the counter-example from this pattern |
| Ivy_FraigCheckOutputSimsSavePattern( p, Ivy_ObjFanin0(pObj) ); |
| return 1; |
| } |
| // complement simulation info |
| // if ( Ivy_ObjFanin0(pObj)->fPhase ^ Ivy_ObjFaninC0(pObj) ) |
| // Ivy_NodeComplementSim( p, Ivy_ObjFanin0(pObj) ); |
| } |
| return 0; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Refines the classes after simulation.] |
| |
| Description [Assumes that simulation info is assigned. Returns the |
| number of classes refined.] |
| |
| SideEffects [Large equivalence class of constant 0 may cause problems.] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Ivy_FraigRefineClasses( Ivy_FraigMan_t * p ) |
| { |
| Ivy_Obj_t * pClass, * pClass2; |
| int RetValue, Counter = 0; |
| abctime clk; |
| // check if some outputs already became non-constant |
| // this is a special case when computation can be stopped!!! |
| if ( p->pParams->fProve ) |
| Ivy_FraigCheckOutputSims( p ); |
| if ( p->pManFraig->pData ) |
| return 0; |
| // refine the classed |
| clk = Abc_Clock(); |
| Ivy_FraigForEachEquivClassSafe( p->lClasses.pHead, pClass, pClass2 ) |
| { |
| if ( pClass->fMarkA ) |
| continue; |
| RetValue = Ivy_FraigRefineClass_rec( p, pClass ); |
| Counter += ( RetValue > 0 ); |
| //if ( Ivy_ObjIsConst1(pClass) ) |
| //printf( "%d ", RetValue ); |
| //if ( Ivy_ObjIsConst1(pClass) ) |
| // p->time1 += Abc_Clock() - clk; |
| } |
| p->timeRef += Abc_Clock() - clk; |
| return Counter; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Print the class.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Ivy_FraigPrintClass( Ivy_Obj_t * pClass ) |
| { |
| Ivy_Obj_t * pObj; |
| printf( "Class {" ); |
| Ivy_FraigForEachClassNode( pClass, pObj ) |
| printf( " %d(%d)%c", pObj->Id, pObj->Level, pObj->fPhase? '+' : '-' ); |
| printf( " }\n" ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Count the number of elements in the class.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Ivy_FraigCountClassNodes( Ivy_Obj_t * pClass ) |
| { |
| Ivy_Obj_t * pObj; |
| int Counter = 0; |
| Ivy_FraigForEachClassNode( pClass, pObj ) |
| Counter++; |
| return Counter; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Prints simulation classes.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Ivy_FraigPrintSimClasses( Ivy_FraigMan_t * p ) |
| { |
| Ivy_Obj_t * pClass; |
| Ivy_FraigForEachEquivClass( p->lClasses.pHead, pClass ) |
| { |
| // Ivy_FraigPrintClass( pClass ); |
| printf( "%d ", Ivy_FraigCountClassNodes( pClass ) ); |
| } |
| // printf( "\n" ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Generated const 0 pattern.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Ivy_FraigSavePattern0( Ivy_FraigMan_t * p ) |
| { |
| memset( p->pPatWords, 0, sizeof(unsigned) * p->nPatWords ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [[Generated const 1 pattern.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Ivy_FraigSavePattern1( Ivy_FraigMan_t * p ) |
| { |
| memset( p->pPatWords, 0xff, sizeof(unsigned) * p->nPatWords ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Generates the counter-example satisfying the miter.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int * Ivy_FraigCreateModel( Ivy_FraigMan_t * p ) |
| { |
| int * pModel; |
| Ivy_Obj_t * pObj; |
| int i; |
| pModel = ABC_ALLOC( int, Ivy_ManPiNum(p->pManFraig) ); |
| Ivy_ManForEachPi( p->pManFraig, pObj, i ) |
| // pModel[i] = ( p->pSat->model.ptr[Ivy_ObjSatNum(pObj)] == l_True ); |
| pModel[i] = ( p->pSat->model[Ivy_ObjSatNum(pObj)] == l_True ); |
| return pModel; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Copy pattern from the solver into the internal storage.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Ivy_FraigSavePattern( Ivy_FraigMan_t * p ) |
| { |
| Ivy_Obj_t * pObj; |
| int i; |
| memset( p->pPatWords, 0, sizeof(unsigned) * p->nPatWords ); |
| Ivy_ManForEachPi( p->pManFraig, pObj, i ) |
| // Vec_PtrForEachEntry( Ivy_Obj_t *, p->vPiVars, pObj, i ) |
| // if ( p->pSat->model.ptr[Ivy_ObjSatNum(pObj)] == l_True ) |
| if ( p->pSat->model[Ivy_ObjSatNum(pObj)] == l_True ) |
| Ivy_InfoSetBit( p->pPatWords, i ); |
| // Ivy_InfoSetBit( p->pPatWords, pObj->Id - 1 ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Copy pattern from the solver into the internal storage.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Ivy_FraigSavePattern2( Ivy_FraigMan_t * p ) |
| { |
| Ivy_Obj_t * pObj; |
| int i; |
| memset( p->pPatWords, 0, sizeof(unsigned) * p->nPatWords ); |
| // Ivy_ManForEachPi( p->pManFraig, pObj, i ) |
| Vec_PtrForEachEntry( Ivy_Obj_t *, p->vPiVars, pObj, i ) |
| // if ( p->pSat->model.ptr[Ivy_ObjSatNum(pObj)] == l_True ) |
| if ( p->pSat->model[Ivy_ObjSatNum(pObj)] == l_True ) |
| // Ivy_InfoSetBit( p->pPatWords, i ); |
| Ivy_InfoSetBit( p->pPatWords, pObj->Id - 1 ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Copy pattern from the solver into the internal storage.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Ivy_FraigSavePattern3( Ivy_FraigMan_t * p ) |
| { |
| Ivy_Obj_t * pObj; |
| int i; |
| for ( i = 0; i < p->nPatWords; i++ ) |
| p->pPatWords[i] = Ivy_ObjRandomSim(); |
| Vec_PtrForEachEntry( Ivy_Obj_t *, p->vPiVars, pObj, i ) |
| // if ( Ivy_InfoHasBit( p->pPatWords, pObj->Id - 1 ) ^ (p->pSat->model.ptr[Ivy_ObjSatNum(pObj)] == l_True) ) |
| if ( Ivy_InfoHasBit( p->pPatWords, pObj->Id - 1 ) ^ sat_solver_var_value(p->pSat, Ivy_ObjSatNum(pObj)) ) |
| Ivy_InfoXorBit( p->pPatWords, pObj->Id - 1 ); |
| } |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [Performs simulation of the manager.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Ivy_FraigSimulate( Ivy_FraigMan_t * p ) |
| { |
| int nChanges, nClasses; |
| // start the classes |
| Ivy_FraigAssignRandom( p ); |
| Ivy_FraigSimulateOne( p ); |
| Ivy_FraigCreateClasses( p ); |
| //printf( "Starting classes = %5d. Pairs = %6d.\n", p->lClasses.nItems, Ivy_FraigCountPairsClasses(p) ); |
| // refine classes by walking 0/1 patterns |
| Ivy_FraigSavePattern0( p ); |
| Ivy_FraigAssignDist1( p, p->pPatWords ); |
| Ivy_FraigSimulateOne( p ); |
| nChanges = Ivy_FraigRefineClasses( p ); |
| if ( p->pManFraig->pData ) |
| return; |
| //printf( "Refined classes = %5d. Changes = %4d. Pairs = %6d.\n", p->lClasses.nItems, nChanges, Ivy_FraigCountPairsClasses(p) ); |
| Ivy_FraigSavePattern1( p ); |
| Ivy_FraigAssignDist1( p, p->pPatWords ); |
| Ivy_FraigSimulateOne( p ); |
| nChanges = Ivy_FraigRefineClasses( p ); |
| if ( p->pManFraig->pData ) |
| return; |
| //printf( "Refined classes = %5d. Changes = %4d. Pairs = %6d.\n", p->lClasses.nItems, nChanges, Ivy_FraigCountPairsClasses(p) ); |
| // refine classes by random simulation |
| do { |
| Ivy_FraigAssignRandom( p ); |
| Ivy_FraigSimulateOne( p ); |
| nClasses = p->lClasses.nItems; |
| nChanges = Ivy_FraigRefineClasses( p ); |
| if ( p->pManFraig->pData ) |
| return; |
| //printf( "Refined classes = %5d. Changes = %4d. Pairs = %6d.\n", p->lClasses.nItems, nChanges, Ivy_FraigCountPairsClasses(p) ); |
| } while ( (double)nChanges / nClasses > p->pParams->dSimSatur ); |
| // Ivy_FraigPrintSimClasses( p ); |
| } |
| |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [Cleans pattern scores.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Ivy_FraigCleanPatScores( Ivy_FraigMan_t * p ) |
| { |
| int i, nLimit = p->nSimWords * 32; |
| for ( i = 0; i < nLimit; i++ ) |
| p->pPatScores[i] = 0; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Adds to pattern scores.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Ivy_FraigAddToPatScores( Ivy_FraigMan_t * p, Ivy_Obj_t * pClass, Ivy_Obj_t * pClassNew ) |
| { |
| Ivy_FraigSim_t * pSims0, * pSims1; |
| unsigned uDiff; |
| int i, w; |
| // get hold of the simulation information |
| pSims0 = Ivy_ObjSim(pClass); |
| pSims1 = Ivy_ObjSim(pClassNew); |
| // iterate through the differences and record the score |
| for ( w = 0; w < p->nSimWords; w++ ) |
| { |
| uDiff = pSims0->pData[w] ^ pSims1->pData[w]; |
| if ( uDiff == 0 ) |
| continue; |
| for ( i = 0; i < 32; i++ ) |
| if ( uDiff & ( 1 << i ) ) |
| p->pPatScores[w*32+i]++; |
| } |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Selects the best pattern.] |
| |
| Description [Returns 1 if such pattern is found.] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Ivy_FraigSelectBestPat( Ivy_FraigMan_t * p ) |
| { |
| Ivy_FraigSim_t * pSims; |
| Ivy_Obj_t * pObj; |
| int i, nLimit = p->nSimWords * 32, MaxScore = 0, BestPat = -1; |
| for ( i = 1; i < nLimit; i++ ) |
| { |
| if ( MaxScore < p->pPatScores[i] ) |
| { |
| MaxScore = p->pPatScores[i]; |
| BestPat = i; |
| } |
| } |
| if ( MaxScore == 0 ) |
| return 0; |
| // if ( MaxScore > p->pParams->MaxScore ) |
| // printf( "Max score is %3d. ", MaxScore ); |
| // copy the best pattern into the selected pattern |
| memset( p->pPatWords, 0, sizeof(unsigned) * p->nPatWords ); |
| Ivy_ManForEachPi( p->pManAig, pObj, i ) |
| { |
| pSims = Ivy_ObjSim(pObj); |
| if ( Ivy_InfoHasBit(pSims->pData, BestPat) ) |
| Ivy_InfoSetBit(p->pPatWords, i); |
| } |
| return MaxScore; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Resimulates fraiging manager after finding a counter-example.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Ivy_FraigResimulate( Ivy_FraigMan_t * p ) |
| { |
| int nChanges; |
| Ivy_FraigAssignDist1( p, p->pPatWords ); |
| Ivy_FraigSimulateOne( p ); |
| if ( p->pParams->fPatScores ) |
| Ivy_FraigCleanPatScores( p ); |
| nChanges = Ivy_FraigRefineClasses( p ); |
| if ( p->pManFraig->pData ) |
| return; |
| if ( nChanges < 1 ) |
| printf( "Error: A counter-example did not refine classes!\n" ); |
| assert( nChanges >= 1 ); |
| //printf( "Refined classes! = %5d. Changes = %4d.\n", p->lClasses.nItems, nChanges ); |
| if ( !p->pParams->fPatScores ) |
| return; |
| |
| // perform additional simulation using dist1 patterns derived from successful patterns |
| while ( Ivy_FraigSelectBestPat(p) > p->pParams->MaxScore ) |
| { |
| Ivy_FraigAssignDist1( p, p->pPatWords ); |
| Ivy_FraigSimulateOne( p ); |
| Ivy_FraigCleanPatScores( p ); |
| nChanges = Ivy_FraigRefineClasses( p ); |
| if ( p->pManFraig->pData ) |
| return; |
| //printf( "Refined class!!! = %5d. Changes = %4d. Pairs = %6d.\n", p->lClasses.nItems, nChanges, Ivy_FraigCountPairsClasses(p) ); |
| if ( nChanges == 0 ) |
| break; |
| } |
| } |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [Prints the status of the miter.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Ivy_FraigMiterPrint( Ivy_Man_t * pNtk, char * pString, abctime clk, int fVerbose ) |
| { |
| if ( !fVerbose ) |
| return; |
| printf( "Nodes = %7d. Levels = %4d. ", Ivy_ManNodeNum(pNtk), Ivy_ManLevels(pNtk) ); |
| ABC_PRT( pString, Abc_Clock() - clk ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Reports the status of the miter.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Ivy_FraigMiterStatus( Ivy_Man_t * pMan ) |
| { |
| Ivy_Obj_t * pObj, * pObjNew; |
| int i, CountConst0 = 0, CountNonConst0 = 0, CountUndecided = 0; |
| if ( pMan->pData ) |
| return 0; |
| Ivy_ManForEachPo( pMan, pObj, i ) |
| { |
| pObjNew = Ivy_ObjChild0(pObj); |
| // check if the output is constant 1 |
| if ( pObjNew == pMan->pConst1 ) |
| { |
| CountNonConst0++; |
| continue; |
| } |
| // check if the output is constant 0 |
| if ( pObjNew == Ivy_Not(pMan->pConst1) ) |
| { |
| CountConst0++; |
| continue; |
| } |
| /* |
| // check if the output is a primary input |
| if ( Ivy_ObjIsPi(Ivy_Regular(pObjNew)) ) |
| { |
| CountNonConst0++; |
| continue; |
| } |
| */ |
| // check if the output can be constant 0 |
| if ( Ivy_Regular(pObjNew)->fPhase != (unsigned)Ivy_IsComplement(pObjNew) ) |
| { |
| CountNonConst0++; |
| continue; |
| } |
| CountUndecided++; |
| } |
| /* |
| if ( p->pParams->fVerbose ) |
| { |
| printf( "Miter has %d outputs. ", Ivy_ManPoNum(p->pManAig) ); |
| printf( "Const0 = %d. ", CountConst0 ); |
| printf( "NonConst0 = %d. ", CountNonConst0 ); |
| printf( "Undecided = %d. ", CountUndecided ); |
| printf( "\n" ); |
| } |
| */ |
| if ( CountNonConst0 ) |
| return 0; |
| if ( CountUndecided ) |
| return -1; |
| return 1; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Tries to prove each output of the miter until encountering a sat output.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Ivy_FraigMiterProve( Ivy_FraigMan_t * p ) |
| { |
| Ivy_Obj_t * pObj, * pObjNew; |
| int i, RetValue; |
| abctime clk = Abc_Clock(); |
| int fVerbose = 0; |
| Ivy_ManForEachPo( p->pManAig, pObj, i ) |
| { |
| if ( i && fVerbose ) |
| { |
| ABC_PRT( "Time", Abc_Clock() -clk ); |
| } |
| pObjNew = Ivy_ObjChild0Equiv(pObj); |
| // check if the output is constant 1 |
| if ( pObjNew == p->pManFraig->pConst1 ) |
| { |
| if ( fVerbose ) |
| printf( "Output %2d (out of %2d) is constant 1. ", i, Ivy_ManPoNum(p->pManAig) ); |
| // assing constant 0 model |
| p->pManFraig->pData = ABC_ALLOC( int, Ivy_ManPiNum(p->pManFraig) ); |
| memset( p->pManFraig->pData, 0, sizeof(int) * Ivy_ManPiNum(p->pManFraig) ); |
| break; |
| } |
| // check if the output is constant 0 |
| if ( pObjNew == Ivy_Not(p->pManFraig->pConst1) ) |
| { |
| if ( fVerbose ) |
| printf( "Output %2d (out of %2d) is already constant 0. ", i, Ivy_ManPoNum(p->pManAig) ); |
| continue; |
| } |
| // check if the output can be constant 0 |
| if ( Ivy_Regular(pObjNew)->fPhase != (unsigned)Ivy_IsComplement(pObjNew) ) |
| { |
| if ( fVerbose ) |
| printf( "Output %2d (out of %2d) cannot be constant 0. ", i, Ivy_ManPoNum(p->pManAig) ); |
| // assing constant 0 model |
| p->pManFraig->pData = ABC_ALLOC( int, Ivy_ManPiNum(p->pManFraig) ); |
| memset( p->pManFraig->pData, 0, sizeof(int) * Ivy_ManPiNum(p->pManFraig) ); |
| break; |
| } |
| /* |
| // check the representative of this node |
| pRepr = Ivy_ObjClassNodeRepr(Ivy_ObjFanin0(pObj)); |
| if ( Ivy_Regular(pRepr) != p->pManAig->pConst1 ) |
| printf( "Representative is not constant 1.\n" ); |
| else |
| printf( "Representative is constant 1.\n" ); |
| */ |
| // try to prove the output constant 0 |
| RetValue = Ivy_FraigNodeIsConst( p, Ivy_Regular(pObjNew) ); |
| if ( RetValue == 1 ) // proved equivalent |
| { |
| if ( fVerbose ) |
| printf( "Output %2d (out of %2d) was proved constant 0. ", i, Ivy_ManPoNum(p->pManAig) ); |
| // set the constant miter |
| Ivy_ObjFanin0(pObj)->pEquiv = Ivy_NotCond( p->pManFraig->pConst1, !Ivy_ObjFaninC0(pObj) ); |
| continue; |
| } |
| if ( RetValue == -1 ) // failed |
| { |
| if ( fVerbose ) |
| printf( "Output %2d (out of %2d) has timed out at %d backtracks. ", i, Ivy_ManPoNum(p->pManAig), p->pParams->nBTLimitMiter ); |
| continue; |
| } |
| // proved satisfiable |
| if ( fVerbose ) |
| printf( "Output %2d (out of %2d) was proved NOT a constant 0. ", i, Ivy_ManPoNum(p->pManAig) ); |
| // create the model |
| p->pManFraig->pData = Ivy_FraigCreateModel(p); |
| break; |
| } |
| if ( fVerbose ) |
| { |
| ABC_PRT( "Time", Abc_Clock() -clk ); |
| } |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Performs fraiging for the internal nodes.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Ivy_FraigSweep( Ivy_FraigMan_t * p ) |
| { |
| Ivy_Obj_t * pObj;//, * pTemp; |
| int i, k = 0; |
| p->nClassesZero = p->lClasses.pHead? (Ivy_ObjIsConst1(p->lClasses.pHead) ? Ivy_FraigCountClassNodes(p->lClasses.pHead) : 0) : 0; |
| p->nClassesBeg = p->lClasses.nItems; |
| // duplicate internal nodes |
| p->pProgress = Extra_ProgressBarStart( stdout, Ivy_ManNodeNum(p->pManAig) ); |
| Ivy_ManForEachNode( p->pManAig, pObj, i ) |
| { |
| Extra_ProgressBarUpdate( p->pProgress, k++, NULL ); |
| // default to simple strashing if simulation detected a counter-example for a PO |
| if ( p->pManFraig->pData ) |
| pObj->pEquiv = Ivy_And( p->pManFraig, Ivy_ObjChild0Equiv(pObj), Ivy_ObjChild1Equiv(pObj) ); |
| else |
| pObj->pEquiv = Ivy_FraigAnd( p, pObj ); |
| assert( pObj->pEquiv != NULL ); |
| // pTemp = Ivy_Regular(pObj->pEquiv); |
| // assert( Ivy_Regular(pObj->pEquiv)->Type ); |
| } |
| Extra_ProgressBarStop( p->pProgress ); |
| p->nClassesEnd = p->lClasses.nItems; |
| // try to prove the outputs of the miter |
| p->nNodesMiter = Ivy_ManNodeNum(p->pManFraig); |
| // Ivy_FraigMiterStatus( p->pManFraig ); |
| if ( p->pParams->fProve && p->pManFraig->pData == NULL ) |
| Ivy_FraigMiterProve( p ); |
| // add the POs |
| Ivy_ManForEachPo( p->pManAig, pObj, i ) |
| Ivy_ObjCreatePo( p->pManFraig, Ivy_ObjChild0Equiv(pObj) ); |
| // clean the old manager |
| Ivy_ManForEachObj( p->pManAig, pObj, i ) |
| pObj->pFanout = pObj->pNextFan0 = pObj->pNextFan1 = pObj->pPrevFan0 = pObj->pPrevFan1 = NULL; |
| // clean the new manager |
| Ivy_ManForEachObj( p->pManFraig, pObj, i ) |
| { |
| if ( Ivy_ObjFaninVec(pObj) ) |
| Vec_PtrFree( Ivy_ObjFaninVec(pObj) ); |
| pObj->pNextFan0 = pObj->pNextFan1 = NULL; |
| pObj->pEquiv = NULL; |
| } |
| // remove dangling nodes |
| Ivy_ManCleanup( p->pManFraig ); |
| // clean up the class marks |
| Ivy_FraigForEachEquivClass( p->lClasses.pHead, pObj ) |
| pObj->fMarkA = 0; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Performs fraiging for one node.] |
| |
| Description [Returns the fraiged node.] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Ivy_Obj_t * Ivy_FraigAnd( Ivy_FraigMan_t * p, Ivy_Obj_t * pObjOld ) |
| { |
| Ivy_Obj_t * pObjNew, * pFanin0New, * pFanin1New, * pObjReprNew; |
| int RetValue; |
| // get the fraiged fanins |
| pFanin0New = Ivy_ObjChild0Equiv(pObjOld); |
| pFanin1New = Ivy_ObjChild1Equiv(pObjOld); |
| // get the candidate fraig node |
| pObjNew = Ivy_And( p->pManFraig, pFanin0New, pFanin1New ); |
| // get representative of this class |
| if ( Ivy_ObjClassNodeRepr(pObjOld) == NULL || // this is a unique node |
| (!p->pParams->fDoSparse && Ivy_ObjClassNodeRepr(pObjOld) == p->pManAig->pConst1) ) // this is a sparse node |
| { |
| // assert( Ivy_Regular(pFanin0New) != Ivy_Regular(pFanin1New) ); |
| // assert( pObjNew != Ivy_Regular(pFanin0New) ); |
| // assert( pObjNew != Ivy_Regular(pFanin1New) ); |
| return pObjNew; |
| } |
| // get the fraiged representative |
| pObjReprNew = Ivy_ObjFraig(Ivy_ObjClassNodeRepr(pObjOld)); |
| // if the fraiged nodes are the same return |
| if ( Ivy_Regular(pObjNew) == Ivy_Regular(pObjReprNew) ) |
| return pObjNew; |
| assert( Ivy_Regular(pObjNew) != Ivy_ManConst1(p->pManFraig) ); |
| // printf( "Node = %d. Repr = %d.\n", pObjOld->Id, Ivy_ObjClassNodeRepr(pObjOld)->Id ); |
| |
| // they are different (the counter-example is in p->pPatWords) |
| RetValue = Ivy_FraigNodesAreEquiv( p, Ivy_Regular(pObjReprNew), Ivy_Regular(pObjNew) ); |
| if ( RetValue == 1 ) // proved equivalent |
| { |
| // mark the class as proved |
| if ( Ivy_ObjClassNodeNext(pObjOld) == NULL ) |
| Ivy_ObjClassNodeRepr(pObjOld)->fMarkA = 1; |
| return Ivy_NotCond( pObjReprNew, pObjOld->fPhase ^ Ivy_ObjClassNodeRepr(pObjOld)->fPhase ); |
| } |
| if ( RetValue == -1 ) // failed |
| return pObjNew; |
| // simulate the counter-example and return the new node |
| Ivy_FraigResimulate( p ); |
| return pObjNew; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Prints variable activity.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Ivy_FraigPrintActivity( Ivy_FraigMan_t * p ) |
| { |
| int i; |
| for ( i = 0; i < p->nSatVars; i++ ) |
| printf( "%d %d ", i, (int)p->pSat->activity[i] ); |
| printf( "\n" ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Runs equivalence test for the two nodes.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Ivy_FraigNodesAreEquiv( Ivy_FraigMan_t * p, Ivy_Obj_t * pOld, Ivy_Obj_t * pNew ) |
| { |
| int pLits[4], RetValue, RetValue1, nBTLimit; |
| abctime clk; //, clk2 = Abc_Clock(); |
| |
| // make sure the nodes are not complemented |
| assert( !Ivy_IsComplement(pNew) ); |
| assert( !Ivy_IsComplement(pOld) ); |
| assert( pNew != pOld ); |
| |
| // if at least one of the nodes is a failed node, perform adjustments: |
| // if the backtrack limit is small, simply skip this node |
| // if the backtrack limit is > 10, take the quare root of the limit |
| nBTLimit = p->pParams->nBTLimitNode; |
| if ( nBTLimit > 0 && (pOld->fFailTfo || pNew->fFailTfo) ) |
| { |
| p->nSatFails++; |
| // fail immediately |
| // return -1; |
| if ( nBTLimit <= 10 ) |
| return -1; |
| nBTLimit = (int)pow(nBTLimit, 0.7); |
| } |
| p->nSatCalls++; |
| |
| // make sure the solver is allocated and has enough variables |
| if ( p->pSat == NULL ) |
| { |
| p->pSat = sat_solver_new(); |
| sat_solver_setnvars( p->pSat, 1000 ); |
| p->pSat->factors = ABC_CALLOC( double, p->pSat->cap ); |
| p->nSatVars = 1; |
| // var 0 is reserved for const1 node - add the clause |
| // pLits[0] = toLit( 0 ); |
| // sat_solver_addclause( p->pSat, pLits, pLits + 1 ); |
| } |
| |
| // if the nodes do not have SAT variables, allocate them |
| Ivy_FraigNodeAddToSolver( p, pOld, pNew ); |
| |
| // prepare variable activity |
| Ivy_FraigSetActivityFactors( p, pOld, pNew ); |
| |
| // solve under assumptions |
| // A = 1; B = 0 OR A = 1; B = 1 |
| clk = Abc_Clock(); |
| pLits[0] = toLitCond( Ivy_ObjSatNum(pOld), 0 ); |
| pLits[1] = toLitCond( Ivy_ObjSatNum(pNew), pOld->fPhase == pNew->fPhase ); |
| //Sat_SolverWriteDimacs( p->pSat, "temp.cnf", pLits, pLits + 2, 1 ); |
| RetValue1 = sat_solver_solve( p->pSat, pLits, pLits + 2, |
| (ABC_INT64_T)nBTLimit, (ABC_INT64_T)0, |
| p->nBTLimitGlobal, p->nInsLimitGlobal ); |
| p->timeSat += Abc_Clock() - clk; |
| if ( RetValue1 == l_False ) |
| { |
| p->timeSatUnsat += Abc_Clock() - clk; |
| pLits[0] = lit_neg( pLits[0] ); |
| pLits[1] = lit_neg( pLits[1] ); |
| RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 ); |
| assert( RetValue ); |
| // continue solving the other implication |
| p->nSatCallsUnsat++; |
| } |
| else if ( RetValue1 == l_True ) |
| { |
| p->timeSatSat += Abc_Clock() - clk; |
| Ivy_FraigSavePattern( p ); |
| p->nSatCallsSat++; |
| return 0; |
| } |
| else // if ( RetValue1 == l_Undef ) |
| { |
| p->timeSatFail += Abc_Clock() - clk; |
| /* |
| if ( nBTLimit > 1000 ) |
| { |
| RetValue = Ivy_FraigCheckCone( p, p->pManFraig, pOld, pNew, nBTLimit ); |
| if ( RetValue != -1 ) |
| return RetValue; |
| } |
| */ |
| // mark the node as the failed node |
| if ( pOld != p->pManFraig->pConst1 ) |
| pOld->fFailTfo = 1; |
| pNew->fFailTfo = 1; |
| p->nSatFailsReal++; |
| return -1; |
| } |
| |
| // if the old node was constant 0, we already know the answer |
| if ( pOld == p->pManFraig->pConst1 ) |
| { |
| p->nSatProof++; |
| return 1; |
| } |
| |
| // solve under assumptions |
| // A = 0; B = 1 OR A = 0; B = 0 |
| clk = Abc_Clock(); |
| pLits[0] = toLitCond( Ivy_ObjSatNum(pOld), 1 ); |
| pLits[1] = toLitCond( Ivy_ObjSatNum(pNew), pOld->fPhase ^ pNew->fPhase ); |
| RetValue1 = sat_solver_solve( p->pSat, pLits, pLits + 2, |
| (ABC_INT64_T)nBTLimit, (ABC_INT64_T)0, |
| p->nBTLimitGlobal, p->nInsLimitGlobal ); |
| p->timeSat += Abc_Clock() - clk; |
| if ( RetValue1 == l_False ) |
| { |
| p->timeSatUnsat += Abc_Clock() - clk; |
| pLits[0] = lit_neg( pLits[0] ); |
| pLits[1] = lit_neg( pLits[1] ); |
| RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 ); |
| assert( RetValue ); |
| p->nSatCallsUnsat++; |
| } |
| else if ( RetValue1 == l_True ) |
| { |
| p->timeSatSat += Abc_Clock() - clk; |
| Ivy_FraigSavePattern( p ); |
| p->nSatCallsSat++; |
| return 0; |
| } |
| else // if ( RetValue1 == l_Undef ) |
| { |
| p->timeSatFail += Abc_Clock() - clk; |
| /* |
| if ( nBTLimit > 1000 ) |
| { |
| RetValue = Ivy_FraigCheckCone( p, p->pManFraig, pOld, pNew, nBTLimit ); |
| if ( RetValue != -1 ) |
| return RetValue; |
| } |
| */ |
| // mark the node as the failed node |
| pOld->fFailTfo = 1; |
| pNew->fFailTfo = 1; |
| p->nSatFailsReal++; |
| return -1; |
| } |
| /* |
| // check BDD proof |
| { |
| int RetVal; |
| ABC_PRT( "Sat", Abc_Clock() - clk2 ); |
| clk2 = Abc_Clock(); |
| RetVal = Ivy_FraigNodesAreEquivBdd( pOld, pNew ); |
| // printf( "%d ", RetVal ); |
| assert( RetVal ); |
| ABC_PRT( "Bdd", Abc_Clock() - clk2 ); |
| printf( "\n" ); |
| } |
| */ |
| // return SAT proof |
| p->nSatProof++; |
| return 1; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Runs equivalence test for one node.] |
| |
| Description [Returns the fraiged node.] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Ivy_FraigNodeIsConst( Ivy_FraigMan_t * p, Ivy_Obj_t * pNew ) |
| { |
| int pLits[2], RetValue1; |
| abctime clk; |
| int RetValue; |
| |
| // make sure the nodes are not complemented |
| assert( !Ivy_IsComplement(pNew) ); |
| assert( pNew != p->pManFraig->pConst1 ); |
| p->nSatCalls++; |
| |
| // make sure the solver is allocated and has enough variables |
| if ( p->pSat == NULL ) |
| { |
| p->pSat = sat_solver_new(); |
| sat_solver_setnvars( p->pSat, 1000 ); |
| p->pSat->factors = ABC_CALLOC( double, p->pSat->cap ); |
| p->nSatVars = 1; |
| // var 0 is reserved for const1 node - add the clause |
| // pLits[0] = toLit( 0 ); |
| // sat_solver_addclause( p->pSat, pLits, pLits + 1 ); |
| } |
| |
| // if the nodes do not have SAT variables, allocate them |
| Ivy_FraigNodeAddToSolver( p, NULL, pNew ); |
| |
| // prepare variable activity |
| Ivy_FraigSetActivityFactors( p, NULL, pNew ); |
| |
| // solve under assumptions |
| clk = Abc_Clock(); |
| pLits[0] = toLitCond( Ivy_ObjSatNum(pNew), pNew->fPhase ); |
| RetValue1 = sat_solver_solve( p->pSat, pLits, pLits + 1, |
| (ABC_INT64_T)p->pParams->nBTLimitMiter, (ABC_INT64_T)0, |
| p->nBTLimitGlobal, p->nInsLimitGlobal ); |
| p->timeSat += Abc_Clock() - clk; |
| if ( RetValue1 == l_False ) |
| { |
| p->timeSatUnsat += Abc_Clock() - clk; |
| pLits[0] = lit_neg( pLits[0] ); |
| RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 1 ); |
| assert( RetValue ); |
| // continue solving the other implication |
| p->nSatCallsUnsat++; |
| } |
| else if ( RetValue1 == l_True ) |
| { |
| p->timeSatSat += Abc_Clock() - clk; |
| if ( p->pPatWords ) |
| Ivy_FraigSavePattern( p ); |
| p->nSatCallsSat++; |
| return 0; |
| } |
| else // if ( RetValue1 == l_Undef ) |
| { |
| p->timeSatFail += Abc_Clock() - clk; |
| /* |
| if ( p->pParams->nBTLimitMiter > 1000 ) |
| { |
| RetValue = Ivy_FraigCheckCone( p, p->pManFraig, p->pManFraig->pConst1, pNew, p->pParams->nBTLimitMiter ); |
| if ( RetValue != -1 ) |
| return RetValue; |
| } |
| */ |
| // mark the node as the failed node |
| pNew->fFailTfo = 1; |
| p->nSatFailsReal++; |
| return -1; |
| } |
| |
| // return SAT proof |
| p->nSatProof++; |
| return 1; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Addes clauses to the solver.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Ivy_FraigAddClausesMux( Ivy_FraigMan_t * p, Ivy_Obj_t * pNode ) |
| { |
| Ivy_Obj_t * pNodeI, * pNodeT, * pNodeE; |
| int pLits[4], RetValue, VarF, VarI, VarT, VarE, fCompT, fCompE; |
| |
| assert( !Ivy_IsComplement( pNode ) ); |
| assert( Ivy_ObjIsMuxType( pNode ) ); |
| // get nodes (I = if, T = then, E = else) |
| pNodeI = Ivy_ObjRecognizeMux( pNode, &pNodeT, &pNodeE ); |
| // get the variable numbers |
| VarF = Ivy_ObjSatNum(pNode); |
| VarI = Ivy_ObjSatNum(pNodeI); |
| VarT = Ivy_ObjSatNum(Ivy_Regular(pNodeT)); |
| VarE = Ivy_ObjSatNum(Ivy_Regular(pNodeE)); |
| // get the complementation flags |
| fCompT = Ivy_IsComplement(pNodeT); |
| fCompE = Ivy_IsComplement(pNodeE); |
| |
| // f = ITE(i, t, e) |
| |
| // i' + t' + f |
| // i' + t + f' |
| // i + e' + f |
| // i + e + f' |
| |
| // create four clauses |
| pLits[0] = toLitCond(VarI, 1); |
| pLits[1] = toLitCond(VarT, 1^fCompT); |
| pLits[2] = toLitCond(VarF, 0); |
| RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); |
| assert( RetValue ); |
| pLits[0] = toLitCond(VarI, 1); |
| pLits[1] = toLitCond(VarT, 0^fCompT); |
| pLits[2] = toLitCond(VarF, 1); |
| RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); |
| assert( RetValue ); |
| pLits[0] = toLitCond(VarI, 0); |
| pLits[1] = toLitCond(VarE, 1^fCompE); |
| pLits[2] = toLitCond(VarF, 0); |
| RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); |
| assert( RetValue ); |
| pLits[0] = toLitCond(VarI, 0); |
| pLits[1] = toLitCond(VarE, 0^fCompE); |
| pLits[2] = toLitCond(VarF, 1); |
| RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); |
| assert( RetValue ); |
| |
| // two additional clauses |
| // t' & e' -> f' |
| // t & e -> f |
| |
| // t + e + f' |
| // t' + e' + f |
| |
| if ( VarT == VarE ) |
| { |
| // assert( fCompT == !fCompE ); |
| return; |
| } |
| |
| pLits[0] = toLitCond(VarT, 0^fCompT); |
| pLits[1] = toLitCond(VarE, 0^fCompE); |
| pLits[2] = toLitCond(VarF, 1); |
| RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); |
| assert( RetValue ); |
| pLits[0] = toLitCond(VarT, 1^fCompT); |
| pLits[1] = toLitCond(VarE, 1^fCompE); |
| pLits[2] = toLitCond(VarF, 0); |
| RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); |
| assert( RetValue ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Addes clauses to the solver.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Ivy_FraigAddClausesSuper( Ivy_FraigMan_t * p, Ivy_Obj_t * pNode, Vec_Ptr_t * vSuper ) |
| { |
| Ivy_Obj_t * pFanin; |
| int * pLits, nLits, RetValue, i; |
| assert( !Ivy_IsComplement(pNode) ); |
| assert( Ivy_ObjIsNode( pNode ) ); |
| // create storage for literals |
| nLits = Vec_PtrSize(vSuper) + 1; |
| pLits = ABC_ALLOC( int, nLits ); |
| // suppose AND-gate is A & B = C |
| // add !A => !C or A + !C |
| Vec_PtrForEachEntry( Ivy_Obj_t *, vSuper, pFanin, i ) |
| { |
| pLits[0] = toLitCond(Ivy_ObjSatNum(Ivy_Regular(pFanin)), Ivy_IsComplement(pFanin)); |
| pLits[1] = toLitCond(Ivy_ObjSatNum(pNode), 1); |
| RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 ); |
| assert( RetValue ); |
| } |
| // add A & B => C or !A + !B + C |
| Vec_PtrForEachEntry( Ivy_Obj_t *, vSuper, pFanin, i ) |
| pLits[i] = toLitCond(Ivy_ObjSatNum(Ivy_Regular(pFanin)), !Ivy_IsComplement(pFanin)); |
| pLits[nLits-1] = toLitCond(Ivy_ObjSatNum(pNode), 0); |
| RetValue = sat_solver_addclause( p->pSat, pLits, pLits + nLits ); |
| assert( RetValue ); |
| ABC_FREE( pLits ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Collects the supergate.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Ivy_FraigCollectSuper_rec( Ivy_Obj_t * pObj, Vec_Ptr_t * vSuper, int fFirst, int fUseMuxes ) |
| { |
| // if the new node is complemented or a PI, another gate begins |
| if ( Ivy_IsComplement(pObj) || Ivy_ObjIsPi(pObj) || (!fFirst && Ivy_ObjRefs(pObj) > 1) || |
| (fUseMuxes && Ivy_ObjIsMuxType(pObj)) ) |
| { |
| Vec_PtrPushUnique( vSuper, pObj ); |
| return; |
| } |
| // go through the branches |
| Ivy_FraigCollectSuper_rec( Ivy_ObjChild0(pObj), vSuper, 0, fUseMuxes ); |
| Ivy_FraigCollectSuper_rec( Ivy_ObjChild1(pObj), vSuper, 0, fUseMuxes ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Collects the supergate.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Vec_Ptr_t * Ivy_FraigCollectSuper( Ivy_Obj_t * pObj, int fUseMuxes ) |
| { |
| Vec_Ptr_t * vSuper; |
| assert( !Ivy_IsComplement(pObj) ); |
| assert( !Ivy_ObjIsPi(pObj) ); |
| vSuper = Vec_PtrAlloc( 4 ); |
| Ivy_FraigCollectSuper_rec( pObj, vSuper, 1, fUseMuxes ); |
| return vSuper; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Updates the solver clause database.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Ivy_FraigObjAddToFrontier( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj, Vec_Ptr_t * vFrontier ) |
| { |
| assert( !Ivy_IsComplement(pObj) ); |
| if ( Ivy_ObjSatNum(pObj) ) |
| return; |
| assert( Ivy_ObjSatNum(pObj) == 0 ); |
| assert( Ivy_ObjFaninVec(pObj) == NULL ); |
| if ( Ivy_ObjIsConst1(pObj) ) |
| return; |
| //printf( "Assigning node %d number %d\n", pObj->Id, p->nSatVars ); |
| Ivy_ObjSetSatNum( pObj, p->nSatVars++ ); |
| if ( Ivy_ObjIsNode(pObj) ) |
| Vec_PtrPush( vFrontier, pObj ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Updates the solver clause database.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Ivy_FraigNodeAddToSolver( Ivy_FraigMan_t * p, Ivy_Obj_t * pOld, Ivy_Obj_t * pNew ) |
| { |
| Vec_Ptr_t * vFrontier, * vFanins; |
| Ivy_Obj_t * pNode, * pFanin; |
| int i, k, fUseMuxes = 1; |
| assert( pOld || pNew ); |
| // quit if CNF is ready |
| if ( (!pOld || Ivy_ObjFaninVec(pOld)) && (!pNew || Ivy_ObjFaninVec(pNew)) ) |
| return; |
| // start the frontier |
| vFrontier = Vec_PtrAlloc( 100 ); |
| if ( pOld ) Ivy_FraigObjAddToFrontier( p, pOld, vFrontier ); |
| if ( pNew ) Ivy_FraigObjAddToFrontier( p, pNew, vFrontier ); |
| // explore nodes in the frontier |
| Vec_PtrForEachEntry( Ivy_Obj_t *, vFrontier, pNode, i ) |
| { |
| // create the supergate |
| assert( Ivy_ObjSatNum(pNode) ); |
| assert( Ivy_ObjFaninVec(pNode) == NULL ); |
| if ( fUseMuxes && Ivy_ObjIsMuxType(pNode) ) |
| { |
| vFanins = Vec_PtrAlloc( 4 ); |
| Vec_PtrPushUnique( vFanins, Ivy_ObjFanin0( Ivy_ObjFanin0(pNode) ) ); |
| Vec_PtrPushUnique( vFanins, Ivy_ObjFanin0( Ivy_ObjFanin1(pNode) ) ); |
| Vec_PtrPushUnique( vFanins, Ivy_ObjFanin1( Ivy_ObjFanin0(pNode) ) ); |
| Vec_PtrPushUnique( vFanins, Ivy_ObjFanin1( Ivy_ObjFanin1(pNode) ) ); |
| Vec_PtrForEachEntry( Ivy_Obj_t *, vFanins, pFanin, k ) |
| Ivy_FraigObjAddToFrontier( p, Ivy_Regular(pFanin), vFrontier ); |
| Ivy_FraigAddClausesMux( p, pNode ); |
| } |
| else |
| { |
| vFanins = Ivy_FraigCollectSuper( pNode, fUseMuxes ); |
| Vec_PtrForEachEntry( Ivy_Obj_t *, vFanins, pFanin, k ) |
| Ivy_FraigObjAddToFrontier( p, Ivy_Regular(pFanin), vFrontier ); |
| Ivy_FraigAddClausesSuper( p, pNode, vFanins ); |
| } |
| assert( Vec_PtrSize(vFanins) > 1 ); |
| Ivy_ObjSetFaninVec( pNode, vFanins ); |
| } |
| Vec_PtrFree( vFrontier ); |
| sat_solver_simplify( p->pSat ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Sets variable activities in the cone.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Ivy_FraigSetActivityFactors_rec( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj, int LevelMin, int LevelMax ) |
| { |
| Vec_Ptr_t * vFanins; |
| Ivy_Obj_t * pFanin; |
| int i, Counter = 0; |
| assert( !Ivy_IsComplement(pObj) ); |
| assert( Ivy_ObjSatNum(pObj) ); |
| // skip visited variables |
| if ( Ivy_ObjIsTravIdCurrent(p->pManFraig, pObj) ) |
| return 0; |
| Ivy_ObjSetTravIdCurrent(p->pManFraig, pObj); |
| // add the PI to the list |
| if ( pObj->Level <= (unsigned)LevelMin || Ivy_ObjIsPi(pObj) ) |
| return 0; |
| // set the factor of this variable |
| // (LevelMax-LevelMin) / (pObj->Level-LevelMin) = p->pParams->dActConeBumpMax / ThisBump |
| p->pSat->factors[Ivy_ObjSatNum(pObj)] = p->pParams->dActConeBumpMax * (pObj->Level - LevelMin)/(LevelMax - LevelMin); |
| veci_push(&p->pSat->act_vars, Ivy_ObjSatNum(pObj)); |
| // explore the fanins |
| vFanins = Ivy_ObjFaninVec( pObj ); |
| Vec_PtrForEachEntry( Ivy_Obj_t *, vFanins, pFanin, i ) |
| Counter += Ivy_FraigSetActivityFactors_rec( p, Ivy_Regular(pFanin), LevelMin, LevelMax ); |
| return 1 + Counter; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Sets variable activities in the cone.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Ivy_FraigSetActivityFactors( Ivy_FraigMan_t * p, Ivy_Obj_t * pOld, Ivy_Obj_t * pNew ) |
| { |
| int LevelMin, LevelMax; |
| abctime clk; |
| assert( pOld || pNew ); |
| clk = Abc_Clock(); |
| // reset the active variables |
| veci_resize(&p->pSat->act_vars, 0); |
| // prepare for traversal |
| Ivy_ManIncrementTravId( p->pManFraig ); |
| // determine the min and max level to visit |
| assert( p->pParams->dActConeRatio > 0 && p->pParams->dActConeRatio < 1 ); |
| LevelMax = IVY_MAX( (pNew ? pNew->Level : 0), (pOld ? pOld->Level : 0) ); |
| LevelMin = (int)(LevelMax * (1.0 - p->pParams->dActConeRatio)); |
| // traverse |
| if ( pOld && !Ivy_ObjIsConst1(pOld) ) |
| Ivy_FraigSetActivityFactors_rec( p, pOld, LevelMin, LevelMax ); |
| if ( pNew && !Ivy_ObjIsConst1(pNew) ) |
| Ivy_FraigSetActivityFactors_rec( p, pNew, LevelMin, LevelMax ); |
| //Ivy_FraigPrintActivity( p ); |
| p->timeTrav += Abc_Clock() - clk; |
| return 1; |
| } |
| |
| ABC_NAMESPACE_IMPL_END |
| |
| #ifdef ABC_USE_CUDD |
| #include "bdd/cudd/cuddInt.h" |
| #endif |
| |
| ABC_NAMESPACE_IMPL_START |
| |
| #ifdef ABC_USE_CUDD |
| |
| /**Function************************************************************* |
| |
| Synopsis [Checks equivalence using BDDs.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| DdNode * Ivy_FraigNodesAreEquivBdd_int( DdManager * dd, DdNode * bFunc, Vec_Ptr_t * vFront, int Level ) |
| { |
| DdNode ** pFuncs; |
| DdNode * bFuncNew; |
| Vec_Ptr_t * vTemp; |
| Ivy_Obj_t * pObj, * pFanin; |
| int i, NewSize; |
| // create new frontier |
| vTemp = Vec_PtrAlloc( 100 ); |
| Vec_PtrForEachEntry( Ivy_Obj_t *, vFront, pObj, i ) |
| { |
| if ( (int)pObj->Level != Level ) |
| { |
| pObj->fMarkB = 1; |
| pObj->TravId = Vec_PtrSize(vTemp); |
| Vec_PtrPush( vTemp, pObj ); |
| continue; |
| } |
| |
| pFanin = Ivy_ObjFanin0(pObj); |
| if ( pFanin->fMarkB == 0 ) |
| { |
| pFanin->fMarkB = 1; |
| pFanin->TravId = Vec_PtrSize(vTemp); |
| Vec_PtrPush( vTemp, pFanin ); |
| } |
| |
| pFanin = Ivy_ObjFanin1(pObj); |
| if ( pFanin->fMarkB == 0 ) |
| { |
| pFanin->fMarkB = 1; |
| pFanin->TravId = Vec_PtrSize(vTemp); |
| Vec_PtrPush( vTemp, pFanin ); |
| } |
| } |
| // collect the permutation |
| NewSize = IVY_MAX(dd->size, Vec_PtrSize(vTemp)); |
| pFuncs = ABC_ALLOC( DdNode *, NewSize ); |
| Vec_PtrForEachEntry( Ivy_Obj_t *, vFront, pObj, i ) |
| { |
| if ( (int)pObj->Level != Level ) |
| pFuncs[i] = Cudd_bddIthVar( dd, pObj->TravId ); |
| else |
| pFuncs[i] = Cudd_bddAnd( dd, |
| Cudd_NotCond( Cudd_bddIthVar(dd, Ivy_ObjFanin0(pObj)->TravId), Ivy_ObjFaninC0(pObj) ), |
| Cudd_NotCond( Cudd_bddIthVar(dd, Ivy_ObjFanin1(pObj)->TravId), Ivy_ObjFaninC1(pObj) ) ); |
| Cudd_Ref( pFuncs[i] ); |
| } |
| // add the remaining vars |
| assert( NewSize == dd->size ); |
| for ( i = Vec_PtrSize(vFront); i < dd->size; i++ ) |
| { |
| pFuncs[i] = Cudd_bddIthVar( dd, i ); |
| Cudd_Ref( pFuncs[i] ); |
| } |
| |
| // create new |
| bFuncNew = Cudd_bddVectorCompose( dd, bFunc, pFuncs ); Cudd_Ref( bFuncNew ); |
| // clean trav Id |
| Vec_PtrForEachEntry( Ivy_Obj_t *, vTemp, pObj, i ) |
| { |
| pObj->fMarkB = 0; |
| pObj->TravId = 0; |
| } |
| // deref |
| for ( i = 0; i < dd->size; i++ ) |
| Cudd_RecursiveDeref( dd, pFuncs[i] ); |
| ABC_FREE( pFuncs ); |
| |
| ABC_FREE( vFront->pArray ); |
| *vFront = *vTemp; |
| |
| vTemp->nCap = vTemp->nSize = 0; |
| vTemp->pArray = NULL; |
| Vec_PtrFree( vTemp ); |
| |
| Cudd_Deref( bFuncNew ); |
| return bFuncNew; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Checks equivalence using BDDs.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Ivy_FraigNodesAreEquivBdd( Ivy_Obj_t * pObj1, Ivy_Obj_t * pObj2 ) |
| { |
| static DdManager * dd = NULL; |
| DdNode * bFunc, * bTemp; |
| Vec_Ptr_t * vFront; |
| Ivy_Obj_t * pObj; |
| int i, RetValue, Iter, Level; |
| // start the manager |
| if ( dd == NULL ) |
| dd = Cudd_Init( 50, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); |
| // create front |
| vFront = Vec_PtrAlloc( 100 ); |
| Vec_PtrPush( vFront, pObj1 ); |
| Vec_PtrPush( vFront, pObj2 ); |
| // get the function |
| bFunc = Cudd_bddXor( dd, Cudd_bddIthVar(dd,0), Cudd_bddIthVar(dd,1) ); Cudd_Ref( bFunc ); |
| bFunc = Cudd_NotCond( bFunc, pObj1->fPhase != pObj2->fPhase ); |
| // try running BDDs |
| for ( Iter = 0; ; Iter++ ) |
| { |
| // find max level |
| Level = 0; |
| Vec_PtrForEachEntry( Ivy_Obj_t *, vFront, pObj, i ) |
| if ( Level < (int)pObj->Level ) |
| Level = (int)pObj->Level; |
| if ( Level == 0 ) |
| break; |
| bFunc = Ivy_FraigNodesAreEquivBdd_int( dd, bTemp = bFunc, vFront, Level ); Cudd_Ref( bFunc ); |
| Cudd_RecursiveDeref( dd, bTemp ); |
| if ( bFunc == Cudd_ReadLogicZero(dd) ) // proved |
| {printf( "%d", Iter ); break;} |
| if ( Cudd_DagSize(bFunc) > 1000 ) |
| {printf( "b" ); break;} |
| if ( dd->size > 120 ) |
| {printf( "s" ); break;} |
| if ( Iter > 50 ) |
| {printf( "i" ); break;} |
| } |
| if ( bFunc == Cudd_ReadLogicZero(dd) ) // unsat |
| RetValue = 1; |
| else if ( Level == 0 ) // sat |
| RetValue = 0; |
| else |
| RetValue = -1; // spaceout/timeout |
| Cudd_RecursiveDeref( dd, bFunc ); |
| Vec_PtrFree( vFront ); |
| return RetValue; |
| } |
| #endif |
| |
| ABC_NAMESPACE_IMPL_END |
| |
| #include "aig/aig/aig.h" |
| |
| ABC_NAMESPACE_IMPL_START |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [Computes truth table of the cut.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Ivy_FraigExtractCone_rec( Ivy_Man_t * p, Ivy_Obj_t * pNode, Vec_Int_t * vLeaves, Vec_Int_t * vNodes ) |
| { |
| if ( pNode->fMarkB ) |
| return; |
| pNode->fMarkB = 1; |
| if ( Ivy_ObjIsPi(pNode) ) |
| { |
| Vec_IntPush( vLeaves, pNode->Id ); |
| return; |
| } |
| assert( Ivy_ObjIsAnd(pNode) ); |
| Ivy_FraigExtractCone_rec( p, Ivy_ObjFanin0(pNode), vLeaves, vNodes ); |
| Ivy_FraigExtractCone_rec( p, Ivy_ObjFanin1(pNode), vLeaves, vNodes ); |
| Vec_IntPush( vNodes, pNode->Id ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Checks equivalence using BDDs.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Aig_Man_t * Ivy_FraigExtractCone( Ivy_Man_t * p, Ivy_Obj_t * pObj1, Ivy_Obj_t * pObj2, Vec_Int_t * vLeaves ) |
| { |
| Aig_Man_t * pMan; |
| Aig_Obj_t * pMiter; |
| Vec_Int_t * vNodes; |
| Ivy_Obj_t * pObjIvy; |
| int i; |
| // collect nodes |
| vNodes = Vec_IntAlloc( 100 ); |
| Ivy_ManConst1(p)->fMarkB = 1; |
| Ivy_FraigExtractCone_rec( p, pObj1, vLeaves, vNodes ); |
| Ivy_FraigExtractCone_rec( p, pObj2, vLeaves, vNodes ); |
| Ivy_ManConst1(p)->fMarkB = 0; |
| // create new manager |
| pMan = Aig_ManStart( 1000 ); |
| Ivy_ManConst1(p)->pEquiv = (Ivy_Obj_t *)Aig_ManConst1(pMan); |
| Ivy_ManForEachNodeVec( p, vLeaves, pObjIvy, i ) |
| { |
| pObjIvy->pEquiv = (Ivy_Obj_t *)Aig_ObjCreateCi( pMan ); |
| pObjIvy->fMarkB = 0; |
| } |
| // duplicate internal nodes |
| Ivy_ManForEachNodeVec( p, vNodes, pObjIvy, i ) |
| { |
| |
| pObjIvy->pEquiv = (Ivy_Obj_t *)Aig_And( pMan, (Aig_Obj_t *)Ivy_ObjChild0Equiv(pObjIvy), (Aig_Obj_t *)Ivy_ObjChild1Equiv(pObjIvy) ); |
| pObjIvy->fMarkB = 0; |
| |
| pMiter = (Aig_Obj_t *)pObjIvy->pEquiv; |
| assert( pMiter->fPhase == pObjIvy->fPhase ); |
| } |
| // create the PO |
| pMiter = Aig_Exor( pMan, (Aig_Obj_t *)pObj1->pEquiv, (Aig_Obj_t *)pObj2->pEquiv ); |
| pMiter = Aig_NotCond( pMiter, Aig_Regular(pMiter)->fPhase ^ Aig_IsComplement(pMiter) ); |
| |
| /* |
| printf( "Polarity = %d\n", pMiter->fPhase ); |
| if ( Ivy_ObjIsConst1(pObj1) || Ivy_ObjIsConst1(pObj2) ) |
| { |
| pMiter = Aig_NotCond( pMiter, 1 ); |
| printf( "***************\n" ); |
| } |
| */ |
| pMiter = Aig_ObjCreateCo( pMan, pMiter ); |
| //printf( "Polarity = %d\n", pMiter->fPhase ); |
| Aig_ManCleanup( pMan ); |
| Vec_IntFree( vNodes ); |
| return pMan; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Checks equivalence using BDDs.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Ivy_FraigCheckCone( Ivy_FraigMan_t * pGlo, Ivy_Man_t * p, Ivy_Obj_t * pObj1, Ivy_Obj_t * pObj2, int nConfLimit ) |
| { |
| extern int Fra_FraigSat( Aig_Man_t * pMan, ABC_INT64_T nConfLimit, ABC_INT64_T nInsLimit, int nLearnedStart, int nLearnedDelta, int nLearnedPerce, int fFlipBits, int fAndOuts, int fNewSolver, int fVerbose ); |
| Vec_Int_t * vLeaves; |
| Aig_Man_t * pMan; |
| Aig_Obj_t * pObj; |
| int i, RetValue; |
| vLeaves = Vec_IntAlloc( 100 ); |
| pMan = Ivy_FraigExtractCone( p, pObj1, pObj2, vLeaves ); |
| RetValue = Fra_FraigSat( pMan, nConfLimit, 0, 0, 0, 0, 0, 0, 0, 1 ); |
| if ( RetValue == 0 ) |
| { |
| int Counter = 0; |
| memset( pGlo->pPatWords, 0, sizeof(unsigned) * pGlo->nPatWords ); |
| Aig_ManForEachCi( pMan, pObj, i ) |
| if ( ((int *)pMan->pData)[i] ) |
| { |
| int iObjIvy = Vec_IntEntry( vLeaves, i ); |
| assert( iObjIvy > 0 && iObjIvy <= Ivy_ManPiNum(p) ); |
| Ivy_InfoSetBit( pGlo->pPatWords, iObjIvy-1 ); |
| //printf( "%d ", iObjIvy ); |
| Counter++; |
| } |
| assert( Counter > 0 ); |
| } |
| Vec_IntFree( vLeaves ); |
| if ( RetValue == 1 ) |
| printf( "UNSAT\n" ); |
| else if ( RetValue == 0 ) |
| printf( "SAT\n" ); |
| else if ( RetValue == -1 ) |
| printf( "UNDEC\n" ); |
| |
| // p->pModel = (int *)pMan->pData, pMan2->pData = NULL; |
| Aig_ManStop( pMan ); |
| return RetValue; |
| } |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// END OF FILE /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| |
| ABC_NAMESPACE_IMPL_END |
| |