/**Function************************************************************* Synopsis [Creates a primary input node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fraig_Node_t * Fraig_NodeCreatePi( Fraig_Man_t * p ) { Fraig_Node_t * pNode, * pNodeRes; int i, clk; // create the node pNode = (Fraig_Node_t *)Fraig_MemFixedEntryFetch( p->mmNodes ); memset( pNode, 0, sizeof(Fraig_Node_t) ); pNode->puSimR = (unsigned *)Fraig_MemFixedEntryFetch( p->mmSims ); pNode->puSimD = pNode->puSimR + p->nWordsRand; memset( pNode->puSimD, 0, sizeof(unsigned) * p->nWordsDyna ); // assign the number and add to the array of nodes pNode->Num = p->vNodes->nSize; Fraig_NodeVecPush( p->vNodes, pNode ); // assign the PI number and add to the array of primary inputs pNode->NumPi = p->vInputs->nSize; Fraig_NodeVecPush( p->vInputs, pNode ); pNode->Level = 0; // PI has 0 level pNode->nRefs = 1; // it is a persistent node, which comes referenced pNode->fInv = 0; // the simulation info of the PI is not complemented // derive the simulation info for the new node clk = clock(); // set the random simulation info for the primary input pNode->uHashR = 0; for ( i = 0; i < p->nWordsRand; i++ ) { // generate the simulation info pNode->puSimR[i] = FRAIG_RANDOM_UNSIGNED; // for reasons that take very long to explain, it makes sense to have (0000000...) // pattern in the set (this helps if we need to return the counter-examples) if ( i == 0 ) pNode->puSimR[i] <<= 1; // compute the hash key pNode->uHashR ^= pNode->puSimR[i] * s_FraigPrimes[i]; } // count the number of ones in the simulation vector pNode->nOnes = Fraig_BitStringCountOnes( pNode->puSimR, p->nWordsRand ); // set the systematic simulation info for the primary input pNode->uHashD = 0; for ( i = 0; i < p->iWordStart; i++ ) { // generate the simulation info pNode->puSimD[i] = FRAIG_RANDOM_UNSIGNED; // compute the hash key pNode->uHashD ^= pNode->puSimD[i] * s_FraigPrimes[i]; } p->timeSims += clock() - clk; // insert it into the hash table pNodeRes = Fraig_HashTableLookupF( p, pNode ); assert( pNodeRes == NULL ); // add to the runtime of simulation return pNode; }
/**Function************************************************************* Synopsis [Creates the constant 1 node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fraig_Node_t * Fraig_NodeCreateConst( Fraig_Man_t * p ) { Fraig_Node_t * pNode; // create the node pNode = (Fraig_Node_t *)Fraig_MemFixedEntryFetch( p->mmNodes ); memset( pNode, 0, sizeof(Fraig_Node_t) ); // assign the number and add to the array of nodes pNode->Num = p->vNodes->nSize; Fraig_NodeVecPush( p->vNodes, pNode ); pNode->NumPi = -1; // this is not a PI, so its number is -1 pNode->Level = 0; // just like a PI, it has 0 level pNode->nRefs = 1; // it is a persistent node, which comes referenced pNode->fInv = 1; // the simulation info is complemented // create the simulation info pNode->puSimR = (unsigned *)Fraig_MemFixedEntryFetch( p->mmSims ); pNode->puSimD = pNode->puSimR + p->nWordsRand; memset( pNode->puSimR, 0, sizeof(unsigned) * p->nWordsRand ); memset( pNode->puSimD, 0, sizeof(unsigned) * p->nWordsDyna ); // count the number of ones in the simulation vector pNode->nOnes = p->nWordsRand * sizeof(unsigned) * 8; // insert it into the hash table Fraig_HashTableLookupF0( p, pNode ); return pNode; }
/**Function************************************************************* Synopsis [Add the element while ensuring uniqueness.] Description [Returns 1 if the element was found, and 0 if it was new. ] SideEffects [] SeeAlso [] ***********************************************************************/ int Fraig_NodeVecPushUnique( Fraig_NodeVec_t * p, Fraig_Node_t * Entry ) { int i; for ( i = 0; i < p->nSize; i++ ) if ( p->pArray[i] == Entry ) return 1; Fraig_NodeVecPush( p, Entry ); return 0; }
/**Function************************************************************* Synopsis [Creates a new node.] Description [This procedure should be called to create the constant node and the PI nodes first.] SideEffects [] SeeAlso [] ***********************************************************************/ Fraig_Node_t * Fraig_NodeCreate( Fraig_Man_t * p, Fraig_Node_t * p1, Fraig_Node_t * p2 ) { Fraig_Node_t * pNode; int clk; // create the node pNode = (Fraig_Node_t *)Fraig_MemFixedEntryFetch( p->mmNodes ); memset( pNode, 0, sizeof(Fraig_Node_t) ); // assign the children pNode->p1 = p1; Fraig_Ref(p1); Fraig_Regular(p1)->nRefs++; pNode->p2 = p2; Fraig_Ref(p2); Fraig_Regular(p2)->nRefs++; // assign the number and add to the array of nodes pNode->Num = p->vNodes->nSize; Fraig_NodeVecPush( p->vNodes, pNode ); // assign the PI number pNode->NumPi = -1; // compute the level of this node pNode->Level = 1 + FRAIG_MAX(Fraig_Regular(p1)->Level, Fraig_Regular(p2)->Level); pNode->fInv = Fraig_NodeIsSimComplement(p1) & Fraig_NodeIsSimComplement(p2); pNode->fFailTfo = Fraig_Regular(p1)->fFailTfo | Fraig_Regular(p2)->fFailTfo; // derive the simulation info clk = clock(); // allocate memory for the simulation info pNode->puSimR = (unsigned *)Fraig_MemFixedEntryFetch( p->mmSims ); pNode->puSimD = pNode->puSimR + p->nWordsRand; // derive random simulation info pNode->uHashR = 0; Fraig_NodeSimulate( pNode, 0, p->nWordsRand, 1 ); // derive dynamic simulation info pNode->uHashD = 0; Fraig_NodeSimulate( pNode, 0, p->iWordStart, 0 ); // count the number of ones in the random simulation info pNode->nOnes = Fraig_BitStringCountOnes( pNode->puSimR, p->nWordsRand ); if ( pNode->fInv ) pNode->nOnes = p->nWordsRand * 32 - pNode->nOnes; // add to the runtime of simulation p->timeSims += clock() - clk; #ifdef FRAIG_ENABLE_FANOUTS // create the fanout info Fraig_NodeAddFaninFanout( Fraig_Regular(p1), pNode ); Fraig_NodeAddFaninFanout( Fraig_Regular(p2), pNode ); #endif return pNode; }
/**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 [Inserts a new node in the order by arrival times.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fraig_NodeVecPushOrderByLevel( Fraig_NodeVec_t * p, Fraig_Node_t * pNode ) { Fraig_Node_t * pNode1, * pNode2; int i; Fraig_NodeVecPush( p, pNode ); // find the p of the node for ( i = p->nSize-1; i > 0; i-- ) { pNode1 = p->pArray[i ]; pNode2 = p->pArray[i-1]; if ( Fraig_Regular(pNode1)->Level <= Fraig_Regular(pNode2)->Level ) break; p->pArray[i ] = pNode2; p->pArray[i-1] = pNode1; } }
/**Function************************************************************* Synopsis [Inserts a new node in the order by arrival times.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fraig_NodeVecPushOrder( Fraig_NodeVec_t * p, Fraig_Node_t * pNode ) { Fraig_Node_t * pNode1, * pNode2; int i; Fraig_NodeVecPush( p, pNode ); // find the p of the node for ( i = p->nSize-1; i > 0; i-- ) { pNode1 = p->pArray[i ]; pNode2 = p->pArray[i-1]; if ( pNode1 >= pNode2 ) break; p->pArray[i ] = pNode2; p->pArray[i-1] = pNode1; } }
/**Function************************************************************* Synopsis [Recursively computes the DFS ordering of the nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fraig_Dfs_rec( Fraig_Man_t * pMan, Fraig_Node_t * pNode, Fraig_NodeVec_t * vNodes, int fEquiv ) { assert( !Fraig_IsComplement(pNode) ); // skip the visited node if ( pNode->TravId == pMan->nTravIds ) return; pNode->TravId = pMan->nTravIds; // visit the transitive fanin if ( Fraig_NodeIsAnd(pNode) ) { Fraig_Dfs_rec( pMan, Fraig_Regular(pNode->p1), vNodes, fEquiv ); Fraig_Dfs_rec( pMan, Fraig_Regular(pNode->p2), vNodes, fEquiv ); } if ( fEquiv && pNode->pNextE ) Fraig_Dfs_rec( pMan, pNode->pNextE, vNodes, fEquiv ); // save the node Fraig_NodeVecPush( vNodes, pNode ); }
/**Function************************************************************* Synopsis [Creates a new PO node.] Description [This procedure may take a complemented node.] SideEffects [] SeeAlso [] ***********************************************************************/ void Fraig_ManSetPo( Fraig_Man_t * p, Fraig_Node_t * pNode ) { // internal node may be a PO two times Fraig_Regular(pNode)->fNodePo = 1; Fraig_NodeVecPush( p->vOutputs, pNode ); }