/**CFile**************************************************************** FileName [ifSeq.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [FPGA mapping based on priority cuts.] Synopsis [Sequential mapping.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - November 21, 2006.] Revision [$Id: ifSeq.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $] ***********************************************************************/ #include "if.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// extern abctime s_MappingTime; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Prepares for sequential mapping by linking the latches.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void If_ManPrepareMappingSeq( If_Man_t * p ) { If_Obj_t * pObjLi, * pObjLo; int i; // link the latch outputs (CIs) directly to the drivers of latch inputs (COs) for ( i = 0; i < p->pPars->nLatchesCi; i++ ) { pObjLi = If_ManLi( p, i ); pObjLo = If_ManLo( p, i ); pObjLo->pFanin0 = If_ObjFanin0( pObjLi ); pObjLo->fCompl0 = If_ObjFaninC0( pObjLi ); } } /**Function************************************************************* Synopsis [Collects latches in the topological order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void If_ManCollectLatches_rec( If_Obj_t * pObj, Vec_Ptr_t * vLatches ) { if ( !If_ObjIsLatch(pObj) ) return; if ( pObj->fMark ) return; pObj->fMark = 1; If_ManCollectLatches_rec( pObj->pFanin0, vLatches ); Vec_PtrPush( vLatches, pObj ); } /**Function************************************************************* Synopsis [Collects latches in the topological order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * If_ManCollectLatches( If_Man_t * p ) { Vec_Ptr_t * vLatches; If_Obj_t * pObj; int i; // collect latches vLatches = Vec_PtrAlloc( p->pPars->nLatchesCi ); If_ManForEachLatchOutput( p, pObj, i ) If_ManCollectLatches_rec( pObj, vLatches ); // clean marks Vec_PtrForEachEntry( If_Obj_t *, vLatches, pObj, i ) pObj->fMark = 0; assert( Vec_PtrSize(vLatches) == p->pPars->nLatchesCi ); return vLatches; } /**Function************************************************************* Synopsis [Performs one pass of l-value computation over all nodes.] Description [Experimentally it was found that checking POs changes is not enough to detect the convergence of l-values in the network.] SideEffects [] SeeAlso [] ***********************************************************************/ int If_ManPerformMappingRoundSeq( If_Man_t * p, int nIter ) { If_Obj_t * pObj; int i; abctime clk = Abc_Clock(); int fVeryVerbose = 0; int fChange = 0; if ( nIter == 1 ) { // if some latches depend on PIs, update their values Vec_PtrForEachEntry( If_Obj_t *, p->vLatchOrder, pObj, i ) { If_ObjSetLValue( pObj, If_ObjLValue(If_ObjFanin0(pObj)) - p->Period ); If_ObjSetArrTime( pObj, If_ObjLValue(pObj) ); } } // map the internal nodes p->nCutsMerged = 0; If_ManForEachNode( p, pObj, i ) { If_ObjPerformMappingAnd( p, pObj, 0, 0, 0 ); if ( pObj->fRepr ) If_ObjPerformMappingChoice( p, pObj, 0, 0 ); } // postprocess the mapping //Abc_Print( 1, "Itereation %d: \n", nIter ); If_ManForEachNode( p, pObj, i ) { // update the LValues stored separately if ( If_ObjLValue(pObj) < If_ObjCutBest(pObj)->Delay - p->fEpsilon ) { If_ObjSetLValue( pObj, If_ObjCutBest(pObj)->Delay ); fChange = 1; } //Abc_Print( 1, "%d ", (int)If_ObjLValue(pObj) ); // reset the visit counters assert( pObj->nVisits == 0 ); pObj->nVisits = pObj->nVisitsCopy; } //Abc_Print( 1, "\n" ); // propagate LValues over the registers Vec_PtrForEachEntry( If_Obj_t *, p->vLatchOrder, pObj, i ) { If_ObjSetLValue( pObj, If_ObjLValue(If_ObjFanin0(pObj)) - p->Period ); If_ObjSetArrTime( pObj, If_ObjLValue(pObj) ); } // compute area and delay If_ManMarkMapping( p ); if ( fVeryVerbose ) { p->RequiredGlo = If_ManDelayMax( p, 1 ); // p->AreaGlo = If_ManScanMapping(p); Abc_Print( 1, "S%d: Fi = %6.2f. Del = %6.2f. Area = %8.2f. Cuts = %8d. ", nIter, (float)p->Period, p->RequiredGlo, p->AreaGlo, p->nCutsMerged ); Abc_PrintTime( 1, "T", Abc_Clock() - clk ); } return fChange; } /**Function************************************************************* Synopsis [Returns 1 if retiming with this clock period is feasible.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int If_ManBinarySearchPeriod( If_Man_t * p ) { If_Obj_t * pObj; int i, c, fConverged; // int fResetRefs = 0; p->nAttempts++; // reset initial LValues (PIs to 0; others to -inf) If_ManForEachObj( p, pObj, i ) { If_ObjSetLValue( pObj, (float)-IF_INFINITY ); If_ObjSetArrTime( pObj, (float)-IF_INFINITY ); // undo any previous mapping, except for CIs if ( If_ObjIsAnd(pObj) ) If_ObjCutBest(pObj)->nLeaves = 0; } pObj = If_ManConst1( p ); If_ObjSetLValue( pObj, (float)0.0 ); If_ObjSetArrTime( pObj, (float)0.0 ); If_ManForEachPi( p, pObj, i ) { pObj = If_ManCi( p, i ); If_ObjSetLValue( pObj, (float)0.0 ); If_ObjSetArrTime( pObj, (float)0.0 ); } // update all values iteratively fConverged = 0; for ( c = 1; c <= p->nMaxIters; c++ ) { if ( !If_ManPerformMappingRoundSeq( p, c ) ) { p->RequiredGlo = If_ManDelayMax( p, 1 ); fConverged = 1; break; } p->RequiredGlo = If_ManDelayMax( p, 1 ); //Abc_Print( 1, "Global = %d \n", (int)p->RequiredGlo ); if ( p->RequiredGlo > p->Period + p->fEpsilon ) break; } // report the results If_ManMarkMapping( p ); if ( p->pPars->fVerbose ) { // p->AreaGlo = If_ManScanMapping(p); Abc_Print( 1, "Attempt = %2d. Iters = %3d. Area = %10.2f. Fi = %6.2f. ", p->nAttempts, c, p->AreaGlo, (float)p->Period ); if ( fConverged ) Abc_Print( 1, " Feasible" ); else if ( c > p->nMaxIters ) Abc_Print( 1, "Infeasible (timeout)" ); else Abc_Print( 1, "Infeasible" ); Abc_Print( 1, "\n" ); } return fConverged; } /**Function************************************************************* Synopsis [Performs binary search for the optimal clock period.] Description [Assumes that FiMin is infeasible while FiMax is feasible.] SideEffects [] SeeAlso [] ***********************************************************************/ int If_ManBinarySearch_rec( If_Man_t * p, int FiMin, int FiMax ) { assert( FiMin < FiMax ); if ( FiMin + 1 == FiMax ) return FiMax; // compute the median p->Period = FiMin + (FiMax - FiMin)/2; if ( If_ManBinarySearchPeriod( p ) ) return If_ManBinarySearch_rec( p, FiMin, p->Period ); // Median is feasible else return If_ManBinarySearch_rec( p, p->Period, FiMax ); // Median is infeasible } /**Function************************************************************* Synopsis [Performs sequential mapping.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void If_ManPerformMappingSeqPost( If_Man_t * p ) { If_Obj_t * pObjLi, * pObjLo, * pObj; int i; assert( 0 ); // set arrival times assert( p->pPars->pTimesArr != NULL ); If_ManForEachLatchOutput( p, pObjLo, i ) p->pPars->pTimesArr[i] = If_ObjLValue(pObjLo); // set the required times assert( p->pPars->pTimesReq == NULL ); p->pPars->pTimesReq = ABC_ALLOC( float, If_ManCoNum(p) ); If_ManForEachPo( p, pObj, i ) p->pPars->pTimesReq[i] = p->RequiredGlo2; If_ManForEachLatchInput( p, pObjLi, i ) p->pPars->pTimesReq[i] = If_ObjLValue(If_ObjFanin0(pObjLi)); // undo previous mapping If_ManForEachObj( p, pObj, i ) if ( If_ObjIsAnd(pObj) ) If_ObjCutBest(pObj)->nLeaves = 0; // map again combinationally // p->pPars->fSeqMap = 0; If_ManPerformMappingComb( p ); // p->pPars->fSeqMap = 1; } /**Function************************************************************* Synopsis [Performs sequential mapping.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int If_ManPerformMappingSeq( If_Man_t * p ) { abctime clkTotal = Abc_Clock(); int PeriodBest; p->SortMode = 0; // perform combinational mapping to get the upper bound on the clock period If_ManPerformMappingRound( p, 1, 0, 0, 1, NULL ); p->RequiredGlo = If_ManDelayMax( p, 0 ); p->RequiredGlo2 = p->RequiredGlo; // set direct linking of latches with their inputs If_ManPrepareMappingSeq( p ); // collect latches p->vLatchOrder = If_ManCollectLatches( p ); // set parameters p->nCutsUsed = p->pPars->nCutsMax; p->nAttempts = 0; p->nMaxIters = 50; p->Period = (int)p->RequiredGlo; // make sure the clock period works if ( !If_ManBinarySearchPeriod( p ) ) { Abc_Print( 1, "If_ManPerformMappingSeq(): The upper bound on the clock period cannot be computed.\n" ); return 0; } // perform binary search PeriodBest = If_ManBinarySearch_rec( p, 0, p->Period ); // recompute the best l-values if ( p->Period != PeriodBest ) { p->Period = PeriodBest; if ( !If_ManBinarySearchPeriod( p ) ) { Abc_Print( 1, "If_ManPerformMappingSeq(): The final clock period cannot be confirmed.\n" ); return 0; } } // if ( p->pPars->fVerbose ) { Abc_Print( 1, "The best clock period is %3d. ", p->Period ); Abc_PrintTime( 1, "Time", Abc_Clock() - clkTotal ); } p->RequiredGlo = (float)(PeriodBest); // postprocess it using combinational mapping If_ManPerformMappingSeqPost( p ); s_MappingTime = Abc_Clock() - clkTotal; return 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END