ABC: A System for Sequential Synthesis and Verification
 
Loading...
Searching...
No Matches
ivyBalance.c
Go to the documentation of this file.
1
20
21#include "ivy.h"
22
24
25
29
30static int Ivy_NodeBalance_rec( Ivy_Man_t * pNew, Ivy_Obj_t * pObj, Vec_Vec_t * vStore, int Level, int fUpdateLevel );
31static Vec_Ptr_t * Ivy_NodeBalanceCone( Ivy_Obj_t * pObj, Vec_Vec_t * vStore, int Level );
32static int Ivy_NodeBalanceFindLeft( Vec_Ptr_t * vSuper );
33static void Ivy_NodeBalancePermute( Ivy_Man_t * p, Vec_Ptr_t * vSuper, int LeftBound, int fExor );
34static void Ivy_NodeBalancePushUniqueOrderByLevel( Vec_Ptr_t * vStore, Ivy_Obj_t * pObj );
35
39
51Ivy_Man_t * Ivy_ManBalance( Ivy_Man_t * p, int fUpdateLevel )
52{
53 Ivy_Man_t * pNew;
54 Ivy_Obj_t * pObj, * pDriver;
55 Vec_Vec_t * vStore;
56 int i, NewNodeId;
57 // clean the old manager
59 // create the new manager
60 pNew = Ivy_ManStart();
61 // map the nodes
62 Ivy_ManConst1(p)->TravId = Ivy_EdgeFromNode( Ivy_ManConst1(pNew) );
63 Ivy_ManForEachPi( p, pObj, i )
64 pObj->TravId = Ivy_EdgeFromNode( Ivy_ObjCreatePi(pNew) );
65 // if HAIG is defined, trasfer the pointers to the PIs/latches
66// if ( p->pHaig )
67// Ivy_ManHaigTrasfer( p, pNew );
68 // balance the AIG
69 vStore = Vec_VecAlloc( 50 );
70 Ivy_ManForEachPo( p, pObj, i )
71 {
72 pDriver = Ivy_ObjReal( Ivy_ObjChild0(pObj) );
73 NewNodeId = Ivy_NodeBalance_rec( pNew, Ivy_Regular(pDriver), vStore, 0, fUpdateLevel );
74 NewNodeId = Ivy_EdgeNotCond( NewNodeId, Ivy_IsComplement(pDriver) );
75 Ivy_ObjCreatePo( pNew, Ivy_EdgeToNode(pNew, NewNodeId) );
76 }
77 Vec_VecFree( vStore );
78 if ( (i = Ivy_ManCleanup( pNew )) )
79 {
80// printf( "Cleanup after balancing removed %d dangling nodes.\n", i );
81 }
82 // check the resulting AIG
83 if ( !Ivy_ManCheck(pNew) )
84 printf( "Ivy_ManBalance(): The check has failed.\n" );
85 return pNew;
86}
87
100{
101 int Diff = Ivy_Regular(*pp1)->Level - Ivy_Regular(*pp2)->Level;
102 if ( Diff > 0 )
103 return -1;
104 if ( Diff < 0 )
105 return 1;
106 Diff = Ivy_Regular(*pp1)->Id - Ivy_Regular(*pp2)->Id;
107 if ( Diff > 0 )
108 return -1;
109 if ( Diff < 0 )
110 return 1;
111 return 0;
112}
113
125int Ivy_NodeBalance_rec( Ivy_Man_t * pNew, Ivy_Obj_t * pObjOld, Vec_Vec_t * vStore, int Level, int fUpdateLevel )
126{
127 Ivy_Obj_t * pObjNew;
128 Vec_Ptr_t * vSuper;
129 int i, NewNodeId;
130 assert( !Ivy_IsComplement(pObjOld) );
131 assert( !Ivy_ObjIsBuf(pObjOld) );
132 // return if the result is known
133 if ( Ivy_ObjIsConst1(pObjOld) )
134 return pObjOld->TravId;
135 if ( pObjOld->TravId )
136 return pObjOld->TravId;
137 assert( Ivy_ObjIsNode(pObjOld) );
138 // get the implication supergate
139 vSuper = Ivy_NodeBalanceCone( pObjOld, vStore, Level );
140 if ( vSuper->nSize == 0 )
141 { // it means that the supergate contains two nodes in the opposite polarity
142 pObjOld->TravId = Ivy_EdgeFromNode( Ivy_ManConst0(pNew) );
143 return pObjOld->TravId;
144 }
145 if ( vSuper->nSize < 2 )
146 printf( "BUG!\n" );
147 // for each old node, derive the new well-balanced node
148 for ( i = 0; i < vSuper->nSize; i++ )
149 {
150 NewNodeId = Ivy_NodeBalance_rec( pNew, Ivy_Regular((Ivy_Obj_t *)vSuper->pArray[i]), vStore, Level + 1, fUpdateLevel );
151 NewNodeId = Ivy_EdgeNotCond( NewNodeId, Ivy_IsComplement((Ivy_Obj_t *)vSuper->pArray[i]) );
152 vSuper->pArray[i] = Ivy_EdgeToNode( pNew, NewNodeId );
153 }
154 // build the supergate
155 pObjNew = Ivy_NodeBalanceBuildSuper( pNew, vSuper, Ivy_ObjType(pObjOld), fUpdateLevel );
156 vSuper->nSize = 0;
157 // make sure the balanced node is not assigned
158 assert( pObjOld->TravId == 0 );
159 pObjOld->TravId = Ivy_EdgeFromNode( pObjNew );
160// assert( pObjOld->Level >= Ivy_Regular(pObjNew)->Level );
161 return pObjOld->TravId;
162}
163
175Ivy_Obj_t * Ivy_NodeBalanceBuildSuper( Ivy_Man_t * p, Vec_Ptr_t * vSuper, Ivy_Type_t Type, int fUpdateLevel )
176{
177 Ivy_Obj_t * pObj1, * pObj2;
178 int LeftBound;
179 assert( vSuper->nSize > 1 );
180 // sort the new nodes by level in the decreasing order
181 Vec_PtrSort( vSuper, (int (*)(const void *, const void *))Ivy_NodeCompareLevelsDecrease );
182 // balance the nodes
183 while ( vSuper->nSize > 1 )
184 {
185 // find the left bound on the node to be paired
186 LeftBound = (!fUpdateLevel)? 0 : Ivy_NodeBalanceFindLeft( vSuper );
187 // find the node that can be shared (if no such node, randomize choice)
188 Ivy_NodeBalancePermute( p, vSuper, LeftBound, Type == IVY_EXOR );
189 // pull out the last two nodes
190 pObj1 = (Ivy_Obj_t *)Vec_PtrPop(vSuper);
191 pObj2 = (Ivy_Obj_t *)Vec_PtrPop(vSuper);
192 Ivy_NodeBalancePushUniqueOrderByLevel( vSuper, Ivy_Oper(p, pObj1, pObj2, Type) );
193 }
194 return (Ivy_Obj_t *)Vec_PtrEntry(vSuper, 0);
195}
196
208int Ivy_NodeBalanceCone_rec( Ivy_Obj_t * pRoot, Ivy_Obj_t * pObj, Vec_Ptr_t * vSuper )
209{
210 int RetValue1, RetValue2, i;
211 // check if the node is visited
212 if ( Ivy_Regular(pObj)->fMarkB )
213 {
214 // check if the node occurs in the same polarity
215 for ( i = 0; i < vSuper->nSize; i++ )
216 if ( vSuper->pArray[i] == pObj )
217 return 1;
218 // check if the node is present in the opposite polarity
219 for ( i = 0; i < vSuper->nSize; i++ )
220 if ( vSuper->pArray[i] == Ivy_Not(pObj) )
221 return -1;
222 assert( 0 );
223 return 0;
224 }
225 // if the new node is complemented or a PI, another gate begins
226 if ( pObj != pRoot && (Ivy_IsComplement(pObj) || Ivy_ObjType(pObj) != Ivy_ObjType(pRoot) || Ivy_ObjRefs(pObj) > 1 || Vec_PtrSize(vSuper) > 10000) )
227 {
228 Vec_PtrPush( vSuper, pObj );
229 Ivy_Regular(pObj)->fMarkB = 1;
230 return 0;
231 }
232 assert( !Ivy_IsComplement(pObj) );
233 assert( Ivy_ObjIsNode(pObj) );
234 // go through the branches
235 RetValue1 = Ivy_NodeBalanceCone_rec( pRoot, Ivy_ObjReal( Ivy_ObjChild0(pObj) ), vSuper );
236 RetValue2 = Ivy_NodeBalanceCone_rec( pRoot, Ivy_ObjReal( Ivy_ObjChild1(pObj) ), vSuper );
237 if ( RetValue1 == -1 || RetValue2 == -1 )
238 return -1;
239 // return 1 if at least one branch has a duplicate
240 return RetValue1 || RetValue2;
241}
242
254Vec_Ptr_t * Ivy_NodeBalanceCone( Ivy_Obj_t * pObj, Vec_Vec_t * vStore, int Level )
255{
256 Vec_Ptr_t * vNodes;
257 int RetValue, i;
258 assert( !Ivy_IsComplement(pObj) );
259 // extend the storage
260 if ( Vec_VecSize( vStore ) <= Level )
261 Vec_VecPush( vStore, Level, 0 );
262 // get the temporary array of nodes
263 vNodes = Vec_VecEntry( vStore, Level );
264 Vec_PtrClear( vNodes );
265 // collect the nodes in the implication supergate
266 RetValue = Ivy_NodeBalanceCone_rec( pObj, pObj, vNodes );
267 assert( vNodes->nSize > 1 );
268 // unmark the visited nodes
269 Vec_PtrForEachEntry( Ivy_Obj_t *, vNodes, pObj, i )
270 Ivy_Regular(pObj)->fMarkB = 0;
271 // if we found the node and its complement in the same implication supergate,
272 // return empty set of nodes (meaning that we should use constant-0 node)
273 if ( RetValue == -1 )
274 vNodes->nSize = 0;
275 return vNodes;
276}
277
293int Ivy_NodeBalanceFindLeft( Vec_Ptr_t * vSuper )
294{
295 Ivy_Obj_t * pObjRight, * pObjLeft;
296 int Current;
297 // if two or less nodes, pair with the first
298 if ( Vec_PtrSize(vSuper) < 3 )
299 return 0;
300 // set the pointer to the one before the last
301 Current = Vec_PtrSize(vSuper) - 2;
302 pObjRight = (Ivy_Obj_t *)Vec_PtrEntry( vSuper, Current );
303 // go through the nodes to the left of this one
304 for ( Current--; Current >= 0; Current-- )
305 {
306 // get the next node on the left
307 pObjLeft = (Ivy_Obj_t *)Vec_PtrEntry( vSuper, Current );
308 // if the level of this node is different, quit the loop
309 if ( Ivy_Regular(pObjLeft)->Level != Ivy_Regular(pObjRight)->Level )
310 break;
311 }
312 Current++;
313 // get the node, for which the equality holds
314 pObjLeft = (Ivy_Obj_t *)Vec_PtrEntry( vSuper, Current );
315 assert( Ivy_Regular(pObjLeft)->Level == Ivy_Regular(pObjRight)->Level );
316 return Current;
317}
318
331void Ivy_NodeBalancePermute( Ivy_Man_t * p, Vec_Ptr_t * vSuper, int LeftBound, int fExor )
332{
333 Ivy_Obj_t * pObj1, * pObj2, * pObj3, * pGhost;
334 int RightBound, i;
335 // get the right bound
336 RightBound = Vec_PtrSize(vSuper) - 2;
337 assert( LeftBound <= RightBound );
338 if ( LeftBound == RightBound )
339 return;
340 // get the two last nodes
341 pObj1 = (Ivy_Obj_t *)Vec_PtrEntry( vSuper, RightBound + 1 );
342 pObj2 = (Ivy_Obj_t *)Vec_PtrEntry( vSuper, RightBound );
343 if ( Ivy_Regular(pObj1) == p->pConst1 || Ivy_Regular(pObj2) == p->pConst1 )
344 return;
345 // find the first node that can be shared
346 for ( i = RightBound; i >= LeftBound; i-- )
347 {
348 pObj3 = (Ivy_Obj_t *)Vec_PtrEntry( vSuper, i );
349 if ( Ivy_Regular(pObj3) == p->pConst1 )
350 {
351 Vec_PtrWriteEntry( vSuper, i, pObj2 );
352 Vec_PtrWriteEntry( vSuper, RightBound, pObj3 );
353 return;
354 }
355 pGhost = Ivy_ObjCreateGhost( p, pObj1, pObj3, fExor? IVY_EXOR : IVY_AND, IVY_INIT_NONE );
356 if ( Ivy_TableLookup( p, pGhost ) )
357 {
358 if ( pObj3 == pObj2 )
359 return;
360 Vec_PtrWriteEntry( vSuper, i, pObj2 );
361 Vec_PtrWriteEntry( vSuper, RightBound, pObj3 );
362 return;
363 }
364 }
365/*
366 // we did not find the node to share, randomize choice
367 {
368 int Choice = rand() % (RightBound - LeftBound + 1);
369 pObj3 = Vec_PtrEntry( vSuper, LeftBound + Choice );
370 if ( pObj3 == pObj2 )
371 return;
372 Vec_PtrWriteEntry( vSuper, LeftBound + Choice, pObj2 );
373 Vec_PtrWriteEntry( vSuper, RightBound, pObj3 );
374 }
375*/
376}
377
389void Ivy_NodeBalancePushUniqueOrderByLevel( Vec_Ptr_t * vStore, Ivy_Obj_t * pObj )
390{
391 Ivy_Obj_t * pObj1, * pObj2;
392 int i;
393 if ( Vec_PtrPushUnique(vStore, pObj) )
394 return;
395 // find the p of the node
396 for ( i = vStore->nSize-1; i > 0; i-- )
397 {
398 pObj1 = (Ivy_Obj_t *)vStore->pArray[i ];
399 pObj2 = (Ivy_Obj_t *)vStore->pArray[i-1];
400 if ( Ivy_Regular(pObj1)->Level <= Ivy_Regular(pObj2)->Level )
401 break;
402 vStore->pArray[i ] = pObj2;
403 vStore->pArray[i-1] = pObj1;
404 }
405}
406
407
411
412
414
#define ABC_NAMESPACE_IMPL_START
#define ABC_NAMESPACE_IMPL_END
Cube * p
Definition exorList.c:222
Ivy_Obj_t * Ivy_NodeBalanceBuildSuper(Ivy_Man_t *p, Vec_Ptr_t *vSuper, Ivy_Type_t Type, int fUpdateLevel)
Definition ivyBalance.c:175
int Ivy_NodeBalanceCone_rec(Ivy_Obj_t *pRoot, Ivy_Obj_t *pObj, Vec_Ptr_t *vSuper)
Definition ivyBalance.c:208
int Ivy_NodeCompareLevelsDecrease(Ivy_Obj_t **pp1, Ivy_Obj_t **pp2)
Definition ivyBalance.c:99
Ivy_Man_t * Ivy_ManBalance(Ivy_Man_t *p, int fUpdateLevel)
FUNCTION DEFINITIONS ///.
Definition ivyBalance.c:51
int Ivy_ManCheck(Ivy_Man_t *p)
DECLARATIONS ///.
Definition ivyCheck.c:45
typedefABC_NAMESPACE_HEADER_START struct Ivy_Man_t_ Ivy_Man_t
INCLUDES ///.
Definition ivy.h:46
@ IVY_INIT_NONE
Definition ivy.h:66
Ivy_Obj_t * Ivy_TableLookup(Ivy_Man_t *p, Ivy_Obj_t *pObj)
FUNCTION DEFINITIONS ///.
Definition ivyTable.c:71
int Ivy_ManCleanup(Ivy_Man_t *p)
Definition ivyMan.c:265
Ivy_Man_t * Ivy_ManStart()
DECLARATIONS ///.
Definition ivyMan.c:45
Ivy_Obj_t * Ivy_ObjCreatePo(Ivy_Man_t *p, Ivy_Obj_t *pDriver)
Definition ivyObj.c:61
Ivy_Obj_t * Ivy_ObjReal(Ivy_Obj_t *pObj)
Definition ivyUtil.c:609
Ivy_Obj_t * Ivy_Oper(Ivy_Man_t *p, Ivy_Obj_t *p0, Ivy_Obj_t *p1, Ivy_Type_t Type)
FUNCTION DEFINITIONS ///.
Definition ivyOper.c:63
#define Ivy_ManForEachPo(p, pObj, i)
Definition ivy.h:390
struct Ivy_Obj_t_ Ivy_Obj_t
Definition ivy.h:47
Ivy_Obj_t * Ivy_ObjCreatePi(Ivy_Man_t *p)
DECLARATIONS ///.
Definition ivyObj.c:45
Ivy_Type_t
Definition ivy.h:52
@ IVY_AND
Definition ivy.h:58
@ IVY_EXOR
Definition ivy.h:59
void Ivy_ManCleanTravId(Ivy_Man_t *p)
Definition ivyUtil.c:63
#define Ivy_ManForEachPi(p, pObj, i)
ITERATORS ///.
Definition ivy.h:387
int TravId
Definition ivy.h:76
#define assert(ex)
Definition util_old.h:213
typedefABC_NAMESPACE_HEADER_START struct Vec_Ptr_t_ Vec_Ptr_t
INCLUDES ///.
Definition vecPtr.h:42
#define Vec_PtrForEachEntry(Type, vVec, pEntry, i)
MACRO DEFINITIONS ///.
Definition vecPtr.h:55
typedefABC_NAMESPACE_HEADER_START struct Vec_Vec_t_ Vec_Vec_t
INCLUDES ///.
Definition vecVec.h:42