blob: ac463b4577a92c211967149c46b1fad6c8b176f6 [file] [log] [blame]
/**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