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