| /**CFile**************************************************************** |
| |
| FileName [cgtMan.c] |
| |
| SystemName [ABC: Logic synthesis and verification system.] |
| |
| PackageName [Clock gating package.] |
| |
| Synopsis [Decide what gate to use for what flop.] |
| |
| Author [Alan Mishchenko] |
| |
| Affiliation [UC Berkeley] |
| |
| Date [Ver. 1.0. Started - June 20, 2005.] |
| |
| Revision [$Id: cgtMan.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] |
| |
| ***********************************************************************/ |
| |
| #include "cgtInt.h" |
| #include "proof/ssw/sswInt.h" |
| |
| ABC_NAMESPACE_IMPL_START |
| |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// DECLARATIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| extern int Ssw_SmlCheckXorImplication( Ssw_Sml_t * p, Aig_Obj_t * pObjLi, Aig_Obj_t * pObjLo, Aig_Obj_t * pCand ); |
| extern int Ssw_SmlCountXorImplication( Ssw_Sml_t * p, Aig_Obj_t * pObjLi, Aig_Obj_t * pObjLo, Aig_Obj_t * pCand ); |
| extern int Ssw_SmlCountEqual( Ssw_Sml_t * p, Aig_Obj_t * pObjLi, Aig_Obj_t * pObjLo ); |
| extern int Ssw_SmlNodeCountOnesReal( Ssw_Sml_t * p, Aig_Obj_t * pObj ); |
| extern int Ssw_SmlNodeCountOnesRealVec( Ssw_Sml_t * p, Vec_Ptr_t * vObjs ); |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// FUNCTION DEFINITIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| /**Function************************************************************* |
| |
| Synopsis [Collects POs in the transitive fanout.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Cgt_ManCollectFanoutPos_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Ptr_t * vFanout ) |
| { |
| Aig_Obj_t * pFanout; |
| int f, iFanout = -1; |
| if ( Aig_ObjIsTravIdCurrent(pAig, pObj) ) |
| return; |
| Aig_ObjSetTravIdCurrent(pAig, pObj); |
| if ( Aig_ObjIsCo(pObj) ) |
| { |
| Vec_PtrPush( vFanout, pObj ); |
| return; |
| } |
| Aig_ObjForEachFanout( pAig, pObj, pFanout, iFanout, f ) |
| Cgt_ManCollectFanoutPos_rec( pAig, pFanout, vFanout ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Collects POs in the transitive fanout.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Cgt_ManCollectFanoutPos( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Ptr_t * vFanout ) |
| { |
| Vec_PtrClear( vFanout ); |
| Aig_ManIncrementTravId( pAig ); |
| Cgt_ManCollectFanoutPos_rec( pAig, pObj, vFanout ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Checks if all PO fanouts can be gated by this node.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Cgt_ManCheckGateComplete( Aig_Man_t * pAig, Vec_Vec_t * vGatesAll, Aig_Obj_t * pGate, Vec_Ptr_t * vFanout ) |
| { |
| Vec_Ptr_t * vGates; |
| Aig_Obj_t * pObj; |
| int i; |
| Vec_PtrForEachEntry( Aig_Obj_t *, vFanout, pObj, i ) |
| { |
| if ( Saig_ObjIsPo(pAig, pObj) ) |
| return 0; |
| vGates = Vec_VecEntry( vGatesAll, Aig_ObjCioId(pObj) - Saig_ManPoNum(pAig) ); |
| if ( Vec_PtrFind( vGates, pGate ) == -1 ) |
| return 0; |
| } |
| return 1; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Computes the set of complete clock gates.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Vec_Ptr_t * Cgt_ManCompleteGates( Aig_Man_t * pAig, Vec_Vec_t * vGatesAll, int nOdcMax, int fVerbose ) |
| { |
| Vec_Ptr_t * vFanout, * vGatesFull; |
| Aig_Obj_t * pGate, * pGateR; |
| int i, k; |
| vFanout = Vec_PtrAlloc( 100 ); |
| vGatesFull = Vec_PtrAlloc( 100 ); |
| Vec_VecForEachEntry( Aig_Obj_t *, vGatesAll, pGate, i, k ) |
| { |
| pGateR = Aig_Regular(pGate); |
| if ( pGateR->fMarkA ) |
| continue; |
| pGateR->fMarkA = 1; |
| Cgt_ManCollectFanoutPos( pAig, pGateR, vFanout ); |
| if ( Cgt_ManCheckGateComplete( pAig, vGatesAll, pGate, vFanout ) ) |
| Vec_PtrPush( vGatesFull, pGate ); |
| } |
| Vec_PtrFree( vFanout ); |
| Vec_VecForEachEntry( Aig_Obj_t *, vGatesAll, pGate, i, k ) |
| Aig_Regular(pGate)->fMarkA = 0; |
| return vGatesFull; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Calculates coverage.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| float Cgt_ManComputeCoverage( Aig_Man_t * pAig, Vec_Vec_t * vGates ) |
| { |
| int nFrames = 32; |
| int nWords = 1; |
| Ssw_Sml_t * pSml; |
| Vec_Ptr_t * vOne; |
| int i, nTransSaved = 0; |
| pSml = Ssw_SmlSimulateSeq( pAig, 0, nFrames, nWords ); |
| Vec_VecForEachLevel( vGates, vOne, i ) |
| nTransSaved += Ssw_SmlNodeCountOnesRealVec( pSml, vOne ); |
| Ssw_SmlStop( pSml ); |
| return (float)100.0*nTransSaved/32/nFrames/nWords/Vec_VecSize(vGates); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Chooses what clock-gate to use for this register.] |
| |
| Description [Currently uses the naive approach: For each register, |
| choose the clock gate, which covers most of the transitions.] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Vec_Vec_t * Cgt_ManDecideSimple( Aig_Man_t * pAig, Vec_Vec_t * vGatesAll, int nOdcMax, int fVerbose ) |
| { |
| int nFrames = 32; |
| int nWords = 1; |
| Ssw_Sml_t * pSml; |
| Vec_Vec_t * vGates; |
| Vec_Ptr_t * vCands; |
| Aig_Obj_t * pObjLi, * pObjLo, * pCand, * pCandBest; |
| int i, k, nHitsCur, nHitsMax, Counter = 0; |
| abctime clk = Abc_Clock(); |
| int nTransTotal = 0, nTransSaved = 0; |
| vGates = Vec_VecStart( Saig_ManRegNum(pAig) ); |
| pSml = Ssw_SmlSimulateSeq( pAig, 0, nFrames, nWords ); |
| Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i ) |
| { |
| nHitsMax = 0; |
| pCandBest = NULL; |
| vCands = Vec_VecEntry( vGatesAll, i ); |
| Vec_PtrForEachEntry( Aig_Obj_t *, vCands, pCand, k ) |
| { |
| // check if this is indeed a clock-gate |
| if ( nOdcMax == 0 && !Ssw_SmlCheckXorImplication( pSml, pObjLi, pObjLo, pCand ) ) |
| printf( "Clock gate candidate is invalid!\n" ); |
| // find its characteristic number |
| nHitsCur = Ssw_SmlNodeCountOnesReal( pSml, pCand ); |
| if ( nHitsMax < nHitsCur ) |
| { |
| nHitsMax = nHitsCur; |
| pCandBest = pCand; |
| } |
| } |
| if ( pCandBest != NULL ) |
| { |
| Vec_VecPush( vGates, i, pCandBest ); |
| Counter++; |
| nTransSaved += nHitsMax; |
| } |
| nTransTotal += 32 * nFrames * nWords; |
| } |
| Ssw_SmlStop( pSml ); |
| if ( fVerbose ) |
| { |
| printf( "Gating signals = %6d. Gated flops = %6d. (Total flops = %6d.)\n", |
| Vec_VecSizeSize(vGatesAll), Counter, Saig_ManRegNum(pAig) ); |
| // printf( "Gated transitions = %5.2f %%. (%5.2f %%.) ", |
| // 100.0*nTransSaved/nTransTotal, Cgt_ManComputeCoverage(pAig, vGates) ); |
| printf( "Gated transitions = %5.2f %%. ", Cgt_ManComputeCoverage(pAig, vGates) ); |
| ABC_PRT( "Time", Abc_Clock() - clk ); |
| } |
| /* |
| { |
| Vec_Ptr_t * vCompletes; |
| vCompletes = Cgt_ManCompleteGates( pAig, vGatesAll, nOdcMax, fVerbose ); |
| printf( "Complete gates = %d. \n", Vec_PtrSize(vCompletes) ); |
| Vec_PtrFree( vCompletes ); |
| } |
| */ |
| return vGates; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Computes the set of complete clock gates.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Vec_Vec_t * Cgt_ManDecideArea( Aig_Man_t * pAig, Vec_Vec_t * vGatesAll, int nOdcMax, int fVerbose ) |
| { |
| Vec_Vec_t * vGates; |
| Vec_Ptr_t * vCompletes, * vOne; |
| Aig_Obj_t * pGate; |
| int i, k, Counter = 0; |
| abctime clk = Abc_Clock(); |
| // derive and label complete gates |
| vCompletes = Cgt_ManCompleteGates( pAig, vGatesAll, nOdcMax, fVerbose ); |
| // label complete gates |
| Vec_PtrForEachEntry( Aig_Obj_t *, vCompletes, pGate, i ) |
| Aig_Regular(pGate)->fMarkA = 1; |
| // select only complete gates |
| vGates = Vec_VecStart( Saig_ManRegNum(pAig) ); |
| Vec_VecForEachEntry( Aig_Obj_t *, vGatesAll, pGate, i, k ) |
| if ( Aig_Regular(pGate)->fMarkA ) |
| Vec_VecPush( vGates, i, pGate ); |
| // unlabel complete gates |
| Vec_PtrForEachEntry( Aig_Obj_t *, vCompletes, pGate, i ) |
| Aig_Regular(pGate)->fMarkA = 0; |
| // count the number of gated flops |
| Vec_VecForEachLevel( vGates, vOne, i ) |
| { |
| Counter += (int)(Vec_PtrSize(vOne) > 0); |
| // printf( "%d ", Vec_PtrSize(vOne) ); |
| } |
| // printf( "\n" ); |
| if ( fVerbose ) |
| { |
| printf( "Gating signals = %6d. Gated flops = %6d. (Total flops = %6d.)\n", |
| Vec_VecSizeSize(vGatesAll), Counter, Saig_ManRegNum(pAig) ); |
| printf( "Complete gates = %6d. Gated transitions = %5.2f %%. ", |
| Vec_PtrSize(vCompletes), Cgt_ManComputeCoverage(pAig, vGates) ); |
| ABC_PRT( "Time", Abc_Clock() - clk ); |
| } |
| Vec_PtrFree( vCompletes ); |
| return vGates; |
| } |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// END OF FILE /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| |
| ABC_NAMESPACE_IMPL_END |
| |