/**Function************************************************************* Synopsis [Returns the array of nodes to be combined into one multi-input AND-gate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fraig_NodeVec_t * Fraig_CollectSupergate( Fraig_Node_t * pNode, int fStopAtMux ) { Fraig_NodeVec_t * vSuper; vSuper = Fraig_NodeVecAlloc( 8 ); Fraig_CollectSupergate_rec( pNode, vSuper, 1, fStopAtMux ); return vSuper; }
/**Function************************************************************* Synopsis [Computes the DFS ordering of the nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fraig_NodeVec_t * Fraig_DfsOne( Fraig_Man_t * pMan, Fraig_Node_t * pNode, int fEquiv ) { Fraig_NodeVec_t * vNodes; pMan->nTravIds++; vNodes = Fraig_NodeVecAlloc( 100 ); Fraig_Dfs_rec( pMan, Fraig_Regular(pNode), vNodes, fEquiv ); return vNodes; }
/**Function************************************************************* Synopsis [Computes the DFS ordering of the nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fraig_NodeVec_t * Fraig_DfsNodes( Fraig_Man_t * pMan, Fraig_Node_t ** ppNodes, int nNodes, int fEquiv ) { Fraig_NodeVec_t * vNodes; int i; pMan->nTravIds++; vNodes = Fraig_NodeVecAlloc( 100 ); for ( i = 0; i < nNodes; i++ ) Fraig_Dfs_rec( pMan, Fraig_Regular(ppNodes[i]), vNodes, fEquiv ); return vNodes; }
/**Function************************************************************* Synopsis [Computes the DFS ordering of the nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fraig_NodeVec_t * Fraig_Dfs( Fraig_Man_t * pMan, int fEquiv ) { Fraig_NodeVec_t * vNodes; int i; pMan->nTravIds++; vNodes = Fraig_NodeVecAlloc( 100 ); for ( i = 0; i < pMan->vOutputs->nSize; i++ ) Fraig_Dfs_rec( pMan, Fraig_Regular(pMan->vOutputs->pArray[i]), vNodes, fEquiv ); return vNodes; }
/**Function************************************************************* Synopsis [Returns the array of nodes to be combined into one multi-input AND-gate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fraig_DetectFanoutFreeConeMux( Fraig_Man_t * pMan, Fraig_Node_t * pNode ) { Fraig_NodeVec_t * vFanins; Fraig_NodeVec_t * vInside; int nCubes; extern int Fraig_CutSopCountCubes( Fraig_Man_t * pMan, Fraig_NodeVec_t * vFanins, Fraig_NodeVec_t * vInside ); vFanins = Fraig_NodeVecAlloc( 8 ); vInside = Fraig_NodeVecAlloc( 8 ); Fraig_DetectFanoutFreeConeMux_rec( pNode, vFanins, vInside, 1 ); assert( vInside->pArray[vInside->nSize-1] == pNode ); // nCubes = Fraig_CutSopCountCubes( pMan, vFanins, vInside ); nCubes = 0; printf( "%d(%d)", vFanins->nSize, nCubes ); Fraig_NodeVecFree( vFanins ); Fraig_NodeVecFree( vInside ); }
/**Function************************************************************* Synopsis [Counts the number of EXOR type nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fraig_ManPrintRefs( Fraig_Man_t * pMan ) { Fraig_NodeVec_t * vPivots; Fraig_Node_t * pNode, * pNode2; int i, k, Counter, nProved; abctime clk; vPivots = Fraig_NodeVecAlloc( 1000 ); for ( i = 0; i < pMan->vNodes->nSize; i++ ) { pNode = pMan->vNodes->pArray[i]; if ( pNode->nOnes == 0 || pNode->nOnes == (unsigned)pMan->nWordsRand * 32 ) continue; if ( pNode->nRefs > 5 ) { Fraig_NodeVecPush( vPivots, pNode ); // printf( "Node %6d : nRefs = %2d Level = %3d.\n", pNode->Num, pNode->nRefs, pNode->Level ); } } printf( "Total nodes = %d. Referenced nodes = %d.\n", pMan->vNodes->nSize, vPivots->nSize ); clk = Abc_Clock(); // count implications Counter = nProved = 0; for ( i = 0; i < vPivots->nSize; i++ ) for ( k = i+1; k < vPivots->nSize; k++ ) { pNode = vPivots->pArray[i]; pNode2 = vPivots->pArray[k]; if ( Fraig_NodeSimsContained( pMan, pNode, pNode2 ) ) { if ( Fraig_NodeIsImplication( pMan, pNode, pNode2, -1 ) ) nProved++; Counter++; } else if ( Fraig_NodeSimsContained( pMan, pNode2, pNode ) ) { if ( Fraig_NodeIsImplication( pMan, pNode2, pNode, -1 ) ) nProved++; Counter++; } } printf( "Number of candidate pairs = %d. Proved = %d.\n", Counter, nProved ); //ABC_PRT( "Time", Abc_Clock() - clk ); return 0; }
/**Function************************************************************* Synopsis [Allocates simulation information for all nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fraig_NodeVec_t * Fraig_UtilInfoAlloc( int nSize, int nWords, bool fClean ) { Fraig_NodeVec_t * vInfo; unsigned * pUnsigned; int i; assert( nSize > 0 && nWords > 0 ); vInfo = Fraig_NodeVecAlloc( nSize ); pUnsigned = ALLOC( unsigned, nSize * nWords ); vInfo->pArray[0] = (Fraig_Node_t *)pUnsigned; if ( fClean ) memset( pUnsigned, 0, sizeof(unsigned) * nSize * nWords ); for ( i = 1; i < nSize; i++ ) vInfo->pArray[i] = (Fraig_Node_t *)(((unsigned *)vInfo->pArray[i-1]) + nWords); vInfo->nSize = nSize; return vInfo; }
/**Function************************************************************* Synopsis [Creates the new FRAIG manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fraig_Man_t * Fraig_ManCreate( Fraig_Params_t * pParams ) { Fraig_Params_t Params; Fraig_Man_t * p; // set the random seed for simulation // srand( 0xFEEDDEAF ); srand( 0xDEADCAFE ); // set parameters for equivalence checking if ( pParams == NULL ) Fraig_ParamsSetDefault( pParams = &Params ); // adjust the amount of simulation info if ( pParams->nPatsRand < 128 ) pParams->nPatsRand = 128; if ( pParams->nPatsRand > 32768 ) pParams->nPatsRand = 32768; if ( pParams->nPatsDyna < 128 ) pParams->nPatsDyna = 128; if ( pParams->nPatsDyna > 32768 ) pParams->nPatsDyna = 32768; // if reduction is not performed, allocate minimum simulation info if ( !pParams->fFuncRed ) pParams->nPatsRand = pParams->nPatsDyna = 128; // start the manager p = ALLOC( Fraig_Man_t, 1 ); memset( p, 0, sizeof(Fraig_Man_t) ); // set the default parameters p->nWordsRand = FRAIG_NUM_WORDS( pParams->nPatsRand ); // the number of words of random simulation info p->nWordsDyna = FRAIG_NUM_WORDS( pParams->nPatsDyna ); // the number of patterns for dynamic simulation info p->nBTLimit = pParams->nBTLimit; // -1 means infinite backtrack limit p->nSeconds = pParams->nSeconds; // the timeout for the final miter p->fFuncRed = pParams->fFuncRed; // enables functional reduction (otherwise, only one-level hashing is performed) p->fFeedBack = pParams->fFeedBack; // enables solver feedback (the use of counter-examples in simulation) p->fDist1Pats = pParams->fDist1Pats; // enables solver feedback (the use of counter-examples in simulation) p->fDoSparse = pParams->fDoSparse; // performs equivalence checking for sparse functions (whose sim-info is 0) p->fChoicing = pParams->fChoicing; // disable accumulation of structural choices (keeps only the first choice) p->fTryProve = pParams->fTryProve; // disable accumulation of structural choices (keeps only the first choice) p->fVerbose = pParams->fVerbose; // disable verbose output p->fVerboseP = pParams->fVerboseP; // disable verbose output p->nInspLimit = pParams->nInspLimit; // the limit on the number of inspections // start memory managers p->mmNodes = Fraig_MemFixedStart( sizeof(Fraig_Node_t) ); p->mmSims = Fraig_MemFixedStart( sizeof(unsigned) * (p->nWordsRand + p->nWordsDyna) ); // allocate node arrays p->vInputs = Fraig_NodeVecAlloc( 1000 ); // the array of primary inputs p->vOutputs = Fraig_NodeVecAlloc( 1000 ); // the array of primary outputs p->vNodes = Fraig_NodeVecAlloc( 1000 ); // the array of internal nodes // start the tables p->pTableS = Fraig_HashTableCreate( 1000 ); // hashing by structure p->pTableF = Fraig_HashTableCreate( 1000 ); // hashing by function p->pTableF0 = Fraig_HashTableCreate( 1000 ); // hashing by function (for sparse functions) // create the constant node p->pConst1 = Fraig_NodeCreateConst( p ); // initialize SAT solver feedback data structures Fraig_FeedBackInit( p ); // initialize other variables p->vProj = Msat_IntVecAlloc( 10 ); p->nTravIds = 1; p->nTravIds2 = 1; return p; }
/**Function************************************************************* Synopsis [Collect variables using their proximity from the nodes.] Description [This procedure creates a variable order based on collecting first the nodes that are the closest to the given two target nodes.] SideEffects [] SeeAlso [] ***********************************************************************/ void Fraig_OrderVariables( Fraig_Man_t * pMan, Fraig_Node_t * pOld, Fraig_Node_t * pNew ) { Fraig_Node_t * pNode, * pFanin; int i, k, Number, fUseMuxes = 1; int nVarsAlloc; assert( pOld != pNew ); assert( !Fraig_IsComplement(pOld) ); assert( !Fraig_IsComplement(pNew) ); pMan->nTravIds++; // clean the variables nVarsAlloc = Msat_IntVecReadSize(pMan->vVarsUsed); Msat_IntVecFill( pMan->vVarsUsed, nVarsAlloc, 0 ); Msat_IntVecClear( pMan->vVarsInt ); // add the first node Msat_IntVecPush( pMan->vVarsInt, pOld->Num ); Msat_IntVecWriteEntry( pMan->vVarsUsed, pOld->Num, 1 ); pOld->TravId = pMan->nTravIds; // add the second node Msat_IntVecPush( pMan->vVarsInt, pNew->Num ); Msat_IntVecWriteEntry( pMan->vVarsUsed, pNew->Num, 1 ); pNew->TravId = pMan->nTravIds; // create the variable order for ( i = 0; i < Msat_IntVecReadSize(pMan->vVarsInt); i++ ) { // get the new node on the frontier Number = Msat_IntVecReadEntry(pMan->vVarsInt, i); pNode = pMan->vNodes->pArray[Number]; if ( !Fraig_NodeIsAnd(pNode) ) continue; // if the node does not have fanins, create them if ( pNode->vFanins == NULL ) { // create the fanins of the supergate assert( pNode->fClauses == 0 ); // detecting a fanout-free cone (experiment only) // Fraig_DetectFanoutFreeCone( pMan, pNode ); if ( fUseMuxes && Fraig_NodeIsMuxType(pNode) ) { pNode->vFanins = Fraig_NodeVecAlloc( 4 ); Fraig_NodeVecPushUnique( pNode->vFanins, Fraig_Regular(Fraig_Regular(pNode->p1)->p1) ); Fraig_NodeVecPushUnique( pNode->vFanins, Fraig_Regular(Fraig_Regular(pNode->p1)->p2) ); Fraig_NodeVecPushUnique( pNode->vFanins, Fraig_Regular(Fraig_Regular(pNode->p2)->p1) ); Fraig_NodeVecPushUnique( pNode->vFanins, Fraig_Regular(Fraig_Regular(pNode->p2)->p2) ); Fraig_SupergateAddClausesMux( pMan, pNode ); // Fraig_DetectFanoutFreeConeMux( pMan, pNode ); nMuxes++; } else { pNode->vFanins = Fraig_CollectSupergate( pNode, fUseMuxes ); Fraig_SupergateAddClauses( pMan, pNode, pNode->vFanins ); } assert( pNode->vFanins->nSize > 1 ); pNode->fClauses = 1; pMan->nVarsClauses++; pNode->fMark2 = 1; // goes together with Fraig_SetupAdjacentMark() } // explore the implication fanins of pNode for ( k = 0; k < pNode->vFanins->nSize; k++ ) { pFanin = Fraig_Regular(pNode->vFanins->pArray[k]); if ( pFanin->TravId == pMan->nTravIds ) // already collected continue; // collect and mark Msat_IntVecPush( pMan->vVarsInt, pFanin->Num ); Msat_IntVecWriteEntry( pMan->vVarsUsed, pFanin->Num, 1 ); pFanin->TravId = pMan->nTravIds; } } // set up the adjacent variable information // Fraig_SetupAdjacent( pMan, pMan->vVarsInt ); Fraig_SetupAdjacentMark( pMan, pMan->vVarsInt ); }
/**Function************************************************************* Synopsis [Traverses the cone, collects the numbers and adds the clauses.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fraig_PrepareCones_rec( Fraig_Man_t * pMan, Fraig_Node_t * pNode ) { Fraig_Node_t * pFanin; Msat_IntVec_t * vAdjs; int fUseMuxes = 1, i; int fItIsTime; // skip if the node is aleady visited assert( !Fraig_IsComplement(pNode) ); if ( pNode->TravId == pMan->nTravIds ) return; pNode->TravId = pMan->nTravIds; // collect the node's number (closer to reverse topological order) Msat_IntVecPush( pMan->vVarsInt, pNode->Num ); Msat_IntVecWriteEntry( pMan->vVarsUsed, pNode->Num, 1 ); if ( !Fraig_NodeIsAnd( pNode ) ) return; // if the node does not have fanins, create them fItIsTime = 0; if ( pNode->vFanins == NULL ) { fItIsTime = 1; // create the fanins of the supergate assert( pNode->fClauses == 0 ); if ( fUseMuxes && Fraig_NodeIsMuxType(pNode) ) { pNode->vFanins = Fraig_NodeVecAlloc( 4 ); Fraig_NodeVecPushUnique( pNode->vFanins, Fraig_Regular(Fraig_Regular(pNode->p1)->p1) ); Fraig_NodeVecPushUnique( pNode->vFanins, Fraig_Regular(Fraig_Regular(pNode->p1)->p2) ); Fraig_NodeVecPushUnique( pNode->vFanins, Fraig_Regular(Fraig_Regular(pNode->p2)->p1) ); Fraig_NodeVecPushUnique( pNode->vFanins, Fraig_Regular(Fraig_Regular(pNode->p2)->p2) ); Fraig_SupergateAddClausesMux( pMan, pNode ); } else { pNode->vFanins = Fraig_CollectSupergate( pNode, fUseMuxes ); Fraig_SupergateAddClauses( pMan, pNode, pNode->vFanins ); } assert( pNode->vFanins->nSize > 1 ); pNode->fClauses = 1; pMan->nVarsClauses++; // add fanins vAdjs = (Msat_IntVec_t *)Msat_ClauseVecReadEntry( pMan->vAdjacents, pNode->Num ); assert( Msat_IntVecReadSize( vAdjs ) == 0 ); for ( i = 0; i < pNode->vFanins->nSize; i++ ) { pFanin = Fraig_Regular(pNode->vFanins->pArray[i]); Msat_IntVecPush( vAdjs, pFanin->Num ); } } // recursively visit the fanins for ( i = 0; i < pNode->vFanins->nSize; i++ ) Fraig_PrepareCones_rec( pMan, Fraig_Regular(pNode->vFanins->pArray[i]) ); if ( fItIsTime ) { // recursively visit the fanins for ( i = 0; i < pNode->vFanins->nSize; i++ ) { pFanin = Fraig_Regular(pNode->vFanins->pArray[i]); vAdjs = (Msat_IntVec_t *)Msat_ClauseVecReadEntry( pMan->vAdjacents, pFanin->Num ); Msat_IntVecPush( vAdjs, pNode->Num ); } } }