1 /**CFile****************************************************************
2 
3   FileName    [gia.c]
4 
5   SystemName  [ABC: Logic synthesis and verification system.]
6 
7   PackageName [Scalable AIG package.]
8 
9   Synopsis    []
10 
11   Author      [Alan Mishchenko]
12 
13   Affiliation [UC Berkeley]
14 
15   Date        [Ver. 1.0. Started - June 20, 2005.]
16 
17   Revision    [$Id: gia.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
18 
19 ***********************************************************************/
20 
21 #include "gia.h"
22 #include "misc/vec/vecHsh.h"
23 #include "misc/vec/vecWec.h"
24 
25 
26 ABC_NAMESPACE_IMPL_START
27 
28 
29 #define ISO_MASK 0xFF
30 static unsigned int s_256Primes[ISO_MASK+1] =
31 {
32     0x984b6ad9,0x18a6eed3,0x950353e2,0x6222f6eb,0xdfbedd47,0xef0f9023,0xac932a26,0x590eaf55,
33     0x97d0a034,0xdc36cd2e,0x22736b37,0xdc9066b0,0x2eb2f98b,0x5d9c7baf,0x85747c9e,0x8aca1055,
34     0x50d66b74,0x2f01ae9e,0xa1a80123,0x3e1ce2dc,0xebedbc57,0x4e68bc34,0x855ee0cf,0x17275120,
35     0x2ae7f2df,0xf71039eb,0x7c283eec,0x70cd1137,0x7cf651f3,0xa87bfa7a,0x14d87f02,0xe82e197d,
36     0x8d8a5ebe,0x1e6a15dc,0x197d49db,0x5bab9c89,0x4b55dea7,0x55dede49,0x9a6a8080,0xe5e51035,
37     0xe148d658,0x8a17eb3b,0xe22e4b38,0xe5be2a9a,0xbe938cbb,0x3b981069,0x7f9c0c8e,0xf756df10,
38     0x8fa783f7,0x252062ce,0x3dc46b4b,0xf70f6432,0x3f378276,0x44b137a1,0x2bf74b77,0x04892ed6,
39     0xfd318de1,0xd58c235e,0x94c6d25b,0x7aa5f218,0x35c9e921,0x5732fbbb,0x06026481,0xf584a44f,
40     0x946e1b5f,0x8463d5b2,0x4ebca7b2,0x54887b15,0x08d1e804,0x5b22067d,0x794580f6,0xb351ea43,
41     0xbce555b9,0x19ae2194,0xd32f1396,0x6fc1a7f1,0x1fd8a867,0x3a89fdb0,0xea49c61c,0x25f8a879,
42     0xde1e6437,0x7c74afca,0x8ba63e50,0xb1572074,0xe4655092,0xdb6f8b1c,0xc2955f3c,0x327f85ba,
43     0x60a17021,0x95bd261d,0xdea94f28,0x04528b65,0xbe0109cc,0x26dd5688,0x6ab2729d,0xc4f029ce,
44     0xacf7a0be,0x4c912f55,0x34c06e65,0x4fbb938e,0x1533fb5f,0x03da06bd,0x48262889,0xc2523d7d,
45     0x28a71d57,0x89f9713a,0xf574c551,0x7a99deb5,0x52834d91,0x5a6f4484,0xc67ba946,0x13ae698f,
46     0x3e390f34,0x34fc9593,0x894c7932,0x6cf414a3,0xdb7928ab,0x13a3b8a3,0x4b381c1d,0xa10b54cb,
47     0x55359d9d,0x35a3422a,0x58d1b551,0x0fd4de20,0x199eb3f4,0x167e09e2,0x3ee6a956,0x5371a7fa,
48     0xd424efda,0x74f521c5,0xcb899ff6,0x4a42e4f4,0x747917b6,0x4b08df0b,0x090c7a39,0x11e909e4,
49     0x258e2e32,0xd9fad92d,0x48fe5f69,0x0545cde6,0x55937b37,0x9b4ae4e4,0x1332b40e,0xc3792351,
50     0xaff982ef,0x4dba132a,0x38b81ef1,0x28e641bf,0x227208c1,0xec4bbe37,0xc4e1821c,0x512c9d09,
51     0xdaef1257,0xb63e7784,0x043e04d7,0x9c2cea47,0x45a0e59a,0x281315ca,0x849f0aac,0xa4071ed3,
52     0x0ef707b3,0xfe8dac02,0x12173864,0x471f6d46,0x24a53c0a,0x35ab9265,0xbbf77406,0xa2144e79,
53     0xb39a884a,0x0baf5b6d,0xcccee3dd,0x12c77584,0x2907325b,0xfd1adcd2,0xd16ee972,0x345ad6c1,
54     0x315ebe66,0xc7ad2b8d,0x99e82c8d,0xe52da8c8,0xba50f1d3,0x66689cd8,0x2e8e9138,0x43e15e74,
55     0xf1ced14d,0x188ec52a,0xe0ef3cbb,0xa958aedc,0x4107a1bc,0x5a9e7a3e,0x3bde939f,0xb5b28d5a,
56     0x596fe848,0xe85ad00c,0x0b6b3aae,0x44503086,0x25b5695c,0xc0c31dcd,0x5ee617f0,0x74d40c3a,
57     0xd2cb2b9f,0x1e19f5fa,0x81e24faf,0xa01ed68f,0xcee172fc,0x7fdf2e4d,0x002f4774,0x664f82dd,
58     0xc569c39a,0xa2d4dcbe,0xaadea306,0xa4c947bf,0xa413e4e3,0x81fb5486,0x8a404970,0x752c980c,
59     0x98d1d881,0x5c932c1e,0xeee65dfb,0x37592cdd,0x0fd4e65b,0xad1d383f,0x62a1452f,0x8872f68d,
60     0xb58c919b,0x345c8ee3,0xb583a6d6,0x43d72cb3,0x77aaa0aa,0xeb508242,0xf2db64f8,0x86294328,
61     0x82211731,0x1239a9d5,0x673ba5de,0xaf4af007,0x44203b19,0x2399d955,0xa175cd12,0x595928a7,
62     0x6918928b,0xde3126bb,0x6c99835c,0x63ba1fa2,0xdebbdff0,0x3d02e541,0xd6f7aac6,0xe80b4cd0,
63     0xd0fa29f1,0x804cac5e,0x2c226798,0x462f624c,0xad05b377,0x22924fcd,0xfbea205c,0x1b47586d
64 };
65 
66 static int s_PrimeC = 49;
67 //static int s_PrimeC = 1;
68 
69 ////////////////////////////////////////////////////////////////////////
70 ///                        DECLARATIONS                              ///
71 ////////////////////////////////////////////////////////////////////////
72 
73 typedef struct Gia_Iso2Man_t_       Gia_Iso2Man_t;
74 struct Gia_Iso2Man_t_
75 {
76     Gia_Man_t *      pGia;
77     int              nObjs;
78     int              nUniques;
79     // internal data
80     Vec_Int_t *      vUniques;      // unique numbers
81     Vec_Int_t *      vTied;         // tied objects
82     Vec_Int_t *      vTable;        // hash table
83     Vec_Int_t *      vPlaces;       // used places in the table
84     Vec_Ptr_t *      vSingles;      // singleton objects
85     // isomorphism check
86     Vec_Int_t *      vVec0;         // isomorphism map
87     Vec_Int_t *      vVec1;         // isomorphism map
88     Vec_Int_t *      vMap0;         // isomorphism map
89     Vec_Int_t *      vMap1;         // isomorphism map
90     // statistics
91     int              nIters;
92     abctime          timeStart;
93     abctime          timeSim;
94     abctime          timeRefine;
95     abctime          timeSort;
96     abctime          timeOther;
97     abctime          timeTotal;
98 };
99 
100 ////////////////////////////////////////////////////////////////////////
101 ///                     FUNCTION DEFINITIONS                         ///
102 ////////////////////////////////////////////////////////////////////////
103 
104 /**Function*************************************************************
105 
106   Synopsis    []
107 
108   Description []
109 
110   SideEffects []
111 
112   SeeAlso     []
113 
114 ***********************************************************************/
Gia_Iso2ManCollectTies(Gia_Man_t * p)115 Vec_Int_t * Gia_Iso2ManCollectTies( Gia_Man_t * p )
116 {
117     Vec_Int_t * vTies;
118     Gia_Obj_t * pObj;
119     int i;
120     vTies = Vec_IntAlloc( Gia_ManCandNum(p) );
121     Gia_ManForEachCand( p, pObj, i )
122         Vec_IntPush( vTies, i );
123     return vTies;
124 }
Gia_Iso2ManPrepare(Gia_Man_t * p)125 void Gia_Iso2ManPrepare( Gia_Man_t * p )
126 {
127     Gia_Obj_t * pObj;
128     int i;
129     Gia_ManForEachObj( p, pObj, i )
130         pObj->Value = Gia_ObjIsAnd(pObj) ? 1 + Abc_MaxInt(Gia_ObjFanin0(pObj)->Value, Gia_ObjFanin1(pObj)->Value) : 0;
131     Gia_ManConst0(p)->Value = s_256Primes[ISO_MASK];
132     Gia_ManForEachObj1( p, pObj, i )
133         if ( Gia_ObjIsAnd(pObj) )
134             pObj->Value = s_256Primes[pObj->Value & ISO_MASK] + s_256Primes[ISO_MASK - 10 + Gia_ObjFaninC0(pObj) + Gia_ObjFaninC1(pObj)];
135         else if ( Gia_ObjIsPi(p, pObj) )
136             pObj->Value = s_256Primes[ISO_MASK-1];
137         else if ( Gia_ObjIsRo(p, pObj) )
138             pObj->Value = s_256Primes[ISO_MASK-2];
139 }
Gia_Iso2ManPropagate(Gia_Man_t * p)140 void Gia_Iso2ManPropagate( Gia_Man_t * p )
141 {
142     Gia_Obj_t * pObj, * pObjRo;
143     int i;
144     Gia_ManForEachObj1( p, pObj, i )
145         if ( Gia_ObjIsAnd(pObj) )
146         {
147             pObj->Value += (Gia_ObjFaninC0(pObj) + s_PrimeC) * Gia_ObjFanin0(pObj)->Value + (Gia_ObjFaninC1(pObj) + s_PrimeC) * Gia_ObjFanin1(pObj)->Value;
148             if ( Gia_ObjFaninC0(pObj) == Gia_ObjFaninC1(pObj) && Gia_ObjFanin0(pObj)->Value == Gia_ObjFanin1(pObj)->Value )
149                 pObj->Value += s_256Primes[ISO_MASK - 11];
150         }
151         else if ( Gia_ObjIsCo(pObj) )
152             pObj->Value += (Gia_ObjFaninC0(pObj) + s_PrimeC) * Gia_ObjFanin0(pObj)->Value;
153     Gia_ManForEachRiRo( p, pObj, pObjRo, i )
154     {
155         pObjRo->Value += pObj->Value;
156         if ( pObjRo == Gia_ObjFanin0(pObj) )
157             pObjRo->Value += s_256Primes[ISO_MASK - 12];
158     }
159 }
160 
161 /**Function*************************************************************
162 
163   Synopsis    []
164 
165   Description []
166 
167   SideEffects []
168 
169   SeeAlso     []
170 
171 ***********************************************************************/
Gia_Iso2ManCone_rec(Gia_Man_t * p,int Id,int Level)172 unsigned Gia_Iso2ManCone_rec( Gia_Man_t * p, int Id, int Level )
173 {
174     Gia_Obj_t * pObj;
175     if ( Level == 0 )
176         return 0;
177     if ( Gia_ObjIsTravIdCurrentId(p, Id) )
178         return 0;
179     Gia_ObjSetTravIdCurrentId(p, Id);
180     pObj = Gia_ManObj( p, Id );
181     if ( Gia_ObjIsAnd(pObj) )
182         return pObj->Value + Gia_Iso2ManCone_rec( p, Gia_ObjFaninId0(pObj, Id), Level-1 ) + Gia_Iso2ManCone_rec( p, Gia_ObjFaninId1(pObj, Id), Level-1 );
183     if ( Gia_ObjIsPi(p, pObj) )
184         return pObj->Value;
185     if ( Gia_ObjIsRo(p, pObj) )
186         return pObj->Value + Gia_Iso2ManCone_rec( p, Gia_ObjId(p, Gia_ObjFanin0(Gia_ObjRoToRi(p, pObj))), Level );
187     assert( Gia_ObjIsConst0(pObj) );
188     return pObj->Value;
189 }
Gia_Iso2ManCone(Gia_Man_t * p,int Id,int Level)190 unsigned Gia_Iso2ManCone( Gia_Man_t * p, int Id, int Level )
191 {
192     Gia_ManIncrementTravId( p );
193     return Gia_Iso2ManCone_rec( p, Id, Level );
194 }
Gia_Iso2ManUpdate(Gia_Iso2Man_t * p,int Level)195 void Gia_Iso2ManUpdate( Gia_Iso2Man_t * p, int Level )
196 {
197     Gia_Obj_t * pObj;
198     int i;
199     Gia_ManForEachObjVec( p->vTied, p->pGia, pObj, i )
200         pObj->Value += Gia_Iso2ManCone( p->pGia, Gia_ObjId(p->pGia, pObj), Level );
201 }
202 
203 /**Function*************************************************************
204 
205   Synopsis    []
206 
207   Description []
208 
209   SideEffects []
210 
211   SeeAlso     []
212 
213 ***********************************************************************/
Gia_Iso2ManStart(Gia_Man_t * pGia)214 Gia_Iso2Man_t * Gia_Iso2ManStart( Gia_Man_t * pGia )
215 {
216     Gia_Iso2Man_t * p;
217     p = ABC_CALLOC( Gia_Iso2Man_t, 1 );
218     p->pGia      = pGia;
219     p->nObjs     = Gia_ManObjNum( pGia );
220     p->nUniques  = 0;
221     // internal data
222     p->vUniques  = Vec_IntStartFull( p->nObjs );
223     p->vTied     = Gia_Iso2ManCollectTies( pGia );
224     p->vTable    = Vec_IntStart( Abc_PrimeCudd(1*p->nObjs) );
225     p->vPlaces   = Vec_IntAlloc( 1000 );
226     p->vSingles  = Vec_PtrAlloc( 1000 );
227     p->vVec0     = Vec_IntAlloc( 10000 );
228     p->vVec1     = Vec_IntAlloc( 10000 );
229     p->vMap0     = Vec_IntStart( p->nObjs );
230     p->vMap1     = Vec_IntStart( p->nObjs );
231     // add constant 0 object
232     Vec_IntWriteEntry( p->vUniques, 0, p->nUniques++ );
233     return p;
234 }
Gia_Iso2ManStop(Gia_Iso2Man_t * p)235 void Gia_Iso2ManStop( Gia_Iso2Man_t * p )
236 {
237     Vec_IntFree( p->vUniques );
238     Vec_IntFree( p->vTied );
239     Vec_IntFree( p->vTable );
240     Vec_IntFree( p->vPlaces );
241     Vec_PtrFree( p->vSingles );
242     Vec_IntFree( p->vMap0 );
243     Vec_IntFree( p->vMap1 );
244     Vec_IntFree( p->vVec0 );
245     Vec_IntFree( p->vVec1 );
246     ABC_FREE( p );
247 }
Gia_Iso2ManPrint(Gia_Iso2Man_t * p,abctime Time,int fVerbose)248 void Gia_Iso2ManPrint( Gia_Iso2Man_t * p, abctime Time, int fVerbose )
249 {
250     if ( !fVerbose )
251         return;
252     printf( "Iter %4d :  ", p->nIters++ );
253     printf( "Entries =%8d.  ", Vec_IntSize(p->vTied) );
254     printf( "Uniques =%8d.  ", p->nUniques );
255     printf( "Singles =%8d.  ", Vec_PtrSize(p->vSingles) );
256     printf( "%9.2f sec", (float)(Time)/(float)(CLOCKS_PER_SEC) );
257     printf( "\n" );
258     fflush( stdout );
259 }
260 
261 /**Function*************************************************************
262 
263   Synopsis    [Uniqifies objects using their signature.]
264 
265   Description [Assumes the tied objects are in p->vTied. Assumes that
266   updated signature (pObj->Value) is assigned to these objects. Returns
267   the array of unique objects p->vSingles sorted by signature.  Compacts
268   the array of tied objects p->vTied.]
269 
270   SideEffects []
271 
272   SeeAlso     []
273 
274 ***********************************************************************/
Gia_ObjCompareByValue2(Gia_Obj_t ** pp1,Gia_Obj_t ** pp2)275 int Gia_ObjCompareByValue2( Gia_Obj_t ** pp1, Gia_Obj_t ** pp2 ) { return (int)(*pp1)->Value - (int)(*pp2)->Value; }
Gia_Iso2ManUniqify(Gia_Iso2Man_t * p)276 int Gia_Iso2ManUniqify( Gia_Iso2Man_t * p )
277 {
278     int fVerify = 0;
279     Gia_Obj_t * pObj, * pTemp;
280     int * pTable = Vec_IntArray(p->vTable);
281     int i, k, nSize = Vec_IntSize(p->vTable);
282 
283     if ( fVerify )
284         for ( k = 0; k < nSize; k++ )
285             assert( pTable[k] == 0 );
286     if ( fVerify )
287         Gia_ManForEachObjVec( p->vTied, p->pGia, pObj, i )
288             assert( pObj->fMark0 == 0 );
289 
290 #if 0
291     Gia_ManForEachObjVec( p->vTied, p->pGia, pObj, i )
292     {
293         printf( "%3d : ", Gia_ObjId(p->pGia, pObj) );
294         Extra_PrintBinary( stdout, &pObj->Value, 32 );
295         printf( "\n" );
296     }
297 #endif
298 
299     // add objects to the table
300     Vec_IntClear( p->vPlaces );
301     Gia_ManForEachObjVec( p->vTied, p->pGia, pObj, i )
302     {
303         for ( k = pObj->Value % nSize; (pTemp = pTable[k] ? Gia_ManObj(p->pGia, pTable[k]) : NULL); k = (k + 1) % nSize )
304             if ( pTemp->Value == pObj->Value )
305             {
306                 pTemp->fMark0 = 1;
307                 pObj->fMark0 = 1;
308                 break;
309             }
310         if ( pTemp != NULL )
311             continue;
312         pTable[k] = Gia_ObjId(p->pGia, pObj);
313         Vec_IntPush( p->vPlaces, k );
314     }
315     // clean the table
316     Vec_IntForEachEntry( p->vPlaces, k, i )
317         pTable[k] = 0;
318     // collect singleton objects and compact tied objects
319     k = 0;
320     Vec_PtrClear( p->vSingles );
321     Gia_ManForEachObjVec( p->vTied, p->pGia, pObj, i )
322         if ( pObj->fMark0 == 0 )
323             Vec_PtrPush( p->vSingles, pObj );
324         else
325         {
326             pObj->fMark0 = 0;
327             Vec_IntWriteEntry( p->vTied, k++, Gia_ObjId(p->pGia, pObj) );
328         }
329     Vec_IntShrink( p->vTied, k );
330     // sort singletons
331     Vec_PtrSort( p->vSingles, (int (*)(void))Gia_ObjCompareByValue2 );
332     // add them to unique and increment signature
333     Vec_PtrForEachEntry( Gia_Obj_t *, p->vSingles, pObj, i )
334     {
335         pObj->Value += s_256Primes[p->nUniques & ISO_MASK];
336         assert( Vec_IntEntry(p->vUniques, Gia_ObjId(p->pGia, pObj)) == -1 );
337         Vec_IntWriteEntry( p->vUniques, Gia_ObjId(p->pGia, pObj), p->nUniques++ );
338     }
339     return Vec_PtrSize( p->vSingles );
340 }
341 
342 /**Function*************************************************************
343 
344   Synopsis    []
345 
346   Description []
347 
348   SideEffects []
349 
350   SeeAlso     []
351 
352 ***********************************************************************/
Gia_Iso2ManDerivePoClasses(Gia_Man_t * pGia)353 Vec_Wec_t * Gia_Iso2ManDerivePoClasses( Gia_Man_t * pGia )
354 {
355     Vec_Wec_t * vEquivs;
356     Vec_Int_t * vValues;
357     Vec_Int_t * vMap;
358     Gia_Obj_t * pObj;
359     int i;
360     vValues = Vec_IntAlloc( Gia_ManPoNum(pGia) );
361     Gia_ManForEachPo( pGia, pObj, i )
362         Vec_IntPush( vValues, pObj->Value );
363     vMap = Hsh_IntManHashArray( vValues, 1 );
364     Vec_IntFree( vValues );
365     vEquivs = Vec_WecCreateClasses( vMap );
366     Vec_IntFree( vMap );
367     return vEquivs;
368 }
369 
370 /**Function*************************************************************
371 
372   Synopsis    []
373 
374   Description []
375 
376   SideEffects []
377 
378   SeeAlso     []
379 
380 ***********************************************************************/
Gia_Iso2ManCollectOrder2_rec(Gia_Man_t * p,int Id,Vec_Int_t * vVec)381 void Gia_Iso2ManCollectOrder2_rec( Gia_Man_t * p, int Id, Vec_Int_t * vVec )
382 {
383     Gia_Obj_t * pObj;
384     if ( Gia_ObjIsTravIdCurrentId(p, Id) )
385         return;
386     Gia_ObjSetTravIdCurrentId(p, Id);
387     pObj = Gia_ManObj( p, Id );
388     if ( Gia_ObjIsAnd(pObj) )
389     {
390         if ( Gia_ObjFanin0(pObj)->Value <= Gia_ObjFanin1(pObj)->Value )
391         {
392             Gia_Iso2ManCollectOrder2_rec( p, Gia_ObjFaninId0(pObj, Id), vVec );
393             Gia_Iso2ManCollectOrder2_rec( p, Gia_ObjFaninId1(pObj, Id), vVec );
394         }
395         else
396         {
397             Gia_Iso2ManCollectOrder2_rec( p, Gia_ObjFaninId1(pObj, Id), vVec );
398             Gia_Iso2ManCollectOrder2_rec( p, Gia_ObjFaninId0(pObj, Id), vVec );
399         }
400     }
401     else if ( Gia_ObjIsCo(pObj) )
402     {
403         Gia_Iso2ManCollectOrder2_rec( p, Gia_ObjFaninId0(pObj, Id), vVec );
404     }
405     else if ( Gia_ObjIsPi(p, pObj) )
406     {
407     }
408     else assert( Gia_ObjIsConst0(pObj) );
409     Vec_IntPush( vVec, Id );
410 }
Gia_Iso2ManCollectOrder2(Gia_Man_t * pGia,int * pPos,int nPos)411 Vec_Int_t * Gia_Iso2ManCollectOrder2( Gia_Man_t * pGia, int * pPos, int nPos )
412 {
413     Vec_Int_t * vVec;
414     int i;
415     vVec = Vec_IntAlloc( 1000 );
416     Gia_ManIncrementTravId( pGia );
417     for ( i = 0; i < nPos; i++ )
418         Gia_Iso2ManCollectOrder2_rec( pGia, Gia_ObjId(pGia, Gia_ManPo(pGia, pPos[i])), vVec );
419     return vVec;
420 }
421 
422 /**Function*************************************************************
423 
424   Synopsis    []
425 
426   Description []
427 
428   SideEffects []
429 
430   SeeAlso     []
431 
432 ***********************************************************************/
Gia_Iso2ManCollectOrder_rec(Gia_Man_t * p,int Id,Vec_Int_t * vRoots,Vec_Int_t * vVec,Vec_Int_t * vMap)433 void Gia_Iso2ManCollectOrder_rec( Gia_Man_t * p, int Id, Vec_Int_t * vRoots, Vec_Int_t * vVec, Vec_Int_t * vMap )
434 {
435     Gia_Obj_t * pObj;
436     if ( Gia_ObjIsTravIdCurrentId(p, Id) )
437         return;
438     Gia_ObjSetTravIdCurrentId(p, Id);
439     pObj = Gia_ManObj( p, Id );
440     if ( Gia_ObjIsAnd(pObj) )
441     {
442         if ( Gia_ObjFanin0(pObj)->Value <= Gia_ObjFanin1(pObj)->Value )
443         {
444             Gia_Iso2ManCollectOrder_rec( p, Gia_ObjFaninId0(pObj, Id), vRoots, vVec, vMap );
445             Gia_Iso2ManCollectOrder_rec( p, Gia_ObjFaninId1(pObj, Id), vRoots, vVec, vMap );
446         }
447         else
448         {
449             Gia_Iso2ManCollectOrder_rec( p, Gia_ObjFaninId1(pObj, Id), vRoots, vVec, vMap );
450             Gia_Iso2ManCollectOrder_rec( p, Gia_ObjFaninId0(pObj, Id), vRoots, vVec, vMap );
451         }
452     }
453     else if ( Gia_ObjIsCo(pObj) )
454     {
455         Gia_Iso2ManCollectOrder_rec( p, Gia_ObjFaninId0(pObj, Id), vRoots, vVec, vMap );
456     }
457     else if ( Gia_ObjIsCi(pObj) )
458     {
459         if ( Gia_ObjIsRo(p, pObj) )
460             Vec_IntPush( vRoots, Gia_ObjId(p, Gia_ObjRoToRi(p, pObj)) );
461     }
462     else assert( Gia_ObjIsConst0(pObj) );
463     Vec_IntWriteEntry( vMap, Id, Vec_IntSize(vVec) );
464     Vec_IntPush( vVec, Id );
465 }
Gia_Iso2ManCollectOrder(Gia_Man_t * pGia,int * pPos,int nPos,Vec_Int_t * vRoots,Vec_Int_t * vVec,Vec_Int_t * vMap)466 void Gia_Iso2ManCollectOrder( Gia_Man_t * pGia, int * pPos, int nPos, Vec_Int_t * vRoots, Vec_Int_t * vVec, Vec_Int_t * vMap )
467 {
468     int i, iRoot;
469     Vec_IntClear( vRoots );
470     for ( i = 0; i < nPos; i++ )
471         Vec_IntPush( vRoots, Gia_ObjId(pGia, Gia_ManPo(pGia, pPos[i])) );
472     Vec_IntClear( vVec );
473     Gia_ManIncrementTravId( pGia );
474     Vec_IntForEachEntry( vRoots, iRoot, i )
475         Gia_Iso2ManCollectOrder_rec( pGia, iRoot, vRoots, vVec, vMap );
476 }
477 
478 /**Function*************************************************************
479 
480   Synopsis    []
481 
482   Description []
483 
484   SideEffects []
485 
486   SeeAlso     []
487 
488 ***********************************************************************/
Gia_Iso2ManCheckIsoPair(Gia_Man_t * p,Vec_Int_t * vVec0,Vec_Int_t * vVec1,Vec_Int_t * vMap0,Vec_Int_t * vMap1)489 int Gia_Iso2ManCheckIsoPair( Gia_Man_t * p, Vec_Int_t * vVec0, Vec_Int_t * vVec1, Vec_Int_t * vMap0, Vec_Int_t * vMap1 )
490 {
491     Gia_Obj_t * pObj0, * pObj1;
492     int k, iObj0, iObj1;
493     Vec_IntForEachEntryTwo( vVec0, vVec1, iObj0, iObj1, k )
494     {
495         if ( iObj0 == iObj1 )
496             continue;
497         pObj0 = Gia_ManObj(p, iObj0);
498         pObj1 = Gia_ManObj(p, iObj1);
499         if ( pObj0->Value != pObj1->Value )
500             return 0;
501         assert( pObj0->Value == pObj1->Value );
502         if ( !Gia_ObjIsAnd(pObj0) )
503             continue;
504         if ( Gia_ObjFanin0(pObj0)->Value <= Gia_ObjFanin1(pObj0)->Value )
505         {
506             if ( Gia_ObjFanin0(pObj1)->Value <= Gia_ObjFanin1(pObj1)->Value )
507             {
508                 if ( Gia_ObjFaninC0(pObj0) != Gia_ObjFaninC0(pObj1)  || Gia_ObjFaninC1(pObj0) != Gia_ObjFaninC1(pObj1)   ||
509                      Vec_IntEntry(vMap0, Gia_ObjFaninId0p(p, pObj0)) != Vec_IntEntry( vMap1, Gia_ObjFaninId0p(p, pObj1)) ||
510                      Vec_IntEntry(vMap0, Gia_ObjFaninId1p(p, pObj0)) != Vec_IntEntry( vMap1, Gia_ObjFaninId1p(p, pObj1)) )
511                      return 0;
512             }
513             else
514             {
515                 if ( Gia_ObjFaninC0(pObj0) != Gia_ObjFaninC1(pObj1)  || Gia_ObjFaninC1(pObj0) != Gia_ObjFaninC0(pObj1)   ||
516                      Vec_IntEntry(vMap0, Gia_ObjFaninId0p(p, pObj0)) != Vec_IntEntry( vMap1, Gia_ObjFaninId1p(p, pObj1)) ||
517                      Vec_IntEntry(vMap0, Gia_ObjFaninId1p(p, pObj0)) != Vec_IntEntry( vMap1, Gia_ObjFaninId0p(p, pObj1)) )
518                      return 0;
519             }
520         }
521         else
522         {
523             if ( Gia_ObjFanin0(pObj1)->Value <= Gia_ObjFanin1(pObj1)->Value )
524             {
525                 if ( Gia_ObjFaninC1(pObj0) != Gia_ObjFaninC0(pObj1)  || Gia_ObjFaninC0(pObj0) != Gia_ObjFaninC1(pObj1)   ||
526                      Vec_IntEntry(vMap0, Gia_ObjFaninId1p(p, pObj0)) != Vec_IntEntry( vMap1, Gia_ObjFaninId0p(p, pObj1)) ||
527                      Vec_IntEntry(vMap0, Gia_ObjFaninId0p(p, pObj0)) != Vec_IntEntry( vMap1, Gia_ObjFaninId1p(p, pObj1)) )
528                      return 0;
529             }
530             else
531             {
532                 if ( Gia_ObjFaninC1(pObj0) != Gia_ObjFaninC1(pObj1)  || Gia_ObjFaninC0(pObj0) != Gia_ObjFaninC0(pObj1)   ||
533                      Vec_IntEntry(vMap0, Gia_ObjFaninId1p(p, pObj0)) != Vec_IntEntry( vMap1, Gia_ObjFaninId1p(p, pObj1)) ||
534                      Vec_IntEntry(vMap0, Gia_ObjFaninId0p(p, pObj0)) != Vec_IntEntry( vMap1, Gia_ObjFaninId0p(p, pObj1)) )
535                      return 0;
536             }
537         }
538     }
539     return 1;
540 }
541 
542 /**Function*************************************************************
543 
544   Synopsis    []
545 
546   Description []
547 
548   SideEffects []
549 
550   SeeAlso     []
551 
552 ***********************************************************************/
Gia_Iso2ManCheckIsoClassOneSkip(Gia_Man_t * p,Vec_Int_t * vClass,Vec_Int_t * vRoots,Vec_Int_t * vVec0,Vec_Int_t * vVec1,Vec_Int_t * vMap0,Vec_Int_t * vMap1)553 int Gia_Iso2ManCheckIsoClassOneSkip( Gia_Man_t * p, Vec_Int_t * vClass, Vec_Int_t * vRoots, Vec_Int_t * vVec0, Vec_Int_t * vVec1, Vec_Int_t * vMap0, Vec_Int_t * vMap1 )
554 {
555     int i, iPo;
556     assert( Vec_IntSize(vClass) > 1 );
557     iPo = Vec_IntEntry( vClass, 0 );
558     Gia_Iso2ManCollectOrder( p, &iPo, 1, vRoots, vVec0, vMap0 );
559     Vec_IntForEachEntryStart( vClass, iPo, i, 1 )
560     {
561         Gia_Iso2ManCollectOrder( p, &iPo, 1, vRoots, vVec1, vMap1 );
562         if ( Vec_IntSize(vVec0) != Vec_IntSize(vVec1) )
563             return 0;
564         if ( !Gia_Iso2ManCheckIsoPair( p, vVec0, vVec1, vMap0, vMap1 ) )
565             return 0;
566     }
567     return 1;
568 }
Gia_Iso2ManCheckIsoClassesSkip(Gia_Man_t * p,Vec_Wec_t * vEquivs)569 Vec_Wec_t * Gia_Iso2ManCheckIsoClassesSkip( Gia_Man_t * p, Vec_Wec_t * vEquivs )
570 {
571     Vec_Wec_t * vEquivs2;
572     Vec_Int_t * vRoots = Vec_IntAlloc( 10000 );
573     Vec_Int_t * vVec0 = Vec_IntAlloc( 10000 );
574     Vec_Int_t * vVec1 = Vec_IntAlloc( 10000 );
575     Vec_Int_t * vMap0 = Vec_IntStart( Gia_ManObjNum(p) );
576     Vec_Int_t * vMap1 = Vec_IntStart( Gia_ManObjNum(p) );
577     Vec_Int_t * vClass, * vClass2;
578     int i, k, Entry, Counter = 0;
579     vEquivs2 = Vec_WecAlloc( 2 * Vec_WecSize(vEquivs) );
580     Vec_WecForEachLevel( vEquivs, vClass, i )
581     {
582         if ( i % 50 == 0 )
583             printf( "Finished %8d outputs (out of %8d)...\r", Counter, Gia_ManPoNum(p) ), fflush(stdout);
584         Counter += Vec_IntSize(vClass);
585         if ( Vec_IntSize(vClass) < 2 || Gia_Iso2ManCheckIsoClassOneSkip(p, vClass, vRoots, vVec0, vVec1, vMap0, vMap1) )
586         {
587             vClass2 = Vec_WecPushLevel( vEquivs2 );
588             *vClass2 = *vClass;
589             vClass->pArray = NULL;
590             vClass->nSize = vClass->nCap = 0;
591         }
592         else
593         {
594             Vec_IntForEachEntry( vClass, Entry, k )
595             {
596                 vClass2 = Vec_WecPushLevel( vEquivs2 );
597                 Vec_IntPush( vClass2, Entry );
598             }
599         }
600     }
601     Vec_IntFree( vRoots );
602     Vec_IntFree( vVec0 );
603     Vec_IntFree( vVec1 );
604     Vec_IntFree( vMap0 );
605     Vec_IntFree( vMap1 );
606     return vEquivs2;
607 }
608 
Gia_Iso2ManCheckIsoClassOne(Gia_Man_t * p,Vec_Int_t * vClass,Vec_Int_t * vRoots,Vec_Int_t * vVec0,Vec_Int_t * vVec1,Vec_Int_t * vMap0,Vec_Int_t * vMap1,Vec_Int_t * vNewClass)609 void Gia_Iso2ManCheckIsoClassOne( Gia_Man_t * p, Vec_Int_t * vClass, Vec_Int_t * vRoots, Vec_Int_t * vVec0, Vec_Int_t * vVec1, Vec_Int_t * vMap0, Vec_Int_t * vMap1, Vec_Int_t * vNewClass )
610 {
611     int i, k = 1, iPo;
612     Vec_IntClear( vNewClass );
613     if ( Vec_IntSize(vClass) <= 1 )
614         return;
615     assert( Vec_IntSize(vClass) > 1 );
616     iPo = Vec_IntEntry( vClass, 0 );
617     Gia_Iso2ManCollectOrder( p, &iPo, 1, vRoots, vVec0, vMap0 );
618     Vec_IntForEachEntryStart( vClass, iPo, i, 1 )
619     {
620         Gia_Iso2ManCollectOrder( p, &iPo, 1, vRoots, vVec1, vMap1 );
621         if ( Vec_IntSize(vVec0) == Vec_IntSize(vVec1) && Gia_Iso2ManCheckIsoPair(p, vVec0, vVec1, vMap0, vMap1) )
622             Vec_IntWriteEntry( vClass, k++, iPo );
623         else
624             Vec_IntPush( vNewClass, iPo );
625     }
626     Vec_IntShrink( vClass, k );
627 }
Gia_Iso2ManCheckIsoClasses(Gia_Man_t * p,Vec_Wec_t * vEquivs)628 Vec_Wec_t * Gia_Iso2ManCheckIsoClasses( Gia_Man_t * p, Vec_Wec_t * vEquivs )
629 {
630     Vec_Wec_t * vEquivs2;
631     Vec_Int_t * vRoots = Vec_IntAlloc( 10000 );
632     Vec_Int_t * vVec0 = Vec_IntAlloc( 10000 );
633     Vec_Int_t * vVec1 = Vec_IntAlloc( 10000 );
634     Vec_Int_t * vMap0 = Vec_IntStart( Gia_ManObjNum(p) );
635     Vec_Int_t * vMap1 = Vec_IntStart( Gia_ManObjNum(p) );
636     Vec_Int_t * vClass, * vClass2, * vNewClass;
637     int i, Counter = 0;
638     vNewClass = Vec_IntAlloc( 100 );
639     vEquivs2 = Vec_WecAlloc( 2 * Vec_WecSize(vEquivs) );
640     Vec_WecForEachLevel( vEquivs, vClass, i )
641     {
642         if ( i % 50 == 0 )
643             printf( "Finished %8d outputs (out of %8d)...\r", Counter, Gia_ManPoNum(p) ), fflush(stdout);
644         // split this class
645         Gia_Iso2ManCheckIsoClassOne( p, vClass, vRoots, vVec0, vVec1, vMap0, vMap1, vNewClass );
646         Counter += Vec_IntSize(vClass);
647         // add remaining class
648         vClass2 = Vec_WecPushLevel( vEquivs2 );
649         *vClass2 = *vClass;
650         vClass->pArray = NULL;
651         vClass->nSize = vClass->nCap = 0;
652         // add new class
653         if ( Vec_IntSize(vNewClass) == 0 )
654             continue;
655         vClass = Vec_WecPushLevel( vEquivs );
656         Vec_IntAppend( vClass, vNewClass );
657     }
658     Vec_IntFree( vNewClass );
659     Vec_IntFree( vRoots );
660     Vec_IntFree( vVec0 );
661     Vec_IntFree( vVec1 );
662     Vec_IntFree( vMap0 );
663     Vec_IntFree( vMap1 );
664     return vEquivs2;
665 }
666 
667 
668 
669 /**Function*************************************************************
670 
671   Synopsis    []
672 
673   Description []
674 
675   SideEffects []
676 
677   SeeAlso     []
678 
679 ***********************************************************************/
Gia_Iso2ManPerform(Gia_Man_t * pGia,int fVerbose)680 Vec_Wec_t * Gia_Iso2ManPerform( Gia_Man_t * pGia, int fVerbose )
681 {
682     Gia_Iso2Man_t * p;
683     abctime clk = Abc_Clock();
684     p = Gia_Iso2ManStart( pGia );
685     Gia_Iso2ManPrepare( pGia );
686     Gia_Iso2ManPropagate( pGia );
687     Gia_Iso2ManPrint( p, Abc_Clock() - clk, fVerbose );
688     while ( Gia_Iso2ManUniqify( p ) )
689     {
690         Gia_Iso2ManPrint( p, Abc_Clock() - clk, fVerbose );
691         Gia_Iso2ManPropagate( pGia );
692     }
693     Gia_Iso2ManPrint( p, Abc_Clock() - clk, fVerbose );
694 /*
695     Gia_Iso2ManUpdate( p, 20 );
696     while ( Gia_Iso2ManUniqify( p ) )
697     {
698         Gia_Iso2ManPrint( p, Abc_Clock() - clk, fVerbose );
699         Gia_Iso2ManPropagate( pGia );
700     }
701     Gia_Iso2ManPrint( p, Abc_Clock() - clk, fVerbose );
702 */
703     Gia_Iso2ManStop( p );
704     return Gia_Iso2ManDerivePoClasses( pGia );
705 }
706 
707 /**Function*************************************************************
708 
709   Synopsis    []
710 
711   Description []
712 
713   SideEffects []
714 
715   SeeAlso     []
716 
717 ***********************************************************************/
Gia_ManIsoReduce2(Gia_Man_t * pGia,Vec_Ptr_t ** pvPosEquivs,Vec_Ptr_t ** pvPiPerms,int fEstimate,int fBetterQual,int fDualOut,int fVerbose,int fVeryVerbose)718 Gia_Man_t * Gia_ManIsoReduce2( Gia_Man_t * pGia, Vec_Ptr_t ** pvPosEquivs, Vec_Ptr_t ** pvPiPerms, int fEstimate, int fBetterQual, int fDualOut, int fVerbose, int fVeryVerbose )
719 {
720     Gia_Man_t * pPart;
721     Vec_Wec_t * vEquivs, * vEquivs2;
722     Vec_Int_t * vRemains;
723     int nClasses, nUsedPos;
724     abctime clk = Abc_Clock();
725     vEquivs = Gia_Iso2ManPerform( pGia, fVeryVerbose );
726     // report class stats
727     nClasses = Vec_WecCountNonTrivial( vEquivs, &nUsedPos );
728     printf( "Reduced %d outputs to %d candidate   classes (%d outputs are in %d non-trivial classes).  ",
729         Gia_ManPoNum(pGia), Vec_WecSize(vEquivs), nUsedPos, nClasses );
730     Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
731     if ( fEstimate )
732     {
733         Vec_WecFree( vEquivs );
734         return Gia_ManDup(pGia);
735     }
736     // verify classes
737     if ( fBetterQual )
738         vEquivs2 = Gia_Iso2ManCheckIsoClasses( pGia, vEquivs );
739     else
740         vEquivs2 = Gia_Iso2ManCheckIsoClassesSkip( pGia, vEquivs );
741     Vec_WecFree( vEquivs );
742     vEquivs = vEquivs2;
743     // sort equiv classes by the first integer
744     Vec_WecSortByFirstInt( vEquivs, 0 );
745     // find the first outputs
746     vRemains = Vec_WecCollectFirsts( vEquivs );
747     // derive the final GIA
748     pPart = Gia_ManDupCones( pGia, Vec_IntArray(vRemains), Vec_IntSize(vRemains), 0 );
749     Vec_IntFree( vRemains );
750     // report class stats
751     nClasses = Vec_WecCountNonTrivial( vEquivs, &nUsedPos );
752     printf( "Reduced %d outputs to %d equivalence classes (%d outputs are in %d non-trivial classes).  ",
753         Gia_ManPoNum(pGia), Vec_WecSize(vEquivs), nUsedPos, nClasses );
754     Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
755     if ( fVerbose )
756     {
757         printf( "Nontrivial classes:\n" );
758         Vec_WecPrint( vEquivs, 1 );
759     }
760     if ( pvPiPerms )
761         *pvPiPerms = NULL;
762     if ( pvPosEquivs )
763         *pvPosEquivs = Vec_WecConvertToVecPtr( vEquivs );
764     Vec_WecFree( vEquivs );
765 //    Gia_ManStopP( &pPart );
766     return pPart;
767 }
768 
769 
770 ////////////////////////////////////////////////////////////////////////
771 ///                       END OF FILE                                ///
772 ////////////////////////////////////////////////////////////////////////
773 
774 
775 ABC_NAMESPACE_IMPL_END
776 
777