Commit ff5d3591 by Alan Mishchenko

Infrastructure to support full Liberty format and unitification of library representations.

parent d1fed2dd
......@@ -2479,11 +2479,19 @@ SOURCE=.\src\map\scl\sclDnsize.c
# End Source File
# Begin Source File
SOURCE=.\src\map\scl\sclLib.c
SOURCE=.\src\map\scl\sclLib.h
# End Source File
# Begin Source File
SOURCE=.\src\map\scl\sclLib.h
SOURCE=.\src\map\scl\sclLiberty.c
# End Source File
# Begin Source File
SOURCE=.\src\map\scl\sclLibScl.c
# End Source File
# Begin Source File
SOURCE=.\src\map\scl\sclLibUtil.c
# End Source File
# Begin Source File
......
......@@ -990,6 +990,10 @@ void Abc_Init( Abc_Frame_t * pAbc )
if ( Sdm_ManCanRead() )
Sdm_ManRead();
{
// extern void Scl_LibertyTest();
// Scl_LibertyTest();
}
}
/**Function*************************************************************
......@@ -70,7 +70,7 @@ Abc_Ntk_t * Abc_NtkMap( Abc_Ntk_t * pNtk, double DelayTarget, double AreaMulti,
assert( Abc_NtkIsStrash(pNtk) );
// derive library from SCL
if ( Abc_FrameReadLibScl() )
Mio_SclDeriveGenlib( Abc_FrameReadLibScl(), Slew, Gain, nGatesMin );
Abc_SclDeriveGenlib( Abc_FrameReadLibScl(), Slew, Gain, nGatesMin );
// quit if there is no library
pLib = (Mio_Library_t *)Abc_FrameReadLibGen();
if ( pLib == NULL )
......
......@@ -220,7 +220,7 @@ int Mio_CommandReadLiberty( Abc_Frame_t * pAbc, int argc, char **argv )
if ( (pFile = Io_FileOpen( pFileName, "open_path", "r", 0 )) == NULL )
{
fprintf( pErr, "Cannot open input file \"%s\". ", pFileName );
if ( (pFileName = Extra_FileGetSimilarName( pFileName, ".genlib", ".lib", ".gen", ".g", NULL )) )
if ( (pFileName = Extra_FileGetSimilarName( pFileName, ".genlib", ".lib", ".scl", ".g", NULL )) )
fprintf( pErr, "Did you mean \"%s\"?", pFileName );
fprintf( pErr, "\n" );
return 1;
......@@ -338,7 +338,7 @@ int Mio_CommandReadGenlib( Abc_Frame_t * pAbc, int argc, char **argv )
if ( (pFile = Io_FileOpen( pFileName, "open_path", "r", 0 )) == NULL )
{
fprintf( pErr, "Cannot open input file \"%s\". ", pFileName );
if ( (pFileName = Extra_FileGetSimilarName( pFileName, ".genlib", ".lib", ".gen", ".g", NULL )) )
if ( (pFileName = Extra_FileGetSimilarName( pFileName, ".genlib", ".lib", ".scl", ".g", NULL )) )
fprintf( pErr, "Did you mean \"%s\"?", pFileName );
fprintf( pErr, "\n" );
return 1;
......
......@@ -82,7 +82,7 @@ static inline char * Mio_UtilStrsav( char * s ) { return s ? strcpy(ABC_A
/*=== mio.c =============================================================*/
extern void Mio_UpdateGenlib( Mio_Library_t * pLib );
extern int Mio_UpdateGenlib2( Vec_Str_t * vStr, Vec_Str_t * vStr2, char * pFileName, int fVerbose );
extern void Mio_SclDeriveGenlib( void * pScl, float Slew, float Gain, int nGatesMin );
extern void Abc_SclDeriveGenlib( void * pScl, float Slew, float Gain, int nGatesMin );
/*=== mioApi.c =============================================================*/
extern char * Mio_LibraryReadName ( Mio_Library_t * pLib );
extern int Mio_LibraryReadGateNum ( Mio_Library_t * pLib );
......
......@@ -399,6 +399,8 @@ Vec_Wrd_t * Mio_ParseFormulaTruth( char * pFormInit, char ** ppVarNames, int nVa
Vec_Wrd_t * vTruth;
// derive expression
vExpr = Mio_ParseFormula( pFormInit, ppVarNames, nVars );
if ( vExpr == NULL )
return NULL;
// convert it into a truth table
vTruth = Vec_WrdStart( Abc_Truth6WordNum(nVars) );
Exp_Truth( nVars, vExpr, Vec_WrdArray(vTruth) );
......
......@@ -2,7 +2,9 @@ SRC += src/map/scl/scl.c \
src/map/scl/sclBuffer.c \
src/map/scl/sclBufSize.c \
src/map/scl/sclDnsize.c \
src/map/scl/sclLib.c \
src/map/scl/sclLiberty.c \
src/map/scl/sclLibScl.c \
src/map/scl/sclLibUtil.c \
src/map/scl/sclLoad.c \
src/map/scl/sclSize.c \
src/map/scl/sclUpsize.c \
......
......@@ -28,6 +28,7 @@ ABC_NAMESPACE_IMPL_START
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
static int Scl_CommandReadLib ( Abc_Frame_t * pAbc, int argc, char **argv );
static int Scl_CommandRead ( Abc_Frame_t * pAbc, int argc, char **argv );
static int Scl_CommandWrite ( Abc_Frame_t * pAbc, int argc, char **argv );
static int Scl_CommandPrintScl( Abc_Frame_t * pAbc, int argc, char **argv );
......@@ -51,6 +52,29 @@ static int Scl_CommandPrintBuf( Abc_Frame_t * pAbc, int argc, char **argv );
/**Function*************************************************************
Synopsis [Updating library in the frameframe.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_SclLoad( SC_Lib * pLib, SC_Lib ** ppScl )
{
if ( *ppScl )
{
Abc_SclLibFree( *ppScl );
*ppScl = NULL;
}
assert( *ppScl == NULL );
if ( pLib )
*(SC_Lib **)ppScl = pLib;
}
/**Function*************************************************************
Synopsis []
Description []
......@@ -62,6 +86,7 @@ static int Scl_CommandPrintBuf( Abc_Frame_t * pAbc, int argc, char **argv );
***********************************************************************/
void Scl_Init( Abc_Frame_t * pAbc )
{
Cmd_CommandAdd( pAbc, "SCL mapping", "read_lib", Scl_CommandReadLib, 0 );
Cmd_CommandAdd( pAbc, "SCL mapping", "read_scl", Scl_CommandRead, 0 );
Cmd_CommandAdd( pAbc, "SCL mapping", "write_scl", Scl_CommandWrite, 0 );
Cmd_CommandAdd( pAbc, "SCL mapping", "print_scl", Scl_CommandPrintScl, 0 );
......@@ -97,20 +122,138 @@ void Scl_End( Abc_Frame_t * pAbc )
SeeAlso []
***********************************************************************/
int Scl_CommandRead( Abc_Frame_t * pAbc, int argc, char ** argv )
int Scl_CommandReadLib( Abc_Frame_t * pAbc, int argc, char ** argv )
{
char * pFileName;
FILE * pFile;
int c, fVerbose = 0;
SC_Lib * pLib;
int c, fDump = 0;
float Slew = 200;
float Gain = 100;
int nGatesMin = 4;
int fVerbose = 1;
int fVeryVerbose = 0;
Extra_UtilGetoptReset();
while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF )
while ( ( c = Extra_UtilGetopt( argc, argv, "SGMdvwh" ) ) != EOF )
{
switch ( c )
{
case 'S':
if ( globalUtilOptind >= argc )
{
Abc_Print( -1, "Command line switch \"-S\" should be followed by a floating point number.\n" );
goto usage;
}
Slew = (float)atof(argv[globalUtilOptind]);
globalUtilOptind++;
if ( Slew <= 0.0 )
goto usage;
break;
case 'G':
if ( globalUtilOptind >= argc )
{
Abc_Print( -1, "Command line switch \"-G\" should be followed by a floating point number.\n" );
goto usage;
}
Gain = (float)atof(argv[globalUtilOptind]);
globalUtilOptind++;
if ( Gain <= 0.0 )
goto usage;
break;
case 'M':
if ( globalUtilOptind >= argc )
{
Abc_Print( -1, "Command line switch \"-M\" should be followed by a positive integer.\n" );
goto usage;
}
nGatesMin = atoi(argv[globalUtilOptind]);
globalUtilOptind++;
if ( nGatesMin < 0 )
goto usage;
break;
case 'd':
fDump ^= 1;
break;
case 'v':
fVerbose ^= 1;
break;
case 'w':
fVeryVerbose ^= 1;
break;
case 'h':
goto usage;
default:
goto usage;
}
}
if ( argc != globalUtilOptind + 1 )
goto usage;
// get the input file name
pFileName = argv[globalUtilOptind];
if ( (pFile = fopen( pFileName, "rb" )) == NULL )
{
fprintf( pAbc->Err, "Cannot open input file \"%s\". \n", pFileName );
return 1;
}
fclose( pFile );
// read new library
pLib = Abc_SclReadLiberty( pFileName, fVerbose, fVeryVerbose );
if ( pLib == NULL )
{
fprintf( pAbc->Err, "Reading SCL library from file \"%s\" has failed. \n", pFileName );
return 1;
}
Abc_SclLoad( pLib, (SC_Lib **)&pAbc->pLibScl );
// dump the resulting library
if ( fDump && pAbc->pLibScl )
Abc_SclWriteLiberty( Extra_FileNameGenericAppend(pFileName, "_temp.lib"), (SC_Lib *)pAbc->pLibScl );
// extract genlib library
if ( pAbc->pLibScl )
Abc_SclDeriveGenlib( pAbc->pLibScl, Slew, Gain, nGatesMin );
return 0;
usage:
fprintf( pAbc->Err, "usage: read_lib [-SG float] [-M num] [-dvwh] <file>\n" );
fprintf( pAbc->Err, "\t reads Liberty library from file\n" );
fprintf( pAbc->Err, "\t-S float : the slew parameter used to generate the library [default = %.2f]\n", Slew );
fprintf( pAbc->Err, "\t-G float : the gain parameter used to generate the library [default = %.2f]\n", Gain );
fprintf( pAbc->Err, "\t-M num : skip gate classes whose size is less than this [default = %d]\n", nGatesMin );
fprintf( pAbc->Err, "\t-d : toggle dumping the parsed library into file \"*_temp.lib\" [default = %s]\n", fDump? "yes": "no" );
fprintf( pAbc->Err, "\t-v : toggle writing verbose information [default = %s]\n", fVerbose? "yes": "no" );
fprintf( pAbc->Err, "\t-v : toggle writing information about skipped gates [default = %s]\n", fVeryVerbose? "yes": "no" );
fprintf( pAbc->Err, "\t-h : prints the command summary\n" );
fprintf( pAbc->Err, "\t<file> : the name of a file to read\n" );
return 1;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Scl_CommandRead( Abc_Frame_t * pAbc, int argc, char ** argv )
{
FILE * pFile;
SC_Lib * pLib;
char * pFileName;
int c, fDump = 0;
Extra_UtilGetoptReset();
while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF )
{
switch ( c )
{
case 'd':
fDump ^= 1;
break;
case 'h':
goto usage;
default:
......@@ -130,15 +273,21 @@ int Scl_CommandRead( Abc_Frame_t * pAbc, int argc, char ** argv )
fclose( pFile );
// read new library
Abc_SclLoad( pFileName, (SC_Lib **)&pAbc->pLibScl );
if ( fVerbose )
Abc_SclWriteText( "scl_out.txt", (SC_Lib *)pAbc->pLibScl );
pLib = Abc_SclReadFromFile( pFileName );
if ( pLib == NULL )
{
fprintf( pAbc->Err, "Reading SCL library from file \"%s\" has failed. \n", pFileName );
return 1;
}
Abc_SclLoad( pLib, (SC_Lib **)&pAbc->pLibScl );
if ( fDump )
Abc_SclWriteLiberty( Extra_FileNameGenericAppend(pFileName, "_temp.lib"), (SC_Lib *)pAbc->pLibScl );
return 0;
usage:
fprintf( pAbc->Err, "usage: read_scl [-vh] <file>\n" );
fprintf( pAbc->Err, "\t reads Liberty library from file\n" );
fprintf( pAbc->Err, "\t-v : toggle writing the result into file \"scl_out.txt\" [default = %s]\n", fVerbose? "yes": "no" );
fprintf( pAbc->Err, "usage: read_scl [-dh] <file>\n" );
fprintf( pAbc->Err, "\t reads extracted Liberty library from file\n" );
fprintf( pAbc->Err, "\t-d : toggle dumping the parsed library into file \"*_temp.lib\" [default = %s]\n", fDump? "yes": "no" );
fprintf( pAbc->Err, "\t-h : prints the command summary\n" );
fprintf( pAbc->Err, "\t<file> : the name of a file to read\n" );
return 1;
......@@ -189,12 +338,12 @@ int Scl_CommandWrite( Abc_Frame_t * pAbc, int argc, char **argv )
fclose( pFile );
// save current library
Abc_SclSave( pFileName, (SC_Lib *)pAbc->pLibScl );
Abc_SclWriteScl( pFileName, (SC_Lib *)pAbc->pLibScl );
return 0;
usage:
fprintf( pAbc->Err, "usage: write_scl [-h] <file>\n" );
fprintf( pAbc->Err, "\t write Liberty library into file\n" );
fprintf( pAbc->Err, "\t write extracted Liberty library into file\n" );
fprintf( pAbc->Err, "\t-h : print the help massage\n" );
fprintf( pAbc->Err, "\t<file> : the name of the file to write\n" );
return 1;
......@@ -216,9 +365,10 @@ int Scl_CommandPrintScl( Abc_Frame_t * pAbc, int argc, char **argv )
float Slew = 200;
float Gain = 100;
int fInvOnly = 0;
int fShort = 0;
int c;
Extra_UtilGetoptReset();
while ( ( c = Extra_UtilGetopt( argc, argv, "SGih" ) ) != EOF )
while ( ( c = Extra_UtilGetopt( argc, argv, "SGish" ) ) != EOF )
{
switch ( c )
{
......@@ -247,6 +397,9 @@ int Scl_CommandPrintScl( Abc_Frame_t * pAbc, int argc, char **argv )
case 'i':
fInvOnly ^= 1;
break;
case 's':
fShort ^= 1;
break;
case 'h':
goto usage;
default:
......@@ -260,15 +413,16 @@ int Scl_CommandPrintScl( Abc_Frame_t * pAbc, int argc, char **argv )
}
// save current library
Abc_SclPrintCells( (SC_Lib *)pAbc->pLibScl, Slew, Gain, fInvOnly );
Abc_SclPrintCells( (SC_Lib *)pAbc->pLibScl, Slew, Gain, fInvOnly, fShort );
return 0;
usage:
fprintf( pAbc->Err, "usage: print_scl [-SG float] [-ih]\n" );
fprintf( pAbc->Err, "usage: print_scl [-SG float] [-ish]\n" );
fprintf( pAbc->Err, "\t prints statistics of Liberty library\n" );
fprintf( pAbc->Err, "\t-S float : the slew parameter used to generate the library [default = %.2f]\n", Slew );
fprintf( pAbc->Err, "\t-G float : the gain parameter used to generate the library [default = %.2f]\n", Gain );
fprintf( pAbc->Err, "\t-i : toggle printing invs/bufs only [default = %s]\n", fInvOnly? "yes": "no" );
fprintf( pAbc->Err, "\t-s : toggle printing in short format [default = %s]\n", fShort? "yes": "no" );
fprintf( pAbc->Err, "\t-h : print the help massage\n" );
return 1;
}
......
......@@ -201,6 +201,7 @@ struct SC_Cell_
struct SC_Lib_
{
char * pName;
char * pFileName;
char * default_wire_load;
char * default_wire_load_sel;
float default_max_out_slew; // -- 'default_max_transition'; this is copied to each output pin where 'max_transition' is not defined (not used)
......@@ -237,7 +238,7 @@ static inline SC_Cell * SC_LibCell( SC_Lib * p, int i ) { return (SC
static inline SC_Pin * SC_CellPin( SC_Cell * p, int i ) { return (SC_Pin *)Vec_PtrEntry(p->vPins, i); }
static inline Vec_Wrd_t * SC_CellFunc( SC_Cell * p ) { return SC_CellPin(p, p->n_inputs)->vFunc; }
static inline float SC_CellPinCap( SC_Cell * p, int i ) { return 0.5 * SC_CellPin(p, i)->rise_cap + 0.5 * SC_CellPin(p, i)->fall_cap; }
static inline float SC_CellPinCapAve( SC_Cell * p ) { int i; float c = 0; for (i = 0; i < p->n_inputs; i++) c += SC_CellPinCap(p, i); return c / p->n_inputs; }
static inline float SC_CellPinCapAve( SC_Cell * p ) { int i; float c = 0; for (i = 0; i < p->n_inputs; i++) c += SC_CellPinCap(p, i); return c / Abc_MaxInt(1, p->n_inputs); }
static inline char * SC_CellPinOutFunc( SC_Cell * p, int i ) { return SC_CellPin(p, p->n_inputs + i)->func_text; }
static inline char * SC_CellPinName( SC_Cell * p, int i ) { return SC_CellPin(p, i)->pName; }
......@@ -462,6 +463,7 @@ static inline void Abc_SclLibFree( SC_Lib * p )
Vec_PtrFree( p->vCells );
Vec_PtrFree( p->vCellClasses );
ABC_FREE( p->pName );
ABC_FREE( p->pFileName );
ABC_FREE( p->default_wire_load );
ABC_FREE( p->default_wire_load_sel );
ABC_FREE( p->pBins );
......@@ -578,22 +580,27 @@ static inline float Scl_LibPinArrivalEstimate( SC_Cell * pCell, int iPin, float
return 0.5 * ArrOut.fall + 0.5 * ArrOut.rise;
}
/*=== sclLib.c ===============================================================*/
extern SC_Lib * Abc_SclRead( char * pFileName );
extern void Abc_SclWrite( char * pFileName, SC_Lib * p );
extern void Abc_SclWriteText( char * pFileName, SC_Lib * p );
extern void Abc_SclLoad( char * pFileName, SC_Lib ** ppScl );
extern void Abc_SclSave( char * pFileName, SC_Lib * pScl );
/*=== sclLiberty.c ===============================================================*/
extern SC_Lib * Abc_SclReadLiberty( char * pFileName, int fVerbose, int fVeryVerbose );
/*=== sclLibScl.c ===============================================================*/
extern SC_Lib * Abc_SclReadFromStr( Vec_Str_t * vOut );
extern SC_Lib * Abc_SclReadFromFile( char * pFileName );
extern void Abc_SclWriteScl( char * pFileName, SC_Lib * p );
extern void Abc_SclWriteLiberty( char * pFileName, SC_Lib * p );
/*=== sclLibUtil.c ===============================================================*/
extern void Abc_SclHashCells( SC_Lib * p );
extern int Abc_SclCellFind( SC_Lib * p, char * pName );
extern int Abc_SclClassCellNum( SC_Cell * pClass );
extern void Abc_SclLinkCells( SC_Lib * p );
extern void Abc_SclPrintCells( SC_Lib * p, float Slew, float Gain, int fInvOnly );
extern void Abc_SclPrintCells( SC_Lib * p, float Slew, float Gain, int fInvOnly, int fShort );
extern SC_Cell * Abc_SclFindInvertor( SC_Lib * p, int fFindBuff );
extern SC_Cell * Abc_SclFindSmallestGate( SC_Cell * p, float CinMin );
extern SC_WireLoad * Abc_SclFindWireLoadModel( SC_Lib * p, float Area );
extern SC_WireLoad * Abc_SclFetchWireLoadModel( SC_Lib * p, char * pName );
extern void Abc_SclDumpGenlib( char * pFileName, SC_Lib * p, float Slew, float Gain, int nGatesMin );
extern void Abc_SclDeriveGenlib( void * pScl, float Slew, float Gain, int nGatesMin );
ABC_NAMESPACE_HEADER_END
......
/**CFile****************************************************************
FileName [sclLib.c]
FileName [sclLibScl.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Standard-cell library representation.]
Synopsis [Standard cell library.]
Synopsis [Liberty abstraction for delay-oriented mapping.]
Author [Alan Mishchenko, Niklas Een]
......@@ -14,7 +14,7 @@
Date [Ver. 1.0. Started - August 24, 2012.]
Revision [$Id: sclLib.c,v 1.0 2012/08/24 00:00:00 alanmi Exp $]
Revision [$Id: sclLibScl.c,v 1.0 2012/08/24 00:00:00 alanmi Exp $]
***********************************************************************/
......@@ -131,7 +131,13 @@ static void Abc_SclReadLibrary( Vec_Str_t * vOut, int * pPos, SC_Lib * p )
pCell->n_inputs = Vec_StrGetI(vOut, pPos);
pCell->n_outputs = Vec_StrGetI(vOut, pPos);
/*
printf( "%s\n", pCell->pName );
if ( !strcmp( "XOR3_X4M_A9TL", pCell->pName ) )
{
int s = 0;
}
*/
for ( j = 0; j < pCell->n_inputs; j++ )
{
SC_Pin * pPin = Abc_SclPinAlloc();
......@@ -194,6 +200,13 @@ static void Abc_SclReadLibrary( Vec_Str_t * vOut, int * pPos, SC_Lib * p )
Vec_WrdFree( pPin->vFunc );
pPin->vFunc = Mio_ParseFormulaTruth( pPin->func_text, (char **)Vec_PtrArray(vNames), pCell->n_inputs );
Vec_PtrFree( vNames );
// skip truth table
assert( Vec_WrdSize(pPin->vFunc) == Abc_Truth6WordNum(pCell->n_inputs) );
for ( k = 0; k < Vec_WrdSize(pPin->vFunc); k++ )
{
word Value = Vec_StrGetW(vOut, pPos);
assert( Value == Vec_WrdEntry(pPin->vFunc, k) );
}
}
}
......@@ -217,18 +230,30 @@ static void Abc_SclReadLibrary( Vec_Str_t * vOut, int * pPos, SC_Lib * p )
Abc_SclReadSurface( vOut, pPos, pTime->pFallTrans );
}
else
assert( Vec_PtrSize(pPin->vRTimings) == 0 );
assert( Vec_PtrSize(pRTime->vTimings) == 0 );
}
}
}
}
SC_Lib * Abc_SclRead( char * pFileName )
SC_Lib * Abc_SclReadFromStr( Vec_Str_t * vOut )
{
SC_Lib * p;
int Pos = 0;
// read the library
p = Abc_SclLibAlloc();
Abc_SclReadLibrary( vOut, &Pos, p );
assert( Pos == Vec_StrSize(vOut) );
// hash gates by name
Abc_SclHashCells( p );
Abc_SclLinkCells( p );
return p;
}
SC_Lib * Abc_SclReadFromFile( char * pFileName )
{
SC_Lib * p;
FILE * pFile;
Vec_Str_t * vOut;
int nFileSize, Pos = 0;
int nFileSize;
pFile = fopen( pFileName, "rb" );
if ( pFile == NULL )
{
......@@ -247,27 +272,11 @@ SC_Lib * Abc_SclRead( char * pFileName )
assert( nFileSize == Vec_StrSize(vOut) );
fclose( pFile );
// read the library
p = Abc_SclLibAlloc();
Abc_SclReadLibrary( vOut, &Pos, p );
assert( Pos == Vec_StrSize(vOut) );
p = Abc_SclReadFromStr( vOut );
p->pFileName = Abc_UtilStrsav( pFileName );
Vec_StrFree( vOut );
// hash gates by name
Abc_SclHashCells( p );
Abc_SclLinkCells( p );
return p;
}
void Abc_SclLoad( char * pFileName, SC_Lib ** ppScl )
{
if ( *ppScl )
{
Abc_SclLibFree( *ppScl );
*ppScl = NULL;
}
assert( *ppScl == NULL );
if ( pFileName )
*(SC_Lib **)ppScl = Abc_SclRead( pFileName );
}
/**Function*************************************************************
......@@ -436,7 +445,7 @@ static void Abc_SclWriteLibrary( Vec_Str_t * vOut, SC_Lib * p )
}
}
}
void Abc_SclWrite( char * pFileName, SC_Lib * p )
void Abc_SclWriteScl( char * pFileName, SC_Lib * p )
{
Vec_Str_t * vOut;
vOut = Vec_StrAlloc( 10000 );
......@@ -454,11 +463,6 @@ void Abc_SclWrite( char * pFileName, SC_Lib * p )
}
Vec_StrFree( vOut );
}
void Abc_SclSave( char * pFileName, SC_Lib * pScl )
{
if ( pScl == NULL ) return;
Abc_SclWrite( pFileName, pScl );
}
/**Function*************************************************************
......@@ -526,6 +530,8 @@ static void Abc_SclWriteLibraryText( FILE * s, SC_Lib * p )
SC_Pin * pPin;
int n_valid_cells;
int i, j, k;
fprintf( s, "/* This Liberty file was generated by ABC on %s. */\n", Extra_TimeStamp() );
fprintf( s, "/* The original unabridged library came from file \"%s\".*/\n\n", p->pFileName );
// fprintf( s, "%d", ABC_SCL_CUR_VERSION );
fprintf( s, "library(%s) {\n\n", p->pName );
......@@ -551,8 +557,8 @@ static void Abc_SclWriteLibraryText( FILE * s, SC_Lib * p )
SC_LibForEachWireLoad( p, pWL, i )
{
fprintf( s, " wire_load(\"%s\") {\n", pWL->pName );
fprintf( s, " capacitance : %f;\n", pWL->cap );
fprintf( s, " resistance : %f;\n", pWL->res );
fprintf( s, " capacitance : %f;\n", pWL->cap );
for ( j = 0; j < Vec_IntSize(pWL->vFanout); j++ )
fprintf( s, " fanout_length( %d, %f );\n", Vec_IntEntry(pWL->vFanout, j), Vec_FltEntry(pWL->vLen, j) );
fprintf( s, " }\n\n" );
......@@ -654,7 +660,7 @@ static void Abc_SclWriteLibraryText( FILE * s, SC_Lib * p )
}
fprintf( s, "}\n\n" );
}
void Abc_SclWriteText( char * pFileName, SC_Lib * p )
void Abc_SclWriteLiberty( char * pFileName, SC_Lib * p )
{
FILE * pFile = fopen( pFileName, "wb" );
if ( pFile == NULL )
......@@ -663,553 +669,10 @@ void Abc_SclWriteText( char * pFileName, SC_Lib * p )
{
Abc_SclWriteLibraryText( pFile, p );
fclose( pFile );
printf( "Dumped internal library into Liberty file \"%s\".\n", pFileName );
}
}
/**Function*************************************************************
Synopsis [Reading library from file.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static unsigned Abc_SclHashString( char * pName, int TableSize )
{
static int s_Primes[10] = { 1291, 1699, 2357, 4177, 5147, 5647, 6343, 7103, 7873, 8147 };
unsigned i, Key = 0;
for ( i = 0; pName[i] != '\0'; i++ )
Key += s_Primes[i%10]*pName[i]*pName[i];
return Key % TableSize;
}
int * Abc_SclHashLookup( SC_Lib * p, char * pName )
{
int i;
for ( i = Abc_SclHashString(pName, p->nBins); i < p->nBins; i = (i + 1) % p->nBins )
if ( p->pBins[i] == -1 || !strcmp(pName, SC_LibCell(p, p->pBins[i])->pName) )
return p->pBins + i;
assert( 0 );
return NULL;
}
void Abc_SclHashCells( SC_Lib * p )
{
SC_Cell * pCell;
int i, * pPlace;
assert( p->nBins == 0 );
p->nBins = Abc_PrimeCudd( 5 * Vec_PtrSize(p->vCells) );
p->pBins = ABC_FALLOC( int, p->nBins );
SC_LibForEachCell( p, pCell, i )
{
pPlace = Abc_SclHashLookup( p, pCell->pName );
assert( *pPlace == -1 );
*pPlace = i;
}
}
int Abc_SclCellFind( SC_Lib * p, char * pName )
{
int *pPlace = Abc_SclHashLookup( p, pName );
return pPlace ? *pPlace : -1;
}
int Abc_SclClassCellNum( SC_Cell * pClass )
{
SC_Cell * pCell;
int i, Count = 0;
SC_RingForEachCell( pClass, pCell, i )
if ( !pCell->fSkip )
Count++;
return Count;
}
/**Function*************************************************************
Synopsis [Links equal gates into rings while sorting them by area.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static int Abc_SclCompareCells( SC_Cell ** pp1, SC_Cell ** pp2 )
{
if ( (*pp1)->n_inputs < (*pp2)->n_inputs )
return -1;
if ( (*pp1)->n_inputs > (*pp2)->n_inputs )
return 1;
// if ( (*pp1)->area < (*pp2)->area )
// return -1;
// if ( (*pp1)->area > (*pp2)->area )
// return 1;
if ( SC_CellPinCapAve(*pp1) < SC_CellPinCapAve(*pp2) )
return -1;
if ( SC_CellPinCapAve(*pp1) > SC_CellPinCapAve(*pp2) )
return 1;
return strcmp( (*pp1)->pName, (*pp2)->pName );
}
void Abc_SclLinkCells( SC_Lib * p )
{
Vec_Ptr_t * vList;
SC_Cell * pCell, * pRepr = NULL;
int i, k;
assert( Vec_PtrSize(p->vCellClasses) == 0 );
SC_LibForEachCell( p, pCell, i )
{
// find gate with the same function
SC_LibForEachCellClass( p, pRepr, k )
if ( pCell->n_inputs == pRepr->n_inputs &&
pCell->n_outputs == pRepr->n_outputs &&
Vec_WrdEqual(SC_CellFunc(pCell), SC_CellFunc(pRepr)) )
break;
if ( k == Vec_PtrSize(p->vCellClasses) )
{
Vec_PtrPush( p->vCellClasses, pCell );
pCell->pNext = pCell->pPrev = pCell;
continue;
}
// add it to the list before the cell
pRepr->pPrev->pNext = pCell; pCell->pNext = pRepr;
pCell->pPrev = pRepr->pPrev; pRepr->pPrev = pCell;
}
// sort cells by size then by name
qsort( (void *)Vec_PtrArray(p->vCellClasses), Vec_PtrSize(p->vCellClasses), sizeof(void *), (int(*)(const void *,const void *))Abc_SclCompareCells );
// sort cell lists
vList = Vec_PtrAlloc( 100 );
SC_LibForEachCellClass( p, pRepr, k )
{
Vec_PtrClear( vList );
SC_RingForEachCell( pRepr, pCell, i )
Vec_PtrPush( vList, pCell );
qsort( (void *)Vec_PtrArray(vList), Vec_PtrSize(vList), sizeof(void *), (int(*)(const void *,const void *))Abc_SclCompareCells );
// create new representative
pRepr = (SC_Cell *)Vec_PtrEntry( vList, 0 );
pRepr->pNext = pRepr->pPrev = pRepr;
pRepr->pRepr = pRepr;
pRepr->pAve = (SC_Cell *)Vec_PtrEntry( vList, Vec_PtrSize(vList)/2 );
pRepr->Order = 0;
pRepr->nGates = Vec_PtrSize(vList);
// relink cells
Vec_PtrForEachEntryStart( SC_Cell *, vList, pCell, i, 1 )
{
pRepr->pPrev->pNext = pCell; pCell->pNext = pRepr;
pCell->pPrev = pRepr->pPrev; pRepr->pPrev = pCell;
pCell->pRepr = pRepr;
pCell->pAve = (SC_Cell *)Vec_PtrEntry( vList, Vec_PtrSize(vList)/2 );
pCell->Order = i;
pCell->nGates = Vec_PtrSize(vList);
}
// update list
Vec_PtrWriteEntry( p->vCellClasses, k, pRepr );
}
Vec_PtrFree( vList );
}
/**Function*************************************************************
Synopsis [Returns the largest inverter.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
SC_Cell * Abc_SclFindInvertor( SC_Lib * p, int fFindBuff )
{
SC_Cell * pCell = NULL;
word Truth = fFindBuff ? ABC_CONST(0xAAAAAAAAAAAAAAAA) : ABC_CONST(0x5555555555555555);
int k;
SC_LibForEachCellClass( p, pCell, k )
if ( pCell->n_inputs == 1 && Vec_WrdEntry(SC_CellPin(pCell, 1)->vFunc, 0) == Truth )
break;
// take representative
return pCell ? pCell->pRepr : NULL;
}
SC_Cell * Abc_SclFindSmallestGate( SC_Cell * p, float CinMin )
{
SC_Cell * pRes = NULL;
int i;
SC_RingForEachCell( p->pRepr, pRes, i )
if ( SC_CellPinCapAve(pRes) > CinMin )
return pRes;
// take the largest gate
return p->pRepr->pPrev;
}
/**Function*************************************************************
Synopsis [Returns the wireload model for the given area.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
SC_WireLoad * Abc_SclFetchWireLoadModel( SC_Lib * p, char * pWLoadUsed )
{
SC_WireLoad * pWL = NULL;
int i;
// Get the actual table and reformat it for 'wire_cap' output:
assert( pWLoadUsed != NULL );
SC_LibForEachWireLoad( p, pWL, i )
if ( !strcmp(pWL->pName, pWLoadUsed) )
break;
if ( i == Vec_PtrSize(p->vWireLoads) )
{
Abc_Print( -1, "Cannot find wire load model \"%s\".\n", pWLoadUsed );
exit(1);
}
// printf( "Using wireload model \"%s\".\n", pWL->pName );
return pWL;
}
SC_WireLoad * Abc_SclFindWireLoadModel( SC_Lib * p, float Area )
{
char * pWLoadUsed = NULL;
int i;
if ( p->default_wire_load_sel && strlen(p->default_wire_load_sel) )
{
SC_WireLoadSel * pWLS = NULL;
SC_LibForEachWireLoadSel( p, pWLS, i )
if ( !strcmp(pWLS->pName, p->default_wire_load_sel) )
break;
if ( i == Vec_PtrSize(p->vWireLoadSels) )
{
Abc_Print( -1, "Cannot find wire load selection model \"%s\".\n", p->default_wire_load_sel );
exit(1);
}
for ( i = 0; i < Vec_FltSize(pWLS->vAreaFrom); i++)
if ( Area >= Vec_FltEntry(pWLS->vAreaFrom, i) && Area < Vec_FltEntry(pWLS->vAreaTo, i) )
{
pWLoadUsed = (char *)Vec_PtrEntry(pWLS->vWireLoadModel, i);
break;
}
if ( i == Vec_FltSize(pWLS->vAreaFrom) )
pWLoadUsed = (char *)Vec_PtrEntryLast(pWLS->vWireLoadModel);
}
else if ( p->default_wire_load && strlen(p->default_wire_load) )
pWLoadUsed = p->default_wire_load;
else
{
Abc_Print( 0, "No wire model given.\n" );
return NULL;
}
return Abc_SclFetchWireLoadModel( p, pWLoadUsed );
}
/**Function*************************************************************
Synopsis [Compute delay parameters of pin/cell/class.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_SclComputeParametersPin( SC_Lib * p, SC_Cell * pCell, int iPin, float Slew, float * pLD, float * pPD )
{
SC_Pair Load0, Load1, Load2;
SC_Pair ArrIn = { 0.0, 0.0 };
SC_Pair SlewIn = { Slew, Slew };
SC_Pair ArrOut0 = { 0.0, 0.0 };
SC_Pair ArrOut1 = { 0.0, 0.0 };
SC_Pair ArrOut2 = { 0.0, 0.0 };
SC_Pair SlewOut = { 0.0, 0.0 };
SC_Timing * pTime = Scl_CellPinTime( pCell, iPin );
Vec_Flt_t * vIndex = pTime->pCellRise->vIndex1; // capacitance
// get load points
Load0.rise = Load0.fall = 0.0;
Load1.rise = Load1.fall = Vec_FltEntry( vIndex, 0 );
Load2.rise = Load2.fall = Vec_FltEntry( vIndex, Vec_FltSize(vIndex) - 2 );
// compute delay
Scl_LibPinArrival( pTime, &ArrIn, &SlewIn, &Load0, &ArrOut0, &SlewOut );
Scl_LibPinArrival( pTime, &ArrIn, &SlewIn, &Load1, &ArrOut1, &SlewOut );
Scl_LibPinArrival( pTime, &ArrIn, &SlewIn, &Load2, &ArrOut2, &SlewOut );
ArrOut0.rise = 0.5 * ArrOut0.rise + 0.5 * ArrOut0.fall;
ArrOut1.rise = 0.5 * ArrOut1.rise + 0.5 * ArrOut1.fall;
ArrOut2.rise = 0.5 * ArrOut2.rise + 0.5 * ArrOut2.fall;
// get tangent
*pLD = (ArrOut2.rise - ArrOut1.rise) / ((Load2.rise - Load1.rise) / SC_CellPinCap(pCell, iPin));
// get constant
*pPD = ArrOut0.rise;
}
void Abc_SclComputeParametersCell( SC_Lib * p, SC_Cell * pCell, float Slew, float * pLD, float * pPD )
{
SC_Pin * pPin;
float LD, PD, ld, pd;
int i;
LD = PD = ld = pd = 0;
SC_CellForEachPinIn( pCell, pPin, i )
{
Abc_SclComputeParametersPin( p, pCell, i, Slew, &ld, &pd );
LD += ld; PD += pd;
}
*pLD = LD / pCell->n_inputs;
*pPD = PD / pCell->n_inputs;
}
void Abc_SclComputeParametersClass( SC_Lib * p, SC_Cell * pRepr, float Slew, float * pLD, float * pPD )
{
SC_Cell * pCell;
float LD, PD, ld, pd;
int i, Count = 0;
LD = PD = ld = pd = 0;
SC_RingForEachCell( pRepr, pCell, i )
{
Abc_SclComputeParametersCell( p, pCell, Slew, &ld, &pd );
LD += ld; PD += pd;
Count++;
}
*pLD = LD / Count;
*pPD = PD / Count;
}
void Abc_SclComputeParametersClassPin( SC_Lib * p, SC_Cell * pRepr, int iPin, float Slew, float * pLD, float * pPD )
{
SC_Cell * pCell;
float LD, PD, ld, pd;
int i, Count = 0;
LD = PD = ld = pd = 0;
SC_RingForEachCell( pRepr, pCell, i )
{
Abc_SclComputeParametersPin( p, pCell, iPin, Slew, &ld, &pd );
LD += ld; PD += pd;
Count++;
}
*pLD = LD / Count;
*pPD = PD / Count;
}
float Abc_SclComputeDelayCellPin( SC_Lib * p, SC_Cell * pCell, int iPin, float Slew, float Gain )
{
float LD = 0, PD = 0;
Abc_SclComputeParametersPin( p, pCell, iPin, Slew, &LD, &PD );
return 0.01 * LD * Gain + PD;
}
float Abc_SclComputeDelayClassPin( SC_Lib * p, SC_Cell * pRepr, int iPin, float Slew, float Gain )
{
SC_Cell * pCell;
float Delay = 0;
int i, Count = 0;
SC_RingForEachCell( pRepr, pCell, i )
{
if ( pCell->fSkip )
continue;
// if ( pRepr == pCell ) // skip the first gate
// continue;
Delay += Abc_SclComputeDelayCellPin( p, pCell, iPin, Slew, Gain );
Count++;
}
return Delay / Abc_MaxInt(1, Count);
}
float Abc_SclComputeAreaClass( SC_Cell * pRepr )
{
SC_Cell * pCell;
float Area = 0;
int i, Count = 0;
SC_RingForEachCell( pRepr, pCell, i )
{
if ( pCell->fSkip )
continue;
Area += pCell->area;
Count++;
}
return Area / Count;
}
/**Function*************************************************************
Synopsis [Print cells]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_SclMarkSkippedCells( SC_Lib * p )
{
char FileName[1000];
char Buffer[1000], * pName;
SC_Cell * pCell;
FILE * pFile;
int CellId, nSkipped = 0;
sprintf( FileName, "%s.skip", p->pName );
pFile = fopen( FileName, "rb" );
if ( pFile == NULL )
return;
while ( fgets( Buffer, 999, pFile ) != NULL )
{
pName = strtok( Buffer, "\r\n\t " );
if ( pName == NULL )
continue;
CellId = Abc_SclCellFind( p, pName );
if ( CellId == -1 )
{
printf( "Cannot find cell \"%s\" in the library \"%s\".\n", pName, p->pName );
continue;
}
pCell = SC_LibCell( p, CellId );
pCell->fSkip = 1;
nSkipped++;
}
fclose( pFile );
printf( "Marked %d cells for skipping in the library \"%s\".\n", nSkipped, p->pName );
}
void Abc_SclPrintCells( SC_Lib * p, float Slew, float Gain, int fInvOnly )
{
SC_Cell * pCell, * pRepr;
int i, k, nLength = 0;
float LD = 0, PD = 0;
assert( Vec_PtrSize(p->vCellClasses) > 0 );
printf( "Library \"%s\" ", p->pName );
printf( "has %d cells in %d classes. ",
Vec_PtrSize(p->vCells), Vec_PtrSize(p->vCellClasses) );
printf( "Delay estimate is based on slew %.2f and gain %.2f.\n", Slew, Gain );
Abc_SclMarkSkippedCells( p );
// find the longest name
SC_LibForEachCellClass( p, pRepr, k )
SC_RingForEachCell( pRepr, pCell, i )
nLength = Abc_MaxInt( nLength, strlen(pRepr->pName) );
// print cells
SC_LibForEachCellClass( p, pRepr, k )
{
if ( fInvOnly && pRepr->n_inputs != 1 )
continue;
printf( "Class%3d : ", k );
printf( "Ins = %d ", pRepr->n_inputs );
printf( "Outs = %d", pRepr->n_outputs );
for ( i = 0; i < pRepr->n_outputs; i++ )
{
printf( " " );
Kit_DsdPrintFromTruth( (unsigned *)Vec_WrdArray(SC_CellPin(pRepr, pRepr->n_inputs+i)->vFunc), pRepr->n_inputs );
}
printf( "\n" );
SC_RingForEachCell( pRepr, pCell, i )
{
Abc_SclComputeParametersCell( p, pCell, Slew, &LD, &PD );
printf( " %3d ", i+1 );
printf( "%s", pCell->fSkip ? "s" : " " );
printf( " : " );
printf( "%-*s ", nLength, pCell->pName );
printf( "%2d ", pCell->drive_strength );
printf( "A =%8.2f ", pCell->area );
printf( "D =%5.0f ps ", 0.01 * LD * Gain + PD );
printf( "LD =%5.0f ps ", LD );
printf( "PD =%5.0f ps ", PD );
printf( "C =%5.1f ff ", SC_CellPinCapAve(pCell) );
printf( "Cm =%5.0f ff ", SC_CellPin(pCell, pCell->n_inputs)->max_out_cap );
printf( "Sm =%5.1f ps ", SC_CellPin(pCell, pCell->n_inputs)->max_out_slew );
printf( "\n" );
}
}
}
/**Function*************************************************************
Synopsis [Derive GENLIB library.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Str_t * Abc_SclDeriveGenlibStr( SC_Lib * p, float Slew, float Gain, int nGatesMin, int * pnCellCount )
{
extern char * Abc_SclFindGateFormula( char * pGateName, char * pOutName );
char Buffer[200];
Vec_Str_t * vStr;
SC_Cell * pRepr;
SC_Pin * pPin;
int i, k, Count = 2;
Abc_SclMarkSkippedCells( p );
vStr = Vec_StrAlloc( 1000 );
Vec_StrPrintStr( vStr, "GATE _const0_ 0.00 z=CONST0;\n" );
Vec_StrPrintStr( vStr, "GATE _const1_ 0.00 z=CONST1;\n" );
SC_LibForEachCellClass( p, pRepr, i )
{
if ( pRepr->n_outputs > 1 )
continue;
if ( Abc_SclClassCellNum(pRepr) < nGatesMin )
continue;
assert( strlen(pRepr->pName) < 200 );
Vec_StrPrintStr( vStr, "GATE " );
sprintf( Buffer, "%-16s", pRepr->pName );
Vec_StrPrintStr( vStr, Buffer );
Vec_StrPrintStr( vStr, " " );
// sprintf( Buffer, "%7.2f", Abc_SclComputeAreaClass(pRepr) );
sprintf( Buffer, "%7.2f", pRepr->area );
Vec_StrPrintStr( vStr, Buffer );
Vec_StrPrintStr( vStr, " " );
Vec_StrPrintStr( vStr, SC_CellPinName(pRepr, pRepr->n_inputs) );
Vec_StrPrintStr( vStr, "=" );
// Vec_StrPrintStr( vStr, SC_CellPinOutFunc(pRepr, 0) );
Vec_StrPrintStr( vStr, Abc_SclFindGateFormula(pRepr->pName, SC_CellPinName(pRepr, pRepr->n_inputs)) );
Vec_StrPrintStr( vStr, ";\n" );
SC_CellForEachPinIn( pRepr, pPin, k )
{
float Delay = Abc_SclComputeDelayClassPin( p, pRepr, k, Slew, Gain );
assert( Delay > 0 );
Vec_StrPrintStr( vStr, " PIN " );
sprintf( Buffer, "%-4s", pPin->pName );
Vec_StrPrintStr( vStr, Buffer );
sprintf( Buffer, " UNKNOWN 1 999 %7.2f 0.00 %7.2f 0.00\n", Delay, Delay );
Vec_StrPrintStr( vStr, Buffer );
}
Count++;
}
Vec_StrPrintStr( vStr, "\n.end\n" );
Vec_StrPush( vStr, '\0' );
// printf( "%s", Vec_StrArray(vStr) );
// printf( "GENLIB library with %d gates is produced.\n", Count );
if ( pnCellCount )
*pnCellCount = Count;
return vStr;
}
void Abc_SclDumpGenlib( char * pFileName, SC_Lib * p, float Slew, float Gain, int nGatesMin )
{
char FileName[1000];
int nCellCount = 0;
Vec_Str_t * vStr;
FILE * pFile;
if ( pFileName == NULL )
sprintf( FileName, "%s_s%03d_g%03d_m%d.genlib", p->pName, (int)Slew, (int)Gain, nGatesMin );
else
sprintf( FileName, "%s", pFileName );
pFile = fopen( FileName, "wb" );
if ( pFile == NULL )
{
printf( "Cannot open file \"%s\" for writing.\n", FileName );
return;
}
vStr = Abc_SclDeriveGenlibStr( p, Slew, Gain, nGatesMin, &nCellCount );
fprintf( pFile, "%s", Vec_StrArray(vStr) );
Vec_StrFree( vStr );
fclose( pFile );
printf( "Written GENLIB library with %d gates into file \"%s\".\n", nCellCount, FileName );
}
void Mio_SclDeriveGenlib( void * pScl, float Slew, float Gain, int nGatesMin )
{
int nGateCount = 0;
Vec_Str_t * vStr = Abc_SclDeriveGenlibStr( (SC_Lib *)pScl, Slew, Gain, nGatesMin, &nGateCount );
Vec_Str_t * vStr2 = Vec_StrDup( vStr );
int RetValue = Mio_UpdateGenlib2( vStr, vStr2, ((SC_Lib *)pScl)->pName, 0 );
Vec_StrFree( vStr );
Vec_StrFree( vStr2 );
if ( RetValue )
printf( "Internally derived GENLIB library \"%s\" with %d gates.\n", ((SC_Lib *)pScl)->pName, nGateCount );
else
printf( "Reading library has filed.\n" );
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
......
/**CFile****************************************************************
FileName [sclLibUtil.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Standard-cell library representation.]
Synopsis [Various library utilities.]
Author [Alan Mishchenko, Niklas Een]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - August 24, 2012.]
Revision [$Id: sclLibUtil.c,v 1.0 2012/08/24 00:00:00 alanmi Exp $]
***********************************************************************/
#include "sclLib.h"
#include "misc/st/st.h"
#include "map/mio/mio.h"
#include "bool/kit/kit.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Reading library from file.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static unsigned Abc_SclHashString( char * pName, int TableSize )
{
static int s_Primes[10] = { 1291, 1699, 2357, 4177, 5147, 5647, 6343, 7103, 7873, 8147 };
unsigned i, Key = 0;
for ( i = 0; pName[i] != '\0'; i++ )
Key += s_Primes[i%10]*pName[i]*pName[i];
return Key % TableSize;
}
int * Abc_SclHashLookup( SC_Lib * p, char * pName )
{
int i;
for ( i = Abc_SclHashString(pName, p->nBins); i < p->nBins; i = (i + 1) % p->nBins )
if ( p->pBins[i] == -1 || !strcmp(pName, SC_LibCell(p, p->pBins[i])->pName) )
return p->pBins + i;
assert( 0 );
return NULL;
}
void Abc_SclHashCells( SC_Lib * p )
{
SC_Cell * pCell;
int i, * pPlace;
assert( p->nBins == 0 );
p->nBins = Abc_PrimeCudd( 5 * Vec_PtrSize(p->vCells) );
p->pBins = ABC_FALLOC( int, p->nBins );
SC_LibForEachCell( p, pCell, i )
{
pPlace = Abc_SclHashLookup( p, pCell->pName );
assert( *pPlace == -1 );
*pPlace = i;
}
}
int Abc_SclCellFind( SC_Lib * p, char * pName )
{
int *pPlace = Abc_SclHashLookup( p, pName );
return pPlace ? *pPlace : -1;
}
int Abc_SclClassCellNum( SC_Cell * pClass )
{
SC_Cell * pCell;
int i, Count = 0;
SC_RingForEachCell( pClass, pCell, i )
if ( !pCell->fSkip )
Count++;
return Count;
}
/**Function*************************************************************
Synopsis [Links equal gates into rings while sorting them by area.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static int Abc_SclCompareCells( SC_Cell ** pp1, SC_Cell ** pp2 )
{
if ( (*pp1)->n_inputs < (*pp2)->n_inputs )
return -1;
if ( (*pp1)->n_inputs > (*pp2)->n_inputs )
return 1;
// if ( (*pp1)->area < (*pp2)->area )
// return -1;
// if ( (*pp1)->area > (*pp2)->area )
// return 1;
if ( SC_CellPinCapAve(*pp1) < SC_CellPinCapAve(*pp2) )
return -1;
if ( SC_CellPinCapAve(*pp1) > SC_CellPinCapAve(*pp2) )
return 1;
return strcmp( (*pp1)->pName, (*pp2)->pName );
}
void Abc_SclLinkCells( SC_Lib * p )
{
Vec_Ptr_t * vList;
SC_Cell * pCell, * pRepr = NULL;
int i, k;
assert( Vec_PtrSize(p->vCellClasses) == 0 );
SC_LibForEachCell( p, pCell, i )
{
// find gate with the same function
SC_LibForEachCellClass( p, pRepr, k )
if ( pCell->n_inputs == pRepr->n_inputs &&
pCell->n_outputs == pRepr->n_outputs &&
Vec_WrdEqual(SC_CellFunc(pCell), SC_CellFunc(pRepr)) )
break;
if ( k == Vec_PtrSize(p->vCellClasses) )
{
Vec_PtrPush( p->vCellClasses, pCell );
pCell->pNext = pCell->pPrev = pCell;
continue;
}
// add it to the list before the cell
pRepr->pPrev->pNext = pCell; pCell->pNext = pRepr;
pCell->pPrev = pRepr->pPrev; pRepr->pPrev = pCell;
}
// sort cells by size then by name
qsort( (void *)Vec_PtrArray(p->vCellClasses), Vec_PtrSize(p->vCellClasses), sizeof(void *), (int(*)(const void *,const void *))Abc_SclCompareCells );
// sort cell lists
vList = Vec_PtrAlloc( 100 );
SC_LibForEachCellClass( p, pRepr, k )
{
Vec_PtrClear( vList );
SC_RingForEachCell( pRepr, pCell, i )
Vec_PtrPush( vList, pCell );
qsort( (void *)Vec_PtrArray(vList), Vec_PtrSize(vList), sizeof(void *), (int(*)(const void *,const void *))Abc_SclCompareCells );
// create new representative
pRepr = (SC_Cell *)Vec_PtrEntry( vList, 0 );
pRepr->pNext = pRepr->pPrev = pRepr;
pRepr->pRepr = pRepr;
pRepr->pAve = (SC_Cell *)Vec_PtrEntry( vList, Vec_PtrSize(vList)/2 );
pRepr->Order = 0;
pRepr->nGates = Vec_PtrSize(vList);
// relink cells
Vec_PtrForEachEntryStart( SC_Cell *, vList, pCell, i, 1 )
{
pRepr->pPrev->pNext = pCell; pCell->pNext = pRepr;
pCell->pPrev = pRepr->pPrev; pRepr->pPrev = pCell;
pCell->pRepr = pRepr;
pCell->pAve = (SC_Cell *)Vec_PtrEntry( vList, Vec_PtrSize(vList)/2 );
pCell->Order = i;
pCell->nGates = Vec_PtrSize(vList);
}
// update list
Vec_PtrWriteEntry( p->vCellClasses, k, pRepr );
}
Vec_PtrFree( vList );
}
/**Function*************************************************************
Synopsis [Returns the largest inverter.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
SC_Cell * Abc_SclFindInvertor( SC_Lib * p, int fFindBuff )
{
SC_Cell * pCell = NULL;
word Truth = fFindBuff ? ABC_CONST(0xAAAAAAAAAAAAAAAA) : ABC_CONST(0x5555555555555555);
int k;
SC_LibForEachCellClass( p, pCell, k )
if ( pCell->n_inputs == 1 && Vec_WrdEntry(SC_CellPin(pCell, 1)->vFunc, 0) == Truth )
break;
// take representative
return pCell ? pCell->pRepr : NULL;
}
SC_Cell * Abc_SclFindSmallestGate( SC_Cell * p, float CinMin )
{
SC_Cell * pRes = NULL;
int i;
SC_RingForEachCell( p->pRepr, pRes, i )
if ( SC_CellPinCapAve(pRes) > CinMin )
return pRes;
// take the largest gate
return p->pRepr->pPrev;
}
/**Function*************************************************************
Synopsis [Returns the wireload model for the given area.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
SC_WireLoad * Abc_SclFetchWireLoadModel( SC_Lib * p, char * pWLoadUsed )
{
SC_WireLoad * pWL = NULL;
int i;
// Get the actual table and reformat it for 'wire_cap' output:
assert( pWLoadUsed != NULL );
SC_LibForEachWireLoad( p, pWL, i )
if ( !strcmp(pWL->pName, pWLoadUsed) )
break;
if ( i == Vec_PtrSize(p->vWireLoads) )
{
Abc_Print( -1, "Cannot find wire load model \"%s\".\n", pWLoadUsed );
exit(1);
}
// printf( "Using wireload model \"%s\".\n", pWL->pName );
return pWL;
}
SC_WireLoad * Abc_SclFindWireLoadModel( SC_Lib * p, float Area )
{
char * pWLoadUsed = NULL;
int i;
if ( p->default_wire_load_sel && strlen(p->default_wire_load_sel) )
{
SC_WireLoadSel * pWLS = NULL;
SC_LibForEachWireLoadSel( p, pWLS, i )
if ( !strcmp(pWLS->pName, p->default_wire_load_sel) )
break;
if ( i == Vec_PtrSize(p->vWireLoadSels) )
{
Abc_Print( -1, "Cannot find wire load selection model \"%s\".\n", p->default_wire_load_sel );
exit(1);
}
for ( i = 0; i < Vec_FltSize(pWLS->vAreaFrom); i++)
if ( Area >= Vec_FltEntry(pWLS->vAreaFrom, i) && Area < Vec_FltEntry(pWLS->vAreaTo, i) )
{
pWLoadUsed = (char *)Vec_PtrEntry(pWLS->vWireLoadModel, i);
break;
}
if ( i == Vec_FltSize(pWLS->vAreaFrom) )
pWLoadUsed = (char *)Vec_PtrEntryLast(pWLS->vWireLoadModel);
}
else if ( p->default_wire_load && strlen(p->default_wire_load) )
pWLoadUsed = p->default_wire_load;
else
{
Abc_Print( 0, "No wire model given.\n" );
return NULL;
}
return Abc_SclFetchWireLoadModel( p, pWLoadUsed );
}
/**Function*************************************************************
Synopsis [Compute delay parameters of pin/cell/class.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_SclComputeParametersPin( SC_Lib * p, SC_Cell * pCell, int iPin, float Slew, float * pLD, float * pPD )
{
SC_Pair Load0, Load1, Load2;
SC_Pair ArrIn = { 0.0, 0.0 };
SC_Pair SlewIn = { Slew, Slew };
SC_Pair ArrOut0 = { 0.0, 0.0 };
SC_Pair ArrOut1 = { 0.0, 0.0 };
SC_Pair ArrOut2 = { 0.0, 0.0 };
SC_Pair SlewOut = { 0.0, 0.0 };
SC_Timing * pTime = Scl_CellPinTime( pCell, iPin );
Vec_Flt_t * vIndex = pTime->pCellRise->vIndex1; // capacitance
// get load points
Load0.rise = Load0.fall = 0.0;
Load1.rise = Load1.fall = Vec_FltEntry( vIndex, 0 );
Load2.rise = Load2.fall = Vec_FltEntry( vIndex, Vec_FltSize(vIndex) - 2 );
// compute delay
Scl_LibPinArrival( pTime, &ArrIn, &SlewIn, &Load0, &ArrOut0, &SlewOut );
Scl_LibPinArrival( pTime, &ArrIn, &SlewIn, &Load1, &ArrOut1, &SlewOut );
Scl_LibPinArrival( pTime, &ArrIn, &SlewIn, &Load2, &ArrOut2, &SlewOut );
ArrOut0.rise = 0.5 * ArrOut0.rise + 0.5 * ArrOut0.fall;
ArrOut1.rise = 0.5 * ArrOut1.rise + 0.5 * ArrOut1.fall;
ArrOut2.rise = 0.5 * ArrOut2.rise + 0.5 * ArrOut2.fall;
// get tangent
*pLD = (ArrOut2.rise - ArrOut1.rise) / ((Load2.rise - Load1.rise) / SC_CellPinCap(pCell, iPin));
// get constant
*pPD = ArrOut0.rise;
}
void Abc_SclComputeParametersCell( SC_Lib * p, SC_Cell * pCell, float Slew, float * pLD, float * pPD )
{
SC_Pin * pPin;
float LD, PD, ld, pd;
int i;
LD = PD = ld = pd = 0;
SC_CellForEachPinIn( pCell, pPin, i )
{
Abc_SclComputeParametersPin( p, pCell, i, Slew, &ld, &pd );
LD += ld; PD += pd;
}
*pLD = LD / Abc_MaxInt(1, pCell->n_inputs);
*pPD = PD / Abc_MaxInt(1, pCell->n_inputs);
}
void Abc_SclComputeParametersClass( SC_Lib * p, SC_Cell * pRepr, float Slew, float * pLD, float * pPD )
{
SC_Cell * pCell;
float LD, PD, ld, pd;
int i, Count = 0;
LD = PD = ld = pd = 0;
SC_RingForEachCell( pRepr, pCell, i )
{
Abc_SclComputeParametersCell( p, pCell, Slew, &ld, &pd );
LD += ld; PD += pd;
Count++;
}
*pLD = LD / Abc_MaxInt(1, Count);
*pPD = PD / Abc_MaxInt(1, Count);
}
void Abc_SclComputeParametersClassPin( SC_Lib * p, SC_Cell * pRepr, int iPin, float Slew, float * pLD, float * pPD )
{
SC_Cell * pCell;
float LD, PD, ld, pd;
int i, Count = 0;
LD = PD = ld = pd = 0;
SC_RingForEachCell( pRepr, pCell, i )
{
Abc_SclComputeParametersPin( p, pCell, iPin, Slew, &ld, &pd );
LD += ld; PD += pd;
Count++;
}
*pLD = LD / Abc_MaxInt(1, Count);
*pPD = PD / Abc_MaxInt(1, Count);
}
float Abc_SclComputeDelayCellPin( SC_Lib * p, SC_Cell * pCell, int iPin, float Slew, float Gain )
{
float LD = 0, PD = 0;
Abc_SclComputeParametersPin( p, pCell, iPin, Slew, &LD, &PD );
return 0.01 * LD * Gain + PD;
}
float Abc_SclComputeDelayClassPin( SC_Lib * p, SC_Cell * pRepr, int iPin, float Slew, float Gain )
{
SC_Cell * pCell;
float Delay = 0;
int i, Count = 0;
SC_RingForEachCell( pRepr, pCell, i )
{
if ( pCell->fSkip )
continue;
// if ( pRepr == pCell ) // skip the first gate
// continue;
Delay += Abc_SclComputeDelayCellPin( p, pCell, iPin, Slew, Gain );
Count++;
}
return Delay / Abc_MaxInt(1, Count);
}
float Abc_SclComputeAreaClass( SC_Cell * pRepr )
{
SC_Cell * pCell;
float Area = 0;
int i, Count = 0;
SC_RingForEachCell( pRepr, pCell, i )
{
if ( pCell->fSkip )
continue;
Area += pCell->area;
Count++;
}
return Area / Abc_MaxInt(1, Count);
}
/**Function*************************************************************
Synopsis [Print cells]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_SclMarkSkippedCells( SC_Lib * p )
{
char FileName[1000];
char Buffer[1000], * pName;
SC_Cell * pCell;
FILE * pFile;
int CellId, nSkipped = 0;
sprintf( FileName, "%s.skip", p->pName );
pFile = fopen( FileName, "rb" );
if ( pFile == NULL )
return;
while ( fgets( Buffer, 999, pFile ) != NULL )
{
pName = strtok( Buffer, "\r\n\t " );
if ( pName == NULL )
continue;
CellId = Abc_SclCellFind( p, pName );
if ( CellId == -1 )
{
printf( "Cannot find cell \"%s\" in the library \"%s\".\n", pName, p->pName );
continue;
}
pCell = SC_LibCell( p, CellId );
pCell->fSkip = 1;
nSkipped++;
}
fclose( pFile );
printf( "Marked %d cells for skipping in the library \"%s\".\n", nSkipped, p->pName );
}
void Abc_SclPrintCells( SC_Lib * p, float Slew, float Gain, int fInvOnly, int fShort )
{
SC_Cell * pCell, * pRepr;
SC_Pin * pPin;
int i, j, k, nLength = 0;
float LD = 0, PD = 0;
assert( Vec_PtrSize(p->vCellClasses) > 0 );
printf( "Library \"%s\" ", p->pName );
printf( "has %d cells in %d classes. ",
Vec_PtrSize(p->vCells), Vec_PtrSize(p->vCellClasses) );
if ( !fShort )
printf( "Delay estimate is based on slew %.2f and gain %.2f.", Slew, Gain );
printf( "\n" );
Abc_SclMarkSkippedCells( p );
// find the longest name
SC_LibForEachCellClass( p, pRepr, k )
SC_RingForEachCell( pRepr, pCell, i )
nLength = Abc_MaxInt( nLength, strlen(pRepr->pName) );
// print cells
SC_LibForEachCellClass( p, pRepr, k )
{
if ( fInvOnly && pRepr->n_inputs != 1 )
continue;
SC_CellForEachPinOut( pRepr, pPin, i )
{
if ( i == pRepr->n_inputs )
{
printf( "Class%4d : ", k );
printf( "Cells =%3d ", Abc_SclClassCellNum(pRepr) );
printf( "Ins =%2d ", pRepr->n_inputs );
printf( "Outs =%2d ", pRepr->n_outputs );
}
else
printf( " " );
if ( pPin->func_text )
printf( "%-30s", pPin->func_text );
printf( " " );
Kit_DsdPrintFromTruth( (unsigned *)Vec_WrdArray(pPin->vFunc), pRepr->n_inputs );
printf( "\n" );
if ( fShort )
continue;
SC_RingForEachCell( pRepr, pCell, j )
{
Abc_SclComputeParametersCell( p, pCell, Slew, &LD, &PD );
printf( " %3d ", j+1 );
printf( "%s", pCell->fSkip ? "s" : " " );
printf( " : " );
printf( "%-*s ", nLength, pCell->pName );
printf( "%2d ", pCell->drive_strength );
printf( "A =%8.2f ", pCell->area );
printf( "D =%6.1f ps ", 0.01 * Gain * LD + PD );
printf( "LD =%6.1f ps ", LD );
printf( "PD =%6.1f ps ", PD );
printf( "C =%5.1f ff ", SC_LibCapFf(p, SC_CellPinCapAve(pCell)) );
printf( "Cm =%5.0f ff ", SC_LibCapFf(p, SC_CellPin(pCell, pCell->n_inputs)->max_out_cap) );
printf( "Sm =%5.1f ps ", SC_LibTimePs(p, SC_CellPin(pCell, pCell->n_inputs)->max_out_slew) );
printf( "\n" );
}
break;
}
}
}
/**Function*************************************************************
Synopsis [Derive GENLIB library.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Str_t * Abc_SclDeriveGenlibStr( SC_Lib * p, float Slew, float Gain, int nGatesMin, int * pnCellCount )
{
char Buffer[200];
Vec_Str_t * vStr;
SC_Cell * pRepr;
SC_Pin * pPin;
int i, k, Count = 2, nClassMax = 0;
// find the largest number of cells in a class
SC_LibForEachCellClass( p, pRepr, i )
if ( pRepr->n_outputs == 1 )
nClassMax = Abc_MaxInt( nClassMax, Abc_SclClassCellNum(pRepr) );
// update the number
if ( nGatesMin && nGatesMin >= nClassMax )
nGatesMin = 0;
// mark skipped cells
Abc_SclMarkSkippedCells( p );
vStr = Vec_StrAlloc( 1000 );
Vec_StrPrintStr( vStr, "GATE _const0_ 0.00 z=CONST0;\n" );
Vec_StrPrintStr( vStr, "GATE _const1_ 0.00 z=CONST1;\n" );
SC_LibForEachCellClass( p, pRepr, i )
{
if ( pRepr->n_inputs == 0 )
continue;
if ( pRepr->n_outputs > 1 )
continue;
if ( nGatesMin && pRepr->n_inputs > 2 && Abc_SclClassCellNum(pRepr) < nGatesMin )
continue;
assert( strlen(pRepr->pName) < 200 );
Vec_StrPrintStr( vStr, "GATE " );
sprintf( Buffer, "%-16s", pRepr->pName );
Vec_StrPrintStr( vStr, Buffer );
Vec_StrPrintStr( vStr, " " );
// sprintf( Buffer, "%7.2f", Abc_SclComputeAreaClass(pRepr) );
sprintf( Buffer, "%7.2f", pRepr->area );
Vec_StrPrintStr( vStr, Buffer );
Vec_StrPrintStr( vStr, " " );
Vec_StrPrintStr( vStr, SC_CellPinName(pRepr, pRepr->n_inputs) );
Vec_StrPrintStr( vStr, "=" );
Vec_StrPrintStr( vStr, SC_CellPinOutFunc(pRepr, 0) ? SC_CellPinOutFunc(pRepr, 0) : "?" );
Vec_StrPrintStr( vStr, ";\n" );
SC_CellForEachPinIn( pRepr, pPin, k )
{
float Delay = Abc_SclComputeDelayClassPin( p, pRepr, k, Slew, Gain );
assert( Delay > 0 );
Vec_StrPrintStr( vStr, " PIN " );
sprintf( Buffer, "%-4s", pPin->pName );
Vec_StrPrintStr( vStr, Buffer );
sprintf( Buffer, " UNKNOWN 1 999 %7.2f 0.00 %7.2f 0.00\n", Delay, Delay );
Vec_StrPrintStr( vStr, Buffer );
}
Count++;
}
Vec_StrPrintStr( vStr, "\n.end\n" );
Vec_StrPush( vStr, '\0' );
// printf( "GENLIB library with %d gates is produced:\n", Count );
// printf( "%s", Vec_StrArray(vStr) );
if ( pnCellCount )
*pnCellCount = Count;
return vStr;
}
void Abc_SclDumpGenlib( char * pFileName, SC_Lib * p, float Slew, float Gain, int nGatesMin )
{
char FileName[1000];
int nCellCount = 0;
Vec_Str_t * vStr;
FILE * pFile;
if ( pFileName == NULL )
sprintf( FileName, "%s_s%03d_g%03d_m%d.genlib", p->pName, (int)Slew, (int)Gain, nGatesMin );
else
sprintf( FileName, "%s", pFileName );
pFile = fopen( FileName, "wb" );
if ( pFile == NULL )
{
printf( "Cannot open file \"%s\" for writing.\n", FileName );
return;
}
vStr = Abc_SclDeriveGenlibStr( p, Slew, Gain, nGatesMin, &nCellCount );
fprintf( pFile, "%s", Vec_StrArray(vStr) );
Vec_StrFree( vStr );
fclose( pFile );
printf( "Written GENLIB library with %d gates into file \"%s\".\n", nCellCount, FileName );
}
void Abc_SclDeriveGenlib( void * pScl, float Slew, float Gain, int nGatesMin )
{
int nGateCount = 0;
Vec_Str_t * vStr = Abc_SclDeriveGenlibStr( (SC_Lib *)pScl, Slew, Gain, nGatesMin, &nGateCount );
Vec_Str_t * vStr2 = Vec_StrDup( vStr );
int RetValue = Mio_UpdateGenlib2( vStr, vStr2, ((SC_Lib *)pScl)->pName, 0 );
Vec_StrFree( vStr );
Vec_StrFree( vStr2 );
if ( RetValue )
printf( "Internally derived GENLIB library \"%s\" with %d gates.\n", ((SC_Lib *)pScl)->pName, nGateCount );
else
printf( "Reading library has filed.\n" );
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END
/**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
......@@ -551,7 +551,7 @@ void Extra_PrintHex( FILE * pFile, unsigned * pTruth, int nVars )
// write the number into the file
fprintf( pFile, "0x" );
nMints = (1 << nVars);
nDigits = nMints / 4;
nDigits = nMints / 4 + ((nMints % 4) > 0);
for ( k = nDigits - 1; k >= 0; k-- )
{
Digit = ((pTruth[k/8] >> (k * 4)) & 15);
......@@ -569,7 +569,7 @@ void Extra_PrintHexReverse( FILE * pFile, unsigned * pTruth, int nVars )
// write the number into the file
fprintf( pFile, "0x" );
nMints = (1 << nVars);
nDigits = nMints / 4;
nDigits = nMints / 4 + ((nMints % 4) > 0);
for ( k = 0; k < nDigits; k++ )
{
Digit = ((pTruth[k/8] >> (k * 4)) & 15);
......
......@@ -664,6 +664,26 @@ static inline float Vec_FltFindMin( Vec_Flt_t * p )
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Vec_FltPrint( Vec_Flt_t * vVec )
{
int i; float Entry;
printf( "Vector has %d entries: {", Vec_FltSize(vVec) );
Vec_FltForEachEntry( vVec, Entry, i )
printf( " %f", Entry );
printf( " }\n" );
}
/**Function*************************************************************
Synopsis [Comparison procedure for two floats.]
Description []
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment