diff options
author | Alan Mishchenko <alanmi@berkeley.edu> | 2013-09-15 18:23:49 -0700 |
---|---|---|
committer | Alan Mishchenko <alanmi@berkeley.edu> | 2013-09-15 18:23:49 -0700 |
commit | ff5d3591d1e7d90199d7395cde9fc6d902ed4b41 (patch) | |
tree | 26a2307c387d50bcd1a01e007bfe370ca8a5a9e3 /src | |
parent | d1fed2dd89bc0549655f8375832628b18b35edd9 (diff) | |
download | abc-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.c | 4 | ||||
-rw-r--r-- | src/base/abci/abcMap.c | 2 | ||||
-rw-r--r-- | src/map/mio/mio.c | 4 | ||||
-rw-r--r-- | src/map/mio/mio.h | 2 | ||||
-rw-r--r-- | src/map/mio/mioParse.c | 2 | ||||
-rw-r--r-- | src/map/scl/module.make | 4 | ||||
-rw-r--r-- | src/map/scl/scl.c | 200 | ||||
-rw-r--r-- | src/map/scl/sclLib.h | 23 | ||||
-rw-r--r-- | src/map/scl/sclLibScl.c (renamed from src/map/scl/sclLib.c) | 619 | ||||
-rw-r--r-- | src/map/scl/sclLibUtil.c | 608 | ||||
-rw-r--r-- | src/map/scl/sclLiberty.c | 1358 | ||||
-rw-r--r-- | src/misc/extra/extraUtilFile.c | 4 | ||||
-rw-r--r-- | src/misc/vec/vecFlt.h | 20 |
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 [] |