abcReconv.c 24.6 KB
Newer Older
Alan Mishchenko committed
1 2
/**CFile****************************************************************

Alan Mishchenko committed
3
  FileName    [abcReconv.c]
Alan Mishchenko committed
4 5 6 7 8

  SystemName  [ABC: Logic synthesis and verification system.]

  PackageName [Network and node package.]

Alan Mishchenko committed
9
  Synopsis    [Computation of reconvergence-driven cuts.]
Alan Mishchenko committed
10 11 12 13 14 15 16

  Author      [Alan Mishchenko]
  
  Affiliation [UC Berkeley]

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

Alan Mishchenko committed
17
  Revision    [$Id: abcReconv.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
Alan Mishchenko committed
18 19 20

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

21
#include "base/abc/abc.h"
22 23

#ifdef ABC_USE_CUDD
24
#include "bdd/extrab/extraBdd.h"
25
#endif
Alan Mishchenko committed
26

27 28 29
ABC_NAMESPACE_IMPL_START


Alan Mishchenko committed
30 31 32 33 34 35 36 37 38
////////////////////////////////////////////////////////////////////////
///                        DECLARATIONS                              ///
////////////////////////////////////////////////////////////////////////

struct Abc_ManCut_t_
{
    // user specified parameters
    int              nNodeSizeMax;  // the limit on the size of the supernode
    int              nConeSizeMax;  // the limit on the size of the containing cone
Alan Mishchenko committed
39 40
    int              nNodeFanStop;  // the limit on the size of the supernode
    int              nConeFanStop;  // the limit on the size of the containing cone
Alan Mishchenko committed
41
    // internal parameters
Alan Mishchenko committed
42 43
    Vec_Ptr_t *      vNodeLeaves;   // fanins of the collapsed node (the cut)
    Vec_Ptr_t *      vConeLeaves;   // fanins of the containing cone
Alan Mishchenko committed
44
    Vec_Ptr_t *      vVisited;      // the visited nodes
Alan Mishchenko committed
45 46
    Vec_Vec_t *      vLevels;       // the data structure to compute TFO nodes
    Vec_Ptr_t *      vNodesTfo;     // the nodes in the TFO of the cut
Alan Mishchenko committed
47 48
};

Alan Mishchenko committed
49 50 51
static int   Abc_NodeBuildCutLevelOne_int( Vec_Ptr_t * vVisited, Vec_Ptr_t * vLeaves, int nSizeLimit, int nFaninLimit );
static int   Abc_NodeBuildCutLevelTwo_int( Vec_Ptr_t * vVisited, Vec_Ptr_t * vLeaves, int nFaninLimit );
static void  Abc_NodeConeMarkCollect_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vVisited );
Alan Mishchenko committed
52 53

////////////////////////////////////////////////////////////////////////
Alan Mishchenko committed
54
///                     FUNCTION DEFINITIONS                         ///
Alan Mishchenko committed
55 56 57 58
////////////////////////////////////////////////////////////////////////

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

Alan Mishchenko committed
59 60 61 62 63 64 65 66 67 68 69 70 71
  Synopsis    [Unmarks the TFI cone.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
static inline void Abc_NodesMark( Vec_Ptr_t * vVisited )
{
    Abc_Obj_t * pNode;
    int i;
72
    Vec_PtrForEachEntry( Abc_Obj_t *, vVisited, pNode, i )
Alan Mishchenko committed
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
        pNode->fMarkA = 1;
}

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

  Synopsis    [Unmarks the TFI cone.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
static inline void Abc_NodesUnmark( Vec_Ptr_t * vVisited )
{
    Abc_Obj_t * pNode;
    int i;
91
    Vec_PtrForEachEntry( Abc_Obj_t *, vVisited, pNode, i )
Alan Mishchenko committed
92 93 94 95 96 97 98 99 100 101 102 103 104 105
        pNode->fMarkA = 0;
}

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

  Synopsis    [Unmarks the TFI cone.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
106
static inline void Abc_NodesUnmarkB( Vec_Ptr_t * vVisited )
Alan Mishchenko committed
107 108 109
{
    Abc_Obj_t * pNode;
    int i;
110
    Vec_PtrForEachEntry( Abc_Obj_t *, vVisited, pNode, i )
Alan Mishchenko committed
111
        pNode->fMarkB = 0;
Alan Mishchenko committed
112 113 114 115
}

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

Alan Mishchenko committed
116
  Synopsis    [Evaluate the cost of removing the node from the set of leaves.]
Alan Mishchenko committed
117

Alan Mishchenko committed
118 119
  Description [Returns the number of new leaves that will be brought in.
  Returns large number if the node cannot be removed from the set of leaves.]
Alan Mishchenko committed
120 121 122 123 124 125
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
126
static inline int Abc_NodeGetLeafCostOne( Abc_Obj_t * pNode, int nFaninLimit )
Alan Mishchenko committed
127
{
Alan Mishchenko committed
128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
    int Cost;
    // make sure the node is in the construction zone
    assert( pNode->fMarkB == 1 );  
    // cannot expand over the PI node
    if ( Abc_ObjIsCi(pNode) )
        return 999;
    // get the cost of the cone
    Cost = (!Abc_ObjFanin0(pNode)->fMarkB) + (!Abc_ObjFanin1(pNode)->fMarkB);
    // always accept if the number of leaves does not increase
    if ( Cost < 2 )
        return Cost;
    // skip nodes with many fanouts
    if ( Abc_ObjFanoutNum(pNode) > nFaninLimit )
        return 999;
    // return the number of nodes that will be on the leaves if this node is removed
    return Cost;
}

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

  Synopsis    [Evaluate the cost of removing the node from the set of leaves.]

  Description [Returns the number of new leaves that will be brought in.
  Returns large number if the node cannot be removed from the set of leaves.]
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
static inline int Abc_NodeGetLeafCostTwo( Abc_Obj_t * pNode, int nFaninLimit, 
    Abc_Obj_t ** ppLeafToAdd, Abc_Obj_t ** pNodeToMark1, Abc_Obj_t ** pNodeToMark2 )
{
    Abc_Obj_t * pFanin0, * pFanin1, * pTemp;
    Abc_Obj_t * pGrand, * pGrandToAdd;
    // make sure the node is in the construction zone
    assert( pNode->fMarkB == 1 );  
    // cannot expand over the PI node
Alan Mishchenko committed
166 167 168
    if ( Abc_ObjIsCi(pNode) )
        return 999;
    // skip nodes with many fanouts
Alan Mishchenko committed
169 170 171 172 173 174 175 176 177
//    if ( Abc_ObjFanoutNum(pNode) > nFaninLimit )
//        return 999;
    // get the children
    pFanin0 = Abc_ObjFanin0(pNode);
    pFanin1 = Abc_ObjFanin1(pNode);
    assert( !pFanin0->fMarkB && !pFanin1->fMarkB );
    // count the number of unique grandchildren that will be included
    // return infinite cost if this number if more than 1
    if ( Abc_ObjIsCi(pFanin0) && Abc_ObjIsCi(pFanin1) )
Alan Mishchenko committed
178
        return 999;
Alan Mishchenko committed
179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235
    // consider the special case when a non-CI fanin can be dropped
    if ( !Abc_ObjIsCi(pFanin0) && Abc_ObjFanin0(pFanin0)->fMarkB && Abc_ObjFanin1(pFanin0)->fMarkB )
    {
        *ppLeafToAdd  = pFanin1;
        *pNodeToMark1 = pFanin0;
        *pNodeToMark2 = NULL;
        return 1;
    }
    if ( !Abc_ObjIsCi(pFanin1) && Abc_ObjFanin0(pFanin1)->fMarkB && Abc_ObjFanin1(pFanin1)->fMarkB )
    {
        *ppLeafToAdd  = pFanin0;
        *pNodeToMark1 = pFanin1;
        *pNodeToMark2 = NULL;
        return 1;
    }

    // make the first node CI if any
    if ( Abc_ObjIsCi(pFanin1) )
        pTemp = pFanin0, pFanin0 = pFanin1, pFanin1 = pTemp;
    // consider the first node
    pGrandToAdd = NULL;
    if ( Abc_ObjIsCi(pFanin0) )
    {
        *pNodeToMark1 = NULL;
        pGrandToAdd = pFanin0;
    }
    else
    {
        *pNodeToMark1 = pFanin0;
        pGrand = Abc_ObjFanin0(pFanin0);
        if ( !pGrand->fMarkB )
        {
            if ( pGrandToAdd && pGrandToAdd != pGrand )
                return 999;
            pGrandToAdd = pGrand;
        }
        pGrand = Abc_ObjFanin1(pFanin0);
        if ( !pGrand->fMarkB )
        {
            if ( pGrandToAdd && pGrandToAdd != pGrand )
                return 999;
            pGrandToAdd = pGrand;
        }
    }
    // consider the second node
    *pNodeToMark2 = pFanin1;
    pGrand = Abc_ObjFanin0(pFanin1);
    if ( !pGrand->fMarkB )
    {
        if ( pGrandToAdd && pGrandToAdd != pGrand )
            return 999;
        pGrandToAdd = pGrand;
    }
    pGrand = Abc_ObjFanin1(pFanin1);
    if ( !pGrand->fMarkB )
    {
        if ( pGrandToAdd && pGrandToAdd != pGrand )
Alan Mishchenko committed
236
            return 999;
Alan Mishchenko committed
237 238 239 240 241
        pGrandToAdd = pGrand;
    }
    assert( pGrandToAdd != NULL );
    *ppLeafToAdd = pGrandToAdd;
    return 1;
Alan Mishchenko committed
242 243 244 245 246 247
}


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

  Synopsis    [Finds a fanin-limited, reconvergence-driven cut for the node.]
Alan Mishchenko committed
248 249 250 251 252 253 254 255

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
256
Vec_Ptr_t * Abc_NodeFindCut( Abc_ManCut_t * p, Abc_Obj_t * pRoot, int fContain )
Alan Mishchenko committed
257
{
Alan Mishchenko committed
258
    Abc_Obj_t * pNode;
Alan Mishchenko committed
259 260
    int i;

Alan Mishchenko committed
261 262 263
    assert( !Abc_ObjIsComplement(pRoot) );
    assert( Abc_ObjIsNode(pRoot) );

Alan Mishchenko committed
264
    // start the visited nodes and mark them
Alan Mishchenko committed
265
    Vec_PtrClear( p->vVisited );
Alan Mishchenko committed
266 267 268
    Vec_PtrPush( p->vVisited, pRoot );
    Vec_PtrPush( p->vVisited, Abc_ObjFanin0(pRoot) );
    Vec_PtrPush( p->vVisited, Abc_ObjFanin1(pRoot) );
Alan Mishchenko committed
269
    pRoot->fMarkB = 1;
Alan Mishchenko committed
270 271
    Abc_ObjFanin0(pRoot)->fMarkB = 1;
    Abc_ObjFanin1(pRoot)->fMarkB = 1;
Alan Mishchenko committed
272

Alan Mishchenko committed
273 274 275 276 277
    // start the cut 
    Vec_PtrClear( p->vNodeLeaves );
    Vec_PtrPush( p->vNodeLeaves, Abc_ObjFanin0(pRoot) );
    Vec_PtrPush( p->vNodeLeaves, Abc_ObjFanin1(pRoot) );

Alan Mishchenko committed
278
    // compute the cut
Alan Mishchenko committed
279 280
    while ( Abc_NodeBuildCutLevelOne_int( p->vVisited, p->vNodeLeaves, p->nNodeSizeMax, p->nNodeFanStop ) );
    assert( Vec_PtrSize(p->vNodeLeaves) <= p->nNodeSizeMax );
Alan Mishchenko committed
281

Alan Mishchenko committed
282 283
    // return if containing cut is not requested
    if ( !fContain )
Alan Mishchenko committed
284
    {
Alan Mishchenko committed
285 286 287
        // unmark both fMarkA and fMarkB in tbe TFI
        Abc_NodesUnmarkB( p->vVisited );
        return p->vNodeLeaves;
Alan Mishchenko committed
288 289
    }

Alan Mishchenko committed
290
//printf( "\n\n\n" );
Alan Mishchenko committed
291 292 293
    // compute the containing cut
    assert( p->nNodeSizeMax < p->nConeSizeMax );
    // copy the current boundary
Alan Mishchenko committed
294
    Vec_PtrClear( p->vConeLeaves );
295
    Vec_PtrForEachEntry( Abc_Obj_t *, p->vNodeLeaves, pNode, i )
Alan Mishchenko committed
296
        Vec_PtrPush( p->vConeLeaves, pNode );
Alan Mishchenko committed
297
    // compute the containing cut
Alan Mishchenko committed
298 299
    while ( Abc_NodeBuildCutLevelOne_int( p->vVisited, p->vConeLeaves, p->nConeSizeMax, p->nConeFanStop ) );
    assert( Vec_PtrSize(p->vConeLeaves) <= p->nConeSizeMax );
Alan Mishchenko committed
300
    // unmark TFI using fMarkA and fMarkB
Alan Mishchenko committed
301 302
    Abc_NodesUnmarkB( p->vVisited );
    return p->vNodeLeaves;
Alan Mishchenko committed
303 304 305 306
}

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

Alan Mishchenko committed
307
  Synopsis    [Builds reconvergence-driven cut by changing one leaf at a time.]
Alan Mishchenko committed
308

Alan Mishchenko committed
309 310 311 312
  Description [This procedure looks at the current leaves and tries to change 
  one leaf at a time in such a way that the cut grows as little as possible.
  In evaluating the fanins, this procedure looks only at their immediate 
  predecessors (this is why it is called a one-level construction procedure).]
Alan Mishchenko committed
313 314 315 316 317 318
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
319
int Abc_NodeBuildCutLevelOne_int( Vec_Ptr_t * vVisited, Vec_Ptr_t * vLeaves, int nSizeLimit, int nFaninLimit )
Alan Mishchenko committed
320 321 322 323 324 325
{
    Abc_Obj_t * pNode, * pFaninBest, * pNext;
    int CostBest, CostCur, i;
    // find the best fanin
    CostBest   = 100;
    pFaninBest = NULL;
Alan Mishchenko committed
326
//printf( "Evaluating fanins of the cut:\n" );
327
    Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pNode, i )
Alan Mishchenko committed
328
    {
Alan Mishchenko committed
329 330
        CostCur = Abc_NodeGetLeafCostOne( pNode, nFaninLimit );
//printf( "    Fanin %s has cost %d.\n", Abc_ObjName(pNode), CostCur );
Alan Mishchenko committed
331 332 333
//        if ( CostBest > CostCur ) // performance improvement: expand the variable with the smallest level
        if ( CostBest > CostCur ||
             (CostBest == CostCur && pNode->Level > pFaninBest->Level) )
Alan Mishchenko committed
334
        {
Alan Mishchenko committed
335 336
            CostBest   = CostCur;
            pFaninBest = pNode;
Alan Mishchenko committed
337
        }
Alan Mishchenko committed
338 339
        if ( CostBest == 0 )
            break;
Alan Mishchenko committed
340 341 342
    }
    if ( pFaninBest == NULL )
        return 0;
Alan Mishchenko committed
343 344
//        return Abc_NodeBuildCutLevelTwo_int( vVisited, vLeaves, nFaninLimit );

Alan Mishchenko committed
345
    assert( CostBest < 3 );
Alan Mishchenko committed
346
    if ( vLeaves->nSize - 1 + CostBest > nSizeLimit )
Alan Mishchenko committed
347
        return 0;
Alan Mishchenko committed
348 349
//        return Abc_NodeBuildCutLevelTwo_int( vVisited, vLeaves, nFaninLimit );

Alan Mishchenko committed
350 351
    assert( Abc_ObjIsNode(pFaninBest) );
    // remove the node from the array
Alan Mishchenko committed
352 353 354
    Vec_PtrRemove( vLeaves, pFaninBest );
//printf( "Removing fanin %s.\n", Abc_ObjName(pFaninBest) );

Alan Mishchenko committed
355 356 357 358
    // add the left child to the fanins
    pNext = Abc_ObjFanin0(pFaninBest);
    if ( !pNext->fMarkB )
    {
Alan Mishchenko committed
359
//printf( "Adding fanin %s.\n", Abc_ObjName(pNext) );
Alan Mishchenko committed
360
        pNext->fMarkB = 1;
Alan Mishchenko committed
361 362
        Vec_PtrPush( vLeaves, pNext );
        Vec_PtrPush( vVisited, pNext );
Alan Mishchenko committed
363 364 365 366 367
    }
    // add the right child to the fanins
    pNext = Abc_ObjFanin1(pFaninBest);
    if ( !pNext->fMarkB )
    {
Alan Mishchenko committed
368
//printf( "Adding fanin %s.\n", Abc_ObjName(pNext) );
Alan Mishchenko committed
369
        pNext->fMarkB = 1;
Alan Mishchenko committed
370 371
        Vec_PtrPush( vLeaves, pNext );
        Vec_PtrPush( vVisited, pNext );
Alan Mishchenko committed
372
    }
Alan Mishchenko committed
373
    assert( vLeaves->nSize <= nSizeLimit );
Alan Mishchenko committed
374 375 376 377 378 379
    // keep doing this
    return 1;
}

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

Alan Mishchenko committed
380 381 382 383 384 385 386 387 388 389 390 391 392 393
  Synopsis    [Builds reconvergence-driven cut by changing one leaf at a time.]

  Description [This procedure looks at the current leaves and tries to change 
  one leaf at a time in such a way that the cut grows as little as possible.
  In evaluating the fanins, this procedure looks across two levels of fanins
  (this is why it is called a two-level construction procedure).]
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
int Abc_NodeBuildCutLevelTwo_int( Vec_Ptr_t * vVisited, Vec_Ptr_t * vLeaves, int nFaninLimit )
{
Alan Mishchenko committed
394 395
    Abc_Obj_t * pNode = NULL, * pLeafToAdd, * pNodeToMark1, * pNodeToMark2;
    int CostCur = 0, i;
Alan Mishchenko committed
396
    // find the best fanin
397
    Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pNode, i )
Alan Mishchenko committed
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 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453
    {
        CostCur = Abc_NodeGetLeafCostTwo( pNode, nFaninLimit, &pLeafToAdd, &pNodeToMark1, &pNodeToMark2 );
        if ( CostCur < 2 )
            break;
    }
    if ( CostCur > 2 )
        return 0;
    // remove the node from the array
    Vec_PtrRemove( vLeaves, pNode );
    // add the node to the leaves
    if ( pLeafToAdd )
    {
        assert( !pLeafToAdd->fMarkB );
        pLeafToAdd->fMarkB = 1;
        Vec_PtrPush( vLeaves, pLeafToAdd );
        Vec_PtrPush( vVisited, pLeafToAdd );
    }
    // mark the other nodes
    if ( pNodeToMark1 )
    {
        assert( !pNodeToMark1->fMarkB );
        pNodeToMark1->fMarkB = 1;
        Vec_PtrPush( vVisited, pNodeToMark1 );
    }
    if ( pNodeToMark2 )
    {
        assert( !pNodeToMark2->fMarkB );
        pNodeToMark2->fMarkB = 1;
        Vec_PtrPush( vVisited, pNodeToMark2 );
    }
    // keep doing this
    return 1;
}


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

  Synopsis    [Get the nodes contained in the cut.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
void Abc_NodeConeCollect( Abc_Obj_t ** ppRoots, int nRoots, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vVisited, int fIncludeFanins )
{
    Abc_Obj_t * pTemp;
    int i;
    // mark the fanins of the cone
    Abc_NodesMark( vLeaves );
    // collect the nodes in the DFS order
    Vec_PtrClear( vVisited );
    // add the fanins
    if ( fIncludeFanins )
454
        Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pTemp, i )
Alan Mishchenko committed
455 456 457 458 459 460 461 462 463 464 465
            Vec_PtrPush( vVisited, pTemp );
    // add other nodes
    for ( i = 0; i < nRoots; i++ )
        Abc_NodeConeMarkCollect_rec( ppRoots[i], vVisited );
    // unmark both sets
    Abc_NodesUnmark( vLeaves );
    Abc_NodesUnmark( vVisited );
}

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

Alan Mishchenko committed
466 467 468 469 470 471 472 473 474
  Synopsis    [Marks the TFI cone.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
475
void Abc_NodeConeMarkCollect_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vVisited )
Alan Mishchenko committed
476 477 478 479 480 481
{
    if ( pNode->fMarkA == 1 )
        return;
    // visit transitive fanin 
    if ( Abc_ObjIsNode(pNode) )
    {
Alan Mishchenko committed
482 483
        Abc_NodeConeMarkCollect_rec( Abc_ObjFanin0(pNode), vVisited );
        Abc_NodeConeMarkCollect_rec( Abc_ObjFanin1(pNode), vVisited );
Alan Mishchenko committed
484 485 486 487 488 489
    }
    assert( pNode->fMarkA == 0 );
    pNode->fMarkA = 1;
    Vec_PtrPush( vVisited, pNode );
}

490 491
#ifdef ABC_USE_CUDD

Alan Mishchenko committed
492 493
/**Function*************************************************************

Alan Mishchenko committed
494
  Synopsis    [Returns BDD representing the logic function of the cone.]
Alan Mishchenko committed
495 496 497 498 499 500 501 502

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
503
DdNode * Abc_NodeConeBdd( DdManager * dd, DdNode ** pbVars, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vVisited )
Alan Mishchenko committed
504
{
Alan Mishchenko committed
505
    Abc_Obj_t * pNode;
Alan Mishchenko committed
506
    DdNode * bFunc0, * bFunc1, * bFunc = NULL;
Alan Mishchenko committed
507
    int i;
Alan Mishchenko committed
508
    // get the nodes in the cut without fanins in the DFS order
Alan Mishchenko committed
509
    Abc_NodeConeCollect( &pRoot, 1, vLeaves, vVisited, 0 );
Alan Mishchenko committed
510
    // set the elementary BDDs
511
    Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pNode, i )
Alan Mishchenko committed
512 513
        pNode->pCopy = (Abc_Obj_t *)pbVars[i];
    // compute the BDDs for the collected nodes
514
    Vec_PtrForEachEntry( Abc_Obj_t *, vVisited, pNode, i )
Alan Mishchenko committed
515
    {
Alan Mishchenko committed
516
        assert( !Abc_ObjIsPi(pNode) );
517 518
        bFunc0 = Cudd_NotCond( Abc_ObjFanin0(pNode)->pCopy, (int)Abc_ObjFaninC0(pNode) );
        bFunc1 = Cudd_NotCond( Abc_ObjFanin1(pNode)->pCopy, (int)Abc_ObjFaninC1(pNode) );
Alan Mishchenko committed
519 520 521
        bFunc  = Cudd_bddAnd( dd, bFunc0, bFunc1 );    Cudd_Ref( bFunc );
        pNode->pCopy = (Abc_Obj_t *)bFunc;
    }
Alan Mishchenko committed
522
    assert(bFunc);
Alan Mishchenko committed
523 524
    Cudd_Ref( bFunc );
    // dereference the intermediate ones
525
    Vec_PtrForEachEntry( Abc_Obj_t *, vVisited, pNode, i )
Alan Mishchenko committed
526 527 528
        Cudd_RecursiveDeref( dd, (DdNode *)pNode->pCopy );
    Cudd_Deref( bFunc );
    return bFunc;
Alan Mishchenko committed
529 530 531 532
}

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

Alan Mishchenko committed
533
  Synopsis    [Returns BDD representing the transition relation of the cone.]
Alan Mishchenko committed
534 535 536 537 538 539 540 541

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
542
DdNode * Abc_NodeConeDcs( DdManager * dd, DdNode ** pbVarsX, DdNode ** pbVarsY, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vRoots, Vec_Ptr_t * vVisited )
Alan Mishchenko committed
543
{
Alan Mishchenko committed
544 545
    DdNode * bFunc0, * bFunc1, * bFunc, * bTrans, * bTemp, * bCube, * bResult;
    Abc_Obj_t * pNode;
Alan Mishchenko committed
546
    int i;
Alan Mishchenko committed
547 548
    // get the nodes in the cut without fanins in the DFS order
    Abc_NodeConeCollect( (Abc_Obj_t **)vRoots->pArray, vRoots->nSize, vLeaves, vVisited, 0 );
Alan Mishchenko committed
549
    // set the elementary BDDs
550
    Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pNode, i )
Alan Mishchenko committed
551
        pNode->pCopy = (Abc_Obj_t *)pbVarsX[i];
Alan Mishchenko committed
552
    // compute the BDDs for the collected nodes
553
    Vec_PtrForEachEntry( Abc_Obj_t *, vVisited, pNode, i )
Alan Mishchenko committed
554
    {
555 556
        bFunc0 = Cudd_NotCond( Abc_ObjFanin0(pNode)->pCopy, (int)Abc_ObjFaninC0(pNode) );
        bFunc1 = Cudd_NotCond( Abc_ObjFanin1(pNode)->pCopy, (int)Abc_ObjFaninC1(pNode) );
Alan Mishchenko committed
557 558 559
        bFunc  = Cudd_bddAnd( dd, bFunc0, bFunc1 );    Cudd_Ref( bFunc );
        pNode->pCopy = (Abc_Obj_t *)bFunc;
    }
Alan Mishchenko committed
560 561
    // compute the transition relation of the cone
    bTrans = b1;    Cudd_Ref( bTrans );
562
    Vec_PtrForEachEntry( Abc_Obj_t *, vRoots, pNode, i )
Alan Mishchenko committed
563 564 565 566 567 568
    {
        bFunc = Cudd_bddXnor( dd, (DdNode *)pNode->pCopy, pbVarsY[i] );  Cudd_Ref( bFunc );
        bTrans = Cudd_bddAnd( dd, bTemp = bTrans, bFunc );               Cudd_Ref( bTrans );
        Cudd_RecursiveDeref( dd, bTemp );
        Cudd_RecursiveDeref( dd, bFunc );
    }
Alan Mishchenko committed
569
    // dereference the intermediate ones
570
    Vec_PtrForEachEntry( Abc_Obj_t *, vVisited, pNode, i )
Alan Mishchenko committed
571
        Cudd_RecursiveDeref( dd, (DdNode *)pNode->pCopy );
Alan Mishchenko committed
572 573 574 575 576 577 578 579
    // compute don't-cares
    bCube = Extra_bddComputeRangeCube( dd, vRoots->nSize, vRoots->nSize + vLeaves->nSize );  Cudd_Ref( bCube );
    bResult = Cudd_bddExistAbstract( dd, bTrans, bCube );                Cudd_Ref( bResult );
    bResult = Cudd_Not( bResult );
    Cudd_RecursiveDeref( dd, bCube );
    Cudd_RecursiveDeref( dd, bTrans );
    Cudd_Deref( bResult );
    return bResult;
Alan Mishchenko committed
580
}
Alan Mishchenko committed
581
 
582 583
#endif

Alan Mishchenko committed
584 585 586 587 588 589 590 591 592 593 594
/**Function*************************************************************

  Synopsis    [Starts the resynthesis manager.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
595
Abc_ManCut_t * Abc_NtkManCutStart( int nNodeSizeMax, int nConeSizeMax, int nNodeFanStop, int nConeFanStop )
Alan Mishchenko committed
596 597
{
    Abc_ManCut_t * p;
Alan Mishchenko committed
598
    p = ABC_ALLOC( Abc_ManCut_t, 1 );
Alan Mishchenko committed
599
    memset( p, 0, sizeof(Abc_ManCut_t) );
Alan Mishchenko committed
600 601
    p->vNodeLeaves  = Vec_PtrAlloc( 100 );
    p->vConeLeaves  = Vec_PtrAlloc( 100 );
Alan Mishchenko committed
602
    p->vVisited     = Vec_PtrAlloc( 100 );
Alan Mishchenko committed
603
    p->vLevels      = Vec_VecAlloc( 100 );
Alan Mishchenko committed
604
    p->vNodesTfo    = Vec_PtrAlloc( 100 );
Alan Mishchenko committed
605 606
    p->nNodeSizeMax = nNodeSizeMax;
    p->nConeSizeMax = nConeSizeMax;
Alan Mishchenko committed
607 608
    p->nNodeFanStop = nNodeFanStop;
    p->nConeFanStop = nConeFanStop;
Alan Mishchenko committed
609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624
    return p;
}

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

  Synopsis    [Stops the resynthesis manager.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
void Abc_NtkManCutStop( Abc_ManCut_t * p )
{
Alan Mishchenko committed
625 626
    Vec_PtrFree( p->vNodeLeaves );
    Vec_PtrFree( p->vConeLeaves );
Alan Mishchenko committed
627
    Vec_PtrFree( p->vVisited    );
Alan Mishchenko committed
628 629
    Vec_VecFree( p->vLevels );
    Vec_PtrFree( p->vNodesTfo );
Alan Mishchenko committed
630
    ABC_FREE( p );
Alan Mishchenko committed
631 632
}

Alan Mishchenko committed
633 634 635 636 637 638 639 640 641 642 643
/**Function*************************************************************

  Synopsis    [Returns the leaves of the cone.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659
Vec_Ptr_t * Abc_NtkManCutReadCutLarge( Abc_ManCut_t * p )
{
    return p->vConeLeaves;
}

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

  Synopsis    [Returns the leaves of the cone.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675
Vec_Ptr_t * Abc_NtkManCutReadCutSmall( Abc_ManCut_t * p )
{
    return p->vNodeLeaves;
}

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

  Synopsis    [Returns the leaves of the cone.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
676
Vec_Ptr_t * Abc_NtkManCutReadVisited( Abc_ManCut_t * p )
Alan Mishchenko committed
677
{
Alan Mishchenko committed
678
    return p->vVisited;
Alan Mishchenko committed
679
}
Alan Mishchenko committed
680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698



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

  Synopsis    [Collects the TFO of the cut in the topological order.]

  Description [TFO of the cut is defined as a set of nodes, for which the cut
  is a cut, that is, every path from the collected nodes to the CIs goes through 
  a node in the cut. The nodes are collected if their level does not exceed
  the given number (LevelMax). The nodes are returned in the topological order.
  If the root node is given, its MFFC is marked, so that the collected nodes
  do not contain any nodes in the MFFC.]
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
699
Vec_Ptr_t * Abc_NodeCollectTfoCands( Abc_ManCut_t * p, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves, int LevelMax )
Alan Mishchenko committed
700
{
Alan Mishchenko committed
701
    Abc_Ntk_t * pNtk = pRoot->pNtk;
Alan Mishchenko committed
702 703 704
    Vec_Ptr_t * vVec;
    Abc_Obj_t * pNode, * pFanout;
    int i, k, v, LevelMin;
Alan Mishchenko committed
705
    assert( Abc_NtkIsStrash(pNtk) );
Alan Mishchenko committed
706 707

    // assuming that the structure is clean
Alan Mishchenko committed
708
    Vec_VecForEachLevel( p->vLevels, vVec, i )
Alan Mishchenko committed
709 710 711 712
        assert( vVec->nSize == 0 );

    // put fanins into the structure while labeling them
    Abc_NtkIncrementTravId( pNtk );
Alan Mishchenko committed
713
    LevelMin = -1;
714
    Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pNode, i )
Alan Mishchenko committed
715 716 717 718
    {
        if ( pNode->Level > (unsigned)LevelMax )
            continue;
        Abc_NodeSetTravIdCurrent( pNode );
Alan Mishchenko committed
719
        Vec_VecPush( p->vLevels, pNode->Level, pNode );
Alan Mishchenko committed
720 721 722 723 724 725 726
        if ( LevelMin < (int)pNode->Level )
            LevelMin = pNode->Level;
    }
    assert( LevelMin >= 0 );

    // mark MFFC 
    if ( pRoot )
Alan Mishchenko committed
727
        Abc_NodeMffcLabelAig( pRoot );
Alan Mishchenko committed
728 729

    // go through the levels up
Alan Mishchenko committed
730
    Vec_PtrClear( p->vNodesTfo );
731
    Vec_VecForEachEntryStart( Abc_Obj_t *, p->vLevels, pNode, i, k, LevelMin )
Alan Mishchenko committed
732
    {
Alan Mishchenko committed
733 734
        if ( i > LevelMax )
            break;
Alan Mishchenko committed
735 736 737 738 739 740 741 742
        // if the node is not marked, it is not a fanin
        if ( !Abc_NodeIsTravIdCurrent(pNode) )
        {
            // check if it belongs to the TFO
            if ( !Abc_NodeIsTravIdCurrent(Abc_ObjFanin0(pNode)) || 
                 !Abc_NodeIsTravIdCurrent(Abc_ObjFanin1(pNode)) )
                 continue;
            // save the node in the TFO and label it
Alan Mishchenko committed
743
            Vec_PtrPush( p->vNodesTfo, pNode );
Alan Mishchenko committed
744 745 746 747 748 749 750 751 752 753 754 755
            Abc_NodeSetTravIdCurrent( pNode );
        }
        // go through the fanouts and add them to the structure if they meet the conditions
        Abc_ObjForEachFanout( pNode, pFanout, v )
        {
            // skip if fanout is a CO or its level exceeds
            if ( Abc_ObjIsCo(pFanout) || pFanout->Level > (unsigned)LevelMax )
                continue;
            // skip if it is already added or if it is in MFFC
            if ( Abc_NodeIsTravIdCurrent(pFanout) )
                continue;
            // add it to the structure but do not mark it (until tested later)
Alan Mishchenko committed
756
            Vec_VecPushUnique( p->vLevels, pFanout->Level, pFanout );
Alan Mishchenko committed
757 758 759 760
        }
    }

    // clear the levelized structure
Alan Mishchenko committed
761 762 763 764
    Vec_VecForEachLevelStart( p->vLevels, vVec, i, LevelMin )
    {
        if ( i > LevelMax )
            break;
Alan Mishchenko committed
765
        Vec_PtrClear( vVec );
Alan Mishchenko committed
766 767
    }
    return p->vNodesTfo;
Alan Mishchenko committed
768 769 770 771 772 773 774
}

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


775 776
ABC_NAMESPACE_IMPL_END