| /**CFile**************************************************************** |
| |
| FileName [cnfCut.c] |
| |
| SystemName [ABC: Logic synthesis and verification system.] |
| |
| PackageName [AIG-to-CNF conversion.] |
| |
| Synopsis [] |
| |
| Author [Alan Mishchenko] |
| |
| Affiliation [UC Berkeley] |
| |
| Date [Ver. 1.0. Started - April 28, 2007.] |
| |
| Revision [$Id: cnfCut.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] |
| |
| ***********************************************************************/ |
| |
| #include "cnf.h" |
| #include "bool/kit/kit.h" |
| |
| ABC_NAMESPACE_IMPL_START |
| |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// DECLARATIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// FUNCTION DEFINITIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| /**Function************************************************************* |
| |
| Synopsis [Allocates cut of the given size.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Cnf_Cut_t * Cnf_CutAlloc( Cnf_Man_t * p, int nLeaves ) |
| { |
| Cnf_Cut_t * pCut; |
| int nSize = sizeof(Cnf_Cut_t) + sizeof(int) * nLeaves + sizeof(unsigned) * Abc_TruthWordNum(nLeaves); |
| pCut = (Cnf_Cut_t *)Aig_MmFlexEntryFetch( p->pMemCuts, nSize ); |
| pCut->nFanins = nLeaves; |
| pCut->nWords = Abc_TruthWordNum(nLeaves); |
| pCut->vIsop[0] = pCut->vIsop[1] = NULL; |
| return pCut; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Deallocates cut.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Cnf_CutFree( Cnf_Cut_t * pCut ) |
| { |
| if ( pCut->vIsop[0] ) |
| Vec_IntFree( pCut->vIsop[0] ); |
| if ( pCut->vIsop[1] ) |
| Vec_IntFree( pCut->vIsop[1] ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Creates cut for the given node.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Cnf_Cut_t * Cnf_CutCreate( Cnf_Man_t * p, Aig_Obj_t * pObj ) |
| { |
| Dar_Cut_t * pCutBest; |
| Cnf_Cut_t * pCut; |
| unsigned * pTruth; |
| assert( Aig_ObjIsNode(pObj) ); |
| pCutBest = Dar_ObjBestCut( pObj ); |
| assert( pCutBest != NULL ); |
| assert( pCutBest->nLeaves <= 4 ); |
| pCut = Cnf_CutAlloc( p, pCutBest->nLeaves ); |
| memcpy( pCut->pFanins, pCutBest->pLeaves, sizeof(int) * pCutBest->nLeaves ); |
| pTruth = Cnf_CutTruth(pCut); |
| *pTruth = (pCutBest->uTruth << 16) | pCutBest->uTruth; |
| pCut->Cost = Cnf_CutSopCost( p, pCutBest ); |
| return pCut; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Deallocates cut.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Cnf_CutPrint( Cnf_Cut_t * pCut ) |
| { |
| int i; |
| printf( "{" ); |
| for ( i = 0; i < pCut->nFanins; i++ ) |
| printf( "%d ", pCut->pFanins[i] ); |
| printf( " } " ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Allocates cut of the given size.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Cnf_CutDeref( Cnf_Man_t * p, Cnf_Cut_t * pCut ) |
| { |
| Aig_Obj_t * pObj; |
| int i; |
| Cnf_CutForEachLeaf( p->pManAig, pCut, pObj, i ) |
| { |
| assert( pObj->nRefs > 0 ); |
| pObj->nRefs--; |
| } |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Allocates cut of the given size.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Cnf_CutRef( Cnf_Man_t * p, Cnf_Cut_t * pCut ) |
| { |
| Aig_Obj_t * pObj; |
| int i; |
| Cnf_CutForEachLeaf( p->pManAig, pCut, pObj, i ) |
| { |
| pObj->nRefs++; |
| } |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Allocates cut of the given size.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Cnf_CutUpdateRefs( Cnf_Man_t * p, Cnf_Cut_t * pCut, Cnf_Cut_t * pCutFan, Cnf_Cut_t * pCutRes ) |
| { |
| Cnf_CutDeref( p, pCut ); |
| Cnf_CutDeref( p, pCutFan ); |
| Cnf_CutRef( p, pCutRes ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Merges two arrays of integers.] |
| |
| Description [Returns the number of items.] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| static inline int Cnf_CutMergeLeaves( Cnf_Cut_t * pCut, Cnf_Cut_t * pCutFan, int * pFanins ) |
| { |
| int i, k, nFanins = 0; |
| for ( i = k = 0; i < pCut->nFanins && k < pCutFan->nFanins; ) |
| { |
| if ( pCut->pFanins[i] == pCutFan->pFanins[k] ) |
| pFanins[nFanins++] = pCut->pFanins[i], i++, k++; |
| else if ( pCut->pFanins[i] < pCutFan->pFanins[k] ) |
| pFanins[nFanins++] = pCut->pFanins[i], i++; |
| else |
| pFanins[nFanins++] = pCutFan->pFanins[k], k++; |
| } |
| for ( ; i < pCut->nFanins; i++ ) |
| pFanins[nFanins++] = pCut->pFanins[i]; |
| for ( ; k < pCutFan->nFanins; k++ ) |
| pFanins[nFanins++] = pCutFan->pFanins[k]; |
| return nFanins; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Computes the stretching phase of the cut w.r.t. the merged cut.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| static inline unsigned Cnf_TruthPhase( Cnf_Cut_t * pCut, Cnf_Cut_t * pCut1 ) |
| { |
| unsigned uPhase = 0; |
| int i, k; |
| for ( i = k = 0; i < pCut->nFanins; i++ ) |
| { |
| if ( k == pCut1->nFanins ) |
| break; |
| if ( pCut->pFanins[i] < pCut1->pFanins[k] ) |
| continue; |
| assert( pCut->pFanins[i] == pCut1->pFanins[k] ); |
| uPhase |= (1 << i); |
| k++; |
| } |
| return uPhase; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Removes the fanin variable.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Cnf_CutRemoveIthVar( Cnf_Cut_t * pCut, int iVar, int iFan ) |
| { |
| int i; |
| assert( pCut->pFanins[iVar] == iFan ); |
| pCut->nFanins--; |
| for ( i = iVar; i < pCut->nFanins; i++ ) |
| pCut->pFanins[i] = pCut->pFanins[i+1]; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Inserts the fanin variable.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Cnf_CutInsertIthVar( Cnf_Cut_t * pCut, int iVar, int iFan ) |
| { |
| int i; |
| for ( i = pCut->nFanins; i > iVar; i-- ) |
| pCut->pFanins[i] = pCut->pFanins[i-1]; |
| pCut->pFanins[iVar] = iFan; |
| pCut->nFanins++; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Merges two cuts.] |
| |
| Description [Returns NULL of the cuts cannot be merged.] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Cnf_Cut_t * Cnf_CutCompose( Cnf_Man_t * p, Cnf_Cut_t * pCut, Cnf_Cut_t * pCutFan, int iFan ) |
| { |
| Cnf_Cut_t * pCutRes; |
| static int pFanins[32]; |
| unsigned * pTruth, * pTruthFan, * pTruthRes; |
| unsigned * pTop = p->pTruths[0], * pFan = p->pTruths[2], * pTemp = p->pTruths[3]; |
| unsigned uPhase, uPhaseFan; |
| int i, iVar, nFanins, RetValue; |
| |
| // make sure the second cut is the fanin of the first |
| for ( iVar = 0; iVar < pCut->nFanins; iVar++ ) |
| if ( pCut->pFanins[iVar] == iFan ) |
| break; |
| assert( iVar < pCut->nFanins ); |
| // remove this variable |
| Cnf_CutRemoveIthVar( pCut, iVar, iFan ); |
| // merge leaves of the cuts |
| nFanins = Cnf_CutMergeLeaves( pCut, pCutFan, pFanins ); |
| if ( nFanins+1 > p->nMergeLimit ) |
| { |
| Cnf_CutInsertIthVar( pCut, iVar, iFan ); |
| return NULL; |
| } |
| // create new cut |
| pCutRes = Cnf_CutAlloc( p, nFanins ); |
| memcpy( pCutRes->pFanins, pFanins, sizeof(int) * nFanins ); |
| assert( pCutRes->nFanins <= pCut->nFanins + pCutFan->nFanins ); |
| |
| // derive its truth table |
| // get the truth tables in the composition space |
| pTruth = Cnf_CutTruth(pCut); |
| pTruthFan = Cnf_CutTruth(pCutFan); |
| pTruthRes = Cnf_CutTruth(pCutRes); |
| for ( i = 0; i < 2*pCutRes->nWords; i++ ) |
| pTop[i] = pTruth[i % pCut->nWords]; |
| for ( i = 0; i < pCutRes->nWords; i++ ) |
| pFan[i] = pTruthFan[i % pCutFan->nWords]; |
| // move the variable to the end |
| uPhase = Kit_BitMask( pCutRes->nFanins+1 ) & ~(1 << iVar); |
| Kit_TruthShrink( pTemp, pTop, pCutRes->nFanins, pCutRes->nFanins+1, uPhase, 1 ); |
| // compute the phases |
| uPhase = Cnf_TruthPhase( pCutRes, pCut ) | (1 << pCutRes->nFanins); |
| uPhaseFan = Cnf_TruthPhase( pCutRes, pCutFan ); |
| // permute truth-tables to the common support |
| Kit_TruthStretch( pTemp, pTop, pCut->nFanins+1, pCutRes->nFanins+1, uPhase, 1 ); |
| Kit_TruthStretch( pTemp, pFan, pCutFan->nFanins, pCutRes->nFanins, uPhaseFan, 1 ); |
| // perform Boolean operation |
| Kit_TruthMux( pTruthRes, pTop, pTop+pCutRes->nWords, pFan, pCutRes->nFanins ); |
| // return the cut to its original condition |
| Cnf_CutInsertIthVar( pCut, iVar, iFan ); |
| // consider the simple case |
| if ( pCutRes->nFanins < 5 ) |
| { |
| pCutRes->Cost = p->pSopSizes[0xFFFF & *pTruthRes] + p->pSopSizes[0xFFFF & ~*pTruthRes]; |
| return pCutRes; |
| } |
| |
| // derive ISOP for positive phase |
| RetValue = Kit_TruthIsop( pTruthRes, pCutRes->nFanins, p->vMemory, 0 ); |
| pCutRes->vIsop[1] = (RetValue == -1)? NULL : Vec_IntDup( p->vMemory ); |
| // derive ISOP for negative phase |
| Kit_TruthNot( pTruthRes, pTruthRes, pCutRes->nFanins ); |
| RetValue = Kit_TruthIsop( pTruthRes, pCutRes->nFanins, p->vMemory, 0 ); |
| pCutRes->vIsop[0] = (RetValue == -1)? NULL : Vec_IntDup( p->vMemory ); |
| Kit_TruthNot( pTruthRes, pTruthRes, pCutRes->nFanins ); |
| |
| // compute the cut cost |
| if ( pCutRes->vIsop[0] == NULL || pCutRes->vIsop[1] == NULL ) |
| pCutRes->Cost = 127; |
| else if ( Vec_IntSize(pCutRes->vIsop[0]) + Vec_IntSize(pCutRes->vIsop[1]) > 127 ) |
| pCutRes->Cost = 127; |
| else |
| pCutRes->Cost = Vec_IntSize(pCutRes->vIsop[0]) + Vec_IntSize(pCutRes->vIsop[1]); |
| return pCutRes; |
| } |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// END OF FILE /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| |
| ABC_NAMESPACE_IMPL_END |
| |