diff options
Diffstat (limited to 'src/opt/fret/fretTime.c')
-rw-r--r-- | src/opt/fret/fretTime.c | 766 |
1 files changed, 766 insertions, 0 deletions
diff --git a/src/opt/fret/fretTime.c b/src/opt/fret/fretTime.c new file mode 100644 index 00000000..b423ace8 --- /dev/null +++ b/src/opt/fret/fretTime.c @@ -0,0 +1,766 @@ +/**CFile**************************************************************** + + FileName [fretTime.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Flow-based retiming package.] + + Synopsis [Delay-constrained retiming code.] + + Author [Aaron Hurst] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - January 1, 2008.] + + Revision [$Id: fretTime.c,v 1.00 2008/01/01 00:00:00 ahurst Exp $] + +***********************************************************************/ + +#include "fretime.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static void Abc_FlowRetime_Dfs_forw( Abc_Obj_t * pObj, Vec_Ptr_t *vNodes ); +static void Abc_FlowRetime_Dfs_back( Abc_Obj_t * pObj, Vec_Ptr_t *vNodes ); + +static void Abc_FlowRetime_ConstrainExact_forw( Abc_Obj_t * pObj ); +static void Abc_FlowRetime_ConstrainExact_back( Abc_Obj_t * pObj ); +static void Abc_FlowRetime_ConstrainConserv_forw( Abc_Ntk_t * pNtk ); +static void Abc_FlowRetime_ConstrainConserv_back( Abc_Ntk_t * pNtk ); + + +void trace2(Abc_Obj_t *pObj) { + Abc_Obj_t *pNext; + int i; + + print_node(pObj); + Abc_ObjForEachFanin(pObj, pNext, i) + if (pNext->Level >= pObj->Level - 1) { + trace2(pNext); + break; + } +} + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + + +/**Function************************************************************* + + Synopsis [Initializes timing] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_FlowRetime_InitTiming( Abc_Ntk_t *pNtk ) { + + pManMR->nConservConstraints = pManMR->nExactConstraints = 0; + + pManMR->vExactNodes = Vec_PtrAlloc(1000); + + pManMR->vTimeEdges = ABC_ALLOC( Vec_Ptr_t, Abc_NtkObjNumMax(pNtk)+1 ); + assert(pManMR->vTimeEdges); + memset(pManMR->vTimeEdges, 0, (Abc_NtkObjNumMax(pNtk)+1) * sizeof(Vec_Ptr_t) ); +} + + +/**Function************************************************************* + + Synopsis [Marks nodes with conservative constraints.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_FlowRetime_ConstrainConserv( Abc_Ntk_t * pNtk ) { + Abc_Obj_t *pObj; + int i; + void *pArray; + + // clear all exact constraints + pManMR->nExactConstraints = 0; + while( Vec_PtrSize( pManMR->vExactNodes )) { + pObj = Vec_PtrPop( pManMR->vExactNodes ); + + if ( Vec_PtrSize( FTIMEEDGES(pObj) )) { + pArray = Vec_PtrReleaseArray( FTIMEEDGES(pObj) ); + ABC_FREE( pArray ); + } + } + +#if !defined(IGNORE_TIMING) + if (pManMR->fIsForward) { + Abc_FlowRetime_ConstrainConserv_forw(pNtk); + } else { + Abc_FlowRetime_ConstrainConserv_back(pNtk); + } +#endif + + Abc_NtkForEachObj( pNtk, pObj, i) + assert( !Vec_PtrSize(FTIMEEDGES(pObj)) ); +} + + +void Abc_FlowRetime_ConstrainConserv_forw( Abc_Ntk_t * pNtk ) { + Vec_Ptr_t *vNodes = pManMR->vNodes; + Abc_Obj_t *pObj, *pNext, *pBi, *pBo; + int i, j; + + assert(!Vec_PtrSize( vNodes )); + pManMR->nConservConstraints = 0; + + // 1. hard constraints + + // (i) collect TFO of PIs + Abc_NtkIncrementTravId(pNtk); + Abc_NtkForEachPi(pNtk, pObj, i) + Abc_FlowRetime_Dfs_forw( pObj, vNodes ); + + // ... propagate values + Vec_PtrForEachEntryReverse( Abc_Obj_t *,vNodes, pObj, i) { + pObj->Level = 0; + Abc_ObjForEachFanin( pObj, pNext, j ) + { + if ( Abc_NodeIsTravIdCurrent(pNext) && + pObj->Level < pNext->Level ) + pObj->Level = pNext->Level; + } + pObj->Level += Abc_ObjIsNode(pObj) ? 1 : 0; + + if ( Abc_ObjIsBi(pObj) ) + pObj->fMarkA = 1; + + assert(pObj->Level <= pManMR->maxDelay); + } + + // collect TFO of latches + // seed arrival times from BIs + Vec_PtrClear(vNodes); + Abc_NtkIncrementTravId(pNtk); + Abc_NtkForEachLatch(pNtk, pObj, i) { + pBo = Abc_ObjFanout0( pObj ); + pBi = Abc_ObjFanin0( pObj ); + + Abc_NodeSetTravIdCurrent( pObj ); + Abc_FlowRetime_Dfs_forw( pBo, vNodes ); + + if (pBi->fMarkA) { + pBi->fMarkA = 0; + pObj->Level = pBi->Level; + assert(pObj->Level <= pManMR->maxDelay); + } else + pObj->Level = 0; + } + +#if defined(DEBUG_CHECK) + // DEBUG: check DFS ordering + Vec_PtrForEachEntryReverse( Abc_Obj_t *,vNodes, pObj, i) { + pObj->fMarkB = 1; + + Abc_ObjForEachFanin( pObj, pNext, j ) + if ( Abc_NodeIsTravIdCurrent(pNext) && !Abc_ObjIsLatch(pNext)) + assert(pNext->fMarkB); + } + Vec_PtrForEachEntryReverse( Abc_Obj_t *,vNodes, pObj, i) + pObj->fMarkB = 0; +#endif + + // ... propagate values + Vec_PtrForEachEntryReverse( Abc_Obj_t *,vNodes, pObj, i) { + pObj->Level = 0; + Abc_ObjForEachFanin( pObj, pNext, j ) + { + if ( Abc_NodeIsTravIdCurrent(pNext) && + pObj->Level < pNext->Level ) + pObj->Level = pNext->Level; + } + pObj->Level += Abc_ObjIsNode(pObj) ? 1 : 0; + + if (pObj->Level > pManMR->maxDelay) { + FSET(pObj, BLOCK); + } + } + + // 2. conservative constraints + + // first pass: seed latches with T=0 + Abc_NtkForEachLatch(pNtk, pObj, i) { + pObj->Level = 0; + } + + // ... propagate values + Vec_PtrForEachEntryReverse( Abc_Obj_t *,vNodes, pObj, i) { + pObj->Level = 0; + Abc_ObjForEachFanin( pObj, pNext, j ) { + if ( Abc_NodeIsTravIdCurrent(pNext) && + pObj->Level < pNext->Level ) + pObj->Level = pNext->Level; + } + pObj->Level += Abc_ObjIsNode(pObj) ? 1 : 0; + + if ( Abc_ObjIsBi(pObj) ) + pObj->fMarkA = 1; + + assert(pObj->Level <= pManMR->maxDelay); + } + + Abc_NtkForEachLatch(pNtk, pObj, i) { + pBo = Abc_ObjFanout0( pObj ); + pBi = Abc_ObjFanin0( pObj ); + + if (pBi->fMarkA) { + pBi->fMarkA = 0; + pObj->Level = pBi->Level; + assert(pObj->Level <= pManMR->maxDelay); + } else + pObj->Level = 0; + } + + // ... propagate values + Vec_PtrForEachEntryReverse( Abc_Obj_t *,vNodes, pObj, i) { + pObj->Level = 0; + Abc_ObjForEachFanin( pObj, pNext, j ) { + if ( Abc_NodeIsTravIdCurrent(pNext) && + pObj->Level < pNext->Level ) + pObj->Level = pNext->Level; + } + pObj->Level += Abc_ObjIsNode(pObj) ? 1 : 0; + + // constrained? + if (pObj->Level > pManMR->maxDelay) { + FSET( pObj, CONSERVATIVE ); + pManMR->nConservConstraints++; + } else + FUNSET( pObj, CONSERVATIVE ); + } + + Vec_PtrClear( vNodes ); +} + + +void Abc_FlowRetime_ConstrainConserv_back( Abc_Ntk_t * pNtk ) { + Vec_Ptr_t *vNodes = pManMR->vNodes; + Abc_Obj_t *pObj, *pNext, *pBi, *pBo; + int i, j, l; + + assert(!Vec_PtrSize(vNodes)); + + pManMR->nConservConstraints = 0; + + // 1. hard constraints + + // (i) collect TFO of POs + Abc_NtkIncrementTravId(pNtk); + Abc_NtkForEachPo(pNtk, pObj, i) + Abc_FlowRetime_Dfs_back( pObj, vNodes ); + + // ... propagate values + Vec_PtrForEachEntryReverse( Abc_Obj_t *,vNodes, pObj, i) { + pObj->Level = 0; + Abc_ObjForEachFanout( pObj, pNext, j ) + { + l = pNext->Level + (Abc_ObjIsNode(pObj) ? 1 : 0); + if ( Abc_NodeIsTravIdCurrent(pNext) && + pObj->Level < l ) + pObj->Level = l; + } + + if ( Abc_ObjIsBo(pObj) ) + pObj->fMarkA = 1; + + assert(pObj->Level <= pManMR->maxDelay); + } + + // collect TFO of latches + // seed arrival times from BIs + Vec_PtrClear(vNodes); + Abc_NtkIncrementTravId(pNtk); + Abc_NtkForEachLatch(pNtk, pObj, i) { + pBo = Abc_ObjFanout0( pObj ); + pBi = Abc_ObjFanin0( pObj ); + + Abc_NodeSetTravIdCurrent( pObj ); + Abc_FlowRetime_Dfs_back( pBi, vNodes ); + + if (pBo->fMarkA) { + pBo->fMarkA = 0; + pObj->Level = pBo->Level; + assert(pObj->Level <= pManMR->maxDelay); + } else + pObj->Level = 0; + } + +#if defined(DEBUG_CHECK) + // DEBUG: check DFS ordering + Vec_PtrForEachEntryReverse( Abc_Obj_t *,vNodes, pObj, i) { + pObj->fMarkB = 1; + + Abc_ObjForEachFanout( pObj, pNext, j ) + if ( Abc_NodeIsTravIdCurrent(pNext) && !Abc_ObjIsLatch(pNext)) + assert(pNext->fMarkB); + } + Vec_PtrForEachEntryReverse( Abc_Obj_t *,vNodes, pObj, i) + pObj->fMarkB = 0; +#endif + + // ... propagate values + Vec_PtrForEachEntryReverse( Abc_Obj_t *,vNodes, pObj, i) { + pObj->Level = 0; + Abc_ObjForEachFanout( pObj, pNext, j ) + { + l = pNext->Level + (Abc_ObjIsNode(pObj) ? 1 : 0); + if ( Abc_NodeIsTravIdCurrent(pNext) && + pObj->Level < l ) + pObj->Level = l; + } + + if (pObj->Level + (Abc_ObjIsNode(pObj)?1:0) > pManMR->maxDelay) { + FSET(pObj, BLOCK); + } + } + + // 2. conservative constraints + + // first pass: seed latches with T=0 + Abc_NtkForEachLatch(pNtk, pObj, i) { + pObj->Level = 0; + } + + // ... propagate values + Vec_PtrForEachEntryReverse( Abc_Obj_t *,vNodes, pObj, i) { + pObj->Level = 0; + Abc_ObjForEachFanout( pObj, pNext, j ) { + l = pNext->Level + (Abc_ObjIsNode(pObj) ? 1 : 0); + if ( Abc_NodeIsTravIdCurrent(pNext) && + pObj->Level < l ) + pObj->Level = l; + } + + if ( Abc_ObjIsBo(pObj) ) { + pObj->fMarkA = 1; + } + + assert(pObj->Level <= pManMR->maxDelay); + } + + Abc_NtkForEachLatch(pNtk, pObj, i) { + pBo = Abc_ObjFanout0( pObj ); + assert(Abc_ObjIsBo(pBo)); + pBi = Abc_ObjFanin0( pObj ); + assert(Abc_ObjIsBi(pBi)); + + if (pBo->fMarkA) { + pBo->fMarkA = 0; + pObj->Level = pBo->Level; + } else + pObj->Level = 0; + } + + // ... propagate values + Vec_PtrForEachEntryReverse( Abc_Obj_t *,vNodes, pObj, i) { + pObj->Level = 0; + Abc_ObjForEachFanout( pObj, pNext, j ) { + l = pNext->Level + (Abc_ObjIsNode(pObj) ? 1 : 0); + if ( Abc_NodeIsTravIdCurrent(pNext) && + pObj->Level < l ) + pObj->Level = l; + } + + // constrained? + if (pObj->Level > pManMR->maxDelay) { + FSET( pObj, CONSERVATIVE ); + pManMR->nConservConstraints++; + } else + FUNSET( pObj, CONSERVATIVE ); + } + + Vec_PtrClear( vNodes ); +} + + +/**Function************************************************************* + + Synopsis [Introduces exact timing constraints for a node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_FlowRetime_ConstrainExact( Abc_Obj_t * pObj ) { + + if (FTEST( pObj, CONSERVATIVE )) { + pManMR->nConservConstraints--; + FUNSET( pObj, CONSERVATIVE ); + } + +#if !defined(IGNORE_TIMING) + if (pManMR->fIsForward) { + Abc_FlowRetime_ConstrainExact_forw(pObj); + } else { + Abc_FlowRetime_ConstrainExact_back(pObj); + } +#endif +} + +void Abc_FlowRetime_ConstrainExact_forw_rec( Abc_Obj_t * pObj, Vec_Ptr_t *vNodes, int latch ) { + Abc_Obj_t *pNext; + int i; + + // terminate? + if (Abc_ObjIsLatch(pObj)) { + if (latch) return; + latch = 1; + } + + // already visited? + if (!latch) { + if (pObj->fMarkA) return; + pObj->fMarkA = 1; + } else { + if (pObj->fMarkB) return; + pObj->fMarkB = 1; + } + + // recurse + Abc_ObjForEachFanin(pObj, pNext, i) { + Abc_FlowRetime_ConstrainExact_forw_rec( pNext, vNodes, latch ); + } + + // add + pObj->Level = 0; + Vec_PtrPush(vNodes, Abc_ObjNotCond(pObj, latch)); +} + +void Abc_FlowRetime_ConstrainExact_forw( Abc_Obj_t * pObj ) { + Vec_Ptr_t *vNodes = pManMR->vNodes; + Abc_Obj_t *pNext, *pCur, *pReg; + // Abc_Ntk_t *pNtk = pManMR->pNtk; + int i, j; + + assert( !Vec_PtrSize(vNodes) ); + assert( !Abc_ObjIsLatch(pObj) ); + assert( !Vec_PtrSize( FTIMEEDGES(pObj) )); + Vec_PtrPush( pManMR->vExactNodes, pObj ); + + // rev topo order + Abc_FlowRetime_ConstrainExact_forw_rec( pObj, vNodes, 0 ); + + Vec_PtrForEachEntryReverse( Abc_Obj_t *, vNodes, pCur, i) { + pReg = Abc_ObjRegular( pCur ); + + if (pReg == pCur) { + assert(!Abc_ObjIsLatch(pReg)); + Abc_ObjForEachFanin(pReg, pNext, j) + pNext->Level = MAX( pNext->Level, pReg->Level + (Abc_ObjIsNode(pReg)?1:0)); + assert(pReg->Level <= pManMR->maxDelay); + pReg->Level = 0; + pReg->fMarkA = pReg->fMarkB = 0; + } + } + Vec_PtrForEachEntryReverse( Abc_Obj_t *, vNodes, pCur, i) { + pReg = Abc_ObjRegular( pCur ); + if (pReg != pCur) { + Abc_ObjForEachFanin(pReg, pNext, j) + if (!Abc_ObjIsLatch(pNext)) + pNext->Level = MAX( pNext->Level, pReg->Level + (Abc_ObjIsNode(pReg)?1:0)); + + if (pReg->Level == pManMR->maxDelay) { + Vec_PtrPush( FTIMEEDGES(pObj), pReg); + pManMR->nExactConstraints++; + } + pReg->Level = 0; + pReg->fMarkA = pReg->fMarkB = 0; + } + } + + Vec_PtrClear( vNodes ); +} + +void Abc_FlowRetime_ConstrainExact_back_rec( Abc_Obj_t * pObj, Vec_Ptr_t *vNodes, int latch ) { + Abc_Obj_t *pNext; + int i; + + // terminate? + if (Abc_ObjIsLatch(pObj)) { + if (latch) return; + latch = 1; + } + + // already visited? + if (!latch) { + if (pObj->fMarkA) return; + pObj->fMarkA = 1; + } else { + if (pObj->fMarkB) return; + pObj->fMarkB = 1; + } + + // recurse + Abc_ObjForEachFanout(pObj, pNext, i) { + Abc_FlowRetime_ConstrainExact_back_rec( pNext, vNodes, latch ); + } + + // add + pObj->Level = 0; + Vec_PtrPush(vNodes, Abc_ObjNotCond(pObj, latch)); +} + + +void Abc_FlowRetime_ConstrainExact_back( Abc_Obj_t * pObj ) { + Vec_Ptr_t *vNodes = pManMR->vNodes; + Abc_Obj_t *pNext, *pCur, *pReg; + // Abc_Ntk_t *pNtk = pManMR->pNtk; + int i, j; + + assert( !Vec_PtrSize( vNodes )); + assert( !Abc_ObjIsLatch(pObj) ); + assert( !Vec_PtrSize( FTIMEEDGES(pObj) )); + Vec_PtrPush( pManMR->vExactNodes, pObj ); + + // rev topo order + Abc_FlowRetime_ConstrainExact_back_rec( pObj, vNodes, 0 ); + + Vec_PtrForEachEntryReverse( Abc_Obj_t *, vNodes, pCur, i) { + pReg = Abc_ObjRegular( pCur ); + + if (pReg == pCur) { + assert(!Abc_ObjIsLatch(pReg)); + Abc_ObjForEachFanout(pReg, pNext, j) + pNext->Level = MAX( pNext->Level, pReg->Level + (Abc_ObjIsNode(pReg)?1:0)); + assert(pReg->Level <= pManMR->maxDelay); + pReg->Level = 0; + pReg->fMarkA = pReg->fMarkB = 0; + } + } + Vec_PtrForEachEntryReverse( Abc_Obj_t *, vNodes, pCur, i) { + pReg = Abc_ObjRegular( pCur ); + if (pReg != pCur) { + Abc_ObjForEachFanout(pReg, pNext, j) + if (!Abc_ObjIsLatch(pNext)) + pNext->Level = MAX( pNext->Level, pReg->Level + (Abc_ObjIsNode(pReg)?1:0)); + + if (pReg->Level == pManMR->maxDelay) { + Vec_PtrPush( FTIMEEDGES(pObj), pReg); + pManMR->nExactConstraints++; + } + pReg->Level = 0; + pReg->fMarkA = pReg->fMarkB = 0; + } + } + + Vec_PtrClear( vNodes ); +} + + +/**Function************************************************************* + + Synopsis [Introduces all exact timing constraints in a network] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_FlowRetime_ConstrainExactAll( Abc_Ntk_t * pNtk ) { + int i; + Abc_Obj_t *pObj; + void *pArray; + + // free existing constraints + Abc_NtkForEachObj( pNtk, pObj, i ) + if ( Vec_PtrSize( FTIMEEDGES(pObj) )) { + pArray = Vec_PtrReleaseArray( FTIMEEDGES(pObj) ); + ABC_FREE( pArray ); + } + pManMR->nExactConstraints = 0; + + // generate all constraints + Abc_NtkForEachObj(pNtk, pObj, i) + if (!Abc_ObjIsLatch(pObj) && FTEST( pObj, CONSERVATIVE ) && !FTEST( pObj, BLOCK )) + if (!Vec_PtrSize( FTIMEEDGES( pObj ) )) + Abc_FlowRetime_ConstrainExact( pObj ); +} + + + +/**Function************************************************************* + + Synopsis [Deallocates exact constraints.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_FlowRetime_FreeTiming( Abc_Ntk_t *pNtk ) { + Abc_Obj_t *pObj; + void *pArray; + + while( Vec_PtrSize( pManMR->vExactNodes )) { + pObj = Vec_PtrPop( pManMR->vExactNodes ); + + if ( Vec_PtrSize( FTIMEEDGES(pObj) )) { + pArray = Vec_PtrReleaseArray( FTIMEEDGES(pObj) ); + ABC_FREE( pArray ); + } + } + + Vec_PtrFree(pManMR->vExactNodes); + ABC_FREE( pManMR->vTimeEdges ); +} + + +/**Function************************************************************* + + Synopsis [DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_FlowRetime_Dfs_forw( Abc_Obj_t * pObj, Vec_Ptr_t *vNodes ) { + Abc_Obj_t *pNext; + int i; + + if (Abc_ObjIsLatch(pObj)) return; + + Abc_NodeSetTravIdCurrent( pObj ); + + Abc_ObjForEachFanout( pObj, pNext, i ) + if (!Abc_NodeIsTravIdCurrent( pNext )) + Abc_FlowRetime_Dfs_forw( pNext, vNodes ); + + Vec_PtrPush( vNodes, pObj ); +} + + +void Abc_FlowRetime_Dfs_back( Abc_Obj_t * pObj, Vec_Ptr_t *vNodes ) { + Abc_Obj_t *pNext; + int i; + + if (Abc_ObjIsLatch(pObj)) return; + + Abc_NodeSetTravIdCurrent( pObj ); + + Abc_ObjForEachFanin( pObj, pNext, i ) + if (!Abc_NodeIsTravIdCurrent( pNext )) + Abc_FlowRetime_Dfs_back( pNext, vNodes ); + + Vec_PtrPush( vNodes, pObj ); +} + + +/**Function************************************************************* + + Synopsis [Main timing-constrained routine.] + + Description [Refines constraints that are limiting area improvement. + These are identified by computing + the min-cuts both with and without the conservative + constraints: these two situation represent an + over- and under-constrained version of the timing.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_FlowRetime_RefineConstraints( ) { + Abc_Ntk_t *pNtk = pManMR->pNtk; + int i, flow, count = 0; + Abc_Obj_t *pObj; + int maxTighten = 99999; + + vprintf("\t\tsubiter %d : constraints = {cons, exact} = %d, %d\n", + pManMR->subIteration, pManMR->nConservConstraints, pManMR->nExactConstraints); + + // 1. overconstrained + pManMR->constraintMask = BLOCK | CONSERVATIVE; + vprintf("\t\trefinement: over "); + fflush(stdout); + flow = Abc_FlowRetime_PushFlows( pNtk, 0 ); + vprintf("= %d ", flow); + + // remember nodes + if (pManMR->fIsForward) { + Abc_NtkForEachObj( pNtk, pObj, i ) + if (!FTEST(pObj, VISITED_R)) + pObj->fMarkC = 1; + } else { + Abc_NtkForEachObj( pNtk, pObj, i ) + if (!FTEST(pObj, VISITED_E)) + pObj->fMarkC = 1; + } + + if (pManMR->fConservTimingOnly) { + vprintf(" done\n"); + return 0; + } + + // 2. underconstrained + pManMR->constraintMask = BLOCK; + Abc_FlowRetime_ClearFlows( 0 ); + vprintf("under = "); + fflush(stdout); + flow = Abc_FlowRetime_PushFlows( pNtk, 0 ); + vprintf("%d refined nodes = ", flow); + fflush(stdout); + + // find area-limiting constraints + if (pManMR->fIsForward) { + Abc_NtkForEachObj( pNtk, pObj, i ) { + if (pObj->fMarkC && + FTEST(pObj, VISITED_R) && + FTEST(pObj, CONSERVATIVE) && + count < maxTighten) { + count++; + Abc_FlowRetime_ConstrainExact( pObj ); + } + pObj->fMarkC = 0; + } + } else { + Abc_NtkForEachObj( pNtk, pObj, i ) { + if (pObj->fMarkC && + FTEST(pObj, VISITED_E) && + FTEST(pObj, CONSERVATIVE) && + count < maxTighten) { + count++; + Abc_FlowRetime_ConstrainExact( pObj ); + } + pObj->fMarkC = 0; + } + } + + vprintf("%d\n", count); + + return (count > 0); +} + + +ABC_NAMESPACE_IMPL_END + |