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


466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482
/**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;

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

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

499 500
    pIndex1 = Vec_FltArray(&p->vIndex1);
    for ( l = 1; l < Vec_FltSize(&p->vIndex1)-1; l++ )
501 502 503 504 505 506 507 508
        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]);

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

    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)
    {
521 522 523 524
        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) );
525 526 527
    }
    if (pTime->tsense == sc_ts_Neg || pTime->tsense == sc_ts_Non)
    {
528 529 530 531
        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) );
532 533 534 535 536 537
    }
}
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)
    {
538 539
        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) );
540 541 542
    }
    if (pTime->tsense == sc_ts_Neg || pTime->tsense == sc_ts_Non)
    {
543 544
        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) );
545 546 547 548 549
    }
}

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

550 551 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
  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;   
}
608
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 )
609 610 611
{
    if (pTime->tsense == sc_ts_Pos || pTime->tsense == sc_ts_Non)
    {
612 613 614 615
        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) );
616 617 618
    }
    if (pTime->tsense == sc_ts_Neg || pTime->tsense == sc_ts_Non)
    {
619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635
        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] );
636 637 638 639 640
    }
}

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

641
  Synopsis    [Compute one timing edge.]
642 643 644 645 646 647 648 649

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
650
static inline SC_Timing * Scl_CellPinTime( SC_Cell * pCell, int iPin )
651 652
{
    SC_Pin * pPin;
653 654 655
    SC_Timings * pRTime;
    assert( iPin >= 0 && iPin < pCell->n_inputs );
    pPin = SC_CellPin( pCell, pCell->n_inputs );
656 657 658
    assert( Vec_PtrSize(&pPin->vRTimings) == pCell->n_inputs );
    pRTime = (SC_Timings *)Vec_PtrEntry( &pPin->vRTimings, iPin );
    if ( Vec_PtrSize(&pRTime->vTimings) == 0 )
659
        return NULL;
660 661
    assert( Vec_PtrSize(&pRTime->vTimings) == 1 );
    return (SC_Timing *)Vec_PtrEntry( &pRTime->vTimings, 0 );
662
}
663
static inline float Scl_LibPinArrivalEstimate( SC_Cell * pCell, int iPin, float Slew, float Load )
664
{
665
    SC_Pair LoadIn = { Load, Load };
666 667 668 669
    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 };
670
//    Vec_Flt_t * vIndex0 = pTime->pCellRise->vIndex0; // slew
671 672 673
//    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 );
674
    return  0.5 * ArrOut.fall +  0.5 * ArrOut.rise;
675
}
676 677 678 679 680 681 682 683 684 685 686 687 688 689 690
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;
}
691

692 693 694 695 696 697 698 699 700 701 702 703 704
/**Function*************************************************************

  Synopsis    [Compute one timing edge.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
static inline int Scl_LibPinArrivalEstimateI( SC_Cell * pCell, int iPin, int Slew, int Load )
{
705
    int Arrray[4];
706 707 708 709 710 711 712 713
    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; 
714
    Scl_LibPinArrivalI( Scl_CellPinTime(pCell, iPin), &ArrIn, &SlewIn, &LoadIn, &ArrOut, &SlewOut, Arrray );
715 716 717 718
    return (ArrOut.fall + ArrOut.rise) >> 1;
}
static inline void Scl_LibHandleInputDriver2( SC_Cell * pCell, SC_PairI * pLoadIn, SC_PairI * pArrOut, SC_PairI * pSlewOut )
{
719
    int Arrray[4];
720 721 722 723 724 725 726 727
    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 );
728 729
    Scl_LibPinArrivalI( Scl_CellPinTime(pCell, 0), &ArrIn, &SlewIn, &LoadIn, &ArrOut0, &SlewOut, Arrray );
    Scl_LibPinArrivalI( Scl_CellPinTime(pCell, 0), &ArrIn, &SlewIn, pLoadIn, &ArrOut1, pSlewOut, Arrray );
730 731 732 733
    pArrOut->fall = ArrOut1.fall - ArrOut0.fall;
    pArrOut->rise = ArrOut1.rise - ArrOut0.rise;
}

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

761 762 763 764 765 766 767 768

ABC_NAMESPACE_HEADER_END

#endif

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