| /**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 | |