| /**CFile**************************************************************** |
| |
| FileName [fraigFeed.c] |
| |
| PackageName [FRAIG: Functionally reduced AND-INV graphs.] |
| |
| Synopsis [Procedures to support the solver feedback.] |
| |
| Author [Alan Mishchenko <alanmi@eecs.berkeley.edu>] |
| |
| Affiliation [UC Berkeley] |
| |
| Date [Ver. 2.0. Started - October 1, 2004] |
| |
| Revision [$Id: fraigFeed.c,v 1.8 2005/07/08 01:01:31 alanmi Exp $] |
| |
| ***********************************************************************/ |
| |
| #include "fraigInt.h" |
| |
| ABC_NAMESPACE_IMPL_START |
| |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// DECLARATIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| static int Fraig_FeedBackPrepare( Fraig_Man_t * p, int * pModel, Msat_IntVec_t * vVars ); |
| static int Fraig_FeedBackInsert( Fraig_Man_t * p, int nVarsPi ); |
| static void Fraig_FeedBackVerify( Fraig_Man_t * p, Fraig_Node_t * pOld, Fraig_Node_t * pNew ); |
| |
| static void Fraig_FeedBackCovering( Fraig_Man_t * p, Msat_IntVec_t * vPats ); |
| static Fraig_NodeVec_t * Fraig_FeedBackCoveringStart( Fraig_Man_t * pMan ); |
| static int Fraig_GetSmallestColumn( int * pHits, int nHits ); |
| static int Fraig_GetHittingPattern( unsigned * pSims, int nWords ); |
| static void Fraig_CancelCoveredColumns( Fraig_NodeVec_t * vColumns, int * pHits, int iPat ); |
| static void Fraig_FeedBackCheckTable( Fraig_Man_t * p ); |
| static void Fraig_FeedBackCheckTableF0( Fraig_Man_t * p ); |
| static void Fraig_ReallocateSimulationInfo( Fraig_Man_t * p ); |
| |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// FUNCTION DEFINITIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| /**Function************************************************************* |
| |
| Synopsis [Initializes the feedback information.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Fraig_FeedBackInit( Fraig_Man_t * p ) |
| { |
| p->vCones = Fraig_NodeVecAlloc( 500 ); |
| p->vPatsReal = Msat_IntVecAlloc( 1000 ); |
| p->pSimsReal = (unsigned *)Fraig_MemFixedEntryFetch( p->mmSims ); |
| memset( p->pSimsReal, 0, sizeof(unsigned) * p->nWordsDyna ); |
| p->pSimsTemp = (unsigned *)Fraig_MemFixedEntryFetch( p->mmSims ); |
| p->pSimsDiff = (unsigned *)Fraig_MemFixedEntryFetch( p->mmSims ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Processes the feedback from teh solver.] |
| |
| Description [Array pModel gives the value of each variable in the SAT |
| solver. Array vVars is the array of integer numbers of variables |
| involves in this conflict.] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Fraig_FeedBack( Fraig_Man_t * p, int * pModel, Msat_IntVec_t * vVars, Fraig_Node_t * pOld, Fraig_Node_t * pNew ) |
| { |
| int nVarsPi, nWords; |
| int i; |
| abctime clk = Abc_Clock(); |
| |
| // get the number of PI vars in the feedback (also sets the PI values) |
| nVarsPi = Fraig_FeedBackPrepare( p, pModel, vVars ); |
| |
| // set the PI values |
| nWords = Fraig_FeedBackInsert( p, nVarsPi ); |
| assert( p->iWordStart + nWords <= p->nWordsDyna ); |
| |
| // resimulates the words from p->iWordStart to iWordStop |
| for ( i = 1; i < p->vNodes->nSize; i++ ) |
| if ( Fraig_NodeIsAnd(p->vNodes->pArray[i]) ) |
| Fraig_NodeSimulate( p->vNodes->pArray[i], p->iWordStart, p->iWordStart + nWords, 0 ); |
| |
| if ( p->fDoSparse ) |
| Fraig_TableRehashF0( p, 0 ); |
| |
| if ( !p->fChoicing ) |
| Fraig_FeedBackVerify( p, pOld, pNew ); |
| |
| // if there is no room left, compress the patterns |
| if ( p->iWordStart + nWords == p->nWordsDyna ) |
| p->iWordStart = Fraig_FeedBackCompress( p ); |
| else // otherwise, update the starting word |
| p->iWordStart += nWords; |
| |
| p->timeFeed += Abc_Clock() - clk; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Get the number and values of the PI variables.] |
| |
| Description [Returns the number of PI variables involved in this feedback. |
| Fills in the internal presence and value data for the primary inputs.] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Fraig_FeedBackPrepare( Fraig_Man_t * p, int * pModel, Msat_IntVec_t * vVars ) |
| { |
| Fraig_Node_t * pNode; |
| int i, nVars, nVarsPis, * pVars; |
| |
| // clean the presence flag for all PIs |
| for ( i = 0; i < p->vInputs->nSize; i++ ) |
| { |
| pNode = p->vInputs->pArray[i]; |
| pNode->fFeedUse = 0; |
| } |
| |
| // get the variables involved in the feedback |
| nVars = Msat_IntVecReadSize(vVars); |
| pVars = Msat_IntVecReadArray(vVars); |
| |
| // set the values for the present variables |
| nVarsPis = 0; |
| for ( i = 0; i < nVars; i++ ) |
| { |
| pNode = p->vNodes->pArray[ pVars[i] ]; |
| if ( !Fraig_NodeIsVar(pNode) ) |
| continue; |
| // set its value |
| pNode->fFeedUse = 1; |
| pNode->fFeedVal = !MSAT_LITSIGN(pModel[pVars[i]]); |
| nVarsPis++; |
| } |
| return nVarsPis; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Inserts the new simulation patterns.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Fraig_FeedBackInsert( Fraig_Man_t * p, int nVarsPi ) |
| { |
| Fraig_Node_t * pNode; |
| int nWords, iPatFlip, nPatFlipLimit, i, w; |
| int fUseNoPats = 0; |
| int fUse2Pats = 0; |
| |
| // get the number of words |
| if ( fUse2Pats ) |
| nWords = FRAIG_NUM_WORDS( 2 * nVarsPi + 1 ); |
| else if ( fUseNoPats ) |
| nWords = 1; |
| else |
| nWords = FRAIG_NUM_WORDS( nVarsPi + 1 ); |
| // update the number of words if they do not fit into the simulation info |
| if ( nWords > p->nWordsDyna - p->iWordStart ) |
| nWords = p->nWordsDyna - p->iWordStart; |
| // determine the bound on the flipping bit |
| nPatFlipLimit = nWords * 32 - 2; |
| |
| // mark the real pattern |
| Msat_IntVecPush( p->vPatsReal, p->iWordStart * 32 ); |
| // record the real pattern |
| Fraig_BitStringSetBit( p->pSimsReal, p->iWordStart * 32 ); |
| |
| // set the values at the PIs |
| iPatFlip = 1; |
| for ( i = 0; i < p->vInputs->nSize; i++ ) |
| { |
| pNode = p->vInputs->pArray[i]; |
| for ( w = p->iWordStart; w < p->iWordStart + nWords; w++ ) |
| if ( !pNode->fFeedUse ) |
| pNode->puSimD[w] = FRAIG_RANDOM_UNSIGNED; |
| else if ( pNode->fFeedVal ) |
| pNode->puSimD[w] = FRAIG_FULL; |
| else // if ( !pNode->fFeedVal ) |
| pNode->puSimD[w] = 0; |
| |
| if ( fUse2Pats ) |
| { |
| // flip two patterns |
| if ( pNode->fFeedUse && 2 * iPatFlip < nPatFlipLimit ) |
| { |
| Fraig_BitStringXorBit( pNode->puSimD + p->iWordStart, 2 * iPatFlip - 1 ); |
| Fraig_BitStringXorBit( pNode->puSimD + p->iWordStart, 2 * iPatFlip ); |
| Fraig_BitStringXorBit( pNode->puSimD + p->iWordStart, 2 * iPatFlip + 1 ); |
| iPatFlip++; |
| } |
| } |
| else if ( fUseNoPats ) |
| { |
| } |
| else |
| { |
| // flip the diagonal |
| if ( pNode->fFeedUse && iPatFlip < nPatFlipLimit ) |
| { |
| Fraig_BitStringXorBit( pNode->puSimD + p->iWordStart, iPatFlip ); |
| iPatFlip++; |
| // Extra_PrintBinary( stdout, &pNode->puSimD, 45 ); printf( "\n" ); |
| } |
| } |
| // clean the use mask |
| pNode->fFeedUse = 0; |
| |
| // add the info to the D hash value of the PIs |
| for ( w = p->iWordStart; w < p->iWordStart + nWords; w++ ) |
| pNode->uHashD ^= pNode->puSimD[w] * s_FraigPrimes[w]; |
| |
| } |
| return nWords; |
| } |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [Checks that the SAT solver pattern indeed distinquishes the nodes.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Fraig_FeedBackVerify( Fraig_Man_t * p, Fraig_Node_t * pOld, Fraig_Node_t * pNew ) |
| { |
| int fValue1, fValue2, iPat; |
| iPat = Msat_IntVecReadEntry( p->vPatsReal, Msat_IntVecReadSize(p->vPatsReal)-1 ); |
| fValue1 = (Fraig_BitStringHasBit( pOld->puSimD, iPat )); |
| fValue2 = (Fraig_BitStringHasBit( pNew->puSimD, iPat )); |
| /* |
| Fraig_PrintNode( p, pOld ); |
| printf( "\n" ); |
| Fraig_PrintNode( p, pNew ); |
| printf( "\n" ); |
| */ |
| // assert( fValue1 != fValue2 ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Compress the simulation patterns.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Fraig_FeedBackCompress( Fraig_Man_t * p ) |
| { |
| unsigned * pSims; |
| unsigned uHash; |
| int i, w, t, nPats, * pPats; |
| int fPerformChecks = (p->nBTLimit == -1); |
| |
| // solve the covering problem |
| if ( fPerformChecks ) |
| { |
| Fraig_FeedBackCheckTable( p ); |
| if ( p->fDoSparse ) |
| Fraig_FeedBackCheckTableF0( p ); |
| } |
| |
| // solve the covering problem |
| Fraig_FeedBackCovering( p, p->vPatsReal ); |
| |
| |
| // get the number of additional patterns |
| nPats = Msat_IntVecReadSize( p->vPatsReal ); |
| pPats = Msat_IntVecReadArray( p->vPatsReal ); |
| // get the new starting word |
| p->iWordStart = FRAIG_NUM_WORDS( p->iPatsPerm + nPats ); |
| |
| // set the simulation info for the PIs |
| for ( i = 0; i < p->vInputs->nSize; i++ ) |
| { |
| // get hold of the simulation info for this PI |
| pSims = p->vInputs->pArray[i]->puSimD; |
| // clean the storage for the new patterns |
| for ( w = p->iWordPerm; w < p->iWordStart; w++ ) |
| p->pSimsTemp[w] = 0; |
| // set the patterns |
| for ( t = 0; t < nPats; t++ ) |
| if ( Fraig_BitStringHasBit( pSims, pPats[t] ) ) |
| { |
| // check if this pattern falls into temporary storage |
| if ( p->iPatsPerm + t < p->iWordPerm * 32 ) |
| Fraig_BitStringSetBit( pSims, p->iPatsPerm + t ); |
| else |
| Fraig_BitStringSetBit( p->pSimsTemp, p->iPatsPerm + t ); |
| } |
| // copy the pattern |
| for ( w = p->iWordPerm; w < p->iWordStart; w++ ) |
| pSims[w] = p->pSimsTemp[w]; |
| // recompute the hashing info |
| uHash = 0; |
| for ( w = 0; w < p->iWordStart; w++ ) |
| uHash ^= pSims[w] * s_FraigPrimes[w]; |
| p->vInputs->pArray[i]->uHashD = uHash; |
| } |
| |
| // update info about the permanently stored patterns |
| p->iWordPerm = p->iWordStart; |
| p->iPatsPerm += nPats; |
| assert( p->iWordPerm == FRAIG_NUM_WORDS( p->iPatsPerm ) ); |
| |
| // resimulate and recompute the hash values |
| for ( i = 1; i < p->vNodes->nSize; i++ ) |
| if ( Fraig_NodeIsAnd(p->vNodes->pArray[i]) ) |
| { |
| p->vNodes->pArray[i]->uHashD = 0; |
| Fraig_NodeSimulate( p->vNodes->pArray[i], 0, p->iWordPerm, 0 ); |
| } |
| |
| // double-check that the nodes are still distinguished |
| if ( fPerformChecks ) |
| Fraig_FeedBackCheckTable( p ); |
| |
| // rehash the values in the F0 table |
| if ( p->fDoSparse ) |
| { |
| Fraig_TableRehashF0( p, 0 ); |
| if ( fPerformChecks ) |
| Fraig_FeedBackCheckTableF0( p ); |
| } |
| |
| // check if we need to resize the simulation info |
| // if less than FRAIG_WORDS_STORE words are left, reallocate simulation info |
| if ( p->iWordPerm + FRAIG_WORDS_STORE > p->nWordsDyna ) |
| Fraig_ReallocateSimulationInfo( p ); |
| |
| // set the real patterns |
| Msat_IntVecClear( p->vPatsReal ); |
| memset( p->pSimsReal, 0, sizeof(unsigned)*p->nWordsDyna ); |
| for ( w = 0; w < p->iWordPerm; w++ ) |
| p->pSimsReal[w] = FRAIG_FULL; |
| if ( p->iPatsPerm % 32 > 0 ) |
| p->pSimsReal[p->iWordPerm-1] = FRAIG_MASK( p->iPatsPerm % 32 ); |
| // printf( "The number of permanent words = %d.\n", p->iWordPerm ); |
| return p->iWordStart; |
| } |
| |
| |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [Checks the correctness of the functional simulation table.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Fraig_FeedBackCovering( Fraig_Man_t * p, Msat_IntVec_t * vPats ) |
| { |
| Fraig_NodeVec_t * vColumns; |
| unsigned * pSims; |
| int * pHits, iPat, iCol, i; |
| int nOnesTotal, nSolStarting; |
| int fVeryVerbose = 0; |
| |
| // collect the pairs to be distinguished |
| vColumns = Fraig_FeedBackCoveringStart( p ); |
| // collect the number of 1s in each simulation vector |
| nOnesTotal = 0; |
| pHits = ABC_ALLOC( int, vColumns->nSize ); |
| for ( i = 0; i < vColumns->nSize; i++ ) |
| { |
| pSims = (unsigned *)vColumns->pArray[i]; |
| pHits[i] = Fraig_BitStringCountOnes( pSims, p->iWordStart ); |
| nOnesTotal += pHits[i]; |
| // assert( pHits[i] > 0 ); |
| } |
| |
| // go through the patterns |
| nSolStarting = Msat_IntVecReadSize(vPats); |
| while ( (iCol = Fraig_GetSmallestColumn( pHits, vColumns->nSize )) != -1 ) |
| { |
| // find the pattern, which hits this column |
| iPat = Fraig_GetHittingPattern( (unsigned *)vColumns->pArray[iCol], p->iWordStart ); |
| // cancel the columns covered by this pattern |
| Fraig_CancelCoveredColumns( vColumns, pHits, iPat ); |
| // save the pattern |
| Msat_IntVecPush( vPats, iPat ); |
| } |
| |
| // free the set of columns |
| for ( i = 0; i < vColumns->nSize; i++ ) |
| Fraig_MemFixedEntryRecycle( p->mmSims, (char *)vColumns->pArray[i] ); |
| |
| // print stats related to the covering problem |
| if ( p->fVerbose && fVeryVerbose ) |
| { |
| printf( "%3d\\%3d\\%3d ", p->nWordsRand, p->nWordsDyna, p->iWordPerm ); |
| printf( "Col (pairs) = %5d. ", vColumns->nSize ); |
| printf( "Row (pats) = %5d. ", p->iWordStart * 32 ); |
| printf( "Dns = %6.2f %%. ", vColumns->nSize==0? 0.0 : 100.0 * nOnesTotal / vColumns->nSize / p->iWordStart / 32 ); |
| printf( "Sol = %3d (%3d). ", Msat_IntVecReadSize(vPats), nSolStarting ); |
| printf( "\n" ); |
| } |
| Fraig_NodeVecFree( vColumns ); |
| ABC_FREE( pHits ); |
| } |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [Checks the correctness of the functional simulation table.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Fraig_NodeVec_t * Fraig_FeedBackCoveringStart( Fraig_Man_t * p ) |
| { |
| Fraig_NodeVec_t * vColumns; |
| Fraig_HashTable_t * pT = p->pTableF; |
| Fraig_Node_t * pEntF, * pEntD; |
| unsigned * pSims; |
| unsigned * pUnsigned1, * pUnsigned2; |
| int i, k, m, w;//, nOnes; |
| |
| // start the set of columns |
| vColumns = Fraig_NodeVecAlloc( 100 ); |
| |
| // go through the pairs of nodes to be distinguished |
| for ( i = 0; i < pT->nBins; i++ ) |
| Fraig_TableBinForEachEntryF( pT->pBins[i], pEntF ) |
| { |
| p->vCones->nSize = 0; |
| Fraig_TableBinForEachEntryD( pEntF, pEntD ) |
| Fraig_NodeVecPush( p->vCones, pEntD ); |
| if ( p->vCones->nSize == 1 ) |
| continue; |
| //////////////////////////////// bug fix by alanmi, September 14, 2006 |
| if ( p->vCones->nSize > 20 ) |
| continue; |
| //////////////////////////////// |
| |
| for ( k = 0; k < p->vCones->nSize; k++ ) |
| for ( m = k+1; m < p->vCones->nSize; m++ ) |
| { |
| if ( !Fraig_CompareSimInfoUnderMask( p->vCones->pArray[k], p->vCones->pArray[m], p->iWordStart, 0, p->pSimsReal ) ) |
| continue; |
| |
| // primary simulation patterns (counter-examples) cannot distinguish this pair |
| // get memory to store the feasible simulation patterns |
| pSims = (unsigned *)Fraig_MemFixedEntryFetch( p->mmSims ); |
| // find the pattern that distinguish this column, exept the primary ones |
| pUnsigned1 = p->vCones->pArray[k]->puSimD; |
| pUnsigned2 = p->vCones->pArray[m]->puSimD; |
| for ( w = 0; w < p->iWordStart; w++ ) |
| pSims[w] = (pUnsigned1[w] ^ pUnsigned2[w]) & ~p->pSimsReal[w]; |
| // store the pattern |
| Fraig_NodeVecPush( vColumns, (Fraig_Node_t *)pSims ); |
| // nOnes = Fraig_BitStringCountOnes(pSims, p->iWordStart); |
| // assert( nOnes > 0 ); |
| } |
| } |
| |
| // if the flag is not set, do not consider sparse nodes in p->pTableF0 |
| if ( !p->fDoSparse ) |
| return vColumns; |
| |
| // recalculate their hash values based on p->pSimsReal |
| pT = p->pTableF0; |
| for ( i = 0; i < pT->nBins; i++ ) |
| Fraig_TableBinForEachEntryF( pT->pBins[i], pEntF ) |
| { |
| pSims = pEntF->puSimD; |
| pEntF->uHashD = 0; |
| for ( w = 0; w < p->iWordStart; w++ ) |
| pEntF->uHashD ^= (pSims[w] & p->pSimsReal[w]) * s_FraigPrimes[w]; |
| } |
| |
| // rehash the table using these values |
| Fraig_TableRehashF0( p, 1 ); |
| |
| // collect the classes of equivalent node pairs |
| for ( i = 0; i < pT->nBins; i++ ) |
| Fraig_TableBinForEachEntryF( pT->pBins[i], pEntF ) |
| { |
| p->vCones->nSize = 0; |
| Fraig_TableBinForEachEntryD( pEntF, pEntD ) |
| Fraig_NodeVecPush( p->vCones, pEntD ); |
| if ( p->vCones->nSize == 1 ) |
| continue; |
| |
| // primary simulation patterns (counter-examples) cannot distinguish all these pairs |
| for ( k = 0; k < p->vCones->nSize; k++ ) |
| for ( m = k+1; m < p->vCones->nSize; m++ ) |
| { |
| // get memory to store the feasible simulation patterns |
| pSims = (unsigned *)Fraig_MemFixedEntryFetch( p->mmSims ); |
| // find the patterns that are not distinquished |
| pUnsigned1 = p->vCones->pArray[k]->puSimD; |
| pUnsigned2 = p->vCones->pArray[m]->puSimD; |
| for ( w = 0; w < p->iWordStart; w++ ) |
| pSims[w] = (pUnsigned1[w] ^ pUnsigned2[w]) & ~p->pSimsReal[w]; |
| // store the pattern |
| Fraig_NodeVecPush( vColumns, (Fraig_Node_t *)pSims ); |
| // nOnes = Fraig_BitStringCountOnes(pSims, p->iWordStart); |
| // assert( nOnes > 0 ); |
| } |
| } |
| return vColumns; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Selects the column, which has the smallest number of hits.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Fraig_GetSmallestColumn( int * pHits, int nHits ) |
| { |
| int i, iColMin = -1, nHitsMin = 1000000; |
| for ( i = 0; i < nHits; i++ ) |
| { |
| // skip covered columns |
| if ( pHits[i] == 0 ) |
| continue; |
| // take the column if it can only be covered by one pattern |
| if ( pHits[i] == 1 ) |
| return i; |
| // find the column, which requires the smallest number of patterns |
| if ( nHitsMin > pHits[i] ) |
| { |
| nHitsMin = pHits[i]; |
| iColMin = i; |
| } |
| } |
| return iColMin; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Select the pattern, which hits this column.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Fraig_GetHittingPattern( unsigned * pSims, int nWords ) |
| { |
| int i, b; |
| for ( i = 0; i < nWords; i++ ) |
| { |
| if ( pSims[i] == 0 ) |
| continue; |
| for ( b = 0; b < 32; b++ ) |
| if ( pSims[i] & (1 << b) ) |
| return i * 32 + b; |
| } |
| return -1; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Cancel covered patterns.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Fraig_CancelCoveredColumns( Fraig_NodeVec_t * vColumns, int * pHits, int iPat ) |
| { |
| unsigned * pSims; |
| int i; |
| for ( i = 0; i < vColumns->nSize; i++ ) |
| { |
| pSims = (unsigned *)vColumns->pArray[i]; |
| if ( Fraig_BitStringHasBit( pSims, iPat ) ) |
| pHits[i] = 0; |
| } |
| } |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [Checks the correctness of the functional simulation table.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Fraig_FeedBackCheckTable( Fraig_Man_t * p ) |
| { |
| Fraig_HashTable_t * pT = p->pTableF; |
| Fraig_Node_t * pEntF, * pEntD; |
| int i, k, m, nPairs; |
| |
| nPairs = 0; |
| for ( i = 0; i < pT->nBins; i++ ) |
| Fraig_TableBinForEachEntryF( pT->pBins[i], pEntF ) |
| { |
| p->vCones->nSize = 0; |
| Fraig_TableBinForEachEntryD( pEntF, pEntD ) |
| Fraig_NodeVecPush( p->vCones, pEntD ); |
| if ( p->vCones->nSize == 1 ) |
| continue; |
| for ( k = 0; k < p->vCones->nSize; k++ ) |
| for ( m = k+1; m < p->vCones->nSize; m++ ) |
| { |
| if ( Fraig_CompareSimInfo( p->vCones->pArray[k], p->vCones->pArray[m], p->iWordStart, 0 ) ) |
| printf( "Nodes %d and %d have the same D simulation info.\n", |
| p->vCones->pArray[k]->Num, p->vCones->pArray[m]->Num ); |
| nPairs++; |
| } |
| } |
| // printf( "\nThe total of %d node pairs have been verified.\n", nPairs ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Checks the correctness of the functional simulation table.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Fraig_FeedBackCheckTableF0( Fraig_Man_t * p ) |
| { |
| Fraig_HashTable_t * pT = p->pTableF0; |
| Fraig_Node_t * pEntF; |
| int i, k, m, nPairs; |
| |
| nPairs = 0; |
| for ( i = 0; i < pT->nBins; i++ ) |
| { |
| p->vCones->nSize = 0; |
| Fraig_TableBinForEachEntryF( pT->pBins[i], pEntF ) |
| Fraig_NodeVecPush( p->vCones, pEntF ); |
| if ( p->vCones->nSize == 1 ) |
| continue; |
| for ( k = 0; k < p->vCones->nSize; k++ ) |
| for ( m = k+1; m < p->vCones->nSize; m++ ) |
| { |
| if ( Fraig_CompareSimInfo( p->vCones->pArray[k], p->vCones->pArray[m], p->iWordStart, 0 ) ) |
| printf( "Nodes %d and %d have the same D simulation info.\n", |
| p->vCones->pArray[k]->Num, p->vCones->pArray[m]->Num ); |
| nPairs++; |
| } |
| } |
| // printf( "\nThe total of %d node pairs have been verified.\n", nPairs ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Doubles the size of simulation info.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Fraig_ReallocateSimulationInfo( Fraig_Man_t * p ) |
| { |
| Fraig_MemFixed_t * mmSimsNew; // new memory manager for simulation info |
| Fraig_Node_t * pNode; |
| unsigned * pSimsNew; |
| unsigned uSignOld; |
| int i; |
| |
| // allocate a new memory manager |
| p->nWordsDyna *= 2; |
| mmSimsNew = Fraig_MemFixedStart( sizeof(unsigned) * (p->nWordsRand + p->nWordsDyna) ); |
| |
| // set the new data for the constant node |
| pNode = p->pConst1; |
| pNode->puSimR = (unsigned *)Fraig_MemFixedEntryFetch( mmSimsNew ); |
| pNode->puSimD = pNode->puSimR + p->nWordsRand; |
| memset( pNode->puSimR, 0, sizeof(unsigned) * p->nWordsRand ); |
| memset( pNode->puSimD, 0, sizeof(unsigned) * p->nWordsDyna ); |
| |
| // copy the simulation info of the PIs |
| for ( i = 0; i < p->vInputs->nSize; i++ ) |
| { |
| pNode = p->vInputs->pArray[i]; |
| // copy the simulation info |
| pSimsNew = (unsigned *)Fraig_MemFixedEntryFetch( mmSimsNew ); |
| memmove( pSimsNew, pNode->puSimR, sizeof(unsigned) * (p->nWordsRand + p->iWordStart) ); |
| // attach the new info |
| pNode->puSimR = pSimsNew; |
| pNode->puSimD = pNode->puSimR + p->nWordsRand; |
| // signatures remain without changes |
| } |
| |
| // replace the manager to free up some memory |
| Fraig_MemFixedStop( p->mmSims, 0 ); |
| p->mmSims = mmSimsNew; |
| |
| // resimulate the internal nodes (this should lead to the same signatures) |
| for ( i = 1; i < p->vNodes->nSize; i++ ) |
| { |
| pNode = p->vNodes->pArray[i]; |
| if ( !Fraig_NodeIsAnd(pNode) ) |
| continue; |
| // allocate memory for the simulation info |
| pNode->puSimR = (unsigned *)Fraig_MemFixedEntryFetch( mmSimsNew ); |
| pNode->puSimD = pNode->puSimR + p->nWordsRand; |
| // derive random simulation info |
| uSignOld = pNode->uHashR; |
| pNode->uHashR = 0; |
| Fraig_NodeSimulate( pNode, 0, p->nWordsRand, 1 ); |
| assert( uSignOld == pNode->uHashR ); |
| // derive dynamic simulation info |
| uSignOld = pNode->uHashD; |
| pNode->uHashD = 0; |
| Fraig_NodeSimulate( pNode, 0, p->iWordStart, 0 ); |
| assert( uSignOld == pNode->uHashD ); |
| } |
| |
| // realloc temporary storage |
| p->pSimsReal = (unsigned *)Fraig_MemFixedEntryFetch( mmSimsNew ); |
| memset( p->pSimsReal, 0, sizeof(unsigned) * p->nWordsDyna ); |
| p->pSimsTemp = (unsigned *)Fraig_MemFixedEntryFetch( mmSimsNew ); |
| p->pSimsDiff = (unsigned *)Fraig_MemFixedEntryFetch( mmSimsNew ); |
| } |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [Generated trivial counter example.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int * Fraig_ManAllocCounterExample( Fraig_Man_t * p ) |
| { |
| int * pModel; |
| pModel = ABC_ALLOC( int, p->vInputs->nSize ); |
| memset( pModel, 0, sizeof(int) * p->vInputs->nSize ); |
| return pModel; |
| } |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [Saves the counter example.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Fraig_ManSimulateBitNode_rec( Fraig_Man_t * p, Fraig_Node_t * pNode ) |
| { |
| int Value0, Value1; |
| if ( Fraig_NodeIsTravIdCurrent( p, pNode ) ) |
| return pNode->fMark3; |
| Fraig_NodeSetTravIdCurrent( p, pNode ); |
| Value0 = Fraig_ManSimulateBitNode_rec( p, Fraig_Regular(pNode->p1) ); |
| Value1 = Fraig_ManSimulateBitNode_rec( p, Fraig_Regular(pNode->p2) ); |
| Value0 ^= Fraig_IsComplement(pNode->p1); |
| Value1 ^= Fraig_IsComplement(pNode->p2); |
| pNode->fMark3 = Value0 & Value1; |
| return pNode->fMark3; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Simulates one bit.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Fraig_ManSimulateBitNode( Fraig_Man_t * p, Fraig_Node_t * pNode, int * pModel ) |
| { |
| int fCompl, RetValue, i; |
| // set the PI values |
| Fraig_ManIncrementTravId( p ); |
| for ( i = 0; i < p->vInputs->nSize; i++ ) |
| { |
| Fraig_NodeSetTravIdCurrent( p, p->vInputs->pArray[i] ); |
| p->vInputs->pArray[i]->fMark3 = pModel[i]; |
| } |
| // perform the traversal |
| fCompl = Fraig_IsComplement(pNode); |
| RetValue = Fraig_ManSimulateBitNode_rec( p, Fraig_Regular(pNode) ); |
| return fCompl ^ RetValue; |
| } |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [Saves the counter example.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int * Fraig_ManSaveCounterExample( Fraig_Man_t * p, Fraig_Node_t * pNode ) |
| { |
| int * pModel; |
| int iPattern; |
| int i, fCompl; |
| |
| // the node can be complemented |
| fCompl = Fraig_IsComplement(pNode); |
| // because we compare with constant 0, p->pConst1 should also be complemented |
| fCompl = !fCompl; |
| |
| // derive the model |
| pModel = Fraig_ManAllocCounterExample( p ); |
| iPattern = Fraig_FindFirstDiff( p->pConst1, Fraig_Regular(pNode), fCompl, p->nWordsRand, 1 ); |
| if ( iPattern >= 0 ) |
| { |
| for ( i = 0; i < p->vInputs->nSize; i++ ) |
| if ( Fraig_BitStringHasBit( p->vInputs->pArray[i]->puSimR, iPattern ) ) |
| pModel[i] = 1; |
| /* |
| printf( "SAT solver's pattern:\n" ); |
| for ( i = 0; i < p->vInputs->nSize; i++ ) |
| printf( "%d", pModel[i] ); |
| printf( "\n" ); |
| */ |
| assert( Fraig_ManSimulateBitNode( p, pNode, pModel ) ); |
| return pModel; |
| } |
| iPattern = Fraig_FindFirstDiff( p->pConst1, Fraig_Regular(pNode), fCompl, p->iWordStart, 0 ); |
| if ( iPattern >= 0 ) |
| { |
| for ( i = 0; i < p->vInputs->nSize; i++ ) |
| if ( Fraig_BitStringHasBit( p->vInputs->pArray[i]->puSimD, iPattern ) ) |
| pModel[i] = 1; |
| /* |
| printf( "SAT solver's pattern:\n" ); |
| for ( i = 0; i < p->vInputs->nSize; i++ ) |
| printf( "%d", pModel[i] ); |
| printf( "\n" ); |
| */ |
| assert( Fraig_ManSimulateBitNode( p, pNode, pModel ) ); |
| return pModel; |
| } |
| ABC_FREE( pModel ); |
| return NULL; |
| } |
| |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// END OF FILE /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| |
| ABC_NAMESPACE_IMPL_END |
| |