/**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" //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static int If_ManBinarySearchPeriod( If_Man_t * p, int Mode ); static int If_ManBinarySearch_rec( If_Man_t * p, int Mode, int FiMin, int FiMax ); static int If_ManPerformMappingRoundSeq( If_Man_t * p, int Mode, int nIter, char * pLabel ); static int If_ManPrepareMappingSeq( If_Man_t * p ); static int If_ObjPerformMappingLatch( If_Man_t * p, If_Obj_t * pObj ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Performs sequential mapping.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int If_ManPerformMappingSeq( If_Man_t * p ) { int PeriodBest, Mode = 0; // collect nodes in the sequential order If_ManPrepareMappingSeq( p ); // perform combinational mapping to get the upper bound on the clock period If_ManPerformMappingRound( p, 2, 0, 0, NULL ); p->RequiredGlo = If_ManDelayMax( p, 0 ); // set parameters p->nCutsUsed = p->pPars->nCutsMax; p->nAttempts = 0; p->nMaxIters = 50; p->Period = (int)p->RequiredGlo; // make sure the clock period words if ( !If_ManBinarySearchPeriod( p, Mode ) ) { printf( "If_ManPerformMappingSeq(): The upper bound on the clock period cannot be computed.\n" ); return 0; } // perform binary search PeriodBest = If_ManBinarySearch_rec( p, Mode, 0, p->Period ); // recompute the best l-values if ( p->Period != PeriodBest ) { p->Period = PeriodBest; if ( !If_ManBinarySearchPeriod( p, Mode ) ) { printf( "If_ManPerformMappingSeq(): The final clock period cannot be confirmed.\n" ); return 0; } } /* // fix the problem with non-converged delays If_ManForEachNode( p, pObj, i ) if ( pObj->LValue < -ABC_INFINITY/2 ) pObj->LValue = (float)0.0; // write the retiming lags p->vLags = Vec_IntStart( If_ManObjNum(p) + 1 ); If_ManForEachNode( p, pObj, i ) Vec_IntWriteEntry( vLags, i, Abc_NodeComputeLag(pObj->LValue, p->Period) ); */ /* // print the statistic into a file { FILE * pTable; pTable = fopen( "iscas/seqmap__stats.txt", "a+" ); fprintf( pTable, "%d ", p->Period ); fprintf( pTable, "\n" ); fclose( pTable ); } */ // print the result if ( p->pPars->fLiftLeaves ) { // if ( p->pPars->fVerbose ) printf( "The best clock period is %3d. (Currently, network is not modified, so mapping will fail.)\n", p->Period ); return 0; } // if ( p->pPars->fVerbose ) printf( "The best clock period is %3d.\n", p->Period ); return 1; } /**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 Mode, 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, Mode ) ) return If_ManBinarySearch_rec( p, Mode, FiMin, p->Period ); // Median is feasible else return If_ManBinarySearch_rec( p, Mode, p->Period, FiMax ); // Median is infeasible } /**Function************************************************************* Synopsis [Returns 1 if retiming with this clock period is feasible.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int If_ManBinarySearchPeriod( If_Man_t * p, int Mode ) { If_Obj_t * pObj; int i, c, fConverged; int fResetRefs = 0; p->nAttempts++; // set l-values of all nodes to be minus infinity, except PIs and constants If_ManForEachObj( p, pObj, i ) { pObj->nCuts = 1; If_ObjSetLValue( pObj, -IF_FLOAT_LARGE ); if ( fResetRefs ) pObj->nRefs = 0; } If_ObjSetLValue( If_ManConst1(p), (float)0.0 ); If_ManForEachPi( p, pObj, i ) If_ObjSetLValue( pObj, (float)0.0 ); // reset references to their original state if ( fResetRefs ) { If_ManForEachObj( p, pObj, i ) { if ( If_ObjIsCo(pObj) ) continue; if ( pObj->pFanin0 ) pObj->pFanin0->nRefs++; if ( pObj->pFanin1 ) pObj->pFanin1->nRefs++; } } // update all values iteratively fConverged = 0; for ( c = 1; c <= p->nMaxIters; c++ ) { if ( !If_ManPerformMappingRoundSeq( p, Mode, c, NULL ) ) { fConverged = 1; break; } p->RequiredGlo = If_ManDelayMax( p, 1 ); if ( p->RequiredGlo > p->Period + p->fEpsilon ) break; } // report the results if ( p->pPars->fVerbose ) { p->AreaGlo = p->pPars->fLiftLeaves? 0/*If_ManScanMappingSeq(p)*/ : If_ManScanMapping(p); printf( "Attempt = %2d. Iters = %3d. Area = %10.2f. Fi = %6.2f. ", p->nAttempts, c, p->AreaGlo, (float)p->Period ); if ( fConverged ) printf( " Feasible" ); else if ( c > p->nMaxIters ) printf( "Infeasible (timeout)" ); else printf( "Infeasible" ); printf( "\n" ); } return fConverged; } /**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 Mode, int nIter, char * pLabel ) { ProgressBar * pProgress; If_Obj_t * pObj; int i, clk = clock(); int fVeryVerbose = 0; int fChange = 0; assert( Mode >= 0 && Mode <= 2 ); if ( !p->pPars->fVerbose ) pProgress = Extra_ProgressBarStart( stdout, If_ManObjNum(p) ); // map the internal nodes p->nCutsMerged = 0; If_ManForEachNode( p, pObj, i ) { if ( !p->pPars->fVerbose ) Extra_ProgressBarUpdate( pProgress, i, pLabel ); // consider the camse of an AND gate assert( If_ObjIsAnd(pObj) ); If_ObjPerformMappingAnd( p, pObj, Mode ); if ( pObj->fRepr ) If_ObjPerformMappingChoice( p, pObj, Mode ); // check if updating happens if ( If_ObjLValue(pObj) < If_ObjCutBest(pObj)->Delay - p->fEpsilon ) { If_ObjSetLValue( pObj, If_ObjCutBest(pObj)->Delay ); fChange = 1; } //if ( If_ObjLValue(pObj) > -1000.0 ) //printf( "Node %d %.2f ", pObj->Id, If_ObjLValue(pObj) ); } if ( !p->pPars->fVerbose ) Extra_ProgressBarStop( pProgress ); // propagate arrival times from the registers Vec_PtrForEachEntry( p->vLatchOrder, pObj, i ) fChange |= If_ObjPerformMappingLatch( p, pObj ); //printf( "\n\n" ); // compute area and delay if ( fVeryVerbose ) { p->RequiredGlo = If_ManDelayMax( p, 1 ); p->AreaGlo = p->pPars->fLiftLeaves? If_ManScanMappingSeq(p) : If_ManScanMapping(p); printf( "S%d: Fi = %6.2f. Del = %6.2f. Area = %8.2f. Cuts = %8d. Lim = %2d. Ave = %5.2f. ", nIter, (float)p->Period, p->RequiredGlo, p->AreaGlo, p->nCutsMerged, p->nCutsUsed, 1.0 * p->nCutsMerged / If_ManAndNum(p) ); PRT( "T", clock() - clk ); } return fChange; } /**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->nLatches ); Vec_PtrForEachEntryStart( p->vCis, pObj, i, If_ManCiNum(p) - p->pPars->nLatches ) If_ManCollectLatches_rec( pObj, vLatches ); // clean marks Vec_PtrForEachEntry( vLatches, pObj, i ) pObj->fMark = 0; assert( Vec_PtrSize(vLatches) == p->pPars->nLatches ); return vLatches; } /**Function************************************************************* Synopsis [Prepares for sequential mapping by linking the latches.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int If_ManPrepareMappingSeq( If_Man_t * p ) { If_Obj_t * pObj, * pObjLi, * pObjLo, * pTemp; If_Cut_t * pCut; int i; // link the latch outputs (PIs) directly to the drivers of latch inputs (POs) for ( i = 0; i < p->pPars->nLatches; i++ ) { pObjLo = If_ManCi( p, If_ManCiNum(p) - p->pPars->nLatches + i ); pObjLi = If_ManCo( p, If_ManCoNum(p) - p->pPars->nLatches + i ); pObjLo->pFanin0 = If_ObjFanin0( pObjLi ); pObjLo->fCompl0 = If_ObjFaninC0( pObjLi ); // pObjLo->pFanin0 = pObjLi; } // collect latches p->vLatchOrder = If_ManCollectLatches( p ); // propagate elementary cuts if ( p->pPars->fLiftLeaves ) { Vec_PtrForEachEntry( p->vLatchOrder, pObj, i ) { pCut = If_ObjCutTriv(pObj); If_CutCopy( pCut, If_ObjFanin0(pObj)->Cuts ); If_CutLift( pCut ); pCut->Delay -= p->Period; pCut->fCompl ^= pObj->fCompl0; // there is a bug here, which shows when there are choices... // pTemp = If_ManObj(p, pCut->pLeaves[0] >> 8); pTemp = If_ManObj(p, pCut->pLeaves[0]); assert( !If_ObjIsLatch(pTemp) ); } } return 1; } /**Function************************************************************* Synopsis [Performs mapping of the latches.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int If_ObjPerformMappingLatch( If_Man_t * p, If_Obj_t * pObj ) { If_Obj_t * pFanin; If_Cut_t * pCut; float LValueOld; int i; assert( If_ObjIsLatch(pObj) ); // save old l-value LValueOld = If_ObjLValue(pObj); pFanin = If_ObjFanin0(pObj); assert( pFanin->nCuts > 0 ); if ( !p->pPars->fLiftLeaves ) { pObj->nCuts = 1; If_ObjSetLValue( pObj, If_ObjLValue(pFanin) - p->Period ); } else { pObj->nCuts = pFanin->nCuts; If_ObjForEachCut( pObj, pCut, i ) { If_CutCopy( pCut, pFanin->Cuts + i ); If_CutLift( pCut ); pCut->Delay -= p->Period; pCut->fCompl ^= pObj->fCompl0; } } return LValueOld != If_ObjLValue(pObj); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// ////////////////////////////////////////////////////////////////////////