1 /**CFile****************************************************************
2 
3   FileName    [sclLibUtil.c]
4 
5   SystemName  [ABC: Logic synthesis and verification system.]
6 
7   PackageName [Standard-cell library representation.]
8 
9   Synopsis    [Various library utilities.]
10 
11   Author      [Alan Mishchenko, Niklas Een]
12 
13   Affiliation [UC Berkeley]
14 
15   Date        [Ver. 1.0. Started - August 24, 2012.]
16 
17   Revision    [$Id: sclLibUtil.c,v 1.0 2012/08/24 00:00:00 alanmi Exp $]
18 
19 ***********************************************************************/
20 
21 #include "sclLib.h"
22 #include "misc/st/st.h"
23 #include "map/mio/mio.h"
24 #include "bool/kit/kit.h"
25 
26 ABC_NAMESPACE_IMPL_START
27 
28 
29 ////////////////////////////////////////////////////////////////////////
30 ///                        DECLARATIONS                              ///
31 ////////////////////////////////////////////////////////////////////////
32 
33 ////////////////////////////////////////////////////////////////////////
34 ///                     FUNCTION DEFINITIONS                         ///
35 ////////////////////////////////////////////////////////////////////////
36 
37 /**Function*************************************************************
38 
39   Synopsis    [Reading library from file.]
40 
41   Description []
42 
43   SideEffects []
44 
45   SeeAlso     []
46 
47 ***********************************************************************/
Abc_SclHashString(char * pName,int TableSize)48 static unsigned Abc_SclHashString( char * pName, int TableSize )
49 {
50     static int s_Primes[10] = { 1291, 1699, 2357, 4177, 5147, 5647, 6343, 7103, 7873, 8147 };
51     unsigned i, Key = 0;
52     for ( i = 0; pName[i] != '\0'; i++ )
53         Key += s_Primes[i%10]*pName[i]*pName[i];
54     return Key % TableSize;
55 }
Abc_SclHashLookup(SC_Lib * p,char * pName)56 int * Abc_SclHashLookup( SC_Lib * p, char * pName )
57 {
58     int i;
59     for ( i = Abc_SclHashString(pName, p->nBins); i < p->nBins; i = (i + 1) % p->nBins )
60         if ( p->pBins[i] == -1 || !strcmp(pName, SC_LibCell(p, p->pBins[i])->pName) )
61             return p->pBins + i;
62     assert( 0 );
63     return NULL;
64 }
Abc_SclHashCells(SC_Lib * p)65 void Abc_SclHashCells( SC_Lib * p )
66 {
67     SC_Cell * pCell;
68     int i, * pPlace;
69     assert( p->nBins == 0 );
70     p->nBins = Abc_PrimeCudd( 5 * SC_LibCellNum(p) );
71     p->pBins = ABC_FALLOC( int, p->nBins );
72     SC_LibForEachCell( p, pCell, i )
73     {
74         pPlace = Abc_SclHashLookup( p, pCell->pName );
75         assert( *pPlace == -1 );
76         *pPlace = i;
77     }
78 }
Abc_SclCellFind(SC_Lib * p,char * pName)79 int Abc_SclCellFind( SC_Lib * p, char * pName )
80 {
81     int *pPlace = Abc_SclHashLookup( p, pName );
82     return pPlace ? *pPlace : -1;
83 }
Abc_SclClassCellNum(SC_Cell * pClass)84 int Abc_SclClassCellNum( SC_Cell * pClass )
85 {
86     SC_Cell * pCell;
87     int i, Count = 0;
88     SC_RingForEachCell( pClass, pCell, i )
89         if ( !pCell->fSkip )
90             Count++;
91     return Count;
92 }
Abc_SclLibClassNum(SC_Lib * pLib)93 int Abc_SclLibClassNum( SC_Lib * pLib )
94 {
95     SC_Cell * pRepr;
96     int i, Count = 0;
97     SC_LibForEachCellClass( pLib, pRepr, i )
98         Count++;
99     return Count;
100 }
101 
102 /**Function*************************************************************
103 
104   Synopsis    [Change cell names and pin names.]
105 
106   Description []
107 
108   SideEffects []
109 
110   SeeAlso     []
111 
112 ***********************************************************************/
Abc_SclIsChar(char c)113 static inline int Abc_SclIsChar( char c )
114 {
115     return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_';
116 }
Abc_SclIsName(char c)117 static inline int Abc_SclIsName( char c )
118 {
119     return Abc_SclIsChar(c) || (c >= '0' && c <= '9');
120 }
Abc_SclFindLimit(char * pName)121 static inline char * Abc_SclFindLimit( char * pName )
122 {
123     assert( Abc_SclIsChar(*pName) );
124     while ( Abc_SclIsName(*pName) )
125         pName++;
126     return pName;
127 }
Abc_SclAreEqual(char * pBase,char * pName,char * pLimit)128 static inline int Abc_SclAreEqual( char * pBase, char * pName, char * pLimit )
129 {
130     return !strncmp( pBase, pName, pLimit - pName );
131 }
Abc_SclShortFormula(SC_Cell * pCell,char * pForm,char * pBuffer)132 void Abc_SclShortFormula( SC_Cell * pCell, char * pForm, char * pBuffer )
133 {
134     SC_Pin * pPin; int i;
135     char * pTemp, * pLimit;
136     for ( pTemp = pForm; *pTemp; )
137     {
138         if ( !Abc_SclIsChar(*pTemp) )
139         {
140             *pBuffer++ = *pTemp++;
141             continue;
142         }
143         pLimit = Abc_SclFindLimit( pTemp );
144         SC_CellForEachPinIn( pCell, pPin, i )
145             if ( Abc_SclAreEqual( pPin->pName, pTemp, pLimit ) )
146             {
147                 *pBuffer++ = 'a' + i;
148                 break;
149             }
150         assert( i < pCell->n_inputs );
151         pTemp = pLimit;
152     }
153     *pBuffer++ = 0;
154 }
Abc_SclTimingUpdate(SC_Cell * pCell,SC_Timing * p,char * Buffer)155 static inline void Abc_SclTimingUpdate( SC_Cell * pCell, SC_Timing * p, char * Buffer )
156 {
157     SC_Pin * pPin; int i;
158     SC_CellForEachPinIn( pCell, pPin, i )
159         if ( p->related_pin && !strcmp(p->related_pin, pPin->pName) )
160         {
161             ABC_FREE( p->related_pin );
162             sprintf( Buffer, "%c", 'a'+i );
163             p->related_pin = Abc_UtilStrsav( Buffer );
164         }
165 }
Abc_SclTimingsUpdate(SC_Cell * pCell,SC_Timings * p,char * Buffer)166 static inline void Abc_SclTimingsUpdate( SC_Cell * pCell, SC_Timings * p, char * Buffer )
167 {
168     SC_Timing * pTemp; int i;
169     Vec_PtrForEachEntry( SC_Timing *, &p->vTimings, pTemp, i )
170         Abc_SclTimingUpdate( pCell, pTemp, Buffer );
171 }
Abc_SclPinUpdate(SC_Cell * pCell,SC_Pin * p,char * Buffer)172 static inline void Abc_SclPinUpdate( SC_Cell * pCell, SC_Pin * p, char * Buffer )
173 {
174     // update pin names in the timing
175     SC_Timings * pTemp; int i;
176     SC_PinForEachRTiming( p, pTemp, i )
177     {
178         SC_Pin * pPin; int k;
179         Abc_SclTimingsUpdate( pCell, pTemp, Buffer );
180         SC_CellForEachPinIn( pCell, pPin, k )
181             if ( pTemp->pName && !strcmp(pTemp->pName, pPin->pName) )
182             {
183                 ABC_FREE( pTemp->pName );
184                 sprintf( Buffer, "%c", 'a'+k );
185                 pTemp->pName = Abc_UtilStrsav( Buffer );
186             }
187     }
188     // update formula
189     Abc_SclShortFormula( pCell, p->func_text, Buffer );
190     ABC_FREE( p->func_text );
191     p->func_text = Abc_UtilStrsav( Buffer );
192 }
Abc_SclShortNames(SC_Lib * p)193 void Abc_SclShortNames( SC_Lib * p )
194 {
195     char Buffer[10000];
196     SC_Cell * pClass, * pCell; SC_Pin * pPin;
197     int i, k, n, nClasses = Abc_SclLibClassNum(p);
198     int nDigits = Abc_Base10Log( nClasses );
199     // itereate through classes
200     SC_LibForEachCellClass( p, pClass, i )
201     {
202         int nDigits2 = Abc_Base10Log( Abc_SclClassCellNum(pClass) );
203         SC_RingForEachCell( pClass, pCell, k )
204         {
205             ABC_FREE( pCell->pName );
206             sprintf( Buffer, "g%0*d_%0*d", nDigits, i, nDigits2, k );
207             pCell->pName = Abc_UtilStrsav( Buffer );
208             // formula
209             SC_CellForEachPinOut( pCell, pPin, n )
210                 Abc_SclPinUpdate( pCell, pPin, Buffer );
211             // pin names
212             SC_CellForEachPinIn( pCell, pPin, n )
213             {
214                 ABC_FREE( pPin->pName );
215                 sprintf( Buffer, "%c", 'a'+n );
216                 pPin->pName = Abc_UtilStrsav( Buffer );
217             }
218             SC_CellForEachPinOut( pCell, pPin, n )
219             {
220                 ABC_FREE( pPin->pName );
221                 sprintf( Buffer, "%c", 'z'-n+pCell->n_inputs );
222                 pPin->pName = Abc_UtilStrsav( Buffer );
223             }
224         }
225     }
226     p->nBins = 0;
227     ABC_FREE( p->pBins );
228     Abc_SclHashCells( p );
229     // update library name
230     printf( "Renaming library \"%s\" into \"%s%d\".\n", p->pName, "lib", SC_LibCellNum(p) );
231     ABC_FREE( p->pName );
232     sprintf( Buffer, "lib%d", SC_LibCellNum(p) );
233     p->pName = Abc_UtilStrsav( Buffer );
234 }
235 /**Function*************************************************************
236 
237   Synopsis    [Links equal gates into rings while sorting them by area.]
238 
239   Description []
240 
241   SideEffects []
242 
243   SeeAlso     []
244 
245 ***********************************************************************/
Abc_SclCompareCells(SC_Cell ** pp1,SC_Cell ** pp2)246 static int Abc_SclCompareCells( SC_Cell ** pp1, SC_Cell ** pp2 )
247 {
248     if ( (*pp1)->n_inputs < (*pp2)->n_inputs )
249         return -1;
250     if ( (*pp1)->n_inputs > (*pp2)->n_inputs )
251         return 1;
252 //    if ( (*pp1)->area < (*pp2)->area )
253 //        return -1;
254 //    if ( (*pp1)->area > (*pp2)->area )
255 //        return 1;
256     if ( SC_CellPinCapAve(*pp1) < SC_CellPinCapAve(*pp2) )
257         return -1;
258     if ( SC_CellPinCapAve(*pp1) > SC_CellPinCapAve(*pp2) )
259         return 1;
260     return strcmp( (*pp1)->pName, (*pp2)->pName );
261 }
Abc_SclLinkCells(SC_Lib * p)262 void Abc_SclLinkCells( SC_Lib * p )
263 {
264     Vec_Ptr_t * vList;
265     SC_Cell * pCell, * pRepr = NULL;
266     int i, k;
267     assert( Vec_PtrSize(&p->vCellClasses) == 0 );
268     SC_LibForEachCell( p, pCell, i )
269     {
270         // find gate with the same function
271         SC_LibForEachCellClass( p, pRepr, k )
272             if ( pCell->n_inputs  == pRepr->n_inputs &&
273                  pCell->n_outputs == pRepr->n_outputs &&
274                  Vec_WrdEqual(SC_CellFunc(pCell), SC_CellFunc(pRepr)) )
275                 break;
276         if ( k == Vec_PtrSize(&p->vCellClasses) )
277         {
278             Vec_PtrPush( &p->vCellClasses, pCell );
279             pCell->pNext = pCell->pPrev = pCell;
280             continue;
281         }
282         // add it to the list before the cell
283         pRepr->pPrev->pNext = pCell; pCell->pNext = pRepr;
284         pCell->pPrev = pRepr->pPrev; pRepr->pPrev = pCell;
285     }
286     // sort cells by size then by name
287     qsort( (void *)Vec_PtrArray(&p->vCellClasses), Vec_PtrSize(&p->vCellClasses), sizeof(void *), (int(*)(const void *,const void *))Abc_SclCompareCells );
288     // sort cell lists
289     vList = Vec_PtrAlloc( 100 );
290     SC_LibForEachCellClass( p, pRepr, k )
291     {
292         Vec_PtrClear( vList );
293         SC_RingForEachCell( pRepr, pCell, i )
294             Vec_PtrPush( vList, pCell );
295         qsort( (void *)Vec_PtrArray(vList), (size_t)Vec_PtrSize(vList), sizeof(void *), (int(*)(const void *,const void *))Abc_SclCompareCells );
296         // create new representative
297         pRepr = (SC_Cell *)Vec_PtrEntry( vList, 0 );
298         pRepr->pNext = pRepr->pPrev = pRepr;
299         pRepr->pRepr = pRepr;
300         pRepr->pAve  = (SC_Cell *)Vec_PtrEntry( vList, Vec_PtrSize(vList)/2 );
301         pRepr->Order = 0;
302         pRepr->nGates = Vec_PtrSize(vList);
303         // relink cells
304         Vec_PtrForEachEntryStart( SC_Cell *, vList, pCell, i, 1 )
305         {
306             pRepr->pPrev->pNext = pCell; pCell->pNext = pRepr;
307             pCell->pPrev = pRepr->pPrev; pRepr->pPrev = pCell;
308             pCell->pRepr = pRepr;
309             pCell->pAve  = (SC_Cell *)Vec_PtrEntry( vList, Vec_PtrSize(vList)/2 );
310             pCell->Order = i;
311             pCell->nGates = Vec_PtrSize(vList);
312         }
313         // update list
314         Vec_PtrWriteEntry( &p->vCellClasses, k, pRepr );
315     }
316     Vec_PtrFree( vList );
317 }
318 
319 /**Function*************************************************************
320 
321   Synopsis    [Returns the largest inverter.]
322 
323   Description []
324 
325   SideEffects []
326 
327   SeeAlso     []
328 
329 ***********************************************************************/
Abc_SclFindInvertor(SC_Lib * p,int fFindBuff)330 SC_Cell * Abc_SclFindInvertor( SC_Lib * p, int fFindBuff )
331 {
332     SC_Cell * pCell = NULL;
333     word Truth = fFindBuff ? ABC_CONST(0xAAAAAAAAAAAAAAAA) : ABC_CONST(0x5555555555555555);
334     int k;
335     SC_LibForEachCellClass( p, pCell, k )
336         if ( pCell->n_inputs == 1 && Vec_WrdEntry(&SC_CellPin(pCell, 1)->vFunc, 0) == Truth )
337             break;
338     // take representative
339     return pCell ? pCell->pRepr : NULL;
340 }
Abc_SclFindSmallestGate(SC_Cell * p,float CinMin)341 SC_Cell * Abc_SclFindSmallestGate( SC_Cell * p, float CinMin )
342 {
343     SC_Cell * pRes = NULL;
344     int i;
345     SC_RingForEachCell( p->pRepr, pRes, i )
346         if ( SC_CellPinCapAve(pRes) > CinMin )
347             return pRes;
348     // take the largest gate
349     return p->pRepr->pPrev;
350 }
351 
352 /**Function*************************************************************
353 
354   Synopsis    [Returns the wireload model for the given area.]
355 
356   Description []
357 
358   SideEffects []
359 
360   SeeAlso     []
361 
362 ***********************************************************************/
Abc_SclFetchWireLoadModel(SC_Lib * p,char * pWLoadUsed)363 SC_WireLoad * Abc_SclFetchWireLoadModel( SC_Lib * p, char * pWLoadUsed )
364 {
365     SC_WireLoad * pWL = NULL;
366     int i;
367     // Get the actual table and reformat it for 'wire_cap' output:
368     assert( pWLoadUsed != NULL );
369     SC_LibForEachWireLoad( p, pWL, i )
370         if ( !strcmp(pWL->pName, pWLoadUsed) )
371             break;
372     if ( i == Vec_PtrSize(&p->vWireLoads) )
373     {
374         Abc_Print( -1, "Cannot find wire load model \"%s\".\n", pWLoadUsed );
375         exit(1);
376     }
377 //    printf( "Using wireload model \"%s\".\n", pWL->pName );
378     return pWL;
379 }
Abc_SclFindWireLoadModel(SC_Lib * p,float Area)380 SC_WireLoad * Abc_SclFindWireLoadModel( SC_Lib * p, float Area )
381 {
382     char * pWLoadUsed = NULL;
383     int i;
384     if ( p->default_wire_load_sel && strlen(p->default_wire_load_sel) )
385     {
386         SC_WireLoadSel * pWLS = NULL;
387         SC_LibForEachWireLoadSel( p, pWLS, i )
388             if ( !strcmp(pWLS->pName, p->default_wire_load_sel) )
389                 break;
390         if ( i == Vec_PtrSize(&p->vWireLoadSels) )
391         {
392             Abc_Print( -1, "Cannot find wire load selection model \"%s\".\n", p->default_wire_load_sel );
393             exit(1);
394         }
395         for ( i = 0; i < Vec_FltSize(&pWLS->vAreaFrom); i++)
396             if ( Area >= Vec_FltEntry(&pWLS->vAreaFrom, i) && Area <  Vec_FltEntry(&pWLS->vAreaTo, i) )
397             {
398                 pWLoadUsed = (char *)Vec_PtrEntry(&pWLS->vWireLoadModel, i);
399                 break;
400             }
401         if ( i == Vec_FltSize(&pWLS->vAreaFrom) )
402             pWLoadUsed = (char *)Vec_PtrEntryLast(&pWLS->vWireLoadModel);
403     }
404     else if ( p->default_wire_load && strlen(p->default_wire_load) )
405         pWLoadUsed = p->default_wire_load;
406     else
407     {
408 //        Abc_Print( 0, "No wire model given.\n" );
409         return NULL;
410     }
411     return Abc_SclFetchWireLoadModel( p, pWLoadUsed );
412 }
413 
414 /**Function*************************************************************
415 
416   Synopsis    [Returns 1 if the library has delay info.]
417 
418   Description []
419 
420   SideEffects []
421 
422   SeeAlso     []
423 
424 ***********************************************************************/
Abc_SclHasDelayInfo(void * pScl)425 int Abc_SclHasDelayInfo( void * pScl )
426 {
427     SC_Lib * p = (SC_Lib *)pScl;
428     SC_Cell * pCell;
429     SC_Timing * pTime;
430     pCell = Abc_SclFindInvertor(p, 0);
431     if ( pCell == NULL )
432         return 0;
433     pTime = Scl_CellPinTime( pCell, 0 );
434     if ( pTime == NULL )
435         return 0;
436     return 1;
437 }
438 
439 /**Function*************************************************************
440 
441   Synopsis    [Returns "average" slew.]
442 
443   Description []
444 
445   SideEffects []
446 
447   SeeAlso     []
448 
449 ***********************************************************************/
Abc_SclComputeAverageSlew(SC_Lib * p)450 float Abc_SclComputeAverageSlew( SC_Lib * p )
451 {
452     SC_Cell * pCell;
453     SC_Timing * pTime;
454     Vec_Flt_t * vIndex;
455     pCell = Abc_SclFindInvertor(p, 0);
456     if ( pCell == NULL )
457         return 0;
458     pTime = Scl_CellPinTime( pCell, 0 );
459     if ( pTime == NULL )
460         return 0;
461     vIndex = &pTime->pCellRise.vIndex0; // slew
462     return Vec_FltEntry( vIndex, Vec_FltSize(vIndex)/3 );
463 }
464 
465 /**Function*************************************************************
466 
467   Synopsis    [Compute delay parameters of pin/cell/class.]
468 
469   Description []
470 
471   SideEffects []
472 
473   SeeAlso     []
474 
475 ***********************************************************************/
Abc_SclComputeParametersPin(SC_Lib * p,SC_Cell * pCell,int iPin,float Slew,float * pLD,float * pPD)476 int Abc_SclComputeParametersPin( SC_Lib * p, SC_Cell * pCell, int iPin, float Slew, float * pLD, float * pPD )
477 {
478     SC_Pair Load0, Load1, Load2;
479     SC_Pair ArrIn  = { 0.0, 0.0 };
480     SC_Pair SlewIn = { Slew, Slew };
481     SC_Pair ArrOut0 = { 0.0, 0.0 };
482     SC_Pair ArrOut1 = { 0.0, 0.0 };
483     SC_Pair ArrOut2 = { 0.0, 0.0 };
484     SC_Pair SlewOut = { 0.0, 0.0 };
485     SC_Timing * pTime = Scl_CellPinTime( pCell, iPin );
486     Vec_Flt_t * vIndex = pTime ? &pTime->pCellRise.vIndex1 : NULL; // capacitance
487     if ( vIndex == NULL )
488         return 0;
489     // handle constant table
490     if ( Vec_FltSize(vIndex) == 1 )
491     {
492         *pLD = 0;
493         *pPD = Vec_FltEntry( (Vec_Flt_t *)Vec_PtrEntry(&pTime->pCellRise.vData, 0), 0 );
494         return 1;
495     }
496     // get load points
497     Load0.rise = Load0.fall = 0.0;
498     Load1.rise = Load1.fall = Vec_FltEntry( vIndex, 0 );
499     Load2.rise = Load2.fall = Vec_FltEntry( vIndex, Vec_FltSize(vIndex) - 2 );
500     // compute delay
501     Scl_LibPinArrival( pTime, &ArrIn, &SlewIn, &Load0, &ArrOut0, &SlewOut );
502     Scl_LibPinArrival( pTime, &ArrIn, &SlewIn, &Load1, &ArrOut1, &SlewOut );
503     Scl_LibPinArrival( pTime, &ArrIn, &SlewIn, &Load2, &ArrOut2, &SlewOut );
504     ArrOut0.rise = 0.5 * ArrOut0.rise + 0.5 * ArrOut0.fall;
505     ArrOut1.rise = 0.5 * ArrOut1.rise + 0.5 * ArrOut1.fall;
506     ArrOut2.rise = 0.5 * ArrOut2.rise + 0.5 * ArrOut2.fall;
507     // get tangent
508     *pLD = (ArrOut2.rise - ArrOut1.rise) / ((Load2.rise - Load1.rise) / SC_CellPinCap(pCell, iPin));
509     // get constant
510     *pPD = ArrOut0.rise;
511     return 1;
512 }
Abc_SclComputeParametersCell(SC_Lib * p,SC_Cell * pCell,float Slew,float * pLD,float * pPD)513 int Abc_SclComputeParametersCell( SC_Lib * p, SC_Cell * pCell, float Slew, float * pLD, float * pPD )
514 {
515     SC_Pin * pPin;
516     float LD, PD, ld, pd;
517     int i;
518     LD = PD = ld = pd = 0;
519     SC_CellForEachPinIn( pCell, pPin, i )
520     {
521         if ( !Abc_SclComputeParametersPin( p, pCell, i, Slew, &ld, &pd ) )
522             return 0;
523         LD += ld; PD += pd;
524     }
525     *pLD = LD / Abc_MaxInt(1, pCell->n_inputs);
526     *pPD = PD / Abc_MaxInt(1, pCell->n_inputs);
527     return 1;
528 }
Abc_SclComputeParametersClass(SC_Lib * p,SC_Cell * pRepr,float Slew,float * pLD,float * pPD)529 void Abc_SclComputeParametersClass( SC_Lib * p, SC_Cell * pRepr, float Slew, float * pLD, float * pPD )
530 {
531     SC_Cell * pCell;
532     float LD, PD, ld, pd;
533     int i, Count = 0;
534     LD = PD = ld = pd = 0;
535     SC_RingForEachCell( pRepr, pCell, i )
536     {
537         Abc_SclComputeParametersCell( p, pCell, Slew, &ld, &pd );
538         LD += ld; PD += pd;
539         Count++;
540     }
541     *pLD = LD / Abc_MaxInt(1, Count);
542     *pPD = PD / Abc_MaxInt(1, Count);
543 }
Abc_SclComputeParametersClassPin(SC_Lib * p,SC_Cell * pRepr,int iPin,float Slew,float * pLD,float * pPD)544 void Abc_SclComputeParametersClassPin( SC_Lib * p, SC_Cell * pRepr, int iPin, float Slew, float * pLD, float * pPD )
545 {
546     SC_Cell * pCell;
547     float LD, PD, ld, pd;
548     int i, Count = 0;
549     LD = PD = ld = pd = 0;
550     SC_RingForEachCell( pRepr, pCell, i )
551     {
552         Abc_SclComputeParametersPin( p, pCell, iPin, Slew, &ld, &pd );
553         LD += ld; PD += pd;
554         Count++;
555     }
556     *pLD = LD / Abc_MaxInt(1, Count);
557     *pPD = PD / Abc_MaxInt(1, Count);
558 }
Abc_SclComputeDelayCellPin(SC_Lib * p,SC_Cell * pCell,int iPin,float Slew,float Gain)559 float Abc_SclComputeDelayCellPin( SC_Lib * p, SC_Cell * pCell, int iPin, float Slew, float Gain )
560 {
561     float LD = 0, PD = 0;
562     Abc_SclComputeParametersPin( p, pCell, iPin, Slew, &LD, &PD );
563     return 0.01 * LD * Gain + PD;
564 }
Abc_SclComputeDelayClassPin(SC_Lib * p,SC_Cell * pRepr,int iPin,float Slew,float Gain)565 float Abc_SclComputeDelayClassPin( SC_Lib * p, SC_Cell * pRepr, int iPin, float Slew, float Gain )
566 {
567     SC_Cell * pCell;
568     float Delay = 0;
569     int i, Count = 0;
570     SC_RingForEachCell( pRepr, pCell, i )
571     {
572         if ( pCell->fSkip )
573             continue;
574 //        if ( pRepr == pCell ) // skip the first gate
575 //            continue;
576         Delay += Abc_SclComputeDelayCellPin( p, pCell, iPin, Slew, Gain );
577         Count++;
578     }
579     return Delay / Abc_MaxInt(1, Count);
580 }
Abc_SclComputeAreaClass(SC_Cell * pRepr)581 float Abc_SclComputeAreaClass( SC_Cell * pRepr )
582 {
583     SC_Cell * pCell;
584     float Area = 0;
585     int i, Count = 0;
586     SC_RingForEachCell( pRepr, pCell, i )
587     {
588         if ( pCell->fSkip )
589             continue;
590         Area += pCell->area;
591         Count++;
592     }
593     return Area / Abc_MaxInt(1, Count);
594 }
595 
596 /**Function*************************************************************
597 
598   Synopsis    [Print cells]
599 
600   Description []
601 
602   SideEffects []
603 
604   SeeAlso     []
605 
606 ***********************************************************************/
Abc_SclMarkSkippedCells(SC_Lib * p)607 void Abc_SclMarkSkippedCells( SC_Lib * p )
608 {
609     char FileName[1000];
610     char Buffer[1000], * pName;
611     SC_Cell * pCell;
612     FILE * pFile;
613     int CellId, nSkipped = 0;
614     sprintf( FileName, "%s.skip", p->pName );
615     pFile = fopen( FileName, "rb" );
616     if ( pFile == NULL )
617         return;
618     while ( fgets( Buffer, 999, pFile ) != NULL )
619     {
620         pName = strtok( Buffer, "\r\n\t " );
621         if ( pName == NULL )
622             continue;
623         CellId = Abc_SclCellFind( p, pName );
624         if ( CellId == -1 )
625         {
626             printf( "Cannot find cell \"%s\" in the library \"%s\".\n", pName, p->pName );
627             continue;
628         }
629         pCell = SC_LibCell( p, CellId );
630         pCell->fSkip = 1;
631         nSkipped++;
632     }
633     fclose( pFile );
634     printf( "Marked %d cells for skipping in the library \"%s\".\n", nSkipped, p->pName );
635 }
Abc_SclPrintCells(SC_Lib * p,float SlewInit,float Gain,int fInvOnly,int fShort)636 void Abc_SclPrintCells( SC_Lib * p, float SlewInit, float Gain, int fInvOnly, int fShort )
637 {
638     SC_Cell * pCell, * pRepr;
639     SC_Pin * pPin;
640     int i, j, k, nLength = 0;
641     float Slew = (SlewInit == 0) ? Abc_SclComputeAverageSlew(p) : SlewInit;
642     float LD = 0, PD = 0;
643     assert( Vec_PtrSize(&p->vCellClasses) > 0 );
644     printf( "Library \"%s\" ", p->pName );
645     printf( "has %d cells in %d classes.  ",
646         Vec_PtrSize(&p->vCells), Vec_PtrSize(&p->vCellClasses) );
647     if ( !fShort )
648         printf( "Delay estimate is based on slew %.2f ps and gain %.2f.", Slew, Gain );
649     printf( "\n" );
650     Abc_SclMarkSkippedCells( p );
651     // find the longest name
652     SC_LibForEachCellClass( p, pRepr, k )
653         SC_RingForEachCell( pRepr, pCell, i )
654             nLength = Abc_MaxInt( nLength, strlen(pRepr->pName) );
655     // print cells
656     SC_LibForEachCellClass( p, pRepr, k )
657     {
658         if ( fInvOnly && pRepr->n_inputs != 1 )
659             continue;
660         SC_CellForEachPinOut( pRepr, pPin, i )
661         {
662             if ( i == pRepr->n_inputs )
663             {
664                 printf( "Class%4d : ",   k );
665                 printf( "Cells =%3d   ", Abc_SclClassCellNum(pRepr) );
666                 printf( "Ins =%2d  ",    pRepr->n_inputs );
667                 printf( "Outs =%2d  ",   pRepr->n_outputs );
668             }
669             else
670                 printf( "                                            " );
671             if ( pPin->func_text )
672                 printf( "%-30s", pPin->func_text  );
673             printf( "    "  );
674             Kit_DsdPrintFromTruth( (unsigned *)Vec_WrdArray(&pPin->vFunc), pRepr->n_inputs );
675             printf( "\n" );
676             if ( fShort )
677                 continue;
678             SC_RingForEachCell( pRepr, pCell, j )
679             {
680                 printf( "  %3d ",           j+1 );
681                 printf( "%s",               pCell->fSkip ? "s" : " " );
682                 printf( " : " );
683                 printf( "%-*s  ",           nLength, pCell->pName );
684                 printf( "%2d   ",           pCell->drive_strength );
685                 printf( "A =%8.2f  ",       pCell->area );
686                 printf( "L =%8.2f  ",       pCell->leakage );
687                 if ( pCell->n_outputs == 1 )
688                 {
689                     if ( Abc_SclComputeParametersCell( p, pCell, Slew, &LD, &PD ) )
690                     {
691                         printf( "D =%6.1f ps  ",    0.01 * Gain * LD + PD );
692                         printf( "LD =%6.1f ps  ",   LD );
693                         printf( "PD =%6.1f ps    ", PD );
694                         printf( "C =%5.1f ff  ",    SC_CellPinCapAve(pCell) );
695                         printf( "Cm =%5.0f ff    ", SC_CellPin(pCell, pCell->n_inputs)->max_out_cap );
696                         printf( "Sm =%5.1f ps ",    SC_CellPin(pCell, pCell->n_inputs)->max_out_slew );
697                     }
698                 }
699                 printf( "\n" );
700             }
701             break;
702         }
703     }
704 }
705 
706 /**Function*************************************************************
707 
708   Synopsis    []
709 
710   Description []
711 
712   SideEffects []
713 
714   SeeAlso     []
715 
716 ***********************************************************************/
Abc_SclConvertLeakageIntoArea(SC_Lib * p,float A,float B)717 void Abc_SclConvertLeakageIntoArea( SC_Lib * p, float A, float B )
718 {
719     SC_Cell * pCell; int i;
720     SC_LibForEachCell( p, pCell, i )
721         pCell->area = A * pCell->area + B * pCell->leakage;
722 }
723 
724 
725 /**Function*************************************************************
726 
727   Synopsis    [Print cells]
728 
729   Description []
730 
731   SideEffects []
732 
733   SeeAlso     []
734 
735 ***********************************************************************/
Abc_SclLibNormalizeSurface(SC_Surface * p,float Time,float Load)736 void Abc_SclLibNormalizeSurface( SC_Surface * p, float Time, float Load )
737 {
738     Vec_Flt_t * vArray;
739     int i, k; float Entry;
740     Vec_FltForEachEntry( &p->vIndex0, Entry, i ) // slew
741         Vec_FltWriteEntry( &p->vIndex0, i, Time * Entry );
742     Vec_FltForEachEntry( &p->vIndex1, Entry, i ) // load
743         Vec_FltWriteEntry( &p->vIndex1, i, Load * Entry );
744     Vec_PtrForEachEntry( Vec_Flt_t *, &p->vData, vArray, k )
745         Vec_FltForEachEntry( vArray, Entry, i ) // delay/slew
746             Vec_FltWriteEntry( vArray, i, Time * Entry );
747 }
Abc_SclLibNormalize(SC_Lib * p)748 void Abc_SclLibNormalize( SC_Lib * p )
749 {
750     SC_WireLoad * pWL;
751     SC_Cell * pCell;
752     SC_Pin * pPin;
753     SC_Timings * pTimings;
754     SC_Timing * pTiming;
755     int i, k, m, n;
756     float Time = 1.0 * pow(10.0, 12 - p->unit_time);
757     float Load = p->unit_cap_fst * pow(10.0, 15 - p->unit_cap_snd);
758     if ( Time == 1 && Load == 1 )
759         return;
760     p->unit_time = 12;
761     p->unit_cap_fst = 1;
762     p->unit_cap_snd = 15;
763     p->default_max_out_slew *= Time;
764     SC_LibForEachWireLoad( p, pWL, i )
765         pWL->cap *= Load;
766     SC_LibForEachCell( p, pCell, i )
767     SC_CellForEachPin( pCell, pPin, k )
768     {
769         pPin->cap *= Load;
770         pPin->rise_cap *= Load;
771         pPin->fall_cap *= Load;
772         pPin->max_out_cap *= Load;
773         pPin->max_out_slew *= Time;
774         SC_PinForEachRTiming( pPin, pTimings, m )
775         Vec_PtrForEachEntry( SC_Timing *, &pTimings->vTimings, pTiming, n )
776         {
777             Abc_SclLibNormalizeSurface( &pTiming->pCellRise, Time, Load );
778             Abc_SclLibNormalizeSurface( &pTiming->pCellFall, Time, Load );
779             Abc_SclLibNormalizeSurface( &pTiming->pRiseTrans, Time, Load );
780             Abc_SclLibNormalizeSurface( &pTiming->pFallTrans, Time, Load );
781         }
782     }
783 }
784 
785 /**Function*************************************************************
786 
787   Synopsis    [Derives simple GENLIB library.]
788 
789   Description []
790 
791   SideEffects []
792 
793   SeeAlso     []
794 
795 ***********************************************************************/
Abc_SclProduceGenlibStrSimple(SC_Lib * p)796 Vec_Str_t * Abc_SclProduceGenlibStrSimple( SC_Lib * p )
797 {
798     char Buffer[200];
799     Vec_Str_t * vStr;
800     SC_Cell * pCell;
801     SC_Pin * pPin, * pPinOut;
802     int i, j, k, Count = 2;
803     // mark skipped cells
804 //    Abc_SclMarkSkippedCells( p );
805     vStr = Vec_StrAlloc( 1000 );
806     Vec_StrPrintStr( vStr, "GATE _const0_            0.00 z=CONST0;\n" );
807     Vec_StrPrintStr( vStr, "GATE _const1_            0.00 z=CONST1;\n" );
808     SC_LibForEachCell( p, pCell, i )
809     {
810         if ( pCell->n_inputs == 0 )
811             continue;
812         assert( strlen(pCell->pName) < 200 );
813         SC_CellForEachPinOut( pCell, pPinOut, j )
814         {
815             Vec_StrPrintStr( vStr, "GATE " );
816             sprintf( Buffer, "%-16s", pCell->pName );
817             Vec_StrPrintStr( vStr, Buffer );
818             Vec_StrPrintStr( vStr, " " );
819             sprintf( Buffer, "%7.2f", pCell->area );
820             Vec_StrPrintStr( vStr, Buffer );
821             Vec_StrPrintStr( vStr, " " );
822             Vec_StrPrintStr( vStr, pPinOut->pName );
823             Vec_StrPrintStr( vStr, "=" );
824             Vec_StrPrintStr( vStr, pPinOut->func_text ? pPinOut->func_text : "?" );
825             Vec_StrPrintStr( vStr, ";\n" );
826             SC_CellForEachPinIn( pCell, pPin, k )
827             {
828                 Vec_StrPrintStr( vStr, "         PIN " );
829                 sprintf( Buffer, "%-4s", pPin->pName );
830                 Vec_StrPrintStr( vStr, Buffer );
831                 sprintf( Buffer, " UNKNOWN  1  999  1.00  0.00  1.00  0.00\n" );
832                 Vec_StrPrintStr( vStr, Buffer );
833             }
834             Count++;
835         }
836     }
837     Vec_StrPrintStr( vStr, "\n.end\n" );
838     Vec_StrPush( vStr, '\0' );
839 //    printf( "GENLIB library with %d gates is produced:\n", Count );
840 //    printf( "%s", Vec_StrArray(vStr) );
841     return vStr;
842 }
Abc_SclDeriveGenlibSimple(void * pScl)843 Mio_Library_t * Abc_SclDeriveGenlibSimple( void * pScl )
844 {
845     SC_Lib * p = (SC_Lib *)pScl;
846     Vec_Str_t * vStr = Abc_SclProduceGenlibStrSimple( p );
847     Mio_Library_t * pLib = Mio_LibraryRead( p->pFileName, Vec_StrArray(vStr), NULL, 0 );
848     Vec_StrFree( vStr );
849     if ( pLib )
850         printf( "Derived GENLIB library \"%s\" with %d gates.\n", p->pName, SC_LibCellNum(p) );
851     else
852         printf( "Reading library has filed.\n" );
853     return pLib;
854 }
855 
856 
857 /**Function*************************************************************
858 
859   Synopsis    [Derive GENLIB library.]
860 
861   Description []
862 
863   SideEffects []
864 
865   SeeAlso     []
866 
867 ***********************************************************************/
Abc_SclProduceGenlibStr(SC_Lib * p,float Slew,float Gain,int nGatesMin,int * pnCellCount)868 Vec_Str_t * Abc_SclProduceGenlibStr( SC_Lib * p, float Slew, float Gain, int nGatesMin, int * pnCellCount )
869 {
870     char Buffer[200];
871     Vec_Str_t * vStr;
872     SC_Cell * pRepr;
873     SC_Pin * pPin;
874     int i, k, Count = 2, nClassMax = 0;
875     // find the largest number of cells in a class
876     SC_LibForEachCellClass( p, pRepr, i )
877         if ( pRepr->n_outputs == 1 )
878             nClassMax = Abc_MaxInt( nClassMax, Abc_SclClassCellNum(pRepr) );
879     // update the number
880     if ( nGatesMin && nGatesMin >= nClassMax )
881         nGatesMin = 0;
882     // mark skipped cells
883     Abc_SclMarkSkippedCells( p );
884     vStr = Vec_StrAlloc( 1000 );
885     Vec_StrPrintStr( vStr, "GATE _const0_            0.00 z=CONST0;\n" );
886     Vec_StrPrintStr( vStr, "GATE _const1_            0.00 z=CONST1;\n" );
887     SC_LibForEachCellClass( p, pRepr, i )
888     {
889         if ( pRepr->n_inputs == 0 )
890             continue;
891         if ( pRepr->n_outputs > 1 )
892             continue;
893         if ( nGatesMin && pRepr->n_inputs > 2 && Abc_SclClassCellNum(pRepr) < nGatesMin )
894             continue;
895         assert( strlen(pRepr->pName) < 200 );
896         Vec_StrPrintStr( vStr, "GATE " );
897         sprintf( Buffer, "%-16s", pRepr->pName );
898         Vec_StrPrintStr( vStr, Buffer );
899         Vec_StrPrintStr( vStr, " " );
900 //        sprintf( Buffer, "%7.2f", Abc_SclComputeAreaClass(pRepr) );
901         sprintf( Buffer, "%7.2f", pRepr->area );
902         Vec_StrPrintStr( vStr, Buffer );
903         Vec_StrPrintStr( vStr, " " );
904         Vec_StrPrintStr( vStr, SC_CellPinName(pRepr, pRepr->n_inputs) );
905         Vec_StrPrintStr( vStr, "=" );
906         Vec_StrPrintStr( vStr, SC_CellPinOutFunc(pRepr, 0) ? SC_CellPinOutFunc(pRepr, 0) : "?" );
907         Vec_StrPrintStr( vStr, ";\n" );
908         SC_CellForEachPinIn( pRepr, pPin, k )
909         {
910             float Delay = Abc_SclComputeDelayClassPin( p, pRepr, k, Slew, Gain );
911             assert( Delay > 0 );
912             Vec_StrPrintStr( vStr, "         PIN " );
913             sprintf( Buffer, "%-4s", pPin->pName );
914             Vec_StrPrintStr( vStr, Buffer );
915             sprintf( Buffer, " UNKNOWN  1  999  %7.2f  0.00  %7.2f  0.00\n", Delay, Delay );
916             Vec_StrPrintStr( vStr, Buffer );
917         }
918         Count++;
919     }
920     Vec_StrPrintStr( vStr, "\n.end\n" );
921     Vec_StrPush( vStr, '\0' );
922 //    printf( "GENLIB library with %d gates is produced:\n", Count );
923 //    printf( "%s", Vec_StrArray(vStr) );
924     if ( pnCellCount )
925         *pnCellCount = Count;
926     return vStr;
927 }
Abc_SclProduceGenlibStrProfile(SC_Lib * p,Mio_Library_t * pLib,float Slew,float Gain,int nGatesMin,int * pnCellCount)928 Vec_Str_t * Abc_SclProduceGenlibStrProfile( SC_Lib * p, Mio_Library_t * pLib, float Slew, float Gain, int nGatesMin, int * pnCellCount )
929 {
930     char Buffer[200];
931     Vec_Str_t * vStr;
932     SC_Cell * pRepr;
933     SC_Pin * pPin;
934     int i, k, Count = 2, nClassMax = 0;
935     // find the largest number of cells in a class
936     SC_LibForEachCellClass( p, pRepr, i )
937         if ( pRepr->n_outputs == 1 )
938             nClassMax = Abc_MaxInt( nClassMax, Abc_SclClassCellNum(pRepr) );
939     // update the number
940     if ( nGatesMin && nGatesMin >= nClassMax )
941         nGatesMin = 0;
942     // mark skipped cells
943     Abc_SclMarkSkippedCells( p );
944     vStr = Vec_StrAlloc( 1000 );
945     Vec_StrPrintStr( vStr, "GATE _const0_            0.00 z=CONST0;\n" );
946     Vec_StrPrintStr( vStr, "GATE _const1_            0.00 z=CONST1;\n" );
947     SC_LibForEachCell( p, pRepr, i )
948     {
949         if ( pRepr->n_inputs == 0 )
950             continue;
951         if ( pRepr->n_outputs > 1 )
952             continue;
953         if ( nGatesMin && pRepr->n_inputs > 2 && Abc_SclClassCellNum(pRepr) < nGatesMin )
954             continue;
955         // check if the gate is in the profile
956         if ( pRepr->n_inputs > 1 )
957         {
958             Mio_Gate_t * pGate = Mio_LibraryReadGateByName( pLib, pRepr->pName, NULL );
959             if ( pGate == NULL || Mio_GateReadProfile(pGate) == 0 )
960                 continue;
961         }
962         // process gate
963         assert( strlen(pRepr->pName) < 200 );
964         Vec_StrPrintStr( vStr, "GATE " );
965         sprintf( Buffer, "%-16s", pRepr->pName );
966         Vec_StrPrintStr( vStr, Buffer );
967         Vec_StrPrintStr( vStr, " " );
968 //        sprintf( Buffer, "%7.2f", Abc_SclComputeAreaClass(pRepr) );
969         sprintf( Buffer, "%7.2f", pRepr->area );
970         Vec_StrPrintStr( vStr, Buffer );
971         Vec_StrPrintStr( vStr, " " );
972         Vec_StrPrintStr( vStr, SC_CellPinName(pRepr, pRepr->n_inputs) );
973         Vec_StrPrintStr( vStr, "=" );
974         Vec_StrPrintStr( vStr, SC_CellPinOutFunc(pRepr, 0) ? SC_CellPinOutFunc(pRepr, 0) : "?" );
975         Vec_StrPrintStr( vStr, ";\n" );
976         SC_CellForEachPinIn( pRepr, pPin, k )
977         {
978             float Delay = Abc_SclComputeDelayClassPin( p, pRepr, k, Slew, Gain );
979             assert( Delay > 0 );
980             Vec_StrPrintStr( vStr, "         PIN " );
981             sprintf( Buffer, "%-4s", pPin->pName );
982             Vec_StrPrintStr( vStr, Buffer );
983             sprintf( Buffer, " UNKNOWN  1  999  %7.2f  0.00  %7.2f  0.00\n", Delay, Delay );
984             Vec_StrPrintStr( vStr, Buffer );
985         }
986         Count++;
987     }
988     Vec_StrPrintStr( vStr, "\n.end\n" );
989     Vec_StrPush( vStr, '\0' );
990 //    printf( "GENLIB library with %d gates is produced:\n", Count );
991 //    printf( "%s", Vec_StrArray(vStr) );
992     if ( pnCellCount )
993         *pnCellCount = Count;
994     return vStr;
995 }
Abc_SclDumpGenlib(char * pFileName,SC_Lib * p,float SlewInit,float Gain,int nGatesMin)996 void Abc_SclDumpGenlib( char * pFileName, SC_Lib * p, float SlewInit, float Gain, int nGatesMin )
997 {
998     int nCellCount = 0;
999     char FileName[1000];
1000     float Slew = (SlewInit == 0) ? Abc_SclComputeAverageSlew(p) : SlewInit;
1001     Vec_Str_t * vStr;
1002     FILE * pFile;
1003     if ( pFileName == NULL )
1004         sprintf( FileName, "%s_s%03d_g%03d_m%d.genlib", p->pName, (int)Slew, (int)Gain, nGatesMin );
1005     else
1006         sprintf( FileName, "%s", pFileName );
1007     pFile = fopen( FileName, "wb" );
1008     if ( pFile == NULL )
1009     {
1010         printf( "Cannot open file \"%s\" for writing.\n", FileName );
1011         return;
1012     }
1013     vStr = Abc_SclProduceGenlibStr( p, Slew, Gain, nGatesMin, &nCellCount );
1014     fprintf( pFile, "%s", Vec_StrArray(vStr) );
1015     Vec_StrFree( vStr );
1016     fclose( pFile );
1017     printf( "Written GENLIB library with %d gates into file \"%s\".\n", nCellCount, FileName );
1018 }
Abc_SclDeriveGenlib(void * pScl,void * pMio,float SlewInit,float Gain,int nGatesMin,int fVerbose)1019 Mio_Library_t * Abc_SclDeriveGenlib( void * pScl, void * pMio, float SlewInit, float Gain, int nGatesMin, int fVerbose )
1020 {
1021     int nCellCount = 0;
1022     SC_Lib * p = (SC_Lib *)pScl;
1023     float Slew = (SlewInit == 0) ? Abc_SclComputeAverageSlew(p) : SlewInit;
1024     Vec_Str_t * vStr;
1025     Mio_Library_t * pLib;
1026     if ( pMio == NULL )
1027         vStr = Abc_SclProduceGenlibStr( p, Slew, Gain, nGatesMin, &nCellCount );
1028     else
1029         vStr = Abc_SclProduceGenlibStrProfile( p, (Mio_Library_t *)pMio, Slew, Gain, nGatesMin, &nCellCount );
1030     pLib = Mio_LibraryRead( p->pFileName, Vec_StrArray(vStr), NULL, 0 );
1031     Vec_StrFree( vStr );
1032     if ( !pLib )
1033         printf( "Reading library has filed.\n" );
1034     else if ( fVerbose )
1035         printf( "Derived GENLIB library \"%s\" with %d gates using slew %.2f ps and gain %.2f.\n", p->pName, nCellCount, Slew, Gain );
1036     return pLib;
1037 }
1038 
1039 /**Function*************************************************************
1040 
1041   Synopsis    [Install library.]
1042 
1043   Description []
1044 
1045   SideEffects []
1046 
1047   SeeAlso     []
1048 
1049 ***********************************************************************/
Abc_SclInstallGenlib(void * pScl,float SlewInit,float Gain,int nGatesMin)1050 void Abc_SclInstallGenlib( void * pScl, float SlewInit, float Gain, int nGatesMin )
1051 {
1052     SC_Lib * p = (SC_Lib *)pScl;
1053     Vec_Str_t * vStr, * vStr2;
1054     float Slew = (SlewInit == 0) ? Abc_SclComputeAverageSlew(p) : SlewInit;
1055     int RetValue, nGateCount = SC_LibCellNum(p);
1056     if ( Gain == 0 )
1057         vStr = Abc_SclProduceGenlibStrSimple(p);
1058     else
1059         vStr = Abc_SclProduceGenlibStr( p, Slew, Gain, nGatesMin, &nGateCount );
1060     vStr2 = Vec_StrDup( vStr );
1061     RetValue = Mio_UpdateGenlib2( vStr, vStr2, p->pName, 0 );
1062     Vec_StrFree( vStr );
1063     Vec_StrFree( vStr2 );
1064     if ( !RetValue )
1065         printf( "Reading library has filed.\n" );
1066     else if ( Gain != 0 )
1067         printf( "Derived GENLIB library \"%s\" with %d gates using slew %.2f ps and gain %.2f.\n", p->pName, nGateCount, Slew, Gain );
1068 //    else
1069 //        printf( "Derived unit-delay GENLIB library \"%s\" with %d gates.\n", p->pName, nGateCount );
1070 }
1071 
1072 ////////////////////////////////////////////////////////////////////////
1073 ///                       END OF FILE                                ///
1074 ////////////////////////////////////////////////////////////////////////
1075 
1076 
1077 ABC_NAMESPACE_IMPL_END
1078 
1079