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

  FileName    [sclBufSize.c]

  SystemName  [ABC: Logic synthesis and verification system.]

  PackageName [Standard-cell library representation.]

  Synopsis    [Buffering and sizing combined.]

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

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

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

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

#include "sclSize.h"
#include "map/mio/mio.h"
23
#include "base/main/main.h"
24 25 26 27 28 29 30 31 32 33 34 35

ABC_NAMESPACE_IMPL_START


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

typedef struct Bus_Man_t_ Bus_Man_t;
struct Bus_Man_t_
{
    // user data
36 37
    SC_BusPars *   pPars;      // parameters    
    Abc_Ntk_t *    pNtk;       // user's network
38
    SC_Cell *      pPiDrive;   // PI driver
39
    // library
40 41 42 43
    SC_Lib *       pLib;       // cell library
    SC_Cell *      pInv;       // base interter (largest/average/???)
    SC_WireLoad *  pWLoadUsed; // name of the used WireLoad model
    Vec_Flt_t *    vWireCaps;  // estimated wire loads
44
    // internal
45
    Vec_Flt_t *    vCins;      // input cap for fanouts
46
    Vec_Flt_t *    vETimes;    // fanout edge departures
47 48
    Vec_Flt_t *    vLoads;     // loads for all nodes
    Vec_Flt_t *    vDepts;     // departure times
49
    Vec_Ptr_t *    vFanouts;   // fanout array
50 51 52 53 54
};


static inline Bus_Man_t * Bus_SclObjMan( Abc_Obj_t * p )                     { return (Bus_Man_t *)p->pNtk->pBSMan;                                  }
static inline float       Bus_SclObjCin( Abc_Obj_t * p )                     { return Vec_FltEntry( Bus_SclObjMan(p)->vCins, Abc_ObjId(p) );         }
55
static inline void        Bus_SclObjSetCin( Abc_Obj_t * p, float cap )       { Vec_FltWriteEntry( Bus_SclObjMan(p)->vCins, Abc_ObjId(p), cap );      }
56 57
static inline float       Bus_SclObjETime( Abc_Obj_t * p )                   { return Vec_FltEntry( Bus_SclObjMan(p)->vETimes, Abc_ObjId(p) );       }
static inline void        Bus_SclObjSetETime( Abc_Obj_t * p, float time )    { Vec_FltWriteEntry( Bus_SclObjMan(p)->vETimes, Abc_ObjId(p), time );   }
58
static inline float       Bus_SclObjLoad( Abc_Obj_t * p )                    { return Vec_FltEntry( Bus_SclObjMan(p)->vLoads, Abc_ObjId(p) );        }
59
static inline void        Bus_SclObjSetLoad( Abc_Obj_t * p, float cap )      { Vec_FltWriteEntry( Bus_SclObjMan(p)->vLoads, Abc_ObjId(p), cap );     }
60
static inline float       Bus_SclObjDept( Abc_Obj_t * p )                    { return Vec_FltEntry( Bus_SclObjMan(p)->vDepts, Abc_ObjId(p) );        }
61
static inline void        Bus_SclObjUpdateDept( Abc_Obj_t * p, float time )  { float *q = Vec_FltEntryP( Bus_SclObjMan(p)->vDepts, Abc_ObjId(p) ); if (*q < time) *q = time;  }
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77

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

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

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
78
Bus_Man_t * Bus_ManStart( Abc_Ntk_t * pNtk, SC_Lib * pLib, SC_BusPars * pPars )
79 80 81
{
    Bus_Man_t * p;
    p = ABC_CALLOC( Bus_Man_t, 1 );
82
    p->pPars     = pPars;
83 84
    p->pNtk      = pNtk;
    p->pLib      = pLib;
85
    p->pInv      = Abc_SclFindInvertor(pLib, pPars->fAddBufs)->pRepr->pPrev;//->pAve;
86
    if ( pPars->fUseWireLoads )
87
    { 
88 89 90 91 92 93 94 95
        if ( pNtk->pWLoadUsed == NULL )
        {            
            p->pWLoadUsed = Abc_SclFindWireLoadModel( pLib, Abc_SclGetTotalArea(pNtk) );
            pNtk->pWLoadUsed = Abc_UtilStrsav( p->pWLoadUsed->pName );
        }
        else
            p->pWLoadUsed = Abc_SclFetchWireLoadModel( pLib, pNtk->pWLoadUsed );
    }
96
    if ( p->pWLoadUsed )
97
    p->vWireCaps = Abc_SclFindWireCaps( p->pWLoadUsed );
98
    p->vFanouts  = Vec_PtrAlloc( 100 );
99 100 101 102 103 104 105 106
    p->vCins     = Vec_FltAlloc( 2*Abc_NtkObjNumMax(pNtk) + 1000 );
    p->vETimes   = Vec_FltAlloc( 2*Abc_NtkObjNumMax(pNtk) + 1000 );
    p->vLoads    = Vec_FltAlloc( 2*Abc_NtkObjNumMax(pNtk) + 1000 );
    p->vDepts    = Vec_FltAlloc( 2*Abc_NtkObjNumMax(pNtk) + 1000 );
    Vec_FltFill( p->vCins,   Abc_NtkObjNumMax(pNtk), 0 );
    Vec_FltFill( p->vETimes, Abc_NtkObjNumMax(pNtk), 0 );
    Vec_FltFill( p->vLoads,  Abc_NtkObjNumMax(pNtk), 0 );
    Vec_FltFill( p->vDepts,  Abc_NtkObjNumMax(pNtk), 0 );
107 108 109 110 111
    pNtk->pBSMan = p;
    return p;
}
void Bus_ManStop( Bus_Man_t * p )
{
112 113 114 115 116 117
    Vec_PtrFreeP( &p->vFanouts );
    Vec_FltFreeP( &p->vWireCaps );
    Vec_FltFreeP( &p->vCins );
    Vec_FltFreeP( &p->vETimes );
    Vec_FltFreeP( &p->vLoads );
    Vec_FltFreeP( &p->vDepts );
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
    ABC_FREE( p );
}

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

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
void Bus_ManReadInOutLoads( Bus_Man_t * p )
{
134
    if ( Abc_FrameReadMaxLoad() )
135
    {
136 137
        Abc_Obj_t * pObj; int i;
        float MaxLoad = Abc_FrameReadMaxLoad();
138
        Abc_NtkForEachCo( p->pNtk, pObj, i )
139
            Bus_SclObjSetCin( pObj, MaxLoad );
140
//        printf( "Default output load is specified (%f ff).\n", MaxLoad );
141
    }
142
    if ( Abc_FrameReadDrivingCell() )
143
    {
144 145 146 147
        int iCell = Abc_SclCellFind( p->pLib, Abc_FrameReadDrivingCell() );
        if ( iCell == -1 )
            printf( "Cannot find the default PI driving cell (%s) in the library.\n", Abc_FrameReadDrivingCell() );
        else
148
        {
149 150 151 152
//            printf( "Default PI driving cell is specified (%s).\n", Abc_FrameReadDrivingCell() );
            p->pPiDrive = SC_LibCell( p->pLib, iCell );
            assert( p->pPiDrive != NULL );
            assert( p->pPiDrive->n_inputs == 1 );
153
//            printf( "Default input driving cell is specified (%s).\n", p->pPiDrive->pName );
154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
        }
    }
}

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

  Synopsis    [Compute load and departure times of the node.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
static inline float Abc_NtkComputeEdgeDept( Abc_Obj_t * pFanout, int iFanin, float Slew )
{
    float Load = Bus_SclObjLoad( pFanout );
    float Dept = Bus_SclObjDept( pFanout );
    float Edge = Scl_LibPinArrivalEstimate( Abc_SclObjCell(pFanout), iFanin, Slew, Load );
//if ( Abc_ObjFaninNum(pFanout) == 0 )
//printf( "Edge = %.2f\n", Edge );
    assert( Edge > 0 );
    return Dept + Edge;
}
float Abc_NtkComputeNodeDeparture( Abc_Obj_t * pObj, float Slew )
{
    Abc_Obj_t * pFanout;
    int i;
    assert( Bus_SclObjDept(pObj) == 0 );
    Abc_ObjForEachFanout( pObj, pFanout, i )
        if ( !Abc_ObjIsCo(pFanout) ) // add required times here
            Bus_SclObjUpdateDept( pObj, Abc_NtkComputeEdgeDept(pFanout, Abc_NodeFindFanin(pFanout, pObj), Slew) );
    return Bus_SclObjDept( pObj );
}
void Abc_NtkComputeFanoutInfo( Abc_Obj_t * pObj, float Slew )
190 191 192 193
{
    Abc_Obj_t * pFanout;
    int i;
    Abc_ObjForEachFanout( pObj, pFanout, i )
194
        if ( !Abc_ObjIsCo(pFanout) )
195
        {
196
            int iFanin = Abc_NodeFindFanin(pFanout, pObj);
197 198
            Bus_SclObjSetETime( pFanout, Abc_NtkComputeEdgeDept(pFanout, iFanin, Slew) );
            Bus_SclObjSetCin( pFanout, SC_CellPinCap( Abc_SclObjCell(pFanout), iFanin ) );
199
        }
200
}
201
float Abc_NtkComputeNodeLoad( Bus_Man_t * p, Abc_Obj_t * pObj )
202 203
{
    Abc_Obj_t * pFanout;
204
    float Load;
205 206
    int i;
    assert( Bus_SclObjLoad(pObj) == 0 );
207
    Load = Abc_SclFindWireLoad( p->vWireCaps, Abc_ObjFanoutNum(pObj) );
208 209 210 211 212
    Abc_ObjForEachFanout( pObj, pFanout, i )
        Load += Bus_SclObjCin( pFanout );
    Bus_SclObjSetLoad( pObj, Load );
    return Load;
}
213
float Abc_NtkComputeFanoutLoad( Bus_Man_t * p, Vec_Ptr_t * vFanouts )
214 215
{
    Abc_Obj_t * pFanout;
216
    float Load;
217
    int i;
218 219 220 221 222 223 224 225 226
    Load = Abc_SclFindWireLoad( p->vWireCaps, Vec_PtrSize(vFanouts) );
    Vec_PtrForEachEntry( Abc_Obj_t *, vFanouts, pFanout, i )
        Load += Bus_SclObjCin( pFanout );
    return Load;
}
void Abc_NtkPrintFanoutProfile( Abc_Obj_t * pObj )
{
    Abc_Obj_t * pFanout;
    int i;
227
    printf( "Obj %6d fanouts (%d):\n", Abc_ObjId(pObj), Abc_ObjFanoutNum(pObj) );
228
    Abc_ObjForEachFanout( pObj, pFanout, i )
229 230 231 232
    {
        printf( "%3d : time = %7.2f ps   load = %7.2f ff  ", i, Bus_SclObjETime(pFanout), Bus_SclObjCin(pFanout) );
        printf( "%s\n", Abc_ObjFaninPhase( pFanout, Abc_NodeFindFanin(pFanout, pObj) ) ? "*" : " " );
    }
233 234
    printf( "\n" );
}
235
void Abc_NtkPrintFanoutProfileVec( Abc_Obj_t * pObj, Vec_Ptr_t * vFanouts )
236 237 238 239 240
{
    Abc_Obj_t * pFanout;
    int i;
    printf( "Fanout profile (%d):\n", Vec_PtrSize(vFanouts) );
    Vec_PtrForEachEntry( Abc_Obj_t *, vFanouts, pFanout, i )
241 242
    {
        printf( "%3d : time = %7.2f ps   load = %7.2f ff  ", i, Bus_SclObjETime(pFanout), Bus_SclObjCin(pFanout) );
243 244 245
        if ( pObj->pNtk->vPhases )
            printf( "%s", (pObj && Abc_ObjFanoutNum(pObj) == Vec_PtrSize(vFanouts) && Abc_ObjFaninPhase( pFanout, Abc_NodeFindFanin(pFanout, pObj) )) ? "*" : " " );
        printf( "\n" );
246 247
    }
    printf( "\n" );
248 249 250 251 252 253 254 255 256 257 258 259 260 261 262
}

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

  Synopsis    [Compare two fanouts by their departure times.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
int Bus_SclCompareFanouts( Abc_Obj_t ** pp1, Abc_Obj_t ** pp2 )
{
263 264
    float Espilon = 0;//10; // 10 ps
    if ( Bus_SclObjETime(*pp1) < Bus_SclObjETime(*pp2) - Espilon )
265
        return -1;
266
    if ( Bus_SclObjETime(*pp1) > Bus_SclObjETime(*pp2) + Espilon )
267
        return 1;
268
    if ( Bus_SclObjCin(*pp1) > Bus_SclObjCin(*pp2) )
269
        return -1;
270
    if ( Bus_SclObjCin(*pp1) < Bus_SclObjCin(*pp2) )
271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293
        return 1;
    return -1;
}
void Bus_SclInsertFanout( Vec_Ptr_t * vFanouts, Abc_Obj_t * pObj )
{
    Abc_Obj_t * pCur;
    int i, k;
    // compact array
    for ( i = k = 0; i < Vec_PtrSize(vFanouts); i++ )
        if ( Vec_PtrEntry(vFanouts, i) != NULL )
            Vec_PtrWriteEntry( vFanouts, k++, Vec_PtrEntry(vFanouts, i) );
    Vec_PtrShrink( vFanouts, k );
    // insert new entry
    Vec_PtrPush( vFanouts, pObj );
    for ( i = Vec_PtrSize(vFanouts) - 1; i > 0; i-- )
    {
        pCur = (Abc_Obj_t *)Vec_PtrEntry(vFanouts, i-1);
        pObj = (Abc_Obj_t *)Vec_PtrEntry(vFanouts, i);
        if ( Bus_SclCompareFanouts( &pCur, &pObj ) == -1 )
            break;
        ABC_SWAP( void *, Vec_PtrArray(vFanouts)[i-1], Vec_PtrArray(vFanouts)[i] );
    }
}
294 295 296 297 298 299 300 301 302 303 304
void Bus_SclCheckSortedFanout( Vec_Ptr_t * vFanouts )
{
    Abc_Obj_t * pObj, * pNext;
    int i;
    for ( i = 0; i < Vec_PtrSize(vFanouts) - 1; i++ )
    {
        pObj  = (Abc_Obj_t *)Vec_PtrEntry(vFanouts, i);
        pNext = (Abc_Obj_t *)Vec_PtrEntry(vFanouts, i+1);
        if ( Bus_SclCompareFanouts( &pObj, &pNext ) != -1 )
        {
            printf( "Fanouts %d and %d are out of order.\n", i, i+1 );
305
            Abc_NtkPrintFanoutProfileVec( NULL, vFanouts );
306 307 308 309
            return;
        }
    }
}
310 311 312 313 314 315 316 317 318 319 320 321

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

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
322 323 324 325 326 327 328 329
void Abc_SclOneNodePrint( Bus_Man_t * p, Abc_Obj_t * pObj )
{
    SC_Cell * pCell = Abc_SclObjCell(pObj);
    printf( "%s%7d :  ",        (Abc_ObjFaninNum(pObj) == 0) ? " Inv" : "Node", Abc_ObjId(pObj) );
    printf( "%d/%2d   ",        Abc_ObjFaninNum(pObj) ? Abc_ObjFaninNum(pObj) : 1, Abc_ObjFanoutNum(pObj) );
    printf( "%12s ",            pCell->pName );
    printf( "(%2d/%2d)  ",      pCell->Order, pCell->nGates );
    printf( "gain =%5d  ",      (int)(100.0 * Bus_SclObjLoad(pObj) / SC_CellPinCapAve(pCell)) );
330
    printf( "dept =%7.0f ps  ", Bus_SclObjDept(pObj) );
331 332 333
    printf( "\n" );
}
Abc_Obj_t * Abc_SclAddOneInv( Bus_Man_t * p, Abc_Obj_t * pObj, Vec_Ptr_t * vFanouts, float Gain )
334 335 336
{
    SC_Cell * pCellNew;
    Abc_Obj_t * pFanout, * pInv;
337
    float Target = SC_CellPinCap(p->pInv, 0) * Gain;
338 339
    float LoadWirePrev, LoadWireThis, LoadNew, Load = 0;
    int Limit = Abc_MinInt( p->pPars->nDegree, Vec_PtrSize(vFanouts) );
340
    int i, iStop;
341 342
    Bus_SclCheckSortedFanout( vFanouts );
    Vec_PtrForEachEntryStop( Abc_Obj_t *, vFanouts, pFanout, iStop, Limit )
343
    {
344 345
        LoadWirePrev = Abc_SclFindWireLoad( p->vWireCaps, iStop );
        LoadWireThis = Abc_SclFindWireLoad( p->vWireCaps, iStop+1 );
346
        Load += Bus_SclObjCin( pFanout ) - LoadWirePrev + LoadWireThis;
347
        if ( Load > Target )
348 349
        {
            iStop++;
350
            break;
351
        }
352 353
    }
    // create inverter
354
    if ( p->pPars->fAddBufs )
355 356 357
        pInv = Abc_NtkCreateNodeBuf( p->pNtk, NULL );
    else
        pInv = Abc_NtkCreateNodeInv( p->pNtk, NULL );
358 359 360 361 362 363
    assert( (int)Abc_ObjId(pInv) == Vec_FltSize(p->vCins) );
    Vec_FltPush( p->vCins,   0 );
    Vec_FltPush( p->vETimes, 0 );
    Vec_FltPush( p->vLoads,  0 );
    Vec_FltPush( p->vDepts,  0 );
    Limit = Abc_MinInt( Abc_MaxInt(iStop, 2), Vec_PtrSize(vFanouts) );
364
    Vec_PtrForEachEntryStop( Abc_Obj_t *, vFanouts, pFanout, i, Limit )
365 366
    {
        Vec_PtrWriteEntry( vFanouts, i, NULL );
367
        if ( Abc_ObjFaninNum(pFanout) == 0 )
368 369 370 371 372 373 374
            Abc_ObjAddFanin( pFanout, pInv );
        else
            Abc_ObjPatchFanin( pFanout, pObj, pInv );
    }
    // set the gate
    pCellNew = Abc_SclFindSmallestGate( p->pInv, Load / Gain );
    Vec_IntSetEntry( p->pNtk->vGates, Abc_ObjId(pInv), pCellNew->Id );
375 376 377 378 379
    // set departure and load
    Abc_NtkComputeNodeDeparture( pInv, p->pPars->Slew );
    LoadNew = Abc_NtkComputeNodeLoad( p, pInv );
    assert( LoadNew - Load < 1 && Load - LoadNew < 1 );
    // set fanout info for the inverter
380
    Bus_SclObjSetCin( pInv, SC_CellPinCap(pCellNew, 0) );
381
    Bus_SclObjSetETime( pInv, Abc_NtkComputeEdgeDept(pInv, 0, p->pPars->Slew) );
382 383 384 385 386 387 388 389
    // update phases
    if ( p->pNtk->vPhases && Abc_SclIsInv(pInv) )
        Abc_NodeInvUpdateFanPolarity( pInv );
    return pInv;
}
void Abc_SclBufSize( Bus_Man_t * p )
{
    SC_Cell * pCell, * pCellNew;
390
    Abc_Obj_t * pObj, * pFanout;
391
    abctime clk = Abc_Clock();
392
    int nObjsOld = Abc_NtkObjNumMax(p->pNtk);
393 394 395 396
    float GainInv = 0.01 * p->pPars->GainRatio;
    float GainGate = (float)1.0 * GainInv;
    float Load, LoadNew, Cin, DeptMax = 0;
    int i, k, nObjOld = Abc_NtkObjNumMax(p->pNtk);
397
    Abc_NtkForEachObjReverse( p->pNtk, pObj, i )
398
    {
399 400
        if ( !((Abc_ObjIsNode(pObj) && Abc_ObjFaninNum(pObj) > 0) || (Abc_ObjIsCi(pObj) && p->pPiDrive)) )
            continue;
401 402 403 404 405
        if ( 2 * nObjsOld < Abc_NtkObjNumMax(p->pNtk) )
        {
            printf( "Buffering could not be completed because the gain value (%d) is too low.\n", p->pPars->GainRatio );
            break;
        }
406
        // compute load
407
        Abc_NtkComputeFanoutInfo( pObj, p->pPars->Slew );
408
        Load = Abc_NtkComputeNodeLoad( p, pObj );
409
        // consider the gate
410 411 412 413 414 415 416 417 418
        if ( Abc_ObjIsCi(pObj) )
        {
            pCell = p->pPiDrive;
            Cin = SC_CellPinCapAve( pCell );
        }
        else
        {
            pCell = Abc_SclObjCell( pObj );
            Cin = SC_CellPinCapAve( pCell->pAve );
419
//        Cin = SC_CellPinCapAve( pCell->pRepr->pNext );
420
        }
421
        // consider upsizing the gate
422
        if ( !p->pPars->fSizeOnly && (Abc_ObjFanoutNum(pObj) > p->pPars->nDegree || Load > GainGate * Cin) )
423 424
        {
            // add one or more inverters
425
//            Abc_NtkPrintFanoutProfile( pObj );
426 427
            Abc_NodeCollectFanouts( pObj, p->vFanouts );
            Vec_PtrSort( p->vFanouts, (int(*)(void))Bus_SclCompareFanouts );
428 429
            do 
            {
430
                Abc_Obj_t * pInv;
431 432
                if ( p->pPars->fVeryVerbose )//|| Vec_PtrSize(p->vFanouts) == Abc_ObjFanoutNum(pObj) )
                    Abc_NtkPrintFanoutProfileVec( pObj, p->vFanouts );
433 434 435 436 437
                pInv = Abc_SclAddOneInv( p, pObj, p->vFanouts, GainInv );
                if ( p->pPars->fVeryVerbose )
                    Abc_SclOneNodePrint( p, pInv );
                Bus_SclInsertFanout( p->vFanouts, pInv );
                Load = Abc_NtkComputeFanoutLoad( p, p->vFanouts );
438
            }
439
            while ( Vec_PtrSize(p->vFanouts) > p->pPars->nDegree || (Vec_PtrSize(p->vFanouts) > 1 && Load > GainGate * Cin) );
440 441 442 443 444 445 446
            // update node fanouts
            Vec_PtrForEachEntry( Abc_Obj_t *, p->vFanouts, pFanout, k )
                if ( Abc_ObjFaninNum(pFanout) == 0 )
                    Abc_ObjAddFanin( pFanout, pObj );
            Bus_SclObjSetLoad( pObj, 0 );
            LoadNew = Abc_NtkComputeNodeLoad( p, pObj );
            assert( LoadNew - Load < 1 && Load - LoadNew < 1 );
447
        } 
448 449
        if ( Abc_ObjIsCi(pObj) )
            continue;
450
        Abc_NtkComputeNodeDeparture( pObj, p->pPars->Slew );
451
        // create cell
452
        pCellNew = Abc_SclFindSmallestGate( pCell, Load / GainGate );
453
        Abc_SclObjSetCell( pObj, pCellNew );
454 455
        if ( p->pPars->fVeryVerbose )
            Abc_SclOneNodePrint( p, pObj );
456
        assert( p->pPars->fSizeOnly || Abc_ObjFanoutNum(pObj) <= p->pPars->nDegree );
457
    }
458
    // compute departure time of the PI
459
    if ( i < 0 ) // finished buffering
460
    Abc_NtkForEachCi( p->pNtk, pObj, i )
461 462 463 464 465 466 467 468 469 470 471
    {
        float DeptCur = Abc_NtkComputeNodeDeparture(pObj, p->pPars->Slew);
        if ( p->pPiDrive )
        {
            float Load = Bus_SclObjLoad( pObj );
            SC_Pair ArrOut, SlewOut, LoadIn = { Load, Load }; 
            Scl_LibHandleInputDriver( p->pPiDrive, &LoadIn, &ArrOut, &SlewOut );
            DeptCur += 0.5 * ArrOut.fall +  0.5 * ArrOut.rise;
        }       
        DeptMax = Abc_MaxFloat( DeptMax, DeptCur );
    }
472
    if ( p->pPars->fVerbose )
473
    {
474 475
        printf( "WireLoads = %d  Degree = %d  Target slew =%4d ps   Gain2 =%5d  Buf = %6d  Delay =%7.0f ps   ", 
            p->pPars->fUseWireLoads, p->pPars->nDegree, p->pPars->Slew, p->pPars->GainRatio, 
476
            Abc_NtkObjNumMax(p->pNtk) - nObjOld, DeptMax );
477 478
        Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
    }
479
}
480
Abc_Ntk_t * Abc_SclBufferingPerform( Abc_Ntk_t * pNtk, SC_Lib * pLib, SC_BusPars * pPars )
481 482 483 484 485
{
    Abc_Ntk_t * pNtkNew;
    Bus_Man_t * p;
    if ( !Abc_SclCheckNtk( pNtk, 0 ) )
        return NULL;
486 487 488
    // update gain if buffers are used
    if ( pPars->fAddBufs )
        pPars->GainRatio = pPars->GainRatio * pPars->GainRatio / 100;
489
    Abc_SclReportDupFanins( pNtk );
490
    Abc_SclMioGates2SclGates( pLib, pNtk );
491
    p = Bus_ManStart( pNtk, pLib, pPars );
492 493 494
    Bus_ManReadInOutLoads( p );
    Abc_SclBufSize( p );
    Bus_ManStop( p );
495
    Abc_SclSclGates2MioGates( pLib, pNtk );
496 497
    if ( pNtk->vPhases )
        Vec_IntFillExtra( pNtk->vPhases, Abc_NtkObjNumMax(pNtk), 0 );
498 499 500 501 502 503 504 505 506 507 508
    pNtkNew = Abc_NtkDupDfs( pNtk );
    return pNtkNew;
}

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


ABC_NAMESPACE_IMPL_END