| /**CFile**************************************************************** |
| |
| FileName [abcMerge.c] |
| |
| SystemName [ABC: Logic synthesis and verification system.] |
| |
| PackageName [Network and node package.] |
| |
| Synopsis [LUT merging algorithm.] |
| |
| Author [Alan Mishchenko] |
| |
| Affiliation [UC Berkeley] |
| |
| Date [Ver. 1.0. Started - June 20, 2005.] |
| |
| Revision [$Id: abcMerge.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] |
| |
| ***********************************************************************/ |
| |
| #include "base/abc/abc.h" |
| #include "aig/aig/aig.h" |
| #include "aig/nwk/nwkMerge.h" |
| |
| ABC_NAMESPACE_IMPL_START |
| |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// DECLARATIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// FUNCTION DEFINITIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| /**Function************************************************************* |
| |
| Synopsis [Marks the fanins of the node with the current trav ID.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Abc_NtkMarkFanins_rec( Abc_Obj_t * pLut, int nLevMin ) |
| { |
| Abc_Obj_t * pNext; |
| int i; |
| if ( !Abc_ObjIsNode(pLut) ) |
| return; |
| if ( Abc_NodeIsTravIdCurrent( pLut ) ) |
| return; |
| Abc_NodeSetTravIdCurrent( pLut ); |
| if ( Abc_ObjLevel(pLut) < nLevMin ) |
| return; |
| Abc_ObjForEachFanin( pLut, pNext, i ) |
| Abc_NtkMarkFanins_rec( pNext, nLevMin ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Marks the fanouts of the node with the current trav ID.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Abc_NtkMarkFanouts_rec( Abc_Obj_t * pLut, int nLevMax, int nFanMax ) |
| { |
| Abc_Obj_t * pNext; |
| int i; |
| if ( !Abc_ObjIsNode(pLut) ) |
| return; |
| if ( Abc_NodeIsTravIdCurrent( pLut ) ) |
| return; |
| Abc_NodeSetTravIdCurrent( pLut ); |
| if ( Abc_ObjLevel(pLut) > nLevMax ) |
| return; |
| if ( Abc_ObjFanoutNum(pLut) > nFanMax ) |
| return; |
| Abc_ObjForEachFanout( pLut, pNext, i ) |
| Abc_NtkMarkFanouts_rec( pNext, nLevMax, nFanMax ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Collects the circle of nodes around the given set.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Abc_NtkCollectCircle( Vec_Ptr_t * vStart, Vec_Ptr_t * vNext, int nFanMax ) |
| { |
| Abc_Obj_t * pObj, * pNext; |
| int i, k; |
| Vec_PtrClear( vNext ); |
| Vec_PtrForEachEntry( Vec_Int_t *, vStart, pObj, i ) |
| { |
| Abc_ObjForEachFanin( pObj, pNext, k ) |
| { |
| if ( !Abc_ObjIsNode(pNext) ) |
| continue; |
| if ( Abc_NodeIsTravIdCurrent( pNext ) ) |
| continue; |
| Abc_NodeSetTravIdCurrent( pNext ); |
| Vec_PtrPush( vNext, pNext ); |
| } |
| Abc_ObjForEachFanout( pObj, pNext, k ) |
| { |
| if ( !Abc_ObjIsNode(pNext) ) |
| continue; |
| if ( Abc_NodeIsTravIdCurrent( pNext ) ) |
| continue; |
| Abc_NodeSetTravIdCurrent( pNext ); |
| if ( Abc_ObjFanoutNum(pNext) > nFanMax ) |
| continue; |
| Vec_PtrPush( vNext, pNext ); |
| } |
| } |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Collects the circle of nodes removes from the given one.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Abc_NtkCollectNonOverlapCands( Abc_Obj_t * pLut, Vec_Ptr_t * vStart, Vec_Ptr_t * vNext, Vec_Ptr_t * vCands, Nwk_LMPars_t * pPars ) |
| { |
| Vec_Ptr_t * vTemp; |
| Abc_Obj_t * pObj; |
| int i, k; |
| Vec_PtrClear( vCands ); |
| if ( pPars->nMaxSuppSize - Abc_ObjFaninNum(pLut) <= 1 ) |
| return; |
| |
| // collect nodes removed by this distance |
| assert( pPars->nMaxDistance > 0 ); |
| Vec_PtrClear( vStart ); |
| Vec_PtrPush( vStart, pLut ); |
| Abc_NtkIncrementTravId( pLut->pNtk ); |
| Abc_NodeSetTravIdCurrent( pLut ); |
| for ( i = 1; i <= pPars->nMaxDistance; i++ ) |
| { |
| Abc_NtkCollectCircle( vStart, vNext, pPars->nMaxFanout ); |
| vTemp = vStart; |
| vStart = vNext; |
| vNext = vTemp; |
| // collect the nodes in vStart |
| Vec_PtrForEachEntry( Vec_Int_t *, vStart, pObj, k ) |
| Vec_PtrPush( vCands, pObj ); |
| } |
| |
| // mark the TFI/TFO nodes |
| Abc_NtkIncrementTravId( pLut->pNtk ); |
| if ( pPars->fUseTfiTfo ) |
| Abc_NodeSetTravIdCurrent( pLut ); |
| else |
| { |
| Abc_NodeSetTravIdPrevious( pLut ); |
| Abc_NtkMarkFanins_rec( pLut, Abc_ObjLevel(pLut) - pPars->nMaxDistance ); |
| Abc_NodeSetTravIdPrevious( pLut ); |
| Abc_NtkMarkFanouts_rec( pLut, Abc_ObjLevel(pLut) + pPars->nMaxDistance, pPars->nMaxFanout ); |
| } |
| |
| // collect nodes satisfying the following conditions: |
| // - they are close enough in terms of distance |
| // - they are not in the TFI/TFO of the LUT |
| // - they have no more than the given number of fanins |
| // - they have no more than the given diff in delay |
| k = 0; |
| Vec_PtrForEachEntry( Vec_Int_t *, vCands, pObj, i ) |
| { |
| if ( Abc_NodeIsTravIdCurrent(pObj) ) |
| continue; |
| if ( Abc_ObjFaninNum(pLut) + Abc_ObjFaninNum(pObj) > pPars->nMaxSuppSize ) |
| continue; |
| if ( Abc_ObjLevel(pLut) - Abc_ObjLevel(pObj) > pPars->nMaxLevelDiff || |
| Abc_ObjLevel(pObj) - Abc_ObjLevel(pLut) > pPars->nMaxLevelDiff ) |
| continue; |
| Vec_PtrWriteEntry( vCands, k++, pObj ); |
| } |
| Vec_PtrShrink( vCands, k ); |
| } |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [Count the total number of fanins.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Abc_NtkCountTotalFanins( Abc_Obj_t * pLut, Abc_Obj_t * pCand ) |
| { |
| Abc_Obj_t * pFanin; |
| int i, nCounter = Abc_ObjFaninNum(pLut); |
| Abc_ObjForEachFanin( pCand, pFanin, i ) |
| nCounter += !pFanin->fMarkC; |
| return nCounter; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Collects overlapping candidates.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Abc_NtkCollectOverlapCands( Abc_Obj_t * pLut, Vec_Ptr_t * vCands, Nwk_LMPars_t * pPars ) |
| { |
| Abc_Obj_t * pFanin, * pObj; |
| int i, k; |
| // mark fanins of pLut |
| Abc_ObjForEachFanin( pLut, pFanin, i ) |
| pFanin->fMarkC = 1; |
| // collect the matching fanouts of each fanin of the node |
| Vec_PtrClear( vCands ); |
| Abc_NtkIncrementTravId( pLut->pNtk ); |
| Abc_NodeSetTravIdCurrent( pLut ); |
| Abc_ObjForEachFanin( pLut, pFanin, i ) |
| { |
| if ( !Abc_ObjIsNode(pFanin) ) |
| continue; |
| if ( Abc_ObjFanoutNum(pFanin) > pPars->nMaxFanout ) |
| continue; |
| Abc_ObjForEachFanout( pFanin, pObj, k ) |
| { |
| if ( !Abc_ObjIsNode(pObj) ) |
| continue; |
| if ( Abc_NodeIsTravIdCurrent( pObj ) ) |
| continue; |
| Abc_NodeSetTravIdCurrent( pObj ); |
| // check the difference in delay |
| if ( Abc_ObjLevel(pLut) - Abc_ObjLevel(pObj) > pPars->nMaxLevelDiff || |
| Abc_ObjLevel(pObj) - Abc_ObjLevel(pLut) > pPars->nMaxLevelDiff ) |
| continue; |
| // check the total number of fanins of the node |
| if ( Abc_NtkCountTotalFanins(pLut, pObj) > pPars->nMaxSuppSize ) |
| continue; |
| Vec_PtrPush( vCands, pObj ); |
| } |
| } |
| // unmark fanins of pLut |
| Abc_ObjForEachFanin( pLut, pFanin, i ) |
| pFanin->fMarkC = 0; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Performs LUT merging with parameters.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Vec_Int_t * Abc_NtkLutMerge( Abc_Ntk_t * pNtk, Nwk_LMPars_t * pPars ) |
| { |
| Nwk_Grf_t * p; |
| Vec_Int_t * vResult; |
| Vec_Ptr_t * vStart, * vNext, * vCands1, * vCands2; |
| Abc_Obj_t * pLut, * pCand; |
| int i, k, nVertsMax, nCands; |
| clock_t clk = clock(); |
| // count the number of vertices |
| nVertsMax = 0; |
| Abc_NtkForEachNode( pNtk, pLut, i ) |
| nVertsMax += (int)(Abc_ObjFaninNum(pLut) <= pPars->nMaxLutSize); |
| p = Nwk_ManGraphAlloc( nVertsMax ); |
| // create graph |
| vStart = Vec_PtrAlloc( 1000 ); |
| vNext = Vec_PtrAlloc( 1000 ); |
| vCands1 = Vec_PtrAlloc( 1000 ); |
| vCands2 = Vec_PtrAlloc( 1000 ); |
| nCands = 0; |
| Abc_NtkForEachNode( pNtk, pLut, i ) |
| { |
| if ( Abc_ObjFaninNum(pLut) > pPars->nMaxLutSize ) |
| continue; |
| Abc_NtkCollectOverlapCands( pLut, vCands1, pPars ); |
| if ( pPars->fUseDiffSupp ) |
| Abc_NtkCollectNonOverlapCands( pLut, vStart, vNext, vCands2, pPars ); |
| if ( Vec_PtrSize(vCands1) == 0 && Vec_PtrSize(vCands2) == 0 ) |
| continue; |
| nCands += Vec_PtrSize(vCands1) + Vec_PtrSize(vCands2); |
| // save candidates |
| Vec_PtrForEachEntry( Vec_Int_t *, vCands1, pCand, k ) |
| Nwk_ManGraphHashEdge( p, Abc_ObjId(pLut), Abc_ObjId(pCand) ); |
| Vec_PtrForEachEntry( Vec_Int_t *, vCands2, pCand, k ) |
| Nwk_ManGraphHashEdge( p, Abc_ObjId(pLut), Abc_ObjId(pCand) ); |
| // print statistics about this node |
| if ( pPars->fVeryVerbose ) |
| printf( "Node %6d : Fanins = %d. Fanouts = %3d. Cand1 = %3d. Cand2 = %3d.\n", |
| Abc_ObjId(pLut), Abc_ObjFaninNum(pLut), Abc_ObjFaninNum(pLut), |
| Vec_PtrSize(vCands1), Vec_PtrSize(vCands2) ); |
| } |
| Vec_PtrFree( vStart ); |
| Vec_PtrFree( vNext ); |
| Vec_PtrFree( vCands1 ); |
| Vec_PtrFree( vCands2 ); |
| if ( pPars->fVerbose ) |
| { |
| printf( "Mergable LUTs = %6d. Total cands = %6d. ", p->nVertsMax, nCands ); |
| ABC_PRT( "Deriving graph", clock() - clk ); |
| } |
| // solve the graph problem |
| clk = clock(); |
| Nwk_ManGraphSolve( p ); |
| if ( pPars->fVerbose ) |
| { |
| printf( "GRAPH: Nodes = %6d. Edges = %6d. Pairs = %6d. ", |
| p->nVerts, p->nEdges, Vec_IntSize(p->vPairs)/2 ); |
| ABC_PRT( "Solving", clock() - clk ); |
| Nwk_ManGraphReportMemoryUsage( p ); |
| } |
| vResult = p->vPairs; p->vPairs = NULL; |
| /* |
| for ( i = 0; i < vResult->nSize; i += 2 ) |
| printf( "(%d,%d) ", vResult->pArray[i], vResult->pArray[i+1] ); |
| printf( "\n" ); |
| */ |
| Nwk_ManGraphFree( p ); |
| return vResult; |
| } |
| |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// END OF FILE /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| |
| ABC_NAMESPACE_IMPL_END |
| |