sclSize.c 31.3 KB
Newer Older
1 2
/**CFile****************************************************************

3
  FileName    [sclSize.c]
4 5 6

  SystemName  [ABC: Logic synthesis and verification system.]

7 8
  PackageName [Standard-cell library representation.]

9
  Synopsis    [Core timing analysis used in gate-sizing.]
10 11 12 13 14 15 16

  Author      [Alan Mishchenko, Niklas Een]
  
  Affiliation [UC Berkeley]

  Date        [Ver. 1.0. Started - August 24, 2012.]

17
  Revision    [$Id: sclSize.c,v 1.0 2012/08/24 00:00:00 alanmi Exp $]
18 19 20

***********************************************************************/

21
#include "sclSize.h"
22
#include "map/mio/mio.h"
23
#include "misc/vec/vecWec.h"
24
#include "base/main/main.h"
25

26 27 28 29
#ifdef WIN32
#include <windows.h>
#endif

30 31 32 33 34 35 36 37 38 39 40 41 42
ABC_NAMESPACE_IMPL_START


////////////////////////////////////////////////////////////////////////
///                        DECLARATIONS                              ///
////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////
///                     FUNCTION DEFINITIONS                         ///
////////////////////////////////////////////////////////////////////////

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

43
  Synopsis    [Finding most critical objects.]
44 45 46 47 48 49 50 51

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
52
Abc_Obj_t * Abc_SclFindCriticalCo( SC_Man * p, int * pfRise )
53
{
54 55 56
    Abc_Obj_t * pObj, * pPivot = NULL;
    float fMaxArr = 0;
    int i;
57
    assert( Abc_NtkPoNum(p->pNtk) > 0 );
58 59 60 61 62 63
    Abc_NtkForEachCo( p->pNtk, pObj, i )
    {
        SC_Pair * pArr = Abc_SclObjTime( p, pObj );
        if ( fMaxArr < pArr->rise )  fMaxArr = pArr->rise, *pfRise = 1, pPivot = pObj;
        if ( fMaxArr < pArr->fall )  fMaxArr = pArr->fall, *pfRise = 0, pPivot = pObj;
    }
64 65
    if ( fMaxArr == 0 )
        pPivot = Abc_NtkPo(p->pNtk, 0);
66 67
    assert( pPivot != NULL );
    return pPivot;
68
}
69 70
// assumes that slacks are not available (uses arrival times)
Abc_Obj_t * Abc_SclFindMostCriticalFanin2( SC_Man * p, int * pfRise, Abc_Obj_t * pNode )
71
{
72
    Abc_Obj_t * pFanin, * pPivot = NULL;
73 74
    float fMaxArr = 0;
    int i;
75
    Abc_ObjForEachFanin( pNode, pFanin, i )
76
    {
77 78 79
        SC_Pair * pArr = Abc_SclObjTime( p, pFanin );
        if ( fMaxArr < pArr->rise )  fMaxArr = pArr->rise, *pfRise = 1, pPivot = pFanin;
        if ( fMaxArr < pArr->fall )  fMaxArr = pArr->fall, *pfRise = 0, pPivot = pFanin;
80 81
    }
    return pPivot;
82
}
83 84 85 86 87 88 89 90 91 92
// assumes that slack are available
Abc_Obj_t * Abc_SclFindMostCriticalFanin( SC_Man * p, int * pfRise, Abc_Obj_t * pNode )
{
    Abc_Obj_t * pFanin, * pPivot = NULL;
    float fMinSlack = ABC_INFINITY;
    SC_Pair * pArr;
    int i;
    *pfRise = 0;
    // find min-slack node
    Abc_ObjForEachFanin( pNode, pFanin, i )
93
        if ( fMinSlack > Abc_SclObjGetSlack( p, pFanin, p->MaxDelay0 ) )
94
        {
95
            fMinSlack = Abc_SclObjGetSlack( p, pFanin, p->MaxDelay0 );
96 97 98 99 100 101 102 103 104
            pPivot = pFanin;
        }
    if ( pPivot == NULL )
        return NULL;
    // find its leading phase
    pArr = Abc_SclObjTime( p, pPivot );
    *pfRise = (pArr->rise >= pArr->fall);
    return pPivot;
}
105 106 107

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

108
  Synopsis    [Printing timing information for the node/network.]
109 110 111 112 113 114 115 116

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
117
static inline void Abc_SclTimeNodePrint( SC_Man * p, Abc_Obj_t * pObj, int fRise, int Length, float maxDelay )
118
{
119
    SC_Cell * pCell = Abc_ObjIsNode(pObj) ? Abc_SclObjCell(pObj) : NULL;
120
    printf( "%8d : ",           Abc_ObjId(pObj) );
121
    printf( "%d ",              Abc_ObjFaninNum(pObj) );
122
    printf( "%4d ",             Abc_ObjFanoutNum(pObj) );
123 124 125
    printf( "%-*s ",            Length, pCell ? pCell->pName : "pi" );
    printf( "A =%7.2f  ",       pCell ? pCell->area : 0.0 );
    printf( "D%s =",            fRise ? "r" : "f" );
126 127 128
    printf( "%6.1f",            Abc_SclObjTimeMax(p, pObj) );
    printf( "%7.1f ps  ",       -Abc_AbsFloat(Abc_SclObjTimeOne(p, pObj, 0) - Abc_SclObjTimeOne(p, pObj, 1)) );
    printf( "S =%6.1f ps  ",    Abc_SclObjSlewMax(p, pObj) );
129
    printf( "Cin =%5.1f ff  ",  pCell ? SC_CellPinCapAve(pCell) : 0.0 );
130
    printf( "Cout =%6.1f ff  ", Abc_SclObjLoadMax(p, pObj) );
131
    printf( "Cmax =%6.1f ff  ", pCell ? SC_CellPin(pCell, pCell->n_inputs)->max_out_cap : 0.0 );
132
    printf( "G =%5d  ",         pCell ? (int)(100.0 * Abc_SclObjLoadAve(p, pObj) / SC_CellPinCapAve(pCell)) : 0 );
133
//    printf( "SL =%6.1f ps",     Abc_SclObjSlackMax(p, pObj, p->MaxDelay0) );
134
    printf( "\n" );
135
}
136
void Abc_SclTimeNtkPrint( SC_Man * p, int fShowAll, int fPrintPath )
137
{
138
    int fReversePath = 1;
139
    int i, nLength = 0, fRise = 0;
140
    Abc_Obj_t * pObj, * pPivot = Abc_SclFindCriticalCo( p, &fRise ); 
141
    float maxDelay = Abc_SclObjTimeOne( p, pPivot, fRise );
142
    p->ReportDelay = maxDelay;
143

144
#ifdef WIN32
145
    printf( "WireLoad = \"%s\"  ", p->pWLoadUsed ? p->pWLoadUsed->pName : "none" );
146
    SetConsoleTextAttribute( GetStdHandle(STD_OUTPUT_HANDLE), 14 ); // yellow
147
    printf( "Gates =%7d ",         Abc_NtkNodeNum(p->pNtk) );
148
    SetConsoleTextAttribute( GetStdHandle(STD_OUTPUT_HANDLE), 7 );  // normal
149
    printf( "(%5.1f %%)   ",       100.0 * Abc_SclGetBufInvCount(p->pNtk) / Abc_NtkNodeNum(p->pNtk) );
150
    SetConsoleTextAttribute( GetStdHandle(STD_OUTPUT_HANDLE), 10 ); // green
151
    printf( "Cap =%5.1f ff ",      p->EstLoadAve );
152
    SetConsoleTextAttribute( GetStdHandle(STD_OUTPUT_HANDLE), 7 );  // normal
153
    printf( "(%5.1f %%)   ",       Abc_SclGetAverageSize(p->pNtk) );
154
    SetConsoleTextAttribute( GetStdHandle(STD_OUTPUT_HANDLE), 11 ); // blue
155
    printf( "Area =%12.2f ",       Abc_SclGetTotalArea(p->pNtk) );
156
    SetConsoleTextAttribute( GetStdHandle(STD_OUTPUT_HANDLE), 7 );  // normal
157
    printf( "(%5.1f %%)   ",       100.0 * Abc_SclCountMinSize(p->pLib, p->pNtk, 0) / Abc_NtkNodeNum(p->pNtk) );
158
    SetConsoleTextAttribute( GetStdHandle(STD_OUTPUT_HANDLE), 13 ); // magenta
159
    printf( "Delay =%9.2f ps  ",   maxDelay );
160
    SetConsoleTextAttribute( GetStdHandle(STD_OUTPUT_HANDLE), 7 );  // normal
161
    printf( "(%5.1f %%)   ",       100.0 * Abc_SclCountNearCriticalNodes(p) / Abc_NtkNodeNum(p->pNtk) );
162
    printf( "            \n" );
163 164
#else
    Abc_Print( 1, "WireLoad = \"%s\"  ",   p->pWLoadUsed ? p->pWLoadUsed->pName : "none" );
165
    Abc_Print( 1, "%sGates =%7d%s ",       "\033[1;33m", Abc_NtkNodeNum(p->pNtk),      "\033[0m" ); // yellow
166
    Abc_Print( 1, "(%5.1f %%)   ",         100.0 * Abc_SclGetBufInvCount(p->pNtk) / Abc_NtkNodeNum(p->pNtk) );
167
    Abc_Print( 1, "%sCap =%5.1f ff%s ",    "\033[1;32m", p->EstLoadAve,                "\033[0m" ); // green
168
    Abc_Print( 1, "(%5.1f %%)   ",         Abc_SclGetAverageSize(p->pNtk) );
169
    Abc_Print( 1, "%sArea =%12.2f%s ",     "\033[1;36m", Abc_SclGetTotalArea(p->pNtk), "\033[0m" ); // blue
170
    Abc_Print( 1, "(%5.1f %%)   ",         100.0 * Abc_SclCountMinSize(p->pLib, p->pNtk, 0) / Abc_NtkNodeNum(p->pNtk) );
171
    Abc_Print( 1, "%sDelay =%9.2f ps%s  ", "\033[1;35m", maxDelay,                     "\033[0m" ); // magenta
172 173 174 175
    Abc_Print( 1, "(%5.1f %%)   ",         100.0 * Abc_SclCountNearCriticalNodes(p) / Abc_NtkNodeNum(p->pNtk) );
    Abc_Print( 1, "            \n" );
#endif

176
    if ( fShowAll )
177
    {
178
//        printf( "Timing information for all nodes: \n" );
179
        // find the longest cell name
180
        Abc_NtkForEachNodeReverse( p->pNtk, pObj, i )
181
            if ( Abc_ObjFaninNum(pObj) > 0 )
182
                nLength = Abc_MaxInt( nLength, strlen(Abc_SclObjCell(pObj)->pName) );
183 184 185
        // print timing
        Abc_NtkForEachNodeReverse( p->pNtk, pObj, i )
            if ( Abc_ObjFaninNum(pObj) > 0 )
186
                Abc_SclTimeNodePrint( p, pObj, -1, nLength, maxDelay );
187
    }
188
    if ( fPrintPath )
189
    {
190 191 192 193
        Abc_Obj_t * pTemp, * pPrev = NULL;
        int iStart = -1, iEnd = -1;
        Vec_Ptr_t * vPath;
//        printf( "Critical path: \n" );        
194 195
        // find the longest cell name
        pObj = Abc_ObjFanin0(pPivot);
196
        i = 0;
197 198
        while ( pObj && Abc_ObjIsNode(pObj) )
        {
199
            i++;
200
            nLength = Abc_MaxInt( nLength, Abc_SclObjCell(pObj) ? strlen(Abc_SclObjCell(pObj)->pName) : 2 /* strlen("pi") */ );
201 202
            pObj = Abc_SclFindMostCriticalFanin( p, &fRise, pObj );
        }
203

204
        // print timing
205
        if ( !fReversePath )
206
        {
207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236
            // print timing
            pObj = Abc_ObjFanin0(pPivot);
            while ( pObj )//&& Abc_ObjIsNode(pObj) )
            {
                printf( "Path%3d --", i-- );
                Abc_SclTimeNodePrint( p, pObj, fRise, nLength, maxDelay );
                pPrev = pObj;
                pObj = Abc_SclFindMostCriticalFanin( p, &fRise, pObj );
            }
        }
        else
        {
            // collect path nodes
            vPath = Vec_PtrAlloc( 100 );
            Vec_PtrPush( vPath, pPivot );
            pObj = Abc_ObjFanin0(pPivot);
            while ( pObj )//&& Abc_ObjIsNode(pObj) )
            {
                Vec_PtrPush( vPath, pObj );
                pPrev = pObj;
                pObj = Abc_SclFindMostCriticalFanin( p, &fRise, pObj );
            }
            Vec_PtrForEachEntryReverse( Abc_Obj_t *, vPath, pObj, i )
            {
                printf( "Path%3d --", Vec_PtrSize(vPath)-1-i );
                Abc_SclTimeNodePrint( p, pObj, fRise, nLength, maxDelay );
                if ( i == 1 )
                    break;
            }
            Vec_PtrFree( vPath );
237
        }
238 239 240 241 242 243 244 245 246 247
        // print start-point and end-point
        Abc_NtkForEachPi( p->pNtk, pTemp, iStart )
            if ( pTemp == pPrev )
                break;
        Abc_NtkForEachPo( p->pNtk, pTemp, iEnd )
            if ( pTemp == pPivot )
                break;
        printf( "Start-point = pi%0*d.  End-point = po%0*d.\n", 
            Abc_Base10Log( Abc_NtkPiNum(p->pNtk) ), iStart, 
            Abc_Base10Log( Abc_NtkPoNum(p->pNtk) ), iEnd );
248 249 250 251 252
    }
}

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

253
  Synopsis    [Timing computation for pin/gate/cone/network.]
254 255 256 257 258 259 260 261

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
262
static inline void Abc_SclTimeFanin( SC_Man * p, SC_Timing * pTime, Abc_Obj_t * pObj, Abc_Obj_t * pFanin )
263
{
264
    SC_Pair * pArrIn   = Abc_SclObjTime( p, pFanin );
265
    SC_Pair * pSlewIn  = Abc_SclObjSlew( p, pFanin );
266
    SC_Pair * pLoad    = Abc_SclObjLoad( p, pObj );
267 268
    SC_Pair * pArrOut  = Abc_SclObjTime( p, pObj );   // modified
    SC_Pair * pSlewOut = Abc_SclObjSlew( p, pObj );   // modified
269
    Scl_LibPinArrival( pTime, pArrIn, pSlewIn, pLoad, pArrOut, pSlewOut );
270
}
271
static inline void Abc_SclDeptFanin( SC_Man * p, SC_Timing * pTime, Abc_Obj_t * pObj, Abc_Obj_t * pFanin )
272 273 274 275 276
{
    SC_Pair * pDepIn   = Abc_SclObjDept( p, pFanin );   // modified
    SC_Pair * pSlewIn  = Abc_SclObjSlew( p, pFanin );
    SC_Pair * pLoad    = Abc_SclObjLoad( p, pObj );
    SC_Pair * pDepOut  = Abc_SclObjDept( p, pObj );
277
    Scl_LibPinDeparture( pTime, pDepIn, pSlewIn, pLoad, pDepOut );
278
}
279 280 281 282 283
static inline void Abc_SclDeptObj( SC_Man * p, Abc_Obj_t * pObj )
{
    SC_Timing * pTime;
    Abc_Obj_t * pFanout;
    int i;
284
    SC_PairClean( Abc_SclObjDept(p, pObj) );
285 286
    Abc_ObjForEachFanout( pObj, pFanout, i )
    {
287
        if ( Abc_ObjIsCo(pFanout) || Abc_ObjIsLatch(pFanout) )
288 289
            continue;
        pTime = Scl_CellPinTime( Abc_SclObjCell(pFanout), Abc_NodeFindFanin(pFanout, pObj) );
290 291 292
        Abc_SclDeptFanin( p, pTime, pFanout, pObj );
    }
}
293 294 295
static inline float Abc_SclObjLoadValue( SC_Man * p, Abc_Obj_t * pObj )
{
//    float Value = Abc_MaxFloat(pLoad->fall, pLoad->rise) / (p->EstLoadAve * p->EstLoadMax);
296
    return (0.5 * Abc_SclObjLoad(p, pObj)->fall + 0.5 * Abc_SclObjLoad(p, pObj)->rise) / (p->EstLoadAve * p->EstLoadMax);
297
}
298 299 300 301 302 303 304 305 306 307
static inline void Abc_SclTimeCi( SC_Man * p, Abc_Obj_t * pObj )
{
    if ( p->pPiDrive != NULL )
    {
        SC_Pair * pLoad = Abc_SclObjLoad( p, pObj );
        SC_Pair * pTime = Abc_SclObjTime( p, pObj );
        SC_Pair * pSlew = Abc_SclObjSlew( p, pObj );
        Scl_LibHandleInputDriver( p->pPiDrive, pLoad, pTime, pSlew );
    }
}
308
void Abc_SclTimeNode( SC_Man * p, Abc_Obj_t * pObj, int fDept )
309 310 311 312
{
    SC_Timing * pTime;
    SC_Cell * pCell;
    int k;
313 314 315 316 317
    SC_Pair * pLoad = Abc_SclObjLoad( p, pObj );
    float LoadRise = pLoad->rise;
    float LoadFall = pLoad->fall;
    float DeptRise = 0;
    float DeptFall = 0;
318
    float Value = p->EstLoadMax ? Abc_SclObjLoadValue( p, pObj ) : 0;
319
    Abc_Obj_t * pFanin;
320 321 322 323 324 325
    if ( Abc_ObjIsCi(pObj) )
    {
        assert( !fDept );
        Abc_SclTimeCi( p, pObj );
        return;
    }
326 327
    if ( Abc_ObjIsCo(pObj) )
    {
328
        if ( !fDept )
329
        {
330
            Abc_SclObjDupFanin( p, pObj );
331 332 333
            Vec_FltWriteEntry( p->vTimesOut, pObj->iData, Abc_SclObjTimeMax(p, pObj) );
            Vec_QueUpdate( p->vQue, pObj->iData );
        }
334 335 336
        return;
    }
    assert( Abc_ObjIsNode(pObj) );
337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352
//    if ( !(Abc_ObjFaninNum(pObj) == 1 && Abc_ObjIsPi(Abc_ObjFanin0(pObj))) && p->EstLoadMax && Value > 1 )
    if ( p->EstLoadMax && Value > 1 )
    {
        pLoad->rise = p->EstLoadAve * p->EstLoadMax;
        pLoad->fall = p->EstLoadAve * p->EstLoadMax;
        if ( fDept )
        {
            SC_Pair * pDepOut  = Abc_SclObjDept( p, pObj );
            float EstDelta = p->EstLinear * log( Value );
            DeptRise = pDepOut->rise;
            DeptFall = pDepOut->fall;
            pDepOut->rise += EstDelta;
            pDepOut->fall += EstDelta;
        }
        p->nEstNodes++;
    }
353
    // get the library cell
354
    pCell = Abc_SclObjCell( pObj );
355 356
    // compute for each fanin
    Abc_ObjForEachFanin( pObj, pFanin, k )
357
    {
358
        pTime = Scl_CellPinTime( pCell, k );
359
        if ( fDept )
360
            Abc_SclDeptFanin( p, pTime, pObj, pFanin );
361
        else
362
            Abc_SclTimeFanin( p, pTime, pObj, pFanin );
363
    }
364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381
    if ( p->EstLoadMax && Value > 1 )
    {
        pLoad->rise = LoadRise;
        pLoad->fall = LoadFall;
        if ( fDept )
        {
            SC_Pair * pDepOut  = Abc_SclObjDept( p, pObj );
            pDepOut->rise = DeptRise;
            pDepOut->fall = DeptFall;
        }
        else
        {
            SC_Pair * pArrOut  = Abc_SclObjTime( p, pObj );
            float EstDelta = p->EstLinear * log( Value );
            pArrOut->rise += EstDelta;
            pArrOut->fall += EstDelta;
        }
    }
382 383 384
}
void Abc_SclTimeCone( SC_Man * p, Vec_Int_t * vCone )
{
385
    int fVerbose = 0;
386 387
    Abc_Obj_t * pObj;
    int i;
388
    Abc_SclConeClean( p, vCone );
389
    Abc_NtkForEachObjVec( vCone, p->pNtk, pObj, i )
390
    {
391
        if ( fVerbose && Abc_ObjIsNode(pObj) )
392
        printf( "  Updating node %d with gate %s\n", Abc_ObjId(pObj), Abc_SclObjCell(pObj)->pName );
393
        if ( fVerbose && Abc_ObjIsNode(pObj) )
394
        printf( "    before (%6.1f ps  %6.1f ps)   ", Abc_SclObjTimeOne(p, pObj, 1), Abc_SclObjTimeOne(p, pObj, 0) );
395
        Abc_SclTimeNode( p, pObj, 0 );
396
        if ( fVerbose && Abc_ObjIsNode(pObj) )
397
        printf( "after (%6.1f ps  %6.1f ps)\n", Abc_SclObjTimeOne(p, pObj, 1), Abc_SclObjTimeOne(p, pObj, 0) );
398 399
    }
}
400
void Abc_SclTimeNtkRecompute( SC_Man * p, float * pArea, float * pDelay, int fReverse, float DUser )
401 402
{
    Abc_Obj_t * pObj;
403
    float D;
404
    int i;
405 406
    Abc_SclComputeLoad( p );
    Abc_SclManCleanTime( p );
407
    p->nEstNodes = 0;
408 409
    Abc_NtkForEachCi( p->pNtk, pObj, i )
        Abc_SclTimeNode( p, pObj, 0 );
410
    Abc_NtkForEachNode1( p->pNtk, pObj, i )
411
        Abc_SclTimeNode( p, pObj, 0 );
412
    Abc_NtkForEachCo( p->pNtk, pObj, i )
413
        Abc_SclTimeNode( p, pObj, 0 );
414
    D = Abc_SclReadMaxDelay( p );
415 416
    if ( fReverse && DUser > 0 && D < DUser )
        D = DUser;
417
    if ( pArea )
418
        *pArea = Abc_SclGetTotalArea(p->pNtk);
419
    if ( pDelay )
420 421
        *pDelay = D;
    if ( fReverse )
422
    {
423
        p->nEstNodes = 0;
424
        Abc_NtkForEachNodeReverse1( p->pNtk, pObj, i )
425
            Abc_SclTimeNode( p, pObj, 1 );
426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456
    }
}

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

  Synopsis    [Incremental timing update.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
static inline void Abc_SclTimeIncUpdateClean( SC_Man * p )
{
    Vec_Int_t * vLevel;
    Abc_Obj_t * pObj;
    int i, k;
    Vec_WecForEachLevel( p->vLevels, vLevel, i )
    {
        Abc_NtkForEachObjVec( vLevel, p->pNtk, pObj, k )
        {
            assert( pObj->fMarkC == 1 );
            pObj->fMarkC = 0;
        }
        Vec_IntClear( vLevel );
    }
}
static inline void Abc_SclTimeIncAddNode( SC_Man * p, Abc_Obj_t * pObj )
{
457
    assert( !Abc_ObjIsLatch(pObj) );
458 459 460 461 462 463 464 465 466 467
    assert( pObj->fMarkC == 0 );
    pObj->fMarkC = 1;
    Vec_IntPush( Vec_WecEntry(p->vLevels, Abc_ObjLevel(pObj)), Abc_ObjId(pObj) );
    p->nIncUpdates++;
}
static inline void Abc_SclTimeIncAddFanins( SC_Man * p, Abc_Obj_t * pObj )
{
    Abc_Obj_t * pFanin;
    int i;
    Abc_ObjForEachFanin( pObj, pFanin, i )
468
//        if ( !pFanin->fMarkC && Abc_ObjIsNode(pFanin) )
469
        if ( !pFanin->fMarkC && !Abc_ObjIsLatch(pFanin) )
470 471 472 473 474 475 476
            Abc_SclTimeIncAddNode( p, pFanin );
}
static inline void Abc_SclTimeIncAddFanouts( SC_Man * p, Abc_Obj_t * pObj )
{
    Abc_Obj_t * pFanout;
    int i;
    Abc_ObjForEachFanout( pObj, pFanout, i )
477
        if ( !pFanout->fMarkC && !Abc_ObjIsLatch(pFanout) )
478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520
            Abc_SclTimeIncAddNode( p, pFanout );
}
static inline void Abc_SclTimeIncUpdateArrival( SC_Man * p )
{
    Vec_Int_t * vLevel;
    SC_Pair ArrOut, SlewOut;
    SC_Pair * pArrOut, *pSlewOut;
    Abc_Obj_t * pObj;
    float E = (float)0.1;
    int i, k;
    Vec_WecForEachLevel( p->vLevels, vLevel, i )
    {
        Abc_NtkForEachObjVec( vLevel, p->pNtk, pObj, k )
        {
            if ( Abc_ObjIsCo(pObj) )
            {
                Abc_SclObjDupFanin( p, pObj );
                Vec_FltWriteEntry( p->vTimesOut, pObj->iData, Abc_SclObjTimeMax(p, pObj) );
                Vec_QueUpdate( p->vQue, pObj->iData );
                continue;
            }
            pArrOut  = Abc_SclObjTime( p, pObj );
            pSlewOut = Abc_SclObjSlew( p, pObj );
            SC_PairMove( &ArrOut,  pArrOut  );
            SC_PairMove( &SlewOut, pSlewOut );
            Abc_SclTimeNode( p, pObj, 0 );
//            if ( !SC_PairEqual(&ArrOut, pArrOut) || !SC_PairEqual(&SlewOut, pSlewOut) )
            if ( !SC_PairEqualE(&ArrOut, pArrOut, E) || !SC_PairEqualE(&SlewOut, pSlewOut, E) )
                Abc_SclTimeIncAddFanouts( p, pObj );
        }
    }
    p->MaxDelay = Abc_SclReadMaxDelay( p );
}
static inline void Abc_SclTimeIncUpdateDeparture( SC_Man * p )
{
    Vec_Int_t * vLevel;
    SC_Pair DepOut, * pDepOut;
    Abc_Obj_t * pObj;
    float E = (float)0.1;
    int i, k;
    Vec_WecForEachLevelReverse( p->vLevels, vLevel, i )
    {
        Abc_NtkForEachObjVec( vLevel, p->pNtk, pObj, k )
521
        {
522 523 524 525 526 527
            pDepOut = Abc_SclObjDept( p, pObj );
            SC_PairMove( &DepOut, pDepOut );
            Abc_SclDeptObj( p, pObj );
//            if ( !SC_PairEqual(&DepOut, pDepOut) )
            if ( !SC_PairEqualE(&DepOut, pDepOut, E) )
                Abc_SclTimeIncAddFanins( p, pObj );
528
        }
529
    } 
530 531
    p->MaxDelay = Abc_SclReadMaxDelay( p );
}
532 533 534 535 536 537 538 539
void Abc_SclTimeIncCheckLevel( Abc_Ntk_t * pNtk )
{
    Abc_Obj_t * pObj;
    int i;
    Abc_NtkForEachObj( pNtk, pObj, i )
        if ( (int)pObj->Level != Abc_ObjLevelNew(pObj) )
            printf( "Level of node %d is out of date!\n", i );
}
540
int Abc_SclTimeIncUpdate( SC_Man * p )
541
{
542
    Abc_Obj_t * pObj;
543
    int i, RetValue;
544
    if ( Vec_IntSize(p->vChanged) == 0 )
545
        return 0;
546 547 548
//    Abc_SclTimeIncCheckLevel( p->pNtk );
    Abc_NtkForEachObjVec( p->vChanged, p->pNtk, pObj, i )
    {
549
        Abc_SclTimeIncAddFanins( p, pObj );
550 551 552 553 554
        if ( pObj->fMarkC )
            continue;
        Abc_SclTimeIncAddNode( p, pObj );
    }
    Vec_IntClear( p->vChanged );
555 556 557
    Abc_SclTimeIncUpdateArrival( p );
    Abc_SclTimeIncUpdateDeparture( p );
    Abc_SclTimeIncUpdateClean( p );
558
    RetValue = p->nIncUpdates;
559
    p->nIncUpdates = 0;
560
    return RetValue;
561 562 563
}
void Abc_SclTimeIncInsert( SC_Man * p, Abc_Obj_t * pObj )
{
564
    Vec_IntPush( p->vChanged, Abc_ObjId(pObj) );
565
}
566 567 568 569
void Abc_SclTimeIncUpdateLevel_rec( Abc_Obj_t * pObj )
{
    Abc_Obj_t * pFanout;
    int i, LevelNew = Abc_ObjLevelNew(pObj);
570
    if ( LevelNew == (int)pObj->Level && Abc_ObjIsNode(pObj) && Abc_ObjFaninNum(pObj) > 0 )
571 572 573 574 575 576 577 578 579 580 581
        return;
    pObj->Level = LevelNew;
    Abc_ObjForEachFanout( pObj, pFanout, i )
        Abc_SclTimeIncUpdateLevel_rec( pFanout );
}
void Abc_SclTimeIncUpdateLevel( Abc_Obj_t * pObj )
{
    Abc_SclTimeIncUpdateLevel_rec( pObj );
}


582

583 584
/**Function*************************************************************

585 586 587 588 589 590 591 592 593 594 595
  Synopsis    [Read input slew and output load.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
void Abc_SclManReadSlewAndLoad( SC_Man * p, Abc_Ntk_t * pNtk )
{
596 597
    if ( Abc_FrameReadMaxLoad() )
    {
598
        Abc_Obj_t * pObj;  int i;
599
        float MaxLoad = Abc_FrameReadMaxLoad();
600
//        printf( "Default output load is specified (%.2f ff).\n", MaxLoad );
601 602 603
        Abc_NtkForEachPo( pNtk, pObj, i )
        {
            SC_Pair * pLoad = Abc_SclObjLoad( p, pObj );
604
            pLoad->rise = pLoad->fall = MaxLoad;
605 606 607 608 609 610 611 612 613 614 615 616
        }
    }
    if ( Abc_FrameReadDrivingCell() )
    {
        int iCell = Abc_SclCellFind( p->pLib, Abc_FrameReadDrivingCell() );
        if ( iCell == -1 )
            printf( "Cannot find the default PI driving cell (%s) in the library.\n", Abc_FrameReadDrivingCell() );
        else
        {
//            printf( "Default PI driving cell is specified (%s).\n", Abc_FrameReadDrivingCell() );
            p->pPiDrive = SC_LibCell( p->pLib, iCell );
            assert( p->pPiDrive != NULL );
617
            assert( p->pPiDrive->n_inputs == 1 );
618 619
        }
    }
620
}
621
 
622 623
/**Function*************************************************************

624
  Synopsis    [Prepare timing manager.]
625 626 627 628 629 630 631 632

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
633
SC_Man * Abc_SclManStart( SC_Lib * pLib, Abc_Ntk_t * pNtk, int fUseWireLoads, int fDept, float DUser, int nTreeCRatio )
634 635
{
    SC_Man * p = Abc_SclManAlloc( pLib, pNtk );
636 637 638 639 640
    if ( nTreeCRatio )
    {
        p->EstLoadMax = 0.01 * nTreeCRatio;  // max ratio of Cout/Cave when the estimation is used
        p->EstLinear  = 100;                  // linear coefficient
    }
641
    Abc_SclMioGates2SclGates( pLib, pNtk );
642
    Abc_SclManReadSlewAndLoad( p, pNtk );
643
    if ( fUseWireLoads )
644 645 646
    {
        if ( pNtk->pWLoadUsed == NULL )
        {            
647
            p->pWLoadUsed = Abc_SclFindWireLoadModel( pLib, Abc_SclGetTotalArea(p->pNtk) );
648
            if ( p->pWLoadUsed )
649 650 651 652 653
            pNtk->pWLoadUsed = Abc_UtilStrsav( p->pWLoadUsed->pName );
        }
        else
            p->pWLoadUsed = Abc_SclFetchWireLoadModel( pLib, pNtk->pWLoadUsed );
    }
654
    Abc_SclTimeNtkRecompute( p, &p->SumArea0, &p->MaxDelay0, fDept, DUser );
655 656
    p->SumArea  = p->SumArea0;
    p->MaxDelay = p->MaxDelay0;
657 658
    return p;
}
659

660 661
/**Function*************************************************************

662
  Synopsis    [Printing out timing information for the network.]
663 664 665 666 667 668 669 670

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
671
void Abc_SclTimePerformInt( SC_Lib * pLib, Abc_Ntk_t * pNtk, int nTreeCRatio, int fUseWireLoads, int fShowAll, int fPrintPath, int fDumpStats )
672 673
{
    SC_Man * p;
674
    p = Abc_SclManStart( pLib, pNtk, fUseWireLoads, 1, 0, nTreeCRatio );
675
    Abc_SclTimeNtkPrint( p, fShowAll, fPrintPath );
676 677
    if ( fDumpStats )
        Abc_SclDumpStats( p, "stats.txt", 0 );
678 679 680
    Abc_SclManFree( p );
}

681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701
/**Function*************************************************************

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
void Abc_SclTimePerform( SC_Lib * pLib, Abc_Ntk_t * pNtk, int nTreeCRatio, int fUseWireLoads, int fShowAll, int fPrintPath, int fDumpStats )
{
    Abc_Ntk_t * pNtkNew = pNtk;
    if ( pNtk->nBarBufs2 > 0 )
        pNtkNew = Abc_NtkDupDfsNoBarBufs( pNtk );
    Abc_SclTimePerformInt( pLib, pNtkNew, nTreeCRatio, fUseWireLoads, fShowAll, fPrintPath, fDumpStats );
    if ( pNtk->nBarBufs2 > 0 )
        Abc_NtkDelete( pNtkNew );
}

702

703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758

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

  Synopsis    [Printing out fanin information.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
int Abc_SclCheckCommonInputs( Abc_Obj_t * pObj, Abc_Obj_t * pFanin )
{
    Abc_Obj_t * pTemp;
    int i;
    Abc_ObjForEachFanin( pObj, pTemp, i )
        if ( Abc_NodeFindFanin( pFanin, pTemp ) >= 0 )
        {
            printf( "Node %d and its fanin %d have common fanin %d.\n", Abc_ObjId(pObj), Abc_ObjId(pFanin), Abc_ObjId(pTemp) );

            printf( "%-16s : ", Mio_GateReadName((Mio_Gate_t *)pObj->pData) ); 
            Abc_ObjPrint( stdout, pObj );

            printf( "%-16s : ", Mio_GateReadName((Mio_Gate_t *)pFanin->pData) ); 
            Abc_ObjPrint( stdout, pFanin );

            if ( pTemp->pData )
            printf( "%-16s : ", Mio_GateReadName((Mio_Gate_t *)pTemp->pData) ); 
            Abc_ObjPrint( stdout, pTemp );
            return 1;
        }
    return 0;
}
void Abc_SclPrintFaninPairs( SC_Man * p, Abc_Ntk_t * pNtk )
{
    Abc_Obj_t * pObj, * pFanin;
    int i, k;
    Abc_NtkForEachNode( pNtk, pObj, i )
        Abc_ObjForEachFanin( pObj, pFanin, k )
            if ( Abc_ObjIsNode(pFanin) && Abc_ObjFanoutNum(pFanin) == 1 )
                Abc_SclCheckCommonInputs( pObj, pFanin );
}

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

  Synopsis    [Printing out buffer information.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
static inline int Abc_ObjIsBuffer( Abc_Obj_t * pObj ) { return Abc_ObjIsNode(pObj) && Abc_ObjFaninNum(pObj) == 1; }
759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781
int Abc_SclHasBufferFanout( Abc_Obj_t * pObj )
{
    Abc_Obj_t * pFanout;
    int i;
    Abc_ObjForEachFanout( pObj, pFanout, i )
        if ( Abc_ObjIsBuffer(pFanout) )
            return 1;
    return 0;
}
int Abc_SclCountBufferFanoutsInt( Abc_Obj_t * pObj )
{
    Abc_Obj_t * pFanout;
    int i, Counter = 0;
    Abc_ObjForEachFanout( pObj, pFanout, i )
        if ( Abc_ObjIsBuffer(pFanout) )
            Counter += Abc_SclCountBufferFanoutsInt( pFanout );
    return Counter + Abc_ObjIsBuffer(pObj);
}
int Abc_SclCountBufferFanouts( Abc_Obj_t * pObj )
{
    return Abc_SclCountBufferFanoutsInt(pObj) - Abc_ObjIsBuffer(pObj);
}
int Abc_SclCountNonBufferFanoutsInt( Abc_Obj_t * pObj )
782 783 784 785 786 787
{
    Abc_Obj_t * pFanout;
    int i, Counter = 0;
    if ( !Abc_ObjIsBuffer(pObj) )
        return 1;
    Abc_ObjForEachFanout( pObj, pFanout, i )
788
        Counter += Abc_SclCountNonBufferFanoutsInt( pFanout );
789 790
    return Counter;
}
791
int Abc_SclCountNonBufferFanouts( Abc_Obj_t * pObj )
792 793
{
    Abc_Obj_t * pFanout;
794
    int i, Counter = 0;
795
    Abc_ObjForEachFanout( pObj, pFanout, i )
796 797
        Counter += Abc_SclCountNonBufferFanoutsInt( pFanout );
    return Counter;
798
}
799 800 801 802 803 804
float Abc_SclCountNonBufferDelayInt( SC_Man * p, Abc_Obj_t * pObj )
{
    Abc_Obj_t * pFanout;
    float Delay = 0;
    int i; 
    if ( !Abc_ObjIsBuffer(pObj) )
805
        return Abc_SclObjTimeMax(p, pObj);
806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828
    Abc_ObjForEachFanout( pObj, pFanout, i )
        Delay += Abc_SclCountNonBufferDelayInt( p, pFanout );
    return Delay;
}
float Abc_SclCountNonBufferDelay( SC_Man * p, Abc_Obj_t * pObj )
{
    Abc_Obj_t * pFanout;
    float Delay = 0;
    int i; 
    Abc_ObjForEachFanout( pObj, pFanout, i )
        Delay += Abc_SclCountNonBufferDelayInt( p, pFanout );
    return Delay;
}
float Abc_SclCountNonBufferLoadInt( SC_Man * p, Abc_Obj_t * pObj )
{
    Abc_Obj_t * pFanout;
    float Load = 0;
    int i; 
    if ( !Abc_ObjIsBuffer(pObj) )
        return 0;
    Abc_ObjForEachFanout( pObj, pFanout, i )
        Load += Abc_SclCountNonBufferLoadInt( p, pFanout );
    Load += 0.5 * Abc_SclObjLoad(p, pObj)->rise + 0.5 * Abc_SclObjLoad(p, pObj)->fall;
829
    Load -= 0.5 * SC_CellPin(Abc_SclObjCell(pObj), 0)->rise_cap + 0.5 * SC_CellPin(Abc_SclObjCell(pObj), 0)->fall_cap;
830 831 832
    return Load;
}
float Abc_SclCountNonBufferLoad( SC_Man * p, Abc_Obj_t * pObj )
833 834
{
    Abc_Obj_t * pFanout;
835 836 837 838 839 840 841 842 843
    float Load = 0;
    int i; 
    Abc_ObjForEachFanout( pObj, pFanout, i )
        Load += Abc_SclCountNonBufferLoadInt( p, pFanout );
    Load += 0.5 * Abc_SclObjLoad(p, pObj)->rise + 0.5 * Abc_SclObjLoad(p, pObj)->fall;
    return Load;
}
void Abc_SclPrintBuffersOne( SC_Man * p, Abc_Obj_t * pObj, int nOffset )
{
844 845 846
    int i;
    for ( i = 0; i < nOffset; i++ )
        printf( "    " );
847 848 849 850 851 852
    printf( "%6d: %-16s (%2d:%3d:%3d)  ", 
        Abc_ObjId(pObj), 
        Abc_ObjIsPi(pObj) ? "pi" : Mio_GateReadName((Mio_Gate_t *)pObj->pData), 
        Abc_ObjFanoutNum(pObj), 
        Abc_SclCountBufferFanouts(pObj), 
        Abc_SclCountNonBufferFanouts(pObj) );
853 854
    for ( ; i < 4; i++ )
        printf( "    " );
855
    printf( "a =%5.2f  ",      Abc_ObjIsPi(pObj) ? 0 : Abc_SclObjCell(pObj)->area );
856
    printf( "d = (" );
857 858 859 860 861
    printf( "%6.0f ps; ",      Abc_SclObjTimeOne(p, pObj, 1) );
    printf( "%6.0f ps)  ",     Abc_SclObjTimeOne(p, pObj, 0) );
    printf( "l =%5.0f ff  ",   Abc_SclObjLoadMax(p, pObj) );
    printf( "s =%5.0f ps   ",  Abc_SclObjSlewMax(p, pObj) );
    printf( "sl =%5.0f ps   ", Abc_SclObjSlackMax(p, pObj, p->MaxDelay0) );
862 863
    if ( nOffset == 0 )
    {
864
    printf( "L =%5.0f ff   ",  Abc_SclCountNonBufferLoad(p, pObj) );
865
    printf( "Lx =%5.0f ff  ",  100.0*Abc_SclCountNonBufferLoad(p, pObj)/p->EstLoadAve );
866 867
    printf( "Dx =%5.0f ps  ",  Abc_SclCountNonBufferDelay(p, pObj)/Abc_SclCountNonBufferFanouts(pObj) - Abc_SclObjTimeOne(p, pObj, 1) );
    printf( "Cx =%5.0f ps",    (Abc_SclCountNonBufferDelay(p, pObj)/Abc_SclCountNonBufferFanouts(pObj) - Abc_SclObjTimeOne(p, pObj, 1))/log(Abc_SclCountNonBufferLoad(p, pObj)/p->EstLoadAve) );
868
    }
869
    printf( "\n" );
870 871 872 873 874 875 876
}
void Abc_SclPrintBuffersInt( SC_Man * p, Abc_Obj_t * pObj, int nOffset )
{
    Abc_Obj_t * pFanout;
    int i;
    Abc_SclPrintBuffersOne( p, pObj, nOffset );
    assert( Abc_ObjIsBuffer(pObj) );
877 878
    Abc_ObjForEachFanout( pObj, pFanout, i )
        if ( Abc_ObjIsBuffer(pFanout) )
879
            Abc_SclPrintBuffersInt( p, pFanout, nOffset + 1 );
880 881 882
}
void Abc_SclPrintBufferTrees( SC_Man * p, Abc_Ntk_t * pNtk )
{
883 884
    Abc_Obj_t * pObj, * pFanout;
    int i, k;
885
    Abc_NtkForEachObj( pNtk, pObj, i )
886 887 888 889 890 891 892 893 894 895
    {
        if ( !Abc_ObjIsBuffer(pObj) && Abc_SclCountBufferFanouts(pObj) > 3 )
        {           
            Abc_SclPrintBuffersOne( p, pObj, 0 );
            Abc_ObjForEachFanout( pObj, pFanout, k )
                if ( Abc_ObjIsBuffer(pFanout) )
                    Abc_SclPrintBuffersInt( p, pFanout, 1 );
            printf( "\n" );
        }
    }
896 897 898 899 900 901
}
void Abc_SclPrintBuffers( SC_Lib * pLib, Abc_Ntk_t * pNtk, int fVerbose )
{
    int fUseWireLoads = 0;
    SC_Man * p;
    assert( Abc_NtkIsMappedLogic(pNtk) );
902
    p = Abc_SclManStart( pLib, pNtk, fUseWireLoads, 1, 0, 10000 ); 
903 904 905 906 907 908
    Abc_SclPrintBufferTrees( p, pNtk ); 
//    Abc_SclPrintFaninPairs( p, pNtk );
    Abc_SclManFree( p );
}


909 910 911 912 913 914 915
////////////////////////////////////////////////////////////////////////
///                       END OF FILE                                ///
////////////////////////////////////////////////////////////////////////


ABC_NAMESPACE_IMPL_END