mirror of https://github.com/YosysHQ/abc.git
329 lines
11 KiB
C
329 lines
11 KiB
C
/**CFile****************************************************************
|
|
|
|
FileName [cgtCore.c]
|
|
|
|
SystemName [ABC: Logic synthesis and verification system.]
|
|
|
|
PackageName [Clock gating package.]
|
|
|
|
Synopsis []
|
|
|
|
Author [Alan Mishchenko]
|
|
|
|
Affiliation [UC Berkeley]
|
|
|
|
Date [Ver. 1.0. Started - June 20, 2005.]
|
|
|
|
Revision [$Id: cgtCore.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
|
|
|
|
***********************************************************************/
|
|
|
|
#include "cgtInt.h"
|
|
#include "misc/bar/bar.h"
|
|
|
|
ABC_NAMESPACE_IMPL_START
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// DECLARATIONS ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// FUNCTION DEFINITIONS ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [This procedure sets default parameters.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Cgt_SetDefaultParams( Cgt_Par_t * p )
|
|
{
|
|
memset( p, 0, sizeof(Cgt_Par_t) );
|
|
p->nLevelMax = 25; // the max number of levels to look for clock-gates
|
|
p->nCandMax = 1000; // the max number of candidates at each node
|
|
p->nOdcMax = 0; // the max number of ODC levels to consider
|
|
p->nConfMax = 10; // the max number of conflicts at a node
|
|
p->nVarsMin = 1000; // the min number of vars to recycle the SAT solver
|
|
p->nFlopsMin = 10; // the min number of flops to recycle the SAT solver
|
|
p->fAreaOnly = 0; // derive clock-gating to minimize area
|
|
p->fVerbose = 0; // verbosity flag
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Returns 1 if simulation does not filter out this candidate.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
int Cgt_SimulationFilter( Cgt_Man_t * p, Aig_Obj_t * pCandPart, Aig_Obj_t * pMiterPart )
|
|
{
|
|
unsigned * pInfoCand, * pInfoMiter;
|
|
int w, nWords = Abc_BitWordNum( p->nPatts );
|
|
pInfoCand = (unsigned *)Vec_PtrEntry( p->vPatts, Aig_ObjId(Aig_Regular(pCandPart)) );
|
|
pInfoMiter = (unsigned *)Vec_PtrEntry( p->vPatts, Aig_ObjId(pMiterPart) );
|
|
// C => !M -- true is the same as C & M -- false
|
|
if ( !Aig_IsComplement(pCandPart) )
|
|
{
|
|
for ( w = 0; w < nWords; w++ )
|
|
if ( pInfoCand[w] & pInfoMiter[w] )
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
for ( w = 0; w < nWords; w++ )
|
|
if ( ~pInfoCand[w] & pInfoMiter[w] )
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Saves one simulation pattern.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Cgt_SimulationRecord( Cgt_Man_t * p )
|
|
{
|
|
Aig_Obj_t * pObj;
|
|
int i;
|
|
Aig_ManForEachObj( p->pPart, pObj, i )
|
|
if ( sat_solver_var_value( p->pSat, p->pCnf->pVarNums[i] ) )
|
|
Abc_InfoSetBit( (unsigned *)Vec_PtrEntry(p->vPatts, i), p->nPatts );
|
|
p->nPatts++;
|
|
if ( p->nPatts == 32 * p->nPattWords )
|
|
{
|
|
Vec_PtrReallocSimInfo( p->vPatts );
|
|
Vec_PtrCleanSimInfo( p->vPatts, p->nPattWords, 2 * p->nPattWords );
|
|
p->nPattWords *= 2;
|
|
}
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Performs clock-gating for the AIG.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Cgt_ClockGatingRangeCheck( Cgt_Man_t * p, int iStart, int nOutputs )
|
|
{
|
|
Vec_Ptr_t * vNodes = p->vFanout;
|
|
Aig_Obj_t * pMiter, * pCand, * pMiterFrame, * pCandFrame, * pMiterPart, * pCandPart;
|
|
int i, k, RetValue, nCalls;
|
|
assert( Vec_VecSize(p->vGatesAll) == Aig_ManCoNum(p->pFrame) );
|
|
// go through all the registers inputs of this range
|
|
for ( i = iStart; i < iStart + nOutputs; i++ )
|
|
{
|
|
nCalls = p->nCalls;
|
|
pMiter = Saig_ManLi( p->pAig, i );
|
|
Cgt_ManDetectCandidates( p->pAig, p->vUseful, Aig_ObjFanin0(pMiter), p->pPars->nLevelMax, vNodes );
|
|
// go through the candidates of this PO
|
|
Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pCand, k )
|
|
{
|
|
// get the corresponding nodes from the frames
|
|
pCandFrame = (Aig_Obj_t *)pCand->pData;
|
|
pMiterFrame = (Aig_Obj_t *)pMiter->pData;
|
|
// get the corresponding nodes from the part
|
|
pCandPart = (Aig_Obj_t *)pCandFrame->pData;
|
|
pMiterPart = (Aig_Obj_t *)pMiterFrame->pData;
|
|
// try direct polarity
|
|
if ( Cgt_SimulationFilter( p, pCandPart, pMiterPart ) )
|
|
{
|
|
RetValue = Cgt_CheckImplication( p, pCandPart, pMiterPart );
|
|
if ( RetValue == 1 )
|
|
{
|
|
Vec_VecPush( p->vGatesAll, i, pCand );
|
|
continue;
|
|
}
|
|
if ( RetValue == 0 )
|
|
Cgt_SimulationRecord( p );
|
|
}
|
|
else
|
|
p->nCallsFiltered++;
|
|
// try reverse polarity
|
|
if ( Cgt_SimulationFilter( p, Aig_Not(pCandPart), pMiterPart ) )
|
|
{
|
|
RetValue = Cgt_CheckImplication( p, Aig_Not(pCandPart), pMiterPart );
|
|
if ( RetValue == 1 )
|
|
{
|
|
Vec_VecPush( p->vGatesAll, i, Aig_Not(pCand) );
|
|
continue;
|
|
}
|
|
if ( RetValue == 0 )
|
|
Cgt_SimulationRecord( p );
|
|
}
|
|
else
|
|
p->nCallsFiltered++;
|
|
}
|
|
|
|
if ( p->pPars->fVerbose )
|
|
{
|
|
// printf( "Flop %3d : Cand = %4d. Gate = %4d. SAT calls = %3d.\n",
|
|
// i, Vec_PtrSize(vNodes), Vec_PtrSize(Vec_VecEntry(p->vGatesAll, i)), p->nCalls-nCalls );
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Performs clock-gating for the AIG.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
int Cgt_ClockGatingRange( Cgt_Man_t * p, int iStart )
|
|
{
|
|
int nOutputs, iStop;
|
|
abctime clk, clkTotal = Abc_Clock();
|
|
int nCallsUnsat = p->nCallsUnsat;
|
|
int nCallsSat = p->nCallsSat;
|
|
int nCallsUndec = p->nCallsUndec;
|
|
int nCallsFiltered = p->nCallsFiltered;
|
|
clk = Abc_Clock();
|
|
p->pPart = Cgt_ManDupPartition( p->pFrame, p->pPars->nVarsMin, p->pPars->nFlopsMin, iStart, p->pCare, p->vSuppsInv, &nOutputs );
|
|
p->pCnf = Cnf_DeriveSimple( p->pPart, nOutputs );
|
|
p->pSat = (sat_solver *)Cnf_DataWriteIntoSolver( p->pCnf, 1, 0 );
|
|
sat_solver_compress( p->pSat );
|
|
p->vPatts = Vec_PtrAllocSimInfo( Aig_ManObjNumMax(p->pPart), p->nPattWords );
|
|
Vec_PtrCleanSimInfo( p->vPatts, 0, p->nPattWords );
|
|
p->timePrepare += Abc_Clock() - clk;
|
|
Cgt_ClockGatingRangeCheck( p, iStart, nOutputs );
|
|
iStop = iStart + nOutputs;
|
|
if ( p->pPars->fVeryVerbose )
|
|
{
|
|
printf( "%5d : D =%4d. C =%5d. Var =%6d. Pr =%5d. Cex =%5d. F =%4d. Saved =%6d. ",
|
|
iStart, iStop-iStart, Aig_ManCoNum(p->pPart)-nOutputs, p->pSat->size,
|
|
p->nCallsUnsat-nCallsUnsat,
|
|
p->nCallsSat -nCallsSat,
|
|
p->nCallsUndec-nCallsUndec,
|
|
p->nCallsFiltered-nCallsFiltered );
|
|
ABC_PRT( "Time", Abc_Clock() - clkTotal );
|
|
}
|
|
Cgt_ManClean( p );
|
|
p->nRecycles++;
|
|
return iStop;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Performs clock-gating for the AIG.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
Vec_Vec_t * Cgt_ClockGatingCandidates( Aig_Man_t * pAig, Aig_Man_t * pCare, Cgt_Par_t * pPars, Vec_Int_t * vUseful )
|
|
{
|
|
Bar_Progress_t * pProgress = NULL;
|
|
Cgt_Par_t Pars;
|
|
Cgt_Man_t * p;
|
|
Vec_Vec_t * vGatesAll;
|
|
int iStart;
|
|
abctime clk = Abc_Clock(), clkTotal = Abc_Clock();
|
|
// reset random numbers
|
|
Aig_ManRandom( 1 );
|
|
if ( pPars == NULL )
|
|
Cgt_SetDefaultParams( pPars = &Pars );
|
|
p = Cgt_ManCreate( pAig, pCare, pPars );
|
|
p->vUseful = vUseful;
|
|
p->pFrame = Cgt_ManDeriveAigForGating( p );
|
|
p->timeAig += Abc_Clock() - clk;
|
|
assert( Aig_ManCoNum(p->pFrame) == Saig_ManRegNum(p->pAig) );
|
|
pProgress = Bar_ProgressStart( stdout, Aig_ManCoNum(p->pFrame) );
|
|
for ( iStart = 0; iStart < Aig_ManCoNum(p->pFrame); )
|
|
{
|
|
Bar_ProgressUpdate( pProgress, iStart, NULL );
|
|
iStart = Cgt_ClockGatingRange( p, iStart );
|
|
}
|
|
Bar_ProgressStop( pProgress );
|
|
vGatesAll = p->vGatesAll;
|
|
p->vGatesAll = NULL;
|
|
p->timeTotal = Abc_Clock() - clkTotal;
|
|
Cgt_ManStop( p );
|
|
return vGatesAll;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Performs clock-gating for the AIG.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
Vec_Vec_t * Cgt_ClockGatingInt( Aig_Man_t * pAig, Aig_Man_t * pCare, Cgt_Par_t * pPars, Vec_Int_t * vUseful )
|
|
{
|
|
Vec_Vec_t * vGatesAll, * vGates;
|
|
vGatesAll = Cgt_ClockGatingCandidates( pAig, pCare, pPars, vUseful );
|
|
if ( pPars->fAreaOnly )
|
|
vGates = Cgt_ManDecideArea( pAig, vGatesAll, pPars->nOdcMax, pPars->fVerbose );
|
|
else
|
|
vGates = Cgt_ManDecideSimple( pAig, vGatesAll, pPars->nOdcMax, pPars->fVerbose );
|
|
Vec_VecFree( vGatesAll );
|
|
return vGates;
|
|
}
|
|
Aig_Man_t * Cgt_ClockGating( Aig_Man_t * pAig, Aig_Man_t * pCare, Cgt_Par_t * pPars )
|
|
{
|
|
Aig_Man_t * pGated;
|
|
Vec_Vec_t * vGates = Cgt_ClockGatingInt( pAig, pCare, pPars, NULL );
|
|
int nNodesUsed;
|
|
if ( pPars->fVerbose )
|
|
{
|
|
// printf( "Before CG: " );
|
|
// Aig_ManPrintStats( pAig );
|
|
}
|
|
pGated = Cgt_ManDeriveGatedAig( pAig, vGates, pPars->fAreaOnly, &nNodesUsed );
|
|
if ( pPars->fVerbose )
|
|
{
|
|
// printf( "After CG: " );
|
|
// Aig_ManPrintStats( pGated );
|
|
printf( "Nodes: Before CG = %6d. After CG = %6d. (%6.2f %%). Total after CG = %6d.\n",
|
|
Aig_ManNodeNum(pAig), nNodesUsed,
|
|
100.0*nNodesUsed/Aig_ManNodeNum(pAig),
|
|
Aig_ManNodeNum(pGated) );
|
|
}
|
|
Vec_VecFree( vGates );
|
|
return pGated;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// END OF FILE ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
ABC_NAMESPACE_IMPL_END
|
|
|