/**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