/**CFile**************************************************************** FileName [retDelay.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Retiming package.] Synopsis [Incremental retiming for optimum delay.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - Oct 31, 2006.] Revision [$Id: retDelay.c,v 1.00 2006/10/31 00:00:00 alanmi Exp $] ***********************************************************************/ #include "retInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static int Abc_NtkRetimeMinDelayTry( Abc_Ntk_t * pNtk, int nDelayLim, int fForward, int fInitial, int nIterLimit, int * pIterBest, int fVerbose ); static int Abc_NtkRetimeTiming( Abc_Ntk_t * pNtk, int fForward, Vec_Ptr_t * vCritical ); static int Abc_NtkRetimeTiming_rec( Abc_Obj_t * pObj, int fForward ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Retimes incrementally for minimum delay.] Description [This procedure cannot be called in the application code because it assumes that the network is preprocessed by removing LIs/LOs.] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkRetimeMinDelay( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkCopy, int nDelayLim, int nIterLimit, int fForward, int fVerbose ) { int IterBest, DelayBest; int IterBest2, DelayBest2; // try to find the best delay iteration on a copy DelayBest = Abc_NtkRetimeMinDelayTry( pNtkCopy, nDelayLim, fForward, 0, nIterLimit, &IterBest, fVerbose ); if ( IterBest == 0 ) return 1; // perform the given number of iterations on the original network DelayBest2 = Abc_NtkRetimeMinDelayTry( pNtk, nDelayLim, fForward, 1, IterBest, &IterBest2, fVerbose ); assert( DelayBest == DelayBest2 ); assert( IterBest == IterBest2 ); return 1; } /**Function************************************************************* Synopsis [Returns the best delay and the number of best iteration.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkRetimeMinDelayTry( Abc_Ntk_t * pNtk, int nDelayLim, int fForward, int fInitial, int nIterLimit, int * pIterBest, int fVerbose ) { Abc_Ntk_t * pNtkNew = NULL; Vec_Ptr_t * vCritical; Vec_Int_t * vValues = NULL; // Suppress "might be used uninitialized" Abc_Obj_t * pObj; int i, k, IterBest, DelayCur, DelayBest; int DelayStart = -1; // Suppress "might be used uninitialized" int LatchesBest; // transfer intitial values if ( fInitial ) { if ( fForward ) Abc_NtkRetimeTranferToCopy( pNtk ); else { // save initial value of the latches vValues = Abc_NtkRetimeCollectLatchValues( pNtk ); // start the network for initial value computation pNtkNew = Abc_NtkRetimeBackwardInitialStart( pNtk ); } } if ( fVerbose && !fInitial ) printf( "Performing analysis:\n" ); // find the best iteration DelayBest = ABC_INFINITY; IterBest = 0; LatchesBest = Abc_NtkLatchNum(pNtk); vCritical = Vec_PtrAlloc( 100 ); for ( i = 0; ; i++ ) { // perform moves for the timing-critical nodes DelayCur = Abc_NtkRetimeTiming( pNtk, fForward, vCritical ); if ( i == 0 ) DelayStart = DelayCur; // record this position if it has the best delay if ( DelayBest > DelayCur ) { if ( fVerbose && !fInitial ) printf( "%s Iter = %3d. Delay = %3d. Latches = %5d. Delta = %6.2f. Ratio = %4.2f %%\n", fForward ? "Fwd": "Bwd", i, DelayCur, Abc_NtkLatchNum(pNtk), 1.0*(Abc_NtkLatchNum(pNtk)-LatchesBest)/(DelayBest-DelayCur), 100.0*(Abc_NtkLatchNum(pNtk)-LatchesBest)/Abc_NtkLatchNum(pNtk)/(DelayBest-DelayCur) ); DelayBest = DelayCur; IterBest = i; LatchesBest = Abc_NtkLatchNum(pNtk); } // quit after timing analysis if ( i == nIterLimit ) break; // skip if 10 interations did not give improvement if ( i - IterBest > 20 ) break; // skip if delay limit is reached if ( nDelayLim > 0 && DelayCur <= nDelayLim ) break; // try retiming to improve the delay Vec_PtrForEachEntry( Abc_Obj_t *, vCritical, pObj, k ) if ( Abc_NtkRetimeNodeIsEnabled(pObj, fForward) ) Abc_NtkRetimeNode( pObj, fForward, fInitial ); // share latches if ( !fForward ) Abc_NtkRetimeShareLatches( pNtk, fInitial ); } Vec_PtrFree( vCritical ); // transfer the initial state back to the latches if ( fInitial ) { if ( fForward ) Abc_NtkRetimeTranferFromCopy( pNtk ); else { Abc_NtkRetimeBackwardInitialFinish( pNtk, pNtkNew, vValues, fVerbose ); Abc_NtkDelete( pNtkNew ); Vec_IntFree( vValues ); } } if ( fVerbose && !fInitial ) printf( "%s : Starting delay = %3d. Final delay = %3d. IterBest = %2d (out of %2d).\n", fForward? "Forward " : "Backward", DelayStart, DelayBest, IterBest, nIterLimit ); *pIterBest = (nIterLimit == 1) ? 1 : IterBest; return DelayBest; } /**Function************************************************************* Synopsis [Returns the set of timing-critical nodes.] Description [Performs static timing analysis on the network. Uses unit-delay model.] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkRetimeTiming( Abc_Ntk_t * pNtk, int fForward, Vec_Ptr_t * vCritical ) { Vec_Ptr_t * vLatches; Abc_Obj_t * pObj, * pNext; int i, k, LevelCur, LevelMax = 0; // mark all objects except nodes Abc_NtkIncrementTravId(pNtk); vLatches = Vec_PtrAlloc( Abc_NtkLatchNum(pNtk) ); Abc_NtkForEachObj( pNtk, pObj, i ) { if ( Abc_ObjIsLatch(pObj) ) Vec_PtrPush( vLatches, pObj ); if ( Abc_ObjIsNode(pObj) ) continue; pObj->Level = 0; Abc_NodeSetTravIdCurrent( pObj ); } // perform analysis from CIs/COs if ( fForward ) { Vec_PtrForEachEntry( Abc_Obj_t *, vLatches, pObj, i ) { Abc_ObjForEachFanout( pObj, pNext, k ) { LevelCur = Abc_NtkRetimeTiming_rec( pNext, fForward ); if ( LevelMax < LevelCur ) LevelMax = LevelCur; } } Abc_NtkForEachPi( pNtk, pObj, i ) { Abc_ObjForEachFanout( pObj, pNext, k ) { LevelCur = Abc_NtkRetimeTiming_rec( pNext, fForward ); if ( LevelMax < LevelCur ) LevelMax = LevelCur; } } } else { Vec_PtrForEachEntry( Abc_Obj_t *, vLatches, pObj, i ) { LevelCur = Abc_NtkRetimeTiming_rec( Abc_ObjFanin0(pObj), fForward ); if ( LevelMax < LevelCur ) LevelMax = LevelCur; } Abc_NtkForEachPo( pNtk, pObj, i ) { LevelCur = Abc_NtkRetimeTiming_rec( Abc_ObjFanin0(pObj), fForward ); if ( LevelMax < LevelCur ) LevelMax = LevelCur; } } // collect timing critical nodes, which should be retimed forward/backward Vec_PtrClear( vCritical ); Abc_NtkIncrementTravId(pNtk); if ( fForward ) { Vec_PtrForEachEntry( Abc_Obj_t *, vLatches, pObj, i ) { Abc_ObjForEachFanout( pObj, pNext, k ) { if ( Abc_NodeIsTravIdCurrent(pNext) ) continue; if ( LevelMax != (int)pNext->Level ) continue; // new critical node Vec_PtrPush( vCritical, pNext ); Abc_NodeSetTravIdCurrent( pNext ); } } } else { Vec_PtrForEachEntry( Abc_Obj_t *, vLatches, pObj, i ) { Abc_ObjForEachFanin( pObj, pNext, k ) { if ( Abc_NodeIsTravIdCurrent(pNext) ) continue; if ( LevelMax != (int)pNext->Level ) continue; // new critical node Vec_PtrPush( vCritical, pNext ); Abc_NodeSetTravIdCurrent( pNext ); } } } Vec_PtrFree( vLatches ); return LevelMax; } /**Function************************************************************* Synopsis [Recursively performs timing analysis.] Description [Performs static timing analysis on the network. Uses unit-delay model.] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkRetimeTiming_rec( Abc_Obj_t * pObj, int fForward ) { Abc_Obj_t * pNext; int i, LevelCur, LevelMax = 0; // skip visited nodes if ( Abc_NodeIsTravIdCurrent(pObj) ) return pObj->Level; Abc_NodeSetTravIdCurrent(pObj); // visit the next nodes if ( fForward ) { Abc_ObjForEachFanout( pObj, pNext, i ) { LevelCur = Abc_NtkRetimeTiming_rec( pNext, fForward ); if ( LevelMax < LevelCur ) LevelMax = LevelCur; } } else { Abc_ObjForEachFanin( pObj, pNext, i ) { LevelCur = Abc_NtkRetimeTiming_rec( pNext, fForward ); if ( LevelMax < LevelCur ) LevelMax = LevelCur; } } // printf( "Node %3d -> Level %3d.\n", pObj->Id, LevelMax + 1 ); pObj->Level = LevelMax + 1; return pObj->Level; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END