1 /**CFile****************************************************************
2 
3   FileName    [dchClass.c]
4 
5   SystemName  [ABC: Logic synthesis and verification system.]
6 
7   PackageName [Choice computation for tech-mapping.]
8 
9   Synopsis    [Representation of candidate equivalence classes.]
10 
11   Author      [Alan Mishchenko]
12 
13   Affiliation [UC Berkeley]
14 
15   Date        [Ver. 1.0. Started - June 29, 2008.]
16 
17   Revision    [$Id: dchClass.c,v 1.00 2008/07/29 00:00:00 alanmi Exp $]
18 
19 ***********************************************************************/
20 
21 #include "dchInt.h"
22 
23 ABC_NAMESPACE_IMPL_START
24 
25 
26 /*
27     The candidate equivalence classes are stored as a vector of pointers
28     to the array of pointers to the nodes in each class.
29     The first node of the class is its representative node.
30     The representative has the smallest topological order among the class nodes.
31     The nodes inside each class are ordered according to their topological order.
32     The classes are ordered according to the topo order of their representatives.
33 */
34 
35 // internal representation of candidate equivalence classes
36 struct Dch_Cla_t_
37 {
38     // class information
39     Aig_Man_t *      pAig;             // original AIG manager
40     Aig_Obj_t ***    pId2Class;        // non-const classes by ID of repr node
41     int *            pClassSizes;      // sizes of each equivalence class
42     // statistics
43     int              nClasses;         // the total number of non-const classes
44     int              nCands1;          // the total number of const candidates
45     int              nLits;            // the number of literals in all classes
46     // memory
47     Aig_Obj_t **     pMemClasses;      // memory allocated for equivalence classes
48     Aig_Obj_t **     pMemClassesFree;  // memory allocated for equivalence classes to be used
49     // temporary data
50     Vec_Ptr_t *      vClassOld;        // old equivalence class after splitting
51     Vec_Ptr_t *      vClassNew;        // new equivalence class(es) after splitting
52     // procedures used for class refinement
53     void *           pManData;
54     unsigned (*pFuncNodeHash) (void *,Aig_Obj_t *);              // returns hash key of the node
55     int (*pFuncNodeIsConst)   (void *,Aig_Obj_t *);              // returns 1 if the node is a constant
56     int (*pFuncNodesAreEqual) (void *,Aig_Obj_t *, Aig_Obj_t *); // returns 1 if nodes are equal up to a complement
57 };
58 
59 ////////////////////////////////////////////////////////////////////////
60 ///                        DECLARATIONS                              ///
61 ////////////////////////////////////////////////////////////////////////
62 
Dch_ObjNext(Aig_Obj_t ** ppNexts,Aig_Obj_t * pObj)63 static inline Aig_Obj_t *  Dch_ObjNext( Aig_Obj_t ** ppNexts, Aig_Obj_t * pObj )                       { return ppNexts[pObj->Id];  }
Dch_ObjSetNext(Aig_Obj_t ** ppNexts,Aig_Obj_t * pObj,Aig_Obj_t * pNext)64 static inline void         Dch_ObjSetNext( Aig_Obj_t ** ppNexts, Aig_Obj_t * pObj, Aig_Obj_t * pNext ) { ppNexts[pObj->Id] = pNext; }
65 
66 // iterator through the equivalence classes
67 #define Dch_ManForEachClass( p, ppClass, i )                 \
68     for ( i = 0; i < Aig_ManObjNumMax(p->pAig); i++ )        \
69         if ( ((ppClass) = p->pId2Class[i]) == NULL ) {} else
70 // iterator through the nodes in one class
71 #define Dch_ClassForEachNode( p, pRepr, pNode, i )           \
72     for ( i = 0; i < p->pClassSizes[pRepr->Id]; i++ )        \
73         if ( ((pNode) = p->pId2Class[pRepr->Id][i]) == NULL ) {} else
74 
75 ////////////////////////////////////////////////////////////////////////
76 ///                     FUNCTION DEFINITIONS                         ///
77 ////////////////////////////////////////////////////////////////////////
78 
79 /**Function*************************************************************
80 
81   Synopsis    [Creates one equivalence class.]
82 
83   Description []
84 
85   SideEffects []
86 
87   SeeAlso     []
88 
89 ***********************************************************************/
Dch_ObjAddClass(Dch_Cla_t * p,Aig_Obj_t * pRepr,Aig_Obj_t ** pClass,int nSize)90 static inline void Dch_ObjAddClass( Dch_Cla_t * p, Aig_Obj_t * pRepr, Aig_Obj_t ** pClass, int nSize )
91 {
92     assert( p->pId2Class[pRepr->Id] == NULL );
93     p->pId2Class[pRepr->Id] = pClass;
94     assert( p->pClassSizes[pRepr->Id] == 0 );
95     assert( nSize > 1 );
96     p->pClassSizes[pRepr->Id] = nSize;
97     p->nClasses++;
98     p->nLits += nSize - 1;
99 }
100 
101 /**Function*************************************************************
102 
103   Synopsis    [Removes one equivalence class.]
104 
105   Description []
106 
107   SideEffects []
108 
109   SeeAlso     []
110 
111 ***********************************************************************/
Dch_ObjRemoveClass(Dch_Cla_t * p,Aig_Obj_t * pRepr)112 static inline Aig_Obj_t ** Dch_ObjRemoveClass( Dch_Cla_t * p, Aig_Obj_t * pRepr )
113 {
114     Aig_Obj_t ** pClass = p->pId2Class[pRepr->Id];
115     int nSize;
116     assert( pClass != NULL );
117     p->pId2Class[pRepr->Id] = NULL;
118     nSize = p->pClassSizes[pRepr->Id];
119     assert( nSize > 1 );
120     p->nClasses--;
121     p->nLits -= nSize - 1;
122     p->pClassSizes[pRepr->Id] = 0;
123     return pClass;
124 }
125 
126 /**Function*************************************************************
127 
128   Synopsis    [Starts representation of equivalence classes.]
129 
130   Description []
131 
132   SideEffects []
133 
134   SeeAlso     []
135 
136 ***********************************************************************/
Dch_ClassesStart(Aig_Man_t * pAig)137 Dch_Cla_t * Dch_ClassesStart( Aig_Man_t * pAig )
138 {
139     Dch_Cla_t * p;
140     p = ABC_ALLOC( Dch_Cla_t, 1 );
141     memset( p, 0, sizeof(Dch_Cla_t) );
142     p->pAig         = pAig;
143     p->pId2Class    = ABC_CALLOC( Aig_Obj_t **, Aig_ManObjNumMax(pAig) );
144     p->pClassSizes  = ABC_CALLOC( int, Aig_ManObjNumMax(pAig) );
145     p->vClassOld    = Vec_PtrAlloc( 100 );
146     p->vClassNew    = Vec_PtrAlloc( 100 );
147     assert( pAig->pReprs == NULL );
148     Aig_ManReprStart( pAig, Aig_ManObjNumMax(pAig) );
149     return p;
150 }
151 
152 /**Function*************************************************************
153 
154   Synopsis    [Starts representation of equivalence classes.]
155 
156   Description []
157 
158   SideEffects []
159 
160   SeeAlso     []
161 
162 ***********************************************************************/
Dch_ClassesSetData(Dch_Cla_t * p,void * pManData,unsigned (* pFuncNodeHash)(void *,Aig_Obj_t *),int (* pFuncNodeIsConst)(void *,Aig_Obj_t *),int (* pFuncNodesAreEqual)(void *,Aig_Obj_t *,Aig_Obj_t *))163 void Dch_ClassesSetData( Dch_Cla_t * p, void * pManData,
164     unsigned (*pFuncNodeHash)(void *,Aig_Obj_t *),               // returns hash key of the node
165     int (*pFuncNodeIsConst)(void *,Aig_Obj_t *),                 // returns 1 if the node is a constant
166     int (*pFuncNodesAreEqual)(void *,Aig_Obj_t *, Aig_Obj_t *) ) // returns 1 if nodes are equal up to a complement
167 {
168     p->pManData           = pManData;
169     p->pFuncNodeHash      = pFuncNodeHash;
170     p->pFuncNodeIsConst   = pFuncNodeIsConst;
171     p->pFuncNodesAreEqual = pFuncNodesAreEqual;
172 }
173 
174 /**Function*************************************************************
175 
176   Synopsis    [Stop representation of equivalence classes.]
177 
178   Description []
179 
180   SideEffects []
181 
182   SeeAlso     []
183 
184 ***********************************************************************/
Dch_ClassesStop(Dch_Cla_t * p)185 void Dch_ClassesStop( Dch_Cla_t * p )
186 {
187     if ( p->vClassNew )    Vec_PtrFree( p->vClassNew );
188     if ( p->vClassOld )    Vec_PtrFree( p->vClassOld );
189     ABC_FREE( p->pId2Class );
190     ABC_FREE( p->pClassSizes );
191     ABC_FREE( p->pMemClasses );
192     ABC_FREE( p );
193 }
194 
195 /**Function*************************************************************
196 
197   Synopsis    [Stop representation of equivalence classes.]
198 
199   Description []
200 
201   SideEffects []
202 
203   SeeAlso     []
204 
205 ***********************************************************************/
Dch_ClassesLitNum(Dch_Cla_t * p)206 int Dch_ClassesLitNum( Dch_Cla_t * p )
207 {
208     return p->nLits;
209 }
210 
211 /**Function*************************************************************
212 
213   Synopsis    [Stop representation of equivalence classes.]
214 
215   Description []
216 
217   SideEffects []
218 
219   SeeAlso     []
220 
221 ***********************************************************************/
Dch_ClassesReadClass(Dch_Cla_t * p,Aig_Obj_t * pRepr,int * pnSize)222 Aig_Obj_t ** Dch_ClassesReadClass( Dch_Cla_t * p, Aig_Obj_t * pRepr, int * pnSize )
223 {
224     assert( p->pId2Class[pRepr->Id] != NULL );
225     assert( p->pClassSizes[pRepr->Id] > 1 );
226     *pnSize = p->pClassSizes[pRepr->Id];
227     return p->pId2Class[pRepr->Id];
228 }
229 
230 /**Function*************************************************************
231 
232   Synopsis    [Checks candidate equivalence classes.]
233 
234   Description []
235 
236   SideEffects []
237 
238   SeeAlso     []
239 
240 ***********************************************************************/
Dch_ClassesCheck(Dch_Cla_t * p)241 void Dch_ClassesCheck( Dch_Cla_t * p )
242 {
243     Aig_Obj_t * pObj, * pPrev, ** ppClass;
244     int i, k, nLits, nClasses, nCands1;
245     nClasses = nLits = 0;
246     Dch_ManForEachClass( p, ppClass, k )
247     {
248         pPrev = NULL;
249         Dch_ClassForEachNode( p, ppClass[0], pObj, i )
250         {
251             if ( i == 0 )
252                 assert( Aig_ObjRepr(p->pAig, pObj) == NULL );
253             else
254             {
255                 assert( Aig_ObjRepr(p->pAig, pObj) == ppClass[0] );
256                 assert( pPrev->Id < pObj->Id );
257                 nLits++;
258             }
259             pPrev = pObj;
260         }
261         nClasses++;
262     }
263     nCands1 = 0;
264     Aig_ManForEachObj( p->pAig, pObj, i )
265         nCands1 += Dch_ObjIsConst1Cand( p->pAig, pObj );
266     assert( p->nLits == nLits );
267     assert( p->nCands1 == nCands1 );
268     assert( p->nClasses == nClasses );
269 }
270 
271 /**Function*************************************************************
272 
273   Synopsis    [Prints simulation classes.]
274 
275   Description []
276 
277   SideEffects []
278 
279   SeeAlso     []
280 
281 ***********************************************************************/
Dch_ClassesPrintOne(Dch_Cla_t * p,Aig_Obj_t * pRepr)282 void Dch_ClassesPrintOne( Dch_Cla_t * p, Aig_Obj_t * pRepr )
283 {
284     Aig_Obj_t * pObj;
285     int i;
286     Abc_Print( 1, "{ " );
287     Dch_ClassForEachNode( p, pRepr, pObj, i )
288         Abc_Print( 1, "%d(%d,%d) ", pObj->Id, pObj->Level, Aig_SupportSize(p->pAig,pObj) );
289     Abc_Print( 1, "}\n" );
290 }
291 
292 /**Function*************************************************************
293 
294   Synopsis    [Prints simulation classes.]
295 
296   Description []
297 
298   SideEffects []
299 
300   SeeAlso     []
301 
302 ***********************************************************************/
Dch_ClassesPrint(Dch_Cla_t * p,int fVeryVerbose)303 void Dch_ClassesPrint( Dch_Cla_t * p, int fVeryVerbose )
304 {
305     Aig_Obj_t ** ppClass;
306     Aig_Obj_t * pObj;
307     int i;
308     Abc_Print( 1, "Equivalence classes: Const1 = %5d. Class = %5d. Lit = %5d.\n",
309         p->nCands1, p->nClasses, p->nLits );
310     if ( !fVeryVerbose )
311         return;
312     Abc_Print( 1, "Constants { " );
313     Aig_ManForEachObj( p->pAig, pObj, i )
314         if ( Dch_ObjIsConst1Cand( p->pAig, pObj ) )
315             Abc_Print( 1, "%d(%d,%d) ", pObj->Id, pObj->Level, Aig_SupportSize(p->pAig,pObj) );
316     Abc_Print( 1, "}\n" );
317     Dch_ManForEachClass( p, ppClass, i )
318     {
319         Abc_Print( 1, "%3d (%3d) : ", i, p->pClassSizes[i] );
320         Dch_ClassesPrintOne( p, ppClass[0] );
321     }
322     Abc_Print( 1, "\n" );
323 }
324 
325 /**Function*************************************************************
326 
327   Synopsis    [Creates initial simulation classes.]
328 
329   Description [Assumes that simulation info is assigned.]
330 
331   SideEffects []
332 
333   SeeAlso     []
334 
335 ***********************************************************************/
Dch_ClassesPrepare(Dch_Cla_t * p,int fLatchCorr,int nMaxLevs)336 void Dch_ClassesPrepare( Dch_Cla_t * p, int fLatchCorr, int nMaxLevs )
337 {
338     Aig_Obj_t ** ppTable, ** ppNexts, ** ppClassNew;
339     Aig_Obj_t * pObj, * pTemp, * pRepr;
340     int i, k, nTableSize, nNodes, iEntry, nEntries, nEntries2;
341 
342     // allocate the hash table hashing simulation info into nodes
343     nTableSize = Abc_PrimeCudd( Aig_ManObjNumMax(p->pAig)/4 );
344     ppTable = ABC_CALLOC( Aig_Obj_t *, nTableSize );
345     ppNexts = ABC_CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(p->pAig) );
346 
347     // add all the nodes to the hash table
348     nEntries = 0;
349     Aig_ManForEachObj( p->pAig, pObj, i )
350     {
351         if ( fLatchCorr )
352         {
353             if ( !Aig_ObjIsCi(pObj) )
354                 continue;
355         }
356         else
357         {
358             if ( !Aig_ObjIsNode(pObj) && !Aig_ObjIsCi(pObj) )
359                 continue;
360             // skip the node with more that the given number of levels
361             if ( nMaxLevs && (int)pObj->Level >= nMaxLevs )
362                 continue;
363         }
364         // check if the node belongs to the class of constant 1
365         if ( p->pFuncNodeIsConst( p->pManData, pObj ) )
366         {
367             Dch_ObjSetConst1Cand( p->pAig, pObj );
368             p->nCands1++;
369             continue;
370         }
371         // hash the node by its simulation info
372         iEntry = p->pFuncNodeHash( p->pManData, pObj ) % nTableSize;
373         // add the node to the class
374         if ( ppTable[iEntry] == NULL )
375             ppTable[iEntry] = pObj;
376         else
377         {
378             // set the representative of this node
379             pRepr = ppTable[iEntry];
380             Aig_ObjSetRepr( p->pAig, pObj, pRepr );
381             // add node to the table
382             if ( Dch_ObjNext( ppNexts, pRepr ) == NULL )
383             { // this will be the second entry
384                 p->pClassSizes[pRepr->Id]++;
385                 nEntries++;
386             }
387             // add the entry to the list
388             Dch_ObjSetNext( ppNexts, pObj, Dch_ObjNext( ppNexts, pRepr ) );
389             Dch_ObjSetNext( ppNexts, pRepr, pObj );
390             p->pClassSizes[pRepr->Id]++;
391             nEntries++;
392         }
393     }
394 
395     // allocate room for classes
396     p->pMemClasses = ABC_ALLOC( Aig_Obj_t *, nEntries + p->nCands1 );
397     p->pMemClassesFree = p->pMemClasses + nEntries;
398 
399     // copy the entries into storage in the topological order
400     nEntries2 = 0;
401     Aig_ManForEachObj( p->pAig, pObj, i )
402     {
403         if ( !Aig_ObjIsNode(pObj) && !Aig_ObjIsCi(pObj) )
404             continue;
405         nNodes = p->pClassSizes[pObj->Id];
406         // skip the nodes that are not representatives of non-trivial classes
407         if ( nNodes == 0 )
408             continue;
409         assert( nNodes > 1 );
410         // add the nodes to the class in the topological order
411         ppClassNew = p->pMemClasses + nEntries2;
412         ppClassNew[0] = pObj;
413         for ( pTemp = Dch_ObjNext(ppNexts, pObj), k = 1; pTemp;
414               pTemp = Dch_ObjNext(ppNexts, pTemp), k++ )
415         {
416             ppClassNew[nNodes-k] = pTemp;
417         }
418         // add the class of nodes
419         p->pClassSizes[pObj->Id] = 0;
420         Dch_ObjAddClass( p, pObj, ppClassNew, nNodes );
421         // increment the number of entries
422         nEntries2 += nNodes;
423     }
424     assert( nEntries == nEntries2 );
425     ABC_FREE( ppTable );
426     ABC_FREE( ppNexts );
427     // now it is time to refine the classes
428     Dch_ClassesRefine( p );
429     Dch_ClassesCheck( p );
430 }
431 
432 /**Function*************************************************************
433 
434   Synopsis    [Iteratively refines the classes after simulation.]
435 
436   Description [Returns the number of refinements performed.]
437 
438   SideEffects []
439 
440   SeeAlso     []
441 
442 ***********************************************************************/
Dch_ClassesRefineOneClass(Dch_Cla_t * p,Aig_Obj_t * pReprOld,int fRecursive)443 int Dch_ClassesRefineOneClass( Dch_Cla_t * p, Aig_Obj_t * pReprOld, int fRecursive )
444 {
445     Aig_Obj_t ** pClassOld, ** pClassNew;
446     Aig_Obj_t * pObj, * pReprNew;
447     int i;
448 
449     // split the class
450     Vec_PtrClear( p->vClassOld );
451     Vec_PtrClear( p->vClassNew );
452     Dch_ClassForEachNode( p, pReprOld, pObj, i )
453         if ( p->pFuncNodesAreEqual(p->pManData, pReprOld, pObj) )
454             Vec_PtrPush( p->vClassOld, pObj );
455         else
456             Vec_PtrPush( p->vClassNew, pObj );
457     // check if splitting happened
458     if ( Vec_PtrSize(p->vClassNew) == 0 )
459         return 0;
460 
461     // get the new representative
462     pReprNew = (Aig_Obj_t *)Vec_PtrEntry( p->vClassNew, 0 );
463     assert( Vec_PtrSize(p->vClassOld) > 0 );
464     assert( Vec_PtrSize(p->vClassNew) > 0 );
465 
466     // create old class
467     pClassOld = Dch_ObjRemoveClass( p, pReprOld );
468     Vec_PtrForEachEntry( Aig_Obj_t *, p->vClassOld, pObj, i )
469     {
470         pClassOld[i] = pObj;
471         Aig_ObjSetRepr( p->pAig, pObj, i? pReprOld : NULL );
472     }
473     // create new class
474     pClassNew = pClassOld + i;
475     Vec_PtrForEachEntry( Aig_Obj_t *, p->vClassNew, pObj, i )
476     {
477         pClassNew[i] = pObj;
478         Aig_ObjSetRepr( p->pAig, pObj, i? pReprNew : NULL );
479     }
480 
481     // put classes back
482     if ( Vec_PtrSize(p->vClassOld) > 1 )
483         Dch_ObjAddClass( p, pReprOld, pClassOld, Vec_PtrSize(p->vClassOld) );
484     if ( Vec_PtrSize(p->vClassNew) > 1 )
485         Dch_ObjAddClass( p, pReprNew, pClassNew, Vec_PtrSize(p->vClassNew) );
486 
487     // check if the class should be recursively refined
488     if ( fRecursive && Vec_PtrSize(p->vClassNew) > 1 )
489         return 1 + Dch_ClassesRefineOneClass( p, pReprNew, 1 );
490     return 1;
491 }
492 
493 /**Function*************************************************************
494 
495   Synopsis    [Refines the classes after simulation.]
496 
497   Description []
498 
499   SideEffects []
500 
501   SeeAlso     []
502 
503 ***********************************************************************/
Dch_ClassesRefine(Dch_Cla_t * p)504 int Dch_ClassesRefine( Dch_Cla_t * p )
505 {
506     Aig_Obj_t ** ppClass;
507     int i, nRefis = 0;
508     Dch_ManForEachClass( p, ppClass, i )
509         nRefis += Dch_ClassesRefineOneClass( p, ppClass[0], 0 );
510     return nRefis;
511 }
512 
513 
514 /**Function*************************************************************
515 
516   Synopsis    [Returns equivalence class of the given node.]
517 
518   Description []
519 
520   SideEffects []
521 
522   SeeAlso     []
523 
524 ***********************************************************************/
Dch_ClassesCollectOneClass(Dch_Cla_t * p,Aig_Obj_t * pRepr,Vec_Ptr_t * vRoots)525 void Dch_ClassesCollectOneClass( Dch_Cla_t * p, Aig_Obj_t * pRepr, Vec_Ptr_t * vRoots )
526 {
527     Aig_Obj_t * pObj;
528     int i;
529     Vec_PtrClear( vRoots );
530     Dch_ClassForEachNode( p, pRepr, pObj, i )
531         Vec_PtrPush( vRoots, pObj );
532     assert( Vec_PtrSize(vRoots) > 1 );
533 }
534 
535 /**Function*************************************************************
536 
537   Synopsis    [Returns equivalence class of the given node.]
538 
539   Description []
540 
541   SideEffects []
542 
543   SeeAlso     []
544 
545 ***********************************************************************/
Dch_ClassesCollectConst1Group(Dch_Cla_t * p,Aig_Obj_t * pObj,int nNodes,Vec_Ptr_t * vRoots)546 void Dch_ClassesCollectConst1Group( Dch_Cla_t * p, Aig_Obj_t * pObj, int nNodes, Vec_Ptr_t * vRoots )
547 {
548     int i, Limit;
549     Vec_PtrClear( vRoots );
550     Limit = Abc_MinInt( pObj->Id + nNodes, Aig_ManObjNumMax(p->pAig) );
551     for ( i = pObj->Id; i < Limit; i++ )
552     {
553         pObj = Aig_ManObj( p->pAig, i );
554         if ( pObj && Dch_ObjIsConst1Cand( p->pAig, pObj ) )
555             Vec_PtrPush( vRoots, pObj );
556     }
557 }
558 
559 /**Function*************************************************************
560 
561   Synopsis    [Refine the group of constant 1 nodes.]
562 
563   Description []
564 
565   SideEffects []
566 
567   SeeAlso     []
568 
569 ***********************************************************************/
Dch_ClassesRefineConst1Group(Dch_Cla_t * p,Vec_Ptr_t * vRoots,int fRecursive)570 int Dch_ClassesRefineConst1Group( Dch_Cla_t * p, Vec_Ptr_t * vRoots, int fRecursive )
571 {
572     Aig_Obj_t * pObj, * pReprNew, ** ppClassNew;
573     int i;
574     if ( Vec_PtrSize(vRoots) == 0 )
575         return 0;
576     // collect the nodes to be refined
577     Vec_PtrClear( p->vClassNew );
578     Vec_PtrForEachEntry( Aig_Obj_t *, vRoots, pObj, i )
579         if ( !p->pFuncNodeIsConst( p->pManData, pObj ) )
580             Vec_PtrPush( p->vClassNew, pObj );
581     // check if there is a new class
582     if ( Vec_PtrSize(p->vClassNew) == 0 )
583         return 0;
584     p->nCands1 -= Vec_PtrSize(p->vClassNew);
585     pReprNew = (Aig_Obj_t *)Vec_PtrEntry( p->vClassNew, 0 );
586     Aig_ObjSetRepr( p->pAig, pReprNew, NULL );
587     if ( Vec_PtrSize(p->vClassNew) == 1 )
588         return 1;
589     // create a new class composed of these nodes
590     ppClassNew = p->pMemClassesFree;
591     p->pMemClassesFree += Vec_PtrSize(p->vClassNew);
592     Vec_PtrForEachEntry( Aig_Obj_t *, p->vClassNew, pObj, i )
593     {
594         ppClassNew[i] = pObj;
595         Aig_ObjSetRepr( p->pAig, pObj, i? pReprNew : NULL );
596     }
597     Dch_ObjAddClass( p, pReprNew, ppClassNew, Vec_PtrSize(p->vClassNew) );
598     // refine them recursively
599     if ( fRecursive )
600         return 1 + Dch_ClassesRefineOneClass( p, pReprNew, 1 );
601     return 1;
602 }
603 
604 
605 ////////////////////////////////////////////////////////////////////////
606 ///                       END OF FILE                                ///
607 ////////////////////////////////////////////////////////////////////////
608 
609 
610 ABC_NAMESPACE_IMPL_END
611 
612