sclUpsize.c 36.1 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
/**CFile****************************************************************

  FileName    [sclUpsize.c]

  SystemName  [ABC: Logic synthesis and verification system.]

  PackageName [Standard-cell library representation.]

  Synopsis    [Selective increase of gate sizes.]

  Author      [Alan Mishchenko, Niklas Een]
  
  Affiliation [UC Berkeley]

  Date        [Ver. 1.0. Started - August 24, 2012.]

  Revision    [$Id: sclUpsize.c,v 1.0 2012/08/24 00:00:00 alanmi Exp $]

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

21
#include "sclSize.h"
22 23 24 25 26 27 28 29 30 31 32 33 34 35

ABC_NAMESPACE_IMPL_START


////////////////////////////////////////////////////////////////////////
///                        DECLARATIONS                              ///
////////////////////////////////////////////////////////////////////////

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

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

36 37 38 39 40 41 42 43 44
  Synopsis    [Collect TFO of nodes.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
45
void Abc_SclFindTFO_rec( Abc_Obj_t * pObj, Vec_Int_t * vNodes, Vec_Int_t * vCos )
46 47 48 49 50 51
{
    Abc_Obj_t * pNext;
    int i;
    if ( Abc_NodeIsTravIdCurrent( pObj ) )
        return;
    Abc_NodeSetTravIdCurrent( pObj );
52 53 54 55 56 57
    if ( Abc_ObjIsCo(pObj) )
    {
        Vec_IntPush( vCos, Abc_ObjId(pObj) );
        return;
    }
    assert( Abc_ObjIsNode(pObj) );
58
    Abc_ObjForEachFanout( pObj, pNext, i )
59
        Abc_SclFindTFO_rec( pNext, vNodes, vCos );
60 61
    if ( Abc_ObjFaninNum(pObj) > 0 )
        Vec_IntPush( vNodes, Abc_ObjId(pObj) );
62 63 64
}
Vec_Int_t * Abc_SclFindTFO( Abc_Ntk_t * p, Vec_Int_t * vPath )
{
65
    Vec_Int_t * vNodes, * vCos;
66 67 68
    Abc_Obj_t * pObj, * pFanin;
    int i, k;
    assert( Vec_IntSize(vPath) > 0 );
69 70
    vCos = Vec_IntAlloc( 100 );
    vNodes = Vec_IntAlloc( 100 );
71 72 73 74 75
    // collect nodes in the TFO
    Abc_NtkIncrementTravId( p ); 
    Abc_NtkForEachObjVec( vPath, p, pObj, i )
        Abc_ObjForEachFanin( pObj, pFanin, k )
            if ( Abc_ObjIsNode(pFanin) )
76
                Abc_SclFindTFO_rec( pFanin, vNodes, vCos );
77
    // reverse order
78 79 80 81 82 83 84
    Vec_IntReverseOrder( vNodes );
//    Vec_IntSort( vNodes, 0 );
//Vec_IntPrint( vNodes );
//Vec_IntPrint( vCos );
    Vec_IntAppend( vNodes, vCos );
    Vec_IntFree( vCos );
    return vNodes;
85 86 87 88
}

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

89
  Synopsis    [Collect near-critical COs.]
90 91 92 93 94 95 96 97

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
98
Vec_Int_t * Abc_SclFindCriticalCoWindow( SC_Man * p, int Window )
99
{
100
    float fMaxArr = Abc_SclReadMaxDelay( p ) * (100.0 - Window) / 100.0;
101
    Vec_Int_t * vPivots;
102
    Abc_Obj_t * pObj;
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
    int i;
    vPivots = Vec_IntAlloc( 100 );
    Abc_NtkForEachCo( p->pNtk, pObj, i )
        if ( Abc_SclObjTimeMax(p, pObj) >= fMaxArr )
            Vec_IntPush( vPivots, Abc_ObjId(pObj) );
    assert( Vec_IntSize(vPivots) > 0 );
    return vPivots;
}

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

  Synopsis    [Collect near-critical internal nodes.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
123
void Abc_SclFindCriticalNodeWindow_rec( SC_Man * p, Abc_Obj_t * pObj, Vec_Int_t * vPath, float fSlack, int fDept )
124 125 126 127 128 129 130 131 132 133 134
{
    Abc_Obj_t * pNext;
    float fArrMax, fSlackFan;
    int i;
    if ( Abc_ObjIsCi(pObj) )
        return;
    if ( Abc_NodeIsTravIdCurrent( pObj ) )
        return;
    Abc_NodeSetTravIdCurrent( pObj );
    assert( Abc_ObjIsNode(pObj) );
    // compute the max arrival time of the fanins
135
    if ( fDept )
136 137
//        fArrMax = p->pSlack[Abc_ObjId(pObj)];
        fArrMax = Abc_SclObjGetSlack(p, pObj, p->MaxDelay);
138 139
    else
        fArrMax = Abc_SclGetMaxDelayNodeFanins( p, pObj );
140
//    assert( fArrMax >= -1 );
141
    fArrMax = Abc_MaxFloat( fArrMax, 0 );
142 143
    // traverse all fanins whose arrival times are within a window
    Abc_ObjForEachFanin( pObj, pNext, i )
144
    {
145 146 147 148
        if ( Abc_ObjIsCi(pNext) || Abc_ObjFaninNum(pNext) == 0 )
            continue;
        assert( Abc_ObjIsNode(pNext) );
        if ( fDept )
149 150
//            fSlackFan = fSlack - (p->pSlack[Abc_ObjId(pNext)] - fArrMax);
            fSlackFan = fSlack - (Abc_SclObjGetSlack(p, pNext, p->MaxDelay) - fArrMax);
151 152
        else
            fSlackFan = fSlack - (fArrMax - Abc_SclObjTimeMax(p, pNext));
153
        if ( fSlackFan >= 0 )
154
            Abc_SclFindCriticalNodeWindow_rec( p, pNext, vPath, fSlackFan, fDept );
155
    }
156 157
    if ( Abc_ObjFaninNum(pObj) > 0 )
        Vec_IntPush( vPath, Abc_ObjId(pObj) );
158
}
159
Vec_Int_t * Abc_SclFindCriticalNodeWindow( SC_Man * p, Vec_Int_t * vPathCos, int Window, int fDept )
160
{
161 162
    float fMaxArr = Abc_SclReadMaxDelay( p );
    float fSlackMax = fMaxArr * Window / 100.0;
163 164 165 166 167
    Vec_Int_t * vPath = Vec_IntAlloc( 100 );
    Abc_Obj_t * pObj;
    int i;
    Abc_NtkIncrementTravId( p->pNtk ); 
    Abc_NtkForEachObjVec( vPathCos, p->pNtk, pObj, i )
168
    {
169
        float fSlackThis = fSlackMax - (fMaxArr - Abc_SclObjTimeMax(p, pObj));
170
        if ( fSlackThis >= 0 )
171
            Abc_SclFindCriticalNodeWindow_rec( p, Abc_ObjFanin0(pObj), vPath, fSlackThis, fDept );
172
    }
173
    // label critical nodes
174 175
    Abc_NtkForEachObjVec( vPathCos, p->pNtk, pObj, i )
        pObj->fMarkA = 1;
176 177 178 179 180 181 182 183 184 185 186
    Abc_NtkForEachObjVec( vPath, p->pNtk, pObj, i )
        pObj->fMarkA = 1;
    return vPath;  
}
void Abc_SclUnmarkCriticalNodeWindow( SC_Man * p, Vec_Int_t * vPath )
{
    Abc_Obj_t * pObj;
    int i;
    Abc_NtkForEachObjVec( vPath, p->pNtk, pObj, i )
        pObj->fMarkA = 0;
}
187 188 189 190 191 192 193 194 195 196 197 198 199 200
int Abc_SclCountNearCriticalNodes( SC_Man * p )
{
    int RetValue;
    Vec_Int_t * vPathPos, * vPathNodes;
    vPathPos   = Abc_SclFindCriticalCoWindow( p, 5 );
    vPathNodes = Abc_SclFindCriticalNodeWindow( p, vPathPos, 5, 0 );
    RetValue   = Vec_IntSize(vPathNodes);
    Abc_SclUnmarkCriticalNodeWindow( p, vPathNodes );
    Abc_SclUnmarkCriticalNodeWindow( p, vPathPos );
    Vec_IntFree( vPathPos );
    Vec_IntFree( vPathNodes );
    return RetValue;
}

201 202 203 204 205 206 207 208 209 210 211 212

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

  Synopsis    [Find the array of nodes to be updated.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
213
void Abc_SclFindNodesToUpdate( Abc_Obj_t * pPivot, Vec_Int_t ** pvNodes, Vec_Int_t ** pvEvals, Abc_Obj_t * pExtra )
214
{
215 216
    Abc_Ntk_t * p = Abc_ObjNtk(pPivot);
    Abc_Obj_t * pObj, * pNext, * pNext2;
217 218
    Vec_Int_t * vNodes = *pvNodes;
    Vec_Int_t * vEvals = *pvEvals;
219 220 221
    int i, k;
    assert( Abc_ObjIsNode(pPivot) );
    assert( pPivot->fMarkA );
222
    // collect fanins, node, and fanouts
223
    Vec_IntClear( vNodes );
224
    Abc_ObjForEachFanin( pPivot, pNext, i )
225 226
//        if ( Abc_ObjIsNode(pNext) && Abc_ObjFaninNum(pNext) > 0 )
        if ( Abc_ObjIsCi(pNext) || Abc_ObjFaninNum(pNext) > 0 )
227
            Vec_IntPush( vNodes, Abc_ObjId(pNext) );
228
    Vec_IntPush( vNodes, Abc_ObjId(pPivot) );
229 230
    if ( pExtra )
        Vec_IntPush( vNodes, Abc_ObjId(pExtra) );
231
    Abc_ObjForEachFanout( pPivot, pNext, i )
232
        if ( Abc_ObjIsNode(pNext) && pNext->fMarkA )
233 234
        {
            Vec_IntPush( vNodes, Abc_ObjId(pNext) );
235
            Abc_ObjForEachFanout( pNext, pNext2, k )
236 237 238 239 240 241 242 243 244 245
                if ( Abc_ObjIsNode(pNext2) && pNext2->fMarkA )
                    Vec_IntPush( vNodes, Abc_ObjId(pNext2) );
        }
    Vec_IntUniqify( vNodes );
    // label nodes
    Abc_NtkForEachObjVec( vNodes, p, pObj, i )
    {
        assert( pObj->fMarkB == 0 );
        pObj->fMarkB = 1;
    }
246
    // collect nodes visible from the critical paths
247
    Vec_IntClear( vEvals );
248 249 250
    Abc_NtkForEachObjVec( vNodes, p, pObj, i )
        Abc_ObjForEachFanout( pObj, pNext, k )
            if ( pNext->fMarkA && !pNext->fMarkB )
251
//            if ( !pNext->fMarkB )
252
            {
253
                assert( pObj->fMarkB );
254
                Vec_IntPush( vEvals, Abc_ObjId(pObj) );
255 256
                break;
            }
257
    assert( Vec_IntSize(vEvals) > 0 );
258 259 260
    // label nodes
    Abc_NtkForEachObjVec( vNodes, p, pObj, i )
        pObj->fMarkB = 0;
261 262 263 264 265
}


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

266 267 268 269 270 271 272 273 274 275 276 277
  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
int Abc_SclFindBestCell( SC_Man * p, Abc_Obj_t * pObj, Vec_Int_t * vRecalcs, Vec_Int_t * vEvals, int Notches, int DelayGap, float * pGainBest )
{
    SC_Cell * pCellOld, * pCellNew;
278
    float dGain, dGainBest;
279
    int k, gateBest, NoChange = 0;
280
    // save old gate, timing, fanin load
281
    pCellOld = Abc_SclObjCell( pObj );
282
    Abc_SclConeStore( p, vRecalcs );
283
    Abc_SclEvalStore( p, vEvals );
284 285 286
    Abc_SclLoadStore( p, pObj );
    // try different gate sizes for this node
    gateBest = -1;
287
    dGainBest = -DelayGap;
288 289 290 291 292 293 294
    SC_RingForEachCell( pCellOld, pCellNew, k )
    {
        if ( pCellNew == pCellOld )
            continue;
        if ( k > Notches )
            break;
        // set new cell
295
        Abc_SclObjSetCell( pObj, pCellNew );
296 297 298 299
        Abc_SclUpdateLoad( p, pObj, pCellOld, pCellNew );
        // recompute timing
        Abc_SclTimeCone( p, vRecalcs );
        // set old cell
300
        Abc_SclObjSetCell( pObj, pCellOld );
301 302
        Abc_SclLoadRestore( p, pObj );
        // save best gain
303
        dGain = Abc_SclEvalPerform( p, vEvals );
304 305 306 307
        if ( dGainBest < dGain )
        {
            dGainBest = dGain;
            gateBest = pCellNew->Id;
308
            NoChange = 1;
309
        }
310 311
        else if ( NoChange )
            NoChange++;
312 313
        if ( NoChange == 4 )
            break;
314
//        printf( "%.2f ", dGain );
315
    }
316 317
//    printf( "Best = %.2f   ", dGainBest );
//    printf( "\n" );
318
    // put back old cell and timing
319
    Abc_SclObjSetCell( pObj, pCellOld );
320 321 322 323 324 325 326
    Abc_SclConeRestore( p, vRecalcs );
    *pGainBest = dGainBest;
    return gateBest;
}

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

327
  Synopsis    [Computes the set of gates to upsize.]
328 329 330 331 332 333

  Description []
               
  SideEffects []

  SeeAlso     []
334

335
***********************************************************************/
336
int Abc_SclFindBypasses( SC_Man * p, Vec_Int_t * vPathNodes, int Ratio, int Notches, int iIter, int DelayGap, int fVeryVerbose )
337 338
{
    SC_Cell * pCellOld, * pCellNew;
339
    Vec_Ptr_t * vFanouts;
340
    Vec_Int_t * vRecalcs, * vEvals;
341
    Abc_Obj_t * pBuf, * pFanin, * pFanout, * pExtra;
342 343
    int i, j, iNode, gateBest, gateBest2, fanBest, Counter = 0;
    float dGainBest, dGainBest2;
344 345 346 347 348 349

    // compute savings due to bypassing buffers
    vFanouts = Vec_PtrAlloc( 100 );
    vRecalcs = Vec_IntAlloc( 100 );
    vEvals = Vec_IntAlloc( 100 );
    Vec_QueClear( p->vNodeByGain );
350
    Abc_NtkForEachObjVec( vPathNodes, p->pNtk, pBuf, i )
351
    {
352
        assert( pBuf->fMarkB == 0 );
353
        if ( Abc_ObjFaninNum(pBuf) != 1 )
354
            continue;
355 356
        pFanin = Abc_ObjFanin0(pBuf);
        if ( !Abc_ObjIsNode(pFanin) )
357
            continue;
358
        pExtra = NULL;
359 360 361 362
        if ( p->pNtk->vPhases == NULL )
        {
            if ( Abc_SclIsInv(pBuf) )
            {
363
                if ( !Abc_SclIsInv(pFanin) )
364 365 366 367 368 369 370 371 372
                    continue;
                pFanin = Abc_ObjFanin0(pFanin);
                if ( !Abc_ObjIsNode(pFanin) )
                    continue;
                pExtra = pBuf;
                // we make pBuf and pFanin are in the same phase and pFanin is a node
            }
        }
        // here we have pBuf and its fanin pFanin, which is a logic node
373
        // compute nodes to recalculate timing and nodes to evaluate afterwards
374
        Abc_SclFindNodesToUpdate( pFanin, &vRecalcs, &vEvals, pExtra );
375 376
        assert( Vec_IntSize(vEvals) > 0 );
        // consider fanouts of this node
377 378 379 380
        fanBest    = -1;
        gateBest2  = -1;
        dGainBest2 =  0;
        Abc_NodeCollectFanouts( pBuf, vFanouts );
381 382 383 384 385 386 387 388 389
        Vec_PtrForEachEntry( Abc_Obj_t *, vFanouts, pFanout, j )
        {
            // skip COs
            if ( Abc_ObjIsCo(pFanout) )
                continue;
            // skip non-critical fanouts
            if ( !pFanout->fMarkA )
                continue;
            // skip if fanin already has fanout as a fanout
390
            if ( Abc_NodeFindFanin(pFanout, pFanin) >= 0 )
391
                continue;
392 393 394
            // skip if fanin already has fanout as a fanout
            if ( pExtra && Abc_NodeFindFanin(pFanout, pExtra) >= 0 )
                continue;
395
            // prepare
396 397 398
            Abc_SclLoadStore3( p, pBuf );
            Abc_SclUpdateLoadSplit( p, pBuf, pFanout );
            Abc_ObjPatchFanin( pFanout, pBuf, pFanin );
399
            // size the fanin
400 401 402 403 404 405
            gateBest = Abc_SclFindBestCell( p, pFanin, vRecalcs, vEvals, Notches, DelayGap, &dGainBest );
            // unprepare
            Abc_SclLoadRestore3( p, pBuf );
            Abc_ObjPatchFanin( pFanout, pFanin, pBuf );
            if ( gateBest == -1 )
                continue;
406 407 408 409 410 411 412 413 414 415 416 417
            // compare gain
            if ( dGainBest2 < dGainBest )
            {
                dGainBest2 = dGainBest;
                gateBest2 = gateBest;
                fanBest = Abc_ObjId(pFanout);
            }
        }
        // remember savings
        if ( gateBest2 >= 0 )
        {
            assert( dGainBest2 > 0.0 );
418 419 420 421
            Vec_FltWriteEntry( p->vNode2Gain, Abc_ObjId(pBuf), dGainBest2 );
            Vec_IntWriteEntry( p->vNode2Gate, Abc_ObjId(pBuf), gateBest2 );
            Vec_QuePush( p->vNodeByGain, Abc_ObjId(pBuf) );
            Vec_IntWriteEntry( p->vBestFans, Abc_ObjId(pBuf), fanBest );
422
        }
423 424
//        if ( ++Counter == 17 )
//            break;
425 426 427 428 429 430
    }
    Vec_PtrFree( vFanouts );
    Vec_IntFree( vRecalcs );
    Vec_IntFree( vEvals );
    if ( Vec_QueSize(p->vNodeByGain) == 0 )
        return 0;
431
    if ( fVeryVerbose ) 
432
        printf( "\n" );
433 434 435 436 437 438 439

    // accept changes for that are half above the average and do not overlap
    Counter = 0;
    dGainBest2 = -1;
    vFanouts = Vec_PtrAlloc( 100 );
    while ( Vec_QueSize(p->vNodeByGain) )
    {
440 441 442 443
        iNode   = Vec_QuePop(p->vNodeByGain);
        pFanout = Abc_NtkObj( p->pNtk, Vec_IntEntry(p->vBestFans, iNode) );
        pBuf    = Abc_NtkObj( p->pNtk, iNode );
        pFanin  = Abc_ObjFanin0(pBuf);
444 445
        if ( pFanout->fMarkB || pBuf->fMarkB )
            continue;
446 447 448 449 450
        if ( p->pNtk->vPhases == NULL )
        {
            // update fanin
            if ( Abc_SclIsInv(pBuf) )
            {
451
                if ( !Abc_SclIsInv(pFanin) )
452 453 454 455 456 457 458 459 460 461 462 463
                {
                    assert( 0 );
                    continue;
                }
                pFanin = Abc_ObjFanin0(pFanin);
                if ( !Abc_ObjIsNode(pFanin) )
                {
                    assert( 0 );
                    continue;
                }
            }
        }
464
        if ( pFanin->fMarkB )
465
            continue;
466 467 468
        pFanout->fMarkB = 1;
        pBuf->fMarkB = 1;
        pFanin->fMarkB = 1;
469
        Vec_PtrPush( vFanouts, pFanout );
470
        Vec_PtrPush( vFanouts, pBuf );
471 472 473 474
        Vec_PtrPush( vFanouts, pFanin );
        // remember gain
        if ( dGainBest2 == -1 )
            dGainBest2 = Vec_FltEntry(p->vNode2Gain, iNode);
475 476
//        else if ( dGainBest2 > 2*Vec_FltEntry(p->vNode2Gain, iNode) )
//            break;
477
        // redirect
478 479 480
        Abc_SclUpdateLoadSplit( p, pBuf, pFanout );
        Abc_SclAddWireLoad( p, pBuf, 1 );
        Abc_SclAddWireLoad( p, pFanin, 1 );
481
        Abc_ObjPatchFanin( pFanout, pBuf, pFanin );
482 483 484
        Abc_SclAddWireLoad( p, pBuf, 0 );
        Abc_SclAddWireLoad( p, pFanin, 0 );
        Abc_SclTimeIncUpdateLevel( pFanout );
485 486 487
        // remember
        Vec_IntPush( p->vUpdates2, Abc_ObjId(pFanout) );
        Vec_IntPush( p->vUpdates2, Abc_ObjId(pFanin) );
488
        Vec_IntPush( p->vUpdates2, Abc_ObjId(pBuf) );
489
        // update cell
490
        pCellOld = Abc_SclObjCell( pFanin );
491 492
        pCellNew = SC_LibCell( p->pLib, Vec_IntEntry(p->vNode2Gate, iNode) );
        p->SumArea += pCellNew->area - pCellOld->area;
493
        Abc_SclObjSetCell( pFanin, pCellNew );
494
        Abc_SclUpdateLoad( p, pFanin, pCellOld, pCellNew );
495 496 497
        // record the update
        Vec_IntPush( p->vUpdates, Abc_ObjId(pFanin) );
        Vec_IntPush( p->vUpdates, pCellNew->Id );
498 499
        Abc_SclTimeIncInsert( p, pFanout );
        Abc_SclTimeIncInsert( p, pBuf );
500
        Abc_SclTimeIncInsert( p, pFanin );
501
        // remember when this node was upsized
502 503 504
        Vec_IntWriteEntry( p->vNodeIter, Abc_ObjId(pFanout), -1 );
        Vec_IntWriteEntry( p->vNodeIter, Abc_ObjId(pBuf), -1 );
        Vec_IntWriteEntry( p->vNodeIter, Abc_ObjId(pFanin), -1 );
505
        // update polarity
506
        if ( p->pNtk->vPhases && Abc_SclIsInv(pBuf) )
507 508 509
            Abc_NodeInvUpdateObjFanoutPolarity( pFanin, pFanout );
        // report
        if ( fVeryVerbose )
510 511 512 513 514 515 516
        {
            printf( "Node %6d  Redir fanout %6d to fanin %6d.  Gain = %7.1f ps. ", 
                Abc_ObjId(pBuf), Abc_ObjId(pFanout), Abc_ObjId(pFanin), Vec_FltEntry(p->vNode2Gain, iNode) );
            printf( "Gate %12s (%2d/%2d)  -> %12s (%2d/%2d) \n", 
                pCellOld->pName, pCellOld->Order, pCellOld->nGates, 
                pCellNew->pName, pCellNew->Order, pCellNew->nGates );
        }
517 518
/*
        // check if the node became useless
519
        if ( Abc_ObjFanoutNum(pBuf) == 0 )
520
        {
521
            pCellOld = Abc_SclObjCell( pBuf );
522
            p->SumArea -= pCellOld->area;
523
            Abc_NtkDeleteObj_rec( pBuf, 1 );
524 525 526 527 528 529
            printf( "Removed node %d.\n", iNode );
        }
*/
        Counter++;
    }
    Vec_PtrForEachEntry( Abc_Obj_t *, vFanouts, pFanout, j )
530
        pFanout->fMarkB = 0;
531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549
    Vec_PtrFree( vFanouts );
    return Counter;
}

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

  Synopsis    [Check marked fanin/fanouts.]

  Description []
               
  SideEffects []

  SeeAlso     []
 
***********************************************************************/
int Abc_SclObjCheckMarkedFanFans( Abc_Obj_t * pObj )
{
    Abc_Obj_t * pNext;
    int i;
550
    if ( pObj->fMarkB )
551 552
        return 1;
    Abc_ObjForEachFanin( pObj, pNext, i )
553
        if ( pNext->fMarkB )
554 555
            return 1;
    Abc_ObjForEachFanout( pObj, pNext, i )
556
        if ( pNext->fMarkB )
557 558 559 560 561 562 563
            return 1;
    return 0;
}
void Abc_SclObjMarkFanFans( Abc_Obj_t * pObj, Vec_Ptr_t * vNodes )
{
//    Abc_Obj_t * pNext;
//    int i;
564
    if ( pObj->fMarkB == 0 )
565 566
    {
        Vec_PtrPush( vNodes, pObj );
567
        pObj->fMarkB = 1;
568 569 570
    }
/*
    Abc_ObjForEachFanin( pObj, pNext, i )
571
        if ( pNext->fMarkB == 0 )
572 573
        {
            Vec_PtrPush( vNodes, pNext );
574
            pNext->fMarkB = 1;
575 576
        }
    Abc_ObjForEachFanout( pObj, pNext, i )
577
        if ( pNext->fMarkB == 0 )
578 579
        {
            Vec_PtrPush( vNodes, pNext );
580
            pNext->fMarkB = 1;
581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600
        }
*/
}

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

  Synopsis    [Computes the set of gates to upsize.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
int Abc_SclFindUpsizes( SC_Man * p, Vec_Int_t * vPathNodes, int Ratio, int Notches, int iIter, int DelayGap, int fMoreConserf )
{
    SC_Cell * pCellOld, * pCellNew;
    Vec_Int_t * vRecalcs, * vEvals;
    Vec_Ptr_t * vFanouts;
601 602 603
    Abc_Obj_t * pObj;
    float dGainBest, dGainBest2;
    int i, gateBest, Limit, Counter, iIterLast;
604

605
    // compute savings due to upsizing each node
606 607
    vRecalcs = Vec_IntAlloc( 100 );
    vEvals = Vec_IntAlloc( 100 );
608
    Vec_QueClear( p->vNodeByGain );
609 610
    Abc_NtkForEachObjVec( vPathNodes, p->pNtk, pObj, i )
    {
611
        assert( pObj->fMarkB == 0 );
612
        iIterLast = Vec_IntEntry(p->vNodeIter, Abc_ObjId(pObj));
613
        if ( iIterLast >= 0 && iIterLast + 5 > iIter )
614
            continue;
615
        // compute nodes to recalculate timing and nodes to evaluate afterwards
616
        Abc_SclFindNodesToUpdate( pObj, &vRecalcs, &vEvals, NULL );
617 618
        assert( Vec_IntSize(vEvals) > 0 );
        //printf( "%d -> %d\n", Vec_IntSize(vRecalcs), Vec_IntSize(vEvals) );
619
        gateBest = Abc_SclFindBestCell( p, pObj, vRecalcs, vEvals, Notches, DelayGap, &dGainBest );
620
        // remember savings
621 622 623 624 625 626 627
        if ( gateBest >= 0 )
        {
            assert( dGainBest > 0.0 );
            Vec_FltWriteEntry( p->vNode2Gain, Abc_ObjId(pObj), dGainBest );
            Vec_IntWriteEntry( p->vNode2Gate, Abc_ObjId(pObj), gateBest );
            Vec_QuePush( p->vNodeByGain, Abc_ObjId(pObj) );
        }
628
    }
629 630 631
    Vec_IntFree( vRecalcs );
    Vec_IntFree( vEvals );
    if ( Vec_QueSize(p->vNodeByGain) == 0 )
632
        return 0;
633
/*
634 635
    Limit = Abc_MinInt( Vec_QueSize(p->vNodeByGain), Abc_MaxInt((int)(0.01 * Ratio * Vec_IntSize(vPathNodes)), 1) ); 
    //printf( "\nSelecting %d out of %d\n", Limit, Vec_QueSize(p->vNodeByGain) );
636
    for ( i = 0; i < Limit; i++ )
637
    {
638
        // get the object
639
        pObj = Abc_NtkObj( p->pNtk, Vec_QuePop(p->vNodeByGain) );
640 641
        assert( pObj->fMarkA );
        // find old and new gates
642
        pCellOld = Abc_SclObjCell( pObj );
643
        pCellNew = SC_LibCell( p->pLib, Vec_IntEntry(p->vNode2Gate, Abc_ObjId(pObj)) );
644
        assert( pCellNew != NULL );
645 646
        //printf( "%6d  %20s -> %20s  ", Abc_ObjId(pObj), pCellOld->pName, pCellNew->pName );
        //printf( "gain is %f\n", Vec_FltEntry(p->vNode2Gain, Abc_ObjId(pObj)) );
647 648 649
        // update gate
        Abc_SclUpdateLoad( p, pObj, pCellOld, pCellNew );
        p->SumArea += pCellNew->area - pCellOld->area;
650
        Abc_SclObjSetCell( pObj, pCellNew );
651 652 653
        // record the update
        Vec_IntPush( p->vUpdates, Abc_ObjId(pObj) );
        Vec_IntPush( p->vUpdates, pCellNew->Id );
654
        Abc_SclTimeIncInsert( p, pObj );
655 656
        // remember when this node was upsized
        Vec_IntWriteEntry( p->vNodeIter, Abc_ObjId(pObj), iIter );
657
    }
658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675
return Limit;
*/

    Limit = Abc_MinInt( Vec_QueSize(p->vNodeByGain), Abc_MaxInt((int)(0.01 * Ratio * Vec_IntSize(vPathNodes)), 1) ); 
    dGainBest2 = -1;
    Counter = 0;
    vFanouts = Vec_PtrAlloc( 100 );
    while ( Vec_QueSize(p->vNodeByGain) )
    {
        int iNode = Vec_QuePop(p->vNodeByGain);
        Abc_Obj_t * pObj = Abc_NtkObj( p->pNtk, iNode );
        assert( pObj->fMarkA );
        if ( Abc_SclObjCheckMarkedFanFans( pObj ) )
            continue;
        Abc_SclObjMarkFanFans( pObj, vFanouts );
        // remember gain
        if ( dGainBest2 == -1 )
            dGainBest2 = Vec_FltEntry(p->vNode2Gain, iNode);
676 677
//        else if ( dGainBest2 > 3*Vec_FltEntry(p->vNode2Gain, iNode) )
//            break;
678 679 680
//        printf( "%.1f ", Vec_FltEntry(p->vNode2Gain, iNode) );

        // find old and new gates
681
        pCellOld = Abc_SclObjCell( pObj );
682 683 684 685
        pCellNew = SC_LibCell( p->pLib, Vec_IntEntry(p->vNode2Gate, Abc_ObjId(pObj)) );
        assert( pCellNew != NULL );
        //printf( "%6d  %20s -> %20s  ", Abc_ObjId(pObj), pCellOld->pName, pCellNew->pName );
        //printf( "gain is %f\n", Vec_FltEntry(p->vNode2Gain, Abc_ObjId(pObj)) );
686 687
//        if ( pCellOld->Order > 0 )
//            printf( "%.2f  %d -> %d(%d)   ", Vec_FltEntry(p->vNode2Gain, iNode), pCellOld->Order, pCellNew->Order, pCellNew->nGates );
688 689
        // update gate
        p->SumArea += pCellNew->area - pCellOld->area;
690
        Abc_SclObjSetCell( pObj, pCellNew );
691
        Abc_SclUpdateLoad( p, pObj, pCellOld, pCellNew );
692 693 694
        // record the update
        Vec_IntPush( p->vUpdates, Abc_ObjId(pObj) );
        Vec_IntPush( p->vUpdates, pCellNew->Id );
695
        Abc_SclTimeIncInsert( p, pObj );
696 697 698 699 700 701 702 703 704
        // remember when this node was upsized
        Vec_IntWriteEntry( p->vNodeIter, Abc_ObjId(pObj), iIter );
        Counter++;
        if ( Counter == Limit )
            break;
    }
//    printf( "\n" );

    Vec_PtrForEachEntry( Abc_Obj_t *, vFanouts, pObj, i )
705
        pObj->fMarkB = 0;
706 707
    Vec_PtrFree( vFanouts );
    return Counter;
708
}
709
void Abc_SclApplyUpdateToBest( Vec_Int_t * vGatesBest, Vec_Int_t * vGates, Vec_Int_t * vUpdate )
710 711 712 713 714
{
    int i, ObjId, GateId, GateId2; 
    Vec_IntForEachEntryDouble( vUpdate, ObjId, GateId, i )
        Vec_IntWriteEntry( vGatesBest, ObjId, GateId );
    Vec_IntClear( vUpdate );
715
    Vec_IntForEachEntryTwo( vGatesBest, vGates, GateId, GateId2, i )
716
        assert( GateId == GateId2 );
717 718
//    Vec_IntClear( vGatesBest );
//    Vec_IntAppend( vGatesBest, vGates );
719
}
720 721 722 723 724 725 726 727 728
void Abc_SclUndoRecentChanges( Abc_Ntk_t * pNtk, Vec_Int_t * vTrans )
{
    int i;
    assert( Vec_IntSize(vTrans) % 3 == 0 );
    for ( i = Vec_IntSize(vTrans)/3 - 1; i >= 0; i-- )
    {
        Abc_Obj_t * pFanout = Abc_NtkObj( pNtk, Vec_IntEntry(vTrans, 3*i+0) );
        Abc_Obj_t * pFanin  = Abc_NtkObj( pNtk, Vec_IntEntry(vTrans, 3*i+1) );
        Abc_Obj_t * pObj    = Abc_NtkObj( pNtk, Vec_IntEntry(vTrans, 3*i+2) );
729
        // we do not update load here because times will be recomputed
730
        Abc_ObjPatchFanin( pFanout, pFanin, pObj );
731
        Abc_SclTimeIncUpdateLevel( pFanout );
732 733 734 735 736 737 738
//        printf( "Node %6d  Redir fanout %6d from fanin %6d. \n", 
//            Abc_ObjId(pObj), Abc_ObjId(pFanout), Abc_ObjId(pFanin) );
        // update polarity
        if ( pNtk->vPhases && Abc_SclIsInv(pObj) )
            Abc_NodeInvUpdateObjFanoutPolarity( pObj, pFanout );
    }
}
739 740 741

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

742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764
  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
void Abc_SclUpsizePrintDiffs( SC_Man * p, SC_Lib * pLib, Abc_Ntk_t * pNtk )
{
    float fDiff = (float)0.001;
    int k;
    Abc_Obj_t * pObj;

    SC_Pair * pTimes = ABC_ALLOC( SC_Pair, p->nObjs );
    SC_Pair * pSlews = ABC_ALLOC( SC_Pair, p->nObjs );
    SC_Pair * pLoads = ABC_ALLOC( SC_Pair, p->nObjs );

    memcpy( pTimes, p->pTimes, sizeof(SC_Pair) * p->nObjs );
    memcpy( pSlews, p->pSlews, sizeof(SC_Pair) * p->nObjs );
    memcpy( pLoads, p->pLoads, sizeof(SC_Pair) * p->nObjs );

765
    Abc_SclTimeNtkRecompute( p, NULL, NULL, 0, 0 );
766 767 768 769

    Abc_NtkForEachNode( pNtk, pObj, k )
    {
        if ( Abc_AbsFloat(p->pLoads[k].rise - pLoads[k].rise) > fDiff )
770
            printf( "%6d : load rise differs %12.6f   %f %f\n", k, p->pLoads[k].rise-pLoads[k].rise, p->pLoads[k].rise, pLoads[k].rise );
771
        if ( Abc_AbsFloat(p->pLoads[k].fall - pLoads[k].fall) > fDiff )
772
            printf( "%6d : load fall differs %12.6f   %f %f\n", k, p->pLoads[k].fall-pLoads[k].fall, p->pLoads[k].fall, pLoads[k].fall );
773 774

        if ( Abc_AbsFloat(p->pSlews[k].rise - pSlews[k].rise) > fDiff )
775
            printf( "%6d : slew rise differs %12.6f   %f %f\n", k, p->pSlews[k].rise-pSlews[k].rise, p->pSlews[k].rise, pSlews[k].rise );
776
        if ( Abc_AbsFloat(p->pSlews[k].fall - pSlews[k].fall) > fDiff )
777
            printf( "%6d : slew fall differs %12.6f   %f %f\n", k, p->pSlews[k].fall-pSlews[k].fall, p->pSlews[k].fall, pSlews[k].fall );
778 779

        if ( Abc_AbsFloat(p->pTimes[k].rise - pTimes[k].rise) > fDiff )
780
            printf( "%6d : time rise differs %12.6f   %f %f\n", k, p->pTimes[k].rise-pTimes[k].rise, p->pTimes[k].rise, pTimes[k].rise );
781
        if ( Abc_AbsFloat(p->pTimes[k].fall - pTimes[k].fall) > fDiff )
782
            printf( "%6d : time fall differs %12.6f   %f %f\n", k, p->pTimes[k].fall-pTimes[k].fall, p->pTimes[k].fall, pTimes[k].fall );
783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800
    }

/*
if ( memcmp( pTimes, p->pTimes, sizeof(SC_Pair) * p->nObjs ) )
    printf( "Times differ!\n" );
if ( memcmp( pSlews, p->pSlews, sizeof(SC_Pair) * p->nObjs ) )
    printf( "Slews differ!\n" );
if ( memcmp( pLoads, p->pLoads, sizeof(SC_Pair) * p->nObjs ) )
    printf( "Loads differ!\n" );
*/

    ABC_FREE( pTimes );
    ABC_FREE( pSlews );
    ABC_FREE( pLoads );
}

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

801 802 803 804 805 806 807
  Synopsis    [Print cumulative statistics.]

  Description []
               
  SideEffects []

  SeeAlso     []
808

809
***********************************************************************/
810
void Abc_SclUpsizePrint( SC_Man * p, int Iter, int win, int nPathPos, int nPathNodes, int nUpsizes, int nTFOs, int fVerbose )
811
{
812
    printf( "%4d ",          Iter );
813
    printf( "Win:%3d. ",     win );
814 815
    printf( "PO:%6d. ",      nPathPos );
    printf( "Path:%7d. ",    nPathNodes );
816
    printf( "Gate:%5d. ",    nUpsizes );
817
    printf( "TFO:%7d. ",     nTFOs );
818 819
    printf( "A: " );
    printf( "%.2f ",         p->SumArea );
820
    printf( "(%+5.1f %%)  ", 100.0 * (p->SumArea - p->SumArea0)/ p->SumArea0 );
821
    printf( "D: " );
822
    printf( "%.2f ps ",      p->MaxDelay );
823
    printf( "(%+5.1f %%)  ", 100.0 * (p->MaxDelay - p->MaxDelay0)/ p->MaxDelay0 );
824
    printf( "B: " );
825
    printf( "%.2f ps ",      p->BestDelay );
826
    printf( "(%+5.1f %%)",   100.0 * (p->BestDelay - p->MaxDelay0)/ p->MaxDelay0 );
827
    printf( "%8.2f sec    ", 1.0*(Abc_Clock() - p->timeTotal)/(CLOCKS_PER_SEC) );
828
    printf( "%c", fVerbose ? '\n' : '\r' );
829 830 831 832 833 834 835 836 837 838 839 840 841
}

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

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
842 843 844 845 846 847 848 849
void Abc_SclUpsizeRemoveDangling( SC_Man * p, Abc_Ntk_t * pNtk )
{
    SC_Cell * pCell;
    Abc_Obj_t * pObj;
    int i;
    Abc_NtkForEachNode( pNtk, pObj, i )
        if ( Abc_ObjFanoutNum(pObj) == 0 )
        {
850
            pCell = Abc_SclObjCell( pObj );
851 852
            p->SumArea -= pCell->area;
            Abc_NtkDeleteObj_rec( pObj, 1 );
853
//            printf( "Removed node %d.\n", i );
854 855 856 857 858 859 860 861 862 863 864 865 866 867
        }
}

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

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
868
void Abc_SclUpsizePerform( SC_Lib * pLib, Abc_Ntk_t * pNtk, SC_SizePars * pPars )
869 870
{
    SC_Man * p;
871 872
    Vec_Int_t * vPathPos = NULL;    // critical POs
    Vec_Int_t * vPathNodes = NULL;  // critical nodes and PIs
873
    abctime clk, nRuntimeLimit = pPars->TimeOut ? pPars->TimeOut * CLOCKS_PER_SEC + Abc_Clock() : 0;
874
    int i = 0, win, nUpsizes = -1, nFramesNoChange = 0, nConeSize = 0;
875
    int nAllPos, nAllNodes, nAllTfos, nAllUpsizes;
876
    if ( pPars->fVerbose )
877
    {
878
        printf( "Parameters: " );
879
        printf( "Iters =%5d.  ",          pPars->nIters   );
880
        printf( "Time win =%3d %%. ",     pPars->Window   );
881 882
        printf( "Update ratio =%3d %%. ", pPars->Ratio    );
        printf( "UseDept =%2d. ",         pPars->fUseDept );
883
        printf( "UseWL =%2d. ",           pPars->fUseWireLoads );
884 885
        printf( "Target =%5d ps. ",       pPars->DelayUser );
        printf( "DelayGap =%3d ps. ",     pPars->DelayGap );
886
        printf( "Timeout =%4d sec",       pPars->TimeOut  );
887 888
        printf( "\n" );
    }
889 890 891
    // increase window for larger networks
    if ( pPars->Window == 1 )
        pPars->Window += (Abc_NtkNodeNum(pNtk) > 40000);
892
    // prepare the manager; collect init stats
893
    p = Abc_SclManStart( pLib, pNtk, pPars->fUseWireLoads, pPars->fUseDept, 0, pPars->BuffTreeEst );
894
    p->timeTotal  = Abc_Clock();
895
    assert( p->vGatesBest == NULL );
896
    p->vGatesBest = Vec_IntDup( p->pNtk->vGates );
897
    p->BestDelay  = p->MaxDelay0;
898
    // perform upsizing
899
    nAllPos = nAllNodes = nAllTfos = nAllUpsizes = 0;
900
    if ( p->BestDelay <= pPars->DelayUser )
901
        printf( "Current delay (%.2f ps) does not exceed the target delay (%.2f ps). Upsizing is not performed.\n", p->BestDelay, (float)pPars->DelayUser );
Alan Mishchenko committed
902
    else
903
    for ( i = 0; i < pPars->nIters; i++ )
904
    {
905
        for ( win = pPars->Window + ((i % 7) == 6); win <= 100;  win *= 2 )
906 907
        {
            // detect critical path
908
            clk = Abc_Clock();
909
            vPathPos   = Abc_SclFindCriticalCoWindow( p, win );
910
            vPathNodes = Abc_SclFindCriticalNodeWindow( p, vPathPos, win, pPars->fUseDept );
911
            p->timeCone += Abc_Clock() - clk;
912 913

            // selectively upsize the nodes
914
            clk = Abc_Clock();
915 916 917 918
            if ( pPars->BypassFreq && i && (i % pPars->BypassFreq) == 0 )
                nUpsizes = Abc_SclFindBypasses( p, vPathNodes, pPars->Ratio, pPars->Notches, i, pPars->DelayGap, pPars->fVeryVerbose );
            else
                nUpsizes = Abc_SclFindUpsizes( p, vPathNodes, pPars->Ratio, pPars->Notches, i, pPars->DelayGap, (pPars->BypassFreq > 0) );
919
            p->timeSize += Abc_Clock() - clk;
920 921

            // unmark critical path
922
            clk = Abc_Clock();
923 924
            Abc_SclUnmarkCriticalNodeWindow( p, vPathNodes );
            Abc_SclUnmarkCriticalNodeWindow( p, vPathPos );
925
            p->timeCone += Abc_Clock() - clk;
926 927 928 929 930 931 932
            if ( nUpsizes > 0 )
                break;
            Vec_IntFree( vPathPos );
            Vec_IntFree( vPathNodes );
        }
        if ( nUpsizes == 0 )
            break;
933

934
        // update timing information
935
        clk = Abc_Clock();
936 937
        if ( pPars->fUseDept )
        {
938
            if ( Vec_IntSize(p->vChanged) && !(pPars->BypassFreq && i && (i % pPars->BypassFreq) == 0) )
939
                nConeSize = Abc_SclTimeIncUpdate( p );
940 941
            else
                Abc_SclTimeNtkRecompute( p, NULL, NULL, pPars->fUseDept, 0 );
942 943 944
        }
        else
        {
945
            Vec_Int_t * vTFO = Abc_SclFindTFO( p->pNtk, vPathNodes );
946
            Abc_SclTimeCone( p, vTFO );
947 948
            nConeSize = Vec_IntSize( vTFO );
            Vec_IntFree( vTFO );
949
        }
950
        p->timeTime += Abc_Clock() - clk;
951 952 953
//        Abc_SclUpsizePrintDiffs( p, pLib, pNtk );

        // save the best network
954
        p->MaxDelay = Abc_SclReadMaxDelay( p );
955 956 957
        if ( p->BestDelay > p->MaxDelay )
        {
            p->BestDelay = p->MaxDelay;
958
            Abc_SclApplyUpdateToBest( p->vGatesBest, p->pNtk->vGates, p->vUpdates );
959
            Vec_IntClear( p->vUpdates2 );
960
            nFramesNoChange = 0;
961
        }
962 963
        else
            nFramesNoChange++;
964

965
        // report and cleanup
966
        Abc_SclUpsizePrint( p, i, win, Vec_IntSize(vPathPos), Vec_IntSize(vPathNodes), nUpsizes, nConeSize, pPars->fVeryVerbose || (pPars->fVerbose && nFramesNoChange == 0) ); //|| (i == nIters-1) );
967 968
        nAllPos     += Vec_IntSize(vPathPos);
        nAllNodes   += Vec_IntSize(vPathNodes);
969
        nAllTfos    += nConeSize;
970
        nAllUpsizes += nUpsizes;
971 972
        Vec_IntFree( vPathPos );
        Vec_IntFree( vPathNodes );
973
        // check timeout
974
        if ( nRuntimeLimit && Abc_Clock() > nRuntimeLimit )
975
            break;
976 977 978 979
        // check no change
        if ( nFramesNoChange > pPars->nIterNoChange )
            break;
        // check best delay
980
        if ( p->BestDelay <= pPars->DelayUser )
981
            break;
982
    }
983
    // update for best gates and recompute timing
984
    ABC_SWAP( Vec_Int_t *, p->vGatesBest, p->pNtk->vGates );
985 986 987 988
    if ( pPars->BypassFreq != 0 )
        Abc_SclUndoRecentChanges( p->pNtk, p->vUpdates2 );
    if ( pPars->BypassFreq != 0 )
        Abc_SclUpsizeRemoveDangling( p, pNtk );
989
    Abc_SclTimeNtkRecompute( p, &p->SumArea, &p->MaxDelay, 0, 0 );
990 991
    if ( pPars->fVerbose )
        Abc_SclUpsizePrint( p, i, pPars->Window, nAllPos/(i?i:1), nAllNodes/(i?i:1), nAllUpsizes/(i?i:1), nAllTfos/(i?i:1), 1 );
992
    else
993
        printf( "                                                                                                                                                  \r" );
994
    // report runtime
995
    p->timeTotal = Abc_Clock() - p->timeTotal;
996
    if ( pPars->fVerbose )
997 998 999 1000 1001 1002 1003 1004
    {
        p->timeOther = p->timeTotal - p->timeCone - p->timeSize - p->timeTime;
        ABC_PRTP( "Runtime: Critical path", p->timeCone,  p->timeTotal );
        ABC_PRTP( "Runtime: Sizing eval  ", p->timeSize,  p->timeTotal );
        ABC_PRTP( "Runtime: Timing update", p->timeTime,  p->timeTotal );
        ABC_PRTP( "Runtime: Other        ", p->timeOther, p->timeTotal );
        ABC_PRTP( "Runtime: TOTAL        ", p->timeTotal, p->timeTotal );
    }
1005
    if ( pPars->fDumpStats )
1006
        Abc_SclDumpStats( p, "stats2.txt", p->timeTotal );
1007
    if ( nRuntimeLimit && Abc_Clock() > nRuntimeLimit )
1008
        printf( "Gate sizing timed out at %d seconds.\n", pPars->TimeOut );
1009 1010

    // save the result and quit
1011
    Abc_SclSclGates2MioGates( pLib, pNtk ); // updates gate pointers
1012
    Abc_SclManFree( p );
1013
//    Abc_NtkCleanMarkAB( pNtk );
1014 1015 1016 1017 1018 1019 1020 1021 1022
}

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


ABC_NAMESPACE_IMPL_END