| /**CFile**************************************************************** |
| |
| FileHead [amapLiberty.c] |
| |
| SystemHead [ABC: Logic synthesis and verification system.] |
| |
| PackageHead [Technology mapper for standard cells.] |
| |
| Synopsis [Liberty parser.] |
| |
| Author [Alan Mishchenko] |
| |
| Affiliation [UC Berkeley] |
| |
| Date [Ver. 1.0. Started - June 20, 2005.] |
| |
| Revision [$Id: amapLiberty.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] |
| |
| ***********************************************************************/ |
| |
| #include "amapInt.h" |
| |
| ABC_NAMESPACE_IMPL_START |
| |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// DECLARATIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| #define ABC_MAX_LIB_STR_LEN 5000 |
| |
| // entry types |
| typedef enum { |
| AMAP_LIBERTY_NONE = 0, // 0: unknown |
| AMAP_LIBERTY_PROC, // 1: procedure : key(head){body} |
| AMAP_LIBERTY_EQUA, // 2: equation : key:head; |
| AMAP_LIBERTY_LIST // 3: list : key(head) |
| } Amap_LibertyType_t; |
| |
| typedef struct Amap_Pair_t_ Amap_Pair_t; |
| struct Amap_Pair_t_ |
| { |
| int Beg; // item beginning |
| int End; // item end |
| }; |
| |
| typedef struct Amap_Item_t_ Amap_Item_t; |
| struct Amap_Item_t_ |
| { |
| int Type; // Amap_LibertyType_t |
| int iLine; // file line where the item's spec begins |
| Amap_Pair_t Key; // key part |
| Amap_Pair_t Head; // head part |
| Amap_Pair_t Body; // body part |
| int Next; // next item in the list |
| int Child; // first child item |
| }; |
| |
| typedef struct Amap_Tree_t_ Amap_Tree_t; |
| struct Amap_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 |
| Amap_Item_t * pItems; // the items |
| char * pError; // the error string |
| }; |
| |
| static inline Amap_Item_t * Amap_LibertyRoot( Amap_Tree_t * p ) { return p->pItems; } |
| static inline Amap_Item_t * Amap_LibertyItem( Amap_Tree_t * p, int v ) { assert( v < p->nItems ); return v < 0 ? NULL : p->pItems + v; } |
| static inline int Amap_LibertyCompare( Amap_Tree_t * p, Amap_Pair_t Pair, char * pStr ) { return strncmp( p->pContents+Pair.Beg, pStr, Pair.End-Pair.Beg ); } |
| static inline void Amap_PrintWord( FILE * pFile, Amap_Tree_t * p, Amap_Pair_t Pair ) { char * pBeg = p->pContents+Pair.Beg, * pEnd = p->pContents+Pair.End; while ( pBeg < pEnd ) fputc( *pBeg++, pFile ); } |
| static inline void Amap_PrintSpace( FILE * pFile, int nOffset ) { int i; for ( i = 0; i < nOffset; i++ ) fputc(' ', pFile); } |
| static inline int Amap_LibertyItemId( Amap_Tree_t * p, Amap_Item_t * pItem ) { return pItem - p->pItems; } |
| |
| #define Amap_ItemForEachChild( p, pItem, pChild ) \ |
| for ( pChild = Amap_LibertyItem(p, pItem->Child); pChild; pChild = Amap_LibertyItem(p, pChild->Next) ) |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// FUNCTION DEFINITIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| /**Function************************************************************* |
| |
| Synopsis [Prints parse tree in Liberty format.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Amap_LibertyPrintLibertyItem( FILE * pFile, Amap_Tree_t * p, Amap_Item_t * pItem, int nOffset ) |
| { |
| if ( pItem->Type == AMAP_LIBERTY_PROC ) |
| { |
| Amap_PrintSpace( pFile, nOffset ); |
| Amap_PrintWord( pFile, p, pItem->Key ); |
| fprintf( pFile, "(" ); |
| Amap_PrintWord( pFile, p, pItem->Head ); |
| fprintf( pFile, ") {\n" ); |
| if ( Amap_LibertyItem(p, pItem->Child) ) |
| Amap_LibertyPrintLibertyItem( pFile, p, Amap_LibertyItem(p, pItem->Child), nOffset + 1 ); |
| Amap_PrintSpace( pFile, nOffset ); |
| fprintf( pFile, "}\n" ); |
| } |
| else if ( pItem->Type == AMAP_LIBERTY_EQUA ) |
| { |
| Amap_PrintSpace( pFile, nOffset ); |
| Amap_PrintWord( pFile, p, pItem->Key ); |
| fprintf( pFile, " : " ); |
| Amap_PrintWord( pFile, p, pItem->Head ); |
| fprintf( pFile, ";\n" ); |
| } |
| else if ( pItem->Type == AMAP_LIBERTY_LIST ) |
| { |
| Amap_PrintSpace( pFile, nOffset ); |
| Amap_PrintWord( pFile, p, pItem->Key ); |
| fprintf( pFile, "(" ); |
| Amap_PrintWord( pFile, p, pItem->Head ); |
| fprintf( pFile, ");\n" ); |
| } |
| else assert( 0 ); |
| if ( Amap_LibertyItem(p, pItem->Next) ) |
| Amap_LibertyPrintLibertyItem( pFile, p, Amap_LibertyItem(p, pItem->Next), nOffset ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Prints parse tree in Liberty format.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Amap_LibertyPrintLiberty( Amap_Tree_t * p, char * pFileName ) |
| { |
| FILE * pFile; |
| if ( pFileName == NULL ) |
| pFile = stdout; |
| else |
| { |
| pFile = fopen( pFileName, "w" ); |
| if ( pFile == NULL ) |
| { |
| printf( "Amap_LibertyPrintLiberty(): The output file is unavailable (absent or open).\n" ); |
| return 0; |
| } |
| } |
| Amap_LibertyPrintLibertyItem( pFile, p, Amap_LibertyRoot(p), 0 ); |
| if ( pFile != stdout ) |
| fclose( pFile ); |
| return 1; |
| } |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [Returns the time stamp.] |
| |
| Description [The file should be closed.] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| char * Amap_LibertyTimeStamp() |
| { |
| static char Buffer[100]; |
| char * TimeStamp; |
| time_t ltime; |
| // get the current time |
| time( <ime ); |
| TimeStamp = asctime( localtime( <ime ) ); |
| TimeStamp[ strlen(TimeStamp) - 1 ] = 0; |
| assert( strlen(TimeStamp) < 100 ); |
| strcpy( Buffer, TimeStamp ); |
| return Buffer; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Returns cell's function.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Amap_LibertyCellIsFlop( Amap_Tree_t * p, Amap_Item_t * pCell ) |
| { |
| Amap_Item_t * pAttr; |
| Amap_ItemForEachChild( p, pCell, pAttr ) |
| if ( !Amap_LibertyCompare(p, pAttr->Key, "ff") || |
| !Amap_LibertyCompare(p, pAttr->Key, "latch") ) |
| return 1; |
| return 0; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Returns pin's function.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Amap_Item_t * Amap_LibertyPinFunction( Amap_Tree_t * p, Amap_Item_t * pPin ) |
| { |
| Amap_Item_t * pFunc; |
| Amap_ItemForEachChild( p, pPin, pFunc ) |
| if ( !Amap_LibertyCompare(p, pFunc->Key, "function") ) |
| return pFunc; |
| return NULL; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Returns output pin(s).] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Amap_Item_t * Amap_LibertyCellOutput( Amap_Tree_t * p, Amap_Item_t * pCell ) |
| { |
| Amap_Item_t * pPin; |
| Amap_ItemForEachChild( p, pCell, pPin ) |
| { |
| if ( Amap_LibertyCompare(p, pPin->Key, "pin") ) |
| continue; |
| if ( Amap_LibertyPinFunction(p, pPin) ) |
| return pPin; |
| } |
| return NULL; |
| } |
| Vec_Ptr_t * Amap_LibertyCellOutputs( Amap_Tree_t * p, Amap_Item_t * pCell ) |
| { |
| Amap_Item_t * pPin; |
| Vec_Ptr_t * vOutPins; |
| vOutPins = Vec_PtrAlloc( 2 ); |
| Amap_ItemForEachChild( p, pCell, pPin ) |
| { |
| if ( Amap_LibertyCompare(p, pPin->Key, "pin") ) |
| continue; |
| if ( Amap_LibertyPinFunction(p, pPin) ) |
| Vec_PtrPush( vOutPins, pPin ); |
| } |
| return vOutPins; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Returns cell's area.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Amap_Item_t * Amap_LibertyCellArea( Amap_Tree_t * p, Amap_Item_t * pCell ) |
| { |
| Amap_Item_t * pArea; |
| Amap_ItemForEachChild( p, pCell, pArea ) |
| { |
| if ( Amap_LibertyCompare(p, pArea->Key, "area") ) |
| continue; |
| return pArea; |
| } |
| return NULL; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Count cell's output pins (pins with a logic function).] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Amap_LibertyCellCountOutputs( Amap_Tree_t * p, Amap_Item_t * pCell ) |
| { |
| Amap_Item_t * pPin; |
| int Counter = 0; |
| Amap_ItemForEachChild( p, pCell, pPin ) |
| { |
| if ( Amap_LibertyCompare(p, pPin->Key, "pin") ) |
| continue; |
| if ( Amap_LibertyPinFunction(p, pPin) ) |
| Counter++; |
| } |
| return Counter; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Gets the name to write.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| char * Amap_LibertyGetString( Amap_Tree_t * p, Amap_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 ); |
| Buffer[Pair.End-Pair.Beg] = 0; |
| return Buffer; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Gets the name to write.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| char * Amap_LibertyGetStringFormula( Amap_Tree_t * p, Amap_Pair_t Pair ) |
| { |
| static char Buffer[ABC_MAX_LIB_STR_LEN]; |
| assert( Pair.End-Pair.Beg-2 < ABC_MAX_LIB_STR_LEN ); |
| strncpy( Buffer, p->pContents+Pair.Beg+1, Pair.End-Pair.Beg-2 ); |
| Buffer[Pair.End-Pair.Beg-2] = 0; |
| return Buffer; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Prints parse tree in Genlib format.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Amap_LibertyPrintGenlib( Amap_Tree_t * p, char * pFileName, int fVerbose ) |
| { |
| FILE * pFile; |
| Vec_Ptr_t * vOutputs; |
| Amap_Item_t * pCell, * pArea, * pFunc, * pPin, * pOutput; |
| char * pForm; |
| int i, Counter; |
| if ( pFileName == NULL ) |
| pFile = stdout; |
| else |
| { |
| pFile = fopen( pFileName, "w" ); |
| if ( pFile == NULL ) |
| { |
| printf( "Amap_LibertyPrintGenlib(): The output file is unavailable (absent or open).\n" ); |
| return 0; |
| } |
| } |
| fprintf( pFile, "# This Genlib file was generated by ABC on %s\n", Amap_LibertyTimeStamp() ); |
| fprintf( pFile, "# The standard cell library \"%s\" is from Liberty file \"%s\"\n", Amap_LibertyGetString(p, Amap_LibertyRoot(p)->Head), p->pFileName ); |
| fprintf( pFile, "# (To find out more about Genlib format, google for \"sis_paper.ps\")\n" ); |
| |
| fprintf( pFile, "GATE " ); |
| fprintf( pFile, "%16s ", "_const0_" ); |
| fprintf( pFile, "%f ", 0.0 ); |
| fprintf( pFile, "%s=", "z" ); |
| fprintf( pFile, "%s;\n", "CONST0" ); |
| |
| fprintf( pFile, "GATE " ); |
| fprintf( pFile, "%16s ", "_const1_" ); |
| fprintf( pFile, "%f ", 0.0 ); |
| fprintf( pFile, "%s=", "z" ); |
| fprintf( pFile, "%s;\n", "CONST1" ); |
| |
| Amap_ItemForEachChild( p, Amap_LibertyRoot(p), pCell ) |
| { |
| /* |
| if ( strcmp(Amap_LibertyGetString(p, pCell->Head), "HA1SVTX1") == 0 ) |
| { |
| int s = 0; |
| } |
| */ |
| if ( Amap_LibertyCompare(p, pCell->Key, "cell") ) |
| continue; |
| if ( Amap_LibertyCellIsFlop(p, pCell) ) |
| { |
| if ( fVerbose ) |
| printf( "Amap_LibertyPrintGenlib() skipped sequential cell \"%s\".\n", Amap_LibertyGetString(p, pCell->Head) ); |
| continue; |
| } |
| Counter = Amap_LibertyCellCountOutputs( p, pCell ); |
| if ( Counter == 0 ) |
| { |
| if ( fVerbose ) |
| printf( "Amap_LibertyPrintGenlib() skipped cell \"%s\" without logic function.\n", Amap_LibertyGetString(p, pCell->Head) ); |
| continue; |
| } |
| /* |
| if ( Counter > 1 ) |
| { |
| if ( fVerbose ) |
| printf( "Amap_LibertyPrintGenlib() skipped multi-output cell \"%s\".\n", Amap_LibertyGetString(p, pCell->Head) ); |
| continue; |
| } |
| */ |
| pArea = Amap_LibertyCellArea( p, pCell ); |
| if ( pArea == NULL ) |
| { |
| if ( fVerbose ) |
| printf( "Amap_LibertyPrintGenlib() skipped cell \"%s\" with unspecified area.\n", Amap_LibertyGetString(p, pCell->Head) ); |
| continue; |
| } |
| // pOutput = Amap_LibertyCellOutput( p, pCell ); |
| vOutputs = Amap_LibertyCellOutputs( p, pCell ); |
| Vec_PtrForEachEntry( Amap_Item_t *, vOutputs, pOutput, i ) |
| { |
| pFunc = Amap_LibertyPinFunction( p, pOutput ); |
| pForm = Amap_LibertyGetStringFormula( p, pFunc->Head ); |
| if ( !strcmp(pForm, "0") || !strcmp(pForm, "1") ) |
| { |
| if ( fVerbose ) |
| printf( "Amap_LibertyPrintGenlib() skipped cell \"%s\" with constant formula \"%s\".\n", Amap_LibertyGetString(p, pCell->Head), pForm ); |
| continue; |
| } |
| fprintf( pFile, "GATE " ); |
| fprintf( pFile, "%16s ", Amap_LibertyGetString(p, pCell->Head) ); |
| fprintf( pFile, "%f ", atof(Amap_LibertyGetString(p, pArea->Head)) ); |
| fprintf( pFile, "%s=", Amap_LibertyGetString(p, pOutput->Head) ); |
| fprintf( pFile, "%s;\n", Amap_LibertyGetStringFormula(p, pFunc->Head) ); |
| Amap_ItemForEachChild( p, pCell, pPin ) |
| if ( Vec_PtrFind(vOutputs, pPin) == -1 && !Amap_LibertyCompare(p, pPin->Key, "pin") ) |
| fprintf( pFile, " PIN %13s UNKNOWN 1 999 1.00 0.00 1.00 0.00\n", Amap_LibertyGetString(p, pPin->Head) ); |
| } |
| Vec_PtrFree( vOutputs ); |
| } |
| if ( pFile != stdout ) |
| fclose( pFile ); |
| return 1; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Prints parse tree in Genlib format.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Vec_Str_t * Amap_LibertyPrintGenlibStr( Amap_Tree_t * p, int fVerbose ) |
| { |
| Vec_Str_t * vStr; |
| char Buffer[100]; |
| Vec_Ptr_t * vOutputs; |
| Amap_Item_t * pCell, * pArea, * pFunc, * pPin, * pOutput; |
| int i, Counter; |
| char * pForm; |
| |
| vStr = Vec_StrAlloc( 1000 ); |
| |
| Vec_StrPrintStr( vStr, "GATE _const0_ 0.000000 z=CONST0;\n" ); |
| Vec_StrPrintStr( vStr, "GATE _const1_ 0.000000 z=CONST1;\n" ); |
| Amap_ItemForEachChild( p, Amap_LibertyRoot(p), pCell ) |
| { |
| if ( Amap_LibertyCompare(p, pCell->Key, "cell") ) |
| continue; |
| if ( Amap_LibertyCellIsFlop(p, pCell) ) |
| { |
| if ( fVerbose ) |
| printf( "Amap_LibertyPrintGenlib() skipped sequential cell \"%s\".\n", Amap_LibertyGetString(p, pCell->Head) ); |
| continue; |
| } |
| Counter = Amap_LibertyCellCountOutputs( p, pCell ); |
| if ( Counter == 0 ) |
| { |
| if ( fVerbose ) |
| printf( "Amap_LibertyPrintGenlib() skipped cell \"%s\" without logic function.\n", Amap_LibertyGetString(p, pCell->Head) ); |
| continue; |
| } |
| pArea = Amap_LibertyCellArea( p, pCell ); |
| if ( pArea == NULL ) |
| { |
| if ( fVerbose ) |
| printf( "Amap_LibertyPrintGenlib() skipped cell \"%s\" with unspecified area.\n", Amap_LibertyGetString(p, pCell->Head) ); |
| continue; |
| } |
| vOutputs = Amap_LibertyCellOutputs( p, pCell ); |
| Vec_PtrForEachEntry( Amap_Item_t *, vOutputs, pOutput, i ) |
| { |
| pFunc = Amap_LibertyPinFunction( p, pOutput ); |
| pForm = Amap_LibertyGetStringFormula( p, pFunc->Head ); |
| if ( !strcmp(pForm, "0") || !strcmp(pForm, "1") ) |
| { |
| if ( fVerbose ) |
| printf( "Amap_LibertyPrintGenlib() skipped cell \"%s\" with constant formula \"%s\".\n", Amap_LibertyGetString(p, pCell->Head), pForm ); |
| continue; |
| } |
| /* |
| fprintf( pFile, "GATE " ); |
| fprintf( pFile, "%16s ", Amap_LibertyGetString(p, pCell->Head) ); |
| fprintf( pFile, "%f ", atof(Amap_LibertyGetString(p, pArea->Head)) ); |
| fprintf( pFile, "%s=", Amap_LibertyGetString(p, pOutput->Head) ); |
| fprintf( pFile, "%s;\n", Amap_LibertyGetStringFormula(p, pFunc->Head) ); |
| Amap_ItemForEachChild( p, pCell, pPin ) |
| if ( Vec_PtrFind(vOutputs, pPin) == -1 && !Amap_LibertyCompare(p, pPin->Key, "pin") ) |
| fprintf( pFile, " PIN %13s UNKNOWN 1 999 1.00 0.00 1.00 0.00\n", Amap_LibertyGetString(p, pPin->Head) ); |
| */ |
| Vec_StrPrintStr( vStr, "GATE " ); |
| Vec_StrPrintStr( vStr, Amap_LibertyGetString(p, pCell->Head) ); |
| Vec_StrPrintStr( vStr, " " ); |
| sprintf( Buffer, "%f", atof(Amap_LibertyGetString(p, pArea->Head)) ); |
| Vec_StrPrintStr( vStr, Buffer ); |
| Vec_StrPrintStr( vStr, " " ); |
| Vec_StrPrintStr( vStr, Amap_LibertyGetString(p, pOutput->Head) ); |
| Vec_StrPrintStr( vStr, "=" ); |
| Vec_StrPrintStr( vStr, Amap_LibertyGetStringFormula(p, pFunc->Head) ); |
| Vec_StrPrintStr( vStr, ";\n" ); |
| Amap_ItemForEachChild( p, pCell, pPin ) |
| if ( Vec_PtrFind(vOutputs, pPin) == -1 && !Amap_LibertyCompare(p, pPin->Key, "pin") ) |
| { |
| Vec_StrPrintStr( vStr, " PIN " ); |
| Vec_StrPrintStr( vStr, Amap_LibertyGetString(p, pPin->Head) ); |
| Vec_StrPrintStr( vStr, " UNKNOWN 1 999 1.00 0.00 1.00 0.00\n" ); |
| } |
| } |
| Vec_PtrFree( vOutputs ); |
| } |
| Vec_StrPrintStr( vStr, "\n.end\n" ); |
| Vec_StrPush( vStr, '\0' ); |
| // printf( "%s", Vec_StrArray(vStr) ); |
| return vStr; |
| } |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [Returns the file size.] |
| |
| Description [The file should be closed.] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Amap_LibertyFileSize( char * pFileName ) |
| { |
| FILE * pFile; |
| int nFileSize; |
| pFile = fopen( pFileName, "rb" ); |
| if ( pFile == NULL ) |
| { |
| printf( "Amap_LibertyFileSize(): The input file is unavailable (absent or open).\n" ); |
| return 0; |
| } |
| fseek( pFile, 0, SEEK_END ); |
| nFileSize = ftell( pFile ); |
| fclose( pFile ); |
| return nFileSize; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Amap_LibertyFixFileHead( char * pFileName ) |
| { |
| char * pHead; |
| for ( pHead = pFileName; *pHead; pHead++ ) |
| if ( *pHead == '>' ) |
| *pHead = '\\'; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Amap_LibertyCountItems( char * pBeg, char * pEnd ) |
| { |
| int Counter = 0; |
| for ( ; pBeg < pEnd; pBeg++ ) |
| Counter += (*pBeg == '(' || *pBeg == ':'); |
| return Counter; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Removes C-style comments.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Amap_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; |
| } |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Returns 1 if the character is space.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| static inline int Amap_LibertyCharIsSpace( char c ) |
| { |
| return c == ' ' || c == '\t' || c == '\r' || c == '\n' || c == '\\'; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Skips spaces.] |
| |
| Description [Returns 1 if reached the end.] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| static inline int Amap_LibertySkipSpaces( Amap_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 ( !Amap_LibertyCharIsSpace(*pPos) ) |
| break; |
| } |
| *ppPos = pPos; |
| return pPos == pEnd; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Skips entry delimited by " :;(){}" ] |
| |
| Description [Returns 1 if reached the end.] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| static inline int Amap_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; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Find the matching closing symbol.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| static inline char * Amap_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; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Find the matching closing symbol.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| static inline Amap_Pair_t Amap_LibertyUpdateHead( Amap_Tree_t * p, Amap_Pair_t Head ) |
| { |
| Amap_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 ( Amap_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; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Returns free item.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| static inline Amap_Item_t * Amap_LibertyNewItem( Amap_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 [Returns free item.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Amap_LibertyBuildItem( Amap_Tree_t * p, char ** ppPos, char * pEnd ) |
| { |
| Amap_Item_t * pItem; |
| Amap_Pair_t Key, Head, Body; |
| char * pNext, * pStop; |
| Key.End = 0; |
| if ( Amap_LibertySkipSpaces( p, ppPos, pEnd, 0 ) ) |
| return -2; |
| Key.Beg = *ppPos - p->pContents; |
| if ( Amap_LibertySkipEntry( ppPos, pEnd ) ) |
| goto exit; |
| Key.End = *ppPos - p->pContents; |
| if ( Amap_LibertySkipSpaces( p, ppPos, pEnd, 0 ) ) |
| goto exit; |
| pNext = *ppPos; |
| if ( *pNext == ':' ) |
| { |
| *ppPos = pNext + 1; |
| if ( Amap_LibertySkipSpaces( p, ppPos, pEnd, 0 ) ) |
| goto exit; |
| Head.Beg = *ppPos - p->pContents; |
| if ( Amap_LibertySkipEntry( ppPos, pEnd ) ) |
| goto exit; |
| Head.End = *ppPos - p->pContents; |
| if ( Amap_LibertySkipSpaces( p, ppPos, pEnd, 1 ) ) |
| goto exit; |
| pNext = *ppPos; |
| if ( *pNext != ';' && *pNext != '\n' ) |
| goto exit; |
| *ppPos = pNext + 1; |
| // end of equation |
| pItem = Amap_LibertyNewItem( p, AMAP_LIBERTY_EQUA ); |
| pItem->Key = Key; |
| pItem->Head = Amap_LibertyUpdateHead( p, Head ); |
| pItem->Next = Amap_LibertyBuildItem( p, ppPos, pEnd ); |
| if ( pItem->Next == -1 ) |
| goto exit; |
| return Amap_LibertyItemId( p, pItem ); |
| } |
| if ( *pNext == '(' ) |
| { |
| pStop = Amap_LibertyFindMatch( pNext, pEnd ); |
| Head.Beg = pNext - p->pContents + 1; |
| Head.End = pStop - p->pContents; |
| *ppPos = pStop + 1; |
| if ( Amap_LibertySkipSpaces( p, ppPos, pEnd, 0 ) ) |
| { |
| // end of list |
| pItem = Amap_LibertyNewItem( p, AMAP_LIBERTY_LIST ); |
| pItem->Key = Key; |
| pItem->Head = Amap_LibertyUpdateHead( p, Head ); |
| return Amap_LibertyItemId( p, pItem ); |
| } |
| pNext = *ppPos; |
| if ( *pNext == '{' ) // beginning of body |
| { |
| pStop = Amap_LibertyFindMatch( pNext, pEnd ); |
| Body.Beg = pNext - p->pContents + 1; |
| Body.End = pStop - p->pContents; |
| // end of body |
| pItem = Amap_LibertyNewItem( p, AMAP_LIBERTY_PROC ); |
| pItem->Key = Key; |
| pItem->Head = Amap_LibertyUpdateHead( p, Head ); |
| pItem->Body = Body; |
| *ppPos = pNext + 1; |
| pItem->Child = Amap_LibertyBuildItem( p, ppPos, pStop ); |
| if ( pItem->Child == -1 ) |
| goto exit; |
| *ppPos = pStop + 1; |
| pItem->Next = Amap_LibertyBuildItem( p, ppPos, pEnd ); |
| if ( pItem->Next == -1 ) |
| goto exit; |
| return Amap_LibertyItemId( p, pItem ); |
| } |
| // end of list |
| if ( *pNext == ';' ) |
| *ppPos = pNext + 1; |
| pItem = Amap_LibertyNewItem( p, AMAP_LIBERTY_LIST ); |
| pItem->Key = Key; |
| pItem->Head = Amap_LibertyUpdateHead( p, Head ); |
| pItem->Next = Amap_LibertyBuildItem( p, ppPos, pEnd ); |
| if ( pItem->Next == -1 ) |
| goto exit; |
| return Amap_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, Amap_LibertyGetString(p, Key) ); |
| } |
| return -1; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Starts the parsing manager.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Amap_Tree_t * Amap_LibertyStart( char * pFileName ) |
| { |
| FILE * pFile; |
| Amap_Tree_t * p; |
| int RetValue; |
| // start the manager |
| p = ABC_ALLOC( Amap_Tree_t, 1 ); |
| memset( p, 0, sizeof(Amap_Tree_t) ); |
| // read the file into the buffer |
| Amap_LibertyFixFileHead( pFileName ); |
| p->nContents = Amap_LibertyFileSize( pFileName ); |
| if ( p->nContents == 0 ) |
| { |
| ABC_FREE( p ); |
| return NULL; |
| } |
| pFile = fopen( pFileName, "rb" ); |
| p->pContents = ABC_ALLOC( char, p->nContents+1 ); |
| RetValue = fread( p->pContents, p->nContents, 1, pFile ); |
| fclose( pFile ); |
| p->pContents[p->nContents] = 0; |
| // other |
| p->pFileName = Abc_UtilStrsav( pFileName ); |
| p->nItermAlloc = 10 + Amap_LibertyCountItems( p->pContents, p->pContents+p->nContents ); |
| p->pItems = ABC_CALLOC( Amap_Item_t, p->nItermAlloc ); |
| p->nItems = 0; |
| p->nLines = 1; |
| return p; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Stops the parsing manager.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Amap_LibertyStop( Amap_Tree_t * p ) |
| { |
| ABC_FREE( p->pFileName ); |
| ABC_FREE( p->pContents ); |
| ABC_FREE( p->pItems ); |
| ABC_FREE( p->pError ); |
| ABC_FREE( p ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Parses the standard cell library in Liberty format.] |
| |
| Description [Writes the resulting file in Genlib format.] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Amap_LibertyParse( char * pFileName, int fVerbose ) |
| { |
| Amap_Tree_t * p; |
| char * pPos; |
| abctime clk = Abc_Clock(); |
| int RetValue; |
| p = Amap_LibertyStart( pFileName ); |
| if ( p == NULL ) |
| return 0; |
| pPos = p->pContents; |
| Amap_LibertyWipeOutComments( p->pContents, p->pContents+p->nContents ); |
| if ( Amap_LibertyBuildItem( p, &pPos, p->pContents + p->nContents ) == 0 ) |
| { |
| if ( fVerbose ) |
| printf( "Parsing finished successfully.\n" ); |
| // Amap_LibertyPrintLiberty( p, "temp_.lib" ); |
| Amap_LibertyPrintGenlib( p, Extra_FileNameGenericAppend(pFileName, ".genlib"), fVerbose ); |
| RetValue = 1; |
| } |
| else |
| { |
| if ( p->pError ) |
| printf( "%s", p->pError ); |
| if ( fVerbose ) |
| printf( "Parsing failed.\n" ); |
| RetValue = 0; |
| } |
| if ( fVerbose ) |
| { |
| printf( "Memory = %7.2f MB. ", 1.0*(p->nContents+p->nItermAlloc*sizeof(Amap_Item_t))/(1<<20) ); |
| ABC_PRT( "Time", Abc_Clock() - clk ); |
| } |
| Amap_LibertyStop( p ); |
| return RetValue; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Parses the standard cell library in Liberty format.] |
| |
| Description [Writes the resulting file in Genlib format.] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Vec_Str_t * Amap_LibertyParseStr( char * pFileName, int fVerbose ) |
| { |
| Amap_Tree_t * p; |
| Vec_Str_t * vStr = NULL; |
| char * pPos; |
| abctime clk = Abc_Clock(); |
| int RetValue; |
| p = Amap_LibertyStart( pFileName ); |
| if ( p == NULL ) |
| return 0; |
| pPos = p->pContents; |
| Amap_LibertyWipeOutComments( p->pContents, p->pContents+p->nContents ); |
| if ( Amap_LibertyBuildItem( p, &pPos, p->pContents + p->nContents ) == 0 ) |
| { |
| if ( fVerbose ) |
| printf( "Parsing finished successfully.\n" ); |
| // Amap_LibertyPrintLiberty( p, "temp_.lib" ); |
| vStr = Amap_LibertyPrintGenlibStr( p, fVerbose ); |
| RetValue = 1; |
| } |
| else |
| { |
| if ( p->pError ) |
| printf( "%s", p->pError ); |
| if ( fVerbose ) |
| printf( "Parsing failed.\n" ); |
| RetValue = 0; |
| } |
| if ( fVerbose ) |
| { |
| printf( "Memory = %7.2f MB. ", 1.0*(p->nContents+p->nItermAlloc*sizeof(Amap_Item_t))/(1<<20) ); |
| ABC_PRT( "Time", Abc_Clock() - clk ); |
| } |
| Amap_LibertyStop( p ); |
| return vStr; |
| } |
| |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// END OF FILE /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| |
| ABC_NAMESPACE_IMPL_END |
| |