ABC: A System for Sequential Synthesis and Verification
 
Loading...
Searching...
No Matches
dchClass.c
Go to the documentation of this file.
1
20
21#include "dchInt.h"
22
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
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
62
63static inline Aig_Obj_t * Dch_ObjNext( Aig_Obj_t ** ppNexts, Aig_Obj_t * pObj ) { return ppNexts[pObj->Id]; }
64static 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
78
90static 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
112static 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
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
163void 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
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
207{
208 return p->nLits;
209}
210
222Aig_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
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
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
303void 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
336void 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
430}
431
443int 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
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
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
546void 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
570int 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
608
609
611
#define ABC_ALLOC(type, num)
Definition abc_global.h:264
#define ABC_CALLOC(type, num)
Definition abc_global.h:265
#define ABC_FREE(obj)
Definition abc_global.h:267
#define ABC_NAMESPACE_IMPL_START
#define ABC_NAMESPACE_IMPL_END
void Aig_ManReprStart(Aig_Man_t *p, int nIdMax)
DECLARATIONS ///.
Definition aigRepr.c:45
#define Aig_ManForEachObj(p, pObj, i)
Definition aig.h:403
int Aig_SupportSize(Aig_Man_t *p, Aig_Obj_t *pObj)
Definition aigDfs.c:772
struct Aig_Obj_t_ Aig_Obj_t
Definition aig.h:51
typedefABC_NAMESPACE_HEADER_START struct Aig_Man_t_ Aig_Man_t
INCLUDES ///.
Definition aig.h:50
Aig_Obj_t ** Dch_ClassesReadClass(Dch_Cla_t *p, Aig_Obj_t *pRepr, int *pnSize)
Definition dchClass.c:222
void Dch_ClassesPrepare(Dch_Cla_t *p, int fLatchCorr, int nMaxLevs)
Definition dchClass.c:336
void Dch_ClassesCollectConst1Group(Dch_Cla_t *p, Aig_Obj_t *pObj, int nNodes, Vec_Ptr_t *vRoots)
Definition dchClass.c:546
void Dch_ClassesStop(Dch_Cla_t *p)
Definition dchClass.c:185
#define Dch_ManForEachClass(p, ppClass, i)
Definition dchClass.c:67
void Dch_ClassesPrintOne(Dch_Cla_t *p, Aig_Obj_t *pRepr)
Definition dchClass.c:282
int Dch_ClassesRefineConst1Group(Dch_Cla_t *p, Vec_Ptr_t *vRoots, int fRecursive)
Definition dchClass.c:570
void Dch_ClassesCheck(Dch_Cla_t *p)
Definition dchClass.c:241
int Dch_ClassesRefine(Dch_Cla_t *p)
Definition dchClass.c:504
void Dch_ClassesPrint(Dch_Cla_t *p, int fVeryVerbose)
Definition dchClass.c:303
void Dch_ClassesCollectOneClass(Dch_Cla_t *p, Aig_Obj_t *pRepr, Vec_Ptr_t *vRoots)
Definition dchClass.c:525
#define Dch_ClassForEachNode(p, pRepr, pNode, i)
Definition dchClass.c:71
int Dch_ClassesRefineOneClass(Dch_Cla_t *p, Aig_Obj_t *pReprOld, int fRecursive)
Definition dchClass.c:443
int Dch_ClassesLitNum(Dch_Cla_t *p)
Definition dchClass.c:206
void 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 *))
Definition dchClass.c:163
Dch_Cla_t * Dch_ClassesStart(Aig_Man_t *pAig)
Definition dchClass.c:137
typedefABC_NAMESPACE_HEADER_START struct Dch_Cla_t_ Dch_Cla_t
INCLUDES ///.
Definition dchInt.h:47
Cube * p
Definition exorList.c:222
int Id
Definition aig.h:85
unsigned Level
Definition aig.h:82
Vec_Ptr_t * vClassOld
Definition dchClass.c:50
int(* pFuncNodeIsConst)(void *, Aig_Obj_t *)
Definition dchClass.c:55
Aig_Obj_t *** pId2Class
Definition dchClass.c:40
Aig_Obj_t ** pMemClassesFree
Definition dchClass.c:48
unsigned(* pFuncNodeHash)(void *, Aig_Obj_t *)
Definition dchClass.c:54
int nCands1
Definition dchClass.c:44
int * pClassSizes
Definition dchClass.c:41
Aig_Obj_t ** pMemClasses
Definition dchClass.c:47
Vec_Ptr_t * vClassNew
Definition dchClass.c:51
int nLits
Definition dchClass.c:45
Aig_Man_t * pAig
Definition dchClass.c:39
void * pManData
Definition dchClass.c:53
int(* pFuncNodesAreEqual)(void *, Aig_Obj_t *, Aig_Obj_t *)
Definition dchClass.c:56
int nClasses
Definition dchClass.c:43
#define assert(ex)
Definition util_old.h:213
char * memset()
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