ABC: A System for Sequential Synthesis and Verification
 
Loading...
Searching...
No Matches
sclLiberty.c
Go to the documentation of this file.
1
20#include <string.h>
21#ifdef _WIN32
22#include <shlwapi.h>
23#pragma comment(lib, "shlwapi.lib")
24#else
25#include <fnmatch.h>
26#endif
27
28#include "misc/zlib/zlib.h"
29#include "sclLib.h"
30#include "misc/st/st.h"
31#include "map/mio/mio.h"
32
34
35
39
40// #define ABC_MAX_LIB_STR_LEN 5000
41
42// entry types
43typedef enum {
44 SCL_LIBERTY_NONE = 0, // 0: unknown
45 SCL_LIBERTY_PROC, // 1: procedure : key(head){body}
46 SCL_LIBERTY_EQUA, // 2: equation : key:head;
47 SCL_LIBERTY_LIST // 3: list : key(head)
49
50typedef struct Scl_Pair_t_ Scl_Pair_t;
52{
53 long Beg; // item beginning
54 long End; // item end
55};
56
57typedef struct Scl_Item_t_ Scl_Item_t;
59{
60 int Type; // Scl_LibertyType_t
61 long iLine; // file line where the item's spec begins
62 Scl_Pair_t Key; // key part
63 Scl_Pair_t Head; // head part
64 Scl_Pair_t Body; // body part
65 long Next; // next item in the list
66 long Child; // first child item
67};
68
69typedef struct Scl_Tree_t_ Scl_Tree_t;
71{
72 char * pFileName; // input Liberty file name
73 char * pContents; // file contents
74 long nContents; // file size
75 long nLines; // line counter
76 long nItems; // number of items
77 long nItermAlloc; // number of items allocated
78 Scl_Item_t * pItems; // the items
79 char * pError; // the error string
80 abctime clkStart; // beginning time
81 Vec_Str_t * vBuffer; // temp string buffer
82};
83
84
85static inline int Scl_LibertyGlobMatch(const char * pattern, const char * string) {
86 #ifdef _WIN32
87 return PathMatchSpec(string, pattern); // if the compiler complains, add "-lshlwapi"
88 #else
89 return fnmatch(pattern, string, 0) == 0;
90 #endif
91}
92static inline Scl_Item_t * Scl_LibertyRoot( Scl_Tree_t * p ) { return p->pItems; }
93static inline Scl_Item_t * Scl_LibertyItem( Scl_Tree_t * p, long v ) { assert( v < p->nItems ); return v < 0 ? NULL : p->pItems + v; }
94static inline long Scl_LibertyCompare( Scl_Tree_t * p, Scl_Pair_t Pair, char * pStr ) { return strncmp( p->pContents+Pair.Beg, pStr, Pair.End-Pair.Beg ) || ((long)strlen(pStr) != Pair.End-Pair.Beg); }
95static inline void Scl_PrintWord( FILE * pFile, Scl_Tree_t * p, Scl_Pair_t Pair ) { char * pBeg = p->pContents+Pair.Beg, * pEnd = p->pContents+Pair.End; while ( pBeg < pEnd ) fputc( *pBeg++, pFile ); }
96static inline void Scl_PrintSpace( FILE * pFile, long nOffset ) { long i; for ( i = 0; i < nOffset; i++ ) fputc(' ', pFile); }
97static inline long Scl_LibertyItemId( Scl_Tree_t * p, Scl_Item_t * pItem ) { return pItem - p->pItems; }
98
99#define Scl_ItemForEachChild( p, pItem, pChild ) \
100 for ( pChild = Scl_LibertyItem(p, pItem->Child); pChild; pChild = Scl_LibertyItem(p, pChild->Next) )
101#define Scl_ItemForEachChildName( p, pItem, pChild, pName ) \
102 for ( pChild = Scl_LibertyItem(p, pItem->Child); pChild; pChild = Scl_LibertyItem(p, pChild->Next) ) if ( Scl_LibertyCompare(p, pChild->Key, pName) ) {} else
103
107
119void Scl_LibertyParseDumpItem( FILE * pFile, Scl_Tree_t * p, Scl_Item_t * pItem, int nOffset )
120{
121 if ( pItem->Type == SCL_LIBERTY_PROC )
122 {
123 Scl_PrintSpace( pFile, nOffset );
124 Scl_PrintWord( pFile, p, pItem->Key );
125 fprintf( pFile, "(" );
126 Scl_PrintWord( pFile, p, pItem->Head );
127 fprintf( pFile, ") {\n" );
128 if ( Scl_LibertyItem(p, pItem->Child) )
129 Scl_LibertyParseDumpItem( pFile, p, Scl_LibertyItem(p, pItem->Child), nOffset + 2 );
130 Scl_PrintSpace( pFile, nOffset );
131 fprintf( pFile, "}\n" );
132 }
133 else if ( pItem->Type == SCL_LIBERTY_EQUA )
134 {
135 Scl_PrintSpace( pFile, nOffset );
136 Scl_PrintWord( pFile, p, pItem->Key );
137 fprintf( pFile, " : " );
138 Scl_PrintWord( pFile, p, pItem->Head );
139 fprintf( pFile, ";\n" );
140 }
141 else if ( pItem->Type == SCL_LIBERTY_LIST )
142 {
143 Scl_PrintSpace( pFile, nOffset );
144 Scl_PrintWord( pFile, p, pItem->Key );
145 fprintf( pFile, "(" );
146 Scl_PrintWord( pFile, p, pItem->Head );
147 fprintf( pFile, ");\n" );
148 }
149 else assert( 0 );
150 if ( Scl_LibertyItem(p, pItem->Next) )
151 Scl_LibertyParseDumpItem( pFile, p, Scl_LibertyItem(p, pItem->Next), nOffset );
152}
153int Scl_LibertyParseDump( Scl_Tree_t * p, char * pFileName )
154{
155 FILE * pFile;
156 if ( pFileName == NULL )
157 pFile = stdout;
158 else
159 {
160 pFile = fopen( pFileName, "w" );
161 if ( pFile == NULL )
162 {
163 printf( "Scl_LibertyParseDump(): The output file is unavailable (absent or open).\n" );
164 return 0;
165 }
166 }
167 Scl_LibertyParseDumpItem( pFile, p, Scl_LibertyRoot(p), 0 );
168 if ( pFile != stdout )
169 fclose( pFile );
170 return 1;
171}
172
173
185long Scl_LibertyCountItems( char * pBeg, char * pEnd )
186{
187 long Counter = 0;
188 for ( ; pBeg < pEnd; pBeg++ )
189 Counter += (*pBeg == '(' || *pBeg == ':');
190 return Counter;
191}
192// removes C-style comments
193/*
194void Scl_LibertyWipeOutComments( char * pBeg, char * pEnd )
195{
196 char * pCur, * pStart;
197 for ( pCur = pBeg; pCur < pEnd; pCur++ )
198 if ( pCur[0] == '/' && pCur[1] == '*' )
199 for ( pStart = pCur; pCur < pEnd; pCur++ )
200 if ( pCur[0] == '*' && pCur[1] == '/' )
201 {
202 for ( ; pStart < pCur + 2; pStart++ )
203 if ( *pStart != '\n' ) *pStart = ' ';
204 break;
205 }
206}
207*/
208void Scl_LibertyWipeOutComments( char * pBeg, char * pEnd )
209{
210 char * pCur, * pStart;
211 for ( pCur = pBeg; pCur < pEnd-1; pCur++ )
212 if ( pCur[0] == '/' && pCur[1] == '*' )
213 {
214 for ( pStart = pCur; pCur < pEnd-1; pCur++ )
215 if ( pCur[0] == '*' && pCur[1] == '/' )
216 {
217 for ( ; pStart < pCur + 2; pStart++ )
218 if ( *pStart != '\n' ) *pStart = ' ';
219 break;
220 }
221 }
222 else if ( pCur[0] == '/' && pCur[1] == '/' )
223 {
224 for ( pStart = pCur; pCur < pEnd; pCur++ )
225 if ( pCur[0] == '\n' || pCur == pEnd-1 )
226 {
227 for ( ; pStart < pCur; pStart++ ) *pStart = ' ';
228 break;
229 }
230 }
231}
232static inline long Scl_LibertyCharIsSpace( char c )
233{
234 return c == ' ' || c == '\t' || c == '\r' || c == '\n' || c == '\\';
235}
236static inline long Scl_LibertySkipSpaces( Scl_Tree_t * p, char ** ppPos, char * pEnd, int fStopAtNewLine )
237{
238 char * pPos = *ppPos;
239 for ( ; pPos < pEnd; pPos++ )
240 {
241 if ( *pPos == '\n' )
242 {
243 p->nLines++;
244 if ( fStopAtNewLine )
245 break;
246 }
247 if ( !Scl_LibertyCharIsSpace(*pPos) )
248 break;
249 }
250 *ppPos = pPos;
251 return pPos == pEnd;
252}
253// skips entry delimited by " :;(){}" and returns 1 if reached the end
254static inline long Scl_LibertySkipEntry( char ** ppPos, char * pEnd )
255{
256 char * pPos = *ppPos;
257 if ( *pPos == '\"' )
258 {
259 for ( pPos++; pPos < pEnd; pPos++ )
260 if ( *pPos == '\"' )
261 {
262 pPos++;
263 break;
264 }
265 }
266 else
267 {
268 for ( ; pPos < pEnd; pPos++ )
269 if ( *pPos == ' ' || *pPos == '\r' || *pPos == '\n' || *pPos == '\t' ||
270 *pPos == ':' || *pPos == ';' ||
271 *pPos == '(' || *pPos == ')' ||
272 *pPos == '{' || *pPos == '}' )
273 break;
274 }
275 *ppPos = pPos;
276 return pPos == pEnd;
277}
278// finds the matching closing symbol
279static inline char * Scl_LibertyFindMatch( char * pPos, char * pEnd )
280{
281 long Counter = 0;
282 assert( *pPos == '(' || *pPos == '{' );
283 if ( *pPos == '(' )
284 {
285 ++Counter;
286 ++pPos;
287 for ( ; pPos < pEnd; pPos++ )
288 {
289 // Invariant: Counter > 0.
290 if ( *pPos == '(' ) {
291 Counter++;
292 continue;
293 }
294 else if ( *pPos == ')' ) {
295 Counter--;
296 if ( Counter == 0 )
297 break;
298 }
299 }
300 }
301 else
302 {
303 ++Counter;
304 ++pPos;
305 for ( ; pPos < pEnd; pPos++ )
306 {
307 // Invariant: Counter > 0.
308 if ( *pPos == '{' ) {
309 Counter++;
310 continue;
311 }
312 else if ( *pPos == '}' ) {
313 Counter--;
314 if ( Counter == 0 )
315 break;
316 }
317 }
318 }
319 assert( *pPos == ')' || *pPos == '}' );
320 return pPos;
321}
322// trims spaces around the head
323static inline Scl_Pair_t Scl_LibertyUpdateHead( Scl_Tree_t * p, Scl_Pair_t Head )
324{
325 Scl_Pair_t Res;
326 char * pBeg = p->pContents + Head.Beg;
327 char * pEnd = p->pContents + Head.End;
328 char * pFirstNonSpace = NULL;
329 char * pLastNonSpace = NULL;
330 char * pChar;
331 for ( pChar = pBeg; pChar < pEnd; pChar++ )
332 {
333 if ( *pChar == '\n' ) {
334 p->nLines++;
335 // Note: Scl_LibertyCharIsSpace returns true for '\n', so we can
336 // continue here and save the call to Scl_LibertyCharIsSpace.
337 continue;
338 } else if ( Scl_LibertyCharIsSpace(*pChar) ) {
339 continue;
340 }
341 pLastNonSpace = pChar;
342 if ( pFirstNonSpace == NULL )
343 pFirstNonSpace = pChar;
344 }
345 if ( pFirstNonSpace == NULL || pLastNonSpace == NULL )
346 return Head;
347 assert( pFirstNonSpace && pLastNonSpace );
348 Res.Beg = pFirstNonSpace - p->pContents;
349 Res.End = pLastNonSpace - p->pContents + 1;
350 return Res;
351}
352// returns new item
353static inline Scl_Item_t * Scl_LibertyNewItem( Scl_Tree_t * p, int Type )
354{
355 p->pItems[p->nItems].iLine = p->nLines;
356 p->pItems[p->nItems].Type = Type;
357 p->pItems[p->nItems].Child = -1;
358 p->pItems[p->nItems].Next = -1;
359 return p->pItems + p->nItems++;
360}
361
362
375{
376 // static char Buffer[ABC_MAX_LIB_STR_LEN];
377 char * Buffer;
378 if ( Pair.End - Pair.Beg + 2 > Vec_StrSize(p->vBuffer) )
379 Vec_StrFill( p->vBuffer, Pair.End - Pair.Beg + 100, '\0' );
380 Buffer = Vec_StrArray( p->vBuffer );
381 strncpy( Buffer, p->pContents+Pair.Beg, Pair.End-Pair.Beg );
382 if ( Pair.Beg < Pair.End && Buffer[0] == '\"' )
383 {
384 assert( Buffer[Pair.End-Pair.Beg-1] == '\"' );
385 Buffer[Pair.End-Pair.Beg-1] = 0;
386 return Buffer + 1;
387 }
388 Buffer[Pair.End-Pair.Beg] = 0;
389 return Buffer;
390}
391long Scl_LibertyItemNum( Scl_Tree_t * p, Scl_Item_t * pRoot, char * pName )
392{
393 Scl_Item_t * pItem;
394 long Counter = 0;
395 Scl_ItemForEachChildName( p, pRoot, pItem, pName )
396 Counter++;
397 return Counter;
398}
399
411long Scl_LibertyBuildItem( Scl_Tree_t * p, char ** ppPos, char * pEnd )
412{
413 Scl_Item_t * pItem;
414 Scl_Pair_t Key, Head, Body;
415 char * pNext, * pStop;
416 Key.End = 0;
417 if ( Scl_LibertySkipSpaces( p, ppPos, pEnd, 0 ) )
418 return -2;
419 Key.Beg = *ppPos - p->pContents;
420 if ( Scl_LibertySkipEntry( ppPos, pEnd ) )
421 goto exit;
422 Key.End = *ppPos - p->pContents;
423 if ( Scl_LibertySkipSpaces( p, ppPos, pEnd, 0 ) )
424 goto exit;
425 pNext = *ppPos;
426 if ( *pNext == ':' )
427 {
428 *ppPos = pNext + 1;
429 if ( Scl_LibertySkipSpaces( p, ppPos, pEnd, 0 ) )
430 goto exit;
431 Head.Beg = *ppPos - p->pContents;
432 if ( Scl_LibertySkipEntry( ppPos, pEnd ) )
433 goto exit;
434 Head.End = *ppPos - p->pContents;
435 if ( Scl_LibertySkipSpaces( p, ppPos, pEnd, 1 ) )
436 goto exit;
437 pNext = *ppPos;
438 while ( *pNext == '+' || *pNext == '-' || *pNext == '*' || *pNext == '/' )
439 {
440 (*ppPos) += 1;
441 if ( Scl_LibertySkipSpaces( p, ppPos, pEnd, 0 ) )
442 goto exit;
443 if ( Scl_LibertySkipEntry( ppPos, pEnd ) )
444 goto exit;
445 Head.End = *ppPos - p->pContents;
446 if ( Scl_LibertySkipSpaces( p, ppPos, pEnd, 1 ) )
447 goto exit;
448 pNext = *ppPos;
449 }
450 if ( *pNext != ';' && *pNext != '\n' )
451 goto exit;
452 *ppPos = pNext + 1;
453 // end of equation
454 pItem = Scl_LibertyNewItem( p, SCL_LIBERTY_EQUA );
455 pItem->Key = Key;
456 pItem->Head = Scl_LibertyUpdateHead( p, Head );
457 pItem->Next = Scl_LibertyBuildItem( p, ppPos, pEnd );
458 if ( pItem->Next == -1 )
459 goto exit;
460 return Scl_LibertyItemId( p, pItem );
461 }
462 if ( *pNext == '(' )
463 {
464 pStop = Scl_LibertyFindMatch( pNext, pEnd );
465 Head.Beg = pNext - p->pContents + 1;
466 Head.End = pStop - p->pContents;
467 *ppPos = pStop + 1;
468 if ( Scl_LibertySkipSpaces( p, ppPos, pEnd, 0 ) )
469 {
470 // end of list
471 pItem = Scl_LibertyNewItem( p, SCL_LIBERTY_LIST );
472 pItem->Key = Key;
473 pItem->Head = Scl_LibertyUpdateHead( p, Head );
474 return Scl_LibertyItemId( p, pItem );
475 }
476 pNext = *ppPos;
477 if ( *pNext == '{' ) // beginning of body
478 {
479 pStop = Scl_LibertyFindMatch( pNext, pEnd );
480 Body.Beg = pNext - p->pContents + 1;
481 Body.End = pStop - p->pContents;
482 // end of body
483 pItem = Scl_LibertyNewItem( p, SCL_LIBERTY_PROC );
484 pItem->Key = Key;
485 pItem->Head = Scl_LibertyUpdateHead( p, Head );
486 pItem->Body = Body;
487 *ppPos = pNext + 1;
488 pItem->Child = Scl_LibertyBuildItem( p, ppPos, pStop );
489 if ( pItem->Child == -1 )
490 goto exit;
491 *ppPos = pStop + 1;
492 pItem->Next = Scl_LibertyBuildItem( p, ppPos, pEnd );
493 if ( pItem->Next == -1 )
494 goto exit;
495 return Scl_LibertyItemId( p, pItem );
496 }
497 // end of list
498 if ( *pNext == ';' )
499 *ppPos = pNext + 1;
500 pItem = Scl_LibertyNewItem( p, SCL_LIBERTY_LIST );
501 pItem->Key = Key;
502 pItem->Head = Scl_LibertyUpdateHead( p, Head );
503 pItem->Next = Scl_LibertyBuildItem( p, ppPos, pEnd );
504 if ( pItem->Next == -1 )
505 goto exit;
506 return Scl_LibertyItemId( p, pItem );
507 }
508 if ( *pNext == ';' )
509 {
510 *ppPos = pNext + 1;
511 return Scl_LibertyBuildItem(p, ppPos, pEnd);
512 }
513exit:
514 if ( p->pError == NULL )
515 {
516 p->pError = ABC_ALLOC( char, 1000 );
517 sprintf( p->pError, "File \"%s\". Line %6ld. Failed to parse entry \"%s\".\n",
518 p->pFileName, p->nLines, Scl_LibertyReadString(p, Key) );
519 }
520 return -1;
521}
522
534void Scl_LibertyFixFileName( char * pFileName )
535{
536 char * pHead;
537 for ( pHead = pFileName; *pHead; pHead++ )
538 if ( *pHead == '>' )
539 *pHead = '\\';
540}
541long Scl_LibertyFileSize( char * pFileName )
542{
543 FILE * pFile;
544 long nFileSize;
545 pFile = fopen( pFileName, "rb" );
546 if ( pFile == NULL )
547 {
548 printf( "Scl_LibertyFileSize(): The input file is unavailable (absent or open).\n" );
549 return 0;
550 }
551 fseek( pFile, 0, SEEK_END );
552 nFileSize = ftell( pFile );
553 fclose( pFile );
554 return nFileSize;
555}
556
557static char * Io_LibLoadFileGz( char * pFileName, long * pnFileSize )
558{
559 const int READ_BLOCK_SIZE = 100000;
560 gzFile pFile;
561 char * pContents;
562 long amtRead, readBlock, nFileSize = READ_BLOCK_SIZE;
563 pFile = gzopen( pFileName, "rb" ); // if pFileName doesn't end in ".gz" then this acts as a passthrough to fopen
564 pContents = ABC_ALLOC( char, nFileSize );
565 readBlock = 0;
566 while ((amtRead = gzread(pFile, pContents + readBlock * READ_BLOCK_SIZE, READ_BLOCK_SIZE)) == READ_BLOCK_SIZE) {
567 //Abc_Print( 1,"%d: read %d bytes\n", readBlock, amtRead);
568 nFileSize += READ_BLOCK_SIZE;
569 pContents = ABC_REALLOC(char, pContents, nFileSize);
570 ++readBlock;
571 }
572 //Abc_Print( 1,"%d: read %d bytes\n", readBlock, amtRead);
573 assert( amtRead != -1 ); // indicates a zlib error
574 nFileSize -= (READ_BLOCK_SIZE - amtRead);
575 gzclose(pFile);
576 *pnFileSize = nFileSize;
577 return pContents;
578}
579
580char * Scl_LibertyFileContents( char * pFileName, long * nContents )
581{
582 char * pContents = NULL;
583 //if file ends in ".gz" then use gzopen
584 if ( !strncmp(pFileName+strlen(pFileName)-3,".gz", 3) )
585 {
586 FILE * pFile = fopen( pFileName, "rb" );
587 //char * pContents;
588 long RetValue = 0;
589 pContents = Io_LibLoadFileGz( pFileName, nContents );
590 if(pContents == NULL) {
591 printf( "Scl_LibertyFileContents(): The input file is unavailable (absent or open).\n" );
592 return NULL;
593 }
594 else {
595 RetValue = 1;
596 }
597 fclose( pFile );
598 }
599 // original .lib file
600 else
601 {
602 FILE * pFile = fopen( pFileName, "rb" );
603 pContents = ABC_ALLOC( char, *nContents+1 );
604 long RetValue = 0;
605 RetValue = fread( pContents, *nContents, 1, pFile );
606 fclose( pFile );
607 pContents[*nContents] = 0;
608 }
609 return pContents;
610}
611void Scl_LibertyStringDump( char * pFileName, Vec_Str_t * vStr )
612{
613 FILE * pFile = fopen( pFileName, "wb" );
614 long RetValue = 0;
615 if ( pFile == NULL )
616 {
617 printf( "Scl_LibertyStringDump(): The output file is unavailable.\n" );
618 return;
619 }
620 RetValue = fwrite( Vec_StrArray(vStr), 1, Vec_StrSize(vStr), pFile );
621 fclose( pFile );
622}
623
635Scl_Tree_t * Scl_LibertyStart( char * pFileName )
636{
637 Scl_Tree_t * p;
638 long RetValue;
639 // read the file into the buffer
640 Scl_LibertyFixFileName( pFileName );
641 RetValue = Scl_LibertyFileSize( pFileName );
642 if ( RetValue == 0 )
643 return NULL;
644 // start the manager
645 p = ABC_ALLOC( Scl_Tree_t, 1 );
646 memset( p, 0, sizeof(Scl_Tree_t) );
647 p->clkStart = Abc_Clock();
648 p->nContents = RetValue;
649 p->pContents = Scl_LibertyFileContents( pFileName, &p->nContents );
650 // other
651 p->pFileName = Abc_UtilStrsav( pFileName );
652 p->nItermAlloc = 10 + Scl_LibertyCountItems( p->pContents, p->pContents+p->nContents );
653 p->pItems = ABC_CALLOC( Scl_Item_t, p->nItermAlloc );
654 p->nItems = 0;
655 p->nLines = 1;
656 p->vBuffer = Vec_StrStart( 10 );
657 return p;
658}
659void Scl_LibertyStop( Scl_Tree_t * p, int fVerbose )
660{
661 if ( fVerbose )
662 {
663 printf( "Memory = %7.2f MB. ", 1.0 * (p->nContents + p->nItermAlloc * sizeof(Scl_Item_t))/(1<<20) );
664 ABC_PRT( "Time", Abc_Clock() - p->clkStart );
665 }
666 Vec_StrFree( p->vBuffer );
667 ABC_FREE( p->pFileName );
668 ABC_FREE( p->pContents );
669 ABC_FREE( p->pItems );
670 ABC_FREE( p->pError );
671 ABC_FREE( p );
672}
673Scl_Tree_t * Scl_LibertyParse( char * pFileName, int fVerbose )
674{
675 Scl_Tree_t * p;
676 char * pPos;
677 if ( (p = Scl_LibertyStart(pFileName)) == NULL )
678 return NULL;
679 pPos = p->pContents;
680 Scl_LibertyWipeOutComments( p->pContents, p->pContents+p->nContents );
681 if ( (!Scl_LibertyBuildItem( p, &pPos, p->pContents + p->nContents )) == 0 )
682 {
683 if ( p->pError ) printf( "%s", p->pError );
684 printf( "Parsing failed. " );
685 Abc_PrintTime( 1, "Parsing time", Abc_Clock() - p->clkStart );
686 }
687 else if ( fVerbose )
688 {
689 printf( "Parsing finished successfully. " );
690 Abc_PrintTime( 1, "Parsing time", Abc_Clock() - p->clkStart );
691 }
692 return p;
693}
694
707{
708 Scl_Item_t * pAttr;
709 Scl_ItemForEachChild( p, pCell, pAttr )
710 if ( !Scl_LibertyCompare(p, pAttr->Key, "ff") ||
711 !Scl_LibertyCompare(p, pAttr->Key, "latch") )
712 return 1;
713 return 0;
714}
716{
717 Scl_Item_t * pAttr;
718 Scl_ItemForEachChild( p, pCell, pAttr )
719 {
720 if ( !Scl_LibertyCompare(p, pAttr->Key, "dont_use") )
721 return 1;
722 const char * cell_name = Scl_LibertyReadString(p, pCell->Head);
723 for (int i = 0; i < dont_use.size; i++) {
724 if (Scl_LibertyGlobMatch(dont_use.dont_use_list[i], cell_name)) {
725 return 1;
726 }
727 }
728 }
729 return 0;
730}
732{
733 Scl_Item_t * pArea;
734 Scl_ItemForEachChildName( p, pCell, pArea, "area" )
735 return Scl_LibertyReadString(p, pArea->Head);
736 return 0;
737}
739{
740 Scl_Item_t * pItem, * pChild;
741 Scl_ItemForEachChildName( p, pCell, pItem, "cell_leakage_power" )
742 return Scl_LibertyReadString(p, pItem->Head);
743 // look for another type
744 Scl_ItemForEachChildName( p, pCell, pItem, "leakage_power" )
745 {
746 Scl_ItemForEachChildName( p, pItem, pChild, "when" )
747 break;
748 if ( pChild && !Scl_LibertyCompare(p, pChild->Key, "when") )
749 continue;
750 Scl_ItemForEachChildName( p, pItem, pChild, "value" )
751 return Scl_LibertyReadString(p, pChild->Head);
752 }
753 return 0;
754}
756{
757 Scl_Item_t * pFunc;
758 Scl_ItemForEachChildName( p, pPin, pFunc, "function" )
759 return Scl_LibertyReadString(p, pFunc->Head);
760 return NULL;
761}
763{
764 Scl_Item_t * pPin, * pItem;
765 Scl_ItemForEachChildName( p, pCell, pPin, "pin" )
766 Scl_ItemForEachChildName( p, pPin, pItem, "three_state" )
767 return 1;
768 return 0;
769}
771{
772 Scl_Item_t * pPin;
773 long Counter = 0;
774 Scl_ItemForEachChildName( p, pCell, pPin, "pin" )
775 if ( Scl_LibertyReadPinFormula(p, pPin) )
776 Counter++;
777 return Counter;
778}
779
792{
793 Vec_Str_t * vStr;
794 Scl_Item_t * pCell, * pOutput, * pInput;
795 char * pFormula;
796 vStr = Vec_StrAlloc( 1000 );
797 Vec_StrPrintStr( vStr, "GATE _const0_ 0.000000 z=CONST0;\n" );
798 Vec_StrPrintStr( vStr, "GATE _const1_ 0.000000 z=CONST1;\n" );
799 Scl_ItemForEachChildName( p, Scl_LibertyRoot(p), pCell, "cell" )
800 {
801 if ( Scl_LibertyReadCellIsFlop(p, pCell) )
802 {
803 if ( fVerbose ) printf( "Scl_LibertyReadGenlib() skipped sequential cell \"%s\".\n", Scl_LibertyReadString(p, pCell->Head) );
804 continue;
805 }
806 if ( Scl_LibertyReadCellIsDontUse(p, pCell, dont_use) )
807 {
808 if ( fVerbose ) printf( "Scl_LibertyReadGenlib() skipped cell \"%s\" due to dont_use attribute.\n", Scl_LibertyReadString(p, pCell->Head) );
809 continue;
810 }
812 {
813 if ( fVerbose ) printf( "Scl_LibertyReadGenlib() skipped three-state cell \"%s\".\n", Scl_LibertyReadString(p, pCell->Head) );
814 continue;
815 }
816 if ( Scl_LibertyReadCellOutputNum(p, pCell) == 0 )
817 {
818 if ( fVerbose ) printf( "Scl_LibertyReadGenlib() skipped cell \"%s\" without logic function.\n", Scl_LibertyReadString(p, pCell->Head) );
819 continue;
820 }
821 // iterate through output pins
822 Scl_ItemForEachChildName( p, pCell, pOutput, "pin" )
823 {
824 if ( !(pFormula = Scl_LibertyReadPinFormula(p, pOutput)) )
825 continue;
826 if ( !strcmp(pFormula, "0") || !strcmp(pFormula, "1") )
827 {
828 if ( fVerbose ) printf( "Scl_LibertyReadGenlib() skipped cell \"%s\" with constant formula \"%s\".\n", Scl_LibertyReadString(p, pCell->Head), pFormula );
829 break;
830 }
831 Vec_StrPrintStr( vStr, "GATE " );
832 Vec_StrPrintStr( vStr, Scl_LibertyReadString(p, pCell->Head) );
833 Vec_StrPrintStr( vStr, " " );
834 Vec_StrPrintStr( vStr, Scl_LibertyReadCellArea(p, pCell) );
835 Vec_StrPrintStr( vStr, " " );
836 Vec_StrPrintStr( vStr, Scl_LibertyReadString(p, pOutput->Head) );
837 Vec_StrPrintStr( vStr, "=" );
838 Vec_StrPrintStr( vStr, pFormula );
839 Vec_StrPrintStr( vStr, ";\n" );
840 // iterate through input pins
841 Scl_ItemForEachChildName( p, pCell, pInput, "pin" )
842 {
843 if ( Scl_LibertyReadPinFormula(p, pInput) == NULL )
844 continue;
845 Vec_StrPrintStr( vStr, " PIN " );
846 Vec_StrPrintStr( vStr, Scl_LibertyReadString(p, pInput->Head) );
847 Vec_StrPrintStr( vStr, " UNKNOWN 1 999 1.00 0.00 1.00 0.00\n" );
848 }
849 }
850 }
851 Vec_StrPrintStr( vStr, "\n.end\n" );
852 Vec_StrPush( vStr, '\0' );
853// printf( "%s", Vec_StrArray(vStr) );
854 return vStr;
855}
856
868//#define SCL_DEBUG
869#ifdef SCL_DEBUG
870static inline void Vec_StrPutI_( Vec_Str_t * vOut, int Val ) { printf( "%d ", Val ); Vec_StrPutI( vOut, Val ); }
871static inline void Vec_StrPutW_( Vec_Str_t * vOut, word Val ) { printf( "%lu ", (long)Val ); Vec_StrPutW( vOut, Val ); }
872static inline void Vec_StrPutF_( Vec_Str_t * vOut, float Val ) { printf( "%f ", Val ); Vec_StrPutF( vOut, Val ); }
873static inline void Vec_StrPutS_( Vec_Str_t * vOut, char * Val ) { printf( "%s ", Val ); Vec_StrPutS( vOut, Val ); }
874static inline void Vec_StrPut_( Vec_Str_t * vOut ) { printf( "\n" ); }
875#else
876static inline void Vec_StrPutI_( Vec_Str_t * vOut, int Val ) { Vec_StrPutI( vOut, Val ); }
877static inline void Vec_StrPutW_( Vec_Str_t * vOut, word Val ) { Vec_StrPutW( vOut, Val ); }
878static inline void Vec_StrPutF_( Vec_Str_t * vOut, float Val ) { Vec_StrPutF( vOut, Val ); }
879static inline void Vec_StrPutS_( Vec_Str_t * vOut, char * Val ) { Vec_StrPutS( vOut, Val ); }
880static inline void Vec_StrPut_( Vec_Str_t * vOut ) { }
881#endif
882
895{
896 Scl_Item_t * pItem;
897 Scl_ItemForEachChildName( p, Scl_LibertyRoot(p), pItem, "default_wire_load" )
898 return Scl_LibertyReadString(p, pItem->Head);
899 return "";
900}
902{
903 Scl_Item_t * pItem;
904 Scl_ItemForEachChildName( p, Scl_LibertyRoot(p), pItem, "default_wire_load_selection" )
905 return Scl_LibertyReadString(p, pItem->Head);
906 return "";
907}
909{
910 Scl_Item_t * pItem;
911 Scl_ItemForEachChildName( p, Scl_LibertyRoot(p), pItem, "default_max_transition" )
912 return atof(Scl_LibertyReadString(p, pItem->Head));
913 return 0;
914}
916{
917 Scl_Item_t * pItem;
918 Scl_ItemForEachChildName( p, Scl_LibertyRoot(p), pItem, "time_unit" )
919 {
920 char * pUnit = Scl_LibertyReadString(p, pItem->Head);
921 // 9=1ns, 10=100ps, 11=10ps, 12=1ps
922 if ( !strcmp(pUnit, "1ns") )
923 return 9;
924 if ( !strcmp(pUnit, "100ps") )
925 return 10;
926 if ( !strcmp(pUnit, "10ps") )
927 return 11;
928 if ( !strcmp(pUnit, "1ps") )
929 return 12;
930 break;
931 }
932 printf( "Liberty parser cannot read \"time_unit\". Assuming time_unit : \"1ns\".\n" );
933 return 9;
934}
936{
937 Scl_Item_t * pItem;
938 Scl_ItemForEachChildName( p, Scl_LibertyRoot(p), pItem, "capacitive_load_unit" )
939 {
940 // expecting (1.00,ff) or (1, pf) ... 12 or 15 for 'pf' or 'ff'
941 char * pHead = Scl_LibertyReadString(p, pItem->Head);
942 float First = atof(strtok(pHead, " \t\n\r\\\","));
943 char * pSecond = strtok(NULL, " \t\n\r\\\",");
944 Vec_StrPutF_( vOut, First );
945 if ( pSecond && !strcmp(pSecond, "pf") )
946 Vec_StrPutI_( vOut, 12 );
947 else if ( pSecond && !strcmp(pSecond, "ff") )
948 Vec_StrPutI_( vOut, 15 );
949 else break;
950 return;
951 }
952 printf( "Liberty parser cannot read \"capacitive_load_unit\". Assuming capacitive_load_unit(1, pf).\n" );
953 Vec_StrPutF_( vOut, 1.0 );
954 Vec_StrPutI_( vOut, 12 );
955}
957{
958 Scl_Item_t * pItem, * pChild;
959 Vec_StrPutI_( vOut, Scl_LibertyItemNum(p, Scl_LibertyRoot(p), "wire_load") );
960 Vec_StrPut_( vOut );
961 Scl_ItemForEachChildName( p, Scl_LibertyRoot(p), pItem, "wire_load" )
962 {
963 Vec_StrPutS_( vOut, Scl_LibertyReadString(p, pItem->Head) );
964 Scl_ItemForEachChildName( p, pItem, pChild, "capacitance" )
965 Vec_StrPutF_( vOut, atof(Scl_LibertyReadString(p, pChild->Head)) );
966 Scl_ItemForEachChildName( p, pItem, pChild, "slope" )
967 Vec_StrPutF_( vOut, atof(Scl_LibertyReadString(p, pChild->Head)) );
968 Vec_StrPut_( vOut );
969 Vec_StrPutI_( vOut, Scl_LibertyItemNum(p, pItem, "fanout_length") );
970 Vec_StrPut_( vOut );
971 Scl_ItemForEachChildName( p, pItem, pChild, "fanout_length" )
972 {
973 char * pHead = Scl_LibertyReadString(p, pChild->Head);
974 int First = atoi( strtok(pHead, " ,") );
975 float Second = atof( strtok(NULL, " ") );
976 Vec_StrPutI_( vOut, First );
977 Vec_StrPutF_( vOut, Second );
978 Vec_StrPut_( vOut );
979 }
980 Vec_StrPut_( vOut );
981 }
982 Vec_StrPut_( vOut );
983}
985{
986 Scl_Item_t * pItem, * pChild;
987 Vec_StrPutI_( vOut, Scl_LibertyItemNum(p, Scl_LibertyRoot(p), "wire_load_selection") );
988 Vec_StrPut_( vOut );
989 Scl_ItemForEachChildName( p, Scl_LibertyRoot(p), pItem, "wire_load_selection" )
990 {
991 Vec_StrPutS_( vOut, Scl_LibertyReadString(p, pItem->Head) );
992 Vec_StrPut_( vOut );
993 Vec_StrPutI_( vOut, Scl_LibertyItemNum(p, pItem, "wire_load_from_area") );
994 Vec_StrPut_( vOut );
995 Scl_ItemForEachChildName( p, pItem, pChild, "wire_load_from_area" )
996 {
997 char * pHead = Scl_LibertyReadString(p, pChild->Head);
998 float First = atof( strtok(pHead, " ,") );
999 float Second = atof( strtok(NULL, " ,") );
1000 char * pThird = strtok(NULL, " ");
1001 if ( pThird[0] == '\"' )
1002 assert(pThird[strlen(pThird)-1] == '\"'), pThird[strlen(pThird)-1] = 0, pThird++;
1003 Vec_StrPutF_( vOut, First );
1004 Vec_StrPutF_( vOut, Second );
1005 Vec_StrPutS_( vOut, pThird );
1006 Vec_StrPut_( vOut );
1007 }
1008 Vec_StrPut_( vOut );
1009 }
1010 Vec_StrPut_( vOut );
1011}
1013{
1014 Scl_Item_t * pItem;
1015 Scl_ItemForEachChildName( p, pCell, pItem, "drive_strength" )
1016 return atoi(Scl_LibertyReadString(p, pItem->Head));
1017 return 0;
1018}
1020{
1021 Scl_Item_t * pItem;
1022 Scl_ItemForEachChildName( p, pPin, pItem, "direction" )
1023 {
1024 char * pToken = Scl_LibertyReadString(p, pItem->Head);
1025 if ( !strcmp(pToken, "input") )
1026 return 0;
1027 if ( !strcmp(pToken, "output") )
1028 return 1;
1029 if ( !strcmp(pToken, "internal") )
1030 return 2;
1031 break;
1032 }
1033 return -1;
1034}
1035float Scl_LibertyReadPinCap( Scl_Tree_t * p, Scl_Item_t * pPin, char * pName )
1036{
1037 Scl_Item_t * pItem;
1038 Scl_ItemForEachChildName( p, pPin, pItem, pName )
1039 return atof(Scl_LibertyReadString(p, pItem->Head));
1040 return 0;
1041}
1043{
1044 Scl_Item_t * pTiming, * pPinIn;
1045 Scl_ItemForEachChildName( p, pPinOut, pTiming, "timing" )
1046 Scl_ItemForEachChildName( p, pTiming, pPinIn, "related_pin" )
1047 if ( !strcmp(Scl_LibertyReadString(p, pPinIn->Head), pNameIn) )
1048 return pTiming;
1049 return NULL;
1050}
1052{
1053 Vec_Ptr_t * vTimings;
1054 Scl_Item_t * pTiming, * pPinIn;
1055 vTimings = Vec_PtrAlloc( 16 );
1056 Scl_ItemForEachChildName( p, pPinOut, pTiming, "timing" )
1057 Scl_ItemForEachChildName( p, pTiming, pPinIn, "related_pin" )
1058 if ( !strcmp(Scl_LibertyReadString(p, pPinIn->Head), pNameIn) )
1059 Vec_PtrPush( vTimings, pTiming );
1060 return vTimings;
1061}
1063{
1064 Scl_Item_t * pItem;
1065 Scl_ItemForEachChildName( p, pPin, pItem, "timing_sense" )
1066 {
1067 char * pToken = Scl_LibertyReadString(p, pItem->Head);
1068 if ( !strcmp(pToken, "positive_unate") )
1069 return sc_ts_Pos;
1070 if ( !strcmp(pToken, "negative_unate") )
1071 return sc_ts_Neg;
1072 if ( !strcmp(pToken, "non_unate") )
1073 return sc_ts_Non;
1074 break;
1075 }
1076 return sc_ts_Non;
1077}
1079{
1080 char * pToken;
1081 Vec_Flt_t * vValues = Vec_FltAlloc( 100 );
1082 for ( pToken = strtok(pName, " \t\n\r\\\","); pToken; pToken = strtok(NULL, " \t\n\r\\\",") )
1083 Vec_FltPush( vValues, atof(pToken) );
1084 return vValues;
1085}
1086
1087void Scl_LibertyDumpTables( Vec_Str_t * vOut, Vec_Flt_t * vInd1, Vec_Flt_t * vInd2, Vec_Flt_t * vValues )
1088{
1089 int i; float Entry;
1090 // write entries
1091 Vec_StrPutI_( vOut, Vec_FltSize(vInd1) );
1092 Vec_FltForEachEntry( vInd1, Entry, i )
1093 Vec_StrPutF_( vOut, Entry );
1094 Vec_StrPut_( vOut );
1095 // write entries
1096 Vec_StrPutI_( vOut, Vec_FltSize(vInd2) );
1097 Vec_FltForEachEntry( vInd2, Entry, i )
1098 Vec_StrPutF_( vOut, Entry );
1099 Vec_StrPut_( vOut );
1100 Vec_StrPut_( vOut );
1101 // write entries
1102 assert( Vec_FltSize(vInd1) * Vec_FltSize(vInd2) == Vec_FltSize(vValues) );
1103 Vec_FltForEachEntry( vValues, Entry, i )
1104 {
1105 Vec_StrPutF_( vOut, Entry );
1106 if ( i % Vec_FltSize(vInd2) == Vec_FltSize(vInd2)-1 )
1107 Vec_StrPut_( vOut );
1108 }
1109 // dump approximations
1110 Vec_StrPut_( vOut );
1111 for ( i = 0; i < 3; i++ )
1112 Vec_StrPutF_( vOut, 0 );
1113 for ( i = 0; i < 4; i++ )
1114 Vec_StrPutF_( vOut, 0 );
1115 for ( i = 0; i < 6; i++ )
1116 Vec_StrPutF_( vOut, 0 );
1117 Vec_StrPut_( vOut );
1118 Vec_StrPut_( vOut );
1119}
1120int Scl_LibertyScanTable( Scl_Tree_t * p, Vec_Ptr_t * vOut, Scl_Item_t * pTiming, char * pName, Vec_Ptr_t * vTemples )
1121{
1122 Vec_Flt_t * vIndex1 = NULL;
1123 Vec_Flt_t * vIndex2 = NULL;
1124 Vec_Flt_t * vValues = NULL;
1125 Vec_Flt_t * vInd1, * vInd2;
1126 Scl_Item_t * pItem, * pTable = NULL;
1127 char * pThis, * pTempl = NULL;
1128 int iPlace, i;
1129 float Entry;
1130 // find the table
1131 Scl_ItemForEachChildName( p, pTiming, pTable, pName )
1132 break;
1133 if ( pTable == NULL )
1134 return 0;
1135 // find the template
1136 pTempl = Scl_LibertyReadString(p, pTable->Head);
1137 if ( pTempl == NULL || pTempl[0] == 0 )
1138 {
1139 // read the numbers
1140 Scl_ItemForEachChild( p, pTable, pItem )
1141 {
1142 if ( !Scl_LibertyCompare(p, pItem->Key, "index_1") )
1143 assert(vIndex1 == NULL), vIndex1 = Scl_LibertyReadFloatVec( Scl_LibertyReadString(p, pItem->Head) );
1144 else if ( !Scl_LibertyCompare(p, pItem->Key, "index_2") )
1145 assert(vIndex2 == NULL), vIndex2 = Scl_LibertyReadFloatVec( Scl_LibertyReadString(p, pItem->Head) );
1146 else if ( !Scl_LibertyCompare(p, pItem->Key, "values") )
1147 assert(vValues == NULL), vValues = Scl_LibertyReadFloatVec( Scl_LibertyReadString(p, pItem->Head) );
1148 }
1149 if ( vIndex1 == NULL || vIndex2 == NULL || vValues == NULL )
1150 { printf( "Incomplete table specification\n" ); return 0; }
1151 // dump the table
1152 vInd1 = vIndex1;
1153 vInd2 = vIndex2;
1154 // write entries
1155 Vec_PtrPush( vOut, vInd1 );
1156 Vec_PtrPush( vOut, vInd2 );
1157 Vec_PtrPush( vOut, vValues );
1158 }
1159 else if ( !strcmp(pTempl, "scalar") )
1160 {
1161 Scl_ItemForEachChild( p, pTable, pItem )
1162 if ( !Scl_LibertyCompare(p, pItem->Key, "values") )
1163 {
1164 assert(vValues == NULL);
1166 assert( Vec_FltSize(vValues) == 1 );
1167 // write entries
1168 Vec_PtrPush( vOut, Vec_IntStart(1) );
1169 Vec_PtrPush( vOut, Vec_IntStart(1) );
1170 Vec_PtrPush( vOut, vValues );
1171 break;
1172 }
1173 else
1174 { printf( "Cannot read \"scalar\" template\n" ); return 0; }
1175 }
1176 else
1177 {
1178 // fetch the template
1179 iPlace = -1;
1180 Vec_PtrForEachEntry( char *, vTemples, pThis, i )
1181 if ( i % 4 == 0 && !strcmp(pTempl, pThis) )
1182 {
1183 iPlace = i;
1184 break;
1185 }
1186 if ( iPlace == -1 )
1187 { printf( "Template cannot be found in the template library\n" ); return 0; }
1188 // read the numbers
1189 Scl_ItemForEachChild( p, pTable, pItem )
1190 {
1191 if ( !Scl_LibertyCompare(p, pItem->Key, "index_1") )
1192 assert(vIndex1 == NULL), vIndex1 = Scl_LibertyReadFloatVec( Scl_LibertyReadString(p, pItem->Head) );
1193 else if ( !Scl_LibertyCompare(p, pItem->Key, "index_2") )
1194 assert(vIndex2 == NULL), vIndex2 = Scl_LibertyReadFloatVec( Scl_LibertyReadString(p, pItem->Head) );
1195 else if ( !Scl_LibertyCompare(p, pItem->Key, "values") )
1196 assert(vValues == NULL), vValues = Scl_LibertyReadFloatVec( Scl_LibertyReadString(p, pItem->Head) );
1197 }
1198 // check the template style
1199 vInd1 = (Vec_Flt_t *)Vec_PtrEntry( vTemples, iPlace + 2 ); // slew
1200 vInd2 = (Vec_Flt_t *)Vec_PtrEntry( vTemples, iPlace + 3 ); // load
1201 if ( Vec_PtrEntry(vTemples, iPlace + 1) == NULL ) // normal order (vIndex1 is slew; vIndex2 is load)
1202 {
1203 assert( !vIndex1 || Vec_FltSize(vIndex1) == Vec_FltSize(vInd1) );
1204 assert( !vIndex2 || Vec_FltSize(vIndex2) == Vec_FltSize(vInd2) );
1205 vInd1 = vIndex1 ? vIndex1 : vInd1;
1206 vInd2 = vIndex2 ? vIndex2 : vInd2;
1207 // write entries
1208 Vec_PtrPush( vOut, Vec_FltDup(vInd1) );
1209 Vec_PtrPush( vOut, Vec_FltDup(vInd2) );
1210 Vec_PtrPush( vOut, Vec_FltDup(vValues) );
1211 }
1212 else // reverse order (vIndex2 is slew; vIndex1 is load)
1213 {
1214 Vec_Flt_t * vValues2 = Vec_FltAlloc( Vec_FltSize(vValues) );
1215 assert( !vIndex2 || Vec_FltSize(vIndex2) == Vec_FltSize(vInd1) );
1216 assert( !vIndex1 || Vec_FltSize(vIndex1) == Vec_FltSize(vInd2) );
1217 vInd1 = vIndex2 ? vIndex2 : vInd1;
1218 vInd2 = vIndex1 ? vIndex1 : vInd2;
1219 // write entries -- transpose
1220 assert( Vec_FltSize(vInd1) * Vec_FltSize(vInd2) == Vec_FltSize(vValues) );
1221 Vec_FltForEachEntry( vValues, Entry, i )
1222 {
1223 int x = i % Vec_FltSize(vInd2);
1224 int y = i / Vec_FltSize(vInd2);
1225 Entry = Vec_FltEntry( vValues, x * Vec_FltSize(vInd1) + y );
1226 Vec_FltPush( vValues2, Entry );
1227 }
1228 assert( Vec_FltSize(vValues) == Vec_FltSize(vValues2) );
1229 // write entries
1230 Vec_PtrPush( vOut, Vec_FltDup(vInd1) );
1231 Vec_PtrPush( vOut, Vec_FltDup(vInd2) );
1232 Vec_PtrPush( vOut, vValues2 );
1233 }
1234 Vec_FltFreeP( &vIndex1 );
1235 Vec_FltFreeP( &vIndex2 );
1236 Vec_FltFreeP( &vValues );
1237 }
1238 return 1;
1239}
1240int Scl_LibertyComputeWorstCase( Vec_Ptr_t * vTables, Vec_Flt_t ** pvInd0, Vec_Flt_t ** pvInd1, Vec_Flt_t ** pvValues )
1241{
1242 Vec_Flt_t * vInd0, * vInd1, * vValues;
1243 Vec_Flt_t * vind0, * vind1, * vvalues;
1244 int i, k, nTriples = Vec_PtrSize(vTables) / 3;
1245 float Entry;
1246 assert( Vec_PtrSize(vTables) > 0 && Vec_PtrSize(vTables) % 3 == 0 );
1247 if ( nTriples == 1 )
1248 {
1249 *pvInd0 = (Vec_Flt_t *)Vec_PtrEntry(vTables, 0);
1250 *pvInd1 = (Vec_Flt_t *)Vec_PtrEntry(vTables, 1);
1251 *pvValues = (Vec_Flt_t *)Vec_PtrEntry(vTables, 2);
1252 Vec_PtrShrink( vTables, 0 );
1253 return 1;
1254 }
1255 vInd0 = Vec_FltDup( (Vec_Flt_t *)Vec_PtrEntry(vTables, 0) );
1256 vInd1 = Vec_FltDup( (Vec_Flt_t *)Vec_PtrEntry(vTables, 1) );
1257 vValues = Vec_FltDup( (Vec_Flt_t *)Vec_PtrEntry(vTables, 2) );
1258 for ( i = 1; i < nTriples; i++ )
1259 {
1260 vind0 = (Vec_Flt_t *)Vec_PtrEntry(vTables, i*3+0);
1261 vind1 = (Vec_Flt_t *)Vec_PtrEntry(vTables, i*3+1);
1262 vvalues = (Vec_Flt_t *)Vec_PtrEntry(vTables, i*3+2);
1263 // check equality of indexes
1264 if ( !Vec_FltEqual(vind0, vInd0) )
1265 continue;//return 0;
1266 if ( !Vec_FltEqual(vind1, vInd1) )
1267 continue;//return 0;
1268// Vec_FltForEachEntry( vvalues, Entry, k )
1269// Vec_FltAddToEntry( vValues, k, Entry );
1270 Vec_FltForEachEntry( vvalues, Entry, k )
1271 if ( Vec_FltEntry(vValues, k) < Entry )
1272 Vec_FltWriteEntry( vValues, k, Entry );
1273 }
1274// Vec_FltForEachEntry( vValues, Entry, k )
1275// Vec_FltWriteEntry( vValues, k, Entry/nTriples );
1276 // return the result
1277 *pvInd0 = vInd0;
1278 *pvInd1 = vInd1;
1279 *pvValues = vValues;
1280 return 1;
1281}
1282
1283int Scl_LibertyReadTable( Scl_Tree_t * p, Vec_Str_t * vOut, Scl_Item_t * pTiming, char * pName, Vec_Ptr_t * vTemples )
1284{
1285 Vec_Flt_t * vIndex1 = NULL;
1286 Vec_Flt_t * vIndex2 = NULL;
1287 Vec_Flt_t * vValues = NULL;
1288 Vec_Flt_t * vInd1, * vInd2;
1289 Scl_Item_t * pItem, * pTable = NULL;
1290 char * pThis, * pTempl = NULL;
1291 int iPlace, i;
1292 float Entry;
1293 // find the table
1294 Scl_ItemForEachChildName( p, pTiming, pTable, pName )
1295 break;
1296 if ( pTable == NULL )
1297 return 0;
1298 // find the template
1299 pTempl = Scl_LibertyReadString(p, pTable->Head);
1300 if ( pTempl == NULL || pTempl[0] == 0 )
1301 {
1302 // read the numbers
1303 Scl_ItemForEachChild( p, pTable, pItem )
1304 {
1305 if ( !Scl_LibertyCompare(p, pItem->Key, "index_1") )
1306 assert(vIndex1 == NULL), vIndex1 = Scl_LibertyReadFloatVec( Scl_LibertyReadString(p, pItem->Head) );
1307 else if ( !Scl_LibertyCompare(p, pItem->Key, "index_2") )
1308 assert(vIndex2 == NULL), vIndex2 = Scl_LibertyReadFloatVec( Scl_LibertyReadString(p, pItem->Head) );
1309 else if ( !Scl_LibertyCompare(p, pItem->Key, "values") )
1310 assert(vValues == NULL), vValues = Scl_LibertyReadFloatVec( Scl_LibertyReadString(p, pItem->Head) );
1311 }
1312 if ( vIndex1 == NULL || vIndex2 == NULL || vValues == NULL )
1313 { printf( "Incomplete table specification\n" ); return 0; }
1314 // dump the table
1315 vInd1 = vIndex1;
1316 vInd2 = vIndex2;
1317 // write entries
1318 Vec_StrPutI_( vOut, Vec_FltSize(vInd1) );
1319 Vec_FltForEachEntry( vInd1, Entry, i )
1320 Vec_StrPutF_( vOut, Entry );
1321 Vec_StrPut_( vOut );
1322 // write entries
1323 Vec_StrPutI_( vOut, Vec_FltSize(vInd2) );
1324 Vec_FltForEachEntry( vInd2, Entry, i )
1325 Vec_StrPutF_( vOut, Entry );
1326 Vec_StrPut_( vOut );
1327 Vec_StrPut_( vOut );
1328 // write entries
1329 assert( Vec_FltSize(vInd1) * Vec_FltSize(vInd2) == Vec_FltSize(vValues) );
1330 Vec_FltForEachEntry( vValues, Entry, i )
1331 {
1332 Vec_StrPutF_( vOut, Entry );
1333 if ( i % Vec_FltSize(vInd2) == Vec_FltSize(vInd2)-1 )
1334 Vec_StrPut_( vOut );
1335 }
1336 }
1337 else
1338 {
1339 // fetch the template
1340 iPlace = -1;
1341 Vec_PtrForEachEntry( char *, vTemples, pThis, i )
1342 if ( i % 4 == 0 && !strcmp(pTempl, pThis) )
1343 {
1344 iPlace = i;
1345 break;
1346 }
1347 if ( iPlace == -1 )
1348 { printf( "Template cannot be found in the template library\n" ); return 0; }
1349 // read the numbers
1350 Scl_ItemForEachChild( p, pTable, pItem )
1351 {
1352 if ( !Scl_LibertyCompare(p, pItem->Key, "index_1") )
1353 assert(vIndex1 == NULL), vIndex1 = Scl_LibertyReadFloatVec( Scl_LibertyReadString(p, pItem->Head) );
1354 else if ( !Scl_LibertyCompare(p, pItem->Key, "index_2") )
1355 assert(vIndex2 == NULL), vIndex2 = Scl_LibertyReadFloatVec( Scl_LibertyReadString(p, pItem->Head) );
1356 else if ( !Scl_LibertyCompare(p, pItem->Key, "values") )
1357 assert(vValues == NULL), vValues = Scl_LibertyReadFloatVec( Scl_LibertyReadString(p, pItem->Head) );
1358 }
1359 // check the template style
1360 vInd1 = (Vec_Flt_t *)Vec_PtrEntry( vTemples, iPlace + 2 ); // slew
1361 vInd2 = (Vec_Flt_t *)Vec_PtrEntry( vTemples, iPlace + 3 ); // load
1362 if ( Vec_PtrEntry(vTemples, iPlace + 1) == NULL ) // normal order (vIndex1 is slew; vIndex2 is load)
1363 {
1364 assert( !vIndex1 || Vec_FltSize(vIndex1) == Vec_FltSize(vInd1) );
1365 assert( !vIndex2 || Vec_FltSize(vIndex2) == Vec_FltSize(vInd2) );
1366 vInd1 = vIndex1 ? vIndex1 : vInd1;
1367 vInd2 = vIndex2 ? vIndex2 : vInd2;
1368 // write entries
1369 Vec_StrPutI_( vOut, Vec_FltSize(vInd1) );
1370 Vec_FltForEachEntry( vInd1, Entry, i )
1371 Vec_StrPutF_( vOut, Entry );
1372 Vec_StrPut_( vOut );
1373 // write entries
1374 Vec_StrPutI_( vOut, Vec_FltSize(vInd2) );
1375 Vec_FltForEachEntry( vInd2, Entry, i )
1376 Vec_StrPutF_( vOut, Entry );
1377 Vec_StrPut_( vOut );
1378 Vec_StrPut_( vOut );
1379 // write entries
1380 assert( Vec_FltSize(vInd1) * Vec_FltSize(vInd2) == Vec_FltSize(vValues) );
1381 Vec_FltForEachEntry( vValues, Entry, i )
1382 {
1383 Vec_StrPutF_( vOut, Entry );
1384 if ( i % Vec_FltSize(vInd2) == Vec_FltSize(vInd2)-1 )
1385 Vec_StrPut_( vOut );
1386 }
1387 }
1388 else // reverse order (vIndex2 is slew; vIndex1 is load)
1389 {
1390 assert( !vIndex2 || Vec_FltSize(vIndex2) == Vec_FltSize(vInd1) );
1391 assert( !vIndex1 || Vec_FltSize(vIndex1) == Vec_FltSize(vInd2) );
1392 vInd1 = vIndex2 ? vIndex2 : vInd1;
1393 vInd2 = vIndex1 ? vIndex1 : vInd2;
1394 // write entries
1395 Vec_StrPutI_( vOut, Vec_FltSize(vInd1) );
1396 Vec_FltForEachEntry( vInd1, Entry, i )
1397 Vec_StrPutF_( vOut, Entry );
1398 Vec_StrPut_( vOut );
1399 // write entries
1400 Vec_StrPutI_( vOut, Vec_FltSize(vInd2) );
1401 Vec_FltForEachEntry( vInd2, Entry, i )
1402 Vec_StrPutF_( vOut, Entry );
1403 Vec_StrPut_( vOut );
1404 Vec_StrPut_( vOut );
1405 // write entries -- transpose
1406 assert( Vec_FltSize(vInd1) * Vec_FltSize(vInd2) == Vec_FltSize(vValues) );
1407 Vec_FltForEachEntry( vValues, Entry, i )
1408 {
1409 int x = i % Vec_FltSize(vInd2);
1410 int y = i / Vec_FltSize(vInd2);
1411 Entry = Vec_FltEntry( vValues, x * Vec_FltSize(vInd1) + y );
1412 Vec_StrPutF_( vOut, Entry );
1413 if ( i % Vec_FltSize(vInd2) == Vec_FltSize(vInd2)-1 )
1414 Vec_StrPut_( vOut );
1415 }
1416 }
1417 }
1418 Vec_StrPut_( vOut );
1419 for ( i = 0; i < 3; i++ )
1420 Vec_StrPutF_( vOut, 0 );
1421 for ( i = 0; i < 4; i++ )
1422 Vec_StrPutF_( vOut, 0 );
1423 for ( i = 0; i < 6; i++ )
1424 Vec_StrPutF_( vOut, 0 );
1425 Vec_FltFreeP( &vIndex1 );
1426 Vec_FltFreeP( &vIndex2 );
1427 Vec_FltFreeP( &vValues );
1428 Vec_StrPut_( vOut );
1429 Vec_StrPut_( vOut );
1430 return 1;
1431}
1433{
1434 Vec_Flt_t * vArray; int i;
1435 assert( Vec_PtrSize(vRes) % 4 == 0 );
1436 printf( "There are %d slew/load templates\n", Vec_PtrSize(vRes) % 4 );
1437 Vec_PtrForEachEntry( Vec_Flt_t *, vRes, vArray, i )
1438 {
1439 if ( i % 4 == 0 )
1440 printf( "%s\n", (char *)vArray );
1441 else if ( i % 4 == 1 )
1442 printf( "%d\n", (int)(vArray != NULL) );
1443 else if ( i % 4 == 2 || i % 4 == 3 )
1444 Vec_FltPrint( vArray );
1445 if ( i % 4 == 3 )
1446 printf( "\n" );
1447 }
1448}
1450{
1451 Vec_Ptr_t * vRes = NULL;
1452 Vec_Flt_t * vIndex1, * vIndex2;
1453 Scl_Item_t * pTempl, * pItem;
1454 char * pVar1, * pVar2;
1455 int fFlag0, fFlag1;
1456 vRes = Vec_PtrAlloc( 100 );
1457 Scl_ItemForEachChildName( p, Scl_LibertyRoot(p), pTempl, "lu_table_template" )
1458 {
1459 pVar1 = pVar2 = NULL;
1460 vIndex1 = vIndex2 = NULL;
1461 Scl_ItemForEachChild( p, pTempl, pItem )
1462 {
1463 if ( !Scl_LibertyCompare(p, pItem->Key, "index_1") )
1464 assert(vIndex1 == NULL), vIndex1 = Scl_LibertyReadFloatVec( Scl_LibertyReadString(p, pItem->Head) );
1465 else if ( !Scl_LibertyCompare(p, pItem->Key, "index_2") )
1466 assert(vIndex2 == NULL), vIndex2 = Scl_LibertyReadFloatVec( Scl_LibertyReadString(p, pItem->Head) );
1467 else if ( !Scl_LibertyCompare(p, pItem->Key, "variable_1") )
1468 assert(pVar1 == NULL), pVar1 = Abc_UtilStrsav( Scl_LibertyReadString(p, pItem->Head) );
1469 else if ( !Scl_LibertyCompare(p, pItem->Key, "variable_2") )
1470 assert(pVar2 == NULL), pVar2 = Abc_UtilStrsav( Scl_LibertyReadString(p, pItem->Head) );
1471 }
1472 if ( pVar1 == NULL || pVar2 == NULL )
1473 {
1474 ABC_FREE( pVar1 );
1475 ABC_FREE( pVar2 );
1476 Vec_FltFreeP( &vIndex1 );
1477 Vec_FltFreeP( &vIndex2 );
1478 continue;
1479 }
1480 assert( pVar1 != NULL && pVar2 != NULL );
1481 fFlag0 = (!strcmp(pVar1, "input_net_transition") && !strcmp(pVar2, "total_output_net_capacitance"));
1482 fFlag1 = (!strcmp(pVar2, "input_net_transition") && !strcmp(pVar1, "total_output_net_capacitance"));
1483 ABC_FREE( pVar1 );
1484 ABC_FREE( pVar2 );
1485 if ( !fFlag0 && !fFlag1 )
1486 {
1487 Vec_FltFreeP( &vIndex1 );
1488 Vec_FltFreeP( &vIndex2 );
1489 continue;
1490 }
1491 Vec_PtrPush( vRes, Abc_UtilStrsav( Scl_LibertyReadString(p, pTempl->Head) ) );
1492 Vec_PtrPush( vRes, fFlag0 ? NULL : (void *)(ABC_PTRINT_T)1 );
1493 Vec_PtrPush( vRes, fFlag0 ? vIndex1 : vIndex2 );
1494 Vec_PtrPush( vRes, fFlag0 ? vIndex2 : vIndex1 );
1495 }
1496 if ( Vec_PtrSize(vRes) == 0 )
1497 Abc_Print( 0, "Templates are not defined.\n" );
1498 // print templates
1499// printf( "Found %d templates\n", Vec_PtrSize(vRes)/4 );
1500// Scl_LibertyPrintTemplates( vRes );
1501 return vRes;
1502}
1503Vec_Str_t * Scl_LibertyReadSclStr( Scl_Tree_t * p, int fVerbose, int fVeryVerbose, SC_DontUse dont_use, int fSkipMultiOuts )
1504{
1505 int fUseFirstTable = 0;
1506 Vec_Str_t * vOut;
1507 Vec_Ptr_t * vNameIns, * vTemples = NULL;
1508 Scl_Item_t * pCell, * pPin, * pTiming;
1509 Vec_Wrd_t * vTruth;
1510 char * pFormula, * pName;
1511 int i, k, Counter, nOutputs, nCells;
1512 int nSkipped[6] = {0};
1513
1514 // read delay-table templates
1515 vTemples = Scl_LibertyReadTemplates( p );
1516
1517 // start the library
1518 vOut = Vec_StrAlloc( 10000 );
1519 Vec_StrPutI_( vOut, ABC_SCL_CUR_VERSION );
1520
1521 // top level information
1522 Vec_StrPut_( vOut );
1523 Vec_StrPutS_( vOut, Scl_LibertyReadString(p, Scl_LibertyRoot(p)->Head) );
1524 Vec_StrPutS_( vOut, Scl_LibertyReadDefaultWireLoad(p) );
1525 Vec_StrPutS_( vOut, Scl_LibertyReadDefaultWireLoadSel(p) );
1526 Vec_StrPutF_( vOut, Scl_LibertyReadDefaultMaxTrans(p) );
1527 Vec_StrPutI_( vOut, Scl_LibertyReadTimeUnit(p) );
1528 Scl_LibertyReadLoadUnit( p, vOut );
1529 Vec_StrPut_( vOut );
1530 Vec_StrPut_( vOut );
1531
1532 // read wire loads
1533 Scl_LibertyReadWireLoad( p, vOut );
1535
1536 // count cells
1537 nCells = 0;
1538 Scl_ItemForEachChildName( p, Scl_LibertyRoot(p), pCell, "cell" )
1539 {
1540 if ( Scl_LibertyReadCellIsFlop(p, pCell) )
1541 {
1542 if ( fVeryVerbose ) printf( "Scl_LibertyReadGenlib() skipped sequential cell \"%s\".\n", Scl_LibertyReadString(p, pCell->Head) );
1543 nSkipped[0]++;
1544 continue;
1545 }
1546 if ( Scl_LibertyReadCellIsDontUse(p, pCell, dont_use) )
1547 {
1548 if ( fVeryVerbose ) printf( "Scl_LibertyReadGenlib() skipped cell \"%s\" due to dont_use attribute.\n", Scl_LibertyReadString(p, pCell->Head) );
1549 nSkipped[3]++;
1550 continue;
1551 }
1552 if ( Scl_LibertyReadCellIsThreeState(p, pCell) )
1553 {
1554 if ( fVeryVerbose ) printf( "Scl_LibertyReadGenlib() skipped three-state cell \"%s\".\n", Scl_LibertyReadString(p, pCell->Head) );
1555 nSkipped[1]++;
1556 continue;
1557 }
1558 if ( (Counter = Scl_LibertyReadCellOutputNum(p, pCell)) == 0 )
1559 {
1560 if ( fVeryVerbose ) printf( "Scl_LibertyReadGenlib() skipped cell \"%s\" without logic function.\n", Scl_LibertyReadString(p, pCell->Head) );
1561 nSkipped[2]++;
1562 continue;
1563 }
1564 if ( Counter > 2 )
1565 {
1566 if ( fVeryVerbose ) printf( "Scl_LibertyReadGenlib() skipped cell \"%s\" with more than two outputs.\n", Scl_LibertyReadString(p, pCell->Head) );
1567 nSkipped[4]++;
1568 continue;
1569 }
1570 if ( fSkipMultiOuts && Counter > 1 )
1571 {
1572 if ( fVeryVerbose ) printf( "Scl_LibertyReadGenlib() skipped cell \"%s\" with two outputs.\n", Scl_LibertyReadString(p, pCell->Head) );
1573 nSkipped[5]++;
1574 continue;
1575 }
1576 nCells++;
1577 }
1578 // read cells
1579 Vec_StrPutI_( vOut, nCells );
1580 Vec_StrPut_( vOut );
1581 Vec_StrPut_( vOut );
1582 Scl_ItemForEachChildName( p, Scl_LibertyRoot(p), pCell, "cell" )
1583 {
1584 if ( Scl_LibertyReadCellIsFlop(p, pCell) )
1585 continue;
1586 if ( Scl_LibertyReadCellIsDontUse(p, pCell, dont_use) )
1587 continue;
1588 if ( Scl_LibertyReadCellIsThreeState(p, pCell) )
1589 continue;
1590 if ( (Counter = Scl_LibertyReadCellOutputNum(p, pCell)) == 0 )
1591 continue;
1592 if ( Counter > 2 )
1593 continue;
1594 if ( fSkipMultiOuts && Counter > 1 )
1595 continue;
1596 // top level information
1597 Vec_StrPutS_( vOut, Scl_LibertyReadString(p, pCell->Head) );
1598 pName = Scl_LibertyReadCellArea(p, pCell);
1599 Vec_StrPutF_( vOut, pName ? atof(pName) : 1 );
1600 pName = Scl_LibertyReadCellLeakage(p, pCell);
1601 Vec_StrPutF_( vOut, pName ? atof(pName) : 0 );
1602 Vec_StrPutI_( vOut, Scl_LibertyReadDeriveStrength(p, pCell) );
1603 // pin count
1604 nOutputs = Scl_LibertyReadCellOutputNum( p, pCell );
1605 Vec_StrPutI_( vOut, Scl_LibertyItemNum(p, pCell, "pin") - nOutputs );
1606 Vec_StrPutI_( vOut, nOutputs );
1607 Vec_StrPut_( vOut );
1608 Vec_StrPut_( vOut );
1609
1610 // input pins
1611 vNameIns = Vec_PtrAlloc( 16 );
1612 Scl_ItemForEachChildName( p, pCell, pPin, "pin" )
1613 {
1614 float CapOne, CapRise, CapFall;
1615 if ( Scl_LibertyReadPinFormula(p, pPin) != NULL ) // skip output pin
1616 continue;
1618 pName = Scl_LibertyReadString(p, pPin->Head);
1619 Vec_PtrPush( vNameIns, Abc_UtilStrsav(pName) );
1620 Vec_StrPutS_( vOut, pName );
1621 CapOne = Scl_LibertyReadPinCap( p, pPin, "capacitance" );
1622 CapRise = Scl_LibertyReadPinCap( p, pPin, "rise_capacitance" );
1623 CapFall = Scl_LibertyReadPinCap( p, pPin, "fall_capacitance" );
1624 if ( CapRise == 0 )
1625 CapRise = CapOne;
1626 if ( CapFall == 0 )
1627 CapFall = CapOne;
1628 Vec_StrPutF_( vOut, CapRise );
1629 Vec_StrPutF_( vOut, CapFall );
1630 Vec_StrPut_( vOut );
1631 }
1632 Vec_StrPut_( vOut );
1633 // output pins
1634 Scl_ItemForEachChildName( p, pCell, pPin, "pin" )
1635 {
1636 if ( !Scl_LibertyReadPinFormula(p, pPin) ) // skip input pin
1637 continue;
1638 if (Scl_LibertyReadPinDirection(p, pPin) == 2) // skip internal pin
1639 continue;
1640 assert( Scl_LibertyReadPinDirection(p, pPin) == 1 );
1641 pName = Scl_LibertyReadString(p, pPin->Head);
1642 Vec_StrPutS_( vOut, pName );
1643 Vec_StrPutF_( vOut, Scl_LibertyReadPinCap( p, pPin, "max_capacitance" ) );
1644 Vec_StrPutF_( vOut, Scl_LibertyReadPinCap( p, pPin, "max_transition" ) );
1645 Vec_StrPutI_( vOut, Vec_PtrSize(vNameIns) );
1646 pFormula = Scl_LibertyReadPinFormula(p, pPin);
1647 Vec_StrPutS_( vOut, pFormula );
1648 // write truth table
1649 vTruth = Mio_ParseFormulaTruth( pFormula, (char **)Vec_PtrArray(vNameIns), Vec_PtrSize(vNameIns) );
1650 if ( vTruth == NULL )
1651 return NULL;
1652 for ( i = 0; i < Abc_Truth6WordNum(Vec_PtrSize(vNameIns)); i++ )
1653 Vec_StrPutW_( vOut, Vec_WrdEntry(vTruth, i) );
1654 Vec_WrdFree( vTruth );
1655 Vec_StrPut_( vOut );
1656 Vec_StrPut_( vOut );
1657
1658 // write the delay tables
1659 if ( fUseFirstTable )
1660 {
1661 Vec_PtrForEachEntry( char *, vNameIns, pName, i )
1662 {
1663 pTiming = Scl_LibertyReadPinTiming( p, pPin, pName );
1664 Vec_StrPutS_( vOut, pName );
1665 Vec_StrPutI_( vOut, (int)(pTiming != NULL) );
1666 if ( pTiming == NULL ) // output does not depend on input
1667 continue;
1668 Vec_StrPutI_( vOut, Scl_LibertyReadTimingSense(p, pTiming) );
1669 Vec_StrPut_( vOut );
1670 Vec_StrPut_( vOut );
1671 // some cells only have 'rise' or 'fall' but not both - here we work around this
1672 if ( !Scl_LibertyReadTable( p, vOut, pTiming, "cell_rise", vTemples ) )
1673 if ( !Scl_LibertyReadTable( p, vOut, pTiming, "cell_fall", vTemples ) )
1674 { printf( "Table cannot be found\n" ); return NULL; }
1675 if ( !Scl_LibertyReadTable( p, vOut, pTiming, "cell_fall", vTemples ) )
1676 if ( !Scl_LibertyReadTable( p, vOut, pTiming, "cell_rise", vTemples ) )
1677 { printf( "Table cannot be found\n" ); return NULL; }
1678 if ( !Scl_LibertyReadTable( p, vOut, pTiming, "rise_transition", vTemples ) )
1679 if ( !Scl_LibertyReadTable( p, vOut, pTiming, "fall_transition", vTemples ) )
1680 { printf( "Table cannot be found\n" ); return NULL; }
1681 if ( !Scl_LibertyReadTable( p, vOut, pTiming, "fall_transition", vTemples ) )
1682 if ( !Scl_LibertyReadTable( p, vOut, pTiming, "rise_transition", vTemples ) )
1683 { printf( "Table cannot be found\n" ); return NULL; }
1684 }
1685 continue;
1686 }
1687
1688 // write the timing tables
1689 Vec_PtrForEachEntry( char *, vNameIns, pName, i )
1690 {
1691 Vec_Ptr_t * vTables[4];
1692 Vec_Ptr_t * vTimings;
1693 vTimings = Scl_LibertyReadPinTimingAll( p, pPin, pName );
1694 Vec_StrPutS_( vOut, pName );
1695 Vec_StrPutI_( vOut, (int)(Vec_PtrSize(vTimings) != 0) );
1696 if ( Vec_PtrSize(vTimings) == 0 ) // output does not depend on input
1697 {
1698 Vec_PtrFree( vTimings );
1699 continue;
1700 }
1701 Vec_StrPutI_( vOut, Scl_LibertyReadTimingSense(p, (Scl_Item_t *)Vec_PtrEntry(vTimings, 0)) );
1702 Vec_StrPut_( vOut );
1703 Vec_StrPut_( vOut );
1704 // collect the timing tables
1705 for ( k = 0; k < 4; k++ )
1706 vTables[k] = Vec_PtrAlloc( 16 );
1707 Vec_PtrForEachEntry( Scl_Item_t *, vTimings, pTiming, k )
1708 {
1709 // some cells only have 'rise' or 'fall' but not both - here we work around this
1710 if ( !Scl_LibertyScanTable( p, vTables[0], pTiming, "cell_rise", vTemples ) )
1711 if ( !Scl_LibertyScanTable( p, vTables[0], pTiming, "cell_fall", vTemples ) )
1712 { printf( "Table cannot be found\n" ); return NULL; }
1713 if ( !Scl_LibertyScanTable( p, vTables[1], pTiming, "cell_fall", vTemples ) )
1714 if ( !Scl_LibertyScanTable( p, vTables[1], pTiming, "cell_rise", vTemples ) )
1715 { printf( "Table cannot be found\n" ); return NULL; }
1716 if ( !Scl_LibertyScanTable( p, vTables[2], pTiming, "rise_transition", vTemples ) )
1717 if ( !Scl_LibertyScanTable( p, vTables[2], pTiming, "fall_transition", vTemples ) )
1718 { printf( "Table cannot be found\n" ); return NULL; }
1719 if ( !Scl_LibertyScanTable( p, vTables[3], pTiming, "fall_transition", vTemples ) )
1720 if ( !Scl_LibertyScanTable( p, vTables[3], pTiming, "rise_transition", vTemples ) )
1721 { printf( "Table cannot be found\n" ); return NULL; }
1722 }
1723 Vec_PtrFree( vTimings );
1724 // compute worse case of the tables
1725 for ( k = 0; k < 4; k++ )
1726 {
1727 Vec_Flt_t * vInd0, * vInd1, * vValues;
1728 if ( !Scl_LibertyComputeWorstCase( vTables[k], &vInd0, &vInd1, &vValues ) )
1729 { printf( "Table indexes have different values\n" ); return NULL; }
1730 Vec_VecFree( (Vec_Vec_t *)vTables[k] );
1731 Scl_LibertyDumpTables( vOut, vInd0, vInd1, vValues );
1732 Vec_FltFree( vInd0 );
1733 Vec_FltFree( vInd1 );
1734 Vec_FltFree( vValues );
1735 }
1736 }
1737 }
1738 Vec_StrPut_( vOut );
1739 Vec_PtrFreeFree( vNameIns );
1740 }
1741 // free templates
1742 if ( vTemples )
1743 {
1744 Vec_Flt_t * vArray;
1745 assert( Vec_PtrSize(vTemples) % 4 == 0 );
1746 Vec_PtrForEachEntry( Vec_Flt_t *, vTemples, vArray, i )
1747 {
1748 if ( vArray == NULL )
1749 continue;
1750 if ( i % 4 == 0 )
1751 ABC_FREE( vArray );
1752 else if ( i % 4 == 2 || i % 4 == 3 )
1753 Vec_FltFree( vArray );
1754 }
1755 Vec_PtrFree( vTemples );
1756 }
1757 if ( fVerbose )
1758 {
1759 printf( "Library \"%s\" from \"%s\" has %d cells ",
1760 Scl_LibertyReadString(p, Scl_LibertyRoot(p)->Head), p->pFileName, nCells );
1761 printf( "(%d skipped: %d seq; %d tri-state; %d no func; %d dont_use; %d with 2 outputs; %d with 3+ outputs). ",
1762 nSkipped[0]+nSkipped[1]+nSkipped[2]+nSkipped[3]+nSkipped[4]+nSkipped[5],
1763 nSkipped[0],nSkipped[1],nSkipped[2],nSkipped[3],nSkipped[5],nSkipped[4] );
1764 Abc_PrintTime( 1, "Time", Abc_Clock() - p->clkStart );
1765 }
1766 return vOut;
1767}
1768SC_Lib * Abc_SclReadLiberty( char * pFileName, int fVerbose, int fVeryVerbose, SC_DontUse dont_use, int fSkipMultiOuts )
1769{
1770 SC_Lib * pLib;
1771 Scl_Tree_t * p;
1772 Vec_Str_t * vStr;
1773 p = Scl_LibertyParse( pFileName, fVeryVerbose );
1774 if ( p == NULL )
1775 return NULL;
1776// Scl_LibertyParseDump( p, "temp_.lib" );
1777 // collect relevant data
1778 vStr = Scl_LibertyReadSclStr( p, fVerbose, fVeryVerbose, dont_use, fSkipMultiOuts );
1779 Scl_LibertyStop( p, fVeryVerbose );
1780 if ( vStr == NULL )
1781 return NULL;
1782 // construct SCL data-structure
1783 pLib = Abc_SclReadFromStr( vStr );
1784 if ( pLib == NULL )
1785 return NULL;
1786 pLib->pFileName = Abc_UtilStrsav( pFileName );
1787 Abc_SclLibNormalize( pLib );
1788 Vec_StrFree( vStr );
1789// printf( "Average slew = %.2f ps\n", Abc_SclComputeAverageSlew(pLib) );
1790 return pLib;
1791}
1792
1805{
1806 char * pFileName = "bwrc.lib";
1807 int fVerbose = 1;
1808 int fVeryVerbose = 0;
1809 Scl_Tree_t * p;
1810 Vec_Str_t * vStr;
1811// return;
1812 p = Scl_LibertyParse( pFileName, fVeryVerbose );
1813 if ( p == NULL )
1814 return;
1815// Scl_LibertyParseDump( p, "temp_.lib" );
1816 SC_DontUse dont_use = {0};
1817 vStr = Scl_LibertyReadSclStr( p, fVerbose, fVeryVerbose, dont_use, 0);
1818 Scl_LibertyStringDump( "test_scl.lib", vStr );
1819 Vec_StrFree( vStr );
1820 Scl_LibertyStop( p, fVerbose );
1821}
1822
1826
1827
1829
ABC_INT64_T abctime
Definition abc_global.h:332
#define ABC_PRT(a, t)
Definition abc_global.h:255
#define ABC_ALLOC(type, num)
Definition abc_global.h:264
#define ABC_REALLOC(type, obj, num)
Definition abc_global.h:268
#define ABC_CALLOC(type, num)
Definition abc_global.h:265
#define ABC_FREE(obj)
Definition abc_global.h:267
#define ABC_NAMESPACE_IMPL_START
#define ABC_NAMESPACE_IMPL_END
struct Vec_Str_t_ Vec_Str_t
Definition bblif.c:46
Cube * p
Definition exorList.c:222
ABC_NAMESPACE_IMPL_START int ZEXPORT gzclose(gzFile file)
Definition gzclose.c:18
gzFile ZEXPORT gzopen(const char *path, const char *mode)
Definition gzlib.c:198
int ZEXPORT gzread(gzFile file, voidp buf, unsigned len)
Definition gzread.c:357
unsigned __int64 word
DECLARATIONS ///.
Definition kitPerm.c:36
Vec_Wrd_t * Mio_ParseFormulaTruth(char *pFormInit, char **ppVarNames, int nVars)
Definition mioParse.c:396
@ sc_ts_Neg
Definition sclLib.h:58
@ sc_ts_Non
Definition sclLib.h:59
@ sc_ts_Pos
Definition sclLib.h:57
struct SC_DontUse_ SC_DontUse
Definition sclLib.h:62
struct SC_Lib_ SC_Lib
Definition sclLib.h:128
SC_Lib * Abc_SclReadFromStr(Vec_Str_t *vOut)
Definition sclLibScl.c:403
void Abc_SclLibNormalize(SC_Lib *p)
Definition sclLibUtil.c:750
#define ABC_SCL_CUR_VERSION
INCLUDES ///.
Definition sclLib.h:43
char * Scl_LibertyReadDefaultWireLoad(Scl_Tree_t *p)
Definition sclLiberty.c:894
void Scl_LibertyReadLoadUnit(Scl_Tree_t *p, Vec_Str_t *vOut)
Definition sclLiberty.c:935
#define Scl_ItemForEachChildName(p, pItem, pChild, pName)
Definition sclLiberty.c:101
void Scl_LibertyReadWireLoad(Scl_Tree_t *p, Vec_Str_t *vOut)
Definition sclLiberty.c:956
Vec_Ptr_t * Scl_LibertyReadTemplates(Scl_Tree_t *p)
void Scl_LibertyFixFileName(char *pFileName)
Definition sclLiberty.c:534
Vec_Flt_t * Scl_LibertyReadFloatVec(char *pName)
int Scl_LibertyReadTable(Scl_Tree_t *p, Vec_Str_t *vOut, Scl_Item_t *pTiming, char *pName, Vec_Ptr_t *vTemples)
int Scl_LibertyReadCellIsThreeState(Scl_Tree_t *p, Scl_Item_t *pCell)
Definition sclLiberty.c:762
void Scl_LibertyStringDump(char *pFileName, Vec_Str_t *vStr)
Definition sclLiberty.c:611
Vec_Str_t * Scl_LibertyReadGenlibStr(Scl_Tree_t *p, int fVerbose, SC_DontUse dont_use)
Definition sclLiberty.c:791
Scl_Item_t * Scl_LibertyReadPinTiming(Scl_Tree_t *p, Scl_Item_t *pPinOut, char *pNameIn)
int Scl_LibertyParseDump(Scl_Tree_t *p, char *pFileName)
Definition sclLiberty.c:153
void Scl_LibertyDumpTables(Vec_Str_t *vOut, Vec_Flt_t *vInd1, Vec_Flt_t *vInd2, Vec_Flt_t *vValues)
int Scl_LibertyReadTimeUnit(Scl_Tree_t *p)
Definition sclLiberty.c:915
void Scl_LibertyPrintTemplates(Vec_Ptr_t *vRes)
long Scl_LibertyItemNum(Scl_Tree_t *p, Scl_Item_t *pRoot, char *pName)
Definition sclLiberty.c:391
#define Scl_ItemForEachChild(p, pItem, pChild)
Definition sclLiberty.c:99
char * Scl_LibertyReadString(Scl_Tree_t *p, Scl_Pair_t Pair)
Definition sclLiberty.c:374
long Scl_LibertyBuildItem(Scl_Tree_t *p, char **ppPos, char *pEnd)
Definition sclLiberty.c:411
int Scl_LibertyScanTable(Scl_Tree_t *p, Vec_Ptr_t *vOut, Scl_Item_t *pTiming, char *pName, Vec_Ptr_t *vTemples)
char * Scl_LibertyFileContents(char *pFileName, long *nContents)
Definition sclLiberty.c:580
struct Scl_Pair_t_ Scl_Pair_t
Definition sclLiberty.c:50
void Scl_LibertyReadWireLoadSelect(Scl_Tree_t *p, Vec_Str_t *vOut)
Definition sclLiberty.c:984
char * Scl_LibertyReadDefaultWireLoadSel(Scl_Tree_t *p)
Definition sclLiberty.c:901
float Scl_LibertyReadPinCap(Scl_Tree_t *p, Scl_Item_t *pPin, char *pName)
Scl_LibertyType_t
DECLARATIONS ///.
Definition sclLiberty.c:43
@ SCL_LIBERTY_LIST
Definition sclLiberty.c:47
@ SCL_LIBERTY_NONE
Definition sclLiberty.c:44
@ SCL_LIBERTY_EQUA
Definition sclLiberty.c:46
@ SCL_LIBERTY_PROC
Definition sclLiberty.c:45
int Scl_LibertyReadPinDirection(Scl_Tree_t *p, Scl_Item_t *pPin)
Vec_Ptr_t * Scl_LibertyReadPinTimingAll(Scl_Tree_t *p, Scl_Item_t *pPinOut, char *pNameIn)
long Scl_LibertyFileSize(char *pFileName)
Definition sclLiberty.c:541
char * Scl_LibertyReadPinFormula(Scl_Tree_t *p, Scl_Item_t *pPin)
Definition sclLiberty.c:755
void Scl_LibertyWipeOutComments(char *pBeg, char *pEnd)
Definition sclLiberty.c:208
long Scl_LibertyReadCellOutputNum(Scl_Tree_t *p, Scl_Item_t *pCell)
Definition sclLiberty.c:770
void Scl_LibertyStop(Scl_Tree_t *p, int fVerbose)
Definition sclLiberty.c:659
struct Scl_Item_t_ Scl_Item_t
Definition sclLiberty.c:57
int Scl_LibertyComputeWorstCase(Vec_Ptr_t *vTables, Vec_Flt_t **pvInd0, Vec_Flt_t **pvInd1, Vec_Flt_t **pvValues)
int Scl_LibertyReadDeriveStrength(Scl_Tree_t *p, Scl_Item_t *pCell)
Scl_Tree_t * Scl_LibertyStart(char *pFileName)
Definition sclLiberty.c:635
void Scl_LibertyParseDumpItem(FILE *pFile, Scl_Tree_t *p, Scl_Item_t *pItem, int nOffset)
FUNCTION DEFINITIONS ///.
Definition sclLiberty.c:119
char * Scl_LibertyReadCellArea(Scl_Tree_t *p, Scl_Item_t *pCell)
Definition sclLiberty.c:731
int Scl_LibertyReadCellIsDontUse(Scl_Tree_t *p, Scl_Item_t *pCell, SC_DontUse dont_use)
Definition sclLiberty.c:715
Scl_Tree_t * Scl_LibertyParse(char *pFileName, int fVerbose)
Definition sclLiberty.c:673
void Scl_LibertyTest()
long Scl_LibertyCountItems(char *pBeg, char *pEnd)
Definition sclLiberty.c:185
int Scl_LibertyReadTimingSense(Scl_Tree_t *p, Scl_Item_t *pPin)
struct Scl_Tree_t_ Scl_Tree_t
Definition sclLiberty.c:69
Vec_Str_t * Scl_LibertyReadSclStr(Scl_Tree_t *p, int fVerbose, int fVeryVerbose, SC_DontUse dont_use, int fSkipMultiOuts)
char * Scl_LibertyReadCellLeakage(Scl_Tree_t *p, Scl_Item_t *pCell)
Definition sclLiberty.c:738
int Scl_LibertyReadCellIsFlop(Scl_Tree_t *p, Scl_Item_t *pCell)
Definition sclLiberty.c:706
float Scl_LibertyReadDefaultMaxTrans(Scl_Tree_t *p)
Definition sclLiberty.c:908
SC_Lib * Abc_SclReadLiberty(char *pFileName, int fVerbose, int fVeryVerbose, SC_DontUse dont_use, int fSkipMultiOuts)
int size
Definition sclLib.h:65
char ** dont_use_list
Definition sclLib.h:66
char * pFileName
Definition sclLib.h:226
Scl_Pair_t Head
Definition sclLiberty.c:63
Scl_Pair_t Body
Definition sclLiberty.c:64
Scl_Pair_t Key
Definition sclLiberty.c:62
char * pFileName
Definition sclLiberty.c:72
char * pContents
Definition sclLiberty.c:73
long nItermAlloc
Definition sclLiberty.c:77
char * pError
Definition sclLiberty.c:79
Scl_Item_t * pItems
Definition sclLiberty.c:78
abctime clkStart
Definition sclLiberty.c:80
long nContents
Definition sclLiberty.c:74
Vec_Str_t * vBuffer
Definition sclLiberty.c:81
#define assert(ex)
Definition util_old.h:213
int strncmp()
char * memset()
int strlen()
char * strncpy()
int strcmp()
char * sprintf()
char * strtok()
VOID_HACK exit()
double atof()
#define Vec_FltForEachEntry(vVec, Entry, i)
MACRO DEFINITIONS ///.
Definition vecFlt.h:54
typedefABC_NAMESPACE_HEADER_START struct Vec_Flt_t_ Vec_Flt_t
INCLUDES ///.
Definition vecFlt.h:42
typedefABC_NAMESPACE_HEADER_START struct Vec_Ptr_t_ Vec_Ptr_t
INCLUDES ///.
Definition vecPtr.h:42
#define Vec_PtrForEachEntry(Type, vVec, pEntry, i)
MACRO DEFINITIONS ///.
Definition vecPtr.h:55
typedefABC_NAMESPACE_HEADER_START struct Vec_Vec_t_ Vec_Vec_t
INCLUDES ///.
Definition vecVec.h:42
typedefABC_NAMESPACE_HEADER_START struct Vec_Wrd_t_ Vec_Wrd_t
INCLUDES ///.
Definition vecWrd.h:42
#define SEEK_END
Definition zconf.h:392
voidp gzFile
Definition zlib.h:1173