abc-master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
hopBalance.c
Go to the documentation of this file.
1 /**CFile****************************************************************
2 
3  FileName [hopBalance.c]
4 
5  SystemName [ABC: Logic synthesis and verification system.]
6 
7  PackageName [Minimalistic And-Inverter Graph package.]
8 
9  Synopsis [Algebraic AIG balancing.]
10 
11  Author [Alan Mishchenko]
12 
13  Affiliation [UC Berkeley]
14 
15  Date [Ver. 1.0. Started - May 11, 2006.]
16 
17  Revision [$Id: hopBalance.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $]
18 
19 ***********************************************************************/
20 
21 #include "hop.h"
22 
24 
25 
26 ////////////////////////////////////////////////////////////////////////
27 /// DECLARATIONS ///
28 ////////////////////////////////////////////////////////////////////////
29 
30 static Hop_Obj_t * Hop_NodeBalance_rec( Hop_Man_t * pNew, Hop_Obj_t * pObj, Vec_Vec_t * vStore, int Level, int fUpdateLevel );
31 static Vec_Ptr_t * Hop_NodeBalanceCone( Hop_Obj_t * pObj, Vec_Vec_t * vStore, int Level );
32 static int Hop_NodeBalanceFindLeft( Vec_Ptr_t * vSuper );
33 static void Hop_NodeBalancePermute( Hop_Man_t * p, Vec_Ptr_t * vSuper, int LeftBound, int fExor );
34 static void Hop_NodeBalancePushUniqueOrderByLevel( Vec_Ptr_t * vStore, Hop_Obj_t * pObj );
35 
36 ////////////////////////////////////////////////////////////////////////
37 /// FUNCTION DEFINITIONS ///
38 ////////////////////////////////////////////////////////////////////////
39 
40 /**Function*************************************************************
41 
42  Synopsis [Performs algebraic balancing of the AIG.]
43 
44  Description []
45 
46  SideEffects []
47 
48  SeeAlso []
49 
50 ***********************************************************************/
51 Hop_Man_t * Hop_ManBalance( Hop_Man_t * p, int fUpdateLevel )
52 {
53  Hop_Man_t * pNew;
54  Hop_Obj_t * pObj, * pObjNew;
55  Vec_Vec_t * vStore;
56  int i;
57  // create the new manager
58  pNew = Hop_ManStart();
59  pNew->fRefCount = 0;
60  // map the PI nodes
61  Hop_ManCleanData( p );
62  Hop_ManConst1(p)->pData = Hop_ManConst1(pNew);
63  Hop_ManForEachPi( p, pObj, i )
64  pObj->pData = Hop_ObjCreatePi(pNew);
65  // balance the AIG
66  vStore = Vec_VecAlloc( 50 );
67  Hop_ManForEachPo( p, pObj, i )
68  {
69  pObjNew = Hop_NodeBalance_rec( pNew, Hop_ObjFanin0(pObj), vStore, 0, fUpdateLevel );
70  Hop_ObjCreatePo( pNew, Hop_NotCond( pObjNew, Hop_ObjFaninC0(pObj) ) );
71  }
72  Vec_VecFree( vStore );
73  // remove dangling nodes
74 // Hop_ManCreateRefs( pNew );
75 // if ( i = Hop_ManCleanup( pNew ) )
76 // printf( "Cleanup after balancing removed %d dangling nodes.\n", i );
77  // check the resulting AIG
78  if ( !Hop_ManCheck(pNew) )
79  printf( "Hop_ManBalance(): The check has failed.\n" );
80  return pNew;
81 }
82 
83 /**Function*************************************************************
84 
85  Synopsis [Returns the new node constructed.]
86 
87  Description []
88 
89  SideEffects []
90 
91  SeeAlso []
92 
93 ***********************************************************************/
94 Hop_Obj_t * Hop_NodeBalance_rec( Hop_Man_t * pNew, Hop_Obj_t * pObjOld, Vec_Vec_t * vStore, int Level, int fUpdateLevel )
95 {
96  Hop_Obj_t * pObjNew;
97  Vec_Ptr_t * vSuper;
98  int i;
99  assert( !Hop_IsComplement(pObjOld) );
100  // return if the result is known
101  if ( pObjOld->pData )
102  return (Hop_Obj_t *)pObjOld->pData;
103  assert( Hop_ObjIsNode(pObjOld) );
104  // get the implication supergate
105  vSuper = Hop_NodeBalanceCone( pObjOld, vStore, Level );
106  // check if supergate contains two nodes in the opposite polarity
107  if ( vSuper->nSize == 0 )
108  return (Hop_Obj_t *)(pObjOld->pData = Hop_ManConst0(pNew));
109  if ( Vec_PtrSize(vSuper) < 2 )
110  printf( "BUG!\n" );
111  // for each old node, derive the new well-balanced node
112  for ( i = 0; i < Vec_PtrSize(vSuper); i++ )
113  {
114  pObjNew = Hop_NodeBalance_rec( pNew, Hop_Regular((Hop_Obj_t *)vSuper->pArray[i]), vStore, Level + 1, fUpdateLevel );
115  vSuper->pArray[i] = Hop_NotCond( pObjNew, Hop_IsComplement((Hop_Obj_t *)vSuper->pArray[i]) );
116  }
117  // build the supergate
118  pObjNew = Hop_NodeBalanceBuildSuper( pNew, vSuper, Hop_ObjType(pObjOld), fUpdateLevel );
119  // make sure the balanced node is not assigned
120 // assert( pObjOld->Level >= Hop_Regular(pObjNew)->Level );
121  assert( pObjOld->pData == NULL );
122  return (Hop_Obj_t *)(pObjOld->pData = pObjNew);
123 }
124 
125 /**Function*************************************************************
126 
127  Synopsis [Collects the nodes of the supergate.]
128 
129  Description []
130 
131  SideEffects []
132 
133  SeeAlso []
134 
135 ***********************************************************************/
136 int Hop_NodeBalanceCone_rec( Hop_Obj_t * pRoot, Hop_Obj_t * pObj, Vec_Ptr_t * vSuper )
137 {
138  int RetValue1, RetValue2, i;
139  // check if the node is visited
140  if ( Hop_Regular(pObj)->fMarkB )
141  {
142  // check if the node occurs in the same polarity
143  for ( i = 0; i < vSuper->nSize; i++ )
144  if ( vSuper->pArray[i] == pObj )
145  return 1;
146  // check if the node is present in the opposite polarity
147  for ( i = 0; i < vSuper->nSize; i++ )
148  if ( vSuper->pArray[i] == Hop_Not(pObj) )
149  return -1;
150  assert( 0 );
151  return 0;
152  }
153  // if the new node is complemented or a PI, another gate begins
154  if ( pObj != pRoot && (Hop_IsComplement(pObj) || Hop_ObjType(pObj) != Hop_ObjType(pRoot) || Hop_ObjRefs(pObj) > 1 || Vec_PtrSize(vSuper) > 10000) )
155  {
156  Vec_PtrPush( vSuper, pObj );
157  Hop_Regular(pObj)->fMarkB = 1;
158  return 0;
159  }
160  assert( !Hop_IsComplement(pObj) );
161  assert( Hop_ObjIsNode(pObj) );
162  // go through the branches
163  RetValue1 = Hop_NodeBalanceCone_rec( pRoot, Hop_ObjChild0(pObj), vSuper );
164  RetValue2 = Hop_NodeBalanceCone_rec( pRoot, Hop_ObjChild1(pObj), vSuper );
165  if ( RetValue1 == -1 || RetValue2 == -1 )
166  return -1;
167  // return 1 if at least one branch has a duplicate
168  return RetValue1 || RetValue2;
169 }
170 
171 /**Function*************************************************************
172 
173  Synopsis [Collects the nodes of the supergate.]
174 
175  Description []
176 
177  SideEffects []
178 
179  SeeAlso []
180 
181 ***********************************************************************/
182 Vec_Ptr_t * Hop_NodeBalanceCone( Hop_Obj_t * pObj, Vec_Vec_t * vStore, int Level )
183 {
184  Vec_Ptr_t * vNodes;
185  int RetValue, i;
186  assert( !Hop_IsComplement(pObj) );
187  // extend the storage
188  if ( Vec_VecSize( vStore ) <= Level )
189  Vec_VecPush( vStore, Level, 0 );
190  // get the temporary array of nodes
191  vNodes = Vec_VecEntry( vStore, Level );
192  Vec_PtrClear( vNodes );
193  // collect the nodes in the implication supergate
194  RetValue = Hop_NodeBalanceCone_rec( pObj, pObj, vNodes );
195  assert( vNodes->nSize > 1 );
196  // unmark the visited nodes
197  Vec_PtrForEachEntry( Hop_Obj_t *, vNodes, pObj, i )
198  Hop_Regular(pObj)->fMarkB = 0;
199  // if we found the node and its complement in the same implication supergate,
200  // return empty set of nodes (meaning that we should use constant-0 node)
201  if ( RetValue == -1 )
202  vNodes->nSize = 0;
203  return vNodes;
204 }
205 
206 /**Function*************************************************************
207 
208  Synopsis [Procedure used for sorting the nodes in decreasing order of levels.]
209 
210  Description []
211 
212  SideEffects []
213 
214  SeeAlso []
215 
216 ***********************************************************************/
218 {
219  int Diff = Hop_ObjLevel(Hop_Regular(*pp1)) - Hop_ObjLevel(Hop_Regular(*pp2));
220  if ( Diff > 0 )
221  return -1;
222  if ( Diff < 0 )
223  return 1;
224  Diff = Hop_Regular(*pp1)->Id - Hop_Regular(*pp2)->Id;
225  if ( Diff > 0 )
226  return -1;
227  if ( Diff < 0 )
228  return 1;
229  return 0;
230 }
231 
232 /**Function*************************************************************
233 
234  Synopsis [Builds implication supergate.]
235 
236  Description []
237 
238  SideEffects []
239 
240  SeeAlso []
241 
242 ***********************************************************************/
243 Hop_Obj_t * Hop_NodeBalanceBuildSuper( Hop_Man_t * p, Vec_Ptr_t * vSuper, Hop_Type_t Type, int fUpdateLevel )
244 {
245  Hop_Obj_t * pObj1, * pObj2;
246  int LeftBound;
247  assert( vSuper->nSize > 1 );
248  // sort the new nodes by level in the decreasing order
249  Vec_PtrSort( vSuper, (int (*)(void))Hop_NodeCompareLevelsDecrease );
250  // balance the nodes
251  while ( vSuper->nSize > 1 )
252  {
253  // find the left bound on the node to be paired
254  LeftBound = (!fUpdateLevel)? 0 : Hop_NodeBalanceFindLeft( vSuper );
255  // find the node that can be shared (if no such node, randomize choice)
256  Hop_NodeBalancePermute( p, vSuper, LeftBound, Type == AIG_EXOR );
257  // pull out the last two nodes
258  pObj1 = (Hop_Obj_t *)Vec_PtrPop(vSuper);
259  pObj2 = (Hop_Obj_t *)Vec_PtrPop(vSuper);
260  Hop_NodeBalancePushUniqueOrderByLevel( vSuper, Hop_Oper(p, pObj1, pObj2, Type) );
261  }
262  return (Hop_Obj_t *)Vec_PtrEntry(vSuper, 0);
263 }
264 
265 /**Function*************************************************************
266 
267  Synopsis [Finds the left bound on the next candidate to be paired.]
268 
269  Description [The nodes in the array are in the decreasing order of levels.
270  The last node in the array has the smallest level. By default it would be paired
271  with the next node on the left. However, it may be possible to pair it with some
272  other node on the left, in such a way that the new node is shared. This procedure
273  finds the index of the left-most node, which can be paired with the last node.]
274 
275  SideEffects []
276 
277  SeeAlso []
278 
279 ***********************************************************************/
281 {
282  Hop_Obj_t * pObjRight, * pObjLeft;
283  int Current;
284  // if two or less nodes, pair with the first
285  if ( Vec_PtrSize(vSuper) < 3 )
286  return 0;
287  // set the pointer to the one before the last
288  Current = Vec_PtrSize(vSuper) - 2;
289  pObjRight = (Hop_Obj_t *)Vec_PtrEntry( vSuper, Current );
290  // go through the nodes to the left of this one
291  for ( Current--; Current >= 0; Current-- )
292  {
293  // get the next node on the left
294  pObjLeft = (Hop_Obj_t *)Vec_PtrEntry( vSuper, Current );
295  // if the level of this node is different, quit the loop
296  if ( Hop_ObjLevel(Hop_Regular(pObjLeft)) != Hop_ObjLevel(Hop_Regular(pObjRight)) )
297  break;
298  }
299  Current++;
300  // get the node, for which the equality holds
301  pObjLeft = (Hop_Obj_t *)Vec_PtrEntry( vSuper, Current );
302  assert( Hop_ObjLevel(Hop_Regular(pObjLeft)) == Hop_ObjLevel(Hop_Regular(pObjRight)) );
303  return Current;
304 }
305 
306 /**Function*************************************************************
307 
308  Synopsis [Moves closer to the end the node that is best for sharing.]
309 
310  Description [If there is no node with sharing, randomly chooses one of
311  the legal nodes.]
312 
313  SideEffects []
314 
315  SeeAlso []
316 
317 ***********************************************************************/
318 void Hop_NodeBalancePermute( Hop_Man_t * p, Vec_Ptr_t * vSuper, int LeftBound, int fExor )
319 {
320  Hop_Obj_t * pObj1, * pObj2, * pObj3, * pGhost;
321  int RightBound, i;
322  // get the right bound
323  RightBound = Vec_PtrSize(vSuper) - 2;
324  assert( LeftBound <= RightBound );
325  if ( LeftBound == RightBound )
326  return;
327  // get the two last nodes
328  pObj1 = (Hop_Obj_t *)Vec_PtrEntry( vSuper, RightBound + 1 );
329  pObj2 = (Hop_Obj_t *)Vec_PtrEntry( vSuper, RightBound );
330  if ( Hop_Regular(pObj1) == p->pConst1 || Hop_Regular(pObj2) == p->pConst1 )
331  return;
332  // find the first node that can be shared
333  for ( i = RightBound; i >= LeftBound; i-- )
334  {
335  pObj3 = (Hop_Obj_t *)Vec_PtrEntry( vSuper, i );
336  if ( Hop_Regular(pObj3) == p->pConst1 )
337  {
338  Vec_PtrWriteEntry( vSuper, i, pObj2 );
339  Vec_PtrWriteEntry( vSuper, RightBound, pObj3 );
340  return;
341  }
342  pGhost = Hop_ObjCreateGhost( p, pObj1, pObj3, fExor? AIG_EXOR : AIG_AND );
343  if ( Hop_TableLookup( p, pGhost ) )
344  {
345  if ( pObj3 == pObj2 )
346  return;
347  Vec_PtrWriteEntry( vSuper, i, pObj2 );
348  Vec_PtrWriteEntry( vSuper, RightBound, pObj3 );
349  return;
350  }
351  }
352 /*
353  // we did not find the node to share, randomize choice
354  {
355  int Choice = rand() % (RightBound - LeftBound + 1);
356  pObj3 = Vec_PtrEntry( vSuper, LeftBound + Choice );
357  if ( pObj3 == pObj2 )
358  return;
359  Vec_PtrWriteEntry( vSuper, LeftBound + Choice, pObj2 );
360  Vec_PtrWriteEntry( vSuper, RightBound, pObj3 );
361  }
362 */
363 }
364 
365 /**Function*************************************************************
366 
367  Synopsis [Inserts a new node in the order by levels.]
368 
369  Description []
370 
371  SideEffects []
372 
373  SeeAlso []
374 
375 ***********************************************************************/
377 {
378  Hop_Obj_t * pObj1, * pObj2;
379  int i;
380  if ( Vec_PtrPushUnique(vStore, pObj) )
381  return;
382  // find the p of the node
383  for ( i = vStore->nSize-1; i > 0; i-- )
384  {
385  pObj1 = (Hop_Obj_t *)vStore->pArray[i ];
386  pObj2 = (Hop_Obj_t *)vStore->pArray[i-1];
387  if ( Hop_ObjLevel(Hop_Regular(pObj1)) <= Hop_ObjLevel(Hop_Regular(pObj2)) )
388  break;
389  vStore->pArray[i ] = pObj2;
390  vStore->pArray[i-1] = pObj1;
391  }
392 }
393 
394 
395 ////////////////////////////////////////////////////////////////////////
396 /// END OF FILE ///
397 ////////////////////////////////////////////////////////////////////////
398 
399 
401 
int Hop_ManCheck(Hop_Man_t *p)
DECLARATIONS ///.
Definition: hopCheck.c:45
static Hop_Obj_t * Hop_ObjChild0(Hop_Obj_t *pObj)
Definition: hop.h:184
typedefABC_NAMESPACE_HEADER_START struct Vec_Ptr_t_ Vec_Ptr_t
INCLUDES ///.
Definition: vecPtr.h:42
static void Vec_VecPush(Vec_Vec_t *p, int Level, void *Entry)
Definition: vecVec.h:456
static Vec_Vec_t * Vec_VecAlloc(int nCap)
FUNCTION DEFINITIONS ///.
Definition: vecVec.h:145
static int Hop_ObjRefs(Hop_Obj_t *pObj)
Definition: hop.h:176
typedefABC_NAMESPACE_HEADER_START struct Vec_Vec_t_ Vec_Vec_t
INCLUDES ///.
Definition: vecVec.h:42
static Hop_Obj_t * Hop_ManConst1(Hop_Man_t *p)
Definition: hop.h:132
static Llb_Mgr_t * p
Definition: llb3Image.c:950
static int Vec_PtrPushUnique(Vec_Ptr_t *p, void *Entry)
Definition: vecPtr.h:656
static void Hop_NodeBalancePermute(Hop_Man_t *p, Vec_Ptr_t *vSuper, int LeftBound, int fExor)
Definition: hopBalance.c:318
static ABC_NAMESPACE_IMPL_START Hop_Obj_t * Hop_NodeBalance_rec(Hop_Man_t *pNew, Hop_Obj_t *pObj, Vec_Vec_t *vStore, int Level, int fUpdateLevel)
DECLARATIONS ///.
Definition: hopBalance.c:94
static int Hop_ObjIsNode(Hop_Obj_t *pObj)
Definition: hop.h:160
int Id
Definition: hop.h:80
static Hop_Type_t Hop_ObjType(Hop_Obj_t *pObj)
Definition: hop.h:153
#define Hop_ManForEachPi(p, pObj, i)
ITERATORS ///.
Definition: hop.h:259
static int Hop_NodeBalanceFindLeft(Vec_Ptr_t *vSuper)
Definition: hopBalance.c:280
#define Hop_ManForEachPo(p, pObj, i)
Definition: hop.h:262
Definition: hop.h:60
static void Vec_PtrSort(Vec_Ptr_t *p, int(*Vec_PtrSortCompare)()) ___unused
Definition: vecPtr.h:851
static void Vec_PtrPush(Vec_Ptr_t *p, void *Entry)
Definition: vecPtr.h:606
int Hop_NodeBalanceCone_rec(Hop_Obj_t *pRoot, Hop_Obj_t *pObj, Vec_Ptr_t *vSuper)
Definition: hopBalance.c:136
static int Vec_PtrSize(Vec_Ptr_t *p)
Definition: vecPtr.h:295
static void Vec_VecFree(Vec_Vec_t *p)
Definition: vecVec.h:347
static void * Vec_PtrPop(Vec_Ptr_t *p)
Definition: vecPtr.h:677
static Hop_Obj_t * Hop_Not(Hop_Obj_t *p)
Definition: hop.h:127
Definition: hop.h:65
Hop_Obj_t * Hop_Oper(Hop_Man_t *p, Hop_Obj_t *p0, Hop_Obj_t *p1, Hop_Type_t Type)
Definition: hopOper.c:83
Hop_Type_t
Definition: hop.h:54
Hop_Man_t * Hop_ManBalance(Hop_Man_t *p, int fUpdateLevel)
FUNCTION DEFINITIONS ///.
Definition: hopBalance.c:51
Hop_Obj_t * Hop_NodeBalanceBuildSuper(Hop_Man_t *p, Vec_Ptr_t *vSuper, Hop_Type_t Type, int fUpdateLevel)
Definition: hopBalance.c:243
#define ABC_NAMESPACE_IMPL_END
Definition: abc_global.h:108
static Hop_Obj_t * Hop_ObjChild1(Hop_Obj_t *pObj)
Definition: hop.h:185
if(last==0)
Definition: sparse_int.h:34
Hop_Man_t * Hop_ManStart()
DECLARATIONS ///.
Definition: hopMan.c:45
static int Hop_IsComplement(Hop_Obj_t *p)
Definition: hop.h:129
void * pData
Definition: hop.h:68
static Hop_Obj_t * Hop_ObjFanin0(Hop_Obj_t *pObj)
Definition: hop.h:182
static void Vec_PtrWriteEntry(Vec_Ptr_t *p, int i, void *Entry)
Definition: vecPtr.h:396
#define ABC_NAMESPACE_IMPL_START
Definition: abc_global.h:107
static void * Vec_PtrEntry(Vec_Ptr_t *p, int i)
Definition: vecPtr.h:362
static int Hop_ObjLevel(Hop_Obj_t *pObj)
Definition: hop.h:190
static Vec_Ptr_t * Hop_NodeBalanceCone(Hop_Obj_t *pObj, Vec_Vec_t *vStore, int Level)
Definition: hopBalance.c:182
static int Hop_ObjFaninC0(Hop_Obj_t *pObj)
Definition: hop.h:180
static Hop_Obj_t * Hop_NotCond(Hop_Obj_t *p, int c)
Definition: hop.h:128
void Hop_ManCleanData(Hop_Man_t *p)
Definition: hopUtil.c:63
static int Vec_VecSize(Vec_Vec_t *p)
Definition: vecVec.h:222
Definition: hop.h:59
#define assert(ex)
Definition: util_old.h:213
static void Vec_PtrClear(Vec_Ptr_t *p)
Definition: vecPtr.h:545
static Hop_Obj_t * Hop_ManConst0(Hop_Man_t *p)
Definition: hop.h:131
static Vec_Ptr_t * Vec_VecEntry(Vec_Vec_t *p, int i)
Definition: vecVec.h:271
Hop_Obj_t * Hop_ObjCreatePo(Hop_Man_t *p, Hop_Obj_t *pDriver)
Definition: hopObj.c:67
#define Vec_PtrForEachEntry(Type, vVec, pEntry, i)
MACRO DEFINITIONS ///.
Definition: vecPtr.h:55
int Hop_NodeCompareLevelsDecrease(Hop_Obj_t **pp1, Hop_Obj_t **pp2)
Definition: hopBalance.c:217
static Hop_Obj_t * Hop_Regular(Hop_Obj_t *p)
Definition: hop.h:126
static Hop_Obj_t * Hop_ObjCreateGhost(Hop_Man_t *p, Hop_Obj_t *p0, Hop_Obj_t *p1, Hop_Type_t Type)
Definition: hop.h:208
Hop_Obj_t * Hop_ObjCreatePi(Hop_Man_t *p)
DECLARATIONS ///.
Definition: hopObj.c:45
static void Hop_NodeBalancePushUniqueOrderByLevel(Vec_Ptr_t *vStore, Hop_Obj_t *pObj)
Definition: hopBalance.c:376
unsigned int fMarkB
Definition: hop.h:78
typedefABC_NAMESPACE_HEADER_START struct Hop_Man_t_ Hop_Man_t
INCLUDES ///.
Definition: hop.h:49
Hop_Obj_t * Hop_TableLookup(Hop_Man_t *p, Hop_Obj_t *pGhost)
FUNCTION DEFINITIONS ///.
Definition: hopTable.c:71