| /**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 = (Abc_Obj_t*)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((int)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((int)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 ((int)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((int)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((int)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 ((int)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) && |
| (int)pObj->Level < l ) |
| pObj->Level = l; |
| } |
| |
| if ( Abc_ObjIsBo(pObj) ) |
| pObj->fMarkA = 1; |
| |
| assert((int)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((int)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) && |
| (int)pObj->Level < l ) |
| pObj->Level = l; |
| } |
| |
| if ((int)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) && |
| (int)pObj->Level < l ) |
| pObj->Level = l; |
| } |
| |
| if ( Abc_ObjIsBo(pObj) ) { |
| pObj->fMarkA = 1; |
| } |
| |
| assert((int)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) && |
| (int)pObj->Level < l ) |
| pObj->Level = l; |
| } |
| |
| // constrained? |
| if ((int)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((int)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 ((int)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((int)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 ((int)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 = (Abc_Obj_t*)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 |
| |