cgtAig.c 20.6 KB
Newer Older
Alan Mishchenko committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
/**CFile****************************************************************

  FileName    [cgtAig.c]

  SystemName  [ABC: Logic synthesis and verification system.]

  PackageName [Clock gating package.]

  Synopsis    [Creates AIG to compute clock-gating.]

  Author      [Alan Mishchenko]
  
  Affiliation [UC Berkeley]

  Date        [Ver. 1.0. Started - June 20, 2005.]

  Revision    [$Id: cgtAig.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]

***********************************************************************/

#include "cgtInt.h"

23 24 25
ABC_NAMESPACE_IMPL_START


Alan Mishchenko committed
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
////////////////////////////////////////////////////////////////////////
///                        DECLARATIONS                              ///
////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////
///                     FUNCTION DEFINITIONS                         ///
////////////////////////////////////////////////////////////////////////

/**Function*************************************************************

  Synopsis    [Computes transitive fanout cone of the node.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
45
void Cgt_ManDetectCandidates_rec( Aig_Man_t * pAig, Vec_Int_t * vUseful, Aig_Obj_t * pObj, int nLevelMax, Vec_Ptr_t * vCands )
Alan Mishchenko committed
46 47 48 49 50 51
{
    if ( Aig_ObjIsTravIdCurrent(pAig, pObj) )
        return;
    Aig_ObjSetTravIdCurrent(pAig, pObj);
    if ( Aig_ObjIsNode(pObj) )
    {
52 53
        Cgt_ManDetectCandidates_rec( pAig, vUseful, Aig_ObjFanin0(pObj), nLevelMax, vCands );
        Cgt_ManDetectCandidates_rec( pAig, vUseful, Aig_ObjFanin1(pObj), nLevelMax, vCands );
Alan Mishchenko committed
54
    }
55
    if ( Aig_ObjLevel(pObj) <= nLevelMax && (vUseful == NULL || Vec_IntEntry(vUseful, Aig_ObjId(pObj))) )
Alan Mishchenko committed
56 57 58 59 60 61 62 63 64 65 66 67 68 69
        Vec_PtrPush( vCands, pObj );
}

/**Function*************************************************************

  Synopsis    [Computes transitive fanout cone of the node.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
70
void Cgt_ManDetectCandidates( Aig_Man_t * pAig, Vec_Int_t * vUseful, Aig_Obj_t * pObj, int nLevelMax, Vec_Ptr_t * vCands )
Alan Mishchenko committed
71 72
{
    Vec_PtrClear( vCands );
Alan Mishchenko committed
73
    if ( !Aig_ObjIsNode(pObj) )
Alan Mishchenko committed
74 75
        return;
    Aig_ManIncrementTravId( pAig );
76
    Cgt_ManDetectCandidates_rec( pAig, vUseful, pObj, nLevelMax, vCands );
Alan Mishchenko committed
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
}

/**Function*************************************************************

  Synopsis    [Computes transitive fanout cone of the node.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
void Cgt_ManDetectFanout_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, int nOdcMax, Vec_Ptr_t * vFanout )
{
    Aig_Obj_t * pFanout;
93
    int f, iFanout = -1;
94
    if ( Aig_ObjIsCo(pObj) || Aig_ObjLevel(pObj) > nOdcMax )
Alan Mishchenko committed
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
        return;
    if ( Aig_ObjIsTravIdCurrent(pAig, pObj) )
        return;
    Aig_ObjSetTravIdCurrent(pAig, pObj);
    Vec_PtrPush( vFanout, pObj );
    Aig_ObjForEachFanout( pAig, pObj, pFanout, iFanout, f )
        Cgt_ManDetectFanout_rec( pAig, pFanout, nOdcMax, vFanout );
}

/**Function*************************************************************

  Synopsis    [Computes transitive fanout cone of the node.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
void Cgt_ManDetectFanout( Aig_Man_t * pAig, Aig_Obj_t * pObj, int nOdcMax, Vec_Ptr_t * vFanout )
{
    Aig_Obj_t * pFanout;
118
    int i, k, f, iFanout = -1;
Alan Mishchenko committed
119 120 121 122 123 124
    // collect visited nodes
    Vec_PtrClear( vFanout );
    Aig_ManIncrementTravId( pAig );
    Cgt_ManDetectFanout_rec( pAig, pObj, nOdcMax, vFanout );
    // remove those nodes whose fanout is included
    k = 0;
125
    Vec_PtrForEachEntry( Aig_Obj_t *, vFanout, pObj, i )
Alan Mishchenko committed
126 127 128 129 130 131 132 133 134 135
    {
        // go through the fanouts of this node
        Aig_ObjForEachFanout( pAig, pObj, pFanout, iFanout, f )
            if ( !Aig_ObjIsTravIdCurrent(pAig, pFanout) )
                break;
        if ( f == Aig_ObjRefs(pObj) ) // all fanouts are included
            continue;
        Vec_PtrWriteEntry( vFanout, k++, pObj );
    }
    Vec_PtrShrink( vFanout, k );
136
    Vec_PtrSort( vFanout, (int (*)(const void *, const void *))Aig_ObjCompareIdIncrease );
Alan Mishchenko committed
137 138 139 140 141
    assert( Vec_PtrSize(vFanout) > 0 );
}

/**Function*************************************************************

Alan Mishchenko committed
142 143 144 145 146 147 148 149 150 151 152
  Synopsis    [Computes visited nodes in the topological order.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
void Cgt_ManCollectVisited_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Ptr_t * vVisited )
{
153
    if ( Aig_ObjIsCi(pObj) )
Alan Mishchenko committed
154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
        return;
    if ( Aig_ObjIsTravIdCurrent(pAig, pObj) )
        return;
    Aig_ObjSetTravIdCurrent(pAig, pObj);
    assert( Aig_ObjIsNode(pObj) );
    Cgt_ManCollectVisited_rec( pAig, Aig_ObjFanin0(pObj), vVisited );
    Cgt_ManCollectVisited_rec( pAig, Aig_ObjFanin1(pObj), vVisited );
    Vec_PtrPush( vVisited, pObj );
}

/**Function*************************************************************

  Synopsis    [Computes visited nodes in the topological order.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
void Cgt_ManCollectVisited( Aig_Man_t * pAig, Vec_Ptr_t * vFanout, Vec_Ptr_t * vVisited )
{
    Aig_Obj_t * pObj;
    int i;
    Vec_PtrClear( vVisited );
    Aig_ManIncrementTravId( pAig );
181
    Vec_PtrForEachEntry( Aig_Obj_t *, vFanout, pObj, i )
Alan Mishchenko committed
182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202
        Cgt_ManCollectVisited_rec( pAig, pObj, vVisited );
}

/**Function*************************************************************

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
static inline Aig_Obj_t *  Aig_ObjChild0CopyVec( Vec_Ptr_t * vCopy, Aig_Obj_t * pObj )  
{ return Aig_NotCond((Aig_Obj_t *)Vec_PtrEntry(vCopy, Aig_ObjFaninId0(pObj)), Aig_ObjFaninC0(pObj));  }
static inline Aig_Obj_t *  Aig_ObjChild1CopyVec( Vec_Ptr_t * vCopy, Aig_Obj_t * pObj )  
{ return Aig_NotCond((Aig_Obj_t *)Vec_PtrEntry(vCopy, Aig_ObjFaninId1(pObj)), Aig_ObjFaninC1(pObj));  }

/**Function*************************************************************

Alan Mishchenko committed
203 204 205 206 207 208 209 210 211
  Synopsis    [Derives miter for clock-gating.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
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 )
Alan Mishchenko committed
213
{
Alan Mishchenko committed
214
    Aig_Obj_t * pMiter, * pObj, * pTemp;
Alan Mishchenko committed
215
    int i;
216
    assert( Aig_ObjIsCi(pObjLo) );
Alan Mishchenko committed
217
    // detect nodes and their cone
Alan Mishchenko committed
218
    Cgt_ManDetectFanout( p->pAig, pObjLo, p->pPars->nOdcMax, p->vFanout );
Alan Mishchenko committed
219 220
    Cgt_ManCollectVisited( p->pAig, p->vFanout, p->vVisited );
    // add new variables if the observability condition depends on PI variables
221
    Vec_PtrForEachEntry( Aig_Obj_t *, p->vVisited, pObj, i )
Alan Mishchenko committed
222 223 224 225
    {
        assert( Aig_ObjIsNode(pObj) );
        if ( Saig_ObjIsPi(p->pAig, Aig_ObjFanin0(pObj)) && Vec_PtrEntry(vCopy0, Aig_ObjFaninId0(pObj)) == NULL )
        {
226
            pTemp = Aig_ObjCreateCi( pNew );
Alan Mishchenko committed
227 228 229 230 231
            Vec_PtrWriteEntry( vCopy0, Aig_ObjFaninId0(pObj), pTemp );
            Vec_PtrWriteEntry( vCopy1, Aig_ObjFaninId0(pObj), pTemp );
        }
        if ( Saig_ObjIsPi(p->pAig, Aig_ObjFanin1(pObj)) && Vec_PtrEntry(vCopy0, Aig_ObjFaninId1(pObj)) == NULL )
        {
232
            pTemp = Aig_ObjCreateCi( pNew );
Alan Mishchenko committed
233 234 235 236 237
            Vec_PtrWriteEntry( vCopy0, Aig_ObjFaninId1(pObj), pTemp );
            Vec_PtrWriteEntry( vCopy1, Aig_ObjFaninId1(pObj), pTemp );
        }
    }
    // construct AIGs for the nodes
238
    Vec_PtrForEachEntry( Aig_Obj_t *, p->vVisited, pObj, i )
Alan Mishchenko committed
239 240 241 242 243 244 245 246
    {
        pTemp = Aig_And( pNew, Aig_ObjChild0CopyVec(vCopy0, pObj), Aig_ObjChild1CopyVec(vCopy0, pObj) );
        Vec_PtrWriteEntry( vCopy0, Aig_ObjId(pObj), pTemp );
        pTemp = Aig_And( pNew, Aig_ObjChild0CopyVec(vCopy1, pObj), Aig_ObjChild1CopyVec(vCopy1, pObj) );
        Vec_PtrWriteEntry( vCopy1, Aig_ObjId(pObj), pTemp );
    }
    // construct the care miter
    pMiter = Aig_ManConst0( pNew );
247
    Vec_PtrForEachEntry( Aig_Obj_t *, p->vFanout, pObj, i )
Alan Mishchenko committed
248
    {
249
        pTemp = Aig_Exor( pNew, (Aig_Obj_t *)Vec_PtrEntry(vCopy0, Aig_ObjId(pObj)), (Aig_Obj_t *)Vec_PtrEntry(vCopy1, Aig_ObjId(pObj)) );
Alan Mishchenko committed
250 251
        pMiter = Aig_Or( pNew, pMiter, pTemp );
    }
Alan Mishchenko committed
252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268
    return pMiter;
}

/**Function*************************************************************

  Synopsis    [Derives AIG for clock-gating.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Aig_Man_t * Cgt_ManDeriveAigForGating( Cgt_Man_t * p )
{
    Aig_Man_t * pNew;
Alan Mishchenko committed
269 270
    Aig_Obj_t * pObj, * pObjLi, * pObjLo, * pCare, * pMiter;
    Vec_Ptr_t * vCopy0, * vCopy1;
Alan Mishchenko committed
271 272 273
    int i;
    assert( Aig_ManRegNum(p->pAig) );
    pNew = Aig_ManStart( Aig_ManObjNumMax(p->pAig) );
274
    pNew->pName = Abc_UtilStrsav( "CG_miter" );
Alan Mishchenko committed
275 276
    // build the first frame
    Aig_ManConst1(p->pAig)->pData = Aig_ManConst1(pNew);
277 278
    Aig_ManForEachCi( p->pAig, pObj, i )
        pObj->pData = Aig_ObjCreateCi( pNew );
Alan Mishchenko committed
279 280 281
    Aig_ManForEachNode( p->pAig, pObj, i )
        pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
//    Saig_ManForEachPo( p->pAig, pObj, i )
282
//        pObj->pData = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) );
Alan Mishchenko committed
283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305
    if ( p->pPars->nOdcMax > 0 )
    {
        // create storage for observability conditions
        vCopy0 = Vec_PtrStart( Aig_ManObjNumMax(p->pAig) );
        vCopy1 = Vec_PtrStart( Aig_ManObjNumMax(p->pAig) );
        // initialize register outputs
        Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i )
        {
            Vec_PtrWriteEntry( vCopy0, Aig_ObjId(pObjLo), Aig_ObjChild0Copy(pObjLi) );
            Vec_PtrWriteEntry( vCopy1, Aig_ObjId(pObjLo), Aig_ObjChild0Copy(pObjLi) );
        }
        // compute observability condition for each latch output
        Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i )
        {
            // set the constants
            Vec_PtrWriteEntry( vCopy0, Aig_ObjId(pObjLo), Aig_ManConst0(pNew) );
            Vec_PtrWriteEntry( vCopy1, Aig_ObjId(pObjLo), Aig_ManConst1(pNew) );
            // compute condition
            pCare = Cgt_ManConstructCareCondition( p, pNew, pObjLo, vCopy0, vCopy1 );
            // restore the values
            Vec_PtrWriteEntry( vCopy0, Aig_ObjId(pObjLo), Aig_ObjChild0Copy(pObjLi) );
            Vec_PtrWriteEntry( vCopy1, Aig_ObjId(pObjLo), Aig_ObjChild0Copy(pObjLi) );
            // compute the miter
306
            pMiter = Aig_Exor( pNew, (Aig_Obj_t *)pObjLo->pData, Aig_ObjChild0Copy(pObjLi) );
Alan Mishchenko committed
307
            pMiter = Aig_And( pNew, pMiter, pCare );
308
            pObjLi->pData = Aig_ObjCreateCo( pNew, pMiter );
Alan Mishchenko committed
309 310 311 312 313 314 315 316 317
        }
        Vec_PtrFree( vCopy0 );
        Vec_PtrFree( vCopy1 );
    }
    else
    {
        // construct clock-gating miters for each register input
        Saig_ManForEachLiLo( p->pAig, pObjLi, pObjLo, i )
        {
318
            pMiter = Aig_Exor( pNew, (Aig_Obj_t *)pObjLo->pData, Aig_ObjChild0Copy(pObjLi) );
319
            pObjLi->pData = Aig_ObjCreateCo( pNew, pMiter );
Alan Mishchenko committed
320 321
        }
    }
Alan Mishchenko committed
322
    Aig_ManCleanup( pNew );
323
    Aig_ManSetCioIds( pNew );
Alan Mishchenko committed
324 325 326 327 328
    return pNew;
}

/**Function*************************************************************

Alan Mishchenko committed
329 330 331 332 333 334 335 336 337 338 339 340 341
  Synopsis    [Adds relevant constraints.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Aig_Obj_t * Cgt_ManConstructCare_rec( Aig_Man_t * pCare, Aig_Obj_t * pObj, Aig_Man_t * pNew )
{
    Aig_Obj_t * pObj0, * pObj1;
    if ( Aig_ObjIsTravIdCurrent( pCare, pObj ) )
342
        return (Aig_Obj_t *)pObj->pData;
Alan Mishchenko committed
343
    Aig_ObjSetTravIdCurrent( pCare, pObj );
344
    if ( Aig_ObjIsCi(pObj) )
345
        return (Aig_Obj_t *)(pObj->pData = NULL);
Alan Mishchenko committed
346 347
    pObj0 = Cgt_ManConstructCare_rec( pCare, Aig_ObjFanin0(pObj), pNew );
    if ( pObj0 == NULL )
348
        return (Aig_Obj_t *)(pObj->pData = NULL);
Alan Mishchenko committed
349 350
    pObj1 = Cgt_ManConstructCare_rec( pCare, Aig_ObjFanin1(pObj), pNew );
    if ( pObj1 == NULL )
351
        return (Aig_Obj_t *)(pObj->pData = NULL);
Alan Mishchenko committed
352 353
    pObj0 = Aig_NotCond( pObj0, Aig_ObjFaninC0(pObj) );
    pObj1 = Aig_NotCond( pObj1, Aig_ObjFaninC1(pObj) );
354
    return (Aig_Obj_t *)(pObj->pData = Aig_And( pNew, pObj0, pObj1 ));
Alan Mishchenko committed
355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375
}

/**Function*************************************************************

  Synopsis    [Builds constraints belonging to the given partition.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
void Cgt_ManConstructCare( Aig_Man_t * pNew, Aig_Man_t * pCare, Vec_Vec_t * vSuppsInv, Vec_Ptr_t * vLeaves )
{
    Vec_Int_t * vOuts;
    Aig_Obj_t * pLeaf, * pPi, * pPo, * pObjAig;
    int i, k, iOut;
    // go through the PIs of the partition
    // label the corresponding PIs of the care set
    Aig_ManIncrementTravId( pCare );
376
    Vec_PtrForEachEntry( Aig_Obj_t *, vLeaves, pLeaf, i )
Alan Mishchenko committed
377
    {
378
        pPi = Aig_ManCi( pCare, Aig_ObjCioId(pLeaf) );
Alan Mishchenko committed
379 380 381 382
        Aig_ObjSetTravIdCurrent( pCare, pPi );
        pPi->pData = pLeaf->pData;
    }
    // construct the constraints
383
    Vec_PtrForEachEntry( Aig_Obj_t *, vLeaves, pLeaf, i )
Alan Mishchenko committed
384
    {
385
        vOuts = Vec_VecEntryInt( vSuppsInv, Aig_ObjCioId(pLeaf) );
Alan Mishchenko committed
386 387
        Vec_IntForEachEntry( vOuts, iOut, k )
        {
388
            pPo = Aig_ManCo( pCare, iOut );
Alan Mishchenko committed
389 390 391 392 393 394 395 396 397
            if ( Aig_ObjIsTravIdCurrent( pCare, pPo ) )
                continue;
            Aig_ObjSetTravIdCurrent( pCare, pPo );
            if ( Aig_ObjFanin0(pPo) == Aig_ManConst1(pCare) )
                continue;
            pObjAig = Cgt_ManConstructCare_rec( pCare, Aig_ObjFanin0(pPo), pNew );
            if ( pObjAig == NULL )
                continue;
            pObjAig = Aig_NotCond( pObjAig, Aig_ObjFaninC0(pPo) );
398
            Aig_ObjCreateCo( pNew, pObjAig );
Alan Mishchenko committed
399 400 401 402 403 404
        }
    }
}

/**Function*************************************************************

Alan Mishchenko committed
405 406 407 408 409 410 411 412 413
  Synopsis    [Duplicates the AIG recursively.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
414
Aig_Obj_t * Cgt_ManDupPartition_rec( Aig_Man_t * pNew, Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Ptr_t * vLeaves )
Alan Mishchenko committed
415 416
{
    if ( Aig_ObjIsTravIdCurrent(pAig, pObj) )
417
        return (Aig_Obj_t *)pObj->pData;
Alan Mishchenko committed
418
    Aig_ObjSetTravIdCurrent(pAig, pObj);
419
    if ( Aig_ObjIsCi(pObj) )
Alan Mishchenko committed
420
    {
421
        pObj->pData = Aig_ObjCreateCi( pNew );
Alan Mishchenko committed
422
        Vec_PtrPush( vLeaves, pObj );
423
        return (Aig_Obj_t *)pObj->pData;
Alan Mishchenko committed
424 425 426
    }
    Cgt_ManDupPartition_rec( pNew, pAig, Aig_ObjFanin0(pObj), vLeaves );
    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) ));
Alan Mishchenko committed
428 429 430 431 432 433 434 435 436 437 438 439 440
}

/**Function*************************************************************

  Synopsis    [Duplicates register outputs starting from the given one.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
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 )
Alan Mishchenko committed
442
{
Alan Mishchenko committed
443
    Vec_Ptr_t * vRoots, * vLeaves, * vPos;
Alan Mishchenko committed
444 445 446
    Aig_Man_t * pNew;
    Aig_Obj_t * pObj;
    int i;
Alan Mishchenko committed
447 448 449 450
    assert( Aig_ManRegNum(pFrame) == 0 );
    vRoots = Vec_PtrAlloc( 100 );
    vLeaves = Vec_PtrAlloc( 100 ); 
    vPos = Vec_PtrAlloc( 100 );
Alan Mishchenko committed
451
    pNew = Aig_ManStart( nVarsMin );
452
    pNew->pName = Abc_UtilStrsav( "partition" );
Alan Mishchenko committed
453 454 455
    Aig_ManIncrementTravId( pFrame );
    Aig_ManConst1(pFrame)->pData = Aig_ManConst1(pNew);
    Aig_ObjSetTravIdCurrent( pFrame, Aig_ManConst1(pFrame) );
456
    for ( i = iStart; i < iStart + nFlopsMin && i < Aig_ManCoNum(pFrame); i++ )
Alan Mishchenko committed
457
    {
458
        pObj = Aig_ManCo( pFrame, i );
Alan Mishchenko committed
459 460 461
        Cgt_ManDupPartition_rec( pNew, pFrame, Aig_ObjFanin0(pObj), vLeaves );
        Vec_PtrPush( vRoots, Aig_ObjChild0Copy(pObj) );
        Vec_PtrPush( vPos, pObj );
Alan Mishchenko committed
462
    }
463
    for ( ; Aig_ManObjNum(pNew) < nVarsMin && i < Aig_ManCoNum(pFrame); i++ )
Alan Mishchenko committed
464
    {
465
        pObj = Aig_ManCo( pFrame, i );
Alan Mishchenko committed
466 467 468
        Cgt_ManDupPartition_rec( pNew, pFrame, Aig_ObjFanin0(pObj), vLeaves );
        Vec_PtrPush( vRoots, Aig_ObjChild0Copy(pObj) );
        Vec_PtrPush( vPos, pObj );
Alan Mishchenko committed
469
    }
Alan Mishchenko committed
470 471 472 473 474
    assert( nFlopsMin >= Vec_PtrSize(vRoots) || Vec_PtrSize(vRoots) >= nFlopsMin );
    // create constaints
    if ( pCare )
        Cgt_ManConstructCare( pNew, pCare, vSuppsInv, vLeaves );
    // 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) );
Alan Mishchenko committed
477 478 479 480 481
    if ( pnOutputs != NULL )
        *pnOutputs = Vec_PtrSize( vPos );
    Vec_PtrFree( vRoots );
    Vec_PtrFree( vLeaves );
    Vec_PtrFree( vPos );
Alan Mishchenko committed
482 483 484 485 486
    return pNew;
}

/**Function*************************************************************

Alan Mishchenko committed
487 488 489 490 491 492 493 494 495 496 497 498 499 500 501
  Synopsis    [Implements one clock-gate.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Aig_Obj_t * Cgt_ManBuildClockGate( Aig_Man_t * pNew, Vec_Ptr_t * vGates )
{
    Aig_Obj_t * pGate, * pTotal;
    int i;
    assert( Vec_PtrSize(vGates) > 0 );
    pTotal = Aig_ManConst0(pNew);
502
    Vec_PtrForEachEntry( Aig_Obj_t *, vGates, pGate, i )
Alan Mishchenko committed
503 504 505 506
    {
        if ( Aig_Regular(pGate)->pNext )
            pGate = Aig_NotCond( Aig_Regular(pGate)->pNext, Aig_IsComplement(pGate) );
        else
507
            pGate = Aig_NotCond( (Aig_Obj_t *)Aig_Regular(pGate)->pData, Aig_IsComplement(pGate) );
Alan Mishchenko committed
508 509 510 511 512 513 514
        pTotal = Aig_Or( pNew, pTotal, pGate );
    }
    return pTotal;
}

/**Function*************************************************************

Alan Mishchenko committed
515 516 517 518 519 520 521 522 523
  Synopsis    [Derives AIG after clock-gating.]

  Description [The array contains, for each flop, its gate if present.]
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
524
Aig_Man_t * Cgt_ManDeriveGatedAig( Aig_Man_t * pAig, Vec_Vec_t * vGates, int fReduce, int * pnUsedNodes )
Alan Mishchenko committed
525 526
{
    Aig_Man_t * pNew;
Alan Mishchenko committed
527 528 529 530 531
    Aig_Obj_t * pObj, * pObjNew, * pObjLi, * pObjLo, * pGateNew;
    Vec_Ptr_t * vOne;
    int i, k;
    Aig_ManCleanNext( pAig );
    // label nodes
532
    Vec_VecForEachEntry( Aig_Obj_t *, vGates, pObj, i, k )
Alan Mishchenko committed
533 534 535 536 537 538 539
    {
        if ( Aig_IsComplement(pObj) )
            Aig_Regular(pObj)->fMarkB = 1;
        else
            Aig_Regular(pObj)->fMarkA = 1;
    }
    // construct AIG
Alan Mishchenko committed
540 541
    assert( Aig_ManRegNum(pAig) );
    pNew = Aig_ManStart( Aig_ManObjNumMax(pAig) );
542 543
    pNew->pName = Abc_UtilStrsav( pAig->pName );
    pNew->pSpec = Abc_UtilStrsav( pAig->pSpec );
Alan Mishchenko committed
544
    Aig_ManConst1(pAig)->pData = Aig_ManConst1(pNew);
545 546
    Aig_ManForEachCi( pAig, pObj, i )
        pObj->pData = Aig_ObjCreateCi( pNew );
Alan Mishchenko committed
547 548 549 550 551 552 553 554
    if ( fReduce )
    {
        Aig_ManForEachNode( pAig, pObj, i )
        {
            assert( !(pObj->fMarkA && pObj->fMarkB) );
            pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
            if ( pObj->fMarkA )
            {
555
                pObj->pNext = (Aig_Obj_t *)pObj->pData;
Alan Mishchenko committed
556 557 558 559
                pObj->pData = Aig_ManConst0(pNew);
            }
            else if ( pObj->fMarkB )
            {
560
                pObj->pNext = (Aig_Obj_t *)pObj->pData;
Alan Mishchenko committed
561 562 563 564 565 566 567 568 569 570 571
                pObj->pData = Aig_ManConst1(pNew);
            }
        }
    }
    else
    {
        Aig_ManForEachNode( pAig, pObj, i )
            pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
    }
    if ( pnUsedNodes != NULL )
        *pnUsedNodes = Aig_ManNodeNum(pNew);
Alan Mishchenko committed
572
    Saig_ManForEachPo( pAig, pObj, i )
573
        pObj->pData = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) );
Alan Mishchenko committed
574 575
    Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i )
    {
576
        vOne = Vec_VecEntry( vGates, i );
Alan Mishchenko committed
577
        if ( Vec_PtrSize(vOne) == 0 )
Alan Mishchenko committed
578 579 580
            pObjNew = Aig_ObjChild0Copy(pObjLi);
        else
        {
Alan Mishchenko committed
581 582
//            pGateNew = Aig_NotCond( Aig_Regular(pGate)->pData, Aig_IsComplement(pGate) );
            pGateNew = Cgt_ManBuildClockGate( pNew, vOne );
583
            pObjNew = Aig_Mux( pNew, pGateNew, (Aig_Obj_t *)pObjLo->pData, Aig_ObjChild0Copy(pObjLi) );
Alan Mishchenko committed
584
        }
585
        pObjLi->pData = Aig_ObjCreateCo( pNew, pObjNew );
Alan Mishchenko committed
586 587 588
    }
    Aig_ManCleanup( pNew );
    Aig_ManSetRegNum( pNew, Aig_ManRegNum(pAig) );
Alan Mishchenko committed
589 590 591
    // unlabel nodes
    Aig_ManCleanMarkAB( pAig );
    Aig_ManCleanNext( pAig );
Alan Mishchenko committed
592 593 594 595 596 597 598 599
    return pNew;
}

////////////////////////////////////////////////////////////////////////
///                       END OF FILE                                ///
////////////////////////////////////////////////////////////////////////


600 601
ABC_NAMESPACE_IMPL_END