mirror of https://github.com/YosysHQ/abc.git
Infrastructure to support full Liberty format and unitification of library representations.
This commit is contained in:
parent
d1fed2dd89
commit
ff5d3591d1
12
abclib.dsp
12
abclib.dsp
|
|
@ -2479,11 +2479,19 @@ SOURCE=.\src\map\scl\sclDnsize.c
|
|||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\src\map\scl\sclLib.c
|
||||
SOURCE=.\src\map\scl\sclLib.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\src\map\scl\sclLib.h
|
||||
SOURCE=.\src\map\scl\sclLiberty.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\src\map\scl\sclLibScl.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\src\map\scl\sclLibUtil.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
|
|
|
|||
|
|
@ -990,6 +990,10 @@ void Abc_Init( Abc_Frame_t * pAbc )
|
|||
|
||||
if ( Sdm_ManCanRead() )
|
||||
Sdm_ManRead();
|
||||
{
|
||||
// extern void Scl_LibertyTest();
|
||||
// Scl_LibertyTest();
|
||||
}
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ Abc_Ntk_t * Abc_NtkMap( Abc_Ntk_t * pNtk, double DelayTarget, double AreaMulti,
|
|||
assert( Abc_NtkIsStrash(pNtk) );
|
||||
// derive library from SCL
|
||||
if ( Abc_FrameReadLibScl() )
|
||||
Mio_SclDeriveGenlib( Abc_FrameReadLibScl(), Slew, Gain, nGatesMin );
|
||||
Abc_SclDeriveGenlib( Abc_FrameReadLibScl(), Slew, Gain, nGatesMin );
|
||||
// quit if there is no library
|
||||
pLib = (Mio_Library_t *)Abc_FrameReadLibGen();
|
||||
if ( pLib == NULL )
|
||||
|
|
|
|||
|
|
@ -220,7 +220,7 @@ int Mio_CommandReadLiberty( Abc_Frame_t * pAbc, int argc, char **argv )
|
|||
if ( (pFile = Io_FileOpen( pFileName, "open_path", "r", 0 )) == NULL )
|
||||
{
|
||||
fprintf( pErr, "Cannot open input file \"%s\". ", pFileName );
|
||||
if ( (pFileName = Extra_FileGetSimilarName( pFileName, ".genlib", ".lib", ".gen", ".g", NULL )) )
|
||||
if ( (pFileName = Extra_FileGetSimilarName( pFileName, ".genlib", ".lib", ".scl", ".g", NULL )) )
|
||||
fprintf( pErr, "Did you mean \"%s\"?", pFileName );
|
||||
fprintf( pErr, "\n" );
|
||||
return 1;
|
||||
|
|
@ -338,7 +338,7 @@ int Mio_CommandReadGenlib( Abc_Frame_t * pAbc, int argc, char **argv )
|
|||
if ( (pFile = Io_FileOpen( pFileName, "open_path", "r", 0 )) == NULL )
|
||||
{
|
||||
fprintf( pErr, "Cannot open input file \"%s\". ", pFileName );
|
||||
if ( (pFileName = Extra_FileGetSimilarName( pFileName, ".genlib", ".lib", ".gen", ".g", NULL )) )
|
||||
if ( (pFileName = Extra_FileGetSimilarName( pFileName, ".genlib", ".lib", ".scl", ".g", NULL )) )
|
||||
fprintf( pErr, "Did you mean \"%s\"?", pFileName );
|
||||
fprintf( pErr, "\n" );
|
||||
return 1;
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ static inline char * Mio_UtilStrsav( char * s ) { return s ? strcpy(ABC_A
|
|||
/*=== mio.c =============================================================*/
|
||||
extern void Mio_UpdateGenlib( Mio_Library_t * pLib );
|
||||
extern int Mio_UpdateGenlib2( Vec_Str_t * vStr, Vec_Str_t * vStr2, char * pFileName, int fVerbose );
|
||||
extern void Mio_SclDeriveGenlib( void * pScl, float Slew, float Gain, int nGatesMin );
|
||||
extern void Abc_SclDeriveGenlib( void * pScl, float Slew, float Gain, int nGatesMin );
|
||||
/*=== mioApi.c =============================================================*/
|
||||
extern char * Mio_LibraryReadName ( Mio_Library_t * pLib );
|
||||
extern int Mio_LibraryReadGateNum ( Mio_Library_t * pLib );
|
||||
|
|
|
|||
|
|
@ -399,6 +399,8 @@ Vec_Wrd_t * Mio_ParseFormulaTruth( char * pFormInit, char ** ppVarNames, int nVa
|
|||
Vec_Wrd_t * vTruth;
|
||||
// derive expression
|
||||
vExpr = Mio_ParseFormula( pFormInit, ppVarNames, nVars );
|
||||
if ( vExpr == NULL )
|
||||
return NULL;
|
||||
// convert it into a truth table
|
||||
vTruth = Vec_WrdStart( Abc_Truth6WordNum(nVars) );
|
||||
Exp_Truth( nVars, vExpr, Vec_WrdArray(vTruth) );
|
||||
|
|
|
|||
|
|
@ -2,7 +2,9 @@ SRC += src/map/scl/scl.c \
|
|||
src/map/scl/sclBuffer.c \
|
||||
src/map/scl/sclBufSize.c \
|
||||
src/map/scl/sclDnsize.c \
|
||||
src/map/scl/sclLib.c \
|
||||
src/map/scl/sclLiberty.c \
|
||||
src/map/scl/sclLibScl.c \
|
||||
src/map/scl/sclLibUtil.c \
|
||||
src/map/scl/sclLoad.c \
|
||||
src/map/scl/sclSize.c \
|
||||
src/map/scl/sclUpsize.c \
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ ABC_NAMESPACE_IMPL_START
|
|||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static int Scl_CommandReadLib ( Abc_Frame_t * pAbc, int argc, char **argv );
|
||||
static int Scl_CommandRead ( Abc_Frame_t * pAbc, int argc, char **argv );
|
||||
static int Scl_CommandWrite ( Abc_Frame_t * pAbc, int argc, char **argv );
|
||||
static int Scl_CommandPrintScl( Abc_Frame_t * pAbc, int argc, char **argv );
|
||||
|
|
@ -49,6 +50,29 @@ static int Scl_CommandPrintBuf( Abc_Frame_t * pAbc, int argc, char **argv );
|
|||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**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 []
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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 ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -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
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -662,6 +662,26 @@ static inline float Vec_FltFindMin( Vec_Flt_t * p )
|
|||
return Best;
|
||||
}
|
||||
|
||||
/**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.]
|
||||
|
|
|
|||
Loading…
Reference in New Issue