nwkMerge.c 30.8 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
/**CFile****************************************************************

  FileName    [nwkMerge.c]

  SystemName  [ABC: Logic synthesis and verification system.]

  PackageName [Netlist representation.]

  Synopsis    [LUT merging algorithm.]

  Author      [Alan Mishchenko]
  
  Affiliation [UC Berkeley]

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

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

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

#include "nwk.h"
Alan Mishchenko committed
22
#include "nwkMerge.h"
Alan Mishchenko committed
23

24 25 26
ABC_NAMESPACE_IMPL_START


Alan Mishchenko committed
27 28 29 30 31 32 33 34 35 36
////////////////////////////////////////////////////////////////////////
///                        DECLARATIONS                              ///
////////////////////////////////////////////////////////////////////////

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

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

Alan Mishchenko committed
37
  Synopsis    [Allocates the graph.]
Alan Mishchenko committed
38 39 40 41 42 43 44 45

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
46
Nwk_Grf_t * Nwk_ManGraphAlloc( int nVertsMax )
Alan Mishchenko committed
47
{
Alan Mishchenko committed
48
    Nwk_Grf_t * p;
Alan Mishchenko committed
49
    p = ABC_ALLOC( Nwk_Grf_t, 1 );
Alan Mishchenko committed
50 51 52
    memset( p, 0, sizeof(Nwk_Grf_t) );
    p->nVertsMax = nVertsMax;
    p->nEdgeHash = Aig_PrimeCudd( 3 * nVertsMax );
Alan Mishchenko committed
53
    p->pEdgeHash = ABC_CALLOC( Nwk_Edg_t *, p->nEdgeHash );
Alan Mishchenko committed
54 55 56
    p->pMemEdges = Aig_MmFixedStart( sizeof(Nwk_Edg_t), p->nEdgeHash );
    p->vPairs    = Vec_IntAlloc( 1000 );
    return p;
Alan Mishchenko committed
57 58 59 60
}

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

Alan Mishchenko committed
61
  Synopsis    [Deallocates the graph.]
Alan Mishchenko committed
62 63 64 65 66 67 68 69

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
70
void Nwk_ManGraphFree( Nwk_Grf_t * p )
Alan Mishchenko committed
71
{
Alan Mishchenko committed
72 73 74
    if ( p->vPairs )    Vec_IntFree( p->vPairs );
    if ( p->pMemEdges ) Aig_MmFixedStop( p->pMemEdges, 0 );
    if ( p->pMemVerts ) Aig_MmFlexStop( p->pMemVerts, 0 );
Alan Mishchenko committed
75 76 77 78 79
    ABC_FREE( p->pVerts );
    ABC_FREE( p->pEdgeHash );
    ABC_FREE( p->pMapLut2Id );
    ABC_FREE( p->pMapId2Lut );
    ABC_FREE( p );
Alan Mishchenko committed
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123
}

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

  Synopsis    [Prepares the graph for solving the problem.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
void Nwk_ManGraphReportMemoryUsage( Nwk_Grf_t * p )
{
    p->nMemBytes1 = 
        sizeof(Nwk_Grf_t) +
        sizeof(void *) * p->nEdgeHash + 
        sizeof(int) * (p->nObjs + p->nVertsMax) +
        sizeof(Nwk_Edg_t) * p->nEdges;
    p->nMemBytes2 = 
        sizeof(Nwk_Vrt_t) * p->nVerts + 
        sizeof(int) * 2 * p->nEdges;
    printf( "Memory usage stats:  Preprocessing = %.2f Mb.  Solving = %.2f Mb.\n",
        1.0 * p->nMemBytes1 / (1<<20), 1.0 * p->nMemBytes2 / (1<<20) );
}


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

  Synopsis    [Finds or adds the edge to the graph.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
void Nwk_ManGraphHashEdge( Nwk_Grf_t * p, int iLut1, int iLut2 )
{
    Nwk_Edg_t * pEntry;
    unsigned Key;
    if ( iLut1 == iLut2 )
Alan Mishchenko committed
124
        return;
Alan Mishchenko committed
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
    if ( iLut1 > iLut2 )
    {
        Key = iLut1;
        iLut1 = iLut2;
        iLut2 = Key;
    }
    assert( iLut1 < iLut2 );
    if ( p->nObjs < iLut2 )
        p->nObjs = iLut2;
    Key = (unsigned)(741457 * iLut1 + 4256249 * iLut2) % p->nEdgeHash;
    for ( pEntry = p->pEdgeHash[Key]; pEntry; pEntry = pEntry->pNext )
        if ( pEntry->iNode1 == iLut1 && pEntry->iNode2 == iLut2 )
            return;
    pEntry = (Nwk_Edg_t *)Aig_MmFixedEntryFetch( p->pMemEdges );
    pEntry->iNode1 = iLut1;
    pEntry->iNode2 = iLut2;
    pEntry->pNext = p->pEdgeHash[Key];
    p->pEdgeHash[Key] = pEntry;
    p->nEdges++;
Alan Mishchenko committed
144 145 146 147
}

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

Alan Mishchenko committed
148
  Synopsis    [Adds one entry to the list.]
Alan Mishchenko committed
149 150 151 152 153 154 155 156

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
157
static inline void Nwk_ManGraphListAdd( Nwk_Grf_t * p, int * pList, Nwk_Vrt_t * pVertex )
Alan Mishchenko committed
158
{
Alan Mishchenko committed
159
    if ( *pList )
Alan Mishchenko committed
160
    {
Alan Mishchenko committed
161 162 163 164 165
        Nwk_Vrt_t * pHead;
        pHead = p->pVerts[*pList];
        pVertex->iPrev = 0;
        pVertex->iNext = pHead->Id;
        pHead->iPrev = pVertex->Id;
Alan Mishchenko committed
166
    }
Alan Mishchenko committed
167
    *pList = pVertex->Id;
Alan Mishchenko committed
168 169 170 171
}

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

Alan Mishchenko committed
172
  Synopsis    [Deletes one entry from the list.]
Alan Mishchenko committed
173 174 175 176 177 178 179 180

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
181
static inline void Nwk_ManGraphListDelete( Nwk_Grf_t * p, int * pList, Nwk_Vrt_t * pVertex )
Alan Mishchenko committed
182
{
Alan Mishchenko committed
183 184 185 186 187 188 189 190 191 192 193 194 195 196 197
    assert( *pList );
    if ( pVertex->iPrev )
    {
//        assert( p->pVerts[pVertex->iPrev]->iNext == pVertex->Id );
        p->pVerts[pVertex->iPrev]->iNext = pVertex->iNext;
    }
    if ( pVertex->iNext )
    {
//        assert( p->pVerts[pVertex->iNext]->iPrev == pVertex->Id );
        p->pVerts[pVertex->iNext]->iPrev = pVertex->iPrev;
    }
    if ( *pList == pVertex->Id )
        *pList = pVertex->iNext;
    pVertex->iPrev = pVertex->iNext = 0;
}
Alan Mishchenko committed
198

Alan Mishchenko committed
199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215
/**Function*************************************************************

  Synopsis    [Inserts the edge into one of the linked lists.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
static inline void Nwk_ManGraphListInsert( Nwk_Grf_t * p, Nwk_Vrt_t * pVertex )
{
    Nwk_Vrt_t * pNext;
    assert( pVertex->nEdges > 0 );

    if ( pVertex->nEdges == 1 )
Alan Mishchenko committed
216
    {
Alan Mishchenko committed
217 218 219 220 221 222 223 224 225 226 227 228
        pNext = p->pVerts[ pVertex->pEdges[0] ];
        if ( pNext->nEdges >= NWK_MAX_LIST )
            Nwk_ManGraphListAdd( p, p->pLists1 + NWK_MAX_LIST, pVertex );
        else
            Nwk_ManGraphListAdd( p, p->pLists1 + pNext->nEdges, pVertex );
    }
    else
    {
        if ( pVertex->nEdges >= NWK_MAX_LIST )
            Nwk_ManGraphListAdd( p, p->pLists2 + NWK_MAX_LIST, pVertex );
        else
            Nwk_ManGraphListAdd( p, p->pLists2 + pVertex->nEdges, pVertex );
Alan Mishchenko committed
229
    }
Alan Mishchenko committed
230
}
Alan Mishchenko committed
231

Alan Mishchenko committed
232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255
/**Function*************************************************************

  Synopsis    [Extracts the edge from one of the linked lists.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
static inline void Nwk_ManGraphListExtract( Nwk_Grf_t * p, Nwk_Vrt_t * pVertex )
{
    Nwk_Vrt_t * pNext;
    assert( pVertex->nEdges > 0 );

    if ( pVertex->nEdges == 1 )
    {
        pNext = p->pVerts[ pVertex->pEdges[0] ];
        if ( pNext->nEdges >= NWK_MAX_LIST )
            Nwk_ManGraphListDelete( p, p->pLists1 + NWK_MAX_LIST, pVertex );
        else
            Nwk_ManGraphListDelete( p, p->pLists1 + pNext->nEdges, pVertex );
    }
Alan Mishchenko committed
256 257
    else
    {
Alan Mishchenko committed
258 259 260 261
        if ( pVertex->nEdges >= NWK_MAX_LIST )
            Nwk_ManGraphListDelete( p, p->pLists2 + NWK_MAX_LIST, pVertex );
        else
            Nwk_ManGraphListDelete( p, p->pLists2 + pVertex->nEdges, pVertex );
Alan Mishchenko committed
262
    }
Alan Mishchenko committed
263
}
Alan Mishchenko committed
264

Alan Mishchenko committed
265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281
/**Function*************************************************************

  Synopsis    [Prepares the graph for solving the problem.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
void Nwk_ManGraphPrepare( Nwk_Grf_t * p )
{
    Nwk_Edg_t * pEntry;
    Nwk_Vrt_t * pVertex;
    int * pnEdges, nBytes, i;
    // allocate memory for the present objects
Alan Mishchenko committed
282 283
    p->pMapLut2Id = ABC_ALLOC( int, p->nObjs+1 );
    p->pMapId2Lut = ABC_ALLOC( int, p->nVertsMax+1 );
Alan Mishchenko committed
284 285 286 287
    memset( p->pMapLut2Id, 0xff, sizeof(int) * (p->nObjs+1) );
    memset( p->pMapId2Lut, 0xff, sizeof(int) * (p->nVertsMax+1) );
    // mark present objects
    Nwk_GraphForEachEdge( p, pEntry, i )
Alan Mishchenko committed
288
    {
Alan Mishchenko committed
289 290 291 292
        assert( pEntry->iNode1 <= p->nObjs );
        assert( pEntry->iNode2 <= p->nObjs );
        p->pMapLut2Id[ pEntry->iNode1 ] = 0;
        p->pMapLut2Id[ pEntry->iNode2 ] = 0;
Alan Mishchenko committed
293
    }
Alan Mishchenko committed
294 295 296 297 298 299 300 301 302 303 304
    // map objects
    p->nVerts = 0;
    for ( i = 0; i <= p->nObjs; i++ )
    {
        if ( p->pMapLut2Id[i] == 0 )
        {
            p->pMapLut2Id[i] = ++p->nVerts;
            p->pMapId2Lut[p->nVerts] = i;
        }
    }
    // count the edges and mark present objects
Alan Mishchenko committed
305
    pnEdges = ABC_CALLOC( int, p->nVerts+1 );
Alan Mishchenko committed
306 307 308 309 310 311 312 313 314 315 316 317 318 319 320
    Nwk_GraphForEachEdge( p, pEntry, i )
    {
        // translate into vertices
        assert( pEntry->iNode1 <= p->nObjs );
        assert( pEntry->iNode2 <= p->nObjs );
        pEntry->iNode1 = p->pMapLut2Id[pEntry->iNode1];
        pEntry->iNode2 = p->pMapLut2Id[pEntry->iNode2];
        // count the edges
        assert( pEntry->iNode1 <= p->nVerts );
        assert( pEntry->iNode2 <= p->nVerts );
        pnEdges[pEntry->iNode1]++;
        pnEdges[pEntry->iNode2]++;
    }
    // allocate the real graph
    p->pMemVerts  = Aig_MmFlexStart();
Alan Mishchenko committed
321
    p->pVerts = ABC_ALLOC( Nwk_Vrt_t *, p->nVerts + 1 );
Alan Mishchenko committed
322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346
    p->pVerts[0] = NULL;
    for ( i = 1; i <= p->nVerts; i++ )
    {
        assert( pnEdges[i] > 0 );
        nBytes = sizeof(Nwk_Vrt_t) + sizeof(int) * pnEdges[i];
        p->pVerts[i] = (Nwk_Vrt_t *)Aig_MmFlexEntryFetch( p->pMemVerts, nBytes );
        memset( p->pVerts[i], 0, nBytes );
        p->pVerts[i]->Id = i;
    }
    // add edges to the real graph
    Nwk_GraphForEachEdge( p, pEntry, i )
    {
        pVertex = p->pVerts[pEntry->iNode1];
        pVertex->pEdges[ pVertex->nEdges++ ] = pEntry->iNode2;
        pVertex = p->pVerts[pEntry->iNode2];
        pVertex->pEdges[ pVertex->nEdges++ ] = pEntry->iNode1;
    }
    // put vertices into the data structure
    for ( i = 1; i <= p->nVerts; i++ )
    {
        assert( p->pVerts[i]->nEdges == pnEdges[i] );
        Nwk_ManGraphListInsert( p, p->pVerts[i] );
    }
    // clean up
    Aig_MmFixedStop( p->pMemEdges, 0 ); p->pMemEdges = NULL;
Alan Mishchenko committed
347
    ABC_FREE( p->pEdgeHash );
Alan Mishchenko committed
348
//    p->nEdgeHash = 0;
Alan Mishchenko committed
349
    ABC_FREE( pnEdges );
Alan Mishchenko committed
350 351
}

Alan Mishchenko committed
352 353
/**Function*************************************************************

Alan Mishchenko committed
354 355 356 357 358 359 360 361 362 363 364 365 366 367
  Synopsis    [Sort pairs by the first vertex in the topological order.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
void Nwk_ManGraphSortPairs( Nwk_Grf_t * p )
{
    int nSize = Vec_IntSize(p->vPairs);
    int * pIdToPair, i;
    // allocate storage
Alan Mishchenko committed
368
    pIdToPair = ABC_ALLOC( int, p->nObjs+1 );
Alan Mishchenko committed
369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386
    for ( i = 0; i <= p->nObjs; i++ )
        pIdToPair[i] = -1;
    // create mapping
    for ( i = 0; i < p->vPairs->nSize; i += 2 )
    {
        assert( pIdToPair[ p->vPairs->pArray[i] ] == -1 );
        pIdToPair[ p->vPairs->pArray[i] ] = p->vPairs->pArray[i+1];
    }
    // recreate pairs
    Vec_IntClear( p->vPairs );
    for ( i = 0; i <= p->nObjs; i++ )
        if ( pIdToPair[i] >= 0 )
        {
            assert( i < pIdToPair[i] );
            Vec_IntPush( p->vPairs, i );
            Vec_IntPush( p->vPairs, pIdToPair[i] );
        }
    assert( nSize == Vec_IntSize(p->vPairs) );
Alan Mishchenko committed
387
    ABC_FREE( pIdToPair );
Alan Mishchenko committed
388 389 390 391 392
}


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

Alan Mishchenko committed
393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424
  Synopsis    [Updates the problem after pulling out one edge.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
void Nwk_ManGraphCheckLists( Nwk_Grf_t * p )
{
    Nwk_Vrt_t * pVertex, * pNext;
    int i, j;
    assert( p->pLists1[0] == 0 );
    for ( i = 1; i <= NWK_MAX_LIST; i++ )
        if ( p->pLists1[i] )
        {
            pVertex = p->pVerts[ p->pLists1[i] ];
            assert( pVertex->nEdges == 1 );
            pNext = p->pVerts[ pVertex->pEdges[0] ];
            assert( pNext->nEdges == i || pNext->nEdges > NWK_MAX_LIST );
        }
    // find the next vertext to extract
    assert( p->pLists2[0] == 0 );
    assert( p->pLists2[1] == 0 );
    for ( j = 2; j <= NWK_MAX_LIST; j++ )
        if ( p->pLists2[j] )
        {
            pVertex = p->pVerts[ p->pLists2[j] ];
            assert( pVertex->nEdges == j || pVertex->nEdges > NWK_MAX_LIST );
        }
}
Alan Mishchenko committed
425 426 427

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

Alan Mishchenko committed
428
  Synopsis    [Extracts the edge from one of the linked lists.]
Alan Mishchenko committed
429 430 431 432 433 434 435 436

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
437
static inline void Nwk_ManGraphVertexRemoveEdge( Nwk_Vrt_t * pThis, Nwk_Vrt_t * pNext )
Alan Mishchenko committed
438
{
Alan Mishchenko committed
439 440 441 442 443 444 445 446
    int k;
    for ( k = 0; k < pThis->nEdges; k++ )
        if ( pThis->pEdges[k] == pNext->Id )
            break;
    assert( k < pThis->nEdges );
    pThis->nEdges--;
    for ( ; k < pThis->nEdges; k++ )
        pThis->pEdges[k] = pThis->pEdges[k+1];
Alan Mishchenko committed
447 448 449 450
}

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

Alan Mishchenko committed
451
  Synopsis    [Updates the problem after pulling out one edge.]
Alan Mishchenko committed
452 453 454 455 456 457 458 459

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
460
void Nwk_ManGraphUpdate( Nwk_Grf_t * p, Nwk_Vrt_t * pVertex, Nwk_Vrt_t * pNext )
Alan Mishchenko committed
461
{
Alan Mishchenko committed
462
    Nwk_Vrt_t * pChanged, * pOther;
Alan Mishchenko committed
463
    int i, k;
Alan Mishchenko committed
464 465 466 467 468
//    Nwk_ManGraphCheckLists( p );
    Nwk_ManGraphListExtract( p, pVertex );
    Nwk_ManGraphListExtract( p, pNext );
    // update neihbors of pVertex
    Nwk_VertexForEachAdjacent( p, pVertex, pChanged, i )
Alan Mishchenko committed
469
    {
Alan Mishchenko committed
470
        if ( pChanged == pNext )
Alan Mishchenko committed
471
            continue;
Alan Mishchenko committed
472 473 474 475
        Nwk_ManGraphListExtract( p, pChanged );
        // move those that use this one
        if ( pChanged->nEdges > 1 )
        Nwk_VertexForEachAdjacent( p, pChanged, pOther, k )
Alan Mishchenko committed
476
        {
Alan Mishchenko committed
477
            if ( pOther == pVertex || pOther->nEdges > 1 )
Alan Mishchenko committed
478
                continue;
Alan Mishchenko committed
479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501
            assert( pOther->nEdges == 1 );
            Nwk_ManGraphListExtract( p, pOther );
            pChanged->nEdges--;
            Nwk_ManGraphListInsert( p, pOther );
            pChanged->nEdges++;
        }
        // remove the edge
        Nwk_ManGraphVertexRemoveEdge( pChanged, pVertex );
        // add the changed vertex back
        if ( pChanged->nEdges > 0 )
            Nwk_ManGraphListInsert( p, pChanged );
    }
    // update neihbors of pNext
    Nwk_VertexForEachAdjacent( p, pNext, pChanged, i )
    {
        if ( pChanged == pVertex )
            continue;
        Nwk_ManGraphListExtract( p, pChanged );
        // move those that use this one
        if ( pChanged->nEdges > 1 )
        Nwk_VertexForEachAdjacent( p, pChanged, pOther, k )
        {
            if ( pOther == pNext || pOther->nEdges > 1 )
Alan Mishchenko committed
502
                continue;
Alan Mishchenko committed
503 504 505 506 507
            assert( pOther->nEdges == 1 );
            Nwk_ManGraphListExtract( p, pOther );
            pChanged->nEdges--;
            Nwk_ManGraphListInsert( p, pOther );
            pChanged->nEdges++;
Alan Mishchenko committed
508
        }
Alan Mishchenko committed
509 510 511 512 513
        // remove the edge
        Nwk_ManGraphVertexRemoveEdge( pChanged, pNext );
        // add the changed vertex back
        if ( pChanged->nEdges > 0 )
            Nwk_ManGraphListInsert( p, pChanged );
Alan Mishchenko committed
514
    }
Alan Mishchenko committed
515 516 517 518 519 520 521 522 523 524 525 526
    // add to the result
    if ( pVertex->Id < pNext->Id )
    {
        Vec_IntPush( p->vPairs, p->pMapId2Lut[pVertex->Id] ); 
        Vec_IntPush( p->vPairs, p->pMapId2Lut[pNext->Id] ); 
    }
    else
    {
        Vec_IntPush( p->vPairs, p->pMapId2Lut[pNext->Id] ); 
        Vec_IntPush( p->vPairs, p->pMapId2Lut[pVertex->Id] ); 
    }
//    Nwk_ManGraphCheckLists( p );
Alan Mishchenko committed
527 528
}

Alan Mishchenko committed
529
/**Function*************************************************************
Alan Mishchenko committed
530

Alan Mishchenko committed
531
  Synopsis    [Counts the number of entries in the list.]
Alan Mishchenko committed
532

Alan Mishchenko committed
533 534 535
  Description []
               
  SideEffects []
Alan Mishchenko committed
536

Alan Mishchenko committed
537 538 539 540
  SeeAlso     []

***********************************************************************/
int Nwk_ManGraphListLength( Nwk_Grf_t * p, int List )
Alan Mishchenko committed
541
{
Alan Mishchenko committed
542 543 544 545 546 547 548 549 550 551 552 553 554
    Nwk_Vrt_t * pThis;
    int fVerbose = 0;
    int Counter = 0;
    Nwk_ListForEachVertex( p, List, pThis )
    {
        if ( fVerbose && Counter < 20 )
            printf( "%d ", p->pVerts[pThis->pEdges[0]]->nEdges );
        Counter++;
    }
    if ( fVerbose )
        printf( "\n" );
    return Counter;
}
Alan Mishchenko committed
555 556 557

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

Alan Mishchenko committed
558
  Synopsis    [Returns the adjacent vertex with the mininum number of edges.]
Alan Mishchenko committed
559 560 561 562 563 564 565 566

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
567
Nwk_Vrt_t * Nwk_ManGraphListFindMinEdge( Nwk_Grf_t * p, Nwk_Vrt_t * pVert )
Alan Mishchenko committed
568
{
Alan Mishchenko committed
569 570 571 572 573 574 575 576
    Nwk_Vrt_t * pThis, * pMinCost = NULL;
    int k;
    Nwk_VertexForEachAdjacent( p, pVert, pThis, k )
    {
        if ( pMinCost == NULL || pMinCost->nEdges > pThis->nEdges )
            pMinCost = pThis;
    }
    return pMinCost;
Alan Mishchenko committed
577 578 579 580
}

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

Alan Mishchenko committed
581
  Synopsis    [Finds the best vertext in the list.]
Alan Mishchenko committed
582 583 584 585 586 587 588 589

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
590
Nwk_Vrt_t * Nwk_ManGraphListFindMin( Nwk_Grf_t * p, int List )
Alan Mishchenko committed
591
{
Alan Mishchenko committed
592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607
    Nwk_Vrt_t * pThis, * pMinCost = NULL;
    int k, Counter = 10000, BestCost = 1000000;
    Nwk_ListForEachVertex( p, List, pThis )
    {
        for ( k = 0; k < pThis->nEdges; k++ )
        {
            if ( pMinCost == NULL || BestCost > p->pVerts[pThis->pEdges[k]]->nEdges )
            {
                BestCost = p->pVerts[pThis->pEdges[k]]->nEdges;
                pMinCost = pThis;
            }
        }
        if ( --Counter == 0 )
            break;
    }
    return pMinCost;
Alan Mishchenko committed
608 609 610 611
}

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

Alan Mishchenko committed
612
  Synopsis    [Solves the problem by extracting one edge at a time.]
Alan Mishchenko committed
613 614 615 616 617 618 619 620

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
621
void Nwk_ManGraphSolve( Nwk_Grf_t * p )
Alan Mishchenko committed
622
{
Alan Mishchenko committed
623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659
    Nwk_Vrt_t * pVertex, * pNext;
    int i, j;
    Nwk_ManGraphPrepare( p );
    while ( 1 )
    {
        // find the next vertex to extract
        assert( p->pLists1[0] == 0 );
        for ( i = 1; i <= NWK_MAX_LIST; i++ )
            if ( p->pLists1[i] )
            {
//                printf( "%d ", i );
//                printf( "ListA = %2d. Length = %5d.\n", i, Nwk_ManGraphListLength(p,p->pLists1[i]) );
                pVertex = p->pVerts[ p->pLists1[i] ];
                assert( pVertex->nEdges == 1 );
                pNext = p->pVerts[ pVertex->pEdges[0] ];
                Nwk_ManGraphUpdate( p, pVertex, pNext );
                break;
            }
        if ( i < NWK_MAX_LIST + 1 )
            continue;
        // find the next vertex to extract
        assert( p->pLists2[0] == 0 );
        assert( p->pLists2[1] == 0 );
        for ( j = 2; j <= NWK_MAX_LIST; j++ )
            if ( p->pLists2[j] )
            {
//                printf( "***%d ", j );
//                printf( "ListB = %2d. Length = %5d.\n", j, Nwk_ManGraphListLength(p,p->pLists2[j]) );
                pVertex = Nwk_ManGraphListFindMin( p, p->pLists2[j] ); 
                assert( pVertex->nEdges == j || j == NWK_MAX_LIST );
                pNext = Nwk_ManGraphListFindMinEdge( p, pVertex );
                Nwk_ManGraphUpdate( p, pVertex, pNext );
                break;
            }
        if ( j == NWK_MAX_LIST + 1 )
            break;
    }
Alan Mishchenko committed
660
    Nwk_ManGraphSortPairs( p );
Alan Mishchenko committed
661 662 663 664
}

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

Alan Mishchenko committed
665
  Synopsis    [Reads graph from file.]
Alan Mishchenko committed
666 667 668 669 670 671 672 673

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
674
Nwk_Grf_t * Nwk_ManLutMergeReadGraph( char * pFileName )
Alan Mishchenko committed
675
{
Alan Mishchenko committed
676 677 678 679 680 681 682 683 684 685 686 687 688
    Nwk_Grf_t * p;
    FILE * pFile;
    char Buffer[100];
    int nNodes, nEdges, iNode1, iNode2;
    pFile = fopen( pFileName, "r" );
    fscanf( pFile, "%s %d", Buffer, &nNodes );
    fscanf( pFile, "%s %d", Buffer, &nEdges );
    p = Nwk_ManGraphAlloc( nNodes );
    while ( fscanf( pFile, "%s %d %d", Buffer, &iNode1, &iNode2 ) == 3 )
        Nwk_ManGraphHashEdge( p, iNode1, iNode2 );
    assert( p->nEdges == nEdges );
    fclose( pFile );
    return p;
Alan Mishchenko committed
689 690 691 692
}

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

Alan Mishchenko committed
693
  Synopsis    [Solves the graph coming from file.]
Alan Mishchenko committed
694 695 696 697 698 699 700 701

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
702
int Nwk_ManLutMergeGraphTest( char * pFileName )
Alan Mishchenko committed
703
{
Alan Mishchenko committed
704 705 706 707
    int nPairs;
    Nwk_Grf_t * p;
    int clk = clock();
    p = Nwk_ManLutMergeReadGraph( pFileName );
Alan Mishchenko committed
708
    ABC_PRT( "Reading", clock() - clk );
Alan Mishchenko committed
709 710 711 712
    clk = clock();
    Nwk_ManGraphSolve( p );
    printf( "GRAPH: Nodes = %6d. Edges = %6d.  Pairs = %6d.  ", 
        p->nVerts, p->nEdges, Vec_IntSize(p->vPairs)/2 );
Alan Mishchenko committed
713
    ABC_PRT( "Solving", clock() - clk );
Alan Mishchenko committed
714 715 716 717
    nPairs = Vec_IntSize(p->vPairs)/2;
    Nwk_ManGraphReportMemoryUsage( p );
    Nwk_ManGraphFree( p );
    return nPairs;
Alan Mishchenko committed
718 719
}

Alan Mishchenko committed
720 721 722



Alan Mishchenko committed
723 724
/**Function*************************************************************

Alan Mishchenko committed
725
  Synopsis    [Marks the fanins of the node with the current trav ID.]
Alan Mishchenko committed
726 727 728 729 730 731 732 733

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
734
void Nwk_ManMarkFanins_rec( Nwk_Obj_t * pLut, int nLevMin )
Alan Mishchenko committed
735
{
Alan Mishchenko committed
736 737 738 739 740 741 742 743 744 745 746
    Nwk_Obj_t * pNext;
    int i;
    if ( !Nwk_ObjIsNode(pLut) )
        return;
    if ( Nwk_ObjIsTravIdCurrent( pLut ) )
        return;
    Nwk_ObjSetTravIdCurrent( pLut );
    if ( Nwk_ObjLevel(pLut) < nLevMin )
        return;
    Nwk_ObjForEachFanin( pLut, pNext, i )
        Nwk_ManMarkFanins_rec( pNext, nLevMin );
Alan Mishchenko committed
747 748 749 750
}

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

Alan Mishchenko committed
751
  Synopsis    [Marks the fanouts of the node with the current trav ID.]
Alan Mishchenko committed
752 753 754 755 756 757 758 759

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
760
void Nwk_ManMarkFanouts_rec( Nwk_Obj_t * pLut, int nLevMax, int nFanMax )
Alan Mishchenko committed
761
{
Alan Mishchenko committed
762 763 764 765 766 767 768 769 770 771 772 773 774
    Nwk_Obj_t * pNext;
    int i;
    if ( !Nwk_ObjIsNode(pLut) )
        return;
    if ( Nwk_ObjIsTravIdCurrent( pLut ) )
        return;
    Nwk_ObjSetTravIdCurrent( pLut );
    if ( Nwk_ObjLevel(pLut) > nLevMax )
        return;
    if ( Nwk_ObjFanoutNum(pLut) > nFanMax )
        return;
    Nwk_ObjForEachFanout( pLut, pNext, i )
        Nwk_ManMarkFanouts_rec( pNext, nLevMax, nFanMax );
Alan Mishchenko committed
775 776 777 778
}

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

Alan Mishchenko committed
779
  Synopsis    [Collects the circle of nodes around the given set.]
Alan Mishchenko committed
780 781 782 783 784 785 786 787

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
788
void Nwk_ManCollectCircle( Vec_Ptr_t * vStart, Vec_Ptr_t * vNext, int nFanMax )
Alan Mishchenko committed
789
{
Alan Mishchenko committed
790 791 792
    Nwk_Obj_t * pObj, * pNext;
    int i, k;
    Vec_PtrClear( vNext );
793
    Vec_PtrForEachEntry( Nwk_Obj_t *, vStart, pObj, i )
Alan Mishchenko committed
794
    {
Alan Mishchenko committed
795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814
        Nwk_ObjForEachFanin( pObj, pNext, k )
        {
            if ( !Nwk_ObjIsNode(pNext) )
                continue;
            if ( Nwk_ObjIsTravIdCurrent( pNext ) )
                continue;
            Nwk_ObjSetTravIdCurrent( pNext );
            Vec_PtrPush( vNext, pNext );
        }
        Nwk_ObjForEachFanout( pObj, pNext, k )
        {
            if ( !Nwk_ObjIsNode(pNext) )
                continue;
            if ( Nwk_ObjIsTravIdCurrent( pNext ) )
                continue;
            Nwk_ObjSetTravIdCurrent( pNext );
            if ( Nwk_ObjFanoutNum(pNext) > nFanMax )
                continue;
            Vec_PtrPush( vNext, pNext );
        }
Alan Mishchenko committed
815 816 817 818 819
    }
}

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

Alan Mishchenko committed
820
  Synopsis    [Collects the circle of nodes removes from the given one.]
Alan Mishchenko committed
821 822 823 824 825 826 827 828

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
829
void Nwk_ManCollectNonOverlapCands( Nwk_Obj_t * pLut, Vec_Ptr_t * vStart, Vec_Ptr_t * vNext, Vec_Ptr_t * vCands, Nwk_LMPars_t * pPars )
Alan Mishchenko committed
830
{
Alan Mishchenko committed
831 832 833 834 835 836 837 838 839 840 841 842 843 844
    Vec_Ptr_t * vTemp;
    Nwk_Obj_t * pObj;
    int i, k;
    Vec_PtrClear( vCands );
    if ( pPars->nMaxSuppSize - Nwk_ObjFaninNum(pLut) <= 1 )
        return;

    // collect nodes removed by this distance
    assert( pPars->nMaxDistance > 0 );
    Vec_PtrClear( vStart );
    Vec_PtrPush( vStart, pLut );
    Nwk_ManIncrementTravId( pLut->pMan );
    Nwk_ObjSetTravIdCurrent( pLut );
    for ( i = 1; i <= pPars->nMaxDistance; i++ )
Alan Mishchenko committed
845
    {
Alan Mishchenko committed
846 847 848 849 850
        Nwk_ManCollectCircle( vStart, vNext, pPars->nMaxFanout );
        vTemp  = vStart;
        vStart = vNext;
        vNext  = vTemp;
        // collect the nodes in vStart
851
        Vec_PtrForEachEntry( Nwk_Obj_t *, vStart, pObj, k )
Alan Mishchenko committed
852
            Vec_PtrPush( vCands, pObj );
Alan Mishchenko committed
853
    }
Alan Mishchenko committed
854 855 856 857 858 859

    // mark the TFI/TFO nodes
    Nwk_ManIncrementTravId( pLut->pMan );
    if ( pPars->fUseTfiTfo )
        Nwk_ObjSetTravIdCurrent( pLut );
    else
Alan Mishchenko committed
860
    {
Alan Mishchenko committed
861 862 863 864
        Nwk_ObjSetTravIdPrevious( pLut );
        Nwk_ManMarkFanins_rec( pLut, Nwk_ObjLevel(pLut) - pPars->nMaxDistance );
        Nwk_ObjSetTravIdPrevious( pLut );
        Nwk_ManMarkFanouts_rec( pLut, Nwk_ObjLevel(pLut) + pPars->nMaxDistance, pPars->nMaxFanout );
Alan Mishchenko committed
865
    }
Alan Mishchenko committed
866 867 868 869 870 871 872

    // collect nodes satisfying the following conditions:
    // - they are close enough in terms of distance
    // - they are not in the TFI/TFO of the LUT
    // - they have no more than the given number of fanins
    // - they have no more than the given diff in delay
    k = 0;
873
    Vec_PtrForEachEntry( Nwk_Obj_t *, vCands, pObj, i )
Alan Mishchenko committed
874 875 876 877 878 879 880 881 882 883 884
    {
        if ( Nwk_ObjIsTravIdCurrent(pObj) )
            continue;
        if ( Nwk_ObjFaninNum(pLut) + Nwk_ObjFaninNum(pObj) > pPars->nMaxSuppSize )
            continue;
        if ( Nwk_ObjLevel(pLut) - Nwk_ObjLevel(pObj) > pPars->nMaxLevelDiff || 
             Nwk_ObjLevel(pObj) - Nwk_ObjLevel(pLut) > pPars->nMaxLevelDiff )
             continue;
        Vec_PtrWriteEntry( vCands, k++, pObj );
    }
    Vec_PtrShrink( vCands, k );
Alan Mishchenko committed
885 886
}

Alan Mishchenko committed
887

Alan Mishchenko committed
888 889
/**Function*************************************************************

Alan Mishchenko committed
890
  Synopsis    [Count the total number of fanins.]
Alan Mishchenko committed
891 892 893 894 895 896 897 898

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
899
int Nwk_ManCountTotalFanins( Nwk_Obj_t * pLut, Nwk_Obj_t * pCand )
Alan Mishchenko committed
900
{
Alan Mishchenko committed
901 902 903 904 905
    Nwk_Obj_t * pFanin;
    int i, nCounter = Nwk_ObjFaninNum(pLut);
    Nwk_ObjForEachFanin( pCand, pFanin, i )
        nCounter += !pFanin->MarkC;
    return nCounter;
Alan Mishchenko committed
906 907 908 909
}

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

Alan Mishchenko committed
910
  Synopsis    [Collects overlapping candidates.]
Alan Mishchenko committed
911 912 913 914 915 916 917 918

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
919
void Nwk_ManCollectOverlapCands( Nwk_Obj_t * pLut, Vec_Ptr_t * vCands, Nwk_LMPars_t * pPars )
Alan Mishchenko committed
920
{
Alan Mishchenko committed
921 922 923 924 925 926 927 928 929 930
    Nwk_Obj_t * pFanin, * pObj;
    int i, k;
    // mark fanins of pLut
    Nwk_ObjForEachFanin( pLut, pFanin, i )
        pFanin->MarkC = 1;
    // collect the matching fanouts of each fanin of the node
    Vec_PtrClear( vCands );
    Nwk_ManIncrementTravId( pLut->pMan );
    Nwk_ObjSetTravIdCurrent( pLut );
    Nwk_ObjForEachFanin( pLut, pFanin, i )
Alan Mishchenko committed
931
    {
Alan Mishchenko committed
932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951
        if ( !Nwk_ObjIsNode(pFanin) )
            continue;
        if ( Nwk_ObjFanoutNum(pFanin) > pPars->nMaxFanout )
            continue;
        Nwk_ObjForEachFanout( pFanin, pObj, k )
        {
            if ( !Nwk_ObjIsNode(pObj) )
                continue;
            if ( Nwk_ObjIsTravIdCurrent( pObj ) )
                continue;
            Nwk_ObjSetTravIdCurrent( pObj );
            // check the difference in delay
            if ( Nwk_ObjLevel(pLut) - Nwk_ObjLevel(pObj) > pPars->nMaxLevelDiff || 
                 Nwk_ObjLevel(pObj) - Nwk_ObjLevel(pLut) > pPars->nMaxLevelDiff )
                 continue;
            // check the total number of fanins of the node
            if ( Nwk_ManCountTotalFanins(pLut, pObj) > pPars->nMaxSuppSize )
                continue;
            Vec_PtrPush( vCands, pObj );
        }
Alan Mishchenko committed
952
    }
Alan Mishchenko committed
953 954 955
    // unmark fanins of pLut
    Nwk_ObjForEachFanin( pLut, pFanin, i )
        pFanin->MarkC = 0;
Alan Mishchenko committed
956 957 958 959 960 961 962 963 964 965 966 967 968
}

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

  Synopsis    [Performs LUT merging with parameters.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
969
Vec_Int_t * Nwk_ManLutMerge( Nwk_Man_t * pNtk, void * pParsInit )
Alan Mishchenko committed
970
{
971
    Nwk_LMPars_t * pPars = (Nwk_LMPars_t *)pParsInit;
Alan Mishchenko committed
972 973 974 975
    Nwk_Grf_t * p;
    Vec_Int_t * vResult;
    Vec_Ptr_t * vStart, * vNext, * vCands1, * vCands2;
    Nwk_Obj_t * pLut, * pCand;
Alan Mishchenko committed
976
    int i, k, nVertsMax, nCands, clk = clock();
Alan Mishchenko committed
977
    // count the number of vertices
Alan Mishchenko committed
978
    nVertsMax = 0;
Alan Mishchenko committed
979
    Nwk_ManForEachNode( pNtk, pLut, i )
Alan Mishchenko committed
980 981
        nVertsMax += (int)(Nwk_ObjFaninNum(pLut) <= pPars->nMaxLutSize);
    p = Nwk_ManGraphAlloc( nVertsMax );
Alan Mishchenko committed
982 983 984 985 986
    // create graph
    vStart  = Vec_PtrAlloc( 1000 );
    vNext   = Vec_PtrAlloc( 1000 );
    vCands1 = Vec_PtrAlloc( 1000 );
    vCands2 = Vec_PtrAlloc( 1000 );
Alan Mishchenko committed
987
    nCands  = 0;
Alan Mishchenko committed
988 989 990 991
    Nwk_ManForEachNode( pNtk, pLut, i )
    {
        if ( Nwk_ObjFaninNum(pLut) > pPars->nMaxLutSize )
            continue;
Alan Mishchenko committed
992
        Nwk_ManCollectOverlapCands( pLut, vCands1, pPars );
Alan Mishchenko committed
993 994
        if ( pPars->fUseDiffSupp )
            Nwk_ManCollectNonOverlapCands( pLut, vStart, vNext, vCands2, pPars );
Alan Mishchenko committed
995 996
        if ( Vec_PtrSize(vCands1) == 0 && Vec_PtrSize(vCands2) == 0 )
            continue;
Alan Mishchenko committed
997
        nCands += Vec_PtrSize(vCands1) + Vec_PtrSize(vCands2);
Alan Mishchenko committed
998
        // save candidates
999
        Vec_PtrForEachEntry( Nwk_Obj_t *, vCands1, pCand, k )
Alan Mishchenko committed
1000
            Nwk_ManGraphHashEdge( p, Nwk_ObjId(pLut), Nwk_ObjId(pCand) );
1001
        Vec_PtrForEachEntry( Nwk_Obj_t *, vCands2, pCand, k )
Alan Mishchenko committed
1002 1003
            Nwk_ManGraphHashEdge( p, Nwk_ObjId(pLut), Nwk_ObjId(pCand) );
        // print statistics about this node
Alan Mishchenko committed
1004
        if ( pPars->fVeryVerbose )
Alan Mishchenko committed
1005 1006 1007 1008 1009 1010 1011 1012
        printf( "Node %6d : Fanins = %d. Fanouts = %3d.  Cand1 = %3d. Cand2 = %3d.\n",
            Nwk_ObjId(pLut), Nwk_ObjFaninNum(pLut), Nwk_ObjFaninNum(pLut), 
            Vec_PtrSize(vCands1), Vec_PtrSize(vCands2) );
    }
    Vec_PtrFree( vStart );
    Vec_PtrFree( vNext );
    Vec_PtrFree( vCands1 );
    Vec_PtrFree( vCands2 );
Alan Mishchenko committed
1013 1014 1015
    if ( pPars->fVerbose )
    {
        printf( "Mergable LUTs = %6d. Total cands = %6d. ", p->nVertsMax, nCands );
Alan Mishchenko committed
1016
        ABC_PRT( "Deriving graph", clock() - clk );
Alan Mishchenko committed
1017
    }
Alan Mishchenko committed
1018
    // solve the graph problem
Alan Mishchenko committed
1019
    clk = clock();
Alan Mishchenko committed
1020
    Nwk_ManGraphSolve( p );
Alan Mishchenko committed
1021 1022 1023 1024
    if ( pPars->fVerbose )
    {
        printf( "GRAPH: Nodes = %6d. Edges = %6d.  Pairs = %6d.  ", 
            p->nVerts, p->nEdges, Vec_IntSize(p->vPairs)/2 );
Alan Mishchenko committed
1025
        ABC_PRT( "Solving", clock() - clk );
Alan Mishchenko committed
1026 1027
        Nwk_ManGraphReportMemoryUsage( p );
    }
Alan Mishchenko committed
1028
    vResult = p->vPairs; p->vPairs = NULL;
Alan Mishchenko committed
1029
/*
Alan Mishchenko committed
1030 1031 1032
    for ( i = 0; i < vResult->nSize; i += 2 )
        printf( "(%d,%d) ", vResult->pArray[i], vResult->pArray[i+1] );
    printf( "\n" );
Alan Mishchenko committed
1033
*/
Alan Mishchenko committed
1034 1035 1036 1037 1038 1039 1040 1041 1042
    Nwk_ManGraphFree( p );
    return vResult;
}

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


1043 1044
ABC_NAMESPACE_IMPL_END