sfmWin.c 15.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
  Synopsis    [Collects used internal nodes in a topological order.]

128 129
  Description [Additionally considers objects in groups as a single object
  and collects them in a topological order together as single entity.]
130 131 132 133 134 135
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
136
void Sfm_NtkDfs_rec( Sfm_Ntk_t * p, int iNode, Vec_Int_t * vNodes, Vec_Wec_t * vGroups, Vec_Int_t * vGroupMap, Vec_Int_t * vBoxesLeft )
137 138 139 140 141 142
{
    int i, iFanin;
    if ( Sfm_ObjIsPi(p, iNode) )
        return;
    if ( Sfm_ObjIsTravIdCurrent(p, iNode) )
        return;
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
    if ( Vec_IntEntry(vGroupMap, iNode) >= 0 )
    {
        int k, iGroup = Abc_Lit2Var( Vec_IntEntry(vGroupMap, iNode) );
        Vec_Int_t * vGroup = Vec_WecEntry( vGroups, iGroup );
        Vec_IntForEachEntry( vGroup, iNode, i )
            assert( Sfm_ObjIsNode(p, iNode) );
        Vec_IntForEachEntry( vGroup, iNode, i )
            Sfm_ObjSetTravIdCurrent( p, iNode );
        Vec_IntForEachEntry( vGroup, iNode, i )
            Sfm_ObjForEachFanin( p, iNode, iFanin, k )
                Sfm_NtkDfs_rec( p, iFanin, vNodes, vGroups, vGroupMap, vBoxesLeft );
        Vec_IntForEachEntry( vGroup, iNode, i )
            Vec_IntPush( vNodes, iNode );
        Vec_IntPush( vBoxesLeft, iGroup );
    }
    else
    {
        Sfm_ObjSetTravIdCurrent(p, iNode);
        Sfm_ObjForEachFanin( p, iNode, iFanin, i )
            Sfm_NtkDfs_rec( p, iFanin, vNodes, vGroups, vGroupMap, vBoxesLeft );
        Vec_IntPush( vNodes, iNode );
    }
165
}
166
Vec_Int_t * Sfm_NtkDfs( Sfm_Ntk_t * p, Vec_Wec_t * vGroups, Vec_Int_t * vGroupMap, Vec_Int_t * vBoxesLeft )
167 168 169
{
    Vec_Int_t * vNodes;
    int i;
170
    Vec_IntClear( vBoxesLeft );
171 172 173
    vNodes = Vec_IntAlloc( p->nObjs );
    Sfm_NtkIncrementTravId( p );
    Sfm_NtkForEachPo( p, i )
174
        Sfm_NtkDfs_rec( p, Sfm_ObjFanin(p, i, 0), vNodes, vGroups, vGroupMap, vBoxesLeft );
175 176 177 178 179
    return vNodes;
}

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

Alan Mishchenko committed
180 181 182 183 184 185 186 187 188 189 190 191 192 193
  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
194 195
//    if ( Sfm_ObjIsTravIdCurrent(p, iThis) )
    if ( Sfm_ObjIsTravIdPrevious(p, iThis) )
Alan Mishchenko committed
196 197
        return 1;
    Sfm_ObjSetTravIdCurrent2(p, iThis);
Alan Mishchenko committed
198
    Sfm_ObjForEachFanin( p, iThis, iFanin, i )
Alan Mishchenko committed
199 200 201 202 203 204 205 206 207 208 209 210
        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
211
  Synopsis    [Recursively collects roots of the window.]
Alan Mishchenko committed
212

Alan Mishchenko committed
213
  Description []
Alan Mishchenko committed
214 215 216 217 218 219
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
220
static inline int Sfm_NtkCheckRoot( Sfm_Ntk_t * p, int iNode, int nLevelMax )
Alan Mishchenko committed
221 222
{
    int i, iFanout;
Alan Mishchenko committed
223
    // the node is the root if one of the following is true:
Alan Mishchenko committed
224 225
    // (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
226 227 228
        return 1;
    // (2) the node has CO fanouts
    // (3) the node has fanouts above the cutoff level
Alan Mishchenko committed
229
    Sfm_ObjForEachFanout( p, iNode, iFanout, i )
Alan Mishchenko committed
230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248
        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
249 250 251 252 253 254 255 256 257 258 259 260 261
}

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

  Synopsis    [Collects divisors of the node.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
262
void Sfm_NtkAddDivisors( Sfm_Ntk_t * p, int iNode, int nLevelMax )
Alan Mishchenko committed
263 264
{
    int i, iFanout;
Alan Mishchenko committed
265
    Sfm_ObjForEachFanout( p, iNode, iFanout, i )
Alan Mishchenko committed
266
    {
Alan Mishchenko committed
267 268
        // skip some of the fanouts if the number is large
        if ( p->pPars->nFanoutMax && i > p->pPars->nFanoutMax )
Alan Mishchenko committed
269
            return;
Alan Mishchenko committed
270
        // skip TFI nodes, PO nodes, or nodes with high logic level
Alan Mishchenko committed
271
        if ( Sfm_ObjIsTravIdCurrent(p, iFanout) || Sfm_ObjIsPo(p, iFanout) || Sfm_ObjLevel(p, iFanout) > nLevelMax )
Alan Mishchenko committed
272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287
            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
288 289 290

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

Alan Mishchenko committed
291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312
  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
313 314 315 316 317 318 319 320 321
  Synopsis    [Computes structural window.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
322
int Sfm_NtkCollectTfi_rec( Sfm_Ntk_t * p, int iNode, Vec_Int_t * vNodes )
Alan Mishchenko committed
323 324 325
{
    int i, iFanin;
    if ( Sfm_ObjIsTravIdCurrent( p, iNode ) )
Alan Mishchenko committed
326
        return 0;
Alan Mishchenko committed
327
    Sfm_ObjSetTravIdCurrent( p, iNode );
Alan Mishchenko committed
328
    Sfm_ObjForEachFanin( p, iNode, iFanin, i )
Alan Mishchenko committed
329
        if ( Sfm_NtkCollectTfi_rec( p, iFanin, vNodes ) )
Alan Mishchenko committed
330
            return 1;
Alan Mishchenko committed
331 332
    Vec_IntPush( vNodes, iNode );
    return p->pPars->nWinSizeMax && (Vec_IntSize(vNodes) > p->pPars->nWinSizeMax);
Alan Mishchenko committed
333
}
Alan Mishchenko committed
334
int Sfm_NtkCreateWindow( Sfm_Ntk_t * p, int iNode, int fVerbose )
Alan Mishchenko committed
335
{
Alan Mishchenko committed
336
    int i, k, iTemp;
Alan Mishchenko committed
337 338
    abctime clkDiv, clkWin = Abc_Clock();

Alan Mishchenko committed
339
    assert( Sfm_ObjIsNode( p, iNode ) );
Alan Mishchenko committed
340
    p->iPivotNode = iNode;
Alan Mishchenko committed
341
    Vec_IntClear( p->vNodes );  // internal
Alan Mishchenko committed
342
    Vec_IntClear( p->vDivs );   // divisors
Alan Mishchenko committed
343 344
    Vec_IntClear( p->vRoots );  // roots
    Vec_IntClear( p->vTfo );    // roots
Alan Mishchenko committed
345
    Vec_IntClear( p->vOrder );  // variable order
Alan Mishchenko committed
346

Alan Mishchenko committed
347
    // collect transitive fanin
Alan Mishchenko committed
348
    Sfm_NtkIncrementTravId( p );
Alan Mishchenko committed
349
    if ( Sfm_NtkCollectTfi_rec( p, iNode, p->vNodes ) )
Alan Mishchenko committed
350
    {
351
        p->nMaxDivs++;
Alan Mishchenko committed
352
        p->timeWin += Abc_Clock() - clkWin;
Alan Mishchenko committed
353
        return 0;
Alan Mishchenko committed
354
    }
Alan Mishchenko committed
355

Alan Mishchenko committed
356
    // create divisors
Alan Mishchenko committed
357
    clkDiv = Abc_Clock();
Alan Mishchenko committed
358
    Vec_IntClear( p->vDivs );
Alan Mishchenko committed
359
    Vec_IntAppend( p->vDivs, p->vNodes );
Alan Mishchenko committed
360 361
    Vec_IntPop( p->vDivs );
    // add non-topological divisors
Alan Mishchenko committed
362
    if ( Vec_IntSize(p->vDivs) < p->pPars->nWinSizeMax + 0 )
Alan Mishchenko committed
363 364 365
    {
        Sfm_NtkIncrementTravId2( p );
        Vec_IntForEachEntry( p->vDivs, iTemp, i )
Alan Mishchenko committed
366
            if ( Vec_IntSize(p->vDivs) < p->pPars->nWinSizeMax + 0 )
Alan Mishchenko committed
367 368
//                Sfm_NtkAddDivisors( p, iTemp, Sfm_ObjLevel(p, iNode) - 1 );
                Sfm_NtkAddDivisors( p, iTemp, p->nLevelMax - Sfm_ObjLevelR(p, iNode) ); 
Alan Mishchenko committed
369 370
    }
    if ( Vec_IntSize(p->vDivs) > p->pPars->nWinSizeMax )
Alan Mishchenko committed
371 372 373 374 375 376 377
    {
/*
        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
378
        Vec_IntShrink( p->vDivs, p->pPars->nWinSizeMax );
Alan Mishchenko committed
379
    }
Alan Mishchenko committed
380
    assert( Vec_IntSize(p->vDivs) <= p->pPars->nWinSizeMax );
Alan Mishchenko committed
381 382
    p->nMaxDivs += (int)(Vec_IntSize(p->vDivs) == p->pPars->nWinSizeMax);
    // remove node/fanins from divisors
Alan Mishchenko committed
383
    // mark fanins
Alan Mishchenko committed
384
    Sfm_NtkIncrementTravId2( p );
Alan Mishchenko committed
385 386 387 388
    Sfm_ObjSetTravIdCurrent2( p, iNode );
    Sfm_ObjForEachFanin( p, iNode, iTemp, i )
        Sfm_ObjSetTravIdCurrent2( p, iTemp );
    // compact divisors
Alan Mishchenko committed
389 390
    k = 0;
    Vec_IntForEachEntry( p->vDivs, iTemp, i )
Alan Mishchenko committed
391
        if ( !Sfm_ObjIsTravIdCurrent2(p, iTemp) && Sfm_ObjIsUseful(p, iTemp) )
Alan Mishchenko committed
392
            Vec_IntWriteEntry( p->vDivs, k++, iTemp );
Alan Mishchenko committed
393 394
    Vec_IntShrink( p->vDivs, k );
    assert( Vec_IntSize(p->vDivs) <= p->pPars->nWinSizeMax );
Alan Mishchenko committed
395 396
    clkDiv = Abc_Clock() - clkDiv;
    p->timeDiv += clkDiv;
Alan Mishchenko committed
397
    p->nTotalDivs += Vec_IntSize(p->vDivs);
Alan Mishchenko committed
398
 
Alan Mishchenko committed
399 400 401 402 403 404 405 406 407 408 409
    // 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
410 411 412 413 414
            if ( Sfm_NtkCollectTfi_rec( p, iTemp, p->vOrder ) )
            {
                Vec_IntClear( p->vRoots );
                Vec_IntClear( p->vTfo );
                Vec_IntClear( p->vOrder );
Alan Mishchenko committed
415
                break;
Alan Mishchenko committed
416 417
            }
        if ( Vec_IntSize(p->vRoots) > 0 )
Alan Mishchenko committed
418 419 420 421 422 423 424 425 426
        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
427 428 429 430 431 432 433 434
        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
435 436
    }

Alan Mishchenko committed
437
    if ( Vec_IntSize(p->vOrder) == 0 )
Alan Mishchenko committed
438
    {
Alan Mishchenko committed
439 440 441 442 443 444 445
        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
446 447 448 449
    }

    // statistics
    p->timeWin += Abc_Clock() - clkWin - clkDiv;
Alan Mishchenko committed
450 451 452 453 454
    if ( !fVerbose )
        return 1;

    // print stats about the window
    printf( "%6d : ", iNode );
Alan Mishchenko committed
455
    printf( "Leaves = %5d. ", 0 );
Alan Mishchenko committed
456 457 458 459
    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
460 461
    return 1;
}
Alan Mishchenko committed
462
void Sfm_NtkWindowTest( Sfm_Ntk_t * p, int iNode )
Alan Mishchenko committed
463
{
Alan Mishchenko committed
464 465
    int i;
    Sfm_NtkForEachNode( p, i )
Alan Mishchenko committed
466 467 468
        Sfm_NtkCreateWindow( p, i, 1 );
}

Alan Mishchenko committed
469 470 471 472 473 474 475
////////////////////////////////////////////////////////////////////////
///                       END OF FILE                                ///
////////////////////////////////////////////////////////////////////////


ABC_NAMESPACE_IMPL_END