1 /**CFile****************************************************************
2 
3   FileName    [cgtAig.c]
4 
5   SystemName  [ABC: Logic synthesis and verification system.]
6 
7   PackageName [Clock gating package.]
8 
9   Synopsis    [Creates AIG to compute clock-gating.]
10 
11   Author      [Alan Mishchenko]
12 
13   Affiliation [UC Berkeley]
14 
15   Date        [Ver. 1.0. Started - June 20, 2005.]
16 
17   Revision    [$Id: cgtAig.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
18 
19 ***********************************************************************/
20 
21 #include "cgtInt.h"
22 
23 ABC_NAMESPACE_IMPL_START
24 
25 
26 ////////////////////////////////////////////////////////////////////////
27 ///                        DECLARATIONS                              ///
28 ////////////////////////////////////////////////////////////////////////
29 
30 ////////////////////////////////////////////////////////////////////////
31 ///                     FUNCTION DEFINITIONS                         ///
32 ////////////////////////////////////////////////////////////////////////
33 
34 /**Function*************************************************************
35 
36   Synopsis    [Computes transitive fanout cone of the node.]
37 
38   Description []
39 
40   SideEffects []
41 
42   SeeAlso     []
43 
44 ***********************************************************************/
Cgt_ManDetectCandidates_rec(Aig_Man_t * pAig,Vec_Int_t * vUseful,Aig_Obj_t * pObj,int nLevelMax,Vec_Ptr_t * vCands)45 void Cgt_ManDetectCandidates_rec( Aig_Man_t * pAig, Vec_Int_t * vUseful, Aig_Obj_t * pObj, int nLevelMax, Vec_Ptr_t * vCands )
46 {
47     if ( Aig_ObjIsTravIdCurrent(pAig, pObj) )
48         return;
49     Aig_ObjSetTravIdCurrent(pAig, pObj);
50     if ( Aig_ObjIsNode(pObj) )
51     {
52         Cgt_ManDetectCandidates_rec( pAig, vUseful, Aig_ObjFanin0(pObj), nLevelMax, vCands );
53         Cgt_ManDetectCandidates_rec( pAig, vUseful, Aig_ObjFanin1(pObj), nLevelMax, vCands );
54     }
55     if ( Aig_ObjLevel(pObj) <= nLevelMax && (vUseful == NULL || Vec_IntEntry(vUseful, Aig_ObjId(pObj))) )
56         Vec_PtrPush( vCands, pObj );
57 }
58 
59 /**Function*************************************************************
60 
61   Synopsis    [Computes transitive fanout cone of the node.]
62 
63   Description []
64 
65   SideEffects []
66 
67   SeeAlso     []
68 
69 ***********************************************************************/
Cgt_ManDetectCandidates(Aig_Man_t * pAig,Vec_Int_t * vUseful,Aig_Obj_t * pObj,int nLevelMax,Vec_Ptr_t * vCands)70 void Cgt_ManDetectCandidates( Aig_Man_t * pAig, Vec_Int_t * vUseful, Aig_Obj_t * pObj, int nLevelMax, Vec_Ptr_t * vCands )
71 {
72     Vec_PtrClear( vCands );
73     if ( !Aig_ObjIsNode(pObj) )
74         return;
75     Aig_ManIncrementTravId( pAig );
76     Cgt_ManDetectCandidates_rec( pAig, vUseful, pObj, nLevelMax, vCands );
77 }
78 
79 /**Function*************************************************************
80 
81   Synopsis    [Computes transitive fanout cone of the node.]
82 
83   Description []
84 
85   SideEffects []
86 
87   SeeAlso     []
88 
89 ***********************************************************************/
Cgt_ManDetectFanout_rec(Aig_Man_t * pAig,Aig_Obj_t * pObj,int nOdcMax,Vec_Ptr_t * vFanout)90 void Cgt_ManDetectFanout_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, int nOdcMax, Vec_Ptr_t * vFanout )
91 {
92     Aig_Obj_t * pFanout;
93     int f, iFanout = -1;
94     if ( Aig_ObjIsCo(pObj) || Aig_ObjLevel(pObj) > nOdcMax )
95         return;
96     if ( Aig_ObjIsTravIdCurrent(pAig, pObj) )
97         return;
98     Aig_ObjSetTravIdCurrent(pAig, pObj);
99     Vec_PtrPush( vFanout, pObj );
100     Aig_ObjForEachFanout( pAig, pObj, pFanout, iFanout, f )
101         Cgt_ManDetectFanout_rec( pAig, pFanout, nOdcMax, vFanout );
102 }
103 
104 /**Function*************************************************************
105 
106   Synopsis    [Computes transitive fanout cone of the node.]
107 
108   Description []
109 
110   SideEffects []
111 
112   SeeAlso     []
113 
114 ***********************************************************************/
Cgt_ManDetectFanout(Aig_Man_t * pAig,Aig_Obj_t * pObj,int nOdcMax,Vec_Ptr_t * vFanout)115 void Cgt_ManDetectFanout( Aig_Man_t * pAig, Aig_Obj_t * pObj, int nOdcMax, Vec_Ptr_t * vFanout )
116 {
117     Aig_Obj_t * pFanout;
118     int i, k, f, iFanout = -1;
119     // collect visited nodes
120     Vec_PtrClear( vFanout );
121     Aig_ManIncrementTravId( pAig );
122     Cgt_ManDetectFanout_rec( pAig, pObj, nOdcMax, vFanout );
123     // remove those nodes whose fanout is included
124     k = 0;
125     Vec_PtrForEachEntry( Aig_Obj_t *, vFanout, pObj, i )
126     {
127         // go through the fanouts of this node
128         Aig_ObjForEachFanout( pAig, pObj, pFanout, iFanout, f )
129             if ( !Aig_ObjIsTravIdCurrent(pAig, pFanout) )
130                 break;
131         if ( f == Aig_ObjRefs(pObj) ) // all fanouts are included
132             continue;
133         Vec_PtrWriteEntry( vFanout, k++, pObj );
134     }
135     Vec_PtrShrink( vFanout, k );
136     Vec_PtrSort( vFanout, (int (*)(void))Aig_ObjCompareIdIncrease );
137     assert( Vec_PtrSize(vFanout) > 0 );
138 }
139 
140 /**Function*************************************************************
141 
142   Synopsis    [Computes visited nodes in the topological order.]
143 
144   Description []
145 
146   SideEffects []
147 
148   SeeAlso     []
149 
150 ***********************************************************************/
Cgt_ManCollectVisited_rec(Aig_Man_t * pAig,Aig_Obj_t * pObj,Vec_Ptr_t * vVisited)151 void Cgt_ManCollectVisited_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Ptr_t * vVisited )
152 {
153     if ( Aig_ObjIsCi(pObj) )
154         return;
155     if ( Aig_ObjIsTravIdCurrent(pAig, pObj) )
156         return;
157     Aig_ObjSetTravIdCurrent(pAig, pObj);
158     assert( Aig_ObjIsNode(pObj) );
159     Cgt_ManCollectVisited_rec( pAig, Aig_ObjFanin0(pObj), vVisited );
160     Cgt_ManCollectVisited_rec( pAig, Aig_ObjFanin1(pObj), vVisited );
161     Vec_PtrPush( vVisited, pObj );
162 }
163 
164 /**Function*************************************************************
165 
166   Synopsis    [Computes visited nodes in the topological order.]
167 
168   Description []
169 
170   SideEffects []
171 
172   SeeAlso     []
173 
174 ***********************************************************************/
Cgt_ManCollectVisited(Aig_Man_t * pAig,Vec_Ptr_t * vFanout,Vec_Ptr_t * vVisited)175 void Cgt_ManCollectVisited( Aig_Man_t * pAig, Vec_Ptr_t * vFanout, Vec_Ptr_t * vVisited )
176 {
177     Aig_Obj_t * pObj;
178     int i;
179     Vec_PtrClear( vVisited );
180     Aig_ManIncrementTravId( pAig );
181     Vec_PtrForEachEntry( Aig_Obj_t *, vFanout, pObj, i )
182         Cgt_ManCollectVisited_rec( pAig, pObj, vVisited );
183 }
184 
185 /**Function*************************************************************
186 
187   Synopsis    []
188 
189   Description []
190 
191   SideEffects []
192 
193   SeeAlso     []
194 
195 ***********************************************************************/
Aig_ObjChild0CopyVec(Vec_Ptr_t * vCopy,Aig_Obj_t * pObj)196 static inline Aig_Obj_t *  Aig_ObjChild0CopyVec( Vec_Ptr_t * vCopy, Aig_Obj_t * pObj )
197 { return Aig_NotCond((Aig_Obj_t *)Vec_PtrEntry(vCopy, Aig_ObjFaninId0(pObj)), Aig_ObjFaninC0(pObj));  }
Aig_ObjChild1CopyVec(Vec_Ptr_t * vCopy,Aig_Obj_t * pObj)198 static inline Aig_Obj_t *  Aig_ObjChild1CopyVec( Vec_Ptr_t * vCopy, Aig_Obj_t * pObj )
199 { return Aig_NotCond((Aig_Obj_t *)Vec_PtrEntry(vCopy, Aig_ObjFaninId1(pObj)), Aig_ObjFaninC1(pObj));  }
200 
201 /**Function*************************************************************
202 
203   Synopsis    [Derives miter for clock-gating.]
204 
205   Description []
206 
207   SideEffects []
208 
209   SeeAlso     []
210 
211 ***********************************************************************/
Cgt_ManConstructCareCondition(Cgt_Man_t * p,Aig_Man_t * pNew,Aig_Obj_t * pObjLo,Vec_Ptr_t * vCopy0,Vec_Ptr_t * vCopy1)212 Aig_Obj_t * Cgt_ManConstructCareCondition( Cgt_Man_t * p, Aig_Man_t * pNew, Aig_Obj_t * pObjLo, Vec_Ptr_t * vCopy0, Vec_Ptr_t * vCopy1 )
213 {
214     Aig_Obj_t * pMiter, * pObj, * pTemp;
215     int i;
216     assert( Aig_ObjIsCi(pObjLo) );
217     // detect nodes and their cone
218     Cgt_ManDetectFanout( p->pAig, pObjLo, p->pPars->nOdcMax, p->vFanout );
219     Cgt_ManCollectVisited( p->pAig, p->vFanout, p->vVisited );
220     // add new variables if the observability condition depends on PI variables
221     Vec_PtrForEachEntry( Aig_Obj_t *, p->vVisited, pObj, i )
222     {
223         assert( Aig_ObjIsNode(pObj) );
224         if ( Saig_ObjIsPi(p->pAig, Aig_ObjFanin0(pObj)) && Vec_PtrEntry(vCopy0, Aig_ObjFaninId0(pObj)) == NULL )
225         {
226             pTemp = Aig_ObjCreateCi( pNew );
227             Vec_PtrWriteEntry( vCopy0, Aig_ObjFaninId0(pObj), pTemp );
228             Vec_PtrWriteEntry( vCopy1, Aig_ObjFaninId0(pObj), pTemp );
229         }
230         if ( Saig_ObjIsPi(p->pAig, Aig_ObjFanin1(pObj)) && Vec_PtrEntry(vCopy0, Aig_ObjFaninId1(pObj)) == NULL )
231         {
232             pTemp = Aig_ObjCreateCi( pNew );
233             Vec_PtrWriteEntry( vCopy0, Aig_ObjFaninId1(pObj), pTemp );
234             Vec_PtrWriteEntry( vCopy1, Aig_ObjFaninId1(pObj), pTemp );
235         }
236     }
237     // construct AIGs for the nodes
238     Vec_PtrForEachEntry( Aig_Obj_t *, p->vVisited, pObj, i )
239     {
240         pTemp = Aig_And( pNew, Aig_ObjChild0CopyVec(vCopy0, pObj), Aig_ObjChild1CopyVec(vCopy0, pObj) );
241         Vec_PtrWriteEntry( vCopy0, Aig_ObjId(pObj), pTemp );
242         pTemp = Aig_And( pNew, Aig_ObjChild0CopyVec(vCopy1, pObj), Aig_ObjChild1CopyVec(vCopy1, pObj) );
243         Vec_PtrWriteEntry( vCopy1, Aig_ObjId(pObj), pTemp );
244     }
245     // construct the care miter
246     pMiter = Aig_ManConst0( pNew );
247     Vec_PtrForEachEntry( Aig_Obj_t *, p->vFanout, pObj, i )
248     {
249         pTemp = Aig_Exor( pNew, (Aig_Obj_t *)Vec_PtrEntry(vCopy0, Aig_ObjId(pObj)), (Aig_Obj_t *)Vec_PtrEntry(vCopy1, Aig_ObjId(pObj)) );
250         pMiter = Aig_Or( pNew, pMiter, pTemp );
251     }
252     return pMiter;
253 }
254 
255 /**Function*************************************************************
256 
257   Synopsis    [Derives AIG for clock-gating.]
258 
259   Description []
260 
261   SideEffects []
262 
263   SeeAlso     []
264 
265 ***********************************************************************/
Cgt_ManDeriveAigForGating(Cgt_Man_t * p)266 Aig_Man_t * Cgt_ManDeriveAigForGating( Cgt_Man_t * p )
267 {
268     Aig_Man_t * pNew;
269     Aig_Obj_t * pObj, * pObjLi, * pObjLo, * pCare, * pMiter;
270     Vec_Ptr_t * vCopy0, * vCopy1;
271     int i;
272     assert( Aig_ManRegNum(p->pAig) );
273     pNew = Aig_ManStart( Aig_ManObjNumMax(p->pAig) );
274     pNew->pName = Abc_UtilStrsav( "CG_miter" );
275     // build the first frame
276     Aig_ManConst1(p->pAig)->pData = Aig_ManConst1(pNew);
277     Aig_ManForEachCi( p->pAig, pObj, i )
278         pObj->pData = Aig_ObjCreateCi( pNew );
279     Aig_ManForEachNode( p->pAig, pObj, i )
280         pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
281 //    Saig_ManForEachPo( p->pAig, pObj, i )
282 //        pObj->pData = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) );
283     if ( p->pPars->nOdcMax > 0 )
284     {
285         // create storage for observability conditions
286         vCopy0 = Vec_PtrStart( Aig_ManObjNumMax(p->pAig) );
287         vCopy1 = Vec_PtrStart( Aig_ManObjNumMax(p->pAig) );
288         // initialize register outputs
289         Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i )
290         {
291             Vec_PtrWriteEntry( vCopy0, Aig_ObjId(pObjLo), Aig_ObjChild0Copy(pObjLi) );
292             Vec_PtrWriteEntry( vCopy1, Aig_ObjId(pObjLo), Aig_ObjChild0Copy(pObjLi) );
293         }
294         // compute observability condition for each latch output
295         Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i )
296         {
297             // set the constants
298             Vec_PtrWriteEntry( vCopy0, Aig_ObjId(pObjLo), Aig_ManConst0(pNew) );
299             Vec_PtrWriteEntry( vCopy1, Aig_ObjId(pObjLo), Aig_ManConst1(pNew) );
300             // compute condition
301             pCare = Cgt_ManConstructCareCondition( p, pNew, pObjLo, vCopy0, vCopy1 );
302             // restore the values
303             Vec_PtrWriteEntry( vCopy0, Aig_ObjId(pObjLo), Aig_ObjChild0Copy(pObjLi) );
304             Vec_PtrWriteEntry( vCopy1, Aig_ObjId(pObjLo), Aig_ObjChild0Copy(pObjLi) );
305             // compute the miter
306             pMiter = Aig_Exor( pNew, (Aig_Obj_t *)pObjLo->pData, Aig_ObjChild0Copy(pObjLi) );
307             pMiter = Aig_And( pNew, pMiter, pCare );
308             pObjLi->pData = Aig_ObjCreateCo( pNew, pMiter );
309         }
310         Vec_PtrFree( vCopy0 );
311         Vec_PtrFree( vCopy1 );
312     }
313     else
314     {
315         // construct clock-gating miters for each register input
316         Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i )
317         {
318             pMiter = Aig_Exor( pNew, (Aig_Obj_t *)pObjLo->pData, Aig_ObjChild0Copy(pObjLi) );
319             pObjLi->pData = Aig_ObjCreateCo( pNew, pMiter );
320         }
321     }
322     Aig_ManCleanup( pNew );
323     Aig_ManSetCioIds( pNew );
324     return pNew;
325 }
326 
327 /**Function*************************************************************
328 
329   Synopsis    [Adds relevant constraints.]
330 
331   Description []
332 
333   SideEffects []
334 
335   SeeAlso     []
336 
337 ***********************************************************************/
Cgt_ManConstructCare_rec(Aig_Man_t * pCare,Aig_Obj_t * pObj,Aig_Man_t * pNew)338 Aig_Obj_t * Cgt_ManConstructCare_rec( Aig_Man_t * pCare, Aig_Obj_t * pObj, Aig_Man_t * pNew )
339 {
340     Aig_Obj_t * pObj0, * pObj1;
341     if ( Aig_ObjIsTravIdCurrent( pCare, pObj ) )
342         return (Aig_Obj_t *)pObj->pData;
343     Aig_ObjSetTravIdCurrent( pCare, pObj );
344     if ( Aig_ObjIsCi(pObj) )
345         return (Aig_Obj_t *)(pObj->pData = NULL);
346     pObj0 = Cgt_ManConstructCare_rec( pCare, Aig_ObjFanin0(pObj), pNew );
347     if ( pObj0 == NULL )
348         return (Aig_Obj_t *)(pObj->pData = NULL);
349     pObj1 = Cgt_ManConstructCare_rec( pCare, Aig_ObjFanin1(pObj), pNew );
350     if ( pObj1 == NULL )
351         return (Aig_Obj_t *)(pObj->pData = NULL);
352     pObj0 = Aig_NotCond( pObj0, Aig_ObjFaninC0(pObj) );
353     pObj1 = Aig_NotCond( pObj1, Aig_ObjFaninC1(pObj) );
354     return (Aig_Obj_t *)(pObj->pData = Aig_And( pNew, pObj0, pObj1 ));
355 }
356 
357 /**Function*************************************************************
358 
359   Synopsis    [Builds constraints belonging to the given partition.]
360 
361   Description []
362 
363   SideEffects []
364 
365   SeeAlso     []
366 
367 ***********************************************************************/
Cgt_ManConstructCare(Aig_Man_t * pNew,Aig_Man_t * pCare,Vec_Vec_t * vSuppsInv,Vec_Ptr_t * vLeaves)368 void Cgt_ManConstructCare( Aig_Man_t * pNew, Aig_Man_t * pCare, Vec_Vec_t * vSuppsInv, Vec_Ptr_t * vLeaves )
369 {
370     Vec_Int_t * vOuts;
371     Aig_Obj_t * pLeaf, * pPi, * pPo, * pObjAig;
372     int i, k, iOut;
373     // go through the PIs of the partition
374     // label the corresponding PIs of the care set
375     Aig_ManIncrementTravId( pCare );
376     Vec_PtrForEachEntry( Aig_Obj_t *, vLeaves, pLeaf, i )
377     {
378         pPi = Aig_ManCi( pCare, Aig_ObjCioId(pLeaf) );
379         Aig_ObjSetTravIdCurrent( pCare, pPi );
380         pPi->pData = pLeaf->pData;
381     }
382     // construct the constraints
383     Vec_PtrForEachEntry( Aig_Obj_t *, vLeaves, pLeaf, i )
384     {
385         vOuts = Vec_VecEntryInt( vSuppsInv, Aig_ObjCioId(pLeaf) );
386         Vec_IntForEachEntry( vOuts, iOut, k )
387         {
388             pPo = Aig_ManCo( pCare, iOut );
389             if ( Aig_ObjIsTravIdCurrent( pCare, pPo ) )
390                 continue;
391             Aig_ObjSetTravIdCurrent( pCare, pPo );
392             if ( Aig_ObjFanin0(pPo) == Aig_ManConst1(pCare) )
393                 continue;
394             pObjAig = Cgt_ManConstructCare_rec( pCare, Aig_ObjFanin0(pPo), pNew );
395             if ( pObjAig == NULL )
396                 continue;
397             pObjAig = Aig_NotCond( pObjAig, Aig_ObjFaninC0(pPo) );
398             Aig_ObjCreateCo( pNew, pObjAig );
399         }
400     }
401 }
402 
403 /**Function*************************************************************
404 
405   Synopsis    [Duplicates the AIG recursively.]
406 
407   Description []
408 
409   SideEffects []
410 
411   SeeAlso     []
412 
413 ***********************************************************************/
Cgt_ManDupPartition_rec(Aig_Man_t * pNew,Aig_Man_t * pAig,Aig_Obj_t * pObj,Vec_Ptr_t * vLeaves)414 Aig_Obj_t * Cgt_ManDupPartition_rec( Aig_Man_t * pNew, Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Ptr_t * vLeaves )
415 {
416     if ( Aig_ObjIsTravIdCurrent(pAig, pObj) )
417         return (Aig_Obj_t *)pObj->pData;
418     Aig_ObjSetTravIdCurrent(pAig, pObj);
419     if ( Aig_ObjIsCi(pObj) )
420     {
421         pObj->pData = Aig_ObjCreateCi( pNew );
422         Vec_PtrPush( vLeaves, pObj );
423         return (Aig_Obj_t *)pObj->pData;
424     }
425     Cgt_ManDupPartition_rec( pNew, pAig, Aig_ObjFanin0(pObj), vLeaves );
426     Cgt_ManDupPartition_rec( pNew, pAig, Aig_ObjFanin1(pObj), vLeaves );
427     return (Aig_Obj_t *)(pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ));
428 }
429 
430 /**Function*************************************************************
431 
432   Synopsis    [Duplicates register outputs starting from the given one.]
433 
434   Description []
435 
436   SideEffects []
437 
438   SeeAlso     []
439 
440 ***********************************************************************/
Cgt_ManDupPartition(Aig_Man_t * pFrame,int nVarsMin,int nFlopsMin,int iStart,Aig_Man_t * pCare,Vec_Vec_t * vSuppsInv,int * pnOutputs)441 Aig_Man_t * Cgt_ManDupPartition( Aig_Man_t * pFrame, int nVarsMin, int nFlopsMin, int iStart, Aig_Man_t * pCare, Vec_Vec_t * vSuppsInv, int * pnOutputs )
442 {
443     Vec_Ptr_t * vRoots, * vLeaves, * vPos;
444     Aig_Man_t * pNew;
445     Aig_Obj_t * pObj;
446     int i;
447     assert( Aig_ManRegNum(pFrame) == 0 );
448     vRoots = Vec_PtrAlloc( 100 );
449     vLeaves = Vec_PtrAlloc( 100 );
450     vPos = Vec_PtrAlloc( 100 );
451     pNew = Aig_ManStart( nVarsMin );
452     pNew->pName = Abc_UtilStrsav( "partition" );
453     Aig_ManIncrementTravId( pFrame );
454     Aig_ManConst1(pFrame)->pData = Aig_ManConst1(pNew);
455     Aig_ObjSetTravIdCurrent( pFrame, Aig_ManConst1(pFrame) );
456     for ( i = iStart; i < iStart + nFlopsMin && i < Aig_ManCoNum(pFrame); i++ )
457     {
458         pObj = Aig_ManCo( pFrame, i );
459         Cgt_ManDupPartition_rec( pNew, pFrame, Aig_ObjFanin0(pObj), vLeaves );
460         Vec_PtrPush( vRoots, Aig_ObjChild0Copy(pObj) );
461         Vec_PtrPush( vPos, pObj );
462     }
463     for ( ; Aig_ManObjNum(pNew) < nVarsMin && i < Aig_ManCoNum(pFrame); i++ )
464     {
465         pObj = Aig_ManCo( pFrame, i );
466         Cgt_ManDupPartition_rec( pNew, pFrame, Aig_ObjFanin0(pObj), vLeaves );
467         Vec_PtrPush( vRoots, Aig_ObjChild0Copy(pObj) );
468         Vec_PtrPush( vPos, pObj );
469     }
470     assert( nFlopsMin >= Vec_PtrSize(vRoots) || Vec_PtrSize(vRoots) >= nFlopsMin );
471     // create constaints
472     if ( pCare )
473         Cgt_ManConstructCare( pNew, pCare, vSuppsInv, vLeaves );
474     // create POs
475     Vec_PtrForEachEntry( Aig_Obj_t *, vPos, pObj, i )
476         pObj->pData = (Aig_Obj_t *)Aig_ObjCreateCo( pNew, (Aig_Obj_t *)Vec_PtrEntry(vRoots, i) );
477     if ( pnOutputs != NULL )
478         *pnOutputs = Vec_PtrSize( vPos );
479     Vec_PtrFree( vRoots );
480     Vec_PtrFree( vLeaves );
481     Vec_PtrFree( vPos );
482     return pNew;
483 }
484 
485 /**Function*************************************************************
486 
487   Synopsis    [Implements one clock-gate.]
488 
489   Description []
490 
491   SideEffects []
492 
493   SeeAlso     []
494 
495 ***********************************************************************/
Cgt_ManBuildClockGate(Aig_Man_t * pNew,Vec_Ptr_t * vGates)496 Aig_Obj_t * Cgt_ManBuildClockGate( Aig_Man_t * pNew, Vec_Ptr_t * vGates )
497 {
498     Aig_Obj_t * pGate, * pTotal;
499     int i;
500     assert( Vec_PtrSize(vGates) > 0 );
501     pTotal = Aig_ManConst0(pNew);
502     Vec_PtrForEachEntry( Aig_Obj_t *, vGates, pGate, i )
503     {
504         if ( Aig_Regular(pGate)->pNext )
505             pGate = Aig_NotCond( Aig_Regular(pGate)->pNext, Aig_IsComplement(pGate) );
506         else
507             pGate = Aig_NotCond( (Aig_Obj_t *)Aig_Regular(pGate)->pData, Aig_IsComplement(pGate) );
508         pTotal = Aig_Or( pNew, pTotal, pGate );
509     }
510     return pTotal;
511 }
512 
513 /**Function*************************************************************
514 
515   Synopsis    [Derives AIG after clock-gating.]
516 
517   Description [The array contains, for each flop, its gate if present.]
518 
519   SideEffects []
520 
521   SeeAlso     []
522 
523 ***********************************************************************/
Cgt_ManDeriveGatedAig(Aig_Man_t * pAig,Vec_Vec_t * vGates,int fReduce,int * pnUsedNodes)524 Aig_Man_t * Cgt_ManDeriveGatedAig( Aig_Man_t * pAig, Vec_Vec_t * vGates, int fReduce, int * pnUsedNodes )
525 {
526     Aig_Man_t * pNew;
527     Aig_Obj_t * pObj, * pObjNew, * pObjLi, * pObjLo, * pGateNew;
528     Vec_Ptr_t * vOne;
529     int i, k;
530     Aig_ManCleanNext( pAig );
531     // label nodes
532     Vec_VecForEachEntry( Aig_Obj_t *, vGates, pObj, i, k )
533     {
534         if ( Aig_IsComplement(pObj) )
535             Aig_Regular(pObj)->fMarkB = 1;
536         else
537             Aig_Regular(pObj)->fMarkA = 1;
538     }
539     // construct AIG
540     assert( Aig_ManRegNum(pAig) );
541     pNew = Aig_ManStart( Aig_ManObjNumMax(pAig) );
542     pNew->pName = Abc_UtilStrsav( pAig->pName );
543     pNew->pSpec = Abc_UtilStrsav( pAig->pSpec );
544     Aig_ManConst1(pAig)->pData = Aig_ManConst1(pNew);
545     Aig_ManForEachCi( pAig, pObj, i )
546         pObj->pData = Aig_ObjCreateCi( pNew );
547     if ( fReduce )
548     {
549         Aig_ManForEachNode( pAig, pObj, i )
550         {
551             assert( !(pObj->fMarkA && pObj->fMarkB) );
552             pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
553             if ( pObj->fMarkA )
554             {
555                 pObj->pNext = (Aig_Obj_t *)pObj->pData;
556                 pObj->pData = Aig_ManConst0(pNew);
557             }
558             else if ( pObj->fMarkB )
559             {
560                 pObj->pNext = (Aig_Obj_t *)pObj->pData;
561                 pObj->pData = Aig_ManConst1(pNew);
562             }
563         }
564     }
565     else
566     {
567         Aig_ManForEachNode( pAig, pObj, i )
568             pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
569     }
570     if ( pnUsedNodes != NULL )
571         *pnUsedNodes = Aig_ManNodeNum(pNew);
572     Saig_ManForEachPo( pAig, pObj, i )
573         pObj->pData = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) );
574     Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i )
575     {
576         vOne = Vec_VecEntry( vGates, i );
577         if ( Vec_PtrSize(vOne) == 0 )
578             pObjNew = Aig_ObjChild0Copy(pObjLi);
579         else
580         {
581 //            pGateNew = Aig_NotCond( Aig_Regular(pGate)->pData, Aig_IsComplement(pGate) );
582             pGateNew = Cgt_ManBuildClockGate( pNew, vOne );
583             pObjNew = Aig_Mux( pNew, pGateNew, (Aig_Obj_t *)pObjLo->pData, Aig_ObjChild0Copy(pObjLi) );
584         }
585         pObjLi->pData = Aig_ObjCreateCo( pNew, pObjNew );
586     }
587     Aig_ManCleanup( pNew );
588     Aig_ManSetRegNum( pNew, Aig_ManRegNum(pAig) );
589     // unlabel nodes
590     Aig_ManCleanMarkAB( pAig );
591     Aig_ManCleanNext( pAig );
592     return pNew;
593 }
594 
595 ////////////////////////////////////////////////////////////////////////
596 ///                       END OF FILE                                ///
597 ////////////////////////////////////////////////////////////////////////
598 
599 
600 ABC_NAMESPACE_IMPL_END
601 
602