00001
00021 #include "retInt.h"
00022
00026
00027
00028 enum { ABC_RET_UPDATE_FAIL, ABC_RET_UPDATE_NO, ABC_RET_UPDATE_YES };
00029
00030
00031 static Vec_Int_t * Abc_NtkRetimeGetLags( Abc_Ntk_t * pNtk, int nIterLimit, int fVerbose );
00032 static int Abc_NtkRetimeSearch_rec( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vLatches, int FiMin, int FiMax, int nMaxIters, int fVerbose );
00033 static int Abc_NtkRetimeForPeriod( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vLatches, int Fi, int nMaxIters, int fVerbose );
00034 static int Abc_NtkRetimeUpdateLValue( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vLatches, int Fi );
00035 static int Abc_NtkRetimePosOverLimit( Abc_Ntk_t * pNtk, int Fi );
00036 static Vec_Ptr_t * Abc_ManCollectLatches( Abc_Ntk_t * pNtk );
00037 static int Abc_NtkRetimeUsingLags( Abc_Ntk_t * pNtk, Vec_Int_t * vLags, int fVerbose );
00038
00039 static inline int Abc_NodeComputeLag( int LValue, int Fi ) { return (LValue + (1<<16)*Fi)/Fi - (1<<16) - (int)(LValue % Fi == 0); }
00040 static inline int Abc_NodeGetLValue( Abc_Obj_t * pNode ) { return (int)pNode->pCopy; }
00041 static inline void Abc_NodeSetLValue( Abc_Obj_t * pNode, int Value ) { pNode->pCopy = (void *)Value; }
00042
00046
00058 int Abc_NtkRetimeLValue( Abc_Ntk_t * pNtk, int nIterLimit, int fVerbose )
00059 {
00060 Vec_Int_t * vLags;
00061 int nLatches = Abc_NtkLatchNum(pNtk);
00062 assert( Abc_NtkIsLogic( pNtk ) );
00063
00064 vLags = Abc_NtkRetimeGetLags( pNtk, nIterLimit, fVerbose );
00065
00066
00067 Vec_IntFree( vLags );
00068
00069
00070
00071 if ( !Abc_NtkCheck( pNtk ) )
00072 fprintf( stdout, "Abc_NtkRetimeLValue(): Network check has failed.\n" );
00073
00074 return nLatches - Abc_NtkLatchNum(pNtk);
00075 }
00076
00088 Vec_Int_t * Abc_NtkRetimeGetLags( Abc_Ntk_t * pNtk, int nIterLimit, int fVerbose )
00089 {
00090 Vec_Int_t * vLags;
00091 Vec_Ptr_t * vNodes, * vLatches;
00092 Abc_Obj_t * pNode;
00093 int i, FiMax, FiBest, RetValue, clk, clkIter;
00094 char NodeLag;
00095
00096
00097 FiMax = Abc_NtkLevel(pNtk);
00098
00099
00100 vNodes = Abc_NtkDfs( pNtk, 0 );
00101 vLatches = Abc_ManCollectLatches( pNtk );
00102 if ( !Abc_NtkRetimeForPeriod( pNtk, vNodes, vLatches, FiMax, nIterLimit, fVerbose ) )
00103 {
00104 Vec_PtrFree( vNodes );
00105 printf( "Abc_NtkRetimeGetLags() error: The upper bound on the clock period cannot be computed.\n" );
00106 return Vec_IntStart( Abc_NtkObjNumMax(pNtk) + 1 );
00107 }
00108
00109
00110 clk = clock();
00111 FiBest = Abc_NtkRetimeSearch_rec( pNtk, vNodes, vLatches, 0, FiMax, nIterLimit, fVerbose );
00112 clkIter = clock() - clk;
00113
00114
00115 RetValue = Abc_NtkRetimeForPeriod( pNtk, vNodes, vLatches, FiBest, nIterLimit, fVerbose );
00116 assert( RetValue );
00117
00118
00119 Abc_NtkForEachNode( pNtk, pNode, i )
00120 if ( Abc_NodeGetLValue(pNode) < -ABC_INFINITY/2 )
00121 Abc_NodeSetLValue( pNode, 0 );
00122
00123
00124 vLags = Vec_IntStart( Abc_NtkObjNumMax(pNtk) + 1 );
00125 Abc_NtkForEachNode( pNtk, pNode, i )
00126 {
00127 NodeLag = Abc_NodeComputeLag( Abc_NodeGetLValue(pNode), FiBest );
00128 Vec_IntWriteEntry( vLags, pNode->Id, NodeLag );
00129 }
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141 printf( "The best clock period is %3d. (Currently, network is not modified.)\n", FiBest );
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151 Vec_PtrFree( vNodes );
00152 Vec_PtrFree( vLatches );
00153 return vLags;
00154 }
00155
00167 int Abc_NtkRetimeSearch_rec( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vLatches, int FiMin, int FiMax, int nMaxIters, int fVerbose )
00168 {
00169 int Median;
00170 assert( FiMin < FiMax );
00171 if ( FiMin + 1 == FiMax )
00172 return FiMax;
00173 Median = FiMin + (FiMax - FiMin)/2;
00174 if ( Abc_NtkRetimeForPeriod( pNtk, vNodes, vLatches, Median, nMaxIters, fVerbose ) )
00175 return Abc_NtkRetimeSearch_rec( pNtk, vNodes, vLatches, FiMin, Median, nMaxIters, fVerbose );
00176 else
00177 return Abc_NtkRetimeSearch_rec( pNtk, vNodes, vLatches, Median, FiMax, nMaxIters, fVerbose );
00178 }
00179
00191 int Abc_NtkRetimeForPeriod( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vLatches, int Fi, int nMaxIters, int fVerbose )
00192 {
00193 Abc_Obj_t * pObj;
00194 int c, i, fConverged;
00195
00196 Abc_NtkForEachObj( pNtk, pObj, i )
00197 if ( Abc_ObjFaninNum(pObj) == 0 )
00198 Abc_NodeSetLValue( pObj, 0 );
00199 else
00200 Abc_NodeSetLValue( pObj, -ABC_INFINITY );
00201
00202 fConverged = 0;
00203 for ( c = 1; c <= nMaxIters; c++ )
00204 {
00205 if ( !Abc_NtkRetimeUpdateLValue( pNtk, vNodes, vLatches, Fi ) )
00206 {
00207 fConverged = 1;
00208 break;
00209 }
00210 if ( Abc_NtkRetimePosOverLimit(pNtk, Fi) )
00211 break;
00212 }
00213
00214 if ( fVerbose )
00215 {
00216 if ( !fConverged )
00217 printf( "Period = %3d. Iterations = %3d. Infeasible %s\n", Fi, c, (c > nMaxIters)? "(timeout)" : "" );
00218 else
00219 printf( "Period = %3d. Iterations = %3d. Feasible\n", Fi, c );
00220 }
00221
00222
00223
00224
00225
00226
00227
00228
00229 return fConverged;
00230 }
00231
00244 int Abc_NtkRetimeUpdateLValue( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vLatches, int Fi )
00245 {
00246 Abc_Obj_t * pObj, * pFanin;
00247 int i, k, lValueNew, fChange;
00248
00249 fChange = 0;
00250 Vec_PtrForEachEntry( vNodes, pObj, i )
00251 {
00252 assert( Abc_ObjIsNode(pObj) );
00253 lValueNew = -ABC_INFINITY;
00254 Abc_ObjForEachFanin( pObj, pFanin, k )
00255 {
00256 if ( lValueNew < Abc_NodeGetLValue(pFanin) )
00257 lValueNew = Abc_NodeGetLValue(pFanin);
00258 }
00259 lValueNew++;
00260 if ( Abc_NodeGetLValue(pObj) < lValueNew )
00261 {
00262 Abc_NodeSetLValue( pObj, lValueNew );
00263 fChange = 1;
00264 }
00265 }
00266
00267 Vec_PtrForEachEntry( vLatches, pObj, i )
00268 Abc_NodeSetLValue( Abc_ObjFanout0(pObj), Abc_NodeGetLValue(Abc_ObjFanin0(Abc_ObjFanin0(pObj))) - Fi );
00269 return fChange;
00270 }
00271
00283 int Abc_NtkRetimePosOverLimit( Abc_Ntk_t * pNtk, int Fi )
00284 {
00285 Abc_Obj_t * pObj;
00286 int i;
00287 Abc_NtkForEachPo( pNtk, pObj, i )
00288 if ( Abc_NodeGetLValue(Abc_ObjFanin0(pObj)) > Fi )
00289 return 1;
00290 return 0;
00291 }
00292
00304 void Abc_ManCollectLatches_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vLatches )
00305 {
00306 Abc_Obj_t * pDriver;
00307 if ( !Abc_ObjIsLatch(pObj) )
00308 return;
00309
00310 if ( Abc_NodeIsTravIdCurrent(pObj) )
00311 return;
00312 Abc_NodeSetTravIdCurrent(pObj);
00313
00314 pDriver = Abc_ObjFanin0(Abc_ObjFanin0(pObj));
00315
00316 if ( Abc_ObjIsBo(pDriver) )
00317 Abc_ManCollectLatches_rec( Abc_ObjFanin0(pDriver), vLatches );
00318
00319 Vec_PtrPush( vLatches, pObj );
00320 }
00321
00333 Vec_Ptr_t * Abc_ManCollectLatches( Abc_Ntk_t * pNtk )
00334 {
00335 Vec_Ptr_t * vLatches;
00336 Abc_Obj_t * pObj;
00337 int i;
00338 vLatches = Vec_PtrAlloc( Abc_NtkLatchNum(pNtk) );
00339 Abc_NtkIncrementTravId( pNtk );
00340 Abc_NtkForEachLatch( pNtk, pObj, i )
00341 Abc_ManCollectLatches_rec( pObj, vLatches );
00342 assert( Vec_PtrSize(vLatches) == Abc_NtkLatchNum(pNtk) );
00343 return vLatches;
00344 }
00345
00357 int Abc_NtkRetimeUsingLags( Abc_Ntk_t * pNtk, Vec_Int_t * vLags, int fVerbose )
00358 {
00359 Abc_Obj_t * pObj;
00360 int fChanges, fForward, nTotalMoves, Lag, Counter, i;
00361
00362 nTotalMoves = 0;
00363 do {
00364 fChanges = 0;
00365 Abc_NtkForEachNode( pNtk, pObj, i )
00366 {
00367 Lag = Vec_IntEntry( vLags, pObj->Id );
00368 if ( !Lag )
00369 continue;
00370 fForward = (Lag < 0);
00371 if ( Abc_NtkRetimeNodeIsEnabled( pObj, fForward ) )
00372 {
00373 Abc_NtkRetimeNode( pObj, fForward, 0 );
00374 fChanges = 1;
00375 nTotalMoves++;
00376 Vec_IntAddToEntry( vLags, pObj->Id, fForward? 1 : -1 );
00377 }
00378 }
00379 } while ( fChanges );
00380 if ( fVerbose )
00381 printf( "Total latch moves = %d.\n", nTotalMoves );
00382
00383 Counter = 0;
00384 Abc_NtkForEachNode( pNtk, pObj, i )
00385 Counter += (Vec_IntEntry( vLags, pObj->Id ) != 0);
00386 if ( Counter )
00387 printf( "Warning! The number of nodes with unrealized lag = %d.\n", Counter );
00388 return 1;
00389 }
00390
00394
00395