/**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" #include "misc/vec/vecWec.h" #include "base/main/main.h" #ifdef WIN32 #include #endif 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; assert( Abc_NtkPoNum(p->pNtk) > 0 ); 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; } if ( fMaxArr == 0 ) pPivot = Abc_NtkPo(p->pNtk, 0); 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_SclObjGetSlack( p, pFanin, p->MaxDelay0 ) ) { fMinSlack = Abc_SclObjGetSlack( p, pFanin, p->MaxDelay0 ); 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 ) { SC_Cell * pCell = Abc_ObjIsNode(pObj) ? Abc_SclObjCell(pObj) : NULL; printf( "%8d : ", Abc_ObjId(pObj) ); printf( "%d ", Abc_ObjFaninNum(pObj) ); printf( "%4d ", Abc_ObjFanoutNum(pObj) ); printf( "%-*s ", Length, pCell ? pCell->pName : "pi" ); printf( "A =%7.2f ", pCell ? pCell->area : 0.0 ); printf( "D%s =", fRise ? "r" : "f" ); printf( "%6.1f", Abc_SclObjTimeMax(p, pObj) ); printf( "%7.1f ps ", -Abc_AbsFloat(Abc_SclObjTimeOne(p, pObj, 0) - Abc_SclObjTimeOne(p, pObj, 1)) ); printf( "S =%6.1f ps ", Abc_SclObjSlewMax(p, pObj) ); printf( "Cin =%5.1f ff ", pCell ? SC_CellPinCapAve(pCell) : 0.0 ); printf( "Cout =%6.1f ff ", Abc_SclObjLoadMax(p, pObj) ); printf( "Cmax =%6.1f ff ", pCell ? SC_CellPin(pCell, pCell->n_inputs)->max_out_cap : 0.0 ); printf( "G =%5d ", pCell ? (int)(100.0 * Abc_SclObjLoadAve(p, pObj) / SC_CellPinCapAve(pCell)) : 0 ); // printf( "SL =%6.1f ps", Abc_SclObjSlackMax(p, pObj, p->MaxDelay0) ); printf( "\n" ); } void Abc_SclTimeNtkPrint( SC_Man * p, int fShowAll, int fPrintPath ) { int fReversePath = 1; int i, nLength = 0, fRise = 0; Abc_Obj_t * pObj, * pPivot = Abc_SclFindCriticalCo( p, &fRise ); float maxDelay = Abc_SclObjTimeOne( p, pPivot, fRise ); p->ReportDelay = maxDelay; #ifdef WIN32 printf( "WireLoad = \"%s\" ", p->pWLoadUsed ? p->pWLoadUsed->pName : "none" ); SetConsoleTextAttribute( GetStdHandle(STD_OUTPUT_HANDLE), 14 ); // yellow printf( "Gates =%7d ", Abc_NtkNodeNum(p->pNtk) ); SetConsoleTextAttribute( GetStdHandle(STD_OUTPUT_HANDLE), 7 ); // normal printf( "(%5.1f %%) ", 100.0 * Abc_SclGetBufInvCount(p->pNtk) / Abc_NtkNodeNum(p->pNtk) ); SetConsoleTextAttribute( GetStdHandle(STD_OUTPUT_HANDLE), 10 ); // green printf( "Cap =%5.1f ff ", p->EstLoadAve ); SetConsoleTextAttribute( GetStdHandle(STD_OUTPUT_HANDLE), 7 ); // normal printf( "(%5.1f %%) ", Abc_SclGetAverageSize(p->pNtk) ); SetConsoleTextAttribute( GetStdHandle(STD_OUTPUT_HANDLE), 11 ); // blue printf( "Area =%12.2f ", Abc_SclGetTotalArea(p->pNtk) ); SetConsoleTextAttribute( GetStdHandle(STD_OUTPUT_HANDLE), 7 ); // normal printf( "(%5.1f %%) ", 100.0 * Abc_SclCountMinSize(p->pLib, p->pNtk, 0) / Abc_NtkNodeNum(p->pNtk) ); SetConsoleTextAttribute( GetStdHandle(STD_OUTPUT_HANDLE), 13 ); // magenta printf( "Delay =%9.2f ps ", maxDelay ); SetConsoleTextAttribute( GetStdHandle(STD_OUTPUT_HANDLE), 7 ); // normal printf( "(%5.1f %%) ", 100.0 * Abc_SclCountNearCriticalNodes(p) / Abc_NtkNodeNum(p->pNtk) ); printf( " \n" ); #else Abc_Print( 1, "WireLoad = \"%s\" ", p->pWLoadUsed ? p->pWLoadUsed->pName : "none" ); Abc_Print( 1, "%sGates =%7d%s ", "\033[1;33m", Abc_NtkNodeNum(p->pNtk), "\033[0m" ); // yellow Abc_Print( 1, "(%5.1f %%) ", 100.0 * Abc_SclGetBufInvCount(p->pNtk) / Abc_NtkNodeNum(p->pNtk) ); Abc_Print( 1, "%sCap =%5.1f ff%s ", "\033[1;32m", p->EstLoadAve, "\033[0m" ); // green Abc_Print( 1, "(%5.1f %%) ", Abc_SclGetAverageSize(p->pNtk) ); Abc_Print( 1, "%sArea =%12.2f%s ", "\033[1;36m", Abc_SclGetTotalArea(p->pNtk), "\033[0m" ); // blue Abc_Print( 1, "(%5.1f %%) ", 100.0 * Abc_SclCountMinSize(p->pLib, p->pNtk, 0) / Abc_NtkNodeNum(p->pNtk) ); Abc_Print( 1, "%sDelay =%9.2f ps%s ", "\033[1;35m", maxDelay, "\033[0m" ); // magenta Abc_Print( 1, "(%5.1f %%) ", 100.0 * Abc_SclCountNearCriticalNodes(p) / Abc_NtkNodeNum(p->pNtk) ); Abc_Print( 1, " \n" ); #endif 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(pObj)->pName) ); // print timing Abc_NtkForEachNodeReverse( p->pNtk, pObj, i ) if ( Abc_ObjFaninNum(pObj) > 0 ) Abc_SclTimeNodePrint( p, pObj, -1, nLength, maxDelay ); } if ( fPrintPath ) { Abc_Obj_t * pTemp, * pPrev = NULL; int iStart = -1, iEnd = -1; Vec_Ptr_t * vPath; // 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(pObj)->pName) ); pObj = Abc_SclFindMostCriticalFanin( p, &fRise, pObj ); } // print timing if ( !fReversePath ) { // print timing pObj = Abc_ObjFanin0(pPivot); while ( pObj )//&& Abc_ObjIsNode(pObj) ) { printf( "Path%3d --", i-- ); Abc_SclTimeNodePrint( p, pObj, fRise, nLength, maxDelay ); pPrev = pObj; pObj = Abc_SclFindMostCriticalFanin( p, &fRise, pObj ); } } else { // collect path nodes vPath = Vec_PtrAlloc( 100 ); Vec_PtrPush( vPath, pPivot ); pObj = Abc_ObjFanin0(pPivot); while ( pObj )//&& Abc_ObjIsNode(pObj) ) { Vec_PtrPush( vPath, pObj ); pPrev = pObj; pObj = Abc_SclFindMostCriticalFanin( p, &fRise, pObj ); } Vec_PtrForEachEntryReverse( Abc_Obj_t *, vPath, pObj, i ) { printf( "Path%3d --", Vec_PtrSize(vPath)-1-i ); Abc_SclTimeNodePrint( p, pObj, fRise, nLength, maxDelay ); if ( i == 1 ) break; } Vec_PtrFree( vPath ); } // print start-point and end-point Abc_NtkForEachPi( p->pNtk, pTemp, iStart ) if ( pTemp == pPrev ) break; Abc_NtkForEachPo( p->pNtk, pTemp, iEnd ) if ( pTemp == pPivot ) break; printf( "Start-point = pi%0*d. End-point = po%0*d.\n", Abc_Base10Log( Abc_NtkPiNum(p->pNtk) ), iStart, Abc_Base10Log( Abc_NtkPoNum(p->pNtk) ), iEnd ); } } /**Function************************************************************* Synopsis [Timing computation for pin/gate/cone/network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline 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 Scl_LibPinArrival( pTime, pArrIn, pSlewIn, pLoad, pArrOut, pSlewOut ); } static inline 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 ); Scl_LibPinDeparture( pTime, pDepIn, pSlewIn, pLoad, pDepOut ); } static inline void Abc_SclDeptObj( SC_Man * p, Abc_Obj_t * pObj ) { SC_Timing * pTime; Abc_Obj_t * pFanout; int i; SC_PairClean( Abc_SclObjDept(p, pObj) ); Abc_ObjForEachFanout( pObj, pFanout, i ) { if ( Abc_ObjIsCo(pFanout) || Abc_ObjIsLatch(pFanout) ) continue; pTime = Scl_CellPinTime( Abc_SclObjCell(pFanout), Abc_NodeFindFanin(pFanout, pObj) ); Abc_SclDeptFanin( p, pTime, pFanout, pObj ); } } static inline float Abc_SclObjLoadValue( SC_Man * p, Abc_Obj_t * pObj ) { // float Value = Abc_MaxFloat(pLoad->fall, pLoad->rise) / (p->EstLoadAve * p->EstLoadMax); return (0.5 * Abc_SclObjLoad(p, pObj)->fall + 0.5 * Abc_SclObjLoad(p, pObj)->rise) / (p->EstLoadAve * p->EstLoadMax); } static inline void Abc_SclTimeCi( SC_Man * p, Abc_Obj_t * pObj ) { if ( p->pPiDrive != NULL ) { SC_Pair * pLoad = Abc_SclObjLoad( p, pObj ); SC_Pair * pTime = Abc_SclObjTime( p, pObj ); SC_Pair * pSlew = Abc_SclObjSlew( p, pObj ); Scl_LibHandleInputDriver( p->pPiDrive, pLoad, pTime, pSlew ); } } void Abc_SclTimeNode( SC_Man * p, Abc_Obj_t * pObj, int fDept ) { SC_Timing * pTime; SC_Cell * pCell; int k; SC_Pair * pLoad = Abc_SclObjLoad( p, pObj ); float LoadRise = pLoad->rise; float LoadFall = pLoad->fall; float DeptRise = 0; float DeptFall = 0; float Value = p->EstLoadMax ? Abc_SclObjLoadValue( p, pObj ) : 0; Abc_Obj_t * pFanin; if ( Abc_ObjIsCi(pObj) ) { assert( !fDept ); Abc_SclTimeCi( p, pObj ); return; } if ( Abc_ObjIsCo(pObj) ) { if ( !fDept ) { Abc_SclObjDupFanin( p, pObj ); Vec_FltWriteEntry( p->vTimesOut, pObj->iData, Abc_SclObjTimeMax(p, pObj) ); Vec_QueUpdate( p->vQue, pObj->iData ); } return; } assert( Abc_ObjIsNode(pObj) ); // if ( !(Abc_ObjFaninNum(pObj) == 1 && Abc_ObjIsPi(Abc_ObjFanin0(pObj))) && p->EstLoadMax && Value > 1 ) if ( p->EstLoadMax && Value > 1 ) { pLoad->rise = p->EstLoadAve * p->EstLoadMax; pLoad->fall = p->EstLoadAve * p->EstLoadMax; if ( fDept ) { SC_Pair * pDepOut = Abc_SclObjDept( p, pObj ); float EstDelta = p->EstLinear * log( Value ); DeptRise = pDepOut->rise; DeptFall = pDepOut->fall; pDepOut->rise += EstDelta; pDepOut->fall += EstDelta; } p->nEstNodes++; } // get the library cell pCell = Abc_SclObjCell( pObj ); // compute for each fanin Abc_ObjForEachFanin( pObj, pFanin, k ) { pTime = Scl_CellPinTime( pCell, k ); if ( fDept ) Abc_SclDeptFanin( p, pTime, pObj, pFanin ); else Abc_SclTimeFanin( p, pTime, pObj, pFanin ); } if ( p->EstLoadMax && Value > 1 ) { pLoad->rise = LoadRise; pLoad->fall = LoadFall; if ( fDept ) { SC_Pair * pDepOut = Abc_SclObjDept( p, pObj ); pDepOut->rise = DeptRise; pDepOut->fall = DeptFall; } else { SC_Pair * pArrOut = Abc_SclObjTime( p, pObj ); float EstDelta = p->EstLinear * log( Value ); pArrOut->rise += EstDelta; pArrOut->fall += EstDelta; } } } void Abc_SclTimeCone( SC_Man * p, Vec_Int_t * vCone ) { int fVerbose = 0; Abc_Obj_t * pObj; int i; Abc_SclConeClean( 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(pObj)->pName ); if ( fVerbose && Abc_ObjIsNode(pObj) ) printf( " before (%6.1f ps %6.1f ps) ", Abc_SclObjTimeOne(p, pObj, 1), Abc_SclObjTimeOne(p, pObj, 0) ); Abc_SclTimeNode( p, pObj, 0 ); if ( fVerbose && Abc_ObjIsNode(pObj) ) printf( "after (%6.1f ps %6.1f ps)\n", Abc_SclObjTimeOne(p, pObj, 1), Abc_SclObjTimeOne(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 ); p->nEstNodes = 0; Abc_NtkForEachCi( p->pNtk, pObj, i ) Abc_SclTimeNode( p, pObj, 0 ); Abc_NtkForEachNode1( p->pNtk, pObj, i ) Abc_SclTimeNode( p, pObj, 0 ); Abc_NtkForEachCo( p->pNtk, pObj, i ) Abc_SclTimeNode( p, pObj, 0 ); D = Abc_SclReadMaxDelay( p ); if ( fReverse && DUser > 0 && D < DUser ) D = DUser; if ( pArea ) *pArea = Abc_SclGetTotalArea(p->pNtk); if ( pDelay ) *pDelay = D; if ( fReverse ) { p->nEstNodes = 0; Abc_NtkForEachNodeReverse1( p->pNtk, pObj, i ) Abc_SclTimeNode( p, pObj, 1 ); } } /**Function************************************************************* Synopsis [Incremental timing update.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Abc_SclTimeIncUpdateClean( SC_Man * p ) { Vec_Int_t * vLevel; Abc_Obj_t * pObj; int i, k; Vec_WecForEachLevel( p->vLevels, vLevel, i ) { Abc_NtkForEachObjVec( vLevel, p->pNtk, pObj, k ) { assert( pObj->fMarkC == 1 ); pObj->fMarkC = 0; } Vec_IntClear( vLevel ); } } static inline void Abc_SclTimeIncAddNode( SC_Man * p, Abc_Obj_t * pObj ) { assert( !Abc_ObjIsLatch(pObj) ); assert( pObj->fMarkC == 0 ); pObj->fMarkC = 1; Vec_IntPush( Vec_WecEntry(p->vLevels, Abc_ObjLevel(pObj)), Abc_ObjId(pObj) ); p->nIncUpdates++; } static inline void Abc_SclTimeIncAddFanins( SC_Man * p, Abc_Obj_t * pObj ) { Abc_Obj_t * pFanin; int i; Abc_ObjForEachFanin( pObj, pFanin, i ) // if ( !pFanin->fMarkC && Abc_ObjIsNode(pFanin) ) if ( !pFanin->fMarkC && !Abc_ObjIsLatch(pFanin) ) Abc_SclTimeIncAddNode( p, pFanin ); } static inline void Abc_SclTimeIncAddFanouts( SC_Man * p, Abc_Obj_t * pObj ) { Abc_Obj_t * pFanout; int i; Abc_ObjForEachFanout( pObj, pFanout, i ) if ( !pFanout->fMarkC && !Abc_ObjIsLatch(pFanout) ) Abc_SclTimeIncAddNode( p, pFanout ); } static inline void Abc_SclTimeIncUpdateArrival( SC_Man * p ) { Vec_Int_t * vLevel; SC_Pair ArrOut, SlewOut; SC_Pair * pArrOut, *pSlewOut; Abc_Obj_t * pObj; float E = (float)0.1; int i, k; Vec_WecForEachLevel( p->vLevels, vLevel, i ) { Abc_NtkForEachObjVec( vLevel, p->pNtk, pObj, k ) { if ( Abc_ObjIsCo(pObj) ) { Abc_SclObjDupFanin( p, pObj ); Vec_FltWriteEntry( p->vTimesOut, pObj->iData, Abc_SclObjTimeMax(p, pObj) ); Vec_QueUpdate( p->vQue, pObj->iData ); continue; } pArrOut = Abc_SclObjTime( p, pObj ); pSlewOut = Abc_SclObjSlew( p, pObj ); SC_PairMove( &ArrOut, pArrOut ); SC_PairMove( &SlewOut, pSlewOut ); Abc_SclTimeNode( p, pObj, 0 ); // if ( !SC_PairEqual(&ArrOut, pArrOut) || !SC_PairEqual(&SlewOut, pSlewOut) ) if ( !SC_PairEqualE(&ArrOut, pArrOut, E) || !SC_PairEqualE(&SlewOut, pSlewOut, E) ) Abc_SclTimeIncAddFanouts( p, pObj ); } } p->MaxDelay = Abc_SclReadMaxDelay( p ); } static inline void Abc_SclTimeIncUpdateDeparture( SC_Man * p ) { Vec_Int_t * vLevel; SC_Pair DepOut, * pDepOut; Abc_Obj_t * pObj; float E = (float)0.1; int i, k; Vec_WecForEachLevelReverse( p->vLevels, vLevel, i ) { Abc_NtkForEachObjVec( vLevel, p->pNtk, pObj, k ) { pDepOut = Abc_SclObjDept( p, pObj ); SC_PairMove( &DepOut, pDepOut ); Abc_SclDeptObj( p, pObj ); // if ( !SC_PairEqual(&DepOut, pDepOut) ) if ( !SC_PairEqualE(&DepOut, pDepOut, E) ) Abc_SclTimeIncAddFanins( p, pObj ); } } p->MaxDelay = Abc_SclReadMaxDelay( p ); } void Abc_SclTimeIncCheckLevel( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pObj; int i; Abc_NtkForEachObj( pNtk, pObj, i ) if ( (int)pObj->Level != Abc_ObjLevelNew(pObj) ) printf( "Level of node %d is out of date!\n", i ); } int Abc_SclTimeIncUpdate( SC_Man * p ) { Abc_Obj_t * pObj; int i, RetValue; if ( Vec_IntSize(p->vChanged) == 0 ) return 0; // Abc_SclTimeIncCheckLevel( p->pNtk ); Abc_NtkForEachObjVec( p->vChanged, p->pNtk, pObj, i ) { Abc_SclTimeIncAddFanins( p, pObj ); if ( pObj->fMarkC ) continue; Abc_SclTimeIncAddNode( p, pObj ); } Vec_IntClear( p->vChanged ); Abc_SclTimeIncUpdateArrival( p ); Abc_SclTimeIncUpdateDeparture( p ); Abc_SclTimeIncUpdateClean( p ); RetValue = p->nIncUpdates; p->nIncUpdates = 0; return RetValue; } void Abc_SclTimeIncInsert( SC_Man * p, Abc_Obj_t * pObj ) { Vec_IntPush( p->vChanged, Abc_ObjId(pObj) ); } void Abc_SclTimeIncUpdateLevel_rec( Abc_Obj_t * pObj ) { Abc_Obj_t * pFanout; int i, LevelNew = Abc_ObjLevelNew(pObj); if ( LevelNew == (int)pObj->Level ) return; pObj->Level = LevelNew; Abc_ObjForEachFanout( pObj, pFanout, i ) Abc_SclTimeIncUpdateLevel_rec( pFanout ); } void Abc_SclTimeIncUpdateLevel( Abc_Obj_t * pObj ) { Abc_SclTimeIncUpdateLevel_rec( pObj ); } /**Function************************************************************* Synopsis [Read input slew and output load.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_SclManReadSlewAndLoad( SC_Man * p, Abc_Ntk_t * pNtk ) { if ( Abc_FrameReadMaxLoad() ) { Abc_Obj_t * pObj; int i; float MaxLoad = Abc_FrameReadMaxLoad(); // printf( "Default output load is specified (%.2f ff).\n", MaxLoad ); Abc_NtkForEachPo( pNtk, pObj, i ) { SC_Pair * pLoad = Abc_SclObjLoad( p, pObj ); pLoad->rise = pLoad->fall = MaxLoad; } } if ( Abc_FrameReadDrivingCell() ) { int iCell = Abc_SclCellFind( p->pLib, Abc_FrameReadDrivingCell() ); if ( iCell == -1 ) printf( "Cannot find the default PI driving cell (%s) in the library.\n", Abc_FrameReadDrivingCell() ); else { // printf( "Default PI driving cell is specified (%s).\n", Abc_FrameReadDrivingCell() ); p->pPiDrive = SC_LibCell( p->pLib, iCell ); assert( p->pPiDrive != NULL ); assert( p->pPiDrive->n_inputs == 1 ); } } } /**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, int nTreeCRatio ) { SC_Man * p = Abc_SclManAlloc( pLib, pNtk ); if ( nTreeCRatio ) { p->EstLoadMax = 0.01 * nTreeCRatio; // max ratio of Cout/Cave when the estimation is used p->EstLinear = 100; // linear coefficient } Abc_SclMioGates2SclGates( pLib, pNtk ); Abc_SclManReadSlewAndLoad( p, pNtk ); if ( fUseWireLoads ) { if ( pNtk->pWLoadUsed == NULL ) { p->pWLoadUsed = Abc_SclFindWireLoadModel( pLib, Abc_SclGetTotalArea(p->pNtk) ); if ( p->pWLoadUsed ) pNtk->pWLoadUsed = Abc_UtilStrsav( p->pWLoadUsed->pName ); } else p->pWLoadUsed = Abc_SclFetchWireLoadModel( pLib, pNtk->pWLoadUsed ); } Abc_SclTimeNtkRecompute( p, &p->SumArea0, &p->MaxDelay0, fDept, DUser ); p->SumArea = p->SumArea0; p->MaxDelay = p->MaxDelay0; return p; } /**Function************************************************************* Synopsis [Printing out timing information for the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_SclTimePerformInt( SC_Lib * pLib, Abc_Ntk_t * pNtk, int nTreeCRatio, int fUseWireLoads, int fShowAll, int fPrintPath, int fDumpStats ) { SC_Man * p; p = Abc_SclManStart( pLib, pNtk, fUseWireLoads, 1, 0, nTreeCRatio ); Abc_SclTimeNtkPrint( p, fShowAll, fPrintPath ); if ( fDumpStats ) Abc_SclDumpStats( p, "stats.txt", 0 ); Abc_SclManFree( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_SclTimePerform( SC_Lib * pLib, Abc_Ntk_t * pNtk, int nTreeCRatio, int fUseWireLoads, int fShowAll, int fPrintPath, int fDumpStats ) { Abc_Ntk_t * pNtkNew = pNtk; if ( pNtk->nBarBufs2 > 0 ) pNtkNew = Abc_NtkDupDfsNoBarBufs( pNtk ); Abc_SclTimePerformInt( pLib, pNtkNew, nTreeCRatio, fUseWireLoads, fShowAll, fPrintPath, fDumpStats ); if ( pNtk->nBarBufs2 > 0 ) Abc_NtkDelete( pNtkNew ); } /**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_SclHasBufferFanout( Abc_Obj_t * pObj ) { Abc_Obj_t * pFanout; int i; Abc_ObjForEachFanout( pObj, pFanout, i ) if ( Abc_ObjIsBuffer(pFanout) ) return 1; return 0; } int Abc_SclCountBufferFanoutsInt( Abc_Obj_t * pObj ) { Abc_Obj_t * pFanout; int i, Counter = 0; Abc_ObjForEachFanout( pObj, pFanout, i ) if ( Abc_ObjIsBuffer(pFanout) ) Counter += Abc_SclCountBufferFanoutsInt( pFanout ); return Counter + Abc_ObjIsBuffer(pObj); } int Abc_SclCountBufferFanouts( Abc_Obj_t * pObj ) { return Abc_SclCountBufferFanoutsInt(pObj) - Abc_ObjIsBuffer(pObj); } int Abc_SclCountNonBufferFanoutsInt( 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_SclCountNonBufferFanoutsInt( pFanout ); return Counter; } int Abc_SclCountNonBufferFanouts( Abc_Obj_t * pObj ) { Abc_Obj_t * pFanout; int i, Counter = 0; Abc_ObjForEachFanout( pObj, pFanout, i ) Counter += Abc_SclCountNonBufferFanoutsInt( pFanout ); return Counter; } float Abc_SclCountNonBufferDelayInt( SC_Man * p, Abc_Obj_t * pObj ) { Abc_Obj_t * pFanout; float Delay = 0; int i; if ( !Abc_ObjIsBuffer(pObj) ) return Abc_SclObjTimeMax(p, pObj); Abc_ObjForEachFanout( pObj, pFanout, i ) Delay += Abc_SclCountNonBufferDelayInt( p, pFanout ); return Delay; } float Abc_SclCountNonBufferDelay( SC_Man * p, Abc_Obj_t * pObj ) { Abc_Obj_t * pFanout; float Delay = 0; int i; Abc_ObjForEachFanout( pObj, pFanout, i ) Delay += Abc_SclCountNonBufferDelayInt( p, pFanout ); return Delay; } float Abc_SclCountNonBufferLoadInt( SC_Man * p, Abc_Obj_t * pObj ) { Abc_Obj_t * pFanout; float Load = 0; int i; if ( !Abc_ObjIsBuffer(pObj) ) return 0; Abc_ObjForEachFanout( pObj, pFanout, i ) Load += Abc_SclCountNonBufferLoadInt( p, pFanout ); Load += 0.5 * Abc_SclObjLoad(p, pObj)->rise + 0.5 * Abc_SclObjLoad(p, pObj)->fall; Load -= 0.5 * SC_CellPin(Abc_SclObjCell(pObj), 0)->rise_cap + 0.5 * SC_CellPin(Abc_SclObjCell(pObj), 0)->fall_cap; return Load; } float Abc_SclCountNonBufferLoad( SC_Man * p, Abc_Obj_t * pObj ) { Abc_Obj_t * pFanout; float Load = 0; int i; Abc_ObjForEachFanout( pObj, pFanout, i ) Load += Abc_SclCountNonBufferLoadInt( p, pFanout ); Load += 0.5 * Abc_SclObjLoad(p, pObj)->rise + 0.5 * Abc_SclObjLoad(p, pObj)->fall; return Load; } void Abc_SclPrintBuffersOne( SC_Man * p, Abc_Obj_t * pObj, int nOffset ) { int i; for ( i = 0; i < nOffset; i++ ) printf( " " ); printf( "%6d: %-16s (%2d:%3d:%3d) ", Abc_ObjId(pObj), Abc_ObjIsPi(pObj) ? "pi" : Mio_GateReadName((Mio_Gate_t *)pObj->pData), Abc_ObjFanoutNum(pObj), Abc_SclCountBufferFanouts(pObj), Abc_SclCountNonBufferFanouts(pObj) ); for ( ; i < 4; i++ ) printf( " " ); printf( "a =%5.2f ", Abc_ObjIsPi(pObj) ? 0 : Abc_SclObjCell(pObj)->area ); printf( "d = (" ); printf( "%6.0f ps; ", Abc_SclObjTimeOne(p, pObj, 1) ); printf( "%6.0f ps) ", Abc_SclObjTimeOne(p, pObj, 0) ); printf( "l =%5.0f ff ", Abc_SclObjLoadMax(p, pObj) ); printf( "s =%5.0f ps ", Abc_SclObjSlewMax(p, pObj) ); printf( "sl =%5.0f ps ", Abc_SclObjSlackMax(p, pObj, p->MaxDelay0) ); if ( nOffset == 0 ) { printf( "L =%5.0f ff ", Abc_SclCountNonBufferLoad(p, pObj) ); printf( "Lx =%5.0f ff ", 100.0*Abc_SclCountNonBufferLoad(p, pObj)/p->EstLoadAve ); printf( "Dx =%5.0f ps ", Abc_SclCountNonBufferDelay(p, pObj)/Abc_SclCountNonBufferFanouts(pObj) - Abc_SclObjTimeOne(p, pObj, 1) ); printf( "Cx =%5.0f ps", (Abc_SclCountNonBufferDelay(p, pObj)/Abc_SclCountNonBufferFanouts(pObj) - Abc_SclObjTimeOne(p, pObj, 1))/log(Abc_SclCountNonBufferLoad(p, pObj)/p->EstLoadAve) ); } printf( "\n" ); } void Abc_SclPrintBuffersInt( SC_Man * p, Abc_Obj_t * pObj, int nOffset ) { Abc_Obj_t * pFanout; int i; Abc_SclPrintBuffersOne( p, pObj, nOffset ); assert( Abc_ObjIsBuffer(pObj) ); 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, * pFanout; int i, k; Abc_NtkForEachObj( pNtk, pObj, i ) { if ( !Abc_ObjIsBuffer(pObj) && Abc_SclCountBufferFanouts(pObj) > 3 ) { Abc_SclPrintBuffersOne( p, pObj, 0 ); Abc_ObjForEachFanout( pObj, pFanout, k ) if ( Abc_ObjIsBuffer(pFanout) ) Abc_SclPrintBuffersInt( p, pFanout, 1 ); 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, 10000 ); Abc_SclPrintBufferTrees( p, pNtk ); // Abc_SclPrintFaninPairs( p, pNtk ); Abc_SclManFree( p ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END