VIS

src/synth/synthOpt.c

Go to the documentation of this file.
00001 
00017 #include "synthInt.h"
00018 
00019 static char rcsid[] UNUSED = "$Id: synthOpt.c,v 1.53 2005/05/11 20:18:25 hhhan Exp $";
00020 
00021 /*---------------------------------------------------------------------------*/
00022 /* Constant declarations                                                     */
00023 /*---------------------------------------------------------------------------*/
00024 
00025 
00026 /*---------------------------------------------------------------------------*/
00027 /* Type declarations                                                         */
00028 /*---------------------------------------------------------------------------*/
00029 
00030 
00031 /*---------------------------------------------------------------------------*/
00032 /* Structure declarations                                                    */
00033 /*---------------------------------------------------------------------------*/
00034 
00035 
00036 /*---------------------------------------------------------------------------*/
00037 /* Variable declarations                                                     */
00038 /*---------------------------------------------------------------------------*/
00039 
00040 int     OutputOrdering = 1; /*
00041                             ** 0 : just use VIS's order
00042                             ** 1 : smaller first in terms of support
00043                             ** 2 : smaller first in terms of bdd size
00044                             */
00045 
00046 static  int     UseFuncDivisor = 1;
00047 static  float   SuppFactor = 10.0;
00048 static  float   ProbFactor = 10.0;
00049 static  int     *SupportCount;
00050 static  float   *Probability;
00051 static  char    **outputNames;
00052 
00053 extern  int     TryNodeSharing;
00054 extern  int     noMemoryFlag;
00055 extern  int     VerifyTreeMode;
00056 
00059 /*---------------------------------------------------------------------------*/
00060 /* Static function prototypes                                                */
00061 /*---------------------------------------------------------------------------*/
00062 
00063 static void GetOutputOrder(bdd_manager *dd, bdd_node **ofuncs, int no, int *order, int verbosity);
00064 static int IsSubsetOfSupportForOneWord(unsigned int mask1, unsigned int mask2);
00065 static int IsNullSupport(int size, unsigned int *mask);
00066 static void PrintSupportMask(int n, int size, unsigned int *mask);
00067 static int GetNumberOfSupport(int n, int size, unsigned int *mask);
00068 static int factorizeNetwork(Ntk_Network_t *net, bdd_manager *dd, bdd_node **ofuncs, MlTree **tree, int no, int *out_order, st_table *table, char **combOutNames, int divisor, MlTree *(* factoring_func)(bdd_manager *, st_table *, bdd_node *, int, int *, MlTree *, int, MlTree *, int), int verbosity);
00069 
00073 /*---------------------------------------------------------------------------*/
00074 /* Definition of exported functions                                          */
00075 /*---------------------------------------------------------------------------*/
00076 
00077 
00078 /*---------------------------------------------------------------------------*/
00079 /* Definition of internal functions                                          */
00080 /*---------------------------------------------------------------------------*/
00081 
00093 void
00094 SynthMultiLevelOptimize(Ntk_Network_t *network,
00095                         bdd_node **combOutBdds,
00096                         bdd_node **combUpperBdds,
00097                         char **combOutNames,
00098                         int *initStates,
00099                         Synth_InfoData_t *synthInfo,
00100                         int verbosity)
00101 {
00102   bdd_manager           *dd = (bdd_manager *)Ntk_NetworkReadMddManager(network);
00103   bdd_node              *top;
00104   bdd_node              **ofuncs;
00105   int                   i, no;
00106   int                   factoring, divisor;
00107   char                  *filename;
00108   char                  *filehead;
00109   MlTree                **tree;
00110   bdd_node              *zdd_I;
00111   st_table              *table;
00112   int                   nml, tml;
00113   int                   *out_order;
00114   FILE                  *feqn;
00115   MlTree                *(* factoring_func)(bdd_manager *, st_table *,
00116                                             bdd_node *, int, int *, MlTree *,
00117                                             int, MlTree *, int);
00118   int                   autoDyn, autoDynZ;
00119   bdd_reorder_type_t    method, methodZ;
00120   int                   error;
00121 
00122   factoring = synthInfo->factoring;
00123   divisor = synthInfo->divisor;
00124   filehead = synthInfo->filehead;
00125   TryNodeSharing = synthInfo->trySharing;
00126   SynthSetInternalNodePrefix(synthInfo->prefix);
00127 
00128   /* Save reordering status and set reordering mode specific to
00129    * synthesis.
00130    */
00131   autoDyn = bdd_reordering_status(dd, &method);
00132   autoDynZ = bdd_reordering_zdd_status(dd, &methodZ);
00133 
00134   switch (synthInfo->reordering) {
00135   case 0 :
00136     bdd_dynamic_reordering_disable(dd);
00137     bdd_dynamic_reordering_zdd_disable(dd);
00138     break;
00139   case 1 :
00140     bdd_dynamic_reordering(dd, method, BDD_REORDER_VERBOSITY_DEFAULT);
00141     bdd_dynamic_reordering_zdd_disable(dd);
00142     break;
00143   case 2 :
00144     bdd_dynamic_reordering_disable(dd);
00145     bdd_dynamic_reordering_zdd(dd, methodZ, BDD_REORDER_VERBOSITY_DEFAULT);
00146     break;
00147   case 3 :
00148     bdd_dynamic_reordering(dd, method, BDD_REORDER_VERBOSITY_DEFAULT);
00149     bdd_dynamic_reordering_zdd(dd, methodZ, BDD_REORDER_VERBOSITY_DEFAULT);
00150     break;
00151   default :
00152     bdd_dynamic_reordering_disable(dd);
00153     bdd_dynamic_reordering_zdd_disable(dd);
00154     break;
00155   }
00156 
00157   if (factoring == 0)
00158     factoring_func = SynthSimpleFactorTree;
00159   else
00160     factoring_func = SynthGenericFactorTree;
00161 
00162   /* outputNames is a static global variable for this file. */
00163   outputNames = combOutNames;
00164 
00165   /* Initialize the node-tree table and other factoring-related variables.
00166    * The table contains pairs of a ZDD node and the corresponding multi-level
00167    * tree.
00168    */
00169   table = st_init_table(st_ptrcmp, st_ptrhash);
00170   SynthInitMlTable();
00171 
00172   /* Create ZDD variables for the positive and negative literals. */
00173   bdd_zdd_vars_from_bdd_vars(dd, 2);
00174 
00175   /* Since we currently support only blif files, the number of
00176    * functions to synthesize should not include the initial
00177    * inputs of latches in case of sequential ckts.
00178    */
00179   no = Ntk_NetworkReadNumCombOutputs(network) -
00180     Ntk_NetworkReadNumLatches(network);
00181 
00182   /* Compute two-level covers for all the functions to be synthesized. */
00183   ofuncs = ALLOC(bdd_node *, no);
00184   for (i = 0; i < no; i++) {
00185     if (verbosity) {
00186       (void)fprintf(vis_stdout, "** synth info: Synthesizing output [%d(%s)]\n",
00187                     i, combOutNames[i]);
00188     }
00189     bdd_ref(top = bdd_zdd_isop(dd, combOutBdds[i], combUpperBdds[i],
00190                                &zdd_I));
00191     bdd_ref(zdd_I);
00192     bdd_recursive_deref(dd, top);
00193     ofuncs[i] = zdd_I;
00194   }
00195 
00196   if (VerifyTreeMode == 2)
00197     SynthDumpBlif(network, dd, no, ofuncs, combOutNames, initStates, filehead);
00198 
00199   /* Initialize array of factoring trees and determine the order in
00200    * which the functions will be processed. Then proceed to factor.
00201    */
00202   tree = ALLOC(MlTree *, no);
00203   (void)memset((void *)tree, 0, no * sizeof(MlTree *));
00204   out_order = ALLOC(int, no);
00205   GetOutputOrder(dd, ofuncs, no, out_order, verbosity);
00206   error = factorizeNetwork(network, dd, ofuncs, tree, no, out_order,
00207                    table, combOutNames, divisor, factoring_func, verbosity);
00208   FREE(out_order);
00209 
00210   if (error) {
00211     (void)fprintf(vis_stderr,
00212                   "** synth error: synthesize_network has finished abnormally");
00213     if (noMemoryFlag)
00214       (void)fprintf(vis_stderr, " due to lack of memory\n");
00215     else
00216       (void)fprintf(vis_stderr, " for some reason\n");
00217     goto cleanup;
00218   }
00219 
00220   /* Count total number of literals in multi-level network. */
00221   tml = 0;
00222   for (i = 0; i < no; i++) {
00223     if (tree[i]) {
00224       nml = SynthCountMlLiteral(dd, tree[i], 1);
00225       tml += nml;
00226     }
00227   }
00228   (void)fprintf(vis_stdout,
00229                 "** synth info: Total number of literals = %d\n", tml);
00230 
00231   /* Write network in eqn and blif formats. */
00232   SynthSetupNodeNameTable(network);
00233   filename = ALLOC(char, strlen(filehead) + 9);
00234   if (synthInfo->eqn) {
00235     sprintf(filename, "%s.eqn", filehead);
00236     feqn = Cmd_FileOpen(filename, "w", NIL(char *), 0);
00237     if (feqn) {
00238       fprintf(feqn, "** synth info: Total number of literals = %d\n", tml);
00239       SynthWriteEqnHeader(feqn, network, dd);
00240       for (i = 0; i < no; i++) {
00241         if (tree[i])
00242           SynthWriteEqn(feqn, network, dd, tree[i], ofuncs, combOutNames[i], 1);
00243       }
00244       fclose(feqn);
00245     } else {
00246       (void)fprintf(vis_stdout,
00247                     "** synth error: Error in opening file [%s]\n", filename);
00248     }
00249   }
00250   sprintf(filename, "%s.ml.blif", filehead);
00251   SynthWriteBlifFile(network, dd, tree, filename, no, ofuncs, initStates,
00252                      0, verbosity);
00253   FREE(filename);
00254   SynthFreeNodeNameTable();
00255 
00256  cleanup:
00257   /* Clean up. */
00258   for (i = 0; i < no; i++) {
00259     if (!tree[i])
00260       continue;
00261     bdd_recursive_deref_zdd(dd, tree[i]->node);
00262     /* frees some trees not in node-tree table */
00263     if (tree[i]->ref)
00264       SynthFreeMlTree(tree[i], 0);
00265   }
00266 
00267   SynthClearMlTable(dd, table);
00268   st_free_table(table);
00269   FREE(tree);
00270 
00271   for (i = 0; i < no; i++) {
00272     if (!ofuncs[i])
00273       continue;
00274     bdd_recursive_deref_zdd(dd, ofuncs[i]);
00275   }
00276 
00277   FREE(ofuncs);
00278 
00279   /* Restore reordering status. */
00280   if (autoDyn)
00281     bdd_dynamic_reordering(dd, method, BDD_REORDER_VERBOSITY_DEFAULT);
00282   else
00283     bdd_dynamic_reordering_disable(dd);
00284   if (autoDynZ)
00285     bdd_dynamic_reordering_zdd(dd, methodZ, BDD_REORDER_VERBOSITY_DEFAULT);
00286   else
00287     bdd_dynamic_reordering_zdd_disable(dd);
00288 }
00289 
00290 
00304 void
00305 SynthSetUseFuncDivisor(int mode)
00306 {
00307   UseFuncDivisor = mode;
00308 }
00309 
00310 
00322 void
00323 SynthSetOutputOrdering(int mode)
00324 {
00325   OutputOrdering = mode;
00326 }
00327 
00328 
00340 void
00341 SynthSetCostFactors(float supp,
00342                     float prob)
00343 {
00344   SuppFactor = supp;
00345   ProbFactor = prob;
00346 }
00347 
00348 
00360 void
00361 SynthSetSupportCount(int *count)
00362 {
00363   SupportCount = count;
00364 }
00365 
00366 
00378 void
00379 SynthSetProbability(float *prob)
00380 {
00381   Probability = prob;
00382 }
00383 
00384 
00396 int
00397 SynthFindDivisorForLowPower(int *count,
00398                             int nvars,
00399                             int min_count,
00400                             int min_pos)
00401 {
00402   int   i, v;
00403   float cost, best;
00404 
00405   if ((!SupportCount) || (!Probability))
00406     return(-1);
00407 
00408   v = min_pos;
00409   if (SuppFactor == 0.0 && ProbFactor == 0.0)
00410     best = (float)SupportCount[min_pos] * Probability[min_pos];
00411   else {
00412     best = (float)SupportCount[min_pos] * SuppFactor +
00413       Probability[min_pos] * ProbFactor;
00414   }
00415 
00416   for (i = min_pos + 1; i < nvars; i++) {
00417     if (count[i] == min_count) {
00418       if (SuppFactor == 0.0 && ProbFactor == 0.0)
00419         cost = (float)SupportCount[i] * Probability[i];
00420       else {
00421         cost = (float)SupportCount[i] * SuppFactor +
00422           Probability[i] * ProbFactor;
00423       }
00424       if (cost > best) {
00425         best = cost;
00426         v = i;
00427       }
00428     }
00429   }
00430 
00431   return(v);
00432 }
00433 
00434 
00446 char *
00447 SynthGetIthOutputName(int i)
00448 {
00449   return outputNames[i];
00450 }
00451 
00452 
00472 int
00473 SynthIsSubsetOfSupport(int size,
00474                        unsigned int *mask1,
00475                        unsigned int *mask2)
00476 {
00477   int   i, tmp, flag = 0;
00478 
00479   if (!mask2)
00480     return(1);
00481 
00482   if (IsNullSupport(size, mask1) && IsNullSupport(size, mask2))
00483     return(0);
00484   else if (IsNullSupport(size, mask1))
00485     return(0);
00486   else if (IsNullSupport(size, mask2))
00487     return(1);
00488 
00489   for (i = 0; i < size; i++) {
00490     tmp = IsSubsetOfSupportForOneWord(mask1[i], mask2[i]);
00491     if (tmp == 0)
00492       return(0);
00493     flag |= tmp;
00494   }
00495 
00496   return(flag);
00497 }
00498 
00499 
00500 /*---------------------------------------------------------------------------*/
00501 /* Definition of static functions                                            */
00502 /*---------------------------------------------------------------------------*/
00503 
00524 static void
00525 GetOutputOrder(bdd_manager *dd,
00526                bdd_node **ofuncs,
00527                int no,
00528                int *order,
00529                int verbosity)
00530 {
00531   int           i, j, k, flag;
00532   int           *support, *bddsize;
00533   int           size;
00534   unsigned int  **mask;
00535   int           word, sizeZ;
00536   int           pos, bit, bit_mask;
00537   int           insert_flag, s1, s2;
00538 
00539   if (no == 1) {
00540     order[0] = 0;
00541     return;
00542   }
00543 
00544   if (OutputOrdering == 0) {
00545     for (i = 0; i < no; i++)
00546       order[i] = i;
00547     return;
00548   }
00549 
00550   bddsize = ALLOC(int, no);
00551   if (OutputOrdering == 2) {
00552     for (i = 0; i < no; i++) {
00553       if (!ofuncs[i]) {
00554         order[i] = i;
00555         bddsize[i] = 0;
00556         continue;
00557       }
00558 
00559       bddsize[i] = bdd_node_size(ofuncs[i]);
00560 
00561       /* Insert i-th output at the right place in the order. */
00562       for (j = 0; j < i; j++) {
00563         if (bddsize[i] < bddsize[order[j]]) {
00564           for (k = i; k > j; k--)
00565             order[k] = order[k - 1];
00566           order[j] = i;
00567           break;
00568         }
00569       }
00570 
00571       if (j == i)
00572         order[i] = i;
00573     }
00574 
00575     if (verbosity) {
00576       fprintf(vis_stdout, "output order :");
00577       for (i = 0; i < no; i++)
00578         fprintf(vis_stdout, " %d", order[i]);
00579       fprintf(vis_stdout, "\n");
00580       if (verbosity > 1) {
00581         for (i = 0; i < no; i++)
00582           fprintf(vis_stdout, "%d - %d", i, bddsize[i]);
00583       }
00584     }
00585 
00586     FREE(bddsize);
00587     return;
00588   }
00589 
00590   /* Here OutputOrdering should be 1. */
00591   mask = ALLOC(unsigned int *, no);
00592   sizeZ = bdd_num_zdd_vars(dd);
00593   support = ALLOC(int, sizeZ);
00594   word = sizeof(int) * 8;
00595   size = sizeZ / word + 1;
00596 
00597   for (i = 0; i < no; i++) {
00598     if (!ofuncs[i]) {
00599       mask[i] = (unsigned int *)NULL;
00600       order[i] = i;
00601       bddsize[i] = 0;
00602       continue;
00603     }
00604 
00605     mask[i] = ALLOC(unsigned int, size);
00606     (void)memset((void *)mask[i], 0, size * sizeof(int));
00607     (void)memset((void *)support, 0, sizeof(int) * sizeZ);
00608     SynthZddSupportStep(bdd_regular(ofuncs[i]), support);
00609     SynthZddClearFlag(bdd_regular(ofuncs[i]));
00610     /* Pack the support array into a bit vector. */
00611     for (j = 0; j < sizeZ; j++) {
00612       if (support[j]) {
00613         pos = j / word;
00614         bit = j % word;
00615         bit_mask = 01 << bit;
00616         mask[i][pos] |= bit_mask;
00617       }
00618     }
00619     bddsize[i] = bdd_node_size(ofuncs[i]);
00620 
00621     for (j = 0; j < i; j++) {
00622       insert_flag = 0;
00623       flag = SynthIsSubsetOfSupport(size, mask[i], mask[order[j]]);
00624       if (flag == 1)
00625         insert_flag = 1;
00626       else if (flag == 2) {
00627         s1 = GetNumberOfSupport(sizeZ, size, mask[i]);
00628         s2 = GetNumberOfSupport(sizeZ, size, mask[order[j]]);
00629         if (s1 < s2 || (s1 == s2 && bddsize[i] < bddsize[order[j]]))
00630           insert_flag = 1;
00631       }
00632       if (insert_flag) {
00633         for (k = i; k > j; k--)
00634           order[k] = order[k - 1];
00635         order[j] = i;
00636         break;
00637       }
00638     }
00639 
00640     if (j == i)
00641       order[i] = i;
00642   }
00643   FREE(support);
00644   FREE(bddsize);
00645 
00646   if (verbosity) {
00647     fprintf(vis_stdout, "output order :");
00648     for (i = 0; i < no; i++)
00649       fprintf(vis_stdout, " %d", order[i]);
00650     fprintf(vis_stdout, "\n");
00651     if (verbosity > 1) {
00652       for (i = 0; i < no; i++) {
00653         if (mask[i])
00654           PrintSupportMask(sizeZ, size, mask[i]);
00655       }
00656     }
00657   }
00658 
00659   for (i = 0; i < no; i++) {
00660     if (mask[i])
00661       FREE(mask[i]);
00662   }
00663   FREE(mask);
00664 }
00665 
00666 
00681 static int
00682 IsSubsetOfSupportForOneWord(unsigned int mask1,
00683                             unsigned int mask2)
00684 {
00685   unsigned int  tmp;
00686 
00687   if (mask1 == mask2)
00688     return(2);
00689 
00690   tmp = mask1 | mask2;
00691   if (tmp != mask2)
00692     return(0);
00693   return(1);
00694 }
00695 
00696 
00708 static int
00709 IsNullSupport(int size,
00710               unsigned int *mask)
00711 {
00712   int   i;
00713 
00714   for (i = 0; i < size; i++) {
00715     if (mask[i] != 0)
00716       return(0);
00717   }
00718   return(1);
00719 }
00720 
00721 
00736 static void
00737 PrintSupportMask(int n,
00738                  int size,
00739                  unsigned int *mask)
00740 {
00741   int   i, j, pos, last;
00742   char  *support;
00743   char  *mark;
00744   int   bit;
00745 
00746   support = ALLOC(char,n);
00747   mark = ALLOC(char,n);
00748 
00749   pos = 0;
00750   for (i = 0; i < size; i++) {
00751     if (i == (size - 1))
00752       last = n % 32;
00753     else
00754       last = 32;
00755     bit = 01;
00756     for (j = 0; j < last; j++) {
00757       sprintf(&mark[pos], "%d", pos % 10);
00758       if (mask[i] & bit)
00759         support[pos] = '1';
00760       else
00761         support[pos] = '0';
00762       pos++;
00763       bit = bit << 1;
00764     }
00765   }
00766   mark[pos] = support[pos] = '\0';
00767 
00768   fprintf(vis_stdout, "%s\n", mark);
00769   fprintf(vis_stdout, "%s\n", support);
00770 
00771   FREE(support);
00772   FREE(mark);
00773 }
00774 
00775 
00787 static int
00788 GetNumberOfSupport(int n,
00789                    int size,
00790                    unsigned int *mask)
00791 {
00792   int   i, j, last;
00793   int   bit;
00794   int   count;
00795 
00796   count = 0;
00797   for (i = 0; i < size; i++) {
00798     if (i == (size - 1))
00799       last = n % 32;
00800     else
00801       last = 32;
00802     bit = 01;
00803     for (j = 0; j < last; j++) {
00804       if (mask[i] & bit)
00805         count++;
00806       bit = bit << 1;
00807     }
00808   }
00809   return(count);
00810 }
00811 
00812 
00825 static int
00826 factorizeNetwork(Ntk_Network_t *net,
00827                  bdd_manager *dd,
00828                  bdd_node **ofuncs,
00829                  MlTree **tree,
00830                  int no,
00831                  int *out_order,
00832                  st_table *table,
00833                  char **combOutNames,
00834                  int divisor,
00835                  MlTree *(* factoring_func)(bdd_manager *, st_table *,
00836                                             bdd_node *, int, int *, MlTree *,
00837                                             int, MlTree *, int),
00838                  int verbosity)
00839 {
00840   int           i, j, k;
00841   int           ref;
00842   int           nml;
00843   MlTree        *tmp_tree;
00844   int           flag;
00845   int           comp_flag;
00846 
00847   SynthSetZddDivisorFunc(divisor); /* set static variable in synthFactor.c */
00848 
00849   for (k = 0; k < no; k++) {
00850     i = out_order[k];
00851     if (!ofuncs[i]) {
00852       tree[i] = NULL;
00853       continue;
00854     }
00855     if (verbosity)
00856       SynthPrintZddCoverWithName(net, dd, ofuncs[i]);
00857 
00858     tree[i] = (MlTree *)NULL;
00859     ref = 0;
00860     if (ofuncs[i] == bdd_read_one(dd) || ofuncs[i] == bdd_read_zero(dd)) {
00861       tree[i] = SynthFindOrCreateMlTree(table, dd, ofuncs[i], 1, 0,
00862                                         &ref, verbosity);
00863       if (!tree[i])
00864         return(1);
00865     } else {
00866       tree[i] = SynthLookupMlTable(table, dd, ofuncs[i], 1, verbosity);
00867       if (tree[i]) {
00868         if (MlTree_IsComplement(tree[i]) || tree[i]->top)
00869           ref = 1;
00870         else
00871           SynthUpdateRefOfParent(tree[i]);
00872       }
00873       else if (UseFuncDivisor) {
00874         /* Try to divide by existing functions. The smaller
00875          * functions are factored first to increase the probability
00876          * of success of this step. Both phases of the divisor are
00877          * tried.
00878          */
00879         for (j = k - 1; j >= 0; j--) {
00880           tree[i] = (* factoring_func)(dd, table, ofuncs[i], 0, &ref,
00881                                        tree[out_order[j]], 0, NULL, verbosity);
00882           if (tree[i]) {
00883             SynthSetSharedFlag(dd, tree[out_order[j]]);
00884             break;
00885           } else if (noMemoryFlag == 1)
00886             return(1);
00887           else {
00888             tree[i] = (* factoring_func)(dd, table, ofuncs[i], 0,
00889                                  &ref, tree[out_order[j]], 1, NULL, verbosity);
00890             if (tree[i]) {
00891               SynthSetSharedFlag(dd, tree[out_order[j]]);
00892               break;
00893             } else if (noMemoryFlag == 1)
00894               return(1);
00895           }
00896         }
00897       }
00898     }
00899     /* Division by other functions did not work. Find a brand-new
00900      * factorization.
00901      */
00902     if (!tree[i]) {
00903       tree[i] = (* factoring_func)(dd, table, ofuncs[i], 0,
00904                                    &ref, NULL, 0, NULL, verbosity);
00905       if (!tree[i])
00906         return(1);
00907     }
00908     /* Compute the complement ZDD node of ofuncs[i], if not exist.
00909      * This is to increase sharing.
00910      */
00911     tmp_tree = tree[i];
00912     tree[i] = SynthCheckAndMakeComplement(dd, table, tree[i], &comp_flag,
00913                                           verbosity);
00914     if (!tree[i])
00915       return(1);
00916     else if (tree[i] != tmp_tree) {
00917       ref = 1;
00918       if (comp_flag)
00919         tree[i] = MlTree_Not(tree[i]);
00920     }
00921 
00922     /* When the tree already exists, create a new tree and copy all
00923      * contents, and set the field 'ref' to 1. This is for the
00924      * purpose of avoiding duplicate literal counting.
00925      */
00926     if (ref) {
00927       int       comp_flag;
00928 
00929       comp_flag = 0;
00930       if (MlTree_IsComplement(tree[i])) {
00931         tree[i] = MlTree_Not(tree[i]);
00932         comp_flag = 1;
00933       }
00934       tmp_tree = ALLOC(MlTree, sizeof(MlTree));
00935       memcpy((void *)tmp_tree, (void *)tree[i], sizeof(MlTree));
00936       tree[i] = tmp_tree;
00937       tree[i]->ref = 1;
00938       tree[i]->comp = comp_flag;
00939     }
00940     tree[i]->top = 1;
00941     bdd_ref(tree[i]->node);
00942 
00943     nml = SynthCountMlLiteral(dd, tree[i], 1);
00944 
00945     if (verbosity) {
00946       SynthPrintMlTreeWithName(net, dd, tree[i], "result : ");
00947       fprintf(vis_stdout, "**** %d (#literal = %d) ****\n", i, nml);
00948       if (verbosity > 1)
00949         SynthWriteEqn(stdout, net, dd, tree[i], ofuncs, combOutNames[i], 1);
00950     }
00951 
00952     if (VerifyTreeMode) {
00953       SynthVerifyTree(dd, tree[i], 1);
00954       SynthVerifyMlTable(dd, table);
00955     }
00956   }
00957 
00958   flag = SynthPostFactoring(dd, table, factoring_func, verbosity);
00959 
00960   if (VerifyTreeMode) {
00961     bdd_node *tmp;
00962 
00963     for (i = 0; i < no; i++) {
00964       if (tree[i]->comp)
00965         tmp = tree[i]->complement;
00966       else
00967         tmp = tree[i]->node;
00968       if (tmp != ofuncs[i]) {
00969         (void) fprintf(vis_stdout,
00970                        "** synth error: Different zdds in [%s].\n",
00971                        combOutNames[i]);
00972       }
00973       SynthVerifyTree(dd, tree[i], 1);
00974     }
00975   }
00976 
00977   return(flag);
00978 }