From fd28deefc7be69cec8a0f7933424a298d918bbdf Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Sun, 21 Jul 2013 17:55:15 -0700 Subject: Restructuring gate-sizing code trying to separate timing analysis. --- src/map/mpm/mpmGates.c | 3 +- src/map/scl/module.make | 4 +- src/map/scl/scl.c | 2 +- src/map/scl/sclBuff.c | 2 +- src/map/scl/sclDnsize.c | 3 +- src/map/scl/sclFile.c | 676 ------------------------------------ src/map/scl/sclInt.h | 468 ------------------------- src/map/scl/sclLib.c | 904 ++++++++++++++++++++++++++++++++++++++++++++++++ src/map/scl/sclLib.h | 458 ++++++++++++++++++++++++ src/map/scl/sclLoad.c | 60 +--- src/map/scl/sclMan.h | 397 --------------------- src/map/scl/sclSize.c | 572 ++++++++++++++++++++++++++++++ src/map/scl/sclSize.h | 405 ++++++++++++++++++++++ src/map/scl/sclTime.c | 573 ------------------------------ src/map/scl/sclTime.h | 288 +++++++++++++++ src/map/scl/sclUpsize.c | 3 +- src/map/scl/sclUtil.c | 174 +--------- 17 files changed, 2637 insertions(+), 2355 deletions(-) delete mode 100644 src/map/scl/sclFile.c delete mode 100644 src/map/scl/sclInt.h create mode 100644 src/map/scl/sclLib.c create mode 100644 src/map/scl/sclLib.h delete mode 100644 src/map/scl/sclMan.h create mode 100644 src/map/scl/sclSize.c create mode 100644 src/map/scl/sclSize.h delete mode 100644 src/map/scl/sclTime.c create mode 100644 src/map/scl/sclTime.h (limited to 'src') diff --git a/src/map/mpm/mpmGates.c b/src/map/mpm/mpmGates.c index d92be969..aa70e143 100644 --- a/src/map/mpm/mpmGates.c +++ b/src/map/mpm/mpmGates.c @@ -21,7 +21,8 @@ #include "mpmInt.h" #include "misc/st/st.h" #include "map/mio/mio.h" -#include "map/scl/sclInt.h" +#include "map/scl/sclSize.h" +#include "map/scl/sclTime.h" ABC_NAMESPACE_IMPL_START diff --git a/src/map/scl/module.make b/src/map/scl/module.make index d0fba6b0..82021af3 100644 --- a/src/map/scl/module.make +++ b/src/map/scl/module.make @@ -1,8 +1,8 @@ SRC += src/map/scl/scl.c \ src/map/scl/sclBuff.c \ src/map/scl/sclDnsize.c \ - src/map/scl/sclFile.c \ + src/map/scl/sclLib.c \ src/map/scl/sclLoad.c \ - src/map/scl/sclTime.c \ + src/map/scl/sclSize.c \ src/map/scl/sclUpsize.c \ src/map/scl/sclUtil.c diff --git a/src/map/scl/scl.c b/src/map/scl/scl.c index d6232d2f..cf1c0c4b 100644 --- a/src/map/scl/scl.c +++ b/src/map/scl/scl.c @@ -18,7 +18,7 @@ ***********************************************************************/ -#include "sclInt.h" +#include "sclSize.h" #include "base/main/mainInt.h" ABC_NAMESPACE_IMPL_START diff --git a/src/map/scl/sclBuff.c b/src/map/scl/sclBuff.c index 808cd1ec..0ae408d6 100644 --- a/src/map/scl/sclBuff.c +++ b/src/map/scl/sclBuff.c @@ -18,7 +18,7 @@ ***********************************************************************/ -#include "sclInt.h" +#include "sclSize.h" #include "map/mio/mio.h" ABC_NAMESPACE_IMPL_START diff --git a/src/map/scl/sclDnsize.c b/src/map/scl/sclDnsize.c index 3df64e80..13ab2822 100644 --- a/src/map/scl/sclDnsize.c +++ b/src/map/scl/sclDnsize.c @@ -18,8 +18,7 @@ ***********************************************************************/ -#include "sclInt.h" -#include "sclMan.h" +#include "sclSize.h" ABC_NAMESPACE_IMPL_START diff --git a/src/map/scl/sclFile.c b/src/map/scl/sclFile.c deleted file mode 100644 index a170b5c7..00000000 --- a/src/map/scl/sclFile.c +++ /dev/null @@ -1,676 +0,0 @@ -/**CFile**************************************************************** - - FileName [sclFile.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Standard-cell library representation.] - - Synopsis [Input/output procedures for simplified library representation.] - - Author [Alan Mishchenko, Niklas Een] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - August 24, 2012.] - - Revision [$Id: sclFile.c,v 1.0 2012/08/24 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "sclInt.h" -#include "map/mio/mio.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -extern void Extra_PrintHex( FILE * pFile, unsigned Sign[], int nBits ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Reading library from file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static void Abc_SclReadSurface( Vec_Str_t * vOut, int * pPos, SC_Surface * p ) -{ - Vec_Flt_t * vVec; - int i, j; - - for ( i = Vec_StrGetI(vOut, pPos); i != 0; i-- ) - Vec_FltPush( p->vIndex0, Vec_StrGetF(vOut, pPos) ); - - for ( i = Vec_StrGetI(vOut, pPos); i != 0; i-- ) - Vec_FltPush( p->vIndex1, Vec_StrGetF(vOut, pPos) ); - - for ( i = 0; i < Vec_FltSize(p->vIndex0); i++ ) - { - vVec = Vec_FltAlloc( Vec_FltSize(p->vIndex1) ); - Vec_PtrPush( p->vData, vVec ); - for ( j = 0; j < Vec_FltSize(p->vIndex1); j++ ) - Vec_FltPush( vVec, Vec_StrGetF(vOut, pPos) ); - } - - for ( i = 0; i < 3; i++ ) - p->approx[0][i] = Vec_StrGetF( vOut, pPos ); - for ( i = 0; i < 4; i++ ) - p->approx[1][i] = Vec_StrGetF( vOut, pPos ); - for ( i = 0; i < 6; i++ ) - p->approx[2][i] = Vec_StrGetF( vOut, pPos ); -} -static void Abc_SclReadLibrary( Vec_Str_t * vOut, int * pPos, SC_Lib * p ) -{ - int i, j, k, n; - int version = Vec_StrGetI( vOut, pPos ); - assert( version == 5 || version == ABC_SCL_CUR_VERSION ); // wrong version of the file - - // Read non-composite fields: - p->pName = Vec_StrGetS(vOut, pPos); - p->default_wire_load = Vec_StrGetS(vOut, pPos); - p->default_wire_load_sel = Vec_StrGetS(vOut, pPos); - p->default_max_out_slew = Vec_StrGetF(vOut, pPos); - - p->unit_time = Vec_StrGetI(vOut, pPos); - p->unit_cap_fst = Vec_StrGetF(vOut, pPos); - p->unit_cap_snd = Vec_StrGetI(vOut, pPos); - - // Read 'wire_load' vector: - for ( i = Vec_StrGetI(vOut, pPos); i != 0; i-- ) - { - SC_WireLoad * pWL = Abc_SclWireLoadAlloc(); - Vec_PtrPush( p->vWireLoads, pWL ); - - pWL->pName = Vec_StrGetS(vOut, pPos); - pWL->res = Vec_StrGetF(vOut, pPos); - pWL->cap = Vec_StrGetF(vOut, pPos); - - for ( j = Vec_StrGetI(vOut, pPos); j != 0; j-- ) - { - Vec_IntPush( pWL->vFanout, Vec_StrGetI(vOut, pPos) ); - Vec_FltPush( pWL->vLen, Vec_StrGetF(vOut, pPos) ); - } - } - - // Read 'wire_load_sel' vector: - for ( i = Vec_StrGetI(vOut, pPos); i != 0; i-- ) - { - SC_WireLoadSel * pWLS = Abc_SclWireLoadSelAlloc(); - Vec_PtrPush( p->vWireLoadSels, pWLS ); - - pWLS->pName = Vec_StrGetS(vOut, pPos); - for ( j = Vec_StrGetI(vOut, pPos); j != 0; j-- ) - { - Vec_FltPush( pWLS->vAreaFrom, Vec_StrGetF(vOut, pPos) ); - Vec_FltPush( pWLS->vAreaTo, Vec_StrGetF(vOut, pPos) ); - Vec_PtrPush( pWLS->vWireLoadModel, Vec_StrGetS(vOut, pPos) ); - } - } - - for ( i = Vec_StrGetI(vOut, pPos); i != 0; i-- ) - { - SC_Cell * pCell = Abc_SclCellAlloc(); - pCell->Id = Vec_PtrSize(p->vCells); - Vec_PtrPush( p->vCells, pCell ); - - pCell->pName = Vec_StrGetS(vOut, pPos); - pCell->area = Vec_StrGetF(vOut, pPos); - pCell->drive_strength = Vec_StrGetI(vOut, pPos); - - pCell->n_inputs = Vec_StrGetI(vOut, pPos); - pCell->n_outputs = Vec_StrGetI(vOut, pPos); - - for ( j = 0; j < pCell->n_inputs; j++ ) - { - SC_Pin * pPin = Abc_SclPinAlloc(); - Vec_PtrPush( pCell->vPins, pPin ); - - pPin->dir = sc_dir_Input; - pPin->pName = Vec_StrGetS(vOut, pPos); - pPin->rise_cap = Vec_StrGetF(vOut, pPos); - pPin->fall_cap = Vec_StrGetF(vOut, pPos); - } - - for ( j = 0; j < pCell->n_outputs; j++ ) - { - SC_Pin * pPin = Abc_SclPinAlloc(); - Vec_PtrPush( pCell->vPins, pPin ); - - pPin->dir = sc_dir_Output; - pPin->pName = Vec_StrGetS(vOut, pPos); - pPin->max_out_cap = Vec_StrGetF(vOut, pPos); - pPin->max_out_slew = Vec_StrGetF(vOut, pPos); - - k = Vec_StrGetI(vOut, pPos); - assert( k == pCell->n_inputs ); - - // read function - if ( version == 5 ) - { - // formula is not given - assert( Vec_WrdSize(pPin->vFunc) == 0 ); - Vec_WrdGrow( pPin->vFunc, Abc_Truth6WordNum(pCell->n_inputs) ); - for ( k = 0; k < Vec_WrdCap(pPin->vFunc); k++ ) - Vec_WrdPush( pPin->vFunc, Vec_StrGetW(vOut, pPos) ); - } - else - { - // (possibly empty) formula is always given - assert( version == ABC_SCL_CUR_VERSION ); - assert( pPin->func_text == NULL ); - pPin->func_text = Vec_StrGetS(vOut, pPos); - if ( pPin->func_text[0] == 0 ) - { - // formula is not given - read truth table - ABC_FREE( pPin->func_text ); - assert( Vec_WrdSize(pPin->vFunc) == 0 ); - Vec_WrdGrow( pPin->vFunc, Abc_Truth6WordNum(pCell->n_inputs) ); - for ( k = 0; k < Vec_WrdCap(pPin->vFunc); k++ ) - Vec_WrdPush( pPin->vFunc, Vec_StrGetW(vOut, pPos) ); - } - else - { - // formula is given - derive truth table - SC_Pin * pPin2; - Vec_Ptr_t * vNames; - // collect input names - vNames = Vec_PtrAlloc( pCell->n_inputs ); - SC_CellForEachPinIn( pCell, pPin2, n ) - Vec_PtrPush( vNames, pPin2->pName ); - // derive truth table - assert( Vec_WrdSize(pPin->vFunc) == 0 ); - Vec_WrdFree( pPin->vFunc ); - pPin->vFunc = Mio_ParseFormulaTruth( pPin->func_text, (char **)Vec_PtrArray(vNames), pCell->n_inputs ); - Vec_PtrFree( vNames ); - } - } - - // Read 'rtiming': (pin-to-pin timing tables for this particular output) - for ( k = 0; k < pCell->n_inputs; k++ ) - { - SC_Timings * pRTime = Abc_SclTimingsAlloc(); - Vec_PtrPush( pPin->vRTimings, pRTime ); - - pRTime->pName = Vec_StrGetS(vOut, pPos); - n = Vec_StrGetI(vOut, pPos); assert( n <= 1 ); - if ( n == 1 ) - { - SC_Timing * pTime = Abc_SclTimingAlloc(); - Vec_PtrPush( pRTime->vTimings, pTime ); - - pTime->tsense = (SC_TSense)Vec_StrGetI(vOut, pPos); - Abc_SclReadSurface( vOut, pPos, pTime->pCellRise ); - Abc_SclReadSurface( vOut, pPos, pTime->pCellFall ); - Abc_SclReadSurface( vOut, pPos, pTime->pRiseTrans ); - Abc_SclReadSurface( vOut, pPos, pTime->pFallTrans ); - } - else - assert( Vec_PtrSize(pPin->vRTimings) == 0 ); - } - } - } -} -SC_Lib * Abc_SclRead( char * pFileName ) -{ - SC_Lib * p; - FILE * pFile; - Vec_Str_t * vOut; - int nFileSize, Pos = 0; - - pFile = fopen( pFileName, "rb" ); - if ( pFile == NULL ) - { - printf( "Cannot open file \"%s\" for reading.\n", pFileName ); - return NULL; - } - // get the file size, in bytes - fseek( pFile, 0, SEEK_END ); - nFileSize = ftell( pFile ); - rewind( pFile ); - // load the contents - vOut = Vec_StrAlloc( nFileSize ); - vOut->nSize = vOut->nCap; - assert( nFileSize == Vec_StrSize(vOut) ); - nFileSize = fread( Vec_StrArray(vOut), 1, Vec_StrSize(vOut), pFile ); - assert( nFileSize == Vec_StrSize(vOut) ); - fclose( pFile ); - // read the library - p = Abc_SclLibAlloc(); - Abc_SclReadLibrary( vOut, &Pos, p ); - assert( Pos == Vec_StrSize(vOut) ); - 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************************************************************* - - Synopsis [Writing library into file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static void Abc_SclWriteSurface( Vec_Str_t * vOut, SC_Surface * p ) -{ - Vec_Flt_t * vVec; - float Entry; - int i, k; - - Vec_StrPutI( vOut, Vec_FltSize(p->vIndex0) ); - Vec_FltForEachEntry( p->vIndex0, Entry, i ) - Vec_StrPutF( vOut, Entry ); - - Vec_StrPutI( vOut, Vec_FltSize(p->vIndex1) ); - Vec_FltForEachEntry( p->vIndex1, Entry, i ) - Vec_StrPutF( vOut, Entry ); - - Vec_PtrForEachEntry( Vec_Flt_t *, p->vData, vVec, i ) - Vec_FltForEachEntry( vVec, Entry, k ) - Vec_StrPutF( vOut, Entry ); - - for ( i = 0; i < 3; i++ ) - Vec_StrPutF( vOut, p->approx[0][i] ); - for ( i = 0; i < 4; i++ ) - Vec_StrPutF( vOut, p->approx[1][i] ); - for ( i = 0; i < 6; i++ ) - Vec_StrPutF( vOut, p->approx[2][i] ); -} -static void Abc_SclWriteLibrary( Vec_Str_t * vOut, SC_Lib * p ) -{ - SC_WireLoad * pWL; - SC_WireLoadSel * pWLS; - SC_Cell * pCell; - SC_Pin * pPin; - int n_valid_cells; - int i, j, k; - - Vec_StrPutI( vOut, ABC_SCL_CUR_VERSION ); - - // Write non-composite fields: - Vec_StrPutS( vOut, p->pName ); - Vec_StrPutS( vOut, p->default_wire_load ); - Vec_StrPutS( vOut, p->default_wire_load_sel ); - Vec_StrPutF( vOut, p->default_max_out_slew ); - - assert( p->unit_time >= 0 ); - assert( p->unit_cap_snd >= 0 ); - Vec_StrPutI( vOut, p->unit_time ); - Vec_StrPutF( vOut, p->unit_cap_fst ); - Vec_StrPutI( vOut, p->unit_cap_snd ); - - // Write 'wire_load' vector: - Vec_StrPutI( vOut, Vec_PtrSize(p->vWireLoads) ); - SC_LibForEachWireLoad( p, pWL, i ) - { - Vec_StrPutS( vOut, pWL->pName ); - Vec_StrPutF( vOut, pWL->res ); - Vec_StrPutF( vOut, pWL->cap ); - - Vec_StrPutI( vOut, Vec_IntSize(pWL->vFanout) ); - for ( j = 0; j < Vec_IntSize(pWL->vFanout); j++ ) - { - Vec_StrPutI( vOut, Vec_IntEntry(pWL->vFanout, j) ); - Vec_StrPutF( vOut, Vec_FltEntry(pWL->vLen, j) ); - } - } - - // Write 'wire_load_sel' vector: - Vec_StrPutI( vOut, Vec_PtrSize(p->vWireLoadSels) ); - SC_LibForEachWireLoadSel( p, pWLS, i ) - { - Vec_StrPutS( vOut, pWLS->pName ); - Vec_StrPutI( vOut, Vec_FltSize(pWLS->vAreaFrom) ); - for ( j = 0; j < Vec_FltSize(pWLS->vAreaFrom); j++) - { - Vec_StrPutF( vOut, Vec_FltEntry(pWLS->vAreaFrom, j) ); - Vec_StrPutF( vOut, Vec_FltEntry(pWLS->vAreaTo, j) ); - Vec_StrPutS( vOut, (char *)Vec_PtrEntry(pWLS->vWireLoadModel, j) ); - } - } - - // Write 'cells' vector: - n_valid_cells = 0; - SC_LibForEachCell( p, pCell, i ) - if ( !(pCell->seq || pCell->unsupp) ) - n_valid_cells++; - - Vec_StrPutI( vOut, n_valid_cells ); - SC_LibForEachCell( p, pCell, i ) - { - if ( pCell->seq || pCell->unsupp ) - continue; - - Vec_StrPutS( vOut, pCell->pName ); - Vec_StrPutF( vOut, pCell->area ); - Vec_StrPutI( vOut, pCell->drive_strength ); - - // Write 'pins': (sorted at this point; first inputs, then outputs) - Vec_StrPutI( vOut, pCell->n_inputs); - Vec_StrPutI( vOut, pCell->n_outputs); - - SC_CellForEachPinIn( pCell, pPin, j ) - { - assert(pPin->dir == sc_dir_Input); - Vec_StrPutS( vOut, pPin->pName ); - Vec_StrPutF( vOut, pPin->rise_cap ); - Vec_StrPutF( vOut, pPin->fall_cap ); - } - - SC_CellForEachPinOut( pCell, pPin, j ) - { - SC_Timings * pRTime; - word uWord; - - assert(pPin->dir == sc_dir_Output); - Vec_StrPutS( vOut, pPin->pName ); - Vec_StrPutF( vOut, pPin->max_out_cap ); - Vec_StrPutF( vOut, pPin->max_out_slew ); - - // write function - if ( pPin->func_text == NULL ) - { - // formula is not given - write empty string - Vec_StrPutS( vOut, "" ); - // write truth table - assert( Vec_WrdSize(pPin->vFunc) == Abc_Truth6WordNum(pCell->n_inputs) ); - Vec_StrPutI( vOut, pCell->n_inputs ); - Vec_WrdForEachEntry( pPin->vFunc, uWord, k ) // -- 'size = 1u << (n_vars - 6)' - Vec_StrPutW( vOut, uWord ); // -- 64-bit number, written uncompressed (low-byte first) - } - else // formula is given - Vec_StrPutS( vOut, pPin->func_text ); - - // Write 'rtiming': (pin-to-pin timing tables for this particular output) - assert( Vec_PtrSize(pPin->vRTimings) == pCell->n_inputs ); - SC_PinForEachRTiming( pPin, pRTime, k ) - { - Vec_StrPutS( vOut, pRTime->pName ); - Vec_StrPutI( vOut, Vec_PtrSize(pRTime->vTimings) ); - // -- NOTE! After post-processing, the size of the 'rtiming[k]' vector is either - // 0 or 1 (in static timing, we have merged all tables to get the worst case). - // The case with size 0 should only occur for multi-output gates. - if ( Vec_PtrSize(pRTime->vTimings) == 1 ) - { - SC_Timing * pTime = (SC_Timing *)Vec_PtrEntry( pRTime->vTimings, 0 ); - // -- NOTE! We don't need to save 'related_pin' string because we have sorted - // the elements on input pins. - Vec_StrPutI( vOut, (int)pTime->tsense); - Abc_SclWriteSurface( vOut, pTime->pCellRise ); - Abc_SclWriteSurface( vOut, pTime->pCellFall ); - Abc_SclWriteSurface( vOut, pTime->pRiseTrans ); - Abc_SclWriteSurface( vOut, pTime->pFallTrans ); - } - else - assert( Vec_PtrSize(pRTime->vTimings) == 0 ); - } - } - } -} -void Abc_SclWrite( char * pFileName, SC_Lib * p ) -{ - Vec_Str_t * vOut; - vOut = Vec_StrAlloc( 10000 ); - Abc_SclWriteLibrary( vOut, p ); - if ( Vec_StrSize(vOut) > 0 ) - { - FILE * pFile = fopen( pFileName, "wb" ); - if ( pFile == NULL ) - printf( "Cannot open file \"%s\" for writing.\n", pFileName ); - else - { - fwrite( Vec_StrArray(vOut), 1, Vec_StrSize(vOut), pFile ); - fclose( pFile ); - } - } - Vec_StrFree( vOut ); -} -void Abc_SclSave( char * pFileName, SC_Lib * pScl ) -{ - if ( pScl == NULL ) return; - Abc_SclWrite( pFileName, pScl ); -} - - -/**Function************************************************************* - - Synopsis [Writing library into text file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static void Abc_SclWriteSurfaceText( FILE * s, SC_Surface * p ) -{ - Vec_Flt_t * vVec; - float Entry; - int i, k; - - fprintf( s, " index_1(\"" ); - Vec_FltForEachEntry( p->vIndex0, Entry, i ) - fprintf( s, "%f%s", Entry, i == Vec_FltSize(p->vIndex0)-1 ? "":", " ); - fprintf( s, "\");\n" ); - - fprintf( s, " index_2(\"" ); - Vec_FltForEachEntry( p->vIndex1, Entry, i ) - fprintf( s, "%f%s", Entry, i == Vec_FltSize(p->vIndex1)-1 ? "":", " ); - fprintf( s, "\");\n" ); - - fprintf( s, " values (\"" ); - Vec_PtrForEachEntry( Vec_Flt_t *, p->vData, vVec, i ) - { - Vec_FltForEachEntry( vVec, Entry, k ) - fprintf( s, "%f%s", Entry, i == Vec_PtrSize(p->vData)-1 && k == Vec_FltSize(vVec)-1 ? "\");":", " ); - if ( i == Vec_PtrSize(p->vData)-1 ) - fprintf( s, "\n" ); - else - { - fprintf( s, "\\\n" ); - fprintf( s, " " ); - } - } -/* - fprintf( s, " approximations: \n" ); - fprintf( s, " " ); - for ( i = 0; i < 3; i++ ) - fprintf( s, "%f ", p->approx[0][i] ); - fprintf( s, "\n" ); - fprintf( s, " " ); - for ( i = 0; i < 4; i++ ) - fprintf( s, "%f ", p->approx[1][i] ); - fprintf( s, "\n" ); - fprintf( s, " " ); - for ( i = 0; i < 6; i++ ) - fprintf( s, "%f ", p->approx[2][i] ); - fprintf( s, "\n" ); - fprintf( s, " \n" ); -*/ -} -static void Abc_SclWriteLibraryText( FILE * s, SC_Lib * p ) -{ - SC_WireLoad * pWL; - SC_WireLoadSel * pWLS; - SC_Cell * pCell; - SC_Pin * pPin; - int n_valid_cells; - int i, j, k; - -// fprintf( s, "%d", ABC_SCL_CUR_VERSION ); - fprintf( s, "library(%s) {\n\n", p->pName ); - if ( p->default_wire_load && strlen(p->default_wire_load) ) - fprintf( s, " default_wire_load : \"%s\";\n", p->default_wire_load ); - if ( p->default_wire_load_sel && strlen(p->default_wire_load_sel) ) - fprintf( s, " default_wire_load_selection : \"%s\";\n", p->default_wire_load_sel ); - if ( p->default_max_out_slew != -1 ) - fprintf( s, " default_max_transition : %f;\n", p->default_max_out_slew ); - if ( p->unit_time == 9 ) - fprintf( s, " time_unit : \"1ns\";\n" ); - else if ( p->unit_time == 10 ) - fprintf( s, " time_unit : \"100ps\";\n" ); - else if ( p->unit_time == 11 ) - fprintf( s, " time_unit : \"10ps\";\n" ); - else if ( p->unit_time == 12 ) - fprintf( s, " time_unit : \"1ps\";\n" ); - else assert( 0 ); - fprintf( s, " capacitive_load_unit(%.1f,%s);\n", p->unit_cap_fst, p->unit_cap_snd == 12 ? "pf" : "ff" ); - fprintf( s, "\n" ); - - // Write 'wire_load' vector: - 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 ); - 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" ); - } - - // Write 'wire_load_sel' vector: - SC_LibForEachWireLoadSel( p, pWLS, i ) - { - fprintf( s, " wire_load_selection(\"%s\") {\n", pWLS->pName ); - for ( j = 0; j < Vec_FltSize(pWLS->vAreaFrom); j++) - fprintf( s, " wire_load_from_area( %f, %f, \"%s\" );\n", - Vec_FltEntry(pWLS->vAreaFrom, j), - Vec_FltEntry(pWLS->vAreaTo, j), - (char *)Vec_PtrEntry(pWLS->vWireLoadModel, j) ); - fprintf( s, " }\n\n" ); - } - - // Write 'cells' vector: - n_valid_cells = 0; - SC_LibForEachCell( p, pCell, i ) - if ( !(pCell->seq || pCell->unsupp) ) - n_valid_cells++; - - SC_LibForEachCell( p, pCell, i ) - { - if ( pCell->seq || pCell->unsupp ) - continue; - - fprintf( s, "\n" ); - fprintf( s, " cell(%s) {\n", pCell->pName ); - fprintf( s, " /* n_inputs = %d n_outputs = %d */\n", pCell->n_inputs, pCell->n_outputs ); - fprintf( s, " area : %f;\n", pCell->area ); - fprintf( s, " drive_strength : %d;\n", pCell->drive_strength ); - - SC_CellForEachPinIn( pCell, pPin, j ) - { - assert(pPin->dir == sc_dir_Input); - fprintf( s, " pin(%s) {\n", pPin->pName ); - fprintf( s, " direction : %s;\n", "input" ); - fprintf( s, " fall_capacitance : %f;\n", pPin->fall_cap ); - fprintf( s, " rise_capacitance : %f;\n", pPin->rise_cap ); - fprintf( s, " }\n" ); - } - - SC_CellForEachPinOut( pCell, pPin, j ) - { - SC_Timings * pRTime; -// word uWord; - assert(pPin->dir == sc_dir_Output); - fprintf( s, " pin(%s) {\n", pPin->pName ); - fprintf( s, " direction : %s;\n", "output" ); - fprintf( s, " max_capacitance : %f;\n", pPin->max_out_cap ); - fprintf( s, " max_transition : %f;\n", pPin->max_out_slew ); - fprintf( s, " function : \"%s\";\n", pPin->func_text ? pPin->func_text : "?" ); - fprintf( s, " /* truth table = " ); - Extra_PrintHex( s, (unsigned *)Vec_WrdArray(pPin->vFunc), pCell->n_inputs ); - fprintf( s, " */\n" ); - - // Write 'rtiming': (pin-to-pin timing tables for this particular output) - assert( Vec_PtrSize(pPin->vRTimings) == pCell->n_inputs ); - SC_PinForEachRTiming( pPin, pRTime, k ) - { - if ( Vec_PtrSize(pRTime->vTimings) == 1 ) - { - SC_Timing * pTime = (SC_Timing *)Vec_PtrEntry( pRTime->vTimings, 0 ); - fprintf( s, " timing() {\n" ); - fprintf( s, " related_pin : \"%s\"\n", pRTime->pName ); - if ( pTime->tsense == sc_ts_Pos ) - fprintf( s, " timing_sense : positive_unate;\n" ); - else if ( pTime->tsense == sc_ts_Neg ) - fprintf( s, " timing_sense : negative_unate;\n" ); - else if ( pTime->tsense == sc_ts_Non ) - fprintf( s, " timing_sense : non_unate;\n" ); - else assert( 0 ); - - fprintf( s, " cell_rise() {\n" ); - Abc_SclWriteSurfaceText( s, pTime->pCellRise ); - fprintf( s, " }\n" ); - - fprintf( s, " cell_fall() {\n" ); - Abc_SclWriteSurfaceText( s, pTime->pCellFall ); - fprintf( s, " }\n" ); - - fprintf( s, " rise_transition() {\n" ); - Abc_SclWriteSurfaceText( s, pTime->pRiseTrans ); - fprintf( s, " }\n" ); - - fprintf( s, " fall_transition() {\n" ); - Abc_SclWriteSurfaceText( s, pTime->pFallTrans ); - fprintf( s, " }\n" ); - fprintf( s, " }\n" ); - } - else - assert( Vec_PtrSize(pRTime->vTimings) == 0 ); - } - fprintf( s, " }\n" ); - } - fprintf( s, " }\n" ); - } - fprintf( s, "}\n\n" ); -} -void Abc_SclWriteText( char * pFileName, SC_Lib * p ) -{ - FILE * pFile = fopen( pFileName, "wb" ); - if ( pFile == NULL ) - printf( "Cannot open text file \"%s\" for writing.\n", pFileName ); - else - { - Abc_SclWriteLibraryText( pFile, p ); - fclose( pFile ); - } -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/map/scl/sclInt.h b/src/map/scl/sclInt.h deleted file mode 100644 index 58a2ca07..00000000 --- a/src/map/scl/sclInt.h +++ /dev/null @@ -1,468 +0,0 @@ -/**CFile**************************************************************** - - FileName [sclInt.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Standard-cell library representation.] - - Synopsis [Simplified library representation for STA.] - - Author [Alan Mishchenko, Niklas Een] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - August 24, 2012.] - - Revision [$Id: sclInt.h,v 1.0 2012/08/24 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef ABC__map__scl__sclInt_h -#define ABC__map__scl__sclInt_h - - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -#include -#include -#include -#include -#include - -#include "base/abc/abc.h" - -ABC_NAMESPACE_HEADER_START - - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -#define ABC_SCL_CUR_VERSION 6 - -typedef enum -{ - sc_dir_NULL, - sc_dir_Input, - sc_dir_Output, - sc_dir_InOut, - sc_dir_Internal, -} SC_Dir; - -typedef enum // -- timing sense, positive-, negative- or non-unate -{ - sc_ts_NULL, - sc_ts_Pos, - sc_ts_Neg, - sc_ts_Non, -} SC_TSense; - -typedef struct SC_SizePars_ SC_SizePars; -struct SC_SizePars_ -{ - int nIters; - int nIterNoChange; - int Window; // used for upsizing - int Ratio; // used for upsizing - int Notches; - int DelayUser; - int DelayGap; - int TimeOut; - int fUseDept; - int fDumpStats; - int fUseWireLoads; - int fVerbose; - int fVeryVerbose; -}; - -//////////////////////////////////////////////////////////////////////// -/// STRUCTURE DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -typedef struct SC_WireLoad_ SC_WireLoad; -typedef struct SC_WireLoadSel_ SC_WireLoadSel; -typedef struct SC_TableTempl_ SC_TableTempl; -typedef struct SC_Surface_ SC_Surface; -typedef struct SC_Timing_ SC_Timing; -typedef struct SC_Timings_ SC_Timings; -typedef struct SC_Pin_ SC_Pin; -typedef struct SC_Cell_ SC_Cell; -typedef struct SC_Lib_ SC_Lib; - -struct SC_WireLoad_ -{ - char * pName; - float res; // (currently not used) - float cap; // }- multiply estimation in 'fanout_len[].snd' with this value - Vec_Int_t * vFanout; // Vec > -- pairs '(#fanouts, est-wire-len)' - Vec_Flt_t * vLen; -}; - -struct SC_WireLoadSel_ -{ - char * pName; - Vec_Flt_t * vAreaFrom; // Vec > -- triplets '(from-area, upto-area, wire-load-model)'; range is [from, upto[ - Vec_Flt_t * vAreaTo; - Vec_Ptr_t * vWireLoadModel; -}; - -struct SC_TableTempl_ -{ - char * pName; - Vec_Ptr_t * vVars; // Vec -- name of variable (numbered from 0, not 1 as in the Liberty file) - Vec_Ptr_t * vIndex; // Vec > -- this is the point of measurement in table for the given variable -}; - -struct SC_Surface_ -{ - char * pName; - Vec_Flt_t * vIndex0; // Vec -- correspondes to "index_1" in the liberty file (for timing: slew) - Vec_Flt_t * vIndex1; // Vec -- correspondes to "index_2" in the liberty file (for timing: load) - Vec_Ptr_t * vData; // Vec > -- 'data[i0][i1]' gives value at '(index0[i0], index1[i1])' - float approx[3][6]; -}; - -struct SC_Timing_ -{ - char * related_pin; // -- related pin - SC_TSense tsense; // -- timing sense (positive_unate, negative_unate, non_unate) - char * when_text; // -- logic condition on inputs triggering this delay model for the output (currently not used) - SC_Surface * pCellRise; // -- Used to compute pin-to-pin delay - SC_Surface * pCellFall; - SC_Surface * pRiseTrans; // -- Used to compute output slew - SC_Surface * pFallTrans; -}; - -struct SC_Timings_ -{ - char * pName; // -- the 'related_pin' field - Vec_Ptr_t * vTimings; // structures of type SC_Timing -}; - -struct SC_Pin_ -{ - char * pName; - SC_Dir dir; - float cap; // -- this value is used if 'rise_cap' and 'fall_cap' is missing (copied by 'postProcess()'). (not used) - float rise_cap; // }- used for input pins ('cap' too). - float fall_cap; // } - float max_out_cap; // } (not used) - float max_out_slew; // }- used only for output pins (max values must not be exceeded or else mapping is illegal) (not used) - char * func_text; // } - Vec_Wrd_t * vFunc; // } - Vec_Ptr_t * vRTimings; // -- for output pins -}; - -struct SC_Cell_ -{ - char * pName; - int Id; - int seq; // -- set to TRUE by parser if a sequential element - int unsupp; // -- set to TRUE by parser if cell contains information we cannot handle - float area; - int drive_strength; // -- some library files provide this field (currently unused, but may be a good hint for sizing) (not used) - Vec_Ptr_t * vPins; // NamedSet - int n_inputs; // -- 'pins[0 .. n_inputs-1]' are input pins - int n_outputs; // -- 'pins[n_inputs .. n_inputs+n_outputs-1]' are output pins - SC_Cell * pNext; // same-functionality cells linked into a ring by area - SC_Cell * pPrev; // same-functionality cells linked into a ring by area - int Order; // order of the gate in the list -}; - -struct SC_Lib_ -{ - char * pName; - 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) - int unit_time; // -- Valid 9..12. Unit is '10^(-val)' seconds (e.g. 9=1ns, 10=100ps, 11=10ps, 12=1ps) - float unit_cap_fst; // -- First part is a multiplier, second either 12 or 15 for 'pf' or 'ff'. - int unit_cap_snd; - Vec_Ptr_t * vWireLoads; // NamedSet - Vec_Ptr_t * vWireLoadSels; // NamedSet - Vec_Ptr_t * vTempls; // NamedSet - Vec_Ptr_t * vCells; // NamedSet - Vec_Ptr_t * vCellClasses; // NamedSet - int * pBins; // hashing gateName -> gateId - int nBins; -}; - -//////////////////////////////////////////////////////////////////////// -/// GLOBAL VARIABLES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -static inline SC_Cell * SC_LibCell( SC_Lib * p, int i ) { return (SC_Cell *)Vec_PtrEntry(p->vCells, i); } -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 double SC_LibCapFf( SC_Lib * p, double cap ) { return cap * p->unit_cap_fst * pow(10.0, 15 - p->unit_cap_snd); } -static inline double SC_LibCapFromFf( SC_Lib * p, double cap ) { return cap / p->unit_cap_fst / pow(10.0, 15 - p->unit_cap_snd); } -static inline double SC_LibTimePs( SC_Lib * p, double time ) { return time * pow(10.0, 12 - p->unit_time); } -static inline double SC_LibTimeFromPs( SC_Lib * p, double ps ) { return ps / pow(10.0, 12 - p->unit_time); } - -#define SC_LibForEachCell( p, pCell, i ) Vec_PtrForEachEntry( SC_Cell *, p->vCells, pCell, i ) -#define SC_LibForEachCellClass( p, pCell, i ) Vec_PtrForEachEntry( SC_Cell *, p->vCellClasses, pCell, i ) -#define SC_LibForEachWireLoad( p, pWL, i ) Vec_PtrForEachEntry( SC_WireLoad *, p->vWireLoads, pWL, i ) -#define SC_LibForEachWireLoadSel( p, pWLS, i ) Vec_PtrForEachEntry( SC_WireLoadSel *, p->vWireLoadSels, pWLS, i ) -#define SC_LibForEachTempl( p, pTempl, i ) Vec_PtrForEachEntry( SC_TableTempl *, p->vTempls, pTempl, i ) -#define SC_CellForEachPin( p, pPin, i ) Vec_PtrForEachEntry( SC_Pin *, p->vPins, pPin, i ) -#define SC_CellForEachPinIn( p, pPin, i ) Vec_PtrForEachEntryStop( SC_Pin *, p->vPins, pPin, i, p->n_inputs ) -#define SC_CellForEachPinOut( p, pPin, i ) Vec_PtrForEachEntryStart( SC_Pin *, p->vPins, pPin, i, p->n_inputs ) -#define SC_RingForEachCell( pRing, pCell, i ) for ( i = 0, pCell = pRing; i == 0 || pCell != pRing; pCell = pCell->pNext, i++ ) -#define SC_RingForEachCellRev( pRing, pCell, i ) for ( i = 0, pCell = pRing; i == 0 || pCell != pRing; pCell = pCell->pPrev, i++ ) -#define SC_PinForEachRTiming( p, pRTime, i ) Vec_PtrForEachEntry( SC_Timings *, p->vRTimings, pRTime, i ) - - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Constructors of the library data-structures.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline SC_WireLoad * Abc_SclWireLoadAlloc() -{ - SC_WireLoad * p; - p = ABC_CALLOC( SC_WireLoad, 1 ); - p->vFanout = Vec_IntAlloc( 0 ); - p->vLen = Vec_FltAlloc( 0 ); - return p; -} -static inline SC_WireLoadSel * Abc_SclWireLoadSelAlloc() -{ - SC_WireLoadSel * p; - p = ABC_CALLOC( SC_WireLoadSel, 1 ); - p->vAreaFrom = Vec_FltAlloc( 0 ); - p->vAreaTo = Vec_FltAlloc( 0 ); - p->vWireLoadModel = Vec_PtrAlloc( 0 ); - return p; -} -static inline SC_TableTempl * Abc_SclTableTemplAlloc() -{ - SC_TableTempl * p; - p = ABC_CALLOC( SC_TableTempl, 1 ); - p->vVars = Vec_PtrAlloc( 0 ); - p->vIndex = Vec_PtrAlloc( 0 ); - return p; -} -static inline SC_Surface * Abc_SclSurfaceAlloc() -{ - SC_Surface * p; - p = ABC_CALLOC( SC_Surface, 1 ); - p->vIndex0 = Vec_FltAlloc( 0 ); - p->vIndex1 = Vec_FltAlloc( 0 ); - p->vData = Vec_PtrAlloc( 0 ); - return p; -} -static inline SC_Timing * Abc_SclTimingAlloc() -{ - SC_Timing * p; - p = ABC_CALLOC( SC_Timing, 1 ); - p->pCellRise = Abc_SclSurfaceAlloc(); - p->pCellFall = Abc_SclSurfaceAlloc(); - p->pRiseTrans = Abc_SclSurfaceAlloc(); - p->pFallTrans = Abc_SclSurfaceAlloc(); - return p; -} -static inline SC_Timings * Abc_SclTimingsAlloc() -{ - SC_Timings * p; - p = ABC_CALLOC( SC_Timings, 1 ); - p->vTimings = Vec_PtrAlloc( 0 ); - return p; -} -static inline SC_Pin * Abc_SclPinAlloc() -{ - SC_Pin * p; - p = ABC_CALLOC( SC_Pin, 1 ); - p->max_out_slew = -1; - p->vFunc = Vec_WrdAlloc( 0 ); - p->vRTimings = Vec_PtrAlloc( 0 ); - return p; -} -static inline SC_Cell * Abc_SclCellAlloc() -{ - SC_Cell * p; - p = ABC_CALLOC( SC_Cell, 1 ); - p->vPins = Vec_PtrAlloc( 0 ); - return p; -} -static inline SC_Lib * Abc_SclLibAlloc() -{ - SC_Lib * p; - p = ABC_CALLOC( SC_Lib, 1 ); - p->default_max_out_slew = -1; - p->unit_time = 9; - p->unit_cap_fst = 1; - p->unit_cap_snd = 12; - p->vWireLoads = Vec_PtrAlloc( 0 ); - p->vWireLoadSels = Vec_PtrAlloc( 0 ); - p->vTempls = Vec_PtrAlloc( 0 ); - p->vCells = Vec_PtrAlloc( 0 ); - p->vCellClasses = Vec_PtrAlloc( 0 ); - return p; -} - - -/**Function************************************************************* - - Synopsis [Destructors of the library data-structures.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Abc_SclWireLoadFree( SC_WireLoad * p ) -{ - Vec_IntFree( p->vFanout ); - Vec_FltFree( p->vLen ); - ABC_FREE( p->pName ); - ABC_FREE( p ); -} -static inline void Abc_SclWireLoadSelFree( SC_WireLoadSel * p ) -{ - Vec_FltFree( p->vAreaFrom ); - Vec_FltFree( p->vAreaTo ); - Vec_PtrFreeFree( p->vWireLoadModel ); - ABC_FREE( p->pName ); - ABC_FREE( p ); -} -static inline void Abc_SclTableTemplFree( SC_TableTempl * p ) -{ - Vec_PtrFreeFree( p->vVars ); - Vec_VecFree( (Vec_Vec_t *)p->vIndex ); - ABC_FREE( p->pName ); - ABC_FREE( p ); -} -static inline void Abc_SclSurfaceFree( SC_Surface * p ) -{ - Vec_FltFree( p->vIndex0 ); - Vec_FltFree( p->vIndex1 ); - Vec_VecFree( (Vec_Vec_t *)p->vData ); - ABC_FREE( p->pName ); - ABC_FREE( p ); -} -static inline void Abc_SclTimingFree( SC_Timing * p ) -{ - Abc_SclSurfaceFree( p->pCellRise ); - Abc_SclSurfaceFree( p->pCellFall ); - Abc_SclSurfaceFree( p->pRiseTrans ); - Abc_SclSurfaceFree( p->pFallTrans ); - ABC_FREE( p->related_pin ); - ABC_FREE( p->when_text ); - ABC_FREE( p ); -} -static inline void Abc_SclTimingsFree( SC_Timings * p ) -{ - SC_Timing * pTemp; - int i; - Vec_PtrForEachEntry( SC_Timing *, p->vTimings, pTemp, i ) - Abc_SclTimingFree( pTemp ); - Vec_PtrFree( p->vTimings ); - ABC_FREE( p->pName ); - ABC_FREE( p ); -} -static inline void Abc_SclPinFree( SC_Pin * p ) -{ - SC_Timings * pTemp; - int i; - SC_PinForEachRTiming( p, pTemp, i ) - Abc_SclTimingsFree( pTemp ); - Vec_PtrFree( p->vRTimings ); - Vec_WrdFree( p->vFunc ); - ABC_FREE( p->func_text ); - ABC_FREE( p->pName ); - ABC_FREE( p ); -} -static inline void Abc_SclCellFree( SC_Cell * p ) -{ - SC_Pin * pTemp; - int i; - SC_CellForEachPin( p, pTemp, i ) - Abc_SclPinFree( pTemp ); - Vec_PtrFree( p->vPins ); - ABC_FREE( p->pName ); - ABC_FREE( p ); -} -static inline void Abc_SclLibFree( SC_Lib * p ) -{ - SC_WireLoad * pWL; - SC_WireLoadSel * pWLS; - SC_TableTempl * pTempl; - SC_Cell * pCell; - int i; - SC_LibForEachWireLoad( p, pWL, i ) - Abc_SclWireLoadFree( pWL ); - Vec_PtrFree( p->vWireLoads ); - SC_LibForEachWireLoadSel( p, pWLS, i ) - Abc_SclWireLoadSelFree( pWLS ); - Vec_PtrFree( p->vWireLoadSels ); - SC_LibForEachTempl( p, pTempl, i ) - Abc_SclTableTemplFree( pTempl ); - Vec_PtrFree( p->vTempls ); - SC_LibForEachCell( p, pCell, i ) - Abc_SclCellFree( pCell ); - Vec_PtrFree( p->vCells ); - Vec_PtrFree( p->vCellClasses ); - ABC_FREE( p->pName ); - ABC_FREE( p->default_wire_load ); - ABC_FREE( p->default_wire_load_sel ); - ABC_FREE( p->pBins ); - ABC_FREE( p ); -} - - -/*=== sclBuff.c ===============================================================*/ -extern int Abc_SclCheckNtk( Abc_Ntk_t * p, int fVerbose ); -extern Abc_Ntk_t * Abc_SclPerformBuffering( Abc_Ntk_t * p, int Degree, int fVerbose ); -/*=== sclDnsize.c ===============================================================*/ -extern void Abc_SclDnsizePerform( SC_Lib * pLib, Abc_Ntk_t * pNtk, SC_SizePars * pPars ); -/*=== sclFile.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 ); -/*=== sclLoad.c ===============================================================*/ -extern SC_WireLoad * Abc_SclFindWireLoadModel( SC_Lib * p, float Area ); -/*=== sclTime.c ===============================================================*/ -extern void Abc_SclTimePerform( SC_Lib * pLib, Abc_Ntk_t * pNtk, int fUseWireLoads, int fShowAll, int fShort, int fDumpStats ); -extern void Abc_SclPrintBuffers( SC_Lib * pLib, Abc_Ntk_t * pNtk, int fVerbose ); -/*=== sclUpsize.c ===============================================================*/ -extern void Abc_SclUpsizePerform( SC_Lib * pLib, Abc_Ntk_t * pNtk, SC_SizePars * pPars ); -/*=== sclUtil.c ===============================================================*/ -extern void Abc_SclHashCells( SC_Lib * p ); -extern int Abc_SclCellFind( SC_Lib * p, char * pName ); -extern void Abc_SclLinkCells( SC_Lib * p ); -extern void Abc_SclPrintCells( SC_Lib * p ); -extern Vec_Int_t * Abc_SclManFindGates( SC_Lib * pLib, Abc_Ntk_t * p ); -extern void Abc_SclManSetGates( SC_Lib * pLib, Abc_Ntk_t * p, Vec_Int_t * vGates ); -extern void Abc_SclPrintGateSizes( SC_Lib * pLib, Abc_Ntk_t * p ); -extern void Abc_SclMinsizePerform( SC_Lib * pLib, Abc_Ntk_t * p, int fUseMax, int fVerbose ); - - -ABC_NAMESPACE_HEADER_END - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// diff --git a/src/map/scl/sclLib.c b/src/map/scl/sclLib.c new file mode 100644 index 00000000..d58c3477 --- /dev/null +++ b/src/map/scl/sclLib.c @@ -0,0 +1,904 @@ +/**CFile**************************************************************** + + FileName [sclLib.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Standard-cell library representation.] + + Synopsis [Standard cell library.] + + Author [Alan Mishchenko, Niklas Een] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - August 24, 2012.] + + Revision [$Id: sclLib.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 void Abc_SclReadSurface( Vec_Str_t * vOut, int * pPos, SC_Surface * p ) +{ + Vec_Flt_t * vVec; + int i, j; + + for ( i = Vec_StrGetI(vOut, pPos); i != 0; i-- ) + Vec_FltPush( p->vIndex0, Vec_StrGetF(vOut, pPos) ); + + for ( i = Vec_StrGetI(vOut, pPos); i != 0; i-- ) + Vec_FltPush( p->vIndex1, Vec_StrGetF(vOut, pPos) ); + + for ( i = 0; i < Vec_FltSize(p->vIndex0); i++ ) + { + vVec = Vec_FltAlloc( Vec_FltSize(p->vIndex1) ); + Vec_PtrPush( p->vData, vVec ); + for ( j = 0; j < Vec_FltSize(p->vIndex1); j++ ) + Vec_FltPush( vVec, Vec_StrGetF(vOut, pPos) ); + } + + for ( i = 0; i < 3; i++ ) + p->approx[0][i] = Vec_StrGetF( vOut, pPos ); + for ( i = 0; i < 4; i++ ) + p->approx[1][i] = Vec_StrGetF( vOut, pPos ); + for ( i = 0; i < 6; i++ ) + p->approx[2][i] = Vec_StrGetF( vOut, pPos ); +} +static void Abc_SclReadLibrary( Vec_Str_t * vOut, int * pPos, SC_Lib * p ) +{ + int i, j, k, n; + int version = Vec_StrGetI( vOut, pPos ); + assert( version == 5 || version == ABC_SCL_CUR_VERSION ); // wrong version of the file + + // Read non-composite fields: + p->pName = Vec_StrGetS(vOut, pPos); + p->default_wire_load = Vec_StrGetS(vOut, pPos); + p->default_wire_load_sel = Vec_StrGetS(vOut, pPos); + p->default_max_out_slew = Vec_StrGetF(vOut, pPos); + + p->unit_time = Vec_StrGetI(vOut, pPos); + p->unit_cap_fst = Vec_StrGetF(vOut, pPos); + p->unit_cap_snd = Vec_StrGetI(vOut, pPos); + + // Read 'wire_load' vector: + for ( i = Vec_StrGetI(vOut, pPos); i != 0; i-- ) + { + SC_WireLoad * pWL = Abc_SclWireLoadAlloc(); + Vec_PtrPush( p->vWireLoads, pWL ); + + pWL->pName = Vec_StrGetS(vOut, pPos); + pWL->res = Vec_StrGetF(vOut, pPos); + pWL->cap = Vec_StrGetF(vOut, pPos); + + for ( j = Vec_StrGetI(vOut, pPos); j != 0; j-- ) + { + Vec_IntPush( pWL->vFanout, Vec_StrGetI(vOut, pPos) ); + Vec_FltPush( pWL->vLen, Vec_StrGetF(vOut, pPos) ); + } + } + + // Read 'wire_load_sel' vector: + for ( i = Vec_StrGetI(vOut, pPos); i != 0; i-- ) + { + SC_WireLoadSel * pWLS = Abc_SclWireLoadSelAlloc(); + Vec_PtrPush( p->vWireLoadSels, pWLS ); + + pWLS->pName = Vec_StrGetS(vOut, pPos); + for ( j = Vec_StrGetI(vOut, pPos); j != 0; j-- ) + { + Vec_FltPush( pWLS->vAreaFrom, Vec_StrGetF(vOut, pPos) ); + Vec_FltPush( pWLS->vAreaTo, Vec_StrGetF(vOut, pPos) ); + Vec_PtrPush( pWLS->vWireLoadModel, Vec_StrGetS(vOut, pPos) ); + } + } + + for ( i = Vec_StrGetI(vOut, pPos); i != 0; i-- ) + { + SC_Cell * pCell = Abc_SclCellAlloc(); + pCell->Id = Vec_PtrSize(p->vCells); + Vec_PtrPush( p->vCells, pCell ); + + pCell->pName = Vec_StrGetS(vOut, pPos); + pCell->area = Vec_StrGetF(vOut, pPos); + pCell->drive_strength = Vec_StrGetI(vOut, pPos); + + pCell->n_inputs = Vec_StrGetI(vOut, pPos); + pCell->n_outputs = Vec_StrGetI(vOut, pPos); + + for ( j = 0; j < pCell->n_inputs; j++ ) + { + SC_Pin * pPin = Abc_SclPinAlloc(); + Vec_PtrPush( pCell->vPins, pPin ); + + pPin->dir = sc_dir_Input; + pPin->pName = Vec_StrGetS(vOut, pPos); + pPin->rise_cap = Vec_StrGetF(vOut, pPos); + pPin->fall_cap = Vec_StrGetF(vOut, pPos); + } + + for ( j = 0; j < pCell->n_outputs; j++ ) + { + SC_Pin * pPin = Abc_SclPinAlloc(); + Vec_PtrPush( pCell->vPins, pPin ); + + pPin->dir = sc_dir_Output; + pPin->pName = Vec_StrGetS(vOut, pPos); + pPin->max_out_cap = Vec_StrGetF(vOut, pPos); + pPin->max_out_slew = Vec_StrGetF(vOut, pPos); + + k = Vec_StrGetI(vOut, pPos); + assert( k == pCell->n_inputs ); + + // read function + if ( version == 5 ) + { + // formula is not given + assert( Vec_WrdSize(pPin->vFunc) == 0 ); + Vec_WrdGrow( pPin->vFunc, Abc_Truth6WordNum(pCell->n_inputs) ); + for ( k = 0; k < Vec_WrdCap(pPin->vFunc); k++ ) + Vec_WrdPush( pPin->vFunc, Vec_StrGetW(vOut, pPos) ); + } + else + { + // (possibly empty) formula is always given + assert( version == ABC_SCL_CUR_VERSION ); + assert( pPin->func_text == NULL ); + pPin->func_text = Vec_StrGetS(vOut, pPos); + if ( pPin->func_text[0] == 0 ) + { + // formula is not given - read truth table + ABC_FREE( pPin->func_text ); + assert( Vec_WrdSize(pPin->vFunc) == 0 ); + Vec_WrdGrow( pPin->vFunc, Abc_Truth6WordNum(pCell->n_inputs) ); + for ( k = 0; k < Vec_WrdCap(pPin->vFunc); k++ ) + Vec_WrdPush( pPin->vFunc, Vec_StrGetW(vOut, pPos) ); + } + else + { + // formula is given - derive truth table + SC_Pin * pPin2; + Vec_Ptr_t * vNames; + // collect input names + vNames = Vec_PtrAlloc( pCell->n_inputs ); + SC_CellForEachPinIn( pCell, pPin2, n ) + Vec_PtrPush( vNames, pPin2->pName ); + // derive truth table + assert( Vec_WrdSize(pPin->vFunc) == 0 ); + Vec_WrdFree( pPin->vFunc ); + pPin->vFunc = Mio_ParseFormulaTruth( pPin->func_text, (char **)Vec_PtrArray(vNames), pCell->n_inputs ); + Vec_PtrFree( vNames ); + } + } + + // Read 'rtiming': (pin-to-pin timing tables for this particular output) + for ( k = 0; k < pCell->n_inputs; k++ ) + { + SC_Timings * pRTime = Abc_SclTimingsAlloc(); + Vec_PtrPush( pPin->vRTimings, pRTime ); + + pRTime->pName = Vec_StrGetS(vOut, pPos); + n = Vec_StrGetI(vOut, pPos); assert( n <= 1 ); + if ( n == 1 ) + { + SC_Timing * pTime = Abc_SclTimingAlloc(); + Vec_PtrPush( pRTime->vTimings, pTime ); + + pTime->tsense = (SC_TSense)Vec_StrGetI(vOut, pPos); + Abc_SclReadSurface( vOut, pPos, pTime->pCellRise ); + Abc_SclReadSurface( vOut, pPos, pTime->pCellFall ); + Abc_SclReadSurface( vOut, pPos, pTime->pRiseTrans ); + Abc_SclReadSurface( vOut, pPos, pTime->pFallTrans ); + } + else + assert( Vec_PtrSize(pPin->vRTimings) == 0 ); + } + } + } +} +SC_Lib * Abc_SclRead( char * pFileName ) +{ + SC_Lib * p; + FILE * pFile; + Vec_Str_t * vOut; + int nFileSize, Pos = 0; + + pFile = fopen( pFileName, "rb" ); + if ( pFile == NULL ) + { + printf( "Cannot open file \"%s\" for reading.\n", pFileName ); + return NULL; + } + // get the file size, in bytes + fseek( pFile, 0, SEEK_END ); + nFileSize = ftell( pFile ); + rewind( pFile ); + // load the contents + vOut = Vec_StrAlloc( nFileSize ); + vOut->nSize = vOut->nCap; + assert( nFileSize == Vec_StrSize(vOut) ); + nFileSize = fread( Vec_StrArray(vOut), 1, Vec_StrSize(vOut), pFile ); + assert( nFileSize == Vec_StrSize(vOut) ); + fclose( pFile ); + // read the library + p = Abc_SclLibAlloc(); + Abc_SclReadLibrary( vOut, &Pos, p ); + assert( Pos == Vec_StrSize(vOut) ); + 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************************************************************* + + Synopsis [Writing library into file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static void Abc_SclWriteSurface( Vec_Str_t * vOut, SC_Surface * p ) +{ + Vec_Flt_t * vVec; + float Entry; + int i, k; + + Vec_StrPutI( vOut, Vec_FltSize(p->vIndex0) ); + Vec_FltForEachEntry( p->vIndex0, Entry, i ) + Vec_StrPutF( vOut, Entry ); + + Vec_StrPutI( vOut, Vec_FltSize(p->vIndex1) ); + Vec_FltForEachEntry( p->vIndex1, Entry, i ) + Vec_StrPutF( vOut, Entry ); + + Vec_PtrForEachEntry( Vec_Flt_t *, p->vData, vVec, i ) + Vec_FltForEachEntry( vVec, Entry, k ) + Vec_StrPutF( vOut, Entry ); + + for ( i = 0; i < 3; i++ ) + Vec_StrPutF( vOut, p->approx[0][i] ); + for ( i = 0; i < 4; i++ ) + Vec_StrPutF( vOut, p->approx[1][i] ); + for ( i = 0; i < 6; i++ ) + Vec_StrPutF( vOut, p->approx[2][i] ); +} +static void Abc_SclWriteLibrary( Vec_Str_t * vOut, SC_Lib * p ) +{ + SC_WireLoad * pWL; + SC_WireLoadSel * pWLS; + SC_Cell * pCell; + SC_Pin * pPin; + int n_valid_cells; + int i, j, k; + + Vec_StrPutI( vOut, ABC_SCL_CUR_VERSION ); + + // Write non-composite fields: + Vec_StrPutS( vOut, p->pName ); + Vec_StrPutS( vOut, p->default_wire_load ); + Vec_StrPutS( vOut, p->default_wire_load_sel ); + Vec_StrPutF( vOut, p->default_max_out_slew ); + + assert( p->unit_time >= 0 ); + assert( p->unit_cap_snd >= 0 ); + Vec_StrPutI( vOut, p->unit_time ); + Vec_StrPutF( vOut, p->unit_cap_fst ); + Vec_StrPutI( vOut, p->unit_cap_snd ); + + // Write 'wire_load' vector: + Vec_StrPutI( vOut, Vec_PtrSize(p->vWireLoads) ); + SC_LibForEachWireLoad( p, pWL, i ) + { + Vec_StrPutS( vOut, pWL->pName ); + Vec_StrPutF( vOut, pWL->res ); + Vec_StrPutF( vOut, pWL->cap ); + + Vec_StrPutI( vOut, Vec_IntSize(pWL->vFanout) ); + for ( j = 0; j < Vec_IntSize(pWL->vFanout); j++ ) + { + Vec_StrPutI( vOut, Vec_IntEntry(pWL->vFanout, j) ); + Vec_StrPutF( vOut, Vec_FltEntry(pWL->vLen, j) ); + } + } + + // Write 'wire_load_sel' vector: + Vec_StrPutI( vOut, Vec_PtrSize(p->vWireLoadSels) ); + SC_LibForEachWireLoadSel( p, pWLS, i ) + { + Vec_StrPutS( vOut, pWLS->pName ); + Vec_StrPutI( vOut, Vec_FltSize(pWLS->vAreaFrom) ); + for ( j = 0; j < Vec_FltSize(pWLS->vAreaFrom); j++) + { + Vec_StrPutF( vOut, Vec_FltEntry(pWLS->vAreaFrom, j) ); + Vec_StrPutF( vOut, Vec_FltEntry(pWLS->vAreaTo, j) ); + Vec_StrPutS( vOut, (char *)Vec_PtrEntry(pWLS->vWireLoadModel, j) ); + } + } + + // Write 'cells' vector: + n_valid_cells = 0; + SC_LibForEachCell( p, pCell, i ) + if ( !(pCell->seq || pCell->unsupp) ) + n_valid_cells++; + + Vec_StrPutI( vOut, n_valid_cells ); + SC_LibForEachCell( p, pCell, i ) + { + if ( pCell->seq || pCell->unsupp ) + continue; + + Vec_StrPutS( vOut, pCell->pName ); + Vec_StrPutF( vOut, pCell->area ); + Vec_StrPutI( vOut, pCell->drive_strength ); + + // Write 'pins': (sorted at this point; first inputs, then outputs) + Vec_StrPutI( vOut, pCell->n_inputs); + Vec_StrPutI( vOut, pCell->n_outputs); + + SC_CellForEachPinIn( pCell, pPin, j ) + { + assert(pPin->dir == sc_dir_Input); + Vec_StrPutS( vOut, pPin->pName ); + Vec_StrPutF( vOut, pPin->rise_cap ); + Vec_StrPutF( vOut, pPin->fall_cap ); + } + + SC_CellForEachPinOut( pCell, pPin, j ) + { + SC_Timings * pRTime; + word uWord; + + assert(pPin->dir == sc_dir_Output); + Vec_StrPutS( vOut, pPin->pName ); + Vec_StrPutF( vOut, pPin->max_out_cap ); + Vec_StrPutF( vOut, pPin->max_out_slew ); + + // write function + if ( pPin->func_text == NULL ) + { + // formula is not given - write empty string + Vec_StrPutS( vOut, "" ); + // write truth table + assert( Vec_WrdSize(pPin->vFunc) == Abc_Truth6WordNum(pCell->n_inputs) ); + Vec_StrPutI( vOut, pCell->n_inputs ); + Vec_WrdForEachEntry( pPin->vFunc, uWord, k ) // -- 'size = 1u << (n_vars - 6)' + Vec_StrPutW( vOut, uWord ); // -- 64-bit number, written uncompressed (low-byte first) + } + else // formula is given + Vec_StrPutS( vOut, pPin->func_text ); + + // Write 'rtiming': (pin-to-pin timing tables for this particular output) + assert( Vec_PtrSize(pPin->vRTimings) == pCell->n_inputs ); + SC_PinForEachRTiming( pPin, pRTime, k ) + { + Vec_StrPutS( vOut, pRTime->pName ); + Vec_StrPutI( vOut, Vec_PtrSize(pRTime->vTimings) ); + // -- NOTE! After post-processing, the size of the 'rtiming[k]' vector is either + // 0 or 1 (in static timing, we have merged all tables to get the worst case). + // The case with size 0 should only occur for multi-output gates. + if ( Vec_PtrSize(pRTime->vTimings) == 1 ) + { + SC_Timing * pTime = (SC_Timing *)Vec_PtrEntry( pRTime->vTimings, 0 ); + // -- NOTE! We don't need to save 'related_pin' string because we have sorted + // the elements on input pins. + Vec_StrPutI( vOut, (int)pTime->tsense); + Abc_SclWriteSurface( vOut, pTime->pCellRise ); + Abc_SclWriteSurface( vOut, pTime->pCellFall ); + Abc_SclWriteSurface( vOut, pTime->pRiseTrans ); + Abc_SclWriteSurface( vOut, pTime->pFallTrans ); + } + else + assert( Vec_PtrSize(pRTime->vTimings) == 0 ); + } + } + } +} +void Abc_SclWrite( char * pFileName, SC_Lib * p ) +{ + Vec_Str_t * vOut; + vOut = Vec_StrAlloc( 10000 ); + Abc_SclWriteLibrary( vOut, p ); + if ( Vec_StrSize(vOut) > 0 ) + { + FILE * pFile = fopen( pFileName, "wb" ); + if ( pFile == NULL ) + printf( "Cannot open file \"%s\" for writing.\n", pFileName ); + else + { + fwrite( Vec_StrArray(vOut), 1, Vec_StrSize(vOut), pFile ); + fclose( pFile ); + } + } + Vec_StrFree( vOut ); +} +void Abc_SclSave( char * pFileName, SC_Lib * pScl ) +{ + if ( pScl == NULL ) return; + Abc_SclWrite( pFileName, pScl ); +} + + +/**Function************************************************************* + + Synopsis [Writing library into text file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static void Abc_SclWriteSurfaceText( FILE * s, SC_Surface * p ) +{ + Vec_Flt_t * vVec; + float Entry; + int i, k; + + fprintf( s, " index_1(\"" ); + Vec_FltForEachEntry( p->vIndex0, Entry, i ) + fprintf( s, "%f%s", Entry, i == Vec_FltSize(p->vIndex0)-1 ? "":", " ); + fprintf( s, "\");\n" ); + + fprintf( s, " index_2(\"" ); + Vec_FltForEachEntry( p->vIndex1, Entry, i ) + fprintf( s, "%f%s", Entry, i == Vec_FltSize(p->vIndex1)-1 ? "":", " ); + fprintf( s, "\");\n" ); + + fprintf( s, " values (\"" ); + Vec_PtrForEachEntry( Vec_Flt_t *, p->vData, vVec, i ) + { + Vec_FltForEachEntry( vVec, Entry, k ) + fprintf( s, "%f%s", Entry, i == Vec_PtrSize(p->vData)-1 && k == Vec_FltSize(vVec)-1 ? "\");":", " ); + if ( i == Vec_PtrSize(p->vData)-1 ) + fprintf( s, "\n" ); + else + { + fprintf( s, "\\\n" ); + fprintf( s, " " ); + } + } +/* + fprintf( s, " approximations: \n" ); + fprintf( s, " " ); + for ( i = 0; i < 3; i++ ) + fprintf( s, "%f ", p->approx[0][i] ); + fprintf( s, "\n" ); + fprintf( s, " " ); + for ( i = 0; i < 4; i++ ) + fprintf( s, "%f ", p->approx[1][i] ); + fprintf( s, "\n" ); + fprintf( s, " " ); + for ( i = 0; i < 6; i++ ) + fprintf( s, "%f ", p->approx[2][i] ); + fprintf( s, "\n" ); + fprintf( s, " \n" ); +*/ +} +static void Abc_SclWriteLibraryText( FILE * s, SC_Lib * p ) +{ + SC_WireLoad * pWL; + SC_WireLoadSel * pWLS; + SC_Cell * pCell; + SC_Pin * pPin; + int n_valid_cells; + int i, j, k; + +// fprintf( s, "%d", ABC_SCL_CUR_VERSION ); + fprintf( s, "library(%s) {\n\n", p->pName ); + if ( p->default_wire_load && strlen(p->default_wire_load) ) + fprintf( s, " default_wire_load : \"%s\";\n", p->default_wire_load ); + if ( p->default_wire_load_sel && strlen(p->default_wire_load_sel) ) + fprintf( s, " default_wire_load_selection : \"%s\";\n", p->default_wire_load_sel ); + if ( p->default_max_out_slew != -1 ) + fprintf( s, " default_max_transition : %f;\n", p->default_max_out_slew ); + if ( p->unit_time == 9 ) + fprintf( s, " time_unit : \"1ns\";\n" ); + else if ( p->unit_time == 10 ) + fprintf( s, " time_unit : \"100ps\";\n" ); + else if ( p->unit_time == 11 ) + fprintf( s, " time_unit : \"10ps\";\n" ); + else if ( p->unit_time == 12 ) + fprintf( s, " time_unit : \"1ps\";\n" ); + else assert( 0 ); + fprintf( s, " capacitive_load_unit(%.1f,%s);\n", p->unit_cap_fst, p->unit_cap_snd == 12 ? "pf" : "ff" ); + fprintf( s, "\n" ); + + // Write 'wire_load' vector: + 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 ); + 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" ); + } + + // Write 'wire_load_sel' vector: + SC_LibForEachWireLoadSel( p, pWLS, i ) + { + fprintf( s, " wire_load_selection(\"%s\") {\n", pWLS->pName ); + for ( j = 0; j < Vec_FltSize(pWLS->vAreaFrom); j++) + fprintf( s, " wire_load_from_area( %f, %f, \"%s\" );\n", + Vec_FltEntry(pWLS->vAreaFrom, j), + Vec_FltEntry(pWLS->vAreaTo, j), + (char *)Vec_PtrEntry(pWLS->vWireLoadModel, j) ); + fprintf( s, " }\n\n" ); + } + + // Write 'cells' vector: + n_valid_cells = 0; + SC_LibForEachCell( p, pCell, i ) + if ( !(pCell->seq || pCell->unsupp) ) + n_valid_cells++; + + SC_LibForEachCell( p, pCell, i ) + { + if ( pCell->seq || pCell->unsupp ) + continue; + + fprintf( s, "\n" ); + fprintf( s, " cell(%s) {\n", pCell->pName ); + fprintf( s, " /* n_inputs = %d n_outputs = %d */\n", pCell->n_inputs, pCell->n_outputs ); + fprintf( s, " area : %f;\n", pCell->area ); + fprintf( s, " drive_strength : %d;\n", pCell->drive_strength ); + + SC_CellForEachPinIn( pCell, pPin, j ) + { + assert(pPin->dir == sc_dir_Input); + fprintf( s, " pin(%s) {\n", pPin->pName ); + fprintf( s, " direction : %s;\n", "input" ); + fprintf( s, " fall_capacitance : %f;\n", pPin->fall_cap ); + fprintf( s, " rise_capacitance : %f;\n", pPin->rise_cap ); + fprintf( s, " }\n" ); + } + + SC_CellForEachPinOut( pCell, pPin, j ) + { + SC_Timings * pRTime; +// word uWord; + assert(pPin->dir == sc_dir_Output); + fprintf( s, " pin(%s) {\n", pPin->pName ); + fprintf( s, " direction : %s;\n", "output" ); + fprintf( s, " max_capacitance : %f;\n", pPin->max_out_cap ); + fprintf( s, " max_transition : %f;\n", pPin->max_out_slew ); + fprintf( s, " function : \"%s\";\n", pPin->func_text ? pPin->func_text : "?" ); + fprintf( s, " /* truth table = " ); + Extra_PrintHex( s, (unsigned *)Vec_WrdArray(pPin->vFunc), pCell->n_inputs ); + fprintf( s, " */\n" ); + + // Write 'rtiming': (pin-to-pin timing tables for this particular output) + assert( Vec_PtrSize(pPin->vRTimings) == pCell->n_inputs ); + SC_PinForEachRTiming( pPin, pRTime, k ) + { + if ( Vec_PtrSize(pRTime->vTimings) == 1 ) + { + SC_Timing * pTime = (SC_Timing *)Vec_PtrEntry( pRTime->vTimings, 0 ); + fprintf( s, " timing() {\n" ); + fprintf( s, " related_pin : \"%s\"\n", pRTime->pName ); + if ( pTime->tsense == sc_ts_Pos ) + fprintf( s, " timing_sense : positive_unate;\n" ); + else if ( pTime->tsense == sc_ts_Neg ) + fprintf( s, " timing_sense : negative_unate;\n" ); + else if ( pTime->tsense == sc_ts_Non ) + fprintf( s, " timing_sense : non_unate;\n" ); + else assert( 0 ); + + fprintf( s, " cell_rise() {\n" ); + Abc_SclWriteSurfaceText( s, pTime->pCellRise ); + fprintf( s, " }\n" ); + + fprintf( s, " cell_fall() {\n" ); + Abc_SclWriteSurfaceText( s, pTime->pCellFall ); + fprintf( s, " }\n" ); + + fprintf( s, " rise_transition() {\n" ); + Abc_SclWriteSurfaceText( s, pTime->pRiseTrans ); + fprintf( s, " }\n" ); + + fprintf( s, " fall_transition() {\n" ); + Abc_SclWriteSurfaceText( s, pTime->pFallTrans ); + fprintf( s, " }\n" ); + fprintf( s, " }\n" ); + } + else + assert( Vec_PtrSize(pRTime->vTimings) == 0 ); + } + fprintf( s, " }\n" ); + } + fprintf( s, " }\n" ); + } + fprintf( s, "}\n\n" ); +} +void Abc_SclWriteText( char * pFileName, SC_Lib * p ) +{ + FILE * pFile = fopen( pFileName, "wb" ); + if ( pFile == NULL ) + printf( "Cannot open text file \"%s\" for writing.\n", pFileName ); + else + { + Abc_SclWriteLibraryText( pFile, p ); + fclose( pFile ); + } +} + + +/**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 ) +{ + return *Abc_SclHashLookup( p, pName ); +} + +/**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; + return strcmp( (*pp1)->pName, (*pp2)->pName ); +} +void Abc_SclLinkCells( SC_Lib * p ) +{ + 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 the 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 + SC_LibForEachCellClass( p, pRepr, k ) + { + Vec_Ptr_t * vList = Vec_PtrAlloc( 100 ); + 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->Order = 0; + // 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->Order = i; + } + // update list + Vec_PtrWriteEntry( p->vCellClasses, k, pRepr ); + Vec_PtrFree( vList ); + } +} +void Abc_SclPrintCells( SC_Lib * p ) +{ + SC_Cell * pCell, * pRepr; + int i, k, j, nLength = 0; + assert( Vec_PtrSize(p->vCellClasses) > 0 ); + printf( "Library \"%s\" ", p->pName ); + printf( "containing %d cells in %d classes.\n", + Vec_PtrSize(p->vCells), Vec_PtrSize(p->vCellClasses) ); + // 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 ) + { + 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 ) + { + printf( " %3d : ", i+1 ); + printf( "%-*s ", nLength, pCell->pName ); + printf( "%2d ", pCell->drive_strength ); + printf( "A =%8.2f D =", pCell->area ); + // print linear approximation + for ( j = 0; j < 3; j++ ) + { + SC_Pin * pPin = SC_CellPin( pCell, pCell->n_inputs ); + if ( Vec_PtrSize(pPin->vRTimings) > 0 ) + { + SC_Timings * pRTime = (SC_Timings *)Vec_PtrEntry( pPin->vRTimings, 0 ); + SC_Timing * pTime = (SC_Timing *)Vec_PtrEntry( pRTime->vTimings, 0 ); + printf( " %6.2f", j ? pTime->pCellRise->approx[0][j] : SC_LibTimePs(p, pTime->pCellRise->approx[0][j]) ); + } + } + // print input capacitance + printf( " Cap =" ); + for ( j = 0; j < pCell->n_inputs; j++ ) + { + SC_Pin * pPin = SC_CellPin( pCell, j ); + printf( " %6.2f", SC_LibCapFf(p, pPin->rise_cap) ); + } + printf( "\n" ); + } + } +} + +/**Function************************************************************* + + Synopsis [Returns the wireload model for the given area.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +SC_WireLoad * Abc_SclFindWireLoadModel( SC_Lib * p, float Area ) +{ + SC_WireLoad * pWL = NULL; + 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; + } + // 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; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/map/scl/sclLib.h b/src/map/scl/sclLib.h new file mode 100644 index 00000000..a5a79a0e --- /dev/null +++ b/src/map/scl/sclLib.h @@ -0,0 +1,458 @@ +/**CFile**************************************************************** + + FileName [sclLib.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Standard-cell library representation.] + + Synopsis [Simplified library representation for STA.] + + Author [Alan Mishchenko, Niklas Een] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - August 24, 2012.] + + Revision [$Id: sclLib.h,v 1.0 2012/08/24 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef ABC__map__scl__sclLib_h +#define ABC__map__scl__sclLib_h + + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include "misc/vec/vec.h" + +ABC_NAMESPACE_HEADER_START + + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +#define ABC_SCL_CUR_VERSION 6 + +typedef enum +{ + sc_dir_NULL, + sc_dir_Input, + sc_dir_Output, + sc_dir_InOut, + sc_dir_Internal, +} SC_Dir; + +typedef enum // -- timing sense, positive-, negative- or non-unate +{ + sc_ts_NULL, + sc_ts_Pos, + sc_ts_Neg, + sc_ts_Non, +} SC_TSense; + +typedef struct SC_SizePars_ SC_SizePars; +struct SC_SizePars_ +{ + int nIters; + int nIterNoChange; + int Window; // used for upsizing + int Ratio; // used for upsizing + int Notches; + int DelayUser; + int DelayGap; + int TimeOut; + int fUseDept; + int fDumpStats; + int fUseWireLoads; + int fVerbose; + int fVeryVerbose; +}; + +typedef struct SC_Pair_ SC_Pair; +struct SC_Pair_ +{ + float rise; + float fall; +}; + +//////////////////////////////////////////////////////////////////////// +/// STRUCTURE DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct SC_WireLoad_ SC_WireLoad; +typedef struct SC_WireLoadSel_ SC_WireLoadSel; +typedef struct SC_TableTempl_ SC_TableTempl; +typedef struct SC_Surface_ SC_Surface; +typedef struct SC_Timing_ SC_Timing; +typedef struct SC_Timings_ SC_Timings; +typedef struct SC_Pin_ SC_Pin; +typedef struct SC_Cell_ SC_Cell; +typedef struct SC_Lib_ SC_Lib; + +struct SC_WireLoad_ +{ + char * pName; + float res; // (currently not used) + float cap; // }- multiply estimation in 'fanout_len[].snd' with this value + Vec_Int_t * vFanout; // Vec > -- pairs '(#fanouts, est-wire-len)' + Vec_Flt_t * vLen; +}; + +struct SC_WireLoadSel_ +{ + char * pName; + Vec_Flt_t * vAreaFrom; // Vec > -- triplets '(from-area, upto-area, wire-load-model)'; range is [from, upto[ + Vec_Flt_t * vAreaTo; + Vec_Ptr_t * vWireLoadModel; +}; + +struct SC_TableTempl_ +{ + char * pName; + Vec_Ptr_t * vVars; // Vec -- name of variable (numbered from 0, not 1 as in the Liberty file) + Vec_Ptr_t * vIndex; // Vec > -- this is the point of measurement in table for the given variable +}; + +struct SC_Surface_ +{ + char * pName; + Vec_Flt_t * vIndex0; // Vec -- correspondes to "index_1" in the liberty file (for timing: slew) + Vec_Flt_t * vIndex1; // Vec -- correspondes to "index_2" in the liberty file (for timing: load) + Vec_Ptr_t * vData; // Vec > -- 'data[i0][i1]' gives value at '(index0[i0], index1[i1])' + float approx[3][6]; +}; + +struct SC_Timing_ +{ + char * related_pin; // -- related pin + SC_TSense tsense; // -- timing sense (positive_unate, negative_unate, non_unate) + char * when_text; // -- logic condition on inputs triggering this delay model for the output (currently not used) + SC_Surface * pCellRise; // -- Used to compute pin-to-pin delay + SC_Surface * pCellFall; + SC_Surface * pRiseTrans; // -- Used to compute output slew + SC_Surface * pFallTrans; +}; + +struct SC_Timings_ +{ + char * pName; // -- the 'related_pin' field + Vec_Ptr_t * vTimings; // structures of type SC_Timing +}; + +struct SC_Pin_ +{ + char * pName; + SC_Dir dir; + float cap; // -- this value is used if 'rise_cap' and 'fall_cap' is missing (copied by 'postProcess()'). (not used) + float rise_cap; // }- used for input pins ('cap' too). + float fall_cap; // } + float max_out_cap; // } (not used) + float max_out_slew; // }- used only for output pins (max values must not be exceeded or else mapping is illegal) (not used) + char * func_text; // } + Vec_Wrd_t * vFunc; // } + Vec_Ptr_t * vRTimings; // -- for output pins +}; + +struct SC_Cell_ +{ + char * pName; + int Id; + int seq; // -- set to TRUE by parser if a sequential element + int unsupp; // -- set to TRUE by parser if cell contains information we cannot handle + float area; + int drive_strength; // -- some library files provide this field (currently unused, but may be a good hint for sizing) (not used) + Vec_Ptr_t * vPins; // NamedSet + int n_inputs; // -- 'pins[0 .. n_inputs-1]' are input pins + int n_outputs; // -- 'pins[n_inputs .. n_inputs+n_outputs-1]' are output pins + SC_Cell * pNext; // same-functionality cells linked into a ring by area + SC_Cell * pPrev; // same-functionality cells linked into a ring by area + int Order; // order of the gate in the list +}; + +struct SC_Lib_ +{ + char * pName; + 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) + int unit_time; // -- Valid 9..12. Unit is '10^(-val)' seconds (e.g. 9=1ns, 10=100ps, 11=10ps, 12=1ps) + float unit_cap_fst; // -- First part is a multiplier, second either 12 or 15 for 'pf' or 'ff'. + int unit_cap_snd; + Vec_Ptr_t * vWireLoads; // NamedSet + Vec_Ptr_t * vWireLoadSels; // NamedSet + Vec_Ptr_t * vTempls; // NamedSet + Vec_Ptr_t * vCells; // NamedSet + Vec_Ptr_t * vCellClasses; // NamedSet + int * pBins; // hashing gateName -> gateId + int nBins; +}; + +//////////////////////////////////////////////////////////////////////// +/// GLOBAL VARIABLES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +static inline SC_Cell * SC_LibCell( SC_Lib * p, int i ) { return (SC_Cell *)Vec_PtrEntry(p->vCells, i); } +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 double SC_LibCapFf( SC_Lib * p, double cap ) { return cap * p->unit_cap_fst * pow(10.0, 15 - p->unit_cap_snd); } +static inline double SC_LibCapFromFf( SC_Lib * p, double cap ) { return cap / p->unit_cap_fst / pow(10.0, 15 - p->unit_cap_snd); } +static inline double SC_LibTimePs( SC_Lib * p, double time ) { return time * pow(10.0, 12 - p->unit_time); } +static inline double SC_LibTimeFromPs( SC_Lib * p, double ps ) { return ps / pow(10.0, 12 - p->unit_time); } + +#define SC_LibForEachCell( p, pCell, i ) Vec_PtrForEachEntry( SC_Cell *, p->vCells, pCell, i ) +#define SC_LibForEachCellClass( p, pCell, i ) Vec_PtrForEachEntry( SC_Cell *, p->vCellClasses, pCell, i ) +#define SC_LibForEachWireLoad( p, pWL, i ) Vec_PtrForEachEntry( SC_WireLoad *, p->vWireLoads, pWL, i ) +#define SC_LibForEachWireLoadSel( p, pWLS, i ) Vec_PtrForEachEntry( SC_WireLoadSel *, p->vWireLoadSels, pWLS, i ) +#define SC_LibForEachTempl( p, pTempl, i ) Vec_PtrForEachEntry( SC_TableTempl *, p->vTempls, pTempl, i ) +#define SC_CellForEachPin( p, pPin, i ) Vec_PtrForEachEntry( SC_Pin *, p->vPins, pPin, i ) +#define SC_CellForEachPinIn( p, pPin, i ) Vec_PtrForEachEntryStop( SC_Pin *, p->vPins, pPin, i, p->n_inputs ) +#define SC_CellForEachPinOut( p, pPin, i ) Vec_PtrForEachEntryStart( SC_Pin *, p->vPins, pPin, i, p->n_inputs ) +#define SC_RingForEachCell( pRing, pCell, i ) for ( i = 0, pCell = pRing; i == 0 || pCell != pRing; pCell = pCell->pNext, i++ ) +#define SC_RingForEachCellRev( pRing, pCell, i ) for ( i = 0, pCell = pRing; i == 0 || pCell != pRing; pCell = pCell->pPrev, i++ ) +#define SC_PinForEachRTiming( p, pRTime, i ) Vec_PtrForEachEntry( SC_Timings *, p->vRTimings, pRTime, i ) + + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Constructors of the library data-structures.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline SC_WireLoad * Abc_SclWireLoadAlloc() +{ + SC_WireLoad * p; + p = ABC_CALLOC( SC_WireLoad, 1 ); + p->vFanout = Vec_IntAlloc( 0 ); + p->vLen = Vec_FltAlloc( 0 ); + return p; +} +static inline SC_WireLoadSel * Abc_SclWireLoadSelAlloc() +{ + SC_WireLoadSel * p; + p = ABC_CALLOC( SC_WireLoadSel, 1 ); + p->vAreaFrom = Vec_FltAlloc( 0 ); + p->vAreaTo = Vec_FltAlloc( 0 ); + p->vWireLoadModel = Vec_PtrAlloc( 0 ); + return p; +} +static inline SC_TableTempl * Abc_SclTableTemplAlloc() +{ + SC_TableTempl * p; + p = ABC_CALLOC( SC_TableTempl, 1 ); + p->vVars = Vec_PtrAlloc( 0 ); + p->vIndex = Vec_PtrAlloc( 0 ); + return p; +} +static inline SC_Surface * Abc_SclSurfaceAlloc() +{ + SC_Surface * p; + p = ABC_CALLOC( SC_Surface, 1 ); + p->vIndex0 = Vec_FltAlloc( 0 ); + p->vIndex1 = Vec_FltAlloc( 0 ); + p->vData = Vec_PtrAlloc( 0 ); + return p; +} +static inline SC_Timing * Abc_SclTimingAlloc() +{ + SC_Timing * p; + p = ABC_CALLOC( SC_Timing, 1 ); + p->pCellRise = Abc_SclSurfaceAlloc(); + p->pCellFall = Abc_SclSurfaceAlloc(); + p->pRiseTrans = Abc_SclSurfaceAlloc(); + p->pFallTrans = Abc_SclSurfaceAlloc(); + return p; +} +static inline SC_Timings * Abc_SclTimingsAlloc() +{ + SC_Timings * p; + p = ABC_CALLOC( SC_Timings, 1 ); + p->vTimings = Vec_PtrAlloc( 0 ); + return p; +} +static inline SC_Pin * Abc_SclPinAlloc() +{ + SC_Pin * p; + p = ABC_CALLOC( SC_Pin, 1 ); + p->max_out_slew = -1; + p->vFunc = Vec_WrdAlloc( 0 ); + p->vRTimings = Vec_PtrAlloc( 0 ); + return p; +} +static inline SC_Cell * Abc_SclCellAlloc() +{ + SC_Cell * p; + p = ABC_CALLOC( SC_Cell, 1 ); + p->vPins = Vec_PtrAlloc( 0 ); + return p; +} +static inline SC_Lib * Abc_SclLibAlloc() +{ + SC_Lib * p; + p = ABC_CALLOC( SC_Lib, 1 ); + p->default_max_out_slew = -1; + p->unit_time = 9; + p->unit_cap_fst = 1; + p->unit_cap_snd = 12; + p->vWireLoads = Vec_PtrAlloc( 0 ); + p->vWireLoadSels = Vec_PtrAlloc( 0 ); + p->vTempls = Vec_PtrAlloc( 0 ); + p->vCells = Vec_PtrAlloc( 0 ); + p->vCellClasses = Vec_PtrAlloc( 0 ); + return p; +} + + +/**Function************************************************************* + + Synopsis [Destructors of the library data-structures.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Abc_SclWireLoadFree( SC_WireLoad * p ) +{ + Vec_IntFree( p->vFanout ); + Vec_FltFree( p->vLen ); + ABC_FREE( p->pName ); + ABC_FREE( p ); +} +static inline void Abc_SclWireLoadSelFree( SC_WireLoadSel * p ) +{ + Vec_FltFree( p->vAreaFrom ); + Vec_FltFree( p->vAreaTo ); + Vec_PtrFreeFree( p->vWireLoadModel ); + ABC_FREE( p->pName ); + ABC_FREE( p ); +} +static inline void Abc_SclTableTemplFree( SC_TableTempl * p ) +{ + Vec_PtrFreeFree( p->vVars ); + Vec_VecFree( (Vec_Vec_t *)p->vIndex ); + ABC_FREE( p->pName ); + ABC_FREE( p ); +} +static inline void Abc_SclSurfaceFree( SC_Surface * p ) +{ + Vec_FltFree( p->vIndex0 ); + Vec_FltFree( p->vIndex1 ); + Vec_VecFree( (Vec_Vec_t *)p->vData ); + ABC_FREE( p->pName ); + ABC_FREE( p ); +} +static inline void Abc_SclTimingFree( SC_Timing * p ) +{ + Abc_SclSurfaceFree( p->pCellRise ); + Abc_SclSurfaceFree( p->pCellFall ); + Abc_SclSurfaceFree( p->pRiseTrans ); + Abc_SclSurfaceFree( p->pFallTrans ); + ABC_FREE( p->related_pin ); + ABC_FREE( p->when_text ); + ABC_FREE( p ); +} +static inline void Abc_SclTimingsFree( SC_Timings * p ) +{ + SC_Timing * pTemp; + int i; + Vec_PtrForEachEntry( SC_Timing *, p->vTimings, pTemp, i ) + Abc_SclTimingFree( pTemp ); + Vec_PtrFree( p->vTimings ); + ABC_FREE( p->pName ); + ABC_FREE( p ); +} +static inline void Abc_SclPinFree( SC_Pin * p ) +{ + SC_Timings * pTemp; + int i; + SC_PinForEachRTiming( p, pTemp, i ) + Abc_SclTimingsFree( pTemp ); + Vec_PtrFree( p->vRTimings ); + Vec_WrdFree( p->vFunc ); + ABC_FREE( p->func_text ); + ABC_FREE( p->pName ); + ABC_FREE( p ); +} +static inline void Abc_SclCellFree( SC_Cell * p ) +{ + SC_Pin * pTemp; + int i; + SC_CellForEachPin( p, pTemp, i ) + Abc_SclPinFree( pTemp ); + Vec_PtrFree( p->vPins ); + ABC_FREE( p->pName ); + ABC_FREE( p ); +} +static inline void Abc_SclLibFree( SC_Lib * p ) +{ + SC_WireLoad * pWL; + SC_WireLoadSel * pWLS; + SC_TableTempl * pTempl; + SC_Cell * pCell; + int i; + SC_LibForEachWireLoad( p, pWL, i ) + Abc_SclWireLoadFree( pWL ); + Vec_PtrFree( p->vWireLoads ); + SC_LibForEachWireLoadSel( p, pWLS, i ) + Abc_SclWireLoadSelFree( pWLS ); + Vec_PtrFree( p->vWireLoadSels ); + SC_LibForEachTempl( p, pTempl, i ) + Abc_SclTableTemplFree( pTempl ); + Vec_PtrFree( p->vTempls ); + SC_LibForEachCell( p, pCell, i ) + Abc_SclCellFree( pCell ); + Vec_PtrFree( p->vCells ); + Vec_PtrFree( p->vCellClasses ); + ABC_FREE( p->pName ); + ABC_FREE( p->default_wire_load ); + ABC_FREE( p->default_wire_load_sel ); + ABC_FREE( p->pBins ); + ABC_FREE( p ); +} + + +/*=== 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 ); +extern void Abc_SclHashCells( SC_Lib * p ); +extern int Abc_SclCellFind( SC_Lib * p, char * pName ); +extern void Abc_SclLinkCells( SC_Lib * p ); +extern void Abc_SclPrintCells( SC_Lib * p ); +extern SC_WireLoad * Abc_SclFindWireLoadModel( SC_Lib * p, float Area ); + + +ABC_NAMESPACE_HEADER_END + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// diff --git a/src/map/scl/sclLoad.c b/src/map/scl/sclLoad.c index f9768b8f..a9f5e527 100644 --- a/src/map/scl/sclLoad.c +++ b/src/map/scl/sclLoad.c @@ -18,8 +18,7 @@ ***********************************************************************/ -#include "sclInt.h" -#include "sclMan.h" +#include "sclSize.h" ABC_NAMESPACE_IMPL_START @@ -32,63 +31,6 @@ ABC_NAMESPACE_IMPL_START /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// -/**Function************************************************************* - - Synopsis [Returns the wireload model for the given area.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -SC_WireLoad * Abc_SclFindWireLoadModel( SC_Lib * p, float Area ) -{ - SC_WireLoad * pWL = NULL; - 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; - } - // 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; -} - /**Function************************************************************* Synopsis [Returns estimated wire capacitances for each fanout count.] diff --git a/src/map/scl/sclMan.h b/src/map/scl/sclMan.h deleted file mode 100644 index 54a6022a..00000000 --- a/src/map/scl/sclMan.h +++ /dev/null @@ -1,397 +0,0 @@ -/**CFile**************************************************************** - - FileName [sclMan.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Standard-cell library representation.] - - Synopsis [Timing/gate-sizing manager.] - - Author [Alan Mishchenko, Niklas Een] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - August 24, 2012.] - - Revision [$Id: sclMan.h,v 1.0 2012/08/24 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef ABC__map__scl__sclMan_h -#define ABC__map__scl__sclMan_h - - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -#include "misc/vec/vecQue.h" - -ABC_NAMESPACE_HEADER_START - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// STRUCTURE DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -typedef struct SC_Pair_ SC_Pair; -typedef struct SC_Man_ SC_Man; - -struct SC_Pair_ -{ - float rise; - float fall; -}; - -struct SC_Man_ -{ - SC_Lib * pLib; // library - Abc_Ntk_t * pNtk; // network - int nObjs; // allocated size - // get assignment - Vec_Int_t * vGates; // mapping of objId into gateId - Vec_Int_t * vGatesBest; // best gate sizes found so far - Vec_Int_t * vUpdates; // sizing updates in this round - // timing information - SC_Pair * pLoads; // loads for each gate - SC_Pair * pLoads2; // loads for each gate - SC_Pair * pDepts; // departures for each gate - SC_Pair * pTimes; // arrivals for each gate - SC_Pair * pSlews; // slews for each gate - SC_Pair * pTimes2; // arrivals for each gate - SC_Pair * pSlews2; // slews for each gate - float * pSlack; // slacks for each gate - Vec_Flt_t * vTimesOut; // output arrival times - Vec_Que_t * vQue; // outputs by their time - SC_WireLoad * pWLoadUsed; // name of the used WireLoad model - // intermediate data - Vec_Que_t * vNodeByGain; // nodes by gain - Vec_Flt_t * vNode2Gain; // mapping node into its gain - Vec_Int_t * vNode2Gate; // mapping node into its best gate - Vec_Int_t * vNodeIter; // the last iteration the node was upsized - // optimization parameters - float SumArea; // total area - float MaxDelay; // max delay - float SumArea0; // total area at the begining - float MaxDelay0; // max delay at the begining - float BestDelay; // best delay in the middle - // runtime statistics - abctime timeTotal; // starting/total time - abctime timeCone; // critical path selection - abctime timeSize; // incremental sizing - abctime timeTime; // timing update - abctime timeOther; // everything else -}; - -//////////////////////////////////////////////////////////////////////// -/// GLOBAL VARIABLES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -static inline SC_Cell * Abc_SclObjCell( SC_Man * p, Abc_Obj_t * pObj ) { return SC_LibCell( p->pLib, Vec_IntEntry(p->vGates, Abc_ObjId(pObj)) ); } -static inline void Abc_SclObjSetCell( SC_Man * p, Abc_Obj_t * pObj, SC_Cell * pCell ) { Vec_IntWriteEntry( p->vGates, Abc_ObjId(pObj), pCell->Id ); } - -static inline SC_Pair * Abc_SclObjLoad( SC_Man * p, Abc_Obj_t * pObj ) { return p->pLoads + Abc_ObjId(pObj); } -static inline SC_Pair * Abc_SclObjLoad2( SC_Man * p, Abc_Obj_t * pObj ) { return p->pLoads2 + Abc_ObjId(pObj); } -static inline SC_Pair * Abc_SclObjDept( SC_Man * p, Abc_Obj_t * pObj ) { return p->pDepts + Abc_ObjId(pObj); } -static inline SC_Pair * Abc_SclObjTime( SC_Man * p, Abc_Obj_t * pObj ) { return p->pTimes + Abc_ObjId(pObj); } -static inline SC_Pair * Abc_SclObjSlew( SC_Man * p, Abc_Obj_t * pObj ) { return p->pSlews + Abc_ObjId(pObj); } -static inline SC_Pair * Abc_SclObjTime2( SC_Man * p, Abc_Obj_t * pObj ) { return p->pTimes2 + Abc_ObjId(pObj); } -static inline SC_Pair * Abc_SclObjSlew2( SC_Man * p, Abc_Obj_t * pObj ) { return p->pSlews2 + Abc_ObjId(pObj); } - -static inline float Abc_SclObjTimeMax( SC_Man * p, Abc_Obj_t * pObj ) { return Abc_MaxFloat(Abc_SclObjTime(p, pObj)->rise, Abc_SclObjTime(p, pObj)->fall); } -static inline float Abc_SclObjDepthMax( SC_Man * p, Abc_Obj_t * pObj ) { return Abc_MaxFloat(Abc_SclObjDept(p, pObj)->rise, Abc_SclObjDept(p, pObj)->fall); } -static inline float Abc_SclObjGetSlack( SC_Man * p, Abc_Obj_t * pObj, float D ) { return D - Abc_MaxFloat(Abc_SclObjTime(p, pObj)->rise + Abc_SclObjDept(p, pObj)->rise, Abc_SclObjTime(p, pObj)->fall + Abc_SclObjDept(p, pObj)->fall); } -static inline float Abc_SclObjGetSlackR( SC_Man * p, Abc_Obj_t * pObj, float D ){ return D - (Abc_SclObjTime(p, pObj)->rise + Abc_SclObjDept(p, pObj)->rise); } -static inline float Abc_SclObjGetSlackF( SC_Man * p, Abc_Obj_t * pObj, float D ){ return D - (Abc_SclObjTime(p, pObj)->fall + Abc_SclObjDept(p, pObj)->fall); } -static inline float Abc_SclObjSlack( SC_Man * p, Abc_Obj_t * pObj ) { return p->pSlack[Abc_ObjId(pObj)]; } - -static inline void Abc_SclObjDupFanin( SC_Man * p, Abc_Obj_t * pObj ) { assert( Abc_ObjIsCo(pObj) ); *Abc_SclObjTime(p, pObj) = *Abc_SclObjTime(p, Abc_ObjFanin0(pObj)); } -static inline float Abc_SclObjGain( SC_Man * p, Abc_Obj_t * pObj ) { return 0.5*((Abc_SclObjTime2(p, pObj)->rise - Abc_SclObjTime(p, pObj)->rise) + (Abc_SclObjTime2(p, pObj)->fall - Abc_SclObjTime(p, pObj)->fall)); } -static inline int Abc_SclObjLegal( SC_Man * p, Abc_Obj_t * pObj, float D ) { return Abc_SclObjTime(p, pObj)->rise <= Abc_SclObjTime2(p, pObj)->rise + Abc_SclObjGetSlackR(p, pObj, D) && Abc_SclObjTime(p, pObj)->fall <= Abc_SclObjTime2(p, pObj)->fall + Abc_SclObjGetSlackF(p, pObj, D); } - -static inline double Abc_SclObjLoadFf( SC_Man * p, Abc_Obj_t * pObj, int fRise ) { return SC_LibCapFf( p->pLib, fRise ? Abc_SclObjLoad(p, pObj)->rise : Abc_SclObjLoad(p, pObj)->fall); } -static inline double Abc_SclObjTimePs( SC_Man * p, Abc_Obj_t * pObj, int fRise ) { return SC_LibTimePs(p->pLib, fRise ? Abc_SclObjTime(p, pObj)->rise : Abc_SclObjTime(p, pObj)->fall); } -static inline double Abc_SclObjSlewPs( SC_Man * p, Abc_Obj_t * pObj, int fRise ) { return SC_LibTimePs(p->pLib, fRise ? Abc_SclObjSlew(p, pObj)->rise : Abc_SclObjSlew(p, pObj)->fall); } - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Constructor/destructor of STA manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline SC_Man * Abc_SclManAlloc( SC_Lib * pLib, Abc_Ntk_t * pNtk ) -{ - SC_Man * p; - int i; - assert( Abc_NtkHasMapping(pNtk) ); - p = ABC_CALLOC( SC_Man, 1 ); - p->pLib = pLib; - p->pNtk = pNtk; - p->nObjs = Abc_NtkObjNumMax(pNtk); - p->pLoads = ABC_CALLOC( SC_Pair, p->nObjs ); - p->pLoads2 = ABC_CALLOC( SC_Pair, p->nObjs ); - p->pDepts = ABC_CALLOC( SC_Pair, p->nObjs ); - p->pTimes = ABC_CALLOC( SC_Pair, p->nObjs ); - p->pSlews = ABC_CALLOC( SC_Pair, p->nObjs ); - p->pTimes2 = ABC_CALLOC( SC_Pair, p->nObjs ); - p->pSlews2 = ABC_CALLOC( SC_Pair, p->nObjs ); - p->pSlack = ABC_FALLOC( float, p->nObjs ); - p->vTimesOut = Vec_FltStart( Abc_NtkCoNum(pNtk) ); - p->vQue = Vec_QueAlloc( Abc_NtkCoNum(pNtk) ); - Vec_QueSetCosts( p->vQue, Vec_FltArrayP(p->vTimesOut) ); - for ( i = 0; i < Abc_NtkCoNum(pNtk); i++ ) - Vec_QuePush( p->vQue, i ); - p->vUpdates = Vec_IntAlloc( 1000 ); - // intermediate data - p->vNode2Gain = Vec_FltStart( p->nObjs ); - p->vNode2Gate = Vec_IntStart( p->nObjs ); - p->vNodeByGain = Vec_QueAlloc( p->nObjs ); - Vec_QueSetCosts( p->vNodeByGain, Vec_FltArrayP(p->vNode2Gain) ); - p->vNodeIter = Vec_IntStartFull( p->nObjs ); - return p; -} -static inline void Abc_SclManFree( SC_Man * p ) -{ - Vec_IntFreeP( &p->vNodeIter ); - Vec_QueFreeP( &p->vNodeByGain ); - Vec_FltFreeP( &p->vNode2Gain ); - Vec_IntFreeP( &p->vNode2Gate ); - // intermediate data - Vec_IntFreeP( &p->vUpdates ); - Vec_IntFreeP( &p->vGatesBest ); -// Vec_QuePrint( p->vQue ); - Vec_QueCheck( p->vQue ); - Vec_QueFreeP( &p->vQue ); - Vec_FltFreeP( &p->vTimesOut ); - Vec_IntFreeP( &p->vGates ); - ABC_FREE( p->pLoads ); - ABC_FREE( p->pLoads2 ); - ABC_FREE( p->pDepts ); - ABC_FREE( p->pTimes ); - ABC_FREE( p->pSlews ); - ABC_FREE( p->pTimes2 ); - ABC_FREE( p->pSlews2 ); - ABC_FREE( p->pSlack ); - ABC_FREE( p ); -} -static inline void Abc_SclManCleanTime( SC_Man * p ) -{ - Vec_Flt_t * vSlews; - Abc_Obj_t * pObj; - int i; - vSlews = Vec_FltAlloc( 2 * Abc_NtkPiNum(p->pNtk) ); - Abc_NtkForEachPi( p->pNtk, pObj, i ) - { - SC_Pair * pSlew = Abc_SclObjSlew( p, pObj ); - Vec_FltPush( vSlews, pSlew->rise ); - Vec_FltPush( vSlews, pSlew->fall ); - } - memset( p->pDepts, 0, sizeof(SC_Pair) * p->nObjs ); - memset( p->pTimes, 0, sizeof(SC_Pair) * p->nObjs ); - memset( p->pSlews, 0, sizeof(SC_Pair) * p->nObjs ); - Abc_NtkForEachPi( p->pNtk, pObj, i ) - { - SC_Pair * pSlew = Abc_SclObjSlew( p, pObj ); - pSlew->rise = Vec_FltEntry( vSlews, 2 * i + 0 ); - pSlew->fall = Vec_FltEntry( vSlews, 2 * i + 1 ); - } - Vec_FltFree( vSlews ); -} - - -/**Function************************************************************* - - Synopsis [Stores/retrivies timing information for the logic cone.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Abc_SclConeStore( SC_Man * p, Vec_Int_t * vCone ) -{ - Abc_Obj_t * pObj; - int i; - Abc_NtkForEachObjVec( vCone, p->pNtk, pObj, i ) - { - *Abc_SclObjTime2(p, pObj) = *Abc_SclObjTime(p, pObj); - *Abc_SclObjSlew2(p, pObj) = *Abc_SclObjSlew(p, pObj); - } -} -static inline void Abc_SclConeRestore( SC_Man * p, Vec_Int_t * vCone ) -{ - Abc_Obj_t * pObj; - int i; - Abc_NtkForEachObjVec( vCone, p->pNtk, pObj, i ) - { - *Abc_SclObjTime(p, pObj) = *Abc_SclObjTime2(p, pObj); - *Abc_SclObjSlew(p, pObj) = *Abc_SclObjSlew2(p, pObj); - } -} -static inline void Abc_SclConeClear( SC_Man * p, Vec_Int_t * vCone ) -{ - SC_Pair Zero = { 0.0, 0.0 }; - Abc_Obj_t * pObj; - int i; - Abc_NtkForEachObjVec( vCone, p->pNtk, pObj, i ) - { - *Abc_SclObjTime(p, pObj) = Zero; - *Abc_SclObjSlew(p, pObj) = Zero; - } -} - -/**Function************************************************************* - - Synopsis [Stores/retrivies load information.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Abc_SclLoadStore( SC_Man * p, Abc_Obj_t * pObj ) -{ - Abc_Obj_t * pFanin; - int i; - Abc_ObjForEachFanin( pObj, pFanin, i ) - *Abc_SclObjLoad2(p, pFanin) = *Abc_SclObjLoad(p, pFanin); -} -static inline void Abc_SclLoadRestore( SC_Man * p, Abc_Obj_t * pObj ) -{ - Abc_Obj_t * pFanin; - int i; - Abc_ObjForEachFanin( pObj, pFanin, i ) - *Abc_SclObjLoad(p, pFanin) = *Abc_SclObjLoad2(p, pFanin); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline float Abc_SclGetTotalArea( SC_Man * p ) -{ - double Area = 0; - Abc_Obj_t * pObj; - int i; - Abc_NtkForEachNode1( p->pNtk, pObj, i ) - Area += Abc_SclObjCell( p, pObj )->area; - return Area; -} -static inline float Abc_SclGetMaxDelay( SC_Man * p ) -{ - float fMaxArr = 0; - Abc_Obj_t * pObj; - int i; - Abc_NtkForEachCo( p->pNtk, pObj, i ) - fMaxArr = Abc_MaxFloat( fMaxArr, Abc_SclObjTimeMax(p, pObj) ); - return fMaxArr; -} -static inline float Abc_SclGetMaxDelayNodeFanins( SC_Man * p, Abc_Obj_t * pNode ) -{ - float fMaxArr = 0; - Abc_Obj_t * pObj; - int i; - assert( Abc_ObjIsNode(pNode) ); - Abc_ObjForEachFanin( pNode, pObj, i ) - fMaxArr = Abc_MaxFloat( fMaxArr, Abc_SclObjTimeMax(p, pObj) ); - return fMaxArr; -} -static inline float Abc_SclReadMaxDelay( SC_Man * p ) -{ - return Abc_SclObjTimeMax( p, Abc_NtkCo(p->pNtk, Vec_QueTop(p->vQue)) ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline SC_Cell * Abc_SclObjResiable( SC_Man * p, Abc_Obj_t * pObj, int fUpsize ) -{ - SC_Cell * pOld = Abc_SclObjCell( p, pObj ); - if ( fUpsize ) - return pOld->pNext->Order > pOld->Order ? pOld->pNext : NULL; - else - return pOld->pPrev->Order < pOld->Order ? pOld->pPrev : NULL; -} - -/**Function************************************************************* - - Synopsis [Dumps timing results into a file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Abc_SclDumpStats( SC_Man * p, char * pFileName, abctime Time ) -{ - FILE * pTable; - pTable = fopen( pFileName, "a+" ); - fprintf( pTable, "%s ", p->pNtk->pName ); - fprintf( pTable, "%d ", Abc_NtkPiNum(p->pNtk) ); - fprintf( pTable, "%d ", Abc_NtkPoNum(p->pNtk) ); - fprintf( pTable, "%d ", Abc_NtkNodeNum(p->pNtk) ); - fprintf( pTable, "%d ", (int)p->SumArea ); - fprintf( pTable, "%d ", (int)SC_LibTimePs(p->pLib, p->MaxDelay) ); - fprintf( pTable, "%.2f ", 1.0*Time/CLOCKS_PER_SEC ); - fprintf( pTable, "\n" ); - fclose( pTable ); -} - - -/*=== sclTime.c =============================================================*/ -extern Abc_Obj_t * Abc_SclFindCriticalCo( SC_Man * p, int * pfRise ); -extern Abc_Obj_t * Abc_SclFindMostCriticalFanin( SC_Man * p, int * pfRise, Abc_Obj_t * pNode ); -extern void Abc_SclTimeNtkPrint( SC_Man * p, int fShowAll, int fShort ); -extern SC_Man * Abc_SclManStart( SC_Lib * pLib, Abc_Ntk_t * pNtk, int fUseWireLoads, int fDept, float DUser ); -extern void Abc_SclTimeCone( SC_Man * p, Vec_Int_t * vCone ); -extern void Abc_SclTimeNtkRecompute( SC_Man * p, float * pArea, float * pDelay, int fReverse, float DUser ); -/*=== sclTime.c =============================================================*/ -extern void Abc_SclComputeLoad( SC_Man * p ); -extern void Abc_SclUpdateLoad( SC_Man * p, Abc_Obj_t * pObj, SC_Cell * pOld, SC_Cell * pNew ); - - -ABC_NAMESPACE_HEADER_END - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// diff --git a/src/map/scl/sclSize.c b/src/map/scl/sclSize.c new file mode 100644 index 00000000..911bf5f3 --- /dev/null +++ b/src/map/scl/sclSize.c @@ -0,0 +1,572 @@ +/**CFile**************************************************************** + + FileName [sclSize.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Standard-cell library representation.] + + Synopsis [Core timing analysis used in gate-sizing.] + + Author [Alan Mishchenko, Niklas Een] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - August 24, 2012.] + + Revision [$Id: sclSize.c,v 1.0 2012/08/24 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "sclSize.h" +#include "map/mio/mio.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Finding most critical objects.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_SclFindCriticalCo( SC_Man * p, int * pfRise ) +{ + Abc_Obj_t * pObj, * pPivot = NULL; + float fMaxArr = 0; + int i; + Abc_NtkForEachCo( p->pNtk, pObj, i ) + { + SC_Pair * pArr = Abc_SclObjTime( p, pObj ); + if ( fMaxArr < pArr->rise ) fMaxArr = pArr->rise, *pfRise = 1, pPivot = pObj; + if ( fMaxArr < pArr->fall ) fMaxArr = pArr->fall, *pfRise = 0, pPivot = pObj; + } + assert( pPivot != NULL ); + return pPivot; +} +// assumes that slacks are not available (uses arrival times) +Abc_Obj_t * Abc_SclFindMostCriticalFanin2( SC_Man * p, int * pfRise, Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pFanin, * pPivot = NULL; + float fMaxArr = 0; + int i; + Abc_ObjForEachFanin( pNode, pFanin, i ) + { + SC_Pair * pArr = Abc_SclObjTime( p, pFanin ); + if ( fMaxArr < pArr->rise ) fMaxArr = pArr->rise, *pfRise = 1, pPivot = pFanin; + if ( fMaxArr < pArr->fall ) fMaxArr = pArr->fall, *pfRise = 0, pPivot = pFanin; + } + return pPivot; +} +// assumes that slack are available +Abc_Obj_t * Abc_SclFindMostCriticalFanin( SC_Man * p, int * pfRise, Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pFanin, * pPivot = NULL; + float fMinSlack = ABC_INFINITY; + SC_Pair * pArr; + int i; + *pfRise = 0; + // find min-slack node + Abc_ObjForEachFanin( pNode, pFanin, i ) + if ( fMinSlack > Abc_SclObjSlack( p, pFanin ) ) + { + fMinSlack = Abc_SclObjSlack( p, pFanin ); + pPivot = pFanin; + } + if ( pPivot == NULL ) + return NULL; + // find its leading phase + pArr = Abc_SclObjTime( p, pPivot ); + *pfRise = (pArr->rise >= pArr->fall); + return pPivot; +} + +/**Function************************************************************* + + Synopsis [Printing timing information for the node/network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Abc_SclTimeNodePrint( SC_Man * p, Abc_Obj_t * pObj, int fRise, int Length, float maxDelay ) +{ + printf( "%6d : ", Abc_ObjId(pObj) ); + printf( "%d ", Abc_ObjFaninNum(pObj) ); + printf( "%2d ", Abc_ObjFanoutNum(pObj) ); + printf( "%-*s ", Length, Abc_ObjIsNode(pObj) ? Abc_SclObjCell(p, pObj)->pName : "pi" ); + if ( fRise >= 0 ) + printf( "(%s) ", fRise ? "rise" : "fall" ); + printf( "A =%7.2f ", Abc_ObjIsNode(pObj) ? Abc_SclObjCell(p, pObj)->area : 0.0 ); + printf( "D = (" ); + printf( "%8.2f ps", Abc_SclObjTimePs(p, pObj, 1) ); + printf( "%8.2f ps ) ", Abc_SclObjTimePs(p, pObj, 0) ); + printf( "L =%7.2f ff ", Abc_SclObjLoadFf(p, pObj, fRise >= 0 ? fRise : 0 ) ); + printf( "S =%7.2f ps ", Abc_SclObjSlewPs(p, pObj, fRise >= 0 ? fRise : 0 ) ); + printf( "SL =%6.2f ps", Abc_SclObjSlack(p, pObj) ); + printf( "\n" ); +} +void Abc_SclTimeNtkPrint( SC_Man * p, int fShowAll, int fShort ) +{ + int i, nLength = 0, fRise = 0; + Abc_Obj_t * pObj, * pPivot = Abc_SclFindCriticalCo( p, &fRise ); + float maxDelay = Abc_SclObjTimePs(p, pPivot, fRise); + + printf( "WireLoad model = \"%s\". ", p->pWLoadUsed ? p->pWLoadUsed->pName : "none" ); + printf( "Gates = %6d. ", Abc_NtkNodeNum(p->pNtk) ); + printf( "Area = %12.2f. ", Abc_SclGetTotalArea( p ) ); + printf( "Critical delay = %8.2f ps\n", maxDelay ); + if ( fShort ) + return; + + if ( fShowAll ) + { +// printf( "Timing information for all nodes: \n" ); + // find the longest cell name + Abc_NtkForEachNodeReverse( p->pNtk, pObj, i ) + if ( Abc_ObjFaninNum(pObj) > 0 ) + nLength = Abc_MaxInt( nLength, strlen(Abc_SclObjCell(p, pObj)->pName) ); + // print timing + Abc_NtkForEachNodeReverse( p->pNtk, pObj, i ) + if ( Abc_ObjFaninNum(pObj) > 0 ) + Abc_SclTimeNodePrint( p, pObj, -1, nLength, maxDelay ); + } + else + { +// printf( "Critical path: \n" ); + // find the longest cell name + pObj = Abc_ObjFanin0(pPivot); + i = 0; + while ( pObj && Abc_ObjIsNode(pObj) ) + { + i++; + nLength = Abc_MaxInt( nLength, strlen(Abc_SclObjCell(p, pObj)->pName) ); + pObj = Abc_SclFindMostCriticalFanin( p, &fRise, pObj ); + } + // print timing + pObj = Abc_ObjFanin0(pPivot); + while ( pObj )//&& Abc_ObjIsNode(pObj) ) + { + printf( "C-path %3d -- ", i-- ); + Abc_SclTimeNodePrint( p, pObj, fRise, nLength, maxDelay ); + pObj = Abc_SclFindMostCriticalFanin( p, &fRise, pObj ); + } + } +} + +/**Function************************************************************* + + Synopsis [Timing computation for pin/gate/cone/network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline float Abc_SclLookup( SC_Surface * p, float slew, float load ) +{ + float * pIndex0, * pIndex1, * pDataS, * pDataS1; + float sfrac, lfrac, p0, p1; + int s, l; + + // Find closest sample points in surface: + pIndex0 = Vec_FltArray(p->vIndex0); + for ( s = 1; s < Vec_FltSize(p->vIndex0)-1; s++ ) + if ( pIndex0[s] > slew ) + break; + s--; + + pIndex1 = Vec_FltArray(p->vIndex1); + for ( l = 1; l < Vec_FltSize(p->vIndex1)-1; l++ ) + if ( pIndex1[l] > load ) + break; + l--; + + // Interpolate (or extrapolate) function value from sample points: + sfrac = (slew - pIndex0[s]) / (pIndex0[s+1] - pIndex0[s]); + lfrac = (load - pIndex1[l]) / (pIndex1[l+1] - pIndex1[l]); + + pDataS = Vec_FltArray( (Vec_Flt_t *)Vec_PtrEntry(p->vData, s) ); + pDataS1 = Vec_FltArray( (Vec_Flt_t *)Vec_PtrEntry(p->vData, s+1) ); + + p0 = pDataS [l] + lfrac * (pDataS [l+1] - pDataS [l]); + p1 = pDataS1[l] + lfrac * (pDataS1[l+1] - pDataS1[l]); + + return p0 + sfrac * (p1 - p0); // <<== multiply result with K factor here +} +void Abc_SclTimeFanin( SC_Man * p, SC_Timing * pTime, Abc_Obj_t * pObj, Abc_Obj_t * pFanin ) +{ + SC_Pair * pArrIn = Abc_SclObjTime( p, pFanin ); + SC_Pair * pSlewIn = Abc_SclObjSlew( p, pFanin ); + SC_Pair * pLoad = Abc_SclObjLoad( p, pObj ); + SC_Pair * pArrOut = Abc_SclObjTime( p, pObj ); // modified + SC_Pair * pSlewOut = Abc_SclObjSlew( p, pObj ); // modified + + if (pTime->tsense == sc_ts_Pos || pTime->tsense == sc_ts_Non) + { + pArrOut->rise = Abc_MaxFloat( pArrOut->rise, pArrIn->rise + Abc_SclLookup(pTime->pCellRise, pSlewIn->rise, pLoad->rise) ); + pArrOut->fall = Abc_MaxFloat( pArrOut->fall, pArrIn->fall + Abc_SclLookup(pTime->pCellFall, pSlewIn->fall, pLoad->fall) ); + pSlewOut->rise = Abc_MaxFloat( pSlewOut->rise, Abc_SclLookup(pTime->pRiseTrans, pSlewIn->rise, pLoad->rise) ); + pSlewOut->fall = Abc_MaxFloat( pSlewOut->fall, Abc_SclLookup(pTime->pFallTrans, pSlewIn->fall, pLoad->fall) ); + } + if (pTime->tsense == sc_ts_Neg || pTime->tsense == sc_ts_Non) + { + pArrOut->rise = Abc_MaxFloat( pArrOut->rise, pArrIn->fall + Abc_SclLookup(pTime->pCellRise, pSlewIn->fall, pLoad->rise) ); + pArrOut->fall = Abc_MaxFloat( pArrOut->fall, pArrIn->rise + Abc_SclLookup(pTime->pCellFall, pSlewIn->rise, pLoad->fall) ); + pSlewOut->rise = Abc_MaxFloat( pSlewOut->rise, Abc_SclLookup(pTime->pRiseTrans, pSlewIn->fall, pLoad->rise) ); + pSlewOut->fall = Abc_MaxFloat( pSlewOut->fall, Abc_SclLookup(pTime->pFallTrans, pSlewIn->rise, pLoad->fall) ); + } +} +void Abc_SclDeptFanin( SC_Man * p, SC_Timing * pTime, Abc_Obj_t * pObj, Abc_Obj_t * pFanin ) +{ + SC_Pair * pDepIn = Abc_SclObjDept( p, pFanin ); // modified + SC_Pair * pSlewIn = Abc_SclObjSlew( p, pFanin ); + SC_Pair * pLoad = Abc_SclObjLoad( p, pObj ); + SC_Pair * pDepOut = Abc_SclObjDept( p, pObj ); + + if (pTime->tsense == sc_ts_Pos || pTime->tsense == sc_ts_Non) + { + pDepIn->rise = Abc_MaxFloat( pDepIn->rise, pDepOut->rise + Abc_SclLookup(pTime->pCellRise, pSlewIn->rise, pLoad->rise) ); + pDepIn->fall = Abc_MaxFloat( pDepIn->fall, pDepOut->fall + Abc_SclLookup(pTime->pCellFall, pSlewIn->fall, pLoad->fall) ); + } + if (pTime->tsense == sc_ts_Neg || pTime->tsense == sc_ts_Non) + { + pDepIn->fall = Abc_MaxFloat( pDepIn->fall, pDepOut->rise + Abc_SclLookup(pTime->pCellRise, pSlewIn->fall, pLoad->rise) ); + pDepIn->rise = Abc_MaxFloat( pDepIn->rise, pDepOut->fall + Abc_SclLookup(pTime->pCellFall, pSlewIn->rise, pLoad->fall) ); + } +} +void Abc_SclTimeNode( SC_Man * p, Abc_Obj_t * pObj, int fDept ) +{ + SC_Timings * pRTime; + SC_Timing * pTime; + SC_Pin * pPin; + SC_Cell * pCell; + int k; + if ( Abc_ObjIsCo(pObj) ) + { + if ( !fDept ) + Abc_SclObjDupFanin( p, pObj ); + return; + } + assert( Abc_ObjIsNode(pObj) ); + // get the library cell + pCell = Abc_SclObjCell( p, pObj ); + // get the output pin +// assert( pCell->n_outputs == 1 ); + pPin = SC_CellPin( pCell, pCell->n_inputs ); + // compute timing using each fanin + assert( Vec_PtrSize(pPin->vRTimings) == pCell->n_inputs ); + SC_PinForEachRTiming( pPin, pRTime, k ) + { + assert( Vec_PtrSize(pRTime->vTimings) == 1 ); + pTime = (SC_Timing *)Vec_PtrEntry( pRTime->vTimings, 0 ); + if ( fDept ) + Abc_SclDeptFanin( p, pTime, pObj, Abc_ObjFanin(pObj, k) ); + else + Abc_SclTimeFanin( p, pTime, pObj, Abc_ObjFanin(pObj, k) ); + } +} +void Abc_SclTimeCone( SC_Man * p, Vec_Int_t * vCone ) +{ + int fVerbose = 0; + Abc_Obj_t * pObj; + int i; + Abc_SclConeClear( p, vCone ); + Abc_NtkForEachObjVec( vCone, p->pNtk, pObj, i ) + { + if ( fVerbose && Abc_ObjIsNode(pObj) ) + printf( " Updating node %d with gate %s\n", Abc_ObjId(pObj), Abc_SclObjCell(p, pObj)->pName ); + if ( fVerbose && Abc_ObjIsNode(pObj) ) + printf( " before (%6.1f ps %6.1f ps) ", Abc_SclObjTimePs(p, pObj, 1), Abc_SclObjTimePs(p, pObj, 0) ); + Abc_SclTimeNode( p, pObj, 0 ); + if ( fVerbose && Abc_ObjIsNode(pObj) ) + printf( "after (%6.1f ps %6.1f ps)\n", Abc_SclObjTimePs(p, pObj, 1), Abc_SclObjTimePs(p, pObj, 0) ); + } +} +void Abc_SclTimeNtkRecompute( SC_Man * p, float * pArea, float * pDelay, int fReverse, float DUser ) +{ + Abc_Obj_t * pObj; + float D; + int i; + Abc_SclComputeLoad( p ); + Abc_SclManCleanTime( p ); + Abc_NtkForEachNode1( p->pNtk, pObj, i ) + Abc_SclTimeNode( p, pObj, 0 ); + Abc_NtkForEachCo( p->pNtk, pObj, i ) + { + Abc_SclObjDupFanin( p, pObj ); + Vec_FltWriteEntry( p->vTimesOut, i, Abc_SclObjTimeMax(p, pObj) ); + Vec_QueUpdate( p->vQue, i ); + } + D = Abc_SclReadMaxDelay( p ); + if ( fReverse && DUser > 0 && D < DUser ) + D = DUser; + if ( pArea ) + *pArea = Abc_SclGetTotalArea( p ); + if ( pDelay ) + *pDelay = D; + if ( fReverse ) + { + Abc_NtkForEachNodeReverse1( p->pNtk, pObj, i ) + Abc_SclTimeNode( p, pObj, 1 ); + Abc_NtkForEachObj( p->pNtk, pObj, i ) + p->pSlack[i] = Abc_MaxFloat( 0.0, Abc_SclObjGetSlack(p, pObj, D) ); + } +} + +/**Function************************************************************* + + Synopsis [Read input slew and output load.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_SclManReadSlewAndLoad( SC_Man * p, Abc_Ntk_t * pNtk ) +{ + Abc_Time_t * pTime; + Abc_Obj_t * pObj; + int i; + if ( pNtk->pManTime == NULL ) + return; + // read input slew + pTime = Abc_NtkReadDefaultInputDrive( pNtk ); + if ( Abc_MaxFloat(pTime->Rise, pTime->Fall) != 0 ) + { + printf( "Default input slew is specified (%.2f ps; %.2f ps).\n", pTime->Rise, pTime->Fall ); + Abc_NtkForEachPi( pNtk, pObj, i ) + { + SC_Pair * pSlew = Abc_SclObjSlew( p, pObj ); + pSlew->rise = SC_LibTimeFromPs( p->pLib, pTime->Rise ); + pSlew->fall = SC_LibTimeFromPs( p->pLib, pTime->Fall ); + } + } + if ( Abc_NodeReadInputDrive(pNtk, 0) != NULL ) + { + printf( "Input slews for some primary inputs are specified.\n" ); + Abc_NtkForEachPi( pNtk, pObj, i ) + { + SC_Pair * pSlew = Abc_SclObjSlew( p, pObj ); + pTime = Abc_NodeReadInputDrive(pNtk, i); + pSlew->rise = SC_LibTimeFromPs( p->pLib, pTime->Rise ); + pSlew->fall = SC_LibTimeFromPs( p->pLib, pTime->Fall ); + } + } + // read output load + pTime = Abc_NtkReadDefaultOutputLoad( pNtk ); + if ( Abc_MaxFloat(pTime->Rise, pTime->Fall) != 0 ) + { + printf( "Default output load is specified (%.2f ff; %.2f ff).\n", pTime->Rise, pTime->Fall ); + Abc_NtkForEachPo( pNtk, pObj, i ) + { + SC_Pair * pSlew = Abc_SclObjLoad( p, pObj ); + pSlew->rise = SC_LibCapFromFf( p->pLib, pTime->Rise ); + pSlew->fall = SC_LibCapFromFf( p->pLib, pTime->Fall ); + } + } + if ( Abc_NodeReadOutputLoad(pNtk, 0) != NULL ) + { + printf( "Output loads for some primary outputs are specified.\n" ); + Abc_NtkForEachPo( pNtk, pObj, i ) + { + SC_Pair * pSlew = Abc_SclObjLoad( p, pObj ); + pTime = Abc_NodeReadOutputLoad(pNtk, i); + pSlew->rise = SC_LibCapFromFf( p->pLib, pTime->Rise ); + pSlew->fall = SC_LibCapFromFf( p->pLib, pTime->Fall ); + } + } +} + +/**Function************************************************************* + + Synopsis [Prepare timing manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +SC_Man * Abc_SclManStart( SC_Lib * pLib, Abc_Ntk_t * pNtk, int fUseWireLoads, int fDept, float DUser ) +{ + SC_Man * p = Abc_SclManAlloc( pLib, pNtk ); + assert( p->vGates == NULL ); + p->vGates = Abc_SclManFindGates( pLib, pNtk ); + Abc_SclManReadSlewAndLoad( p, pNtk ); + if ( fUseWireLoads ) + p->pWLoadUsed = Abc_SclFindWireLoadModel( pLib, Abc_SclGetTotalArea(p) ); + Abc_SclTimeNtkRecompute( p, &p->SumArea0, &p->MaxDelay0, fDept, DUser ); + p->SumArea = p->SumArea0; + return p; +} + +/**Function************************************************************* + + Synopsis [Printing out timing information for the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_SclTimePerform( SC_Lib * pLib, Abc_Ntk_t * pNtk, int fUseWireLoads, int fShowAll, int fShort, int fDumpStats ) +{ + SC_Man * p; + p = Abc_SclManStart( pLib, pNtk, fUseWireLoads, 1, 0 ); + Abc_SclTimeNtkPrint( p, fShowAll, fShort ); + if ( fDumpStats ) + Abc_SclDumpStats( p, "stats.txt", 0 ); + Abc_SclManFree( p ); +} + + + +/**Function************************************************************* + + Synopsis [Printing out fanin information.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_SclCheckCommonInputs( Abc_Obj_t * pObj, Abc_Obj_t * pFanin ) +{ + Abc_Obj_t * pTemp; + int i; + Abc_ObjForEachFanin( pObj, pTemp, i ) + if ( Abc_NodeFindFanin( pFanin, pTemp ) >= 0 ) + { + printf( "Node %d and its fanin %d have common fanin %d.\n", Abc_ObjId(pObj), Abc_ObjId(pFanin), Abc_ObjId(pTemp) ); + + printf( "%-16s : ", Mio_GateReadName((Mio_Gate_t *)pObj->pData) ); + Abc_ObjPrint( stdout, pObj ); + + printf( "%-16s : ", Mio_GateReadName((Mio_Gate_t *)pFanin->pData) ); + Abc_ObjPrint( stdout, pFanin ); + + if ( pTemp->pData ) + printf( "%-16s : ", Mio_GateReadName((Mio_Gate_t *)pTemp->pData) ); + Abc_ObjPrint( stdout, pTemp ); + return 1; + } + return 0; +} +void Abc_SclPrintFaninPairs( SC_Man * p, Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj, * pFanin; + int i, k; + Abc_NtkForEachNode( pNtk, pObj, i ) + Abc_ObjForEachFanin( pObj, pFanin, k ) + if ( Abc_ObjIsNode(pFanin) && Abc_ObjFanoutNum(pFanin) == 1 ) + Abc_SclCheckCommonInputs( pObj, pFanin ); +} + +/**Function************************************************************* + + Synopsis [Printing out buffer information.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Abc_ObjIsBuffer( Abc_Obj_t * pObj ) { return Abc_ObjIsNode(pObj) && Abc_ObjFaninNum(pObj) == 1; } +int Abc_SclCountNonBufferFanouts( Abc_Obj_t * pObj ) +{ + Abc_Obj_t * pFanout; + int i, Counter = 0; + if ( !Abc_ObjIsBuffer(pObj) ) + return 1; + Abc_ObjForEachFanout( pObj, pFanout, i ) + Counter += Abc_SclCountNonBufferFanouts( pFanout ); + return Counter; +} +int Abc_SclHasBufferFanout( Abc_Obj_t * pObj ) +{ + Abc_Obj_t * pFanout; + int i; + Abc_ObjForEachFanout( pObj, pFanout, i ) + if ( Abc_ObjIsBuffer(pFanout) ) + return 1; + return 0; +} +void Abc_SclPrintBuffersInt( SC_Man * p, Abc_Obj_t * pObj, int nOffset ) +{ +// SC_Cell_t * pCell = Abc_SclObjCell(p, pObj); + Abc_Obj_t * pFanout; + int i; + assert( Abc_ObjIsBuffer(pObj) ); + for ( i = 0; i < nOffset; i++ ) + printf( " " ); + printf( "%6d: %-16s (%2d:%3d) ", Abc_ObjId(pObj), Mio_GateReadName((Mio_Gate_t *)pObj->pData), + Abc_ObjFanoutNum(pObj), Abc_SclCountNonBufferFanouts(pObj) ); + for ( ; i < 4; i++ ) + printf( " " ); + printf( "a =%5.2f ", Abc_SclObjCell(p, pObj)->area ); + printf( "d = (" ); + printf( "%7.2f ps; ", Abc_SclObjTimePs(p, pObj, 1) ); + printf( "%7.2f ps) ", Abc_SclObjTimePs(p, pObj, 0) ); + printf( "l =%6.2f ff ", Abc_SclObjLoadFf(p, pObj, 0 ) ); + printf( "s =%6.2f ps ", Abc_SclObjSlewPs(p, pObj, 0 ) ); + printf( "sl =%6.2f ps", Abc_SclObjSlack(p, pObj) ); + printf( "\n" ); + Abc_ObjForEachFanout( pObj, pFanout, i ) + if ( Abc_ObjIsBuffer(pFanout) ) + Abc_SclPrintBuffersInt( p, pFanout, nOffset + 1 ); +} +void Abc_SclPrintBufferTrees( SC_Man * p, Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int i; + Abc_NtkForEachObj( pNtk, pObj, i ) + if ( Abc_ObjIsBuffer(pObj) && Abc_SclHasBufferFanout(pObj) ) + Abc_SclPrintBuffersInt( p, pObj, 0 ), printf( "\n" ); +} +void Abc_SclPrintBuffers( SC_Lib * pLib, Abc_Ntk_t * pNtk, int fVerbose ) +{ + int fUseWireLoads = 0; + SC_Man * p; + assert( Abc_NtkIsMappedLogic(pNtk) ); + p = Abc_SclManStart( pLib, pNtk, fUseWireLoads, 1, 0 ); + Abc_SclPrintBufferTrees( p, pNtk ); +// Abc_SclPrintFaninPairs( p, pNtk ); + Abc_SclManFree( p ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/map/scl/sclSize.h b/src/map/scl/sclSize.h new file mode 100644 index 00000000..e02f03a5 --- /dev/null +++ b/src/map/scl/sclSize.h @@ -0,0 +1,405 @@ +/**CFile**************************************************************** + + FileName [sclSize.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Standard-cell library representation.] + + Synopsis [Timing/gate-sizing manager.] + + Author [Alan Mishchenko, Niklas Een] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - August 24, 2012.] + + Revision [$Id: sclSize.h,v 1.0 2012/08/24 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef ABC__map__scl__sclSize_h +#define ABC__map__scl__sclSize_h + + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include "base/abc/abc.h" +#include "misc/vec/vecQue.h" +#include "sclLib.h" + +ABC_NAMESPACE_HEADER_START + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// STRUCTURE DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct SC_Man_ SC_Man; +struct SC_Man_ +{ + SC_Lib * pLib; // library + Abc_Ntk_t * pNtk; // network + int nObjs; // allocated size + // get assignment + Vec_Int_t * vGates; // mapping of objId into gateId + Vec_Int_t * vGatesBest; // best gate sizes found so far + Vec_Int_t * vUpdates; // sizing updates in this round + // timing information + SC_Pair * pLoads; // loads for each gate + SC_Pair * pLoads2; // loads for each gate + SC_Pair * pDepts; // departures for each gate + SC_Pair * pTimes; // arrivals for each gate + SC_Pair * pSlews; // slews for each gate + SC_Pair * pTimes2; // arrivals for each gate + SC_Pair * pSlews2; // slews for each gate + float * pSlack; // slacks for each gate + Vec_Flt_t * vTimesOut; // output arrival times + Vec_Que_t * vQue; // outputs by their time + SC_WireLoad * pWLoadUsed; // name of the used WireLoad model + // intermediate data + Vec_Que_t * vNodeByGain; // nodes by gain + Vec_Flt_t * vNode2Gain; // mapping node into its gain + Vec_Int_t * vNode2Gate; // mapping node into its best gate + Vec_Int_t * vNodeIter; // the last iteration the node was upsized + // optimization parameters + float SumArea; // total area + float MaxDelay; // max delay + float SumArea0; // total area at the begining + float MaxDelay0; // max delay at the begining + float BestDelay; // best delay in the middle + // runtime statistics + abctime timeTotal; // starting/total time + abctime timeCone; // critical path selection + abctime timeSize; // incremental sizing + abctime timeTime; // timing update + abctime timeOther; // everything else +}; + +//////////////////////////////////////////////////////////////////////// +/// GLOBAL VARIABLES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +static inline SC_Cell * Abc_SclObjCell( SC_Man * p, Abc_Obj_t * pObj ) { return SC_LibCell( p->pLib, Vec_IntEntry(p->vGates, Abc_ObjId(pObj)) ); } +static inline void Abc_SclObjSetCell( SC_Man * p, Abc_Obj_t * pObj, SC_Cell * pCell ) { Vec_IntWriteEntry( p->vGates, Abc_ObjId(pObj), pCell->Id ); } + +static inline SC_Pair * Abc_SclObjLoad( SC_Man * p, Abc_Obj_t * pObj ) { return p->pLoads + Abc_ObjId(pObj); } +static inline SC_Pair * Abc_SclObjLoad2( SC_Man * p, Abc_Obj_t * pObj ) { return p->pLoads2 + Abc_ObjId(pObj); } +static inline SC_Pair * Abc_SclObjDept( SC_Man * p, Abc_Obj_t * pObj ) { return p->pDepts + Abc_ObjId(pObj); } +static inline SC_Pair * Abc_SclObjTime( SC_Man * p, Abc_Obj_t * pObj ) { return p->pTimes + Abc_ObjId(pObj); } +static inline SC_Pair * Abc_SclObjSlew( SC_Man * p, Abc_Obj_t * pObj ) { return p->pSlews + Abc_ObjId(pObj); } +static inline SC_Pair * Abc_SclObjTime2( SC_Man * p, Abc_Obj_t * pObj ) { return p->pTimes2 + Abc_ObjId(pObj); } +static inline SC_Pair * Abc_SclObjSlew2( SC_Man * p, Abc_Obj_t * pObj ) { return p->pSlews2 + Abc_ObjId(pObj); } + +static inline float Abc_SclObjTimeMax( SC_Man * p, Abc_Obj_t * pObj ) { return Abc_MaxFloat(Abc_SclObjTime(p, pObj)->rise, Abc_SclObjTime(p, pObj)->fall); } +static inline float Abc_SclObjDepthMax( SC_Man * p, Abc_Obj_t * pObj ) { return Abc_MaxFloat(Abc_SclObjDept(p, pObj)->rise, Abc_SclObjDept(p, pObj)->fall); } +static inline float Abc_SclObjGetSlack( SC_Man * p, Abc_Obj_t * pObj, float D ) { return D - Abc_MaxFloat(Abc_SclObjTime(p, pObj)->rise + Abc_SclObjDept(p, pObj)->rise, Abc_SclObjTime(p, pObj)->fall + Abc_SclObjDept(p, pObj)->fall); } +static inline float Abc_SclObjGetSlackR( SC_Man * p, Abc_Obj_t * pObj, float D ){ return D - (Abc_SclObjTime(p, pObj)->rise + Abc_SclObjDept(p, pObj)->rise); } +static inline float Abc_SclObjGetSlackF( SC_Man * p, Abc_Obj_t * pObj, float D ){ return D - (Abc_SclObjTime(p, pObj)->fall + Abc_SclObjDept(p, pObj)->fall); } +static inline float Abc_SclObjSlack( SC_Man * p, Abc_Obj_t * pObj ) { return p->pSlack[Abc_ObjId(pObj)]; } + +static inline void Abc_SclObjDupFanin( SC_Man * p, Abc_Obj_t * pObj ) { assert( Abc_ObjIsCo(pObj) ); *Abc_SclObjTime(p, pObj) = *Abc_SclObjTime(p, Abc_ObjFanin0(pObj)); } +static inline float Abc_SclObjGain( SC_Man * p, Abc_Obj_t * pObj ) { return 0.5*((Abc_SclObjTime2(p, pObj)->rise - Abc_SclObjTime(p, pObj)->rise) + (Abc_SclObjTime2(p, pObj)->fall - Abc_SclObjTime(p, pObj)->fall)); } +static inline int Abc_SclObjLegal( SC_Man * p, Abc_Obj_t * pObj, float D ) { return Abc_SclObjTime(p, pObj)->rise <= Abc_SclObjTime2(p, pObj)->rise + Abc_SclObjGetSlackR(p, pObj, D) && Abc_SclObjTime(p, pObj)->fall <= Abc_SclObjTime2(p, pObj)->fall + Abc_SclObjGetSlackF(p, pObj, D); } + +static inline double Abc_SclObjLoadFf( SC_Man * p, Abc_Obj_t * pObj, int fRise ) { return SC_LibCapFf( p->pLib, fRise ? Abc_SclObjLoad(p, pObj)->rise : Abc_SclObjLoad(p, pObj)->fall); } +static inline double Abc_SclObjTimePs( SC_Man * p, Abc_Obj_t * pObj, int fRise ) { return SC_LibTimePs(p->pLib, fRise ? Abc_SclObjTime(p, pObj)->rise : Abc_SclObjTime(p, pObj)->fall); } +static inline double Abc_SclObjSlewPs( SC_Man * p, Abc_Obj_t * pObj, int fRise ) { return SC_LibTimePs(p->pLib, fRise ? Abc_SclObjSlew(p, pObj)->rise : Abc_SclObjSlew(p, pObj)->fall); } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Constructor/destructor of STA manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline SC_Man * Abc_SclManAlloc( SC_Lib * pLib, Abc_Ntk_t * pNtk ) +{ + SC_Man * p; + int i; + assert( Abc_NtkHasMapping(pNtk) ); + p = ABC_CALLOC( SC_Man, 1 ); + p->pLib = pLib; + p->pNtk = pNtk; + p->nObjs = Abc_NtkObjNumMax(pNtk); + p->pLoads = ABC_CALLOC( SC_Pair, p->nObjs ); + p->pLoads2 = ABC_CALLOC( SC_Pair, p->nObjs ); + p->pDepts = ABC_CALLOC( SC_Pair, p->nObjs ); + p->pTimes = ABC_CALLOC( SC_Pair, p->nObjs ); + p->pSlews = ABC_CALLOC( SC_Pair, p->nObjs ); + p->pTimes2 = ABC_CALLOC( SC_Pair, p->nObjs ); + p->pSlews2 = ABC_CALLOC( SC_Pair, p->nObjs ); + p->pSlack = ABC_FALLOC( float, p->nObjs ); + p->vTimesOut = Vec_FltStart( Abc_NtkCoNum(pNtk) ); + p->vQue = Vec_QueAlloc( Abc_NtkCoNum(pNtk) ); + Vec_QueSetCosts( p->vQue, Vec_FltArrayP(p->vTimesOut) ); + for ( i = 0; i < Abc_NtkCoNum(pNtk); i++ ) + Vec_QuePush( p->vQue, i ); + p->vUpdates = Vec_IntAlloc( 1000 ); + // intermediate data + p->vNode2Gain = Vec_FltStart( p->nObjs ); + p->vNode2Gate = Vec_IntStart( p->nObjs ); + p->vNodeByGain = Vec_QueAlloc( p->nObjs ); + Vec_QueSetCosts( p->vNodeByGain, Vec_FltArrayP(p->vNode2Gain) ); + p->vNodeIter = Vec_IntStartFull( p->nObjs ); + return p; +} +static inline void Abc_SclManFree( SC_Man * p ) +{ + Vec_IntFreeP( &p->vNodeIter ); + Vec_QueFreeP( &p->vNodeByGain ); + Vec_FltFreeP( &p->vNode2Gain ); + Vec_IntFreeP( &p->vNode2Gate ); + // intermediate data + Vec_IntFreeP( &p->vUpdates ); + Vec_IntFreeP( &p->vGatesBest ); +// Vec_QuePrint( p->vQue ); + Vec_QueCheck( p->vQue ); + Vec_QueFreeP( &p->vQue ); + Vec_FltFreeP( &p->vTimesOut ); + Vec_IntFreeP( &p->vGates ); + ABC_FREE( p->pLoads ); + ABC_FREE( p->pLoads2 ); + ABC_FREE( p->pDepts ); + ABC_FREE( p->pTimes ); + ABC_FREE( p->pSlews ); + ABC_FREE( p->pTimes2 ); + ABC_FREE( p->pSlews2 ); + ABC_FREE( p->pSlack ); + ABC_FREE( p ); +} +static inline void Abc_SclManCleanTime( SC_Man * p ) +{ + Vec_Flt_t * vSlews; + Abc_Obj_t * pObj; + int i; + vSlews = Vec_FltAlloc( 2 * Abc_NtkPiNum(p->pNtk) ); + Abc_NtkForEachPi( p->pNtk, pObj, i ) + { + SC_Pair * pSlew = Abc_SclObjSlew( p, pObj ); + Vec_FltPush( vSlews, pSlew->rise ); + Vec_FltPush( vSlews, pSlew->fall ); + } + memset( p->pDepts, 0, sizeof(SC_Pair) * p->nObjs ); + memset( p->pTimes, 0, sizeof(SC_Pair) * p->nObjs ); + memset( p->pSlews, 0, sizeof(SC_Pair) * p->nObjs ); + Abc_NtkForEachPi( p->pNtk, pObj, i ) + { + SC_Pair * pSlew = Abc_SclObjSlew( p, pObj ); + pSlew->rise = Vec_FltEntry( vSlews, 2 * i + 0 ); + pSlew->fall = Vec_FltEntry( vSlews, 2 * i + 1 ); + } + Vec_FltFree( vSlews ); +} + + +/**Function************************************************************* + + Synopsis [Stores/retrivies timing information for the logic cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Abc_SclConeStore( SC_Man * p, Vec_Int_t * vCone ) +{ + Abc_Obj_t * pObj; + int i; + Abc_NtkForEachObjVec( vCone, p->pNtk, pObj, i ) + { + *Abc_SclObjTime2(p, pObj) = *Abc_SclObjTime(p, pObj); + *Abc_SclObjSlew2(p, pObj) = *Abc_SclObjSlew(p, pObj); + } +} +static inline void Abc_SclConeRestore( SC_Man * p, Vec_Int_t * vCone ) +{ + Abc_Obj_t * pObj; + int i; + Abc_NtkForEachObjVec( vCone, p->pNtk, pObj, i ) + { + *Abc_SclObjTime(p, pObj) = *Abc_SclObjTime2(p, pObj); + *Abc_SclObjSlew(p, pObj) = *Abc_SclObjSlew2(p, pObj); + } +} +static inline void Abc_SclConeClear( SC_Man * p, Vec_Int_t * vCone ) +{ + SC_Pair Zero = { 0.0, 0.0 }; + Abc_Obj_t * pObj; + int i; + Abc_NtkForEachObjVec( vCone, p->pNtk, pObj, i ) + { + *Abc_SclObjTime(p, pObj) = Zero; + *Abc_SclObjSlew(p, pObj) = Zero; + } +} + +/**Function************************************************************* + + Synopsis [Stores/retrivies load information.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Abc_SclLoadStore( SC_Man * p, Abc_Obj_t * pObj ) +{ + Abc_Obj_t * pFanin; + int i; + Abc_ObjForEachFanin( pObj, pFanin, i ) + *Abc_SclObjLoad2(p, pFanin) = *Abc_SclObjLoad(p, pFanin); +} +static inline void Abc_SclLoadRestore( SC_Man * p, Abc_Obj_t * pObj ) +{ + Abc_Obj_t * pFanin; + int i; + Abc_ObjForEachFanin( pObj, pFanin, i ) + *Abc_SclObjLoad(p, pFanin) = *Abc_SclObjLoad2(p, pFanin); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline float Abc_SclGetTotalArea( SC_Man * p ) +{ + double Area = 0; + Abc_Obj_t * pObj; + int i; + Abc_NtkForEachNode1( p->pNtk, pObj, i ) + Area += Abc_SclObjCell( p, pObj )->area; + return Area; +} +static inline float Abc_SclGetMaxDelay( SC_Man * p ) +{ + float fMaxArr = 0; + Abc_Obj_t * pObj; + int i; + Abc_NtkForEachCo( p->pNtk, pObj, i ) + fMaxArr = Abc_MaxFloat( fMaxArr, Abc_SclObjTimeMax(p, pObj) ); + return fMaxArr; +} +static inline float Abc_SclGetMaxDelayNodeFanins( SC_Man * p, Abc_Obj_t * pNode ) +{ + float fMaxArr = 0; + Abc_Obj_t * pObj; + int i; + assert( Abc_ObjIsNode(pNode) ); + Abc_ObjForEachFanin( pNode, pObj, i ) + fMaxArr = Abc_MaxFloat( fMaxArr, Abc_SclObjTimeMax(p, pObj) ); + return fMaxArr; +} +static inline float Abc_SclReadMaxDelay( SC_Man * p ) +{ + return Abc_SclObjTimeMax( p, Abc_NtkCo(p->pNtk, Vec_QueTop(p->vQue)) ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline SC_Cell * Abc_SclObjResiable( SC_Man * p, Abc_Obj_t * pObj, int fUpsize ) +{ + SC_Cell * pOld = Abc_SclObjCell( p, pObj ); + if ( fUpsize ) + return pOld->pNext->Order > pOld->Order ? pOld->pNext : NULL; + else + return pOld->pPrev->Order < pOld->Order ? pOld->pPrev : NULL; +} + +/**Function************************************************************* + + Synopsis [Dumps timing results into a file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Abc_SclDumpStats( SC_Man * p, char * pFileName, abctime Time ) +{ + FILE * pTable; + pTable = fopen( pFileName, "a+" ); + fprintf( pTable, "%s ", p->pNtk->pName ); + fprintf( pTable, "%d ", Abc_NtkPiNum(p->pNtk) ); + fprintf( pTable, "%d ", Abc_NtkPoNum(p->pNtk) ); + fprintf( pTable, "%d ", Abc_NtkNodeNum(p->pNtk) ); + fprintf( pTable, "%d ", (int)p->SumArea ); + fprintf( pTable, "%d ", (int)SC_LibTimePs(p->pLib, p->MaxDelay) ); + fprintf( pTable, "%.2f ", 1.0*Time/CLOCKS_PER_SEC ); + fprintf( pTable, "\n" ); + fclose( pTable ); +} + + +/*=== sclBuff.c ===============================================================*/ +extern int Abc_SclCheckNtk( Abc_Ntk_t * p, int fVerbose ); +extern Abc_Ntk_t * Abc_SclPerformBuffering( Abc_Ntk_t * p, int Degree, int fVerbose ); +/*=== sclDnsize.c ===============================================================*/ +extern void Abc_SclDnsizePerform( SC_Lib * pLib, Abc_Ntk_t * pNtk, SC_SizePars * pPars ); +/*=== sclLoad.c ===============================================================*/ +extern void Abc_SclComputeLoad( SC_Man * p ); +extern void Abc_SclUpdateLoad( SC_Man * p, Abc_Obj_t * pObj, SC_Cell * pOld, SC_Cell * pNew ); +/*=== sclSize.c ===============================================================*/ +extern Abc_Obj_t * Abc_SclFindCriticalCo( SC_Man * p, int * pfRise ); +extern Abc_Obj_t * Abc_SclFindMostCriticalFanin( SC_Man * p, int * pfRise, Abc_Obj_t * pNode ); +extern void Abc_SclTimeNtkPrint( SC_Man * p, int fShowAll, int fShort ); +extern SC_Man * Abc_SclManStart( SC_Lib * pLib, Abc_Ntk_t * pNtk, int fUseWireLoads, int fDept, float DUser ); +extern void Abc_SclTimeCone( SC_Man * p, Vec_Int_t * vCone ); +extern void Abc_SclTimeNtkRecompute( SC_Man * p, float * pArea, float * pDelay, int fReverse, float DUser ); +extern void Abc_SclTimePerform( SC_Lib * pLib, Abc_Ntk_t * pNtk, int fUseWireLoads, int fShowAll, int fShort, int fDumpStats ); +extern void Abc_SclPrintBuffers( SC_Lib * pLib, Abc_Ntk_t * pNtk, int fVerbose ); +/*=== sclUpsize.c ===============================================================*/ +extern void Abc_SclUpsizePerform( SC_Lib * pLib, Abc_Ntk_t * pNtk, SC_SizePars * pPars ); +/*=== sclUtil.c ===============================================================*/ +extern Vec_Int_t * Abc_SclManFindGates( SC_Lib * pLib, Abc_Ntk_t * p ); +extern void Abc_SclManSetGates( SC_Lib * pLib, Abc_Ntk_t * p, Vec_Int_t * vGates ); +extern void Abc_SclPrintGateSizes( SC_Lib * pLib, Abc_Ntk_t * p ); +extern void Abc_SclMinsizePerform( SC_Lib * pLib, Abc_Ntk_t * p, int fUseMax, int fVerbose ); + + +ABC_NAMESPACE_HEADER_END + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// diff --git a/src/map/scl/sclTime.c b/src/map/scl/sclTime.c deleted file mode 100644 index 7d2ddc31..00000000 --- a/src/map/scl/sclTime.c +++ /dev/null @@ -1,573 +0,0 @@ -/**CFile**************************************************************** - - FileName [sclTime.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Standard-cell library representation.] - - Synopsis [Static timing analysis using Liberty delay model.] - - Author [Alan Mishchenko, Niklas Een] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - August 24, 2012.] - - Revision [$Id: sclTime.c,v 1.0 2012/08/24 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "sclInt.h" -#include "sclMan.h" -#include "map/mio/mio.h" - -ABC_NAMESPACE_IMPL_START - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Finding most critical objects.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Abc_SclFindCriticalCo( SC_Man * p, int * pfRise ) -{ - Abc_Obj_t * pObj, * pPivot = NULL; - float fMaxArr = 0; - int i; - Abc_NtkForEachCo( p->pNtk, pObj, i ) - { - SC_Pair * pArr = Abc_SclObjTime( p, pObj ); - if ( fMaxArr < pArr->rise ) fMaxArr = pArr->rise, *pfRise = 1, pPivot = pObj; - if ( fMaxArr < pArr->fall ) fMaxArr = pArr->fall, *pfRise = 0, pPivot = pObj; - } - assert( pPivot != NULL ); - return pPivot; -} -// assumes that slacks are not available (uses arrival times) -Abc_Obj_t * Abc_SclFindMostCriticalFanin2( SC_Man * p, int * pfRise, Abc_Obj_t * pNode ) -{ - Abc_Obj_t * pFanin, * pPivot = NULL; - float fMaxArr = 0; - int i; - Abc_ObjForEachFanin( pNode, pFanin, i ) - { - SC_Pair * pArr = Abc_SclObjTime( p, pFanin ); - if ( fMaxArr < pArr->rise ) fMaxArr = pArr->rise, *pfRise = 1, pPivot = pFanin; - if ( fMaxArr < pArr->fall ) fMaxArr = pArr->fall, *pfRise = 0, pPivot = pFanin; - } - return pPivot; -} -// assumes that slack are available -Abc_Obj_t * Abc_SclFindMostCriticalFanin( SC_Man * p, int * pfRise, Abc_Obj_t * pNode ) -{ - Abc_Obj_t * pFanin, * pPivot = NULL; - float fMinSlack = ABC_INFINITY; - SC_Pair * pArr; - int i; - *pfRise = 0; - // find min-slack node - Abc_ObjForEachFanin( pNode, pFanin, i ) - if ( fMinSlack > Abc_SclObjSlack( p, pFanin ) ) - { - fMinSlack = Abc_SclObjSlack( p, pFanin ); - pPivot = pFanin; - } - if ( pPivot == NULL ) - return NULL; - // find its leading phase - pArr = Abc_SclObjTime( p, pPivot ); - *pfRise = (pArr->rise >= pArr->fall); - return pPivot; -} - -/**Function************************************************************* - - Synopsis [Printing timing information for the node/network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Abc_SclTimeNodePrint( SC_Man * p, Abc_Obj_t * pObj, int fRise, int Length, float maxDelay ) -{ - printf( "%6d : ", Abc_ObjId(pObj) ); - printf( "%d ", Abc_ObjFaninNum(pObj) ); - printf( "%2d ", Abc_ObjFanoutNum(pObj) ); - printf( "%-*s ", Length, Abc_ObjIsNode(pObj) ? Abc_SclObjCell(p, pObj)->pName : "pi" ); - if ( fRise >= 0 ) - printf( "(%s) ", fRise ? "rise" : "fall" ); - printf( "A =%7.2f ", Abc_ObjIsNode(pObj) ? Abc_SclObjCell(p, pObj)->area : 0.0 ); - printf( "D = (" ); - printf( "%8.2f ps", Abc_SclObjTimePs(p, pObj, 1) ); - printf( "%8.2f ps ) ", Abc_SclObjTimePs(p, pObj, 0) ); - printf( "L =%7.2f ff ", Abc_SclObjLoadFf(p, pObj, fRise >= 0 ? fRise : 0 ) ); - printf( "S =%7.2f ps ", Abc_SclObjSlewPs(p, pObj, fRise >= 0 ? fRise : 0 ) ); - printf( "SL =%6.2f ps", Abc_SclObjSlack(p, pObj) ); - printf( "\n" ); -} -void Abc_SclTimeNtkPrint( SC_Man * p, int fShowAll, int fShort ) -{ - int i, nLength = 0, fRise = 0; - Abc_Obj_t * pObj, * pPivot = Abc_SclFindCriticalCo( p, &fRise ); - float maxDelay = Abc_SclObjTimePs(p, pPivot, fRise); - - printf( "WireLoad model = \"%s\". ", p->pWLoadUsed ? p->pWLoadUsed->pName : "none" ); - printf( "Gates = %6d. ", Abc_NtkNodeNum(p->pNtk) ); - printf( "Area = %12.2f. ", Abc_SclGetTotalArea( p ) ); - printf( "Critical delay = %8.2f ps\n", maxDelay ); - if ( fShort ) - return; - - if ( fShowAll ) - { -// printf( "Timing information for all nodes: \n" ); - // find the longest cell name - Abc_NtkForEachNodeReverse( p->pNtk, pObj, i ) - if ( Abc_ObjFaninNum(pObj) > 0 ) - nLength = Abc_MaxInt( nLength, strlen(Abc_SclObjCell(p, pObj)->pName) ); - // print timing - Abc_NtkForEachNodeReverse( p->pNtk, pObj, i ) - if ( Abc_ObjFaninNum(pObj) > 0 ) - Abc_SclTimeNodePrint( p, pObj, -1, nLength, maxDelay ); - } - else - { -// printf( "Critical path: \n" ); - // find the longest cell name - pObj = Abc_ObjFanin0(pPivot); - i = 0; - while ( pObj && Abc_ObjIsNode(pObj) ) - { - i++; - nLength = Abc_MaxInt( nLength, strlen(Abc_SclObjCell(p, pObj)->pName) ); - pObj = Abc_SclFindMostCriticalFanin( p, &fRise, pObj ); - } - // print timing - pObj = Abc_ObjFanin0(pPivot); - while ( pObj )//&& Abc_ObjIsNode(pObj) ) - { - printf( "C-path %3d -- ", i-- ); - Abc_SclTimeNodePrint( p, pObj, fRise, nLength, maxDelay ); - pObj = Abc_SclFindMostCriticalFanin( p, &fRise, pObj ); - } - } -} - -/**Function************************************************************* - - Synopsis [Timing computation for pin/gate/cone/network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline float Abc_SclLookup( SC_Surface * p, float slew, float load ) -{ - float * pIndex0, * pIndex1, * pDataS, * pDataS1; - float sfrac, lfrac, p0, p1; - int s, l; - - // Find closest sample points in surface: - pIndex0 = Vec_FltArray(p->vIndex0); - for ( s = 1; s < Vec_FltSize(p->vIndex0)-1; s++ ) - if ( pIndex0[s] > slew ) - break; - s--; - - pIndex1 = Vec_FltArray(p->vIndex1); - for ( l = 1; l < Vec_FltSize(p->vIndex1)-1; l++ ) - if ( pIndex1[l] > load ) - break; - l--; - - // Interpolate (or extrapolate) function value from sample points: - sfrac = (slew - pIndex0[s]) / (pIndex0[s+1] - pIndex0[s]); - lfrac = (load - pIndex1[l]) / (pIndex1[l+1] - pIndex1[l]); - - pDataS = Vec_FltArray( (Vec_Flt_t *)Vec_PtrEntry(p->vData, s) ); - pDataS1 = Vec_FltArray( (Vec_Flt_t *)Vec_PtrEntry(p->vData, s+1) ); - - p0 = pDataS [l] + lfrac * (pDataS [l+1] - pDataS [l]); - p1 = pDataS1[l] + lfrac * (pDataS1[l+1] - pDataS1[l]); - - return p0 + sfrac * (p1 - p0); // <<== multiply result with K factor here -} -void Abc_SclTimeFanin( SC_Man * p, SC_Timing * pTime, Abc_Obj_t * pObj, Abc_Obj_t * pFanin ) -{ - SC_Pair * pArrIn = Abc_SclObjTime( p, pFanin ); - SC_Pair * pSlewIn = Abc_SclObjSlew( p, pFanin ); - SC_Pair * pLoad = Abc_SclObjLoad( p, pObj ); - SC_Pair * pArrOut = Abc_SclObjTime( p, pObj ); // modified - SC_Pair * pSlewOut = Abc_SclObjSlew( p, pObj ); // modified - - if (pTime->tsense == sc_ts_Pos || pTime->tsense == sc_ts_Non) - { - pArrOut->rise = Abc_MaxFloat( pArrOut->rise, pArrIn->rise + Abc_SclLookup(pTime->pCellRise, pSlewIn->rise, pLoad->rise) ); - pArrOut->fall = Abc_MaxFloat( pArrOut->fall, pArrIn->fall + Abc_SclLookup(pTime->pCellFall, pSlewIn->fall, pLoad->fall) ); - pSlewOut->rise = Abc_MaxFloat( pSlewOut->rise, Abc_SclLookup(pTime->pRiseTrans, pSlewIn->rise, pLoad->rise) ); - pSlewOut->fall = Abc_MaxFloat( pSlewOut->fall, Abc_SclLookup(pTime->pFallTrans, pSlewIn->fall, pLoad->fall) ); - } - if (pTime->tsense == sc_ts_Neg || pTime->tsense == sc_ts_Non) - { - pArrOut->rise = Abc_MaxFloat( pArrOut->rise, pArrIn->fall + Abc_SclLookup(pTime->pCellRise, pSlewIn->fall, pLoad->rise) ); - pArrOut->fall = Abc_MaxFloat( pArrOut->fall, pArrIn->rise + Abc_SclLookup(pTime->pCellFall, pSlewIn->rise, pLoad->fall) ); - pSlewOut->rise = Abc_MaxFloat( pSlewOut->rise, Abc_SclLookup(pTime->pRiseTrans, pSlewIn->fall, pLoad->rise) ); - pSlewOut->fall = Abc_MaxFloat( pSlewOut->fall, Abc_SclLookup(pTime->pFallTrans, pSlewIn->rise, pLoad->fall) ); - } -} -void Abc_SclDeptFanin( SC_Man * p, SC_Timing * pTime, Abc_Obj_t * pObj, Abc_Obj_t * pFanin ) -{ - SC_Pair * pDepIn = Abc_SclObjDept( p, pFanin ); // modified - SC_Pair * pSlewIn = Abc_SclObjSlew( p, pFanin ); - SC_Pair * pLoad = Abc_SclObjLoad( p, pObj ); - SC_Pair * pDepOut = Abc_SclObjDept( p, pObj ); - - if (pTime->tsense == sc_ts_Pos || pTime->tsense == sc_ts_Non) - { - pDepIn->rise = Abc_MaxFloat( pDepIn->rise, pDepOut->rise + Abc_SclLookup(pTime->pCellRise, pSlewIn->rise, pLoad->rise) ); - pDepIn->fall = Abc_MaxFloat( pDepIn->fall, pDepOut->fall + Abc_SclLookup(pTime->pCellFall, pSlewIn->fall, pLoad->fall) ); - } - if (pTime->tsense == sc_ts_Neg || pTime->tsense == sc_ts_Non) - { - pDepIn->fall = Abc_MaxFloat( pDepIn->fall, pDepOut->rise + Abc_SclLookup(pTime->pCellRise, pSlewIn->fall, pLoad->rise) ); - pDepIn->rise = Abc_MaxFloat( pDepIn->rise, pDepOut->fall + Abc_SclLookup(pTime->pCellFall, pSlewIn->rise, pLoad->fall) ); - } -} -void Abc_SclTimeNode( SC_Man * p, Abc_Obj_t * pObj, int fDept ) -{ - SC_Timings * pRTime; - SC_Timing * pTime; - SC_Pin * pPin; - SC_Cell * pCell; - int k; - if ( Abc_ObjIsCo(pObj) ) - { - if ( !fDept ) - Abc_SclObjDupFanin( p, pObj ); - return; - } - assert( Abc_ObjIsNode(pObj) ); - // get the library cell - pCell = Abc_SclObjCell( p, pObj ); - // get the output pin -// assert( pCell->n_outputs == 1 ); - pPin = SC_CellPin( pCell, pCell->n_inputs ); - // compute timing using each fanin - assert( Vec_PtrSize(pPin->vRTimings) == pCell->n_inputs ); - SC_PinForEachRTiming( pPin, pRTime, k ) - { - assert( Vec_PtrSize(pRTime->vTimings) == 1 ); - pTime = (SC_Timing *)Vec_PtrEntry( pRTime->vTimings, 0 ); - if ( fDept ) - Abc_SclDeptFanin( p, pTime, pObj, Abc_ObjFanin(pObj, k) ); - else - Abc_SclTimeFanin( p, pTime, pObj, Abc_ObjFanin(pObj, k) ); - } -} -void Abc_SclTimeCone( SC_Man * p, Vec_Int_t * vCone ) -{ - int fVerbose = 0; - Abc_Obj_t * pObj; - int i; - Abc_SclConeClear( p, vCone ); - Abc_NtkForEachObjVec( vCone, p->pNtk, pObj, i ) - { - if ( fVerbose && Abc_ObjIsNode(pObj) ) - printf( " Updating node %d with gate %s\n", Abc_ObjId(pObj), Abc_SclObjCell(p, pObj)->pName ); - if ( fVerbose && Abc_ObjIsNode(pObj) ) - printf( " before (%6.1f ps %6.1f ps) ", Abc_SclObjTimePs(p, pObj, 1), Abc_SclObjTimePs(p, pObj, 0) ); - Abc_SclTimeNode( p, pObj, 0 ); - if ( fVerbose && Abc_ObjIsNode(pObj) ) - printf( "after (%6.1f ps %6.1f ps)\n", Abc_SclObjTimePs(p, pObj, 1), Abc_SclObjTimePs(p, pObj, 0) ); - } -} -void Abc_SclTimeNtkRecompute( SC_Man * p, float * pArea, float * pDelay, int fReverse, float DUser ) -{ - Abc_Obj_t * pObj; - float D; - int i; - Abc_SclComputeLoad( p ); - Abc_SclManCleanTime( p ); - Abc_NtkForEachNode1( p->pNtk, pObj, i ) - Abc_SclTimeNode( p, pObj, 0 ); - Abc_NtkForEachCo( p->pNtk, pObj, i ) - { - Abc_SclObjDupFanin( p, pObj ); - Vec_FltWriteEntry( p->vTimesOut, i, Abc_SclObjTimeMax(p, pObj) ); - Vec_QueUpdate( p->vQue, i ); - } - D = Abc_SclReadMaxDelay( p ); - if ( fReverse && DUser > 0 && D < DUser ) - D = DUser; - if ( pArea ) - *pArea = Abc_SclGetTotalArea( p ); - if ( pDelay ) - *pDelay = D; - if ( fReverse ) - { - Abc_NtkForEachNodeReverse1( p->pNtk, pObj, i ) - Abc_SclTimeNode( p, pObj, 1 ); - Abc_NtkForEachObj( p->pNtk, pObj, i ) - p->pSlack[i] = Abc_MaxFloat( 0.0, Abc_SclObjGetSlack(p, pObj, D) ); - } -} - -/**Function************************************************************* - - Synopsis [Read input slew and output load.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_SclManReadSlewAndLoad( SC_Man * p, Abc_Ntk_t * pNtk ) -{ - Abc_Time_t * pTime; - Abc_Obj_t * pObj; - int i; - if ( pNtk->pManTime == NULL ) - return; - // read input slew - pTime = Abc_NtkReadDefaultInputDrive( pNtk ); - if ( Abc_MaxFloat(pTime->Rise, pTime->Fall) != 0 ) - { - printf( "Default input slew is specified (%.2f ps; %.2f ps).\n", pTime->Rise, pTime->Fall ); - Abc_NtkForEachPi( pNtk, pObj, i ) - { - SC_Pair * pSlew = Abc_SclObjSlew( p, pObj ); - pSlew->rise = SC_LibTimeFromPs( p->pLib, pTime->Rise ); - pSlew->fall = SC_LibTimeFromPs( p->pLib, pTime->Fall ); - } - } - if ( Abc_NodeReadInputDrive(pNtk, 0) != NULL ) - { - printf( "Input slews for some primary inputs are specified.\n" ); - Abc_NtkForEachPi( pNtk, pObj, i ) - { - SC_Pair * pSlew = Abc_SclObjSlew( p, pObj ); - pTime = Abc_NodeReadInputDrive(pNtk, i); - pSlew->rise = SC_LibTimeFromPs( p->pLib, pTime->Rise ); - pSlew->fall = SC_LibTimeFromPs( p->pLib, pTime->Fall ); - } - } - // read output load - pTime = Abc_NtkReadDefaultOutputLoad( pNtk ); - if ( Abc_MaxFloat(pTime->Rise, pTime->Fall) != 0 ) - { - printf( "Default output load is specified (%.2f ff; %.2f ff).\n", pTime->Rise, pTime->Fall ); - Abc_NtkForEachPo( pNtk, pObj, i ) - { - SC_Pair * pSlew = Abc_SclObjLoad( p, pObj ); - pSlew->rise = SC_LibCapFromFf( p->pLib, pTime->Rise ); - pSlew->fall = SC_LibCapFromFf( p->pLib, pTime->Fall ); - } - } - if ( Abc_NodeReadOutputLoad(pNtk, 0) != NULL ) - { - printf( "Output loads for some primary outputs are specified.\n" ); - Abc_NtkForEachPo( pNtk, pObj, i ) - { - SC_Pair * pSlew = Abc_SclObjLoad( p, pObj ); - pTime = Abc_NodeReadOutputLoad(pNtk, i); - pSlew->rise = SC_LibCapFromFf( p->pLib, pTime->Rise ); - pSlew->fall = SC_LibCapFromFf( p->pLib, pTime->Fall ); - } - } -} - -/**Function************************************************************* - - Synopsis [Prepare timing manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -SC_Man * Abc_SclManStart( SC_Lib * pLib, Abc_Ntk_t * pNtk, int fUseWireLoads, int fDept, float DUser ) -{ - SC_Man * p = Abc_SclManAlloc( pLib, pNtk ); - assert( p->vGates == NULL ); - p->vGates = Abc_SclManFindGates( pLib, pNtk ); - Abc_SclManReadSlewAndLoad( p, pNtk ); - if ( fUseWireLoads ) - p->pWLoadUsed = Abc_SclFindWireLoadModel( pLib, Abc_SclGetTotalArea(p) ); - Abc_SclTimeNtkRecompute( p, &p->SumArea0, &p->MaxDelay0, fDept, DUser ); - p->SumArea = p->SumArea0; - return p; -} - -/**Function************************************************************* - - Synopsis [Printing out timing information for the network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_SclTimePerform( SC_Lib * pLib, Abc_Ntk_t * pNtk, int fUseWireLoads, int fShowAll, int fShort, int fDumpStats ) -{ - SC_Man * p; - p = Abc_SclManStart( pLib, pNtk, fUseWireLoads, 1, 0 ); - Abc_SclTimeNtkPrint( p, fShowAll, fShort ); - if ( fDumpStats ) - Abc_SclDumpStats( p, "stats.txt", 0 ); - Abc_SclManFree( p ); -} - - - -/**Function************************************************************* - - Synopsis [Printing out fanin information.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_SclCheckCommonInputs( Abc_Obj_t * pObj, Abc_Obj_t * pFanin ) -{ - Abc_Obj_t * pTemp; - int i; - Abc_ObjForEachFanin( pObj, pTemp, i ) - if ( Abc_NodeFindFanin( pFanin, pTemp ) >= 0 ) - { - printf( "Node %d and its fanin %d have common fanin %d.\n", Abc_ObjId(pObj), Abc_ObjId(pFanin), Abc_ObjId(pTemp) ); - - printf( "%-16s : ", Mio_GateReadName((Mio_Gate_t *)pObj->pData) ); - Abc_ObjPrint( stdout, pObj ); - - printf( "%-16s : ", Mio_GateReadName((Mio_Gate_t *)pFanin->pData) ); - Abc_ObjPrint( stdout, pFanin ); - - if ( pTemp->pData ) - printf( "%-16s : ", Mio_GateReadName((Mio_Gate_t *)pTemp->pData) ); - Abc_ObjPrint( stdout, pTemp ); - return 1; - } - return 0; -} -void Abc_SclPrintFaninPairs( SC_Man * p, Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pObj, * pFanin; - int i, k; - Abc_NtkForEachNode( pNtk, pObj, i ) - Abc_ObjForEachFanin( pObj, pFanin, k ) - if ( Abc_ObjIsNode(pFanin) && Abc_ObjFanoutNum(pFanin) == 1 ) - Abc_SclCheckCommonInputs( pObj, pFanin ); -} - -/**Function************************************************************* - - Synopsis [Printing out buffer information.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Abc_ObjIsBuffer( Abc_Obj_t * pObj ) { return Abc_ObjIsNode(pObj) && Abc_ObjFaninNum(pObj) == 1; } -int Abc_SclCountNonBufferFanouts( Abc_Obj_t * pObj ) -{ - Abc_Obj_t * pFanout; - int i, Counter = 0; - if ( !Abc_ObjIsBuffer(pObj) ) - return 1; - Abc_ObjForEachFanout( pObj, pFanout, i ) - Counter += Abc_SclCountNonBufferFanouts( pFanout ); - return Counter; -} -int Abc_SclHasBufferFanout( Abc_Obj_t * pObj ) -{ - Abc_Obj_t * pFanout; - int i; - Abc_ObjForEachFanout( pObj, pFanout, i ) - if ( Abc_ObjIsBuffer(pFanout) ) - return 1; - return 0; -} -void Abc_SclPrintBuffersInt( SC_Man * p, Abc_Obj_t * pObj, int nOffset ) -{ -// SC_Cell_t * pCell = Abc_SclObjCell(p, pObj); - Abc_Obj_t * pFanout; - int i; - assert( Abc_ObjIsBuffer(pObj) ); - for ( i = 0; i < nOffset; i++ ) - printf( " " ); - printf( "%6d: %-16s (%2d:%3d) ", Abc_ObjId(pObj), Mio_GateReadName((Mio_Gate_t *)pObj->pData), - Abc_ObjFanoutNum(pObj), Abc_SclCountNonBufferFanouts(pObj) ); - for ( ; i < 4; i++ ) - printf( " " ); - printf( "a =%5.2f ", Abc_SclObjCell(p, pObj)->area ); - printf( "d = (" ); - printf( "%7.2f ps; ", Abc_SclObjTimePs(p, pObj, 1) ); - printf( "%7.2f ps) ", Abc_SclObjTimePs(p, pObj, 0) ); - printf( "l =%6.2f ff ", Abc_SclObjLoadFf(p, pObj, 0 ) ); - printf( "s =%6.2f ps ", Abc_SclObjSlewPs(p, pObj, 0 ) ); - printf( "sl =%6.2f ps", Abc_SclObjSlack(p, pObj) ); - printf( "\n" ); - Abc_ObjForEachFanout( pObj, pFanout, i ) - if ( Abc_ObjIsBuffer(pFanout) ) - Abc_SclPrintBuffersInt( p, pFanout, nOffset + 1 ); -} -void Abc_SclPrintBufferTrees( SC_Man * p, Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pObj; - int i; - Abc_NtkForEachObj( pNtk, pObj, i ) - if ( Abc_ObjIsBuffer(pObj) && Abc_SclHasBufferFanout(pObj) ) - Abc_SclPrintBuffersInt( p, pObj, 0 ), printf( "\n" ); -} -void Abc_SclPrintBuffers( SC_Lib * pLib, Abc_Ntk_t * pNtk, int fVerbose ) -{ - int fUseWireLoads = 0; - SC_Man * p; - assert( Abc_NtkIsMappedLogic(pNtk) ); - p = Abc_SclManStart( pLib, pNtk, fUseWireLoads, 1, 0 ); - Abc_SclPrintBufferTrees( p, pNtk ); -// Abc_SclPrintFaninPairs( p, pNtk ); - Abc_SclManFree( p ); -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - -ABC_NAMESPACE_IMPL_END - diff --git a/src/map/scl/sclTime.h b/src/map/scl/sclTime.h new file mode 100644 index 00000000..3ba2bed0 --- /dev/null +++ b/src/map/scl/sclTime.h @@ -0,0 +1,288 @@ +/**CFile**************************************************************** + + FileName [sclTime.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Standard-cell library representation.] + + Synopsis [Timing/gate-sizing manager.] + + Author [Alan Mishchenko, Niklas Een] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - August 24, 2012.] + + Revision [$Id: sclTime.h,v 1.0 2012/08/24 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef ABC__map__scl__sclTime_h +#define ABC__map__scl__sclTime_h + + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include "misc/vec/vec.h" +#include "sclLib.h" + +ABC_NAMESPACE_HEADER_START + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// STRUCTURE DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct SC_Time_ SC_Time; +struct SC_Time_ +{ + SC_Lib * pLib; // library + Vec_Int_t * vCis; // comb inputs + Vec_Int_t * vCos; // comb outputs + int nObjs; // allocated size + // get assignment + Vec_Int_t * vGates; // mapping of objId into gateId + // timing information + SC_Pair * pLoads; // loads for each gate + SC_Pair * pLoads2; // loads for each gate + SC_Pair * pDepts; // departures for each gate + SC_Pair * pTimes; // arrivals for each gate + SC_Pair * pSlews; // slews for each gate + SC_Pair * pTimes2; // arrivals for each gate + SC_Pair * pSlews2; // slews for each gate + float * pSlack; // slacks for each gate + SC_WireLoad * pWLoadUsed; // name of the used WireLoad model + // optimization parameters + float SumArea; // total area + float MaxDelay; // max delay + float SumArea0; // total area at the begining + float MaxDelay0; // max delay at the begining + float BestDelay; // best delay in the middle +}; + +//////////////////////////////////////////////////////////////////////// +/// GLOBAL VARIABLES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +static inline SC_Cell * Scl_ObjCell( SC_Time * p, int i ) { return SC_LibCell( p->pLib, Vec_IntEntry(p->vGates, i) ); } +static inline void Scl_ObjSetCell( SC_Time * p, int i, SC_Cell * pCell ) { Vec_IntWriteEntry( p->vGates, i, pCell->Id ); } + +static inline SC_Pair * Scl_ObjLoad( SC_Time * p, int i ) { return p->pLoads + i; } +static inline SC_Pair * Scl_ObjLoad2( SC_Time * p, int i ) { return p->pLoads2 + i; } +static inline SC_Pair * Scl_ObjDept( SC_Time * p, int i ) { return p->pDepts + i; } +static inline SC_Pair * Scl_ObjTime( SC_Time * p, int i ) { return p->pTimes + i; } +static inline SC_Pair * Scl_ObjSlew( SC_Time * p, int i ) { return p->pSlews + i; } +static inline SC_Pair * Scl_ObjTime2( SC_Time * p, int i ) { return p->pTimes2 + i; } +static inline SC_Pair * Scl_ObjSlew2( SC_Time * p, int i ) { return p->pSlews2 + i; } + +static inline float Scl_ObjTimeMax( SC_Time * p, int i ) { return Abc_MaxFloat(Scl_ObjTime(p, i)->rise, Scl_ObjTime(p, i)->fall); } +static inline float Scl_ObjDepthMax( SC_Time * p, int i ) { return Abc_MaxFloat(Scl_ObjDept(p, i)->rise, Scl_ObjDept(p, i)->fall); } +static inline float Scl_ObjGetSlack( SC_Time * p, int i, float D ) { return D - Abc_MaxFloat(Scl_ObjTime(p, i)->rise + Scl_ObjDept(p, i)->rise, Scl_ObjTime(p, i)->fall + Scl_ObjDept(p, i)->fall); } +static inline float Scl_ObjGetSlackR( SC_Time * p, int i, float D ) { return D - (Scl_ObjTime(p, i)->rise + Scl_ObjDept(p, i)->rise); } +static inline float Scl_ObjGetSlackF( SC_Time * p, int i, float D ) { return D - (Scl_ObjTime(p, i)->fall + Scl_ObjDept(p, i)->fall); } +static inline float Scl_ObjSlack( SC_Time * p, int i ) { return p->pSlack[i]; } + +static inline void Scl_ObjDupFanin( SC_Time * p, int i, int iFanin ) { *Scl_ObjTime(p, i) = *Scl_ObjTime(p, iFanin); } +static inline float Scl_ObjGain( SC_Time * p, int i ) { return 0.5*((Scl_ObjTime2(p, i)->rise - Scl_ObjTime(p, i)->rise) + (Scl_ObjTime2(p, i)->fall - Scl_ObjTime(p, i)->fall)); } +static inline int Scl_ObjLegal( SC_Time * p, int i, float D ) { return Scl_ObjTime(p, i)->rise <= Scl_ObjTime2(p, i)->rise + Scl_ObjGetSlackR(p, i, D) && Scl_ObjTime(p, i)->fall <= Scl_ObjTime2(p, i)->fall + Scl_ObjGetSlackF(p, i, D); } + +static inline double Scl_ObjLoadFf( SC_Time * p, int i, int fRise ) { return SC_LibCapFf( p->pLib, fRise ? Scl_ObjLoad(p, i)->rise : Scl_ObjLoad(p, i)->fall); } +static inline double Scl_ObjTimePs( SC_Time * p, int i, int fRise ) { return SC_LibTimePs(p->pLib, fRise ? Scl_ObjTime(p, i)->rise : Scl_ObjTime(p, i)->fall); } +static inline double Scl_ObjSlewPs( SC_Time * p, int i, int fRise ) { return SC_LibTimePs(p->pLib, fRise ? Scl_ObjSlew(p, i)->rise : Scl_ObjSlew(p, i)->fall); } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Constructor/destructor of STA manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline SC_Time * Scl_ManAlloc( SC_Lib * pLib, Vec_Int_t * vCis, Vec_Int_t * vCos, int nObjs ) +{ + SC_Time * p; + p = ABC_CALLOC( SC_Time, 1 ); + p->pLib = pLib; + p->vCis = vCis; + p->vCos = vCos; + p->nObjs = nObjs; + p->pLoads = ABC_CALLOC( SC_Pair, p->nObjs ); + p->pLoads2 = ABC_CALLOC( SC_Pair, p->nObjs ); + p->pDepts = ABC_CALLOC( SC_Pair, p->nObjs ); + p->pTimes = ABC_CALLOC( SC_Pair, p->nObjs ); + p->pSlews = ABC_CALLOC( SC_Pair, p->nObjs ); + p->pTimes2 = ABC_CALLOC( SC_Pair, p->nObjs ); + p->pSlews2 = ABC_CALLOC( SC_Pair, p->nObjs ); + p->pSlack = ABC_FALLOC( float, p->nObjs ); + return p; +} +static inline void Scl_ManFree( SC_Time * p ) +{ + Vec_IntFreeP( &p->vGates ); + ABC_FREE( p->pLoads ); + ABC_FREE( p->pLoads2 ); + ABC_FREE( p->pDepts ); + ABC_FREE( p->pTimes ); + ABC_FREE( p->pSlews ); + ABC_FREE( p->pTimes2 ); + ABC_FREE( p->pSlews2 ); + ABC_FREE( p->pSlack ); + ABC_FREE( p ); +} +static inline void Scl_ManCleanTime( SC_Time * p ) +{ + memset( p->pDepts, 0, sizeof(SC_Pair) * p->nObjs ); + memset( p->pTimes, 0, sizeof(SC_Pair) * p->nObjs ); + memset( p->pSlews, 0, sizeof(SC_Pair) * p->nObjs ); +} + + +/**Function************************************************************* + + Synopsis [Stores/retrieves timing information for the logic cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Scl_ConeStore( SC_Time * p, Vec_Int_t * vCone ) +{ + int i, iObj; + Vec_IntForEachEntry( vCone, iObj, i ) + { + *Scl_ObjTime2(p, iObj) = *Scl_ObjTime(p, iObj); + *Scl_ObjSlew2(p, iObj) = *Scl_ObjSlew(p, iObj); + } +} +static inline void Scl_ConeRestore( SC_Time * p, Vec_Int_t * vCone ) +{ + int i, iObj; + Vec_IntForEachEntry( vCone, iObj, i ) + { + *Scl_ObjTime(p, iObj) = *Scl_ObjTime2(p, iObj); + *Scl_ObjSlew(p, iObj) = *Scl_ObjSlew2(p, iObj); + } +} +static inline void Scl_ConeClear( SC_Time * p, Vec_Int_t * vCone ) +{ + SC_Pair Zero = { 0.0, 0.0 }; + int i, iObj; + Vec_IntForEachEntry( vCone, iObj, i ) + { + *Scl_ObjTime(p, iObj) = Zero; + *Scl_ObjSlew(p, iObj) = Zero; + } +} + +/**Function************************************************************* + + Synopsis [Timing computation for pin/gate/cone/network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline float Scl_Lookup( SC_Surface * p, float slew, float load ) +{ + float * pIndex0, * pIndex1, * pDataS, * pDataS1; + float sfrac, lfrac, p0, p1; + int s, l; + + // Find closest sample points in surface: + pIndex0 = Vec_FltArray(p->vIndex0); + for ( s = 1; s < Vec_FltSize(p->vIndex0)-1; s++ ) + if ( pIndex0[s] > slew ) + break; + s--; + + pIndex1 = Vec_FltArray(p->vIndex1); + for ( l = 1; l < Vec_FltSize(p->vIndex1)-1; l++ ) + if ( pIndex1[l] > load ) + break; + l--; + + // Interpolate (or extrapolate) function value from sample points: + sfrac = (slew - pIndex0[s]) / (pIndex0[s+1] - pIndex0[s]); + lfrac = (load - pIndex1[l]) / (pIndex1[l+1] - pIndex1[l]); + + pDataS = Vec_FltArray( (Vec_Flt_t *)Vec_PtrEntry(p->vData, s) ); + pDataS1 = Vec_FltArray( (Vec_Flt_t *)Vec_PtrEntry(p->vData, s+1) ); + + p0 = pDataS [l] + lfrac * (pDataS [l+1] - pDataS [l]); + p1 = pDataS1[l] + lfrac * (pDataS1[l+1] - pDataS1[l]); + + return p0 + sfrac * (p1 - p0); // <<== multiply result with K factor here +} +static inline void Scl_TimeFanin( SC_Time * p, SC_Timing * pTime, int iObj, int iFanin ) +{ + SC_Pair * pArrIn = Scl_ObjTime( p, iFanin ); + SC_Pair * pSlewIn = Scl_ObjSlew( p, iFanin ); + SC_Pair * pLoad = Scl_ObjLoad( p, iObj ); + SC_Pair * pArrOut = Scl_ObjTime( p, iObj ); // modified + SC_Pair * pSlewOut = Scl_ObjSlew( p, iObj ); // modified + + if (pTime->tsense == sc_ts_Pos || pTime->tsense == sc_ts_Non) + { + pArrOut->rise = Abc_MaxFloat( pArrOut->rise, pArrIn->rise + Scl_Lookup(pTime->pCellRise, pSlewIn->rise, pLoad->rise) ); + pArrOut->fall = Abc_MaxFloat( pArrOut->fall, pArrIn->fall + Scl_Lookup(pTime->pCellFall, pSlewIn->fall, pLoad->fall) ); + pSlewOut->rise = Abc_MaxFloat( pSlewOut->rise, Scl_Lookup(pTime->pRiseTrans, pSlewIn->rise, pLoad->rise) ); + pSlewOut->fall = Abc_MaxFloat( pSlewOut->fall, Scl_Lookup(pTime->pFallTrans, pSlewIn->fall, pLoad->fall) ); + } + if (pTime->tsense == sc_ts_Neg || pTime->tsense == sc_ts_Non) + { + pArrOut->rise = Abc_MaxFloat( pArrOut->rise, pArrIn->fall + Scl_Lookup(pTime->pCellRise, pSlewIn->fall, pLoad->rise) ); + pArrOut->fall = Abc_MaxFloat( pArrOut->fall, pArrIn->rise + Scl_Lookup(pTime->pCellFall, pSlewIn->rise, pLoad->fall) ); + pSlewOut->rise = Abc_MaxFloat( pSlewOut->rise, Scl_Lookup(pTime->pRiseTrans, pSlewIn->fall, pLoad->rise) ); + pSlewOut->fall = Abc_MaxFloat( pSlewOut->fall, Scl_Lookup(pTime->pFallTrans, pSlewIn->rise, pLoad->fall) ); + } +} +static inline void Scl_DeptFanin( SC_Time * p, SC_Timing * pTime, int iObj, int iFanin ) +{ + SC_Pair * pDepIn = Scl_ObjDept( p, iFanin ); // modified + SC_Pair * pSlewIn = Scl_ObjSlew( p, iFanin ); + SC_Pair * pLoad = Scl_ObjLoad( p, iObj ); + SC_Pair * pDepOut = Scl_ObjDept( p, iObj ); + + if (pTime->tsense == sc_ts_Pos || pTime->tsense == sc_ts_Non) + { + pDepIn->rise = Abc_MaxFloat( pDepIn->rise, pDepOut->rise + Scl_Lookup(pTime->pCellRise, pSlewIn->rise, pLoad->rise) ); + pDepIn->fall = Abc_MaxFloat( pDepIn->fall, pDepOut->fall + Scl_Lookup(pTime->pCellFall, pSlewIn->fall, pLoad->fall) ); + } + if (pTime->tsense == sc_ts_Neg || pTime->tsense == sc_ts_Non) + { + pDepIn->fall = Abc_MaxFloat( pDepIn->fall, pDepOut->rise + Scl_Lookup(pTime->pCellRise, pSlewIn->fall, pLoad->rise) ); + pDepIn->rise = Abc_MaxFloat( pDepIn->rise, pDepOut->fall + Scl_Lookup(pTime->pCellFall, pSlewIn->rise, pLoad->fall) ); + } +} + + +ABC_NAMESPACE_HEADER_END + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// diff --git a/src/map/scl/sclUpsize.c b/src/map/scl/sclUpsize.c index f56d1afd..d0d82d97 100644 --- a/src/map/scl/sclUpsize.c +++ b/src/map/scl/sclUpsize.c @@ -18,8 +18,7 @@ ***********************************************************************/ -#include "sclInt.h" -#include "sclMan.h" +#include "sclSize.h" ABC_NAMESPACE_IMPL_START diff --git a/src/map/scl/sclUtil.c b/src/map/scl/sclUtil.c index d535ee66..5543fff8 100644 --- a/src/map/scl/sclUtil.c +++ b/src/map/scl/sclUtil.c @@ -18,9 +18,8 @@ ***********************************************************************/ -#include "sclInt.h" +#include "sclSize.h" #include "map/mio/mio.h" -#include "bool/kit/kit.h" ABC_NAMESPACE_IMPL_START @@ -33,177 +32,6 @@ ABC_NAMESPACE_IMPL_START /// 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 ) -{ - return *Abc_SclHashLookup( p, pName ); -} - -/**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; - return strcmp( (*pp1)->pName, (*pp2)->pName ); -} -void Abc_SclLinkCells( SC_Lib * p ) -{ - 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 the 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 - SC_LibForEachCellClass( p, pRepr, k ) - { - Vec_Ptr_t * vList = Vec_PtrAlloc( 100 ); - 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->Order = 0; - // 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->Order = i; - } - // update list - Vec_PtrWriteEntry( p->vCellClasses, k, pRepr ); - Vec_PtrFree( vList ); - } -} -void Abc_SclPrintCells( SC_Lib * p ) -{ - SC_Cell * pCell, * pRepr; - int i, k, j, nLength = 0; - assert( Vec_PtrSize(p->vCellClasses) > 0 ); - printf( "Library \"%s\" ", p->pName ); - printf( "containing %d cells in %d classes.\n", - Vec_PtrSize(p->vCells), Vec_PtrSize(p->vCellClasses) ); - // 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 ) - { - 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 ) - { - printf( " %3d : ", i+1 ); - printf( "%-*s ", nLength, pCell->pName ); - printf( "%2d ", pCell->drive_strength ); - printf( "A =%8.2f D =", pCell->area ); - // print linear approximation - for ( j = 0; j < 3; j++ ) - { - SC_Pin * pPin = SC_CellPin( pCell, pCell->n_inputs ); - if ( Vec_PtrSize(pPin->vRTimings) > 0 ) - { - SC_Timings * pRTime = (SC_Timings *)Vec_PtrEntry( pPin->vRTimings, 0 ); - SC_Timing * pTime = (SC_Timing *)Vec_PtrEntry( pRTime->vTimings, 0 ); - printf( " %6.2f", j ? pTime->pCellRise->approx[0][j] : SC_LibTimePs(p, pTime->pCellRise->approx[0][j]) ); - } - } - // print input capacitance - printf( " Cap =" ); - for ( j = 0; j < pCell->n_inputs; j++ ) - { - SC_Pin * pPin = SC_CellPin( pCell, j ); - printf( " %6.2f", SC_LibCapFf(p, pPin->rise_cap) ); - } - printf( "\n" ); - } - } -} - /**Function************************************************************* Synopsis [Converts pNode->pData gates into array of SC_Lit gate IDs and back.] -- cgit v1.2.3