| /**CFile**************************************************************** |
| |
| FileName [fretInit.c] |
| |
| SystemName [ABC: Logic synthesis and verification system.] |
| |
| PackageName [Flow-based retiming package.] |
| |
| Synopsis [Initialization for retiming package.] |
| |
| Author [Aaron Hurst] |
| |
| Affiliation [UC Berkeley] |
| |
| Date [Ver. 1.0. Started - January 1, 2008.] |
| |
| Revision [$Id: fretInit.c,v 1.00 2008/01/01 00:00:00 ahurst Exp $] |
| |
| ***********************************************************************/ |
| |
| #include "fretime.h" |
| |
| #include "base/io/ioAbc.h" |
| #include "map/mio/mio.h" |
| #include "aig/hop/hop.h" |
| |
| #ifdef ABC_USE_CUDD |
| #include "bdd/cudd/cuddInt.h" |
| #endif |
| |
| ABC_NAMESPACE_IMPL_START |
| |
| |
| #undef DEBUG_PRINT_INIT_NTK |
| |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// FUNCTION PROTOTYPES /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| static void Abc_FlowRetime_UpdateForwardInit_rec( Abc_Obj_t * pObj ); |
| static void Abc_FlowRetime_VerifyBackwardInit( Abc_Ntk_t * pNtk ); |
| static void Abc_FlowRetime_VerifyBackwardInit_rec( Abc_Obj_t * pObj ); |
| static Abc_Obj_t* Abc_FlowRetime_UpdateBackwardInit_rec( Abc_Obj_t *pOrigObj ); |
| |
| static void Abc_FlowRetime_SimulateNode( Abc_Obj_t * pObj ); |
| static void Abc_FlowRetime_SimulateSop( Abc_Obj_t * pObj, char *pSop ); |
| |
| static void Abc_FlowRetime_SetInitToOrig( Abc_Obj_t *pInit, Abc_Obj_t *pOrig ); |
| static void Abc_FlowRetime_GetInitToOrig( Abc_Obj_t *pInit, Abc_Obj_t **pOrig, int *lag ); |
| static void Abc_FlowRetime_ClearInitToOrig( Abc_Obj_t *pInit ); |
| |
| extern void * Abc_FrameReadLibGen(); |
| |
| extern void Abc_NtkMarkCone_rec( Abc_Obj_t * pObj, int fForward ); |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// FUNCTION DEFINITIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [Updates initial state information.] |
| |
| Description [Assumes latch boxes in original position, latches in |
| new positions.] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void |
| Abc_FlowRetime_InitState( Abc_Ntk_t * pNtk ) { |
| |
| if (!pManMR->fComputeInitState) return; |
| |
| if (pManMR->fIsForward) |
| Abc_FlowRetime_UpdateForwardInit( pNtk ); |
| else { |
| Abc_FlowRetime_UpdateBackwardInit( pNtk ); |
| } |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Prints initial state information.] |
| |
| Description [Prints distribution of 0,1,and X initial states.] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| static inline int |
| Abc_FlowRetime_ObjFirstNonLatchBox( Abc_Obj_t * pOrigObj, Abc_Obj_t ** pResult ) { |
| int lag = 0; |
| Abc_Ntk_t *pNtk; |
| *pResult = pOrigObj; |
| pNtk = Abc_ObjNtk( pOrigObj ); |
| |
| Abc_NtkIncrementTravId( pNtk ); |
| |
| while( Abc_ObjIsBo(*pResult) || Abc_ObjIsLatch(*pResult) || Abc_ObjIsBi(*pResult) ) { |
| assert(Abc_ObjFaninNum(*pResult)); |
| *pResult = Abc_ObjFanin0(*pResult); |
| |
| if (Abc_NodeIsTravIdCurrent(*pResult)) |
| return -1; |
| Abc_NodeSetTravIdCurrent(*pResult); |
| |
| if (Abc_ObjIsLatch(*pResult)) ++lag; |
| } |
| |
| return lag; |
| } |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [Prints initial state information.] |
| |
| Description [Prints distribution of 0,1,and X initial states.] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void |
| Abc_FlowRetime_PrintInitStateInfo( Abc_Ntk_t * pNtk ) { |
| int i, n0=0, n1=0, nDC=0, nOther=0; |
| Abc_Obj_t *pLatch; |
| |
| Abc_NtkForEachLatch( pNtk, pLatch, i ) { |
| if (Abc_LatchIsInit0(pLatch)) n0++; |
| else if (Abc_LatchIsInit1(pLatch)) n1++; |
| else if (Abc_LatchIsInitDc(pLatch)) nDC++; |
| else nOther++; |
| } |
| |
| printf("\tinitial states {0,1,x} = {%d, %d, %d}", n0, n1, nDC); |
| if (nOther) |
| printf(" + %d UNKNOWN", nOther); |
| printf("\n"); |
| } |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [Computes initial state after forward retiming.] |
| |
| Description [Assumes box outputs in old positions stored w/ init values. |
| Uses three-value simulation to preserve don't cares.] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Abc_FlowRetime_UpdateForwardInit( Abc_Ntk_t * pNtk ) { |
| Abc_Obj_t *pObj, *pFanin; |
| int i; |
| |
| vprintf("\t\tupdating init state\n"); |
| |
| Abc_NtkIncrementTravId( pNtk ); |
| |
| Abc_NtkForEachLatch( pNtk, pObj, i ) { |
| pFanin = Abc_ObjFanin0(pObj); |
| Abc_FlowRetime_UpdateForwardInit_rec( pFanin ); |
| |
| if (FTEST(pFanin, INIT_0)) |
| Abc_LatchSetInit0( pObj ); |
| else if (FTEST(pFanin, INIT_1)) |
| Abc_LatchSetInit1( pObj ); |
| else |
| Abc_LatchSetInitDc( pObj ); |
| } |
| } |
| |
| void Abc_FlowRetime_UpdateForwardInit_rec( Abc_Obj_t * pObj ) { |
| Abc_Obj_t *pNext; |
| int i; |
| |
| assert(!Abc_ObjIsPi(pObj)); // should never reach the inputs |
| |
| if (Abc_ObjIsBo(pObj)) return; |
| |
| // visited? |
| if (Abc_NodeIsTravIdCurrent(pObj)) return; |
| Abc_NodeSetTravIdCurrent(pObj); |
| |
| Abc_ObjForEachFanin( pObj, pNext, i ) { |
| Abc_FlowRetime_UpdateForwardInit_rec( pNext ); |
| } |
| |
| Abc_FlowRetime_SimulateNode( pObj ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Recursively evaluates HOP netlist.] |
| |
| Description [Exponential. There aren't enough flags on a HOP node.] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| static void Abc_FlowRetime_EvalHop_rec( Hop_Man_t *pHop, Hop_Obj_t *pObj, int *f, int *dc ) { |
| int f1, dc1, f2, dc2; |
| Hop_Obj_t *pReg = Hop_Regular(pObj); |
| |
| // const 0 |
| if (Hop_ObjIsConst1(pReg)) { |
| *f = 1; |
| *f ^= (pReg == pObj ? 1 : 0); |
| *dc = 0; |
| return; |
| } |
| |
| // PI |
| if (Hop_ObjIsPi(pReg)) { |
| *f = pReg->fMarkA; |
| *f ^= (pReg == pObj ? 1 : 0); |
| *dc = pReg->fMarkB; |
| return; |
| } |
| |
| // PO |
| if (Hop_ObjIsPo(pReg)) { |
| assert( pReg == pObj ); |
| Abc_FlowRetime_EvalHop_rec(pHop, Hop_ObjChild0(pReg), f, dc); |
| return; |
| } |
| |
| // AND |
| if (Hop_ObjIsAnd(pReg)) { |
| Abc_FlowRetime_EvalHop_rec(pHop, Hop_ObjChild0(pReg), &f1, &dc1); |
| Abc_FlowRetime_EvalHop_rec(pHop, Hop_ObjChild1(pReg), &f2, &dc2); |
| |
| *dc = (dc1 & f2) | (dc2 & f1) | (dc1 & dc2); |
| *f = f1 & f2; |
| *f ^= (pReg == pObj ? 1 : 0); |
| return; |
| } |
| |
| assert(0); |
| } |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [Sets initial value flags.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| static inline void Abc_FlowRetime_SetInitValue( Abc_Obj_t * pObj, |
| int val, int dc ) { |
| |
| // store init value |
| FUNSET(pObj, INIT_CARE); |
| if (!dc){ |
| if (val) { |
| FSET(pObj, INIT_1); |
| } else { |
| FSET(pObj, INIT_0); |
| } |
| } |
| } |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [Propogates initial state through a logic node.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Abc_FlowRetime_SimulateNode( Abc_Obj_t * pObj ) { |
| Abc_Ntk_t *pNtk = Abc_ObjNtk(pObj); |
| Abc_Obj_t * pFanin; |
| int i, rAnd, rVar, dcAnd, dcVar; |
| #ifdef ABC_USE_CUDD |
| DdManager * dd = (DdManager*)pNtk->pManFunc; |
| DdNode *pBdd = (DdNode*)pObj->pData, *pVar; |
| #endif |
| Hop_Man_t *pHop = (Hop_Man_t*)pNtk->pManFunc; |
| |
| assert(!Abc_ObjIsLatch(pObj)); |
| assert(Abc_ObjRegular(pObj)); |
| |
| // (i) constant nodes |
| if (Abc_NtkIsStrash(pNtk) && Abc_AigNodeIsConst(pObj)) { |
| Abc_FlowRetime_SetInitValue(pObj, 1, 0); |
| return; |
| } |
| if (!Abc_NtkIsStrash( pNtk ) && Abc_ObjIsNode(pObj)) { |
| if (Abc_NodeIsConst0(pObj)) { |
| Abc_FlowRetime_SetInitValue(pObj, 0, 0); |
| return; |
| } else if (Abc_NodeIsConst1(pObj)) { |
| Abc_FlowRetime_SetInitValue(pObj, 1, 0); |
| return; |
| } |
| } |
| |
| // (ii) terminal nodes |
| if (!Abc_ObjIsNode(pObj)) { |
| pFanin = Abc_ObjFanin0(pObj); |
| |
| Abc_FlowRetime_SetInitValue(pObj, |
| (FTEST(pFanin, INIT_1) ? 1 : 0) ^ pObj->fCompl0, |
| !FTEST(pFanin, INIT_CARE)); |
| return; |
| } |
| |
| // (iii) logic nodes |
| |
| // ------ SOP network |
| if ( Abc_NtkHasSop( pNtk )) { |
| Abc_FlowRetime_SimulateSop( pObj, (char *)Abc_ObjData(pObj) ); |
| return; |
| } |
| #ifdef ABC_USE_CUDD |
| // ------ BDD network |
| else if ( Abc_NtkHasBdd( pNtk )) { |
| assert(dd); |
| assert(pBdd); |
| |
| // cofactor for 0,1 inputs |
| // do nothing for X values |
| Abc_ObjForEachFanin(pObj, pFanin, i) { |
| pVar = Cudd_bddIthVar( dd, i ); |
| if (FTEST(pFanin, INIT_CARE)) { |
| if (FTEST(pFanin, INIT_0)) |
| pBdd = Cudd_Cofactor( dd, pBdd, Cudd_Not(pVar) ); |
| else |
| pBdd = Cudd_Cofactor( dd, pBdd, pVar ); |
| } |
| } |
| |
| // if function has not been reduced to |
| // a constant, propagate an X |
| rVar = (pBdd == Cudd_ReadOne(dd)); |
| dcVar = !Cudd_IsConstant(pBdd); |
| |
| Abc_FlowRetime_SetInitValue(pObj, rVar, dcVar); |
| return; |
| } |
| #endif // #ifdef ABC_USE_CUDD |
| |
| // ------ AIG logic network |
| else if ( Abc_NtkHasAig( pNtk ) && !Abc_NtkIsStrash( pNtk )) { |
| |
| assert(Abc_ObjIsNode(pObj)); |
| assert(pObj->pData); |
| assert(Abc_ObjFaninNum(pObj) <= Hop_ManPiNum(pHop) ); |
| |
| // set vals at inputs |
| Abc_ObjForEachFanin(pObj, pFanin, i) { |
| Hop_ManPi(pHop, i)->fMarkA = FTEST(pFanin, INIT_1)?1:0; |
| Hop_ManPi(pHop, i)->fMarkB = FTEST(pFanin, INIT_CARE)?1:0; |
| } |
| |
| Abc_FlowRetime_EvalHop_rec( pHop, (Hop_Obj_t*)pObj->pData, &rVar, &dcVar ); |
| |
| Abc_FlowRetime_SetInitValue(pObj, rVar, dcVar); |
| |
| // clear flags |
| Abc_ObjForEachFanin(pObj, pFanin, i) { |
| Hop_ManPi(pHop, i)->fMarkA = 0; |
| Hop_ManPi(pHop, i)->fMarkB = 0; |
| } |
| |
| return; |
| } |
| |
| // ------ strashed network |
| else if ( Abc_NtkIsStrash( pNtk )) { |
| |
| assert(Abc_ObjType(pObj) == ABC_OBJ_NODE); |
| dcAnd = 0, rAnd = 1; |
| |
| pFanin = Abc_ObjFanin0(pObj); |
| dcAnd |= FTEST(pFanin, INIT_CARE) ? 0 : 1; |
| rVar = FTEST(pFanin, INIT_0) ? 0 : 1; |
| if (pObj->fCompl0) rVar ^= 1; // complimented? |
| rAnd &= rVar; |
| |
| pFanin = Abc_ObjFanin1(pObj); |
| dcAnd |= FTEST(pFanin, INIT_CARE) ? 0 : 1; |
| rVar = FTEST(pFanin, INIT_0) ? 0 : 1; |
| if (pObj->fCompl1) rVar ^= 1; // complimented? |
| rAnd &= rVar; |
| |
| if (!rAnd) dcAnd = 0; /* controlling value */ |
| |
| Abc_FlowRetime_SetInitValue(pObj, rAnd, dcAnd); |
| return; |
| } |
| |
| // ------ MAPPED network |
| else if ( Abc_NtkHasMapping( pNtk )) { |
| Abc_FlowRetime_SimulateSop( pObj, (char *)Mio_GateReadSop((Mio_Gate_t*)pObj->pData) ); |
| return; |
| } |
| |
| assert(0); |
| } |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [Propogates initial state through a SOP node.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Abc_FlowRetime_SimulateSop( Abc_Obj_t * pObj, char *pSop ) { |
| Abc_Obj_t * pFanin; |
| char *pCube; |
| int i, j, rAnd, rOr, rVar, dcAnd, dcOr, v; |
| |
| assert( pSop && !Abc_SopIsExorType(pSop) ); |
| |
| rOr = 0, dcOr = 0; |
| |
| i = Abc_SopGetVarNum(pSop); |
| Abc_SopForEachCube( pSop, i, pCube ) { |
| rAnd = 1, dcAnd = 0; |
| Abc_CubeForEachVar( pCube, v, j ) { |
| pFanin = Abc_ObjFanin(pObj, j); |
| if ( v == '0' ) |
| rVar = FTEST(pFanin, INIT_0) ? 1 : 0; |
| else if ( v == '1' ) |
| rVar = FTEST(pFanin, INIT_1) ? 1 : 0; |
| else |
| continue; |
| |
| if (FTEST(pFanin, INIT_CARE)) |
| rAnd &= rVar; |
| else |
| dcAnd = 1; |
| } |
| if (!rAnd) dcAnd = 0; /* controlling value */ |
| if (dcAnd) |
| dcOr = 1; |
| else |
| rOr |= rAnd; |
| } |
| if (rOr) dcOr = 0; /* controlling value */ |
| |
| // complement the result if necessary |
| if ( !Abc_SopGetPhase(pSop) ) |
| rOr ^= 1; |
| |
| Abc_FlowRetime_SetInitValue(pObj, rOr, dcOr); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Sets up backward initial state computation.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Abc_FlowRetime_SetupBackwardInit( Abc_Ntk_t * pNtk ) { |
| Abc_Obj_t *pLatch, *pObj, *pPi; |
| int i; |
| Vec_Ptr_t *vObj = Vec_PtrAlloc(100); |
| |
| // create the network used for the initial state computation |
| if (Abc_NtkIsStrash(pNtk)) { |
| pManMR->pInitNtk = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_SOP, 1 ); |
| } else if (Abc_NtkHasMapping(pNtk)) |
| pManMR->pInitNtk = Abc_NtkAlloc( pNtk->ntkType, ABC_FUNC_SOP, 1 ); |
| else |
| pManMR->pInitNtk = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 ); |
| |
| // mitre inputs |
| Abc_NtkForEachLatch( pNtk, pLatch, i ) { |
| // map latch to initial state network |
| pPi = Abc_NtkCreatePi( pManMR->pInitNtk ); |
| |
| // DEBUG |
| // printf("setup : mapping latch %d to PI %d\n", pLatch->Id, pPi->Id); |
| |
| // has initial state requirement? |
| if (Abc_LatchIsInit0(pLatch)) { |
| pObj = Abc_NtkCreateNodeInv( pManMR->pInitNtk, pPi ); |
| Vec_PtrPush(vObj, pObj); |
| } |
| else if (Abc_LatchIsInit1(pLatch)) { |
| Vec_PtrPush(vObj, pPi); |
| } |
| |
| Abc_ObjSetData( pLatch, pPi ); // if not verifying init state |
| // FDATA(pLatch)->pInitObj = pPi; // if verifying init state |
| } |
| |
| // are there any nodes not DC? |
| if (!Vec_PtrSize(vObj)) { |
| pManMR->fSolutionIsDc = 1; |
| return; |
| } else |
| pManMR->fSolutionIsDc = 0; |
| |
| // mitre output |
| |
| // create n-input AND gate |
| pObj = Abc_NtkCreateNodeAnd( pManMR->pInitNtk, vObj ); |
| |
| Abc_ObjAddFanin( Abc_NtkCreatePo( pManMR->pInitNtk ), pObj ); |
| |
| Vec_PtrFree( vObj ); |
| } |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [Solves backward initial state computation.] |
| |
| Description [] |
| |
| SideEffects [Sets object copies in init ntk.] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Abc_FlowRetime_SolveBackwardInit( Abc_Ntk_t * pNtk ) { |
| int i; |
| Abc_Obj_t *pObj, *pInitObj; |
| Vec_Ptr_t *vDelete = Vec_PtrAlloc(0); |
| Abc_Ntk_t *pSatNtk; |
| int result; |
| |
| assert(pManMR->pInitNtk); |
| |
| // is the solution entirely DC's? |
| if (pManMR->fSolutionIsDc) { |
| Vec_PtrFree(vDelete); |
| Abc_NtkForEachLatch( pNtk, pObj, i ) Abc_LatchSetInitDc( pObj ); |
| vprintf("\tno init state computation: all-don't-care solution\n"); |
| return 1; |
| } |
| |
| // check that network is combinational |
| Abc_NtkForEachObj( pManMR->pInitNtk, pObj, i ) { |
| assert(!Abc_ObjIsLatch(pObj)); |
| assert(!Abc_ObjIsBo(pObj)); |
| assert(!Abc_ObjIsBi(pObj)); |
| } |
| |
| // delete superfluous nodes |
| while(Vec_PtrSize( vDelete )) { |
| pObj = (Abc_Obj_t *)Vec_PtrPop( vDelete ); |
| Abc_NtkDeleteObj( pObj ); |
| } |
| Vec_PtrFree(vDelete); |
| |
| // do some final cleanup on the network |
| Abc_NtkAddDummyPoNames(pManMR->pInitNtk); |
| Abc_NtkAddDummyPiNames(pManMR->pInitNtk); |
| if (Abc_NtkIsLogic(pManMR->pInitNtk)) |
| Abc_NtkCleanup(pManMR->pInitNtk, 0); |
| |
| #if defined(DEBUG_PRINT_INIT_NTK) |
| Abc_NtkLevelReverse( pManMR->pInitNtk ); |
| Abc_NtkForEachObj( pManMR->pInitNtk, pObj, i ) |
| if (Abc_ObjLevel( pObj ) < 2) |
| Abc_ObjPrint(stdout, pObj); |
| #endif |
| |
| vprintf("\tsolving for init state (%d nodes)... ", Abc_NtkObjNum(pManMR->pInitNtk)); |
| fflush(stdout); |
| #ifdef ABC_USE_CUDD |
| // convert SOPs to BDD |
| if (Abc_NtkHasSop(pManMR->pInitNtk)) |
| Abc_NtkSopToBdd( pManMR->pInitNtk ); |
| // convert AIGs to BDD |
| if (Abc_NtkHasAig(pManMR->pInitNtk)) |
| Abc_NtkAigToBdd( pManMR->pInitNtk ); |
| #else |
| // convert SOPs to AIG |
| if (Abc_NtkHasSop(pManMR->pInitNtk)) |
| Abc_NtkSopToAig( pManMR->pInitNtk ); |
| #endif |
| pSatNtk = pManMR->pInitNtk; |
| |
| // solve |
| result = Abc_NtkMiterSat( pSatNtk, (ABC_INT64_T)500000, (ABC_INT64_T)50000000, 0, NULL, NULL ); |
| |
| if (!result) { |
| vprintf("SUCCESS\n"); |
| } else { |
| vprintf("FAILURE\n"); |
| return 0; |
| } |
| |
| // clear initial values, associate PIs to latches |
| Abc_NtkForEachPi( pManMR->pInitNtk, pInitObj, i ) Abc_ObjSetCopy( pInitObj, NULL ); |
| Abc_NtkForEachLatch( pNtk, pObj, i ) { |
| pInitObj = (Abc_Obj_t*)Abc_ObjData( pObj ); |
| assert( Abc_ObjIsPi( pInitObj )); |
| Abc_ObjSetCopy( pInitObj, pObj ); |
| Abc_LatchSetInitNone( pObj ); |
| |
| // DEBUG |
| // printf("solve : getting latch %d from PI %d\n", pObj->Id, pInitObj->Id); |
| } |
| |
| // copy solution from PIs to latches |
| assert(pManMR->pInitNtk->pModel); |
| Abc_NtkForEachPi( pManMR->pInitNtk, pInitObj, i ) { |
| if ((pObj = Abc_ObjCopy( pInitObj ))) { |
| if ( pManMR->pInitNtk->pModel[i] ) |
| Abc_LatchSetInit1( pObj ); |
| else |
| Abc_LatchSetInit0( pObj ); |
| } |
| } |
| |
| #if defined(DEBUG_CHECK) |
| // check that all latches have initial state |
| Abc_NtkForEachLatch( pNtk, pObj, i ) assert( !Abc_LatchIsInitNone( pObj ) ); |
| #endif |
| |
| return 1; |
| } |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [Updates backward initial state computation problem.] |
| |
| Description [Assumes box outputs in old positions stored w/ init values.] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Abc_FlowRetime_UpdateBackwardInit( Abc_Ntk_t * pNtk ) { |
| Abc_Obj_t *pOrigObj, *pInitObj; |
| Vec_Ptr_t *vBo = Vec_PtrAlloc(100); |
| Vec_Ptr_t *vPi = Vec_PtrAlloc(100); |
| Abc_Ntk_t *pInitNtk = pManMR-> pInitNtk; |
| Abc_Obj_t *pBuf; |
| int i; |
| |
| // remove PIs from network (from BOs) |
| Abc_NtkForEachObj( pNtk, pOrigObj, i ) |
| if (Abc_ObjIsBo(pOrigObj)) { |
| pInitObj = FDATA(pOrigObj)->pInitObj; |
| assert(Abc_ObjIsPi(pInitObj)); |
| |
| // DEBUG |
| // printf("update : freeing PI %d\n", pInitObj->Id); |
| |
| // create a buffer instead |
| pBuf = Abc_NtkCreateNodeBuf( pInitNtk, NULL ); |
| Abc_FlowRetime_ClearInitToOrig( pBuf ); |
| |
| Abc_ObjBetterTransferFanout( pInitObj, pBuf, 0 ); |
| FDATA(pOrigObj)->pInitObj = pBuf; |
| pOrigObj->fMarkA = 1; |
| |
| Vec_PtrPush(vBo, pOrigObj); |
| Vec_PtrPush(vPi, pInitObj); |
| } |
| |
| // check that PIs are all free |
| Abc_NtkForEachPi( pInitNtk, pInitObj, i) { |
| assert( Abc_ObjFanoutNum( pInitObj ) == 0); |
| } |
| |
| // add PIs to to latches |
| Abc_NtkForEachLatch( pNtk, pOrigObj, i ) { |
| assert(Vec_PtrSize(vPi) > 0); |
| pInitObj = (Abc_Obj_t*)Vec_PtrPop(vPi); |
| |
| // DEBUG |
| // printf("update : mapping latch %d to PI %d\n", pOrigObj->Id, pInitObj->Id); |
| |
| pOrigObj->fMarkA = pOrigObj->fMarkB = 1; |
| FDATA(pOrigObj)->pInitObj = pInitObj; |
| Abc_ObjSetData(pOrigObj, pInitObj); |
| } |
| |
| // recursively build init network |
| Vec_PtrForEachEntry( Abc_Obj_t *, vBo, pOrigObj, i ) |
| Abc_FlowRetime_UpdateBackwardInit_rec( pOrigObj ); |
| |
| // clear flags |
| Abc_NtkForEachObj( pNtk, pOrigObj, i ) |
| pOrigObj->fMarkA = pOrigObj->fMarkB = 0; |
| |
| // deallocate |
| Vec_PtrFree( vBo ); |
| Vec_PtrFree( vPi ); |
| } |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [Creates a corresponding node in the init state network] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Abc_Obj_t *Abc_FlowRetime_CopyNodeToInitNtk( Abc_Obj_t *pOrigObj ) { |
| Abc_Ntk_t *pNtk = pManMR->pNtk; |
| Abc_Ntk_t *pInitNtk = pManMR->pInitNtk; |
| Abc_Obj_t *pInitObj; |
| void *pData; |
| int fCompl[2]; |
| |
| assert(pOrigObj); |
| |
| // what we do depends on the ntk types of original / init networks... |
| |
| // (0) convert BI/BO nodes to buffers |
| if (Abc_ObjIsBi( pOrigObj ) || Abc_ObjIsBo( pOrigObj ) ) { |
| pInitObj = Abc_NtkCreateNodeBuf( pInitNtk, NULL ); |
| Abc_FlowRetime_ClearInitToOrig( pInitObj ); |
| return pInitObj; |
| } |
| |
| // (i) strash node -> SOP node |
| if (Abc_NtkIsStrash( pNtk )) { |
| |
| if (Abc_AigNodeIsConst( pOrigObj )) { |
| return Abc_NtkCreateNodeConst1( pInitNtk ); |
| } |
| if (!Abc_ObjIsNode( pOrigObj )) { |
| assert(Abc_ObjFaninNum(pOrigObj) == 1); |
| pInitObj = Abc_NtkCreateNodeBuf( pInitNtk, NULL ); |
| Abc_FlowRetime_ClearInitToOrig( pInitObj ); |
| return pInitObj; |
| } |
| |
| assert( Abc_ObjIsNode(pOrigObj) ); |
| pInitObj = Abc_NtkCreateObj( pInitNtk, ABC_OBJ_NODE ); |
| |
| fCompl[0] = pOrigObj->fCompl0 ? 1 : 0; |
| fCompl[1] = pOrigObj->fCompl1 ? 1 : 0; |
| |
| pData = Abc_SopCreateAnd( (Mem_Flex_t *)pInitNtk->pManFunc, 2, fCompl ); |
| assert(pData); |
| pInitObj->pData = Abc_SopRegister( (Mem_Flex_t *)pInitNtk->pManFunc, (const char*)pData ); |
| } |
| |
| // (ii) mapped node -> SOP node |
| else if (Abc_NtkHasMapping( pNtk )) { |
| if (!pOrigObj->pData) { |
| // assume terminal... |
| assert(Abc_ObjFaninNum(pOrigObj) == 1); |
| |
| pInitObj = Abc_NtkCreateNodeBuf( pInitNtk, NULL ); |
| Abc_FlowRetime_ClearInitToOrig( pInitObj ); |
| return pInitObj; |
| } |
| |
| pInitObj = Abc_NtkCreateObj( pInitNtk, (Abc_ObjType_t)Abc_ObjType(pOrigObj) ); |
| pData = Mio_GateReadSop((Mio_Gate_t*)pOrigObj->pData); |
| assert( Abc_SopGetVarNum((char*)pData) == Abc_ObjFaninNum(pOrigObj) ); |
| |
| pInitObj->pData = Abc_SopRegister( (Mem_Flex_t *)pInitNtk->pManFunc, (const char*)pData ); |
| } |
| |
| // (iii) otherwise, duplicate obj |
| else { |
| pInitObj = Abc_NtkDupObj( pInitNtk, pOrigObj, 0 ); |
| |
| // copy phase |
| pInitObj->fPhase = pOrigObj->fPhase; |
| } |
| |
| assert(pInitObj); |
| return pInitObj; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Updates backward initial state computation problem.] |
| |
| Description [Creates a duplicate node in the initial state network |
| corresponding to a node in the original circuit. If |
| fRecurse is set, the procedure recurses on and connects |
| the new node to its fan-ins. A latch in the original |
| circuit corresponds to a PI in the initial state network. |
| An existing PI may be supplied by pUseThisPi, and if the |
| node is a latch, it will be used; otherwise the PI is |
| saved in the list vOtherPis and subsequently used for |
| another latch.] |
| |
| SideEffects [Nodes that have a corresponding initial state node |
| are marked with fMarkA. Nodes that have been fully |
| connected in the initial state network are marked with |
| fMarkB.] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Abc_Obj_t* Abc_FlowRetime_UpdateBackwardInit_rec( Abc_Obj_t *pOrigObj) { |
| Abc_Obj_t *pOrigFanin, *pInitFanin, *pInitObj; |
| int i; |
| |
| assert(pOrigObj); |
| |
| // should never reach primary IOs |
| assert(!Abc_ObjIsPi(pOrigObj)); |
| assert(!Abc_ObjIsPo(pOrigObj)); |
| |
| // skip bias nodes |
| if (FTEST(pOrigObj, BIAS_NODE)) |
| return NULL; |
| |
| // does an init node already exist? |
| if(!pOrigObj->fMarkA) { |
| |
| pInitObj = Abc_FlowRetime_CopyNodeToInitNtk( pOrigObj ); |
| |
| Abc_FlowRetime_SetInitToOrig( pInitObj, pOrigObj ); |
| FDATA(pOrigObj)->pInitObj = pInitObj; |
| |
| pOrigObj->fMarkA = 1; |
| } else { |
| pInitObj = FDATA(pOrigObj)->pInitObj; |
| } |
| assert(pInitObj); |
| |
| // have we already connected this object? |
| if (!pOrigObj->fMarkB) { |
| |
| // create and/or connect fanins |
| Abc_ObjForEachFanin( pOrigObj, pOrigFanin, i ) { |
| // should not reach BOs (i.e. the start of the next frame) |
| // the new latch bounday should lie before it |
| assert(!Abc_ObjIsBo( pOrigFanin )); |
| pInitFanin = Abc_FlowRetime_UpdateBackwardInit_rec( pOrigFanin ); |
| Abc_ObjAddFanin( pInitObj, pInitFanin ); |
| } |
| |
| pOrigObj->fMarkB = 1; |
| } |
| |
| return pInitObj; |
| } |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [Verifies backward init state computation.] |
| |
| Description [This procedure requires the BOs to store the original |
| latch values and the latches to store the new values: |
| both in the INIT_0 and INIT_1 flags in the Flow_Data |
| structure. (This is not currently the case in the rest |
| of the code.) Also, can not verify backward state |
| computations that span multiple combinational frames.] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Abc_FlowRetime_VerifyBackwardInit( Abc_Ntk_t * pNtk ) { |
| Abc_Obj_t *pObj, *pFanin; |
| int i; |
| |
| vprintf("\t\tupdating init state\n"); |
| |
| Abc_NtkIncrementTravId( pNtk ); |
| |
| Abc_NtkForEachObj( pNtk, pObj, i ) |
| if (Abc_ObjIsBo( pObj )) { |
| pFanin = Abc_ObjFanin0(pObj); |
| Abc_FlowRetime_VerifyBackwardInit_rec( pFanin ); |
| |
| if (FTEST(pObj, INIT_CARE)) { |
| if(FTEST(pObj, INIT_CARE) != FTEST(pFanin, INIT_CARE)) { |
| printf("ERROR: expected val=%d care=%d and got val=%d care=%d\n", |
| FTEST(pObj, INIT_1)?1:0, FTEST(pObj, INIT_CARE)?1:0, |
| FTEST(pFanin, INIT_1)?1:0, FTEST(pFanin, INIT_CARE)?1:0 ); |
| |
| } |
| } |
| } |
| } |
| |
| void Abc_FlowRetime_VerifyBackwardInit_rec( Abc_Obj_t * pObj ) { |
| Abc_Obj_t *pNext; |
| int i; |
| |
| assert(!Abc_ObjIsBo(pObj)); // should never reach the inputs |
| assert(!Abc_ObjIsPi(pObj)); // should never reach the inputs |
| |
| // visited? |
| if (Abc_NodeIsTravIdCurrent(pObj)) return; |
| Abc_NodeSetTravIdCurrent(pObj); |
| |
| if (Abc_ObjIsLatch(pObj)) { |
| FUNSET(pObj, INIT_CARE); |
| if (Abc_LatchIsInit0(pObj)) |
| FSET(pObj, INIT_0); |
| else if (Abc_LatchIsInit1(pObj)) |
| FSET(pObj, INIT_1); |
| return; |
| } |
| |
| Abc_ObjForEachFanin( pObj, pNext, i ) { |
| Abc_FlowRetime_VerifyBackwardInit_rec( pNext ); |
| } |
| |
| Abc_FlowRetime_SimulateNode( pObj ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Constrains backward retiming for initializability.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Abc_FlowRetime_PartialSat(Vec_Ptr_t *vNodes, int cut) { |
| Abc_Ntk_t *pPartNtk, *pInitNtk = pManMR->pInitNtk; |
| Abc_Obj_t *pObj, *pNext, *pPartObj, *pPartNext, *pPo; |
| int i, j, result; |
| |
| assert( Abc_NtkPoNum( pInitNtk ) == 1 ); |
| |
| pPartNtk = Abc_NtkAlloc( pInitNtk->ntkType, pInitNtk->ntkFunc, 0 ); |
| |
| // copy network |
| Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) { |
| pObj->Level = i; |
| assert(!Abc_ObjIsPo( pObj )); |
| |
| if (i < cut && !pObj->fMarkA) { |
| pPartObj = Abc_NtkCreatePi( pPartNtk ); |
| Abc_ObjSetCopy( pObj, pPartObj ); |
| } else { |
| // copy node |
| pPartObj = Abc_NtkDupObj( pPartNtk, pObj, 0 ); |
| // copy complementation |
| pPartObj->fPhase = pObj->fPhase; |
| |
| // connect fanins |
| Abc_ObjForEachFanin( pObj, pNext, j ) { |
| pPartNext = Abc_ObjCopy( pNext ); |
| assert(pPartNext); |
| Abc_ObjAddFanin( pPartObj, pPartNext ); |
| } |
| } |
| |
| assert(pObj->pCopy == pPartObj); |
| } |
| |
| // create PO |
| pPo = Abc_NtkCreatePo( pPartNtk ); |
| pNext = Abc_ObjFanin0( Abc_NtkPo( pInitNtk, 0 ) ); |
| pPartNext = Abc_ObjCopy( pNext ); |
| assert( pPartNext ); |
| Abc_ObjAddFanin( pPo, pPartNext ); |
| |
| // check network |
| #if defined(DEBUG_CHECK) |
| Abc_NtkAddDummyPoNames(pPartNtk); |
| Abc_NtkAddDummyPiNames(pPartNtk); |
| Abc_NtkCheck( pPartNtk ); |
| #endif |
| |
| result = Abc_NtkMiterSat( pPartNtk, (ABC_INT64_T)500000, (ABC_INT64_T)50000000, 0, NULL, NULL ); |
| |
| Abc_NtkDelete( pPartNtk ); |
| |
| return !result; |
| } |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [Constrains backward retiming for initializability.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Abc_FlowRetime_ConstrainInit( ) { |
| Vec_Ptr_t *vNodes; |
| int low, high, mid; |
| int i, n, lag; |
| Abc_Obj_t *pObj = NULL, *pOrigObj; |
| InitConstraint_t *pConstraint = ABC_ALLOC( InitConstraint_t, 1 ); |
| |
| memset( pConstraint, 0, sizeof(InitConstraint_t) ); |
| |
| assert(pManMR->pInitNtk); |
| |
| vprintf("\tsearch for initial state conflict...\n"); |
| |
| vNodes = Abc_NtkDfs(pManMR->pInitNtk, 0); |
| n = Vec_PtrSize(vNodes); |
| // also add PIs to vNodes |
| Abc_NtkForEachPi(pManMR->pInitNtk, pObj, i) |
| Vec_PtrPush(vNodes, pObj); |
| Vec_PtrReorder(vNodes, n); |
| |
| #if defined(DEBUG_CHECK) |
| assert(!Abc_FlowRetime_PartialSat( vNodes, 0 )); |
| #endif |
| |
| // grow initialization constraint |
| do { |
| vprintf("\t\t"); |
| |
| // find element to add to set... |
| low = 0, high = Vec_PtrSize(vNodes); |
| while (low != high-1) { |
| mid = (low + high) >> 1; |
| |
| if (!Abc_FlowRetime_PartialSat( vNodes, mid )) { |
| low = mid; |
| vprintf("-"); |
| } else { |
| high = mid; |
| vprintf("*"); |
| } |
| fflush(stdout); |
| } |
| |
| #if defined(DEBUG_CHECK) |
| assert(Abc_FlowRetime_PartialSat( vNodes, high )); |
| assert(!Abc_FlowRetime_PartialSat( vNodes, low )); |
| #endif |
| |
| // mark its TFO |
| pObj = (Abc_Obj_t*)Vec_PtrEntry( vNodes, low ); |
| Abc_NtkMarkCone_rec( pObj, 1 ); |
| vprintf(" conflict term = %d ", low); |
| |
| #if 0 |
| printf("init ------\n"); |
| Abc_ObjPrint(stdout, pObj); |
| printf("\n"); |
| Abc_ObjPrintNeighborhood( pObj, 1 ); |
| printf("------\n"); |
| #endif |
| |
| // add node to constraint |
| Abc_FlowRetime_GetInitToOrig( pObj, &pOrigObj, &lag ); |
| assert(pOrigObj); |
| vprintf(" <=> %d/%d\n", Abc_ObjId(pOrigObj), lag); |
| |
| #if 0 |
| printf("orig ------\n"); |
| Abc_ObjPrint(stdout, pOrigObj); |
| printf("\n"); |
| Abc_ObjPrintNeighborhood( pOrigObj, 1 ); |
| printf("------\n"); |
| #endif |
| Vec_IntPush( &pConstraint->vNodes, Abc_ObjId(pOrigObj) ); |
| Vec_IntPush( &pConstraint->vLags, lag ); |
| |
| } while (Abc_FlowRetime_PartialSat( vNodes, Vec_PtrSize(vNodes) )); |
| |
| pConstraint->pBiasNode = NULL; |
| |
| // add constraint |
| Vec_PtrPush( pManMR->vInitConstraints, pConstraint ); |
| |
| // clear marks |
| Abc_NtkForEachObj( pManMR->pInitNtk, pObj, i) |
| pObj->fMarkA = 0; |
| |
| // free |
| Vec_PtrFree( vNodes ); |
| } |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [Removes nodes to bias against uninitializable cuts.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Abc_FlowRetime_RemoveInitBias( ) { |
| // Abc_Ntk_t *pNtk = pManMR->pNtk; |
| Abc_Obj_t *pBiasNode; |
| InitConstraint_t *pConstraint; |
| int i; |
| |
| Vec_PtrForEachEntry( InitConstraint_t *, pManMR->vInitConstraints, pConstraint, i ) { |
| pBiasNode = pConstraint->pBiasNode; |
| pConstraint->pBiasNode = NULL; |
| |
| if (pBiasNode) |
| Abc_NtkDeleteObj(pBiasNode); |
| } |
| } |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [Connects the bias node to one of the constraint vertices.] |
| |
| Description [ACK! |
| Currently this is dumb dumb hack. |
| What should we do with biases that belong on BOs? These |
| move through the circuit. |
| Currently, the bias gets marked on the fan-in of BO |
| and the bias gets implemented on every BO fan-out of a |
| node.] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| static void Abc_FlowRetime_ConnectBiasNode(Abc_Obj_t *pBiasNode, Abc_Obj_t *pObj, int biasLag) { |
| Abc_Obj_t *pCur, *pNext; |
| int i; |
| int lag; |
| Vec_Ptr_t *vNodes = Vec_PtrAlloc(1); |
| Vec_Int_t *vLags = Vec_IntAlloc(1); |
| Abc_Ntk_t *pNtk = Abc_ObjNtk( pObj ); |
| |
| Vec_PtrPush( vNodes, pObj ); |
| Vec_IntPush( vLags, 0 ); |
| |
| Abc_NtkIncrementTravId( pNtk ); |
| |
| while (Vec_PtrSize( vNodes )) { |
| pCur = (Abc_Obj_t*)Vec_PtrPop( vNodes ); |
| lag = Vec_IntPop( vLags ); |
| |
| if (Abc_NodeIsTravIdCurrent( pCur )) continue; |
| Abc_NodeSetTravIdCurrent( pCur ); |
| |
| if (!Abc_ObjIsLatch(pCur) && |
| !Abc_ObjIsBo(pCur) && |
| Abc_FlowRetime_GetLag(pObj)+lag == biasLag ) { |
| |
| // printf("biasing : "); |
| // Abc_ObjPrint(stdout, pCur ); |
| #if 1 |
| FSET( pCur, BLOCK ); |
| #else |
| Abc_ObjAddFanin( pCur, pBiasNode ); |
| #endif |
| } |
| |
| Abc_ObjForEachFanout( pCur, pNext, i ) { |
| if (Abc_ObjIsBi(pNext) || |
| Abc_ObjIsLatch(pNext) || |
| Abc_ObjIsBo(pNext) || |
| Abc_ObjIsBo(pCur)) { |
| Vec_PtrPush( vNodes, pNext ); |
| Vec_IntPush( vLags, lag - Abc_ObjIsLatch(pNext) ? 1 : 0 ); |
| } |
| } |
| } |
| |
| Vec_PtrFree( vNodes ); |
| Vec_IntFree( vLags ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Adds nodes to bias against uninitializable cuts.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Abc_FlowRetime_AddInitBias( ) { |
| Abc_Ntk_t *pNtk = pManMR->pNtk; |
| Abc_Obj_t *pBiasNode, *pObj; |
| InitConstraint_t *pConstraint; |
| int i, j, id; |
| const int nConstraints = Vec_PtrSize( pManMR->vInitConstraints ); |
| |
| pManMR->pDataArray = ABC_REALLOC( Flow_Data_t, pManMR->pDataArray, pManMR->nNodes + (nConstraints*(pManMR->iteration+1)) ); |
| memset(pManMR->pDataArray + pManMR->nNodes, 0, sizeof(Flow_Data_t)*(nConstraints*(pManMR->iteration+1))); |
| |
| vprintf("\t\tcreating %d bias structures\n", nConstraints); |
| |
| Vec_PtrForEachEntry(InitConstraint_t*, pManMR->vInitConstraints, pConstraint, i ) { |
| if (pConstraint->pBiasNode) continue; |
| |
| // printf("\t\t\tbias %d...\n", i); |
| pBiasNode = Abc_NtkCreateBlackbox( pNtk ); |
| |
| Vec_IntForEachEntry( &pConstraint->vNodes, id, j ) { |
| pObj = Abc_NtkObj(pNtk, id); |
| Abc_FlowRetime_ConnectBiasNode(pBiasNode, pObj, Vec_IntEntry(&pConstraint->vLags, j)); |
| } |
| |
| // pConstraint->pBiasNode = pBiasNode; |
| } |
| } |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [Clears mapping from init node to original node.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Abc_FlowRetime_ClearInitToOrig( Abc_Obj_t *pInit ) |
| { |
| int id = Abc_ObjId( pInit ); |
| |
| // grow data structure if necessary |
| if (id >= pManMR->sizeInitToOrig) { |
| int oldSize = pManMR->sizeInitToOrig; |
| pManMR->sizeInitToOrig = 1.5*id + 10; |
| pManMR->pInitToOrig = (NodeLag_t*)realloc(pManMR->pInitToOrig, sizeof(NodeLag_t)*pManMR->sizeInitToOrig); |
| memset( &(pManMR->pInitToOrig[oldSize]), 0, sizeof(NodeLag_t)*(pManMR->sizeInitToOrig-oldSize) ); |
| } |
| assert( pManMR->pInitToOrig ); |
| |
| pManMR->pInitToOrig[id].id = -1; |
| } |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [Sets mapping from init node to original node.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Abc_FlowRetime_SetInitToOrig( Abc_Obj_t *pInit, Abc_Obj_t *pOrig) |
| { |
| int lag; |
| int id = Abc_ObjId( pInit ); |
| |
| // grow data structure if necessary |
| if (id >= pManMR->sizeInitToOrig) { |
| int oldSize = pManMR->sizeInitToOrig; |
| pManMR->sizeInitToOrig = 1.5*id + 10; |
| pManMR->pInitToOrig = (NodeLag_t*)realloc(pManMR->pInitToOrig, sizeof(NodeLag_t)*pManMR->sizeInitToOrig); |
| memset( &(pManMR->pInitToOrig[oldSize]), 0, sizeof(NodeLag_t)*(pManMR->sizeInitToOrig-oldSize) ); |
| } |
| assert( pManMR->pInitToOrig ); |
| |
| // ignore BI, BO, and latch nodes |
| if (Abc_ObjIsBo(pOrig) || Abc_ObjIsBi(pOrig) || Abc_ObjIsLatch(pOrig)) { |
| Abc_FlowRetime_ClearInitToOrig(pInit); |
| return; |
| } |
| |
| // move out of latch boxes |
| lag = Abc_FlowRetime_ObjFirstNonLatchBox(pOrig, &pOrig); |
| |
| pManMR->pInitToOrig[id].id = Abc_ObjId(pOrig); |
| pManMR->pInitToOrig[id].lag = Abc_FlowRetime_GetLag(pOrig) + lag; |
| } |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [Gets mapping from init node to original node.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Abc_FlowRetime_GetInitToOrig( Abc_Obj_t *pInit, Abc_Obj_t **pOrig, int *lag ) { |
| |
| int id = Abc_ObjId( pInit ); |
| int origId; |
| |
| assert(id < pManMR->sizeInitToOrig); |
| |
| origId = pManMR->pInitToOrig[id].id; |
| |
| if (origId < 0) { |
| assert(Abc_ObjFaninNum(pInit)); |
| Abc_FlowRetime_GetInitToOrig( Abc_ObjFanin0(pInit), pOrig, lag); |
| return; |
| } |
| |
| *pOrig = Abc_NtkObj(pManMR->pNtk, origId); |
| *lag = pManMR->pInitToOrig[id].lag; |
| } |
| ABC_NAMESPACE_IMPL_END |
| |