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