00001
00019 #include "dsdInt.h"
00020
00021
00025
00026
00027 void dsdKernelDecompose( Dsd_Manager_t * pDsdMan, DdNode ** pbFuncs, int nFuncs );
00028 static Dsd_Node_t * dsdKernelDecompose_rec( Dsd_Manager_t * pDsdMan, DdNode * F );
00029
00030
00031 static Dsd_Node_t * dsdKernelFindContainingComponent( Dsd_Manager_t * pDsdMan, Dsd_Node_t * pWhere, DdNode * Var, int * fPolarity );
00032 static int dsdKernelFindCommonComponents( Dsd_Manager_t * pDsdMan, Dsd_Node_t * pL, Dsd_Node_t * pH, Dsd_Node_t *** pCommon, Dsd_Node_t ** pLastDiffL, Dsd_Node_t ** pLastDiffH );
00033 static void dsdKernelComputeSumOfComponents( Dsd_Manager_t * pDsdMan, Dsd_Node_t ** pCommon, int nCommon, DdNode ** pCompF, DdNode ** pCompS, int fExor );
00034 static int dsdKernelCheckContainment( Dsd_Manager_t * pDsdMan, Dsd_Node_t * pL, Dsd_Node_t * pH, Dsd_Node_t ** pLarge, Dsd_Node_t ** pSmall );
00035
00036
00037 static void dsdKernelCopyListPlusOne( Dsd_Node_t * p, Dsd_Node_t * First, Dsd_Node_t ** ppList, int nListSize );
00038 static void dsdKernelCopyListPlusOneMinusOne( Dsd_Node_t * p, Dsd_Node_t * First, Dsd_Node_t ** ppList, int nListSize, int Skipped );
00039
00040
00041 static int dsdKernelVerifyDecomposition( Dsd_Manager_t * pDsdMan, Dsd_Node_t * pDE );
00042
00046
00047
00048 static int s_Mark;
00049
00050
00051 static int s_Show = 0;
00052
00053 static int Depth = 0;
00054
00055 static int s_Loops1;
00056 static int s_Loops2;
00057 static int s_Loops3;
00058 static int s_Pivot;
00059 static int s_PivotNo;
00060 static int s_Common;
00061 static int s_CommonNo;
00062
00063 static int s_Case4Calls;
00064 static int s_Case4CallsSpecial;
00065
00066 static int s_Case5;
00067 static int s_Loops2Useless;
00068
00069
00070 static int s_DecNodesTotal;
00071 static int s_DecNodesUsed;
00072
00073
00074 static int s_nDecBlocks;
00075 static int s_nLiterals;
00076 static int s_nExorGates;
00077 static int s_nReusedBlocks;
00078 static int s_nCascades;
00079 static float s_nArea;
00080 static float s_MaxDelay;
00081 static long s_Time;
00082 static int s_nInvertors;
00083 static int s_nPrimeBlocks;
00084
00085 static int HashSuccess = 0;
00086 static int HashFailure = 0;
00087
00088 static int s_CacheEntries;
00089
00090
00094
00120 void Dsd_Decompose( Dsd_Manager_t * pDsdMan, DdNode ** pbFuncs, int nFuncs )
00121 {
00122 DdManager * dd = pDsdMan->dd;
00123 int i;
00124 long clk;
00125 Dsd_Node_t * pTemp;
00126 int SumMaxGateSize = 0;
00127 int nDecOutputs = 0;
00128 int nCBFOutputs = 0;
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139 if ( pDsdMan->nRootsAlloc < nFuncs )
00140 {
00141 if ( pDsdMan->nRootsAlloc > 0 )
00142 free( pDsdMan->pRoots );
00143 pDsdMan->nRootsAlloc = nFuncs;
00144 pDsdMan->pRoots = (Dsd_Node_t **) malloc( pDsdMan->nRootsAlloc * sizeof(Dsd_Node_t *) );
00145 }
00146
00147 if ( pDsdMan->fVerbose )
00148 printf( "\nDecomposability statistics for individual outputs:\n" );
00149
00150
00151 s_nDecBlocks = 0;
00152
00153
00154 clk = clock();
00155 pDsdMan->nRoots = 0;
00156 s_nCascades = 0;
00157 for ( i = 0; i < nFuncs; i++ )
00158 {
00159 int nLiteralsPrev;
00160 int nDecBlocksPrev;
00161 int nExorGatesPrev;
00162 int nReusedBlocksPres;
00163 int nCascades;
00164 int MaxBlock;
00165 int nPrimeBlocks;
00166 long clk;
00167
00168 clk = clock();
00169 nLiteralsPrev = s_nLiterals;
00170 nDecBlocksPrev = s_nDecBlocks;
00171 nExorGatesPrev = s_nExorGates;
00172 nReusedBlocksPres = s_nReusedBlocks;
00173 nPrimeBlocks = s_nPrimeBlocks;
00174
00175 pDsdMan->pRoots[ pDsdMan->nRoots++ ] = dsdKernelDecompose_rec( pDsdMan, pbFuncs[i] );
00176
00177 Dsd_TreeNodeGetInfoOne( pDsdMan->pRoots[i], &nCascades, &MaxBlock );
00178 s_nCascades = ddMax( s_nCascades, nCascades );
00179 pTemp = Dsd_Regular(pDsdMan->pRoots[i]);
00180 if ( pTemp->Type != DSD_NODE_PRIME || pTemp->nDecs != Extra_bddSuppSize(dd,pTemp->S) )
00181 nDecOutputs++;
00182 if ( MaxBlock < 3 )
00183 nCBFOutputs++;
00184 SumMaxGateSize += MaxBlock;
00185
00186 if ( pDsdMan->fVerbose )
00187 {
00188 printf("#%02d: ", i );
00189 printf("Ins=%2d. ", Cudd_SupportSize(dd,pbFuncs[i]) );
00190 printf("Gts=%3d. ", Dsd_TreeCountNonTerminalNodesOne( pDsdMan->pRoots[i] ) );
00191 printf("Pri=%3d. ", Dsd_TreeCountPrimeNodesOne( pDsdMan->pRoots[i] ) );
00192 printf("Max=%3d. ", MaxBlock );
00193 printf("Reuse=%2d. ", s_nReusedBlocks-nReusedBlocksPres );
00194 printf("Csc=%2d. ", nCascades );
00195 printf("T= %.2f s. ", (float)(clock()-clk)/(float)(CLOCKS_PER_SEC) ) ;
00196 printf("Bdd=%2d. ", Cudd_DagSize(pbFuncs[i]) );
00197 printf("\n");
00198 fflush( stdout );
00199 }
00200 }
00201 assert( pDsdMan->nRoots == nFuncs );
00202
00203 if ( pDsdMan->fVerbose )
00204 {
00205 printf( "\n" );
00206 printf( "The cumulative decomposability statistics:\n" );
00207 printf( " Total outputs = %5d\n", nFuncs );
00208 printf( " Decomposable outputs = %5d\n", nDecOutputs );
00209 printf( " Completely decomposable outputs = %5d\n", nCBFOutputs );
00210 printf( " The sum of max gate sizes = %5d\n", SumMaxGateSize );
00211 printf( " Shared BDD size = %5d\n", Cudd_SharingSize( pbFuncs, nFuncs ) );
00212 printf( " Decomposition entries = %5d\n", st_count( pDsdMan->Table ) );
00213 printf( " Pure decomposition time = %.2f sec\n", (float)(clock() - clk)/(float)(CLOCKS_PER_SEC) );
00214 }
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224 }
00225
00237 Dsd_Node_t * Dsd_DecomposeOne( Dsd_Manager_t * pDsdMan, DdNode * bFunc )
00238 {
00239 return dsdKernelDecompose_rec( pDsdMan, bFunc );
00240 }
00241
00253 Dsd_Node_t * dsdKernelDecompose_rec( Dsd_Manager_t * pDsdMan, DdNode * bFunc0 )
00254 {
00255 DdManager * dd = pDsdMan->dd;
00256 DdNode * bLow;
00257 DdNode * bLowR;
00258 DdNode * bHigh;
00259
00260 int VarInt;
00261 DdNode * bVarCur;
00262 Dsd_Node_t * pVarCurDE;
00263
00264 DdNode * bSuppNew = NULL, * bTemp;
00265
00266 int fContained;
00267 int nSuppLH;
00268 int nSuppL;
00269 int nSuppH;
00270
00271
00272
00273
00274 Dsd_Node_t * pThis, * pL, * pH, * pLR, * pHR;
00275
00276 Dsd_Node_t * pSmallR, * pLargeR;
00277 Dsd_Node_t * pTableEntry;
00278
00279
00280
00281 DdNode * bF = Cudd_Regular(bFunc0);
00282 int fCompF = (int)(bF != bFunc0);
00283
00284
00285 if ( st_lookup( pDsdMan->Table, (char*)bF, (char**)&pTableEntry ) )
00286 {
00287 HashSuccess++;
00288 return Dsd_NotCond( pTableEntry, fCompF );
00289 }
00290 HashFailure++;
00291 Depth++;
00292
00293
00295
00297 bLow = cuddE(bF);
00298 bLowR = Cudd_Regular(bLow);
00299 bHigh = cuddT(bF);
00300 VarInt = bF->index;
00301 bVarCur = dd->vars[VarInt];
00302 pVarCurDE = pDsdMan->pInputs[VarInt];
00303
00304 bSuppNew = NULL;
00305
00306 if ( bLowR->index == CUDD_CONST_INDEX || bHigh->index == CUDD_CONST_INDEX )
00307 {
00308 if ( bHigh == b1 )
00309 if ( bLow == b0 )
00311
00313 {
00314 assert(0);
00315 pThis = Dsd_TreeNodeCreate( DSD_NODE_BUF, 1, s_nDecBlocks++ );
00316 pThis->pDecs[0] = NULL;
00317 }
00318 else
00320
00322 {
00323 pL = dsdKernelDecompose_rec( pDsdMan, bLow );
00324 pLR = Dsd_Regular( pL );
00325 bSuppNew = Cudd_bddAnd( dd, bVarCur, pLR->S ); Cudd_Ref(bSuppNew);
00326 if ( pLR->Type == DSD_NODE_OR && pL == pLR )
00327 {
00328 pThis = Dsd_TreeNodeCreate( DSD_NODE_OR, pL->nDecs+1, s_nDecBlocks++ );
00329 dsdKernelCopyListPlusOne( pThis, pVarCurDE, pL->pDecs, pL->nDecs );
00330 }
00331 else
00332 {
00333 pThis = Dsd_TreeNodeCreate( DSD_NODE_OR, 2, s_nDecBlocks++ );
00334 dsdKernelCopyListPlusOne( pThis, pVarCurDE, &pL, 1 );
00335 }
00336 }
00337 else
00338 {
00339 pH = dsdKernelDecompose_rec( pDsdMan, bHigh );
00340 pHR = Dsd_Regular( pH );
00341 bSuppNew = Cudd_bddAnd( dd, bVarCur, pHR->S ); Cudd_Ref(bSuppNew);
00342 if ( bLow == b0 )
00344
00346 if ( pHR->Type == DSD_NODE_OR && pH != pHR )
00347 {
00348 pThis = Dsd_TreeNodeCreate( DSD_NODE_OR, pHR->nDecs+1, s_nDecBlocks++ );
00349 dsdKernelCopyListPlusOne( pThis, Dsd_Not(pVarCurDE), pHR->pDecs, pHR->nDecs );
00350 pThis = Dsd_Not(pThis);
00351 }
00352 else
00353 {
00354 pThis = Dsd_TreeNodeCreate( DSD_NODE_OR, 2, s_nDecBlocks++ );
00355 pH = Dsd_Not(pH);
00356 dsdKernelCopyListPlusOne( pThis, Dsd_Not(pVarCurDE), &pH, 1 );
00357 pThis = Dsd_Not(pThis);
00358 }
00359 else
00361
00363 if ( pHR->Type == DSD_NODE_OR && pH == pHR )
00364 {
00365 pThis = Dsd_TreeNodeCreate( DSD_NODE_OR, pH->nDecs+1, s_nDecBlocks++ );
00366 dsdKernelCopyListPlusOne( pThis, Dsd_Not(pVarCurDE), pH->pDecs, pH->nDecs );
00367 }
00368 else
00369 {
00370 pThis = Dsd_TreeNodeCreate( DSD_NODE_OR, 2, s_nDecBlocks++ );
00371 dsdKernelCopyListPlusOne( pThis, Dsd_Not(pVarCurDE), &pH, 1 );
00372 }
00373 }
00374 goto EXIT;
00375 }
00376
00377
00378
00379 if ( bLowR == bHigh )
00381
00383 {
00384 pL = dsdKernelDecompose_rec( pDsdMan, bLow );
00385 pLR = Dsd_Regular( pL );
00386 bSuppNew = Cudd_bddAnd( dd, bVarCur, pLR->S ); Cudd_Ref(bSuppNew);
00387 if ( pLR->Type == DSD_NODE_EXOR )
00388 {
00389 pThis = Dsd_TreeNodeCreate( DSD_NODE_EXOR, pLR->nDecs+1, s_nDecBlocks++ );
00390 dsdKernelCopyListPlusOne( pThis, pVarCurDE, pLR->pDecs, pLR->nDecs );
00391 if ( pL != pLR )
00392 pThis = Dsd_Not( pThis );
00393 }
00394 else
00395 {
00396 pThis = Dsd_TreeNodeCreate( DSD_NODE_EXOR, 2, s_nDecBlocks++ );
00397 if ( pL != pLR )
00398 {
00399 dsdKernelCopyListPlusOne( pThis, pVarCurDE, &pLR, 1 );
00400 pThis = Dsd_Not( pThis );
00401 }
00402 else
00403 dsdKernelCopyListPlusOne( pThis, pVarCurDE, &pL, 1 );
00404 }
00405 goto EXIT;
00406 }
00407
00409
00411 pL = dsdKernelDecompose_rec( pDsdMan, bLow );
00412 pH = dsdKernelDecompose_rec( pDsdMan, bHigh );
00413 pLR = Dsd_Regular( pL );
00414 pHR = Dsd_Regular( pH );
00415
00416 assert( pLR->Type == DSD_NODE_BUF || pLR->Type == DSD_NODE_OR || pLR->Type == DSD_NODE_EXOR || pLR->Type == DSD_NODE_PRIME );
00417 assert( pHR->Type == DSD_NODE_BUF || pHR->Type == DSD_NODE_OR || pHR->Type == DSD_NODE_EXOR || pHR->Type == DSD_NODE_PRIME );
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432 bTemp = Cudd_bddAnd( dd, pLR->S, pHR->S ); Cudd_Ref( bTemp );
00433 nSuppL = Extra_bddSuppSize( dd, pLR->S );
00434 nSuppH = Extra_bddSuppSize( dd, pHR->S );
00435 nSuppLH = Extra_bddSuppSize( dd, bTemp );
00436 bSuppNew = Cudd_bddAnd( dd, bTemp, bVarCur ); Cudd_Ref( bSuppNew );
00437 Cudd_RecursiveDeref( dd, bTemp );
00438
00439
00440
00441
00442
00443 fContained = dsdKernelCheckContainment( pDsdMan, pLR, pHR, &pLargeR, &pSmallR );
00444
00446
00448
00449
00450
00451 if ( fContained )
00452 {
00453 Dsd_Node_t * pSmall, * pLarge;
00454 int c, iCompLarge;
00455 int fLowIsLarge;
00456
00457 DdNode * bFTemp;
00458 Dsd_Node_t * pDETemp, * pDENew;
00459
00460 Dsd_Node_t * pComp = NULL;
00461 int nComp;
00462
00463 if ( pSmallR == pLR )
00464 {
00465 pSmall = pL;
00466 pLarge = pH;
00467 fLowIsLarge = 0;
00468 }
00469 else
00470 {
00471 pSmall = pH;
00472 pLarge = pL;
00473 fLowIsLarge = 1;
00474 }
00475
00476
00477 if ( pLargeR->Type == DSD_NODE_PRIME )
00478 {
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498 int g, fFoundComp;
00499
00500 DdNode * bLarge, * bSmall;
00501 if ( fLowIsLarge )
00502 {
00503 bLarge = bLow;
00504 bSmall = bHigh;
00505 }
00506 else
00507 {
00508 bLarge = bHigh;
00509 bSmall = bLow;
00510 }
00511
00512 for ( g = 0; g < pLargeR->nDecs; g++ )
00513
00514 {
00515 pDETemp = pLargeR->pDecs[g];
00516 if ( Dsd_CheckRootFunctionIdentity( dd, bLarge, bSmall, pDETemp->G, b1 ) )
00517 {
00518 fFoundComp = 1;
00519 break;
00520 }
00521
00522 s_Loops1++;
00523
00524 if ( Dsd_CheckRootFunctionIdentity( dd, bLarge, bSmall, Cudd_Not(pDETemp->G), b1 ) )
00525 {
00526 fFoundComp = 0;
00527 break;
00528 }
00529
00530 s_Loops1++;
00531 }
00532
00533 if ( g != pLargeR->nDecs )
00534 {
00535 if ( fFoundComp )
00536 if ( fLowIsLarge )
00537 bFTemp = Cudd_bddOr( dd, bVarCur, pLargeR->pDecs[g]->G );
00538 else
00539 bFTemp = Cudd_bddOr( dd, Cudd_Not(bVarCur), pLargeR->pDecs[g]->G );
00540 else
00541 if ( fLowIsLarge )
00542 bFTemp = Cudd_bddAnd( dd, Cudd_Not(bVarCur), pLargeR->pDecs[g]->G );
00543 else
00544 bFTemp = Cudd_bddAnd( dd, bVarCur, pLargeR->pDecs[g]->G );
00545 Cudd_Ref( bFTemp );
00546
00547 pDENew = dsdKernelDecompose_rec( pDsdMan, bFTemp );
00548 pDENew = Dsd_Regular( pDENew );
00549 Cudd_RecursiveDeref( dd, bFTemp );
00550
00551
00552 pThis = Dsd_TreeNodeCreate( DSD_NODE_PRIME, pLargeR->nDecs, s_nDecBlocks++ );
00553 dsdKernelCopyListPlusOneMinusOne( pThis, pDENew, pLargeR->pDecs, pLargeR->nDecs, g );
00554 goto EXIT;
00555 }
00556 }
00557
00558
00559 for ( c = 0; c < pLargeR->nDecs; c++ )
00560 if ( pLargeR->pDecs[c] == pSmall || pLargeR->pDecs[c] == Dsd_Not(pSmall) )
00561 {
00562 iCompLarge = c;
00563 break;
00564 }
00565
00566
00567 if ( c != pLargeR->nDecs )
00568 {
00569 pComp = pLargeR->pDecs[iCompLarge];
00570 nComp = 1;
00571 }
00572 else
00573 {
00574
00575
00576
00577 if ( pLargeR->Type == pSmallR->Type &&
00578 (pLargeR->Type == DSD_NODE_EXOR || pSmallR->Type == DSD_NODE_OR&& ((pLarge==pLargeR) == (pSmall==pSmallR))) )
00579 {
00580 Dsd_Node_t ** pCommon, * pLastDiffL = NULL, * pLastDiffH = NULL;
00581 int nCommon = dsdKernelFindCommonComponents( pDsdMan, pLargeR, pSmallR, &pCommon, &pLastDiffL, &pLastDiffH );
00582
00583
00584 if ( nCommon == pSmallR->nDecs )
00585 {
00586 pComp = pSmallR;
00587 nComp = pSmallR->nDecs;
00588 }
00589 }
00590 }
00591
00592 if ( pComp )
00593 {
00594
00595 Dsd_Node_t * pCompR = Dsd_Regular( pComp );
00596 int fComp1 = (int)( pLarge != pLargeR );
00597 int fComp2 = (int)( pComp != pCompR );
00598 int fComp3 = (int)( pSmall != pSmallR );
00599
00600 DdNode * bFuncComp;
00601 DdNode * bFuncNew;
00602
00603 if ( pLargeR->Type == DSD_NODE_OR )
00604 {
00605
00606
00607 if ( (fComp1 ^ fComp2) == fComp3 )
00608 {
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633 bFTemp = (fComp1)? Cudd_Not( bF ): bF;
00634 bFuncComp = (fComp2)? Cudd_Not( pCompR->G ): pCompR->G;
00635 bFuncNew = Cudd_bddAndAbstract( dd, bFTemp, Cudd_Not(bFuncComp), pCompR->S ); Cudd_Ref( bFuncNew );
00636
00637
00638
00639 pDENew = dsdKernelDecompose_rec( pDsdMan, bFuncNew );
00640 assert( Dsd_IsComplement(pDENew) );
00641 Cudd_RecursiveDeref( dd, bFuncNew );
00642
00643
00644 if ( nComp == 1 )
00645 {
00646 pThis = Dsd_TreeNodeCreate( DSD_NODE_OR, 2, s_nDecBlocks++ );
00647 pThis->pDecs[0] = pDENew;
00648 pThis->pDecs[1] = pComp;
00649 }
00650 else
00651 {
00652 pThis = Dsd_TreeNodeCreate( DSD_NODE_OR, nComp+1, s_nDecBlocks++ );
00653 dsdKernelCopyListPlusOne( pThis, pDENew, pComp->pDecs, nComp );
00654 }
00655
00656 if ( fComp1 )
00657 pThis = Dsd_Not( pThis );
00658 goto EXIT;
00659 }
00660 }
00661 else if ( pLargeR->Type == DSD_NODE_EXOR )
00662 {
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684 assert( fComp2 == 0 );
00685
00686 bFTemp = (fComp3)? bF: Cudd_Not( bF );
00687 bFuncNew = Cudd_bddXor( dd, bFTemp, pComp->G ); Cudd_Ref( bFuncNew );
00688
00689 pDENew = dsdKernelDecompose_rec( pDsdMan, bFuncNew );
00690 assert( !Dsd_IsComplement(pDENew) );
00691 Cudd_RecursiveDeref( dd, bFuncNew );
00692
00693
00694 if ( nComp == 1 )
00695 {
00696 pThis = Dsd_TreeNodeCreate( DSD_NODE_EXOR, 2, s_nDecBlocks++ );
00697 pThis->pDecs[0] = pDENew;
00698 pThis->pDecs[1] = pComp;
00699 }
00700 else
00701 {
00702 pThis = Dsd_TreeNodeCreate( DSD_NODE_EXOR, nComp+1, s_nDecBlocks++ );
00703 dsdKernelCopyListPlusOne( pThis, pDENew, pComp->pDecs, nComp );
00704 }
00705
00706 if ( !fComp3 )
00707 pThis = Dsd_Not( pThis );
00708 goto EXIT;
00709 }
00710 }
00711 }
00712
00713
00714
00715 if ( nSuppLH == nSuppL + nSuppH )
00716 {
00717
00718 pThis = Dsd_TreeNodeCreate( DSD_NODE_PRIME, 3, s_nDecBlocks++ );
00719 if ( dd->perm[pLR->S->index] < dd->perm[pHR->S->index] )
00720 {
00721 pThis->pDecs[1] = pLR;
00722 pThis->pDecs[2] = pHR;
00723 }
00724 else
00725 {
00726 pThis->pDecs[1] = pHR;
00727 pThis->pDecs[2] = pLR;
00728 }
00729
00730 pThis->pDecs[0] = pVarCurDE;
00731 goto EXIT;
00732 }
00733
00734
00736
00738
00739
00740
00741 if ( pLR->Type == pHR->Type &&
00742 pLR->Type != DSD_NODE_BUF &&
00743 (pLR->Type != DSD_NODE_OR || ( pL == pLR && pH == pHR || pL != pLR && pH != pHR ) ) &&
00744 (pLR->Type != DSD_NODE_PRIME || pLR->nDecs == pHR->nDecs) )
00745 {
00746
00747 Dsd_Node_t ** pCommon, * pLastDiffL = NULL, * pLastDiffH = NULL;
00748 int nCommon = dsdKernelFindCommonComponents( pDsdMan, pLR, pHR, &pCommon, &pLastDiffL, &pLastDiffH );
00749 if ( nCommon )
00750 {
00751 if ( pLR->Type == DSD_NODE_OR )
00752 {
00753
00754
00755
00756
00757 DdNode * bCommF, * bCommS, * bFTemp, * bFuncNew;
00758 Dsd_Node_t * pDENew;
00759
00760 dsdKernelComputeSumOfComponents( pDsdMan, pCommon, nCommon, &bCommF, &bCommS, 0 );
00761 Cudd_Ref( bCommF );
00762 Cudd_Ref( bCommS );
00763 bFTemp = ( pL != pLR )? Cudd_Not(bF): bF;
00764
00765 bFuncNew = Cudd_bddAndAbstract( dd, bFTemp, Cudd_Not(bCommF), bCommS ); Cudd_Ref( bFuncNew );
00766 Cudd_RecursiveDeref( dd, bCommF );
00767 Cudd_RecursiveDeref( dd, bCommS );
00768
00769
00770
00771
00772
00773 pThis = Dsd_TreeNodeCreate( DSD_NODE_OR, nCommon + 1, s_nDecBlocks++ );
00774 dsdKernelCopyListPlusOne( pThis, NULL, pCommon, nCommon );
00775
00776
00777 pDENew = dsdKernelDecompose_rec( pDsdMan, bFuncNew );
00778
00779 Cudd_RecursiveDeref( dd, bFuncNew );
00780
00781
00782 pThis->pDecs[0] = pDENew;
00783
00784 if ( pL != pLR )
00785 pThis = Dsd_Not( pThis );
00786 goto EXIT;
00787 }
00788 else
00789 if ( pLR->Type == DSD_NODE_EXOR )
00790 {
00791
00792 DdNode * bCommF, * bFuncNew;
00793 Dsd_Node_t * pDENew;
00794 int fCompExor;
00795
00796 dsdKernelComputeSumOfComponents( pDsdMan, pCommon, nCommon, &bCommF, NULL, 1 );
00797 Cudd_Ref( bCommF );
00798
00799 bFuncNew = Cudd_bddXor( dd, bF, bCommF ); Cudd_Ref( bFuncNew );
00800 Cudd_RecursiveDeref( dd, bCommF );
00801
00802
00803
00804
00805
00806 pThis = Dsd_TreeNodeCreate( DSD_NODE_EXOR, nCommon + 1, s_nDecBlocks++ );
00807 dsdKernelCopyListPlusOne( pThis, NULL, pCommon, nCommon );
00808
00809
00810 pDENew = dsdKernelDecompose_rec( pDsdMan, bFuncNew );
00811 Cudd_RecursiveDeref( dd, bFuncNew );
00812
00813
00814 fCompExor = Dsd_IsComplement(pDENew);
00815 pDENew = Dsd_Regular(pDENew);
00816
00817
00818 pThis->pDecs[0] = pDENew;
00819
00820
00821 if ( fCompExor )
00822 pThis = Dsd_Not( pThis );
00823 goto EXIT;
00824 }
00825 else
00826 if ( pLR->Type == DSD_NODE_PRIME && (nCommon == pLR->nDecs-1 || nCommon == pLR->nDecs) )
00827 {
00828
00829
00830
00831
00832 Dsd_Node_t * pDENew;
00833 DdNode * bFuncNew;
00834 int fCompComp = 0;
00835
00836
00837
00838 if ( nCommon == pLR->nDecs )
00839 {
00840
00841 int m;
00842 Dsd_Node_t * pTempL, * pTempH;
00843
00844 s_Common++;
00845 for ( m = 0; m < pLR->nDecs; m++ )
00846 {
00847 pTempL = pLR->pDecs[m];
00848 pTempH = pHR->pDecs[m];
00849
00850 if ( Dsd_CheckRootFunctionIdentity( dd, bLow, bHigh, pTempL->G, Cudd_Not(pTempH->G) ) &&
00851 Dsd_CheckRootFunctionIdentity( dd, bLow, bHigh, Cudd_Not(pTempL->G), pTempH->G ) )
00852 {
00853 pLastDiffL = pTempL;
00854 pLastDiffH = pTempH;
00855 assert( pLastDiffL == pLastDiffH );
00856 fCompComp = 2;
00857 break;
00858 }
00859
00860 s_Loops2++;
00861 s_Loops2++;
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873 }
00874
00875
00876
00877 if ( fCompComp )
00878 {
00879 nCommon = 0;
00880 for ( m = 0; m < pLR->nDecs; m++ )
00881 if ( pLR->pDecs[m] != pLastDiffL )
00882 pCommon[nCommon++] = pLR->pDecs[m];
00883 assert( nCommon = pLR->nDecs-1 );
00884 }
00885 }
00886 else
00887 {
00888
00889 s_CommonNo++;
00890
00891
00892 assert( pLastDiffL );
00893 assert( pLastDiffH );
00894
00895
00896 if ( Dsd_CheckRootFunctionIdentity( dd, bLow, bHigh, Cudd_Not(pLastDiffL->G), Cudd_Not(pLastDiffH->G) ) &&
00897 Dsd_CheckRootFunctionIdentity( dd, bLow, bHigh, pLastDiffL->G, pLastDiffH->G ) )
00898 fCompComp = 1;
00899 else if ( Dsd_CheckRootFunctionIdentity( dd, bLow, bHigh, pLastDiffL->G, Cudd_Not(pLastDiffH->G) ) &&
00900 Dsd_CheckRootFunctionIdentity( dd, bLow, bHigh, Cudd_Not(pLastDiffL->G), pLastDiffH->G ) )
00901 fCompComp = 2;
00902
00903 s_Loops3 += 4;
00904 }
00905
00906 if ( fCompComp )
00907 {
00908 if ( fCompComp == 1 )
00909 bFuncNew = Cudd_bddIte( dd, bVarCur, pLastDiffH->G, pLastDiffL->G );
00910 else
00911 bFuncNew = Cudd_bddIte( dd, bVarCur, Cudd_Not(pLastDiffH->G), pLastDiffL->G );
00912 Cudd_Ref( bFuncNew );
00913
00914
00915
00916
00917
00918 pThis = Dsd_TreeNodeCreate( DSD_NODE_PRIME, pLR->nDecs, s_nDecBlocks++ );
00919 dsdKernelCopyListPlusOne( pThis, NULL, pCommon, nCommon );
00920
00921
00922 pDENew = dsdKernelDecompose_rec( pDsdMan, bFuncNew );
00923 Cudd_RecursiveDeref( dd, bFuncNew );
00924
00925 pDENew = Dsd_Regular(pDENew);
00926
00927
00928 pThis->pDecs[0] = pDENew;
00929 goto EXIT;
00930 }
00931 }
00932 }
00933 }
00934
00935
00936
00937
00938
00940
00942 {
00943
00944 int nEntriesMax = pDsdMan->nInputs - dd->perm[VarInt];
00945
00946
00947 int nEntries = 0;
00948
00949 DdNode * SuppL, * SuppH, * SuppL_init, * SuppH_init;
00950 Dsd_Node_t *pHigher, *pLower, * pTemp, * pDENew;
00951
00952
00953 int levTopSuppL;
00954 int levTopSuppH;
00955 int levTop;
00956
00957 pThis = Dsd_TreeNodeCreate( DSD_NODE_PRIME, nEntriesMax, s_nDecBlocks++ );
00958 pThis->pDecs[ nEntries++ ] = pVarCurDE;
00959
00960
00961
00962 s_Case4Calls++;
00963
00964
00965
00966
00967
00968 if ( (((pLR->Type == DSD_NODE_PRIME && nSuppL == pLR->nDecs) || (pHR->Type == DSD_NODE_PRIME && nSuppH == pHR->nDecs)) && pLR->S == pHR->S) ||
00969 ((pLR->Type == DSD_NODE_PRIME && nSuppL == pLR->nDecs) && (pHR->Type == DSD_NODE_PRIME && nSuppH == pHR->nDecs)) )
00970 {
00971
00972 s_Case4CallsSpecial++;
00973
00974 SuppL = pLR->S;
00975 SuppH = pHR->S;
00976 do
00977 {
00978
00979 levTopSuppL = cuddI(dd,SuppL->index);
00980 levTopSuppH = cuddI(dd,SuppH->index);
00981
00982
00983 if ( levTopSuppL <= levTopSuppH )
00984 {
00985 levTop = levTopSuppL;
00986 SuppL = cuddT(SuppL);
00987 }
00988 else
00989 levTop = levTopSuppH;
00990
00991 if ( levTopSuppH <= levTopSuppL )
00992 SuppH = cuddT(SuppH);
00993
00994
00995 pThis->pDecs[ nEntries++ ] = pDsdMan->pInputs[ dd->invperm[levTop] ];
00996 }
00997 while ( SuppL != b1 || SuppH != b1 );
00998 }
00999 else
01000 {
01001
01002
01003 SuppL_init = pLR->S;
01004 SuppH_init = pHR->S;
01005
01006 SuppL = pLR->S; Cudd_Ref( SuppL );
01007 SuppH = pHR->S; Cudd_Ref( SuppH );
01008 while ( SuppL != b1 || SuppH != b1 )
01009 {
01010
01011
01012 int TopLevL = cuddI(dd,SuppL->index);
01013 int TopLevH = cuddI(dd,SuppH->index);
01014 int TopLevel = TopLevH;
01015 int fEqualLevel = 0;
01016
01017 DdNode * bVarTop;
01018 DdNode * bSuppSubract;
01019
01020
01021 if ( TopLevL < TopLevH )
01022 {
01023 pHigher = pLR;
01024 pLower = pHR;
01025 TopLevel = TopLevL;
01026 }
01027 else if ( TopLevL > TopLevH )
01028 {
01029 pHigher = pHR;
01030 pLower = pLR;
01031 }
01032 else
01033 fEqualLevel = 1;
01034 assert( TopLevel != CUDD_CONST_INDEX );
01035
01036
01037
01038 bVarTop = dd->vars[dd->invperm[TopLevel]];
01039
01040 if ( !fEqualLevel )
01041 {
01042
01043 DdNode * bSuppLower = (TopLevL < TopLevH)? SuppH_init: SuppL_init;
01044
01045
01046
01047
01048 int fPolarity;
01049 Dsd_Node_t * pPrev = NULL;
01050 Dsd_Node_t * pCur = pHigher;
01051 while ( Extra_bddSuppOverlapping( dd, pCur->S, bSuppLower ) )
01052 {
01053 pPrev = pCur;
01054 pCur = dsdKernelFindContainingComponent( pDsdMan, pCur, bVarTop, &fPolarity );
01055 };
01056
01057
01058 if ( pPrev == NULL || pPrev->Type == DSD_NODE_PRIME )
01059 {
01060
01061
01062
01063 pThis->pDecs[ nEntries++ ] = pCur;
01064
01065 bSuppSubract = pCur->S;
01066 }
01067 else
01068 {
01069
01070
01071
01072 static Dsd_Node_t * pNonOverlap[MAXINPUTS];
01073 int i, nNonOverlap = 0;
01074 for ( i = 0; i < pPrev->nDecs; i++ )
01075 {
01076 pTemp = Dsd_Regular( pPrev->pDecs[i] );
01077 if ( !Extra_bddSuppOverlapping( dd, pTemp->S, bSuppLower ) )
01078 pNonOverlap[ nNonOverlap++ ] = pPrev->pDecs[i];
01079 }
01080 assert( nNonOverlap > 0 );
01081
01082 if ( nNonOverlap == 1 )
01083 {
01084 assert( Dsd_Regular(pNonOverlap[0]) == pCur);
01085
01086 pThis->pDecs[ nEntries++ ] = pCur;
01087
01088 bSuppSubract = pCur->S;
01089 }
01090 else
01091 {
01092
01093 DdNode * bCommF;
01094 dsdKernelComputeSumOfComponents( pDsdMan, pNonOverlap, nNonOverlap, &bCommF, NULL, (int)(pPrev->Type==DSD_NODE_EXOR) );
01095 Cudd_Ref( bCommF );
01096
01097
01098 pDENew = dsdKernelDecompose_rec( pDsdMan, bCommF );
01099 Cudd_RecursiveDeref(dd, bCommF);
01100
01101 assert( !Dsd_IsComplement(pDENew) );
01102
01103
01104 pThis->pDecs[ nEntries++ ] = pDENew;
01105
01106 bSuppSubract = pDENew->S;
01107 }
01108 }
01109
01110
01111 if ( TopLevL < TopLevH )
01112 {
01113 SuppL = Cudd_bddExistAbstract( dd, bTemp = SuppL, bSuppSubract ); Cudd_Ref( SuppL );
01114 Cudd_RecursiveDeref(dd, bTemp);
01115 }
01116 else
01117 {
01118 SuppH = Cudd_bddExistAbstract( dd, bTemp = SuppH, bSuppSubract ); Cudd_Ref( SuppH );
01119 Cudd_RecursiveDeref(dd, bTemp);
01120 }
01121 }
01122 else
01123 {
01124 static Dsd_Node_t * pMarkedLeft[MAXINPUTS];
01125 static char pMarkedPols[MAXINPUTS];
01126 int nMarkedLeft = 0;
01127
01128 int fPolarity = 0;
01129 Dsd_Node_t * pTempL = pLR;
01130
01131 int fPolarityCurH = 0;
01132 Dsd_Node_t * pPrevH = NULL, * pCurH = pHR;
01133
01134 int fPolarityCurL = 0;
01135 Dsd_Node_t * pPrevL = NULL, * pCurL = pLR;
01136 int index = 1;
01137
01138
01139 s_Mark++;
01140
01141
01142 assert( Extra_bddSuppContainVar( dd, pLR->S, bVarTop ) );
01143 assert( Extra_bddSuppContainVar( dd, pHR->S, bVarTop ) );
01144 do {
01145 pTempL->Mark = s_Mark;
01146 pMarkedLeft[ nMarkedLeft ] = pTempL;
01147 pMarkedPols[ nMarkedLeft ] = fPolarity;
01148 nMarkedLeft++;
01149 } while ( pTempL = dsdKernelFindContainingComponent( pDsdMan, pTempL, bVarTop, &fPolarity ) );
01150
01151
01152
01153 while ( pCurH->Mark != s_Mark )
01154 {
01155 pPrevH = pCurH;
01156 pCurH = dsdKernelFindContainingComponent( pDsdMan, pCurH, bVarTop, &fPolarityCurH );
01157 assert( pCurH );
01158 }
01159
01160
01161
01162 while ( pCurL != pCurH )
01163 {
01164 pPrevL = pCurL;
01165 pCurL = pMarkedLeft[index];
01166 fPolarityCurL = pMarkedPols[index];
01167 index++;
01168 }
01169
01170
01171 if ( !pPrevL || !pPrevH || pPrevL->Type != pPrevH->Type || pPrevL->Type == DSD_NODE_PRIME || fPolarityCurL != fPolarityCurH )
01172 {
01173 pThis->pDecs[ nEntries++ ] = pCurH;
01174
01175 bSuppSubract = pCurH->S;
01176 }
01177 else
01178 {
01179
01180 Dsd_Node_t ** pCommon, * pLastDiffL = NULL, * pLastDiffH = NULL;
01181 int nCommon = dsdKernelFindCommonComponents( pDsdMan, pPrevL, pPrevH, &pCommon, &pLastDiffL, &pLastDiffH );
01182
01183 if ( nCommon == 0 || nCommon == 1 )
01184 {
01185
01186
01187 pThis->pDecs[ nEntries++ ] = pCurL;
01188
01189 bSuppSubract = pCurL->S;
01190 }
01191 else
01192 {
01193
01194 DdNode * bCommF;
01195 dsdKernelComputeSumOfComponents( pDsdMan, pCommon, nCommon, &bCommF, NULL, (int)(pPrevL->Type==DSD_NODE_EXOR) );
01196 Cudd_Ref( bCommF );
01197
01198 pDENew = dsdKernelDecompose_rec( pDsdMan, bCommF );
01199 assert( !Dsd_IsComplement(pDENew) );
01200 Cudd_RecursiveDeref( dd, bCommF );
01201
01202
01203 pThis->pDecs[ nEntries++ ] = pDENew;
01204
01205
01206 bSuppSubract = pDENew->S;
01207 }
01208 }
01209
01210 SuppL = Cudd_bddExistAbstract( dd, bTemp = SuppL, bSuppSubract ), Cudd_Ref( SuppL );
01211 Cudd_RecursiveDeref(dd, bTemp);
01212
01213 SuppH = Cudd_bddExistAbstract( dd, bTemp = SuppH, bSuppSubract ), Cudd_Ref( SuppH );
01214 Cudd_RecursiveDeref(dd, bTemp);
01215
01216 }
01217
01218 }
01219 Cudd_RecursiveDeref( dd, SuppL );
01220 Cudd_RecursiveDeref( dd, SuppH );
01221
01222 }
01223
01224
01225 assert( nEntries <= nEntriesMax );
01226
01227
01228
01229
01230
01231 pThis->nDecs = nEntries;
01232 }
01233
01234 EXIT:
01235
01236 {
01237
01238
01239 Dsd_Node_t * pThisR = Dsd_Regular( pThis );
01240 assert( pThisR->G == NULL );
01241 assert( pThisR->S == NULL );
01242
01243 if ( pThisR == pThis )
01244 pThisR->G = bF;
01245 else
01246 pThisR->G = Cudd_Not(bF);
01247 Cudd_Ref(bF);
01248
01249 assert( bSuppNew );
01250 pThisR->S = bSuppNew;
01251 if ( st_insert( pDsdMan->Table, (char*)bF, (char*)pThis ) )
01252 {
01253 assert( 0 );
01254 }
01255 s_CacheEntries++;
01256
01257
01258
01259
01260
01261
01262
01263
01264
01265
01266
01267
01268
01269
01270
01271
01272
01273
01274
01275
01276
01277
01278
01279
01280
01281
01282 }
01283
01284 Depth--;
01285 return Dsd_NotCond( pThis, fCompF );
01286 }
01287
01288
01292
01306 Dsd_Node_t * dsdKernelFindContainingComponent( Dsd_Manager_t * pDsdMan, Dsd_Node_t * pWhere, DdNode * Var, int * fPolarity )
01307
01308 {
01309 Dsd_Node_t * pTemp;
01310 int i;
01311
01312
01313
01314
01315 if ( pWhere->nDecs == 1 )
01316 return NULL;
01317
01318 for( i = 0; i < pWhere->nDecs; i++ )
01319 {
01320 pTemp = Dsd_Regular( pWhere->pDecs[i] );
01321 if ( Extra_bddSuppContainVar( pDsdMan->dd, pTemp->S, Var ) )
01322 {
01323 *fPolarity = (int)( pTemp != pWhere->pDecs[i] );
01324 return pTemp;
01325 }
01326 }
01327 assert( 0 );
01328 return NULL;
01329 }
01330
01346 int dsdKernelFindCommonComponents( Dsd_Manager_t * pDsdMan, Dsd_Node_t * pL, Dsd_Node_t * pH, Dsd_Node_t *** pCommon, Dsd_Node_t ** pLastDiffL, Dsd_Node_t ** pLastDiffH )
01347 {
01348 static Dsd_Node_t * Common[MAXINPUTS];
01349 int nCommon = 0;
01350
01351
01352 Dsd_Node_t * pLcur;
01353 Dsd_Node_t * pHcur;
01354
01355
01356 DdNode * bSLcur;
01357 DdNode * bSHcur;
01358
01359
01360 int TopVar;
01361
01362
01363 int iCurL = 0;
01364 int iCurH = 0;
01365 while ( iCurL < pL->nDecs && iCurH < pH->nDecs )
01366 {
01367
01368 pLcur = Dsd_Regular(pL->pDecs[iCurL]);
01369 pHcur = Dsd_Regular(pH->pDecs[iCurH]);
01370
01371 bSLcur = pLcur->S;
01372 bSHcur = pHcur->S;
01373
01374
01375 if ( pDsdMan->dd->perm[bSLcur->index] < pDsdMan->dd->perm[bSHcur->index] )
01376 TopVar = bSLcur->index;
01377 else
01378 TopVar = bSHcur->index;
01379
01380 if ( TopVar == bSLcur->index && TopVar == bSHcur->index )
01381 {
01382
01383 if ( pL->pDecs[iCurL] == pH->pDecs[iCurH] )
01384 Common[nCommon++] = pL->pDecs[iCurL];
01385 else
01386 {
01387 *pLastDiffL = pL->pDecs[iCurL];
01388 *pLastDiffH = pH->pDecs[iCurH];
01389 }
01390
01391
01392 iCurL++;
01393 iCurH++;
01394 }
01395 else if ( TopVar == bSLcur->index )
01396 {
01397
01398 *pLastDiffL = pL->pDecs[iCurL++];
01399 }
01400 else
01401 {
01402
01403 *pLastDiffH = pH->pDecs[iCurH++];
01404 }
01405 }
01406
01407
01408 if ( iCurL < pL->nDecs )
01409 *pLastDiffL = pL->pDecs[iCurL];
01410
01411 if ( iCurH < pH->nDecs )
01412 *pLastDiffH = pH->pDecs[iCurH];
01413
01414
01415 *pCommon = Common;
01416
01417 return nCommon;
01418 }
01419
01431 void dsdKernelComputeSumOfComponents( Dsd_Manager_t * pDsdMan, Dsd_Node_t ** pCommon, int nCommon, DdNode ** pCompF, DdNode ** pCompS, int fExor )
01432 {
01433 DdManager * dd = pDsdMan->dd;
01434 DdNode * bF, * bS, * bFadd, * bTemp;
01435 Dsd_Node_t * pDE, * pDER;
01436 int i;
01437
01438
01439 bF = b0; Cudd_Ref( bF );
01440
01441 if ( pCompS )
01442 bS = b1, Cudd_Ref( bS );
01443
01444 assert( nCommon > 0 );
01445 for ( i = 0; i < nCommon; i++ )
01446 {
01447 pDE = pCommon[i];
01448 pDER = Dsd_Regular( pDE );
01449 bFadd = (pDE != pDER)? Cudd_Not(pDER->G): pDER->G;
01450
01451 if ( fExor )
01452 bF = Cudd_bddXor( dd, bTemp = bF, bFadd );
01453 else
01454 bF = Cudd_bddOr( dd, bTemp = bF, bFadd );
01455 Cudd_Ref( bF );
01456 Cudd_RecursiveDeref( dd, bTemp );
01457 if ( pCompS )
01458 {
01459
01460 bS = Cudd_bddAnd( dd, bTemp = bS, pDER->S ); Cudd_Ref( bS );
01461 Cudd_RecursiveDeref( dd, bTemp );
01462 }
01463 }
01464
01465 Cudd_Deref( bF );
01466 *pCompF = bF;
01467
01468
01469 if ( pCompS )
01470 Cudd_Deref( bS ), *pCompS = bS;
01471 }
01472
01488 int dsdKernelCheckContainment( Dsd_Manager_t * pDsdMan, Dsd_Node_t * pL, Dsd_Node_t * pH, Dsd_Node_t ** pLarge, Dsd_Node_t ** pSmall )
01489 {
01490 DdManager * dd = pDsdMan->dd;
01491 DdNode * bSuppLarge, * bSuppSmall;
01492 int RetValue;
01493
01494 RetValue = Extra_bddSuppCheckContainment( dd, pL->S, pH->S, &bSuppLarge, &bSuppSmall );
01495
01496 if ( RetValue == 0 )
01497 return 0;
01498
01499 if ( pH->S == bSuppLarge )
01500 {
01501 *pLarge = pH;
01502 *pSmall = pL;
01503 }
01504 else
01505 {
01506 *pLarge = pL;
01507 *pSmall = pH;
01508 }
01509 return 1;
01510 }
01511
01523 void dsdKernelCopyListPlusOne( Dsd_Node_t * p, Dsd_Node_t * First, Dsd_Node_t ** ppList, int nListSize )
01524 {
01525 int i;
01526 assert( nListSize+1 == p->nDecs );
01527 p->pDecs[0] = First;
01528 for( i = 0; i < nListSize; i++ )
01529 p->pDecs[i+1] = ppList[i];
01530 }
01531
01543 void dsdKernelCopyListPlusOneMinusOne( Dsd_Node_t * p, Dsd_Node_t * First, Dsd_Node_t ** ppList, int nListSize, int iSkipped )
01544 {
01545 int i, Counter;
01546 assert( nListSize == p->nDecs );
01547 p->pDecs[0] = First;
01548 for( i = 0, Counter = 1; i < nListSize; i++ )
01549 if ( i != iSkipped )
01550 p->pDecs[Counter++] = ppList[i];
01551 }
01552
01564 int dsdKernelVerifyDecomposition( Dsd_Manager_t * pDsdMan, Dsd_Node_t * pDE )
01565 {
01566 DdManager * dd = pDsdMan->dd;
01567 Dsd_Node_t * pR = Dsd_Regular(pDE);
01568 int fCompP = (int)( pDE != pR );
01569 int RetValue;
01570
01571 DdNode * bRes;
01572 if ( pR->Type == DSD_NODE_CONST1 )
01573 bRes = b1;
01574 else if ( pR->Type == DSD_NODE_BUF )
01575 bRes = pR->G;
01576 else if ( pR->Type == DSD_NODE_OR || pR->Type == DSD_NODE_EXOR )
01577 dsdKernelComputeSumOfComponents( pDsdMan, pR->pDecs, pR->nDecs, &bRes, NULL, (int)(pR->Type == DSD_NODE_EXOR) );
01578 else if ( pR->Type == DSD_NODE_PRIME )
01579 {
01580 int i;
01581 static DdNode * bGVars[MAXINPUTS];
01582
01583
01584 DdNode * bNewFunc = Dsd_TreeGetPrimeFunctionOld( dd, pR, 1 ); Cudd_Ref( bNewFunc );
01585
01586
01587
01588 for ( i = 0; i < dd->size; i++ )
01589 bGVars[i] = dd->vars[i];
01590
01591
01592 for ( i = 0; i < pR->nDecs; i++ )
01593 bGVars[dd->invperm[i]] = pR->pDecs[i]->G;
01594
01595
01596 bRes = Cudd_bddVectorCompose( dd, bNewFunc, bGVars ); Cudd_Ref( bRes );
01597 Cudd_RecursiveDeref( dd, bNewFunc );
01598
01600 RetValue = (int)( bRes == pR->G );
01602 Cudd_Deref( bRes );
01603 }
01604 else
01605 {
01606 assert(0);
01607 }
01608
01609 Cudd_Ref( bRes );
01610 RetValue = (int)( bRes == pR->G );
01611 Cudd_RecursiveDeref( dd, bRes );
01612 return RetValue;
01613 }
01614