From 56592b28c20d09825d5f2c8159de35590b4d1b10 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Sat, 20 Jul 2013 19:11:29 -0700 Subject: Added command 'dnsize' to complement command 'upsize'. --- src/map/scl/module.make | 1 + src/map/scl/scl.c | 206 +++++++++++++++++++++++++++- src/map/scl/sclDnsize.c | 352 ++++++++++++++++++++++++++++++++++++++++++++++++ src/map/scl/sclInt.h | 27 +++- src/map/scl/sclMan.h | 7 +- src/map/scl/sclTime.c | 130 +++++++++++++++++- src/map/scl/sclUpsize.c | 27 ++-- src/map/scl/sclUtil.c | 11 +- 8 files changed, 730 insertions(+), 31 deletions(-) create mode 100644 src/map/scl/sclDnsize.c (limited to 'src/map') diff --git a/src/map/scl/module.make b/src/map/scl/module.make index 355d29f6..d0fba6b0 100644 --- a/src/map/scl/module.make +++ b/src/map/scl/module.make @@ -1,5 +1,6 @@ SRC += src/map/scl/scl.c \ src/map/scl/sclBuff.c \ + src/map/scl/sclDnsize.c \ src/map/scl/sclFile.c \ src/map/scl/sclLoad.c \ src/map/scl/sclTime.c \ diff --git a/src/map/scl/scl.c b/src/map/scl/scl.c index 4b856321..51fc8cec 100644 --- a/src/map/scl/scl.c +++ b/src/map/scl/scl.c @@ -37,7 +37,9 @@ static int Scl_CommandTopo ( Abc_Frame_t * pAbc, int argc, char **argv ); static int Scl_CommandBuffer ( Abc_Frame_t * pAbc, int argc, char **argv ); static int Scl_CommandGsize ( Abc_Frame_t * pAbc, int argc, char **argv ); static int Scl_CommandUpsize ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int Scl_CommandDnsize ( Abc_Frame_t * pAbc, int argc, char **argv ); static int Scl_CommandMinsize ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int Scl_CommandPrintBuf( Abc_Frame_t * pAbc, int argc, char **argv ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// @@ -65,6 +67,8 @@ void Scl_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "SCL mapping", "buffer", Scl_CommandBuffer, 1 ); Cmd_CommandAdd( pAbc, "SCL mapping", "minsize", Scl_CommandMinsize, 1 ); Cmd_CommandAdd( pAbc, "SCL mapping", "upsize", Scl_CommandUpsize, 1 ); + Cmd_CommandAdd( pAbc, "SCL mapping", "dnsize", Scl_CommandDnsize, 1 ); + Cmd_CommandAdd( pAbc, "SCL mapping", "print_buf", Scl_CommandPrintBuf, 1 ); // Cmd_CommandAdd( pAbc, "SCL mapping", "gsize", Scl_CommandGsize, 1 ); } void Scl_End( Abc_Frame_t * pAbc ) @@ -298,10 +302,10 @@ usage: int Scl_CommandStime( Abc_Frame_t * pAbc, int argc, char **argv ) { int c; - int fShowAll = 0; + int fShowAll = 0; int fUseWireLoads = 1; - int fShort = 0; - int fDumpStats = 0; + int fShort = 1; + int fDumpStats = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "casdh" ) ) != EOF ) @@ -840,7 +844,7 @@ int Scl_CommandUpsize( Abc_Frame_t * pAbc, int argc, char **argv ) return 0; usage: - fprintf( pAbc->Err, "usage: upsize [-IJWRNT num] [-dvwh]\n" ); + fprintf( pAbc->Err, "usage: upsize [-IJWRNT num] [-sdvwh]\n" ); fprintf( pAbc->Err, "\t selectively increases gate sizes on the critical path\n" ); fprintf( pAbc->Err, "\t-I : the number of upsizing iterations to perform [default = %d]\n", pPars->nIters ); fprintf( pAbc->Err, "\t-J : the number of iterations without improvement to stop [default = %d]\n", pPars->nIterNoChange ); @@ -856,6 +860,200 @@ usage: return 1; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Scl_CommandDnsize( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + SC_DnSizePars Pars, * pPars = &Pars; + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + int c; + memset( pPars, 0, sizeof(SC_DnSizePars) ); + pPars->DUser = 0; + pPars->nIters = 5; + pPars->nIterNoChange = 50; + pPars->TimeOut = 0; + pPars->fUseDept = 1; + pPars->fDumpStats = 0; + pPars->fVerbose = 0; + pPars->fVeryVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "DIJTsdvwh" ) ) != EOF ) + { + switch ( c ) + { + case 'D': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-D\" should be followed by a positive integer.\n" ); + goto usage; + } + pPars->DUser = atof(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->DUser < 0 ) + goto usage; + break; + case 'I': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-I\" should be followed by a positive integer.\n" ); + goto usage; + } + pPars->nIters = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nIters < 0 ) + goto usage; + break; + case 'J': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-J\" should be followed by a positive integer.\n" ); + goto usage; + } + pPars->nIterNoChange = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nIterNoChange < 0 ) + goto usage; + break; + case 'T': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-T\" should be followed by a positive integer.\n" ); + goto usage; + } + pPars->TimeOut = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->TimeOut < 0 ) + goto usage; + break; + case 's': + pPars->fUseDept ^= 1; + break; + case 'd': + pPars->fDumpStats ^= 1; + break; + case 'v': + pPars->fVerbose ^= 1; + break; + case 'w': + pPars->fVeryVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( Abc_FrameReadNtk(pAbc) == NULL ) + { + fprintf( pAbc->Err, "There is no current network.\n" ); + return 1; + } + if ( !Abc_NtkHasMapping(Abc_FrameReadNtk(pAbc)) ) + { + fprintf( pAbc->Err, "The current network is not mapped.\n" ); + return 1; + } + if ( !Abc_SclCheckNtk(Abc_FrameReadNtk(pAbc), 0) ) + { + fprintf( pAbc->Err, "The current network is not in a topo order (run \"topo\").\n" ); + return 1; + } + if ( pAbc->pLibScl == NULL ) + { + fprintf( pAbc->Err, "There is no Liberty library available.\n" ); + return 1; + } + + Abc_SclDnsizePerform( (SC_Lib *)pAbc->pLibScl, pNtk, pPars ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: dnsize [-DIJT num] [-sdvwh]\n" ); + fprintf( pAbc->Err, "\t selectively decreases gate sizes while maintaining delay\n" ); + fprintf( pAbc->Err, "\t-D : the target max delay after downsizing in picosecs [default = %.2f]\n", pPars->DUser ); + fprintf( pAbc->Err, "\t-I : the number of upsizing iterations to perform [default = %d]\n", pPars->nIters ); + fprintf( pAbc->Err, "\t-J : the number of iterations without improvement to stop [default = %d]\n", pPars->nIterNoChange ); + fprintf( pAbc->Err, "\t-T : approximate timeout in seconds [default = %d]\n", pPars->TimeOut ); + fprintf( pAbc->Err, "\t-s : toggle using slack based on departure times [default = %s]\n", pPars->fUseDept? "yes": "no" ); + fprintf( pAbc->Err, "\t-d : toggle dumping statistics into a file [default = %s]\n", pPars->fDumpStats? "yes": "no" ); + fprintf( pAbc->Err, "\t-v : toggle printing verbose information [default = %s]\n", pPars->fVerbose? "yes": "no" ); + fprintf( pAbc->Err, "\t-w : toggle printing more verbose information [default = %s]\n", pPars->fVeryVerbose? "yes": "no" ); + fprintf( pAbc->Err, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Scl_CommandPrintBuf( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + int c, fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) + { + switch ( c ) + { + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( Abc_FrameReadNtk(pAbc) == NULL ) + { + fprintf( pAbc->Err, "There is no current network.\n" ); + return 1; + } + if ( !Abc_NtkHasMapping(Abc_FrameReadNtk(pAbc)) ) + { + fprintf( pAbc->Err, "The current network is not mapped.\n" ); + return 1; + } + if ( !Abc_SclCheckNtk(Abc_FrameReadNtk(pAbc), 0) ) + { + fprintf( pAbc->Err, "The current network is not in a topo order (run \"topo\").\n" ); + return 1; + } + if ( pAbc->pLibScl == NULL ) + { + fprintf( pAbc->Err, "There is no Liberty library available.\n" ); + return 1; + } + + Abc_SclPrintBuffers( (SC_Lib *)pAbc->pLibScl, pNtk, fVerbose ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: minsize [-vh]\n" ); + fprintf( pAbc->Err, "\t downsized all gates to their minimum size\n" ); + fprintf( pAbc->Err, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pAbc->Err, "\t-h : print the command usage\n"); + return 1; +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/map/scl/sclDnsize.c b/src/map/scl/sclDnsize.c new file mode 100644 index 00000000..590e1bc7 --- /dev/null +++ b/src/map/scl/sclDnsize.c @@ -0,0 +1,352 @@ +/**CFile**************************************************************** + + FileName [sclDnsize.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Standard-cell library representation.] + + Synopsis [Selective decrease of gate sizes.] + + Author [Alan Mishchenko, Niklas Een] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - August 24, 2012.] + + Revision [$Id: sclDnsize.c,v 1.0 2012/08/24 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "sclInt.h" +#include "sclMan.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Find the array of nodes to be updated.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_SclFindWindow( Abc_Obj_t * pPivot, Vec_Int_t ** pvNodes, Vec_Int_t ** pvEvals ) +{ + Abc_Ntk_t * p = Abc_ObjNtk(pPivot); + Abc_Obj_t * pObj, * pNext, * pNext2; + Vec_Int_t * vNodes = *pvNodes; + Vec_Int_t * vEvals = *pvEvals; + int i, k; + assert( Abc_ObjIsNode(pPivot) ); + // collect fanins, node, and fanouts + Vec_IntClear( vNodes ); + Abc_ObjForEachFanin( pPivot, pNext, i ) + if ( Abc_ObjIsNode(pNext) && Abc_ObjFaninNum(pNext) > 0 ) + Vec_IntPush( vNodes, Abc_ObjId(pNext) ); + Vec_IntPush( vNodes, Abc_ObjId(pPivot) ); + Abc_ObjForEachFanout( pPivot, pNext, i ) + if ( Abc_ObjIsNode(pNext) ) + { + Vec_IntPush( vNodes, Abc_ObjId(pNext) ); + Abc_ObjForEachFanout( pNext, pNext2, k ) + if ( Abc_ObjIsNode(pNext2) ) + Vec_IntPush( vNodes, Abc_ObjId(pNext2) ); + } + Vec_IntUniqify( vNodes ); + // label nodes + Abc_NtkForEachObjVec( vNodes, p, pObj, i ) + { + assert( pObj->fMarkB == 0 ); + pObj->fMarkB = 1; + } + // collect nodes visible from the critical paths + Vec_IntClear( vEvals ); + Abc_NtkForEachObjVec( vNodes, p, pObj, i ) + Abc_ObjForEachFanout( pObj, pNext, k ) + if ( !pNext->fMarkB ) + { + assert( pObj->fMarkB ); + Vec_IntPush( vEvals, Abc_ObjId(pObj) ); + break; + } + assert( Vec_IntSize(vEvals) > 0 ); + // label nodes + Abc_NtkForEachObjVec( vNodes, p, pObj, i ) + pObj->fMarkB = 0; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the node can be improved.] + + Description [Updated the node to have a new gate.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_SclCheckImprovement( SC_Man * p, Abc_Obj_t * pObj, Vec_Int_t * vNodes, Vec_Int_t * vEvals ) +{ + Abc_Obj_t * pTemp; + SC_Cell * pCellOld, * pCellNew; + float dGain, dGainBest; + int i, k, gateBest; + abctime clk; +clk = Abc_Clock(); +// printf( "%d -> %d\n", Vec_IntSize(vNodes), Vec_IntSize(vEvals) ); + // save old gate, timing, fanin load + pCellOld = Abc_SclObjCell( p, pObj ); + Abc_SclConeStore( p, vNodes ); + Abc_SclLoadStore( p, pObj ); + // try different gate sizes for this node + gateBest = -1; + dGainBest = -ABC_INFINITY; //0.0; + SC_RingForEachCell( pCellOld, pCellNew, i ) + { + if ( pCellNew->area >= pCellOld->area ) + continue; + // set new cell + Abc_SclObjSetCell( p, pObj, pCellNew ); + Abc_SclUpdateLoad( p, pObj, pCellOld, pCellNew ); + // recompute timing + Abc_SclTimeCone( p, vNodes ); + // set old cell + Abc_SclObjSetCell( p, pObj, pCellOld ); + Abc_SclLoadRestore( p, pObj ); + // evaluate gain + dGain = 0.0; + Abc_NtkForEachObjVec( vEvals, p->pNtk, pTemp, k ) + if ( Abc_SclObjLegal(p, pTemp, p->MaxDelay0) ) + dGain += Abc_SclObjGain( p, pTemp ); + else + break; + if ( k < Vec_IntSize(vEvals) ) + continue; + dGain /= Vec_IntSize(vEvals); + // save best gain + if ( dGainBest < dGain ) + { + dGainBest = dGain; + gateBest = pCellNew->Id; + } + } + // put back old cell and timing + Abc_SclObjSetCell( p, pObj, pCellOld ); + Abc_SclConeRestore( p, vNodes ); +p->timeSize += Abc_Clock() - clk; + if ( gateBest >= 0 ) + { + pCellNew = SC_LibCell( p->pLib, gateBest ); + Abc_SclObjSetCell( p, pObj, pCellNew ); + p->SumArea += pCellNew->area - pCellOld->area; +// printf( "%f %f -> %f\n", pCellNew->area - pCellOld->area, p->SumArea - (pCellNew->area - pCellOld->area), p->SumArea ); +// printf( "%6d %20s -> %20s %f -> %f\n", Abc_ObjId(pObj), pCellOld->pName, pCellNew->pName, pCellOld->area, pCellNew->area ); + // mark used nodes with the current trav ID + Abc_NtkForEachObjVec( vNodes, p->pNtk, pTemp, k ) + Abc_NodeSetTravIdCurrent( pTemp ); + // to need to update load and timing... + return 1; + } + return 0; +} + +/**Function************************************************************* + + Synopsis [Collect nodes by area.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkCollectNodesByArea( SC_Man * p, Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int i; + assert( Vec_QueSize(p->vNodeByGain) == 0 ); + Vec_QueClear( p->vNodeByGain ); + Abc_NtkForEachNode( pNtk, pObj, i ) + if ( Abc_ObjFaninNum(pObj) > 0 ) + { + Vec_FltWriteEntry( p->vNode2Gain, Abc_ObjId(pObj), Abc_SclObjCell(p, pObj)->area ); + Vec_QuePush( p->vNodeByGain, Abc_ObjId(pObj) ); + } +} +int Abc_SclCheckOverlap( Abc_Ntk_t * pNtk, Vec_Int_t * vNodes ) +{ + Abc_Obj_t * pObj; + int i; + Abc_NtkForEachObjVec( vNodes, pNtk, pObj, i ) + if ( Abc_NodeIsTravIdCurrent(pObj) ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Print cumulative statistics.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_SclDnsizePrint( SC_Man * p, int Iter, int nAttempts, int nOverlaps, int nChanges, int fVerbose ) +{ + if ( Iter == -1 ) + printf( "Total : " ); + else + printf( "%5d : ", Iter ); + printf( "Try =%6d ", nAttempts ); + printf( "Over =%6d ", nOverlaps ); + printf( "Fail =%6d ", nAttempts-nOverlaps-nChanges ); + printf( "Win =%6d ", nChanges ); + printf( "A: " ); + printf( "%.2f ", p->SumArea ); + printf( "(%+5.1f %%) ", 100.0 * (p->SumArea - p->SumArea0)/ p->SumArea0 ); + printf( "D: " ); + printf( "%.2f ps ", SC_LibTimePs(p->pLib, p->MaxDelay) ); + printf( "(%+5.1f %%) ", 100.0 * (p->MaxDelay - p->MaxDelay0)/ p->MaxDelay0 ); + printf( "%8.2f sec", 1.0*(Abc_Clock() - p->timeTotal)/(CLOCKS_PER_SEC) ); + printf( "%c", fVerbose ? '\n' : '\r' ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_SclDnsizePerform( SC_Lib * pLib, Abc_Ntk_t * pNtk, SC_DnSizePars * pPars ) +{ + SC_Man * p; + Abc_Obj_t * pObj; + Vec_Int_t * vNodes, * vEvals, * vTryLater; + abctime clk, nRuntimeLimit = pPars->TimeOut ? pPars->TimeOut * CLOCKS_PER_SEC + Abc_Clock() : 0; + int i, k; + + if ( pPars->fVerbose ) + { + printf( "Downsizing parameters: " ); + printf( "Delay =%8.2f ps. ", pPars->DUser ); + printf( "Iters =%5d. ", pPars->nIters ); + printf( "UseDept =%2d. ", pPars->fUseDept ); + printf( "Timeout =%4d sec", pPars->TimeOut ); + printf( "\n" ); + } + + // prepare the manager; collect init stats + p = Abc_SclManStart( pLib, pNtk, 1, pPars->fUseDept, SC_LibTimeFromPs(pLib, pPars->DUser) ); + p->timeTotal = Abc_Clock(); + assert( p->vGatesBest == NULL ); + p->vGatesBest = Vec_IntDup( p->vGates ); + + // perform upsizing + vNodes = Vec_IntAlloc( 1000 ); + vEvals = Vec_IntAlloc( 1000 ); + vTryLater = Vec_IntAlloc( 1000 ); + for ( i = 0; i < pPars->nIters; i++ ) + { + int nRounds = 0; + int nAttemptAll = 0, nOverlapAll = 0, nChangesAll = 0; + Abc_NtkCollectNodesByArea( p, pNtk ); + while ( Vec_QueSize(p->vNodeByGain) > 0 ) + { + int nAttempt = 0, nOverlap = 0, nChanges = 0; + Vec_IntClear( vTryLater ); + Abc_NtkIncrementTravId( pNtk ); + while ( Vec_QueSize(p->vNodeByGain) > 0 ) + { +clk = Abc_Clock(); + pObj = Abc_NtkObj( p->pNtk, Vec_QuePop(p->vNodeByGain) ); + Abc_SclFindWindow( pObj, &vNodes, &vEvals ); +p->timeCone += Abc_Clock() - clk; + if ( Abc_SclCheckOverlap( p->pNtk, vNodes ) ) + nOverlap++, Vec_IntPush( vTryLater, Abc_ObjId(pObj) ); + else + nChanges += Abc_SclCheckImprovement( p, pObj, vNodes, vEvals ); + nAttempt++; + } + Abc_NtkForEachObjVec( vTryLater, pNtk, pObj, k ) + Vec_QuePush( p->vNodeByGain, Abc_ObjId(pObj) ); +clk = Abc_Clock(); + Abc_SclTimeNtkRecompute( p, NULL, NULL, pPars->fUseDept, pPars->DUser ); +p->timeTime += Abc_Clock() - clk; + + p->MaxDelay = Abc_SclReadMaxDelay( p ); + if ( pPars->fUseDept && pPars->DUser > 0 && p->MaxDelay < pPars->DUser ) + p->MaxDelay = pPars->DUser; + Abc_SclDnsizePrint( p, nRounds++, nAttempt, nOverlap, nChanges, pPars->fVeryVerbose ); + nAttemptAll += nAttempt; + nOverlapAll += nOverlap; + nChangesAll += nChanges; + if ( nRuntimeLimit && Abc_Clock() > nRuntimeLimit ) + break; + } + // recompute + Abc_SclTimeNtkRecompute( p, &p->SumArea, &p->MaxDelay, pPars->fUseDept, pPars->DUser ); + if ( pPars->fVerbose ) + Abc_SclDnsizePrint( p, -1, nAttemptAll, nOverlapAll, nChangesAll, 1 ); + else + printf( " \r" ); + if ( nRuntimeLimit && Abc_Clock() > nRuntimeLimit ) + break; + if ( nAttemptAll == 0 ) + break; + } + Vec_IntFree( vNodes ); + Vec_IntFree( vEvals ); + Vec_IntFree( vTryLater ); + + // report runtime + p->timeTotal = Abc_Clock() - p->timeTotal; + if ( pPars->fVerbose ) + { + p->timeOther = p->timeTotal - p->timeCone - p->timeSize - p->timeTime; + ABC_PRTP( "Runtime: Critical path", p->timeCone, p->timeTotal ); + ABC_PRTP( "Runtime: Sizing eval ", p->timeSize, p->timeTotal ); + ABC_PRTP( "Runtime: Timing update", p->timeTime, p->timeTotal ); + ABC_PRTP( "Runtime: Other ", p->timeOther, p->timeTotal ); + ABC_PRTP( "Runtime: TOTAL ", p->timeTotal, p->timeTotal ); + } +// if ( pPars->fDumpStats ) +// Abc_SclDumpStats( p, "stats2.txt", p->timeTotal ); + if ( nRuntimeLimit && Abc_Clock() > nRuntimeLimit ) + printf( "Gate sizing timed out at %d seconds.\n", pPars->TimeOut ); + + // save the result and quit + Abc_SclManSetGates( pLib, pNtk, p->vGates ); // updates gate pointers + Abc_SclManFree( p ); +// Abc_NtkCleanMarkAB( pNtk ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/map/scl/sclInt.h b/src/map/scl/sclInt.h index 9818c8c8..ca93a631 100644 --- a/src/map/scl/sclInt.h +++ b/src/map/scl/sclInt.h @@ -89,6 +89,19 @@ struct SC_UpSizePars_ int fVeryVerbose; }; +typedef struct SC_DnSizePars_ SC_DnSizePars; +struct SC_DnSizePars_ +{ + float DUser; + int nIters; + int nIterNoChange; + int TimeOut; + int fUseDept; + int fDumpStats; + int fVerbose; + int fVeryVerbose; +}; + //////////////////////////////////////////////////////////////////////// /// STRUCTURE DEFINITIONS /// //////////////////////////////////////////////////////////////////////// @@ -209,12 +222,13 @@ struct SC_Lib_ /// 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 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_LibTimePs( SC_Lib * p, double time ) { return time * pow(10.0, 12 - p->unit_time); } +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_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 ) @@ -441,6 +455,8 @@ static inline void Abc_SclLibFree( SC_Lib * 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_DnSizePars * pPars ); /*=== sclFile.c ===============================================================*/ extern SC_Lib * Abc_SclRead( char * pFileName ); extern void Abc_SclWrite( char * pFileName, SC_Lib * p ); @@ -451,6 +467,7 @@ extern void Abc_SclSave( char * pFileName, SC_Lib * pScl ); 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 ); /*=== sclSize.c ===============================================================*/ extern void Abc_SclSizingPerform( SC_Lib * pLib, Abc_Ntk_t * pNtk, SC_SizePars * p ); /*=== sclUpsize.c ===============================================================*/ diff --git a/src/map/scl/sclMan.h b/src/map/scl/sclMan.h index a5657dc4..495c2b34 100644 --- a/src/map/scl/sclMan.h +++ b/src/map/scl/sclMan.h @@ -109,10 +109,13 @@ static inline SC_Pair * Abc_SclObjSlew2( SC_Man * p, Abc_Obj_t * 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 (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); } @@ -360,9 +363,9 @@ static inline void Abc_SclDumpStats( SC_Man * p, char * pFileName, abctime Time 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 ); +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 ); +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 ); diff --git a/src/map/scl/sclTime.c b/src/map/scl/sclTime.c index b153db89..dfb2032b 100644 --- a/src/map/scl/sclTime.c +++ b/src/map/scl/sclTime.c @@ -20,6 +20,7 @@ #include "sclInt.h" #include "sclMan.h" +#include "map/mio/mio.h" ABC_NAMESPACE_IMPL_START @@ -300,7 +301,7 @@ void Abc_SclTimeCone( SC_Man * p, Vec_Int_t * vCone ) 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 ) +void Abc_SclTimeNtkRecompute( SC_Man * p, float * pArea, float * pDelay, int fReverse, float DUser ) { Abc_Obj_t * pObj; float D; @@ -316,6 +317,8 @@ void Abc_SclTimeNtkRecompute( SC_Man * p, float * pArea, float * pDelay, int fRe 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 ) @@ -340,14 +343,14 @@ void Abc_SclTimeNtkRecompute( SC_Man * p, float * pArea, float * pDelay, int fRe SeeAlso [] ***********************************************************************/ -SC_Man * Abc_SclManStart( SC_Lib * pLib, Abc_Ntk_t * pNtk, int fUseWireLoads, int fDept ) +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 ); if ( fUseWireLoads ) p->pWLoadUsed = Abc_SclFindWireLoadModel( pLib, Abc_SclGetTotalArea(p) ); - Abc_SclTimeNtkRecompute( p, &p->SumArea0, &p->MaxDelay0, fDept ); + Abc_SclTimeNtkRecompute( p, &p->SumArea0, &p->MaxDelay0, fDept, DUser ); p->SumArea = p->SumArea0; return p; } @@ -366,7 +369,7 @@ SC_Man * Abc_SclManStart( SC_Lib * pLib, Abc_Ntk_t * pNtk, int fUseWireLoads, in 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 ); + p = Abc_SclManStart( pLib, pNtk, fUseWireLoads, 1, 0 ); Abc_SclTimeNtkPrint( p, fShowAll, fShort ); if ( fDumpStats ) Abc_SclDumpStats( p, "stats.txt", 0 ); @@ -374,6 +377,125 @@ void Abc_SclTimePerform( SC_Lib * pLib, Abc_Ntk_t * pNtk, int fUseWireLoads, int } + +/**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_Scl_PrintBuffers( 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_Scl_PrintBuffers( 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_Scl_PrintBuffers( 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 /// //////////////////////////////////////////////////////////////////////// diff --git a/src/map/scl/sclUpsize.c b/src/map/scl/sclUpsize.c index 17ae658d..5f59e79e 100644 --- a/src/map/scl/sclUpsize.c +++ b/src/map/scl/sclUpsize.c @@ -384,7 +384,7 @@ void Abc_SclUpsizePrintDiffs( SC_Man * p, SC_Lib * pLib, Abc_Ntk_t * pNtk ) memcpy( pSlews, p->pSlews, sizeof(SC_Pair) * p->nObjs ); memcpy( pLoads, p->pLoads, sizeof(SC_Pair) * p->nObjs ); - Abc_SclTimeNtkRecompute( p, NULL, NULL, 0 ); + Abc_SclTimeNtkRecompute( p, NULL, NULL, 0, 0 ); Abc_NtkForEachNode( pNtk, pObj, k ) { @@ -437,17 +437,16 @@ void Abc_SclUpsizePrint( SC_Man * p, int Iter, int win, int nPathPos, int nPathN printf( "Path:%6d. ", nPathNodes ); printf( "Gate:%5d. ", nUpsizes ); printf( "TFO:%6d. ", nTFOs ); - printf( "B: " ); - printf( "%.2f ps ", SC_LibTimePs(p->pLib, p->BestDelay) ); - printf( "(%+5.1f %%) ", 100.0 * (p->BestDelay - p->MaxDelay0)/ p->MaxDelay0 ); + printf( "A: " ); + printf( "%.2f ", p->SumArea ); + printf( "(%+5.1f %%) ", 100.0 * (p->SumArea - p->SumArea0)/ p->SumArea0 ); printf( "D: " ); printf( "%.2f ps ", SC_LibTimePs(p->pLib, p->MaxDelay) ); printf( "(%+5.1f %%) ", 100.0 * (p->MaxDelay - p->MaxDelay0)/ p->MaxDelay0 ); - printf( "A: " ); - printf( "%.2f ", p->SumArea ); - printf( "(%+5.1f %%)", 100.0 * (p->SumArea - p->SumArea0)/ p->SumArea0 ); - printf( "%8.2f", 1.0*(Abc_Clock() - p->timeTotal)/(CLOCKS_PER_SEC) ); - printf( " " ); + printf( "B: " ); + printf( "%.2f ps ", SC_LibTimePs(p->pLib, p->BestDelay) ); + printf( "(%+5.1f %%)", 100.0 * (p->BestDelay - p->MaxDelay0)/ p->MaxDelay0 ); + printf( "%8.2f sec", 1.0*(Abc_Clock() - p->timeTotal)/(CLOCKS_PER_SEC) ); printf( "%c", fVerbose ? '\n' : '\r' ); } @@ -474,7 +473,7 @@ void Abc_SclUpsizePerform( SC_Lib * pLib, Abc_Ntk_t * pNtk, SC_UpSizePars * pPar if ( pPars->fVerbose ) { - printf( "Sizing parameters: " ); + printf( "Upsizing parameters: " ); printf( "Iters =%5d. ", pPars->nIters ); printf( "Time window =%3d %%. ", pPars->Window ); printf( "Update ratio =%3d %%. ", pPars->Ratio ); @@ -485,7 +484,7 @@ void Abc_SclUpsizePerform( SC_Lib * pLib, Abc_Ntk_t * pNtk, SC_UpSizePars * pPar } // prepare the manager; collect init stats - p = Abc_SclManStart( pLib, pNtk, 1, pPars->fUseDept ); + p = Abc_SclManStart( pLib, pNtk, 1, pPars->fUseDept, 0 ); p->timeTotal = Abc_Clock(); assert( p->vGatesBest == NULL ); p->vGatesBest = Vec_IntDup( p->vGates ); @@ -526,7 +525,7 @@ void Abc_SclUpsizePerform( SC_Lib * pLib, Abc_Ntk_t * pNtk, SC_UpSizePars * pPar if ( pPars->fUseDept ) { vTFO = Vec_IntAlloc( 0 ); - Abc_SclTimeNtkRecompute( p, NULL, NULL, pPars->fUseDept ); + Abc_SclTimeNtkRecompute( p, NULL, NULL, pPars->fUseDept, 0 ); } else { @@ -555,7 +554,7 @@ void Abc_SclUpsizePerform( SC_Lib * pLib, Abc_Ntk_t * pNtk, SC_UpSizePars * pPar } // report and cleanup - Abc_SclUpsizePrint( p, i, win, Vec_IntSize(vPathPos), Vec_IntSize(vPathNodes), nUpsizes, Vec_IntSize(vTFO), pPars->fVeryVerbose ); //|| (i == nIters-1) ); + Abc_SclUpsizePrint( p, i, win, Vec_IntSize(vPathPos), Vec_IntSize(vPathNodes), nUpsizes, Vec_IntSize(vTFO), pPars->fVeryVerbose || (pPars->fVerbose && nFramesNoChange == 0) ); //|| (i == nIters-1) ); nAllPos += Vec_IntSize(vPathPos); nAllNodes += Vec_IntSize(vPathNodes); nAllTfos += Vec_IntSize(vTFO); @@ -569,7 +568,7 @@ void Abc_SclUpsizePerform( SC_Lib * pLib, Abc_Ntk_t * pNtk, SC_UpSizePars * pPar } // update for best gates and recompute timing ABC_SWAP( Vec_Int_t *, p->vGatesBest, p->vGates ); - Abc_SclTimeNtkRecompute( p, &p->SumArea, &p->MaxDelay, 0 ); + Abc_SclTimeNtkRecompute( p, &p->SumArea, &p->MaxDelay, 0, 0 ); if ( pPars->fVerbose ) Abc_SclUpsizePrint( p, i, pPars->Window, nAllPos/(i?i:1), nAllNodes/(i?i:1), nAllUpsizes/(i?i:1), nAllTfos/(i?i:1), 1 ); else diff --git a/src/map/scl/sclUtil.c b/src/map/scl/sclUtil.c index 37efbd44..4d392844 100644 --- a/src/map/scl/sclUtil.c +++ b/src/map/scl/sclUtil.c @@ -180,7 +180,7 @@ void Abc_SclPrintCells( SC_Lib * p ) printf( " %3d : ", i+1 ); printf( "%-*s ", nLength, pCell->pName ); printf( "%2d ", pCell->drive_strength ); - printf( "A =%8.3f D =", pCell->area ); + printf( "A =%8.2f D =", pCell->area ); // print linear approximation for ( j = 0; j < 3; j++ ) { @@ -189,9 +189,16 @@ void Abc_SclPrintCells( SC_Lib * p ) { SC_Timings * pRTime = (SC_Timings *)Vec_PtrEntry( pPin->vRTimings, 0 ); SC_Timing * pTime = (SC_Timing *)Vec_PtrEntry( pRTime->vTimings, 0 ); - printf( "%7.3f ", pTime->pCellRise->approx[0][j] ); + 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" ); } } -- cgit v1.2.3