sfmWin.c 14.7 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 23 24 25 26 27 28 29 30 31 32 33 34 35
/**CFile****************************************************************

  FileName    [sfmWin.c]

  SystemName  [ABC: Logic synthesis and verification system.]

  PackageName [SAT-based optimization using internal don't-cares.]

  Synopsis    [Structural window computation.]

  Author      [Alan Mishchenko]
  
  Affiliation [UC Berkeley]

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

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

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

#include "sfmInt.h"

ABC_NAMESPACE_IMPL_START


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

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

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

Alan Mishchenko committed
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
  Synopsis    [Returns the MFFC size.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
int Sfm_ObjRef_rec( Sfm_Ntk_t * p, int iObj )
{
    int i, iFanin, Value, Count;
    if ( Sfm_ObjIsPi(p, iObj) )
        return 0;
    assert( Sfm_ObjIsNode(p, iObj) );
    Value = Sfm_ObjRefIncrement(p, iObj);
    if ( Value > 1 )
        return 0;
    assert( Value == 1 );
    Count = 1;
    Sfm_ObjForEachFanin( p, iObj, iFanin, i )
        Count += Sfm_ObjRef_rec( p, iFanin );
    return Count;
}
int Sfm_ObjRef( Sfm_Ntk_t * p, int iObj )
{
    int i, iFanin, Count = 1;
    Sfm_ObjForEachFanin( p, iObj, iFanin, i )
        Count += Sfm_ObjRef_rec( p, iFanin );
    return Count;
}
int Sfm_ObjDeref_rec( Sfm_Ntk_t * p, int iObj )
{
    int i, iFanin, Value, Count;
    if ( Sfm_ObjIsPi(p, iObj) )
        return 0;
    assert( Sfm_ObjIsNode(p, iObj) );
    Value = Sfm_ObjRefDecrement(p, iObj);
    if ( Value > 0 )
        return 0;
    assert( Value == 0 );
    Count = 1;
    Sfm_ObjForEachFanin( p, iObj, iFanin, i )
        Count += Sfm_ObjDeref_rec( p, iFanin );
    return Count;
}
int Sfm_ObjDeref( Sfm_Ntk_t * p, int iObj )
{
    int i, iFanin, Count = 1;
    Sfm_ObjForEachFanin( p, iObj, iFanin, i )
        Count += Sfm_ObjDeref_rec( p, iFanin );
    return Count;
}
int Sfm_ObjMffcSize( Sfm_Ntk_t * p, int iObj )
{
    int Count1, Count2;
Alan Mishchenko committed
92 93 94 95
    if ( Sfm_ObjIsPi(p, iObj) )
        return 0;
    if ( Sfm_ObjFanoutNum(p, iObj) != 1 )
        return 0;
Alan Mishchenko committed
96 97 98 99 100 101 102 103 104
    assert( Sfm_ObjIsNode( p, iObj ) );
    Count1 = Sfm_ObjDeref( p, iObj );
    Count2 = Sfm_ObjRef( p, iObj );
    assert( Count1 == Count2 );
    return Count1;
}

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

Alan Mishchenko committed
105 106 107 108 109 110 111 112 113
  Synopsis    [Working with traversal IDs.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
114 115 116
static inline void  Sfm_NtkIncrementTravId( Sfm_Ntk_t * p )            { p->nTravIds++;                                            }       
static inline void  Sfm_ObjSetTravIdCurrent( Sfm_Ntk_t * p, int Id )   { Vec_IntWriteEntry( &p->vTravIds, Id, p->nTravIds );       }
static inline int   Sfm_ObjIsTravIdCurrent( Sfm_Ntk_t * p, int Id )    { return (Vec_IntEntry(&p->vTravIds, Id) == p->nTravIds);   }   
Alan Mishchenko committed
117
static inline int   Sfm_ObjIsTravIdPrevious( Sfm_Ntk_t * p, int Id )   { return (Vec_IntEntry(&p->vTravIds, Id) == p->nTravIds-1); }   
Alan Mishchenko committed
118 119 120 121 122 123 124 125

static inline void  Sfm_NtkIncrementTravId2( Sfm_Ntk_t * p )           { p->nTravIds2++;                                           }       
static inline void  Sfm_ObjSetTravIdCurrent2( Sfm_Ntk_t * p, int Id )  { Vec_IntWriteEntry( &p->vTravIds2, Id, p->nTravIds2 );     }
static inline int   Sfm_ObjIsTravIdCurrent2( Sfm_Ntk_t * p, int Id )   { return (Vec_IntEntry(&p->vTravIds2, Id) == p->nTravIds2); }   


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

126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
  Synopsis    [Collects used internal nodes in a topological order.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
void Sfm_NtkDfs_rec( Sfm_Ntk_t * p, int iNode, Vec_Int_t * vNodes )
{
    int i, iFanin;
    if ( Sfm_ObjIsPi(p, iNode) )
        return;
    if ( Sfm_ObjIsTravIdCurrent(p, iNode) )
        return;
    Sfm_ObjSetTravIdCurrent(p, iNode);
    Sfm_ObjForEachFanin( p, iNode, iFanin, i )
        Sfm_NtkDfs_rec( p, iFanin, vNodes );
    Vec_IntPush( vNodes, iNode );
}
Vec_Int_t * Sfm_NtkDfs( Sfm_Ntk_t * p )
{
    Vec_Int_t * vNodes;
    int i;
    vNodes = Vec_IntAlloc( p->nObjs );
    Sfm_NtkIncrementTravId( p );
    Sfm_NtkForEachPo( p, i )
        Sfm_NtkDfs_rec( p, Sfm_ObjFanin(p, i, 0), vNodes );
    return vNodes;
}

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

Alan Mishchenko committed
160 161 162 163 164 165 166 167 168 169 170 171 172 173
  Synopsis    [Check if this fanout overlaps with TFI cone of the node.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
int Sfm_NtkCheckOverlap_rec( Sfm_Ntk_t * p, int iThis, int iNode )
{
    int i, iFanin;
    if ( Sfm_ObjIsTravIdCurrent2(p, iThis) || iThis == iNode )
        return 0;
Alan Mishchenko committed
174 175
//    if ( Sfm_ObjIsTravIdCurrent(p, iThis) )
    if ( Sfm_ObjIsTravIdPrevious(p, iThis) )
Alan Mishchenko committed
176 177
        return 1;
    Sfm_ObjSetTravIdCurrent2(p, iThis);
Alan Mishchenko committed
178
    Sfm_ObjForEachFanin( p, iThis, iFanin, i )
Alan Mishchenko committed
179 180 181 182 183 184 185 186 187 188 189 190
        if ( Sfm_NtkCheckOverlap_rec(p, iFanin, iNode) )
            return 1;
    return 0;
}
int Sfm_NtkCheckOverlap( Sfm_Ntk_t * p, int iFan, int iNode )
{
    Sfm_NtkIncrementTravId2( p );
    return Sfm_NtkCheckOverlap_rec( p, iFan, iNode );
}

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

Alan Mishchenko committed
191
  Synopsis    [Recursively collects roots of the window.]
Alan Mishchenko committed
192

Alan Mishchenko committed
193
  Description []
Alan Mishchenko committed
194 195 196 197 198 199
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
200
static inline int Sfm_NtkCheckRoot( Sfm_Ntk_t * p, int iNode, int nLevelMax )
Alan Mishchenko committed
201 202
{
    int i, iFanout;
Alan Mishchenko committed
203
    // the node is the root if one of the following is true:
Alan Mishchenko committed
204 205
    // (1) the node has more than fanouts than the limit or has no fanouts (should not happen in general)
    if ( Sfm_ObjFanoutNum(p, iNode) == 0 || Sfm_ObjFanoutNum(p, iNode) > p->pPars->nFanoutMax )
Alan Mishchenko committed
206 207 208
        return 1;
    // (2) the node has CO fanouts
    // (3) the node has fanouts above the cutoff level
Alan Mishchenko committed
209
    Sfm_ObjForEachFanout( p, iNode, iFanout, i )
Alan Mishchenko committed
210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228
        if ( Sfm_ObjIsPo(p, iFanout) || Sfm_ObjLevel(p, iFanout) > nLevelMax )//|| !Sfm_NtkCheckOverlap(p, iFanout, iNode) )
            return 1;
    return 0;
}
void Sfm_NtkComputeRoots_rec( Sfm_Ntk_t * p, int iNode, int nLevelMax, Vec_Int_t * vRoots, Vec_Int_t * vTfo )
{
    int i, iFanout;
    assert( Sfm_ObjIsNode(p, iNode) );
    if ( Sfm_ObjIsTravIdCurrent(p, iNode) )
        return;
    Sfm_ObjSetTravIdCurrent(p, iNode);
    if ( iNode != p->iPivotNode )
        Vec_IntPush( vTfo, iNode );
    // check if the node should be the root
    if ( Sfm_NtkCheckRoot( p, iNode, nLevelMax ) )
        Vec_IntPush( vRoots, iNode );
    else // if not, explore its fanouts
        Sfm_ObjForEachFanout( p, iNode, iFanout, i )
            Sfm_NtkComputeRoots_rec( p, iFanout, nLevelMax, vRoots, vTfo );
Alan Mishchenko committed
229 230 231 232 233 234 235 236 237 238 239 240 241
}

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

  Synopsis    [Collects divisors of the node.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
242
void Sfm_NtkAddDivisors( Sfm_Ntk_t * p, int iNode, int nLevelMax )
Alan Mishchenko committed
243 244
{
    int i, iFanout;
Alan Mishchenko committed
245
    Sfm_ObjForEachFanout( p, iNode, iFanout, i )
Alan Mishchenko committed
246
    {
Alan Mishchenko committed
247 248
        // skip some of the fanouts if the number is large
        if ( p->pPars->nFanoutMax && i > p->pPars->nFanoutMax )
Alan Mishchenko committed
249
            return;
Alan Mishchenko committed
250
        // skip TFI nodes, PO nodes, or nodes with high logic level
Alan Mishchenko committed
251
        if ( Sfm_ObjIsTravIdCurrent(p, iFanout) || Sfm_ObjIsPo(p, iFanout) || Sfm_ObjLevel(p, iFanout) > nLevelMax )
Alan Mishchenko committed
252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267
            continue;
        // handle single-input nodes
        if ( Sfm_ObjFaninNum(p, iFanout) == 1 )
            Vec_IntPush( p->vDivs, iFanout );
        // visit node for the first time
        else if ( !Sfm_ObjIsTravIdCurrent2(p, iFanout) )
        {
            assert( Sfm_ObjFaninNum(p, iFanout) > 1 );
            Sfm_ObjSetTravIdCurrent2( p, iFanout );
            Sfm_ObjResetFaninCount( p, iFanout );
        }
        // visit node again
        else if ( Sfm_ObjUpdateFaninCount(p, iFanout) == 0 )
            Vec_IntPush( p->vDivs, iFanout );
    }
}
Alan Mishchenko committed
268 269 270

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

Alan Mishchenko committed
271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292
  Synopsis    [Fixed object is useful when it has a non-fixed fanout.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
static inline int Sfm_ObjIsUseful( Sfm_Ntk_t * p, int iNode )
{
    int i, iFanout;
    if ( !Sfm_ObjIsFixed(p, iNode) )
        return 1;
    Sfm_ObjForEachFanout( p, iNode, iFanout, i )
        if ( !Sfm_ObjIsFixed(p, iFanout) )
            return 1;
    return 0;
}

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

Alan Mishchenko committed
293 294 295 296 297 298 299 300 301
  Synopsis    [Computes structural window.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
302
int Sfm_NtkCollectTfi_rec( Sfm_Ntk_t * p, int iNode, Vec_Int_t * vNodes )
Alan Mishchenko committed
303 304 305
{
    int i, iFanin;
    if ( Sfm_ObjIsTravIdCurrent( p, iNode ) )
Alan Mishchenko committed
306
        return 0;
Alan Mishchenko committed
307
    Sfm_ObjSetTravIdCurrent( p, iNode );
Alan Mishchenko committed
308
    Sfm_ObjForEachFanin( p, iNode, iFanin, i )
Alan Mishchenko committed
309
        if ( Sfm_NtkCollectTfi_rec( p, iFanin, vNodes ) )
Alan Mishchenko committed
310
            return 1;
Alan Mishchenko committed
311 312
    Vec_IntPush( vNodes, iNode );
    return p->pPars->nWinSizeMax && (Vec_IntSize(vNodes) > p->pPars->nWinSizeMax);
Alan Mishchenko committed
313
}
Alan Mishchenko committed
314
int Sfm_NtkCreateWindow( Sfm_Ntk_t * p, int iNode, int fVerbose )
Alan Mishchenko committed
315
{
Alan Mishchenko committed
316
    int i, k, iTemp;
Alan Mishchenko committed
317 318
    abctime clkDiv, clkWin = Abc_Clock();

Alan Mishchenko committed
319
    assert( Sfm_ObjIsNode( p, iNode ) );
Alan Mishchenko committed
320
    p->iPivotNode = iNode;
Alan Mishchenko committed
321
    Vec_IntClear( p->vNodes );  // internal
Alan Mishchenko committed
322
    Vec_IntClear( p->vDivs );   // divisors
Alan Mishchenko committed
323 324
    Vec_IntClear( p->vRoots );  // roots
    Vec_IntClear( p->vTfo );    // roots
Alan Mishchenko committed
325
    Vec_IntClear( p->vOrder );  // variable order
Alan Mishchenko committed
326

Alan Mishchenko committed
327
    // collect transitive fanin
Alan Mishchenko committed
328
    Sfm_NtkIncrementTravId( p );
Alan Mishchenko committed
329
    if ( Sfm_NtkCollectTfi_rec( p, iNode, p->vNodes ) )
Alan Mishchenko committed
330
    {
331
        p->nMaxDivs++;
Alan Mishchenko committed
332
        p->timeWin += Abc_Clock() - clkWin;
Alan Mishchenko committed
333
        return 0;
Alan Mishchenko committed
334
    }
Alan Mishchenko committed
335

Alan Mishchenko committed
336
    // create divisors
Alan Mishchenko committed
337
    clkDiv = Abc_Clock();
Alan Mishchenko committed
338
    Vec_IntClear( p->vDivs );
Alan Mishchenko committed
339
    Vec_IntAppend( p->vDivs, p->vNodes );
Alan Mishchenko committed
340 341
    Vec_IntPop( p->vDivs );
    // add non-topological divisors
Alan Mishchenko committed
342
    if ( Vec_IntSize(p->vDivs) < p->pPars->nWinSizeMax + 0 )
Alan Mishchenko committed
343 344 345
    {
        Sfm_NtkIncrementTravId2( p );
        Vec_IntForEachEntry( p->vDivs, iTemp, i )
Alan Mishchenko committed
346
            if ( Vec_IntSize(p->vDivs) < p->pPars->nWinSizeMax + 0 )
Alan Mishchenko committed
347 348
//                Sfm_NtkAddDivisors( p, iTemp, Sfm_ObjLevel(p, iNode) - 1 );
                Sfm_NtkAddDivisors( p, iTemp, p->nLevelMax - Sfm_ObjLevelR(p, iNode) ); 
Alan Mishchenko committed
349 350
    }
    if ( Vec_IntSize(p->vDivs) > p->pPars->nWinSizeMax )
Alan Mishchenko committed
351 352 353 354 355 356 357
    {
/*
        k = 0;
        Vec_IntForEachEntryStart( p->vDivs, iTemp, i, Vec_IntSize(p->vDivs) - p->pPars->nWinSizeMax )
            Vec_IntWriteEntry( p->vDivs, k++, iTemp );
        assert( k == p->pPars->nWinSizeMax );
*/
Alan Mishchenko committed
358
        Vec_IntShrink( p->vDivs, p->pPars->nWinSizeMax );
Alan Mishchenko committed
359
    }
Alan Mishchenko committed
360
    assert( Vec_IntSize(p->vDivs) <= p->pPars->nWinSizeMax );
Alan Mishchenko committed
361 362
    p->nMaxDivs += (int)(Vec_IntSize(p->vDivs) == p->pPars->nWinSizeMax);
    // remove node/fanins from divisors
Alan Mishchenko committed
363
    // mark fanins
Alan Mishchenko committed
364
    Sfm_NtkIncrementTravId2( p );
Alan Mishchenko committed
365 366 367 368
    Sfm_ObjSetTravIdCurrent2( p, iNode );
    Sfm_ObjForEachFanin( p, iNode, iTemp, i )
        Sfm_ObjSetTravIdCurrent2( p, iTemp );
    // compact divisors
Alan Mishchenko committed
369 370
    k = 0;
    Vec_IntForEachEntry( p->vDivs, iTemp, i )
Alan Mishchenko committed
371
        if ( !Sfm_ObjIsTravIdCurrent2(p, iTemp) && Sfm_ObjIsUseful(p, iTemp) )
Alan Mishchenko committed
372
            Vec_IntWriteEntry( p->vDivs, k++, iTemp );
Alan Mishchenko committed
373 374
    Vec_IntShrink( p->vDivs, k );
    assert( Vec_IntSize(p->vDivs) <= p->pPars->nWinSizeMax );
Alan Mishchenko committed
375 376
    clkDiv = Abc_Clock() - clkDiv;
    p->timeDiv += clkDiv;
Alan Mishchenko committed
377
    p->nTotalDivs += Vec_IntSize(p->vDivs);
Alan Mishchenko committed
378
 
Alan Mishchenko committed
379 380 381 382 383 384 385 386 387 388 389
    // collect TFO and window roots
    if ( p->pPars->nTfoLevMax > 0 && !Sfm_NtkCheckRoot(p, iNode, Sfm_ObjLevel(p, iNode) + p->pPars->nTfoLevMax) )
    {
        // explore transitive fanout
        Sfm_NtkIncrementTravId( p );
        Sfm_NtkComputeRoots_rec( p, iNode, Sfm_ObjLevel(p, iNode) + p->pPars->nTfoLevMax, p->vRoots, p->vTfo );
        assert( Vec_IntSize(p->vRoots) > 0 );
        assert( Vec_IntSize(p->vTfo) > 0 );
        // compute new leaves and nodes
        Sfm_NtkIncrementTravId( p );
        Vec_IntForEachEntry( p->vRoots, iTemp, i )
Alan Mishchenko committed
390 391 392 393 394
            if ( Sfm_NtkCollectTfi_rec( p, iTemp, p->vOrder ) )
            {
                Vec_IntClear( p->vRoots );
                Vec_IntClear( p->vTfo );
                Vec_IntClear( p->vOrder );
Alan Mishchenko committed
395
                break;
Alan Mishchenko committed
396 397
            }
        if ( Vec_IntSize(p->vRoots) > 0 )
Alan Mishchenko committed
398 399 400 401 402 403 404 405 406
        Vec_IntForEachEntry( p->vTfo, iTemp, i )
            if ( Sfm_NtkCollectTfi_rec( p, iTemp, p->vOrder ) )
            {
                Vec_IntClear( p->vRoots );
                Vec_IntClear( p->vTfo );
                Vec_IntClear( p->vOrder );
                break;
            }
        if ( Vec_IntSize(p->vRoots) > 0 )
Alan Mishchenko committed
407 408 409 410 411 412 413 414
        Vec_IntForEachEntry( p->vDivs, iTemp, i )
            if ( Sfm_NtkCollectTfi_rec( p, iTemp, p->vOrder ) )
            {
                Vec_IntClear( p->vRoots );
                Vec_IntClear( p->vTfo );
                Vec_IntClear( p->vOrder );
                break;
            }
Alan Mishchenko committed
415 416
    }

Alan Mishchenko committed
417
    if ( Vec_IntSize(p->vOrder) == 0 )
Alan Mishchenko committed
418
    {
Alan Mishchenko committed
419 420 421 422 423 424 425
        int Temp = p->pPars->nWinSizeMax;
        p->pPars->nWinSizeMax = 0;
        Sfm_NtkIncrementTravId( p );
        Sfm_NtkCollectTfi_rec( p, iNode, p->vOrder );
        Vec_IntForEachEntry( p->vDivs, iTemp, i )
            Sfm_NtkCollectTfi_rec( p, iTemp, p->vOrder );
        p->pPars->nWinSizeMax = Temp;
Alan Mishchenko committed
426 427 428 429
    }

    // statistics
    p->timeWin += Abc_Clock() - clkWin - clkDiv;
Alan Mishchenko committed
430 431 432 433 434
    if ( !fVerbose )
        return 1;

    // print stats about the window
    printf( "%6d : ", iNode );
Alan Mishchenko committed
435
    printf( "Leaves = %5d. ", 0 );
Alan Mishchenko committed
436 437 438 439
    printf( "Nodes = %5d. ",  Vec_IntSize(p->vNodes) );
    printf( "Roots = %5d. ",  Vec_IntSize(p->vRoots) );
    printf( "Divs = %5d. ",   Vec_IntSize(p->vDivs) );
    printf( "\n" );
Alan Mishchenko committed
440 441
    return 1;
}
Alan Mishchenko committed
442
void Sfm_NtkWindowTest( Sfm_Ntk_t * p, int iNode )
Alan Mishchenko committed
443
{
Alan Mishchenko committed
444 445
    int i;
    Sfm_NtkForEachNode( p, i )
Alan Mishchenko committed
446 447 448
        Sfm_NtkCreateWindow( p, i, 1 );
}

Alan Mishchenko committed
449 450 451 452 453 454 455
////////////////////////////////////////////////////////////////////////
///                       END OF FILE                                ///
////////////////////////////////////////////////////////////////////////


ABC_NAMESPACE_IMPL_END