| /**CFile**************************************************************** |
| |
| FileName [ifUtil.c] |
| |
| SystemName [ABC: Logic synthesis and verification system.] |
| |
| PackageName [FPGA mapping based on priority cuts.] |
| |
| Synopsis [Various utilities.] |
| |
| Author [Alan Mishchenko] |
| |
| Affiliation [UC Berkeley] |
| |
| Date [Ver. 1.0. Started - November 21, 2006.] |
| |
| Revision [$Id: ifUtil.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $] |
| |
| ***********************************************************************/ |
| |
| #include "if.h" |
| |
| ABC_NAMESPACE_IMPL_START |
| |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// DECLARATIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// FUNCTION DEFINITIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| /**Function************************************************************* |
| |
| Synopsis [Sets all the node copy to NULL.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void If_ManCleanNodeCopy( If_Man_t * p ) |
| { |
| If_Obj_t * pObj; |
| int i; |
| If_ManForEachObj( p, pObj, i ) |
| If_ObjSetCopy( pObj, NULL ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Sets all the cut data to NULL.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void If_ManCleanCutData( If_Man_t * p ) |
| { |
| If_Obj_t * pObj; |
| int i; |
| If_ManForEachObj( p, pObj, i ) |
| If_CutSetData( If_ObjCutBest(pObj), NULL ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Sets all visited marks to 0.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void If_ManCleanMarkV( If_Man_t * p ) |
| { |
| If_Obj_t * pObj; |
| int i; |
| If_ManForEachObj( p, pObj, i ) |
| pObj->fVisit = 0; |
| } |
| |
| #if 0 |
| |
| /**Function************************************************************* |
| |
| Synopsis [Computes area, references, and nodes used in the mapping.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| float If_ManScanMapping_rec( If_Man_t * p, If_Obj_t * pObj, If_Obj_t ** ppStore ) |
| { |
| If_Obj_t * pLeaf; |
| If_Cut_t * pCutBest; |
| float aArea; |
| int i; |
| if ( pObj->nRefs++ || If_ObjIsCi(pObj) || If_ObjIsConst1(pObj) ) |
| return 0.0; |
| // store the node in the structure by level |
| assert( If_ObjIsAnd(pObj) ); |
| pObj->pCopy = (char *)ppStore[pObj->Level]; |
| ppStore[pObj->Level] = pObj; |
| // visit the transitive fanin of the selected cut |
| pCutBest = If_ObjCutBest(pObj); |
| p->nNets += pCutBest->nLeaves; |
| aArea = If_CutLutArea( p, pCutBest ); |
| If_CutForEachLeaf( p, pCutBest, pLeaf, i ) |
| aArea += If_ManScanMapping_rec( p, pLeaf, ppStore ); |
| return aArea; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Computes area, references, and nodes used in the mapping.] |
| |
| Description [Collects the nodes in reverse topological order in array |
| p->vMapping.] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| float If_ManScanMapping( If_Man_t * p ) |
| { |
| If_Obj_t * pObj, ** ppStore; |
| float aArea; |
| int i; |
| assert( !p->pPars->fLiftLeaves ); |
| // clean all references |
| p->nNets = 0; |
| If_ManForEachObj( p, pObj, i ) |
| { |
| pObj->Required = IF_FLOAT_LARGE; |
| pObj->nVisits = pObj->nVisitsCopy; |
| pObj->nRefs = 0; |
| } |
| // allocate place to store the nodes |
| ppStore = ABC_ALLOC( If_Obj_t *, p->nLevelMax + 1 ); |
| memset( ppStore, 0, sizeof(If_Obj_t *) * (p->nLevelMax + 1) ); |
| // collect nodes reachable from POs in the DFS order through the best cuts |
| aArea = 0; |
| If_ManForEachCo( p, pObj, i ) |
| aArea += If_ManScanMapping_rec( p, If_ObjFanin0(pObj), ppStore ); |
| // reconnect the nodes in reverse topological order |
| Vec_PtrClear( p->vMapped ); |
| for ( i = p->nLevelMax; i >= 0; i-- ) |
| for ( pObj = ppStore[i]; pObj; pObj = pObj->pCopy ) |
| Vec_PtrPush( p->vMapped, pObj ); |
| ABC_FREE( ppStore ); |
| return aArea; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Computes area, references, and nodes used in the mapping.] |
| |
| Description [Collects the nodes in reverse topological order in array |
| p->vMapping.] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| float If_ManScanMappingDirect( If_Man_t * p ) |
| { |
| If_Obj_t * pObj, ** ppStore; |
| float aArea; |
| int i; |
| assert( !p->pPars->fLiftLeaves ); |
| // clean all references |
| If_ManForEachObj( p, pObj, i ) |
| { |
| pObj->Required = IF_FLOAT_LARGE; |
| pObj->nVisits = pObj->nVisitsCopy; |
| pObj->nRefs = 0; |
| } |
| // allocate place to store the nodes |
| ppStore = ABC_ALLOC( If_Obj_t *, p->nLevelMax + 1 ); |
| memset( ppStore, 0, sizeof(If_Obj_t *) * (p->nLevelMax + 1) ); |
| // collect nodes reachable from POs in the DFS order through the best cuts |
| aArea = 0; |
| If_ManForEachCo( p, pObj, i ) |
| aArea += If_ManScanMapping_rec( p, If_ObjFanin0(pObj), ppStore ); |
| // reconnect the nodes in reverse topological order |
| Vec_PtrClear( p->vMapped ); |
| // for ( i = p->nLevelMax; i >= 0; i-- ) |
| for ( i = 0; i <= p->nLevelMax; i++ ) |
| for ( pObj = ppStore[i]; pObj; pObj = pObj->pCopy ) |
| Vec_PtrPush( p->vMapped, pObj ); |
| ABC_FREE( ppStore ); |
| return aArea; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Computes area, references, and nodes used in the mapping.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| float If_ManScanMappingSeq_rec( If_Man_t * p, If_Obj_t * pObj, Vec_Ptr_t * vMapped ) |
| { |
| If_Obj_t * pLeaf; |
| If_Cut_t * pCutBest; |
| float aArea; |
| int i, Shift; |
| // treat latches transparently |
| if ( If_ObjIsLatch(pObj) ) |
| return If_ManScanMappingSeq_rec( p, If_ObjFanin0(pObj), vMapped ); |
| // consider trivial cases |
| if ( pObj->nRefs++ || If_ObjIsPi(pObj) || If_ObjIsConst1(pObj) ) |
| return 0.0; |
| // store the node in the structure by level |
| assert( If_ObjIsAnd(pObj) ); |
| // visit the transitive fanin of the selected cut |
| pCutBest = If_ObjCutBest(pObj); |
| aArea = If_ObjIsAnd(pObj)? If_CutLutArea(p, pCutBest) : (float)0.0; |
| If_CutForEachLeafSeq( p, pCutBest, pLeaf, Shift, i ) |
| aArea += If_ManScanMappingSeq_rec( p, pLeaf, vMapped ); |
| // add the node |
| Vec_PtrPush( vMapped, pObj ); |
| return aArea; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Computes area, references, and nodes used in the mapping.] |
| |
| Description [Collects the nodes in reverse topological order in array |
| p->vMapping.] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| float If_ManScanMappingSeq( If_Man_t * p ) |
| { |
| If_Obj_t * pObj; |
| float aArea; |
| int i; |
| assert( p->pPars->fLiftLeaves ); |
| // clean all references |
| If_ManForEachObj( p, pObj, i ) |
| pObj->nRefs = 0; |
| // collect nodes reachable from POs in the DFS order through the best cuts |
| aArea = 0; |
| Vec_PtrClear( p->vMapped ); |
| If_ManForEachPo( p, pObj, i ) |
| aArea += If_ManScanMappingSeq_rec( p, If_ObjFanin0(pObj), p->vMapped ); |
| return aArea; |
| } |
| |
| #endif |
| |
| /**Function************************************************************* |
| |
| Synopsis [Computes area, references, and nodes used in the mapping.] |
| |
| Description [Collects the nodes in reverse topological order in array |
| p->vMapping.] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void If_ManResetOriginalRefs( If_Man_t * p ) |
| { |
| If_Obj_t * pObj; |
| int i; |
| If_ManForEachObj( p, pObj, i ) |
| pObj->nRefs = 0; |
| If_ManForEachObj( p, pObj, i ) |
| { |
| if ( If_ObjIsAnd(pObj) ) |
| { |
| pObj->pFanin0->nRefs++; |
| pObj->pFanin1->nRefs++; |
| } |
| else if ( If_ObjIsCo(pObj) ) |
| pObj->pFanin0->nRefs++; |
| } |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Computes cross-cut of the circuit.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int If_ManCrossCut( If_Man_t * p ) |
| { |
| If_Obj_t * pObj, * pFanin; |
| int i, nCutSize = 0, nCutSizeMax = 0; |
| If_ManForEachObj( p, pObj, i ) |
| { |
| if ( !If_ObjIsAnd(pObj) ) |
| continue; |
| // consider the node |
| if ( nCutSizeMax < ++nCutSize ) |
| nCutSizeMax = nCutSize; |
| if ( pObj->nVisits == 0 ) |
| nCutSize--; |
| // consider the fanins |
| pFanin = If_ObjFanin0(pObj); |
| if ( !If_ObjIsCi(pFanin) && --pFanin->nVisits == 0 ) |
| nCutSize--; |
| pFanin = If_ObjFanin1(pObj); |
| if ( !If_ObjIsCi(pFanin) && --pFanin->nVisits == 0 ) |
| nCutSize--; |
| // consider the choice class |
| if ( pObj->fRepr ) |
| for ( pFanin = pObj; pFanin; pFanin = pFanin->pEquiv ) |
| if ( !If_ObjIsCi(pFanin) && --pFanin->nVisits == 0 ) |
| nCutSize--; |
| } |
| If_ManForEachObj( p, pObj, i ) |
| { |
| assert( If_ObjIsCi(pObj) || pObj->fVisit == 0 ); |
| pObj->nVisits = pObj->nVisitsCopy; |
| } |
| assert( nCutSize == 0 ); |
| // Abc_Print( 1, "Max cross cut size = %6d.\n", nCutSizeMax ); |
| return nCutSizeMax; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Computes the reverse topological order of nodes.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Vec_Ptr_t * If_ManReverseOrder( If_Man_t * p ) |
| { |
| Vec_Ptr_t * vOrder; |
| If_Obj_t * pObj, ** ppStore; |
| int i; |
| // allocate place to store the nodes |
| ppStore = ABC_ALLOC( If_Obj_t *, p->nLevelMax + 1 ); |
| memset( ppStore, 0, sizeof(If_Obj_t *) * (p->nLevelMax + 1) ); |
| // add the nodes |
| If_ManForEachObj( p, pObj, i ) |
| { |
| assert( pObj->Level >= 0 && pObj->Level <= (unsigned)p->nLevelMax ); |
| pObj->pCopy = (char *)ppStore[pObj->Level]; |
| ppStore[pObj->Level] = pObj; |
| } |
| vOrder = Vec_PtrAlloc( If_ManObjNum(p) ); |
| for ( i = p->nLevelMax; i >= 0; i-- ) |
| for ( pObj = ppStore[i]; pObj; pObj = (If_Obj_t *)pObj->pCopy ) |
| Vec_PtrPush( vOrder, pObj ); |
| ABC_FREE( ppStore ); |
| // print the order |
| // Vec_PtrForEachEntry( If_Obj_t *, vOrder, pObj, i ) |
| // Abc_Print( 1, "Obj %2d Type %d Level = %d\n", pObj->Id, pObj->Type, pObj->Level ); |
| return vOrder; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Computes area, references, and nodes used in the mapping.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| float If_ManMarkMapping_rec( If_Man_t * p, If_Obj_t * pObj ) |
| { |
| If_Obj_t * pLeaf; |
| If_Cut_t * pCutBest; |
| float * pSwitching = p->vSwitching? (float*)p->vSwitching->pArray : NULL; |
| float aArea; |
| int i; |
| if ( pObj->nRefs++ || If_ObjIsCi(pObj) || If_ObjIsConst1(pObj) ) |
| return 0.0; |
| // store the node in the structure by level |
| assert( If_ObjIsAnd(pObj) ); |
| // visit the transitive fanin of the selected cut |
| pCutBest = If_ObjCutBest(pObj); |
| p->nNets += pCutBest->nLeaves; |
| aArea = If_CutLutArea( p, pCutBest ); |
| If_CutForEachLeaf( p, pCutBest, pLeaf, i ) |
| { |
| p->dPower += pSwitching? pSwitching[pLeaf->Id] : 0.0; |
| aArea += If_ManMarkMapping_rec( p, pLeaf ); |
| } |
| return aArea; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Computes area, references, and nodes used in the mapping.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void If_ManMarkMapping( If_Man_t * p ) |
| { |
| If_Obj_t * pObj; |
| int i; |
| If_ManForEachObj( p, pObj, i ) |
| { |
| pObj->Required = IF_FLOAT_LARGE; |
| pObj->nVisits = pObj->nVisitsCopy; |
| pObj->nRefs = 0; |
| } |
| p->nNets = 0; |
| p->dPower = 0.0; |
| p->AreaGlo = 0.0; |
| If_ManForEachCo( p, pObj, i ) |
| p->AreaGlo += If_ManMarkMapping_rec( p, If_ObjFanin0(pObj) ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Collects nodes used in the mapping in the topological order.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Vec_Ptr_t * If_ManCollectMappingDirect( If_Man_t * p ) |
| { |
| Vec_Ptr_t * vOrder; |
| If_Obj_t * pObj; |
| int i; |
| If_ManMarkMapping( p ); |
| vOrder = Vec_PtrAlloc( If_ManObjNum(p) ); |
| If_ManForEachObj( p, pObj, i ) |
| if ( If_ObjIsAnd(pObj) && pObj->nRefs ) |
| Vec_PtrPush( vOrder, pObj ); |
| return vOrder; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Collects nodes used in the mapping in the topological order.] |
| |
| Description [Represents mapping as an array of integers.] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Vec_Int_t * If_ManCollectMappingInt( If_Man_t * p ) |
| { |
| Vec_Int_t * vOrder; |
| If_Cut_t * pCutBest; |
| If_Obj_t * pObj; |
| int i, k, nLeaves, * ppLeaves; |
| If_ManMarkMapping( p ); |
| vOrder = Vec_IntAlloc( If_ManObjNum(p) ); |
| If_ManForEachObj( p, pObj, i ) |
| if ( If_ObjIsAnd(pObj) && pObj->nRefs ) |
| { |
| pCutBest = If_ObjCutBest( pObj ); |
| nLeaves = If_CutLeaveNum( pCutBest ); |
| ppLeaves = If_CutLeaves( pCutBest ); |
| // save the number of leaves, the leaves, and finally, the root |
| Vec_IntPush( vOrder, nLeaves ); |
| for ( k = 0; k < nLeaves; k++ ) |
| Vec_IntPush( vOrder, ppLeaves[k] ); |
| Vec_IntPush( vOrder, pObj->Id ); |
| } |
| return vOrder; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Returns the number of POs pointing to the same internal nodes.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int If_ManCountSpecialPos( If_Man_t * p ) |
| { |
| If_Obj_t * pObj; |
| int i, Counter = 0; |
| // clean all marks |
| If_ManForEachPo( p, pObj, i ) |
| If_ObjFanin0(pObj)->fMark = 0; |
| // label nodes |
| If_ManForEachPo( p, pObj, i ) |
| if ( !If_ObjFaninC0(pObj) ) |
| If_ObjFanin0(pObj)->fMark = 1; |
| // label nodes |
| If_ManForEachPo( p, pObj, i ) |
| if ( If_ObjFaninC0(pObj) ) |
| Counter += If_ObjFanin0(pObj)->fMark; |
| // clean all marks |
| If_ManForEachPo( p, pObj, i ) |
| If_ObjFanin0(pObj)->fMark = 0; |
| return Counter; |
| } |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [Traverse the cut and counts its volume.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| static void If_CutTraverse_rec( If_Obj_t * pNode, Vec_Ptr_t * vNodes ) |
| { |
| if ( pNode->fMark ) |
| return; |
| pNode->fMark = 1; |
| // assert( !If_ObjIsCi(pNode) ); // does not hold with cut minimization |
| if ( If_ObjIsAnd(pNode) ) |
| If_CutTraverse_rec( If_ObjFanin0(pNode), vNodes ); |
| if ( If_ObjIsAnd(pNode) ) |
| If_CutTraverse_rec( If_ObjFanin1(pNode), vNodes ); |
| Vec_PtrPush( vNodes, pNode ); |
| } |
| void If_CutTraverse( If_Man_t * p, If_Obj_t * pRoot, If_Cut_t * pCut, Vec_Ptr_t * vNodes ) |
| { |
| If_Obj_t * pLeaf; |
| int i; |
| // collect the internal nodes of the cut |
| Vec_PtrClear( vNodes ); |
| If_CutForEachLeaf( p, pCut, pLeaf, i ) |
| { |
| Vec_PtrPush( vNodes, pLeaf ); |
| assert( pLeaf->fMark == 0 ); |
| pLeaf->fMark = 1; |
| } |
| // collect other nodes |
| If_CutTraverse_rec( pRoot, vNodes ); |
| // clean the mark |
| Vec_PtrForEachEntry( If_Obj_t *, vNodes, pLeaf, i ) |
| pLeaf->fMark = 0; |
| } |
| void If_CutTraverseTest( If_Man_t * p, If_Obj_t * pRoot, If_Cut_t * pCut ) |
| { |
| Vec_Ptr_t * vNodes; |
| vNodes = Vec_PtrAlloc( 1000 ); |
| If_CutTraverse( p, pRoot, pCut, vNodes ); |
| //if ( Vec_PtrSize(vNodes) > 30 ) |
| //printf( "%d ", Vec_PtrSize(vNodes) ); |
| Vec_PtrFree( vNodes ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void If_ObjPrint( If_Obj_t * pObj ) |
| { |
| if ( pObj == NULL ) |
| { |
| printf( "Object is NULL." ); |
| return; |
| } |
| printf( "Obj %4d : ", If_ObjId(pObj) ); |
| if ( If_ObjIsConst1(pObj) ) |
| printf( "constant 1" ); |
| else if ( If_ObjIsCi(pObj) ) |
| printf( "PI" ); |
| else if ( If_ObjIsCo(pObj) ) |
| printf( "PO( %4d%s )", If_ObjId(If_ObjFanin0(pObj)), (If_ObjFaninC0(pObj)? "\'" : " ") ); |
| else |
| printf( "AND( %4d%s, %4d%s )", |
| If_ObjId(If_ObjFanin0(pObj)), (If_ObjFaninC0(pObj)? "\'" : " "), |
| If_ObjId(If_ObjFanin1(pObj)), (If_ObjFaninC1(pObj)? "\'" : " ") ); |
| printf( " (refs = %3d)", pObj->nVisitsCopy ); |
| printf( "\n" ); |
| } |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// END OF FILE /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| |
| ABC_NAMESPACE_IMPL_END |
| |