1 /**CFile****************************************************************
2
3 FileName [abcPrint.c]
4
5 SystemName [ABC: Logic synthesis and verification system.]
6
7 PackageName [Network and node package.]
8
9 Synopsis [Printing statistics.]
10
11 Author [Alan Mishchenko]
12
13 Affiliation [UC Berkeley]
14
15 Date [Ver. 1.0. Started - June 20, 2005.]
16
17 Revision [$Id: abcPrint.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
18
19 ***********************************************************************/
20
21 #include <math.h>
22 #include "base/abc/abc.h"
23 #include "bool/dec/dec.h"
24 #include "base/main/main.h"
25 #include "map/mio/mio.h"
26 #include "aig/aig/aig.h"
27 #include "map/if/if.h"
28
29 #ifdef ABC_USE_CUDD
30 #include "bdd/extrab/extraBdd.h"
31 #endif
32
33 #ifdef WIN32
34 #include <windows.h>
35 #endif
36
37 ABC_NAMESPACE_IMPL_START
38
39
40 ////////////////////////////////////////////////////////////////////////
41 /// DECLARATIONS ///
42 ////////////////////////////////////////////////////////////////////////
43
44 //extern int s_TotalNodes = 0;
45 //extern int s_TotalChanges = 0;
46
47 abctime s_MappingTime = 0;
48 int s_MappingMem = 0;
49 abctime s_ResubTime = 0;
50 abctime s_ResynTime = 0;
51
52 ////////////////////////////////////////////////////////////////////////
53 /// FUNCTION DEFINITIONS ///
54 ////////////////////////////////////////////////////////////////////////
55
56 /**Function*************************************************************
57
58 Synopsis [If the network is best, saves it in "best.blif" and returns 1.]
59
60 Description [If the networks are incomparable, saves the new network,
61 returns its parameters in the internal parameter structure, and returns 1.
62 If the new network is not a logic network, quits without saving and returns 0.]
63
64 SideEffects []
65
66 SeeAlso []
67
68 ***********************************************************************/
Abc_NtkCompareAndSaveBest(Abc_Ntk_t * pNtk)69 int Abc_NtkCompareAndSaveBest( Abc_Ntk_t * pNtk )
70 {
71 extern void Io_Write( Abc_Ntk_t * pNtk, char * pFileName, Io_FileType_t FileType );
72 static struct ParStruct {
73 char * pName; // name of the best saved network
74 int Depth; // depth of the best saved network
75 int Flops; // flops in the best saved network
76 int Nodes; // nodes in the best saved network
77 int Edges; // edges in the best saved network
78 int nPis; // the number of primary inputs
79 int nPos; // the number of primary outputs
80 } ParsNew, ParsBest = { 0 };
81 char * pFileNameOut;
82 // free storage for the name
83 if ( pNtk == NULL )
84 {
85 ABC_FREE( ParsBest.pName );
86 return 0;
87 }
88 // quit if not a logic network
89 if ( !Abc_NtkIsLogic(pNtk) )
90 return 0;
91 // get the parameters
92 ParsNew.Depth = Abc_NtkLevel( pNtk );
93 ParsNew.Flops = Abc_NtkLatchNum( pNtk );
94 ParsNew.Nodes = Abc_NtkNodeNum( pNtk );
95 ParsNew.Edges = Abc_NtkGetTotalFanins( pNtk );
96 ParsNew.nPis = Abc_NtkPiNum( pNtk );
97 ParsNew.nPos = Abc_NtkPoNum( pNtk );
98 // reset the parameters if the network has the same name
99 if ( ParsBest.pName == NULL ||
100 strcmp(ParsBest.pName, pNtk->pName) ||
101 ParsBest.Depth > ParsNew.Depth ||
102 (ParsBest.Depth == ParsNew.Depth && ParsBest.Flops > ParsNew.Flops) ||
103 (ParsBest.Depth == ParsNew.Depth && ParsBest.Flops == ParsNew.Flops && ParsBest.Edges > ParsNew.Edges) )
104 {
105 ABC_FREE( ParsBest.pName );
106 ParsBest.pName = Extra_UtilStrsav( pNtk->pName );
107 ParsBest.Depth = ParsNew.Depth;
108 ParsBest.Flops = ParsNew.Flops;
109 ParsBest.Nodes = ParsNew.Nodes;
110 ParsBest.Edges = ParsNew.Edges;
111 ParsBest.nPis = ParsNew.nPis;
112 ParsBest.nPos = ParsNew.nPos;
113 // writ the network
114 if ( strcmp(pNtk->pSpec + strlen(pNtk->pSpec) - strlen("_best.blif"), "_best.blif") )
115 pFileNameOut = Extra_FileNameGenericAppend( pNtk->pSpec, "_best.blif" );
116 else
117 pFileNameOut = pNtk->pSpec;
118 Io_Write( pNtk, pFileNameOut, IO_FILE_BLIF );
119 return 1;
120 }
121 return 0;
122 }
123
124 /**Function*************************************************************
125
126 Synopsis [Collects memory usage.]
127
128 Description []
129
130 SideEffects []
131
132 SeeAlso []
133
134 ***********************************************************************/
Abc_NtkMemory(Abc_Ntk_t * p)135 double Abc_NtkMemory( Abc_Ntk_t * p )
136 {
137 Abc_Obj_t * pObj; int i;
138 double Memory = sizeof(Abc_Ntk_t);
139 Memory += sizeof(Abc_Obj_t) * Abc_NtkObjNum(p);
140 Memory += Vec_PtrMemory(p->vPis);
141 Memory += Vec_PtrMemory(p->vPos);
142 Memory += Vec_PtrMemory(p->vCis);
143 Memory += Vec_PtrMemory(p->vCos);
144 Memory += Vec_PtrMemory(p->vObjs);
145 Memory += Vec_IntMemory(&p->vTravIds);
146 Memory += Vec_IntMemory(p->vLevelsR);
147 Abc_NtkForEachObj( p, pObj, i )
148 Memory += sizeof(int) * (Vec_IntCap(&pObj->vFanins) + Vec_IntCap(&pObj->vFanouts));
149 return Memory;
150 }
151
152 /**Function*************************************************************
153
154 Synopsis [Marks nodes for power-optimization.]
155
156 Description []
157
158 SideEffects []
159
160 SeeAlso []
161
162 ***********************************************************************/
Abc_NtkMfsTotalSwitching(Abc_Ntk_t * pNtk)163 float Abc_NtkMfsTotalSwitching( Abc_Ntk_t * pNtk )
164 {
165 extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters );
166 extern Vec_Int_t * Saig_ManComputeSwitchProbs( Aig_Man_t * p, int nFrames, int nPref, int fProbOne );
167 Vec_Int_t * vSwitching;
168 float * pSwitching;
169 Abc_Ntk_t * pNtkStr;
170 Aig_Man_t * pAig;
171 Aig_Obj_t * pObjAig;
172 Abc_Obj_t * pObjAbc, * pObjAbc2;
173 float Result = (float)0;
174 int i;
175 // strash the network
176 pNtkStr = Abc_NtkStrash( pNtk, 0, 1, 0 );
177 Abc_NtkForEachObj( pNtk, pObjAbc, i )
178 if ( (pObjAbc->pTemp && Abc_ObjRegular((Abc_Obj_t *)pObjAbc->pTemp)->Type == ABC_FUNC_NONE) || (!Abc_ObjIsCi(pObjAbc) && !Abc_ObjIsNode(pObjAbc)) )
179 pObjAbc->pTemp = NULL;
180 // map network into an AIG
181 pAig = Abc_NtkToDar( pNtkStr, 0, (int)(Abc_NtkLatchNum(pNtk) > 0) );
182 vSwitching = Saig_ManComputeSwitchProbs( pAig, 48, 16, 0 );
183 pSwitching = (float *)vSwitching->pArray;
184 Abc_NtkForEachObj( pNtk, pObjAbc, i )
185 {
186 if ( (pObjAbc2 = Abc_ObjRegular((Abc_Obj_t *)pObjAbc->pTemp)) && (pObjAig = Aig_Regular((Aig_Obj_t *)pObjAbc2->pTemp)) )
187 {
188 Result += Abc_ObjFanoutNum(pObjAbc) * pSwitching[pObjAig->Id];
189 // Abc_ObjPrint( stdout, pObjAbc );
190 // printf( "%d = %.2f\n", i, Abc_ObjFanoutNum(pObjAbc) * pSwitching[pObjAig->Id] );
191 }
192 }
193 Vec_IntFree( vSwitching );
194 Aig_ManStop( pAig );
195 Abc_NtkDelete( pNtkStr );
196 return Result;
197 }
198
199 /**Function*************************************************************
200
201 Synopsis [Compute area using LUT library.]
202
203 Description []
204
205 SideEffects []
206
207 SeeAlso []
208
209 ***********************************************************************/
Abc_NtkGetArea(Abc_Ntk_t * pNtk)210 float Abc_NtkGetArea( Abc_Ntk_t * pNtk )
211 {
212 If_LibLut_t * pLutLib;
213 Abc_Obj_t * pObj;
214 float Counter = 0.0;
215 int i;
216 assert( Abc_NtkIsLogic(pNtk) );
217 // get the library
218 pLutLib = (If_LibLut_t *)Abc_FrameReadLibLut();
219 if ( pLutLib && pLutLib->LutMax >= Abc_NtkGetFaninMax(pNtk) )
220 {
221 Abc_NtkForEachNode( pNtk, pObj, i )
222 Counter += pLutLib->pLutAreas[Abc_ObjFaninNum(pObj)];
223 }
224 return Counter;
225 }
226
227 /**Function*************************************************************
228
229 Synopsis [Print the vital stats of the network.]
230
231 Description []
232
233 SideEffects []
234
235 SeeAlso []
236
237 ***********************************************************************/
Abc_NtkPrintStats(Abc_Ntk_t * pNtk,int fFactored,int fSaveBest,int fDumpResult,int fUseLutLib,int fPrintMuxes,int fPower,int fGlitch,int fSkipBuf,int fSkipSmall,int fPrintMem)238 void Abc_NtkPrintStats( Abc_Ntk_t * pNtk, int fFactored, int fSaveBest, int fDumpResult, int fUseLutLib, int fPrintMuxes, int fPower, int fGlitch, int fSkipBuf, int fSkipSmall, int fPrintMem )
239 {
240 int nSingles = fSkipBuf ? Abc_NtkGetBufNum(pNtk) : 0;
241 if ( fPrintMuxes && Abc_NtkIsStrash(pNtk) )
242 {
243 extern int Abc_NtkCountMuxes( Abc_Ntk_t * pNtk );
244 int nXors = Abc_NtkGetExorNum(pNtk);
245 int nMuxs = Abc_NtkCountMuxes(pNtk) - nXors;
246 int nAnds = Abc_NtkNodeNum(pNtk) - (nMuxs + nXors) * 3 - nSingles;
247 Abc_Print( 1, "XMA stats: " );
248 Abc_Print( 1,"Xor =%7d (%6.2f %%) ", nXors, 300.0 * nXors / Abc_NtkNodeNum(pNtk) );
249 Abc_Print( 1,"Mux =%7d (%6.2f %%) ", nMuxs, 300.0 * nMuxs / Abc_NtkNodeNum(pNtk) );
250 Abc_Print( 1,"And =%7d (%6.2f %%) ", nAnds, 100.0 * nAnds / Abc_NtkNodeNum(pNtk) );
251 Abc_Print( 1,"Total =%7d", nAnds + nXors + nMuxs );
252 Abc_Print( 1,"\n" );
253 return;
254 }
255 if ( fSaveBest )
256 Abc_NtkCompareAndSaveBest( pNtk );
257 /*
258 if ( fDumpResult )
259 {
260 char Buffer[1000] = {0};
261 const char * pNameGen = pNtk->pSpec? Extra_FileNameGeneric( pNtk->pSpec ) : "nameless_";
262 sprintf( Buffer, "%s_dump.blif", pNameGen );
263 Io_Write( pNtk, Buffer, IO_FILE_BLIF );
264 if ( pNtk->pSpec ) ABC_FREE( pNameGen );
265 }
266 */
267
268 // if ( Abc_NtkIsStrash(pNtk) )
269 // Abc_AigCountNext( pNtk->pManFunc );
270
271 #ifdef WIN32
272 SetConsoleTextAttribute( GetStdHandle(STD_OUTPUT_HANDLE), 15 ); // bright
273 Abc_Print( 1,"%-30s:", pNtk->pName );
274 SetConsoleTextAttribute( GetStdHandle(STD_OUTPUT_HANDLE), 7 ); // normal
275 #else
276 Abc_Print( 1,"%s%-30s:%s", "\033[1;37m", pNtk->pName, "\033[0m" ); // bright
277 #endif
278 Abc_Print( 1," i/o =%5d/%5d", Abc_NtkPiNum(pNtk), Abc_NtkPoNum(pNtk) );
279 if ( Abc_NtkConstrNum(pNtk) )
280 Abc_Print( 1,"(c=%d)", Abc_NtkConstrNum(pNtk) );
281 Abc_Print( 1," lat =%5d", Abc_NtkLatchNum(pNtk) );
282 if ( pNtk->nBarBufs )
283 Abc_Print( 1,"(b=%d)", pNtk->nBarBufs );
284 if ( Abc_NtkIsNetlist(pNtk) )
285 {
286 Abc_Print( 1," net =%5d", Abc_NtkNetNum(pNtk) );
287 Abc_Print( 1," nd =%5d", fSkipSmall ? Abc_NtkGetLargeNodeNum(pNtk) : Abc_NtkNodeNum(pNtk) - nSingles );
288 Abc_Print( 1," wbox =%3d", Abc_NtkWhiteboxNum(pNtk) );
289 Abc_Print( 1," bbox =%3d", Abc_NtkBlackboxNum(pNtk) );
290 }
291 else if ( Abc_NtkIsStrash(pNtk) )
292 {
293 Abc_Print( 1," and =%7d", Abc_NtkNodeNum(pNtk) );
294 if ( Abc_NtkGetChoiceNum(pNtk) )
295 Abc_Print( 1," (choice = %d)", Abc_NtkGetChoiceNum(pNtk) );
296 }
297 else
298 {
299 Abc_Print( 1," nd =%6d", fSkipSmall ? Abc_NtkGetLargeNodeNum(pNtk) : Abc_NtkNodeNum(pNtk) - nSingles );
300 Abc_Print( 1," edge =%7d", Abc_NtkGetTotalFanins(pNtk) - nSingles );
301 }
302
303 if ( Abc_NtkIsStrash(pNtk) || Abc_NtkIsNetlist(pNtk) )
304 {
305 }
306 else if ( Abc_NtkHasSop(pNtk) )
307 {
308
309 Abc_Print( 1," cube =%6d", Abc_NtkGetCubeNum(pNtk) - nSingles );
310 if ( fFactored )
311 Abc_Print( 1," lit(sop) =%6d", Abc_NtkGetLitNum(pNtk) - nSingles );
312 if ( fFactored )
313 Abc_Print( 1," lit(fac) =%6d", Abc_NtkGetLitFactNum(pNtk) - nSingles );
314 }
315 else if ( Abc_NtkHasAig(pNtk) )
316 Abc_Print( 1," aig =%6d", Abc_NtkGetAigNodeNum(pNtk) - nSingles );
317 else if ( Abc_NtkHasBdd(pNtk) )
318 Abc_Print( 1," bdd =%6d", Abc_NtkGetBddNodeNum(pNtk) - nSingles );
319 else if ( Abc_NtkHasMapping(pNtk) )
320 {
321 int fHasTimeMan = (int)(pNtk->pManTime != NULL);
322 assert( pNtk->pManFunc == Abc_FrameReadLibGen() );
323 Abc_Print( 1," area =%5.2f", Abc_NtkGetMappedArea(pNtk) );
324 Abc_Print( 1," delay =%5.2f", Abc_NtkDelayTrace(pNtk, NULL, NULL, 0) );
325 if ( !fHasTimeMan && pNtk->pManTime )
326 {
327 Abc_ManTimeStop( pNtk->pManTime );
328 pNtk->pManTime = NULL;
329 }
330 }
331 else if ( !Abc_NtkHasBlackbox(pNtk) )
332 {
333 assert( 0 );
334 }
335
336 if ( Abc_NtkIsStrash(pNtk) )
337 {
338 extern int Abc_NtkGetMultiRefNum( Abc_Ntk_t * pNtk );
339 Abc_Print( 1," lev =%3d", Abc_AigLevel(pNtk) );
340 // Abc_Print( 1," ff = %5d", Abc_NtkNodeNum(pNtk) + 2 * (Abc_NtkCoNum(pNtk)+Abc_NtkGetMultiRefNum(pNtk)) );
341 // Abc_Print( 1," var = %5d", Abc_NtkCiNum(pNtk) + Abc_NtkCoNum(pNtk)+Abc_NtkGetMultiRefNum(pNtk) );
342 }
343 else
344 Abc_Print( 1," lev = %d", Abc_NtkLevel(pNtk) );
345 if ( pNtk->nBarBufs2 )
346 Abc_Print( 1," buf = %d", pNtk->nBarBufs2 );
347 if ( fUseLutLib && Abc_FrameReadLibLut() )
348 Abc_Print( 1," delay =%5.2f", Abc_NtkDelayTraceLut(pNtk, 1) );
349 if ( fUseLutLib && Abc_FrameReadLibLut() )
350 Abc_Print( 1," area =%5.2f", Abc_NtkGetArea(pNtk) );
351 if ( fPower )
352 Abc_Print( 1," power =%7.2f", Abc_NtkMfsTotalSwitching(pNtk) );
353 if ( fGlitch )
354 {
355 if ( Abc_NtkIsLogic(pNtk) && Abc_NtkGetFaninMax(pNtk) <= 6 )
356 Abc_Print( 1," glitch =%7.2f %%", Abc_NtkMfsTotalGlitching(pNtk, 4000, 8, 0) );
357 else
358 printf( "\nCurrently computes glitching only for K-LUT networks with K <= 6." );
359 }
360 if ( fPrintMem )
361 Abc_Print( 1," mem =%5.2f MB", Abc_NtkMemory(pNtk)/(1<<20) );
362 Abc_Print( 1,"\n" );
363
364 // print the statistic into a file
365 if ( fDumpResult )
366 {
367 FILE * pTable = fopen( "abcstats.txt", "a+" );
368 fprintf( pTable, "%s ", pNtk->pName );
369 fprintf( pTable, "%d ", Abc_NtkPiNum(pNtk) );
370 fprintf( pTable, "%d ", Abc_NtkPoNum(pNtk) );
371 fprintf( pTable, "%d ", Abc_NtkNodeNum(pNtk) );
372 fprintf( pTable, "%d ", Abc_NtkGetTotalFanins(pNtk) );
373 fprintf( pTable, "%d ", Abc_NtkLevel(pNtk) );
374 fprintf( pTable, "\n" );
375 fclose( pTable );
376 }
377 /*
378 {
379 FILE * pTable;
380 pTable = fopen( "ibm/seq_stats.txt", "a+" );
381 // fprintf( pTable, "%s ", pNtk->pName );
382 // fprintf( pTable, "%d ", Abc_NtkPiNum(pNtk) );
383 // fprintf( pTable, "%d ", Abc_NtkPoNum(pNtk) );
384 fprintf( pTable, "%d ", Abc_NtkNodeNum(pNtk) );
385 fprintf( pTable, "%d ", Abc_NtkLatchNum(pNtk) );
386 fprintf( pTable, "%d ", Abc_NtkLevel(pNtk) );
387 fprintf( pTable, "\n" );
388 fclose( pTable );
389 }
390 */
391
392 /*
393 // print the statistic into a file
394 {
395 FILE * pTable;
396 pTable = fopen( "ucsb/stats.txt", "a+" );
397 // fprintf( pTable, "%s ", pNtk->pSpec );
398 fprintf( pTable, "%d ", Abc_NtkNodeNum(pNtk) );
399 // fprintf( pTable, "%d ", Abc_NtkLevel(pNtk) );
400 // fprintf( pTable, "%.0f ", Abc_NtkGetMappedArea(pNtk) );
401 // fprintf( pTable, "%.2f ", Abc_NtkDelayTrace(pNtk) );
402 fprintf( pTable, "\n" );
403 fclose( pTable );
404 }
405 */
406
407 /*
408 // print the statistic into a file
409 {
410 FILE * pTable;
411 pTable = fopen( "x/stats_new.txt", "a+" );
412 fprintf( pTable, "%s ", pNtk->pName );
413 // fprintf( pTable, "%d ", Abc_NtkPiNum(pNtk) );
414 // fprintf( pTable, "%d ", Abc_NtkPoNum(pNtk) );
415 // fprintf( pTable, "%d ", Abc_NtkLevel(pNtk) );
416 // fprintf( pTable, "%d ", Abc_NtkNodeNum(pNtk) );
417 // fprintf( pTable, "%d ", Abc_NtkGetTotalFanins(pNtk) );
418 // fprintf( pTable, "%d ", Abc_NtkLatchNum(pNtk) );
419 // fprintf( pTable, "%.2f ", (float)(s_MappingMem)/(float)(1<<20) );
420 fprintf( pTable, "%.2f", (float)(s_MappingTime)/(float)(CLOCKS_PER_SEC) );
421 // fprintf( pTable, "%.2f", (float)(s_ResynTime)/(float)(CLOCKS_PER_SEC) );
422 fprintf( pTable, "\n" );
423 fclose( pTable );
424
425 s_ResynTime = 0;
426 }
427 */
428
429 /*
430 // print the statistic into a file
431 {
432 static int Counter = 0;
433 extern int timeRetime;
434 FILE * pTable;
435 Counter++;
436 pTable = fopen( "d/stats.txt", "a+" );
437 fprintf( pTable, "%s ", pNtk->pName );
438 // fprintf( pTable, "%d ", Abc_NtkPiNum(pNtk) );
439 // fprintf( pTable, "%d ", Abc_NtkPoNum(pNtk) );
440 // fprintf( pTable, "%d ", Abc_NtkLatchNum(pNtk) );
441 fprintf( pTable, "%d ", Abc_NtkNodeNum(pNtk) );
442 fprintf( pTable, "%.2f ", (float)(timeRetime)/(float)(CLOCKS_PER_SEC) );
443 fprintf( pTable, "\n" );
444 fclose( pTable );
445 }
446
447
448 s_TotalNodes += Abc_NtkNodeNum(pNtk);
449 printf( "Total nodes = %6d %6.2f MB Changes = %6d.\n",
450 s_TotalNodes, s_TotalNodes * 20.0 / (1<<20), s_TotalChanges );
451 */
452
453 // if ( Abc_NtkHasSop(pNtk) )
454 // printf( "The total number of cube pairs = %d.\n", Abc_NtkGetCubePairNum(pNtk) );
455
456 fflush( stdout );
457 if ( pNtk->pExdc )
458 Abc_NtkPrintStats( pNtk->pExdc, fFactored, fSaveBest, fDumpResult, fUseLutLib, fPrintMuxes, fPower, fGlitch, fSkipBuf, fSkipSmall, fPrintMem );
459 }
460
461 /**Function*************************************************************
462
463 Synopsis [Prints PIs/POs and LIs/LOs.]
464
465 Description []
466
467 SideEffects []
468
469 SeeAlso []
470
471 ***********************************************************************/
Abc_NtkPrintIo(FILE * pFile,Abc_Ntk_t * pNtk,int fPrintFlops)472 void Abc_NtkPrintIo( FILE * pFile, Abc_Ntk_t * pNtk, int fPrintFlops )
473 {
474 Abc_Obj_t * pObj;
475 int i;
476
477 fprintf( pFile, "Primary inputs (%d): ", Abc_NtkPiNum(pNtk) );
478 Abc_NtkForEachPi( pNtk, pObj, i )
479 fprintf( pFile, " %d=%s", i, Abc_ObjName(pObj) );
480 // fprintf( pFile, " %s(%d)", Abc_ObjName(pObj), Abc_ObjFanoutNum(pObj) );
481 fprintf( pFile, "\n" );
482
483 fprintf( pFile, "Primary outputs (%d):", Abc_NtkPoNum(pNtk) );
484 Abc_NtkForEachPo( pNtk, pObj, i )
485 fprintf( pFile, " %d=%s", i, Abc_ObjName(pObj) );
486 fprintf( pFile, "\n" );
487
488 if ( !fPrintFlops )
489 return;
490
491 fprintf( pFile, "Latches (%d): ", Abc_NtkLatchNum(pNtk) );
492 Abc_NtkForEachLatch( pNtk, pObj, i )
493 fprintf( pFile, " %s(%s=%s)", Abc_ObjName(pObj),
494 Abc_ObjName(Abc_ObjFanout0(pObj)), Abc_ObjName(Abc_ObjFanin0(pObj)) );
495 fprintf( pFile, "\n" );
496 }
497
498 /**Function*************************************************************
499
500 Synopsis [Prints statistics about latches.]
501
502 Description []
503
504 SideEffects []
505
506 SeeAlso []
507
508 ***********************************************************************/
Abc_NtkPrintLatch(FILE * pFile,Abc_Ntk_t * pNtk)509 void Abc_NtkPrintLatch( FILE * pFile, Abc_Ntk_t * pNtk )
510 {
511 Abc_Obj_t * pLatch, * pFanin;
512 int i, Counter0, Counter1, Counter2;
513 int InitNums[4], Init;
514
515 assert( !Abc_NtkIsNetlist(pNtk) );
516 if ( Abc_NtkLatchNum(pNtk) == 0 )
517 {
518 fprintf( pFile, "The network is combinational.\n" );
519 return;
520 }
521
522 for ( i = 0; i < 4; i++ )
523 InitNums[i] = 0;
524 Counter0 = Counter1 = Counter2 = 0;
525 Abc_NtkForEachLatch( pNtk, pLatch, i )
526 {
527 Init = Abc_LatchInit( pLatch );
528 assert( Init < 4 );
529 InitNums[Init]++;
530
531 pFanin = Abc_ObjFanin0(Abc_ObjFanin0(pLatch));
532 if ( Abc_NtkIsLogic(pNtk) )
533 {
534 if ( !Abc_NodeIsConst(pFanin) )
535 continue;
536 }
537 else if ( Abc_NtkIsStrash(pNtk) )
538 {
539 if ( !Abc_AigNodeIsConst(pFanin) )
540 continue;
541 }
542 else
543 assert( 0 );
544
545 // the latch input is a constant node
546 Counter0++;
547 if ( Abc_LatchIsInitDc(pLatch) )
548 {
549 Counter1++;
550 continue;
551 }
552 // count the number of cases when the constant is equal to the initial value
553 if ( Abc_NtkIsStrash(pNtk) )
554 {
555 if ( Abc_LatchIsInit1(pLatch) == !Abc_ObjFaninC0(pLatch) )
556 Counter2++;
557 }
558 else
559 {
560 if ( Abc_LatchIsInit1(pLatch) == Abc_NodeIsConst1(Abc_ObjFanin0(Abc_ObjFanin0(pLatch))) )
561 Counter2++;
562 }
563 }
564 // fprintf( pFile, "%-15s: ", pNtk->pName );
565 fprintf( pFile, "Total latches = %5d. Init0 = %d. Init1 = %d. InitDC = %d. Const data = %d.\n",
566 Abc_NtkLatchNum(pNtk), InitNums[1], InitNums[2], InitNums[3], Counter0 );
567 // fprintf( pFile, "Const fanin = %3d. DC init = %3d. Matching init = %3d. ", Counter0, Counter1, Counter2 );
568 // fprintf( pFile, "Self-feed latches = %2d.\n", -1 ); //Abc_NtkCountSelfFeedLatches(pNtk) );
569 }
570
571 /**Function*************************************************************
572
573 Synopsis [Prints the distribution of fanins/fanouts in the network.]
574
575 Description []
576
577 SideEffects []
578
579 SeeAlso []
580
581 ***********************************************************************/
Abc_NtkFaninFanoutCounters(Abc_Ntk_t * pNtk,Vec_Int_t * vFan,Vec_Int_t * vFon,Vec_Int_t * vFanR,Vec_Int_t * vFonR)582 void Abc_NtkFaninFanoutCounters( Abc_Ntk_t * pNtk, Vec_Int_t * vFan, Vec_Int_t * vFon, Vec_Int_t * vFanR, Vec_Int_t * vFonR )
583 {
584 Abc_Obj_t * pNode;
585 int i, nFanins, nFanouts;
586 int nFaninsMax = 0, nFanoutsMax = 0;
587 Abc_NtkForEachObj( pNtk, pNode, i )
588 {
589 nFaninsMax = Abc_MaxInt( nFaninsMax, Abc_ObjFaninNum(pNode) );
590 nFanoutsMax = Abc_MaxInt( nFanoutsMax, Abc_ObjFanoutNum(pNode) );
591 }
592 Vec_IntFill( vFan, nFaninsMax + 1, 0 );
593 Vec_IntFill( vFon, nFanoutsMax + 1, 0 );
594 Vec_IntFill( vFanR, nFaninsMax + 1, 0 );
595 Vec_IntFill( vFonR, nFanoutsMax + 1, 0 );
596 Abc_NtkForEachObjReverse( pNtk, pNode, i )
597 {
598 nFanins = Abc_ObjFaninNum( pNode );
599 nFanouts = Abc_ObjFanoutNum( pNode );
600 Vec_IntAddToEntry( vFan, nFanins, 1 );
601 Vec_IntAddToEntry( vFon, nFanouts, 1 );
602 Vec_IntWriteEntry( vFanR, nFanins, i );
603 Vec_IntWriteEntry( vFonR, nFanouts, i );
604 }
605 }
Abc_NtkInputOutputCounters(Abc_Ntk_t * pNtk,Vec_Int_t * vFan,Vec_Int_t * vFon,Vec_Int_t * vFanR,Vec_Int_t * vFonR)606 void Abc_NtkInputOutputCounters( Abc_Ntk_t * pNtk, Vec_Int_t * vFan, Vec_Int_t * vFon, Vec_Int_t * vFanR, Vec_Int_t * vFonR )
607 {
608 Abc_Obj_t * pNode;
609 int i, nFanins, nFanouts;
610 int nFaninsMax = 0, nFanoutsMax = 0;
611 Abc_NtkForEachCi( pNtk, pNode, i )
612 nFanoutsMax = Abc_MaxInt( nFanoutsMax, Abc_ObjFanoutNum(pNode) );
613 Abc_NtkForEachCo( pNtk, pNode, i )
614 nFaninsMax = Abc_MaxInt( nFaninsMax, Abc_ObjFaninNum(Abc_ObjFanin0(pNode)) );
615 Vec_IntFill( vFan, nFaninsMax + 1, 0 );
616 Vec_IntFill( vFon, nFanoutsMax + 1, 0 );
617 Vec_IntFill( vFanR, nFaninsMax + 1, 0 );
618 Vec_IntFill( vFonR, nFanoutsMax + 1, 0 );
619 Abc_NtkForEachCi( pNtk, pNode, i )
620 {
621 nFanouts = Abc_ObjFanoutNum( pNode );
622 Vec_IntAddToEntry( vFon, nFanouts, 1 );
623 Vec_IntWriteEntry( vFonR, nFanouts, Abc_ObjId(pNode) );
624 }
625 Abc_NtkForEachCo( pNtk, pNode, i )
626 {
627 nFanins = Abc_ObjFaninNum( Abc_ObjFanin0(pNode) );
628 Vec_IntAddToEntry( vFan, nFanins, 1 );
629 Vec_IntWriteEntry( vFanR, nFanins, Abc_ObjId(pNode) );
630 }
631 }
Abc_NtkCollectCoSupps(Abc_Ntk_t * pNtk,int fVerbose)632 Vec_Int_t * Abc_NtkCollectCoSupps( Abc_Ntk_t * pNtk, int fVerbose )
633 {
634 abctime clk = Abc_Clock();
635 Abc_Obj_t * pNode; int i, k;
636 Vec_Ptr_t * vNodes = Abc_NtkDfs( pNtk, 0 );
637 Vec_Int_t * vFanin, * vFanout, * vTemp = Vec_IntAlloc( 0 );
638 Vec_Int_t * vSuppsCo = Vec_IntAlloc( Abc_NtkCoNum(pNtk) );
639 Vec_Wec_t * vSupps = Vec_WecStart( Abc_NtkObjNumMax(pNtk) );
640 Abc_NtkForEachCi( pNtk, pNode, i )
641 Vec_IntPush( Vec_WecEntry(vSupps, Abc_ObjId(pNode)), i );
642 Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i )
643 {
644 vFanout = Vec_WecEntry(vSupps, Abc_ObjId(pNode));
645 for ( k = 0; k < Abc_ObjFaninNum(pNode); k++ )
646 {
647 vFanin = Vec_WecEntry(vSupps, Abc_ObjFaninId(pNode, k));
648 Vec_IntTwoMerge2( vFanout, vFanin, vTemp );
649 ABC_SWAP( Vec_Int_t, *vFanout, *vTemp );
650 }
651 }
652 Abc_NtkForEachCo( pNtk, pNode, i )
653 Vec_IntPush( vSuppsCo, Vec_IntSize(Vec_WecEntry(vSupps, Abc_ObjFaninId0(pNode))) );
654 Vec_WecFree( vSupps );
655 Vec_PtrFree( vNodes );
656 Vec_IntFree( vTemp );
657 if ( fVerbose )
658 Abc_PrintTime( 1, "Input support computation", Abc_Clock() - clk );
659 //Vec_IntPrint( vSuppsCo );
660 return vSuppsCo;
661 }
Abc_NtkCollectCiSupps(Abc_Ntk_t * pNtk,int fVerbose)662 Vec_Int_t * Abc_NtkCollectCiSupps( Abc_Ntk_t * pNtk, int fVerbose )
663 {
664 abctime clk = Abc_Clock();
665 Abc_Obj_t * pNode; int i, k;
666 Vec_Ptr_t * vNodes = Abc_NtkDfs( pNtk, 0 );
667 Vec_Int_t * vFanin, * vFanout, * vTemp = Vec_IntAlloc( 0 );
668 Vec_Int_t * vSuppsCi = Vec_IntAlloc( Abc_NtkCiNum(pNtk) );
669 Vec_Wec_t * vSupps = Vec_WecStart( Abc_NtkObjNumMax(pNtk) );
670 Abc_NtkForEachCo( pNtk, pNode, i )
671 {
672 vFanout = Vec_WecEntry(vSupps, Abc_ObjId(pNode));
673 vFanin = Vec_WecEntry(vSupps, Abc_ObjFaninId0(pNode));
674 Vec_IntPush( vFanout, i );
675 Vec_IntTwoMerge2( vFanin, vFanout, vTemp );
676 ABC_SWAP( Vec_Int_t, *vFanin, *vTemp );
677 }
678 Vec_PtrForEachEntryReverse( Abc_Obj_t *, vNodes, pNode, i )
679 {
680 vFanout = Vec_WecEntry(vSupps, Abc_ObjId(pNode));
681 for ( k = 0; k < Abc_ObjFaninNum(pNode); k++ )
682 {
683 vFanin = Vec_WecEntry(vSupps, Abc_ObjFaninId(pNode, k));
684 Vec_IntTwoMerge2( vFanin, vFanout, vTemp );
685 ABC_SWAP( Vec_Int_t, *vFanin, *vTemp );
686 }
687 }
688 Abc_NtkForEachCi( pNtk, pNode, i )
689 Vec_IntPush( vSuppsCi, Vec_IntSize(Vec_WecEntry(vSupps, Abc_ObjId(pNode))) );
690 Vec_WecFree( vSupps );
691 Vec_PtrFree( vNodes );
692 Vec_IntFree( vTemp );
693 if ( fVerbose )
694 Abc_PrintTime( 1, "Output support computation", Abc_Clock() - clk );
695 //Vec_IntPrint( vSuppsCi );
696 return vSuppsCi;
697 }
Abc_NtkInOutSupportCounters(Abc_Ntk_t * pNtk,Vec_Int_t * vFan,Vec_Int_t * vFon,Vec_Int_t * vFanR,Vec_Int_t * vFonR)698 void Abc_NtkInOutSupportCounters( Abc_Ntk_t * pNtk, Vec_Int_t * vFan, Vec_Int_t * vFon, Vec_Int_t * vFanR, Vec_Int_t * vFonR )
699 {
700 Abc_Obj_t * pNode;
701 Vec_Int_t * vSuppsCo = Abc_NtkCollectCoSupps( pNtk, 1 );
702 Vec_Int_t * vSuppsCi = Abc_NtkCollectCiSupps( pNtk, 1 );
703 int i, nFanins, nFanouts;
704 int nFaninsMax = Vec_IntFindMax( vSuppsCo );
705 int nFanoutsMax = Vec_IntFindMax( vSuppsCi );
706 Vec_IntFill( vFan, nFaninsMax + 1, 0 );
707 Vec_IntFill( vFon, nFanoutsMax + 1, 0 );
708 Vec_IntFill( vFanR, nFaninsMax + 1, 0 );
709 Vec_IntFill( vFonR, nFanoutsMax + 1, 0 );
710 Abc_NtkForEachCo( pNtk, pNode, i )
711 {
712 nFanins = Vec_IntEntry( vSuppsCo, i );
713 Vec_IntAddToEntry( vFan, nFanins, 1 );
714 Vec_IntWriteEntry( vFanR, nFanins, Abc_ObjId(pNode) );
715 }
716 Abc_NtkForEachCi( pNtk, pNode, i )
717 {
718 nFanouts = Vec_IntEntry( vSuppsCi, i );
719 Vec_IntAddToEntry( vFon, nFanouts, 1 );
720 Vec_IntWriteEntry( vFonR, nFanouts, Abc_ObjId(pNode) );
721 }
722 Vec_IntFree( vSuppsCo );
723 Vec_IntFree( vSuppsCi );
724 }
725
Abc_NtkCollectCoCones(Abc_Ntk_t * pNtk,int fVerbose)726 Vec_Int_t * Abc_NtkCollectCoCones( Abc_Ntk_t * pNtk, int fVerbose )
727 {
728 abctime clk = Abc_Clock();
729 Abc_Obj_t * pNode; int i, k;
730 Vec_Ptr_t * vNodes = Abc_NtkDfs( pNtk, 0 );
731 Vec_Int_t * vFanin, * vFanout, * vTemp = Vec_IntAlloc( 0 );
732 Vec_Int_t * vSuppsCo = Vec_IntAlloc( Abc_NtkCoNum(pNtk) );
733 Vec_Wec_t * vSupps = Vec_WecStart( Abc_NtkObjNumMax(pNtk) );
734 Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i )
735 {
736 vFanout = Vec_WecEntry(vSupps, Abc_ObjId(pNode));
737 for ( k = 0; k < Abc_ObjFaninNum(pNode); k++ )
738 {
739 vFanin = Vec_WecEntry(vSupps, Abc_ObjFaninId(pNode, k));
740 Vec_IntTwoMerge2( vFanout, vFanin, vTemp );
741 ABC_SWAP( Vec_Int_t, *vFanout, *vTemp );
742 }
743 Vec_IntPush( vFanout, i );
744 }
745 Abc_NtkForEachCo( pNtk, pNode, i )
746 Vec_IntPush( vSuppsCo, Vec_IntSize(Vec_WecEntry(vSupps, Abc_ObjFaninId0(pNode))) );
747 Vec_WecFree( vSupps );
748 Vec_PtrFree( vNodes );
749 Vec_IntFree( vTemp );
750 if ( fVerbose )
751 Abc_PrintTime( 1, "Input cone computation", Abc_Clock() - clk );
752 //Vec_IntPrint( vSuppsCo );
753 return vSuppsCo;
754 }
Abc_NtkCollectCiCones(Abc_Ntk_t * pNtk,int fVerbose)755 Vec_Int_t * Abc_NtkCollectCiCones( Abc_Ntk_t * pNtk, int fVerbose )
756 {
757 abctime clk = Abc_Clock();
758 Abc_Obj_t * pNode; int i, k;
759 Vec_Ptr_t * vNodes = Abc_NtkDfs( pNtk, 0 );
760 Vec_Int_t * vFanin, * vFanout, * vTemp = Vec_IntAlloc( 0 );
761 Vec_Int_t * vSuppsCi = Vec_IntAlloc( Abc_NtkCiNum(pNtk) );
762 Vec_Wec_t * vSupps = Vec_WecStart( Abc_NtkObjNumMax(pNtk) );
763 Vec_PtrForEachEntryReverse( Abc_Obj_t *, vNodes, pNode, i )
764 {
765 vFanout = Vec_WecEntry(vSupps, Abc_ObjId(pNode));
766 Vec_IntPush( vFanout, i );
767 for ( k = 0; k < Abc_ObjFaninNum(pNode); k++ )
768 {
769 vFanin = Vec_WecEntry(vSupps, Abc_ObjFaninId(pNode, k));
770 Vec_IntTwoMerge2( vFanin, vFanout, vTemp );
771 ABC_SWAP( Vec_Int_t, *vFanin, *vTemp );
772 }
773 }
774 Abc_NtkForEachCi( pNtk, pNode, i )
775 Vec_IntPush( vSuppsCi, Vec_IntSize(Vec_WecEntry(vSupps, Abc_ObjId(pNode))) );
776 Vec_WecFree( vSupps );
777 Vec_PtrFree( vNodes );
778 Vec_IntFree( vTemp );
779 if ( fVerbose )
780 Abc_PrintTime( 1, "Output cone computation", Abc_Clock() - clk );
781 //Vec_IntPrint( vSuppsCi );
782 return vSuppsCi;
783 }
Abc_NtkInOutConeCounters(Abc_Ntk_t * pNtk,Vec_Int_t * vFan,Vec_Int_t * vFon,Vec_Int_t * vFanR,Vec_Int_t * vFonR)784 void Abc_NtkInOutConeCounters( Abc_Ntk_t * pNtk, Vec_Int_t * vFan, Vec_Int_t * vFon, Vec_Int_t * vFanR, Vec_Int_t * vFonR )
785 {
786 Abc_Obj_t * pNode;
787 Vec_Int_t * vSuppsCo = Abc_NtkCollectCoCones( pNtk, 1 );
788 Vec_Int_t * vSuppsCi = Abc_NtkCollectCiCones( pNtk, 1 );
789 int i, nFanins, nFanouts;
790 int nFaninsMax = Vec_IntFindMax( vSuppsCo );
791 int nFanoutsMax = Vec_IntFindMax( vSuppsCi );
792 Vec_IntFill( vFan, nFaninsMax + 1, 0 );
793 Vec_IntFill( vFon, nFanoutsMax + 1, 0 );
794 Vec_IntFill( vFanR, nFaninsMax + 1, 0 );
795 Vec_IntFill( vFonR, nFanoutsMax + 1, 0 );
796 Abc_NtkForEachCo( pNtk, pNode, i )
797 {
798 nFanins = Vec_IntEntry( vSuppsCo, i );
799 Vec_IntAddToEntry( vFan, nFanins, 1 );
800 Vec_IntWriteEntry( vFanR, nFanins, Abc_ObjId(pNode) );
801 }
802 Abc_NtkForEachCi( pNtk, pNode, i )
803 {
804 nFanouts = Vec_IntEntry( vSuppsCi, i );
805 Vec_IntAddToEntry( vFon, nFanouts, 1 );
806 Vec_IntWriteEntry( vFonR, nFanouts, Abc_ObjId(pNode) );
807 }
808 Vec_IntFree( vSuppsCo );
809 Vec_IntFree( vSuppsCi );
810 }
811
Abc_NtkPrintDistribInternal(FILE * pFile,Abc_Ntk_t * pNtk,char * pFanins,char * pFanouts,char * pNode,char * pFanin,char * pFanout,Vec_Int_t * vFan,Vec_Int_t * vFon,Vec_Int_t * vFanR,Vec_Int_t * vFonR)812 void Abc_NtkPrintDistribInternal( FILE * pFile, Abc_Ntk_t * pNtk, char * pFanins, char * pFanouts, char * pNode, char * pFanin, char * pFanout,
813 Vec_Int_t * vFan, Vec_Int_t * vFon, Vec_Int_t * vFanR, Vec_Int_t * vFonR )
814 {
815 int k, nSizeMax = Abc_MaxInt( Vec_IntSize(vFan), Vec_IntSize(vFon) );
816 fprintf( pFile, "The distribution of %s and %s in the network:\n", pFanins, pFanouts );
817 fprintf( pFile, " Number %s with %s %s with %s Repr1 Repr2\n", pNode, pFanin, pNode, pFanout );
818 for ( k = 0; k < nSizeMax; k++ )
819 {
820 int EntryFan = k < Vec_IntSize(vFan) ? Vec_IntEntry(vFan, k) : 0;
821 int EntryFon = k < Vec_IntSize(vFon) ? Vec_IntEntry(vFon, k) : 0;
822 if ( EntryFan == 0 && EntryFon == 0 )
823 continue;
824
825 fprintf( pFile, "%5d : ", k );
826 if ( EntryFan == 0 )
827 fprintf( pFile, " " );
828 else
829 fprintf( pFile, "%12d ", EntryFan );
830 fprintf( pFile, " " );
831 if ( EntryFon == 0 )
832 fprintf( pFile, " " );
833 else
834 fprintf( pFile, "%12d ", EntryFon );
835
836 fprintf( pFile, " " );
837 if ( EntryFan == 0 )
838 fprintf( pFile, " " );
839 else
840 fprintf( pFile, "%12s ", Abc_ObjName(Abc_NtkObj(pNtk, Vec_IntEntry(vFanR, k))) );
841 fprintf( pFile, " " );
842 if ( EntryFon == 0 )
843 fprintf( pFile, " " );
844 else
845 fprintf( pFile, "%12s ", Abc_ObjName(Abc_NtkObj(pNtk, Vec_IntEntry(vFonR, k))) );
846 fprintf( pFile, "\n" );
847 }
848 }
Abc_NtkPrintFanio(FILE * pFile,Abc_Ntk_t * pNtk,int fUseFanio,int fUsePio,int fUseSupp,int fUseCone)849 void Abc_NtkPrintFanio( FILE * pFile, Abc_Ntk_t * pNtk, int fUseFanio, int fUsePio, int fUseSupp, int fUseCone )
850 {
851 Vec_Int_t * vFan = Vec_IntAlloc( 0 );
852 Vec_Int_t * vFon = Vec_IntAlloc( 0 );
853 Vec_Int_t * vFanR = Vec_IntAlloc( 0 );
854 Vec_Int_t * vFonR = Vec_IntAlloc( 0 );
855 assert( fUseFanio + fUsePio + fUseSupp + fUseCone == 1 );
856 if ( fUseFanio )
857 {
858 Abc_NtkFaninFanoutCounters( pNtk, vFan, vFon, vFanR, vFonR );
859 Abc_NtkPrintDistribInternal( pFile, pNtk, "fanins", "fanouts", "Nodes", "fanin", "fanout", vFan, vFon, vFanR, vFonR );
860 }
861 else if ( fUsePio )
862 {
863 Abc_NtkInputOutputCounters( pNtk, vFan, vFon, vFanR, vFonR );
864 Abc_NtkPrintDistribInternal( pFile, pNtk, "fanins", "fanouts", "I/O", "fanin", "fanout", vFan, vFon, vFanR, vFonR );
865 }
866 else if ( fUseSupp )
867 {
868 Abc_NtkInOutSupportCounters( pNtk, vFan, vFon, vFanR, vFonR );
869 Abc_NtkPrintDistribInternal( pFile, pNtk, "input supports", "output supports", "I/O", "in-supp", "out-supp", vFan, vFon, vFanR, vFonR );
870 }
871 else if ( fUseCone )
872 {
873 Abc_NtkInOutConeCounters( pNtk, vFan, vFon, vFanR, vFonR );
874 Abc_NtkPrintDistribInternal( pFile, pNtk, "input cones", "output cones", "I/O", "in-cone", "out-cone", vFan, vFon, vFanR, vFonR );
875 }
876 Vec_IntFree( vFan );
877 Vec_IntFree( vFon );
878 Vec_IntFree( vFanR );
879 Vec_IntFree( vFonR );
880 }
881
882
883 /**Function*************************************************************
884
885 Synopsis [Prints the distribution of fanins/fanouts in the network.]
886
887 Description []
888
889 SideEffects []
890
891 SeeAlso []
892
893 ***********************************************************************/
Abc_NtkPrintFanioNew(FILE * pFile,Abc_Ntk_t * pNtk,int fMffc)894 void Abc_NtkPrintFanioNew( FILE * pFile, Abc_Ntk_t * pNtk, int fMffc )
895 {
896 char Buffer[100];
897 Abc_Obj_t * pNode;
898 Vec_Int_t * vFanins, * vFanouts;
899 int nFanins, nFanouts, nFaninsMax, nFanoutsMax, nFaninsAll, nFanoutsAll;
900 int i, k, nSizeMax;
901
902 // determine the largest fanin and fanout
903 nFaninsMax = nFanoutsMax = 0;
904 nFaninsAll = nFanoutsAll = 0;
905 Abc_NtkForEachNode( pNtk, pNode, i )
906 {
907 if ( fMffc && Abc_ObjFanoutNum(pNode) == 1 )
908 continue;
909 nFanins = Abc_ObjFaninNum(pNode);
910 if ( Abc_NtkIsNetlist(pNtk) )
911 nFanouts = Abc_ObjFanoutNum( Abc_ObjFanout0(pNode) );
912 else if ( fMffc )
913 nFanouts = Abc_NodeMffcSize(pNode);
914 else
915 nFanouts = Abc_ObjFanoutNum(pNode);
916 nFaninsAll += nFanins;
917 nFanoutsAll += nFanouts;
918 nFaninsMax = Abc_MaxInt( nFaninsMax, nFanins );
919 nFanoutsMax = Abc_MaxInt( nFanoutsMax, nFanouts );
920 }
921
922 // allocate storage for fanin/fanout numbers
923 nSizeMax = Abc_MaxInt( 10 * (Abc_Base10Log(nFaninsMax) + 1), 10 * (Abc_Base10Log(nFanoutsMax) + 1) );
924 vFanins = Vec_IntStart( nSizeMax );
925 vFanouts = Vec_IntStart( nSizeMax );
926
927 // count the number of fanins and fanouts
928 Abc_NtkForEachNode( pNtk, pNode, i )
929 {
930 if ( fMffc && Abc_ObjFanoutNum(pNode) == 1 )
931 continue;
932 nFanins = Abc_ObjFaninNum(pNode);
933 if ( Abc_NtkIsNetlist(pNtk) )
934 nFanouts = Abc_ObjFanoutNum( Abc_ObjFanout0(pNode) );
935 else if ( fMffc )
936 nFanouts = Abc_NodeMffcSize(pNode);
937 else
938 nFanouts = Abc_ObjFanoutNum(pNode);
939
940 if ( nFanins < 10 )
941 Vec_IntAddToEntry( vFanins, nFanins, 1 );
942 else if ( nFanins < 100 )
943 Vec_IntAddToEntry( vFanins, 10 + nFanins/10, 1 );
944 else if ( nFanins < 1000 )
945 Vec_IntAddToEntry( vFanins, 20 + nFanins/100, 1 );
946 else if ( nFanins < 10000 )
947 Vec_IntAddToEntry( vFanins, 30 + nFanins/1000, 1 );
948 else if ( nFanins < 100000 )
949 Vec_IntAddToEntry( vFanins, 40 + nFanins/10000, 1 );
950 else if ( nFanins < 1000000 )
951 Vec_IntAddToEntry( vFanins, 50 + nFanins/100000, 1 );
952 else if ( nFanins < 10000000 )
953 Vec_IntAddToEntry( vFanins, 60 + nFanins/1000000, 1 );
954
955 if ( nFanouts < 10 )
956 Vec_IntAddToEntry( vFanouts, nFanouts, 1 );
957 else if ( nFanouts < 100 )
958 Vec_IntAddToEntry( vFanouts, 10 + nFanouts/10, 1 );
959 else if ( nFanouts < 1000 )
960 Vec_IntAddToEntry( vFanouts, 20 + nFanouts/100, 1 );
961 else if ( nFanouts < 10000 )
962 Vec_IntAddToEntry( vFanouts, 30 + nFanouts/1000, 1 );
963 else if ( nFanouts < 100000 )
964 Vec_IntAddToEntry( vFanouts, 40 + nFanouts/10000, 1 );
965 else if ( nFanouts < 1000000 )
966 Vec_IntAddToEntry( vFanouts, 50 + nFanouts/100000, 1 );
967 else if ( nFanouts < 10000000 )
968 Vec_IntAddToEntry( vFanouts, 60 + nFanouts/1000000, 1 );
969 }
970
971 fprintf( pFile, "The distribution of fanins and fanouts in the network:\n" );
972 fprintf( pFile, " Number Nodes with fanin Nodes with fanout\n" );
973 for ( k = 0; k < nSizeMax; k++ )
974 {
975 if ( vFanins->pArray[k] == 0 && vFanouts->pArray[k] == 0 )
976 continue;
977 if ( k < 10 )
978 fprintf( pFile, "%15d : ", k );
979 else
980 {
981 sprintf( Buffer, "%d - %d", (int)pow((double)10, k/10) * (k%10), (int)pow((double)10, k/10) * (k%10+1) - 1 );
982 fprintf( pFile, "%15s : ", Buffer );
983 }
984 if ( vFanins->pArray[k] == 0 )
985 fprintf( pFile, " " );
986 else
987 fprintf( pFile, "%12d ", vFanins->pArray[k] );
988 fprintf( pFile, " " );
989 if ( vFanouts->pArray[k] == 0 )
990 fprintf( pFile, " " );
991 else
992 fprintf( pFile, "%12d ", vFanouts->pArray[k] );
993 fprintf( pFile, "\n" );
994 }
995 Vec_IntFree( vFanins );
996 Vec_IntFree( vFanouts );
997
998 fprintf( pFile, "Fanins: Max = %d. Ave = %.2f. Fanouts: Max = %d. Ave = %.2f.\n",
999 nFaninsMax, 1.0*nFaninsAll/Abc_NtkNodeNum(pNtk),
1000 nFanoutsMax, 1.0*nFanoutsAll/Abc_NtkNodeNum(pNtk) );
1001 /*
1002 Abc_NtkForEachCi( pNtk, pNode, i )
1003 {
1004 printf( "%d ", Abc_ObjFanoutNum(pNode) );
1005 }
1006 printf( "\n" );
1007 */
1008 }
1009
1010 /**Function*************************************************************
1011
1012 Synopsis [Prints the fanins/fanouts of a node.]
1013
1014 Description []
1015
1016 SideEffects []
1017
1018 SeeAlso []
1019
1020 ***********************************************************************/
Abc_NodePrintFanio(FILE * pFile,Abc_Obj_t * pNode)1021 void Abc_NodePrintFanio( FILE * pFile, Abc_Obj_t * pNode )
1022 {
1023 Abc_Obj_t * pNode2;
1024 int i;
1025 if ( Abc_ObjIsPo(pNode) )
1026 pNode = Abc_ObjFanin0(pNode);
1027
1028 fprintf( pFile, "Node %s", Abc_ObjName(pNode) );
1029 fprintf( pFile, "\n" );
1030
1031 fprintf( pFile, "Fanins (%d): ", Abc_ObjFaninNum(pNode) );
1032 Abc_ObjForEachFanin( pNode, pNode2, i )
1033 fprintf( pFile, " %s", Abc_ObjName(pNode2) );
1034 fprintf( pFile, "\n" );
1035
1036 fprintf( pFile, "Fanouts (%d): ", Abc_ObjFaninNum(pNode) );
1037 Abc_ObjForEachFanout( pNode, pNode2, i )
1038 fprintf( pFile, " %s", Abc_ObjName(pNode2) );
1039 fprintf( pFile, "\n" );
1040 }
1041
1042 /**Function*************************************************************
1043
1044 Synopsis [Prints the MFFCs of the nodes.]
1045
1046 Description []
1047
1048 SideEffects []
1049
1050 SeeAlso []
1051
1052 ***********************************************************************/
Abc_NtkPrintMffc(FILE * pFile,Abc_Ntk_t * pNtk)1053 void Abc_NtkPrintMffc( FILE * pFile, Abc_Ntk_t * pNtk )
1054 {
1055 Abc_Obj_t * pNode;
1056 int i;
1057 extern void Abc_NodeMffcConeSuppPrint( Abc_Obj_t * pNode );
1058 Abc_NtkForEachNode( pNtk, pNode, i )
1059 if ( Abc_ObjFanoutNum(pNode) > 1 )
1060 Abc_NodeMffcConeSuppPrint( pNode );
1061 }
1062
1063 /**Function*************************************************************
1064
1065 Synopsis [Prints the factored form of one node.]
1066
1067 Description []
1068
1069 SideEffects []
1070
1071 SeeAlso []
1072
1073 ***********************************************************************/
Abc_NtkPrintFactor(FILE * pFile,Abc_Ntk_t * pNtk,int fUseRealNames)1074 void Abc_NtkPrintFactor( FILE * pFile, Abc_Ntk_t * pNtk, int fUseRealNames )
1075 {
1076 Abc_Obj_t * pNode;
1077 int i;
1078 assert( Abc_NtkIsSopLogic(pNtk) );
1079 Abc_NtkForEachNode( pNtk, pNode, i )
1080 Abc_NodePrintFactor( pFile, pNode, fUseRealNames );
1081 }
1082
1083 /**Function*************************************************************
1084
1085 Synopsis [Prints the factored form of one node.]
1086
1087 Description []
1088
1089 SideEffects []
1090
1091 SeeAlso []
1092
1093 ***********************************************************************/
Abc_NodePrintFactor(FILE * pFile,Abc_Obj_t * pNode,int fUseRealNames)1094 void Abc_NodePrintFactor( FILE * pFile, Abc_Obj_t * pNode, int fUseRealNames )
1095 {
1096 Dec_Graph_t * pGraph;
1097 Vec_Ptr_t * vNamesIn;
1098 if ( Abc_ObjIsCo(pNode) )
1099 pNode = Abc_ObjFanin0(pNode);
1100 if ( Abc_ObjIsPi(pNode) )
1101 {
1102 fprintf( pFile, "Skipping the PI node.\n" );
1103 return;
1104 }
1105 if ( Abc_ObjIsLatch(pNode) )
1106 {
1107 fprintf( pFile, "Skipping the latch.\n" );
1108 return;
1109 }
1110 assert( Abc_ObjIsNode(pNode) );
1111 pGraph = Dec_Factor( (char *)pNode->pData );
1112 if ( fUseRealNames )
1113 {
1114 vNamesIn = Abc_NodeGetFaninNames(pNode);
1115 Dec_GraphPrint( stdout, pGraph, (char **)vNamesIn->pArray, Abc_ObjName(pNode) );
1116 Abc_NodeFreeNames( vNamesIn );
1117 }
1118 else
1119 Dec_GraphPrint( stdout, pGraph, (char **)NULL, Abc_ObjName(pNode) );
1120 Dec_GraphFree( pGraph );
1121 }
1122
1123
1124 /**Function*************************************************************
1125
1126 Synopsis [Prints the level stats of the PO node.]
1127
1128 Description []
1129
1130 SideEffects []
1131
1132 SeeAlso []
1133
1134 ***********************************************************************/
Abc_NtkPrintLevel(FILE * pFile,Abc_Ntk_t * pNtk,int fProfile,int fListNodes,int fVerbose)1135 void Abc_NtkPrintLevel( FILE * pFile, Abc_Ntk_t * pNtk, int fProfile, int fListNodes, int fVerbose )
1136 {
1137 Abc_Obj_t * pNode;
1138 int i, k, Length;
1139
1140 if ( fListNodes )
1141 {
1142 int nLevels;
1143 nLevels = Abc_NtkLevel(pNtk);
1144 printf( "Nodes by level:\n" );
1145 for ( i = 0; i <= nLevels; i++ )
1146 {
1147 printf( "%2d : ", i );
1148 Abc_NtkForEachNode( pNtk, pNode, k )
1149 if ( (int)pNode->Level == i )
1150 printf( " %s", Abc_ObjName(pNode) );
1151 printf( "\n" );
1152 }
1153 return;
1154 }
1155
1156 // print the delay profile
1157 if ( fProfile && Abc_NtkHasMapping(pNtk) )
1158 {
1159 int nIntervals = 12;
1160 float DelayMax, DelayCur, DelayDelta;
1161 int * pLevelCounts;
1162 int DelayInt, nOutsSum, nOutsTotal;
1163
1164 // get the max delay and delta
1165 DelayMax = Abc_NtkDelayTrace( pNtk, NULL, NULL, 0 );
1166 DelayDelta = DelayMax/nIntervals;
1167 // collect outputs by delay
1168 pLevelCounts = ABC_ALLOC( int, nIntervals );
1169 memset( pLevelCounts, 0, sizeof(int) * nIntervals );
1170 Abc_NtkForEachCo( pNtk, pNode, i )
1171 {
1172 if ( Abc_ObjIsNode(Abc_ObjFanin0(pNode)) && Abc_ObjFaninNum(Abc_ObjFanin0(pNode)) == 0 )
1173 DelayInt = 0;
1174 else
1175 {
1176 DelayCur = Abc_NodeReadArrivalWorst( Abc_ObjFanin0(pNode) );
1177 DelayInt = (int)(DelayCur / DelayDelta);
1178 if ( DelayInt >= nIntervals )
1179 DelayInt = nIntervals - 1;
1180 }
1181 pLevelCounts[DelayInt]++;
1182 }
1183
1184 nOutsSum = 0;
1185 nOutsTotal = Abc_NtkCoNum(pNtk);
1186 for ( i = 0; i < nIntervals; i++ )
1187 {
1188 nOutsSum += pLevelCounts[i];
1189 printf( "[%8.2f - %8.2f] : COs = %4d. %5.1f %%\n",
1190 DelayDelta * i, DelayDelta * (i+1), pLevelCounts[i], 100.0 * nOutsSum/nOutsTotal );
1191 }
1192 ABC_FREE( pLevelCounts );
1193 return;
1194 }
1195 else if ( fProfile )
1196 {
1197 int LevelMax, * pLevelCounts;
1198 int nOutsSum, nOutsTotal;
1199
1200 if ( !Abc_NtkIsStrash(pNtk) )
1201 Abc_NtkLevel(pNtk);
1202
1203 LevelMax = 0;
1204 Abc_NtkForEachCo( pNtk, pNode, i )
1205 if ( LevelMax < (int)Abc_ObjFanin0(pNode)->Level )
1206 LevelMax = Abc_ObjFanin0(pNode)->Level;
1207 pLevelCounts = ABC_ALLOC( int, LevelMax + 1 );
1208 memset( pLevelCounts, 0, sizeof(int) * (LevelMax + 1) );
1209 Abc_NtkForEachCo( pNtk, pNode, i )
1210 pLevelCounts[Abc_ObjFanin0(pNode)->Level]++;
1211
1212 nOutsSum = 0;
1213 nOutsTotal = Abc_NtkCoNum(pNtk);
1214 for ( i = 0; i <= LevelMax; i++ )
1215 if ( pLevelCounts[i] )
1216 {
1217 nOutsSum += pLevelCounts[i];
1218 printf( "Level = %4d. COs = %4d. %5.1f %%\n", i, pLevelCounts[i], 100.0 * nOutsSum/nOutsTotal );
1219 }
1220 ABC_FREE( pLevelCounts );
1221 return;
1222 }
1223 assert( Abc_NtkIsStrash(pNtk) );
1224
1225 if ( fVerbose )
1226 {
1227 // find the longest name
1228 Length = 0;
1229 Abc_NtkForEachCo( pNtk, pNode, i )
1230 if ( Length < (int)strlen(Abc_ObjName(pNode)) )
1231 Length = strlen(Abc_ObjName(pNode));
1232 if ( Length < 5 )
1233 Length = 5;
1234 // print stats for each output
1235 Abc_NtkForEachCo( pNtk, pNode, i )
1236 {
1237 fprintf( pFile, "CO %4d : %*s ", i, Length, Abc_ObjName(pNode) );
1238 Abc_NodePrintLevel( pFile, pNode );
1239 }
1240 }
1241 }
1242
1243 /**Function*************************************************************
1244
1245 Synopsis [Prints the factored form of one node.]
1246
1247 Description []
1248
1249 SideEffects []
1250
1251 SeeAlso []
1252
1253 ***********************************************************************/
Abc_NodePrintLevel(FILE * pFile,Abc_Obj_t * pNode)1254 void Abc_NodePrintLevel( FILE * pFile, Abc_Obj_t * pNode )
1255 {
1256 Abc_Obj_t * pDriver;
1257 Vec_Ptr_t * vNodes;
1258
1259 pDriver = Abc_ObjIsCo(pNode)? Abc_ObjFanin0(pNode) : pNode;
1260 if ( Abc_ObjIsPi(pDriver) )
1261 {
1262 fprintf( pFile, "Primary input.\n" );
1263 return;
1264 }
1265 if ( Abc_ObjIsLatch(pDriver) )
1266 {
1267 fprintf( pFile, "Latch.\n" );
1268 return;
1269 }
1270 if ( Abc_NodeIsConst(pDriver) )
1271 {
1272 fprintf( pFile, "Constant %d.\n", !Abc_ObjFaninC0(pNode) );
1273 return;
1274 }
1275 // print the level
1276 fprintf( pFile, "Level = %3d. ", pDriver->Level );
1277 // print the size of MFFC
1278 fprintf( pFile, "Mffc = %5d. ", Abc_NodeMffcSize(pDriver) );
1279 // print the size of the shole cone
1280 vNodes = Abc_NtkDfsNodes( pNode->pNtk, &pDriver, 1 );
1281 fprintf( pFile, "Cone = %5d. ", Vec_PtrSize(vNodes) );
1282 Vec_PtrFree( vNodes );
1283 fprintf( pFile, "\n" );
1284 }
1285
1286 /**Function*************************************************************
1287
1288 Synopsis [Prints the factored form of one node.]
1289
1290 Description []
1291
1292 SideEffects []
1293
1294 SeeAlso []
1295
1296 ***********************************************************************/
Abc_NodePrintKMap(Abc_Obj_t * pNode,int fUseRealNames)1297 void Abc_NodePrintKMap( Abc_Obj_t * pNode, int fUseRealNames )
1298 {
1299 #ifdef ABC_USE_CUDD
1300 Vec_Ptr_t * vNamesIn;
1301 if ( fUseRealNames )
1302 {
1303 vNamesIn = Abc_NodeGetFaninNames(pNode);
1304 Extra_PrintKMap( stdout, (DdManager *)pNode->pNtk->pManFunc, (DdNode *)pNode->pData, Cudd_Not(pNode->pData),
1305 Abc_ObjFaninNum(pNode), NULL, 0, (char **)vNamesIn->pArray );
1306 Abc_NodeFreeNames( vNamesIn );
1307 }
1308 else
1309 Extra_PrintKMap( stdout, (DdManager *)pNode->pNtk->pManFunc, (DdNode *)pNode->pData, Cudd_Not(pNode->pData),
1310 Abc_ObjFaninNum(pNode), NULL, 0, NULL );
1311 #endif
1312 }
1313
1314 /**Function*************************************************************
1315
1316 Synopsis [Prints statistics about gates used in the network.]
1317
1318 Description []
1319
1320 SideEffects []
1321
1322 SeeAlso []
1323
1324 ***********************************************************************/
Abc_NtkPrintGates(Abc_Ntk_t * pNtk,int fUseLibrary,int fUpdateProfile)1325 void Abc_NtkPrintGates( Abc_Ntk_t * pNtk, int fUseLibrary, int fUpdateProfile )
1326 {
1327 Abc_Obj_t * pObj;
1328 int fHasBdds, i;
1329 int CountConst, CountBuf, CountInv, CountAnd, CountOr, CountOther, CounterTotal, TotalDiff = 0;
1330 char * pSop;
1331
1332 if ( fUseLibrary && Abc_NtkHasMapping(pNtk) )
1333 {
1334 Mio_Gate_t ** ppGates;
1335 double Area, AreaTotal;
1336 int Counter, nGates, i, nGateNameLen;
1337
1338 // clean value of all gates
1339 nGates = Mio_LibraryReadGateNum( (Mio_Library_t *)pNtk->pManFunc );
1340 ppGates = Mio_LibraryReadGateArray( (Mio_Library_t *)pNtk->pManFunc );
1341 for ( i = 0; i < nGates; i++ )
1342 {
1343 Mio_GateSetValue( ppGates[i], 0 );
1344 if ( fUpdateProfile )
1345 Mio_GateSetProfile2( ppGates[i], 0 );
1346 }
1347
1348 // count the gates by name
1349 CounterTotal = 0;
1350 Abc_NtkForEachNodeNotBarBuf( pNtk, pObj, i )
1351 {
1352 if ( i == 0 ) continue;
1353 Mio_GateSetValue( (Mio_Gate_t *)pObj->pData, 1 + Mio_GateReadValue((Mio_Gate_t *)pObj->pData) );
1354 if ( fUpdateProfile )
1355 Mio_GateIncProfile2( (Mio_Gate_t *)pObj->pData );
1356 CounterTotal++;
1357 // assuming that twin gates follow each other
1358 if ( Abc_NtkFetchTwinNode(pObj) )
1359 i++;
1360 }
1361
1362 // determine the longest gate name
1363 nGateNameLen = 5;
1364 for ( i = 0; i < nGates; i++ )
1365 {
1366 Counter = Mio_GateReadValue( ppGates[i] );
1367 if ( Counter == 0 )
1368 continue;
1369 nGateNameLen = Abc_MaxInt( nGateNameLen, strlen(Mio_GateReadName(ppGates[i])) );
1370 }
1371
1372 // print the gates
1373 AreaTotal = Abc_NtkGetMappedArea(pNtk);
1374 for ( i = 0; i < nGates; i++ )
1375 {
1376 Counter = Mio_GateReadValue( ppGates[i] );
1377 if ( Counter == 0 && Mio_GateReadProfile(ppGates[i]) == 0 )
1378 continue;
1379 if ( Mio_GateReadPinNum(ppGates[i]) > 1 )
1380 TotalDiff += Abc_AbsInt( Mio_GateReadProfile(ppGates[i]) - Mio_GateReadProfile2(ppGates[i]) );
1381 Area = Counter * Mio_GateReadArea( ppGates[i] );
1382 printf( "%-*s Fanin = %2d Instance = %8d Area = %10.2f %6.2f %% %8d %8d %s\n",
1383 nGateNameLen, Mio_GateReadName( ppGates[i] ),
1384 Mio_GateReadPinNum( ppGates[i] ),
1385 Counter, Area, 100.0 * Area / AreaTotal,
1386 Mio_GateReadProfile(ppGates[i]),
1387 Mio_GateReadProfile2(ppGates[i]),
1388 Mio_GateReadForm(ppGates[i]) );
1389 }
1390 printf( "%-*s Instance = %8d Area = %10.2f %6.2f %% AbsDiff = %d\n",
1391 nGateNameLen, "TOTAL",
1392 CounterTotal, AreaTotal, 100.0, TotalDiff );
1393 return;
1394 }
1395
1396 if ( Abc_NtkIsAigLogic(pNtk) )
1397 return;
1398
1399 // transform logic functions from BDD to SOP
1400 if ( (fHasBdds = Abc_NtkIsBddLogic(pNtk)) )
1401 {
1402 if ( !Abc_NtkBddToSop(pNtk, -1, ABC_INFINITY) )
1403 {
1404 printf( "Abc_NtkPrintGates(): Converting to SOPs has failed.\n" );
1405 return;
1406 }
1407 }
1408
1409 // get hold of the SOP of the node
1410 CountConst = CountBuf = CountInv = CountAnd = CountOr = CountOther = CounterTotal = 0;
1411 Abc_NtkForEachNodeNotBarBuf( pNtk, pObj, i )
1412 {
1413 if ( i == 0 ) continue;
1414 if ( Abc_NtkHasMapping(pNtk) )
1415 pSop = Mio_GateReadSop((Mio_Gate_t *)pObj->pData);
1416 else
1417 pSop = (char *)pObj->pData;
1418 // collect the stats
1419 if ( Abc_SopIsConst0(pSop) || Abc_SopIsConst1(pSop) )
1420 CountConst++;
1421 else if ( Abc_SopIsBuf(pSop) )
1422 CountBuf++;
1423 else if ( Abc_SopIsInv(pSop) )
1424 CountInv++;
1425 else if ( (!Abc_SopIsComplement(pSop) && Abc_SopIsAndType(pSop)) ||
1426 ( Abc_SopIsComplement(pSop) && Abc_SopIsOrType(pSop)) )
1427 CountAnd++;
1428 else if ( ( Abc_SopIsComplement(pSop) && Abc_SopIsAndType(pSop)) ||
1429 (!Abc_SopIsComplement(pSop) && Abc_SopIsOrType(pSop)) )
1430 CountOr++;
1431 else
1432 CountOther++;
1433 CounterTotal++;
1434 }
1435 printf( "Const = %8d %6.2f %%\n", CountConst , 100.0 * CountConst / CounterTotal );
1436 printf( "Buffer = %8d %6.2f %%\n", CountBuf , 100.0 * CountBuf / CounterTotal );
1437 printf( "Inverter = %8d %6.2f %%\n", CountInv , 100.0 * CountInv / CounterTotal );
1438 printf( "And = %8d %6.2f %%\n", CountAnd , 100.0 * CountAnd / CounterTotal );
1439 printf( "Or = %8d %6.2f %%\n", CountOr , 100.0 * CountOr / CounterTotal );
1440 printf( "Other = %8d %6.2f %%\n", CountOther , 100.0 * CountOther / CounterTotal );
1441 printf( "TOTAL = %8d %6.2f %%\n", CounterTotal, 100.0 * CounterTotal / CounterTotal );
1442
1443 // convert the network back into BDDs if this is how it was
1444 if ( fHasBdds )
1445 Abc_NtkSopToBdd(pNtk);
1446 }
1447
1448 /**Function*************************************************************
1449
1450 Synopsis [Prints statistics about gates used in the network.]
1451
1452 Description []
1453
1454 SideEffects []
1455
1456 SeeAlso []
1457
1458 ***********************************************************************/
Abc_NtkPrintSharing(Abc_Ntk_t * pNtk)1459 void Abc_NtkPrintSharing( Abc_Ntk_t * pNtk )
1460 {
1461 Vec_Ptr_t * vNodes1, * vNodes2;
1462 Abc_Obj_t * pObj1, * pObj2, * pNode1, * pNode2;
1463 int i, k, m, n, Counter;
1464
1465 // print the template
1466 printf( "Statistics about sharing of logic nodes among the CO pairs.\n" );
1467 printf( "(CO1,CO2)=NumShared : " );
1468 // go though the CO pairs
1469 Abc_NtkForEachCo( pNtk, pObj1, i )
1470 {
1471 vNodes1 = Abc_NtkDfsNodes( pNtk, &pObj1, 1 );
1472 // mark the nodes
1473 Vec_PtrForEachEntry( Abc_Obj_t *, vNodes1, pNode1, m )
1474 pNode1->fMarkA = 1;
1475 // go through the second COs
1476 Abc_NtkForEachCo( pNtk, pObj2, k )
1477 {
1478 if ( i >= k )
1479 continue;
1480 vNodes2 = Abc_NtkDfsNodes( pNtk, &pObj2, 1 );
1481 // count the number of marked
1482 Counter = 0;
1483 Vec_PtrForEachEntry( Abc_Obj_t *, vNodes2, pNode2, n )
1484 Counter += pNode2->fMarkA;
1485 // print
1486 printf( "(%d,%d)=%d ", i, k, Counter );
1487 Vec_PtrFree( vNodes2 );
1488 }
1489 // unmark the nodes
1490 Vec_PtrForEachEntry( Abc_Obj_t *, vNodes1, pNode1, m )
1491 pNode1->fMarkA = 0;
1492 Vec_PtrFree( vNodes1 );
1493 }
1494 printf( "\n" );
1495 }
1496
1497 /**Function*************************************************************
1498
1499 Synopsis [Prints info for each output cone.]
1500
1501 Description []
1502
1503 SideEffects []
1504
1505 SeeAlso []
1506
1507 ***********************************************************************/
Abc_NtkCountPis(Vec_Ptr_t * vSupp)1508 int Abc_NtkCountPis( Vec_Ptr_t * vSupp )
1509 {
1510 Abc_Obj_t * pObj;
1511 int i, Counter = 0;
1512 Vec_PtrForEachEntry( Abc_Obj_t *, vSupp, pObj, i )
1513 Counter += Abc_ObjIsPi(pObj);
1514 return Counter;
1515 }
Abc_NtkPrintStrSupports(Abc_Ntk_t * pNtk,int fMatrix)1516 void Abc_NtkPrintStrSupports( Abc_Ntk_t * pNtk, int fMatrix )
1517 {
1518 Vec_Ptr_t * vSupp, * vNodes;
1519 Abc_Obj_t * pObj;
1520 int i, k, nPis;
1521 printf( "Structural support info:\n" );
1522 Abc_NtkForEachCo( pNtk, pObj, i )
1523 {
1524 vSupp = Abc_NtkNodeSupport( pNtk, &pObj, 1 );
1525 vNodes = Abc_NtkDfsNodes( pNtk, &pObj, 1 );
1526 nPis = Abc_NtkCountPis( vSupp );
1527 printf( "%5d %20s : Cone = %5d. Supp = %5d. (PIs = %5d. FFs = %5d.)\n",
1528 i, Abc_ObjName(pObj), vNodes->nSize, vSupp->nSize, nPis, vSupp->nSize - nPis );
1529 Vec_PtrFree( vNodes );
1530 Vec_PtrFree( vSupp );
1531 }
1532 if ( !fMatrix )
1533 {
1534 Abc_NtkCleanMarkA( pNtk );
1535 return;
1536 }
1537
1538 Abc_NtkForEachCi( pNtk, pObj, k )
1539 pObj->fMarkA = 0;
1540
1541 printf( "Actual support info:\n" );
1542 Abc_NtkForEachCo( pNtk, pObj, i )
1543 {
1544 vSupp = Abc_NtkNodeSupport( pNtk, &pObj, 1 );
1545 Vec_PtrForEachEntry( Abc_Obj_t *, vSupp, pObj, k )
1546 pObj->fMarkA = 1;
1547 Vec_PtrFree( vSupp );
1548
1549 Abc_NtkForEachCi( pNtk, pObj, k )
1550 printf( "%d", pObj->fMarkA );
1551 printf( "\n" );
1552
1553 Abc_NtkForEachCi( pNtk, pObj, k )
1554 pObj->fMarkA = 0;
1555 }
1556 Abc_NtkCleanMarkA( pNtk );
1557 }
1558
1559 /**Function*************************************************************
1560
1561 Synopsis [Prints information about the object.]
1562
1563 Description []
1564
1565 SideEffects []
1566
1567 SeeAlso []
1568
1569 ***********************************************************************/
Abc_ObjPrint(FILE * pFile,Abc_Obj_t * pObj)1570 void Abc_ObjPrint( FILE * pFile, Abc_Obj_t * pObj )
1571 {
1572 Abc_Obj_t * pFanin;
1573 int i;
1574 fprintf( pFile, "Object %5d : ", pObj->Id );
1575 switch ( pObj->Type )
1576 {
1577 case ABC_OBJ_NONE:
1578 fprintf( pFile, "NONE " );
1579 break;
1580 case ABC_OBJ_CONST1:
1581 fprintf( pFile, "Const1 " );
1582 break;
1583 case ABC_OBJ_PI:
1584 fprintf( pFile, "PI " );
1585 break;
1586 case ABC_OBJ_PO:
1587 fprintf( pFile, "PO " );
1588 break;
1589 case ABC_OBJ_BI:
1590 fprintf( pFile, "BI " );
1591 break;
1592 case ABC_OBJ_BO:
1593 fprintf( pFile, "BO " );
1594 break;
1595 case ABC_OBJ_NET:
1596 fprintf( pFile, "Net " );
1597 break;
1598 case ABC_OBJ_NODE:
1599 fprintf( pFile, "Node " );
1600 break;
1601 case ABC_OBJ_LATCH:
1602 fprintf( pFile, "Latch " );
1603 break;
1604 case ABC_OBJ_WHITEBOX:
1605 fprintf( pFile, "Whitebox" );
1606 break;
1607 case ABC_OBJ_BLACKBOX:
1608 fprintf( pFile, "Blackbox" );
1609 break;
1610 default:
1611 assert(0);
1612 break;
1613 }
1614 // print the fanins
1615 fprintf( pFile, " Fanins ( " );
1616 Abc_ObjForEachFanin( pObj, pFanin, i )
1617 fprintf( pFile, "%d ", pFanin->Id );
1618 fprintf( pFile, ") " );
1619 /*
1620 fprintf( pFile, " Fanouts ( " );
1621 Abc_ObjForEachFanout( pObj, pFanin, i )
1622 fprintf( pFile, "%d(%c) ", pFanin->Id, Abc_NodeIsTravIdCurrent(pFanin)? '+' : '-' );
1623 fprintf( pFile, ") " );
1624 */
1625 // print the logic function
1626 if ( Abc_ObjIsNode(pObj) && Abc_NtkIsSopLogic(pObj->pNtk) )
1627 fprintf( pFile, " %s", (char*)pObj->pData );
1628 else if ( Abc_ObjIsNode(pObj) && Abc_NtkIsMappedLogic(pObj->pNtk) )
1629 fprintf( pFile, " %s\n", Mio_GateReadName((Mio_Gate_t *)pObj->pData) );
1630 else
1631 fprintf( pFile, "\n" );
1632 }
1633
1634
1635 /**Function*************************************************************
1636
1637 Synopsis [Checks the status of the miter.]
1638
1639 Description []
1640
1641 SideEffects []
1642
1643 SeeAlso []
1644
1645 ***********************************************************************/
Abc_NtkPrintMiter(Abc_Ntk_t * pNtk)1646 void Abc_NtkPrintMiter( Abc_Ntk_t * pNtk )
1647 {
1648 Abc_Obj_t * pObj, * pChild, * pConst1 = Abc_AigConst1(pNtk);
1649 int i, iOut = -1;
1650 abctime Time = Abc_Clock();
1651 int nUnsat = 0;
1652 int nSat = 0;
1653 int nUndec = 0;
1654 int nPis = 0;
1655 Abc_NtkForEachPi( pNtk, pObj, i )
1656 nPis += (int)( Abc_ObjFanoutNum(pObj) > 0 );
1657 Abc_NtkForEachPo( pNtk, pObj, i )
1658 {
1659 pChild = Abc_ObjChild0(pObj);
1660 // check if the output is constant 0
1661 if ( pChild == Abc_ObjNot(pConst1) )
1662 nUnsat++;
1663 // check if the output is constant 1
1664 else if ( pChild == pConst1 )
1665 {
1666 nSat++;
1667 if ( iOut == -1 )
1668 iOut = i;
1669 }
1670 // check if the output is a primary input
1671 else if ( Abc_ObjIsPi(Abc_ObjRegular(pChild)) )
1672 {
1673 nSat++;
1674 if ( iOut == -1 )
1675 iOut = i;
1676 }
1677 // check if the output is 1 for the 0000 pattern
1678 else if ( Abc_ObjRegular(pChild)->fPhase != (unsigned)Abc_ObjIsComplement(pChild) )
1679 {
1680 nSat++;
1681 if ( iOut == -1 )
1682 iOut = i;
1683 }
1684 else
1685 nUndec++;
1686 }
1687 printf( "Miter: I =%6d", nPis );
1688 printf( " N =%7d", Abc_NtkNodeNum(pNtk) );
1689 printf( " ? =%7d", nUndec );
1690 printf( " U =%6d", nUnsat );
1691 printf( " S =%6d", nSat );
1692 Time = Abc_Clock() - Time;
1693 printf(" %7.2f sec\n", (float)(Time)/(float)(CLOCKS_PER_SEC));
1694 if ( iOut >= 0 )
1695 printf( "The first satisfiable output is number %d (%s).\n", iOut, Abc_ObjName( Abc_NtkPo(pNtk, iOut) ) );
1696 }
1697
1698 /**Function*************************************************************
1699
1700 Synopsis [Checks the status of the miter.]
1701
1702 Description []
1703
1704 SideEffects []
1705
1706 SeeAlso []
1707
1708 ***********************************************************************/
Abc_NtkPrintPoEquivs(Abc_Ntk_t * pNtk)1709 void Abc_NtkPrintPoEquivs( Abc_Ntk_t * pNtk )
1710 {
1711 Abc_Obj_t * pObj, * pDriver, * pRepr; int i, iRepr;
1712 Vec_Int_t * vMap = Vec_IntStartFull( Abc_NtkObjNumMax(pNtk) );
1713 Abc_NtkForEachPo( pNtk, pObj, i )
1714 {
1715 pDriver = Abc_ObjFanin0(pObj);
1716 if ( Abc_NtkIsStrash(pNtk) && pDriver == Abc_AigConst1(pNtk) )
1717 {
1718 printf( "%s = Const%d\n", Abc_ObjName(pObj), !Abc_ObjFaninC0(pObj) );
1719 continue;
1720 }
1721 else if ( !Abc_NtkIsStrash(pNtk) && Abc_NodeIsConst(pDriver) )
1722 {
1723 printf( "%s = Const%d\n", Abc_ObjName(pObj), Abc_NodeIsConst1(pDriver) );
1724 continue;
1725 }
1726 iRepr = Vec_IntEntry( vMap, Abc_ObjId(pDriver) );
1727 if ( iRepr == -1 )
1728 {
1729 Vec_IntWriteEntry( vMap, Abc_ObjId(pDriver), i );
1730 continue;
1731 }
1732 pRepr = Abc_NtkCo(pNtk, iRepr);
1733 printf( "%s = %s%s\n", Abc_ObjName(pObj), Abc_ObjFaninC0(pRepr) == Abc_ObjFaninC0(pObj) ? "" : "!", Abc_ObjName(pRepr) );
1734 }
1735 Vec_IntFree( vMap );
1736 }
1737
1738
1739
1740
1741 typedef struct Gli_Man_t_ Gli_Man_t;
1742
1743 extern Gli_Man_t * Gli_ManAlloc( int nObjs, int nRegs, int nFanioPairs );
1744 extern void Gli_ManStop( Gli_Man_t * p );
1745 extern int Gli_ManCreateCi( Gli_Man_t * p, int nFanouts );
1746 extern int Gli_ManCreateCo( Gli_Man_t * p, int iFanin );
1747 extern int Gli_ManCreateNode( Gli_Man_t * p, Vec_Int_t * vFanins, int nFanouts, word * pGateTruth );
1748
1749 extern void Gli_ManSwitchesAndGlitches( Gli_Man_t * p, int nPatterns, float PiTransProb, int fVerbose );
1750 extern int Gli_ObjNumSwitches( Gli_Man_t * p, int iNode );
1751 extern int Gli_ObjNumGlitches( Gli_Man_t * p, int iNode );
1752
1753 /**Function*************************************************************
1754
1755 Synopsis [Returns the percentable of increased power due to glitching.]
1756
1757 Description []
1758
1759 SideEffects []
1760
1761 SeeAlso []
1762
1763 ***********************************************************************/
Abc_NtkMfsTotalGlitchingLut(Abc_Ntk_t * pNtk,int nPats,int Prob,int fVerbose)1764 float Abc_NtkMfsTotalGlitchingLut( Abc_Ntk_t * pNtk, int nPats, int Prob, int fVerbose )
1765 {
1766 int nSwitches, nGlitches;
1767 Gli_Man_t * p;
1768 Vec_Ptr_t * vNodes;
1769 Vec_Int_t * vFanins, * vTruth;
1770 Abc_Obj_t * pObj, * pFanin;
1771 Vec_Wrd_t * vTruths; word * pTruth;
1772 unsigned * puTruth;
1773 int i, k;
1774 assert( Abc_NtkIsLogic(pNtk) );
1775 assert( Abc_NtkGetFaninMax(pNtk) <= 6 );
1776 if ( Abc_NtkGetFaninMax(pNtk) > 6 )
1777 {
1778 printf( "Abc_NtkMfsTotalGlitching() This procedure works only for mapped networks with LUTs size up to 6 inputs.\n" );
1779 return -1.0;
1780 }
1781 Abc_NtkToAig( pNtk );
1782 vNodes = Abc_NtkDfs( pNtk, 0 );
1783 vFanins = Vec_IntAlloc( 6 );
1784 vTruth = Vec_IntAlloc( 1 << 12 );
1785 vTruths = Vec_WrdStart( Abc_NtkObjNumMax(pNtk) );
1786
1787 // derive network for glitch computation
1788 p = Gli_ManAlloc( Vec_PtrSize(vNodes) + Abc_NtkCiNum(pNtk) + Abc_NtkCoNum(pNtk),
1789 Abc_NtkLatchNum(pNtk), Abc_NtkGetTotalFanins(pNtk) + Abc_NtkCoNum(pNtk) );
1790 Abc_NtkForEachObj( pNtk, pObj, i )
1791 pObj->iTemp = -1;
1792 Abc_NtkForEachCi( pNtk, pObj, i )
1793 pObj->iTemp = Gli_ManCreateCi( p, Abc_ObjFanoutNum(pObj) );
1794 Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
1795 {
1796 Vec_IntClear( vFanins );
1797 Abc_ObjForEachFanin( pObj, pFanin, k )
1798 Vec_IntPush( vFanins, pFanin->iTemp );
1799 puTruth = Hop_ManConvertAigToTruth( (Hop_Man_t *)pNtk->pManFunc, (Hop_Obj_t *)pObj->pData, Abc_ObjFaninNum(pObj), vTruth, 0 );
1800 pTruth = Vec_WrdEntryP( vTruths, Abc_ObjId(pObj) );
1801 *pTruth = ((word)puTruth[Abc_ObjFaninNum(pObj) == 6] << 32) | (word)puTruth[0];
1802 pObj->iTemp = Gli_ManCreateNode( p, vFanins, Abc_ObjFanoutNum(pObj), pTruth );
1803 }
1804 Abc_NtkForEachCo( pNtk, pObj, i )
1805 Gli_ManCreateCo( p, Abc_ObjFanin0(pObj)->iTemp );
1806
1807 // compute glitching
1808 Gli_ManSwitchesAndGlitches( p, 4000, 1.0/8.0, 0 );
1809
1810 // compute the ratio
1811 nSwitches = nGlitches = 0;
1812 Abc_NtkForEachObj( pNtk, pObj, i )
1813 if ( pObj->iTemp >= 0 )
1814 {
1815 nSwitches += Abc_ObjFanoutNum(pObj) * Gli_ObjNumSwitches(p, pObj->iTemp);
1816 nGlitches += Abc_ObjFanoutNum(pObj) * Gli_ObjNumGlitches(p, pObj->iTemp);
1817 }
1818
1819 Gli_ManStop( p );
1820 Vec_PtrFree( vNodes );
1821 Vec_IntFree( vTruth );
1822 Vec_IntFree( vFanins );
1823 Vec_WrdFree( vTruths );
1824 return nSwitches ? 100.0*(nGlitches-nSwitches)/nSwitches : 0.0;
1825 }
1826
1827 /**Function*************************************************************
1828
1829 Synopsis [Returns the percentable of increased power due to glitching.]
1830
1831 Description []
1832
1833 SideEffects []
1834
1835 SeeAlso []
1836
1837 ***********************************************************************/
Abc_NtkMfsTotalGlitching(Abc_Ntk_t * pNtk,int nPats,int Prob,int fVerbose)1838 float Abc_NtkMfsTotalGlitching( Abc_Ntk_t * pNtk, int nPats, int Prob, int fVerbose )
1839 {
1840 int nSwitches, nGlitches;
1841 Gli_Man_t * p;
1842 Vec_Ptr_t * vNodes;
1843 Vec_Int_t * vFanins;
1844 Abc_Obj_t * pObj, * pFanin;
1845 int i, k, nFaninMax = Abc_NtkGetFaninMax(pNtk);
1846 if ( !Abc_NtkIsMappedLogic(pNtk) )
1847 return Abc_NtkMfsTotalGlitchingLut( pNtk, nPats, Prob, fVerbose );
1848 assert( Abc_NtkIsMappedLogic(pNtk) );
1849 if ( nFaninMax > 16 )
1850 {
1851 printf( "Abc_NtkMfsTotalGlitching() This procedure works only for mapped networks with LUTs size up to 6 inputs.\n" );
1852 return -1.0;
1853 }
1854 vNodes = Abc_NtkDfs( pNtk, 0 );
1855 vFanins = Vec_IntAlloc( 6 );
1856
1857 // derive network for glitch computation
1858 p = Gli_ManAlloc( Vec_PtrSize(vNodes) + Abc_NtkCiNum(pNtk) + Abc_NtkCoNum(pNtk),
1859 Abc_NtkLatchNum(pNtk), Abc_NtkGetTotalFanins(pNtk) + Abc_NtkCoNum(pNtk) );
1860 Abc_NtkForEachObj( pNtk, pObj, i )
1861 pObj->iTemp = -1;
1862 Abc_NtkForEachCi( pNtk, pObj, i )
1863 pObj->iTemp = Gli_ManCreateCi( p, Abc_ObjFanoutNum(pObj) );
1864 Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
1865 {
1866 Vec_IntClear( vFanins );
1867 Abc_ObjForEachFanin( pObj, pFanin, k )
1868 Vec_IntPush( vFanins, pFanin->iTemp );
1869 pObj->iTemp = Gli_ManCreateNode( p, vFanins, Abc_ObjFanoutNum(pObj), Mio_GateReadTruthP((Mio_Gate_t *)pObj->pData) );
1870 }
1871 Abc_NtkForEachCo( pNtk, pObj, i )
1872 Gli_ManCreateCo( p, Abc_ObjFanin0(pObj)->iTemp );
1873
1874 // compute glitching
1875 Gli_ManSwitchesAndGlitches( p, nPats, 1.0/Prob, fVerbose );
1876
1877 // compute the ratio
1878 nSwitches = nGlitches = 0;
1879 Abc_NtkForEachObj( pNtk, pObj, i )
1880 if ( pObj->iTemp >= 0 )
1881 {
1882 nSwitches += Abc_ObjFanoutNum(pObj) * Gli_ObjNumSwitches(p, pObj->iTemp);
1883 nGlitches += Abc_ObjFanoutNum(pObj) * Gli_ObjNumGlitches(p, pObj->iTemp);
1884 }
1885
1886 Gli_ManStop( p );
1887 Vec_PtrFree( vNodes );
1888 Vec_IntFree( vFanins );
1889 return nSwitches ? 100.0*(nGlitches-nSwitches)/nSwitches : 0.0;
1890 }
1891
1892 /**Function*************************************************************
1893
1894 Synopsis [Prints K-map of 6-var function represented by truth table.]
1895
1896 Description []
1897
1898 SideEffects []
1899
1900 SeeAlso []
1901
1902 ***********************************************************************/
Abc_Show6VarFunc(word F0,word F1)1903 void Abc_Show6VarFunc( word F0, word F1 )
1904 {
1905 // order of cells in the Karnaugh map
1906 // int Cells[8] = { 0, 1, 3, 2, 6, 7, 5, 4 };
1907 int Cells[8] = { 0, 4, 6, 2, 3, 7, 5, 1 };
1908 // intermediate variables
1909 int s; // symbol counter
1910 int h; // horizontal coordinate;
1911 int v; // vertical coordinate;
1912 assert( (F0 & F1) == 0 );
1913
1914 // output minterms above
1915 for ( s = 0; s < 4; s++ )
1916 printf( " " );
1917 printf( " " );
1918 for ( h = 0; h < 8; h++ )
1919 {
1920 for ( s = 0; s < 3; s++ )
1921 printf( "%d", ((Cells[h] >> (2-s)) & 1) );
1922 printf( " " );
1923 }
1924 printf( "\n" );
1925
1926 // output horizontal line above
1927 for ( s = 0; s < 4; s++ )
1928 printf( " " );
1929 printf( "+" );
1930 for ( h = 0; h < 8; h++ )
1931 {
1932 for ( s = 0; s < 3; s++ )
1933 printf( "-" );
1934 printf( "+" );
1935 }
1936 printf( "\n" );
1937
1938 // output lines with function values
1939 for ( v = 0; v < 8; v++ )
1940 {
1941 for ( s = 0; s < 3; s++ )
1942 printf( "%d", ((Cells[v] >> (2-s)) & 1) );
1943 printf( " |" );
1944
1945 for ( h = 0; h < 8; h++ )
1946 {
1947 printf( " " );
1948 if ( ((F0 >> ((Cells[v]*8)+Cells[h])) & 1) )
1949 printf( "0" );
1950 else if ( ((F1 >> ((Cells[v]*8)+Cells[h])) & 1) )
1951 printf( "1" );
1952 else
1953 printf( " " );
1954 printf( " |" );
1955 }
1956 printf( "\n" );
1957
1958 // output horizontal line above
1959 for ( s = 0; s < 4; s++ )
1960 printf( " " );
1961 // printf( "%c", v == 7 ? '+' : '|' );
1962 printf( "+" );
1963 for ( h = 0; h < 8; h++ )
1964 {
1965 for ( s = 0; s < 3; s++ )
1966 printf( "-" );
1967 // printf( "%c", v == 7 ? '+' : '|' );
1968 printf( "%c", (v == 7 || h == 7) ? '+' : '|' );
1969 }
1970 printf( "\n" );
1971 }
1972 }
1973
1974 /**Function*************************************************************
1975
1976 Synopsis [Prints K-map of 6-var function represented by truth table.]
1977
1978 Description []
1979
1980 SideEffects []
1981
1982 SeeAlso []
1983
1984 ***********************************************************************/
Abc_NtkShow6VarFunc(char * pF0,char * pF1)1985 void Abc_NtkShow6VarFunc( char * pF0, char * pF1 )
1986 {
1987 word F0, F1;
1988 if ( strlen(pF0) != 16 )
1989 {
1990 printf( "Wrong length (%d) of 6-var truth table.\n", (int)strlen(pF0) );
1991 return;
1992 }
1993 if ( strlen(pF1) != 16 )
1994 {
1995 printf( "Wrong length (%d) of 6-var truth table.\n", (int)strlen(pF1) );
1996 return;
1997 }
1998 Extra_ReadHexadecimal( (unsigned *)&F0, pF0, 6 );
1999 Extra_ReadHexadecimal( (unsigned *)&F1, pF1, 6 );
2000 Abc_Show6VarFunc( F0, F1 );
2001 }
2002
2003
2004 ////////////////////////////////////////////////////////////////////////
2005 /// END OF FILE ///
2006 ////////////////////////////////////////////////////////////////////////
2007
2008
2009 ABC_NAMESPACE_IMPL_END
2010