summaryrefslogtreecommitdiffstats
path: root/src/map/scl/sclDnsize.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/map/scl/sclDnsize.c')
-rw-r--r--src/map/scl/sclDnsize.c352
1 files changed, 352 insertions, 0 deletions
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
+