abc-master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
abcLutmin.c
Go to the documentation of this file.
1 /**CFile****************************************************************
2 
3  FileName [abcLutmin.c]
4 
5  SystemName [ABC: Logic synthesis and verification system.]
6 
7  PackageName [Network and node package.]
8 
9  Synopsis [Minimization of the number of LUTs.]
10 
11  Author [Alan Mishchenko]
12 
13  Affiliation [UC Berkeley]
14 
15  Date [Ver. 1.0. Started - June 20, 2005.]
16 
17  Revision [$Id: abcLutmin.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
18 
19 ***********************************************************************/
20 
21 #include "base/abc/abc.h"
22 #include "misc/extra/extraBdd.h"
23 
25 
26 
27 /*
28  Implememented here is the algorithm for minimal-LUT decomposition
29  described in the paper: T. Sasao et al. "On the number of LUTs
30  to implement logic functions", To appear in Proc. IWLS'09.
31 */
32 
33 ////////////////////////////////////////////////////////////////////////
34 /// DECLARATIONS ///
35 ////////////////////////////////////////////////////////////////////////
36 
37 ////////////////////////////////////////////////////////////////////////
38 /// FUNCTION DEFINITIONS ///
39 ////////////////////////////////////////////////////////////////////////
40 
41 /**Function*************************************************************
42 
43  Synopsis [Check if a LUT can absort a fanin.]
44 
45  Description [The fanins are (c, d0, d1).]
46 
47  SideEffects []
48 
49  SeeAlso []
50 
51 ***********************************************************************/
52 int Abc_ObjCheckAbsorb( Abc_Obj_t * pObj, Abc_Obj_t * pPivot, int nLutSize, Vec_Ptr_t * vFanins )
53 {
54  Abc_Obj_t * pFanin;
55  int i;
56  assert( Abc_ObjIsNode(pObj) && Abc_ObjIsNode(pPivot) );
57  // add fanins of the node
58  Vec_PtrClear( vFanins );
59  Abc_ObjForEachFanin( pObj, pFanin, i )
60  if ( pFanin != pPivot )
61  Vec_PtrPush( vFanins, pFanin );
62  // add fanins of the fanin
63  Abc_ObjForEachFanin( pPivot, pFanin, i )
64  {
65  Vec_PtrPushUnique( vFanins, pFanin );
66  if ( Vec_PtrSize(vFanins) > nLutSize )
67  return 0;
68  }
69  return 1;
70 }
71 
72 /**Function*************************************************************
73 
74  Synopsis [Check how many times a LUT can absorb a fanin.]
75 
76  Description [The fanins are (c, d0, d1).]
77 
78  SideEffects []
79 
80  SeeAlso []
81 
82 ***********************************************************************/
83 void Abc_NtkCheckAbsorb( Abc_Ntk_t * pNtk, int nLutSize )
84 {
85  Vec_Int_t * vCounts;
86  Vec_Ptr_t * vFanins;
87  Abc_Obj_t * pObj, * pFanin;
88  int i, k, Counter = 0, Counter2 = 0;
89  abctime clk = Abc_Clock();
90  vCounts = Vec_IntStart( Abc_NtkObjNumMax(pNtk) );
91  vFanins = Vec_PtrAlloc( 100 );
92  Abc_NtkForEachNode( pNtk, pObj, i )
93  Abc_ObjForEachFanin( pObj, pFanin, k )
94  if ( Abc_ObjIsNode(pFanin) && Abc_ObjCheckAbsorb( pObj, pFanin, nLutSize, vFanins ) )
95  {
96  Vec_IntAddToEntry( vCounts, Abc_ObjId(pFanin), 1 );
97  Counter++;
98  }
99  Vec_PtrFree( vFanins );
100  Abc_NtkForEachNode( pNtk, pObj, i )
101  if ( Vec_IntEntry(vCounts, Abc_ObjId(pObj)) == Abc_ObjFanoutNum(pObj) )
102  {
103 // printf( "%d ", Abc_ObjId(pObj) );
104  Counter2++;
105  }
106  printf( "Absorted = %6d. (%6.2f %%) Fully = %6d. (%6.2f %%) ",
107  Counter, 100.0 * Counter / Abc_NtkNodeNum(pNtk),
108  Counter2, 100.0 * Counter2 / Abc_NtkNodeNum(pNtk) );
109  Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
110 }
111 
112 /**Function*************************************************************
113 
114  Synopsis [Implements 2:1 MUX using one 3-LUT.]
115 
116  Description [The fanins are (c, d0, d1).]
117 
118  SideEffects []
119 
120  SeeAlso []
121 
122 ***********************************************************************/
123 Abc_Obj_t * Abc_NtkBddMux21( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pFanins[] )
124 {
125  DdManager * dd = (DdManager *)pNtkNew->pManFunc;
126  Abc_Obj_t * pNode;
127  DdNode * bSpin, * bCof0, * bCof1;
128  pNode = Abc_NtkCreateNode( pNtkNew );
129  Abc_ObjAddFanin( pNode, pFanins[0] );
130  Abc_ObjAddFanin( pNode, pFanins[1] );
131  Abc_ObjAddFanin( pNode, pFanins[2] );
132  bSpin = Cudd_bddIthVar(dd, 0);
133  bCof0 = Cudd_bddIthVar(dd, 1);
134  bCof1 = Cudd_bddIthVar(dd, 2);
135  pNode->pData = Cudd_bddIte( dd, bSpin, bCof1, bCof0 ); Cudd_Ref( (DdNode *)pNode->pData );
136  return pNode;
137 }
138 
139 /**Function*************************************************************
140 
141  Synopsis [Implements 4:1 MUX using one 6-LUT.]
142 
143  Description [The fanins are (c0, c1, d00, d01, d10, d11).]
144 
145  SideEffects []
146 
147  SeeAlso []
148 
149 ***********************************************************************/
150 Abc_Obj_t * Abc_NtkBddMux411( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pFanins[] )
151 {
152  DdManager * dd = (DdManager *)pNtkNew->pManFunc;
153  Abc_Obj_t * pNode;
154  DdNode * bSpin, * bCof0, * bCof1;
155  pNode = Abc_NtkCreateNode( pNtkNew );
156  Abc_ObjAddFanin( pNode, pFanins[0] );
157  Abc_ObjAddFanin( pNode, pFanins[1] );
158  Abc_ObjAddFanin( pNode, pFanins[2] );
159  Abc_ObjAddFanin( pNode, pFanins[3] );
160  Abc_ObjAddFanin( pNode, pFanins[4] );
161  Abc_ObjAddFanin( pNode, pFanins[5] );
162  bSpin = Cudd_bddIthVar(dd, 1);
163  bCof0 = Cudd_bddIte( dd, bSpin, Cudd_bddIthVar(dd, 3), Cudd_bddIthVar(dd, 2) ); Cudd_Ref( bCof0 );
164  bCof1 = Cudd_bddIte( dd, bSpin, Cudd_bddIthVar(dd, 5), Cudd_bddIthVar(dd, 4) ); Cudd_Ref( bCof1 );
165  bSpin = Cudd_bddIthVar(dd, 0);
166  pNode->pData = Cudd_bddIte( dd, bSpin, bCof1, bCof0 ); Cudd_Ref( (DdNode *)pNode->pData );
167  Cudd_RecursiveDeref( dd, bCof0 );
168  Cudd_RecursiveDeref( dd, bCof1 );
169  return pNode;
170 }
171 
172 /**Function*************************************************************
173 
174  Synopsis [Implementes 4:1 MUX using two 4-LUTs.]
175 
176  Description [The fanins are (c0, c1, d00, d01, d10, d11).]
177 
178  SideEffects []
179 
180  SeeAlso []
181 
182 ***********************************************************************/
183 Abc_Obj_t * Abc_NtkBddMux412( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pFanins[] )
184 {
185  DdManager * dd = (DdManager *)pNtkNew->pManFunc;
186  Abc_Obj_t * pNodeBot, * pNodeTop;
187  DdNode * bSpin, * bCof0, * bCof1;
188  // bottom node
189  pNodeBot = Abc_NtkCreateNode( pNtkNew );
190  Abc_ObjAddFanin( pNodeBot, pFanins[0] );
191  Abc_ObjAddFanin( pNodeBot, pFanins[1] );
192  Abc_ObjAddFanin( pNodeBot, pFanins[2] );
193  Abc_ObjAddFanin( pNodeBot, pFanins[3] );
194  bSpin = Cudd_bddIthVar(dd, 0);
195  bCof0 = Cudd_bddIte( dd, Cudd_bddIthVar(dd, 1), Cudd_bddIthVar(dd, 3), Cudd_bddIthVar(dd, 2) ); Cudd_Ref( bCof0 );
196  bCof1 = Cudd_bddIthVar(dd, 1);
197  pNodeBot->pData = Cudd_bddIte( dd, bSpin, bCof1, bCof0 ); Cudd_Ref( (DdNode *)pNodeBot->pData );
198  Cudd_RecursiveDeref( dd, bCof0 );
199  // top node
200  pNodeTop = Abc_NtkCreateNode( pNtkNew );
201  Abc_ObjAddFanin( pNodeTop, pFanins[0] );
202  Abc_ObjAddFanin( pNodeTop, pNodeBot );
203  Abc_ObjAddFanin( pNodeTop, pFanins[4] );
204  Abc_ObjAddFanin( pNodeTop, pFanins[5] );
205  bSpin = Cudd_bddIthVar(dd, 0);
206  bCof0 = Cudd_bddIthVar(dd, 1);
207  bCof1 = Cudd_bddIte( dd, Cudd_bddIthVar(dd, 1), Cudd_bddIthVar(dd, 3), Cudd_bddIthVar(dd, 2) ); Cudd_Ref( bCof1 );
208  pNodeTop->pData = Cudd_bddIte( dd, bSpin, bCof1, bCof0 ); Cudd_Ref( (DdNode *)pNodeTop->pData );
209  Cudd_RecursiveDeref( dd, bCof1 );
210  return pNodeTop;
211 }
212 
213 /**Function*************************************************************
214 
215  Synopsis [Implementes 4:1 MUX using two 4-LUTs.]
216 
217  Description [The fanins are (c0, c1, d00, d01, d10, d11).]
218 
219  SideEffects []
220 
221  SeeAlso []
222 
223 ***********************************************************************/
224 Abc_Obj_t * Abc_NtkBddMux412a( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pFanins[] )
225 {
226  DdManager * dd = (DdManager *)pNtkNew->pManFunc;
227  Abc_Obj_t * pNodeBot, * pNodeTop;
228  DdNode * bSpin, * bCof0, * bCof1;
229  // bottom node
230  pNodeBot = Abc_NtkCreateNode( pNtkNew );
231  Abc_ObjAddFanin( pNodeBot, pFanins[1] );
232  Abc_ObjAddFanin( pNodeBot, pFanins[2] );
233  Abc_ObjAddFanin( pNodeBot, pFanins[3] );
234  bSpin = Cudd_bddIthVar(dd, 0);
235  bCof0 = Cudd_bddIthVar(dd, 1);
236  bCof1 = Cudd_bddIthVar(dd, 2);
237  pNodeBot->pData = Cudd_bddIte( dd, bSpin, bCof1, bCof0 ); Cudd_Ref( (DdNode *)pNodeBot->pData );
238  // top node
239  pNodeTop = Abc_NtkCreateNode( pNtkNew );
240  Abc_ObjAddFanin( pNodeTop, pFanins[0] );
241  Abc_ObjAddFanin( pNodeTop, pFanins[1] );
242  Abc_ObjAddFanin( pNodeTop, pNodeBot );
243  Abc_ObjAddFanin( pNodeTop, pFanins[4] );
244  Abc_ObjAddFanin( pNodeTop, pFanins[5] );
245  bSpin = Cudd_bddIthVar(dd, 0);
246  bCof0 = Cudd_bddIthVar(dd, 2);
247  bCof1 = Cudd_bddIte( dd, Cudd_bddIthVar(dd, 1), Cudd_bddIthVar(dd, 4), Cudd_bddIthVar(dd, 3) ); Cudd_Ref( bCof1 );
248  pNodeTop->pData = Cudd_bddIte( dd, bSpin, bCof1, bCof0 ); Cudd_Ref( (DdNode *)pNodeTop->pData );
249  Cudd_RecursiveDeref( dd, bCof1 );
250  return pNodeTop;
251 }
252 
253 /**Function*************************************************************
254 
255  Synopsis [Implements 4:1 MUX using three 2:1 MUXes.]
256 
257  Description [The fanins are (c0, c1, d00, d01, d10, d11).]
258 
259  SideEffects []
260 
261  SeeAlso []
262 
263 ***********************************************************************/
264 Abc_Obj_t * Abc_NtkBddMux413( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pFanins[] )
265 {
266  Abc_Obj_t * pNodesBot[3], * pNodesTop[3];
267  // left bottom
268  pNodesBot[0] = pFanins[1];
269  pNodesBot[1] = pFanins[2];
270  pNodesBot[2] = pFanins[3];
271  pNodesTop[1] = Abc_NtkBddMux21( pNtkNew, pNodesBot );
272  // right bottom
273  pNodesBot[0] = pFanins[1];
274  pNodesBot[1] = pFanins[4];
275  pNodesBot[2] = pFanins[5];
276  pNodesTop[2] = Abc_NtkBddMux21( pNtkNew, pNodesBot );
277  // top node
278  pNodesTop[0] = pFanins[0];
279  return Abc_NtkBddMux21( pNtkNew, pNodesTop );
280 }
281 
282 /**Function*************************************************************
283 
284  Synopsis [Finds unique cofactors of the function on the given level.]
285 
286  Description []
287 
288  SideEffects []
289 
290  SeeAlso []
291 
292 ***********************************************************************/
293 DdNode * Abc_NtkBddCofactors_rec( DdManager * dd, DdNode * bNode, int iCof, int iLevel, int nLevels )
294 {
295  DdNode * bNode0, * bNode1;
296  if ( Cudd_IsConstant(bNode) || iLevel == nLevels )
297  return bNode;
298  if ( Cudd_ReadPerm( dd, Cudd_NodeReadIndex(bNode) ) > iLevel )
299  {
300  bNode0 = bNode;
301  bNode1 = bNode;
302  }
303  else if ( Cudd_IsComplement(bNode) )
304  {
305  bNode0 = Cudd_Not(cuddE(Cudd_Regular(bNode)));
306  bNode1 = Cudd_Not(cuddT(Cudd_Regular(bNode)));
307  }
308  else
309  {
310  bNode0 = cuddE(bNode);
311  bNode1 = cuddT(bNode);
312  }
313  if ( (iCof >> (nLevels-1-iLevel)) & 1 )
314  return Abc_NtkBddCofactors_rec( dd, bNode1, iCof, iLevel + 1, nLevels );
315  return Abc_NtkBddCofactors_rec( dd, bNode0, iCof, iLevel + 1, nLevels );
316 }
317 
318 /**Function*************************************************************
319 
320  Synopsis [Finds unique cofactors of the function on the given level.]
321 
322  Description []
323 
324  SideEffects []
325 
326  SeeAlso []
327 
328 ***********************************************************************/
329 Vec_Ptr_t * Abc_NtkBddCofactors( DdManager * dd, DdNode * bNode, int Level )
330 {
331  Vec_Ptr_t * vCofs;
332  int i, nCofs = (1<<Level);
333  assert( Level > 0 && Level < 10 );
334  vCofs = Vec_PtrAlloc( 8 );
335  for ( i = 0; i < nCofs; i++ )
336  Vec_PtrPush( vCofs, Abc_NtkBddCofactors_rec( dd, bNode, i, 0, Level ) );
337  return vCofs;
338 }
339 
340 /**Function*************************************************************
341 
342  Synopsis [Comparison procedure for two integers.]
343 
344  Description []
345 
346  SideEffects []
347 
348  SeeAlso []
349 
350 ***********************************************************************/
351 static int Vec_PtrSortCompare( void ** pp1, void ** pp2 )
352 {
353  if ( *pp1 < *pp2 )
354  return -1;
355  if ( *pp1 > *pp2 )
356  return 1;
357  return 0;
358 }
359 
360 /**Function*************************************************************
361 
362  Synopsis [Converts the node to MUXes.]
363 
364  Description []
365 
366  SideEffects []
367 
368  SeeAlso []
369 
370 ***********************************************************************/
371 Abc_Obj_t * Abc_NtkCreateCofLut( Abc_Ntk_t * pNtkNew, DdManager * dd, DdNode * bCof, Abc_Obj_t * pNode, int Level )
372 {
373  int fVerbose = 0;
374  DdNode * bFuncNew;
375  Abc_Obj_t * pNodeNew;
376  int i;
377  assert( Abc_ObjFaninNum(pNode) > Level );
378  // create a new node
379  pNodeNew = Abc_NtkCreateNode( pNtkNew );
380  // add the fanins in the order, in which they appear in the reordered manager
381  for ( i = Level; i < Abc_ObjFaninNum(pNode); i++ )
382  Abc_ObjAddFanin( pNodeNew, Abc_ObjFanin(pNode, i)->pCopy );
383 if ( fVerbose )
384 {
385 Extra_bddPrint( dd, bCof );
386 printf( "\n" );
387 printf( "\n" );
388 }
389  // transfer the function
390  bFuncNew = Extra_bddMove( dd, bCof, -Level ); Cudd_Ref( bFuncNew );
391 if ( fVerbose )
392 {
393 Extra_bddPrint( dd, bFuncNew );
394 printf( "\n" );
395 printf( "\n" );
396 }
397  pNodeNew->pData = Extra_TransferLevelByLevel( dd, (DdManager *)pNtkNew->pManFunc, bFuncNew ); Cudd_Ref( (DdNode *)pNodeNew->pData );
398 //Extra_bddPrint( pNtkNew->pManFunc, pNodeNew->pData );
399 //printf( "\n" );
400 //printf( "\n" );
401  Cudd_RecursiveDeref( dd, bFuncNew );
402  return pNodeNew;
403 }
404 
405 /**Function*************************************************************
406 
407  Synopsis [Performs one step of Ashenhurst-Curtis decomposition.]
408 
409  Description []
410 
411  SideEffects []
412 
413  SeeAlso []
414 
415 ***********************************************************************/
416 Abc_Obj_t * Abc_NtkBddCurtis( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode, Vec_Ptr_t * vCofs, Vec_Ptr_t * vUniq )
417 {
418  DdManager * ddOld = (DdManager *)pNode->pNtk->pManFunc;
419  DdManager * ddNew = (DdManager *)pNtkNew->pManFunc;
420  DdNode * bCof, * bUniq, * bMint, * bTemp, * bFunc, * bBits[10], ** pbCodeVars;
421  Abc_Obj_t * pNodeNew = NULL, * pNodeBS[10];
422  int nLutSize = Abc_Base2Log( Vec_PtrSize(vCofs) );
423  int nBits = Abc_Base2Log( Vec_PtrSize(vUniq) );
424  int b, c, u, i;
425  assert( nBits + 2 <= nLutSize );
426  assert( nLutSize < Abc_ObjFaninNum(pNode) );
427  // start BDDs for the decompoosed blocks
428  for ( b = 0; b < nBits; b++ )
429  bBits[b] = Cudd_ReadLogicZero(ddNew), Cudd_Ref( bBits[b] );
430  // add each bound set minterm to one of the blccks
431  Vec_PtrForEachEntry( DdNode *, vCofs, bCof, c )
432  {
433  Vec_PtrForEachEntry( DdNode *, vUniq, bUniq, u )
434  if ( bUniq == bCof )
435  break;
436  assert( u < Vec_PtrSize(vUniq) );
437  for ( b = 0; b < nBits; b++ )
438  {
439  if ( ((u >> b) & 1) == 0 )
440  continue;
441  bMint = Extra_bddBitsToCube( ddNew, c, nLutSize, ddNew->vars, 1 ); Cudd_Ref( bMint );
442  bBits[b] = Cudd_bddOr( ddNew, bTemp = bBits[b], bMint ); Cudd_Ref( bBits[b] );
443  Cudd_RecursiveDeref( ddNew, bTemp );
444  Cudd_RecursiveDeref( ddNew, bMint );
445  }
446  }
447  // create bound set nodes
448  for ( b = 0; b < nBits; b++ )
449  {
450  pNodeBS[b] = Abc_NtkCreateNode( pNtkNew );
451  for ( i = 0; i < nLutSize; i++ )
452  Abc_ObjAddFanin( pNodeBS[b], Abc_ObjFanin(pNode, i)->pCopy );
453  pNodeBS[b]->pData = bBits[b]; // takes ref
454  }
455  // create composition node
456  pNodeNew = Abc_NtkCreateNode( pNtkNew );
457  // add free set variables first
458  for ( i = nLutSize; i < Abc_ObjFaninNum(pNode); i++ )
459  Abc_ObjAddFanin( pNodeNew, Abc_ObjFanin(pNode, i)->pCopy );
460  // add code bit variables next
461  for ( b = 0; b < nBits; b++ )
462  Abc_ObjAddFanin( pNodeNew, pNodeBS[b] );
463  // derive function of the composition node
464  bFunc = Cudd_ReadLogicZero(ddNew); Cudd_Ref( bFunc );
465  pbCodeVars = ddNew->vars + Abc_ObjFaninNum(pNode) - nLutSize;
466  Vec_PtrForEachEntry( DdNode *, vUniq, bUniq, u )
467  {
468  bUniq = Extra_bddMove( ddOld, bUniq, -nLutSize ); Cudd_Ref( bUniq );
469  bUniq = Extra_TransferLevelByLevel( ddOld, ddNew, bTemp = bUniq ); Cudd_Ref( bUniq );
470  Cudd_RecursiveDeref( ddOld, bTemp );
471 
472  bMint = Extra_bddBitsToCube( ddNew, u, nBits, pbCodeVars, 0 ); Cudd_Ref( bMint );
473  bMint = Cudd_bddAnd( ddNew, bTemp = bMint, bUniq ); Cudd_Ref( bMint );
474  Cudd_RecursiveDeref( ddNew, bTemp );
475  Cudd_RecursiveDeref( ddNew, bUniq );
476 
477  bFunc = Cudd_bddOr( ddNew, bTemp = bFunc, bMint ); Cudd_Ref( bFunc );
478  Cudd_RecursiveDeref( ddNew, bTemp );
479  Cudd_RecursiveDeref( ddNew, bMint );
480  }
481  pNodeNew->pData = bFunc; // takes ref
482  return pNodeNew;
483 }
484 
485 /**Function*************************************************************
486 
487  Synopsis [Tries to decompose using cofactoring into two LUTs.]
488 
489  Description []
490 
491  SideEffects []
492 
493  SeeAlso []
494 
495 ***********************************************************************/
496 Abc_Obj_t * Abc_NtkBddFindCofactor( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode, int nLutSize )
497 {
498  Abc_Obj_t * pNodeBot, * pNodeTop;
499  DdManager * ddOld = (DdManager *)pNode->pNtk->pManFunc;
500  DdManager * ddNew = (DdManager *)pNtkNew->pManFunc;
501  DdNode * bCof0 = NULL, * bCof1 = NULL, * bSupp, * bTemp, * bVar;
502  DdNode * bCof0n, * bCof1n;
503  int i, iCof, iFreeVar, fCof1Smaller = -1;
504  assert( Abc_ObjFaninNum(pNode) == nLutSize + 1 );
505  for ( iCof = 0; iCof < Abc_ObjFaninNum(pNode); iCof++ )
506  {
507  bVar = Cudd_bddIthVar( ddOld, iCof );
508  bCof0 = Cudd_Cofactor( ddOld, (DdNode *)pNode->pData, Cudd_Not(bVar) ); Cudd_Ref( bCof0 );
509  bCof1 = Cudd_Cofactor( ddOld, (DdNode *)pNode->pData, bVar ); Cudd_Ref( bCof1 );
510  if ( Cudd_SupportSize( ddOld, bCof0 ) <= nLutSize - 2 )
511  {
512  fCof1Smaller = 0;
513  break;
514  }
515  if ( Cudd_SupportSize( ddOld, bCof1 ) <= nLutSize - 2 )
516  {
517  fCof1Smaller = 1;
518  break;
519  }
520  Cudd_RecursiveDeref( ddOld, bCof0 );
521  Cudd_RecursiveDeref( ddOld, bCof1 );
522  }
523  if ( iCof == Abc_ObjFaninNum(pNode) )
524  return NULL;
525  // find unused variable
526  bSupp = Cudd_Support( ddOld, fCof1Smaller? bCof1 : bCof0 ); Cudd_Ref( bSupp );
527  iFreeVar = -1;
528  for ( i = 0; i < Abc_ObjFaninNum(pNode); i++ )
529  {
530  assert( i == Cudd_ReadPerm(ddOld, i) );
531  if ( i == iCof )
532  continue;
533  for ( bTemp = bSupp; !Cudd_IsConstant(bTemp); bTemp = cuddT(bTemp) )
534  if ( i == (int)Cudd_NodeReadIndex(bTemp) )
535  break;
536  if ( Cudd_IsConstant(bTemp) )
537  {
538  iFreeVar = i;
539  break;
540  }
541  }
542  assert( iFreeVar != iCof && iFreeVar < Abc_ObjFaninNum(pNode) );
543  Cudd_RecursiveDeref( ddOld, bSupp );
544  // transfer the cofactors
545  bCof0n = Extra_TransferLevelByLevel( ddOld, ddNew, bCof0 ); Cudd_Ref( bCof0n );
546  bCof1n = Extra_TransferLevelByLevel( ddOld, ddNew, bCof1 ); Cudd_Ref( bCof1n );
547  Cudd_RecursiveDeref( ddOld, bCof0 );
548  Cudd_RecursiveDeref( ddOld, bCof1 );
549  // create bottom node
550  pNodeBot = Abc_NtkCreateNode( pNtkNew );
551  for ( i = 0; i < Abc_ObjFaninNum(pNode); i++ )
552  Abc_ObjAddFanin( pNodeBot, Abc_ObjFanin(pNode, i)->pCopy );
553  pNodeBot->pData = fCof1Smaller? bCof0n : bCof1n;
554  // create top node
555  pNodeTop = Abc_NtkCreateNode( pNtkNew );
556  for ( i = 0; i < Abc_ObjFaninNum(pNode); i++ )
557  if ( i == iFreeVar )
558  Abc_ObjAddFanin( pNodeTop, pNodeBot );
559  else
560  Abc_ObjAddFanin( pNodeTop, Abc_ObjFanin(pNode, i)->pCopy );
561  // derive the new function
562  pNodeTop->pData = Cudd_bddIte( ddNew,
563  Cudd_bddIthVar(ddNew, iCof),
564  fCof1Smaller? bCof1n : Cudd_bddIthVar(ddNew, iFreeVar),
565  fCof1Smaller? Cudd_bddIthVar(ddNew, iFreeVar) : bCof0n );
566  Cudd_Ref( (DdNode *)pNodeTop->pData );
567  Cudd_RecursiveDeref( ddNew, fCof1Smaller? bCof1n : bCof0n );
568  return pNodeTop;
569 }
570 
571 /**Function*************************************************************
572 
573  Synopsis [Decompose the function once.]
574 
575  Description []
576 
577  SideEffects []
578 
579  SeeAlso []
580 
581 ***********************************************************************/
582 Abc_Obj_t * Abc_NtkBddDecompose( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode, int nLutSize, int fVerbose )
583 {
584  Vec_Ptr_t * vCofs, * vUniq;
585  DdManager * dd = (DdManager *)pNode->pNtk->pManFunc;
586  DdNode * bCof;
587  Abc_Obj_t * pNodeNew = NULL;
588  Abc_Obj_t * pCofs[20];
589  int i;
590  assert( Abc_ObjFaninNum(pNode) > nLutSize );
591  // try to decompose with two LUTs (the best case for Supp = LutSize + 1)
592  if ( Abc_ObjFaninNum(pNode) == nLutSize + 1 )
593  {
594 
595  pNodeNew = Abc_NtkBddFindCofactor( pNtkNew, pNode, nLutSize );
596  if ( pNodeNew != NULL )
597  {
598  if ( fVerbose )
599  printf( "Decomposing %d-input node %d using MUX.\n",
600  Abc_ObjFaninNum(pNode), Abc_ObjId(pNode) );
601  return pNodeNew;
602  }
603 
604  }
605  // cofactor w.r.t. the bound set variables
606  vCofs = Abc_NtkBddCofactors( dd, (DdNode *)pNode->pData, nLutSize );
607  vUniq = Vec_PtrDup( vCofs );
608  Vec_PtrUniqify( vUniq, (int (*)())Vec_PtrSortCompare );
609  // only perform decomposition with it is support reduring with two less vars
610  if( Vec_PtrSize(vUniq) > (1 << (nLutSize-2)) )
611  {
612  Vec_PtrFree( vCofs );
613  vCofs = Abc_NtkBddCofactors( dd, (DdNode *)pNode->pData, 2 );
614  if ( fVerbose )
615  printf( "Decomposing %d-input node %d using cofactoring with %d cofactors.\n",
616  Abc_ObjFaninNum(pNode), Abc_ObjId(pNode), Vec_PtrSize(vCofs) );
617  // implement the cofactors
618  pCofs[0] = Abc_ObjFanin(pNode, 0)->pCopy;
619  pCofs[1] = Abc_ObjFanin(pNode, 1)->pCopy;
620  Vec_PtrForEachEntry( DdNode *, vCofs, bCof, i )
621  pCofs[2+i] = Abc_NtkCreateCofLut( pNtkNew, dd, bCof, pNode, 2 );
622  if ( nLutSize == 4 )
623  pNodeNew = Abc_NtkBddMux412( pNtkNew, pCofs );
624  else if ( nLutSize == 5 )
625  pNodeNew = Abc_NtkBddMux412a( pNtkNew, pCofs );
626  else if ( nLutSize == 6 )
627  pNodeNew = Abc_NtkBddMux411( pNtkNew, pCofs );
628  else assert( 0 );
629  }
630  // alternative decompose using MUX-decomposition
631  else
632  {
633  if ( fVerbose )
634  printf( "Decomposing %d-input node %d using Curtis with %d unique columns.\n",
635  Abc_ObjFaninNum(pNode), Abc_ObjId(pNode), Vec_PtrSize(vUniq) );
636  pNodeNew = Abc_NtkBddCurtis( pNtkNew, pNode, vCofs, vUniq );
637  }
638  Vec_PtrFree( vCofs );
639  Vec_PtrFree( vUniq );
640  return pNodeNew;
641 }
642 
643 /**Function*************************************************************
644 
645  Synopsis []
646 
647  Description []
648 
649  SideEffects []
650 
651  SeeAlso []
652 
653 ***********************************************************************/
654 void Abc_NtkLutminConstruct( Abc_Ntk_t * pNtkClp, Abc_Ntk_t * pNtkDec, int nLutSize, int fVerbose )
655 {
656  Vec_Ptr_t * vNodes;
657  Abc_Obj_t * pNode, * pFanin;
658  int i, k;
659  vNodes = Abc_NtkDfs( pNtkClp, 0 );
660  Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i )
661  {
662  if ( Abc_ObjFaninNum(pNode) <= nLutSize )
663  {
664  pNode->pCopy = Abc_NtkDupObj( pNtkDec, pNode, 0 );
665  Abc_ObjForEachFanin( pNode, pFanin, k )
666  Abc_ObjAddFanin( pNode->pCopy, pFanin->pCopy );
667  }
668  else
669  pNode->pCopy = Abc_NtkBddDecompose( pNtkDec, pNode, nLutSize, fVerbose );
670  }
671  Vec_PtrFree( vNodes );
672 }
673 
674 /**Function*************************************************************
675 
676  Synopsis []
677 
678  Description []
679 
680  SideEffects []
681 
682  SeeAlso []
683 
684 ***********************************************************************/
685 Abc_Ntk_t * Abc_NtkLutminInt( Abc_Ntk_t * pNtk, int nLutSize, int fVerbose )
686 {
687  extern void Abc_NtkBddReorder( Abc_Ntk_t * pNtk, int fVerbose );
688  Abc_Ntk_t * pNtkDec;
689  // minimize BDDs
690 // Abc_NtkBddReorder( pNtk, fVerbose );
691  Abc_NtkBddReorder( pNtk, 0 );
692  // decompose one output at a time
693  pNtkDec = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_BDD );
694  // make sure the new manager has enough inputs
695  Cudd_bddIthVar( (DdManager *)pNtkDec->pManFunc, Abc_NtkGetFaninMax(pNtk) );
696  // put the results into the new network (save new CO drivers in old CO drivers)
697  Abc_NtkLutminConstruct( pNtk, pNtkDec, nLutSize, fVerbose );
698  // finalize the new network
699  Abc_NtkFinalize( pNtk, pNtkDec );
700  // make the network minimum base
701  Abc_NtkMinimumBase( pNtkDec );
702  return pNtkDec;
703 }
704 
705 /**Function*************************************************************
706 
707  Synopsis [Performs minimum-LUT decomposition of the network.]
708 
709  Description []
710 
711  SideEffects []
712 
713  SeeAlso []
714 
715 ***********************************************************************/
716 Abc_Ntk_t * Abc_NtkLutmin( Abc_Ntk_t * pNtkInit, int nLutSize, int fVerbose )
717 {
718  extern int Abc_NtkFraigSweep( Abc_Ntk_t * pNtk, int fUseInv, int fExdc, int fVerbose, int fVeryVerbose );
719  Abc_Ntk_t * pNtkNew, * pTemp;
720  int i;
721  if ( nLutSize < 4 )
722  {
723  printf( "The LUT count (%d) should be at least 4.\n", nLutSize );
724  return NULL;
725  }
726  if ( nLutSize > 6 )
727  {
728  printf( "The LUT count (%d) should not exceed 6.\n", nLutSize );
729  return NULL;
730  }
731  // create internal representation
732  if ( Abc_NtkIsStrash(pNtkInit) )
733  pNtkNew = Abc_NtkDup( pNtkInit );
734  else
735  pNtkNew = Abc_NtkStrash( pNtkInit, 0, 1, 0 );
736  // collapse the network
737  pNtkNew = Abc_NtkCollapse( pTemp = pNtkNew, 10000, 0, 1, 0 );
738  Abc_NtkDelete( pTemp );
739  if ( pNtkNew == NULL )
740  return NULL;
741  // convert it to BDD
742  if ( !Abc_NtkIsBddLogic(pNtkNew) )
743  Abc_NtkToBdd( pNtkNew );
744  // iterate decomposition
745  for ( i = 0; Abc_NtkGetFaninMax(pNtkNew) > nLutSize; i++ )
746  {
747  if ( fVerbose )
748  printf( "*** Iteration %d:\n", i+1 );
749  if ( fVerbose )
750  printf( "Decomposing network with %d nodes and %d max fanin count for K = %d.\n",
751  Abc_NtkNodeNum(pNtkNew), Abc_NtkGetFaninMax(pNtkNew), nLutSize );
752  pNtkNew = Abc_NtkLutminInt( pTemp = pNtkNew, nLutSize, fVerbose );
753  Abc_NtkDelete( pTemp );
754  }
755  // fix the problem with complemented and duplicated CO edges
756  Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 );
757  // merge functionally equivalent nodes
758  Abc_NtkFraigSweep( pNtkNew, 1, 0, 0, 0 );
759  // make sure everything is okay
760  if ( !Abc_NtkCheck( pNtkNew ) )
761  {
762  printf( "Abc_NtkLutmin: The network check has failed.\n" );
763  return 0;
764  }
765  return pNtkNew;
766 }
767 
768 ////////////////////////////////////////////////////////////////////////
769 /// END OF FILE ///
770 ////////////////////////////////////////////////////////////////////////
771 
772 
774 
static unsigned Abc_ObjId(Abc_Obj_t *pObj)
Definition: abc.h:329
static int Abc_NtkIsStrash(Abc_Ntk_t *pNtk)
Definition: abc.h:251
typedefABC_NAMESPACE_HEADER_START struct Vec_Ptr_t_ Vec_Ptr_t
INCLUDES ///.
Definition: vecPtr.h:42
Abc_Obj_t * Abc_NtkBddMux412(Abc_Ntk_t *pNtkNew, Abc_Obj_t *pFanins[])
Definition: abcLutmin.c:183
DdNode * Abc_NtkBddCofactors_rec(DdManager *dd, DdNode *bNode, int iCof, int iLevel, int nLevels)
Definition: abcLutmin.c:293
void Cudd_RecursiveDeref(DdManager *table, DdNode *n)
Definition: cuddRef.c:154
Definition: cudd.h:278
#define Cudd_Not(node)
Definition: cudd.h:367
static int Abc_NtkObjNumMax(Abc_Ntk_t *pNtk)
Definition: abc.h:284
ABC_DLL int Abc_NtkMinimumBase(Abc_Ntk_t *pNtk)
FUNCTION DEFINITIONS ///.
Definition: abcMinBase.c:48
static int Vec_PtrSortCompare(void **pp1, void **pp2)
Definition: abcLutmin.c:351
typedefABC_NAMESPACE_IMPL_START struct Vec_Int_t_ Vec_Int_t
DECLARATIONS ///.
Definition: bblif.c:37
static int Vec_PtrPushUnique(Vec_Ptr_t *p, void *Entry)
Definition: vecPtr.h:656
DdNode * Cudd_Support(DdManager *dd, DdNode *f)
Definition: cuddUtil.c:740
static int Abc_ObjFanoutNum(Abc_Obj_t *pObj)
Definition: abc.h:365
#define Cudd_IsConstant(node)
Definition: cudd.h:352
ABC_DLL Abc_Ntk_t * Abc_NtkStrash(Abc_Ntk_t *pNtk, int fAllNodes, int fCleanup, int fRecord)
Definition: abcStrash.c:265
DdNode * Cudd_ReadLogicZero(DdManager *dd)
Definition: cuddAPI.c:1058
#define Cudd_Regular(node)
Definition: cudd.h:397
static int Abc_ObjFaninNum(Abc_Obj_t *pObj)
Definition: abc.h:364
ABC_DLL int Abc_NtkGetFaninMax(Abc_Ntk_t *pNtk)
Definition: abcUtil.c:453
ABC_DLL Abc_Obj_t * Abc_NtkDupObj(Abc_Ntk_t *pNtkNew, Abc_Obj_t *pObj, int fCopyName)
Definition: abcObj.c:337
Abc_Obj_t * Abc_NtkBddMux411(Abc_Ntk_t *pNtkNew, Abc_Obj_t *pFanins[])
Definition: abcLutmin.c:150
ABC_DLL Abc_Ntk_t * Abc_NtkDup(Abc_Ntk_t *pNtk)
Definition: abcNtk.c:419
static void Vec_PtrPush(Vec_Ptr_t *p, void *Entry)
Definition: vecPtr.h:606
Abc_Ntk_t * Abc_NtkLutminInt(Abc_Ntk_t *pNtk, int nLutSize, int fVerbose)
Definition: abcLutmin.c:685
static Vec_Ptr_t * Vec_PtrDup(Vec_Ptr_t *pVec)
Definition: vecPtr.h:169
ABC_DLL int Abc_NtkCheck(Abc_Ntk_t *pNtk)
FUNCTION DEFINITIONS ///.
Definition: abcCheck.c:61
DdNode * Cudd_bddIte(DdManager *dd, DdNode *f, DdNode *g, DdNode *h)
Definition: cuddBddIte.c:143
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
Abc_Obj_t * Abc_NtkBddDecompose(Abc_Ntk_t *pNtkNew, Abc_Obj_t *pNode, int nLutSize, int fVerbose)
Definition: abcLutmin.c:582
ABC_NAMESPACE_IMPL_START int Abc_ObjCheckAbsorb(Abc_Obj_t *pObj, Abc_Obj_t *pPivot, int nLutSize, Vec_Ptr_t *vFanins)
DECLARATIONS ///.
Definition: abcLutmin.c:52
ABC_DLL void Abc_NtkDelete(Abc_Ntk_t *pNtk)
Definition: abcNtk.c:1233
ABC_DLL void Abc_ObjAddFanin(Abc_Obj_t *pObj, Abc_Obj_t *pFanin)
Definition: abcFanio.c:84
static void Vec_PtrUniqify(Vec_Ptr_t *p, int(*Vec_PtrSortCompare)()) ___unused
Definition: vecPtr.h:875
ABC_DLL Abc_Ntk_t * Abc_NtkCollapse(Abc_Ntk_t *pNtk, int fBddSizeMax, int fDualRail, int fReorder, int fVerbose)
FUNCTION DEFINITIONS ///.
Definition: abcCollapse.c:49
static void Abc_PrintTime(int level, const char *pStr, abctime time)
Definition: abc_global.h:367
void * pManFunc
Definition: abc.h:191
static int Abc_ObjIsNode(Abc_Obj_t *pObj)
Definition: abc.h:355
static int Abc_NtkNodeNum(Abc_Ntk_t *pNtk)
Definition: abc.h:293
Abc_Obj_t * Abc_NtkBddMux413(Abc_Ntk_t *pNtkNew, Abc_Obj_t *pFanins[])
Definition: abcLutmin.c:264
DdNode * Extra_TransferLevelByLevel(DdManager *ddSource, DdManager *ddDestination, DdNode *f)
Definition: extraBddMisc.c:112
static Vec_Int_t * Vec_IntStart(int nSize)
Definition: bblif.c:172
#define Cudd_IsComplement(node)
Definition: cudd.h:425
ABC_DLL Abc_Ntk_t * Abc_NtkStartFrom(Abc_Ntk_t *pNtk, Abc_NtkType_t Type, Abc_NtkFunc_t Func)
Definition: abcNtk.c:106
Abc_Obj_t * pCopy
Definition: abc.h:148
Abc_Obj_t * Abc_NtkBddCurtis(Abc_Ntk_t *pNtkNew, Abc_Obj_t *pNode, Vec_Ptr_t *vCofs, Vec_Ptr_t *vUniq)
Definition: abcLutmin.c:416
DdNode * Cudd_Cofactor(DdManager *dd, DdNode *f, DdNode *g)
Definition: cuddCof.c:123
int Cudd_ReadPerm(DdManager *dd, int i)
Definition: cuddAPI.c:2301
Vec_Ptr_t * Abc_NtkBddCofactors(DdManager *dd, DdNode *bNode, int Level)
Definition: abcLutmin.c:329
static void Vec_IntAddToEntry(Vec_Int_t *p, int i, int Addition)
Definition: bblif.c:302
DdNode * Extra_bddMove(DdManager *dd, DdNode *bF, int nVars)
Definition: extraBddMisc.c:187
static int Vec_IntEntry(Vec_Int_t *p, int i)
Definition: bblif.c:268
int Abc_NtkFraigSweep(Abc_Ntk_t *pNtk, int fUseInv, int fExdc, int fVerbose, int fVeryVerbose)
FUNCTION DEFINITIONS ///.
Definition: abcSweep.c:60
void Extra_bddPrint(DdManager *dd, DdNode *F)
Definition: extraBddMisc.c:246
Abc_Obj_t * Abc_NtkBddMux21(Abc_Ntk_t *pNtkNew, Abc_Obj_t *pFanins[])
Definition: abcLutmin.c:123
#define ABC_NAMESPACE_IMPL_END
Definition: abc_global.h:108
ABC_DLL void Abc_NtkFinalize(Abc_Ntk_t *pNtk, Abc_Ntk_t *pNtkNew)
Definition: abcNtk.c:302
void Abc_NtkLutminConstruct(Abc_Ntk_t *pNtkClp, Abc_Ntk_t *pNtkDec, int nLutSize, int fVerbose)
Definition: abcLutmin.c:654
ABC_DLL int Abc_NtkToBdd(Abc_Ntk_t *pNtk)
Definition: abcFunc.c:1160
static int Counter
Abc_Ntk_t * Abc_NtkLutmin(Abc_Ntk_t *pNtkInit, int nLutSize, int fVerbose)
Definition: abcLutmin.c:716
DdNode * Cudd_bddOr(DdManager *dd, DdNode *f, DdNode *g)
Definition: cuddBddIte.c:381
#define cuddT(node)
Definition: cuddInt.h:636
#define Abc_NtkForEachNode(pNtk, pNode, i)
Definition: abc.h:461
#define ABC_NAMESPACE_IMPL_START
Definition: abc_global.h:107
ABC_DLL int Abc_NtkLogicMakeSimpleCos(Abc_Ntk_t *pNtk, int fDuplicate)
Definition: abcUtil.c:1047
Abc_Ntk_t * pNtk
Definition: abc.h:130
static Vec_Ptr_t * Vec_PtrAlloc(int nCap)
FUNCTION DEFINITIONS ///.
Definition: vecPtr.h:83
#define Abc_ObjForEachFanin(pObj, pFanin, i)
Definition: abc.h:524
static int Abc_NtkIsBddLogic(Abc_Ntk_t *pNtk)
Definition: abc.h:265
unsigned int Cudd_NodeReadIndex(DdNode *node)
Definition: cuddAPI.c:2277
static int Abc_Base2Log(unsigned n)
Definition: abc_global.h:251
DdNode * Cudd_bddIthVar(DdManager *dd, int i)
Definition: cuddAPI.c:416
static Abc_Obj_t * Abc_NtkCreateNode(Abc_Ntk_t *pNtk)
Definition: abc.h:308
Abc_Obj_t * Abc_NtkBddFindCofactor(Abc_Ntk_t *pNtkNew, Abc_Obj_t *pNode, int nLutSize)
Definition: abcLutmin.c:496
#define cuddE(node)
Definition: cuddInt.h:652
void Abc_NtkCheckAbsorb(Abc_Ntk_t *pNtk, int nLutSize)
Definition: abcLutmin.c:83
DdNode * Cudd_bddAnd(DdManager *dd, DdNode *f, DdNode *g)
Definition: cuddBddIte.c:314
DdNode * Extra_bddBitsToCube(DdManager *dd, int Code, int CodeWidth, DdNode **pbVars, int fMsbFirst)
Definition: extraBddMisc.c:730
#define assert(ex)
Definition: util_old.h:213
static void Vec_PtrClear(Vec_Ptr_t *p)
Definition: vecPtr.h:545
Abc_Obj_t * Abc_NtkCreateCofLut(Abc_Ntk_t *pNtkNew, DdManager *dd, DdNode *bCof, Abc_Obj_t *pNode, int Level)
Definition: abcLutmin.c:371
void * pData
Definition: abc.h:145
Abc_Obj_t * Abc_NtkBddMux412a(Abc_Ntk_t *pNtkNew, Abc_Obj_t *pFanins[])
Definition: abcLutmin.c:224
void Cudd_Ref(DdNode *n)
Definition: cuddRef.c:129
static Abc_Obj_t * Abc_ObjFanin(Abc_Obj_t *pObj, int i)
Definition: abc.h:372
#define Vec_PtrForEachEntry(Type, vVec, pEntry, i)
MACRO DEFINITIONS ///.
Definition: vecPtr.h:55
ABC_INT64_T abctime
Definition: abc_global.h:278
int Cudd_SupportSize(DdManager *dd, DdNode *f)
Definition: cuddUtil.c:857
void Abc_NtkBddReorder(Abc_Ntk_t *pNtk, int fVerbose)
Definition: abcReorder.c:77
static void Vec_PtrFree(Vec_Ptr_t *p)
Definition: vecPtr.h:223