cgtCore.c 10.8 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
    p->nConfMax   =    10;   // the max number of conflicts at a node
    p->nVarsMin   =  1000;   // the min number of vars to recycle the SAT solver
54
    p->nFlopsMin  =    10;   // the min number of flops to recycle the SAT solver
Alan Mishchenko committed
55
    p->fAreaOnly  =     0;   // derive clock-gating to minimize area
56
    p->fVerbose   =     0;   // 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
        pMiter = Saig_ManLi( p->pAig, i );
141
        Cgt_ManDetectCandidates( p->pAig, p->vUseful, Aig_ObjFanin0(pMiter), p->pPars->nLevelMax, vNodes );
Alan Mishchenko committed
142
        // 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
    return iStop;
}

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

  Synopsis    [Performs clock-gating for the AIG.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
245
Vec_Vec_t * Cgt_ClockGatingCandidates( Aig_Man_t * pAig, Aig_Man_t * pCare, Cgt_Par_t * pPars, Vec_Int_t * vUseful )
Alan Mishchenko committed
246
{
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
    if ( pPars == NULL )
        Cgt_SetDefaultParams( pPars = &Pars );    
    p = Cgt_ManCreate( pAig, pCare, pPars );
258
    p->vUseful = vUseful;
Alan Mishchenko committed
259
    p->pFrame = Cgt_ManDeriveAigForGating( p );
260
p->timeAig += Abc_Clock() - clk;
261 262 263
    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
264 265
    {
        Bar_ProgressUpdate( pProgress, iStart, NULL );
Alan Mishchenko committed
266
        iStart = Cgt_ClockGatingRange( p, iStart );
Alan Mishchenko committed
267 268
    }
    Bar_ProgressStop( pProgress );
Alan Mishchenko committed
269
    vGatesAll = p->vGatesAll;
Alan Mishchenko committed
270
    p->vGatesAll = NULL;
271
p->timeTotal = Abc_Clock() - clkTotal;
Alan Mishchenko committed
272
    Cgt_ManStop( p );
Alan Mishchenko committed
273 274 275 276 277 278 279 280 281 282 283 284 285 286
    return vGatesAll;
}

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

  Synopsis    [Performs clock-gating for the AIG.]

  Description []
               
  SideEffects []

  SeeAlso     []

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

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


327 328
ABC_NAMESPACE_IMPL_END