sclLibScl.c 23.9 KB
Newer Older
1 2
/**CFile****************************************************************

3
  FileName    [sclLibScl.c]
4 5 6

  SystemName  [ABC: Logic synthesis and verification system.]

7 8
  PackageName [Standard-cell library representation.]

9
  Synopsis    [Liberty abstraction for delay-oriented mapping.]
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: sclLibScl.c,v 1.0 2012/08/24 00:00:00 alanmi Exp $]
18 19 20

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

21 22
#include "sclLib.h"
#include "misc/st/st.h"
23
#include "map/mio/mio.h"
24
#include "bool/kit/kit.h"
25 26 27 28 29 30 31 32 33 34 35 36 37 38

ABC_NAMESPACE_IMPL_START


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

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

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

39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
  Synopsis    [Reading library from file.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
static void Abc_SclReadSurface( Vec_Str_t * vOut, int * pPos, SC_Surface * p )
{
    Vec_Flt_t * vVec;
    int i, j;

    for ( i = Vec_StrGetI(vOut, pPos); i != 0; i-- )
        Vec_FltPush( p->vIndex0, Vec_StrGetF(vOut, pPos) );

    for ( i = Vec_StrGetI(vOut, pPos); i != 0; i-- )
        Vec_FltPush( p->vIndex1, Vec_StrGetF(vOut, pPos) );

    for ( i = 0; i < Vec_FltSize(p->vIndex0); i++ )
    {
        vVec = Vec_FltAlloc( Vec_FltSize(p->vIndex1) );
        Vec_PtrPush( p->vData, vVec );
        for ( j = 0; j < Vec_FltSize(p->vIndex1); j++ )
            Vec_FltPush( vVec, Vec_StrGetF(vOut, pPos) );
    }

    for ( i = 0; i < 3; i++ ) 
        p->approx[0][i] = Vec_StrGetF( vOut, pPos );
    for ( i = 0; i < 4; i++ ) 
        p->approx[1][i] = Vec_StrGetF( vOut, pPos );
    for ( i = 0; i < 6; i++ ) 
        p->approx[2][i] = Vec_StrGetF( vOut, pPos );
}
74
static int Abc_SclReadLibrary( Vec_Str_t * vOut, int * pPos, SC_Lib * p )
75 76 77
{
    int i, j, k, n;
    int version = Vec_StrGetI( vOut, pPos );
78 79 80 81 82 83
    if ( version != ABC_SCL_CUR_VERSION )
    { 
        Abc_Print( -1, "Wrong version of the SCL file.\n" ); 
        return 0; 
    }
    assert( version == ABC_SCL_CUR_VERSION ); // wrong version of the file
84 85

    // Read non-composite fields:
86
    p->pName                 = Vec_StrGetS(vOut, pPos);
87 88 89 90 91 92 93 94 95 96 97 98 99 100
    p->default_wire_load     = Vec_StrGetS(vOut, pPos);
    p->default_wire_load_sel = Vec_StrGetS(vOut, pPos);
    p->default_max_out_slew  = Vec_StrGetF(vOut, pPos);

    p->unit_time             = Vec_StrGetI(vOut, pPos);
    p->unit_cap_fst          = Vec_StrGetF(vOut, pPos);
    p->unit_cap_snd          = Vec_StrGetI(vOut, pPos);

    // Read 'wire_load' vector:
    for ( i = Vec_StrGetI(vOut, pPos); i != 0; i-- )
    {
        SC_WireLoad * pWL = Abc_SclWireLoadAlloc();
        Vec_PtrPush( p->vWireLoads, pWL );

101
        pWL->pName = Vec_StrGetS(vOut, pPos);
102 103
        pWL->cap   = Vec_StrGetF(vOut, pPos);
        pWL->slope = Vec_StrGetF(vOut, pPos);
104 105 106 107 108 109 110 111 112 113 114 115 116 117

        for ( j = Vec_StrGetI(vOut, pPos); j != 0; j-- )
        {
            Vec_IntPush( pWL->vFanout, Vec_StrGetI(vOut, pPos) );
            Vec_FltPush( pWL->vLen,    Vec_StrGetF(vOut, pPos) );
        }
    }

    // Read 'wire_load_sel' vector:
    for ( i = Vec_StrGetI(vOut, pPos); i != 0; i-- )
    {
        SC_WireLoadSel * pWLS = Abc_SclWireLoadSelAlloc();
        Vec_PtrPush( p->vWireLoadSels, pWLS );

118
        pWLS->pName = Vec_StrGetS(vOut, pPos);
119 120 121 122 123 124 125 126 127 128 129
        for ( j = Vec_StrGetI(vOut, pPos); j != 0; j-- )
        {
            Vec_FltPush( pWLS->vAreaFrom,      Vec_StrGetF(vOut, pPos) );
            Vec_FltPush( pWLS->vAreaTo,        Vec_StrGetF(vOut, pPos) );
            Vec_PtrPush( pWLS->vWireLoadModel, Vec_StrGetS(vOut, pPos) );
        }
    }

    for ( i = Vec_StrGetI(vOut, pPos); i != 0; i-- )
    {
        SC_Cell * pCell = Abc_SclCellAlloc();
130
        pCell->Id = SC_LibCellNum(p);
131 132
        Vec_PtrPush( p->vCells, pCell );

133
        pCell->pName           = Vec_StrGetS(vOut, pPos);     
134 135 136 137 138
        pCell->area           = Vec_StrGetF(vOut, pPos);
        pCell->drive_strength = Vec_StrGetI(vOut, pPos);

        pCell->n_inputs       = Vec_StrGetI(vOut, pPos);
        pCell->n_outputs      = Vec_StrGetI(vOut, pPos);
139 140 141 142 143 144 145
/*
        printf( "%s\n", pCell->pName );
        if ( !strcmp( "XOR3_X4M_A9TL", pCell->pName ) )
        {
            int s = 0;
        }
*/
146 147 148 149 150 151
        for ( j = 0; j < pCell->n_inputs; j++ )
        {
            SC_Pin * pPin = Abc_SclPinAlloc();
            Vec_PtrPush( pCell->vPins, pPin );

            pPin->dir      = sc_dir_Input;
152
            pPin->pName    = Vec_StrGetS(vOut, pPos); 
153 154 155 156 157 158 159 160 161 162
            pPin->rise_cap = Vec_StrGetF(vOut, pPos);
            pPin->fall_cap = Vec_StrGetF(vOut, pPos);
        }

        for ( j = 0; j < pCell->n_outputs; j++ )
        {
            SC_Pin * pPin = Abc_SclPinAlloc();
            Vec_PtrPush( pCell->vPins, pPin );

            pPin->dir          = sc_dir_Output;
163
            pPin->pName        = Vec_StrGetS(vOut, pPos); 
164 165 166 167 168 169
            pPin->max_out_cap  = Vec_StrGetF(vOut, pPos);
            pPin->max_out_slew = Vec_StrGetF(vOut, pPos);

            k = Vec_StrGetI(vOut, pPos);
            assert( k == pCell->n_inputs );

170
            // read function
171 172 173 174 175 176 177 178
            // (possibly empty) formula is always given
            assert( version == ABC_SCL_CUR_VERSION );
            assert( pPin->func_text == NULL );
            pPin->func_text = Vec_StrGetS(vOut, pPos); 
            if ( pPin->func_text[0] == 0 )
            {
                // formula is not given - read truth table
                ABC_FREE( pPin->func_text );
179 180 181 182 183 184 185
                assert( Vec_WrdSize(pPin->vFunc) == 0 );
                Vec_WrdGrow( pPin->vFunc, Abc_Truth6WordNum(pCell->n_inputs) );
                for ( k = 0; k < Vec_WrdCap(pPin->vFunc); k++ )
                    Vec_WrdPush( pPin->vFunc, Vec_StrGetW(vOut, pPos) );
            }
            else
            {
186 187 188 189 190 191 192 193 194 195 196 197 198 199 200
                // formula is given - derive truth table
                SC_Pin * pPin2;
                Vec_Ptr_t * vNames;
                // collect input names
                vNames = Vec_PtrAlloc( pCell->n_inputs );
                SC_CellForEachPinIn( pCell, pPin2, n )
                    Vec_PtrPush( vNames, pPin2->pName );
                // derive truth table
                assert( Vec_WrdSize(pPin->vFunc) == 0 );
                Vec_WrdFree( pPin->vFunc );
                pPin->vFunc = Mio_ParseFormulaTruth( pPin->func_text, (char **)Vec_PtrArray(vNames), pCell->n_inputs );
                Vec_PtrFree( vNames );
                // skip truth table
                assert( Vec_WrdSize(pPin->vFunc) == Abc_Truth6WordNum(pCell->n_inputs) );
                for ( k = 0; k < Vec_WrdSize(pPin->vFunc); k++ )
201
                {
202 203
                    word Value = Vec_StrGetW(vOut, pPos);
                    assert( Value == Vec_WrdEntry(pPin->vFunc, k) );
204 205
                }
            }
206 207 208 209 210 211 212

            // Read 'rtiming': (pin-to-pin timing tables for this particular output)
            for ( k = 0; k < pCell->n_inputs; k++ )
            {
                SC_Timings * pRTime = Abc_SclTimingsAlloc();
                Vec_PtrPush( pPin->vRTimings, pRTime );

213
                pRTime->pName = Vec_StrGetS(vOut, pPos);
214 215 216 217 218 219 220 221 222 223 224 225 226
                n = Vec_StrGetI(vOut, pPos); assert( n <= 1 );
                if ( n == 1 )
                {
                    SC_Timing * pTime = Abc_SclTimingAlloc();
                    Vec_PtrPush( pRTime->vTimings, pTime );

                    pTime->tsense = (SC_TSense)Vec_StrGetI(vOut, pPos);
                    Abc_SclReadSurface( vOut, pPos, pTime->pCellRise );
                    Abc_SclReadSurface( vOut, pPos, pTime->pCellFall );
                    Abc_SclReadSurface( vOut, pPos, pTime->pRiseTrans );
                    Abc_SclReadSurface( vOut, pPos, pTime->pFallTrans );
                }
                else
227
                    assert( Vec_PtrSize(pRTime->vTimings) == 0 );
228 229 230
            }
        }
    }
231
    return 1;
232
}
233 234 235 236 237 238
SC_Lib * Abc_SclReadFromStr( Vec_Str_t * vOut )
{
    SC_Lib * p;
    int Pos = 0;
    // read the library
    p = Abc_SclLibAlloc();
239 240
    if ( !Abc_SclReadLibrary( vOut, &Pos, p ) )
        return NULL;
241 242 243 244 245 246 247
    assert( Pos == Vec_StrSize(vOut) );
    // hash gates by name
    Abc_SclHashCells( p );
    Abc_SclLinkCells( p );
    return p;
}
SC_Lib * Abc_SclReadFromFile( char * pFileName )
248 249 250 251
{
    SC_Lib * p;
    FILE * pFile;
    Vec_Str_t * vOut;
252
    int nFileSize;
253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270
    pFile = fopen( pFileName, "rb" );
    if ( pFile == NULL )
    {
        printf( "Cannot open file \"%s\" for reading.\n", pFileName );
        return NULL;
    }
    // get the file size, in bytes
    fseek( pFile, 0, SEEK_END );  
    nFileSize = ftell( pFile );  
    rewind( pFile ); 
    // load the contents
    vOut = Vec_StrAlloc( nFileSize );
    vOut->nSize = vOut->nCap;
    assert( nFileSize == Vec_StrSize(vOut) );
    nFileSize = fread( Vec_StrArray(vOut), 1, Vec_StrSize(vOut), pFile );
    assert( nFileSize == Vec_StrSize(vOut) );
    fclose( pFile );
    // read the library
271
    p = Abc_SclReadFromStr( vOut );
272 273 274 275
    if ( p != NULL )
        p->pFileName = Abc_UtilStrsav( pFileName );
    if ( p != NULL )
        Abc_SclLibNormalize( p );
276 277 278
    Vec_StrFree( vOut );
    return p;
}
279 280 281 282 283 284 285 286 287 288 289 290 291 292 293

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

  Synopsis    [Writing library into file.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
static void Abc_SclWriteSurface( Vec_Str_t * vOut, SC_Surface * p )
{
    Vec_Flt_t * vVec;
294 295
    float Entry;
    int i, k;
296

297
    Vec_StrPutI( vOut, Vec_FltSize(p->vIndex0) );
298
    Vec_FltForEachEntry( p->vIndex0, Entry, i )
299
        Vec_StrPutF( vOut, Entry );
300

301
    Vec_StrPutI( vOut, Vec_FltSize(p->vIndex1) );
302
    Vec_FltForEachEntry( p->vIndex1, Entry, i )
303
        Vec_StrPutF( vOut, Entry );
304

305 306
    Vec_PtrForEachEntry( Vec_Flt_t *, p->vData, vVec, i )
        Vec_FltForEachEntry( vVec, Entry, k )
307
            Vec_StrPutF( vOut, Entry );
308 309

    for ( i = 0; i < 3; i++ ) 
310
        Vec_StrPutF( vOut, p->approx[0][i] );
311
    for ( i = 0; i < 4; i++ ) 
312
        Vec_StrPutF( vOut, p->approx[1][i] );
313
    for ( i = 0; i < 6; i++ ) 
314
        Vec_StrPutF( vOut, p->approx[2][i] );
315 316 317 318 319 320
}
static void Abc_SclWriteLibrary( Vec_Str_t * vOut, SC_Lib * p )
{
    SC_WireLoad * pWL;
    SC_WireLoadSel * pWLS;
    SC_Cell * pCell;
321
    SC_Pin * pPin;
322 323 324
    int n_valid_cells;
    int i, j, k;

325
    Vec_StrPutI( vOut, ABC_SCL_CUR_VERSION );
326 327

    // Write non-composite fields:
328
    Vec_StrPutS( vOut, p->pName );
329 330 331
    Vec_StrPutS( vOut, p->default_wire_load );
    Vec_StrPutS( vOut, p->default_wire_load_sel );
    Vec_StrPutF( vOut, p->default_max_out_slew );
332 333

    assert( p->unit_time >= 0 );
334
    assert( p->unit_cap_snd >= 0 );
335 336 337
    Vec_StrPutI( vOut, p->unit_time );
    Vec_StrPutF( vOut, p->unit_cap_fst );
    Vec_StrPutI( vOut, p->unit_cap_snd );
338 339

    // Write 'wire_load' vector:
340
    Vec_StrPutI( vOut, Vec_PtrSize(p->vWireLoads) );
341
    SC_LibForEachWireLoad( p, pWL, i )
342
    {
343
        Vec_StrPutS( vOut, pWL->pName );
344
        Vec_StrPutF( vOut, pWL->cap );
345
        Vec_StrPutF( vOut, pWL->slope );
346

347
        Vec_StrPutI( vOut, Vec_IntSize(pWL->vFanout) );
348 349
        for ( j = 0; j < Vec_IntSize(pWL->vFanout); j++ )
        {
350 351
            Vec_StrPutI( vOut, Vec_IntEntry(pWL->vFanout, j) );
            Vec_StrPutF( vOut, Vec_FltEntry(pWL->vLen, j) );
352 353 354 355
        }
    }

    // Write 'wire_load_sel' vector:
356
    Vec_StrPutI( vOut, Vec_PtrSize(p->vWireLoadSels) );
357
    SC_LibForEachWireLoadSel( p, pWLS, i )
358
    {
359
        Vec_StrPutS( vOut, pWLS->pName );
360
        Vec_StrPutI( vOut, Vec_FltSize(pWLS->vAreaFrom) );
361 362
        for ( j = 0; j < Vec_FltSize(pWLS->vAreaFrom); j++)
        {
363 364 365
            Vec_StrPutF( vOut, Vec_FltEntry(pWLS->vAreaFrom, j) );
            Vec_StrPutF( vOut, Vec_FltEntry(pWLS->vAreaTo, j) );
            Vec_StrPutS( vOut, (char *)Vec_PtrEntry(pWLS->vWireLoadModel, j) );
366 367 368 369 370
        }
    }

    // Write 'cells' vector:
    n_valid_cells = 0;
371
    SC_LibForEachCell( p, pCell, i )
372
        if ( !(pCell->seq || pCell->unsupp) )
373 374
            n_valid_cells++;

375
    Vec_StrPutI( vOut, n_valid_cells );
376
    SC_LibForEachCell( p, pCell, i )
377 378 379 380
    {
        if ( pCell->seq || pCell->unsupp )
            continue;

381
        Vec_StrPutS( vOut, pCell->pName );
382 383
        Vec_StrPutF( vOut, pCell->area );
        Vec_StrPutI( vOut, pCell->drive_strength );
384 385

        // Write 'pins': (sorted at this point; first inputs, then outputs)
386 387
        Vec_StrPutI( vOut, pCell->n_inputs);
        Vec_StrPutI( vOut, pCell->n_outputs);
388

389
        SC_CellForEachPinIn( pCell, pPin, j )
390 391
        {
            assert(pPin->dir == sc_dir_Input);
392
            Vec_StrPutS( vOut, pPin->pName );
393 394
            Vec_StrPutF( vOut, pPin->rise_cap );
            Vec_StrPutF( vOut, pPin->fall_cap );
395 396
        }

397
        SC_CellForEachPinOut( pCell, pPin, j )
398 399 400 401
        {
            SC_Timings * pRTime;
            word uWord;

402
            assert(pPin->dir == sc_dir_Output);
403
            Vec_StrPutS( vOut, pPin->pName );
404 405
            Vec_StrPutF( vOut, pPin->max_out_cap );
            Vec_StrPutF( vOut, pPin->max_out_slew );
406
            Vec_StrPutI( vOut, pCell->n_inputs );
407

408
            // write function
409
            Vec_StrPutS( vOut, pPin->func_text ? pPin->func_text : (char *)"" );
410 411 412 413 414

            // write truth table
            assert( Vec_WrdSize(pPin->vFunc) == Abc_Truth6WordNum(pCell->n_inputs) );
            Vec_WrdForEachEntry( pPin->vFunc, uWord, k ) // -- 'size = 1u << (n_vars - 6)'
                Vec_StrPutW( vOut, uWord );  // -- 64-bit number, written uncompressed (low-byte first)
415 416 417

            // Write 'rtiming': (pin-to-pin timing tables for this particular output)
            assert( Vec_PtrSize(pPin->vRTimings) == pCell->n_inputs );
418
            SC_PinForEachRTiming( pPin, pRTime, k )
419
            {
420
                Vec_StrPutS( vOut, pRTime->pName );
421
                Vec_StrPutI( vOut, Vec_PtrSize(pRTime->vTimings) );
422 423 424 425 426 427 428 429
                    // -- NOTE! After post-processing, the size of the 'rtiming[k]' vector is either
                    // 0 or 1 (in static timing, we have merged all tables to get the worst case).
                    // The case with size 0 should only occur for multi-output gates.
                if ( Vec_PtrSize(pRTime->vTimings) == 1 )
                {
                    SC_Timing * pTime = (SC_Timing *)Vec_PtrEntry( pRTime->vTimings, 0 );
                        // -- NOTE! We don't need to save 'related_pin' string because we have sorted 
                        // the elements on input pins.
430
                    Vec_StrPutI( vOut, (int)pTime->tsense);
431 432 433 434 435 436 437 438 439 440 441
                    Abc_SclWriteSurface( vOut, pTime->pCellRise );
                    Abc_SclWriteSurface( vOut, pTime->pCellFall );
                    Abc_SclWriteSurface( vOut, pTime->pRiseTrans );
                    Abc_SclWriteSurface( vOut, pTime->pFallTrans );
                }
                else
                    assert( Vec_PtrSize(pRTime->vTimings) == 0 );
            }
        }
    }
}
442
void Abc_SclWriteScl( char * pFileName, SC_Lib * p )
443 444 445 446 447 448 449
{
    Vec_Str_t * vOut;
    vOut = Vec_StrAlloc( 10000 );
    Abc_SclWriteLibrary( vOut, p );
    if ( Vec_StrSize(vOut) > 0 )
    {
        FILE * pFile = fopen( pFileName, "wb" );
450 451 452
        if ( pFile == NULL )
            printf( "Cannot open file \"%s\" for writing.\n", pFileName );
        else
453
        {
454
            fwrite( Vec_StrArray(vOut), 1, Vec_StrSize(vOut), pFile );
455 456 457 458 459 460 461 462 463
            fclose( pFile );
        }
    }
    Vec_StrFree( vOut );    
}


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

464
  Synopsis    [Writing library into text file.]
465 466 467 468 469 470 471 472

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
473
static void Abc_SclWriteSurfaceText( FILE * s, SC_Surface * p )
474 475
{
    Vec_Flt_t * vVec;
476 477 478
    float Entry;
    int i, k;

479
    fprintf( s, "          index_1(\"" );  
480
    Vec_FltForEachEntry( p->vIndex0, Entry, i )
481 482
        fprintf( s, "%f%s", Entry, i == Vec_FltSize(p->vIndex0)-1 ? "":", " );
    fprintf( s, "\");\n" );
483

484
    fprintf( s, "          index_2(\"" );  
485
    Vec_FltForEachEntry( p->vIndex1, Entry, i )
486 487
        fprintf( s, "%f%s", Entry, i == Vec_FltSize(p->vIndex1)-1 ? "":", " );
    fprintf( s, "\");\n" );
488

489
    fprintf( s, "          values (\"" );  
490
    Vec_PtrForEachEntry( Vec_Flt_t *, p->vData, vVec, i )
491
    {
492
        Vec_FltForEachEntry( vVec, Entry, k )
493 494 495 496 497 498 499 500
            fprintf( s, "%f%s", Entry, i == Vec_PtrSize(p->vData)-1 && k == Vec_FltSize(vVec)-1 ? "\");":", " );
        if ( i == Vec_PtrSize(p->vData)-1 )
            fprintf( s, "\n" );
        else
        {
            fprintf( s, "\\\n" );
            fprintf( s, "                   " );  
        }
501
    }
502 503 504
/*
    fprintf( s, "       approximations: \n" );
    fprintf( s, "       " );
505
    for ( i = 0; i < 3; i++ ) 
506 507
        fprintf( s, "%f ", p->approx[0][i] );
    fprintf( s, "\n" );
508
    fprintf( s, "       " );
509
    for ( i = 0; i < 4; i++ ) 
510 511
        fprintf( s, "%f ", p->approx[1][i] );
    fprintf( s, "\n" );
512
    fprintf( s, "       " );
513
    for ( i = 0; i < 6; i++ ) 
514 515
        fprintf( s, "%f ", p->approx[2][i] );
    fprintf( s, "\n" );
516 517
    fprintf( s, "       \n" );
*/
518
}
519
static void Abc_SclWriteLibraryText( FILE * s, SC_Lib * p )
520
{
521 522 523 524 525 526
    SC_WireLoad * pWL;
    SC_WireLoadSel * pWLS;
    SC_Cell * pCell;
    SC_Pin * pPin;
    int n_valid_cells;
    int i, j, k;
527
    fprintf( s, "/* This Liberty file was generated by ABC on %s */\n", Extra_TimeStamp() );
528
    fprintf( s, "/* The original unabridged library came from file \"%s\".*/\n\n", p->pFileName );
529

530
//    fprintf( s, "%d", ABC_SCL_CUR_VERSION );
531
    fprintf( s, "library(%s) {\n\n",                         p->pName );
532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547
    if ( p->default_wire_load && strlen(p->default_wire_load) )
    fprintf( s, "  default_wire_load : \"%s\";\n",           p->default_wire_load );
    if ( p->default_wire_load_sel && strlen(p->default_wire_load_sel) )
    fprintf( s, "  default_wire_load_selection : \"%s\";\n", p->default_wire_load_sel );
    if ( p->default_max_out_slew != -1 )
    fprintf( s, "  default_max_transition : %f;\n",          p->default_max_out_slew );
    if ( p->unit_time == 9 )
    fprintf( s, "  time_unit : \"1ns\";\n" );
    else if ( p->unit_time == 10 )
    fprintf( s, "  time_unit : \"100ps\";\n" );
    else if ( p->unit_time == 11 )
    fprintf( s, "  time_unit : \"10ps\";\n" );
    else if ( p->unit_time == 12 )
    fprintf( s, "  time_unit : \"1ps\";\n" );
    else assert( 0 );
    fprintf( s, "  capacitive_load_unit(%.1f,%s);\n",        p->unit_cap_fst, p->unit_cap_snd == 12 ? "pf" : "ff" );
548
    fprintf( s, "\n" );
549

550
    // Write 'wire_load' vector:
551
    SC_LibForEachWireLoad( p, pWL, i )
552
    {
553
        fprintf( s, "  wire_load(\"%s\") {\n", pWL->pName );
554
        fprintf( s, "    capacitance : %f;\n", pWL->cap );
555
        fprintf( s, "    slope : %f;\n", pWL->slope );
556
        for ( j = 0; j < Vec_IntSize(pWL->vFanout); j++ )
557 558
            fprintf( s, "    fanout_length( %d, %f );\n", Vec_IntEntry(pWL->vFanout, j), Vec_FltEntry(pWL->vLen, j) );
        fprintf( s, "  }\n\n" );
559 560
    }

561
    // Write 'wire_load_sel' vector:
562
    SC_LibForEachWireLoadSel( p, pWLS, i )
563
    {
564
        fprintf( s, "  wire_load_selection(\"%s\") {\n", pWLS->pName );
565
        for ( j = 0; j < Vec_FltSize(pWLS->vAreaFrom); j++)
566
            fprintf( s, "    wire_load_from_area( %f, %f, %s );\n", 
567 568 569 570
                Vec_FltEntry(pWLS->vAreaFrom, j), 
                Vec_FltEntry(pWLS->vAreaTo, j), 
                (char *)Vec_PtrEntry(pWLS->vWireLoadModel, j) );
        fprintf( s, "  }\n\n" );
571
    }
572 573 574

    // Write 'cells' vector:
    n_valid_cells = 0;
575
    SC_LibForEachCell( p, pCell, i )
576 577
        if ( !(pCell->seq || pCell->unsupp) )
            n_valid_cells++;
578

579
    SC_LibForEachCell( p, pCell, i )
580
    {
581 582
        if ( pCell->seq || pCell->unsupp )
            continue;
583

584
        fprintf( s, "\n" );
585
        fprintf( s, "  cell(%s) {\n", pCell->pName );
586 587 588
        fprintf( s, "    /*  n_inputs = %d  n_outputs = %d */\n", pCell->n_inputs, pCell->n_outputs );
        fprintf( s, "    area : %f;\n", pCell->area );
        fprintf( s, "    drive_strength : %d;\n", pCell->drive_strength );
589

590
        SC_CellForEachPinIn( pCell, pPin, j )
591
        {
592
            assert(pPin->dir == sc_dir_Input);
593
            fprintf( s, "    pin(%s) {\n", pPin->pName );
594 595 596 597
            fprintf( s, "      direction : %s;\n", "input" );
            fprintf( s, "      fall_capacitance : %f;\n", pPin->fall_cap );
            fprintf( s, "      rise_capacitance : %f;\n", pPin->rise_cap );
            fprintf( s, "    }\n" );
598 599
        }

600
        SC_CellForEachPinOut( pCell, pPin, j )
601
        {
602 603 604
            SC_Timings * pRTime;
//            word uWord;
            assert(pPin->dir == sc_dir_Output);
605
            fprintf( s, "    pin(%s) {\n", pPin->pName );
606 607 608 609 610
            fprintf( s, "      direction : %s;\n", "output" );
            fprintf( s, "      max_capacitance : %f;\n", pPin->max_out_cap );
            fprintf( s, "      max_transition : %f;\n", pPin->max_out_slew );
            fprintf( s, "      function : \"%s\";\n", pPin->func_text ? pPin->func_text : "?" );
            fprintf( s, "      /*  truth table = " );
611
            Extra_PrintHex( s, (unsigned *)Vec_WrdArray(pPin->vFunc), pCell->n_inputs );
612
            fprintf( s, "  */\n" );
613

614 615
            // Write 'rtiming': (pin-to-pin timing tables for this particular output)
            assert( Vec_PtrSize(pPin->vRTimings) == pCell->n_inputs );
616
            SC_PinForEachRTiming( pPin, pRTime, k )
617
            {
618
                if ( Vec_PtrSize(pRTime->vTimings) == 1 )
619
                {
620
                    SC_Timing * pTime = (SC_Timing *)Vec_PtrEntry( pRTime->vTimings, 0 );
621
                    fprintf( s, "      timing() {\n" );
622
                    fprintf( s, "        related_pin : \"%s\"\n", pRTime->pName );
623 624 625 626 627 628 629 630 631
                    if ( pTime->tsense == sc_ts_Pos )
                        fprintf( s, "        timing_sense : positive_unate;\n" );
                    else if ( pTime->tsense == sc_ts_Neg )
                        fprintf( s, "        timing_sense : negative_unate;\n" );
                    else if ( pTime->tsense == sc_ts_Non )
                        fprintf( s, "        timing_sense : non_unate;\n" );
                    else assert( 0 );

                    fprintf( s, "        cell_rise() {\n" );
632
                    Abc_SclWriteSurfaceText( s, pTime->pCellRise );
633 634 635
                    fprintf( s, "        }\n" );

                    fprintf( s, "        cell_fall() {\n" );
636
                    Abc_SclWriteSurfaceText( s, pTime->pCellFall );
637 638 639
                    fprintf( s, "        }\n" );

                    fprintf( s, "        rise_transition() {\n" );
640
                    Abc_SclWriteSurfaceText( s, pTime->pRiseTrans );
641 642 643
                    fprintf( s, "        }\n" );

                    fprintf( s, "        fall_transition() {\n" );
644
                    Abc_SclWriteSurfaceText( s, pTime->pFallTrans );
645 646
                    fprintf( s, "        }\n" );
                    fprintf( s, "      }\n" );
647 648
                }
                else
649
                    assert( Vec_PtrSize(pRTime->vTimings) == 0 );
650
            }
651
            fprintf( s, "    }\n" );
652
        }
653
        fprintf( s, "  }\n" );
654
    }
655
    fprintf( s, "}\n\n" );
656
}
657
void Abc_SclWriteLiberty( char * pFileName, SC_Lib * p )
658
{
659
    FILE * pFile = fopen( pFileName, "wb" );
660
    if ( pFile == NULL )
661 662
        printf( "Cannot open text file \"%s\" for writing.\n", pFileName );
    else
663
    {
664 665
        Abc_SclWriteLibraryText( pFile, p );
        fclose( pFile );
666
        printf( "Dumped internal library into Liberty file \"%s\".\n", pFileName );
667 668 669 670 671 672 673 674 675 676
    }
}

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


ABC_NAMESPACE_IMPL_END