blob: 13b18df5fd7569334f557a175e2647bf61bf1b77 [file] [log] [blame]
/**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( &ltime );
TimeStamp = asctime( localtime( &ltime ) );
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