summaryrefslogtreecommitdiffstats
path: root/src/map/scl/sclLiberty.c
diff options
context:
space:
mode:
authorAlan Mishchenko <alanmi@berkeley.edu>2013-09-15 18:23:49 -0700
committerAlan Mishchenko <alanmi@berkeley.edu>2013-09-15 18:23:49 -0700
commitff5d3591d1e7d90199d7395cde9fc6d902ed4b41 (patch)
tree26a2307c387d50bcd1a01e007bfe370ca8a5a9e3 /src/map/scl/sclLiberty.c
parentd1fed2dd89bc0549655f8375832628b18b35edd9 (diff)
downloadabc-ff5d3591d1e7d90199d7395cde9fc6d902ed4b41.tar.gz
abc-ff5d3591d1e7d90199d7395cde9fc6d902ed4b41.tar.bz2
abc-ff5d3591d1e7d90199d7395cde9fc6d902ed4b41.zip
Infrastructure to support full Liberty format and unitification of library representations.
Diffstat (limited to 'src/map/scl/sclLiberty.c')
-rw-r--r--src/map/scl/sclLiberty.c1358
1 files changed, 1358 insertions, 0 deletions
diff --git a/src/map/scl/sclLiberty.c b/src/map/scl/sclLiberty.c
new file mode 100644
index 00000000..4b98f7ef
--- /dev/null
+++ b/src/map/scl/sclLiberty.c
@@ -0,0 +1,1358 @@
+/**CFile****************************************************************
+
+ FileName [sclLiberty.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Standard-cell library representation.]
+
+ Synopsis [Liberty parser.]
+
+ Author [Alan Mishchenko, Niklas Een]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - August 24, 2012.]
+
+ Revision [$Id: sclLiberty.c,v 1.0 2012/08/24 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "sclLib.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+#define ABC_MAX_LIB_STR_LEN 5000
+
+// entry types
+typedef enum {
+ SCL_LIBERTY_NONE = 0, // 0: unknown
+ SCL_LIBERTY_PROC, // 1: procedure : key(head){body}
+ SCL_LIBERTY_EQUA, // 2: equation : key:head;
+ SCL_LIBERTY_LIST // 3: list : key(head)
+} Scl_LibertyType_t;
+
+typedef struct Scl_Pair_t_ Scl_Pair_t;
+struct Scl_Pair_t_
+{
+ int Beg; // item beginning
+ int End; // item end
+};
+
+typedef struct Scl_Item_t_ Scl_Item_t;
+struct Scl_Item_t_
+{
+ int Type; // Scl_LibertyType_t
+ int iLine; // file line where the item's spec begins
+ Scl_Pair_t Key; // key part
+ Scl_Pair_t Head; // head part
+ Scl_Pair_t Body; // body part
+ int Next; // next item in the list
+ int Child; // first child item
+};
+
+typedef struct Scl_Tree_t_ Scl_Tree_t;
+struct Scl_Tree_t_
+{
+ char * pFileName; // input Liberty file name
+ char * pContents; // file contents
+ int nContents; // file size
+ int nLines; // line counter
+ int nItems; // number of items
+ int nItermAlloc; // number of items allocated
+ Scl_Item_t * pItems; // the items
+ char * pError; // the error string
+ abctime clkStart; // beginning time
+};
+
+static inline Scl_Item_t * Scl_LibertyRoot( Scl_Tree_t * p ) { return p->pItems; }
+static inline Scl_Item_t * Scl_LibertyItem( Scl_Tree_t * p, int v ) { assert( v < p->nItems ); return v < 0 ? NULL : p->pItems + v; }
+static inline int Scl_LibertyCompare( Scl_Tree_t * p, Scl_Pair_t Pair, char * pStr ) { return strncmp( p->pContents+Pair.Beg, pStr, Pair.End-Pair.Beg ) || ((int)strlen(pStr) != Pair.End-Pair.Beg); }
+static 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 ); }
+static inline void Scl_PrintSpace( FILE * pFile, int nOffset ) { int i; for ( i = 0; i < nOffset; i++ ) fputc(' ', pFile); }
+static inline int Scl_LibertyItemId( Scl_Tree_t * p, Scl_Item_t * pItem ) { return pItem - p->pItems; }
+
+#define Scl_ItemForEachChild( p, pItem, pChild ) \
+ for ( pChild = Scl_LibertyItem(p, pItem->Child); pChild; pChild = Scl_LibertyItem(p, pChild->Next) )
+#define Scl_ItemForEachChildName( p, pItem, pChild, pName ) \
+ for ( pChild = Scl_LibertyItem(p, pItem->Child); pChild; pChild = Scl_LibertyItem(p, pChild->Next) ) if ( Scl_LibertyCompare(p, pChild->Key, pName) ) {} else
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Prints parse tree in Liberty format.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Scl_LibertyParseDumpItem( FILE * pFile, Scl_Tree_t * p, Scl_Item_t * pItem, int nOffset )
+{
+ if ( pItem->Type == SCL_LIBERTY_PROC )
+ {
+ Scl_PrintSpace( pFile, nOffset );
+ Scl_PrintWord( pFile, p, pItem->Key );
+ fprintf( pFile, "(" );
+ Scl_PrintWord( pFile, p, pItem->Head );
+ fprintf( pFile, ") {\n" );
+ if ( Scl_LibertyItem(p, pItem->Child) )
+ Scl_LibertyParseDumpItem( pFile, p, Scl_LibertyItem(p, pItem->Child), nOffset + 2 );
+ Scl_PrintSpace( pFile, nOffset );
+ fprintf( pFile, "}\n" );
+ }
+ else if ( pItem->Type == SCL_LIBERTY_EQUA )
+ {
+ Scl_PrintSpace( pFile, nOffset );
+ Scl_PrintWord( pFile, p, pItem->Key );
+ fprintf( pFile, " : " );
+ Scl_PrintWord( pFile, p, pItem->Head );
+ fprintf( pFile, ";\n" );
+ }
+ else if ( pItem->Type == SCL_LIBERTY_LIST )
+ {
+ Scl_PrintSpace( pFile, nOffset );
+ Scl_PrintWord( pFile, p, pItem->Key );
+ fprintf( pFile, "(" );
+ Scl_PrintWord( pFile, p, pItem->Head );
+ fprintf( pFile, ");\n" );
+ }
+ else assert( 0 );
+ if ( Scl_LibertyItem(p, pItem->Next) )
+ Scl_LibertyParseDumpItem( pFile, p, Scl_LibertyItem(p, pItem->Next), nOffset );
+}
+int Scl_LibertyParseDump( Scl_Tree_t * p, char * pFileName )
+{
+ FILE * pFile;
+ if ( pFileName == NULL )
+ pFile = stdout;
+ else
+ {
+ pFile = fopen( pFileName, "w" );
+ if ( pFile == NULL )
+ {
+ printf( "Scl_LibertyParseDump(): The output file is unavailable (absent or open).\n" );
+ return 0;
+ }
+ }
+ Scl_LibertyParseDumpItem( pFile, p, Scl_LibertyRoot(p), 0 );
+ if ( pFile != stdout )
+ fclose( pFile );
+ return 1;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Gets the name to write.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Scl_LibertyCountItems( char * pBeg, char * pEnd )
+{
+ int Counter = 0;
+ for ( ; pBeg < pEnd; pBeg++ )
+ Counter += (*pBeg == '(' || *pBeg == ':');
+ return Counter;
+}
+// removes C-style comments
+void Scl_LibertyWipeOutComments( char * pBeg, char * pEnd )
+{
+ char * pCur, * pStart;
+ for ( pCur = pBeg; pCur < pEnd; pCur++ )
+ if ( pCur[0] == '/' && pCur[1] == '*' )
+ for ( pStart = pCur; pCur < pEnd; pCur++ )
+ if ( pCur[0] == '*' && pCur[1] == '/' )
+ {
+ for ( ; pStart < pCur + 2; pStart++ )
+ if ( *pStart != '\n' ) *pStart = ' ';
+ break;
+ }
+}
+static inline int Scl_LibertyCharIsSpace( char c )
+{
+ return c == ' ' || c == '\t' || c == '\r' || c == '\n' || c == '\\';
+}
+static inline int Scl_LibertySkipSpaces( Scl_Tree_t * p, char ** ppPos, char * pEnd, int fStopAtNewLine )
+{
+ char * pPos = *ppPos;
+ for ( ; pPos < pEnd; pPos++ )
+ {
+ if ( *pPos == '\n' )
+ {
+ p->nLines++;
+ if ( fStopAtNewLine )
+ break;
+ }
+ if ( !Scl_LibertyCharIsSpace(*pPos) )
+ break;
+ }
+ *ppPos = pPos;
+ return pPos == pEnd;
+}
+// skips entry delimited by " :;(){}" and returns 1 if reached the end
+static inline int Scl_LibertySkipEntry( char ** ppPos, char * pEnd )
+{
+ char * pPos = *ppPos;
+ if ( *pPos == '\"' )
+ {
+ for ( pPos++; pPos < pEnd; pPos++ )
+ if ( *pPos == '\"' )
+ {
+ pPos++;
+ break;
+ }
+ }
+ else
+ {
+ for ( ; pPos < pEnd; pPos++ )
+ if ( *pPos == ' ' || *pPos == '\r' || *pPos == '\n' || *pPos == '\t' ||
+ *pPos == ':' || *pPos == ';' ||
+ *pPos == '(' || *pPos == ')' ||
+ *pPos == '{' || *pPos == '}' )
+ break;
+ }
+ *ppPos = pPos;
+ return pPos == pEnd;
+}
+// finds the matching closing symbol
+static inline char * Scl_LibertyFindMatch( char * pPos, char * pEnd )
+{
+ int Counter = 0;
+ assert( *pPos == '(' || *pPos == '{' );
+ if ( *pPos == '(' )
+ {
+ for ( ; pPos < pEnd; pPos++ )
+ {
+ if ( *pPos == '(' )
+ Counter++;
+ if ( *pPos == ')' )
+ Counter--;
+ if ( Counter == 0 )
+ break;
+ }
+ }
+ else
+ {
+ for ( ; pPos < pEnd; pPos++ )
+ {
+ if ( *pPos == '{' )
+ Counter++;
+ if ( *pPos == '}' )
+ Counter--;
+ if ( Counter == 0 )
+ break;
+ }
+ }
+ assert( *pPos == ')' || *pPos == '}' );
+ return pPos;
+}
+// trims spaces around the head
+static inline Scl_Pair_t Scl_LibertyUpdateHead( Scl_Tree_t * p, Scl_Pair_t Head )
+{
+ Scl_Pair_t Res;
+ char * pBeg = p->pContents + Head.Beg;
+ char * pEnd = p->pContents + Head.End;
+ char * pFirstNonSpace = NULL;
+ char * pLastNonSpace = NULL;
+ char * pChar;
+ for ( pChar = pBeg; pChar < pEnd; pChar++ )
+ {
+ if ( *pChar == '\n' )
+ p->nLines++;
+ if ( Scl_LibertyCharIsSpace(*pChar) )
+ continue;
+ pLastNonSpace = pChar;
+ if ( pFirstNonSpace == NULL )
+ pFirstNonSpace = pChar;
+ }
+ if ( pFirstNonSpace == NULL || pLastNonSpace == NULL )
+ return Head;
+ assert( pFirstNonSpace && pLastNonSpace );
+ Res.Beg = pFirstNonSpace - p->pContents;
+ Res.End = pLastNonSpace - p->pContents + 1;
+ return Res;
+}
+// returns new item
+static inline Scl_Item_t * Scl_LibertyNewItem( Scl_Tree_t * p, int Type )
+{
+ p->pItems[p->nItems].iLine = p->nLines;
+ p->pItems[p->nItems].Type = Type;
+ p->pItems[p->nItems].Child = -1;
+ p->pItems[p->nItems].Next = -1;
+ return p->pItems + p->nItems++;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Gets the name to write.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char * Scl_LibertyReadString( Scl_Tree_t * p, Scl_Pair_t Pair )
+{
+ static char Buffer[ABC_MAX_LIB_STR_LEN];
+ assert( Pair.End-Pair.Beg < ABC_MAX_LIB_STR_LEN );
+ strncpy( Buffer, p->pContents+Pair.Beg, Pair.End-Pair.Beg );
+ if ( Pair.Beg < Pair.End && Buffer[0] == '\"' )
+ {
+ assert( Buffer[Pair.End-Pair.Beg-1] == '\"' );
+ Buffer[Pair.End-Pair.Beg-1] = 0;
+ return Buffer + 1;
+ }
+ Buffer[Pair.End-Pair.Beg] = 0;
+ return Buffer;
+}
+int Scl_LibertyItemNum( Scl_Tree_t * p, Scl_Item_t * pRoot, char * pName )
+{
+ Scl_Item_t * pItem;
+ int Counter = 0;
+ Scl_ItemForEachChildName( p, pRoot, pItem, pName )
+ Counter++;
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns free item.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Scl_LibertyBuildItem( Scl_Tree_t * p, char ** ppPos, char * pEnd )
+{
+ Scl_Item_t * pItem;
+ Scl_Pair_t Key, Head, Body;
+ char * pNext, * pStop;
+ Key.End = 0;
+ if ( Scl_LibertySkipSpaces( p, ppPos, pEnd, 0 ) )
+ return -2;
+ Key.Beg = *ppPos - p->pContents;
+ if ( Scl_LibertySkipEntry( ppPos, pEnd ) )
+ goto exit;
+ Key.End = *ppPos - p->pContents;
+ if ( Scl_LibertySkipSpaces( p, ppPos, pEnd, 0 ) )
+ goto exit;
+ pNext = *ppPos;
+ if ( *pNext == ':' )
+ {
+ *ppPos = pNext + 1;
+ if ( Scl_LibertySkipSpaces( p, ppPos, pEnd, 0 ) )
+ goto exit;
+ Head.Beg = *ppPos - p->pContents;
+ if ( Scl_LibertySkipEntry( ppPos, pEnd ) )
+ goto exit;
+ Head.End = *ppPos - p->pContents;
+ if ( Scl_LibertySkipSpaces( p, ppPos, pEnd, 1 ) )
+ goto exit;
+ pNext = *ppPos;
+ if ( *pNext != ';' && *pNext != '\n' )
+ goto exit;
+ *ppPos = pNext + 1;
+ // end of equation
+ pItem = Scl_LibertyNewItem( p, SCL_LIBERTY_EQUA );
+ pItem->Key = Key;
+ pItem->Head = Scl_LibertyUpdateHead( p, Head );
+ pItem->Next = Scl_LibertyBuildItem( p, ppPos, pEnd );
+ if ( pItem->Next == -1 )
+ goto exit;
+ return Scl_LibertyItemId( p, pItem );
+ }
+ if ( *pNext == '(' )
+ {
+ pStop = Scl_LibertyFindMatch( pNext, pEnd );
+ Head.Beg = pNext - p->pContents + 1;
+ Head.End = pStop - p->pContents;
+ *ppPos = pStop + 1;
+ if ( Scl_LibertySkipSpaces( p, ppPos, pEnd, 0 ) )
+ {
+ // end of list
+ pItem = Scl_LibertyNewItem( p, SCL_LIBERTY_LIST );
+ pItem->Key = Key;
+ pItem->Head = Scl_LibertyUpdateHead( p, Head );
+ return Scl_LibertyItemId( p, pItem );
+ }
+ pNext = *ppPos;
+ if ( *pNext == '{' ) // beginning of body
+ {
+ pStop = Scl_LibertyFindMatch( pNext, pEnd );
+ Body.Beg = pNext - p->pContents + 1;
+ Body.End = pStop - p->pContents;
+ // end of body
+ pItem = Scl_LibertyNewItem( p, SCL_LIBERTY_PROC );
+ pItem->Key = Key;
+ pItem->Head = Scl_LibertyUpdateHead( p, Head );
+ pItem->Body = Body;
+ *ppPos = pNext + 1;
+ pItem->Child = Scl_LibertyBuildItem( p, ppPos, pStop );
+ if ( pItem->Child == -1 )
+ goto exit;
+ *ppPos = pStop + 1;
+ pItem->Next = Scl_LibertyBuildItem( p, ppPos, pEnd );
+ if ( pItem->Next == -1 )
+ goto exit;
+ return Scl_LibertyItemId( p, pItem );
+ }
+ // end of list
+ if ( *pNext == ';' )
+ *ppPos = pNext + 1;
+ pItem = Scl_LibertyNewItem( p, SCL_LIBERTY_LIST );
+ pItem->Key = Key;
+ pItem->Head = Scl_LibertyUpdateHead( p, Head );
+ pItem->Next = Scl_LibertyBuildItem( p, ppPos, pEnd );
+ if ( pItem->Next == -1 )
+ goto exit;
+ return Scl_LibertyItemId( p, pItem );
+ }
+exit:
+ if ( p->pError == NULL )
+ {
+ p->pError = ABC_ALLOC( char, 1000 );
+ sprintf( p->pError, "File \"%s\". Line %6d. Failed to parse entry \"%s\".\n",
+ p->pFileName, p->nLines, Scl_LibertyReadString(p, Key) );
+ }
+ return -1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [File management.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Scl_LibertyFixFileName( char * pFileName )
+{
+ char * pHead;
+ for ( pHead = pFileName; *pHead; pHead++ )
+ if ( *pHead == '>' )
+ *pHead = '\\';
+}
+int Scl_LibertyFileSize( char * pFileName )
+{
+ FILE * pFile;
+ int nFileSize;
+ pFile = fopen( pFileName, "rb" );
+ if ( pFile == NULL )
+ {
+ printf( "Scl_LibertyFileSize(): The input file is unavailable (absent or open).\n" );
+ return 0;
+ }
+ fseek( pFile, 0, SEEK_END );
+ nFileSize = ftell( pFile );
+ fclose( pFile );
+ return nFileSize;
+}
+char * Scl_LibertyFileContents( char * pFileName, int nContents )
+{
+ FILE * pFile = fopen( pFileName, "rb" );
+ char * pContents = ABC_ALLOC( char, nContents+1 );
+ int RetValue = fread( pContents, nContents, 1, pFile );
+ fclose( pFile );
+ pContents[nContents] = 0;
+ return pContents;
+}
+void Scl_LibertyStringDump( char * pFileName, Vec_Str_t * vStr )
+{
+ FILE * pFile = fopen( pFileName, "wb" );
+ int RetValue;
+ if ( pFile == NULL )
+ {
+ printf( "Scl_LibertyStringDump(): The output file is unavailable.\n" );
+ return;
+ }
+ RetValue = fwrite( Vec_StrArray(vStr), 1, Vec_StrSize(vStr), pFile );
+ fclose( pFile );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Starts the parsing manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Scl_Tree_t * Scl_LibertyStart( char * pFileName )
+{
+ Scl_Tree_t * p;
+ int RetValue;
+ // read the file into the buffer
+ Scl_LibertyFixFileName( pFileName );
+ RetValue = Scl_LibertyFileSize( pFileName );
+ if ( RetValue == 0 )
+ return NULL;
+ // start the manager
+ p = ABC_ALLOC( Scl_Tree_t, 1 );
+ memset( p, 0, sizeof(Scl_Tree_t) );
+ p->clkStart = Abc_Clock();
+ p->nContents = RetValue;
+ p->pContents = Scl_LibertyFileContents( pFileName, p->nContents );
+ // other
+ p->pFileName = Abc_UtilStrsav( pFileName );
+ p->nItermAlloc = 10 + Scl_LibertyCountItems( p->pContents, p->pContents+p->nContents );
+ p->pItems = ABC_CALLOC( Scl_Item_t, p->nItermAlloc );
+ p->nItems = 0;
+ p->nLines = 1;
+ return p;
+}
+void Scl_LibertyStop( Scl_Tree_t * p, int fVerbose )
+{
+ if ( fVerbose )
+ {
+ printf( "Memory = %7.2f MB. ", 1.0 * (p->nContents + p->nItermAlloc * sizeof(Scl_Item_t))/(1<<20) );
+ ABC_PRT( "Time", Abc_Clock() - p->clkStart );
+ }
+ ABC_FREE( p->pFileName );
+ ABC_FREE( p->pContents );
+ ABC_FREE( p->pItems );
+ ABC_FREE( p->pError );
+ ABC_FREE( p );
+}
+Scl_Tree_t * Scl_LibertyParse( char * pFileName, int fVerbose )
+{
+ Scl_Tree_t * p;
+ char * pPos;
+ if ( (p = Scl_LibertyStart(pFileName)) == NULL )
+ return NULL;
+ pPos = p->pContents;
+ Scl_LibertyWipeOutComments( p->pContents, p->pContents+p->nContents );
+ if ( !Scl_LibertyBuildItem( p, &pPos, p->pContents + p->nContents ) == 0 )
+ {
+ if ( p->pError ) printf( "%s", p->pError );
+ printf( "Parsing failed. " );
+ Abc_PrintTime( 1, "Parsing time", Abc_Clock() - p->clkStart );
+ }
+ else if ( fVerbose )
+ {
+ printf( "Parsing finished successfully. " );
+ Abc_PrintTime( 1, "Parsing time", Abc_Clock() - p->clkStart );
+ }
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Fetching attributes.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Scl_LibertyReadCellIsFlop( Scl_Tree_t * p, Scl_Item_t * pCell )
+{
+ Scl_Item_t * pAttr;
+ Scl_ItemForEachChild( p, pCell, pAttr )
+ if ( !Scl_LibertyCompare(p, pAttr->Key, "ff") ||
+ !Scl_LibertyCompare(p, pAttr->Key, "latch") )
+ return 1;
+ return 0;
+}
+char * Scl_LibertyReadCellArea( Scl_Tree_t * p, Scl_Item_t * pCell )
+{
+ Scl_Item_t * pArea;
+ Scl_ItemForEachChildName( p, pCell, pArea, "area" )
+ return Scl_LibertyReadString(p, pArea->Head);
+ return 0;
+}
+char * Scl_LibertyReadPinFormula( Scl_Tree_t * p, Scl_Item_t * pPin )
+{
+ Scl_Item_t * pFunc;
+ Scl_ItemForEachChildName( p, pPin, pFunc, "function" )
+ return Scl_LibertyReadString(p, pFunc->Head);
+ return NULL;
+}
+int Scl_LibertyReadCellIsThreeState( Scl_Tree_t * p, Scl_Item_t * pCell )
+{
+ Scl_Item_t * pPin, * pItem;
+ Scl_ItemForEachChildName( p, pCell, pPin, "pin" )
+ Scl_ItemForEachChildName( p, pPin, pItem, "three_state" )
+ return 1;
+ return 0;
+}
+int Scl_LibertyReadCellOutputNum( Scl_Tree_t * p, Scl_Item_t * pCell )
+{
+ Scl_Item_t * pPin;
+ int Counter = 0;
+ Scl_ItemForEachChildName( p, pCell, pPin, "pin" )
+ if ( Scl_LibertyReadPinFormula(p, pPin) )
+ Counter++;
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Parses the standard cell library in Liberty format.]
+
+ Description [Writes the resulting file in Genlib format.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Str_t * Scl_LibertyReadGenlibStr( Scl_Tree_t * p, int fVerbose )
+{
+ Vec_Str_t * vStr;
+ Scl_Item_t * pCell, * pOutput, * pInput;
+ char * pFormula;
+ vStr = Vec_StrAlloc( 1000 );
+ Vec_StrPrintStr( vStr, "GATE _const0_ 0.000000 z=CONST0;\n" );
+ Vec_StrPrintStr( vStr, "GATE _const1_ 0.000000 z=CONST1;\n" );
+ Scl_ItemForEachChildName( p, Scl_LibertyRoot(p), pCell, "cell" )
+ {
+ if ( Scl_LibertyReadCellIsFlop(p, pCell) )
+ {
+ if ( fVerbose ) printf( "Scl_LibertyReadGenlib() skipped sequential cell \"%s\".\n", Scl_LibertyReadString(p, pCell->Head) );
+ continue;
+ }
+ if ( Scl_LibertyReadCellIsThreeState(p, pCell) )
+ {
+ if ( fVerbose ) printf( "Scl_LibertyReadGenlib() skipped three-state cell \"%s\".\n", Scl_LibertyReadString(p, pCell->Head) );
+ continue;
+ }
+ if ( Scl_LibertyReadCellOutputNum(p, pCell) == 0 )
+ {
+ if ( fVerbose ) printf( "Scl_LibertyReadGenlib() skipped cell \"%s\" without logic function.\n", Scl_LibertyReadString(p, pCell->Head) );
+ continue;
+ }
+ // iterate through output pins
+ Scl_ItemForEachChildName( p, pCell, pOutput, "pin" )
+ {
+ if ( (pFormula = Scl_LibertyReadPinFormula(p, pOutput)) )
+ continue;
+ if ( !strcmp(pFormula, "0") || !strcmp(pFormula, "1") )
+ {
+ if ( fVerbose ) printf( "Scl_LibertyReadGenlib() skipped cell \"%s\" with constant formula \"%s\".\n", Scl_LibertyReadString(p, pCell->Head), pFormula );
+ break;
+ }
+ Vec_StrPrintStr( vStr, "GATE " );
+ Vec_StrPrintStr( vStr, Scl_LibertyReadString(p, pCell->Head) );
+ Vec_StrPrintStr( vStr, " " );
+ Vec_StrPrintStr( vStr, Scl_LibertyReadCellArea(p, pCell) );
+ Vec_StrPrintStr( vStr, " " );
+ Vec_StrPrintStr( vStr, Scl_LibertyReadString(p, pOutput->Head) );
+ Vec_StrPrintStr( vStr, "=" );
+ Vec_StrPrintStr( vStr, pFormula );
+ Vec_StrPrintStr( vStr, ";\n" );
+ // iterate through input pins
+ Scl_ItemForEachChildName( p, pCell, pInput, "pin" )
+ {
+ if ( Scl_LibertyReadPinFormula(p, pInput) == NULL )
+ continue;
+ Vec_StrPrintStr( vStr, " PIN " );
+ Vec_StrPrintStr( vStr, Scl_LibertyReadString(p, pInput->Head) );
+ Vec_StrPrintStr( vStr, " UNKNOWN 1 999 1.00 0.00 1.00 0.00\n" );
+ }
+ }
+ }
+ Vec_StrPrintStr( vStr, "\n.end\n" );
+ Vec_StrPush( vStr, '\0' );
+// printf( "%s", Vec_StrArray(vStr) );
+ return vStr;
+}
+Vec_Str_t * Scl_LibertyParseGenlibStr( char * pFileName, int fVerbose )
+{
+ Scl_Tree_t * p;
+ Vec_Str_t * vStr;
+ p = Scl_LibertyParse( pFileName, fVerbose );
+ if ( p == NULL )
+ return NULL;
+// Scl_LibertyRead( p, "temp_.lib" );
+ vStr = Scl_LibertyReadGenlibStr( p, fVerbose );
+ Scl_LibertyStop( p, fVerbose );
+// Scl_LibertyStringDump( "test_genlib.lib", vStr );
+ return vStr;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Enabling debug output.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+//#define SCL_DEBUG
+#ifdef SCL_DEBUG
+static inline void Vec_StrPutI_( Vec_Str_t * vOut, int Val ) { printf( "%d ", Val ); Vec_StrPutI( vOut, Val ); }
+static inline void Vec_StrPutW_( Vec_Str_t * vOut, word Val ) { printf( "%lu ", Val ); Vec_StrPutW( vOut, Val ); }
+static inline void Vec_StrPutF_( Vec_Str_t * vOut, float Val ) { printf( "%f ", Val ); Vec_StrPutF( vOut, Val ); }
+static inline void Vec_StrPutS_( Vec_Str_t * vOut, char * Val ) { printf( "%s ", Val ); Vec_StrPutS( vOut, Val ); }
+static inline void Vec_StrPut_( Vec_Str_t * vOut ) { printf( "\n" ); }
+#else
+static inline void Vec_StrPutI_( Vec_Str_t * vOut, int Val ) { Vec_StrPutI( vOut, Val ); }
+static inline void Vec_StrPutW_( Vec_Str_t * vOut, word Val ) { Vec_StrPutW( vOut, Val ); }
+static inline void Vec_StrPutF_( Vec_Str_t * vOut, float Val ) { Vec_StrPutF( vOut, Val ); }
+static inline void Vec_StrPutS_( Vec_Str_t * vOut, char * Val ) { Vec_StrPutS( vOut, Val ); }
+static inline void Vec_StrPut_( Vec_Str_t * vOut ) { }
+#endif
+
+/**Function*************************************************************
+
+ Synopsis [Parsing Liberty into internal data representation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+char * Scl_LibertyReadDefaultWireLoad( Scl_Tree_t * p )
+{
+ Scl_Item_t * pItem;
+ Scl_ItemForEachChildName( p, Scl_LibertyRoot(p), pItem, "default_wire_load" )
+ return Scl_LibertyReadString(p, pItem->Head);
+ return "";
+}
+char * Scl_LibertyReadDefaultWireLoadSel( Scl_Tree_t * p )
+{
+ Scl_Item_t * pItem;
+ Scl_ItemForEachChildName( p, Scl_LibertyRoot(p), pItem, "default_wire_load_selection" )
+ return Scl_LibertyReadString(p, pItem->Head);
+ return "";
+}
+float Scl_LibertyReadDefaultMaxTrans( Scl_Tree_t * p )
+{
+ Scl_Item_t * pItem;
+ Scl_ItemForEachChildName( p, Scl_LibertyRoot(p), pItem, "default_max_transition" )
+ return atof(Scl_LibertyReadString(p, pItem->Head));
+ return 0;
+}
+int Scl_LibertyReadTimeUnit( Scl_Tree_t * p )
+{
+ Scl_Item_t * pItem;
+ Scl_ItemForEachChildName( p, Scl_LibertyRoot(p), pItem, "time_unit" )
+ {
+ char * pUnit = Scl_LibertyReadString(p, pItem->Head);
+ // 9=1ns, 10=100ps, 11=10ps, 12=1ps
+ if ( !strcmp(pUnit, "1ns") )
+ return 9;
+ if ( !strcmp(pUnit, "100ps") )
+ return 10;
+ if ( !strcmp(pUnit, "10ps") )
+ return 11;
+ if ( !strcmp(pUnit, "1ps") )
+ return 12;
+ break;
+ }
+ printf( "Libery parser cannot read \"time_unit\". Assuming time_unit : \"1ns\".\n" );
+ return 9;
+}
+void Scl_LibertyReadLoadUnit( Scl_Tree_t * p, Vec_Str_t * vOut )
+{
+ Scl_Item_t * pItem;
+ Scl_ItemForEachChildName( p, Scl_LibertyRoot(p), pItem, "capacitive_load_unit" )
+ {
+ // expecting (1.00,ff) or (1, pf) ... 12 or 15 for 'pf' or 'ff'
+ char * pHead = Scl_LibertyReadString(p, pItem->Head);
+ float First = atof(strtok(pHead, " \t\n\r\\\","));
+ char * pSecond = strtok(NULL, " \t\n\r\\\",");
+ Vec_StrPutF_( vOut, First );
+ if ( pSecond && !strcmp(pSecond, "pf") )
+ Vec_StrPutI_( vOut, 12 );
+ else if ( pSecond && !strcmp(pSecond, "ff") )
+ Vec_StrPutI_( vOut, 15 );
+ else break;
+ return;
+ }
+ printf( "Libery parser cannot read \"capacitive_load_unit\". Assuming capacitive_load_unit(1, pf).\n" );
+ Vec_StrPutF_( vOut, 1.0 );
+ Vec_StrPutI_( vOut, 12 );
+}
+void Scl_LibertyReadWireLoad( Scl_Tree_t * p, Vec_Str_t * vOut )
+{
+ Scl_Item_t * pItem, * pChild;
+ Vec_StrPutI_( vOut, Scl_LibertyItemNum(p, Scl_LibertyRoot(p), "wire_load") );
+ Vec_StrPut_( vOut );
+ Scl_ItemForEachChildName( p, Scl_LibertyRoot(p), pItem, "wire_load" )
+ {
+ Vec_StrPutS_( vOut, Scl_LibertyReadString(p, pItem->Head) );
+ Scl_ItemForEachChildName( p, pItem, pChild, "resistance" )
+ Vec_StrPutF_( vOut, atof(Scl_LibertyReadString(p, pChild->Head)) );
+ Scl_ItemForEachChildName( p, pItem, pChild, "capacitance" )
+ Vec_StrPutF_( vOut, atof(Scl_LibertyReadString(p, pChild->Head)) );
+ Vec_StrPut_( vOut );
+ Vec_StrPutI_( vOut, Scl_LibertyItemNum(p, pItem, "fanout_length") );
+ Vec_StrPut_( vOut );
+ Scl_ItemForEachChildName( p, pItem, pChild, "fanout_length" )
+ {
+ char * pHead = Scl_LibertyReadString(p, pChild->Head);
+ int First = atoi( strtok(pHead, " ,") );
+ float Second = atof( strtok(NULL, " ") );
+ Vec_StrPutI_( vOut, First );
+ Vec_StrPutF_( vOut, Second );
+ Vec_StrPut_( vOut );
+ }
+ Vec_StrPut_( vOut );
+ }
+ Vec_StrPut_( vOut );
+}
+void Scl_LibertyReadWireLoadSelect( Scl_Tree_t * p, Vec_Str_t * vOut )
+{
+ Scl_Item_t * pItem, * pChild;
+ Vec_StrPutI_( vOut, Scl_LibertyItemNum(p, Scl_LibertyRoot(p), "wire_load_selection") );
+ Vec_StrPut_( vOut );
+ Scl_ItemForEachChildName( p, Scl_LibertyRoot(p), pItem, "wire_load_selection" )
+ {
+ Vec_StrPutS_( vOut, Scl_LibertyReadString(p, pItem->Head) );
+ Vec_StrPut_( vOut );
+ Vec_StrPutI_( vOut, Scl_LibertyItemNum(p, pItem, "wire_load_from_area") );
+ Vec_StrPut_( vOut );
+ Scl_ItemForEachChildName( p, pItem, pChild, "wire_load_from_area" )
+ {
+ char * pHead = Scl_LibertyReadString(p, pChild->Head);
+ float First = atof( strtok(pHead, " ,") );
+ float Second = atof( strtok(NULL, " ,") );
+ char * pThird = strtok(NULL, " ");
+ Vec_StrPutF_( vOut, First );
+ Vec_StrPutF_( vOut, Second );
+ Vec_StrPutS_( vOut, pThird );
+ Vec_StrPut_( vOut );
+ }
+ Vec_StrPut_( vOut );
+ }
+ Vec_StrPut_( vOut );
+}
+int Scl_LibertyReadDeriveStrength( Scl_Tree_t * p, Scl_Item_t * pCell )
+{
+ Scl_Item_t * pItem;
+ Scl_ItemForEachChildName( p, pCell, pItem, "drive_strength" )
+ return atoi(Scl_LibertyReadString(p, pItem->Head));
+ return 0;
+}
+int Scl_LibertyReadPinDirection( Scl_Tree_t * p, Scl_Item_t * pPin )
+{
+ Scl_Item_t * pItem;
+ Scl_ItemForEachChildName( p, pPin, pItem, "direction" )
+ {
+ char * pToken = Scl_LibertyReadString(p, pItem->Head);
+ if ( !strcmp(pToken, "input") )
+ return 0;
+ if ( !strcmp(pToken, "output") )
+ return 1;
+ break;
+ }
+ return -1;
+}
+float Scl_LibertyReadPinCap( Scl_Tree_t * p, Scl_Item_t * pPin, char * pName )
+{
+ Scl_Item_t * pItem;
+ Scl_ItemForEachChildName( p, pPin, pItem, pName )
+ return atof(Scl_LibertyReadString(p, pItem->Head));
+ return 0;
+}
+Scl_Item_t * Scl_LibertyReadPinTiming( Scl_Tree_t * p, Scl_Item_t * pPinOut, char * pNameIn )
+{
+ Scl_Item_t * pTiming, * pPinIn;
+ Scl_ItemForEachChildName( p, pPinOut, pTiming, "timing" )
+ Scl_ItemForEachChildName( p, pTiming, pPinIn, "related_pin" )
+ if ( !strcmp(Scl_LibertyReadString(p, pPinIn->Head), pNameIn) )
+ return pTiming;
+ return NULL;
+}
+int Scl_LibertyReadTimingSense( Scl_Tree_t * p, Scl_Item_t * pPin )
+{
+ Scl_Item_t * pItem;
+ Scl_ItemForEachChildName( p, pPin, pItem, "timing_sense" )
+ {
+ char * pToken = Scl_LibertyReadString(p, pItem->Head);
+ if ( !strcmp(pToken, "positive_unate") )
+ return sc_ts_Pos;
+ if ( !strcmp(pToken, "negative_unate") )
+ return sc_ts_Neg;
+ if ( !strcmp(pToken, "non_unate") )
+ return sc_ts_Non;
+ break;
+ }
+ return sc_ts_Non;
+}
+
+Vec_Flt_t * Scl_LibertyReadFloatVec( char * pName )
+{
+ char * pToken;
+ Vec_Flt_t * vValues = Vec_FltAlloc( 100 );
+ for ( pToken = strtok(pName, " \t\n\r\\\","); pToken; pToken = strtok(NULL, " \t\n\r\\\",") )
+ Vec_FltPush( vValues, atof(pToken) );
+ return vValues;
+}
+void Scl_LibertyReadTable( Scl_Tree_t * p, Vec_Str_t * vOut, Scl_Item_t * pTiming, char * pName, Vec_Ptr_t * vTemples )
+{
+ Vec_Flt_t * vIndex1 = NULL;
+ Vec_Flt_t * vIndex2 = NULL;
+ Vec_Flt_t * vValues = NULL;
+ Vec_Flt_t * vInd1, * vInd2;
+ Scl_Item_t * pItem, * pTable = NULL;
+ char * pThis, * pTempl = NULL;
+ int iPlace, i;
+ float Entry;
+ // find the table
+ Scl_ItemForEachChildName( p, pTiming, pTable, pName )
+ break;
+ if ( pTable == NULL )
+ { printf( "Table cannot be found\n" ); return; }
+ // find the template
+ pTempl = Scl_LibertyReadString(p, pTable->Head);
+ if ( pTempl == NULL || pTempl[0] == 0 )
+ {
+ // read the numbers
+ Scl_ItemForEachChild( p, pTable, pItem )
+ {
+ if ( !Scl_LibertyCompare(p, pItem->Key, "index_1") )
+ assert(vIndex1 == NULL), vIndex1 = Scl_LibertyReadFloatVec( Scl_LibertyReadString(p, pItem->Head) );
+ else if ( !Scl_LibertyCompare(p, pItem->Key, "index_2") )
+ assert(vIndex2 == NULL), vIndex2 = Scl_LibertyReadFloatVec( Scl_LibertyReadString(p, pItem->Head) );
+ else if ( !Scl_LibertyCompare(p, pItem->Key, "values") )
+ assert(vValues == NULL), vValues = Scl_LibertyReadFloatVec( Scl_LibertyReadString(p, pItem->Head) );
+ }
+ if ( vIndex1 == NULL || vIndex2 == NULL || vValues == NULL )
+ { printf( "Incomplete table specification\n" ); return; }
+ // dump the table
+ vInd1 = vIndex1;
+ vInd2 = vIndex2;
+ // write entries
+ Vec_StrPutI_( vOut, Vec_FltSize(vInd1) );
+ Vec_FltForEachEntry( vInd1, Entry, i )
+ Vec_StrPutF_( vOut, Entry );
+ Vec_StrPut_( vOut );
+ // write entries
+ Vec_StrPutI_( vOut, Vec_FltSize(vInd2) );
+ Vec_FltForEachEntry( vInd2, Entry, i )
+ Vec_StrPutF_( vOut, Entry );
+ Vec_StrPut_( vOut );
+ Vec_StrPut_( vOut );
+ // write entries
+ assert( Vec_FltSize(vInd1) * Vec_FltSize(vInd2) == Vec_FltSize(vValues) );
+ Vec_FltForEachEntry( vValues, Entry, i )
+ {
+ Vec_StrPutF_( vOut, Entry );
+ if ( i % Vec_FltSize(vInd2) == Vec_FltSize(vInd2)-1 )
+ Vec_StrPut_( vOut );
+ }
+ }
+ else
+ {
+ // fetch the template
+ iPlace = -1;
+ Vec_PtrForEachEntry( char *, vTemples, pThis, i )
+ if ( i % 4 == 0 && !strcmp(pTempl, pThis) )
+ {
+ iPlace = i;
+ break;
+ }
+ if ( iPlace == -1 )
+ { printf( "Template cannot be found in the template library\n" ); return; }
+ // read the numbers
+ Scl_ItemForEachChild( p, pTable, pItem )
+ {
+ if ( !Scl_LibertyCompare(p, pItem->Key, "index_1") )
+ assert(vIndex1 == NULL), vIndex1 = Scl_LibertyReadFloatVec( Scl_LibertyReadString(p, pItem->Head) );
+ else if ( !Scl_LibertyCompare(p, pItem->Key, "index_2") )
+ assert(vIndex2 == NULL), vIndex2 = Scl_LibertyReadFloatVec( Scl_LibertyReadString(p, pItem->Head) );
+ else if ( !Scl_LibertyCompare(p, pItem->Key, "values") )
+ assert(vValues == NULL), vValues = Scl_LibertyReadFloatVec( Scl_LibertyReadString(p, pItem->Head) );
+ }
+ // check the template style
+ vInd1 = (Vec_Flt_t *)Vec_PtrEntry( vTemples, iPlace + 2 ); // slew
+ vInd2 = (Vec_Flt_t *)Vec_PtrEntry( vTemples, iPlace + 3 ); // load
+ if ( Vec_PtrEntry(vTemples, iPlace + 1) == NULL ) // normal order (vIndex1 is slew; vIndex2 is load)
+ {
+ assert( !vIndex1 || Vec_FltSize(vIndex1) == Vec_FltSize(vInd1) );
+ assert( !vIndex2 || Vec_FltSize(vIndex2) == Vec_FltSize(vInd2) );
+ vInd1 = vIndex1 ? vIndex1 : vInd1;
+ vInd2 = vIndex2 ? vIndex2 : vInd2;
+ // write entries
+ Vec_StrPutI_( vOut, Vec_FltSize(vInd1) );
+ Vec_FltForEachEntry( vInd1, Entry, i )
+ Vec_StrPutF_( vOut, Entry );
+ Vec_StrPut_( vOut );
+ // write entries
+ Vec_StrPutI_( vOut, Vec_FltSize(vInd2) );
+ Vec_FltForEachEntry( vInd2, Entry, i )
+ Vec_StrPutF_( vOut, Entry );
+ Vec_StrPut_( vOut );
+ Vec_StrPut_( vOut );
+ // write entries
+ assert( Vec_FltSize(vInd1) * Vec_FltSize(vInd2) == Vec_FltSize(vValues) );
+ Vec_FltForEachEntry( vValues, Entry, i )
+ {
+ Vec_StrPutF_( vOut, Entry );
+ if ( i % Vec_FltSize(vInd2) == Vec_FltSize(vInd2)-1 )
+ Vec_StrPut_( vOut );
+ }
+ }
+ else // reverse order (vIndex2 is slew; vIndex1 is load)
+ {
+ assert( !vIndex2 || Vec_FltSize(vIndex2) == Vec_FltSize(vInd1) );
+ assert( !vIndex1 || Vec_FltSize(vIndex1) == Vec_FltSize(vInd2) );
+ vInd1 = vIndex2 ? vIndex2 : vInd1;
+ vInd2 = vIndex1 ? vIndex1 : vInd2;
+ // write entries
+ Vec_StrPutI_( vOut, Vec_FltSize(vInd1) );
+ Vec_FltForEachEntry( vInd1, Entry, i )
+ Vec_StrPutF_( vOut, Entry );
+ Vec_StrPut_( vOut );
+ // write entries
+ Vec_StrPutI_( vOut, Vec_FltSize(vInd2) );
+ Vec_FltForEachEntry( vInd2, Entry, i )
+ Vec_StrPutF_( vOut, Entry );
+ Vec_StrPut_( vOut );
+ Vec_StrPut_( vOut );
+ // write entries -- transpose
+ assert( Vec_FltSize(vInd1) * Vec_FltSize(vInd2) == Vec_FltSize(vValues) );
+ Vec_FltForEachEntry( vValues, Entry, i )
+ {
+ int x = i % Vec_FltSize(vInd2);
+ int y = i / Vec_FltSize(vInd2);
+ Entry = Vec_FltEntry( vValues, x * Vec_FltSize(vInd1) + y );
+ Vec_StrPutF_( vOut, Entry );
+ if ( i % Vec_FltSize(vInd2) == Vec_FltSize(vInd2)-1 )
+ Vec_StrPut_( vOut );
+ }
+ }
+ }
+ Vec_StrPut_( vOut );
+ for ( i = 0; i < 3; i++ )
+ Vec_StrPutF_( vOut, 0 );
+ for ( i = 0; i < 4; i++ )
+ Vec_StrPutF_( vOut, 0 );
+ for ( i = 0; i < 6; i++ )
+ Vec_StrPutF_( vOut, 0 );
+ Vec_FltFreeP( &vIndex1 );
+ Vec_FltFreeP( &vIndex2 );
+ Vec_FltFreeP( &vValues );
+ Vec_StrPut_( vOut );
+ Vec_StrPut_( vOut );
+}
+void Scl_LibertyPrintTemplates( Vec_Ptr_t * vRes )
+{
+ Vec_Flt_t * vArray; int i;
+ assert( Vec_PtrSize(vRes) % 4 == 0 );
+ printf( "There are %d slew/load templates\n", Vec_PtrSize(vRes) % 4 );
+ Vec_PtrForEachEntry( Vec_Flt_t *, vRes, vArray, i )
+ {
+ if ( i % 4 == 0 )
+ printf( "%s\n", (char *)vArray );
+ else if ( i % 4 == 1 )
+ printf( "%d\n", (int)(vArray != NULL) );
+ else if ( i % 4 == 2 || i % 4 == 3 )
+ Vec_FltPrint( vArray );
+ if ( i % 4 == 3 )
+ printf( "\n" );
+ }
+}
+Vec_Ptr_t * Scl_LibertyReadTemplates( Scl_Tree_t * p )
+{
+ Vec_Ptr_t * vRes = NULL;
+ Vec_Flt_t * vIndex1, * vIndex2;
+ Scl_Item_t * pTempl, * pItem;
+ char * pVar1, * pVar2;
+ int fFlag0, fFlag1;
+ vRes = Vec_PtrAlloc( 100 );
+ Scl_ItemForEachChildName( p, Scl_LibertyRoot(p), pTempl, "lu_table_template" )
+ {
+ pVar1 = pVar2 = NULL;
+ vIndex1 = vIndex2 = NULL;
+ Scl_ItemForEachChild( p, pTempl, pItem )
+ {
+ if ( !Scl_LibertyCompare(p, pItem->Key, "index_1") )
+ assert(vIndex1 == NULL), vIndex1 = Scl_LibertyReadFloatVec( Scl_LibertyReadString(p, pItem->Head) );
+ else if ( !Scl_LibertyCompare(p, pItem->Key, "index_2") )
+ assert(vIndex2 == NULL), vIndex2 = Scl_LibertyReadFloatVec( Scl_LibertyReadString(p, pItem->Head) );
+ else if ( !Scl_LibertyCompare(p, pItem->Key, "variable_1") )
+ assert(pVar1 == NULL), pVar1 = Abc_UtilStrsav( Scl_LibertyReadString(p, pItem->Head) );
+ else if ( !Scl_LibertyCompare(p, pItem->Key, "variable_2") )
+ assert(pVar2 == NULL), pVar2 = Abc_UtilStrsav( Scl_LibertyReadString(p, pItem->Head) );
+ }
+ if ( pVar1 == NULL || pVar2 == NULL )
+ {
+ ABC_FREE( pVar1 );
+ ABC_FREE( pVar2 );
+ Vec_FltFreeP( &vIndex1 );
+ Vec_FltFreeP( &vIndex2 );
+ continue;
+ }
+ assert( pVar1 != NULL && pVar2 != NULL );
+ fFlag0 = (!strcmp(pVar1, "input_net_transition") && !strcmp(pVar2, "total_output_net_capacitance"));
+ fFlag1 = (!strcmp(pVar2, "input_net_transition") && !strcmp(pVar1, "total_output_net_capacitance"));
+ ABC_FREE( pVar1 );
+ ABC_FREE( pVar2 );
+ if ( !fFlag0 && !fFlag1 )
+ {
+ Vec_FltFreeP( &vIndex1 );
+ Vec_FltFreeP( &vIndex2 );
+ continue;
+ }
+ Vec_PtrPush( vRes, Abc_UtilStrsav( Scl_LibertyReadString(p, pTempl->Head) ) );
+ Vec_PtrPush( vRes, fFlag0 ? NULL : (void *)(ABC_PTRINT_T)1 );
+ Vec_PtrPush( vRes, fFlag0 ? vIndex1 : vIndex2 );
+ Vec_PtrPush( vRes, fFlag0 ? vIndex2 : vIndex1 );
+ }
+ if ( Vec_PtrSize(vRes) == 0 )
+ Abc_Print( 0, "Templates are not defined.\n" );
+ // print templates
+// printf( "Found %d templates\n", Vec_PtrSize(vRes)/4 );
+// Scl_LibertyPrintTemplates( vRes );
+ return vRes;
+}
+Vec_Str_t * Scl_LibertyReadSclStr( Scl_Tree_t * p, int fVerbose, int fVeryVerbose )
+{
+ Vec_Str_t * vOut;
+ Vec_Ptr_t * vNameIns, * vTemples = NULL;
+ Scl_Item_t * pCell, * pPin, * pTiming;
+ Vec_Wrd_t * vTruth;
+ char * pFormula, * pName;
+ int i, Counter, nOutputs, nCells;
+ int nSkipped[3] = {0};
+
+ // read delay-table templates
+ vTemples = Scl_LibertyReadTemplates( p );
+
+ // start the library
+ vOut = Vec_StrAlloc( 10000 );
+ Vec_StrPutI_( vOut, ABC_SCL_CUR_VERSION );
+
+ // top level information
+ Vec_StrPut_( vOut );
+ Vec_StrPutS_( vOut, Scl_LibertyReadString(p, Scl_LibertyRoot(p)->Head) );
+ Vec_StrPutS_( vOut, Scl_LibertyReadDefaultWireLoad(p) );
+ Vec_StrPutS_( vOut, Scl_LibertyReadDefaultWireLoadSel(p) );
+ Vec_StrPutF_( vOut, Scl_LibertyReadDefaultMaxTrans(p) );
+ Vec_StrPutI_( vOut, Scl_LibertyReadTimeUnit(p) );
+ Scl_LibertyReadLoadUnit( p, vOut );
+ Vec_StrPut_( vOut );
+ Vec_StrPut_( vOut );
+
+ // read wire loads
+ Scl_LibertyReadWireLoad( p, vOut );
+ Scl_LibertyReadWireLoadSelect( p, vOut );
+
+ // count cells
+ nCells = 0;
+ Scl_ItemForEachChildName( p, Scl_LibertyRoot(p), pCell, "cell" )
+ {
+ if ( Scl_LibertyReadCellIsFlop(p, pCell) )
+ {
+ if ( fVeryVerbose ) printf( "Scl_LibertyReadGenlib() skipped sequential cell \"%s\".\n", Scl_LibertyReadString(p, pCell->Head) );
+ nSkipped[0]++;
+ continue;
+ }
+ if ( Scl_LibertyReadCellIsThreeState(p, pCell) )
+ {
+ if ( fVeryVerbose ) printf( "Scl_LibertyReadGenlib() skipped three-state cell \"%s\".\n", Scl_LibertyReadString(p, pCell->Head) );
+ nSkipped[1]++;
+ continue;
+ }
+ if ( (Counter = Scl_LibertyReadCellOutputNum(p, pCell)) == 0 )
+ {
+ if ( fVeryVerbose ) printf( "Scl_LibertyReadGenlib() skipped cell \"%s\" without logic function.\n", Scl_LibertyReadString(p, pCell->Head) );
+ nSkipped[2]++;
+ continue;
+ }
+ nCells++;
+ }
+ // read cells
+ Vec_StrPutI_( vOut, nCells );
+ Vec_StrPut_( vOut );
+ Vec_StrPut_( vOut );
+ Scl_ItemForEachChildName( p, Scl_LibertyRoot(p), pCell, "cell" )
+ {
+ if ( Scl_LibertyReadCellIsFlop(p, pCell) )
+ continue;
+ if ( Scl_LibertyReadCellIsThreeState(p, pCell) )
+ continue;
+ if ( (Counter = Scl_LibertyReadCellOutputNum(p, pCell)) == 0 )
+ continue;
+ // top level information
+ Vec_StrPutS_( vOut, Scl_LibertyReadString(p, pCell->Head) );
+ Vec_StrPutF_( vOut, atof(Scl_LibertyReadCellArea(p, pCell)) );
+ Vec_StrPutI_( vOut, Scl_LibertyReadDeriveStrength(p, pCell) );
+ // pin count
+ nOutputs = Scl_LibertyReadCellOutputNum( p, pCell );
+ Vec_StrPutI_( vOut, Scl_LibertyItemNum(p, pCell, "pin") - nOutputs );
+ Vec_StrPutI_( vOut, nOutputs );
+ Vec_StrPut_( vOut );
+ Vec_StrPut_( vOut );
+
+ // input pins
+ vNameIns = Vec_PtrAlloc( 16 );
+ Scl_ItemForEachChildName( p, pCell, pPin, "pin" )
+ {
+ float CapOne, CapRise, CapFall;
+ if ( Scl_LibertyReadPinFormula(p, pPin) != NULL ) // skip output pin
+ continue;
+ assert( Scl_LibertyReadPinDirection(p, pPin) == 0 );
+ pName = Scl_LibertyReadString(p, pPin->Head);
+ Vec_PtrPush( vNameIns, Abc_UtilStrsav(pName) );
+ Vec_StrPutS_( vOut, pName );
+ CapOne = Scl_LibertyReadPinCap( p, pPin, "capacitance" );
+ CapRise = Scl_LibertyReadPinCap( p, pPin, "rise_capacitance" );
+ CapFall = Scl_LibertyReadPinCap( p, pPin, "fall_capacitance" );
+ if ( CapRise == 0 )
+ CapRise = CapOne;
+ if ( CapFall == 0 )
+ CapFall = CapOne;
+ Vec_StrPutF_( vOut, CapRise );
+ Vec_StrPutF_( vOut, CapFall );
+ Vec_StrPut_( vOut );
+ }
+ Vec_StrPut_( vOut );
+ // output pins
+ Scl_ItemForEachChildName( p, pCell, pPin, "pin" )
+ {
+ extern Vec_Wrd_t * Mio_ParseFormulaTruth( char * pFormInit, char ** ppVarNames, int nVars );
+ if ( !Scl_LibertyReadPinFormula(p, pPin) ) // skip input pin
+ continue;
+ assert( Scl_LibertyReadPinDirection(p, pPin) == 1 );
+ pName = Scl_LibertyReadString(p, pPin->Head);
+ Vec_StrPutS_( vOut, pName );
+ Vec_StrPutF_( vOut, Scl_LibertyReadPinCap( p, pPin, "max_capacitance" ) );
+ Vec_StrPutF_( vOut, Scl_LibertyReadPinCap( p, pPin, "max_transition" ) );
+ Vec_StrPutI_( vOut, Vec_PtrSize(vNameIns) );
+ pFormula = Scl_LibertyReadPinFormula(p, pPin);
+ Vec_StrPutS_( vOut, pFormula );
+ // write truth table
+ vTruth = Mio_ParseFormulaTruth( pFormula, (char **)Vec_PtrArray(vNameIns), Vec_PtrSize(vNameIns) );
+ for ( i = 0; i < Abc_Truth6WordNum(Vec_PtrSize(vNameIns)); i++ )
+ Vec_StrPutW_( vOut, Vec_WrdEntry(vTruth, i) );
+ Vec_WrdFree( vTruth );
+ Vec_StrPut_( vOut );
+ Vec_StrPut_( vOut );
+
+ // write the delay tables
+ Vec_PtrForEachEntry( char *, vNameIns, pName, i )
+ {
+ pTiming = Scl_LibertyReadPinTiming( p, pPin, pName );
+ Vec_StrPutS_( vOut, pName );
+ Vec_StrPutI_( vOut, (int)(pTiming != NULL) );
+ if ( pTiming == NULL ) // output does not depend on input
+ continue;
+ Vec_StrPutI_( vOut, Scl_LibertyReadTimingSense(p, pTiming) );
+ Vec_StrPut_( vOut );
+ Vec_StrPut_( vOut );
+ Scl_LibertyReadTable( p, vOut, pTiming, "cell_rise", vTemples );
+ Scl_LibertyReadTable( p, vOut, pTiming, "cell_fall", vTemples );
+ Scl_LibertyReadTable( p, vOut, pTiming, "rise_transition", vTemples );
+ Scl_LibertyReadTable( p, vOut, pTiming, "fall_transition", vTemples );
+ }
+ }
+ Vec_StrPut_( vOut );
+ Vec_PtrFreeFree( vNameIns );
+ }
+ // free templates
+ if ( vTemples )
+ {
+ Vec_Flt_t * vArray;
+ assert( Vec_PtrSize(vTemples) % 4 == 0 );
+ Vec_PtrForEachEntry( Vec_Flt_t *, vTemples, vArray, i )
+ if ( i % 4 == 0 )
+ ABC_FREE( vArray );
+ else if ( i % 4 == 2 || i % 4 == 3 )
+ Vec_FltFree( vArray );
+ Vec_PtrFree( vTemples );
+ }
+ if ( fVerbose )
+ {
+ printf( "Library \"%s\" from \"%s\" has %d cells ",
+ Scl_LibertyReadString(p, Scl_LibertyRoot(p)->Head), p->pFileName, nCells );
+ printf( "(%d skipped: %d seq; %d tri-state; %d no func). ",
+ nSkipped[0]+nSkipped[1]+nSkipped[2], nSkipped[0], nSkipped[1], nSkipped[2] );
+ Abc_PrintTime( 1, "Time", Abc_Clock() - p->clkStart );
+ }
+ return vOut;
+}
+SC_Lib * Abc_SclReadLiberty( char * pFileName, int fVerbose, int fVeryVerbose )
+{
+ SC_Lib * pLib;
+ Scl_Tree_t * p;
+ Vec_Str_t * vStr;
+ p = Scl_LibertyParse( pFileName, fVeryVerbose );
+ if ( p == NULL )
+ return NULL;
+// Scl_LibertyParseDump( p, "temp_.lib" );
+ // collect relevant data
+ vStr = Scl_LibertyReadSclStr( p, fVerbose, fVeryVerbose );
+ Scl_LibertyStop( p, fVeryVerbose );
+ // construct SCL data-structure
+ pLib = Abc_SclReadFromStr( vStr );
+ pLib->pFileName = Abc_UtilStrsav( pFileName );
+ Vec_StrFree( vStr );
+ return pLib;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Experiments with Liberty parsing.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Scl_LibertyTest()
+{
+ char * pFileName = "bwrc.lib";
+ int fVerbose = 1;
+ int fVeryVerbose = 0;
+ Scl_Tree_t * p;
+ Vec_Str_t * vStr;
+// return;
+ p = Scl_LibertyParse( pFileName, fVeryVerbose );
+ if ( p == NULL )
+ return;
+// Scl_LibertyParseDump( p, "temp_.lib" );
+ vStr = Scl_LibertyReadSclStr( p, fVerbose, fVeryVerbose );
+ Scl_LibertyStringDump( "test_scl.lib", vStr );
+ Vec_StrFree( vStr );
+ Scl_LibertyStop( p, fVerbose );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+