summaryrefslogtreecommitdiffstats
path: root/src/map/scl/sclBufSize.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/map/scl/sclBufSize.c')
-rw-r--r--src/map/scl/sclBufSize.c376
1 files changed, 376 insertions, 0 deletions
diff --git a/src/map/scl/sclBufSize.c b/src/map/scl/sclBufSize.c
new file mode 100644
index 00000000..229b387a
--- /dev/null
+++ b/src/map/scl/sclBufSize.c
@@ -0,0 +1,376 @@
+/**CFile****************************************************************
+
+ FileName [sclBufSize.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Standard-cell library representation.]
+
+ Synopsis [Buffering and sizing combined.]
+
+ Author [Alan Mishchenko, Niklas Een]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - August 24, 2012.]
+
+ Revision [$Id: sclBufSize.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 ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Bus_Man_t_ Bus_Man_t;
+struct Bus_Man_t_
+{
+ // parameters
+ float Gain; // target gain
+ int nDegree; // max branching factor
+ int fBufPis; // use CI buffering
+ int fVerbose; // verbose
+ // user data
+ Abc_Ntk_t * pNtk; // user's network
+ // library
+ SC_Lib * pLib; // cell library
+ SC_Cell * pInv; // base interter (largest/average/???)
+ // internal
+ Vec_Flt_t * vCins; // input cap for fanouts
+ Vec_Flt_t * vLoads; // loads for all nodes
+ Vec_Flt_t * vDepts; // departure times
+};
+
+
+static inline Bus_Man_t * Bus_SclObjMan( Abc_Obj_t * p ) { return (Bus_Man_t *)p->pNtk->pBSMan; }
+static inline float Bus_SclObjCin( Abc_Obj_t * p ) { return Vec_FltEntry( Bus_SclObjMan(p)->vCins, Abc_ObjId(p) ); }
+static inline void Bus_SclObjSetCin( Abc_Obj_t * p, float load ) { Vec_FltWriteEntry( Bus_SclObjMan(p)->vCins, Abc_ObjId(p), load ); }
+static inline float Bus_SclObjLoad( Abc_Obj_t * p ) { return Vec_FltEntry( Bus_SclObjMan(p)->vLoads, Abc_ObjId(p) ); }
+static inline void Bus_SclObjSetLoad( Abc_Obj_t * p, float load ) { Vec_FltWriteEntry( Bus_SclObjMan(p)->vLoads, Abc_ObjId(p), load ); }
+static inline float Bus_SclObjDept( Abc_Obj_t * p ) { return Vec_FltEntry( Bus_SclObjMan(p)->vDepts, Abc_ObjId(p) ); }
+static inline void Bus_SclObjUpdateDept( Abc_Obj_t * p, float dept ) { float *q = Vec_FltEntryP( Bus_SclObjMan(p)->vDepts, Abc_ObjId(p) ); if (*q < dept) *q = dept; }
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Bus_Man_t * Bus_ManStart( Abc_Ntk_t * pNtk, SC_Lib * pLib, int GainRatio, int nDegree, int fBufPis, int fVerbose )
+{
+ Bus_Man_t * p;
+ p = ABC_CALLOC( Bus_Man_t, 1 );
+ p->Gain = 0.01 * GainRatio;
+ p->nDegree = nDegree;
+ p->fBufPis = fBufPis;
+ p->fVerbose = fVerbose;
+ p->pNtk = pNtk;
+ p->pLib = pLib;
+ p->pInv = Abc_SclFindInvertor(pLib)->pAve;
+ p->vCins = Vec_FltStart( 2*Abc_NtkObjNumMax(pNtk) );
+ p->vLoads = Vec_FltStart( 2*Abc_NtkObjNumMax(pNtk) );
+ p->vDepts = Vec_FltStart( 2*Abc_NtkObjNumMax(pNtk) );
+ pNtk->pBSMan = p;
+ return p;
+}
+void Bus_ManStop( Bus_Man_t * p )
+{
+ Vec_FltFree( p->vCins );
+ Vec_FltFree( p->vLoads );
+ Vec_FltFree( p->vDepts );
+ ABC_FREE( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Bus_ManReadInOutLoads( Bus_Man_t * p )
+{
+ Abc_Time_t * pTime;
+ Abc_Obj_t * pObj;
+ int i;
+ // read input load
+ pTime = Abc_NtkReadDefaultInputDrive( p->pNtk );
+ if ( Abc_MaxFloat(pTime->Rise, pTime->Fall) != 0 )
+ {
+ printf( "Default input drive strength is specified (%.2f ff; %.2f ff).\n", pTime->Rise, pTime->Fall );
+ Abc_NtkForEachPi( p->pNtk, pObj, i )
+ Vec_FltWriteEntry( p->vLoads, Abc_ObjId(pObj), 0.5 * SC_LibCapFromFf(p->pLib, pTime->Rise) + 0.5 * SC_LibCapFromFf(p->pLib, pTime->Fall) );
+ }
+ if ( Abc_NodeReadInputDrive(p->pNtk, 0) != NULL )
+ {
+ printf( "Input drive strengths for some primary inputs are specified.\n" );
+ Abc_NtkForEachPi( p->pNtk, pObj, i )
+ {
+ pTime = Abc_NodeReadInputDrive(p->pNtk, i);
+ Vec_FltWriteEntry( p->vLoads, Abc_ObjId(pObj), 0.5 * SC_LibCapFromFf(p->pLib, pTime->Rise) + 0.5 * SC_LibCapFromFf(p->pLib, pTime->Fall) );
+ }
+ }
+ // read output load
+ pTime = Abc_NtkReadDefaultOutputLoad( p->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( p->pNtk, pObj, i )
+ Vec_FltWriteEntry( p->vLoads, Abc_ObjId(pObj), 0.5 * SC_LibCapFromFf(p->pLib, pTime->Rise) + 0.5 * SC_LibCapFromFf(p->pLib, pTime->Fall) );
+ }
+ if ( Abc_NodeReadOutputLoad(p->pNtk, 0) != NULL )
+ {
+ printf( "Output loads for some primary outputs are specified.\n" );
+ Abc_NtkForEachPo( p->pNtk, pObj, i )
+ {
+ pTime = Abc_NodeReadOutputLoad(p->pNtk, i);
+ Vec_FltWriteEntry( p->vLoads, Abc_ObjId(pObj), 0.5 * SC_LibCapFromFf(p->pLib, pTime->Rise) + 0.5 * SC_LibCapFromFf(p->pLib, pTime->Fall) );
+ }
+ }
+ // read arrival/required times
+}
+
+/**Function*************************************************************
+
+ Synopsis [Compute load and departure times of the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Abc_NtkComputeFanoutCins( Abc_Obj_t * pObj )
+{
+ Abc_Obj_t * pFanout;
+ int i;
+ Abc_ObjForEachFanout( pObj, pFanout, i )
+ if ( Abc_ObjIsNode(pFanout) )
+ Bus_SclObjSetCin( pFanout, SC_CellPinCap( Abc_SclObjCell(pFanout), Abc_NodeFindFanin(pFanout, pObj) ) );
+}
+float Abc_NtkComputeNodeLoad( Abc_Obj_t * pObj )
+{
+ Abc_Obj_t * pFanout;
+ float Load = 0;
+ int i;
+ assert( Bus_SclObjLoad(pObj) == 0 );
+ Abc_ObjForEachFanout( pObj, pFanout, i )
+ Load += Bus_SclObjCin( pFanout );
+ Bus_SclObjSetLoad( pObj, Load );
+ return Load;
+}
+float Abc_NtkComputeNodeDept( Abc_Obj_t * pObj )
+{
+ Abc_Obj_t * pFanout;
+ float Load, Dept, Edge;
+ int i;
+ assert( Bus_SclObjDept(pObj) == 0 );
+ Abc_ObjForEachFanout( pObj, pFanout, i )
+ {
+ if ( Abc_ObjIsCo(pFanout) ) // add required times here
+ continue;
+ Load = Bus_SclObjLoad( pFanout );
+ Dept = Bus_SclObjDept( pFanout );
+ Edge = Scl_LibPinTime( Abc_SclObjCell(pFanout), Abc_NodeFindFanin(pFanout, pObj), Load );
+ Bus_SclObjUpdateDept( pObj, Dept + Edge );
+ assert( Edge > 0 );
+ assert( Load > 0 );
+ }
+ return Bus_SclObjDept( pObj );
+}
+/*
+void Abc_NtkUpdateFaninDeparture( Bus_Man_t * p, Abc_Obj_t * pObj, float Load )
+{
+ SC_Cell * pCell = Abc_SclObjCell( pObj );
+ Abc_Obj_t * pFanin;
+ float Dept, Edge;
+ int i;
+ Dept = Bus_SclObjDept( pObj );
+ Abc_ObjForEachFanin( pObj, pFanin, i )
+ {
+ Edge = Scl_LibPinTime( pCell, i, Load );
+ Bus_SclObjUpdateDept( pFanin, Dept + Edge );
+ }
+}
+*/
+
+/**Function*************************************************************
+
+ Synopsis [Compare two fanouts by their departure times.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Bus_SclCompareFanouts( Abc_Obj_t ** pp1, Abc_Obj_t ** pp2 )
+{
+ float Espilon = 10; // 10 ps
+ if ( Bus_SclObjDept(*pp1) < Bus_SclObjDept(*pp2) - Espilon )
+ return -1;
+ if ( Bus_SclObjDept(*pp1) > Bus_SclObjDept(*pp2) + Espilon )
+ return 1;
+ if ( Bus_SclObjCin(*pp1) > Bus_SclObjCin(*pp2) - Espilon )
+ return -1;
+ if ( Bus_SclObjCin(*pp1) < Bus_SclObjCin(*pp2) + Espilon )
+ return 1;
+ return -1;
+}
+void Bus_SclInsertFanout( Vec_Ptr_t * vFanouts, Abc_Obj_t * pObj )
+{
+ Abc_Obj_t * pCur;
+ int i, k;
+ assert( Bus_SclObjDept(pObj) > 0 );
+ assert( Bus_SclObjLoad(pObj) > 0 );
+ // compact array
+ for ( i = k = 0; i < Vec_PtrSize(vFanouts); i++ )
+ if ( Vec_PtrEntry(vFanouts, i) != NULL )
+ Vec_PtrWriteEntry( vFanouts, k++, Vec_PtrEntry(vFanouts, i) );
+ Vec_PtrShrink( vFanouts, k );
+ // insert new entry
+ Vec_PtrPush( vFanouts, pObj );
+ for ( i = Vec_PtrSize(vFanouts) - 1; i > 0; i-- )
+ {
+ pCur = (Abc_Obj_t *)Vec_PtrEntry(vFanouts, i-1);
+ pObj = (Abc_Obj_t *)Vec_PtrEntry(vFanouts, i);
+ if ( Bus_SclCompareFanouts( &pCur, &pObj ) == -1 )
+ break;
+ ABC_SWAP( void *, Vec_PtrArray(vFanouts)[i-1], Vec_PtrArray(vFanouts)[i] );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Abc_Obj_t * Abc_SclAddOneInv( Bus_Man_t * p, Abc_Obj_t * pObj, Vec_Ptr_t * vFanouts, float Gain, int Degree )
+{
+ SC_Cell * pCellNew;
+ Abc_Obj_t * pFanout, * pInv;
+ float Target = SC_CellPinCap( p->pInv, 0 ) * Gain;
+ float Load = 0;
+ int i, iStop;
+ Vec_PtrForEachEntryStop( Abc_Obj_t *, vFanouts, pFanout, iStop, Degree )
+ {
+ Load += Bus_SclObjCin( pFanout );
+ if ( Load > Target )
+ break;
+ }
+ // create inverter
+ pInv = Abc_NtkCreateNodeInv( p->pNtk, NULL );
+ assert( (int)Abc_ObjId(pInv) < Vec_FltSize(p->vDepts) );
+ Vec_PtrForEachEntryStop( Abc_Obj_t *, vFanouts, pFanout, i, iStop )
+ {
+ Vec_PtrWriteEntry( vFanouts, i, NULL );
+ if ( Abc_ObjFanin0(pFanout) == NULL )
+ Abc_ObjAddFanin( pFanout, pInv );
+ else
+ Abc_ObjPatchFanin( pFanout, pObj, pInv );
+ }
+ // set the gate
+ pCellNew = Abc_SclFindSmallestGate( p->pInv, Load / Gain );
+ Vec_IntSetEntry( p->pNtk->vGates, Abc_ObjId(pInv), pCellNew->Id );
+ Bus_SclObjSetCin( pInv, SC_CellPinCap(pCellNew, 0) );
+ // update timing
+ Abc_NtkComputeNodeLoad( pInv );
+ Abc_NtkComputeNodeDept( pInv );
+ // update phases
+ if ( p->pNtk->vPhases && Abc_SclIsInv(pInv) )
+ Abc_NodeInvUpdateFanPolarity( pInv );
+ return pInv;
+}
+void Abc_SclBufSize( Bus_Man_t * p )
+{
+ SC_Cell * pCell, * pCellNew;
+ Vec_Ptr_t * vFanouts;
+ Abc_Obj_t * pObj, * pInv;
+ float Load, Cin;
+ int i;
+ vFanouts = Vec_PtrAlloc( 100 );
+ Abc_SclMioGates2SclGates( p->pLib, p->pNtk );
+ Abc_NtkForEachNodeReverse( p->pNtk, pObj, i )
+ {
+ // compute load
+ Abc_NtkComputeFanoutCins( pObj );
+ Load = Abc_NtkComputeNodeLoad( pObj );
+ // consider the gate
+ pCell = Abc_SclObjCell( pObj );
+ Cin = SC_CellPinCapAve( pCell->pAve );
+ // consider upsizing the gate
+ if ( Load > p->Gain * Cin )
+ {
+ // add one or more inverters
+ Abc_NodeCollectFanouts( pObj, vFanouts );
+ Vec_PtrSort( vFanouts, (int(*)(const void *,const void *))Bus_SclCompareFanouts );
+ do
+ {
+ pInv = Abc_SclAddOneInv( p, pObj, vFanouts, p->Gain, p->nDegree );
+ Bus_SclInsertFanout( vFanouts, pInv );
+ Load = Bus_SclObjCin( pInv );
+ }
+ while ( Vec_PtrSize(vFanouts) > 1 || Load > p->Gain * Cin );
+ // connect last inverter
+ assert( Abc_ObjFanin0(pInv) == NULL );
+ Abc_ObjAddFanin( pInv, pObj );
+ Bus_SclObjSetLoad( pObj, Load );
+ }
+ // create cell
+ pCellNew = Abc_SclFindSmallestGate( pCell, Load / p->Gain );
+ Abc_SclObjSetCell( pObj, pCellNew );
+ Abc_NtkComputeNodeDept( pObj );
+ }
+ Abc_SclSclGates2MioGates( p->pLib, p->pNtk );
+ Vec_PtrFree( vFanouts );
+}
+Abc_Ntk_t * Abc_SclBufSizePerform( Abc_Ntk_t * pNtk, SC_Lib * pLib, int GainRatio, int nDegree, int fAddBufs, int fBufPis, int fVerbose )
+{
+ Abc_Ntk_t * pNtkNew;
+ Bus_Man_t * p;
+ if ( !Abc_SclCheckNtk( pNtk, 0 ) )
+ return NULL;
+ Abc_SclReportDupFanins( pNtk );
+ p = Bus_ManStart( pNtk, pLib, GainRatio, nDegree, fBufPis, fVerbose );
+ Bus_ManReadInOutLoads( p );
+ Abc_SclBufSize( p );
+ Bus_ManStop( p );
+ Vec_IntFillExtra( pNtk->vPhases, Abc_NtkObjNumMax(pNtk), 0 );
+ pNtkNew = Abc_NtkDupDfs( pNtk );
+ return pNtkNew;
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+