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

  FileName    [timMan.c]

  SystemName  [ABC: Logic synthesis and verification system.]

  PackageName [Hierarchy/timing manager.]

  Synopsis    [Manipulation of manager data-structure.]

  Author      [Alan Mishchenko]
  
  Affiliation [UC Berkeley]

  Date        [Ver. 1.0. Started - April 28, 2007.]

  Revision    [$Id: timMan.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]

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

#include "timInt.h"
22
#include "map/if/if.h"
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92

ABC_NAMESPACE_IMPL_START

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

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

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

  Synopsis    [Starts the timing manager.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Tim_Man_t * Tim_ManStart( int nCis, int nCos )
{
    Tim_Man_t * p;
    Tim_Obj_t * pObj;
    int i;
    p = ABC_ALLOC( Tim_Man_t, 1 );
    memset( p, 0, sizeof(Tim_Man_t) );
    p->pMemObj = Mem_FlexStart();
    p->nCis = nCis;
    p->nCos = nCos;
    p->pCis = ABC_ALLOC( Tim_Obj_t, nCis );
    memset( p->pCis, 0, sizeof(Tim_Obj_t) * nCis );
    p->pCos = ABC_ALLOC( Tim_Obj_t, nCos );
    memset( p->pCos, 0, sizeof(Tim_Obj_t) * nCos );
    Tim_ManForEachCi( p, pObj, i )
    {
        pObj->Id = i;
        pObj->iObj2Box = pObj->iObj2Num = -1;
        pObj->timeReq = TIM_ETERNITY;
    }
    Tim_ManForEachCo( p, pObj, i )
    {
        pObj->Id = i;
        pObj->iObj2Box = pObj->iObj2Num = -1;
        pObj->timeReq = TIM_ETERNITY;
    }
    p->fUseTravId = 1;
    return p;
}

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

  Synopsis    [Duplicates the timing manager.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Tim_Man_t * Tim_ManDup( Tim_Man_t * p, int fUnitDelay )
{
    Tim_Man_t * pNew;
    Tim_Box_t * pBox;
    Tim_Obj_t * pObj;
    float * pDelayTable, * pDelayTableNew;
    int i, k, nInputs, nOutputs;
93 94 95 96 97
    // clear traversal IDs
    Tim_ManForEachCi( p, pObj, i ) 
        pObj->TravId = 0;          
    Tim_ManForEachCo( p, pObj, i ) 
        pObj->TravId = 0;          
98 99 100
    // create new manager
    pNew = Tim_ManStart( p->nCis, p->nCos );
    // copy box connectivity information
101 102
    memcpy( pNew->pCis, p->pCis, sizeof(Tim_Obj_t) * p->nCis ); 
    memcpy( pNew->pCos, p->pCos, sizeof(Tim_Obj_t) * p->nCos ); 
103 104 105 106 107 108 109 110 111 112 113 114 115
    if ( fUnitDelay )
    {
        // discretize PI arrival times
//        Tim_ManForEachPi( pNew, pObj, k )
//          pObj->timeArr = (int)pObj->timeArr;
        // discretize PO required times
//        Tim_ManForEachPo( pNew, pObj, k )
//          pObj->timeReq = 1 + (int)pObj->timeReq;
        // clear PI arrival and PO required
        Tim_ManInitPiArrivalAll( p, 0.0 );
        Tim_ManInitPoRequiredAll( p, (float)TIM_ETERNITY );
    }
    // duplicate delay tables
116
    if ( Tim_ManDelayTableNum(p) > 0 )
117
    {
118
        pNew->vDelayTables = Vec_PtrStart( Vec_PtrSize(p->vDelayTables) );
119 120
        Tim_ManForEachTable( p, pDelayTable, i )
        {
121 122
            if ( pDelayTable == NULL )
                continue;
123 124 125 126 127 128 129 130
            assert( i == (int)pDelayTable[0] );
            nInputs   = (int)pDelayTable[1];
            nOutputs  = (int)pDelayTable[2];
            pDelayTableNew = ABC_ALLOC( float, 3 + nInputs * nOutputs );
            pDelayTableNew[0] = (int)pDelayTable[0];
            pDelayTableNew[1] = (int)pDelayTable[1];
            pDelayTableNew[2] = (int)pDelayTable[2];
            for ( k = 0; k < nInputs * nOutputs; k++ )
131 132 133 134
                if ( pDelayTable[3+k] == -ABC_INFINITY )
                    pDelayTableNew[3+k] = -ABC_INFINITY;
                else
                    pDelayTableNew[3+k] = fUnitDelay ? (float)fUnitDelay : pDelayTable[3+k];
135 136 137
//            assert( (int)pDelayTableNew[0] == Vec_PtrSize(pNew->vDelayTables) );
            assert( Vec_PtrEntry(pNew->vDelayTables, i) == NULL );
            Vec_PtrWriteEntry( pNew->vDelayTables, i, pDelayTableNew );
138
//printf( "Finished duplicating delay table %d.\n", i );
139
        }
140 141
    }
    // duplicate boxes
142 143 144 145
    if ( Tim_ManBoxNum(p) > 0 )
    {
        pNew->vBoxes = Vec_PtrAlloc( Tim_ManBoxNum(p) );
        Tim_ManForEachBox( p, pBox, i )
146
        {
147
           Tim_ManCreateBox( pNew, pBox->Inouts[0], pBox->nInputs, 
148
                pBox->Inouts[pBox->nInputs], pBox->nOutputs, pBox->iDelayTable, pBox->fBlack );
149 150
           Tim_ManBoxSetCopy( pNew, i, pBox->iCopy );
        }
151
    }
152 153 154 155 156
    return pNew;
}

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

157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
  Synopsis    [Trims the timing manager.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Tim_Man_t * Tim_ManTrim( Tim_Man_t * p, Vec_Int_t * vBoxPres )
{
    Tim_Man_t * pNew;
    Tim_Box_t * pBox;
    Tim_Obj_t * pObj;
    float * pDelayTable, * pDelayTableNew;
172
    int i, k, nNewCis, nNewCos, nInputs, nOutputs;
173
    assert( Vec_IntSize(vBoxPres) == Tim_ManBoxNum(p) );
174 175 176
    // count the number of CIs and COs in the trimmed manager
    nNewCis = Tim_ManPiNum(p);
    nNewCos = Tim_ManPoNum(p);
177 178 179 180 181 182 183
    if ( Tim_ManBoxNum(p) )
        Tim_ManForEachBox( p, pBox, i )
            if ( Vec_IntEntry(vBoxPres, i) )
            {
                nNewCis += pBox->nOutputs;
                nNewCos += pBox->nInputs;
            }
184
    if ( nNewCis == Tim_ManCiNum(p) && nNewCos == Tim_ManCoNum(p) )
185
        return Tim_ManDup( p, 0 );
186 187 188 189 190 191 192
    assert( nNewCis < Tim_ManCiNum(p) );
    assert( nNewCos < Tim_ManCoNum(p) );
    // clear traversal IDs
    Tim_ManForEachCi( p, pObj, i ) 
        pObj->TravId = 0;          
    Tim_ManForEachCo( p, pObj, i ) 
        pObj->TravId = 0;          
193
    // create new manager
194
    pNew = Tim_ManStart( nNewCis, nNewCos );
195
    // copy box connectivity information
196
    memcpy( pNew->pCis, p->pCis, sizeof(Tim_Obj_t) * Tim_ManPiNum(p) );
197 198 199
    memcpy( pNew->pCos + nNewCos - Tim_ManPoNum(p), 
            p->pCos + Tim_ManCoNum(p) - Tim_ManPoNum(p), 
            sizeof(Tim_Obj_t) * Tim_ManPoNum(p) );
200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224
    // duplicate delay tables
    if ( Tim_ManDelayTableNum(p) > 0 )
    {
        pNew->vDelayTables = Vec_PtrStart( Vec_PtrSize(p->vDelayTables) );
        Tim_ManForEachTable( p, pDelayTable, i )
        {
            if ( pDelayTable == NULL )
                continue;
            assert( i == (int)pDelayTable[0] );
            nInputs   = (int)pDelayTable[1];
            nOutputs  = (int)pDelayTable[2];
            pDelayTableNew = ABC_ALLOC( float, 3 + nInputs * nOutputs );
            pDelayTableNew[0] = (int)pDelayTable[0];
            pDelayTableNew[1] = (int)pDelayTable[1];
            pDelayTableNew[2] = (int)pDelayTable[2];
            for ( k = 0; k < nInputs * nOutputs; k++ )
                pDelayTableNew[3+k] = pDelayTable[3+k];
//            assert( (int)pDelayTableNew[0] == Vec_PtrSize(pNew->vDelayTables) );
            assert( Vec_PtrEntry(pNew->vDelayTables, i) == NULL );
            Vec_PtrWriteEntry( pNew->vDelayTables, i, pDelayTableNew );
        }
    }
    // duplicate boxes
    if ( Tim_ManBoxNum(p) > 0 )
    {
225 226
        int curPi = Tim_ManPiNum(p);
        int curPo = 0;
227 228 229
        pNew->vBoxes = Vec_PtrAlloc( Tim_ManBoxNum(p) );
        Tim_ManForEachBox( p, pBox, i )
            if ( Vec_IntEntry(vBoxPres, i) )
230
            {
231
                Tim_ManCreateBox( pNew, curPo, pBox->nInputs, curPi, pBox->nOutputs, pBox->iDelayTable, pBox->fBlack );
232
                Tim_ManBoxSetCopy( pNew, Tim_ManBoxNum(pNew) - 1, Tim_ManBoxCopy(p, i) == -1 ? i : Tim_ManBoxCopy(p, i) );
233 234 235 236 237 238
                curPi += pBox->nOutputs;
                curPo += pBox->nInputs;
            }
        curPo += Tim_ManPoNum(p);
        assert( curPi == Tim_ManCiNum(pNew) );
        assert( curPo == Tim_ManCoNum(pNew) );
239 240 241 242 243 244
    }
    return pNew;
}

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

245
  Synopsis    [Reduces the timing manager.]
246 247 248 249 250 251 252 253

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
254
Tim_Man_t * Tim_ManReduce( Tim_Man_t * p, Vec_Int_t * vBoxesLeft, int nTermsDiff )
255 256 257 258 259 260
{
    Tim_Man_t * pNew;
    Tim_Box_t * pBox;
    Tim_Obj_t * pObj;
    float * pDelayTable, * pDelayTableNew;
    int i, k, iBox, nNewCis, nNewCos, nInputs, nOutputs;
261 262
    int nNewPiNum = Tim_ManPiNum(p) - nTermsDiff;
    int nNewPoNum = Tim_ManPoNum(p) - nTermsDiff;
263
    assert( Vec_IntSize(vBoxesLeft) <= Tim_ManBoxNum(p) );
264
    // count the number of CIs and COs in the trimmed manager
265 266
    nNewCis = nNewPiNum;
    nNewCos = nNewPoNum;
267 268 269 270 271 272
    Vec_IntForEachEntry( vBoxesLeft, iBox, i )
    {
        pBox = Tim_ManBox( p, iBox );
        nNewCis += pBox->nOutputs;
        nNewCos += pBox->nInputs;
    }
273 274
    assert( nNewCis <= Tim_ManCiNum(p) - nTermsDiff );
    assert( nNewCos <= Tim_ManCoNum(p) - nTermsDiff );
275 276 277 278 279 280 281 282
    // clear traversal IDs
    Tim_ManForEachCi( p, pObj, i ) 
        pObj->TravId = 0;          
    Tim_ManForEachCo( p, pObj, i ) 
        pObj->TravId = 0;          
    // create new manager
    pNew = Tim_ManStart( nNewCis, nNewCos );
    // copy box connectivity information
283 284
    memcpy( pNew->pCis, p->pCis, sizeof(Tim_Obj_t) * nNewPiNum );
    memcpy( pNew->pCos + nNewCos - nNewPoNum, 
285
            p->pCos + Tim_ManCoNum(p) - Tim_ManPoNum(p), 
286
            sizeof(Tim_Obj_t) * nNewPoNum );
287 288 289
    // duplicate delay tables
    if ( Tim_ManDelayTableNum(p) > 0 )
    {
290
        int fWarning = 0;
291 292 293 294 295
        pNew->vDelayTables = Vec_PtrStart( Vec_PtrSize(p->vDelayTables) );
        Tim_ManForEachTable( p, pDelayTable, i )
        {
            if ( pDelayTable == NULL )
                continue;
296 297 298 299 300 301
            if ( i != (int)pDelayTable[0] && fWarning == 0 )
            {
                printf( "Warning: Mismatch in delay-table number between the manager and the box.\n" );
                fWarning = 1;
            }
            //assert( i == (int)pDelayTable[0] );
302 303 304
            nInputs   = (int)pDelayTable[1];
            nOutputs  = (int)pDelayTable[2];
            pDelayTableNew = ABC_ALLOC( float, 3 + nInputs * nOutputs );
305
            pDelayTableNew[0] = i;//(int)pDelayTable[0];
306 307 308 309 310 311 312 313 314 315 316 317
            pDelayTableNew[1] = (int)pDelayTable[1];
            pDelayTableNew[2] = (int)pDelayTable[2];
            for ( k = 0; k < nInputs * nOutputs; k++ )
                pDelayTableNew[3+k] = pDelayTable[3+k];
//            assert( (int)pDelayTableNew[0] == Vec_PtrSize(pNew->vDelayTables) );
            assert( Vec_PtrEntry(pNew->vDelayTables, i) == NULL );
            Vec_PtrWriteEntry( pNew->vDelayTables, i, pDelayTableNew );
        }
    }
    // duplicate boxes
    if ( Tim_ManBoxNum(p) > 0 )
    {
318
        int curPi = nNewPiNum;
319 320 321 322 323
        int curPo = 0;
        pNew->vBoxes = Vec_PtrAlloc( Tim_ManBoxNum(p) );
        Vec_IntForEachEntry( vBoxesLeft, iBox, i )
        {
            pBox = Tim_ManBox( p, iBox );
324
            Tim_ManCreateBox( pNew, curPo, pBox->nInputs, curPi, pBox->nOutputs, pBox->iDelayTable, pBox->fBlack );
325
            Tim_ManBoxSetCopy( pNew, Tim_ManBoxNum(pNew) - 1, Tim_ManBoxCopy(p, iBox) == -1 ? iBox : Tim_ManBoxCopy(p, iBox) );
326 327 328
            curPi += pBox->nOutputs;
            curPo += pBox->nInputs;
        }
329
        curPo += nNewPoNum;
330 331
        assert( curPi == Tim_ManCiNum(pNew) );
        assert( curPo == Tim_ManCoNum(pNew) );
332 333 334 335
    }
    return pNew;
}

336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365
/**Function*************************************************************

  Synopsis    [Aligns two sets of boxes using the copy field.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Vec_Int_t * Tim_ManAlignTwo( Tim_Man_t * pSpec, Tim_Man_t * pImpl )
{
    Vec_Int_t * vBoxPres;
    Tim_Box_t * pBox;
    int i;
    assert( Tim_ManBoxNum(pSpec) > Tim_ManBoxNum(pImpl) );
    // check if boxes of pImpl can be aligned
    Tim_ManForEachBox( pImpl, pBox, i )
        if ( pBox->iCopy < 0 || pBox->iCopy >= Tim_ManBoxNum(pSpec) ) 
            return NULL;
    // map dropped boxes into 1, others into 0
    vBoxPres = Vec_IntStart( Tim_ManBoxNum(pSpec) );
    Tim_ManForEachBox( pImpl, pBox, i )
    {
        assert( !Vec_IntEntry(vBoxPres, pBox->iCopy) );
        Vec_IntWriteEntry( vBoxPres, pBox->iCopy, 1 );
    }
    return vBoxPres;
}
366 367 368

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

369 370 371 372 373 374 375 376 377 378 379
  Synopsis    [Stops the timing manager.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
void Tim_ManStop( Tim_Man_t * p )
{
380 381
    Vec_PtrFreeFree( p->vDelayTables );
    Vec_PtrFreeP( &p->vBoxes );
382 383 384 385 386 387 388 389 390 391 392 393 394 395 396
    Mem_FlexStop( p->pMemObj, 0 );
    ABC_FREE( p->pCis );
    ABC_FREE( p->pCos );
    ABC_FREE( p );
}
void Tim_ManStopP( Tim_Man_t ** p )
{
    if ( *p == NULL )
        return;
    Tim_ManStop( *p );
    *p = NULL;
}

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

397 398 399 400 401 402 403 404 405
  Synopsis    [Creates manager using hierarchy / box library / delay info.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
406
void Tim_ManCreate( Tim_Man_t * p, void * pLib, Vec_Flt_t * vInArrs, Vec_Flt_t * vOutReqs )
407 408 409
{
    If_LibBox_t * pLibBox = (If_LibBox_t *)pLib;
    If_Box_t * pIfBox;
410
    Tim_Box_t * pBox;
411 412
    Tim_Obj_t * pObj;
    float * pTable;
413
    int i, k;
414
    assert( p->vDelayTables == NULL );
415
    p->vDelayTables = pLibBox ? Vec_PtrStart( Vec_PtrSize(pLibBox->vBoxes) ) : Vec_PtrAlloc( 100 );
416
    if ( p->vBoxes )
417 418
    Tim_ManForEachBox( p, pBox, i )
    {
419
        if ( pBox->iDelayTable == -1 || pLibBox == NULL )
420 421
        {
            // create table with constants
422 423 424 425
            pTable = ABC_ALLOC( float, 3 + pBox->nInputs * pBox->nOutputs );
            pTable[0] = pBox->iDelayTable;
            pTable[1] = pBox->nInputs;
            pTable[2] = pBox->nOutputs;
426
            for ( k = 0; k < pBox->nInputs * pBox->nOutputs; k++ )
427 428 429 430
                pTable[3 + k] = 1.0;
            // save table
            pBox->iDelayTable = Vec_PtrSize(p->vDelayTables);
            Vec_PtrPush( p->vDelayTables, pTable );
431 432 433 434 435 436 437
            continue;
        }
        assert( pBox->iDelayTable >= 0 && pBox->iDelayTable < Vec_PtrSize(pLibBox->vBoxes) );
        pIfBox = (If_Box_t *)Vec_PtrEntry( pLibBox->vBoxes, pBox->iDelayTable );
        assert( pIfBox != NULL );
        assert( pIfBox->nPis == pBox->nInputs );
        assert( pIfBox->nPos == pBox->nOutputs );
438
        pBox->fBlack = pIfBox->fBlack;
439 440 441
        if ( Vec_PtrEntry( p->vDelayTables, pBox->iDelayTable ) != NULL )
            continue;
        // create table of boxes
442 443 444 445
        pTable = ABC_ALLOC( float, 3 + pBox->nInputs * pBox->nOutputs );
        pTable[0] = pBox->iDelayTable;
        pTable[1] = pBox->nInputs;
        pTable[2] = pBox->nOutputs;
446
        for ( k = 0; k < pBox->nInputs * pBox->nOutputs; k++ )
447 448 449
            pTable[3 + k] = pIfBox->pDelays[k];
        // save table
        Vec_PtrWriteEntry( p->vDelayTables, pBox->iDelayTable, pTable );
450 451 452 453 454
    }
    // create arrival times
    if ( vInArrs )
    {
        assert( Vec_FltSize(vInArrs) == Tim_ManPiNum(p) );
455 456 457
        Tim_ManForEachPi( p, pObj, i )
            pObj->timeArr = Vec_FltEntry(vInArrs, i);

458 459 460 461
    }
    // create required times
    if ( vOutReqs )
    {
462
        k = 0;
463
        assert( Vec_FltSize(vOutReqs) == Tim_ManPoNum(p) );
464 465 466
        Tim_ManForEachPo( p, pObj, i )
            pObj->timeReq = Vec_FltEntry(vOutReqs, k++);
        assert( k == Tim_ManPoNum(p) );
467 468 469 470 471 472
    }
}


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

473 474 475 476 477 478 479 480 481
  Synopsis    [Get arrival and required times if they are non-trivial.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
482
float * Tim_ManGetArrTimes( Tim_Man_t * p )
483
{
484
    float * pTimes;
485
    Tim_Obj_t * pObj;
486
    int i;
487 488 489
    Tim_ManForEachPi( p, pObj, i )
        if ( pObj->timeArr != 0.0 )
            break;
490 491
    if ( i == Tim_ManPiNum(p) )
        return NULL;
492
    pTimes  = ABC_FALLOC( float, Tim_ManCiNum(p) );
493 494 495 496 497 498 499 500 501
    Tim_ManForEachPi( p, pObj, i )
        pTimes[i] = pObj->timeArr;
    return pTimes;
}
float * Tim_ManGetReqTimes( Tim_Man_t * p )
{
    float * pTimes;
    Tim_Obj_t * pObj;
    int i, k = 0;
502 503 504
    Tim_ManForEachPo( p, pObj, i )
        if ( pObj->timeReq != TIM_ETERNITY )
            break;
505 506
    if ( i == Tim_ManPoNum(p) )
        return NULL;
507
    pTimes  = ABC_FALLOC( float, Tim_ManCoNum(p) );
508
    Tim_ManForEachPo( p, pObj, i )
509 510 511
        pTimes[k++] = pObj->timeArr;
    assert( k == Tim_ManPoNum(p) );
    return pTimes;
512 513 514 515 516
}


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

517 518 519 520 521 522 523 524 525 526 527 528 529 530
  Synopsis    [Prints the timing manager.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
void Tim_ManPrint( Tim_Man_t * p )
{
    Tim_Box_t * pBox;
    Tim_Obj_t * pObj, * pPrev;
    float * pTable;
531
    int i, j, k, TableX, TableY;
532 533 534
    if ( p == NULL )
        return;
    printf( "TIMING MANAGER:\n" );
535 536
    printf( "PI = %d. CI = %d. PO = %d. CO = %d. Box = %d.\n", 
        Tim_ManPiNum(p), Tim_ManCiNum(p), Tim_ManPoNum(p), Tim_ManCoNum(p), Tim_ManBoxNum(p) );
537 538 539 540 541 542 543

    // print CI info
    pPrev = p->pCis;
    Tim_ManForEachPi( p, pObj, i )
        if ( pPrev->timeArr != pObj->timeArr || pPrev->timeReq != pObj->timeReq )
            break;
    if ( i == Tim_ManCiNum(p) )
544
        printf( "All PIs     :  arrival = %5.3f  required = %5.3f\n", pPrev->timeArr, pPrev->timeReq );
545 546
    else
        Tim_ManForEachPi( p, pObj, i )
547
            printf( "PI%5d     :  arrival = %5.3f  required = %5.3f\n", i, pObj->timeArr, pObj->timeReq );
548 549 550 551 552 553 554

    // print CO info
    pPrev = p->pCos;
    Tim_ManForEachPo( p, pObj, i )
        if ( pPrev->timeArr != pObj->timeArr || pPrev->timeReq != pObj->timeReq )
            break;
    if ( i == Tim_ManCoNum(p) )
555
        printf( "All POs     :  arrival = %5.3f  required = %5.3f\n", pPrev->timeArr, pPrev->timeReq );
556
    else
557 558
    {
        int k = 0;
559
        Tim_ManForEachPo( p, pObj, i )
560
            printf( "PO%5d     :  arrival = %5.3f  required = %5.3f\n", k++, pObj->timeArr, pObj->timeReq );
561
    }
562 563

    // print box info
564
    if ( Tim_ManBoxNum(p) > 0 )
565 566
    Tim_ManForEachBox( p, pBox, i )
    {
567 568 569 570
        printf( "*** Box %5d :  I =%4d. O =%4d. I1 =%6d. O1 =%6d. Table =%4d\n", 
            i, pBox->nInputs, pBox->nOutputs, 
            Tim_ManBoxInputFirst(p, i), Tim_ManBoxOutputFirst(p, i), 
            pBox->iDelayTable );
571 572 573

        // print box inputs
        pPrev = Tim_ManBoxInput( p, pBox, 0 );
574
        Tim_ManBoxForEachInput( p, pBox, pObj, k )
575 576
            if ( pPrev->timeArr != pObj->timeArr || pPrev->timeReq != pObj->timeReq )
                break;
577
        if ( k == Tim_ManBoxInputNum(p, pBox->iBox) )
578
            printf( "Box inputs  :  arrival = %5.3f  required = %5.3f\n", pPrev->timeArr, pPrev->timeReq );
579
        else
580
            Tim_ManBoxForEachInput( p, pBox, pObj, k )
581
                printf( "box-in%4d :  arrival = %5.3f  required = %5.3f\n", k, pObj->timeArr, pObj->timeReq );
582 583 584

        // print box outputs
        pPrev = Tim_ManBoxOutput( p, pBox, 0 );
585
        Tim_ManBoxForEachOutput( p, pBox, pObj, k )
586 587
            if ( pPrev->timeArr != pObj->timeArr || pPrev->timeReq != pObj->timeReq )
                break;
588
        if ( k == Tim_ManBoxOutputNum(p, pBox->iBox) )
589
            printf( "Box outputs :  arrival = %5.3f  required = %5.3f\n", pPrev->timeArr, pPrev->timeReq );
590
        else
591
            Tim_ManBoxForEachOutput( p, pBox, pObj, k )
592
                printf( "box-out%3d :  arrival = %5.3f  required = %5.3f\n", k, pObj->timeArr, pObj->timeReq );
593 594 595

        if ( i > 2 )
            break;
596 597 598 599 600 601
    }

    // print delay tables
    if ( Tim_ManDelayTableNum(p) > 0 )
    Tim_ManForEachTable( p, pTable, i )
    {
602 603
        if ( pTable == NULL )
            continue;
604 605 606 607 608 609 610 611 612 613
        printf( "Delay table %d:\n", i );
        assert( i == (int)pTable[0] );
        TableX = (int)pTable[1];
        TableY = (int)pTable[2];
        for ( j = 0; j < TableY; j++, printf( "\n" ) )
            for ( k = 0; k < TableX; k++ )
                if ( pTable[3+j*TableX+k] == -ABC_INFINITY )
                    printf( "%5s", "-" );
                else
                    printf( "%5.0f", pTable[3+j*TableX+k] );
614 615 616
    }
    printf( "\n" );
}
617 618 619 620 621 622 623 624 625 626 627 628 629 630 631
void Tim_ManPrintBoxCopy( Tim_Man_t * p )
{
    Tim_Box_t * pBox;
    int i;
    if ( p == NULL )
        return;
    printf( "TIMING MANAGER:\n" );
    printf( "PI = %d. CI = %d. PO = %d. CO = %d. Box = %d.\n", 
        Tim_ManPiNum(p), Tim_ManCiNum(p), Tim_ManPoNum(p), Tim_ManCoNum(p), Tim_ManBoxNum(p) );

    if ( Tim_ManBoxNum(p) > 0 )
    Tim_ManForEachBox( p, pBox, i )
        printf( "%d ", pBox->iCopy );
    printf( "\n" );
}
632 633 634

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

635 636 637 638 639 640 641 642 643
  Synopsis    [Prints statistics of the timing manager.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
644
void Tim_ManPrintStats( Tim_Man_t * p, int nAnd2Delay )
645 646 647 648 649 650 651
{
    Tim_Box_t * pBox;
    Vec_Int_t * vCounts;
    Vec_Ptr_t * vBoxes;
    int i, Count, IdMax;
    if ( p == NULL )
        return;
652
    Abc_Print( 1, "Hierarchy      :  " );
653
    printf( "PI/CI = %d/%d   PO/CO = %d/%d   Box = %d   ", 
654 655 656
        Tim_ManPiNum(p), Tim_ManCiNum(p), 
        Tim_ManPoNum(p), Tim_ManCoNum(p), 
        Tim_ManBoxNum(p) );
657 658
    if ( nAnd2Delay )
        printf( "delay(AND2) = %d", nAnd2Delay );
659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688
    printf( "\n" );
    if ( Tim_ManBoxNum(p) == 0 )
        return;
    IdMax = 0;
    Tim_ManForEachBox( p, pBox, i )
        IdMax = Abc_MaxInt( IdMax, pBox->iDelayTable );
    vCounts = Vec_IntStart( IdMax+1 );
    vBoxes  = Vec_PtrStart( IdMax+1 );
    Tim_ManForEachBox( p, pBox, i )
    {
        Vec_IntAddToEntry( vCounts, pBox->iDelayTable, 1 );
        Vec_PtrWriteEntry( vBoxes, pBox->iDelayTable, pBox );
    }
    // print statistics about boxes
    Vec_IntForEachEntry( vCounts, Count, i )
    {
        if ( Count == 0 ) continue;
        pBox = (Tim_Box_t *)Vec_PtrEntry( vBoxes, i );
        printf( "    Box %4d      ", i );
        printf( "Num = %4d   ", Count );
        printf( "Ins = %4d   ", pBox->nInputs );
        printf( "Outs = %4d",   pBox->nOutputs );
        printf( "\n" );
    }
    Vec_IntFree( vCounts );
    Vec_PtrFree( vBoxes );
}

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

689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707
  Synopsis    [Read parameters.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
int Tim_ManCiNum( Tim_Man_t * p )
{
    return p->nCis;
}
int Tim_ManCoNum( Tim_Man_t * p )
{
    return p->nCos;
}
int Tim_ManPiNum( Tim_Man_t * p )
{
708 709
    if ( Tim_ManBoxNum(p) == 0 )
        return Tim_ManCiNum(p);
710 711 712 713
    return Tim_ManBoxOutputFirst(p, 0);
}
int Tim_ManPoNum( Tim_Man_t * p )
{
714 715 716 717
    int iLastBoxId;
    if ( Tim_ManBoxNum(p) == 0 )
        return Tim_ManCoNum(p);
    iLastBoxId = Tim_ManBoxNum(p) - 1;
718 719 720 721
    return Tim_ManCoNum(p) - (Tim_ManBoxInputFirst(p, iLastBoxId) + Tim_ManBoxInputNum(p, iLastBoxId));
}
int Tim_ManBoxNum( Tim_Man_t * p )
{
722
    return p->vBoxes ? Vec_PtrSize(p->vBoxes) : 0;
723
}
724 725 726 727 728 729 730 731 732
int Tim_ManBlackBoxNum( Tim_Man_t * p )
{
    Tim_Box_t * pBox;
    int i, Counter = 0;
    if ( Tim_ManBoxNum(p) )
        Tim_ManForEachBox( p, pBox, i )
            Counter += pBox->fBlack;
    return Counter;
}
733 734 735 736 737 738 739 740
void Tim_ManBlackBoxIoNum( Tim_Man_t * p, int * pnBbIns, int * pnBbOuts )
{
    Tim_Box_t * pBox;
    int i;
    *pnBbIns = *pnBbOuts = 0;
    if ( Tim_ManBoxNum(p) )
        Tim_ManForEachBox( p, pBox, i )
        {
741
            if ( !pBox->fBlack )//&& pBox->nInputs <= 6 )
742 743 744 745 746
                continue;
            *pnBbIns  += Tim_ManBoxInputNum( p, i );
            *pnBbOuts += Tim_ManBoxOutputNum( p, i );
        }
}
747 748
int Tim_ManDelayTableNum( Tim_Man_t * p )
{
749
    return p->vDelayTables ? Vec_PtrSize(p->vDelayTables) : 0;
750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807
}

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

  Synopsis    [Sets the vector of timing tables associated with the manager.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
void Tim_ManSetDelayTables( Tim_Man_t * p, Vec_Ptr_t * vDelayTables )
{
    assert( p->vDelayTables == NULL );
    p->vDelayTables = vDelayTables;
}

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

  Synopsis    [Disables the use of the traversal ID.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
void Tim_ManTravIdDisable( Tim_Man_t * p )
{
    p->fUseTravId = 0;
}

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

  Synopsis    [Enables the use of the traversal ID.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
void Tim_ManTravIdEnable( Tim_Man_t * p )
{
    p->fUseTravId = 1;
}

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


ABC_NAMESPACE_IMPL_END