abc-master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
retLvalue.c
Go to the documentation of this file.
1 /**CFile****************************************************************
2 
3  FileName [retLvalue.c]
4 
5  SystemName [ABC: Logic synthesis and verification system.]
6 
7  PackageName [Retiming package.]
8 
9  Synopsis [Implementation of Pan's retiming algorithm.]
10 
11  Author [Alan Mishchenko]
12 
13  Affiliation [UC Berkeley]
14 
15  Date [Ver. 1.0. Started - Oct 31, 2006.]
16 
17  Revision [$Id: retLvalue.c,v 1.00 2006/10/31 00:00:00 alanmi Exp $]
18 
19 ***********************************************************************/
20 
21 #include "retInt.h"
22 
24 
25 
26 ////////////////////////////////////////////////////////////////////////
27 /// DECLARATIONS ///
28 ////////////////////////////////////////////////////////////////////////
29 
30 // node status after updating its arrival time
32 
33 // the internal procedures
34 static Vec_Int_t * Abc_NtkRetimeGetLags( Abc_Ntk_t * pNtk, int nIterLimit, int fVerbose );
35 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 );
36 static int Abc_NtkRetimeForPeriod( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vLatches, int Fi, int nMaxIters, int fVerbose );
37 static int Abc_NtkRetimeUpdateLValue( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vLatches, int Fi );
38 static int Abc_NtkRetimePosOverLimit( Abc_Ntk_t * pNtk, int Fi );
39 static Vec_Ptr_t * Abc_ManCollectLatches( Abc_Ntk_t * pNtk );
40 static int Abc_NtkRetimeUsingLags( Abc_Ntk_t * pNtk, Vec_Int_t * vLags, int fVerbose );
41 
42 static inline int Abc_NodeComputeLag( int LValue, int Fi ) { return (LValue + (1<<16)*Fi)/Fi - (1<<16) - (int)(LValue % Fi == 0); }
43 static inline int Abc_NodeGetLValue( Abc_Obj_t * pNode ) { return (int)(ABC_PTRUINT_T)pNode->pCopy; }
44 static inline void Abc_NodeSetLValue( Abc_Obj_t * pNode, int Value ) { pNode->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)Value; }
45 
46 ////////////////////////////////////////////////////////////////////////
47 /// FUNCTION DEFINITIONS ///
48 ////////////////////////////////////////////////////////////////////////
49 
50 /**Function*************************************************************
51 
52  Synopsis [Implements Pan's retiming algorithm.]
53 
54  Description []
55 
56  SideEffects []
57 
58  SeeAlso []
59 
60 ***********************************************************************/
61 int Abc_NtkRetimeLValue( Abc_Ntk_t * pNtk, int nIterLimit, int fVerbose )
62 {
63  Vec_Int_t * vLags;
64  int nLatches = Abc_NtkLatchNum(pNtk);
65  assert( Abc_NtkIsLogic( pNtk ) );
66  // get the lags
67  vLags = Abc_NtkRetimeGetLags( pNtk, nIterLimit, fVerbose );
68  // compute the retiming
69 // Abc_NtkRetimeUsingLags( pNtk, vLags, fVerbose );
70  Vec_IntFree( vLags );
71  // fix the COs
72 // Abc_NtkLogicMakeSimpleCos( pNtk, 0 );
73  // check for correctness
74  if ( !Abc_NtkCheck( pNtk ) )
75  fprintf( stdout, "Abc_NtkRetimeLValue(): Network check has failed.\n" );
76  // return the number of latches saved
77  return nLatches - Abc_NtkLatchNum(pNtk);
78 }
79 
80 /**Function*************************************************************
81 
82  Synopsis [Computes the retiming lags.]
83 
84  Description []
85 
86  SideEffects []
87 
88  SeeAlso []
89 
90 ***********************************************************************/
91 Vec_Int_t * Abc_NtkRetimeGetLags( Abc_Ntk_t * pNtk, int nIterLimit, int fVerbose )
92 {
93  Vec_Int_t * vLags;
94  Vec_Ptr_t * vNodes, * vLatches;
95  Abc_Obj_t * pNode;
96  int i, FiMax, FiBest, RetValue;
97  abctime clk, clkIter;
98  char NodeLag;
99 
100  // get the upper bound on the clock period
101  FiMax = Abc_NtkLevel(pNtk);
102 
103  // make sure this clock period is feasible
104  vNodes = Abc_NtkDfs( pNtk, 0 );
105  vLatches = Abc_ManCollectLatches( pNtk );
106  if ( !Abc_NtkRetimeForPeriod( pNtk, vNodes, vLatches, FiMax, nIterLimit, fVerbose ) )
107  {
108  Vec_PtrFree( vLatches );
109  Vec_PtrFree( vNodes );
110  printf( "Abc_NtkRetimeGetLags() error: The upper bound on the clock period cannot be computed.\n" );
111  return Vec_IntStart( Abc_NtkObjNumMax(pNtk) + 1 );
112  }
113 
114  // search for the optimal clock period between 0 and nLevelMax
115 clk = Abc_Clock();
116  FiBest = Abc_NtkRetimeSearch_rec( pNtk, vNodes, vLatches, 0, FiMax, nIterLimit, fVerbose );
117 clkIter = Abc_Clock() - clk;
118 
119  // recompute the best l-values
120  RetValue = Abc_NtkRetimeForPeriod( pNtk, vNodes, vLatches, FiBest, nIterLimit, fVerbose );
121  assert( RetValue );
122 
123  // fix the problem with non-converged delays
124  Abc_NtkForEachNode( pNtk, pNode, i )
125  if ( Abc_NodeGetLValue(pNode) < -ABC_INFINITY/2 )
126  Abc_NodeSetLValue( pNode, 0 );
127 
128  // write the retiming lags
129  vLags = Vec_IntStart( Abc_NtkObjNumMax(pNtk) + 1 );
130  Abc_NtkForEachNode( pNtk, pNode, i )
131  {
132  NodeLag = Abc_NodeComputeLag( Abc_NodeGetLValue(pNode), FiBest );
133  Vec_IntWriteEntry( vLags, pNode->Id, NodeLag );
134  }
135 /*
136  Abc_NtkForEachPo( pNtk, pNode, i )
137  printf( "%d ", Abc_NodeGetLValue(Abc_ObjFanin0(pNode)) );
138  printf( "\n" );
139  Abc_NtkForEachLatch( pNtk, pNode, i )
140  printf( "%d/%d ", Abc_NodeGetLValue(Abc_ObjFanout0(pNode)), Abc_NodeGetLValue(Abc_ObjFanout0(pNode)) + FiBest );
141  printf( "\n" );
142 */
143 
144  // print the result
145 // if ( fVerbose )
146  printf( "The best clock period is %3d. (Currently, network is not modified.)\n", FiBest );
147 /*
148  {
149  FILE * pTable;
150  pTable = fopen( "iscas/seqmap__stats2.txt", "a+" );
151  fprintf( pTable, "%d ", FiBest );
152  fprintf( pTable, "\n" );
153  fclose( pTable );
154  }
155 */
156  Vec_PtrFree( vNodes );
157  Vec_PtrFree( vLatches );
158  return vLags;
159 }
160 
161 /**Function*************************************************************
162 
163  Synopsis [Performs binary search for the optimal clock period.]
164 
165  Description [Assumes that FiMin is infeasible while FiMax is feasible.]
166 
167  SideEffects []
168 
169  SeeAlso []
170 
171 ***********************************************************************/
172 int Abc_NtkRetimeSearch_rec( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vLatches, int FiMin, int FiMax, int nMaxIters, int fVerbose )
173 {
174  int Median;
175  assert( FiMin < FiMax );
176  if ( FiMin + 1 == FiMax )
177  return FiMax;
178  Median = FiMin + (FiMax - FiMin)/2;
179  if ( Abc_NtkRetimeForPeriod( pNtk, vNodes, vLatches, Median, nMaxIters, fVerbose ) )
180  return Abc_NtkRetimeSearch_rec( pNtk, vNodes, vLatches, FiMin, Median, nMaxIters, fVerbose ); // Median is feasible
181  else
182  return Abc_NtkRetimeSearch_rec( pNtk, vNodes, vLatches, Median, FiMax, nMaxIters, fVerbose ); // Median is infeasible
183 }
184 
185 /**Function*************************************************************
186 
187  Synopsis [Returns 1 if retiming with this clock period is feasible.]
188 
189  Description []
190 
191  SideEffects []
192 
193  SeeAlso []
194 
195 ***********************************************************************/
196 int Abc_NtkRetimeForPeriod( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vLatches, int Fi, int nMaxIters, int fVerbose )
197 {
198  Abc_Obj_t * pObj;
199  int c, i, fConverged;
200  // set l-values of all nodes to be minus infinity, except PIs and constants
201  Abc_NtkForEachObj( pNtk, pObj, i )
202  if ( Abc_ObjFaninNum(pObj) == 0 )
203  Abc_NodeSetLValue( pObj, 0 );
204  else
206  // update all values iteratively
207  fConverged = 0;
208  for ( c = 1; c <= nMaxIters; c++ )
209  {
210  if ( !Abc_NtkRetimeUpdateLValue( pNtk, vNodes, vLatches, Fi ) )
211  {
212  fConverged = 1;
213  break;
214  }
215  if ( Abc_NtkRetimePosOverLimit(pNtk, Fi) )
216  break;
217  }
218  // report the results
219  if ( fVerbose )
220  {
221  if ( !fConverged )
222  printf( "Period = %3d. Iterations = %3d. Infeasible %s\n", Fi, c, (c > nMaxIters)? "(timeout)" : "" );
223  else
224  printf( "Period = %3d. Iterations = %3d. Feasible\n", Fi, c );
225  }
226 /*
227  // check if any AND gates have infinite delay
228  Counter = 0;
229  Abc_NtkForEachNode( pNtk, pObj, i )
230  Counter += (Abc_NodeGetLValue(pObj) < -ABC_INFINITY/2);
231  if ( Counter > 0 )
232  printf( "Warning: %d internal nodes have wrong l-values!\n", Counter );
233 */
234  return fConverged;
235 }
236 
237 /**Function*************************************************************
238 
239  Synopsis [Performs one iteration of l-value computation for the nodes.]
240 
241  Description [Experimentally it was found that checking POs changes
242  is not enough to detect the convergence of l-values in the network.]
243 
244  SideEffects []
245 
246  SeeAlso []
247 
248 ***********************************************************************/
249 int Abc_NtkRetimeUpdateLValue( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vLatches, int Fi )
250 {
251  Abc_Obj_t * pObj, * pFanin;
252  int i, k, lValueNew, fChange;
253  // go through the nodes and detect change
254  fChange = 0;
255  Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
256  {
257  assert( Abc_ObjIsNode(pObj) );
258  lValueNew = -ABC_INFINITY;
259  Abc_ObjForEachFanin( pObj, pFanin, k )
260  {
261  if ( lValueNew < Abc_NodeGetLValue(pFanin) )
262  lValueNew = Abc_NodeGetLValue(pFanin);
263  }
264  lValueNew++;
265  if ( Abc_NodeGetLValue(pObj) < lValueNew )
266  {
267  Abc_NodeSetLValue( pObj, lValueNew );
268  fChange = 1;
269  }
270  }
271  // propagate values through the latches
272  Vec_PtrForEachEntry( Abc_Obj_t *, vLatches, pObj, i )
274  return fChange;
275 }
276 
277 /**Function*************************************************************
278 
279  Synopsis [Detects the case when l-values exceeded the limit.]
280 
281  Description []
282 
283  SideEffects []
284 
285  SeeAlso []
286 
287 ***********************************************************************/
289 {
290  Abc_Obj_t * pObj;
291  int i;
292  Abc_NtkForEachPo( pNtk, pObj, i )
293  if ( Abc_NodeGetLValue(Abc_ObjFanin0(pObj)) > Fi )
294  return 1;
295  return 0;
296 }
297 
298 /**Function*************************************************************
299 
300  Synopsis [Collects latches in the topological order.]
301 
302  Description []
303 
304  SideEffects []
305 
306  SeeAlso []
307 
308 ***********************************************************************/
310 {
311  Abc_Obj_t * pDriver;
312  if ( !Abc_ObjIsLatch(pObj) )
313  return;
314  // skip already collected latches
315  if ( Abc_NodeIsTravIdCurrent(pObj) )
316  return;
318  // get the driver node feeding into the latch
319  pDriver = Abc_ObjFanin0(Abc_ObjFanin0(pObj));
320  // call recursively if the driver looks like a latch output
321  if ( Abc_ObjIsBo(pDriver) )
322  Abc_ManCollectLatches_rec( Abc_ObjFanin0(pDriver), vLatches );
323  // collect the latch
324  Vec_PtrPush( vLatches, pObj );
325 }
326 
327 /**Function*************************************************************
328 
329  Synopsis [Collects latches in the topological order.]
330 
331  Description []
332 
333  SideEffects []
334 
335  SeeAlso []
336 
337 ***********************************************************************/
339 {
340  Vec_Ptr_t * vLatches;
341  Abc_Obj_t * pObj;
342  int i;
343  vLatches = Vec_PtrAlloc( Abc_NtkLatchNum(pNtk) );
344  Abc_NtkIncrementTravId( pNtk );
345  Abc_NtkForEachLatch( pNtk, pObj, i )
346  Abc_ManCollectLatches_rec( pObj, vLatches );
347  assert( Vec_PtrSize(vLatches) == Abc_NtkLatchNum(pNtk) );
348  return vLatches;
349 }
350 
351 /**Function*************************************************************
352 
353  Synopsis [Implements the retiming given as the array of retiming lags.]
354 
355  Description []
356 
357  SideEffects []
358 
359  SeeAlso []
360 
361 ***********************************************************************/
362 int Abc_NtkRetimeUsingLags( Abc_Ntk_t * pNtk, Vec_Int_t * vLags, int fVerbose )
363 {
364  Abc_Obj_t * pObj;
365  int fChanges, fForward, nTotalMoves, Lag, Counter, i;
366  // iterate over the nodes
367  nTotalMoves = 0;
368  do {
369  fChanges = 0;
370  Abc_NtkForEachNode( pNtk, pObj, i )
371  {
372  Lag = Vec_IntEntry( vLags, pObj->Id );
373  if ( !Lag )
374  continue;
375  fForward = (Lag < 0);
376  if ( Abc_NtkRetimeNodeIsEnabled( pObj, fForward ) )
377  {
378  Abc_NtkRetimeNode( pObj, fForward, 0 );
379  fChanges = 1;
380  nTotalMoves++;
381  Vec_IntAddToEntry( vLags, pObj->Id, fForward? 1 : -1 );
382  }
383  }
384  } while ( fChanges );
385  if ( fVerbose )
386  printf( "Total latch moves = %d.\n", nTotalMoves );
387  // check if there are remaining lags
388  Counter = 0;
389  Abc_NtkForEachNode( pNtk, pObj, i )
390  Counter += (Vec_IntEntry( vLags, pObj->Id ) != 0);
391  if ( Counter )
392  printf( "Warning! The number of nodes with unrealized lag = %d.\n", Counter );
393  return 1;
394 }
395 
396 ////////////////////////////////////////////////////////////////////////
397 /// END OF FILE ///
398 ////////////////////////////////////////////////////////////////////////
399 
400 
402 
static int Abc_NtkRetimeForPeriod(Abc_Ntk_t *pNtk, Vec_Ptr_t *vNodes, Vec_Ptr_t *vLatches, int Fi, int nMaxIters, int fVerbose)
Definition: retLvalue.c:196
void Abc_ManCollectLatches_rec(Abc_Obj_t *pObj, Vec_Ptr_t *vLatches)
Definition: retLvalue.c:309
static int Abc_NtkRetimeUsingLags(Abc_Ntk_t *pNtk, Vec_Int_t *vLags, int fVerbose)
Definition: retLvalue.c:362
static int Abc_NtkIsLogic(Abc_Ntk_t *pNtk)
Definition: abc.h:250
typedefABC_NAMESPACE_HEADER_START struct Vec_Ptr_t_ Vec_Ptr_t
INCLUDES ///.
Definition: vecPtr.h:42
static void Abc_NodeSetLValue(Abc_Obj_t *pNode, int Value)
Definition: retLvalue.c:44
static int Abc_NtkObjNumMax(Abc_Ntk_t *pNtk)
Definition: abc.h:284
static int Abc_ObjIsBo(Abc_Obj_t *pObj)
Definition: abc.h:350
typedefABC_NAMESPACE_IMPL_START struct Vec_Int_t_ Vec_Int_t
DECLARATIONS ///.
Definition: bblif.c:37
static int Abc_NodeGetLValue(Abc_Obj_t *pNode)
Definition: retLvalue.c:43
static int Abc_ObjIsLatch(Abc_Obj_t *pObj)
Definition: abc.h:356
static int Abc_ObjFaninNum(Abc_Obj_t *pObj)
Definition: abc.h:364
static int Abc_NtkLatchNum(Abc_Ntk_t *pNtk)
Definition: abc.h:294
static void Vec_PtrPush(Vec_Ptr_t *p, void *Entry)
Definition: vecPtr.h:606
ABC_DLL int Abc_NtkCheck(Abc_Ntk_t *pNtk)
FUNCTION DEFINITIONS ///.
Definition: abcCheck.c:61
ABC_DLL Vec_Ptr_t * Abc_NtkDfs(Abc_Ntk_t *pNtk, int fCollectAll)
Definition: abcDfs.c:81
static abctime Abc_Clock()
Definition: abc_global.h:279
static int Vec_PtrSize(Vec_Ptr_t *p)
Definition: vecPtr.h:295
static Abc_Obj_t * Abc_ObjFanin0(Abc_Obj_t *pObj)
Definition: abc.h:373
static int Abc_NodeComputeLag(int LValue, int Fi)
Definition: retLvalue.c:42
static void Vec_IntWriteEntry(Vec_Int_t *p, int i, int Entry)
Definition: bblif.c:285
static int Abc_ObjIsNode(Abc_Obj_t *pObj)
Definition: abc.h:355
static Vec_Int_t * Vec_IntStart(int nSize)
Definition: bblif.c:172
Abc_Obj_t * pCopy
Definition: abc.h:148
static void Vec_IntAddToEntry(Vec_Int_t *p, int i, int Addition)
Definition: bblif.c:302
void Abc_NtkRetimeNode(Abc_Obj_t *pObj, int fForward, int fInitial)
Definition: retIncrem.c:315
static int Vec_IntEntry(Vec_Int_t *p, int i)
Definition: bblif.c:268
#define ABC_NAMESPACE_IMPL_END
Definition: abc_global.h:108
static int Counter
#define Abc_NtkForEachLatch(pNtk, pObj, i)
Definition: abc.h:497
int Abc_NtkRetimeNodeIsEnabled(Abc_Obj_t *pObj, int fForward)
Definition: retIncrem.c:284
#define Abc_NtkForEachNode(pNtk, pNode, i)
Definition: abc.h:461
#define ABC_NAMESPACE_IMPL_START
Definition: abc_global.h:107
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)
Definition: retLvalue.c:172
static int Abc_NodeIsTravIdCurrent(Abc_Obj_t *p)
Definition: abc.h:411
static int Abc_NtkRetimeUpdateLValue(Abc_Ntk_t *pNtk, Vec_Ptr_t *vNodes, Vec_Ptr_t *vLatches, int Fi)
Definition: retLvalue.c:249
static Vec_Ptr_t * Vec_PtrAlloc(int nCap)
FUNCTION DEFINITIONS ///.
Definition: vecPtr.h:83
#define Abc_ObjForEachFanin(pObj, pFanin, i)
Definition: abc.h:524
int Id
Definition: abc.h:132
static Vec_Int_t * Abc_NtkRetimeGetLags(Abc_Ntk_t *pNtk, int nIterLimit, int fVerbose)
Definition: retLvalue.c:91
static void Abc_NtkIncrementTravId(Abc_Ntk_t *p)
Definition: abc.h:406
#define ABC_INFINITY
MACRO DEFINITIONS ///.
Definition: abc_global.h:216
#define assert(ex)
Definition: util_old.h:213
static Vec_Ptr_t * Abc_ManCollectLatches(Abc_Ntk_t *pNtk)
Definition: retLvalue.c:338
#define Abc_NtkForEachPo(pNtk, pPo, i)
Definition: abc.h:517
static void Vec_IntFree(Vec_Int_t *p)
Definition: bblif.c:235
#define Vec_PtrForEachEntry(Type, vVec, pEntry, i)
MACRO DEFINITIONS ///.
Definition: vecPtr.h:55
ABC_INT64_T abctime
Definition: abc_global.h:278
#define Abc_NtkForEachObj(pNtk, pObj, i)
ITERATORS ///.
Definition: abc.h:446
ABC_DLL int Abc_NtkLevel(Abc_Ntk_t *pNtk)
Definition: abcDfs.c:1265
static int Abc_NtkRetimePosOverLimit(Abc_Ntk_t *pNtk, int Fi)
Definition: retLvalue.c:288
static Abc_Obj_t * Abc_ObjFanout0(Abc_Obj_t *pObj)
Definition: abc.h:371
int Abc_NtkRetimeLValue(Abc_Ntk_t *pNtk, int nIterLimit, int fVerbose)
FUNCTION DEFINITIONS ///.
Definition: retLvalue.c:61
static void Abc_NodeSetTravIdCurrent(Abc_Obj_t *p)
Definition: abc.h:409
static void Vec_PtrFree(Vec_Ptr_t *p)
Definition: vecPtr.h:223