1 /**CFile****************************************************************
2 
3   FileName    [aigPartReg.c]
4 
5   SystemName  [ABC: Logic synthesis and verification system.]
6 
7   PackageName [AIG package.]
8 
9   Synopsis    [Register partitioning algorithm.]
10 
11   Author      [Alan Mishchenko]
12 
13   Affiliation [UC Berkeley]
14 
15   Date        [Ver. 1.0. Started - April 28, 2007.]
16 
17   Revision    [$Id: aigPartReg.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
18 
19 ***********************************************************************/
20 
21 #include "aig.h"
22 //#include "fra.h"
23 
24 ABC_NAMESPACE_IMPL_START
25 
26 
27 ////////////////////////////////////////////////////////////////////////
28 ///                        DECLARATIONS                              ///
29 ////////////////////////////////////////////////////////////////////////
30 
31 typedef struct Aig_ManPre_t_         Aig_ManPre_t;
32 
33 struct Aig_ManPre_t_
34 {
35     // input data
36     Aig_Man_t *     pAig;            // seq AIG manager
37     Vec_Ptr_t *     vMatrix;         // register dependency
38     int             nRegsMax;        // the max number of registers in the cluster
39     // information about partitions
40     Vec_Ptr_t *     vParts;          // the partitions
41     char *          pfUsedRegs;      // the registers already included in the partitions
42     // info about the current partition
43     Vec_Int_t *     vRegs;           // registers of this partition
44     Vec_Int_t *     vUniques;        // unique registers of this partition
45     Vec_Int_t *     vFreeVars;       // free variables of this partition
46     Vec_Flt_t *     vPartCost;       // costs of adding each variable
47     char *          pfPartVars;      // input/output registers of the partition
48 };
49 
50 
51 ////////////////////////////////////////////////////////////////////////
52 ///                     FUNCTION DEFINITIONS                         ///
53 ////////////////////////////////////////////////////////////////////////
54 
55 /**Function*************************************************************
56 
57   Synopsis    [Computes partitioning of registers.]
58 
59   Description []
60 
61   SideEffects []
62 
63   SeeAlso     []
64 
65 ***********************************************************************/
Aig_ManRegManStart(Aig_Man_t * pAig,int nPartSize)66 Aig_ManPre_t * Aig_ManRegManStart( Aig_Man_t * pAig, int nPartSize )
67 {
68     Aig_ManPre_t * p;
69     p = ABC_ALLOC( Aig_ManPre_t, 1 );
70     memset( p, 0, sizeof(Aig_ManPre_t) );
71     p->pAig      = pAig;
72     p->vMatrix   = Aig_ManSupportsRegisters( pAig );
73     p->nRegsMax  = nPartSize;
74     p->vParts    = Vec_PtrAlloc(256);
75     p->vRegs     = Vec_IntAlloc(256);
76     p->vUniques  = Vec_IntAlloc(256);
77     p->vFreeVars = Vec_IntAlloc(256);
78     p->vPartCost = Vec_FltAlloc(256);
79     p->pfUsedRegs = ABC_ALLOC( char, Aig_ManRegNum(p->pAig) );
80     memset( p->pfUsedRegs, 0, sizeof(char) * Aig_ManRegNum(p->pAig) );
81     p->pfPartVars  = ABC_ALLOC( char, Aig_ManRegNum(p->pAig) );
82     return p;
83 }
84 
85 /**Function*************************************************************
86 
87   Synopsis    [Computes partitioning of registers.]
88 
89   Description []
90 
91   SideEffects []
92 
93   SeeAlso     []
94 
95 ***********************************************************************/
Aig_ManRegManStop(Aig_ManPre_t * p)96 void Aig_ManRegManStop( Aig_ManPre_t * p )
97 {
98     Vec_VecFree( (Vec_Vec_t *)p->vMatrix );
99     if ( p->vParts )
100         Vec_VecFree( (Vec_Vec_t *)p->vParts );
101     Vec_IntFree( p->vRegs );
102     Vec_IntFree( p->vUniques );
103     Vec_IntFree( p->vFreeVars );
104     Vec_FltFree( p->vPartCost );
105     ABC_FREE( p->pfUsedRegs );
106     ABC_FREE( p->pfPartVars );
107     ABC_FREE( p );
108 }
109 
110 /**Function*************************************************************
111 
112   Synopsis    [Determines what register to use as the seed.]
113 
114   Description [The register is selected as the one having the largest
115   number of non-taken registers in its support.]
116 
117   SideEffects []
118 
119   SeeAlso     []
120 
121 ***********************************************************************/
Aig_ManRegFindSeed(Aig_ManPre_t * p)122 int Aig_ManRegFindSeed( Aig_ManPre_t * p )
123 {
124     Vec_Int_t * vRegs;
125     int i, k, iReg;
126     int iMax = -1; // Suppress "might be used uninitialized"
127     int nRegsCur, nRegsMax = -1;
128     for ( i = 0; i < Aig_ManRegNum(p->pAig); i++ )
129     {
130         if ( p->pfUsedRegs[i] )
131             continue;
132         nRegsCur = 0;
133         vRegs = (Vec_Int_t *)Vec_PtrEntry( p->vMatrix, i );
134         Vec_IntForEachEntry( vRegs, iReg, k )
135             nRegsCur += !p->pfUsedRegs[iReg];
136         if ( nRegsMax < nRegsCur )
137         {
138             nRegsMax = nRegsCur;
139             iMax = i;
140         }
141     }
142     return iMax;
143 }
144 
145 /**Function*************************************************************
146 
147   Synopsis    [Computes the next register to be added to the set.]
148 
149   Description []
150 
151   SideEffects []
152 
153   SeeAlso     []
154 
155 ***********************************************************************/
Aig_ManRegFindBestVar(Aig_ManPre_t * p)156 int Aig_ManRegFindBestVar( Aig_ManPre_t * p )
157 {
158     Vec_Int_t * vSupp;
159     int nNewVars, nNewVarsBest = ABC_INFINITY;
160     int iVarFree, iVarSupp, iVarBest = -1, i, k;
161     // go through the free variables
162     Vec_IntForEachEntry( p->vFreeVars, iVarFree, i )
163     {
164 //        if ( p->pfUsedRegs[iVarFree] )
165 //            continue;
166         // get support of this variable
167         vSupp = (Vec_Int_t *)Vec_PtrEntry( p->vMatrix, iVarFree );
168         // count the number of new vars
169         nNewVars = 0;
170         Vec_IntForEachEntry( vSupp, iVarSupp, k )
171         {
172             if ( p->pfPartVars[iVarSupp] )
173                 continue;
174             nNewVars += 1 + 3 * p->pfUsedRegs[iVarSupp];
175         }
176         // quit if there is no new variables
177         if ( nNewVars == 0 )
178             return iVarFree;
179         // compare the cost of this
180         if ( nNewVarsBest > nNewVars )
181         {
182             nNewVarsBest = nNewVars;
183             iVarBest = iVarFree;
184         }
185     }
186     return iVarBest;
187 }
188 
189 /**Function*************************************************************
190 
191   Synopsis    [Computes partitioning of registers.]
192 
193   Description []
194 
195   SideEffects []
196 
197   SeeAlso     []
198 
199 ***********************************************************************/
Aig_ManRegPartitionAdd(Aig_ManPre_t * p,int iReg)200 void Aig_ManRegPartitionAdd( Aig_ManPre_t * p, int iReg )
201 {
202     Vec_Int_t * vSupp;
203     int RetValue, iVar, i;
204     // make sure this is a new variable
205 //    assert( !p->pfUsedRegs[iReg] );
206     if ( !p->pfUsedRegs[iReg] )
207     {
208         p->pfUsedRegs[iReg] = 1;
209         Vec_IntPush( p->vUniques, iReg );
210     }
211     // remove it from the free variables
212     if ( Vec_IntSize(p->vFreeVars) > 0 )
213     {
214         assert( p->pfPartVars[iReg] );
215         RetValue = Vec_IntRemove( p->vFreeVars, iReg );
216         assert( RetValue );
217     }
218     else
219         assert( !p->pfPartVars[iReg] );
220     // add it to the partition
221     p->pfPartVars[iReg] = 1;
222     Vec_IntPush( p->vRegs, iReg );
223     // add new variables
224     vSupp = (Vec_Int_t *)Vec_PtrEntry( p->vMatrix, iReg );
225     Vec_IntForEachEntry( vSupp, iVar, i )
226     {
227         if ( p->pfPartVars[iVar] )
228             continue;
229         p->pfPartVars[iVar] = 1;
230         Vec_IntPush( p->vFreeVars, iVar );
231     }
232     // add it to the cost
233     Vec_FltPush( p->vPartCost, 1.0*Vec_IntSize(p->vFreeVars)/Vec_IntSize(p->vRegs) );
234 }
235 
236 /**Function*************************************************************
237 
238   Synopsis    [Creates projection of 1-hot registers onto the given partition.]
239 
240   Description [Assumes that the relevant register outputs are labeled with
241   the current traversal ID.]
242 
243   SideEffects []
244 
245   SeeAlso     []
246 
247 ***********************************************************************/
Aig_ManRegProjectOnehots(Aig_Man_t * pAig,Aig_Man_t * pPart,Vec_Ptr_t * vOnehots,int fVerbose)248 Vec_Ptr_t * Aig_ManRegProjectOnehots( Aig_Man_t * pAig, Aig_Man_t * pPart, Vec_Ptr_t * vOnehots, int fVerbose )
249 {
250     Vec_Ptr_t * vOnehotsPart = NULL;
251     Vec_Int_t * vGroup, * vGroupNew;
252     Aig_Obj_t * pObj, * pObjNew;
253     int nOffset, iReg, i, k;
254     // set the PI numbers
255     Aig_ManForEachCi( pPart, pObj, i )
256         pObj->iData = i;
257     // go through each group and check if registers are involved in this one
258     nOffset = Aig_ManCiNum(pAig)-Aig_ManRegNum(pAig);
259     Vec_PtrForEachEntry( Vec_Int_t *, vOnehots, vGroup, i )
260     {
261         vGroupNew = NULL;
262         Vec_IntForEachEntry( vGroup, iReg, k )
263         {
264             pObj = Aig_ManCi( pAig, nOffset+iReg );
265             if ( !Aig_ObjIsTravIdCurrent(pAig, pObj) )
266                 continue;
267             if ( vGroupNew == NULL )
268                 vGroupNew = Vec_IntAlloc( Vec_IntSize(vGroup) );
269             pObjNew = (Aig_Obj_t *)pObj->pData;
270             Vec_IntPush( vGroupNew, pObjNew->iData );
271         }
272         if ( vGroupNew == NULL )
273             continue;
274         if ( Vec_IntSize(vGroupNew) > 1 )
275         {
276             if ( vOnehotsPart == NULL )
277                 vOnehotsPart = Vec_PtrAlloc( 100 );
278             Vec_PtrPush( vOnehotsPart, vGroupNew );
279         }
280         else
281             Vec_IntFree( vGroupNew );
282     }
283     // clear the PI numbers
284     Aig_ManForEachCi( pPart, pObj, i )
285         pObj->iData = 0;
286     // print out
287     if ( vOnehotsPart && fVerbose )
288     {
289         printf( "Partition contains %d groups of 1-hot registers: { ", Vec_PtrSize(vOnehotsPart) );
290         Vec_PtrForEachEntry( Vec_Int_t *, vOnehotsPart, vGroup, k )
291             printf( "%d ", Vec_IntSize(vGroup) );
292         printf( "}\n" );
293     }
294     return vOnehotsPart;
295 }
296 
297 /**Function*************************************************************
298 
299   Synopsis    [Computes partitioning of registers.]
300 
301   Description []
302 
303   SideEffects []
304 
305   SeeAlso     []
306 
307 ***********************************************************************/
Aig_ManRegCreatePart(Aig_Man_t * pAig,Vec_Int_t * vPart,int * pnCountPis,int * pnCountRegs,int ** ppMapBack)308 Aig_Man_t * Aig_ManRegCreatePart( Aig_Man_t * pAig, Vec_Int_t * vPart, int * pnCountPis, int * pnCountRegs, int ** ppMapBack )
309 {
310     Aig_Man_t * pNew;
311     Aig_Obj_t * pObj, * pObjNew;
312     Vec_Ptr_t * vNodes;
313     Vec_Ptr_t * vRoots;
314     int nOffset, iOut, i;
315     int nCountPis, nCountRegs;
316     int * pMapBack;
317     // collect roots
318     vRoots = Vec_PtrAlloc( Vec_IntSize(vPart) );
319     nOffset = Aig_ManCoNum(pAig)-Aig_ManRegNum(pAig);
320     Vec_IntForEachEntry( vPart, iOut, i )
321     {
322         pObj = Aig_ManCo(pAig, nOffset+iOut);
323         Vec_PtrPush( vRoots, Aig_ObjFanin0(pObj) );
324     }
325     // collect/mark nodes/PIs in the DFS order
326     vNodes = Aig_ManDfsNodes( pAig, (Aig_Obj_t **)Vec_PtrArray(vRoots), Vec_PtrSize(vRoots) );
327     Vec_PtrFree( vRoots );
328     // unmark register outputs
329     nOffset = Aig_ManCiNum(pAig)-Aig_ManRegNum(pAig);
330     Vec_IntForEachEntry( vPart, iOut, i )
331     {
332         pObj = Aig_ManCi(pAig, nOffset+iOut);
333         Aig_ObjSetTravIdPrevious( pAig, pObj );
334     }
335     // count pure PIs
336     nCountPis = nCountRegs = 0;
337     Aig_ManForEachPiSeq( pAig, pObj, i )
338         nCountPis += Aig_ObjIsTravIdCurrent(pAig, pObj);
339     // count outputs of other registers
340     Aig_ManForEachLoSeq( pAig, pObj, i )
341         nCountRegs += Aig_ObjIsTravIdCurrent(pAig, pObj);
342     if ( pnCountPis )
343         *pnCountPis = nCountPis;
344     if ( pnCountRegs )
345         *pnCountRegs = nCountRegs;
346     // create the new manager
347     pNew = Aig_ManStart( Vec_PtrSize(vNodes) );
348     Aig_ManConst1(pAig)->pData = Aig_ManConst1(pNew);
349     // create the PIs
350     Aig_ManForEachCi( pAig, pObj, i )
351         if ( Aig_ObjIsTravIdCurrent(pAig, pObj) )
352             pObj->pData = Aig_ObjCreateCi(pNew);
353     // add variables for the register outputs
354     // create fake POs to hold the register outputs
355     nOffset = Aig_ManCiNum(pAig)-Aig_ManRegNum(pAig);
356     Vec_IntForEachEntry( vPart, iOut, i )
357     {
358         pObj = Aig_ManCi(pAig, nOffset+iOut);
359         pObj->pData = Aig_ObjCreateCi(pNew);
360         Aig_ObjCreateCo( pNew, (Aig_Obj_t *)pObj->pData );
361         Aig_ObjSetTravIdCurrent( pAig, pObj ); // added
362     }
363     // create the nodes
364     Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
365         if ( Aig_ObjIsNode(pObj) )
366             pObj->pData = Aig_And(pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
367     // add real POs for the registers
368     nOffset = Aig_ManCoNum(pAig)-Aig_ManRegNum(pAig);
369     Vec_IntForEachEntry( vPart, iOut, i )
370     {
371         pObj = Aig_ManCo( pAig, nOffset+iOut );
372         Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) );
373     }
374     pNew->nRegs = Vec_IntSize(vPart);
375     // create map
376     if ( ppMapBack )
377     {
378         pMapBack = ABC_ALLOC( int, Aig_ManObjNumMax(pNew) );
379         memset( pMapBack, 0xff, sizeof(int) * Aig_ManObjNumMax(pNew) );
380         // map constant nodes
381         pMapBack[0] = 0;
382         // logic cones of register outputs
383         Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
384         {
385             pObjNew = Aig_Regular((Aig_Obj_t *)pObj->pData);
386             pMapBack[pObjNew->Id] = pObj->Id;
387         }
388         // map register outputs
389         nOffset = Aig_ManCiNum(pAig)-Aig_ManRegNum(pAig);
390         Vec_IntForEachEntry( vPart, iOut, i )
391         {
392             pObj = Aig_ManCi(pAig, nOffset+iOut);
393             pObjNew = (Aig_Obj_t *)pObj->pData;
394             pMapBack[pObjNew->Id] = pObj->Id;
395         }
396         *ppMapBack = pMapBack;
397     }
398     Vec_PtrFree( vNodes );
399     return pNew;
400 }
401 
402 /**Function*************************************************************
403 
404   Synopsis    [Computes partitioning of registers.]
405 
406   Description []
407 
408   SideEffects []
409 
410   SeeAlso     []
411 
412 ***********************************************************************/
Aig_ManRegPartitionSmart(Aig_Man_t * pAig,int nPartSize)413 Vec_Ptr_t * Aig_ManRegPartitionSmart( Aig_Man_t * pAig, int nPartSize )
414 {
415     extern void Ioa_WriteAiger( Aig_Man_t * pMan, char * pFileName, int fWriteSymbols, int fCompact );
416 
417     Aig_ManPre_t * p;
418     Vec_Ptr_t * vResult;
419     int iSeed, iNext, i, k;
420     // create the manager
421     p = Aig_ManRegManStart( pAig, nPartSize );
422     // add partitions as long as registers remain
423     for ( i = 0; (iSeed = Aig_ManRegFindSeed(p)) >= 0; i++ )
424     {
425 //printf( "Seed variable = %d.\n", iSeed );
426         // clean the current partition information
427         Vec_IntClear( p->vRegs );
428         Vec_IntClear( p->vUniques );
429         Vec_IntClear( p->vFreeVars );
430         Vec_FltClear( p->vPartCost );
431         memset( p->pfPartVars, 0, sizeof(char) * Aig_ManRegNum(p->pAig) );
432         // add the register and its partition support
433         Aig_ManRegPartitionAdd( p, iSeed );
434         // select the best var to add
435         for ( k = 0; Vec_IntSize(p->vRegs) < p->nRegsMax; k++ )
436         {
437             // get the next best variable
438             iNext = Aig_ManRegFindBestVar( p );
439             if ( iNext == -1 )
440                 break;
441             // add the register to the support of the partition
442             Aig_ManRegPartitionAdd( p, iNext );
443             // report the result
444 //printf( "Part %3d  Reg %3d : Free = %4d. Total = %4d. Ratio = %6.2f. Unique = %4d.\n", i, k,
445 //                Vec_IntSize(p->vFreeVars), Vec_IntSize(p->vRegs),
446 //                1.0*Vec_IntSize(p->vFreeVars)/Vec_IntSize(p->vRegs), Vec_IntSize(p->vUniques) );
447             // quit if there are not free variables
448             if ( Vec_IntSize(p->vFreeVars) == 0 )
449                 break;
450         }
451         // add this partition to the set
452         Vec_PtrPush( p->vParts, Vec_IntDup(p->vRegs) );
453 printf( "Part %3d  SUMMARY:  Free = %4d. Total = %4d. Ratio = %6.2f. Unique = %4d.\n", i,
454                 Vec_IntSize(p->vFreeVars), Vec_IntSize(p->vRegs),
455                 1.0*Vec_IntSize(p->vFreeVars)/Vec_IntSize(p->vRegs), Vec_IntSize(p->vUniques) );
456 //printf( "\n" );
457     }
458     vResult = p->vParts; p->vParts = NULL;
459     Aig_ManRegManStop( p );
460     return vResult;
461 }
462 
463 /**Function*************************************************************
464 
465   Synopsis    [Computes partitioning of registers.]
466 
467   Description []
468 
469   SideEffects []
470 
471   SeeAlso     []
472 
473 ***********************************************************************/
Aig_ManRegPartitionSimple(Aig_Man_t * pAig,int nPartSize,int nOverSize)474 Vec_Ptr_t * Aig_ManRegPartitionSimple( Aig_Man_t * pAig, int nPartSize, int nOverSize )
475 {
476     Vec_Ptr_t * vResult;
477     Vec_Int_t * vPart;
478     int i, Counter;
479     if ( nOverSize >= nPartSize )
480     {
481         printf( "Overlap size (%d) is more or equal than the partition size (%d).\n", nOverSize, nPartSize );
482         printf( "Adjusting it to be equal to half of the partition size.\n" );
483         nOverSize = nPartSize/2;
484     }
485     assert( nOverSize < nPartSize );
486     vResult = Vec_PtrAlloc( 100 );
487     for ( Counter = 0; Counter < Aig_ManRegNum(pAig); Counter -= nOverSize )
488     {
489         vPart = Vec_IntAlloc( nPartSize );
490         for ( i = 0; i < nPartSize; i++, Counter++ )
491             if ( Counter < Aig_ManRegNum(pAig) )
492                 Vec_IntPush( vPart, Counter );
493         if ( Vec_IntSize(vPart) <= nOverSize )
494             Vec_IntFree(vPart);
495         else
496             Vec_PtrPush( vResult, vPart );
497     }
498     return vResult;
499 }
500 
501 
502 /**Function*************************************************************
503 
504   Synopsis    [Divides a large partition into several ones.]
505 
506   Description []
507 
508   SideEffects []
509 
510   SeeAlso     []
511 
512 ***********************************************************************/
Aig_ManPartDivide(Vec_Ptr_t * vResult,Vec_Int_t * vDomain,int nPartSize,int nOverSize)513 void Aig_ManPartDivide( Vec_Ptr_t * vResult, Vec_Int_t * vDomain, int nPartSize, int nOverSize )
514 {
515     Vec_Int_t * vPart;
516     int i, Counter;
517     assert( nPartSize && Vec_IntSize(vDomain) > nPartSize );
518     if ( nOverSize >= nPartSize )
519     {
520         printf( "Overlap size (%d) is more or equal than the partition size (%d).\n", nOverSize, nPartSize );
521         printf( "Adjusting it to be equal to half of the partition size.\n" );
522         nOverSize = nPartSize/2;
523     }
524     assert( nOverSize < nPartSize );
525     for ( Counter = 0; Counter < Vec_IntSize(vDomain); Counter -= nOverSize )
526     {
527         vPart = Vec_IntAlloc( nPartSize );
528         for ( i = 0; i < nPartSize; i++, Counter++ )
529             if ( Counter < Vec_IntSize(vDomain) )
530                 Vec_IntPush( vPart, Vec_IntEntry(vDomain, Counter) );
531         if ( Vec_IntSize(vPart) <= nOverSize )
532             Vec_IntFree(vPart);
533         else
534             Vec_PtrPush( vResult, vPart );
535     }
536 }
537 
538 /**Function*************************************************************
539 
540   Synopsis    [Computes partitioning of registers.]
541 
542   Description []
543 
544   SideEffects []
545 
546   SeeAlso     []
547 
548 ***********************************************************************/
Aig_ManRegPartitionTraverse_rec(Aig_Man_t * p,Aig_Obj_t * pObj,Vec_Ptr_t * vLos)549 void Aig_ManRegPartitionTraverse_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vLos )
550 {
551     if ( Aig_ObjIsTravIdCurrent(p, pObj) )
552         return;
553     Aig_ObjSetTravIdCurrent( p, pObj );
554     if ( Aig_ObjIsCi(pObj) )
555     {
556         if ( pObj->iData >= Aig_ManCiNum(p) - Aig_ManRegNum(p) )
557         {
558             Vec_PtrPush( vLos, pObj );
559             printf( "%d ", pObj->iData - (Aig_ManCiNum(p) - Aig_ManRegNum(p)) );
560         }
561         return;
562     }
563     Aig_ManRegPartitionTraverse_rec( p, Aig_ObjFanin0(pObj), vLos );
564     Aig_ManRegPartitionTraverse_rec( p, Aig_ObjFanin1(pObj), vLos );
565 }
566 
567 /**Function*************************************************************
568 
569   Synopsis    [Computes partitioning of registers.]
570 
571   Description []
572 
573   SideEffects []
574 
575   SeeAlso     []
576 
577 ***********************************************************************/
Aig_ManRegPartitionTraverse(Aig_Man_t * p)578 Vec_Ptr_t * Aig_ManRegPartitionTraverse( Aig_Man_t * p )
579 {
580     Vec_Ptr_t * vLos;
581     Aig_Obj_t * pObj;
582     int i, nPrev, Counter;
583     // mark the registers
584     Aig_ManForEachCi( p, pObj, i )
585        pObj->iData = i;
586     // collect registers
587     vLos = Vec_PtrAlloc( Aig_ManRegNum(p) );
588     nPrev = 0;
589     Counter = 0;
590     Aig_ManIncrementTravId( p );
591     Aig_ManForEachLiSeq( p, pObj, i )
592     {
593         ++Counter;
594         printf( "Latch %d: ", Counter );
595         Aig_ManRegPartitionTraverse_rec( p, Aig_ObjFanin0(pObj), vLos );
596 printf( "%d=%d \n", Counter, Vec_PtrSize(vLos)-nPrev );
597         nPrev = Vec_PtrSize(vLos);
598     }
599     printf( "Total collected = %d. Total regs = %d.\n", Vec_PtrSize(vLos), Aig_ManRegNum(p) );
600     return vLos;
601 }
602 
603 /**Function*************************************************************
604 
605   Synopsis    [Computes partitioning of registers.]
606 
607   Description []
608 
609   SideEffects []
610 
611   SeeAlso     []
612 
613 ***********************************************************************/
Aig_ManRegPartitionLinear(Aig_Man_t * pAig,int nPartSize)614 Vec_Ptr_t * Aig_ManRegPartitionLinear( Aig_Man_t * pAig, int nPartSize )
615 {
616     Vec_Ptr_t * vLos;
617     vLos = Aig_ManRegPartitionTraverse( pAig );
618     Vec_PtrFree( vLos );
619     return NULL;
620 }
621 
622 
623 ////////////////////////////////////////////////////////////////////////
624 ///                       END OF FILE                                ///
625 ////////////////////////////////////////////////////////////////////////
626 
627 
628 ABC_NAMESPACE_IMPL_END
629 
630