VIS

src/ord/ordMain.c

Go to the documentation of this file.
00001 
00032 #include "ordInt.h"
00033 
00034 static char rcsid[] UNUSED = "$Id: ordMain.c,v 1.17 2005/04/16 06:15:25 fabio Exp $";
00035 
00036 /*---------------------------------------------------------------------------*/
00037 /* Constant declarations                                                     */
00038 /*---------------------------------------------------------------------------*/
00039 
00040 /*---------------------------------------------------------------------------*/
00041 /* Structure declarations                                                     */
00042 /*---------------------------------------------------------------------------*/
00043 
00046 /*---------------------------------------------------------------------------*/
00047 /* Static function prototypes                                                */
00048 /*---------------------------------------------------------------------------*/
00049 
00050 static int NodesCompareDepth(Ntk_Node_t *node1, Ntk_Node_t *node2);
00051 static long NodeComputeDepth(Ntk_Node_t * node);
00052 static void NetworkAddDanglingNodesToOrderList(Ntk_Network_t * network, lsList nodeOrderList, st_table *nodeToHandle);
00053 static void NetworkAddNSVarsToOrderList(Ntk_Network_t * network, lsList nodeOrderList, st_table *nodeToHandle, boolean nsAfterSupport);
00054 static lsList LatchNSListConvertToLatchDataInputList(lsList latchNSList);
00055 static void NodeSetDepth(Ntk_Node_t * node, long depth);
00056 static void MddGroupVariables(mdd_manager *mddMgr, int initMddId, int blockSize);
00057 
00061 /*---------------------------------------------------------------------------*/
00062 /* Definition of exported functions                                          */
00063 /*---------------------------------------------------------------------------*/
00064 
00109 void
00110 Ord_NetworkOrderVariables(
00111   Ntk_Network_t *network,
00112   Ord_RootMethod rootOrderMethod,
00113   Ord_NodeMethod nodeOrderMethod,
00114   boolean        nsAfterSupport,
00115   Ord_OrderType  generatedOrderType /* Ord_All_c or Ord_InputAndLatch_c */,
00116   Ord_OrderType  suppliedOrderType /* no restrictions */,
00117   lsList         suppliedNodeList /* list of nodes Ntk_Node_t* from ordering file */,
00118   int            verbose)
00119 {
00120   lsList totalOrderList;      /* list of nodes (Ntk_Node_t *) */
00121   long   initialTime = util_cpu_time();
00122   
00123   /*
00124    * The condition where suppliedOrderType==InputAndLatch and
00125    * generatedOrderType==All is not currently allowed because we're not sure
00126    * if it's useful.
00127    */
00128   assert(!((suppliedOrderType == Ord_InputAndLatch_c)
00129            && (generatedOrderType == Ord_All_c))); 
00130 
00131   /*
00132    * Either get a total ordering of the network nodes from suppliedNodeList,
00133    * or compute it working from the network.
00134    */
00135   if ((suppliedOrderType == Ord_All_c)
00136       || (suppliedOrderType == Ord_InputAndLatch_c)) {
00137     totalOrderList = lsCopy(suppliedNodeList,
00138                             (lsGeneric (*) (lsGeneric)) NULL);
00139   }
00140   else {
00141     totalOrderList = Ord_NetworkOrderNodes(network, rootOrderMethod,
00142                                            nodeOrderMethod, nsAfterSupport,
00143                                            generatedOrderType,
00144                                            suppliedOrderType,
00145                                            suppliedNodeList, 
00146                                            verbose);
00147   }
00148     
00149 
00150   OrdNetworkAssignMddIds(network, generatedOrderType, totalOrderList, nsAfterSupport);
00151   (void) lsDestroy(totalOrderList, (void (*) (lsGeneric)) NULL);
00152 
00153   /*
00154    * If nsAfterSupport is FALSE, this implies that NS comes right after PS.
00155    *
00156    */
00157   if ( nsAfterSupport == FALSE ) {
00158     lsGen tmpGen;
00159     Ntk_Node_t *tmpLatch;
00160  
00161    /*
00162     * Iterate over each latch, and group the PS variable with the next
00163     * variable in the ordering, which is guaranteed to be the corresponding NS
00164     * variable.
00165     */
00166     Ntk_NetworkForEachLatch(network, tmpGen, tmpLatch) {
00167       mdd_manager *mddMgr = Ntk_NetworkReadMddManager( network );
00168           Ntk_Node_t *nsNode = Ntk_NodeReadShadow( tmpLatch );
00169       int psMddId = Ntk_NodeReadMddId( tmpLatch );
00170       int nsMddId = Ntk_NodeReadMddId( nsNode );
00171 
00172       /* 
00173        * Group size = 2 ( ps and ns )
00174        */
00175       if (nsMddId == (psMddId+1)) {
00176         MddGroupVariables(mddMgr, psMddId, 2);
00177       }
00178       /* Adnan's fix: See his mail to vis@ic on Oct 24, 1997 */
00179       if (nsMddId == (psMddId-1)) {
00180         MddGroupVariables(mddMgr, nsMddId, 2);
00181       }
00182     }
00183   }
00184 
00185   if (verbose > 0) {
00186     long finalTime = util_cpu_time();
00187     (void) fprintf(vis_stdout, "\nTotal ordering time = %2.1f\n",
00188                    (finalTime-initialTime)/1000.0);
00189   }
00190 }
00191 
00192 
00234 lsList
00235 Ord_NetworkOrderNodes(
00236   Ntk_Network_t *network,
00237   Ord_RootMethod rootOrderMethod,
00238   Ord_NodeMethod nodeOrderMethod,
00239   boolean        nsAfterSupport,
00240   Ord_OrderType  generatedOrderType /* Ord_All_c or Ord_InputAndLatch_c */,
00241   Ord_OrderType  suppliedOrderType  /* Ord_NextStateNode_c, Ord_Partial_c, or
00242                                         Ord_Unassigned_c */, 
00243   lsList         suppliedNodeList   /* list of nodes Ntk_Node_t* from ordering file */,
00244   int            verbose)
00245 {
00246   lsList      partialRootOrder;   /* list of nodes (Ntk_Node_t *) */
00247   lsList      roots;              /* list of nodes (Ntk_Node_t *) */
00248   lsList      nodeOrderList;      /* list of nodes (Ntk_Node_t *) */
00249   st_table   *nodeToHandle;       /* Ntk_Node_t* to lsHandle */
00250 
00251   /*
00252    * Check the input arguments.
00253    */
00254   assert(   (generatedOrderType == Ord_All_c)
00255          || (generatedOrderType == Ord_InputAndLatch_c));
00256 
00257   assert(   (suppliedOrderType == Ord_NextStateNode_c)
00258          || (suppliedOrderType == Ord_Partial_c)
00259          || (suppliedOrderType == Ord_Unassigned_c));
00260   
00261 
00262   /*
00263    * Compute an ordering on the roots. The nodes of the network are explored
00264    * in DFS order from the roots, in the root order computed.  If
00265    * suppliedOrderType is Ord_NextStateNode_c, then suppliedNodeList contains
00266    * the next state nodes; this list serves as a seed to compute the root
00267    * ordering.
00268    */
00269   partialRootOrder = (suppliedOrderType == Ord_NextStateNode_c)
00270       ? LatchNSListConvertToLatchDataInputList(suppliedNodeList)
00271       : (lsList) NULL;
00272   roots = Ord_NetworkOrderRoots(network, rootOrderMethod,
00273                                 partialRootOrder, verbose);
00274   if (suppliedOrderType == Ord_NextStateNode_c) {
00275     (void) lsDestroy(partialRootOrder, (void (*) (lsGeneric)) NULL);
00276   }
00277   if (verbose > 0) {
00278     (void) fprintf(vis_stdout, "\nOrder in which roots are visited:\n");
00279     OrdNodeListWrite(vis_stdout, roots);
00280   }
00281   
00282   /*
00283    * Compute an order on all nodes in the transitive fanin of roots, including
00284    * the roots themselves. Pass in an empty nodeToHandle table.
00285    */
00286   nodeToHandle  = st_init_table(st_ptrcmp, st_ptrhash);
00287   nodeOrderList = OrdNetworkOrderTFIOfRoots(network, roots, nodeOrderMethod,
00288                                             nodeToHandle, verbose);
00289   (void) lsDestroy(roots, (void (*) (lsGeneric)) NULL);
00290 
00291   if (verbose > 0) {
00292     (void) fprintf(vis_stdout, "\nOrder of network nodes without NS:\n");
00293     OrdNodeListWrite(vis_stdout, nodeOrderList);
00294   }
00295   
00296   /*
00297    * Add in the next state variables (represented by the shadow nodes of
00298    * latches).
00299    */
00300   NetworkAddNSVarsToOrderList(network, nodeOrderList, nodeToHandle, nsAfterSupport);
00301   if (verbose > 2) {
00302     (void) fprintf(vis_stdout, "\nOrder of network nodes with NS:\n");
00303     OrdNodeListWrite(vis_stdout, nodeOrderList);
00304   }
00305   
00306   
00307   /*
00308    * There may be some nodes that are not in the TFI of any root. Put such
00309    * nodes at the end of nodeOrderList (in no particular order).
00310    */
00311   NetworkAddDanglingNodesToOrderList(network, nodeOrderList, nodeToHandle);
00312   st_free_table(nodeToHandle);
00313   
00314   /*
00315    * If the suppliedOrderType is Partial, then merge (left, arbitrarily) the
00316    * computed node order into the supplied node order and return the result.
00317    * Otherwise, just return the nodeOrderList computed.
00318    */
00319   if (suppliedOrderType == Ord_Partial_c) {
00320     lsList suppliedNodeListCopy = lsCopy(suppliedNodeList,
00321                                          (lsGeneric (*) (lsGeneric)) NULL);
00322 
00323     Ord_ListMergeList(suppliedNodeListCopy, nodeOrderList, Ord_ListMergeLeft_c);
00324     (void) lsDestroy(nodeOrderList, (void (*) (lsGeneric)) NULL);
00325     return suppliedNodeListCopy;
00326   }
00327   else {
00328     return nodeOrderList;
00329   }
00330 }
00331 
00332 
00350 void
00351 Ord_NetworkAssignMddIdForNode(
00352   Ntk_Network_t *network,
00353   Ntk_Node_t    *node)
00354 {
00355   if (Ntk_NodeReadMddId(node) != NTK_UNASSIGNED_MDD_ID) {
00356     return;
00357   }
00358   else {
00359     int          mddId;
00360     mdd_manager *mddManager = Ntk_NetworkReadMddManager(network);
00361     array_t     *mvarValues = array_alloc(int, 0);
00362     array_t     *mvarNames  = array_alloc(char *, 0);
00363   
00364     /*
00365      * If the network doesn't already have an MDD manager, then create one.  In
00366      * any case, set mddId to be the number of variables currently existing in
00367      * the manager.
00368      */
00369     if (mddManager == NIL(mdd_manager)) {
00370       mddManager = Ntk_NetworkInitializeMddManager(network);
00371       mddId = 0;
00372     }
00373     else {
00374       array_t *mvarArray  = mdd_ret_mvar_list(mddManager);
00375       mddId = array_n(mvarArray);
00376     }
00377   
00378     Ntk_NodeSetMddId(node, mddId);
00379 
00380     array_insert_last(int, mvarValues,
00381                       Var_VariableReadNumValues(Ntk_NodeReadVariable(node)));
00382     array_insert_last(char *, mvarNames, Ntk_NodeReadName(node));
00383 
00384     /*
00385      * Create the variable in the MDD manager.  The last argument being NIL
00386      * means that the variable will not be interleaved.
00387      */
00388     mdd_create_variables(mddManager, mvarValues, mvarNames, NIL(array_t));
00389 
00390     array_free(mvarValues);
00391     array_free(mvarNames);
00392   }
00393 }
00394 
00395 
00431 void
00432 Ord_ListMergeLeftListUsingTable(
00433   lsList    list1,
00434   lsList    list2,
00435   st_table *dataToHandle1)
00436 {
00437   lsGen      gen1;   /* generator for list1 */
00438   lsGen      gen2;   /* generator for list2 */
00439   lsHandle   handle; /* handle of an item in list1 */
00440   lsGeneric  data;   
00441   lsGeneric  prevData;
00442 
00443   /*
00444    * Walk through list2 forwards, keeping track of the previous item just visited.
00445    */
00446   gen2 = lsStart(list2);
00447   prevData = NULL;
00448   while (lsNext(gen2, &data, LS_NH) == LS_OK) {
00449 
00450     if (!st_is_member(dataToHandle1, (char *) data)) {
00451       /*
00452        * Data is not present in list1, so we must insert it at the proper
00453        * location.
00454        */
00455       if (prevData == NULL) {
00456         /*
00457          * Data is the head of list2, so insert it at the head of list1.
00458          */
00459         (void) lsNewBegin(list1, data, &handle);
00460       }
00461       else {
00462         lsGeneric dummyData;
00463         lsHandle  prevHandle;
00464 
00465         /*
00466          * Data is not the head of list1.  Hence, insert it just to the right
00467          * of the location of prevData in list1 (by induction, prevData must
00468          * currently exist in list1). Do this by getting the handle of
00469          * prevData in list1, creating a generator initialized to just after
00470          * prevData, and then inserting data at this point. Note that
00471          * lsInAfter and lsInBefore are equivalent in this case, since we
00472          * immediately kill gen1. 
00473          */
00474         st_lookup(dataToHandle1, prevData, &prevHandle);
00475         gen1 = lsGenHandle(prevHandle, &dummyData, LS_AFTER);
00476         (void) lsInAfter(gen1, data, &handle);
00477         (void) lsFinish(gen1);
00478       }
00479       st_insert(dataToHandle1, data, handle);
00480 
00481     } /* else, data already present in list1, so do nothing */
00482 
00483     prevData = data;
00484 
00485   } /* end while */
00486   (void) lsFinish(gen2);
00487 }
00488 
00489 
00521 void
00522 Ord_ListMergeRightListUsingTable(
00523   lsList    list1,
00524   lsList    list2,
00525   st_table *dataToHandle1)
00526 {
00527   lsGen      gen1;   /* generator for list1 */
00528   lsGen      gen2;   /* generator for list2 */
00529   lsHandle   handle; /* handle of an item in list1 */
00530   lsGeneric  data;   
00531   lsGeneric  succData;
00532 
00533   /*
00534    * Walk through list2 backwards, keeping track of the successor item just visited.
00535    */
00536   gen2 = lsEnd(list2);
00537   succData = NULL;
00538   while (lsPrev(gen2, &data, LS_NH) == LS_OK) {
00539 
00540     if (!st_is_member(dataToHandle1, (char *) data)) {
00541       /*
00542        * Data is not present in list1, so we must insert it at the proper
00543        * location.
00544        */
00545       if (succData == NULL) {
00546         /*
00547          * Data is the tail of list2, so insert it at the tail of list1.
00548          */
00549         (void) lsNewEnd(list1, data, &handle);
00550       }
00551       else {
00552         lsGeneric dummyData;
00553         lsHandle  succHandle;
00554 
00555         /*
00556          * Data is not the tail of list1.  Hence, insert it just to the left
00557          * of the location of succData in list1 (by induction, succData must
00558          * currently exist in list1). Do this by getting the handle of
00559          * succData in list1, creating a generator initialized to just before
00560          * succData, and then inserting data at this point. Note that
00561          * lsInAfter and lsInBefore are equivalent in this case, since we are
00562          * immediately kill gen1. 
00563          */
00564         st_lookup(dataToHandle1, succData, &succHandle);
00565         gen1 = lsGenHandle(succHandle, &dummyData, LS_BEFORE);
00566         (void) lsInAfter(gen1, data, &handle);
00567         (void) lsFinish(gen1);
00568       }
00569       st_insert(dataToHandle1, data, handle);
00570 
00571     } /* else, data already present in list1, so do nothing */
00572 
00573     succData = data;
00574 
00575   } /* end while */
00576   (void) lsFinish(gen2);
00577 }
00578 
00579 
00593 void
00594 Ord_ListMergeListUsingTable(
00595   lsList               list1,
00596   lsList               list2,
00597   st_table            *dataToHandle1,
00598   Ord_ListMergeMethod  method)
00599 {
00600   if (method == Ord_ListMergeLeft_c) {
00601     Ord_ListMergeLeftListUsingTable(list1, list2, dataToHandle1);
00602   }
00603   else if (method == Ord_ListMergeRight_c) {
00604     Ord_ListMergeRightListUsingTable(list1, list2, dataToHandle1);
00605   }
00606   else {
00607     fail("unrecognized method");
00608   }
00609 }
00610     
00611 
00624 void
00625 Ord_ListMergeList(
00626   lsList              list1,
00627   lsList              list2,
00628   Ord_ListMergeMethod method)
00629 {
00630   lsGen      gen1;   /* generator for list1 */
00631   lsHandle   handle; /* handle of an item in list1 */
00632   lsGeneric  data;   
00633   st_table  *dataToHandle1 = st_init_table(st_ptrcmp, st_ptrhash);
00634 
00635   /*
00636    * Load a hash table mapping each item in list1 to its handle in list1.
00637    */
00638   gen1 = lsStart(list1);
00639   while (lsNext(gen1, &data, &handle) == LS_OK) {
00640     st_insert(dataToHandle1, (char *) data, (char *) handle);
00641   }
00642   (void) lsFinish(gen1);
00643 
00644   Ord_ListMergeListUsingTable(list1, list2, dataToHandle1, method);
00645 
00646   st_free_table(dataToHandle1);
00647 }
00648 
00649   
00660 void
00661 Ord_ListAppendList(
00662   lsList list1,
00663   lsList list2)
00664 {
00665   lsGen gen;
00666   lsHandle handle; /* unused */
00667   lsGeneric data;   
00668 
00669   /*
00670    * Walk through list2 forwards, inserting each element to the end of list1.
00671    */
00672   gen = lsStart(list2);
00673   while (lsNext(gen, &data, LS_NH) == LS_OK) {
00674     (void) lsNewEnd(list1, data, &handle);
00675   } 
00676   (void) lsFinish(gen);
00677 }
00678 
00679   
00680 /*---------------------------------------------------------------------------*/
00681 /* Definition of internal functions                                          */
00682 /*---------------------------------------------------------------------------*/
00683 
00694 int
00695 OrdNodesFromListCompareDepth(
00696   lsGeneric node1,
00697   lsGeneric node2)
00698 {
00699   return NodesCompareDepth((Ntk_Node_t *) node1, (Ntk_Node_t *) node2);
00700 }
00701 
00702 
00713 int
00714 OrdNodesFromArrayCompareDepth(
00715   const void * node1,
00716   const void * node2)
00717 {
00718   return NodesCompareDepth(*(Ntk_Node_t **) node1, *(Ntk_Node_t **) node2);
00719 }
00720 
00721 
00738 void
00739 OrdNetworkComputeNodeDepths(
00740   Ntk_Network_t * network,
00741   lsList  roots /* list of Ntk_Node_t  */)
00742 {
00743   lsGen       gen;
00744   Ntk_Node_t *node;
00745   Ntk_Node_t *root;
00746 
00747   /*
00748    * Initialize the depth of each node to unassigned.
00749    */
00750   Ntk_NetworkForEachNode(network, gen, node) {
00751     NodeSetDepth(node, ORDUNASSIGNED_DEPTH);
00752   }
00753 
00754   /*
00755    * Start the recursive computation from each root.
00756    */
00757   lsForEachItem(roots, gen, root) {
00758     (void) NodeComputeDepth(root);
00759   }
00760 }
00761 
00762 
00770 void
00771 OrdNodeListWrite(
00772   FILE *fp,
00773   lsList nodeList)
00774 {
00775   lsGen gen;
00776   Ntk_Node_t *node;
00777 
00778   lsForEachItem(nodeList, gen, node) {
00779     (void) fprintf(fp, "%s\n", Ntk_NodeReadName(node));
00780   }
00781 }
00782 
00783 
00798 long
00799 OrdNodeReadDepth(
00800   Ntk_Node_t * node)
00801 {
00802   return ((long) Ntk_NodeReadUndef(node));
00803 }
00804 
00805 
00823 void
00824 OrdNetworkAssignMddIds(
00825   Ntk_Network_t * network,
00826   Ord_OrderType  orderType,
00827   lsList  orderList,
00828   boolean nsAfterSupport)
00829 {
00830   lsGen        gen;
00831   Ntk_Node_t  *node;
00832   int          mddId;
00833   mdd_manager *mddManager = Ntk_NetworkReadMddManager(network);
00834   array_t     *mvarValues = array_alloc(int, lsLength(orderList));
00835   array_t     *mvarNames  = array_alloc(char *, lsLength(orderList));
00836 
00837   assert((orderType == Ord_All_c) || (orderType == Ord_InputAndLatch_c));
00838 
00839   /*
00840    * If the network doesn't already have an MDD manager, then create one.  In
00841    * any case, set mddId to be the number of variables currently existing in
00842    * the manager.
00843    */
00844   if (mddManager == NIL(mdd_manager)) {
00845     mddManager = Ntk_NetworkInitializeMddManager(network);
00846     mddId = 0;
00847   }
00848   else {
00849     array_t *mvarArray  = mdd_ret_mvar_list(mddManager);
00850     mddId = array_n(mvarArray);
00851   }
00852   
00853   lsForEachItem(orderList, gen, node) {
00854     /*
00855      * A node gets an MDD id if node is a combinational input, next state
00856      * node, or orderType is Ord_All_c.
00857      */
00858     if (Ntk_NodeTestIsCombInput(node) || Ntk_NodeTestIsNextStateNode(node)
00859         || (orderType == Ord_All_c) ) {
00860 
00861       Ntk_NodeSetMddId(node, mddId);
00862       mddId++;
00863 
00864       array_insert_last(int, mvarValues,
00865                         Var_VariableReadNumValues(Ntk_NodeReadVariable(node)));
00866       array_insert_last(char *, mvarNames, Ntk_NodeReadName(node));
00867     }
00868   }
00869 
00870   /*
00871    * Create the variables in the MDD manager.  The last argument being NIL
00872    * means that the variables will not be interleaved.
00873    */
00874   mdd_create_variables(mddManager, mvarValues, mvarNames, NIL(array_t));
00875 
00876   array_free(mvarValues);
00877   array_free(mvarNames);
00878 }
00879     
00880 
00881 /*---------------------------------------------------------------------------*/
00882 /* Definition of static functions                                            */
00883 /*---------------------------------------------------------------------------*/
00884 
00894 static int
00895 NodesCompareDepth(
00896   Ntk_Node_t *node1,
00897   Ntk_Node_t *node2)
00898 {
00899   long depth1 = OrdNodeReadDepth(node1);
00900   long depth2 = OrdNodeReadDepth(node2);
00901 
00902   if (depth1 > depth2) {
00903     return -1;
00904   }
00905   else if (depth1 < depth2) {
00906     return 1;
00907   }
00908   else {
00909     char *name1 = Ntk_NodeReadName(node1);
00910     char *name2 = Ntk_NodeReadName(node2);
00911 
00912     /*
00913      * As a tiebreaker, sort based on name, so that the sorted result is not
00914      * sensitive to the order in which the nodes are passed to the compare
00915      * function. When sorting based on name, the order doesn't really matter,
00916      * but right now it's done so that "foo<i>" will come before "foo<j>" in
00917      * the ordering, where i < j.  This is just a little heuristic to put lower
00918      * order bits first. */
00919     if (strcmp(name1, name2) < 0) {
00920       return -1;
00921     }
00922     else if (strcmp(name1, name2) > 0) {
00923       return 1;
00924     }
00925     else {
00926       return 0;
00927     }
00928   }
00929 }
00930 
00931 
00941 static long
00942 NodeComputeDepth(
00943   Ntk_Node_t * node)
00944 {
00945   long depth = OrdNodeReadDepth(node);
00946 
00947   /*
00948    * If the node's depth has already been computed (i.e. it's not unassigned),
00949    * then just return it below.  If it's unassigned, then recursively compute
00950    * it.
00951    */
00952   if (depth == ORDUNASSIGNED_DEPTH) {
00953 
00954     if (Ntk_NodeTestIsCombInput(node) || Ntk_NodeTestIsConstant(node)) {
00955       /*
00956        * Latches, and nodes with no fanins, get depth 0. This is the terminal
00957        * case of recursion. 
00958        */
00959       depth = 0;
00960     }
00961     else {
00962       int         i;
00963       Ntk_Node_t *fanin;
00964       /*
00965        * Compute the depth of each fanin node in the support of node, and
00966        * maintain the maximum.  We start depth at 0 for max calculation.
00967        */
00968       depth = 0;
00969       Ntk_NodeForEachFanin(node, i, fanin) {  
00970         long faninDepth = NodeComputeDepth(fanin);
00971 
00972         depth = (depth > faninDepth) ? depth : faninDepth;
00973       }
00974       
00975       /*
00976        * The depth of node is one more than the max depths of its fanins.
00977        */
00978       depth++;
00979     }
00980 
00981     /*
00982      * Store the depth.
00983      */
00984     NodeSetDepth(node, depth);
00985   }
00986   
00987   return depth;
00988 }
00989 
00990   
01008 static void
01009 NetworkAddDanglingNodesToOrderList(
01010   Ntk_Network_t * network,
01011   lsList  nodeOrderList /* of Ntk_Node_t*  */,
01012   st_table *nodeToHandle /* Ntk_Node_t* to lsHandle */)
01013 {
01014   lsGen       gen;
01015   Ntk_Node_t *node;
01016 
01017   /*
01018    * For each network node, if it's not in nodeOrderList, then add it to the
01019    * end of the list. 
01020    * (NOTE: may be sensitive to ordering in memory.)
01021    */
01022   Ntk_NetworkForEachNode(network, gen, node) {
01023     if (!st_is_member(nodeToHandle, (char *) node)) {
01024       lsHandle handle;
01025       
01026       (void) lsNewEnd(nodeOrderList, (lsGeneric) node, &handle);
01027       st_insert(nodeToHandle, (char *) node, (char *) handle);
01028     }
01029   }
01030 }
01031 
01032 
01054 static void
01055 NetworkAddNSVarsToOrderList(
01056   Ntk_Network_t * network,
01057   lsList  nodeOrderList /* of Ntk_Node_t  */,
01058   st_table *nodeToHandle /* Ntk_Node_t* to lsHandle */,
01059   boolean nsAfterSupport)
01060 {
01061   lsGen       gen1;
01062   Ntk_Node_t *latch;
01063 
01064   /*
01065    * For each latch, add the latch's corresponding NS node to the ordering.
01066    * (NOTE: may be sensitive to ordering in memory.)
01067    */
01068   Ntk_NetworkForEachLatch(network, gen1, latch) {
01069     lsHandle    handle;
01070     lsGen       gen2;
01071     lsGeneric   dummyData;
01072     Ntk_Node_t *latchNS   = Ntk_NodeReadShadow(latch);
01073 
01074     if (nsAfterSupport) {
01075       /* Add just after the latch's dataInput. */
01076       lsHandle    dataInputHandle;
01077       Ntk_Node_t *dataInput = Ntk_LatchReadDataInput(latch);
01078       int         status UNUSED = st_lookup(nodeToHandle, dataInput,
01079                                             &dataInputHandle);
01080 
01081       assert(status);
01082       gen2 = lsGenHandle(dataInputHandle, &dummyData, LS_AFTER);
01083     }
01084     else {
01085       /* Add just after the latch. */
01086       lsHandle latchHandle;
01087       int      status = st_lookup(nodeToHandle, latch, &latchHandle);
01088 
01089       if (!status) {
01090         /*
01091          * Latch itself is not yet in the ordering.  This can happen if the
01092          * latch is not in the TFI of any other latch.  So add the latch first
01093          * (at the end of the ordering). 
01094          */
01095         (void) lsNewEnd(nodeOrderList, (lsGeneric) latch, &latchHandle);
01096         st_insert(nodeToHandle, (char *) latch, (char *) latchHandle);
01097       }
01098     
01099       gen2 = lsGenHandle(latchHandle, &dummyData, LS_AFTER);
01100     }
01101 
01102     /* Actually add to list here. */
01103     (void) lsInAfter(gen2, (lsGeneric) latchNS, &handle);  
01104     st_insert(nodeToHandle, (char *) latchNS, (char *) handle);
01105     (void) lsFinish(gen2);
01106       
01107   }
01108 }
01109 
01110 
01119 static lsList
01120 LatchNSListConvertToLatchDataInputList(
01121   lsList latchNSList)
01122 {
01123   lsGen       gen;
01124   Ntk_Node_t *node;
01125   Ntk_Node_t *latch;
01126   lsList      latchDataInputList = lsCreate();
01127 
01128   lsForEachItem(latchNSList, gen, node) {
01129     assert(Ntk_NodeTestIsNextStateNode(node));
01130     latch = Ntk_ShadowReadOrigin(node);
01131     (void) lsNewEnd(latchDataInputList, (lsGeneric)
01132                     Ntk_LatchReadDataInput(latch), LS_NH); 
01133   }
01134 
01135   return latchDataInputList;
01136 }
01137 
01138 
01148 static void
01149 NodeSetDepth(
01150   Ntk_Node_t * node,
01151   long depth)
01152 {
01153   Ntk_NodeSetUndef(node, (void *) depth);
01154 }
01155 
01170 static void
01171 MddGroupVariables(
01172   mdd_manager *mddMgr,
01173   int initMddId,
01174   int blockSize )
01175 {
01176   int i, j;
01177   int length;
01178   int aIndex;
01179   int startingBddIndex;
01180   int sanityCheck;
01181   mvar_type initMv, anMv;
01182   bvar_type initBvar, aBvar;
01183   array_t *mvar_list, *bvar_list;
01184   bdd_t *bdd;
01185   
01186   mvar_list = mdd_ret_mvar_list(mddMgr);
01187   bvar_list = mdd_ret_bvar_list(mddMgr);
01188 
01189   /*
01190    * mvar for initMddId 
01191    */
01192   initMv = array_fetch(mvar_type, mvar_list, initMddId);
01193 
01194   /*
01195    * bvar for first bdd for initMddId 
01196    */
01197   initBvar = mdd_ret_bvar(&initMv, 0, bvar_list);
01198 
01199   /*
01200    * number of bdd variables to group 
01201    */
01202   length = 0;
01203 
01204   /*
01205    * startingBddIndex is the level of the first bdd variable 
01206    */
01207   startingBddIndex = bdd_top_var_level( mddMgr, initBvar.node );
01208   sanityCheck = startingBddIndex;
01209 
01210   /*
01211    * in this loop we are simply ensuring that the bdd variables
01212    * corresponding to the mdd vars are infact contiguous. If this
01213    * is not the case we fail. length is the total number of bdd variables
01214    * to be grouped.
01215    */
01216   for( i = 0; i < blockSize; i++) {
01217     anMv = array_fetch(mvar_type, mvar_list, ( initMddId + i ) );
01218     for ( j = 0 ; j < anMv.encode_length; j++ ) {
01219 
01220       aBvar = mdd_ret_bvar( & anMv, j, bvar_list );
01221       aIndex = bdd_top_var_level( mddMgr,  aBvar.node );
01222 
01223       if ( sanityCheck != aIndex ) {
01224         /* bdd vars are not contiguous!! */
01225         fprintf(vis_stderr, "Badly formed block - bdd vars for %s (mvar_id = %d) are not contiguous!!\n",
01226                              anMv.name, anMv.mvar_id );
01227         fail("Wont go on\n");
01228       }
01229       else {
01230         /* number of variables to group increased by one */
01231         sanityCheck++;
01232         length++;
01233       }
01234     }
01235   }
01236 
01237   bdd = bdd_var_with_index(mddMgr, startingBddIndex);
01238   (void) bdd_new_var_block(bdd, length);
01239   bdd_free(bdd);
01240 }
01241 
01242