sclLib.h 31.4 KB
Newer Older
1 2
/**CFile****************************************************************

3
  FileName    [sclLib.h]
4 5 6

  SystemName  [ABC: Logic synthesis and verification system.]

7 8 9
  PackageName [Standard-cell library representation.]

  Synopsis    [Simplified library representation for STA.]
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: sclLib.h,v 1.0 2012/08/24 00:00:00 alanmi Exp $]
18 19 20

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

21 22
#ifndef ABC__map__scl__sclLib_h
#define ABC__map__scl__sclLib_h
23 24 25 26 27 28 29 30 31 32


////////////////////////////////////////////////////////////////////////
///                          INCLUDES                                ///
////////////////////////////////////////////////////////////////////////

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
33
#include <math.h>
34
#include "misc/vec/vec.h"
35 36 37 38 39 40 41 42

ABC_NAMESPACE_HEADER_START


////////////////////////////////////////////////////////////////////////
///                         PARAMETERS                               ///
////////////////////////////////////////////////////////////////////////

43
#define ABC_SCL_CUR_VERSION 8
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61

typedef enum  
{
    sc_dir_NULL,
    sc_dir_Input,
    sc_dir_Output,
    sc_dir_InOut,
    sc_dir_Internal,
} SC_Dir;

typedef enum      // -- timing sense, positive-, negative- or non-unate
{
    sc_ts_NULL,
    sc_ts_Pos,
    sc_ts_Neg,
    sc_ts_Non,
} SC_TSense;

62 63 64 65 66 67
typedef struct SC_Pair_         SC_Pair;
struct SC_Pair_ 
{
    float      rise;
    float      fall;
};
68 69 70 71 72 73
typedef struct SC_PairI_        SC_PairI;
struct SC_PairI_ 
{
    int        rise;
    int        fall;
};
74

75 76 77
typedef struct SC_SizePars_    SC_SizePars;
struct SC_SizePars_
{
78 79
    int        nIters;
    int        nIterNoChange;
80 81
    int        Window;           // used for upsizing
    int        Ratio;            // used for upsizing
82
    int        Notches;
83 84
    int        DelayUser;
    int        DelayGap;
85
    int        TimeOut;
86
    int        BuffTreeEst;      // ratio for buffer tree estimation
87
    int        BypassFreq;       // frequency to try bypassing
88 89
    int        fUseDept;
    int        fDumpStats;
90
    int        fUseWireLoads;
91 92 93 94
    int        fVerbose;
    int        fVeryVerbose;
};

95 96 97 98 99 100 101 102 103
typedef struct SC_BusPars_     SC_BusPars;
struct SC_BusPars_
{
    int        GainRatio;       // target gain
    int        Slew;            // target slew
    int        nDegree;         // max branching factor
    int        fSizeOnly;       // perform only sizing
    int        fAddBufs;        // add buffers
    int        fBufPis;         // use CI buffering
104
    int        fUseWireLoads;   // wire loads
105 106
    int        fVerbose;        // verbose
    int        fVeryVerbose;    // verbose
107 108
};

109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
////////////////////////////////////////////////////////////////////////
///                    STRUCTURE DEFINITIONS                         ///
////////////////////////////////////////////////////////////////////////

typedef struct SC_WireLoad_    SC_WireLoad;
typedef struct SC_WireLoadSel_ SC_WireLoadSel;
typedef struct SC_TableTempl_  SC_TableTempl;
typedef struct SC_Surface_     SC_Surface;
typedef struct SC_Timing_      SC_Timing;
typedef struct SC_Timings_     SC_Timings;
typedef struct SC_Pin_         SC_Pin;
typedef struct SC_Cell_        SC_Cell;
typedef struct SC_Lib_         SC_Lib;

struct SC_WireLoad_ 
{
125
    char *         pName;
126
    float          cap;            // }- multiply estimation in 'fanout_len[].snd' with this value
127
    float          slope;          // used to extrapolate wireload for large fanout count
128 129
    Vec_Int_t      vFanout;        // Vec<Pair<uint,float> > -- pairs '(#fanouts, est-wire-len)'
    Vec_Flt_t      vLen;
130 131 132 133
};

struct SC_WireLoadSel_
{
134
    char *         pName;
135 136 137
    Vec_Flt_t      vAreaFrom;      // Vec<Trip<float,float,Str> > -- triplets '(from-area, upto-area, wire-load-model)'; range is [from, upto[
    Vec_Flt_t      vAreaTo;
    Vec_Ptr_t      vWireLoadModel;
138 139 140 141
};

struct SC_TableTempl_ 
{
142
    char *         pName;
143 144
    Vec_Ptr_t      vVars;          // Vec<Str>         -- name of variable (numbered from 0, not 1 as in the Liberty file) 
    Vec_Ptr_t      vIndex;         // Vec<Vec<float> > -- this is the point of measurement in table for the given variable 
145 146 147 148
};

struct SC_Surface_ 
{
149
    char *         pName;
150 151 152
    Vec_Flt_t      vIndex0;        // Vec<float>       -- correspondes to "index_1" in the liberty file (for timing: slew)
    Vec_Flt_t      vIndex1;        // Vec<float>       -- correspondes to "index_2" in the liberty file (for timing: load)
    Vec_Ptr_t      vData;          // Vec<Vec<float> > -- 'data[i0][i1]' gives value at '(index0[i0], index1[i1])' 
153 154 155
    Vec_Int_t      vIndex0I;       // Vec<float>       -- correspondes to "index_1" in the liberty file (for timing: slew)
    Vec_Int_t      vIndex1I;       // Vec<float>       -- correspondes to "index_2" in the liberty file (for timing: load)
    Vec_Ptr_t      vDataI;         // Vec<Vec<float> > -- 'data[i0][i1]' gives value at '(index0[i0], index1[i1])' 
156
    float          approx[3][6];
157 158 159 160 161 162
};

struct SC_Timing_ 
{
    char *         related_pin;    // -- related pin
    SC_TSense      tsense;         // -- timing sense (positive_unate, negative_unate, non_unate)
163
    char *         when_text;      // -- logic condition on inputs triggering this delay model for the output (currently not used)
164 165 166 167
    SC_Surface     pCellRise;      // -- Used to compute pin-to-pin delay
    SC_Surface     pCellFall;
    SC_Surface     pRiseTrans;     // -- Used to compute output slew
    SC_Surface     pFallTrans;
168 169 170 171
};

struct SC_Timings_ 
{
172
    char *         pName;          // -- the 'related_pin' field
173
    Vec_Ptr_t      vTimings;       // structures of type SC_Timing
174 175 176 177
};

struct SC_Pin_ 
{
178
    char *         pName;
179
    SC_Dir         dir;
180
    float          cap;            // -- this value is used if 'rise_cap' and 'fall_cap' is missing (copied by 'postProcess()'). (not used)
181 182
    float          rise_cap;       // }- used for input pins ('cap' too).
    float          fall_cap;       // }
183 184
    int            rise_capI;      // }- used for input pins ('cap' too).
    int            fall_capI;      // }
185 186
    float          max_out_cap;    // } (not used)
    float          max_out_slew;   // }- used only for output pins (max values must not be exceeded or else mapping is illegal) (not used)
187
    char *         func_text;      // }
188 189 190
    Vec_Wrd_t      vFunc;          // }
    Vec_Ptr_t      vRTimings;      // -- for output pins
//    SC_Timing      Timing;         // -- for output pins  
191 192 193 194
};

struct SC_Cell_ 
{
195
    char *         pName;
196
    int            Id;
Alan Mishchenko committed
197
    int            fSkip;          // skip this cell during genlib computation
198 199 200
    int            seq;            // -- set to TRUE by parser if a sequential element
    int            unsupp;         // -- set to TRUE by parser if cell contains information we cannot handle
    float          area;
201
    float          leakage;
202 203
    int            areaI;
    int            leakageI;
204
    int            drive_strength; // -- some library files provide this field (currently unused, but may be a good hint for sizing) (not used)
205
    Vec_Ptr_t      vPins;          // NamedSet<SC_Pin> 
206 207
    int            n_inputs;       // -- 'pins[0 .. n_inputs-1]' are input pins
    int            n_outputs;      // -- 'pins[n_inputs .. n_inputs+n_outputs-1]' are output pins
208 209
    SC_Cell *      pNext;          // same-functionality cells linked into a ring by area
    SC_Cell *      pPrev;          // same-functionality cells linked into a ring by area
210 211
    SC_Cell *      pRepr;          // representative of the class
    SC_Cell *      pAve;           // average size cell of this class
212
    int            Order;          // order of the gate in the list
213
    int            nGates;         // the number of gates in the list      
214 215 216 217
};

struct SC_Lib_ 
{
218
    char *         pName;
219
    char *         pFileName;
220 221
    char *         default_wire_load;
    char *         default_wire_load_sel;
222
    float          default_max_out_slew;   // -- 'default_max_transition'; this is copied to each output pin where 'max_transition' is not defined  (not used)
223
    int            unit_time;      // -- Valid 9..12. Unit is '10^(-val)' seconds (e.g. 9=1ns, 10=100ps, 11=10ps, 12=1ps)
224 225
    float          unit_cap_fst;   // -- First part is a multiplier, second either 12 or 15 for 'pf' or 'ff'.
    int            unit_cap_snd;
226 227 228 229 230
    Vec_Ptr_t      vWireLoads;     // NamedSet<SC_WireLoad>
    Vec_Ptr_t      vWireLoadSels;  // NamedSet<SC_WireLoadSel>
    Vec_Ptr_t      vTempls;        // NamedSet<SC_TableTempl>  
    Vec_Ptr_t      vCells;         // NamedSet<SC_Cell>
    Vec_Ptr_t      vCellClasses;   // NamedSet<SC_Cell>
231 232
    int *          pBins;          // hashing gateName -> gateId
    int            nBins;
233 234 235 236 237 238 239 240 241 242
};

////////////////////////////////////////////////////////////////////////
///                       GLOBAL VARIABLES                           ///
////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////
///                       MACRO DEFINITIONS                          ///
////////////////////////////////////////////////////////////////////////

243 244 245 246 247 248
static inline void        SC_PairClean( SC_Pair * d )               { d->rise = d->fall = 0;                 }
static inline float       SC_PairMax( SC_Pair * d )                 { return Abc_MaxFloat(d->rise, d->fall); }
static inline float       SC_PairMin( SC_Pair * d )                 { return Abc_MinFloat(d->rise, d->fall); }
static inline float       SC_PairAve( SC_Pair * d )                 { return 0.5 * d->rise + 0.5 * d->fall;  }
static inline void        SC_PairDup( SC_Pair * d, SC_Pair * s )    { *d = *s;                               }
static inline void        SC_PairMove( SC_Pair * d, SC_Pair * s )   { *d = *s; s->rise = s->fall = 0;        }
249
static inline void        SC_PairAdd( SC_Pair * d, SC_Pair * s )    { d->rise += s->rise; d->fall += s->fall;}
250 251 252
static inline int         SC_PairEqual( SC_Pair * d, SC_Pair * s )  { return d->rise == s->rise && d->fall == s->fall;                }
static inline int         SC_PairEqualE( SC_Pair * d, SC_Pair * s, float E )  { return d->rise - s->rise < E && s->rise - d->rise < E &&  d->fall - s->fall < E && s->fall - d->fall < E;    }

253 254 255 256
static inline int         SC_LibCellNum( SC_Lib * p )               { return Vec_PtrSize(&p->vCells);                                  }
static inline SC_Cell *   SC_LibCell( SC_Lib * p, int i )           { return (SC_Cell *)Vec_PtrEntry(&p->vCells, i);                   }
static inline SC_Pin  *   SC_CellPin( SC_Cell * p, int i )          { return (SC_Pin *)Vec_PtrEntry(&p->vPins, i);                     }
static inline Vec_Wrd_t * SC_CellFunc( SC_Cell * p )                { return &SC_CellPin(p, p->n_inputs)->vFunc;                       }
257
static inline float       SC_CellPinCap( SC_Cell * p, int i )       { return 0.5 * SC_CellPin(p, i)->rise_cap + 0.5 * SC_CellPin(p, i)->fall_cap; }
258
static inline float       SC_CellPinCapAve( SC_Cell * p )           { int i; float c = 0; for (i = 0; i < p->n_inputs; i++) c += SC_CellPinCap(p, i); return c / Abc_MaxInt(1, p->n_inputs); }
259 260
static inline char *      SC_CellPinOutFunc( SC_Cell * p, int i )   { return SC_CellPin(p, p->n_inputs + i)->func_text;               }
static inline char *      SC_CellPinName( SC_Cell * p, int i )      { return SC_CellPin(p, i)->pName;                                 }
261

262 263 264 265 266 267 268 269
#define SC_LibForEachCell( p, pCell, i )         Vec_PtrForEachEntry( SC_Cell *, &p->vCells, pCell, i )
#define SC_LibForEachCellClass( p, pCell, i )    Vec_PtrForEachEntry( SC_Cell *, &p->vCellClasses, pCell, i )
#define SC_LibForEachWireLoad( p, pWL, i )       Vec_PtrForEachEntry( SC_WireLoad *, &p->vWireLoads, pWL, i )
#define SC_LibForEachWireLoadSel( p, pWLS, i )   Vec_PtrForEachEntry( SC_WireLoadSel *, &p->vWireLoadSels, pWLS, i )
#define SC_LibForEachTempl( p, pTempl, i )       Vec_PtrForEachEntry( SC_TableTempl *, &p->vTempls, pTempl, i )
#define SC_CellForEachPin( p, pPin, i )          Vec_PtrForEachEntry( SC_Pin *, &p->vPins, pPin, i )
#define SC_CellForEachPinIn( p, pPin, i )        Vec_PtrForEachEntryStop( SC_Pin *, &p->vPins, pPin, i, p->n_inputs )
#define SC_CellForEachPinOut( p, pPin, i )       Vec_PtrForEachEntryStart( SC_Pin *, &p->vPins, pPin, i, p->n_inputs )
270
#define SC_RingForEachCell( pRing, pCell, i )    for ( i = 0, pCell = pRing; i == 0 || pCell != pRing; pCell = pCell->pNext, i++ )
271
#define SC_RingForEachCellRev( pRing, pCell, i ) for ( i = 0, pCell = pRing; i == 0 || pCell != pRing; pCell = pCell->pPrev, i++ )
272
#define SC_PinForEachRTiming( p, pRTime, i )     Vec_PtrForEachEntry( SC_Timings *, &p->vRTimings, pRTime, i )
273

274

275 276 277 278
////////////////////////////////////////////////////////////////////////
///                     FUNCTION DEFINITIONS                         ///
////////////////////////////////////////////////////////////////////////

279 280 281 282 283 284 285 286 287 288 289
/**Function*************************************************************

  Synopsis    [Constructors of the library data-structures.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344
static inline SC_WireLoad * Abc_SclWireLoadAlloc()
{
    SC_WireLoad * p;
    p = ABC_CALLOC( SC_WireLoad, 1 );
    return p;
}
static inline SC_WireLoadSel * Abc_SclWireLoadSelAlloc()
{
    SC_WireLoadSel * p;
    p = ABC_CALLOC( SC_WireLoadSel, 1 );
    return p;
}
static inline SC_TableTempl * Abc_SclTableTemplAlloc()
{
    SC_TableTempl * p;
    p = ABC_CALLOC( SC_TableTempl, 1 );
    return p;
}
static inline SC_Surface * Abc_SclSurfaceAlloc()
{
    SC_Surface * p;
    p = ABC_CALLOC( SC_Surface, 1 );
    return p;
}
static inline SC_Timing * Abc_SclTimingAlloc()
{
    SC_Timing * p;
    p = ABC_CALLOC( SC_Timing, 1 );
    return p;
}
static inline SC_Timings * Abc_SclTimingsAlloc()
{
    SC_Timings * p;
    p = ABC_CALLOC( SC_Timings, 1 );
    return p;
}
static inline SC_Pin * Abc_SclPinAlloc()
{
    SC_Pin * p;
    p = ABC_CALLOC( SC_Pin, 1 );
    p->max_out_slew = -1;
    return p;
}
static inline SC_Cell * Abc_SclCellAlloc()
{
    SC_Cell * p;
    p = ABC_CALLOC( SC_Cell, 1 );
    return p;
}
static inline SC_Lib * Abc_SclLibAlloc()
{
    SC_Lib * p;
    p = ABC_CALLOC( SC_Lib, 1 );
    p->default_max_out_slew = -1;
    p->unit_time      = 9;
345 346
    p->unit_cap_fst   = 1;
    p->unit_cap_snd   = 12;
347 348 349 350
    return p;
}


351 352 353 354 355 356 357 358 359 360 361
/**Function*************************************************************

  Synopsis    [Destructors of the library data-structures.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
362 363
static inline void Abc_SclWireLoadFree( SC_WireLoad * p )
{
364 365
    Vec_IntErase( &p->vFanout );
    Vec_FltErase( &p->vLen );
366
    ABC_FREE( p->pName );
367 368 369 370
    ABC_FREE( p );
}
static inline void Abc_SclWireLoadSelFree( SC_WireLoadSel * p )
{
371 372 373
    Vec_FltErase( &p->vAreaFrom );
    Vec_FltErase( &p->vAreaTo );
    Vec_PtrFreeData( &p->vWireLoadModel );
374
    Vec_PtrErase( &p->vWireLoadModel );
375
    ABC_FREE( p->pName );
376 377 378 379
    ABC_FREE( p );
}
static inline void Abc_SclTableTemplFree( SC_TableTempl * p )
{
380
    Vec_PtrFreeData( &p->vVars );
381
    Vec_PtrErase( &p->vVars );
382
    Vec_VecErase( (Vec_Vec_t *)&p->vIndex );
383
    ABC_FREE( p->pName );
384 385 386 387
    ABC_FREE( p );
}
static inline void Abc_SclSurfaceFree( SC_Surface * p )
{
388 389
    Vec_FltErase( &p->vIndex0 );
    Vec_FltErase( &p->vIndex1 );
390 391
    Vec_IntErase( &p->vIndex0I );
    Vec_IntErase( &p->vIndex1I );
392
    Vec_VecErase( (Vec_Vec_t *)&p->vData );
393
    Vec_VecErase( (Vec_Vec_t *)&p->vDataI );
394
    ABC_FREE( p->pName );
395
//    ABC_FREE( p );
396 397 398
}
static inline void Abc_SclTimingFree( SC_Timing * p )
{
399 400 401 402
    Abc_SclSurfaceFree( &p->pCellRise );
    Abc_SclSurfaceFree( &p->pCellFall );
    Abc_SclSurfaceFree( &p->pRiseTrans );
    Abc_SclSurfaceFree( &p->pFallTrans );
403 404 405 406 407 408 409 410
    ABC_FREE( p->related_pin );
    ABC_FREE( p->when_text );
    ABC_FREE( p );
}
static inline void Abc_SclTimingsFree( SC_Timings * p )
{
    SC_Timing * pTemp;
    int i;
411
    Vec_PtrForEachEntry( SC_Timing *, &p->vTimings, pTemp, i )
412
        Abc_SclTimingFree( pTemp );
413
    Vec_PtrErase( &p->vTimings );
414
    ABC_FREE( p->pName );
415 416 417 418 419 420
    ABC_FREE( p );
}
static inline void Abc_SclPinFree( SC_Pin * p )
{
    SC_Timings * pTemp;
    int i;
421
    SC_PinForEachRTiming( p, pTemp, i )
422
        Abc_SclTimingsFree( pTemp );
423 424
    Vec_PtrErase( &p->vRTimings );
    Vec_WrdErase( &p->vFunc );
425
    ABC_FREE( p->func_text );
426
    ABC_FREE( p->pName );
427 428 429 430 431 432
    ABC_FREE( p );
}
static inline void Abc_SclCellFree( SC_Cell * p )
{
    SC_Pin * pTemp;
    int i;
433
    SC_CellForEachPin( p, pTemp, i )
434
        Abc_SclPinFree( pTemp );
435
    Vec_PtrErase( &p->vPins );
436
    ABC_FREE( p->pName );
437 438 439 440
    ABC_FREE( p );
}
static inline void Abc_SclLibFree( SC_Lib * p )
{
441 442 443 444
    SC_WireLoad * pWL;
    SC_WireLoadSel * pWLS;
    SC_TableTempl * pTempl;
    SC_Cell * pCell;
445
    int i;
446
    SC_LibForEachWireLoad( p, pWL, i )
447
        Abc_SclWireLoadFree( pWL );
448
    Vec_PtrErase( &p->vWireLoads );
449
    SC_LibForEachWireLoadSel( p, pWLS, i )
450
        Abc_SclWireLoadSelFree( pWLS );
451
    Vec_PtrErase( &p->vWireLoadSels );
452
    SC_LibForEachTempl( p, pTempl, i )
453
        Abc_SclTableTemplFree( pTempl );
454
    Vec_PtrErase( &p->vTempls );
455
    SC_LibForEachCell( p, pCell, i )
456
        Abc_SclCellFree( pCell );
457 458
    Vec_PtrErase( &p->vCells );
    Vec_PtrErase( &p->vCellClasses );
459
    ABC_FREE( p->pName );
460
    ABC_FREE( p->pFileName );
461 462
    ABC_FREE( p->default_wire_load );
    ABC_FREE( p->default_wire_load_sel );
463
    ABC_FREE( p->pBins );
464 465 466 467
    ABC_FREE( p );
}


468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484
/**Function*************************************************************

  Synopsis    [Lookup table delay computation.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
static inline float Scl_LibLookup( SC_Surface * p, float slew, float load )
{
    float * pIndex0, * pIndex1, * pDataS, * pDataS1;
    float sfrac, lfrac, p0, p1;
    int s, l;

485
    // handle constant table
486
    if ( Vec_FltSize(&p->vIndex0) == 1 && Vec_FltSize(&p->vIndex1) == 1 )
487
    {
488 489
        Vec_Flt_t * vTemp = (Vec_Flt_t *)Vec_PtrEntry(&p->vData, 0);
        assert( Vec_PtrSize(&p->vData) == 1 );
490 491 492 493
        assert( Vec_FltSize(vTemp) == 1 );
        return Vec_FltEntry(vTemp, 0);
    }

494
    // Find closest sample points in surface:
495 496
    pIndex0 = Vec_FltArray(&p->vIndex0);
    for ( s = 1; s < Vec_FltSize(&p->vIndex0)-1; s++ )
497 498 499 500
        if ( pIndex0[s] > slew )
            break;
    s--;

501 502
    pIndex1 = Vec_FltArray(&p->vIndex1);
    for ( l = 1; l < Vec_FltSize(&p->vIndex1)-1; l++ )
503 504 505 506 507 508 509 510
        if ( pIndex1[l] > load )
            break;
    l--;

    // Interpolate (or extrapolate) function value from sample points:
    sfrac = (slew - pIndex0[s]) / (pIndex0[s+1] - pIndex0[s]);
    lfrac = (load - pIndex1[l]) / (pIndex1[l+1] - pIndex1[l]);

511 512
    pDataS  = Vec_FltArray( (Vec_Flt_t *)Vec_PtrEntry(&p->vData, s) );
    pDataS1 = Vec_FltArray( (Vec_Flt_t *)Vec_PtrEntry(&p->vData, s+1) );
513 514 515 516 517 518 519 520 521 522

    p0 = pDataS [l] + lfrac * (pDataS [l+1] - pDataS [l]);
    p1 = pDataS1[l] + lfrac * (pDataS1[l+1] - pDataS1[l]);

    return p0 + sfrac * (p1 - p0);      // <<== multiply result with K factor here 
}
static inline void Scl_LibPinArrival( SC_Timing * pTime, SC_Pair * pArrIn, SC_Pair * pSlewIn, SC_Pair * pLoad, SC_Pair * pArrOut, SC_Pair * pSlewOut )
{
    if (pTime->tsense == sc_ts_Pos || pTime->tsense == sc_ts_Non)
    {
523 524 525 526
        pArrOut->rise  = Abc_MaxFloat( pArrOut->rise,  pArrIn->rise + Scl_LibLookup(&pTime->pCellRise,  pSlewIn->rise, pLoad->rise) );
        pArrOut->fall  = Abc_MaxFloat( pArrOut->fall,  pArrIn->fall + Scl_LibLookup(&pTime->pCellFall,  pSlewIn->fall, pLoad->fall) );
        pSlewOut->rise = Abc_MaxFloat( pSlewOut->rise,                Scl_LibLookup(&pTime->pRiseTrans, pSlewIn->rise, pLoad->rise) );
        pSlewOut->fall = Abc_MaxFloat( pSlewOut->fall,                Scl_LibLookup(&pTime->pFallTrans, pSlewIn->fall, pLoad->fall) );
527 528 529
    }
    if (pTime->tsense == sc_ts_Neg || pTime->tsense == sc_ts_Non)
    {
530 531 532 533
        pArrOut->rise  = Abc_MaxFloat( pArrOut->rise,  pArrIn->fall + Scl_LibLookup(&pTime->pCellRise,  pSlewIn->fall, pLoad->rise) );
        pArrOut->fall  = Abc_MaxFloat( pArrOut->fall,  pArrIn->rise + Scl_LibLookup(&pTime->pCellFall,  pSlewIn->rise, pLoad->fall) );
        pSlewOut->rise = Abc_MaxFloat( pSlewOut->rise,                Scl_LibLookup(&pTime->pRiseTrans, pSlewIn->fall, pLoad->rise) );
        pSlewOut->fall = Abc_MaxFloat( pSlewOut->fall,                Scl_LibLookup(&pTime->pFallTrans, pSlewIn->rise, pLoad->fall) );
534 535 536 537 538 539
    }
}
static inline void Scl_LibPinDeparture( SC_Timing * pTime, SC_Pair * pDepIn, SC_Pair * pSlewIn, SC_Pair * pLoad, SC_Pair * pDepOut )
{
    if (pTime->tsense == sc_ts_Pos || pTime->tsense == sc_ts_Non)
    {
540 541
        pDepIn->rise  = Abc_MaxFloat( pDepIn->rise,  pDepOut->rise + Scl_LibLookup(&pTime->pCellRise,  pSlewIn->rise, pLoad->rise) );
        pDepIn->fall  = Abc_MaxFloat( pDepIn->fall,  pDepOut->fall + Scl_LibLookup(&pTime->pCellFall,  pSlewIn->fall, pLoad->fall) );
542 543 544
    }
    if (pTime->tsense == sc_ts_Neg || pTime->tsense == sc_ts_Non)
    {
545 546
        pDepIn->fall  = Abc_MaxFloat( pDepIn->fall,  pDepOut->rise + Scl_LibLookup(&pTime->pCellRise,  pSlewIn->fall, pLoad->rise) );
        pDepIn->rise  = Abc_MaxFloat( pDepIn->rise,  pDepOut->fall + Scl_LibLookup(&pTime->pCellFall,  pSlewIn->rise, pLoad->fall) );
547 548 549 550 551
    }
}

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

552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609
  Synopsis    [Lookup table delay computation.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
static inline int Scl_LibLookupI( SC_Surface * p, int slew, int load )
{
    int * pIndex0, * pIndex1, * pDataS, * pDataS1;
    int p0, p1, s, l;
    iword lFrac0, lFrac1, sFrac;

    // handle constant table
    if ( Vec_IntSize(&p->vIndex0I) == 1 && Vec_IntSize(&p->vIndex1I) == 1 )
    {
        Vec_Int_t * vTemp = (Vec_Int_t *)Vec_PtrEntry(&p->vDataI, 0);
        assert( Vec_PtrSize(&p->vDataI) == 1 );
        assert( Vec_IntSize(vTemp) == 1 );
        return Vec_IntEntry(vTemp, 0);
    }

    // Find closest sample points in surface:
    pIndex0 = Vec_IntArray(&p->vIndex0I);
    for ( s = 1; s < Vec_IntSize(&p->vIndex0I)-1; s++ )
        if ( pIndex0[s] > slew )
            break;
    s--;

    pIndex1 = Vec_IntArray(&p->vIndex1I);
    for ( l = 1; l < Vec_IntSize(&p->vIndex1I)-1; l++ )
        if ( pIndex1[l] > load )
            break;
    l--;

    pDataS  = Vec_IntArray( (Vec_Int_t *)Vec_PtrEntry(&p->vDataI, s) );
    pDataS1 = Vec_IntArray( (Vec_Int_t *)Vec_PtrEntry(&p->vDataI, s+1) );

    // Interpolate (or extrapolate) function value from sample points:
//    lfrac = (load - pIndex1[l]) / (pIndex1[l+1] - pIndex1[l]);
//    sfrac = (slew - pIndex0[s]) / (pIndex0[s+1] - pIndex0[s]);

    lFrac0 = (iword)(pDataS [l+1] - pDataS [l]) * (iword)(load - pIndex1[l]) / (iword)(pIndex1[l+1] - pIndex1[l]);
    lFrac1 = (iword)(pDataS1[l+1] - pDataS1[l]) * (iword)(load - pIndex1[l]) / (iword)(pIndex1[l+1] - pIndex1[l]);

//    p0 = pDataS [l] + lfrac * (pDataS [l+1] - pDataS [l]);
//    p1 = pDataS1[l] + lfrac * (pDataS1[l+1] - pDataS1[l]);

    p0 = pDataS [l] + (int)lFrac0;
    p1 = pDataS1[l] + (int)lFrac1;

    sFrac = (iword)(p1 - p0) * (iword)(slew - pIndex0[s]) / (iword)(pIndex0[s+1] - pIndex0[s]);

//    return p0 + sfrac * (p1 - p0); 
    return p0 + (int)sFrac;   
}
610
static inline void Scl_LibPinArrivalI( SC_Timing * pTime, SC_PairI * pArrIn, SC_PairI * pSlewIn, SC_PairI * pLoad, SC_PairI * pArrOut, SC_PairI * pSlewOut, int * pArray )
611 612 613
{
    if (pTime->tsense == sc_ts_Pos || pTime->tsense == sc_ts_Non)
    {
614 615 616 617
        pArrOut->rise  = Abc_MaxInt( pArrOut->rise,  pArrIn->rise + (pArray[0] = Scl_LibLookupI(&pTime->pCellRise,  pSlewIn->rise, pLoad->rise)) );
        pArrOut->fall  = Abc_MaxInt( pArrOut->fall,  pArrIn->fall + (pArray[1] = Scl_LibLookupI(&pTime->pCellFall,  pSlewIn->fall, pLoad->fall)) );
        pSlewOut->rise = Abc_MaxInt( pSlewOut->rise,                             Scl_LibLookupI(&pTime->pRiseTrans, pSlewIn->rise, pLoad->rise) );
        pSlewOut->fall = Abc_MaxInt( pSlewOut->fall,                             Scl_LibLookupI(&pTime->pFallTrans, pSlewIn->fall, pLoad->fall) );
618 619 620
    }
    if (pTime->tsense == sc_ts_Neg || pTime->tsense == sc_ts_Non)
    {
621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637
        pArrOut->rise  = Abc_MaxInt( pArrOut->rise,  pArrIn->fall + (pArray[2] = Scl_LibLookupI(&pTime->pCellRise,  pSlewIn->fall, pLoad->rise)) );
        pArrOut->fall  = Abc_MaxInt( pArrOut->fall,  pArrIn->rise + (pArray[3] = Scl_LibLookupI(&pTime->pCellFall,  pSlewIn->rise, pLoad->fall)) );
        pSlewOut->rise = Abc_MaxInt( pSlewOut->rise,                             Scl_LibLookupI(&pTime->pRiseTrans, pSlewIn->fall, pLoad->rise) );
        pSlewOut->fall = Abc_MaxInt( pSlewOut->fall,                             Scl_LibLookupI(&pTime->pFallTrans, pSlewIn->rise, pLoad->fall) );
    }
}
static inline void Scl_LibPinRequiredI( SC_Timing * pTime, SC_PairI * pReqIn, SC_PairI * pReqOut, int * pArray )
{
    if (pTime->tsense == sc_ts_Pos || pTime->tsense == sc_ts_Non)
    {
        pReqIn->rise  = Abc_MinInt( pReqIn->rise,  pReqOut->rise - pArray[0] );
        pReqIn->fall  = Abc_MinInt( pReqIn->fall,  pReqOut->fall - pArray[1] );
    }
    if (pTime->tsense == sc_ts_Neg || pTime->tsense == sc_ts_Non)
    {
        pReqIn->fall  = Abc_MinInt( pReqIn->fall,  pReqOut->rise - pArray[2] );
        pReqIn->rise  = Abc_MinInt( pReqIn->rise,  pReqOut->fall - pArray[3] );
638 639 640 641 642
    }
}

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

643
  Synopsis    [Compute one timing edge.]
644 645 646 647 648 649 650 651

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
652
static inline SC_Timing * Scl_CellPinTime( SC_Cell * pCell, int iPin )
653 654
{
    SC_Pin * pPin;
655 656 657
    SC_Timings * pRTime;
    assert( iPin >= 0 && iPin < pCell->n_inputs );
    pPin = SC_CellPin( pCell, pCell->n_inputs );
658 659 660
    assert( Vec_PtrSize(&pPin->vRTimings) == pCell->n_inputs );
    pRTime = (SC_Timings *)Vec_PtrEntry( &pPin->vRTimings, iPin );
    if ( Vec_PtrSize(&pRTime->vTimings) == 0 )
661
        return NULL;
662 663
    assert( Vec_PtrSize(&pRTime->vTimings) == 1 );
    return (SC_Timing *)Vec_PtrEntry( &pRTime->vTimings, 0 );
664
}
665
static inline float Scl_LibPinArrivalEstimate( SC_Cell * pCell, int iPin, float Slew, float Load )
666
{
667
    SC_Pair LoadIn = { Load, Load };
668 669 670 671
    SC_Pair ArrIn  = { 0.0, 0.0 };
    SC_Pair ArrOut = { 0.0, 0.0 };
    SC_Pair SlewIn = { 0.0, 0.0 };
    SC_Pair SlewOut = { 0.0, 0.0 };
672
//    Vec_Flt_t * vIndex0 = pTime->pCellRise->vIndex0; // slew
673 674 675
//    SlewIn.fall = SlewIn.rise = Vec_FltEntry( vIndex0, Vec_FltSize(vIndex0)/2 );
    SlewIn.fall = SlewIn.rise = Slew; 
    Scl_LibPinArrival( Scl_CellPinTime(pCell, iPin), &ArrIn, &SlewIn, &LoadIn, &ArrOut, &SlewOut );
676
    return  0.5 * ArrOut.fall +  0.5 * ArrOut.rise;
677
}
678 679 680 681 682 683 684 685 686 687 688 689 690 691 692
static inline void Scl_LibHandleInputDriver( SC_Cell * pCell, SC_Pair * pLoadIn, SC_Pair * pArrOut, SC_Pair * pSlewOut )
{
    SC_Pair LoadIn   = { 0.0, 0.0 }; // zero input load
    SC_Pair ArrIn    = { 0.0, 0.0 }; // zero input time
    SC_Pair SlewIn   = { 0.0, 0.0 }; // zero input slew
    SC_Pair ArrOut0  = { 0.0, 0.0 }; // output time under zero load
    SC_Pair ArrOut1  = { 0.0, 0.0 }; // output time under given load
    SC_Pair SlewOut  = { 0.0, 0.0 }; // output slew under zero load 
    pSlewOut->fall = pSlewOut->rise = 0;
    assert( pCell->n_inputs == 1 );
    Scl_LibPinArrival( Scl_CellPinTime(pCell, 0), &ArrIn, &SlewIn, &LoadIn, &ArrOut0, &SlewOut );
    Scl_LibPinArrival( Scl_CellPinTime(pCell, 0), &ArrIn, &SlewIn, pLoadIn, &ArrOut1, pSlewOut );
    pArrOut->fall = ArrOut1.fall - ArrOut0.fall;
    pArrOut->rise = ArrOut1.rise - ArrOut0.rise;
}
693

694 695 696 697 698 699 700 701 702 703 704 705 706
/**Function*************************************************************

  Synopsis    [Compute one timing edge.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
static inline int Scl_LibPinArrivalEstimateI( SC_Cell * pCell, int iPin, int Slew, int Load )
{
707
    int Arrray[4];
708 709 710 711 712 713 714 715
    SC_PairI LoadIn = { Load, Load };
    SC_PairI ArrIn  = { 0, 0 };
    SC_PairI ArrOut = { 0, 0 };
    SC_PairI SlewIn = { 0, 0 };
    SC_PairI SlewOut = { 0, 0 };
//    Vec_Flt_t * vIndex0 = pTime->pCellRise->vIndex0; // slew
//    SlewIn.fall = SlewIn.rise = Vec_FltEntry( vIndex0, Vec_FltSize(vIndex0)/2 );
    SlewIn.fall = SlewIn.rise = Slew; 
716
    Scl_LibPinArrivalI( Scl_CellPinTime(pCell, iPin), &ArrIn, &SlewIn, &LoadIn, &ArrOut, &SlewOut, Arrray );
717 718 719 720
    return (ArrOut.fall + ArrOut.rise) >> 1;
}
static inline void Scl_LibHandleInputDriver2( SC_Cell * pCell, SC_PairI * pLoadIn, SC_PairI * pArrOut, SC_PairI * pSlewOut )
{
721
    int Arrray[4];
722 723 724 725 726 727 728 729
    SC_PairI LoadIn   = { 0, 0 }; // zero input load
    SC_PairI ArrIn    = { 0, 0 }; // zero input time
    SC_PairI SlewIn   = { 0, 0 }; // zero input slew
    SC_PairI ArrOut0  = { 0, 0 }; // output time under zero load
    SC_PairI ArrOut1  = { 0, 0 }; // output time under given load
    SC_PairI SlewOut  = { 0, 0 }; // output slew under zero load 
    pSlewOut->fall = pSlewOut->rise = 0;
    assert( pCell->n_inputs == 1 );
730 731
    Scl_LibPinArrivalI( Scl_CellPinTime(pCell, 0), &ArrIn, &SlewIn, &LoadIn, &ArrOut0, &SlewOut, Arrray );
    Scl_LibPinArrivalI( Scl_CellPinTime(pCell, 0), &ArrIn, &SlewIn, pLoadIn, &ArrOut1, pSlewOut, Arrray );
732 733 734 735
    pArrOut->fall = ArrOut1.fall - ArrOut0.fall;
    pArrOut->rise = ArrOut1.rise - ArrOut0.rise;
}

736 737 738
/*=== sclLiberty.c ===============================================================*/
extern SC_Lib *      Abc_SclReadLiberty( char * pFileName, int fVerbose, int fVeryVerbose );
/*=== sclLibScl.c ===============================================================*/
739
extern SC_Lib *      Abc_SclReadFromGenlib( void * pLib );
740 741 742 743 744
extern SC_Lib *      Abc_SclReadFromStr( Vec_Str_t * vOut );
extern SC_Lib *      Abc_SclReadFromFile( char * pFileName );
extern void          Abc_SclWriteScl( char * pFileName, SC_Lib * p );
extern void          Abc_SclWriteLiberty( char * pFileName, SC_Lib * p );
/*=== sclLibUtil.c ===============================================================*/
745 746
extern void          Abc_SclHashCells( SC_Lib * p );
extern int           Abc_SclCellFind( SC_Lib * p, char * pName );
747
extern int           Abc_SclClassCellNum( SC_Cell * pClass );
748
extern void          Abc_SclShortNames( SC_Lib * p );
749
extern int           Abc_SclLibClassNum( SC_Lib * pLib );
750
extern void          Abc_SclLinkCells( SC_Lib * p );
751
extern void          Abc_SclPrintCells( SC_Lib * p, float Slew, float Gain, int fInvOnly, int fShort );
752
extern void          Abc_SclConvertLeakageIntoArea( SC_Lib * p, float A, float B );
753
extern void          Abc_SclLibNormalize( SC_Lib * p );
754
extern SC_Cell *     Abc_SclFindInvertor( SC_Lib * p, int fFindBuff );
755
extern SC_Cell *     Abc_SclFindSmallestGate( SC_Cell * p, float CinMin );
756
extern SC_WireLoad * Abc_SclFindWireLoadModel( SC_Lib * p, float Area );
757
extern SC_WireLoad * Abc_SclFetchWireLoadModel( SC_Lib * p, char * pName );
758
extern int           Abc_SclHasDelayInfo( void * pScl );
759
extern float         Abc_SclComputeAverageSlew( SC_Lib * p );
760
extern void          Abc_SclDumpGenlib( char * pFileName, SC_Lib * p, float Slew, float Gain, int nGatesMin );
761
extern void          Abc_SclInstallGenlib( void * pScl, float Slew, float Gain, int nGatesMin );
762

763 764 765 766 767 768 769 770

ABC_NAMESPACE_HEADER_END

#endif

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