cgtCore.c 10.6 KB
Newer Older
Alan Mishchenko committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
/**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"
22
#include "misc/bar/bar.h"
Alan Mishchenko committed
23

24 25 26
ABC_NAMESPACE_IMPL_START


Alan Mishchenko committed
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
////////////////////////////////////////////////////////////////////////
///                        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) );
Alan Mishchenko committed
49
    p->nLevelMax  =    25;   // the max number of levels to look for clock-gates
Alan Mishchenko committed
50 51
    p->nCandMax   =  1000;   // the max number of candidates at each node
    p->nOdcMax    =     0;   // the max number of ODC levels to consider
Alan Mishchenko committed
52 53 54 55 56
    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  =     5;   // the min number of flops to recycle the SAT solver
    p->fAreaOnly  =     0;   // derive clock-gating to minimize area
    p->fVerbose   =     1;   // verbosity flag
Alan Mishchenko committed
57 58 59 60 61 62 63 64 65 66 67 68 69
}

/**Function*************************************************************

  Synopsis    [Returns 1 if simulation does not filter out this candidate.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
70
int Cgt_SimulationFilter( Cgt_Man_t * p, Aig_Obj_t * pCandPart, Aig_Obj_t * pMiterPart )
Alan Mishchenko committed
71 72
{
    unsigned * pInfoCand, * pInfoMiter;
73
    int w, nWords = Abc_BitWordNum( p->nPatts );  
74 75
    pInfoCand  = (unsigned *)Vec_PtrEntry( p->vPatts, Aig_ObjId(Aig_Regular(pCandPart)) );
    pInfoMiter = (unsigned *)Vec_PtrEntry( p->vPatts, Aig_ObjId(pMiterPart) );
Alan Mishchenko committed
76
    // C => !M -- true   is the same as    C & M -- false
Alan Mishchenko committed
77
    if ( !Aig_IsComplement(pCandPart) )
Alan Mishchenko committed
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
    {
        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] ) )
109
            Abc_InfoSetBit( (unsigned *)Vec_PtrEntry(p->vPatts, i), p->nPatts );
Alan Mishchenko committed
110 111 112 113
    p->nPatts++;
    if ( p->nPatts == 32 * p->nPattWords )
    {
        Vec_PtrReallocSimInfo( p->vPatts );
Alan Mishchenko committed
114
        Vec_PtrCleanSimInfo( p->vPatts, p->nPattWords, 2 * p->nPattWords );
Alan Mishchenko committed
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
        p->nPattWords *= 2;
    }
}

/**Function*************************************************************

  Synopsis    [Performs clock-gating for the AIG.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
130
void Cgt_ClockGatingRangeCheck( Cgt_Man_t * p, int iStart, int nOutputs )
Alan Mishchenko committed
131 132 133
{
    Vec_Ptr_t * vNodes = p->vFanout;
    Aig_Obj_t * pMiter, * pCand, * pMiterFrame, * pCandFrame, * pMiterPart, * pCandPart;
Alan Mishchenko committed
134
    int i, k, RetValue, nCalls;
135
    assert( Vec_VecSize(p->vGatesAll) == Aig_ManCoNum(p->pFrame) );
Alan Mishchenko committed
136
    // go through all the registers inputs of this range
Alan Mishchenko committed
137
    for ( i = iStart; i < iStart + nOutputs; i++ )
Alan Mishchenko committed
138
    {
Alan Mishchenko committed
139
        nCalls = p->nCalls;
Alan Mishchenko committed
140 141 142
        pMiter = Saig_ManLi( p->pAig, i );
        Cgt_ManDetectCandidates( p->pAig, Aig_ObjFanin0(pMiter), p->pPars->nLevelMax, vNodes );
        // go through the candidates of this PO
143
        Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pCand, k )
Alan Mishchenko committed
144 145
        {
            // get the corresponding nodes from the frames
146 147
            pCandFrame  = (Aig_Obj_t *)pCand->pData;
            pMiterFrame = (Aig_Obj_t *)pMiter->pData;
Alan Mishchenko committed
148
            // get the corresponding nodes from the part
149 150
            pCandPart   = (Aig_Obj_t *)pCandFrame->pData;
            pMiterPart  = (Aig_Obj_t *)pMiterFrame->pData;
Alan Mishchenko committed
151 152 153 154 155 156 157 158 159 160 161 162
            // 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 );
            }
Alan Mishchenko committed
163 164
            else
                p->nCallsFiltered++;
Alan Mishchenko committed
165 166 167 168 169 170 171 172 173 174 175 176
            // 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 );
            }
Alan Mishchenko committed
177 178
            else
                p->nCallsFiltered++;
Alan Mishchenko committed
179
        }
Alan Mishchenko committed
180 181 182 183 184 185 186

        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 );
        }

Alan Mishchenko committed
187
    }
Alan Mishchenko committed
188
} 
Alan Mishchenko committed
189 190 191 192 193 194 195 196 197 198 199 200 201 202

/**Function*************************************************************

  Synopsis    [Performs clock-gating for the AIG.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
int Cgt_ClockGatingRange( Cgt_Man_t * p, int iStart )
{
203
    int nOutputs, iStop;
204
    abctime clk, clkTotal = Abc_Clock();
Alan Mishchenko committed
205 206 207 208
    int nCallsUnsat    = p->nCallsUnsat;
    int nCallsSat      = p->nCallsSat;
    int nCallsUndec    = p->nCallsUndec;
    int nCallsFiltered = p->nCallsFiltered;
209
clk = Abc_Clock();
Alan Mishchenko committed
210 211
    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 );
212
    p->pSat  = (sat_solver *)Cnf_DataWriteIntoSolver( p->pCnf, 1, 0 );
Alan Mishchenko committed
213
    sat_solver_compress( p->pSat );
Alan Mishchenko committed
214
    p->vPatts = Vec_PtrAllocSimInfo( Aig_ManObjNumMax(p->pPart), p->nPattWords );
Alan Mishchenko committed
215
    Vec_PtrCleanSimInfo( p->vPatts, 0, p->nPattWords );
216
p->timePrepare += Abc_Clock() - clk;
Alan Mishchenko committed
217 218 219 220 221
    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. ",
222
            iStart, iStop-iStart, Aig_ManCoNum(p->pPart)-nOutputs, p->pSat->size, 
Alan Mishchenko committed
223 224 225 226
            p->nCallsUnsat-nCallsUnsat, 
            p->nCallsSat  -nCallsSat, 
            p->nCallsUndec-nCallsUndec,
            p->nCallsFiltered-nCallsFiltered );
227
        ABC_PRT( "Time", Abc_Clock() - clkTotal );
Alan Mishchenko committed
228
    }
Alan Mishchenko committed
229
    Cgt_ManClean( p );
Alan Mishchenko committed
230
    p->nRecycles++;
Alan Mishchenko committed
231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246
    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 )
{
Alan Mishchenko committed
247 248
    Bar_Progress_t * pProgress = NULL;
    Cgt_Par_t Pars; 
Alan Mishchenko committed
249 250
    Cgt_Man_t * p;
    Vec_Vec_t * vGatesAll;
251
    int iStart;
252
    abctime clk = Abc_Clock(), clkTotal = Abc_Clock();
Alan Mishchenko committed
253 254
    // reset random numbers
    Aig_ManRandom( 1 );
Alan Mishchenko committed
255 256 257 258
    if ( pPars == NULL )
        Cgt_SetDefaultParams( pPars = &Pars );    
    p = Cgt_ManCreate( pAig, pCare, pPars );
    p->pFrame = Cgt_ManDeriveAigForGating( p );
259
p->timeAig += Abc_Clock() - clk;
260 261 262
    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); )
Alan Mishchenko committed
263 264
    {
        Bar_ProgressUpdate( pProgress, iStart, NULL );
Alan Mishchenko committed
265
        iStart = Cgt_ClockGatingRange( p, iStart );
Alan Mishchenko committed
266 267
    }
    Bar_ProgressStop( pProgress );
Alan Mishchenko committed
268
    vGatesAll = p->vGatesAll;
Alan Mishchenko committed
269
    p->vGatesAll = NULL;
270
p->timeTotal = Abc_Clock() - clkTotal;
Alan Mishchenko committed
271
    Cgt_ManStop( p );
Alan Mishchenko committed
272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289
    return vGatesAll;
}

/**Function*************************************************************

  Synopsis    [Performs clock-gating for the AIG.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Aig_Man_t * Cgt_ClockGating( Aig_Man_t * pAig, Aig_Man_t * pCare, Cgt_Par_t * pPars )
{
    Aig_Man_t * pGated;
    Vec_Vec_t * vGatesAll;
Alan Mishchenko committed
290
    Vec_Vec_t * vGates;
291
    int nNodesUsed;//, clk = Abc_Clock();
Alan Mishchenko committed
292
    vGatesAll = Cgt_ClockGatingCandidates( pAig, pCare, pPars );
Alan Mishchenko committed
293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312
    if ( pPars->fAreaOnly )
        vGates = Cgt_ManDecideArea( pAig, vGatesAll, pPars->nOdcMax, pPars->fVerbose );
    else
        vGates = Cgt_ManDecideSimple( pAig, vGatesAll, pPars->nOdcMax, pPars->fVerbose );
    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 );
Alan Mishchenko committed
313 314 315 316 317 318 319 320 321
    Vec_VecFree( vGatesAll );
    return pGated;
}

////////////////////////////////////////////////////////////////////////
///                       END OF FILE                                ///
////////////////////////////////////////////////////////////////////////


322 323
ABC_NAMESPACE_IMPL_END