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( <ime );
182 TimeStamp = asctime( localtime( <ime ) );
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