| /**CFile**************************************************************** |
| |
| FileName [mfsDiv.c] |
| |
| SystemName [ABC: Logic synthesis and verification system.] |
| |
| PackageName [The good old minimization with complete don't-cares.] |
| |
| Synopsis [Procedures to compute candidate divisors.] |
| |
| Author [Alan Mishchenko] |
| |
| Affiliation [UC Berkeley] |
| |
| Date [Ver. 1.0. Started - June 20, 2005.] |
| |
| Revision [$Id: mfsDiv.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] |
| |
| ***********************************************************************/ |
| |
| #include "mfsInt.h" |
| |
| ABC_NAMESPACE_IMPL_START |
| |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// DECLARATIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// FUNCTION DEFINITIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| /**Function************************************************************* |
| |
| Synopsis [Marks and collects the TFI cone of the node.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Abc_MfsWinMarkTfi_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vCone ) |
| { |
| Abc_Obj_t * pFanin; |
| int i; |
| if ( Abc_NodeIsTravIdCurrent(pObj) ) |
| return; |
| Abc_NodeSetTravIdCurrent( pObj ); |
| if ( Abc_ObjIsCi(pObj) ) |
| { |
| Vec_PtrPush( vCone, pObj ); |
| return; |
| } |
| assert( Abc_ObjIsNode(pObj) ); |
| // visit the fanins of the node |
| Abc_ObjForEachFanin( pObj, pFanin, i ) |
| Abc_MfsWinMarkTfi_rec( pFanin, vCone ); |
| Vec_PtrPush( vCone, pObj ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Marks and collects the TFI cone of the node.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Vec_Ptr_t * Abc_MfsWinMarkTfi( Abc_Obj_t * pNode ) |
| { |
| Vec_Ptr_t * vCone; |
| vCone = Vec_PtrAlloc( 100 ); |
| Abc_MfsWinMarkTfi_rec( pNode, vCone ); |
| return vCone; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Marks the TFO of the collected nodes up to the given level.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Abc_MfsWinSweepLeafTfo_rec( Abc_Obj_t * pObj, int nLevelLimit ) |
| { |
| Abc_Obj_t * pFanout; |
| int i; |
| if ( Abc_ObjIsCo(pObj) || (int)pObj->Level > nLevelLimit ) |
| return; |
| if ( Abc_NodeIsTravIdCurrent(pObj) ) |
| return; |
| Abc_NodeSetTravIdCurrent( pObj ); |
| Abc_ObjForEachFanout( pObj, pFanout, i ) |
| Abc_MfsWinSweepLeafTfo_rec( pFanout, nLevelLimit ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Dereferences the node's MFFC.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Abc_MfsNodeDeref_rec( Abc_Obj_t * pNode ) |
| { |
| Abc_Obj_t * pFanin; |
| int i, Counter = 1; |
| if ( Abc_ObjIsCi(pNode) ) |
| return 0; |
| Abc_NodeSetTravIdCurrent( pNode ); |
| Abc_ObjForEachFanin( pNode, pFanin, i ) |
| { |
| assert( pFanin->vFanouts.nSize > 0 ); |
| if ( --pFanin->vFanouts.nSize == 0 ) |
| Counter += Abc_MfsNodeDeref_rec( pFanin ); |
| } |
| return Counter; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [References the node's MFFC.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Abc_MfsNodeRef_rec( Abc_Obj_t * pNode ) |
| { |
| Abc_Obj_t * pFanin; |
| int i, Counter = 1; |
| if ( Abc_ObjIsCi(pNode) ) |
| return 0; |
| Abc_ObjForEachFanin( pNode, pFanin, i ) |
| { |
| if ( pFanin->vFanouts.nSize++ == 0 ) |
| Counter += Abc_MfsNodeRef_rec( pFanin ); |
| } |
| return Counter; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Labels MFFC of the node with the current trav ID.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Abc_MfsWinVisitMffc( Abc_Obj_t * pNode ) |
| { |
| int Count1, Count2; |
| assert( Abc_ObjIsNode(pNode) ); |
| // dereference the node (mark with the current trav ID) |
| Count1 = Abc_MfsNodeDeref_rec( pNode ); |
| // reference it back |
| Count2 = Abc_MfsNodeRef_rec( pNode ); |
| assert( Count1 == Count2 ); |
| return Count1; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Computes divisors and add them to nodes in the window.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Vec_Ptr_t * Abc_MfsComputeDivisors( Mfs_Man_t * p, Abc_Obj_t * pNode, int nLevDivMax ) |
| { |
| Vec_Ptr_t * vCone, * vDivs; |
| Abc_Obj_t * pObj, * pFanout, * pFanin; |
| int k, f, m; |
| int nDivsPlus = 0, nTrueSupp; |
| assert( p->vDivs == NULL ); |
| |
| // mark the TFI with the current trav ID |
| Abc_NtkIncrementTravId( pNode->pNtk ); |
| vCone = Abc_MfsWinMarkTfi( pNode ); |
| |
| // count the number of PIs |
| nTrueSupp = 0; |
| Vec_PtrForEachEntry( Abc_Obj_t *, vCone, pObj, k ) |
| nTrueSupp += Abc_ObjIsCi(pObj); |
| // printf( "%d(%d) ", Vec_PtrSize(p->vSupp), m ); |
| |
| // mark with the current trav ID those nodes that should not be divisors: |
| // (1) the node and its TFO |
| // (2) the MFFC of the node |
| // (3) the node's fanins (these are treated as a special case) |
| Abc_NtkIncrementTravId( pNode->pNtk ); |
| Abc_MfsWinSweepLeafTfo_rec( pNode, nLevDivMax ); |
| // Abc_MfsWinVisitMffc( pNode ); |
| Abc_ObjForEachFanin( pNode, pObj, k ) |
| Abc_NodeSetTravIdCurrent( pObj ); |
| |
| // at this point the nodes are marked with two trav IDs: |
| // nodes to be collected as divisors are marked with previous trav ID |
| // nodes to be avoided as divisors are marked with current trav ID |
| |
| // start collecting the divisors |
| vDivs = Vec_PtrAlloc( p->pPars->nWinMax ); |
| Vec_PtrForEachEntry( Abc_Obj_t *, vCone, pObj, k ) |
| { |
| if ( !Abc_NodeIsTravIdPrevious(pObj) ) |
| continue; |
| if ( (int)pObj->Level > nLevDivMax ) |
| continue; |
| Vec_PtrPush( vDivs, pObj ); |
| if ( Vec_PtrSize(vDivs) >= p->pPars->nWinMax ) |
| break; |
| } |
| Vec_PtrFree( vCone ); |
| |
| // explore the fanouts of already collected divisors |
| if ( Vec_PtrSize(vDivs) < p->pPars->nWinMax ) |
| Vec_PtrForEachEntry( Abc_Obj_t *, vDivs, pObj, k ) |
| { |
| // consider fanouts of this node |
| Abc_ObjForEachFanout( pObj, pFanout, f ) |
| { |
| // stop if there are too many fanouts |
| if ( p->pPars->nFanoutsMax && f > p->pPars->nFanoutsMax ) |
| break; |
| // skip nodes that are already added |
| if ( Abc_NodeIsTravIdPrevious(pFanout) ) |
| continue; |
| // skip nodes in the TFO or in the MFFC of node |
| if ( Abc_NodeIsTravIdCurrent(pFanout) ) |
| continue; |
| // skip COs |
| if ( !Abc_ObjIsNode(pFanout) ) |
| continue; |
| // skip nodes with large level |
| if ( (int)pFanout->Level > nLevDivMax ) |
| continue; |
| // skip nodes whose fanins are not divisors -- here we skip more than we need to skip!!! (revise later) August 7, 2009 |
| Abc_ObjForEachFanin( pFanout, pFanin, m ) |
| if ( !Abc_NodeIsTravIdPrevious(pFanin) ) |
| break; |
| if ( m < Abc_ObjFaninNum(pFanout) ) |
| continue; |
| // make sure this divisor in not among the nodes |
| // Vec_PtrForEachEntry( Abc_Obj_t *, p->vNodes, pFanin, m ) |
| // assert( pFanout != pFanin ); |
| // add the node to the divisors |
| Vec_PtrPush( vDivs, pFanout ); |
| // Vec_PtrPush( p->vNodes, pFanout ); |
| Vec_PtrPushUnique( p->vNodes, pFanout ); |
| Abc_NodeSetTravIdPrevious( pFanout ); |
| nDivsPlus++; |
| if ( Vec_PtrSize(vDivs) >= p->pPars->nWinMax ) |
| break; |
| } |
| if ( Vec_PtrSize(vDivs) >= p->pPars->nWinMax ) |
| break; |
| } |
| p->nMaxDivs += (Vec_PtrSize(vDivs) >= p->pPars->nWinMax); |
| |
| // sort the divisors by level in the increasing order |
| Vec_PtrSort( vDivs, (int (*)(void))Abc_NodeCompareLevelsIncrease ); |
| |
| // add the fanins of the node |
| Abc_ObjForEachFanin( pNode, pFanin, k ) |
| Vec_PtrPush( vDivs, pFanin ); |
| |
| /* |
| printf( "Node level = %d. ", Abc_ObjLevel(p->pNode) ); |
| Vec_PtrForEachEntryStart( Abc_Obj_t *, vDivs, pObj, k, Vec_PtrSize(vDivs)-p->nDivsPlus ) |
| printf( "%d ", Abc_ObjLevel(pObj) ); |
| printf( "\n" ); |
| */ |
| //printf( "%d ", p->nDivsPlus ); |
| // printf( "(%d+%d)(%d+%d+%d) ", Vec_PtrSize(p->vSupp), Vec_PtrSize(p->vNodes), |
| // nTrueSupp, Vec_PtrSize(vDivs)-nTrueSupp-nDivsPlus, nDivsPlus ); |
| return vDivs; |
| } |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// END OF FILE /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| |
| ABC_NAMESPACE_IMPL_END |
| |