VIS

src/res/resCompose.c

Go to the documentation of this file.
00001 
00019 #include "resInt.h"
00020 
00021 static char rcsid[] UNUSED = "$Id: resCompose.c,v 1.30 2005/04/18 05:00:14 fabio Exp $";
00022 
00023 /*---------------------------------------------------------------------------*/
00024 /* Constant declarations                                                     */
00025 /*---------------------------------------------------------------------------*/
00026 
00027 /*---------------------------------------------------------------------------*/
00028 /* Structure declarations                                                    */
00029 /*---------------------------------------------------------------------------*/
00030 
00031 /*---------------------------------------------------------------------------*/
00032 /* Type declarations                                                         */
00033 /*---------------------------------------------------------------------------*/
00034 
00035 /*---------------------------------------------------------------------------*/
00036 /* Variable declarations                                                     */
00037 /*---------------------------------------------------------------------------*/
00038 long Res_composeTime;
00039 long Res_shuffleTime;
00040 long Res_smartVarTime;
00041 long Res_orderTime;
00042 
00043 /*---------------------------------------------------------------------------*/
00044 /* Macro declarations                                                        */
00045 /*---------------------------------------------------------------------------*/
00046 
00049 /*---------------------------------------------------------------------------*/
00050 /* Static function prototypes                                                */
00051 /*---------------------------------------------------------------------------*/
00052 
00053 static void UpdateUnassignedNodesWithNewIds(lsList orderList, array_t *newIdArray);
00054 static lsList CreateNodeAndFaninOrderList(array_t *currentLayer);
00055 static lsList ListAppend(Ntk_Node_t *nodePtr, lsList newList, lsList faninList);
00056 static int IdCompare(const void *obj1, const void *obj2);
00057 static int IdListCompare(lsGeneric item1, lsGeneric item2);
00058 static lsList CreateFaninVarSetList(array_t *currentLayer, st_table *faninTable);
00059 static bdd_node * ComposeLayer(bdd_manager *ddManager, bdd_node *residueDd, array_t *currentLayer, bdd_node **functionArray);
00060 static Mvf_Function_t * NodeBuildConstantMvf(Ntk_Node_t * node, mdd_manager *mddMgr);
00061 
00065 /*---------------------------------------------------------------------------*/
00066 /* Definition of exported functions                                          */
00067 /*---------------------------------------------------------------------------*/
00068 
00069 
00070 /*---------------------------------------------------------------------------*/
00071 /* Definition of internal functions                                          */
00072 /*---------------------------------------------------------------------------*/
00073 
00074  
00090 bdd_node *
00091 BuildBDDforNode(Ntk_Network_t *network,
00092                 Ntk_Node_t *nodePtr,
00093                 int fanin)
00094 {
00095   bdd_node *function;
00096   st_table *leaves;
00097   array_t *mvfArray;
00098   Mvf_Function_t *nodeFunction;
00099   Ntk_Node_t *faninNodePtr;
00100   lsGen netGen;
00101   array_t *root;
00102   int j;
00103   mdd_manager *mddMgr;
00104 
00105   /* if it is a constant, build the mvf for it */
00106   if( Ntk_NodeTestIsConstant(nodePtr) == 1) {
00107     mddMgr = (mdd_manager *)Ntk_NetworkReadMddManager(network);
00108     nodeFunction = NodeBuildConstantMvf(nodePtr, mddMgr);
00109   } else if (Ntk_NodeTestIsCombInput(nodePtr)) {
00110     /* the Bdd for a latch input is itself */
00111     mddMgr = (mdd_manager *)Ntk_NetworkReadMddManager(network);
00112     nodeFunction = Mvf_FunctionCreateFromVariable(mddMgr, Ntk_NodeReadMddId(nodePtr));
00113   } else {
00114 
00115     /* Set the root to build the Mvf */
00116     root = array_alloc(Ntk_Node_t *, 1);
00117     array_insert(Ntk_Node_t *, root, 0, nodePtr);
00118     
00119     /* Set the leaves depending on the fanin flag*/
00120     leaves = st_init_table(st_ptrcmp, st_ptrhash);
00121     if (fanin == IMMEDIATE_FANIN) {
00122       Ntk_NodeForEachFanin(nodePtr, j, faninNodePtr) {
00123         st_insert(leaves, (char *)faninNodePtr, (char *)NTM_UNUSED);
00124       }
00125     } else if (fanin == PRIMARY_INPUTS) {
00126       Ntk_NetworkForEachCombInput(network, netGen, nodePtr) {
00127         st_insert(leaves, (char *)nodePtr, (char *)NTM_UNUSED);
00128       }
00129     }
00130         
00131     /* Effectively compute the function (We are not using don't cares)*/
00132     mvfArray = Ntm_NetworkBuildMvfs(network, root, leaves, NIL(mdd_t));
00133     st_free_table(leaves);
00134     array_free(root);
00135     
00136     nodeFunction = array_fetch(Mvf_Function_t *, mvfArray, 0);
00137     /* since we built the MDD for only one root */
00138     array_free(mvfArray);
00139   } /* end of else if not a latch output */
00140   /* 
00141    * The function above returned a Mvf_Function_t, but since we are 
00142    * working with binary nodes (so far), we do not need the Mvf 
00143    * representation, therefore we only keep one single Bdd and deallocate
00144    * all the memory attached to the rest of the Mvf.
00145    */
00146   function = (bdd_node *)bdd_extract_node_as_is(Mvf_FunctionReadComponent(nodeFunction, 1));
00147   if (function != NULL) {
00148     bdd_ref(function);
00149   }
00150   
00151   /* Clean up */
00152   Mvf_FunctionFree(nodeFunction);
00153   return (function);
00154 }
00155 
00156 
00194 bdd_node *
00195 ComposeLayersIntoResidue(Ntk_Network_t *network, 
00196                          array_t *layerArray, 
00197                          bdd_node *residueDd,
00198                          array_t *outputArray)
00199 {
00200   bdd_manager *ddManager;                 /* Dd Manager */
00201   bdd_node *newResidueDd = NIL(bdd_node); /* final composed Dd */
00202   bdd_node *currentDd;                   /* local copy of residue Dd to
00203                                           * perform composition
00204                                           */
00205   lsList outputList, orderList;          /* output and layer+fanin node
00206                                           * list fed to the ordering procedure
00207                                           */
00208   lsHandle nodeHandle;                   /* handle for node list */ 
00209   int *invPermArray;                     /* inverse permutation array
00210                                           * for the Dd manager
00211                                           */
00212   array_t *newIdArray;                   /* array with new Ids to be
00213                                           * assigned to each node
00214                                           */
00215   Ntk_Node_t *nodePtr;                   /* variable to store node pointer */
00216   array_t *currentLayer;                 /* current layer of nodes */
00217   int numNodes;                          /* number of nodes in current layer */
00218   bdd_node **functionArray;              /* array of Adds of the current nodes
00219                                           * in terms of their fanin
00220                                           */
00221                                           
00222   bdd_node *functionBdd;                 /* Bdds of current layer nodes */
00223   char *flagValue;                       /* string that stores flag values */
00224   int verbose;                           /* verbosity level */
00225   int j, k;                              /* iterators */
00226   int layerIndex, nodeIndex;             /* iterators */
00227   long tempTime, thisComposeTime;        /* local time measurement variables */
00228   long thisSmartVarTime, thisOrderTime;  /* local time measurement variables */
00229   long thisShuffleTime;                  /* local time measurement variables */
00230   int unassignedValue;                   /* NTK_UNASSIGNED_MDD_ID value holder */
00231   
00232   /* initialize local time measurement variables */
00233   tempTime = 0;
00234   thisSmartVarTime = 0;
00235   thisOrderTime = 0;
00236   thisShuffleTime = 0;
00237   thisComposeTime = 0;
00238   unassignedValue =  NTK_UNASSIGNED_MDD_ID;
00239   
00240   /* make a local copy of the residue Dd to compose the network into */
00241   bdd_ref(currentDd = residueDd);
00242   
00243   /* read verbosity flag */
00244   verbose = 0;
00245   flagValue = Cmd_FlagReadByName("residue_verbosity");
00246   if (flagValue != NIL(char)) {
00247     verbose = atoi(flagValue);
00248   }
00249   
00250   ddManager = (bdd_manager *)Ntk_NetworkReadMddManager(network);
00251   /* initialize the variable manager that keeps track of what variables
00252    * are in use in residue verification.
00253    */
00254   ResResidueInitializeVariableManager(bdd_num_vars(ddManager));
00255   
00256   /* assume the pos are labeled before they come here each time */
00257   outputList = lsCreate();
00258 
00259   /* outputs do not need to be ordered as the node ids are already
00260    * assigned. Here this list is created just so that the variable
00261    * manager can be updated
00262    */
00263 
00264   arrayForEachItem(Ntk_Node_t *, outputArray, j, nodePtr) {
00265     lsNewEnd(outputList, (lsGeneric)nodePtr, (lsHandle *)&nodeHandle);
00266   }
00267   
00268   newIdArray = array_alloc(int, 0);
00269   tempTime = util_cpu_time();
00270   /* update the variable manager with the output node ids */
00271   invPermArray = ResResidueVarAllocate(ddManager, outputList, newIdArray);
00272   if (invPermArray == NIL(int)) {
00273     error_append("Unable to update variable manager\n");
00274     array_free(newIdArray);
00275     ResResidueFreeVariableManager();
00276     return NULL;
00277   } /* end of error */
00278   thisSmartVarTime += util_cpu_time() - tempTime;
00279   FREE(invPermArray);
00280   array_free(newIdArray);
00281   lsDestroy(outputList, (void (*)(lsGeneric))0);
00282 
00283   /* start the main loop for composition of layers into the residue Add */
00284   for(layerIndex = 0; layerIndex < array_n(layerArray); layerIndex++) {
00285     /* fetch each layer */
00286     currentLayer = ResLayerFetchIthLayer(layerArray, layerIndex);
00287     numNodes = ResLayerNumNodes(currentLayer);
00288     if (verbose >= 3) {
00289       fprintf(vis_stdout, "Layer %d being composed", layerIndex);
00290       fprintf(vis_stdout, " with %d nodes\n", numNodes);
00291     }
00292 
00293     /* create the order of the nodes in the layer and their fanin
00294      * for composition
00295      */
00296     tempTime = util_cpu_time();
00297     orderList = CreateNodeAndFaninOrderList(currentLayer);
00298     thisOrderTime +=  util_cpu_time() - tempTime;
00299 
00300     /* assign new Ids if required and create the corresponding variables
00301      * in the manager
00302      */
00303     newIdArray = array_alloc(int, 0);
00304     tempTime = util_cpu_time();
00305     invPermArray = ResResidueVarAllocate(ddManager, orderList, newIdArray);
00306     if (invPermArray == NIL(int)) {
00307       error_append("Unable to update variable manager\n");
00308       bdd_recursive_deref(ddManager, currentDd);
00309       array_free(newIdArray);
00310       ResResidueFreeVariableManager();
00311       return NULL;
00312     } /* end of error */
00313     thisSmartVarTime += util_cpu_time() - tempTime;
00314 
00315     /* assign Ids to unassigned fanin nodes */
00316     if (array_n(newIdArray)) {
00317       UpdateUnassignedNodesWithNewIds(orderList, newIdArray);
00318     }
00319     array_free(newIdArray);
00320     lsDestroy(orderList, (void (*)(lsGeneric))0);
00321     
00322     /* shuffle the IDs */
00323     tempTime = util_cpu_time();
00324     (void) bdd_shuffle_heap(ddManager, invPermArray);
00325     thisShuffleTime += util_cpu_time() - tempTime;
00326     FREE(invPermArray);
00327     
00328     /* array initialized for dd nodes of the current layer */
00329     tempTime = util_cpu_time();
00330     functionArray = ALLOC(bdd_node *, numNodes);
00331     LayerForEachNode(currentLayer, nodeIndex, nodePtr) {
00332 
00333       /* build the BDD for the function of each node */
00334       functionBdd = BuildBDDforNode(network, nodePtr, IMMEDIATE_FANIN);
00335       if (functionBdd == NULL) { /* error */
00336         error_append("Unable to build function for node ");
00337         error_append(Ntk_NodeReadName(nodePtr));
00338         error_append("\n");
00339         for (k = 0; k < nodeIndex; k++) {
00340           bdd_recursive_deref(ddManager, functionArray[k]);
00341         }
00342         FREE(functionArray);
00343         bdd_recursive_deref(ddManager, currentDd);
00344         ResResidueFreeVariableManager();
00345         return NULL;
00346       } /* end of error */
00347 
00348       /* Convert to ADD */
00349       bdd_ref(functionArray[nodeIndex] = bdd_bdd_to_add(ddManager, functionBdd));
00350       bdd_recursive_deref(ddManager, functionBdd);
00351       if (functionArray[nodeIndex] == NULL) { /* error */
00352         error_append("Unable to build add from bdd for node ");
00353         error_append(Ntk_NodeReadName(nodePtr));
00354         error_append("\n");
00355         for (k = 0; k < nodeIndex; k++) {
00356           bdd_recursive_deref(ddManager, functionArray[k]);
00357         }
00358         FREE(functionArray);
00359         bdd_recursive_deref(ddManager, currentDd);
00360         ResResidueFreeVariableManager();
00361         return NULL;
00362       } /* end of error */
00363     } /* end of iterating over each node in a layer */
00364     /* compose the array into the residue ADD */
00365 
00366     /* Perform the actual composition of current layer */
00367     tempTime = util_cpu_time();
00368     newResidueDd = ComposeLayer(ddManager, currentDd,  currentLayer, functionArray);
00369     thisComposeTime += util_cpu_time() - tempTime;
00370     /* free old residue Dd */
00371     bdd_recursive_deref(ddManager, currentDd);
00372     if (newResidueDd == NULL) { /* error */
00373       error_append("Unable to do composition for layer\n");
00374       for (k = 0; k < numNodes; k++) {
00375         bdd_recursive_deref(ddManager, functionArray[k]);
00376       }
00377       FREE(functionArray);
00378       ResResidueFreeVariableManager();
00379       return NULL;
00380     } /* end of error */
00381     currentDd = newResidueDd;
00382     if (verbose >= 3) {
00383       mdd_t *fnMddT;
00384       int size;
00385       bdd_ref(currentDd);
00386       fnMddT = bdd_construct_bdd_t(ddManager, currentDd);
00387       size = bdd_size(fnMddT);
00388       bdd_free(fnMddT);
00389       fprintf(vis_stdout, "Layer %d has %d nodes\n", layerIndex,
00390               size);
00391     }
00392     
00393     /* free function array */
00394     for (j = 0; j < numNodes; j++) {
00395       bdd_recursive_deref(ddManager, functionArray[j]);
00396     }
00397     FREE(functionArray);
00398     
00399     /*  free ids of nodes just composed */
00400     ResResidueVarDeallocate(currentLayer);
00401     /* reset node Ids of the composed layer */
00402     LayerForEachNode(currentLayer, j, nodePtr) {
00403       if (!Ntk_NodeTestIsCombInput(nodePtr)) {
00404         Ntk_NodeSetMddId(nodePtr, unassignedValue);
00405       }
00406     }
00407   } /* end of iterating over the layers */
00408 
00409   /* free the variable manager */
00410   ResResidueFreeVariableManager();
00411   if (verbose >= 1) {
00412     (void) fprintf(vis_stdout, "ADD Compose Time = %.3f\n",(thisComposeTime)/1000.0);
00413     (void) fprintf(vis_stdout, "Smart variable allocation time = %.3f\n", (thisSmartVarTime)/1000.0);
00414     (void) fprintf(vis_stdout, "Shuffle time = %.3f\n", (thisShuffleTime)/1000.0);
00415     (void) fprintf(vis_stdout, "Order time = %.3f\n", (thisOrderTime)/1000.0);
00416   }
00417   /* update global time variables */
00418   Res_composeTime += thisComposeTime;
00419   Res_smartVarTime += thisSmartVarTime;
00420   Res_shuffleTime += thisShuffleTime;
00421   Res_orderTime += thisOrderTime;
00422 
00423   /* return the composed residue Dd in terms of the primary inputs */
00424   return(newResidueDd);
00425   
00426 } /* End of ComposeLayersIntoResidue */
00427 
00428 /*---------------------------------------------------------------------------*/
00429 /* Definition of static functions                                            */
00430 /*---------------------------------------------------------------------------*/
00431 
00447 static void
00448 UpdateUnassignedNodesWithNewIds(lsList orderList,   
00449                                 array_t *newIdArray) 
00450 {
00451   int i, id;
00452   lsGen listGen;
00453   Ntk_Node_t *nodePtr;
00454   char *flagValue;
00455   int verbose;
00456   
00457   verbose = 0;
00458   flagValue = Cmd_FlagReadByName("residue_verbosity");
00459   if (flagValue != NIL(char)) {
00460     verbose = atoi(flagValue);
00461   }
00462 
00463   /* step through each item in the list to find nodes with unassigned Ids */
00464   i = 0;
00465   lsForEachItem(orderList, listGen, nodePtr) {
00466     if (Ntk_NodeReadMddId(nodePtr) == NTK_UNASSIGNED_MDD_ID) {
00467       id = array_fetch(int, newIdArray, i);
00468       Ntk_NodeSetMddId(nodePtr, id);
00469       i++;
00470       if (verbose >= 4) {
00471         fprintf(vis_stdout, "Id %d being assigned to node %s\n", id,
00472                 Ntk_NodeReadName(nodePtr));
00473       }
00474     }
00475   }
00476   assert(i == array_n(newIdArray));
00477   return;
00478 } /* End of UpdateUnassignedNodesWithNewIds */
00479 
00480 
00511 static lsList
00512 CreateNodeAndFaninOrderList(array_t *currentLayer) 
00513 {
00514   st_table *faninTable;       /* table to store fanin */
00515   lsList layerList;           /* list of nodes in layer */
00516   lsList faninVarSetList;     /* list of support corresponding to layer
00517                                * nodes.
00518                                */
00519   lsList newList;             /* ordered list of nodes and fanins */
00520   lsGen listGen;              /* generator to step through list */
00521   lsGen layerGen, faninGen;   /* generators to step through lists */
00522   int totalFanins;/* variable to store total number of fanins
00523                                * of this layer
00524                                */
00525   int intersect;              /* number of elements in the intersection
00526                                * of support.
00527                                */
00528   int i, j, faninIndex;       /* iterators */
00529   Ntk_Node_t *nodePtr;        /* node pointer variables */
00530   Ntk_Node_t *faninNodePtr;   /* node pointer variables */
00531   Ntk_Node_t *nextNodePtr;    /* node pointer variables */
00532   lsHandle nodeHandle;        /* handle for ls procedure */
00533   lsHandle varSetHandle;      /* handle for ls procedure */
00534   lsHandle newNodeHandle;     /* handle for ls procedure */
00535   lsHandle maxIntersectNodeHandle;   /* handle for ls procedure */
00536   lsHandle maxIntersectVarSetHandle; /* handle for ls procedure */
00537   var_set_t *currVarSet;      /* support of current node */
00538   var_set_t *varSetIntersect; /* intersection of support between 2 nodes */
00539   var_set_t *nextVarSet;      /* support of next node */
00540   array_t *faninArray;        /* array of fanin of a node read from network */
00541   lsList faninList;           /* list of fanins of current layer */
00542   int nodeIndex;              /* iterator */
00543   int verbose;                /* verbosity level */
00544   char *flagValue;            /* string to read flag value */
00545   
00546   verbose = 0;
00547   flagValue = Cmd_FlagReadByName("residue_verbosity");
00548   if (flagValue != NIL(char)) {
00549     verbose = atoi(flagValue);
00550   }
00551 
00552   /* sort current layer by position in the dd manager for least number
00553    * of shuffles
00554    */
00555   LayerSort(currentLayer, IdCompare);
00556   /* create a list to be able to order the list and later manipulation */
00557   layerList = lsCreate();
00558   if (verbose >= 4) {
00559     fprintf(vis_stdout, "Nodes in this layer are: ");
00560   }
00561   LayerForEachNode(currentLayer, i, nodePtr) {
00562     lsNewEnd(layerList, (lsGeneric)nodePtr, (lsHandle *)&nodeHandle);
00563     if (verbose >= 4) {
00564       fprintf(vis_stdout, "%s ",Ntk_NodeReadName(nodePtr));
00565     }
00566   }
00567   if (verbose >= 4) {
00568     fprintf(vis_stdout, "\n");
00569   }
00570 
00571   /* insert all fanins in a table with a unique index. This is to identify
00572    * each fanin as a support variable
00573    */
00574   faninIndex = 0;
00575   faninTable = st_init_table(st_ptrcmp, st_ptrhash);
00576 
00577   LayerForEachNode(currentLayer, nodeIndex, nodePtr) {
00578     Ntk_NodeForEachFanin(nodePtr, j, faninNodePtr) {
00579       /* here constants are omitted, so that they are not assigned an
00580        * Id. The other case to be avoided is when the node in consideration
00581        * is a latch output i.e. a combinational input. Hence it is not
00582        * desirable that the latch data input and latch initial input
00583        * be considered as its fanin.
00584        */
00585       if ((!st_is_member(faninTable, (char *)faninNodePtr)) &&
00586         (!(Ntk_NodeTestIsConstant(faninNodePtr) ||
00587         (Ntk_NodeTestIsLatch(nodePtr) &&
00588          (Ntk_NodeTestIsLatchDataInput(faninNodePtr) ||
00589           Ntk_NodeTestIsLatchInitialInput(faninNodePtr)))))) {
00590         st_insert(faninTable, (char *)faninNodePtr,
00591                   (char *)(long)faninIndex);
00592         faninIndex++;
00593       }
00594     }
00595   }
00596   /* keep a count of the total number of fanins to this layer */
00597   totalFanins = faninIndex;
00598   
00599   /* Create fanin var set for each node */
00600   faninVarSetList = CreateFaninVarSetList(currentLayer, faninTable);
00601   st_free_table(faninTable);
00602 
00603   /* Main sorting part: Like Insertion Sort*/
00604   /* initialize to first item from both layer and fanin lists */
00605   /* starting here, find the list element in the list with max overlap
00606    * with this element. Here each node in the layer is brought up
00607    * neighbor
00608    */
00609   (void) lsFirstItem(faninVarSetList, &currVarSet, &varSetHandle);
00610   (void) lsFirstItem(layerList, &nodePtr, &nodeHandle);
00611   (void) lsRemoveItem(nodeHandle, &nodePtr);
00612   (void) lsRemoveItem(varSetHandle, &currVarSet);
00613   
00614   /* insert first item in new list */
00615   newList = lsCreate();
00616   lsNewEnd(newList, (lsGeneric)nodePtr, (lsHandle *)&newNodeHandle);
00617   
00618   /* create var set for checking overlap of support */
00619   varSetIntersect = var_set_new(totalFanins);
00620   /* done when all the nodes in the layerList have been transferred
00621    * to new list. In each iteration of this list, the node with max
00622    * support overlap with the current node is taken out of the list
00623    * and added to the new list. Its corresponding var set is also
00624    * removed, the current var set is freed and the new var set is
00625    * set to the current var set. The var set list has to be manipulated
00626    * simultaneously to keep the correspondence between the node list
00627    * and its support list.
00628    */
00629   while(lsLength(newList) != ResLayerNumNodes(currentLayer)) { /* while not done */
00630     /* create generators to step through list */
00631     faninGen = lsStart(faninVarSetList);
00632     layerGen = lsStart(layerList);
00633     /* initialize */
00634     intersect = 0;
00635     maxIntersectNodeHandle = NULL;
00636     maxIntersectVarSetHandle = NULL;
00637     while (lsNext(layerGen, &nextNodePtr, &nodeHandle) != LS_NOMORE) {
00638       /* clear result var set */
00639       var_set_clear(varSetIntersect);
00640       /* position var set corresponding to node in layer list */
00641       lsNext(faninGen, &nextVarSet, &varSetHandle);
00642       /* get support overlap */
00643       varSetIntersect = var_set_and(varSetIntersect, currVarSet, nextVarSet);
00644       /* check if current overlap is larger than current max */
00645       if (var_set_n_elts(varSetIntersect) > intersect) {
00646         /* record current position */
00647         intersect = var_set_n_elts(varSetIntersect);
00648         maxIntersectNodeHandle = nodeHandle;
00649         maxIntersectVarSetHandle = varSetHandle;
00650       }
00651     } /* end of iterating over layer list */
00652 
00653     /* destroy Generator */
00654     (void) lsFinish(layerGen);
00655     (void) lsFinish(faninGen);
00656     /* free current var set */
00657     var_set_free(currVarSet);
00658     /* process differently if there was overlap and if there wasn't */
00659     if (maxIntersectNodeHandle == NULL) {
00660       /* support overlap was zero with the rest of the nodes */
00661       /* set current item to first in the lists */
00662       (void) lsFirstItem(faninVarSetList, &nextVarSet, &maxIntersectVarSetHandle);
00663       (void) lsFirstItem(layerList, &nextNodePtr, &maxIntersectNodeHandle);
00664     }
00665     
00666     /* remove max support overlap item from the lists */
00667     (void) lsRemoveItem(maxIntersectNodeHandle, &nextNodePtr);
00668     (void) lsRemoveItem(maxIntersectVarSetHandle, &nextVarSet);
00669     
00670     /* add node to the new list */
00671     lsNewEnd(newList, (lsGeneric)nextNodePtr, (lsHandle *)&newNodeHandle);
00672     /* move current item to the new item */
00673     currVarSet = nextVarSet;
00674 
00675   }
00676   /* Clean up */
00677   var_set_free(varSetIntersect);
00678   var_set_free(currVarSet);
00679   lsDestroy(faninVarSetList, (void (*)(lsGeneric))0);
00680   lsDestroy(layerList, (void (*)(lsGeneric))0);
00681   /* end of sorting part */
00682   
00683   /* insert nodes in new order in the current layer */
00684   i = 0;
00685   lsForEachItem(newList, listGen, nodePtr) {
00686     LayerAddNodeAtIthPosition(currentLayer, i, nodePtr);
00687     i++;
00688   }
00689   assert(lsLength(newList) == array_n(currentLayer));
00690 
00691   /* keep track of running update of the fanins included */
00692   faninTable = st_init_table(st_ptrcmp, st_ptrhash);
00693   /* insert fanin nodes after the last node in the order */
00694   nodeIndex = ResLayerNumNodes(currentLayer)-1;
00695   /* while nodes exist that have to be processed and all fanins haven't
00696    * been processed, repeat
00697    */
00698   while ((nodeIndex >= 0) || (st_count(faninTable) != totalFanins)) {
00699     nodePtr = LayerFetchIthNode(currentLayer, nodeIndex);
00700     faninArray = Ntk_NodeReadFanins(nodePtr);
00701     /* create a fanin list to append to the nodeList */
00702     faninList = lsCreate();
00703     arrayForEachItem(Ntk_Node_t *, faninArray, i, faninNodePtr) {
00704       /* only include those fanins that haven't appeared yet. Also
00705        * exclude the cases where the node is a constant and it is
00706        * a latch data/initial input. You don't want to compose a
00707        * latch output i.e. a combinational input with the latch input.
00708        */
00709       if ((!st_is_member(faninTable, (char *)faninNodePtr)) &&
00710           (!(Ntk_NodeTestIsConstant(faninNodePtr) ||
00711              (Ntk_NodeTestIsLatch(nodePtr) &&
00712               (Ntk_NodeTestIsLatchDataInput(faninNodePtr) ||
00713                Ntk_NodeTestIsLatchInitialInput(faninNodePtr)))))) {
00714         lsNewEnd(faninList, (lsGeneric)faninNodePtr, (lsHandle *)&nodeHandle);
00715         st_insert(faninTable, (char *)faninNodePtr, NIL(char));
00716         /* done when all fanins have been processed */
00717         if (st_count(faninTable) == totalFanins) break;
00718       }
00719     }
00720     /* if list is not empty add fanin behind the node */
00721     if (lsLength(faninList)) { 
00722       /* sort fanins by their level in the ddmanager */
00723       lsSort(faninList, IdListCompare);
00724       /* append the fanin list to the node list */
00725       newList = ListAppend(nodePtr, newList, faninList);
00726     }
00727     lsDestroy(faninList, (void (*)(lsGeneric))0);
00728     nodeIndex--;
00729 
00730   } /* end of while fanin nodes need to be processed and nodes
00731      * are present in layer */
00732   st_free_table(faninTable);
00733   assert(lsLength(newList) == (array_n(currentLayer) + totalFanins));
00734 
00735   return(newList);
00736 } /* End of CreateNodeAndFaninOrderList */
00737 
00738 
00754 static lsList
00755 ListAppend(Ntk_Node_t *nodePtr, 
00756            lsList newList,      
00757            lsList faninList)    
00758 {
00759   lsGen layerGen, newGen, faninGen;
00760   Ntk_Node_t *currNodePtr, *faninNodePtr;
00761   lsHandle nodeHandle, faninNodeHandle;
00762   lsStatus status;
00763   
00764   layerGen = lsEnd(newList);
00765   /* find the spot to insert fanin List */
00766   while(lsPrev(layerGen, &currNodePtr, &nodeHandle) != LS_NOMORE) {
00767     if (nodePtr == currNodePtr) {
00768       /* when spot found, insert fanin list */
00769       newGen = lsGenHandle(nodeHandle, &currNodePtr, LS_AFTER);
00770       lsForEachItem(faninList, faninGen, faninNodePtr) {
00771         status = lsInAfter(newGen, (lsGeneric)faninNodePtr, (lsHandle *)&faninNodeHandle);
00772         if (status != LS_OK) {
00773           error_append("Something wrong with fanin list to be appended\n");
00774           status = lsFinish(layerGen);
00775           status = lsFinish(newGen);
00776           status = lsFinish(faninGen);
00777           return NULL;
00778         }
00779       } /* end of iterating through the fanin list */
00780       /* done as fanin list has been inserted */
00781       lsFinish(newGen);
00782       break;
00783     } /* end of if node found  in the list */
00784   } /* end of stepping through the new list */
00785   
00786   /* Clean up generators */
00787   lsFinish(layerGen);
00788   
00789   /* return modified list */
00790   return (newList);
00791 }/* End of ListAppend */
00792     
00793 
00806 static int
00807 IdCompare(const void *obj1,
00808           const void *obj2)
00809 {
00810   Ntk_Node_t *nodePtr1, *nodePtr2;
00811   int id1 , id2;
00812   int level1, level2;
00813   Ntk_Network_t *network;
00814   bdd_manager *ddManager;
00815   
00816   nodePtr1 = *(Ntk_Node_t **)obj1;
00817   nodePtr2 = *(Ntk_Node_t **)obj2;
00818   id1 = Ntk_NodeReadMddId((Ntk_Node_t *)nodePtr1);
00819   id2 = Ntk_NodeReadMddId((Ntk_Node_t *)nodePtr2);
00820   /* if unassigned Ids return the value before reading the
00821    * position . If equal return -1.
00822    */
00823   if ((id1 == NTK_UNASSIGNED_MDD_ID) || (id2 == NTK_UNASSIGNED_MDD_ID)) {
00824     if (id1 == NTK_UNASSIGNED_MDD_ID) {
00825       return -1;
00826     } else {
00827       return 1;
00828     }
00829   }
00830 
00831   network = Ntk_NodeReadNetwork(nodePtr1);
00832   ddManager = (bdd_manager *)Ntk_NetworkReadMddManager(network);
00833   level1 = bdd_get_level_from_id(ddManager, id1);
00834   level2 = bdd_get_level_from_id(ddManager, id2);
00835   if (level1 > level2) {
00836     return 1;
00837   } else if (level1 == level2) {
00838     return 0;
00839   } else {
00840     return -1;
00841   }
00842 } /* End of IdCompare */
00843 
00855 static int
00856 IdListCompare(lsGeneric item1,
00857               lsGeneric item2)
00858 {
00859   Ntk_Node_t *nodePtr1, *nodePtr2;
00860   int id1 , id2;
00861   int level1, level2;
00862   Ntk_Network_t *network;
00863   bdd_manager *ddManager;
00864 
00865   
00866   nodePtr1 = (Ntk_Node_t *)item1;
00867   nodePtr2 = (Ntk_Node_t *)item2;
00868   id1 = Ntk_NodeReadMddId((Ntk_Node_t *)nodePtr1);
00869   id2 = Ntk_NodeReadMddId((Ntk_Node_t *)nodePtr2);
00870   /* if unassigned Ids return the value before reading the
00871    * position . If equal return -1.
00872    */
00873   if ((id1 == NTK_UNASSIGNED_MDD_ID) || (id2 == NTK_UNASSIGNED_MDD_ID)) {
00874     if (id1 == NTK_UNASSIGNED_MDD_ID) {
00875       return -1;
00876     } else {
00877       return 1;
00878     }
00879   }
00880   network = Ntk_NodeReadNetwork(nodePtr1);
00881   ddManager = (bdd_manager *)Ntk_NetworkReadMddManager(network);
00882   level1 = bdd_get_level_from_id(ddManager, id1);
00883   level2 = bdd_get_level_from_id(ddManager, id2);
00884   if (level1 > level2) {
00885     return 1;
00886   } else if (level1 == level2) {
00887     return 0;
00888   } else {
00889     return -1;
00890   }
00891 } /* End of IdListCompare */
00892 
00893 
00909 static lsList
00910 CreateFaninVarSetList(array_t *currentLayer, 
00911                       st_table *faninTable)  
00912 {
00913   Ntk_Node_t *nodePtr, *faninNodePtr;  /* variables to store nodes */
00914   array_t *faninArray;                 /* array of fanin of nodes */
00915   lsList faninVarSetList;              /* list of var set representing
00916                                         * support of nodes in layer
00917                                         */
00918   var_set_t *currVarSet;               /* var set indicating current
00919                                         * node support
00920                                         */
00921   lsHandle varSetHandle;               /* handle for ls procedure */
00922   int totalFanins;                     /* total number of fanins of this
00923                                         * layer.
00924                                         */
00925   int i, j, faninIndex;                /* iterators */
00926 
00927 
00928   
00929   totalFanins = (int)st_count(faninTable);
00930   faninVarSetList = lsCreate();
00931   /* create var-set of support for each node in this layer */
00932   arrayForEachItem(Ntk_Node_t *, currentLayer, i, nodePtr) {
00933     faninArray = Ntk_NodeReadFanins(nodePtr);
00934     currVarSet = var_set_new(totalFanins);
00935     /* if the above node is a constant, the var set will be empty
00936      * also if it a latch output(comb. input), then the var set will
00937      * be empty.
00938      */
00939     arrayForEachItem(Ntk_Node_t *, faninArray, j, faninNodePtr) {
00940       /* process only those fanins in the table, i.e. no constants
00941        * no latch inputs (combinational outputs) are fanins to this array
00942        */
00943       if (st_lookup_int(faninTable, (char *)faninNodePtr, &faninIndex)) {
00944         /* these aren't supposed to be here */
00945         assert(!((Ntk_NodeTestIsConstant(faninNodePtr) ||
00946                   (Ntk_NodeTestIsLatch(nodePtr) &&
00947                    (Ntk_NodeTestIsLatchDataInput(faninNodePtr) ||
00948                     Ntk_NodeTestIsLatchInitialInput(faninNodePtr))))));
00949         /* set the bit in the support according to the index the fanin
00950          * was assigned
00951          */
00952         var_set_set_elt(currVarSet, faninIndex);
00953       } /* end of if is in the fanin table (has no constants and no
00954          * latch data or initial input.
00955          */
00956     } /* end of if present in fanin table */
00957     /* insert var set in fanin var set list */
00958     lsNewEnd(faninVarSetList, (lsGeneric)currVarSet, (lsHandle *)&varSetHandle);
00959   }
00960   return (faninVarSetList);
00961 } /* End of CreateFaninVarSetList */
00962 
00982 static bdd_node *
00983 ComposeLayer(bdd_manager *ddManager,    
00984              bdd_node *residueDd,       
00985              array_t *currentLayer,   
00986              bdd_node **functionArray)  
00987 {
00988   Ntk_Node_t *nodePtr;          /* variable to store nodes */
00989   char *flagValue;              /* string to read flag value */
00990   ResCompositionMethod method;  /* type of composition to be performed */
00991   int i, j, layerIndex;                     /* iterators */
00992   int nodeId;                   /* current node id */
00993   bdd_node **composeVector;       /* vector required for composition */
00994   bdd_node *new_ = NIL(bdd_node), *andDd,*yDd, *nodeReln, *currentDd; /* temporary Dds */
00995   int maxLayerSize;             /* max size of layers */
00996   int first, last;              /* first and last positions of the array */
00997   
00998   /* read the type of composition to be performed, default is vector
00999    * composition.
01000    */
01001   flagValue = Cmd_FlagReadByName("residue_composition_method");
01002   if (flagValue == NIL(char)) {
01003     method = ResDefaultComposeMethod_c;
01004   } else if (strcmp(flagValue, "vector") == 0) {
01005       method = ResVector_c;
01006   } else if (strcmp(flagValue, "onegate") == 0) {
01007     method =  ResOneGateAtATime_c;
01008   } else if (strcmp(flagValue, "preimage") == 0) {
01009     method = ResPreimageComputation_c;
01010   } else if (strcmp(flagValue, "superG") == 0) {
01011     method = ResSuperG_c;
01012   } else {
01013     fprintf(vis_stderr, 
01014             "** res warning: Unknown composition method, %s, resorting to default.\n", 
01015             flagValue);
01016     method = ResDefaultComposeMethod_c;
01017   } 
01018 
01019   switch(method) {
01020 
01021   case ResVector_c:
01022   case ResSuperG_c:
01023     {
01024       /* read the flag for maximum value of layer size */
01025       flagValue = Cmd_FlagReadByName("residue_layer_size");
01026       if (flagValue == NIL(char)) {
01027         maxLayerSize = ResLayerNumNodes(currentLayer);  
01028       } else {
01029         maxLayerSize = atoi(flagValue);
01030       }
01031       /* if max layer size is within 5 nodes of the length of the
01032        * size of the array, resize it to the size of the array
01033        */
01034       if (maxLayerSize + 5 >= ResLayerNumNodes(currentLayer)) {
01035         maxLayerSize = ResLayerNumNodes(currentLayer);
01036       }
01037 
01038       /* initialize a vector with projection functions */
01039       composeVector = ALLOC(bdd_node *, bdd_num_vars(ddManager));
01040       for(i = 0; (unsigned) i < bdd_num_vars(ddManager); i++) {
01041         bdd_ref(composeVector[i] = bdd_add_ith_var(ddManager, i));
01042         if (composeVector[i] == NIL(bdd_node)) { /* error */
01043           error_append("Something wrong in obtaining projection functions");
01044           for(j = 0; j < i; j++) {
01045             bdd_recursive_deref(ddManager, composeVector[j]);
01046           }
01047           return NIL(bdd_node);
01048         } /* end of if error */
01049       }
01050       /* break this layer up into sub-layers to ease composition
01051        * process. Hence the composition will be performed for several
01052        * subarrays.
01053        */
01054       /* start at the end of the layer */
01055       layerIndex = ResLayerNumNodes(currentLayer);
01056       /* make a local copy */
01057       bdd_ref(currentDd = residueDd);
01058       do {
01059         /* extract sublayers in the size of maxLayerSize starting from the
01060          * end of the layer or a smaller sub-layer (leftover) in the end
01061          */
01062 
01063         /* record last+1 position of the sub-layer in the current layer */
01064         last = layerIndex;
01065 
01066         /* record the position of the beginning of this sub-layer */ 
01067         first = (last < maxLayerSize) ? 0 : (last - maxLayerSize);
01068 
01069         /* iterate through the layer to find the sublayer */
01070         while(layerIndex  > first) { /* extract sub-layer */
01071           layerIndex--;
01072           nodePtr = LayerFetchIthNode(currentLayer, layerIndex);
01073           nodeId = Ntk_NodeReadMddId(nodePtr);
01074           bdd_recursive_deref(ddManager, composeVector[nodeId]);
01075           /* plug in the functions of the nodes in the layer instead of
01076            * the projection functions
01077            */
01078           bdd_ref(composeVector[nodeId] = functionArray[layerIndex]);
01079         }
01080 
01081         /* perform composition */
01082         if (method == ResVector_c) {
01083           bdd_ref(new_ = bdd_add_vector_compose(ddManager, currentDd, composeVector));
01084         } else {
01085           bdd_ref(new_ = bdd_add_nonsim_compose(ddManager, currentDd, composeVector));
01086         }
01087 
01088         /* free old copy and use new to compose in the next sub-layer, if any */
01089         bdd_recursive_deref(ddManager, currentDd);
01090         currentDd = new_;
01091         
01092         if (new_ == NULL) { /* error */
01093           error_append("NULL Dd returned on vector or superG compose\n");
01094           break;
01095         } /* end of error */
01096 
01097         /* undo the compose vector changes for this sub-array to
01098          * prepare it for the next subarray. Replace the function of
01099          * nodes with the projection functions
01100          */
01101         for (i = first; i < last; i++) {
01102           nodePtr = LayerFetchIthNode(currentLayer, i);
01103           nodeId = Ntk_NodeReadMddId(nodePtr);
01104           bdd_recursive_deref(ddManager, composeVector[nodeId]);
01105           bdd_ref(composeVector[nodeId] = bdd_add_ith_var(ddManager, nodeId));
01106         }
01107       } while(layerIndex  > 0);
01108 
01109       /* clean up */
01110       for(i = 0; (unsigned) i < bdd_num_vars(ddManager); i++) {
01111         bdd_recursive_deref(ddManager, composeVector[i]);
01112       }
01113       FREE(composeVector);
01114       break;
01115     } /* end of cases: ResVector_c, ResSuperG_c */
01116   case ResOneGateAtATime_c:
01117     {
01118       /* duplicate  as current Dd gets freed later */
01119       bdd_ref(currentDd = residueDd);
01120       /* compose the nodes in one at a time */
01121       LayerForEachNode(currentLayer, i, nodePtr) {
01122         nodeId = Ntk_NodeReadMddId(nodePtr);
01123         bdd_ref(new_ = bdd_add_compose(ddManager, currentDd, functionArray[i],
01124                                        nodeId));
01125         bdd_recursive_deref(ddManager, currentDd);
01126         if (new_ == NULL) { /* error */
01127           error_append("NULL Dd returned on single gate compose, node: ");
01128           error_append(Ntk_NodeReadName(nodePtr));
01129           error_append("\n");
01130           return NULL;
01131         } /* end of error */
01132         currentDd = new_;
01133       }
01134       break;
01135     } /* end of case Res_OneGateAtATime_c */
01136   case ResPreimageComputation_c:
01137     {
01138       /* duplicate  as current Dd gets freed later */
01139       bdd_ref(currentDd = residueDd);
01140       /* form the y_i \equiv f_i(x) relation, this would be wrong
01141        * if the node appeared again in the circuit. But here it is
01142        * correct due to the one time rule
01143        */
01144       LayerForEachNode(currentLayer, i, nodePtr) {
01145         nodeId = Ntk_NodeReadMddId(nodePtr);
01146         /* find the var for this node */
01147         bdd_ref(yDd = bdd_add_ith_var(ddManager, nodeId));
01148         if (yDd == NULL) { /* error */
01149           error_append("Null Dd returned on preimage compose- y_i stage. ");
01150           error_append("Node: ");
01151           error_append(Ntk_NodeReadName(nodePtr));
01152           bdd_recursive_deref(ddManager, currentDd);
01153           error_append("\n");
01154           return NULL;
01155         } /* end of error */
01156         /* construct the relation */
01157         bdd_ref(nodeReln = bdd_add_apply(ddManager, bdd_add_xnor, yDd, functionArray[i]));
01158 
01159         if (nodeReln == NULL) { /* error */
01160           error_append("Null Dd returned on preimage compose - node reln stage");
01161           error_append("Node: ");
01162           error_append(Ntk_NodeReadName(nodePtr));
01163           bdd_recursive_deref(ddManager, yDd);
01164           bdd_recursive_deref(ddManager, currentDd);
01165           error_append("\n");
01166           return NULL;
01167         } /* end of error */
01168         /* perform the and of the and-abstract */
01169         bdd_ref(andDd = bdd_add_apply(ddManager, bdd_add_times, currentDd, nodeReln));
01170         bdd_recursive_deref(ddManager, currentDd);
01171         bdd_recursive_deref(ddManager, nodeReln);
01172         if (andDd == NULL) { /* error */
01173           error_append("Null Dd returned on preimage compose - and dd stage");
01174           error_append("Node: ");
01175           error_append(Ntk_NodeReadName(nodePtr));
01176           error_append("\n");
01177           bdd_recursive_deref(ddManager, yDd);
01178           return NULL;
01179         } /* end of error */
01180         /* perform the abstract of the and-abstract */
01181         bdd_ref(new_ = bdd_add_exist_abstract(ddManager, andDd, yDd));
01182         bdd_recursive_deref(ddManager, andDd);
01183         bdd_recursive_deref(ddManager, yDd);
01184         if (new_ == NULL) { /* error */
01185           error_append("Null Dd returned on preimage compose - and dd stage");
01186           error_append("Node: ");
01187           error_append((char *)Ntk_NodeReadName(nodePtr));
01188           error_append("\n");
01189           return NULL;
01190         } /* end of error */
01191         currentDd = new_;
01192       }
01193       break;
01194     } /* end of case Res_PreimageComputation_c */
01195   } /* end of switch(method) */
01196   
01197   /* return the new composed Dd */
01198   return new_;
01199 } /* End of ComposeLayersIntoResidue */
01200  
01201 
01214 static Mvf_Function_t *
01215 NodeBuildConstantMvf(
01216   Ntk_Node_t * node,
01217   mdd_manager *mddMgr)
01218 {
01219   int             value        = 0; /* initialized to stop lint complaining */
01220   mdd_t          *oneMdd       = mdd_one(mddMgr);
01221   Var_Variable_t *variable     = Ntk_NodeReadVariable(node);
01222   int             numVarValues = Var_VariableReadNumValues(variable);
01223   Mvf_Function_t *mvf          = Mvf_FunctionAlloc(mddMgr, numVarValues);
01224   int          outputIndex = Ntk_NodeReadOutputIndex(node);
01225   Tbl_Table_t *table       = Ntk_NodeReadTable(node);
01226 
01227   assert(Ntk_NodeTestIsConstant(node));
01228   value = Tbl_TableReadConstValue(table, outputIndex);
01229   assert(value != -1);
01230   
01231   Mvf_FunctionAddMintermsToComponent(mvf, value, oneMdd);
01232   mdd_free(oneMdd);
01233   return mvf;
01234 }