/**CFile**************************************************************** FileName [fraigNode.c] PackageName [FRAIG: Functionally reduced AND-INV graphs.] Synopsis [Implementation of the FRAIG node.] Author [Alan Mishchenko ] Affiliation [UC Berkeley] Date [Ver. 2.0. Started - October 1, 2004] Revision [$Id: fraigNode.c,v 1.3 2005/07/08 01:01:32 alanmi Exp $] ***********************************************************************/ #include "fraigInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // returns the complemented attribute of the node #define Fraig_NodeIsSimComplement(p) (Fraig_IsComplement(p)? !(Fraig_Regular(p)->fInv) : (p)->fInv) //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**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 [Creates a primary input node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fraig_Node_t * Fraig_NodeCreatePi( Fraig_Man_t * p ) { Fraig_Node_t * pNode, * pNodeRes; int i; abctime 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 = Abc_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 += Abc_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 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; abctime 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 + Abc_MaxInt(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 = Abc_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 += Abc_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 [Simulates the node.] Description [Simulates the random or dynamic simulation info through the node. Uses phases of the children to determine their real simulation info. Uses phase of the node to determine the way its simulation info is stored. The resulting info is guaranteed to be 0 for the first pattern.] SideEffects [This procedure modified the hash value of the simulation info.] SeeAlso [] ***********************************************************************/ void Fraig_NodeSimulate( Fraig_Node_t * pNode, int iWordStart, int iWordStop, int fUseRand ) { unsigned * pSims, * pSims1, * pSims2; unsigned uHash; int fCompl, fCompl1, fCompl2, i; assert( !Fraig_IsComplement(pNode) ); // get hold of the simulation information pSims = fUseRand? pNode->puSimR : pNode->puSimD; pSims1 = fUseRand? Fraig_Regular(pNode->p1)->puSimR : Fraig_Regular(pNode->p1)->puSimD; pSims2 = fUseRand? Fraig_Regular(pNode->p2)->puSimR : Fraig_Regular(pNode->p2)->puSimD; // get complemented attributes of the children using their random info fCompl = pNode->fInv; fCompl1 = Fraig_NodeIsSimComplement(pNode->p1); fCompl2 = Fraig_NodeIsSimComplement(pNode->p2); // simulate uHash = 0; if ( fCompl1 && fCompl2 ) { if ( fCompl ) for ( i = iWordStart; i < iWordStop; i++ ) { pSims[i] = (pSims1[i] | pSims2[i]); uHash ^= pSims[i] * s_FraigPrimes[i]; } else for ( i = iWordStart; i < iWordStop; i++ ) { pSims[i] = ~(pSims1[i] | pSims2[i]); uHash ^= pSims[i] * s_FraigPrimes[i]; } } else if ( fCompl1 && !fCompl2 ) { if ( fCompl ) for ( i = iWordStart; i < iWordStop; i++ ) { pSims[i] = (pSims1[i] | ~pSims2[i]); uHash ^= pSims[i] * s_FraigPrimes[i]; } else for ( i = iWordStart; i < iWordStop; i++ ) { pSims[i] = (~pSims1[i] & pSims2[i]); uHash ^= pSims[i] * s_FraigPrimes[i]; } } else if ( !fCompl1 && fCompl2 ) { if ( fCompl ) for ( i = iWordStart; i < iWordStop; i++ ) { pSims[i] = (~pSims1[i] | pSims2[i]); uHash ^= pSims[i] * s_FraigPrimes[i]; } else for ( i = iWordStart; i < iWordStop; i++ ) { pSims[i] = (pSims1[i] & ~pSims2[i]); uHash ^= pSims[i] * s_FraigPrimes[i]; } } else // if ( !fCompl1 && !fCompl2 ) { if ( fCompl ) for ( i = iWordStart; i < iWordStop; i++ ) { pSims[i] = ~(pSims1[i] & pSims2[i]); uHash ^= pSims[i] * s_FraigPrimes[i]; } else for ( i = iWordStart; i < iWordStop; i++ ) { pSims[i] = (pSims1[i] & pSims2[i]); uHash ^= pSims[i] * s_FraigPrimes[i]; } } if ( fUseRand ) pNode->uHashR ^= uHash; else pNode->uHashD ^= uHash; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END