1 /**CFile****************************************************************
2 
3   FileHead    [amapLiberty.c]
4 
5   SystemHead  [ABC: Logic synthesis and verification system.]
6 
7   PackageHead [Technology mapper for standard cells.]
8 
9   Synopsis    [Liberty parser.]
10 
11   Author      [Alan Mishchenko]
12 
13   Affiliation [UC Berkeley]
14 
15   Date        [Ver. 1.0. Started - June 20, 2005.]
16 
17   Revision    [$Id: amapLiberty.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
18 
19 ***********************************************************************/
20 
21 #include "amapInt.h"
22 
23 ABC_NAMESPACE_IMPL_START
24 
25 
26 ////////////////////////////////////////////////////////////////////////
27 ///                        DECLARATIONS                              ///
28 ////////////////////////////////////////////////////////////////////////
29 
30 #define ABC_MAX_LIB_STR_LEN 5000
31 
32 // entry types
33 typedef enum {
34     AMAP_LIBERTY_NONE = 0,        // 0:  unknown
35     AMAP_LIBERTY_PROC,            // 1:  procedure :  key(head){body}
36     AMAP_LIBERTY_EQUA,            // 2:  equation  :  key:head;
37     AMAP_LIBERTY_LIST             // 3:  list      :  key(head)
38 } Amap_LibertyType_t;
39 
40 typedef struct Amap_Pair_t_ Amap_Pair_t;
41 struct Amap_Pair_t_
42 {
43     int             Beg;          // item beginning
44     int             End;          // item end
45 };
46 
47 typedef struct Amap_Item_t_ Amap_Item_t;
48 struct Amap_Item_t_
49 {
50     int             Type;         // Amap_LibertyType_t
51     int             iLine;        // file line where the item's spec begins
52     Amap_Pair_t     Key;          // key part
53     Amap_Pair_t     Head;         // head part
54     Amap_Pair_t     Body;         // body part
55     int             Next;         // next item in the list
56     int             Child;        // first child item
57 };
58 
59 typedef struct Amap_Tree_t_ Amap_Tree_t;
60 struct Amap_Tree_t_
61 {
62     char *          pFileName;    // input Liberty file name
63     char *          pContents;    // file contents
64     int             nContents;    // file size
65     int             nLines;       // line counter
66     int             nItems;       // number of items
67     int             nItermAlloc;  // number of items allocated
68     Amap_Item_t *   pItems;       // the items
69     char *          pError;       // the error string
70 };
71 
Amap_LibertyRoot(Amap_Tree_t * p)72 static inline Amap_Item_t *  Amap_LibertyRoot( Amap_Tree_t * p )                                       { return p->pItems;                                                 }
Amap_LibertyItem(Amap_Tree_t * p,int v)73 static inline Amap_Item_t *  Amap_LibertyItem( Amap_Tree_t * p, int v )                                { assert( v < p->nItems ); return v < 0 ? NULL : p->pItems + v;     }
Amap_LibertyCompare(Amap_Tree_t * p,Amap_Pair_t Pair,char * pStr)74 static inline int            Amap_LibertyCompare( Amap_Tree_t * p, Amap_Pair_t Pair, char * pStr )     { return strncmp( p->pContents+Pair.Beg, pStr, Pair.End-Pair.Beg ); }
Amap_PrintWord(FILE * pFile,Amap_Tree_t * p,Amap_Pair_t Pair)75 static inline void           Amap_PrintWord( FILE * pFile, Amap_Tree_t * p, Amap_Pair_t Pair )         { char * pBeg = p->pContents+Pair.Beg, * pEnd = p->pContents+Pair.End; while ( pBeg < pEnd ) fputc( *pBeg++, pFile ); }
Amap_PrintSpace(FILE * pFile,int nOffset)76 static inline void           Amap_PrintSpace( FILE * pFile, int nOffset )                              { int i; for ( i = 0; i < nOffset; i++ ) fputc(' ', pFile);         }
Amap_LibertyItemId(Amap_Tree_t * p,Amap_Item_t * pItem)77 static inline int            Amap_LibertyItemId( Amap_Tree_t * p, Amap_Item_t * pItem )                { return pItem - p->pItems;                                         }
78 
79 #define Amap_ItemForEachChild( p, pItem, pChild ) \
80     for ( pChild = Amap_LibertyItem(p, pItem->Child); pChild; pChild = Amap_LibertyItem(p, pChild->Next) )
81 
82 ////////////////////////////////////////////////////////////////////////
83 ///                     FUNCTION DEFINITIONS                         ///
84 ////////////////////////////////////////////////////////////////////////
85 
86 /**Function*************************************************************
87 
88   Synopsis    [Prints parse tree in Liberty format.]
89 
90   Description []
91 
92   SideEffects []
93 
94   SeeAlso     []
95 
96 ***********************************************************************/
Amap_LibertyPrintLibertyItem(FILE * pFile,Amap_Tree_t * p,Amap_Item_t * pItem,int nOffset)97 void Amap_LibertyPrintLibertyItem( FILE * pFile, Amap_Tree_t * p, Amap_Item_t * pItem, int nOffset )
98 {
99     if ( pItem->Type == AMAP_LIBERTY_PROC )
100     {
101         Amap_PrintSpace( pFile, nOffset );
102         Amap_PrintWord( pFile, p, pItem->Key );
103         fprintf( pFile, "(" );
104         Amap_PrintWord( pFile, p, pItem->Head );
105         fprintf( pFile, ") {\n" );
106         if ( Amap_LibertyItem(p, pItem->Child) )
107             Amap_LibertyPrintLibertyItem( pFile, p, Amap_LibertyItem(p, pItem->Child), nOffset + 1 );
108         Amap_PrintSpace( pFile, nOffset );
109         fprintf( pFile, "}\n" );
110     }
111     else if ( pItem->Type == AMAP_LIBERTY_EQUA )
112     {
113         Amap_PrintSpace( pFile, nOffset );
114         Amap_PrintWord( pFile, p, pItem->Key );
115         fprintf( pFile, " : " );
116         Amap_PrintWord( pFile, p, pItem->Head );
117         fprintf( pFile, ";\n" );
118     }
119     else if ( pItem->Type == AMAP_LIBERTY_LIST )
120     {
121         Amap_PrintSpace( pFile, nOffset );
122         Amap_PrintWord( pFile, p, pItem->Key );
123         fprintf( pFile, "(" );
124         Amap_PrintWord( pFile, p, pItem->Head );
125         fprintf( pFile, ");\n" );
126     }
127     else assert( 0 );
128     if ( Amap_LibertyItem(p, pItem->Next) )
129         Amap_LibertyPrintLibertyItem( pFile, p, Amap_LibertyItem(p, pItem->Next), nOffset );
130 }
131 
132 /**Function*************************************************************
133 
134   Synopsis    [Prints parse tree in Liberty format.]
135 
136   Description []
137 
138   SideEffects []
139 
140   SeeAlso     []
141 
142 ***********************************************************************/
Amap_LibertyPrintLiberty(Amap_Tree_t * p,char * pFileName)143 int Amap_LibertyPrintLiberty( Amap_Tree_t * p, char * pFileName )
144 {
145     FILE * pFile;
146     if ( pFileName == NULL )
147         pFile = stdout;
148     else
149     {
150         pFile = fopen( pFileName, "w" );
151         if ( pFile == NULL )
152         {
153             printf( "Amap_LibertyPrintLiberty(): The output file is unavailable (absent or open).\n" );
154             return 0;
155         }
156     }
157     Amap_LibertyPrintLibertyItem( pFile, p, Amap_LibertyRoot(p), 0 );
158     if ( pFile != stdout )
159         fclose( pFile );
160     return 1;
161 }
162 
163 
164 /**Function*************************************************************
165 
166   Synopsis    [Returns the time stamp.]
167 
168   Description [The file should be closed.]
169 
170   SideEffects []
171 
172   SeeAlso     []
173 
174 ***********************************************************************/
Amap_LibertyTimeStamp()175 char * Amap_LibertyTimeStamp()
176 {
177     static char Buffer[100];
178     char * TimeStamp;
179     time_t ltime;
180     // get the current time
181     time( &ltime );
182     TimeStamp = asctime( localtime( &ltime ) );
183     TimeStamp[ strlen(TimeStamp) - 1 ] = 0;
184     assert( strlen(TimeStamp) < 100 );
185     strcpy( Buffer, TimeStamp );
186     return Buffer;
187 }
188 
189 /**Function*************************************************************
190 
191   Synopsis    [Returns cell's function.]
192 
193   Description []
194 
195   SideEffects []
196 
197   SeeAlso     []
198 
199 ***********************************************************************/
Amap_LibertyCellIsFlop(Amap_Tree_t * p,Amap_Item_t * pCell)200 int Amap_LibertyCellIsFlop( Amap_Tree_t * p, Amap_Item_t * pCell )
201 {
202     Amap_Item_t * pAttr;
203     Amap_ItemForEachChild( p, pCell, pAttr )
204         if ( !Amap_LibertyCompare(p, pAttr->Key, "ff") ||
205              !Amap_LibertyCompare(p, pAttr->Key, "latch") )
206             return 1;
207     return 0;
208 }
209 
210 /**Function*************************************************************
211 
212   Synopsis    [Returns cell's function.]
213 
214   Description []
215 
216   SideEffects []
217 
218   SeeAlso     []
219 
220 ***********************************************************************/
Amap_LibertyCellIsDontUse(Amap_Tree_t * p,Amap_Item_t * pCell)221 int Amap_LibertyCellIsDontUse( Amap_Tree_t * p, Amap_Item_t * pCell )
222 {
223     Amap_Item_t * pAttr;
224     Amap_ItemForEachChild( p, pCell, pAttr )
225         if ( !Amap_LibertyCompare(p, pAttr->Key, "dont_use") )
226             return 1;
227     return 0;
228 }
229 
230 /**Function*************************************************************
231 
232   Synopsis    [Returns pin's function.]
233 
234   Description []
235 
236   SideEffects []
237 
238   SeeAlso     []
239 
240 ***********************************************************************/
Amap_LibertyPinFunction(Amap_Tree_t * p,Amap_Item_t * pPin)241 Amap_Item_t * Amap_LibertyPinFunction( Amap_Tree_t * p, Amap_Item_t * pPin )
242 {
243     Amap_Item_t * pFunc;
244     Amap_ItemForEachChild( p, pPin, pFunc )
245         if ( !Amap_LibertyCompare(p, pFunc->Key, "function") )
246             return pFunc;
247     return NULL;
248 }
249 
250 /**Function*************************************************************
251 
252   Synopsis    [Returns output pin(s).]
253 
254   Description []
255 
256   SideEffects []
257 
258   SeeAlso     []
259 
260 ***********************************************************************/
Amap_LibertyCellOutput(Amap_Tree_t * p,Amap_Item_t * pCell)261 Amap_Item_t * Amap_LibertyCellOutput( Amap_Tree_t * p, Amap_Item_t * pCell )
262 {
263     Amap_Item_t * pPin;
264     Amap_ItemForEachChild( p, pCell, pPin )
265     {
266         if ( Amap_LibertyCompare(p, pPin->Key, "pin") )
267             continue;
268         if ( Amap_LibertyPinFunction(p, pPin) )
269             return pPin;
270     }
271     return NULL;
272 }
Amap_LibertyCellOutputs(Amap_Tree_t * p,Amap_Item_t * pCell)273 Vec_Ptr_t * Amap_LibertyCellOutputs( Amap_Tree_t * p, Amap_Item_t * pCell )
274 {
275     Amap_Item_t * pPin;
276     Vec_Ptr_t * vOutPins;
277     vOutPins = Vec_PtrAlloc( 2 );
278     Amap_ItemForEachChild( p, pCell, pPin )
279     {
280         if ( Amap_LibertyCompare(p, pPin->Key, "pin") )
281             continue;
282         if ( Amap_LibertyPinFunction(p, pPin) )
283             Vec_PtrPush( vOutPins, pPin );
284     }
285     return vOutPins;
286 }
287 
288 /**Function*************************************************************
289 
290   Synopsis    [Returns cell's area.]
291 
292   Description []
293 
294   SideEffects []
295 
296   SeeAlso     []
297 
298 ***********************************************************************/
Amap_LibertyCellArea(Amap_Tree_t * p,Amap_Item_t * pCell)299 Amap_Item_t * Amap_LibertyCellArea( Amap_Tree_t * p, Amap_Item_t * pCell )
300 {
301     Amap_Item_t * pArea;
302     Amap_ItemForEachChild( p, pCell, pArea )
303     {
304         if ( Amap_LibertyCompare(p, pArea->Key, "area") )
305             continue;
306         return pArea;
307     }
308     return NULL;
309 }
310 
311 /**Function*************************************************************
312 
313   Synopsis    [Count cell's output pins (pins with a logic function).]
314 
315   Description []
316 
317   SideEffects []
318 
319   SeeAlso     []
320 
321 ***********************************************************************/
Amap_LibertyCellCountOutputs(Amap_Tree_t * p,Amap_Item_t * pCell)322 int Amap_LibertyCellCountOutputs( Amap_Tree_t * p, Amap_Item_t * pCell )
323 {
324     Amap_Item_t * pPin;
325     int Counter = 0;
326     Amap_ItemForEachChild( p, pCell, pPin )
327     {
328         if ( Amap_LibertyCompare(p, pPin->Key, "pin") )
329             continue;
330         if ( Amap_LibertyPinFunction(p, pPin) )
331             Counter++;
332     }
333     return Counter;
334 }
335 
336 /**Function*************************************************************
337 
338   Synopsis    [Gets the name to write.]
339 
340   Description []
341 
342   SideEffects []
343 
344   SeeAlso     []
345 
346 ***********************************************************************/
Amap_LibertyGetString(Amap_Tree_t * p,Amap_Pair_t Pair)347 char * Amap_LibertyGetString( Amap_Tree_t * p, Amap_Pair_t Pair )
348 {
349     static char Buffer[ABC_MAX_LIB_STR_LEN];
350     assert( Pair.End-Pair.Beg < ABC_MAX_LIB_STR_LEN );
351     strncpy( Buffer, p->pContents+Pair.Beg, Pair.End-Pair.Beg );
352     Buffer[Pair.End-Pair.Beg] = 0;
353     return Buffer;
354 }
355 
356 /**Function*************************************************************
357 
358   Synopsis    [Gets the name to write.]
359 
360   Description []
361 
362   SideEffects []
363 
364   SeeAlso     []
365 
366 ***********************************************************************/
Amap_LibertyGetStringFormula(Amap_Tree_t * p,Amap_Pair_t Pair)367 char * Amap_LibertyGetStringFormula( Amap_Tree_t * p, Amap_Pair_t Pair )
368 {
369     static char Buffer[ABC_MAX_LIB_STR_LEN];
370     assert( Pair.End-Pair.Beg-2 < ABC_MAX_LIB_STR_LEN );
371     strncpy( Buffer, p->pContents+Pair.Beg+1, Pair.End-Pair.Beg-2 );
372     Buffer[Pair.End-Pair.Beg-2] = 0;
373     return Buffer;
374 }
375 
376 /**Function*************************************************************
377 
378   Synopsis    [Prints parse tree in Genlib format.]
379 
380   Description []
381 
382   SideEffects []
383 
384   SeeAlso     []
385 
386 ***********************************************************************/
Amap_LibertyPrintGenlib(Amap_Tree_t * p,char * pFileName,int fVerbose)387 int Amap_LibertyPrintGenlib( Amap_Tree_t * p, char * pFileName, int fVerbose )
388 {
389     FILE * pFile;
390     Vec_Ptr_t * vOutputs;
391     Amap_Item_t * pCell, * pArea, * pFunc, * pPin, * pOutput;
392     char * pForm;
393     int i, Counter;
394     if ( pFileName == NULL )
395         pFile = stdout;
396     else
397     {
398         pFile = fopen( pFileName, "w" );
399         if ( pFile == NULL )
400         {
401             printf( "Amap_LibertyPrintGenlib(): The output file is unavailable (absent or open).\n" );
402             return 0;
403         }
404     }
405     fprintf( pFile, "# This Genlib file was generated by ABC on %s\n", Amap_LibertyTimeStamp() );
406     fprintf( pFile, "# The standard cell library \"%s\" is from Liberty file \"%s\"\n", Amap_LibertyGetString(p, Amap_LibertyRoot(p)->Head), p->pFileName );
407     fprintf( pFile, "# (To find out more about Genlib format, google for \"sis_paper.ps\")\n" );
408 
409     fprintf( pFile, "GATE  " );
410     fprintf( pFile, "%16s  ", "_const0_" );
411     fprintf( pFile, "%f  ",   0.0 );
412     fprintf( pFile, "%s=",    "z" );
413     fprintf( pFile, "%s;\n",  "CONST0" );
414 
415     fprintf( pFile, "GATE  " );
416     fprintf( pFile, "%16s  ", "_const1_" );
417     fprintf( pFile, "%f  ",   0.0 );
418     fprintf( pFile, "%s=",    "z" );
419     fprintf( pFile, "%s;\n",  "CONST1" );
420 
421     Amap_ItemForEachChild( p, Amap_LibertyRoot(p), pCell )
422     {
423 /*
424     if ( strcmp(Amap_LibertyGetString(p, pCell->Head), "HA1SVTX1") == 0 )
425     {
426         int s = 0;
427     }
428 */
429         if ( Amap_LibertyCompare(p, pCell->Key, "cell") )
430             continue;
431         if ( Amap_LibertyCellIsFlop(p, pCell) )
432         {
433             if ( fVerbose )
434                 printf( "Amap_LibertyPrintGenlib() skipped sequential cell \"%s\".\n", Amap_LibertyGetString(p, pCell->Head) );
435             continue;
436         }
437         if ( Amap_LibertyCellIsDontUse(p, pCell) )
438         {
439             if ( fVerbose )
440                 printf( "Amap_LibertyPrintGenlib() skipped cell \"%s\" due to dont_use attribute.\n", Amap_LibertyGetString(p, pCell->Head) );
441             continue;
442         }
443         Counter = Amap_LibertyCellCountOutputs( p, pCell );
444         if ( Counter == 0 )
445         {
446             if ( fVerbose )
447                 printf( "Amap_LibertyPrintGenlib() skipped cell \"%s\" without logic function.\n", Amap_LibertyGetString(p, pCell->Head) );
448             continue;
449         }
450 /*
451         if ( Counter > 1 )
452         {
453             if ( fVerbose )
454                 printf( "Amap_LibertyPrintGenlib() skipped multi-output cell \"%s\".\n", Amap_LibertyGetString(p, pCell->Head) );
455             continue;
456         }
457 */
458         pArea = Amap_LibertyCellArea( p, pCell );
459         if ( pArea == NULL )
460         {
461             if ( fVerbose )
462                 printf( "Amap_LibertyPrintGenlib() skipped cell \"%s\" with unspecified area.\n", Amap_LibertyGetString(p, pCell->Head) );
463             continue;
464         }
465 //        pOutput = Amap_LibertyCellOutput( p, pCell );
466         vOutputs = Amap_LibertyCellOutputs( p, pCell );
467         Vec_PtrForEachEntry( Amap_Item_t *, vOutputs, pOutput, i )
468         {
469             pFunc   = Amap_LibertyPinFunction( p, pOutput );
470             pForm   = Amap_LibertyGetStringFormula( p, pFunc->Head );
471             if ( !strcmp(pForm, "0") || !strcmp(pForm, "1") )
472             {
473                 if ( fVerbose )
474                     printf( "Amap_LibertyPrintGenlib() skipped cell \"%s\" with constant formula \"%s\".\n", Amap_LibertyGetString(p, pCell->Head), pForm );
475                 continue;
476             }
477             fprintf( pFile, "GATE  " );
478             fprintf( pFile, "%16s  ", Amap_LibertyGetString(p, pCell->Head) );
479             fprintf( pFile, "%f  ",   atof(Amap_LibertyGetString(p, pArea->Head)) );
480             fprintf( pFile, "%s=",    Amap_LibertyGetString(p, pOutput->Head) );
481             fprintf( pFile, "%s;\n",  Amap_LibertyGetStringFormula(p, pFunc->Head) );
482             Amap_ItemForEachChild( p, pCell, pPin )
483                 if ( Vec_PtrFind(vOutputs, pPin) == -1 && !Amap_LibertyCompare(p, pPin->Key, "pin") )
484                     fprintf( pFile, "    PIN  %13s  UNKNOWN  1  999  1.00  0.00  1.00  0.00\n", Amap_LibertyGetString(p, pPin->Head) );
485         }
486         Vec_PtrFree( vOutputs );
487     }
488     if ( pFile != stdout )
489         fclose( pFile );
490     return 1;
491 }
492 
493 /**Function*************************************************************
494 
495   Synopsis    [Prints parse tree in Genlib format.]
496 
497   Description []
498 
499   SideEffects []
500 
501   SeeAlso     []
502 
503 ***********************************************************************/
Amap_LibertyPrintGenlibStr(Amap_Tree_t * p,int fVerbose)504 Vec_Str_t * Amap_LibertyPrintGenlibStr( Amap_Tree_t * p, int fVerbose )
505 {
506     Vec_Str_t * vStr;
507     char Buffer[100];
508     Vec_Ptr_t * vOutputs;
509     Amap_Item_t * pCell, * pArea, * pFunc, * pPin, * pOutput;
510     int i, Counter;
511     char * pForm;
512 
513     vStr = Vec_StrAlloc( 1000 );
514 
515     Vec_StrPrintStr( vStr, "GATE          _const0_  0.000000  z=CONST0;\n" );
516     Vec_StrPrintStr( vStr, "GATE          _const1_  0.000000  z=CONST1;\n" );
517     Amap_ItemForEachChild( p, Amap_LibertyRoot(p), pCell )
518     {
519         if ( Amap_LibertyCompare(p, pCell->Key, "cell") )
520             continue;
521         if ( Amap_LibertyCellIsFlop(p, pCell) )
522         {
523             if ( fVerbose )
524                 printf( "Amap_LibertyPrintGenlib() skipped sequential cell \"%s\".\n", Amap_LibertyGetString(p, pCell->Head) );
525             continue;
526         }
527         if ( Amap_LibertyCellIsDontUse(p, pCell) )
528         {
529             if ( fVerbose )
530                 printf( "Amap_LibertyPrintGenlib() skipped cell \"%s\" due to dont_use attribute.\n", Amap_LibertyGetString(p, pCell->Head) );
531             continue;
532         }
533         Counter = Amap_LibertyCellCountOutputs( p, pCell );
534         if ( Counter == 0 )
535         {
536             if ( fVerbose )
537                 printf( "Amap_LibertyPrintGenlib() skipped cell \"%s\" without logic function.\n", Amap_LibertyGetString(p, pCell->Head) );
538             continue;
539         }
540         pArea = Amap_LibertyCellArea( p, pCell );
541         if ( pArea == NULL )
542         {
543             if ( fVerbose )
544                 printf( "Amap_LibertyPrintGenlib() skipped cell \"%s\" with unspecified area.\n", Amap_LibertyGetString(p, pCell->Head) );
545             continue;
546         }
547         vOutputs = Amap_LibertyCellOutputs( p, pCell );
548         Vec_PtrForEachEntry( Amap_Item_t *, vOutputs, pOutput, i )
549         {
550             pFunc   = Amap_LibertyPinFunction( p, pOutput );
551             pForm   = Amap_LibertyGetStringFormula( p, pFunc->Head );
552             if ( !strcmp(pForm, "0") || !strcmp(pForm, "1") )
553             {
554                 if ( fVerbose )
555                     printf( "Amap_LibertyPrintGenlib() skipped cell \"%s\" with constant formula \"%s\".\n", Amap_LibertyGetString(p, pCell->Head), pForm );
556                 continue;
557             }
558 /*
559             fprintf( pFile, "GATE  " );
560             fprintf( pFile, "%16s  ", Amap_LibertyGetString(p, pCell->Head) );
561             fprintf( pFile, "%f  ",   atof(Amap_LibertyGetString(p, pArea->Head)) );
562             fprintf( pFile, "%s=",    Amap_LibertyGetString(p, pOutput->Head) );
563             fprintf( pFile, "%s;\n",  Amap_LibertyGetStringFormula(p, pFunc->Head) );
564             Amap_ItemForEachChild( p, pCell, pPin )
565                 if ( Vec_PtrFind(vOutputs, pPin) == -1 && !Amap_LibertyCompare(p, pPin->Key, "pin") )
566                     fprintf( pFile, "    PIN  %13s  UNKNOWN  1  999  1.00  0.00  1.00  0.00\n", Amap_LibertyGetString(p, pPin->Head) );
567 */
568             Vec_StrPrintStr( vStr, "GATE " );
569             Vec_StrPrintStr( vStr, Amap_LibertyGetString(p, pCell->Head) );
570             Vec_StrPrintStr( vStr, " " );
571             sprintf( Buffer, "%f", atof(Amap_LibertyGetString(p, pArea->Head)) );
572             Vec_StrPrintStr( vStr, Buffer );
573             Vec_StrPrintStr( vStr, " " );
574             Vec_StrPrintStr( vStr, Amap_LibertyGetString(p, pOutput->Head) );
575             Vec_StrPrintStr( vStr, "=" );
576             Vec_StrPrintStr( vStr, Amap_LibertyGetStringFormula(p, pFunc->Head) );
577             Vec_StrPrintStr( vStr, ";\n" );
578             Amap_ItemForEachChild( p, pCell, pPin )
579                 if ( Vec_PtrFind(vOutputs, pPin) == -1 && !Amap_LibertyCompare(p, pPin->Key, "pin") )
580                 {
581                     Vec_StrPrintStr( vStr, "  PIN " );
582                     Vec_StrPrintStr( vStr, Amap_LibertyGetString(p, pPin->Head) );
583                     Vec_StrPrintStr( vStr, " UNKNOWN  1  999  1.00  0.00  1.00  0.00\n" );
584                 }
585         }
586         Vec_PtrFree( vOutputs );
587     }
588     Vec_StrPrintStr( vStr, "\n.end\n" );
589     Vec_StrPush( vStr, '\0' );
590 //    printf( "%s", Vec_StrArray(vStr) );
591     return vStr;
592 }
593 
594 
595 /**Function*************************************************************
596 
597   Synopsis    [Returns the file size.]
598 
599   Description [The file should be closed.]
600 
601   SideEffects []
602 
603   SeeAlso     []
604 
605 ***********************************************************************/
Amap_LibertyFileSize(char * pFileName)606 int Amap_LibertyFileSize( char * pFileName )
607 {
608     FILE * pFile;
609     int nFileSize;
610     pFile = fopen( pFileName, "rb" );
611     if ( pFile == NULL )
612     {
613         printf( "Amap_LibertyFileSize(): The input file is unavailable (absent or open).\n" );
614         return 0;
615     }
616     fseek( pFile, 0, SEEK_END );
617     nFileSize = ftell( pFile );
618     fclose( pFile );
619     return nFileSize;
620 }
621 
622 /**Function*************************************************************
623 
624   Synopsis    []
625 
626   Description []
627 
628   SideEffects []
629 
630   SeeAlso     []
631 
632 ***********************************************************************/
Amap_LibertyFixFileHead(char * pFileName)633 void Amap_LibertyFixFileHead( char * pFileName )
634 {
635     char * pHead;
636     for ( pHead = pFileName; *pHead; pHead++ )
637         if ( *pHead == '>' )
638             *pHead = '\\';
639 }
640 
641 /**Function*************************************************************
642 
643   Synopsis    []
644 
645   Description []
646 
647   SideEffects []
648 
649   SeeAlso     []
650 
651 ***********************************************************************/
Amap_LibertyCountItems(char * pBeg,char * pEnd)652 int Amap_LibertyCountItems( char * pBeg, char * pEnd )
653 {
654     int Counter = 0;
655     for ( ; pBeg < pEnd; pBeg++ )
656         Counter += (*pBeg == '(' || *pBeg == ':');
657     return Counter;
658 }
659 
660 /**Function*************************************************************
661 
662   Synopsis    [Removes C-style comments.]
663 
664   Description []
665 
666   SideEffects []
667 
668   SeeAlso     []
669 
670 ***********************************************************************/
Amap_LibertyWipeOutComments(char * pBeg,char * pEnd)671 void Amap_LibertyWipeOutComments( char * pBeg, char * pEnd )
672 {
673     char * pCur, * pStart;
674     for ( pCur = pBeg; pCur < pEnd; pCur++ )
675     if ( pCur[0] == '/' && pCur[1] == '*' )
676         for ( pStart = pCur; pCur < pEnd; pCur++ )
677         if ( pCur[0] == '*' && pCur[1] == '/' )
678         {
679             for ( ; pStart < pCur + 2; pStart++ )
680             if ( *pStart != '\n' ) *pStart = ' ';
681             break;
682         }
683 }
684 
685 /**Function*************************************************************
686 
687   Synopsis    [Returns 1 if the character is space.]
688 
689   Description []
690 
691   SideEffects []
692 
693   SeeAlso     []
694 
695 ***********************************************************************/
Amap_LibertyCharIsSpace(char c)696 static inline int Amap_LibertyCharIsSpace( char c )
697 {
698     return c == ' ' || c == '\t' || c == '\r' || c == '\n' || c == '\\';
699 }
700 
701 /**Function*************************************************************
702 
703   Synopsis    [Skips spaces.]
704 
705   Description [Returns 1 if reached the end.]
706 
707   SideEffects []
708 
709   SeeAlso     []
710 
711 ***********************************************************************/
Amap_LibertySkipSpaces(Amap_Tree_t * p,char ** ppPos,char * pEnd,int fStopAtNewLine)712 static inline int Amap_LibertySkipSpaces( Amap_Tree_t * p, char ** ppPos, char * pEnd, int fStopAtNewLine )
713 {
714     char * pPos = *ppPos;
715     for ( ; pPos < pEnd; pPos++ )
716     {
717         if ( *pPos == '\n' )
718         {
719             p->nLines++;
720             if ( fStopAtNewLine )
721                 break;
722         }
723         if ( !Amap_LibertyCharIsSpace(*pPos) )
724             break;
725     }
726     *ppPos = pPos;
727     return pPos == pEnd;
728 }
729 
730 /**Function*************************************************************
731 
732   Synopsis    [Skips entry delimited by " :;(){}" ]
733 
734   Description [Returns 1 if reached the end.]
735 
736   SideEffects []
737 
738   SeeAlso     []
739 
740 ***********************************************************************/
Amap_LibertySkipEntry(char ** ppPos,char * pEnd)741 static inline int Amap_LibertySkipEntry( char ** ppPos, char * pEnd )
742 {
743     char * pPos = *ppPos;
744     if ( *pPos == '\"' )
745     {
746         for ( pPos++; pPos < pEnd; pPos++ )
747             if ( *pPos == '\"' )
748             {
749                 pPos++;
750                 break;
751             }
752     }
753     else
754     {
755         for ( ; pPos < pEnd; pPos++ )
756             if ( *pPos == ' ' || *pPos == '\r' || *pPos == '\n' || *pPos == '\t' ||
757                  *pPos == ':' || *pPos == ';'  ||
758                  *pPos == '(' || *pPos == ')'  ||
759                  *pPos == '{' || *pPos == '}' )
760                 break;
761     }
762     *ppPos = pPos;
763     return pPos == pEnd;
764 }
765 
766 /**Function*************************************************************
767 
768   Synopsis    [Find the matching closing symbol.]
769 
770   Description []
771 
772   SideEffects []
773 
774   SeeAlso     []
775 
776 ***********************************************************************/
Amap_LibertyFindMatch(char * pPos,char * pEnd)777 static inline char * Amap_LibertyFindMatch( char * pPos, char * pEnd )
778 {
779     int Counter = 0;
780     assert( *pPos == '(' || *pPos == '{' );
781     if ( *pPos == '(' )
782     {
783         for ( ; pPos < pEnd; pPos++ )
784         {
785             if ( *pPos == '(' )
786                 Counter++;
787             if ( *pPos == ')' )
788                 Counter--;
789             if ( Counter == 0 )
790                 break;
791         }
792     }
793     else
794     {
795         for ( ; pPos < pEnd; pPos++ )
796         {
797             if ( *pPos == '{' )
798                 Counter++;
799             if ( *pPos == '}' )
800                 Counter--;
801             if ( Counter == 0 )
802                 break;
803         }
804     }
805     assert( *pPos == ')' || *pPos == '}' );
806     return pPos;
807 }
808 
809 /**Function*************************************************************
810 
811   Synopsis    [Find the matching closing symbol.]
812 
813   Description []
814 
815   SideEffects []
816 
817   SeeAlso     []
818 
819 ***********************************************************************/
Amap_LibertyUpdateHead(Amap_Tree_t * p,Amap_Pair_t Head)820 static inline Amap_Pair_t Amap_LibertyUpdateHead( Amap_Tree_t * p, Amap_Pair_t Head )
821 {
822     Amap_Pair_t Res;
823     char * pBeg = p->pContents + Head.Beg;
824     char * pEnd = p->pContents + Head.End;
825     char * pFirstNonSpace = NULL;
826     char * pLastNonSpace = NULL;
827     char * pChar;
828     for ( pChar = pBeg; pChar < pEnd; pChar++ )
829     {
830         if ( *pChar == '\n' )
831             p->nLines++;
832         if ( Amap_LibertyCharIsSpace(*pChar) )
833             continue;
834         pLastNonSpace = pChar;
835         if ( pFirstNonSpace == NULL )
836             pFirstNonSpace = pChar;
837     }
838     if ( pFirstNonSpace == NULL || pLastNonSpace == NULL )
839         return Head;
840     assert( pFirstNonSpace && pLastNonSpace );
841     Res.Beg = pFirstNonSpace - p->pContents;
842     Res.End = pLastNonSpace  - p->pContents + 1;
843     return Res;
844 }
845 
846 /**Function*************************************************************
847 
848   Synopsis    [Returns free item.]
849 
850   Description []
851 
852   SideEffects []
853 
854   SeeAlso     []
855 
856 ***********************************************************************/
Amap_LibertyNewItem(Amap_Tree_t * p,int Type)857 static inline Amap_Item_t * Amap_LibertyNewItem( Amap_Tree_t * p, int Type )
858 {
859     p->pItems[p->nItems].iLine = p->nLines;
860     p->pItems[p->nItems].Type  = Type;
861     p->pItems[p->nItems].Child = -1;
862     p->pItems[p->nItems].Next  = -1;
863     return p->pItems + p->nItems++;
864 }
865 
866 /**Function*************************************************************
867 
868   Synopsis    [Returns free item.]
869 
870   Description []
871 
872   SideEffects []
873 
874   SeeAlso     []
875 
876 ***********************************************************************/
Amap_LibertyBuildItem(Amap_Tree_t * p,char ** ppPos,char * pEnd)877 int Amap_LibertyBuildItem( Amap_Tree_t * p, char ** ppPos, char * pEnd )
878 {
879     Amap_Item_t * pItem;
880     Amap_Pair_t Key, Head, Body;
881     char * pNext, * pStop;
882     Key.End = 0;
883     if ( Amap_LibertySkipSpaces( p, ppPos, pEnd, 0 ) )
884         return -2;
885     Key.Beg = *ppPos - p->pContents;
886     if ( Amap_LibertySkipEntry( ppPos, pEnd ) )
887         goto exit;
888     Key.End = *ppPos - p->pContents;
889     if ( Amap_LibertySkipSpaces( p, ppPos, pEnd, 0 ) )
890         goto exit;
891     pNext = *ppPos;
892     if ( *pNext == ':' )
893     {
894         *ppPos = pNext + 1;
895         if ( Amap_LibertySkipSpaces( p, ppPos, pEnd, 0 ) )
896             goto exit;
897         Head.Beg = *ppPos - p->pContents;
898         if ( Amap_LibertySkipEntry( ppPos, pEnd ) )
899             goto exit;
900         Head.End = *ppPos - p->pContents;
901         if ( Amap_LibertySkipSpaces( p, ppPos, pEnd, 1 ) )
902             goto exit;
903         pNext = *ppPos;
904         if ( *pNext != ';' && *pNext != '\n' )
905             goto exit;
906         *ppPos = pNext + 1;
907         // end of equation
908         pItem = Amap_LibertyNewItem( p, AMAP_LIBERTY_EQUA );
909         pItem->Key  = Key;
910         pItem->Head = Amap_LibertyUpdateHead( p, Head );
911         pItem->Next = Amap_LibertyBuildItem( p, ppPos, pEnd );
912         if ( pItem->Next == -1 )
913             goto exit;
914         return Amap_LibertyItemId( p, pItem );
915     }
916     if ( *pNext == '(' )
917     {
918         pStop = Amap_LibertyFindMatch( pNext, pEnd );
919         Head.Beg = pNext - p->pContents + 1;
920         Head.End = pStop - p->pContents;
921         *ppPos = pStop + 1;
922         if ( Amap_LibertySkipSpaces( p, ppPos, pEnd, 0 ) )
923         {
924             // end of list
925             pItem = Amap_LibertyNewItem( p, AMAP_LIBERTY_LIST );
926             pItem->Key  = Key;
927             pItem->Head = Amap_LibertyUpdateHead( p, Head );
928             return Amap_LibertyItemId( p, pItem );
929         }
930         pNext = *ppPos;
931         if ( *pNext == '{' ) // beginning of body
932         {
933             pStop = Amap_LibertyFindMatch( pNext, pEnd );
934             Body.Beg = pNext - p->pContents + 1;
935             Body.End = pStop - p->pContents;
936             // end of body
937             pItem = Amap_LibertyNewItem( p, AMAP_LIBERTY_PROC );
938             pItem->Key  = Key;
939             pItem->Head = Amap_LibertyUpdateHead( p, Head );
940             pItem->Body = Body;
941             *ppPos = pNext + 1;
942             pItem->Child = Amap_LibertyBuildItem( p, ppPos, pStop );
943             if ( pItem->Child == -1 )
944                 goto exit;
945             *ppPos = pStop + 1;
946             pItem->Next = Amap_LibertyBuildItem( p, ppPos, pEnd );
947             if ( pItem->Next == -1 )
948                 goto exit;
949             return Amap_LibertyItemId( p, pItem );
950         }
951         // end of list
952         if ( *pNext == ';' )
953             *ppPos = pNext + 1;
954         pItem = Amap_LibertyNewItem( p, AMAP_LIBERTY_LIST );
955         pItem->Key  = Key;
956         pItem->Head = Amap_LibertyUpdateHead( p, Head );
957         pItem->Next = Amap_LibertyBuildItem( p, ppPos, pEnd );
958         if ( pItem->Next == -1 )
959             goto exit;
960         return Amap_LibertyItemId( p, pItem );
961     }
962 exit:
963     if ( p->pError == NULL )
964     {
965         p->pError = ABC_ALLOC( char, 1000 );
966         sprintf( p->pError, "File \"%s\". Line %6d. Failed to parse entry \"%s\".\n",
967             p->pFileName, p->nLines, Amap_LibertyGetString(p, Key) );
968     }
969     return -1;
970 }
971 
972 /**Function*************************************************************
973 
974   Synopsis    [Starts the parsing manager.]
975 
976   Description []
977 
978   SideEffects []
979 
980   SeeAlso     []
981 
982 ***********************************************************************/
Amap_LibertyStart(char * pFileName)983 Amap_Tree_t * Amap_LibertyStart( char * pFileName )
984 {
985     FILE * pFile;
986     Amap_Tree_t * p;
987     int RetValue;
988     // start the manager
989     p = ABC_ALLOC( Amap_Tree_t, 1 );
990     memset( p, 0, sizeof(Amap_Tree_t) );
991     // read the file into the buffer
992     Amap_LibertyFixFileHead( pFileName );
993     p->nContents = Amap_LibertyFileSize( pFileName );
994     if ( p->nContents == 0 )
995     {
996         ABC_FREE( p );
997         return NULL;
998     }
999     pFile = fopen( pFileName, "rb" );
1000     p->pContents = ABC_ALLOC( char, p->nContents+1 );
1001     RetValue = fread( p->pContents, p->nContents, 1, pFile );
1002     fclose( pFile );
1003     p->pContents[p->nContents] = 0;
1004     // other
1005     p->pFileName = Abc_UtilStrsav( pFileName );
1006     p->nItermAlloc = 10 + Amap_LibertyCountItems( p->pContents, p->pContents+p->nContents );
1007     p->pItems = ABC_CALLOC( Amap_Item_t, p->nItermAlloc );
1008     p->nItems = 0;
1009     p->nLines = 1;
1010     return p;
1011 }
1012 
1013 /**Function*************************************************************
1014 
1015   Synopsis    [Stops the parsing manager.]
1016 
1017   Description []
1018 
1019   SideEffects []
1020 
1021   SeeAlso     []
1022 
1023 ***********************************************************************/
Amap_LibertyStop(Amap_Tree_t * p)1024 void Amap_LibertyStop( Amap_Tree_t * p )
1025 {
1026     ABC_FREE( p->pFileName );
1027     ABC_FREE( p->pContents );
1028     ABC_FREE( p->pItems );
1029     ABC_FREE( p->pError );
1030     ABC_FREE( p );
1031 }
1032 
1033 /**Function*************************************************************
1034 
1035   Synopsis    [Parses the standard cell library in Liberty format.]
1036 
1037   Description [Writes the resulting file in Genlib format.]
1038 
1039   SideEffects []
1040 
1041   SeeAlso     []
1042 
1043 ***********************************************************************/
Amap_LibertyParse(char * pFileName,int fVerbose)1044 int Amap_LibertyParse( char * pFileName, int fVerbose )
1045 {
1046     Amap_Tree_t * p;
1047     char * pPos;
1048     abctime clk = Abc_Clock();
1049     int RetValue;
1050     p = Amap_LibertyStart( pFileName );
1051     if ( p == NULL )
1052         return 0;
1053     pPos = p->pContents;
1054     Amap_LibertyWipeOutComments( p->pContents, p->pContents+p->nContents );
1055     if ( Amap_LibertyBuildItem( p, &pPos, p->pContents + p->nContents ) == 0 )
1056     {
1057         if ( fVerbose )
1058         printf( "Parsing finished successfully.\n" );
1059 //        Amap_LibertyPrintLiberty( p, "temp_.lib" );
1060         Amap_LibertyPrintGenlib( p, Extra_FileNameGenericAppend(pFileName, ".genlib"), fVerbose );
1061         RetValue = 1;
1062     }
1063     else
1064     {
1065         if ( p->pError )
1066             printf( "%s", p->pError );
1067         if ( fVerbose )
1068         printf( "Parsing failed.\n" );
1069         RetValue = 0;
1070     }
1071     if ( fVerbose )
1072     {
1073     printf( "Memory = %7.2f MB. ", 1.0*(p->nContents+p->nItermAlloc*sizeof(Amap_Item_t))/(1<<20) );
1074     ABC_PRT( "Time", Abc_Clock() - clk );
1075     }
1076     Amap_LibertyStop( p );
1077     return RetValue;
1078 }
1079 
1080 /**Function*************************************************************
1081 
1082   Synopsis    [Parses the standard cell library in Liberty format.]
1083 
1084   Description [Writes the resulting file in Genlib format.]
1085 
1086   SideEffects []
1087 
1088   SeeAlso     []
1089 
1090 ***********************************************************************/
Amap_LibertyParseStr(char * pFileName,int fVerbose)1091 Vec_Str_t * Amap_LibertyParseStr( char * pFileName, int fVerbose )
1092 {
1093     Amap_Tree_t * p;
1094     Vec_Str_t * vStr = NULL;
1095     char * pPos;
1096     abctime clk = Abc_Clock();
1097     int RetValue;
1098     p = Amap_LibertyStart( pFileName );
1099     if ( p == NULL )
1100         return 0;
1101     pPos = p->pContents;
1102     Amap_LibertyWipeOutComments( p->pContents, p->pContents+p->nContents );
1103     if ( Amap_LibertyBuildItem( p, &pPos, p->pContents + p->nContents ) == 0 )
1104     {
1105         if ( fVerbose )
1106         printf( "Parsing finished successfully.\n" );
1107 //        Amap_LibertyPrintLiberty( p, "temp_.lib" );
1108         vStr = Amap_LibertyPrintGenlibStr( p, fVerbose );
1109         RetValue = 1;
1110     }
1111     else
1112     {
1113         if ( p->pError )
1114             printf( "%s", p->pError );
1115         if ( fVerbose )
1116         printf( "Parsing failed.\n" );
1117         RetValue = 0;
1118     }
1119     if ( fVerbose )
1120     {
1121     printf( "Memory = %7.2f MB. ", 1.0*(p->nContents+p->nItermAlloc*sizeof(Amap_Item_t))/(1<<20) );
1122     ABC_PRT( "Time", Abc_Clock() - clk );
1123     }
1124     Amap_LibertyStop( p );
1125     return vStr;
1126 }
1127 
1128 
1129 ////////////////////////////////////////////////////////////////////////
1130 ///                       END OF FILE                                ///
1131 ////////////////////////////////////////////////////////////////////////
1132 
1133 
1134 ABC_NAMESPACE_IMPL_END
1135 
1136