diff options
Diffstat (limited to 'src/map/scl/sclBufSize.c')
-rw-r--r-- | src/map/scl/sclBufSize.c | 376 |
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 + |