| /**CFile**************************************************************** |
| |
| FileName [cgtAig.c] |
| |
| SystemName [ABC: Logic synthesis and verification system.] |
| |
| PackageName [Clock gating package.] |
| |
| Synopsis [Creates AIG to compute clock-gating.] |
| |
| Author [Alan Mishchenko] |
| |
| Affiliation [UC Berkeley] |
| |
| Date [Ver. 1.0. Started - June 20, 2005.] |
| |
| Revision [$Id: cgtAig.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] |
| |
| ***********************************************************************/ |
| |
| #include "cgtInt.h" |
| |
| ABC_NAMESPACE_IMPL_START |
| |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// DECLARATIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// FUNCTION DEFINITIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| /**Function************************************************************* |
| |
| Synopsis [Computes transitive fanout cone of the node.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Cgt_ManDetectCandidates_rec( Aig_Man_t * pAig, Vec_Int_t * vUseful, Aig_Obj_t * pObj, int nLevelMax, Vec_Ptr_t * vCands ) |
| { |
| if ( Aig_ObjIsTravIdCurrent(pAig, pObj) ) |
| return; |
| Aig_ObjSetTravIdCurrent(pAig, pObj); |
| if ( Aig_ObjIsNode(pObj) ) |
| { |
| Cgt_ManDetectCandidates_rec( pAig, vUseful, Aig_ObjFanin0(pObj), nLevelMax, vCands ); |
| Cgt_ManDetectCandidates_rec( pAig, vUseful, Aig_ObjFanin1(pObj), nLevelMax, vCands ); |
| } |
| if ( Aig_ObjLevel(pObj) <= nLevelMax && (vUseful == NULL || Vec_IntEntry(vUseful, Aig_ObjId(pObj))) ) |
| Vec_PtrPush( vCands, pObj ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Computes transitive fanout cone of the node.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Cgt_ManDetectCandidates( Aig_Man_t * pAig, Vec_Int_t * vUseful, Aig_Obj_t * pObj, int nLevelMax, Vec_Ptr_t * vCands ) |
| { |
| Vec_PtrClear( vCands ); |
| if ( !Aig_ObjIsNode(pObj) ) |
| return; |
| Aig_ManIncrementTravId( pAig ); |
| Cgt_ManDetectCandidates_rec( pAig, vUseful, pObj, nLevelMax, vCands ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Computes transitive fanout cone of the node.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Cgt_ManDetectFanout_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, int nOdcMax, Vec_Ptr_t * vFanout ) |
| { |
| Aig_Obj_t * pFanout; |
| int f, iFanout = -1; |
| if ( Aig_ObjIsCo(pObj) || Aig_ObjLevel(pObj) > nOdcMax ) |
| return; |
| if ( Aig_ObjIsTravIdCurrent(pAig, pObj) ) |
| return; |
| Aig_ObjSetTravIdCurrent(pAig, pObj); |
| Vec_PtrPush( vFanout, pObj ); |
| Aig_ObjForEachFanout( pAig, pObj, pFanout, iFanout, f ) |
| Cgt_ManDetectFanout_rec( pAig, pFanout, nOdcMax, vFanout ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Computes transitive fanout cone of the node.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Cgt_ManDetectFanout( Aig_Man_t * pAig, Aig_Obj_t * pObj, int nOdcMax, Vec_Ptr_t * vFanout ) |
| { |
| Aig_Obj_t * pFanout; |
| int i, k, f, iFanout = -1; |
| // collect visited nodes |
| Vec_PtrClear( vFanout ); |
| Aig_ManIncrementTravId( pAig ); |
| Cgt_ManDetectFanout_rec( pAig, pObj, nOdcMax, vFanout ); |
| // remove those nodes whose fanout is included |
| k = 0; |
| Vec_PtrForEachEntry( Aig_Obj_t *, vFanout, pObj, i ) |
| { |
| // go through the fanouts of this node |
| Aig_ObjForEachFanout( pAig, pObj, pFanout, iFanout, f ) |
| if ( !Aig_ObjIsTravIdCurrent(pAig, pFanout) ) |
| break; |
| if ( f == Aig_ObjRefs(pObj) ) // all fanouts are included |
| continue; |
| Vec_PtrWriteEntry( vFanout, k++, pObj ); |
| } |
| Vec_PtrShrink( vFanout, k ); |
| Vec_PtrSort( vFanout, (int (*)(void))Aig_ObjCompareIdIncrease ); |
| assert( Vec_PtrSize(vFanout) > 0 ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Computes visited nodes in the topological order.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Cgt_ManCollectVisited_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Ptr_t * vVisited ) |
| { |
| if ( Aig_ObjIsCi(pObj) ) |
| return; |
| if ( Aig_ObjIsTravIdCurrent(pAig, pObj) ) |
| return; |
| Aig_ObjSetTravIdCurrent(pAig, pObj); |
| assert( Aig_ObjIsNode(pObj) ); |
| Cgt_ManCollectVisited_rec( pAig, Aig_ObjFanin0(pObj), vVisited ); |
| Cgt_ManCollectVisited_rec( pAig, Aig_ObjFanin1(pObj), vVisited ); |
| Vec_PtrPush( vVisited, pObj ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Computes visited nodes in the topological order.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Cgt_ManCollectVisited( Aig_Man_t * pAig, Vec_Ptr_t * vFanout, Vec_Ptr_t * vVisited ) |
| { |
| Aig_Obj_t * pObj; |
| int i; |
| Vec_PtrClear( vVisited ); |
| Aig_ManIncrementTravId( pAig ); |
| Vec_PtrForEachEntry( Aig_Obj_t *, vFanout, pObj, i ) |
| Cgt_ManCollectVisited_rec( pAig, pObj, vVisited ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| static inline Aig_Obj_t * Aig_ObjChild0CopyVec( Vec_Ptr_t * vCopy, Aig_Obj_t * pObj ) |
| { return Aig_NotCond((Aig_Obj_t *)Vec_PtrEntry(vCopy, Aig_ObjFaninId0(pObj)), Aig_ObjFaninC0(pObj)); } |
| static inline Aig_Obj_t * Aig_ObjChild1CopyVec( Vec_Ptr_t * vCopy, Aig_Obj_t * pObj ) |
| { return Aig_NotCond((Aig_Obj_t *)Vec_PtrEntry(vCopy, Aig_ObjFaninId1(pObj)), Aig_ObjFaninC1(pObj)); } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Derives miter for clock-gating.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Aig_Obj_t * Cgt_ManConstructCareCondition( Cgt_Man_t * p, Aig_Man_t * pNew, Aig_Obj_t * pObjLo, Vec_Ptr_t * vCopy0, Vec_Ptr_t * vCopy1 ) |
| { |
| Aig_Obj_t * pMiter, * pObj, * pTemp; |
| int i; |
| assert( Aig_ObjIsCi(pObjLo) ); |
| // detect nodes and their cone |
| Cgt_ManDetectFanout( p->pAig, pObjLo, p->pPars->nOdcMax, p->vFanout ); |
| Cgt_ManCollectVisited( p->pAig, p->vFanout, p->vVisited ); |
| // add new variables if the observability condition depends on PI variables |
| Vec_PtrForEachEntry( Aig_Obj_t *, p->vVisited, pObj, i ) |
| { |
| assert( Aig_ObjIsNode(pObj) ); |
| if ( Saig_ObjIsPi(p->pAig, Aig_ObjFanin0(pObj)) && Vec_PtrEntry(vCopy0, Aig_ObjFaninId0(pObj)) == NULL ) |
| { |
| pTemp = Aig_ObjCreateCi( pNew ); |
| Vec_PtrWriteEntry( vCopy0, Aig_ObjFaninId0(pObj), pTemp ); |
| Vec_PtrWriteEntry( vCopy1, Aig_ObjFaninId0(pObj), pTemp ); |
| } |
| if ( Saig_ObjIsPi(p->pAig, Aig_ObjFanin1(pObj)) && Vec_PtrEntry(vCopy0, Aig_ObjFaninId1(pObj)) == NULL ) |
| { |
| pTemp = Aig_ObjCreateCi( pNew ); |
| Vec_PtrWriteEntry( vCopy0, Aig_ObjFaninId1(pObj), pTemp ); |
| Vec_PtrWriteEntry( vCopy1, Aig_ObjFaninId1(pObj), pTemp ); |
| } |
| } |
| // construct AIGs for the nodes |
| Vec_PtrForEachEntry( Aig_Obj_t *, p->vVisited, pObj, i ) |
| { |
| pTemp = Aig_And( pNew, Aig_ObjChild0CopyVec(vCopy0, pObj), Aig_ObjChild1CopyVec(vCopy0, pObj) ); |
| Vec_PtrWriteEntry( vCopy0, Aig_ObjId(pObj), pTemp ); |
| pTemp = Aig_And( pNew, Aig_ObjChild0CopyVec(vCopy1, pObj), Aig_ObjChild1CopyVec(vCopy1, pObj) ); |
| Vec_PtrWriteEntry( vCopy1, Aig_ObjId(pObj), pTemp ); |
| } |
| // construct the care miter |
| pMiter = Aig_ManConst0( pNew ); |
| Vec_PtrForEachEntry( Aig_Obj_t *, p->vFanout, pObj, i ) |
| { |
| pTemp = Aig_Exor( pNew, (Aig_Obj_t *)Vec_PtrEntry(vCopy0, Aig_ObjId(pObj)), (Aig_Obj_t *)Vec_PtrEntry(vCopy1, Aig_ObjId(pObj)) ); |
| pMiter = Aig_Or( pNew, pMiter, pTemp ); |
| } |
| return pMiter; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Derives AIG for clock-gating.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Aig_Man_t * Cgt_ManDeriveAigForGating( Cgt_Man_t * p ) |
| { |
| Aig_Man_t * pNew; |
| Aig_Obj_t * pObj, * pObjLi, * pObjLo, * pCare, * pMiter; |
| Vec_Ptr_t * vCopy0, * vCopy1; |
| int i; |
| assert( Aig_ManRegNum(p->pAig) ); |
| pNew = Aig_ManStart( Aig_ManObjNumMax(p->pAig) ); |
| pNew->pName = Abc_UtilStrsav( "CG_miter" ); |
| // build the first frame |
| Aig_ManConst1(p->pAig)->pData = Aig_ManConst1(pNew); |
| Aig_ManForEachCi( p->pAig, pObj, i ) |
| pObj->pData = Aig_ObjCreateCi( pNew ); |
| Aig_ManForEachNode( p->pAig, pObj, i ) |
| pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); |
| // Saig_ManForEachPo( p->pAig, pObj, i ) |
| // pObj->pData = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); |
| if ( p->pPars->nOdcMax > 0 ) |
| { |
| // create storage for observability conditions |
| vCopy0 = Vec_PtrStart( Aig_ManObjNumMax(p->pAig) ); |
| vCopy1 = Vec_PtrStart( Aig_ManObjNumMax(p->pAig) ); |
| // initialize register outputs |
| Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i ) |
| { |
| Vec_PtrWriteEntry( vCopy0, Aig_ObjId(pObjLo), Aig_ObjChild0Copy(pObjLi) ); |
| Vec_PtrWriteEntry( vCopy1, Aig_ObjId(pObjLo), Aig_ObjChild0Copy(pObjLi) ); |
| } |
| // compute observability condition for each latch output |
| Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i ) |
| { |
| // set the constants |
| Vec_PtrWriteEntry( vCopy0, Aig_ObjId(pObjLo), Aig_ManConst0(pNew) ); |
| Vec_PtrWriteEntry( vCopy1, Aig_ObjId(pObjLo), Aig_ManConst1(pNew) ); |
| // compute condition |
| pCare = Cgt_ManConstructCareCondition( p, pNew, pObjLo, vCopy0, vCopy1 ); |
| // restore the values |
| Vec_PtrWriteEntry( vCopy0, Aig_ObjId(pObjLo), Aig_ObjChild0Copy(pObjLi) ); |
| Vec_PtrWriteEntry( vCopy1, Aig_ObjId(pObjLo), Aig_ObjChild0Copy(pObjLi) ); |
| // compute the miter |
| pMiter = Aig_Exor( pNew, (Aig_Obj_t *)pObjLo->pData, Aig_ObjChild0Copy(pObjLi) ); |
| pMiter = Aig_And( pNew, pMiter, pCare ); |
| pObjLi->pData = Aig_ObjCreateCo( pNew, pMiter ); |
| } |
| Vec_PtrFree( vCopy0 ); |
| Vec_PtrFree( vCopy1 ); |
| } |
| else |
| { |
| // construct clock-gating miters for each register input |
| Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i ) |
| { |
| pMiter = Aig_Exor( pNew, (Aig_Obj_t *)pObjLo->pData, Aig_ObjChild0Copy(pObjLi) ); |
| pObjLi->pData = Aig_ObjCreateCo( pNew, pMiter ); |
| } |
| } |
| Aig_ManCleanup( pNew ); |
| Aig_ManSetCioIds( pNew ); |
| return pNew; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Adds relevant constraints.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Aig_Obj_t * Cgt_ManConstructCare_rec( Aig_Man_t * pCare, Aig_Obj_t * pObj, Aig_Man_t * pNew ) |
| { |
| Aig_Obj_t * pObj0, * pObj1; |
| if ( Aig_ObjIsTravIdCurrent( pCare, pObj ) ) |
| return (Aig_Obj_t *)pObj->pData; |
| Aig_ObjSetTravIdCurrent( pCare, pObj ); |
| if ( Aig_ObjIsCi(pObj) ) |
| return (Aig_Obj_t *)(pObj->pData = NULL); |
| pObj0 = Cgt_ManConstructCare_rec( pCare, Aig_ObjFanin0(pObj), pNew ); |
| if ( pObj0 == NULL ) |
| return (Aig_Obj_t *)(pObj->pData = NULL); |
| pObj1 = Cgt_ManConstructCare_rec( pCare, Aig_ObjFanin1(pObj), pNew ); |
| if ( pObj1 == NULL ) |
| return (Aig_Obj_t *)(pObj->pData = NULL); |
| pObj0 = Aig_NotCond( pObj0, Aig_ObjFaninC0(pObj) ); |
| pObj1 = Aig_NotCond( pObj1, Aig_ObjFaninC1(pObj) ); |
| return (Aig_Obj_t *)(pObj->pData = Aig_And( pNew, pObj0, pObj1 )); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Builds constraints belonging to the given partition.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Cgt_ManConstructCare( Aig_Man_t * pNew, Aig_Man_t * pCare, Vec_Vec_t * vSuppsInv, Vec_Ptr_t * vLeaves ) |
| { |
| Vec_Int_t * vOuts; |
| Aig_Obj_t * pLeaf, * pPi, * pPo, * pObjAig; |
| int i, k, iOut; |
| // go through the PIs of the partition |
| // label the corresponding PIs of the care set |
| Aig_ManIncrementTravId( pCare ); |
| Vec_PtrForEachEntry( Aig_Obj_t *, vLeaves, pLeaf, i ) |
| { |
| pPi = Aig_ManCi( pCare, Aig_ObjCioId(pLeaf) ); |
| Aig_ObjSetTravIdCurrent( pCare, pPi ); |
| pPi->pData = pLeaf->pData; |
| } |
| // construct the constraints |
| Vec_PtrForEachEntry( Aig_Obj_t *, vLeaves, pLeaf, i ) |
| { |
| vOuts = Vec_VecEntryInt( vSuppsInv, Aig_ObjCioId(pLeaf) ); |
| Vec_IntForEachEntry( vOuts, iOut, k ) |
| { |
| pPo = Aig_ManCo( pCare, iOut ); |
| if ( Aig_ObjIsTravIdCurrent( pCare, pPo ) ) |
| continue; |
| Aig_ObjSetTravIdCurrent( pCare, pPo ); |
| if ( Aig_ObjFanin0(pPo) == Aig_ManConst1(pCare) ) |
| continue; |
| pObjAig = Cgt_ManConstructCare_rec( pCare, Aig_ObjFanin0(pPo), pNew ); |
| if ( pObjAig == NULL ) |
| continue; |
| pObjAig = Aig_NotCond( pObjAig, Aig_ObjFaninC0(pPo) ); |
| Aig_ObjCreateCo( pNew, pObjAig ); |
| } |
| } |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Duplicates the AIG recursively.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Aig_Obj_t * Cgt_ManDupPartition_rec( Aig_Man_t * pNew, Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Ptr_t * vLeaves ) |
| { |
| if ( Aig_ObjIsTravIdCurrent(pAig, pObj) ) |
| return (Aig_Obj_t *)pObj->pData; |
| Aig_ObjSetTravIdCurrent(pAig, pObj); |
| if ( Aig_ObjIsCi(pObj) ) |
| { |
| pObj->pData = Aig_ObjCreateCi( pNew ); |
| Vec_PtrPush( vLeaves, pObj ); |
| return (Aig_Obj_t *)pObj->pData; |
| } |
| Cgt_ManDupPartition_rec( pNew, pAig, Aig_ObjFanin0(pObj), vLeaves ); |
| Cgt_ManDupPartition_rec( pNew, pAig, Aig_ObjFanin1(pObj), vLeaves ); |
| return (Aig_Obj_t *)(pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) )); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Duplicates register outputs starting from the given one.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Aig_Man_t * Cgt_ManDupPartition( Aig_Man_t * pFrame, int nVarsMin, int nFlopsMin, int iStart, Aig_Man_t * pCare, Vec_Vec_t * vSuppsInv, int * pnOutputs ) |
| { |
| Vec_Ptr_t * vRoots, * vLeaves, * vPos; |
| Aig_Man_t * pNew; |
| Aig_Obj_t * pObj; |
| int i; |
| assert( Aig_ManRegNum(pFrame) == 0 ); |
| vRoots = Vec_PtrAlloc( 100 ); |
| vLeaves = Vec_PtrAlloc( 100 ); |
| vPos = Vec_PtrAlloc( 100 ); |
| pNew = Aig_ManStart( nVarsMin ); |
| pNew->pName = Abc_UtilStrsav( "partition" ); |
| Aig_ManIncrementTravId( pFrame ); |
| Aig_ManConst1(pFrame)->pData = Aig_ManConst1(pNew); |
| Aig_ObjSetTravIdCurrent( pFrame, Aig_ManConst1(pFrame) ); |
| for ( i = iStart; i < iStart + nFlopsMin && i < Aig_ManCoNum(pFrame); i++ ) |
| { |
| pObj = Aig_ManCo( pFrame, i ); |
| Cgt_ManDupPartition_rec( pNew, pFrame, Aig_ObjFanin0(pObj), vLeaves ); |
| Vec_PtrPush( vRoots, Aig_ObjChild0Copy(pObj) ); |
| Vec_PtrPush( vPos, pObj ); |
| } |
| for ( ; Aig_ManObjNum(pNew) < nVarsMin && i < Aig_ManCoNum(pFrame); i++ ) |
| { |
| pObj = Aig_ManCo( pFrame, i ); |
| Cgt_ManDupPartition_rec( pNew, pFrame, Aig_ObjFanin0(pObj), vLeaves ); |
| Vec_PtrPush( vRoots, Aig_ObjChild0Copy(pObj) ); |
| Vec_PtrPush( vPos, pObj ); |
| } |
| assert( nFlopsMin >= Vec_PtrSize(vRoots) || Vec_PtrSize(vRoots) >= nFlopsMin ); |
| // create constaints |
| if ( pCare ) |
| Cgt_ManConstructCare( pNew, pCare, vSuppsInv, vLeaves ); |
| // create POs |
| Vec_PtrForEachEntry( Aig_Obj_t *, vPos, pObj, i ) |
| pObj->pData = (Aig_Obj_t *)Aig_ObjCreateCo( pNew, (Aig_Obj_t *)Vec_PtrEntry(vRoots, i) ); |
| if ( pnOutputs != NULL ) |
| *pnOutputs = Vec_PtrSize( vPos ); |
| Vec_PtrFree( vRoots ); |
| Vec_PtrFree( vLeaves ); |
| Vec_PtrFree( vPos ); |
| return pNew; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Implements one clock-gate.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Aig_Obj_t * Cgt_ManBuildClockGate( Aig_Man_t * pNew, Vec_Ptr_t * vGates ) |
| { |
| Aig_Obj_t * pGate, * pTotal; |
| int i; |
| assert( Vec_PtrSize(vGates) > 0 ); |
| pTotal = Aig_ManConst0(pNew); |
| Vec_PtrForEachEntry( Aig_Obj_t *, vGates, pGate, i ) |
| { |
| if ( Aig_Regular(pGate)->pNext ) |
| pGate = Aig_NotCond( Aig_Regular(pGate)->pNext, Aig_IsComplement(pGate) ); |
| else |
| pGate = Aig_NotCond( (Aig_Obj_t *)Aig_Regular(pGate)->pData, Aig_IsComplement(pGate) ); |
| pTotal = Aig_Or( pNew, pTotal, pGate ); |
| } |
| return pTotal; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Derives AIG after clock-gating.] |
| |
| Description [The array contains, for each flop, its gate if present.] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Aig_Man_t * Cgt_ManDeriveGatedAig( Aig_Man_t * pAig, Vec_Vec_t * vGates, int fReduce, int * pnUsedNodes ) |
| { |
| Aig_Man_t * pNew; |
| Aig_Obj_t * pObj, * pObjNew, * pObjLi, * pObjLo, * pGateNew; |
| Vec_Ptr_t * vOne; |
| int i, k; |
| Aig_ManCleanNext( pAig ); |
| // label nodes |
| Vec_VecForEachEntry( Aig_Obj_t *, vGates, pObj, i, k ) |
| { |
| if ( Aig_IsComplement(pObj) ) |
| Aig_Regular(pObj)->fMarkB = 1; |
| else |
| Aig_Regular(pObj)->fMarkA = 1; |
| } |
| // construct AIG |
| assert( Aig_ManRegNum(pAig) ); |
| pNew = Aig_ManStart( Aig_ManObjNumMax(pAig) ); |
| pNew->pName = Abc_UtilStrsav( pAig->pName ); |
| pNew->pSpec = Abc_UtilStrsav( pAig->pSpec ); |
| Aig_ManConst1(pAig)->pData = Aig_ManConst1(pNew); |
| Aig_ManForEachCi( pAig, pObj, i ) |
| pObj->pData = Aig_ObjCreateCi( pNew ); |
| if ( fReduce ) |
| { |
| Aig_ManForEachNode( pAig, pObj, i ) |
| { |
| assert( !(pObj->fMarkA && pObj->fMarkB) ); |
| pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); |
| if ( pObj->fMarkA ) |
| { |
| pObj->pNext = (Aig_Obj_t *)pObj->pData; |
| pObj->pData = Aig_ManConst0(pNew); |
| } |
| else if ( pObj->fMarkB ) |
| { |
| pObj->pNext = (Aig_Obj_t *)pObj->pData; |
| pObj->pData = Aig_ManConst1(pNew); |
| } |
| } |
| } |
| else |
| { |
| Aig_ManForEachNode( pAig, pObj, i ) |
| pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); |
| } |
| if ( pnUsedNodes != NULL ) |
| *pnUsedNodes = Aig_ManNodeNum(pNew); |
| Saig_ManForEachPo( pAig, pObj, i ) |
| pObj->pData = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); |
| Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i ) |
| { |
| vOne = Vec_VecEntry( vGates, i ); |
| if ( Vec_PtrSize(vOne) == 0 ) |
| pObjNew = Aig_ObjChild0Copy(pObjLi); |
| else |
| { |
| // pGateNew = Aig_NotCond( Aig_Regular(pGate)->pData, Aig_IsComplement(pGate) ); |
| pGateNew = Cgt_ManBuildClockGate( pNew, vOne ); |
| pObjNew = Aig_Mux( pNew, pGateNew, (Aig_Obj_t *)pObjLo->pData, Aig_ObjChild0Copy(pObjLi) ); |
| } |
| pObjLi->pData = Aig_ObjCreateCo( pNew, pObjNew ); |
| } |
| Aig_ManCleanup( pNew ); |
| Aig_ManSetRegNum( pNew, Aig_ManRegNum(pAig) ); |
| // unlabel nodes |
| Aig_ManCleanMarkAB( pAig ); |
| Aig_ManCleanNext( pAig ); |
| return pNew; |
| } |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// END OF FILE /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| |
| ABC_NAMESPACE_IMPL_END |
| |