ABC: A System for Sequential Synthesis and Verification
 
Loading...
Searching...
No Matches
retLvalue.c
Go to the documentation of this file.
1
20
21#include "retInt.h"
22
24
25
29
30// node status after updating its arrival time
32
33// the internal procedures
34static Vec_Int_t * Abc_NtkRetimeGetLags( Abc_Ntk_t * pNtk, int nIterLimit, int fVerbose );
35static int Abc_NtkRetimeSearch_rec( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vLatches, int FiMin, int FiMax, int nMaxIters, int fVerbose );
36static int Abc_NtkRetimeForPeriod( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vLatches, int Fi, int nMaxIters, int fVerbose );
37static int Abc_NtkRetimeUpdateLValue( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vLatches, int Fi );
38static int Abc_NtkRetimePosOverLimit( Abc_Ntk_t * pNtk, int Fi );
39static Vec_Ptr_t * Abc_ManCollectLatches( Abc_Ntk_t * pNtk );
40static int Abc_NtkRetimeUsingLags( Abc_Ntk_t * pNtk, Vec_Int_t * vLags, int fVerbose );
41
42static inline int Abc_NodeComputeLag( int LValue, int Fi ) { return (LValue + (1<<16)*Fi)/Fi - (1<<16) - (int)(LValue % Fi == 0); }
43static inline int Abc_NodeGetLValue( Abc_Obj_t * pNode ) { return (int)(ABC_PTRUINT_T)pNode->pCopy; }
44static inline void Abc_NodeSetLValue( Abc_Obj_t * pNode, int Value ) { pNode->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)Value; }
45
49
61int 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
91Vec_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
115clk = Abc_Clock();
116 FiBest = Abc_NtkRetimeSearch_rec( pNtk, vNodes, vLatches, 0, FiMax, nIterLimit, fVerbose );
117clkIter = 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
172int 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
196int 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
205 Abc_NodeSetLValue( pObj, -ABC_INFINITY );
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
249int 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 )
273 Abc_NodeSetLValue( Abc_ObjFanout0(pObj), Abc_NodeGetLValue(Abc_ObjFanin0(Abc_ObjFanin0(pObj))) - Fi );
274 return fChange;
275}
276
288int Abc_NtkRetimePosOverLimit( Abc_Ntk_t * pNtk, int Fi )
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
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;
317 Abc_NodeSetTravIdCurrent(pObj);
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
338Vec_Ptr_t * Abc_ManCollectLatches( Abc_Ntk_t * pNtk )
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
362int 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
399
400
402
struct Abc_Obj_t_ Abc_Obj_t
Definition abc.h:116
#define Abc_NtkForEachPo(pNtk, pPo, i)
Definition abc.h:520
#define Abc_NtkForEachLatch(pNtk, pObj, i)
Definition abc.h:500
ABC_DLL Vec_Ptr_t * Abc_NtkDfs(Abc_Ntk_t *pNtk, int fCollectAll)
Definition abcDfs.c:82
ABC_DLL int Abc_NtkCheck(Abc_Ntk_t *pNtk)
FUNCTION DEFINITIONS ///.
Definition abcCheck.c:64
#define Abc_NtkForEachObj(pNtk, pObj, i)
ITERATORS ///.
Definition abc.h:449
#define Abc_ObjForEachFanin(pObj, pFanin, i)
Definition abc.h:527
struct Abc_Ntk_t_ Abc_Ntk_t
Definition abc.h:115
ABC_DLL int Abc_NtkLevel(Abc_Ntk_t *pNtk)
Definition abcDfs.c:1449
#define Abc_NtkForEachNode(pNtk, pNode, i)
Definition abc.h:464
ABC_INT64_T abctime
Definition abc_global.h:332
#define ABC_INFINITY
MACRO DEFINITIONS ///.
Definition abc_global.h:250
#define ABC_NAMESPACE_IMPL_START
#define ABC_NAMESPACE_IMPL_END
typedefABC_NAMESPACE_IMPL_START struct Vec_Int_t_ Vec_Int_t
DECLARATIONS ///.
Definition bblif.c:37
void Abc_NtkRetimeNode(Abc_Obj_t *pObj, int fForward, int fInitial)
Definition retIncrem.c:324
int Abc_NtkRetimeNodeIsEnabled(Abc_Obj_t *pObj, int fForward)
Definition retIncrem.c:293
int Abc_NtkRetimeLValue(Abc_Ntk_t *pNtk, int nIterLimit, int fVerbose)
FUNCTION DEFINITIONS ///.
Definition retLvalue.c:61
@ ABC_RET_UPDATE_FAIL
Definition retLvalue.c:31
@ ABC_RET_UPDATE_YES
Definition retLvalue.c:31
@ ABC_RET_UPDATE_NO
Definition retLvalue.c:31
void Abc_ManCollectLatches_rec(Abc_Obj_t *pObj, Vec_Ptr_t *vLatches)
Definition retLvalue.c:309
int Id
Definition abc.h:132
Abc_Obj_t * pCopy
Definition abc.h:148
#define assert(ex)
Definition util_old.h:213
typedefABC_NAMESPACE_HEADER_START struct Vec_Ptr_t_ Vec_Ptr_t
INCLUDES ///.
Definition vecPtr.h:42
#define Vec_PtrForEachEntry(Type, vVec, pEntry, i)
MACRO DEFINITIONS ///.
Definition vecPtr.h:55