00001
00076 #ifdef __STDC__
00077 #include <float.h>
00078 #else
00079 #define DBL_MAX_EXP 1024
00080 #endif
00081 #include "util.h"
00082 #include "cuddInt.h"
00083
00084
00085
00086
00087
00088 #define NOTHING 0
00089 #define REPLACE_T 1
00090 #define REPLACE_E 2
00091 #define REPLACE_N 3
00092 #define REPLACE_TT 4
00093 #define REPLACE_TE 5
00094
00095 #define DONT_CARE 0
00096 #define CARE 1
00097 #define TOTAL_CARE 2
00098 #define CARE_ERROR 3
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116 typedef struct NodeData {
00117 double mintermsP;
00118 double mintermsN;
00119 int functionRef;
00120 char care;
00121 char replace;
00122 short int parity;
00123 DdNode *resultP;
00124 DdNode *resultN;
00125 } NodeData;
00126
00127 typedef struct ApproxInfo {
00128 DdNode *one;
00129 DdNode *zero;
00130 NodeData *page;
00131 st_table *table;
00132 int index;
00133 double max;
00134 int size;
00135 double minterms;
00136 } ApproxInfo;
00137
00138
00139 #ifdef __osf__
00140 #pragma pointer_size save
00141 #pragma pointer_size short
00142 #endif
00143 typedef struct GlobalQueueItem {
00144 struct GlobalQueueItem *next;
00145 struct GlobalQueueItem *cnext;
00146 DdNode *node;
00147 double impactP;
00148 double impactN;
00149 } GlobalQueueItem;
00150
00151 typedef struct LocalQueueItem {
00152 struct LocalQueueItem *next;
00153 struct LocalQueueItem *cnext;
00154 DdNode *node;
00155 int localRef;
00156 } LocalQueueItem;
00157 #ifdef __osf__
00158 #pragma pointer_size restore
00159 #endif
00160
00161
00162
00163
00164
00165
00166 #ifndef lint
00167 static char rcsid[] DD_UNUSED = "$Id: cuddApprox.c,v 1.27 2009/02/19 16:16:51 fabio Exp $";
00168 #endif
00169
00170
00171
00172
00173
00176
00177
00178
00179
00180 static void updateParity (DdNode *node, ApproxInfo *info, int newparity);
00181 static NodeData * gatherInfoAux (DdNode *node, ApproxInfo *info, int parity);
00182 static ApproxInfo * gatherInfo (DdManager *dd, DdNode *node, int numVars, int parity);
00183 static int computeSavings (DdManager *dd, DdNode *f, DdNode *skip, ApproxInfo *info, DdLevelQueue *queue);
00184 static int updateRefs (DdManager *dd, DdNode *f, DdNode *skip, ApproxInfo *info, DdLevelQueue *queue);
00185 static int UAmarkNodes (DdManager *dd, DdNode *f, ApproxInfo *info, int threshold, int safe, double quality);
00186 static DdNode * UAbuildSubset (DdManager *dd, DdNode *node, ApproxInfo *info);
00187 static int RAmarkNodes (DdManager *dd, DdNode *f, ApproxInfo *info, int threshold, double quality);
00188 static int BAmarkNodes (DdManager *dd, DdNode *f, ApproxInfo *info, int threshold, double quality1, double quality0);
00189 static DdNode * RAbuildSubset (DdManager *dd, DdNode *node, ApproxInfo *info);
00190 static int BAapplyBias (DdManager *dd, DdNode *f, DdNode *b, ApproxInfo *info, DdHashTable *cache);
00191
00195
00196
00197
00198
00223 DdNode *
00224 Cudd_UnderApprox(
00225 DdManager * dd ,
00226 DdNode * f ,
00227 int numVars ,
00228 int threshold ,
00229 int safe ,
00230 double quality )
00231 {
00232 DdNode *subset;
00233
00234 do {
00235 dd->reordered = 0;
00236 subset = cuddUnderApprox(dd, f, numVars, threshold, safe, quality);
00237 } while (dd->reordered == 1);
00238
00239 return(subset);
00240
00241 }
00242
00243
00270 DdNode *
00271 Cudd_OverApprox(
00272 DdManager * dd ,
00273 DdNode * f ,
00274 int numVars ,
00275 int threshold ,
00276 int safe ,
00277 double quality )
00278 {
00279 DdNode *subset, *g;
00280
00281 g = Cudd_Not(f);
00282 do {
00283 dd->reordered = 0;
00284 subset = cuddUnderApprox(dd, g, numVars, threshold, safe, quality);
00285 } while (dd->reordered == 1);
00286
00287 return(Cudd_NotCond(subset, (subset != NULL)));
00288
00289 }
00290
00291
00315 DdNode *
00316 Cudd_RemapUnderApprox(
00317 DdManager * dd ,
00318 DdNode * f ,
00319 int numVars ,
00320 int threshold ,
00321 double quality )
00322 {
00323 DdNode *subset;
00324
00325 do {
00326 dd->reordered = 0;
00327 subset = cuddRemapUnderApprox(dd, f, numVars, threshold, quality);
00328 } while (dd->reordered == 1);
00329
00330 return(subset);
00331
00332 }
00333
00334
00361 DdNode *
00362 Cudd_RemapOverApprox(
00363 DdManager * dd ,
00364 DdNode * f ,
00365 int numVars ,
00366 int threshold ,
00367 double quality )
00368 {
00369 DdNode *subset, *g;
00370
00371 g = Cudd_Not(f);
00372 do {
00373 dd->reordered = 0;
00374 subset = cuddRemapUnderApprox(dd, g, numVars, threshold, quality);
00375 } while (dd->reordered == 1);
00376
00377 return(Cudd_NotCond(subset, (subset != NULL)));
00378
00379 }
00380
00381
00408 DdNode *
00409 Cudd_BiasedUnderApprox(
00410 DdManager *dd ,
00411 DdNode *f ,
00412 DdNode *b ,
00413 int numVars ,
00414 int threshold ,
00415 double quality1 ,
00416 double quality0 )
00417 {
00418 DdNode *subset;
00419
00420 do {
00421 dd->reordered = 0;
00422 subset = cuddBiasedUnderApprox(dd, f, b, numVars, threshold, quality1,
00423 quality0);
00424 } while (dd->reordered == 1);
00425
00426 return(subset);
00427
00428 }
00429
00430
00458 DdNode *
00459 Cudd_BiasedOverApprox(
00460 DdManager *dd ,
00461 DdNode *f ,
00462 DdNode *b ,
00463 int numVars ,
00464 int threshold ,
00465 double quality1 ,
00466 double quality0 )
00467 {
00468 DdNode *subset, *g;
00469
00470 g = Cudd_Not(f);
00471 do {
00472 dd->reordered = 0;
00473 subset = cuddBiasedUnderApprox(dd, g, b, numVars, threshold, quality1,
00474 quality0);
00475 } while (dd->reordered == 1);
00476
00477 return(Cudd_NotCond(subset, (subset != NULL)));
00478
00479 }
00480
00481
00482
00483
00484
00485
00486
00506 DdNode *
00507 cuddUnderApprox(
00508 DdManager * dd ,
00509 DdNode * f ,
00510 int numVars ,
00511 int threshold ,
00512 int safe ,
00513 double quality )
00514 {
00515 ApproxInfo *info;
00516 DdNode *subset;
00517 int result;
00518
00519 if (f == NULL) {
00520 fprintf(dd->err, "Cannot subset, nil object\n");
00521 return(NULL);
00522 }
00523
00524 if (Cudd_IsConstant(f)) {
00525 return(f);
00526 }
00527
00528
00529 info = gatherInfo(dd, f, numVars, safe);
00530 if (info == NULL) {
00531 (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n");
00532 dd->errorCode = CUDD_MEMORY_OUT;
00533 return(NULL);
00534 }
00535
00536
00537 result = UAmarkNodes(dd, f, info, threshold, safe, quality);
00538 if (result == 0) {
00539 (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n");
00540 FREE(info->page);
00541 st_free_table(info->table);
00542 FREE(info);
00543 dd->errorCode = CUDD_MEMORY_OUT;
00544 return(NULL);
00545 }
00546
00547
00548 subset = UAbuildSubset(dd, f, info);
00549 #if 1
00550 if (subset && info->size < Cudd_DagSize(subset))
00551 (void) fprintf(dd->err, "Wrong prediction: %d versus actual %d\n",
00552 info->size, Cudd_DagSize(subset));
00553 #endif
00554 FREE(info->page);
00555 st_free_table(info->table);
00556 FREE(info);
00557
00558 #ifdef DD_DEBUG
00559 if (subset != NULL) {
00560 cuddRef(subset);
00561 #if 0
00562 (void) Cudd_DebugCheck(dd);
00563 (void) Cudd_CheckKeys(dd);
00564 #endif
00565 if (!Cudd_bddLeq(dd, subset, f)) {
00566 (void) fprintf(dd->err, "Wrong subset\n");
00567 dd->errorCode = CUDD_INTERNAL_ERROR;
00568 }
00569 cuddDeref(subset);
00570 }
00571 #endif
00572 return(subset);
00573
00574 }
00575
00576
00596 DdNode *
00597 cuddRemapUnderApprox(
00598 DdManager * dd ,
00599 DdNode * f ,
00600 int numVars ,
00601 int threshold ,
00602 double quality )
00603 {
00604 ApproxInfo *info;
00605 DdNode *subset;
00606 int result;
00607
00608 if (f == NULL) {
00609 fprintf(dd->err, "Cannot subset, nil object\n");
00610 dd->errorCode = CUDD_INVALID_ARG;
00611 return(NULL);
00612 }
00613
00614 if (Cudd_IsConstant(f)) {
00615 return(f);
00616 }
00617
00618
00619 info = gatherInfo(dd, f, numVars, TRUE);
00620 if (info == NULL) {
00621 (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n");
00622 dd->errorCode = CUDD_MEMORY_OUT;
00623 return(NULL);
00624 }
00625
00626
00627 result = RAmarkNodes(dd, f, info, threshold, quality);
00628 if (result == 0) {
00629 (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n");
00630 FREE(info->page);
00631 st_free_table(info->table);
00632 FREE(info);
00633 dd->errorCode = CUDD_MEMORY_OUT;
00634 return(NULL);
00635 }
00636
00637
00638 subset = RAbuildSubset(dd, f, info);
00639 #if 1
00640 if (subset && info->size < Cudd_DagSize(subset))
00641 (void) fprintf(dd->err, "Wrong prediction: %d versus actual %d\n",
00642 info->size, Cudd_DagSize(subset));
00643 #endif
00644 FREE(info->page);
00645 st_free_table(info->table);
00646 FREE(info);
00647
00648 #ifdef DD_DEBUG
00649 if (subset != NULL) {
00650 cuddRef(subset);
00651 #if 0
00652 (void) Cudd_DebugCheck(dd);
00653 (void) Cudd_CheckKeys(dd);
00654 #endif
00655 if (!Cudd_bddLeq(dd, subset, f)) {
00656 (void) fprintf(dd->err, "Wrong subset\n");
00657 }
00658 cuddDeref(subset);
00659 dd->errorCode = CUDD_INTERNAL_ERROR;
00660 }
00661 #endif
00662 return(subset);
00663
00664 }
00665
00666
00686 DdNode *
00687 cuddBiasedUnderApprox(
00688 DdManager *dd ,
00689 DdNode *f ,
00690 DdNode *b ,
00691 int numVars ,
00692 int threshold ,
00693 double quality1 ,
00694 double quality0 )
00695 {
00696 ApproxInfo *info;
00697 DdNode *subset;
00698 int result;
00699 DdHashTable *cache;
00700
00701 if (f == NULL) {
00702 fprintf(dd->err, "Cannot subset, nil object\n");
00703 dd->errorCode = CUDD_INVALID_ARG;
00704 return(NULL);
00705 }
00706
00707 if (Cudd_IsConstant(f)) {
00708 return(f);
00709 }
00710
00711
00712 info = gatherInfo(dd, f, numVars, TRUE);
00713 if (info == NULL) {
00714 (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n");
00715 dd->errorCode = CUDD_MEMORY_OUT;
00716 return(NULL);
00717 }
00718
00719 cache = cuddHashTableInit(dd,2,2);
00720 result = BAapplyBias(dd, Cudd_Regular(f), b, info, cache);
00721 if (result == CARE_ERROR) {
00722 (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n");
00723 cuddHashTableQuit(cache);
00724 FREE(info->page);
00725 st_free_table(info->table);
00726 FREE(info);
00727 dd->errorCode = CUDD_MEMORY_OUT;
00728 return(NULL);
00729 }
00730 cuddHashTableQuit(cache);
00731
00732
00733 result = BAmarkNodes(dd, f, info, threshold, quality1, quality0);
00734 if (result == 0) {
00735 (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n");
00736 FREE(info->page);
00737 st_free_table(info->table);
00738 FREE(info);
00739 dd->errorCode = CUDD_MEMORY_OUT;
00740 return(NULL);
00741 }
00742
00743
00744 subset = RAbuildSubset(dd, f, info);
00745 #if 1
00746 if (subset && info->size < Cudd_DagSize(subset))
00747 (void) fprintf(dd->err, "Wrong prediction: %d versus actual %d\n",
00748 info->size, Cudd_DagSize(subset));
00749 #endif
00750 FREE(info->page);
00751 st_free_table(info->table);
00752 FREE(info);
00753
00754 #ifdef DD_DEBUG
00755 if (subset != NULL) {
00756 cuddRef(subset);
00757 #if 0
00758 (void) Cudd_DebugCheck(dd);
00759 (void) Cudd_CheckKeys(dd);
00760 #endif
00761 if (!Cudd_bddLeq(dd, subset, f)) {
00762 (void) fprintf(dd->err, "Wrong subset\n");
00763 }
00764 cuddDeref(subset);
00765 dd->errorCode = CUDD_INTERNAL_ERROR;
00766 }
00767 #endif
00768 return(subset);
00769
00770 }
00771
00772
00773
00774
00775
00776
00777
00790 static void
00791 updateParity(
00792 DdNode * node ,
00793 ApproxInfo * info ,
00794 int newparity )
00795 {
00796 NodeData *infoN;
00797 DdNode *E;
00798
00799 if (!st_lookup(info->table, node, &infoN)) return;
00800 if ((infoN->parity & newparity) != 0) return;
00801 infoN->parity |= (short) newparity;
00802 if (Cudd_IsConstant(node)) return;
00803 updateParity(cuddT(node),info,newparity);
00804 E = cuddE(node);
00805 if (Cudd_IsComplement(E)) {
00806 updateParity(Cudd_Not(E),info,3-newparity);
00807 } else {
00808 updateParity(E,info,newparity);
00809 }
00810 return;
00811
00812 }
00813
00814
00832 static NodeData *
00833 gatherInfoAux(
00834 DdNode * node ,
00835 ApproxInfo * info ,
00836 int parity )
00837 {
00838 DdNode *N, *Nt, *Ne;
00839 NodeData *infoN, *infoT, *infoE;
00840
00841 N = Cudd_Regular(node);
00842
00843
00844 if (st_lookup(info->table, N, &infoN)) {
00845 if (parity) {
00846
00847 updateParity(N, info, 1 + (int) Cudd_IsComplement(node));
00848 }
00849 return(infoN);
00850 }
00851
00852
00853 Nt = Cudd_NotCond(cuddT(N), N != node);
00854 Ne = Cudd_NotCond(cuddE(N), N != node);
00855
00856 infoT = gatherInfoAux(Nt, info, parity);
00857 if (infoT == NULL) return(NULL);
00858 infoE = gatherInfoAux(Ne, info, parity);
00859 if (infoE == NULL) return(NULL);
00860
00861 infoT->functionRef++;
00862 infoE->functionRef++;
00863
00864
00865 infoN = &(info->page[info->index++]);
00866 infoN->parity |= (short) (1 + Cudd_IsComplement(node));
00867
00868 infoN->mintermsP = infoT->mintermsP/2;
00869 infoN->mintermsN = infoT->mintermsN/2;
00870 if (Cudd_IsComplement(Ne) ^ Cudd_IsComplement(node)) {
00871 infoN->mintermsP += infoE->mintermsN/2;
00872 infoN->mintermsN += infoE->mintermsP/2;
00873 } else {
00874 infoN->mintermsP += infoE->mintermsP/2;
00875 infoN->mintermsN += infoE->mintermsN/2;
00876 }
00877
00878
00879 if (st_insert(info->table,(char *)N, (char *)infoN) == ST_OUT_OF_MEM) {
00880 return(NULL);
00881 }
00882 return(infoN);
00883
00884 }
00885
00886
00902 static ApproxInfo *
00903 gatherInfo(
00904 DdManager * dd ,
00905 DdNode * node ,
00906 int numVars ,
00907 int parity )
00908 {
00909 ApproxInfo *info;
00910 NodeData *infoTop;
00911
00912
00913
00914
00915
00916
00917 if (numVars == 0) {
00918 numVars = DBL_MAX_EXP - 1;
00919 }
00920
00921 info = ALLOC(ApproxInfo,1);
00922 if (info == NULL) {
00923 dd->errorCode = CUDD_MEMORY_OUT;
00924 return(NULL);
00925 }
00926 info->max = pow(2.0,(double) numVars);
00927 info->one = DD_ONE(dd);
00928 info->zero = Cudd_Not(info->one);
00929 info->size = Cudd_DagSize(node);
00930
00931
00932
00933
00934
00935 info->page = ALLOC(NodeData,info->size);
00936 if (info->page == NULL) {
00937 dd->errorCode = CUDD_MEMORY_OUT;
00938 FREE(info);
00939 return(NULL);
00940 }
00941 memset(info->page, 0, info->size * sizeof(NodeData));
00942 info->table = st_init_table(st_ptrcmp,st_ptrhash);
00943 if (info->table == NULL) {
00944 FREE(info->page);
00945 FREE(info);
00946 return(NULL);
00947 }
00948
00949
00950
00951
00952 if (st_insert(info->table, (char *)info->one, (char *)info->page) == ST_OUT_OF_MEM) {
00953 FREE(info->page);
00954 FREE(info);
00955 st_free_table(info->table);
00956 return(NULL);
00957 }
00958 info->page[0].mintermsP = info->max;
00959 info->index = 1;
00960
00961 infoTop = gatherInfoAux(node,info,parity);
00962 if (infoTop == NULL) {
00963 FREE(info->page);
00964 st_free_table(info->table);
00965 FREE(info);
00966 return(NULL);
00967 }
00968 if (Cudd_IsComplement(node)) {
00969 info->minterms = infoTop->mintermsN;
00970 } else {
00971 info->minterms = infoTop->mintermsP;
00972 }
00973
00974 infoTop->functionRef = 1;
00975 return(info);
00976
00977 }
00978
00979
00996 static int
00997 computeSavings(
00998 DdManager * dd,
00999 DdNode * f,
01000 DdNode * skip,
01001 ApproxInfo * info,
01002 DdLevelQueue * queue)
01003 {
01004 NodeData *infoN;
01005 LocalQueueItem *item;
01006 DdNode *node;
01007 int savings = 0;
01008
01009 node = Cudd_Regular(f);
01010 skip = Cudd_Regular(skip);
01011
01012
01013
01014 item = (LocalQueueItem *)
01015 cuddLevelQueueEnqueue(queue,node,cuddI(dd,node->index));
01016 if (item == NULL)
01017 return(0);
01018 (void) st_lookup(info->table, node, &infoN);
01019 item->localRef = infoN->functionRef;
01020
01021
01022 while (queue->first != NULL) {
01023 item = (LocalQueueItem *) queue->first;
01024 node = item->node;
01025 cuddLevelQueueDequeue(queue,cuddI(dd,node->index));
01026 if (node == skip) continue;
01027 (void) st_lookup(info->table, node, &infoN);
01028 if (item->localRef != infoN->functionRef) {
01029
01030 continue;
01031 }
01032 savings++;
01033 if (!cuddIsConstant(cuddT(node))) {
01034 item = (LocalQueueItem *) cuddLevelQueueEnqueue(queue,cuddT(node),
01035 cuddI(dd,cuddT(node)->index));
01036 if (item == NULL) return(0);
01037 item->localRef++;
01038 }
01039 if (!Cudd_IsConstant(cuddE(node))) {
01040 item = (LocalQueueItem *) cuddLevelQueueEnqueue(queue,Cudd_Regular(cuddE(node)),
01041 cuddI(dd,Cudd_Regular(cuddE(node))->index));
01042 if (item == NULL) return(0);
01043 item->localRef++;
01044 }
01045 }
01046
01047 #ifdef DD_DEBUG
01048
01049 assert(queue->size == 0);
01050 #endif
01051 return(savings);
01052
01053 }
01054
01055
01068 static int
01069 updateRefs(
01070 DdManager * dd,
01071 DdNode * f,
01072 DdNode * skip,
01073 ApproxInfo * info,
01074 DdLevelQueue * queue)
01075 {
01076 NodeData *infoN;
01077 LocalQueueItem *item;
01078 DdNode *node;
01079 int savings = 0;
01080
01081 node = Cudd_Regular(f);
01082
01083
01084
01085 item = (LocalQueueItem *) cuddLevelQueueEnqueue(queue,node,cuddI(dd,node->index));
01086 if (item == NULL)
01087 return(0);
01088 (void) st_lookup(info->table, node, &infoN);
01089 infoN->functionRef = 0;
01090
01091 if (skip != NULL) {
01092
01093
01094 skip = Cudd_Regular(skip);
01095 (void) st_lookup(info->table, skip, &infoN);
01096 infoN->functionRef++;
01097 }
01098
01099
01100 while (queue->first != NULL) {
01101 item = (LocalQueueItem *) queue->first;
01102 node = item->node;
01103 cuddLevelQueueDequeue(queue,cuddI(dd,node->index));
01104 (void) st_lookup(info->table, node, &infoN);
01105 if (infoN->functionRef != 0) {
01106
01107 continue;
01108 }
01109 savings++;
01110 if (!cuddIsConstant(cuddT(node))) {
01111 item = (LocalQueueItem *) cuddLevelQueueEnqueue(queue,cuddT(node),
01112 cuddI(dd,cuddT(node)->index));
01113 if (item == NULL) return(0);
01114 (void) st_lookup(info->table, cuddT(node), &infoN);
01115 infoN->functionRef--;
01116 }
01117 if (!Cudd_IsConstant(cuddE(node))) {
01118 item = (LocalQueueItem *) cuddLevelQueueEnqueue(queue,Cudd_Regular(cuddE(node)),
01119 cuddI(dd,Cudd_Regular(cuddE(node))->index));
01120 if (item == NULL) return(0);
01121 (void) st_lookup(info->table, Cudd_Regular(cuddE(node)), &infoN);
01122 infoN->functionRef--;
01123 }
01124 }
01125
01126 #ifdef DD_DEBUG
01127
01128 assert(queue->size == 0);
01129 #endif
01130 return(savings);
01131
01132 }
01133
01134
01147 static int
01148 UAmarkNodes(
01149 DdManager * dd ,
01150 DdNode * f ,
01151 ApproxInfo * info ,
01152 int threshold ,
01153 int safe ,
01154 double quality )
01155 {
01156 DdLevelQueue *queue;
01157 DdLevelQueue *localQueue;
01158 NodeData *infoN;
01159 GlobalQueueItem *item;
01160 DdNode *node;
01161 double numOnset;
01162 double impactP, impactN;
01163 int savings;
01164
01165 #if 0
01166 (void) printf("initial size = %d initial minterms = %g\n",
01167 info->size, info->minterms);
01168 #endif
01169 queue = cuddLevelQueueInit(dd->size,sizeof(GlobalQueueItem),info->size);
01170 if (queue == NULL) {
01171 return(0);
01172 }
01173 localQueue = cuddLevelQueueInit(dd->size,sizeof(LocalQueueItem),
01174 dd->initSlots);
01175 if (localQueue == NULL) {
01176 cuddLevelQueueQuit(queue);
01177 return(0);
01178 }
01179 node = Cudd_Regular(f);
01180 item = (GlobalQueueItem *) cuddLevelQueueEnqueue(queue,node,cuddI(dd,node->index));
01181 if (item == NULL) {
01182 cuddLevelQueueQuit(queue);
01183 cuddLevelQueueQuit(localQueue);
01184 return(0);
01185 }
01186 if (Cudd_IsComplement(f)) {
01187 item->impactP = 0.0;
01188 item->impactN = 1.0;
01189 } else {
01190 item->impactP = 1.0;
01191 item->impactN = 0.0;
01192 }
01193 while (queue->first != NULL) {
01194
01195 if (info->size <= threshold)
01196 break;
01197 item = (GlobalQueueItem *) queue->first;
01198 node = item->node;
01199 node = Cudd_Regular(node);
01200 (void) st_lookup(info->table, node, &infoN);
01201 if (safe && infoN->parity == 3) {
01202 cuddLevelQueueDequeue(queue,cuddI(dd,node->index));
01203 continue;
01204 }
01205 impactP = item->impactP;
01206 impactN = item->impactN;
01207 numOnset = infoN->mintermsP * impactP + infoN->mintermsN * impactN;
01208 savings = computeSavings(dd,node,NULL,info,localQueue);
01209 if (savings == 0) {
01210 cuddLevelQueueQuit(queue);
01211 cuddLevelQueueQuit(localQueue);
01212 return(0);
01213 }
01214 cuddLevelQueueDequeue(queue,cuddI(dd,node->index));
01215 #if 0
01216 (void) printf("node %p: impact = %g/%g numOnset = %g savings %d\n",
01217 node, impactP, impactN, numOnset, savings);
01218 #endif
01219 if ((1 - numOnset / info->minterms) >
01220 quality * (1 - (double) savings / info->size)) {
01221 infoN->replace = TRUE;
01222 info->size -= savings;
01223 info->minterms -=numOnset;
01224 #if 0
01225 (void) printf("replace: new size = %d new minterms = %g\n",
01226 info->size, info->minterms);
01227 #endif
01228 savings -= updateRefs(dd,node,NULL,info,localQueue);
01229 assert(savings == 0);
01230 continue;
01231 }
01232 if (!cuddIsConstant(cuddT(node))) {
01233 item = (GlobalQueueItem *) cuddLevelQueueEnqueue(queue,cuddT(node),
01234 cuddI(dd,cuddT(node)->index));
01235 item->impactP += impactP/2.0;
01236 item->impactN += impactN/2.0;
01237 }
01238 if (!Cudd_IsConstant(cuddE(node))) {
01239 item = (GlobalQueueItem *) cuddLevelQueueEnqueue(queue,Cudd_Regular(cuddE(node)),
01240 cuddI(dd,Cudd_Regular(cuddE(node))->index));
01241 if (Cudd_IsComplement(cuddE(node))) {
01242 item->impactP += impactN/2.0;
01243 item->impactN += impactP/2.0;
01244 } else {
01245 item->impactP += impactP/2.0;
01246 item->impactN += impactN/2.0;
01247 }
01248 }
01249 }
01250
01251 cuddLevelQueueQuit(queue);
01252 cuddLevelQueueQuit(localQueue);
01253 return(1);
01254
01255 }
01256
01257
01271 static DdNode *
01272 UAbuildSubset(
01273 DdManager * dd ,
01274 DdNode * node ,
01275 ApproxInfo * info )
01276 {
01277
01278 DdNode *Nt, *Ne, *N, *t, *e, *r;
01279 NodeData *infoN;
01280
01281 if (Cudd_IsConstant(node))
01282 return(node);
01283
01284 N = Cudd_Regular(node);
01285
01286 if (st_lookup(info->table, N, &infoN)) {
01287 if (infoN->replace == TRUE) {
01288 return(info->zero);
01289 }
01290 if (N == node ) {
01291 if (infoN->resultP != NULL) {
01292 return(infoN->resultP);
01293 }
01294 } else {
01295 if (infoN->resultN != NULL) {
01296 return(infoN->resultN);
01297 }
01298 }
01299 } else {
01300 (void) fprintf(dd->err,
01301 "Something is wrong, ought to be in info table\n");
01302 dd->errorCode = CUDD_INTERNAL_ERROR;
01303 return(NULL);
01304 }
01305
01306 Nt = Cudd_NotCond(cuddT(N), Cudd_IsComplement(node));
01307 Ne = Cudd_NotCond(cuddE(N), Cudd_IsComplement(node));
01308
01309 t = UAbuildSubset(dd, Nt, info);
01310 if (t == NULL) {
01311 return(NULL);
01312 }
01313 cuddRef(t);
01314
01315 e = UAbuildSubset(dd, Ne, info);
01316 if (e == NULL) {
01317 Cudd_RecursiveDeref(dd,t);
01318 return(NULL);
01319 }
01320 cuddRef(e);
01321
01322 if (Cudd_IsComplement(t)) {
01323 t = Cudd_Not(t);
01324 e = Cudd_Not(e);
01325 r = (t == e) ? t : cuddUniqueInter(dd, N->index, t, e);
01326 if (r == NULL) {
01327 Cudd_RecursiveDeref(dd, e);
01328 Cudd_RecursiveDeref(dd, t);
01329 return(NULL);
01330 }
01331 r = Cudd_Not(r);
01332 } else {
01333 r = (t == e) ? t : cuddUniqueInter(dd, N->index, t, e);
01334 if (r == NULL) {
01335 Cudd_RecursiveDeref(dd, e);
01336 Cudd_RecursiveDeref(dd, t);
01337 return(NULL);
01338 }
01339 }
01340 cuddDeref(t);
01341 cuddDeref(e);
01342
01343 if (N == node) {
01344 infoN->resultP = r;
01345 } else {
01346 infoN->resultN = r;
01347 }
01348
01349 return(r);
01350
01351 }
01352
01353
01366 static int
01367 RAmarkNodes(
01368 DdManager * dd ,
01369 DdNode * f ,
01370 ApproxInfo * info ,
01371 int threshold ,
01372 double quality )
01373 {
01374 DdLevelQueue *queue;
01375 DdLevelQueue *localQueue;
01376 NodeData *infoN, *infoT, *infoE;
01377 GlobalQueueItem *item;
01378 DdNode *node, *T, *E;
01379 DdNode *shared;
01380 double numOnset;
01381 double impact, impactP, impactN;
01382 double minterms;
01383 int savings;
01384 int replace;
01385
01386 #if 0
01387 (void) fprintf(dd->out,"initial size = %d initial minterms = %g\n",
01388 info->size, info->minterms);
01389 #endif
01390 queue = cuddLevelQueueInit(dd->size,sizeof(GlobalQueueItem),info->size);
01391 if (queue == NULL) {
01392 return(0);
01393 }
01394 localQueue = cuddLevelQueueInit(dd->size,sizeof(LocalQueueItem),
01395 dd->initSlots);
01396 if (localQueue == NULL) {
01397 cuddLevelQueueQuit(queue);
01398 return(0);
01399 }
01400
01401 node = Cudd_Regular(f);
01402 item = (GlobalQueueItem *)
01403 cuddLevelQueueEnqueue(queue,node,cuddI(dd,node->index));
01404 if (item == NULL) {
01405 cuddLevelQueueQuit(queue);
01406 cuddLevelQueueQuit(localQueue);
01407 return(0);
01408 }
01409 if (Cudd_IsComplement(f)) {
01410 item->impactP = 0.0;
01411 item->impactN = 1.0;
01412 } else {
01413 item->impactP = 1.0;
01414 item->impactN = 0.0;
01415 }
01416
01417
01418
01419
01420 while (queue->first != NULL) {
01421
01422 if (info->size <= threshold)
01423 break;
01424 item = (GlobalQueueItem *) queue->first;
01425 node = item->node;
01426 #ifdef DD_DEBUG
01427 assert(item->impactP >= 0 && item->impactP <= 1.0);
01428 assert(item->impactN >= 0 && item->impactN <= 1.0);
01429 assert(!Cudd_IsComplement(node));
01430 assert(!Cudd_IsConstant(node));
01431 #endif
01432 if (!st_lookup(info->table, node, &infoN)) {
01433 cuddLevelQueueQuit(queue);
01434 cuddLevelQueueQuit(localQueue);
01435 return(0);
01436 }
01437 #ifdef DD_DEBUG
01438 assert(infoN->parity >= 1 && infoN->parity <= 3);
01439 #endif
01440 if (infoN->parity == 3) {
01441
01442
01443
01444
01445 cuddLevelQueueDequeue(queue,cuddI(dd,node->index));
01446 continue;
01447 }
01448 T = cuddT(node);
01449 E = cuddE(node);
01450 shared = NULL;
01451 impactP = item->impactP;
01452 impactN = item->impactN;
01453 if (Cudd_bddLeq(dd,T,E)) {
01454
01455 #ifdef DD_DEBUG
01456 assert(!Cudd_IsComplement(E));
01457 #endif
01458 (void) st_lookup(info->table, T, &infoT);
01459 (void) st_lookup(info->table, E, &infoE);
01460 if (infoN->parity == 1) {
01461 impact = impactP;
01462 minterms = infoE->mintermsP/2.0 - infoT->mintermsP/2.0;
01463 if (infoE->functionRef == 1 && !Cudd_IsConstant(E)) {
01464 savings = 1 + computeSavings(dd,E,NULL,info,localQueue);
01465 if (savings == 1) {
01466 cuddLevelQueueQuit(queue);
01467 cuddLevelQueueQuit(localQueue);
01468 return(0);
01469 }
01470 } else {
01471 savings = 1;
01472 }
01473 replace = REPLACE_E;
01474 } else {
01475 #ifdef DD_DEBUG
01476 assert(infoN->parity == 2);
01477 #endif
01478 impact = impactN;
01479 minterms = infoT->mintermsN/2.0 - infoE->mintermsN/2.0;
01480 if (infoT->functionRef == 1 && !Cudd_IsConstant(T)) {
01481 savings = 1 + computeSavings(dd,T,NULL,info,localQueue);
01482 if (savings == 1) {
01483 cuddLevelQueueQuit(queue);
01484 cuddLevelQueueQuit(localQueue);
01485 return(0);
01486 }
01487 } else {
01488 savings = 1;
01489 }
01490 replace = REPLACE_T;
01491 }
01492 numOnset = impact * minterms;
01493 } else if (Cudd_bddLeq(dd,E,T)) {
01494
01495 DdNode *Ereg = Cudd_Regular(E);
01496 (void) st_lookup(info->table, T, &infoT);
01497 (void) st_lookup(info->table, Ereg, &infoE);
01498 if (infoN->parity == 1) {
01499 impact = impactP;
01500 minterms = infoT->mintermsP/2.0 -
01501 ((E == Ereg) ? infoE->mintermsP : infoE->mintermsN)/2.0;
01502 if (infoT->functionRef == 1 && !Cudd_IsConstant(T)) {
01503 savings = 1 + computeSavings(dd,T,NULL,info,localQueue);
01504 if (savings == 1) {
01505 cuddLevelQueueQuit(queue);
01506 cuddLevelQueueQuit(localQueue);
01507 return(0);
01508 }
01509 } else {
01510 savings = 1;
01511 }
01512 replace = REPLACE_T;
01513 } else {
01514 #ifdef DD_DEBUG
01515 assert(infoN->parity == 2);
01516 #endif
01517 impact = impactN;
01518 minterms = ((E == Ereg) ? infoE->mintermsN :
01519 infoE->mintermsP)/2.0 - infoT->mintermsN/2.0;
01520 if (infoE->functionRef == 1 && !Cudd_IsConstant(E)) {
01521 savings = 1 + computeSavings(dd,E,NULL,info,localQueue);
01522 if (savings == 1) {
01523 cuddLevelQueueQuit(queue);
01524 cuddLevelQueueQuit(localQueue);
01525 return(0);
01526 }
01527 } else {
01528 savings = 1;
01529 }
01530 replace = REPLACE_E;
01531 }
01532 numOnset = impact * minterms;
01533 } else {
01534 DdNode *Ereg = Cudd_Regular(E);
01535 DdNode *TT = cuddT(T);
01536 DdNode *ET = Cudd_NotCond(cuddT(Ereg), Cudd_IsComplement(E));
01537 if (T->index == Ereg->index && TT == ET) {
01538 shared = TT;
01539 replace = REPLACE_TT;
01540 } else {
01541 DdNode *TE = cuddE(T);
01542 DdNode *EE = Cudd_NotCond(cuddE(Ereg), Cudd_IsComplement(E));
01543 if (T->index == Ereg->index && TE == EE) {
01544 shared = TE;
01545 replace = REPLACE_TE;
01546 } else {
01547 replace = REPLACE_N;
01548 }
01549 }
01550 numOnset = infoN->mintermsP * impactP + infoN->mintermsN * impactN;
01551 savings = computeSavings(dd,node,shared,info,localQueue);
01552 if (shared != NULL) {
01553 NodeData *infoS;
01554 (void) st_lookup(info->table, Cudd_Regular(shared), &infoS);
01555 if (Cudd_IsComplement(shared)) {
01556 numOnset -= (infoS->mintermsN * impactP +
01557 infoS->mintermsP * impactN)/2.0;
01558 } else {
01559 numOnset -= (infoS->mintermsP * impactP +
01560 infoS->mintermsN * impactN)/2.0;
01561 }
01562 savings--;
01563 }
01564 }
01565
01566 cuddLevelQueueDequeue(queue,cuddI(dd,node->index));
01567 #if 0
01568 if (replace == REPLACE_T || replace == REPLACE_E)
01569 (void) printf("node %p: impact = %g numOnset = %g savings %d\n",
01570 node, impact, numOnset, savings);
01571 else
01572 (void) printf("node %p: impact = %g/%g numOnset = %g savings %d\n",
01573 node, impactP, impactN, numOnset, savings);
01574 #endif
01575 if ((1 - numOnset / info->minterms) >
01576 quality * (1 - (double) savings / info->size)) {
01577 infoN->replace = (char) replace;
01578 info->size -= savings;
01579 info->minterms -=numOnset;
01580 #if 0
01581 (void) printf("remap(%d): new size = %d new minterms = %g\n",
01582 replace, info->size, info->minterms);
01583 #endif
01584 if (replace == REPLACE_N) {
01585 savings -= updateRefs(dd,node,NULL,info,localQueue);
01586 } else if (replace == REPLACE_T) {
01587 savings -= updateRefs(dd,node,E,info,localQueue);
01588 } else if (replace == REPLACE_E) {
01589 savings -= updateRefs(dd,node,T,info,localQueue);
01590 } else {
01591 #ifdef DD_DEBUG
01592 assert(replace == REPLACE_TT || replace == REPLACE_TE);
01593 #endif
01594 savings -= updateRefs(dd,node,shared,info,localQueue) - 1;
01595 }
01596 assert(savings == 0);
01597 } else {
01598 replace = NOTHING;
01599 }
01600 if (replace == REPLACE_N) continue;
01601 if ((replace == REPLACE_E || replace == NOTHING) &&
01602 !cuddIsConstant(cuddT(node))) {
01603 item = (GlobalQueueItem *) cuddLevelQueueEnqueue(queue,cuddT(node),
01604 cuddI(dd,cuddT(node)->index));
01605 if (replace == REPLACE_E) {
01606 item->impactP += impactP;
01607 item->impactN += impactN;
01608 } else {
01609 item->impactP += impactP/2.0;
01610 item->impactN += impactN/2.0;
01611 }
01612 }
01613 if ((replace == REPLACE_T || replace == NOTHING) &&
01614 !Cudd_IsConstant(cuddE(node))) {
01615 item = (GlobalQueueItem *) cuddLevelQueueEnqueue(queue,Cudd_Regular(cuddE(node)),
01616 cuddI(dd,Cudd_Regular(cuddE(node))->index));
01617 if (Cudd_IsComplement(cuddE(node))) {
01618 if (replace == REPLACE_T) {
01619 item->impactP += impactN;
01620 item->impactN += impactP;
01621 } else {
01622 item->impactP += impactN/2.0;
01623 item->impactN += impactP/2.0;
01624 }
01625 } else {
01626 if (replace == REPLACE_T) {
01627 item->impactP += impactP;
01628 item->impactN += impactN;
01629 } else {
01630 item->impactP += impactP/2.0;
01631 item->impactN += impactN/2.0;
01632 }
01633 }
01634 }
01635 if ((replace == REPLACE_TT || replace == REPLACE_TE) &&
01636 !Cudd_IsConstant(shared)) {
01637 item = (GlobalQueueItem *) cuddLevelQueueEnqueue(queue,Cudd_Regular(shared),
01638 cuddI(dd,Cudd_Regular(shared)->index));
01639 if (Cudd_IsComplement(shared)) {
01640 item->impactP += impactN;
01641 item->impactN += impactP;
01642 } else {
01643 item->impactP += impactP;
01644 item->impactN += impactN;
01645 }
01646 }
01647 }
01648
01649 cuddLevelQueueQuit(queue);
01650 cuddLevelQueueQuit(localQueue);
01651 return(1);
01652
01653 }
01654
01655
01668 static int
01669 BAmarkNodes(
01670 DdManager *dd ,
01671 DdNode *f ,
01672 ApproxInfo *info ,
01673 int threshold ,
01674 double quality1 ,
01675 double quality0 )
01676 {
01677 DdLevelQueue *queue;
01678 DdLevelQueue *localQueue;
01679 NodeData *infoN, *infoT, *infoE;
01680 GlobalQueueItem *item;
01681 DdNode *node, *T, *E;
01682 DdNode *shared;
01683 double numOnset;
01684 double impact, impactP, impactN;
01685 double minterms;
01686 double quality;
01687 int savings;
01688 int replace;
01689
01690 #if 0
01691 (void) fprintf(dd->out,"initial size = %d initial minterms = %g\n",
01692 info->size, info->minterms);
01693 #endif
01694 queue = cuddLevelQueueInit(dd->size,sizeof(GlobalQueueItem),info->size);
01695 if (queue == NULL) {
01696 return(0);
01697 }
01698 localQueue = cuddLevelQueueInit(dd->size,sizeof(LocalQueueItem),
01699 dd->initSlots);
01700 if (localQueue == NULL) {
01701 cuddLevelQueueQuit(queue);
01702 return(0);
01703 }
01704
01705 node = Cudd_Regular(f);
01706 item = (GlobalQueueItem *)
01707 cuddLevelQueueEnqueue(queue,node,cuddI(dd,node->index));
01708 if (item == NULL) {
01709 cuddLevelQueueQuit(queue);
01710 cuddLevelQueueQuit(localQueue);
01711 return(0);
01712 }
01713 if (Cudd_IsComplement(f)) {
01714 item->impactP = 0.0;
01715 item->impactN = 1.0;
01716 } else {
01717 item->impactP = 1.0;
01718 item->impactN = 0.0;
01719 }
01720
01721
01722
01723
01724 while (queue->first != NULL) {
01725
01726 if (info->size <= threshold)
01727 break;
01728 item = (GlobalQueueItem *) queue->first;
01729 node = item->node;
01730 #ifdef DD_DEBUG
01731 assert(item->impactP >= 0 && item->impactP <= 1.0);
01732 assert(item->impactN >= 0 && item->impactN <= 1.0);
01733 assert(!Cudd_IsComplement(node));
01734 assert(!Cudd_IsConstant(node));
01735 #endif
01736 if (!st_lookup(info->table, node, &infoN)) {
01737 cuddLevelQueueQuit(queue);
01738 cuddLevelQueueQuit(localQueue);
01739 return(0);
01740 }
01741 quality = infoN->care ? quality1 : quality0;
01742 #ifdef DD_DEBUG
01743 assert(infoN->parity >= 1 && infoN->parity <= 3);
01744 #endif
01745 if (infoN->parity == 3) {
01746
01747
01748
01749
01750 cuddLevelQueueDequeue(queue,cuddI(dd,node->index));
01751 continue;
01752 }
01753 T = cuddT(node);
01754 E = cuddE(node);
01755 shared = NULL;
01756 impactP = item->impactP;
01757 impactN = item->impactN;
01758 if (Cudd_bddLeq(dd,T,E)) {
01759
01760 #ifdef DD_DEBUG
01761 assert(!Cudd_IsComplement(E));
01762 #endif
01763 (void) st_lookup(info->table, T, &infoT);
01764 (void) st_lookup(info->table, E, &infoE);
01765 if (infoN->parity == 1) {
01766 impact = impactP;
01767 minterms = infoE->mintermsP/2.0 - infoT->mintermsP/2.0;
01768 if (infoE->functionRef == 1 && !Cudd_IsConstant(E)) {
01769 savings = 1 + computeSavings(dd,E,NULL,info,localQueue);
01770 if (savings == 1) {
01771 cuddLevelQueueQuit(queue);
01772 cuddLevelQueueQuit(localQueue);
01773 return(0);
01774 }
01775 } else {
01776 savings = 1;
01777 }
01778 replace = REPLACE_E;
01779 } else {
01780 #ifdef DD_DEBUG
01781 assert(infoN->parity == 2);
01782 #endif
01783 impact = impactN;
01784 minterms = infoT->mintermsN/2.0 - infoE->mintermsN/2.0;
01785 if (infoT->functionRef == 1 && !Cudd_IsConstant(T)) {
01786 savings = 1 + computeSavings(dd,T,NULL,info,localQueue);
01787 if (savings == 1) {
01788 cuddLevelQueueQuit(queue);
01789 cuddLevelQueueQuit(localQueue);
01790 return(0);
01791 }
01792 } else {
01793 savings = 1;
01794 }
01795 replace = REPLACE_T;
01796 }
01797 numOnset = impact * minterms;
01798 } else if (Cudd_bddLeq(dd,E,T)) {
01799
01800 DdNode *Ereg = Cudd_Regular(E);
01801 (void) st_lookup(info->table, T, &infoT);
01802 (void) st_lookup(info->table, Ereg, &infoE);
01803 if (infoN->parity == 1) {
01804 impact = impactP;
01805 minterms = infoT->mintermsP/2.0 -
01806 ((E == Ereg) ? infoE->mintermsP : infoE->mintermsN)/2.0;
01807 if (infoT->functionRef == 1 && !Cudd_IsConstant(T)) {
01808 savings = 1 + computeSavings(dd,T,NULL,info,localQueue);
01809 if (savings == 1) {
01810 cuddLevelQueueQuit(queue);
01811 cuddLevelQueueQuit(localQueue);
01812 return(0);
01813 }
01814 } else {
01815 savings = 1;
01816 }
01817 replace = REPLACE_T;
01818 } else {
01819 #ifdef DD_DEBUG
01820 assert(infoN->parity == 2);
01821 #endif
01822 impact = impactN;
01823 minterms = ((E == Ereg) ? infoE->mintermsN :
01824 infoE->mintermsP)/2.0 - infoT->mintermsN/2.0;
01825 if (infoE->functionRef == 1 && !Cudd_IsConstant(E)) {
01826 savings = 1 + computeSavings(dd,E,NULL,info,localQueue);
01827 if (savings == 1) {
01828 cuddLevelQueueQuit(queue);
01829 cuddLevelQueueQuit(localQueue);
01830 return(0);
01831 }
01832 } else {
01833 savings = 1;
01834 }
01835 replace = REPLACE_E;
01836 }
01837 numOnset = impact * minterms;
01838 } else {
01839 DdNode *Ereg = Cudd_Regular(E);
01840 DdNode *TT = cuddT(T);
01841 DdNode *ET = Cudd_NotCond(cuddT(Ereg), Cudd_IsComplement(E));
01842 if (T->index == Ereg->index && TT == ET) {
01843 shared = TT;
01844 replace = REPLACE_TT;
01845 } else {
01846 DdNode *TE = cuddE(T);
01847 DdNode *EE = Cudd_NotCond(cuddE(Ereg), Cudd_IsComplement(E));
01848 if (T->index == Ereg->index && TE == EE) {
01849 shared = TE;
01850 replace = REPLACE_TE;
01851 } else {
01852 replace = REPLACE_N;
01853 }
01854 }
01855 numOnset = infoN->mintermsP * impactP + infoN->mintermsN * impactN;
01856 savings = computeSavings(dd,node,shared,info,localQueue);
01857 if (shared != NULL) {
01858 NodeData *infoS;
01859 (void) st_lookup(info->table, Cudd_Regular(shared), &infoS);
01860 if (Cudd_IsComplement(shared)) {
01861 numOnset -= (infoS->mintermsN * impactP +
01862 infoS->mintermsP * impactN)/2.0;
01863 } else {
01864 numOnset -= (infoS->mintermsP * impactP +
01865 infoS->mintermsN * impactN)/2.0;
01866 }
01867 savings--;
01868 }
01869 }
01870
01871 cuddLevelQueueDequeue(queue,cuddI(dd,node->index));
01872 #if 0
01873 if (replace == REPLACE_T || replace == REPLACE_E)
01874 (void) printf("node %p: impact = %g numOnset = %g savings %d\n",
01875 node, impact, numOnset, savings);
01876 else
01877 (void) printf("node %p: impact = %g/%g numOnset = %g savings %d\n",
01878 node, impactP, impactN, numOnset, savings);
01879 #endif
01880 if ((1 - numOnset / info->minterms) >
01881 quality * (1 - (double) savings / info->size)) {
01882 infoN->replace = (char) replace;
01883 info->size -= savings;
01884 info->minterms -=numOnset;
01885 #if 0
01886 (void) printf("remap(%d): new size = %d new minterms = %g\n",
01887 replace, info->size, info->minterms);
01888 #endif
01889 if (replace == REPLACE_N) {
01890 savings -= updateRefs(dd,node,NULL,info,localQueue);
01891 } else if (replace == REPLACE_T) {
01892 savings -= updateRefs(dd,node,E,info,localQueue);
01893 } else if (replace == REPLACE_E) {
01894 savings -= updateRefs(dd,node,T,info,localQueue);
01895 } else {
01896 #ifdef DD_DEBUG
01897 assert(replace == REPLACE_TT || replace == REPLACE_TE);
01898 #endif
01899 savings -= updateRefs(dd,node,shared,info,localQueue) - 1;
01900 }
01901 assert(savings == 0);
01902 } else {
01903 replace = NOTHING;
01904 }
01905 if (replace == REPLACE_N) continue;
01906 if ((replace == REPLACE_E || replace == NOTHING) &&
01907 !cuddIsConstant(cuddT(node))) {
01908 item = (GlobalQueueItem *) cuddLevelQueueEnqueue(queue,cuddT(node),
01909 cuddI(dd,cuddT(node)->index));
01910 if (replace == REPLACE_E) {
01911 item->impactP += impactP;
01912 item->impactN += impactN;
01913 } else {
01914 item->impactP += impactP/2.0;
01915 item->impactN += impactN/2.0;
01916 }
01917 }
01918 if ((replace == REPLACE_T || replace == NOTHING) &&
01919 !Cudd_IsConstant(cuddE(node))) {
01920 item = (GlobalQueueItem *) cuddLevelQueueEnqueue(queue,Cudd_Regular(cuddE(node)),
01921 cuddI(dd,Cudd_Regular(cuddE(node))->index));
01922 if (Cudd_IsComplement(cuddE(node))) {
01923 if (replace == REPLACE_T) {
01924 item->impactP += impactN;
01925 item->impactN += impactP;
01926 } else {
01927 item->impactP += impactN/2.0;
01928 item->impactN += impactP/2.0;
01929 }
01930 } else {
01931 if (replace == REPLACE_T) {
01932 item->impactP += impactP;
01933 item->impactN += impactN;
01934 } else {
01935 item->impactP += impactP/2.0;
01936 item->impactN += impactN/2.0;
01937 }
01938 }
01939 }
01940 if ((replace == REPLACE_TT || replace == REPLACE_TE) &&
01941 !Cudd_IsConstant(shared)) {
01942 item = (GlobalQueueItem *) cuddLevelQueueEnqueue(queue,Cudd_Regular(shared),
01943 cuddI(dd,Cudd_Regular(shared)->index));
01944 if (Cudd_IsComplement(shared)) {
01945 if (replace == REPLACE_T) {
01946 item->impactP += impactN;
01947 item->impactN += impactP;
01948 } else {
01949 item->impactP += impactN/2.0;
01950 item->impactN += impactP/2.0;
01951 }
01952 } else {
01953 if (replace == REPLACE_T) {
01954 item->impactP += impactP;
01955 item->impactN += impactN;
01956 } else {
01957 item->impactP += impactP/2.0;
01958 item->impactN += impactN/2.0;
01959 }
01960 }
01961 }
01962 }
01963
01964 cuddLevelQueueQuit(queue);
01965 cuddLevelQueueQuit(localQueue);
01966 return(1);
01967
01968 }
01969
01970
01985 static DdNode *
01986 RAbuildSubset(
01987 DdManager * dd ,
01988 DdNode * node ,
01989 ApproxInfo * info )
01990 {
01991 DdNode *Nt, *Ne, *N, *t, *e, *r;
01992 NodeData *infoN;
01993
01994 if (Cudd_IsConstant(node))
01995 return(node);
01996
01997 N = Cudd_Regular(node);
01998
01999 Nt = Cudd_NotCond(cuddT(N), Cudd_IsComplement(node));
02000 Ne = Cudd_NotCond(cuddE(N), Cudd_IsComplement(node));
02001
02002 if (st_lookup(info->table, N, &infoN)) {
02003 if (N == node ) {
02004 if (infoN->resultP != NULL) {
02005 return(infoN->resultP);
02006 }
02007 } else {
02008 if (infoN->resultN != NULL) {
02009 return(infoN->resultN);
02010 }
02011 }
02012 if (infoN->replace == REPLACE_T) {
02013 r = RAbuildSubset(dd, Ne, info);
02014 return(r);
02015 } else if (infoN->replace == REPLACE_E) {
02016 r = RAbuildSubset(dd, Nt, info);
02017 return(r);
02018 } else if (infoN->replace == REPLACE_N) {
02019 return(info->zero);
02020 } else if (infoN->replace == REPLACE_TT) {
02021 DdNode *Ntt = Cudd_NotCond(cuddT(cuddT(N)),
02022 Cudd_IsComplement(node));
02023 int index = cuddT(N)->index;
02024 e = info->zero;
02025 t = RAbuildSubset(dd, Ntt, info);
02026 if (t == NULL) {
02027 return(NULL);
02028 }
02029 cuddRef(t);
02030 if (Cudd_IsComplement(t)) {
02031 t = Cudd_Not(t);
02032 e = Cudd_Not(e);
02033 r = (t == e) ? t : cuddUniqueInter(dd, index, t, e);
02034 if (r == NULL) {
02035 Cudd_RecursiveDeref(dd, t);
02036 return(NULL);
02037 }
02038 r = Cudd_Not(r);
02039 } else {
02040 r = (t == e) ? t : cuddUniqueInter(dd, index, t, e);
02041 if (r == NULL) {
02042 Cudd_RecursiveDeref(dd, t);
02043 return(NULL);
02044 }
02045 }
02046 cuddDeref(t);
02047 return(r);
02048 } else if (infoN->replace == REPLACE_TE) {
02049 DdNode *Nte = Cudd_NotCond(cuddE(cuddT(N)),
02050 Cudd_IsComplement(node));
02051 int index = cuddT(N)->index;
02052 t = info->one;
02053 e = RAbuildSubset(dd, Nte, info);
02054 if (e == NULL) {
02055 return(NULL);
02056 }
02057 cuddRef(e);
02058 e = Cudd_Not(e);
02059 r = (t == e) ? t : cuddUniqueInter(dd, index, t, e);
02060 if (r == NULL) {
02061 Cudd_RecursiveDeref(dd, e);
02062 return(NULL);
02063 }
02064 r =Cudd_Not(r);
02065 cuddDeref(e);
02066 return(r);
02067 }
02068 } else {
02069 (void) fprintf(dd->err,
02070 "Something is wrong, ought to be in info table\n");
02071 dd->errorCode = CUDD_INTERNAL_ERROR;
02072 return(NULL);
02073 }
02074
02075 t = RAbuildSubset(dd, Nt, info);
02076 if (t == NULL) {
02077 return(NULL);
02078 }
02079 cuddRef(t);
02080
02081 e = RAbuildSubset(dd, Ne, info);
02082 if (e == NULL) {
02083 Cudd_RecursiveDeref(dd,t);
02084 return(NULL);
02085 }
02086 cuddRef(e);
02087
02088 if (Cudd_IsComplement(t)) {
02089 t = Cudd_Not(t);
02090 e = Cudd_Not(e);
02091 r = (t == e) ? t : cuddUniqueInter(dd, N->index, t, e);
02092 if (r == NULL) {
02093 Cudd_RecursiveDeref(dd, e);
02094 Cudd_RecursiveDeref(dd, t);
02095 return(NULL);
02096 }
02097 r = Cudd_Not(r);
02098 } else {
02099 r = (t == e) ? t : cuddUniqueInter(dd, N->index, t, e);
02100 if (r == NULL) {
02101 Cudd_RecursiveDeref(dd, e);
02102 Cudd_RecursiveDeref(dd, t);
02103 return(NULL);
02104 }
02105 }
02106 cuddDeref(t);
02107 cuddDeref(e);
02108
02109 if (N == node) {
02110 infoN->resultP = r;
02111 } else {
02112 infoN->resultN = r;
02113 }
02114
02115 return(r);
02116
02117 }
02118
02119
02133 static int
02134 BAapplyBias(
02135 DdManager *dd,
02136 DdNode *f,
02137 DdNode *b,
02138 ApproxInfo *info,
02139 DdHashTable *cache)
02140 {
02141 DdNode *one, *zero, *res;
02142 DdNode *Ft, *Fe, *B, *Bt, *Be;
02143 unsigned int topf, topb;
02144 NodeData *infoF;
02145 int careT, careE;
02146
02147 one = DD_ONE(dd);
02148 zero = Cudd_Not(one);
02149
02150 if (!st_lookup(info->table, f, &infoF))
02151 return(CARE_ERROR);
02152 if (f == one) return(TOTAL_CARE);
02153 if (b == zero) return(infoF->care);
02154 if (infoF->care == TOTAL_CARE) return(TOTAL_CARE);
02155
02156 if ((f->ref != 1 || Cudd_Regular(b)->ref != 1) &&
02157 (res = cuddHashTableLookup2(cache,f,b)) != NULL) {
02158 if (res->ref == 0) {
02159 cache->manager->dead++;
02160 cache->manager->constants.dead++;
02161 }
02162 return(infoF->care);
02163 }
02164
02165 topf = dd->perm[f->index];
02166 B = Cudd_Regular(b);
02167 topb = cuddI(dd,B->index);
02168 if (topf <= topb) {
02169 Ft = cuddT(f); Fe = cuddE(f);
02170 } else {
02171 Ft = Fe = f;
02172 }
02173 if (topb <= topf) {
02174
02175 Bt = cuddT(B); Be = cuddE(B);
02176 if (Cudd_IsComplement(b)) {
02177 Bt = Cudd_Not(Bt);
02178 Be = Cudd_Not(Be);
02179 }
02180 } else {
02181 Bt = Be = b;
02182 }
02183
02184 careT = BAapplyBias(dd, Ft, Bt, info, cache);
02185 if (careT == CARE_ERROR)
02186 return(CARE_ERROR);
02187 careE = BAapplyBias(dd, Cudd_Regular(Fe), Be, info, cache);
02188 if (careE == CARE_ERROR)
02189 return(CARE_ERROR);
02190 if (careT == TOTAL_CARE && careE == TOTAL_CARE) {
02191 infoF->care = TOTAL_CARE;
02192 } else {
02193 infoF->care = CARE;
02194 }
02195
02196 if (f->ref != 1 || Cudd_Regular(b)->ref != 1) {
02197 ptrint fanout = (ptrint) f->ref * Cudd_Regular(b)->ref;
02198 cuddSatDec(fanout);
02199 if (!cuddHashTableInsert2(cache,f,b,one,fanout)) {
02200 return(CARE_ERROR);
02201 }
02202 }
02203 return(infoF->care);
02204
02205 }