00001
00049 #ifdef __STDC__
00050 #include <float.h>
00051 #else
00052 #define DBL_MAX_EXP 1024
00053 #endif
00054 #include "util_hack.h"
00055 #include "cuddInt.h"
00056
00057
00058
00059
00060
00061 #define NOTHING 0
00062 #define REPLACE_T 1
00063 #define REPLACE_E 2
00064 #define REPLACE_N 3
00065 #define REPLACE_TT 4
00066 #define REPLACE_TE 5
00067
00068 #define DONT_CARE 0
00069 #define CARE 1
00070 #define TOTAL_CARE 2
00071 #define CARE_ERROR 3
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089 typedef struct NodeData {
00090 double mintermsP;
00091 double mintermsN;
00092 int functionRef;
00093 char care;
00094 char replace;
00095 short int parity;
00096 DdNode *resultP;
00097 DdNode *resultN;
00098 } NodeData;
00099
00100 typedef struct ApproxInfo {
00101 DdNode *one;
00102 DdNode *zero;
00103 NodeData *page;
00104 st_table *table;
00105 int index;
00106 double max;
00107 int size;
00108 double minterms;
00109 } ApproxInfo;
00110
00111
00112 #ifdef __osf__
00113 #pragma pointer_size save
00114 #pragma pointer_size short
00115 #endif
00116 typedef struct GlobalQueueItem {
00117 struct GlobalQueueItem *next;
00118 struct GlobalQueueItem *cnext;
00119 DdNode *node;
00120 double impactP;
00121 double impactN;
00122 } GlobalQueueItem;
00123
00124 typedef struct LocalQueueItem {
00125 struct LocalQueueItem *next;
00126 struct LocalQueueItem *cnext;
00127 DdNode *node;
00128 int localRef;
00129 } LocalQueueItem;
00130 #ifdef __osf__
00131 #pragma pointer_size restore
00132 #endif
00133
00134
00135
00136
00137
00138
00139 #ifndef lint
00140 static char rcsid[] DD_UNUSED = "$Id: cuddApprox.c,v 1.1.1.1 2003/02/24 22:23:51 wjiang Exp $";
00141 #endif
00142
00143
00144
00145
00146
00149
00150
00151
00152
00153 static void updateParity ARGS((DdNode *node, ApproxInfo *info, int newparity));
00154 static NodeData * gatherInfoAux ARGS((DdNode *node, ApproxInfo *info, int parity));
00155 static ApproxInfo * gatherInfo ARGS((DdManager *dd, DdNode *node, int numVars, int parity));
00156 static int computeSavings ARGS((DdManager *dd, DdNode *f, DdNode *skip, ApproxInfo *info, DdLevelQueue *queue));
00157 static int updateRefs ARGS((DdManager *dd, DdNode *f, DdNode *skip, ApproxInfo *info, DdLevelQueue *queue));
00158 static int UAmarkNodes ARGS((DdManager *dd, DdNode *f, ApproxInfo *info, int threshold, int safe, double quality));
00159 static DdNode * UAbuildSubset ARGS((DdManager *dd, DdNode *node, ApproxInfo *info));
00160 static int RAmarkNodes ARGS((DdManager *dd, DdNode *f, ApproxInfo *info, int threshold, double quality));
00161 static int BAmarkNodes ARGS((DdManager *dd, DdNode *f, ApproxInfo *info, int threshold, double quality1, double quality0));
00162 static DdNode * RAbuildSubset ARGS((DdManager *dd, DdNode *node, ApproxInfo *info));
00163 static int BAapplyBias ARGS((DdManager *dd, DdNode *f, DdNode *b, ApproxInfo *info, DdHashTable *cache));
00164
00168
00169
00170
00171
00196 DdNode *
00197 Cudd_UnderApprox(
00198 DdManager * dd ,
00199 DdNode * f ,
00200 int numVars ,
00201 int threshold ,
00202 int safe ,
00203 double quality )
00204 {
00205 DdNode *subset;
00206
00207 do {
00208 dd->reordered = 0;
00209 subset = cuddUnderApprox(dd, f, numVars, threshold, safe, quality);
00210 } while (dd->reordered == 1);
00211
00212 return(subset);
00213
00214 }
00215
00216
00243 DdNode *
00244 Cudd_OverApprox(
00245 DdManager * dd ,
00246 DdNode * f ,
00247 int numVars ,
00248 int threshold ,
00249 int safe ,
00250 double quality )
00251 {
00252 DdNode *subset, *g;
00253
00254 g = Cudd_Not(f);
00255 do {
00256 dd->reordered = 0;
00257 subset = cuddUnderApprox(dd, g, numVars, threshold, safe, quality);
00258 } while (dd->reordered == 1);
00259
00260 return(Cudd_NotCond(subset, (subset != NULL)));
00261
00262 }
00263
00264
00288 DdNode *
00289 Cudd_RemapUnderApprox(
00290 DdManager * dd ,
00291 DdNode * f ,
00292 int numVars ,
00293 int threshold ,
00294 double quality )
00295 {
00296 DdNode *subset;
00297
00298 do {
00299 dd->reordered = 0;
00300 subset = cuddRemapUnderApprox(dd, f, numVars, threshold, quality);
00301 } while (dd->reordered == 1);
00302
00303 return(subset);
00304
00305 }
00306
00307
00334 DdNode *
00335 Cudd_RemapOverApprox(
00336 DdManager * dd ,
00337 DdNode * f ,
00338 int numVars ,
00339 int threshold ,
00340 double quality )
00341 {
00342 DdNode *subset, *g;
00343
00344 g = Cudd_Not(f);
00345 do {
00346 dd->reordered = 0;
00347 subset = cuddRemapUnderApprox(dd, g, numVars, threshold, quality);
00348 } while (dd->reordered == 1);
00349
00350 return(Cudd_NotCond(subset, (subset != NULL)));
00351
00352 }
00353
00354
00381 DdNode *
00382 Cudd_BiasedUnderApprox(
00383 DdManager *dd ,
00384 DdNode *f ,
00385 DdNode *b ,
00386 int numVars ,
00387 int threshold ,
00388 double quality1 ,
00389 double quality0 )
00390 {
00391 DdNode *subset;
00392
00393 do {
00394 dd->reordered = 0;
00395 subset = cuddBiasedUnderApprox(dd, f, b, numVars, threshold, quality1,
00396 quality0);
00397 } while (dd->reordered == 1);
00398
00399 return(subset);
00400
00401 }
00402
00403
00431 DdNode *
00432 Cudd_BiasedOverApprox(
00433 DdManager *dd ,
00434 DdNode *f ,
00435 DdNode *b ,
00436 int numVars ,
00437 int threshold ,
00438 double quality1 ,
00439 double quality0 )
00440 {
00441 DdNode *subset, *g;
00442
00443 g = Cudd_Not(f);
00444 do {
00445 dd->reordered = 0;
00446 subset = cuddBiasedUnderApprox(dd, g, b, numVars, threshold, quality1,
00447 quality0);
00448 } while (dd->reordered == 1);
00449
00450 return(Cudd_NotCond(subset, (subset != NULL)));
00451
00452 }
00453
00454
00455
00456
00457
00458
00459
00479 DdNode *
00480 cuddUnderApprox(
00481 DdManager * dd ,
00482 DdNode * f ,
00483 int numVars ,
00484 int threshold ,
00485 int safe ,
00486 double quality )
00487 {
00488 ApproxInfo *info;
00489 DdNode *subset;
00490 int result;
00491
00492 if (f == NULL) {
00493 fprintf(dd->err, "Cannot subset, nil object\n");
00494 return(NULL);
00495 }
00496
00497 if (Cudd_IsConstant(f)) {
00498 return(f);
00499 }
00500
00501
00502 info = gatherInfo(dd, f, numVars, safe);
00503 if (info == NULL) {
00504 (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n");
00505 dd->errorCode = CUDD_MEMORY_OUT;
00506 return(NULL);
00507 }
00508
00509
00510 result = UAmarkNodes(dd, f, info, threshold, safe, quality);
00511 if (result == 0) {
00512 (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n");
00513 FREE(info->page);
00514 st_free_table(info->table);
00515 FREE(info);
00516 dd->errorCode = CUDD_MEMORY_OUT;
00517 return(NULL);
00518 }
00519
00520
00521 subset = UAbuildSubset(dd, f, info);
00522 #if 1
00523 if (subset && info->size < Cudd_DagSize(subset))
00524 (void) fprintf(dd->err, "Wrong prediction: %d versus actual %d\n",
00525 info->size, Cudd_DagSize(subset));
00526 #endif
00527 FREE(info->page);
00528 st_free_table(info->table);
00529 FREE(info);
00530
00531 #ifdef DD_DEBUG
00532 if (subset != NULL) {
00533 cuddRef(subset);
00534 #if 0
00535 (void) Cudd_DebugCheck(dd);
00536 (void) Cudd_CheckKeys(dd);
00537 #endif
00538 if (!Cudd_bddLeq(dd, subset, f)) {
00539 (void) fprintf(dd->err, "Wrong subset\n");
00540 dd->errorCode = CUDD_INTERNAL_ERROR;
00541 }
00542 cuddDeref(subset);
00543 }
00544 #endif
00545 return(subset);
00546
00547 }
00548
00549
00569 DdNode *
00570 cuddRemapUnderApprox(
00571 DdManager * dd ,
00572 DdNode * f ,
00573 int numVars ,
00574 int threshold ,
00575 double quality )
00576 {
00577 ApproxInfo *info;
00578 DdNode *subset;
00579 int result;
00580
00581 if (f == NULL) {
00582 fprintf(dd->err, "Cannot subset, nil object\n");
00583 dd->errorCode = CUDD_INVALID_ARG;
00584 return(NULL);
00585 }
00586
00587 if (Cudd_IsConstant(f)) {
00588 return(f);
00589 }
00590
00591
00592 info = gatherInfo(dd, f, numVars, TRUE);
00593 if (info == NULL) {
00594 (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n");
00595 dd->errorCode = CUDD_MEMORY_OUT;
00596 return(NULL);
00597 }
00598
00599
00600 result = RAmarkNodes(dd, f, info, threshold, quality);
00601 if (result == 0) {
00602 (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n");
00603 FREE(info->page);
00604 st_free_table(info->table);
00605 FREE(info);
00606 dd->errorCode = CUDD_MEMORY_OUT;
00607 return(NULL);
00608 }
00609
00610
00611 subset = RAbuildSubset(dd, f, info);
00612 #if 1
00613 if (subset && info->size < Cudd_DagSize(subset))
00614 (void) fprintf(dd->err, "Wrong prediction: %d versus actual %d\n",
00615 info->size, Cudd_DagSize(subset));
00616 #endif
00617 FREE(info->page);
00618 st_free_table(info->table);
00619 FREE(info);
00620
00621 #ifdef DD_DEBUG
00622 if (subset != NULL) {
00623 cuddRef(subset);
00624 #if 0
00625 (void) Cudd_DebugCheck(dd);
00626 (void) Cudd_CheckKeys(dd);
00627 #endif
00628 if (!Cudd_bddLeq(dd, subset, f)) {
00629 (void) fprintf(dd->err, "Wrong subset\n");
00630 }
00631 cuddDeref(subset);
00632 dd->errorCode = CUDD_INTERNAL_ERROR;
00633 }
00634 #endif
00635 return(subset);
00636
00637 }
00638
00639
00659 DdNode *
00660 cuddBiasedUnderApprox(
00661 DdManager *dd ,
00662 DdNode *f ,
00663 DdNode *b ,
00664 int numVars ,
00665 int threshold ,
00666 double quality1 ,
00667 double quality0 )
00668 {
00669 ApproxInfo *info;
00670 DdNode *subset;
00671 int result;
00672 DdHashTable *cache;
00673
00674 if (f == NULL) {
00675 fprintf(dd->err, "Cannot subset, nil object\n");
00676 dd->errorCode = CUDD_INVALID_ARG;
00677 return(NULL);
00678 }
00679
00680 if (Cudd_IsConstant(f)) {
00681 return(f);
00682 }
00683
00684
00685 info = gatherInfo(dd, f, numVars, TRUE);
00686 if (info == NULL) {
00687 (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n");
00688 dd->errorCode = CUDD_MEMORY_OUT;
00689 return(NULL);
00690 }
00691
00692 cache = cuddHashTableInit(dd,2,2);
00693 result = BAapplyBias(dd, Cudd_Regular(f), b, info, cache);
00694 if (result == CARE_ERROR) {
00695 (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n");
00696 cuddHashTableQuit(cache);
00697 FREE(info->page);
00698 st_free_table(info->table);
00699 FREE(info);
00700 dd->errorCode = CUDD_MEMORY_OUT;
00701 return(NULL);
00702 }
00703 cuddHashTableQuit(cache);
00704
00705
00706 result = BAmarkNodes(dd, f, info, threshold, quality1, quality0);
00707 if (result == 0) {
00708 (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n");
00709 FREE(info->page);
00710 st_free_table(info->table);
00711 FREE(info);
00712 dd->errorCode = CUDD_MEMORY_OUT;
00713 return(NULL);
00714 }
00715
00716
00717 subset = RAbuildSubset(dd, f, info);
00718 #if 1
00719 if (subset && info->size < Cudd_DagSize(subset))
00720 (void) fprintf(dd->err, "Wrong prediction: %d versus actual %d\n",
00721 info->size, Cudd_DagSize(subset));
00722 #endif
00723 FREE(info->page);
00724 st_free_table(info->table);
00725 FREE(info);
00726
00727 #ifdef DD_DEBUG
00728 if (subset != NULL) {
00729 cuddRef(subset);
00730 #if 0
00731 (void) Cudd_DebugCheck(dd);
00732 (void) Cudd_CheckKeys(dd);
00733 #endif
00734 if (!Cudd_bddLeq(dd, subset, f)) {
00735 (void) fprintf(dd->err, "Wrong subset\n");
00736 }
00737 cuddDeref(subset);
00738 dd->errorCode = CUDD_INTERNAL_ERROR;
00739 }
00740 #endif
00741 return(subset);
00742
00743 }
00744
00745
00746
00747
00748
00749
00750
00763 static void
00764 updateParity(
00765 DdNode * node ,
00766 ApproxInfo * info ,
00767 int newparity )
00768 {
00769 NodeData *infoN;
00770 DdNode *E;
00771
00772 if (!st_lookup(info->table, (char *)node, (char **)&infoN)) return;
00773 if ((infoN->parity & newparity) != 0) return;
00774 infoN->parity |= newparity;
00775 if (Cudd_IsConstant(node)) return;
00776 updateParity(cuddT(node),info,newparity);
00777 E = cuddE(node);
00778 if (Cudd_IsComplement(E)) {
00779 updateParity(Cudd_Not(E),info,3-newparity);
00780 } else {
00781 updateParity(E,info,newparity);
00782 }
00783 return;
00784
00785 }
00786
00787
00805 static NodeData *
00806 gatherInfoAux(
00807 DdNode * node ,
00808 ApproxInfo * info ,
00809 int parity )
00810 {
00811 DdNode *N, *Nt, *Ne;
00812 NodeData *infoN, *infoT, *infoE;
00813
00814 N = Cudd_Regular(node);
00815
00816
00817 if (st_lookup(info->table, (char *)N, (char **)&infoN)) {
00818 if (parity) {
00819
00820 updateParity(N, info, 1 + (int) Cudd_IsComplement(node));
00821 }
00822 return(infoN);
00823 }
00824
00825
00826 Nt = Cudd_NotCond(cuddT(N), N != node);
00827 Ne = Cudd_NotCond(cuddE(N), N != node);
00828
00829 infoT = gatherInfoAux(Nt, info, parity);
00830 if (infoT == NULL) return(NULL);
00831 infoE = gatherInfoAux(Ne, info, parity);
00832 if (infoE == NULL) return(NULL);
00833
00834 infoT->functionRef++;
00835 infoE->functionRef++;
00836
00837
00838 infoN = &(info->page[info->index++]);
00839 infoN->parity |= 1 + (short) Cudd_IsComplement(node);
00840
00841 infoN->mintermsP = infoT->mintermsP/2;
00842 infoN->mintermsN = infoT->mintermsN/2;
00843 if (Cudd_IsComplement(Ne) ^ Cudd_IsComplement(node)) {
00844 infoN->mintermsP += infoE->mintermsN/2;
00845 infoN->mintermsN += infoE->mintermsP/2;
00846 } else {
00847 infoN->mintermsP += infoE->mintermsP/2;
00848 infoN->mintermsN += infoE->mintermsN/2;
00849 }
00850
00851
00852 if (st_insert(info->table,(char *)N, (char *)infoN) == ST_OUT_OF_MEM) {
00853 return(NULL);
00854 }
00855 return(infoN);
00856
00857 }
00858
00859
00875 static ApproxInfo *
00876 gatherInfo(
00877 DdManager * dd ,
00878 DdNode * node ,
00879 int numVars ,
00880 int parity )
00881 {
00882 ApproxInfo *info;
00883 NodeData *infoTop;
00884
00885
00886
00887
00888
00889
00890 if (numVars == 0) {
00891 numVars = DBL_MAX_EXP - 1;
00892 }
00893
00894 info = ALLOC(ApproxInfo,1);
00895 if (info == NULL) {
00896 dd->errorCode = CUDD_MEMORY_OUT;
00897 return(NULL);
00898 }
00899 info->max = pow(2.0,(double) numVars);
00900 info->one = DD_ONE(dd);
00901 info->zero = Cudd_Not(info->one);
00902 info->size = Cudd_DagSize(node);
00903
00904
00905
00906
00907
00908 info->page = ALLOC(NodeData,info->size);
00909 if (info->page == NULL) {
00910 dd->errorCode = CUDD_MEMORY_OUT;
00911 FREE(info);
00912 return(NULL);
00913 }
00914 memset(info->page, 0, info->size * sizeof(NodeData));
00915 info->table = st_init_table(st_ptrcmp,st_ptrhash);
00916 if (info->table == NULL) {
00917 FREE(info->page);
00918 FREE(info);
00919 return(NULL);
00920 }
00921
00922
00923
00924
00925 if (st_insert(info->table, (char *)info->one, (char *)info->page) == ST_OUT_OF_MEM) {
00926 FREE(info->page);
00927 FREE(info);
00928 st_free_table(info->table);
00929 return(NULL);
00930 }
00931 info->page[0].mintermsP = info->max;
00932 info->index = 1;
00933
00934 infoTop = gatherInfoAux(node,info,parity);
00935 if (infoTop == NULL) {
00936 FREE(info->page);
00937 st_free_table(info->table);
00938 FREE(info);
00939 return(NULL);
00940 }
00941 if (Cudd_IsComplement(node)) {
00942 info->minterms = infoTop->mintermsN;
00943 } else {
00944 info->minterms = infoTop->mintermsP;
00945 }
00946
00947 infoTop->functionRef = 1;
00948 return(info);
00949
00950 }
00951
00952
00969 static int
00970 computeSavings(
00971 DdManager * dd,
00972 DdNode * f,
00973 DdNode * skip,
00974 ApproxInfo * info,
00975 DdLevelQueue * queue)
00976 {
00977 NodeData *infoN;
00978 LocalQueueItem *item;
00979 DdNode *node;
00980 int savings = 0;
00981
00982 node = Cudd_Regular(f);
00983 skip = Cudd_Regular(skip);
00984
00985
00986
00987 item = (LocalQueueItem *)
00988 cuddLevelQueueEnqueue(queue,node,cuddI(dd,node->index));
00989 if (item == NULL)
00990 return(0);
00991 (void) st_lookup(info->table, (char *)node, (char **)&infoN);
00992 item->localRef = infoN->functionRef;
00993
00994
00995 while (queue->first != NULL) {
00996 item = (LocalQueueItem *) queue->first;
00997 node = item->node;
00998 cuddLevelQueueDequeue(queue,cuddI(dd,node->index));
00999 if (node == skip) continue;
01000 (void) st_lookup(info->table, (char *)node, (char **)&infoN);
01001 if (item->localRef != infoN->functionRef) {
01002
01003 continue;
01004 }
01005 savings++;
01006 if (!cuddIsConstant(cuddT(node))) {
01007 item = (LocalQueueItem *) cuddLevelQueueEnqueue(queue,cuddT(node),
01008 cuddI(dd,cuddT(node)->index));
01009 if (item == NULL) return(0);
01010 item->localRef++;
01011 }
01012 if (!Cudd_IsConstant(cuddE(node))) {
01013 item = (LocalQueueItem *) cuddLevelQueueEnqueue(queue,Cudd_Regular(cuddE(node)),
01014 cuddI(dd,Cudd_Regular(cuddE(node))->index));
01015 if (item == NULL) return(0);
01016 item->localRef++;
01017 }
01018 }
01019
01020 #ifdef DD_DEBUG
01021
01022 assert(queue->size == 0);
01023 #endif
01024 return(savings);
01025
01026 }
01027
01028
01041 static int
01042 updateRefs(
01043 DdManager * dd,
01044 DdNode * f,
01045 DdNode * skip,
01046 ApproxInfo * info,
01047 DdLevelQueue * queue)
01048 {
01049 NodeData *infoN;
01050 LocalQueueItem *item;
01051 DdNode *node;
01052 int savings = 0;
01053
01054 node = Cudd_Regular(f);
01055
01056
01057
01058 item = (LocalQueueItem *) cuddLevelQueueEnqueue(queue,node,cuddI(dd,node->index));
01059 if (item == NULL)
01060 return(0);
01061 (void) st_lookup(info->table, (char *)node, (char **)&infoN);
01062 infoN->functionRef = 0;
01063
01064 if (skip != NULL) {
01065
01066
01067 skip = Cudd_Regular(skip);
01068 (void) st_lookup(info->table, (char *)skip, (char **)&infoN);
01069 infoN->functionRef++;
01070 }
01071
01072
01073 while (queue->first != NULL) {
01074 item = (LocalQueueItem *) queue->first;
01075 node = item->node;
01076 cuddLevelQueueDequeue(queue,cuddI(dd,node->index));
01077 (void) st_lookup(info->table, (char *)node, (char **)&infoN);
01078 if (infoN->functionRef != 0) {
01079
01080 continue;
01081 }
01082 savings++;
01083 if (!cuddIsConstant(cuddT(node))) {
01084 item = (LocalQueueItem *) cuddLevelQueueEnqueue(queue,cuddT(node),
01085 cuddI(dd,cuddT(node)->index));
01086 if (item == NULL) return(0);
01087 (void) st_lookup(info->table, (char *)cuddT(node),
01088 (char **)&infoN);
01089 infoN->functionRef--;
01090 }
01091 if (!Cudd_IsConstant(cuddE(node))) {
01092 item = (LocalQueueItem *) cuddLevelQueueEnqueue(queue,Cudd_Regular(cuddE(node)),
01093 cuddI(dd,Cudd_Regular(cuddE(node))->index));
01094 if (item == NULL) return(0);
01095 (void) st_lookup(info->table, (char *)Cudd_Regular(cuddE(node)),
01096 (char **)&infoN);
01097 infoN->functionRef--;
01098 }
01099 }
01100
01101 #ifdef DD_DEBUG
01102
01103 assert(queue->size == 0);
01104 #endif
01105 return(savings);
01106
01107 }
01108
01109
01122 static int
01123 UAmarkNodes(
01124 DdManager * dd ,
01125 DdNode * f ,
01126 ApproxInfo * info ,
01127 int threshold ,
01128 int safe ,
01129 double quality )
01130 {
01131 DdLevelQueue *queue;
01132 DdLevelQueue *localQueue;
01133 NodeData *infoN;
01134 GlobalQueueItem *item;
01135 DdNode *node;
01136 double numOnset;
01137 double impactP, impactN;
01138 int savings;
01139
01140 #if 0
01141 (void) printf("initial size = %d initial minterms = %g\n",
01142 info->size, info->minterms);
01143 #endif
01144 queue = cuddLevelQueueInit(dd->size,sizeof(GlobalQueueItem),info->size);
01145 if (queue == NULL) {
01146 return(0);
01147 }
01148 localQueue = cuddLevelQueueInit(dd->size,sizeof(LocalQueueItem),
01149 dd->initSlots);
01150 if (localQueue == NULL) {
01151 cuddLevelQueueQuit(queue);
01152 return(0);
01153 }
01154 node = Cudd_Regular(f);
01155 item = (GlobalQueueItem *) cuddLevelQueueEnqueue(queue,node,cuddI(dd,node->index));
01156 if (item == NULL) {
01157 cuddLevelQueueQuit(queue);
01158 cuddLevelQueueQuit(localQueue);
01159 return(0);
01160 }
01161 if (Cudd_IsComplement(f)) {
01162 item->impactP = 0.0;
01163 item->impactN = 1.0;
01164 } else {
01165 item->impactP = 1.0;
01166 item->impactN = 0.0;
01167 }
01168 while (queue->first != NULL) {
01169
01170 if (info->size <= threshold)
01171 break;
01172 item = (GlobalQueueItem *) queue->first;
01173 node = item->node;
01174 node = Cudd_Regular(node);
01175 (void) st_lookup(info->table, (char *)node, (char **)&infoN);
01176 if (safe && infoN->parity == 3) {
01177 cuddLevelQueueDequeue(queue,cuddI(dd,node->index));
01178 continue;
01179 }
01180 impactP = item->impactP;
01181 impactN = item->impactN;
01182 numOnset = infoN->mintermsP * impactP + infoN->mintermsN * impactN;
01183 savings = computeSavings(dd,node,NULL,info,localQueue);
01184 if (savings == 0) {
01185 cuddLevelQueueQuit(queue);
01186 cuddLevelQueueQuit(localQueue);
01187 return(0);
01188 }
01189 cuddLevelQueueDequeue(queue,cuddI(dd,node->index));
01190 #if 0
01191 (void) printf("node %p: impact = %g/%g numOnset = %g savings %d\n",
01192 node, impactP, impactN, numOnset, savings);
01193 #endif
01194 if ((1 - numOnset / info->minterms) >
01195 quality * (1 - (double) savings / info->size)) {
01196 infoN->replace = TRUE;
01197 info->size -= savings;
01198 info->minterms -=numOnset;
01199 #if 0
01200 (void) printf("replace: new size = %d new minterms = %g\n",
01201 info->size, info->minterms);
01202 #endif
01203 savings -= updateRefs(dd,node,NULL,info,localQueue);
01204 assert(savings == 0);
01205 continue;
01206 }
01207 if (!cuddIsConstant(cuddT(node))) {
01208 item = (GlobalQueueItem *) cuddLevelQueueEnqueue(queue,cuddT(node),
01209 cuddI(dd,cuddT(node)->index));
01210 item->impactP += impactP/2.0;
01211 item->impactN += impactN/2.0;
01212 }
01213 if (!Cudd_IsConstant(cuddE(node))) {
01214 item = (GlobalQueueItem *) cuddLevelQueueEnqueue(queue,Cudd_Regular(cuddE(node)),
01215 cuddI(dd,Cudd_Regular(cuddE(node))->index));
01216 if (Cudd_IsComplement(cuddE(node))) {
01217 item->impactP += impactN/2.0;
01218 item->impactN += impactP/2.0;
01219 } else {
01220 item->impactP += impactP/2.0;
01221 item->impactN += impactN/2.0;
01222 }
01223 }
01224 }
01225
01226 cuddLevelQueueQuit(queue);
01227 cuddLevelQueueQuit(localQueue);
01228 return(1);
01229
01230 }
01231
01232
01246 static DdNode *
01247 UAbuildSubset(
01248 DdManager * dd ,
01249 DdNode * node ,
01250 ApproxInfo * info )
01251 {
01252
01253 DdNode *Nt, *Ne, *N, *t, *e, *r;
01254 NodeData *infoN;
01255
01256 if (Cudd_IsConstant(node))
01257 return(node);
01258
01259 N = Cudd_Regular(node);
01260
01261 if (st_lookup(info->table, (char *)N, (char **)&infoN)) {
01262 if (infoN->replace == TRUE) {
01263 return(info->zero);
01264 }
01265 if (N == node ) {
01266 if (infoN->resultP != NULL) {
01267 return(infoN->resultP);
01268 }
01269 } else {
01270 if (infoN->resultN != NULL) {
01271 return(infoN->resultN);
01272 }
01273 }
01274 } else {
01275 (void) fprintf(dd->err,
01276 "Something is wrong, ought to be in info table\n");
01277 dd->errorCode = CUDD_INTERNAL_ERROR;
01278 return(NULL);
01279 }
01280
01281 Nt = Cudd_NotCond(cuddT(N), Cudd_IsComplement(node));
01282 Ne = Cudd_NotCond(cuddE(N), Cudd_IsComplement(node));
01283
01284 t = UAbuildSubset(dd, Nt, info);
01285 if (t == NULL) {
01286 return(NULL);
01287 }
01288 cuddRef(t);
01289
01290 e = UAbuildSubset(dd, Ne, info);
01291 if (e == NULL) {
01292 Cudd_RecursiveDeref(dd,t);
01293 return(NULL);
01294 }
01295 cuddRef(e);
01296
01297 if (Cudd_IsComplement(t)) {
01298 t = Cudd_Not(t);
01299 e = Cudd_Not(e);
01300 r = (t == e) ? t : cuddUniqueInter(dd, N->index, t, e);
01301 if (r == NULL) {
01302 Cudd_RecursiveDeref(dd, e);
01303 Cudd_RecursiveDeref(dd, t);
01304 return(NULL);
01305 }
01306 r = Cudd_Not(r);
01307 } else {
01308 r = (t == e) ? t : cuddUniqueInter(dd, N->index, t, e);
01309 if (r == NULL) {
01310 Cudd_RecursiveDeref(dd, e);
01311 Cudd_RecursiveDeref(dd, t);
01312 return(NULL);
01313 }
01314 }
01315 cuddDeref(t);
01316 cuddDeref(e);
01317
01318 if (N == node) {
01319 infoN->resultP = r;
01320 } else {
01321 infoN->resultN = r;
01322 }
01323
01324 return(r);
01325
01326 }
01327
01328
01341 static int
01342 RAmarkNodes(
01343 DdManager * dd ,
01344 DdNode * f ,
01345 ApproxInfo * info ,
01346 int threshold ,
01347 double quality )
01348 {
01349 DdLevelQueue *queue;
01350 DdLevelQueue *localQueue;
01351 NodeData *infoN, *infoT, *infoE;
01352 GlobalQueueItem *item;
01353 DdNode *node, *T, *E;
01354 DdNode *shared;
01355 double numOnset;
01356 double impact, impactP, impactN;
01357 double minterms;
01358 int savings;
01359 int replace;
01360
01361 #if 0
01362 (void) fprintf(dd->out,"initial size = %d initial minterms = %g\n",
01363 info->size, info->minterms);
01364 #endif
01365 queue = cuddLevelQueueInit(dd->size,sizeof(GlobalQueueItem),info->size);
01366 if (queue == NULL) {
01367 return(0);
01368 }
01369 localQueue = cuddLevelQueueInit(dd->size,sizeof(LocalQueueItem),
01370 dd->initSlots);
01371 if (localQueue == NULL) {
01372 cuddLevelQueueQuit(queue);
01373 return(0);
01374 }
01375
01376 node = Cudd_Regular(f);
01377 item = (GlobalQueueItem *)
01378 cuddLevelQueueEnqueue(queue,node,cuddI(dd,node->index));
01379 if (item == NULL) {
01380 cuddLevelQueueQuit(queue);
01381 cuddLevelQueueQuit(localQueue);
01382 return(0);
01383 }
01384 if (Cudd_IsComplement(f)) {
01385 item->impactP = 0.0;
01386 item->impactN = 1.0;
01387 } else {
01388 item->impactP = 1.0;
01389 item->impactN = 0.0;
01390 }
01391
01392
01393
01394
01395 while (queue->first != NULL) {
01396
01397 if (info->size <= threshold)
01398 break;
01399 item = (GlobalQueueItem *) queue->first;
01400 node = item->node;
01401 #ifdef DD_DEBUG
01402 assert(item->impactP >= 0 && item->impactP <= 1.0);
01403 assert(item->impactN >= 0 && item->impactN <= 1.0);
01404 assert(!Cudd_IsComplement(node));
01405 assert(!Cudd_IsConstant(node));
01406 #endif
01407 if (!st_lookup(info->table, (char *)node, (char **)&infoN)) {
01408 cuddLevelQueueQuit(queue);
01409 cuddLevelQueueQuit(localQueue);
01410 return(0);
01411 }
01412 #ifdef DD_DEBUG
01413 assert(infoN->parity >= 1 && infoN->parity <= 3);
01414 #endif
01415 if (infoN->parity == 3) {
01416
01417
01418
01419
01420 cuddLevelQueueDequeue(queue,cuddI(dd,node->index));
01421 continue;
01422 }
01423 T = cuddT(node);
01424 E = cuddE(node);
01425 shared = NULL;
01426 impactP = item->impactP;
01427 impactN = item->impactN;
01428 if (Cudd_bddLeq(dd,T,E)) {
01429
01430 #ifdef DD_DEBUG
01431 assert(!Cudd_IsComplement(E));
01432 #endif
01433 (void) st_lookup(info->table, (char *)T, (char **)&infoT);
01434 (void) st_lookup(info->table, (char *)E, (char **)&infoE);
01435 if (infoN->parity == 1) {
01436 impact = impactP;
01437 minterms = infoE->mintermsP/2.0 - infoT->mintermsP/2.0;
01438 if (infoE->functionRef == 1 && !Cudd_IsConstant(E)) {
01439 savings = 1 + computeSavings(dd,E,NULL,info,localQueue);
01440 if (savings == 1) {
01441 cuddLevelQueueQuit(queue);
01442 cuddLevelQueueQuit(localQueue);
01443 return(0);
01444 }
01445 } else {
01446 savings = 1;
01447 }
01448 replace = REPLACE_E;
01449 } else {
01450 #ifdef DD_DEBUG
01451 assert(infoN->parity == 2);
01452 #endif
01453 impact = impactN;
01454 minterms = infoT->mintermsN/2.0 - infoE->mintermsN/2.0;
01455 if (infoT->functionRef == 1 && !Cudd_IsConstant(T)) {
01456 savings = 1 + computeSavings(dd,T,NULL,info,localQueue);
01457 if (savings == 1) {
01458 cuddLevelQueueQuit(queue);
01459 cuddLevelQueueQuit(localQueue);
01460 return(0);
01461 }
01462 } else {
01463 savings = 1;
01464 }
01465 replace = REPLACE_T;
01466 }
01467 numOnset = impact * minterms;
01468 } else if (Cudd_bddLeq(dd,E,T)) {
01469
01470 DdNode *Ereg = Cudd_Regular(E);
01471 (void) st_lookup(info->table, (char *)T, (char **)&infoT);
01472 (void) st_lookup(info->table, (char *)Ereg, (char **)&infoE);
01473 if (infoN->parity == 1) {
01474 impact = impactP;
01475 minterms = infoT->mintermsP/2.0 -
01476 ((E == Ereg) ? infoE->mintermsP : infoE->mintermsN)/2.0;
01477 if (infoT->functionRef == 1 && !Cudd_IsConstant(T)) {
01478 savings = 1 + computeSavings(dd,T,NULL,info,localQueue);
01479 if (savings == 1) {
01480 cuddLevelQueueQuit(queue);
01481 cuddLevelQueueQuit(localQueue);
01482 return(0);
01483 }
01484 } else {
01485 savings = 1;
01486 }
01487 replace = REPLACE_T;
01488 } else {
01489 #ifdef DD_DEBUG
01490 assert(infoN->parity == 2);
01491 #endif
01492 impact = impactN;
01493 minterms = ((E == Ereg) ? infoE->mintermsN :
01494 infoE->mintermsP)/2.0 - infoT->mintermsN/2.0;
01495 if (infoE->functionRef == 1 && !Cudd_IsConstant(E)) {
01496 savings = 1 + computeSavings(dd,E,NULL,info,localQueue);
01497 if (savings == 1) {
01498 cuddLevelQueueQuit(queue);
01499 cuddLevelQueueQuit(localQueue);
01500 return(0);
01501 }
01502 } else {
01503 savings = 1;
01504 }
01505 replace = REPLACE_E;
01506 }
01507 numOnset = impact * minterms;
01508 } else {
01509 DdNode *Ereg = Cudd_Regular(E);
01510 DdNode *TT = cuddT(T);
01511 DdNode *ET = Cudd_NotCond(cuddT(Ereg), Cudd_IsComplement(E));
01512 if (T->index == Ereg->index && TT == ET) {
01513 shared = TT;
01514 replace = REPLACE_TT;
01515 } else {
01516 DdNode *TE = cuddE(T);
01517 DdNode *EE = Cudd_NotCond(cuddE(Ereg), Cudd_IsComplement(E));
01518 if (T->index == Ereg->index && TE == EE) {
01519 shared = TE;
01520 replace = REPLACE_TE;
01521 } else {
01522 replace = REPLACE_N;
01523 }
01524 }
01525 numOnset = infoN->mintermsP * impactP + infoN->mintermsN * impactN;
01526 savings = computeSavings(dd,node,shared,info,localQueue);
01527 if (shared != NULL) {
01528 NodeData *infoS;
01529 (void) st_lookup(info->table, (char *)Cudd_Regular(shared),
01530 (char **)&infoS);
01531 if (Cudd_IsComplement(shared)) {
01532 numOnset -= (infoS->mintermsN * impactP +
01533 infoS->mintermsP * impactN)/2.0;
01534 } else {
01535 numOnset -= (infoS->mintermsP * impactP +
01536 infoS->mintermsN * impactN)/2.0;
01537 }
01538 savings--;
01539 }
01540 }
01541
01542 cuddLevelQueueDequeue(queue,cuddI(dd,node->index));
01543 #if 0
01544 if (replace == REPLACE_T || replace == REPLACE_E)
01545 (void) printf("node %p: impact = %g numOnset = %g savings %d\n",
01546 node, impact, numOnset, savings);
01547 else
01548 (void) printf("node %p: impact = %g/%g numOnset = %g savings %d\n",
01549 node, impactP, impactN, numOnset, savings);
01550 #endif
01551 if ((1 - numOnset / info->minterms) >
01552 quality * (1 - (double) savings / info->size)) {
01553 infoN->replace = replace;
01554 info->size -= savings;
01555 info->minterms -=numOnset;
01556 #if 0
01557 (void) printf("remap(%d): new size = %d new minterms = %g\n",
01558 replace, info->size, info->minterms);
01559 #endif
01560 if (replace == REPLACE_N) {
01561 savings -= updateRefs(dd,node,NULL,info,localQueue);
01562 } else if (replace == REPLACE_T) {
01563 savings -= updateRefs(dd,node,E,info,localQueue);
01564 } else if (replace == REPLACE_E) {
01565 savings -= updateRefs(dd,node,T,info,localQueue);
01566 } else {
01567 #ifdef DD_DEBUG
01568 assert(replace == REPLACE_TT || replace == REPLACE_TE);
01569 #endif
01570 savings -= updateRefs(dd,node,shared,info,localQueue) - 1;
01571 }
01572 assert(savings == 0);
01573 } else {
01574 replace = NOTHING;
01575 }
01576 if (replace == REPLACE_N) continue;
01577 if ((replace == REPLACE_E || replace == NOTHING) &&
01578 !cuddIsConstant(cuddT(node))) {
01579 item = (GlobalQueueItem *) cuddLevelQueueEnqueue(queue,cuddT(node),
01580 cuddI(dd,cuddT(node)->index));
01581 if (replace == REPLACE_E) {
01582 item->impactP += impactP;
01583 item->impactN += impactN;
01584 } else {
01585 item->impactP += impactP/2.0;
01586 item->impactN += impactN/2.0;
01587 }
01588 }
01589 if ((replace == REPLACE_T || replace == NOTHING) &&
01590 !Cudd_IsConstant(cuddE(node))) {
01591 item = (GlobalQueueItem *) cuddLevelQueueEnqueue(queue,Cudd_Regular(cuddE(node)),
01592 cuddI(dd,Cudd_Regular(cuddE(node))->index));
01593 if (Cudd_IsComplement(cuddE(node))) {
01594 if (replace == REPLACE_T) {
01595 item->impactP += impactN;
01596 item->impactN += impactP;
01597 } else {
01598 item->impactP += impactN/2.0;
01599 item->impactN += impactP/2.0;
01600 }
01601 } else {
01602 if (replace == REPLACE_T) {
01603 item->impactP += impactP;
01604 item->impactN += impactN;
01605 } else {
01606 item->impactP += impactP/2.0;
01607 item->impactN += impactN/2.0;
01608 }
01609 }
01610 }
01611 if ((replace == REPLACE_TT || replace == REPLACE_TE) &&
01612 !Cudd_IsConstant(shared)) {
01613 item = (GlobalQueueItem *) cuddLevelQueueEnqueue(queue,Cudd_Regular(shared),
01614 cuddI(dd,Cudd_Regular(shared)->index));
01615 if (Cudd_IsComplement(shared)) {
01616 if (replace == REPLACE_T) {
01617 item->impactP += impactN;
01618 item->impactN += impactP;
01619 } else {
01620 item->impactP += impactN/2.0;
01621 item->impactN += impactP/2.0;
01622 }
01623 } else {
01624 if (replace == REPLACE_T) {
01625 item->impactP += impactP;
01626 item->impactN += impactN;
01627 } else {
01628 item->impactP += impactP/2.0;
01629 item->impactN += impactN/2.0;
01630 }
01631 }
01632 }
01633 }
01634
01635 cuddLevelQueueQuit(queue);
01636 cuddLevelQueueQuit(localQueue);
01637 return(1);
01638
01639 }
01640
01641
01654 static int
01655 BAmarkNodes(
01656 DdManager *dd ,
01657 DdNode *f ,
01658 ApproxInfo *info ,
01659 int threshold ,
01660 double quality1 ,
01661 double quality0 )
01662 {
01663 DdLevelQueue *queue;
01664 DdLevelQueue *localQueue;
01665 NodeData *infoN, *infoT, *infoE;
01666 GlobalQueueItem *item;
01667 DdNode *node, *T, *E;
01668 DdNode *shared;
01669 double numOnset;
01670 double impact, impactP, impactN;
01671 double minterms;
01672 double quality;
01673 int savings;
01674 int replace;
01675
01676 #if 0
01677 (void) fprintf(dd->out,"initial size = %d initial minterms = %g\n",
01678 info->size, info->minterms);
01679 #endif
01680 queue = cuddLevelQueueInit(dd->size,sizeof(GlobalQueueItem),info->size);
01681 if (queue == NULL) {
01682 return(0);
01683 }
01684 localQueue = cuddLevelQueueInit(dd->size,sizeof(LocalQueueItem),
01685 dd->initSlots);
01686 if (localQueue == NULL) {
01687 cuddLevelQueueQuit(queue);
01688 return(0);
01689 }
01690
01691 node = Cudd_Regular(f);
01692 item = (GlobalQueueItem *)
01693 cuddLevelQueueEnqueue(queue,node,cuddI(dd,node->index));
01694 if (item == NULL) {
01695 cuddLevelQueueQuit(queue);
01696 cuddLevelQueueQuit(localQueue);
01697 return(0);
01698 }
01699 if (Cudd_IsComplement(f)) {
01700 item->impactP = 0.0;
01701 item->impactN = 1.0;
01702 } else {
01703 item->impactP = 1.0;
01704 item->impactN = 0.0;
01705 }
01706
01707
01708
01709
01710 while (queue->first != NULL) {
01711
01712 if (info->size <= threshold)
01713 break;
01714 item = (GlobalQueueItem *) queue->first;
01715 node = item->node;
01716 #ifdef DD_DEBUG
01717 assert(item->impactP >= 0 && item->impactP <= 1.0);
01718 assert(item->impactN >= 0 && item->impactN <= 1.0);
01719 assert(!Cudd_IsComplement(node));
01720 assert(!Cudd_IsConstant(node));
01721 #endif
01722 if (!st_lookup(info->table, (char *)node, (char **)&infoN)) {
01723 cuddLevelQueueQuit(queue);
01724 cuddLevelQueueQuit(localQueue);
01725 return(0);
01726 }
01727 quality = infoN->care ? quality1 : quality0;
01728 #ifdef DD_DEBUG
01729 assert(infoN->parity >= 1 && infoN->parity <= 3);
01730 #endif
01731 if (infoN->parity == 3) {
01732
01733
01734
01735
01736 cuddLevelQueueDequeue(queue,cuddI(dd,node->index));
01737 continue;
01738 }
01739 T = cuddT(node);
01740 E = cuddE(node);
01741 shared = NULL;
01742 impactP = item->impactP;
01743 impactN = item->impactN;
01744 if (Cudd_bddLeq(dd,T,E)) {
01745
01746 #ifdef DD_DEBUG
01747 assert(!Cudd_IsComplement(E));
01748 #endif
01749 (void) st_lookup(info->table, (char *)T, (char **)&infoT);
01750 (void) st_lookup(info->table, (char *)E, (char **)&infoE);
01751 if (infoN->parity == 1) {
01752 impact = impactP;
01753 minterms = infoE->mintermsP/2.0 - infoT->mintermsP/2.0;
01754 if (infoE->functionRef == 1 && !Cudd_IsConstant(E)) {
01755 savings = 1 + computeSavings(dd,E,NULL,info,localQueue);
01756 if (savings == 1) {
01757 cuddLevelQueueQuit(queue);
01758 cuddLevelQueueQuit(localQueue);
01759 return(0);
01760 }
01761 } else {
01762 savings = 1;
01763 }
01764 replace = REPLACE_E;
01765 } else {
01766 #ifdef DD_DEBUG
01767 assert(infoN->parity == 2);
01768 #endif
01769 impact = impactN;
01770 minterms = infoT->mintermsN/2.0 - infoE->mintermsN/2.0;
01771 if (infoT->functionRef == 1 && !Cudd_IsConstant(T)) {
01772 savings = 1 + computeSavings(dd,T,NULL,info,localQueue);
01773 if (savings == 1) {
01774 cuddLevelQueueQuit(queue);
01775 cuddLevelQueueQuit(localQueue);
01776 return(0);
01777 }
01778 } else {
01779 savings = 1;
01780 }
01781 replace = REPLACE_T;
01782 }
01783 numOnset = impact * minterms;
01784 } else if (Cudd_bddLeq(dd,E,T)) {
01785
01786 DdNode *Ereg = Cudd_Regular(E);
01787 (void) st_lookup(info->table, (char *)T, (char **)&infoT);
01788 (void) st_lookup(info->table, (char *)Ereg, (char **)&infoE);
01789 if (infoN->parity == 1) {
01790 impact = impactP;
01791 minterms = infoT->mintermsP/2.0 -
01792 ((E == Ereg) ? infoE->mintermsP : infoE->mintermsN)/2.0;
01793 if (infoT->functionRef == 1 && !Cudd_IsConstant(T)) {
01794 savings = 1 + computeSavings(dd,T,NULL,info,localQueue);
01795 if (savings == 1) {
01796 cuddLevelQueueQuit(queue);
01797 cuddLevelQueueQuit(localQueue);
01798 return(0);
01799 }
01800 } else {
01801 savings = 1;
01802 }
01803 replace = REPLACE_T;
01804 } else {
01805 #ifdef DD_DEBUG
01806 assert(infoN->parity == 2);
01807 #endif
01808 impact = impactN;
01809 minterms = ((E == Ereg) ? infoE->mintermsN :
01810 infoE->mintermsP)/2.0 - infoT->mintermsN/2.0;
01811 if (infoE->functionRef == 1 && !Cudd_IsConstant(E)) {
01812 savings = 1 + computeSavings(dd,E,NULL,info,localQueue);
01813 if (savings == 1) {
01814 cuddLevelQueueQuit(queue);
01815 cuddLevelQueueQuit(localQueue);
01816 return(0);
01817 }
01818 } else {
01819 savings = 1;
01820 }
01821 replace = REPLACE_E;
01822 }
01823 numOnset = impact * minterms;
01824 } else {
01825 DdNode *Ereg = Cudd_Regular(E);
01826 DdNode *TT = cuddT(T);
01827 DdNode *ET = Cudd_NotCond(cuddT(Ereg), Cudd_IsComplement(E));
01828 if (T->index == Ereg->index && TT == ET) {
01829 shared = TT;
01830 replace = REPLACE_TT;
01831 } else {
01832 DdNode *TE = cuddE(T);
01833 DdNode *EE = Cudd_NotCond(cuddE(Ereg), Cudd_IsComplement(E));
01834 if (T->index == Ereg->index && TE == EE) {
01835 shared = TE;
01836 replace = REPLACE_TE;
01837 } else {
01838 replace = REPLACE_N;
01839 }
01840 }
01841 numOnset = infoN->mintermsP * impactP + infoN->mintermsN * impactN;
01842 savings = computeSavings(dd,node,shared,info,localQueue);
01843 if (shared != NULL) {
01844 NodeData *infoS;
01845 (void) st_lookup(info->table, (char *)Cudd_Regular(shared),
01846 (char **)&infoS);
01847 if (Cudd_IsComplement(shared)) {
01848 numOnset -= (infoS->mintermsN * impactP +
01849 infoS->mintermsP * impactN)/2.0;
01850 } else {
01851 numOnset -= (infoS->mintermsP * impactP +
01852 infoS->mintermsN * impactN)/2.0;
01853 }
01854 savings--;
01855 }
01856 }
01857
01858 cuddLevelQueueDequeue(queue,cuddI(dd,node->index));
01859 #if 0
01860 if (replace == REPLACE_T || replace == REPLACE_E)
01861 (void) printf("node %p: impact = %g numOnset = %g savings %d\n",
01862 node, impact, numOnset, savings);
01863 else
01864 (void) printf("node %p: impact = %g/%g numOnset = %g savings %d\n",
01865 node, impactP, impactN, numOnset, savings);
01866 #endif
01867 if ((1 - numOnset / info->minterms) >
01868 quality * (1 - (double) savings / info->size)) {
01869 infoN->replace = replace;
01870 info->size -= savings;
01871 info->minterms -=numOnset;
01872 #if 0
01873 (void) printf("remap(%d): new size = %d new minterms = %g\n",
01874 replace, info->size, info->minterms);
01875 #endif
01876 if (replace == REPLACE_N) {
01877 savings -= updateRefs(dd,node,NULL,info,localQueue);
01878 } else if (replace == REPLACE_T) {
01879 savings -= updateRefs(dd,node,E,info,localQueue);
01880 } else if (replace == REPLACE_E) {
01881 savings -= updateRefs(dd,node,T,info,localQueue);
01882 } else {
01883 #ifdef DD_DEBUG
01884 assert(replace == REPLACE_TT || replace == REPLACE_TE);
01885 #endif
01886 savings -= updateRefs(dd,node,shared,info,localQueue) - 1;
01887 }
01888 assert(savings == 0);
01889 } else {
01890 replace = NOTHING;
01891 }
01892 if (replace == REPLACE_N) continue;
01893 if ((replace == REPLACE_E || replace == NOTHING) &&
01894 !cuddIsConstant(cuddT(node))) {
01895 item = (GlobalQueueItem *) cuddLevelQueueEnqueue(queue,cuddT(node),
01896 cuddI(dd,cuddT(node)->index));
01897 if (replace == REPLACE_E) {
01898 item->impactP += impactP;
01899 item->impactN += impactN;
01900 } else {
01901 item->impactP += impactP/2.0;
01902 item->impactN += impactN/2.0;
01903 }
01904 }
01905 if ((replace == REPLACE_T || replace == NOTHING) &&
01906 !Cudd_IsConstant(cuddE(node))) {
01907 item = (GlobalQueueItem *) cuddLevelQueueEnqueue(queue,Cudd_Regular(cuddE(node)),
01908 cuddI(dd,Cudd_Regular(cuddE(node))->index));
01909 if (Cudd_IsComplement(cuddE(node))) {
01910 if (replace == REPLACE_T) {
01911 item->impactP += impactN;
01912 item->impactN += impactP;
01913 } else {
01914 item->impactP += impactN/2.0;
01915 item->impactN += impactP/2.0;
01916 }
01917 } else {
01918 if (replace == REPLACE_T) {
01919 item->impactP += impactP;
01920 item->impactN += impactN;
01921 } else {
01922 item->impactP += impactP/2.0;
01923 item->impactN += impactN/2.0;
01924 }
01925 }
01926 }
01927 if ((replace == REPLACE_TT || replace == REPLACE_TE) &&
01928 !Cudd_IsConstant(shared)) {
01929 item = (GlobalQueueItem *) cuddLevelQueueEnqueue(queue,Cudd_Regular(shared),
01930 cuddI(dd,Cudd_Regular(shared)->index));
01931 if (Cudd_IsComplement(shared)) {
01932 if (replace == REPLACE_T) {
01933 item->impactP += impactN;
01934 item->impactN += impactP;
01935 } else {
01936 item->impactP += impactN/2.0;
01937 item->impactN += impactP/2.0;
01938 }
01939 } else {
01940 if (replace == REPLACE_T) {
01941 item->impactP += impactP;
01942 item->impactN += impactN;
01943 } else {
01944 item->impactP += impactP/2.0;
01945 item->impactN += impactN/2.0;
01946 }
01947 }
01948 }
01949 }
01950
01951 cuddLevelQueueQuit(queue);
01952 cuddLevelQueueQuit(localQueue);
01953 return(1);
01954
01955 }
01956
01957
01972 static DdNode *
01973 RAbuildSubset(
01974 DdManager * dd ,
01975 DdNode * node ,
01976 ApproxInfo * info )
01977 {
01978 DdNode *Nt, *Ne, *N, *t, *e, *r;
01979 NodeData *infoN;
01980
01981 if (Cudd_IsConstant(node))
01982 return(node);
01983
01984 N = Cudd_Regular(node);
01985
01986 Nt = Cudd_NotCond(cuddT(N), Cudd_IsComplement(node));
01987 Ne = Cudd_NotCond(cuddE(N), Cudd_IsComplement(node));
01988
01989 if (st_lookup(info->table, (char *)N, (char **)&infoN)) {
01990 if (N == node ) {
01991 if (infoN->resultP != NULL) {
01992 return(infoN->resultP);
01993 }
01994 } else {
01995 if (infoN->resultN != NULL) {
01996 return(infoN->resultN);
01997 }
01998 }
01999 if (infoN->replace == REPLACE_T) {
02000 r = RAbuildSubset(dd, Ne, info);
02001 return(r);
02002 } else if (infoN->replace == REPLACE_E) {
02003 r = RAbuildSubset(dd, Nt, info);
02004 return(r);
02005 } else if (infoN->replace == REPLACE_N) {
02006 return(info->zero);
02007 } else if (infoN->replace == REPLACE_TT) {
02008 DdNode *Ntt = Cudd_NotCond(cuddT(cuddT(N)),
02009 Cudd_IsComplement(node));
02010 int index = cuddT(N)->index;
02011 DdNode *e = info->zero;
02012 DdNode *t = RAbuildSubset(dd, Ntt, info);
02013 if (t == NULL) {
02014 return(NULL);
02015 }
02016 cuddRef(t);
02017 if (Cudd_IsComplement(t)) {
02018 t = Cudd_Not(t);
02019 e = Cudd_Not(e);
02020 r = (t == e) ? t : cuddUniqueInter(dd, index, t, e);
02021 if (r == NULL) {
02022 Cudd_RecursiveDeref(dd, t);
02023 return(NULL);
02024 }
02025 r = Cudd_Not(r);
02026 } else {
02027 r = (t == e) ? t : cuddUniqueInter(dd, index, t, e);
02028 if (r == NULL) {
02029 Cudd_RecursiveDeref(dd, t);
02030 return(NULL);
02031 }
02032 }
02033 cuddDeref(t);
02034 return(r);
02035 } else if (infoN->replace == REPLACE_TE) {
02036 DdNode *Nte = Cudd_NotCond(cuddE(cuddT(N)),
02037 Cudd_IsComplement(node));
02038 int index = cuddT(N)->index;
02039 DdNode *t = info->one;
02040 DdNode *e = RAbuildSubset(dd, Nte, info);
02041 if (e == NULL) {
02042 return(NULL);
02043 }
02044 cuddRef(e);
02045 e = Cudd_Not(e);
02046 r = (t == e) ? t : cuddUniqueInter(dd, index, t, e);
02047 if (r == NULL) {
02048 Cudd_RecursiveDeref(dd, e);
02049 return(NULL);
02050 }
02051 r =Cudd_Not(r);
02052 cuddDeref(e);
02053 return(r);
02054 }
02055 } else {
02056 (void) fprintf(dd->err,
02057 "Something is wrong, ought to be in info table\n");
02058 dd->errorCode = CUDD_INTERNAL_ERROR;
02059 return(NULL);
02060 }
02061
02062 t = RAbuildSubset(dd, Nt, info);
02063 if (t == NULL) {
02064 return(NULL);
02065 }
02066 cuddRef(t);
02067
02068 e = RAbuildSubset(dd, Ne, info);
02069 if (e == NULL) {
02070 Cudd_RecursiveDeref(dd,t);
02071 return(NULL);
02072 }
02073 cuddRef(e);
02074
02075 if (Cudd_IsComplement(t)) {
02076 t = Cudd_Not(t);
02077 e = Cudd_Not(e);
02078 r = (t == e) ? t : cuddUniqueInter(dd, N->index, t, e);
02079 if (r == NULL) {
02080 Cudd_RecursiveDeref(dd, e);
02081 Cudd_RecursiveDeref(dd, t);
02082 return(NULL);
02083 }
02084 r = Cudd_Not(r);
02085 } else {
02086 r = (t == e) ? t : cuddUniqueInter(dd, N->index, t, e);
02087 if (r == NULL) {
02088 Cudd_RecursiveDeref(dd, e);
02089 Cudd_RecursiveDeref(dd, t);
02090 return(NULL);
02091 }
02092 }
02093 cuddDeref(t);
02094 cuddDeref(e);
02095
02096 if (N == node) {
02097 infoN->resultP = r;
02098 } else {
02099 infoN->resultN = r;
02100 }
02101
02102 return(r);
02103
02104 }
02105
02106
02120 static int
02121 BAapplyBias(
02122 DdManager *dd,
02123 DdNode *f,
02124 DdNode *b,
02125 ApproxInfo *info,
02126 DdHashTable *cache)
02127 {
02128 DdNode *one, *zero, *res;
02129 DdNode *Ft, *Fe, *B, *Bt, *Be;
02130 unsigned int topf, topb;
02131 NodeData *infoF;
02132 int careT, careE;
02133
02134 one = DD_ONE(dd);
02135 zero = Cudd_Not(one);
02136
02137 if (!st_lookup(info->table, (char *) f, (char **)&infoF))
02138 return(CARE_ERROR);
02139 if (f == one) return(TOTAL_CARE);
02140 if (b == zero) return(infoF->care);
02141 if (infoF->care == TOTAL_CARE) return(TOTAL_CARE);
02142
02143 if ((f->ref != 1 || Cudd_Regular(b)->ref != 1) &&
02144 (res = cuddHashTableLookup2(cache,f,b)) != NULL) {
02145 if (res->ref == 0) {
02146 cache->manager->dead++;
02147 cache->manager->constants.dead++;
02148 }
02149 return(infoF->care);
02150 }
02151
02152 topf = dd->perm[f->index];
02153 B = Cudd_Regular(b);
02154 topb = cuddI(dd,B->index);
02155 if (topf <= topb) {
02156 Ft = cuddT(f); Fe = cuddE(f);
02157 } else {
02158 Ft = Fe = f;
02159 }
02160 if (topb <= topf) {
02161
02162 Bt = cuddT(B); Be = cuddE(B);
02163 if (Cudd_IsComplement(b)) {
02164 Bt = Cudd_Not(Bt);
02165 Be = Cudd_Not(Be);
02166 }
02167 } else {
02168 Bt = Be = b;
02169 }
02170
02171 careT = BAapplyBias(dd, Ft, Bt, info, cache);
02172 if (careT == CARE_ERROR)
02173 return(CARE_ERROR);
02174 careE = BAapplyBias(dd, Cudd_Regular(Fe), Be, info, cache);
02175 if (careE == CARE_ERROR)
02176 return(CARE_ERROR);
02177 if (careT == TOTAL_CARE && careE == TOTAL_CARE) {
02178 infoF->care = TOTAL_CARE;
02179 } else {
02180 infoF->care = CARE;
02181 }
02182
02183 if (f->ref != 1 || Cudd_Regular(b)->ref != 1) {
02184 ptrint fanout = (ptrint) f->ref * Cudd_Regular(b)->ref;
02185 cuddSatDec(fanout);
02186 if (!cuddHashTableInsert2(cache,f,b,one,fanout)) {
02187 return(CARE_ERROR);
02188 }
02189 }
02190 return(infoF->care);
02191
02192 }