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

This commit is contained in:
Alan Mishchenko 2013-09-15 18:23:49 -07:00
parent d1fed2dd89
commit ff5d3591d1
14 changed files with 2244 additions and 618 deletions

View File

@ -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

View File

@ -990,6 +990,10 @@ void Abc_Init( Abc_Frame_t * pAbc )
if ( Sdm_ManCanRead() )
Sdm_ManRead();
{
// extern void Scl_LibertyTest();
// Scl_LibertyTest();
}
}
/**Function*************************************************************

View File

@ -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 )

View File

@ -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;

View File

@ -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 );

View File

@ -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) );

View File

@ -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 \

View File

@ -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;
}

View File

@ -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

View File

@ -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 ///
////////////////////////////////////////////////////////////////////////

608
src/map/scl/sclLibUtil.c Normal file
View 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

1358
src/map/scl/sclLiberty.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -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);

View File

@ -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.]