nwkMerge.c 30.9 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
    memset( p, 0, sizeof(Nwk_Grf_t) );
    p->nVertsMax = nVertsMax;
52
    p->nEdgeHash = Abc_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
}

/**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;
103
    printf( "Memory usage stats:  Preprocessing = %.2f MB.  Solving = %.2f MB.\n",
Alan Mishchenko committed
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123
        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
    Nwk_Grf_t * p;
    FILE * pFile;
    char Buffer[100];
    int nNodes, nEdges, iNode1, iNode2;
680
    int RetValue;
Alan Mishchenko committed
681
    pFile = fopen( pFileName, "r" );
682 683
    RetValue = fscanf( pFile, "%s %d", Buffer, &nNodes );
    RetValue = fscanf( pFile, "%s %d", Buffer, &nEdges );
Alan Mishchenko committed
684 685 686 687 688 689
    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
690 691 692 693
}

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

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

  Description []
               
  SideEffects []

  SeeAlso     []

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

Alan Mishchenko committed
721 722 723



Alan Mishchenko committed
724 725
/**Function*************************************************************

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

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
735
void Nwk_ManMarkFanins_rec( Nwk_Obj_t * pLut, int nLevMin )
Alan Mishchenko committed
736
{
Alan Mishchenko committed
737 738 739 740 741 742 743 744 745 746 747
    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
748 749 750 751
}

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

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

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
761
void Nwk_ManMarkFanouts_rec( Nwk_Obj_t * pLut, int nLevMax, int nFanMax )
Alan Mishchenko committed
762
{
Alan Mishchenko committed
763 764 765 766 767 768 769 770 771 772 773 774 775
    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
776 777 778 779
}

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

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

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
789
void Nwk_ManCollectCircle( Vec_Ptr_t * vStart, Vec_Ptr_t * vNext, int nFanMax )
Alan Mishchenko committed
790
{
Alan Mishchenko committed
791 792 793
    Nwk_Obj_t * pObj, * pNext;
    int i, k;
    Vec_PtrClear( vNext );
794
    Vec_PtrForEachEntry( Nwk_Obj_t *, vStart, pObj, i )
Alan Mishchenko committed
795
    {
Alan Mishchenko committed
796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815
        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
816 817 818 819 820
    }
}

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

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

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
830
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
831
{
Alan Mishchenko committed
832 833 834 835 836 837 838 839 840 841 842 843 844 845
    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
846
    {
Alan Mishchenko committed
847 848 849 850 851
        Nwk_ManCollectCircle( vStart, vNext, pPars->nMaxFanout );
        vTemp  = vStart;
        vStart = vNext;
        vNext  = vTemp;
        // collect the nodes in vStart
852
        Vec_PtrForEachEntry( Nwk_Obj_t *, vStart, pObj, k )
Alan Mishchenko committed
853
            Vec_PtrPush( vCands, pObj );
Alan Mishchenko committed
854
    }
Alan Mishchenko committed
855 856 857 858 859 860

    // mark the TFI/TFO nodes
    Nwk_ManIncrementTravId( pLut->pMan );
    if ( pPars->fUseTfiTfo )
        Nwk_ObjSetTravIdCurrent( pLut );
    else
Alan Mishchenko committed
861
    {
Alan Mishchenko committed
862 863 864 865
        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
866
    }
Alan Mishchenko committed
867 868 869 870 871 872 873

    // 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;
874
    Vec_PtrForEachEntry( Nwk_Obj_t *, vCands, pObj, i )
Alan Mishchenko committed
875 876 877 878 879 880 881 882 883 884 885
    {
        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
886 887
}

Alan Mishchenko committed
888

Alan Mishchenko committed
889 890
/**Function*************************************************************

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

  Description []
               
  SideEffects []

  SeeAlso     []

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

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

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

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
920
void Nwk_ManCollectOverlapCands( Nwk_Obj_t * pLut, Vec_Ptr_t * vCands, Nwk_LMPars_t * pPars )
Alan Mishchenko committed
921
{
Alan Mishchenko committed
922 923 924 925 926 927 928 929 930 931
    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
932
    {
Alan Mishchenko committed
933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952
        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
953
    }
Alan Mishchenko committed
954 955 956
    // unmark fanins of pLut
    Nwk_ObjForEachFanin( pLut, pFanin, i )
        pFanin->MarkC = 0;
Alan Mishchenko committed
957 958 959 960 961 962 963 964 965 966 967 968 969
}

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

  Synopsis    [Performs LUT merging with parameters.]

  Description []
               
  SideEffects []

  SeeAlso     []

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

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


1045 1046
ABC_NAMESPACE_IMPL_END