VIS

src/part/partFrontier.c

Go to the documentation of this file.
00001 
00041 #include "partInt.h"
00042 
00043 static char rcsid[] UNUSED = "$Id: partFrontier.c,v 1.25 2005/05/11 20:50:32 jinh Exp $";
00044 
00045 /*---------------------------------------------------------------------------*/
00046 /* Constant declarations                                                     */
00047 /*---------------------------------------------------------------------------*/
00048 
00049 
00050 /*---------------------------------------------------------------------------*/
00051 /* Stucture declarations                                                     */
00052 /*---------------------------------------------------------------------------*/
00053 
00054 /*---------------------------------------------------------------------------*/
00055 /* Type declarations                                                         */
00056 /*---------------------------------------------------------------------------*/
00057 
00058 
00059 /*---------------------------------------------------------------------------*/
00060 /* Variable declarations                                                     */
00061 /*---------------------------------------------------------------------------*/
00062 
00063 /*---------------------------------------------------------------------------*/
00064 /* Macro declarations                                                        */
00065 /*---------------------------------------------------------------------------*/
00066 
00067 
00070 /*---------------------------------------------------------------------------*/
00071 /* Static function prototypes                                                */
00072 /*---------------------------------------------------------------------------*/
00073 
00074 static void PartitionCreateEdges(graph_t *partition);
00075 static Mvf_Function_t * NodeBuildMvf(Ntk_Node_t * node, st_table * nodeToMvfTable);
00076 static Mvf_Function_t * NodeBuildMvf2(Ntk_Node_t * node, st_table * nodeToMvfTable, st_table *faninNumberTable);
00077 static Mvf_Function_t * NodeBuildPseudoInputMvf(Ntk_Node_t * node);
00078 static void PrintPartitionRecursively(vertex_t *vertex, st_table *vertexTable, int indent);
00079 
00083 /*---------------------------------------------------------------------------*/
00084 /* Definition of exported functions                                          */
00085 /*---------------------------------------------------------------------------*/
00086 
00100 void 
00101 Part_PartitionReadOrCreateBnvs(
00102   Ntk_Network_t *network,
00103   st_table *coiLatchTable,
00104   st_table *coiBnvTable)
00105 {
00106   graph_t    *partition;
00107   lsGen      lsgen;
00108   vertex_t   *vertex;
00109   long       mddId;
00110   Ntk_Node_t *node;
00111 
00112   /* if the partition is not available, sweep the network  */
00113   partition = Part_NetworkReadPartition(network);
00114   if (partition == NIL(graph_t)) {
00115     PartInsertBnvs(network, coiLatchTable, coiBnvTable);
00116     return;
00117   }
00118 
00119   /* otherwise, go through the vertices */
00120   foreach_vertex(partition, lsgen, vertex) {
00121     mddId = PartVertexReadMddId(vertex);
00122     if (mddId == -1) continue;
00123 
00124     node = Ntk_NetworkFindNodeByMddId(network, mddId);
00125     assert(node != NIL(Ntk_Node_t));
00126 
00127     if ( !Ntk_NodeTestIsCombInput(node) &&
00128          Ntk_NodeReadNumFanouts(node)!=0 )
00129       st_insert(coiBnvTable, (char *)node, NIL(char));
00130   }
00131  
00132 }
00133 
00147 void
00148 Part_PartitionWithExistingBnvs(
00149   Ntk_Network_t *network,
00150   graph_t *partition,
00151   st_table *coiBnvTable,
00152   st_table *absLatchTable,
00153   st_table *absBnvTable)
00154 {
00155 
00156   PartPartitionWithExistingBnvs(network, partition, coiBnvTable, 
00157                                 absLatchTable, absBnvTable);
00158 }
00159 
00160 /*---------------------------------------------------------------------------*/
00161 /* Definition of internal functions                                          */
00162 /*---------------------------------------------------------------------------*/
00163 
00199 void
00200 PartPartitionFrontier(Ntk_Network_t *network,
00201                       graph_t *partition,
00202                       lsList  rootList,
00203                       lsList  leaveList,
00204                       mdd_t   *careSet)
00205 {
00206   Ntk_Node_t    *node;           /* Pointer to iterate over nodes */
00207   lsGen         gen;                /* To iterate over lists */
00208   vertex_t      *vertex;          /* Destination of the edge being added */
00209   char          *name;              /* Name of the node being processed */
00210   int           mddId;              /* Id of the node being processed */
00211   int           i;
00212   mdd_manager   *mddManager = PartPartitionReadMddManager(partition);
00213   /* nodeToMvfTable maps a node to the mvf in the form that is needed to build
00214      mvfs for the fanouts of the node.  I.e., a cutpoint node is mapped to an
00215      mdd for a new variable. */
00216   st_table *nodeToMvfTable = st_init_table(st_ptrcmp, st_ptrhash);
00217   st_table *leafNodesTable = st_init_table(st_ptrcmp, st_ptrhash);
00218   st_table *topoNodeTable;
00219   Ntk_Node_t *fanoutNode;
00220   array_t *rootNodesArray;
00221   long fanoutNumber = 0;
00222   Mvf_Function_t *nodeMvf; 
00223   long bddSize;
00224   int sizeThreshold;
00225   lsList topologicalNodeList;
00226   lsGen lsgen;
00227   st_generator *stgen;
00228   char *flagValue =  Cmd_FlagReadByName("partition_threshold");
00229 
00230   if (flagValue == NIL(char)){
00231     sizeThreshold = 1000; /* the default value */
00232   }
00233   else {
00234     sizeThreshold = atoi(flagValue);
00235   }
00236 
00237   /* Put combinational inputs in the leafNodesTable. */
00238   if (leaveList == (lsList)0) {
00239     Ntk_NetworkForEachCombInput(network, gen, node) {
00240       st_insert(leafNodesTable, (char *)node, (char *) (long) (-1) );
00241     }
00242   } /* End of then */ 
00243   else {
00244     lsForEachItem(leaveList, gen, node) {
00245       st_insert(leafNodesTable, (char *)node, (char *) (long) (-1) );
00246     }
00247   } /* End of if-then-else */
00248 
00249   
00250   /* Take the nodes in rootList as the roots */
00251   if (rootList == (lsList)0) {
00252     rootNodesArray = array_alloc(Ntk_Node_t *, 
00253                                Ntk_NetworkReadNumCombOutputs(network));
00254     i = 0;
00255     Ntk_NetworkForEachCombOutput(network, gen, node) {
00256       array_insert(Ntk_Node_t *, rootNodesArray, i++, node);
00257     }
00258 
00259   } /* End of then */ 
00260   else {
00261     rootNodesArray = array_alloc(Ntk_Node_t *, lsLength(rootList));
00262     i = 0;
00263     lsForEachItem(rootList, gen, node) {
00264       array_insert(Ntk_Node_t *, rootNodesArray, i++, node);
00265     }
00266   } /* End of if-then-else */
00267 
00268   /* Get an array of nodes sorted in topological order */
00269   topologicalNodeList = Ntk_NetworkComputeTopologicalOrder(network,
00270                                                            rootNodesArray,
00271                                                            leafNodesTable);   
00272 
00273   /* For each node, compute the number of its fanouts */
00274   topoNodeTable = st_init_table(st_ptrcmp, st_ptrhash);
00275   lsForEachItem(topologicalNodeList, lsgen, node){
00276     st_insert(topoNodeTable, (char *)node, NIL(char));
00277   }
00278   lsForEachItem(topologicalNodeList, lsgen, node){
00279     fanoutNumber = 0;
00280     Ntk_NodeForEachFanout(node, i, fanoutNode) {
00281       if (st_is_member(topoNodeTable, fanoutNode) &&
00282           !st_is_member(leafNodesTable, fanoutNode))
00283         fanoutNumber++;
00284     }
00285     st_insert(topoNodeTable, node, (char *) fanoutNumber);
00286   }
00287 
00288   /* For each leaf nodes, create a vertex in the partition, create the mvf, and
00289    * a mapping of name to vertex, and mddId to vertex.
00290    */
00291   st_foreach_item(leafNodesTable, stgen, &node, NULL) {
00292     if (!st_lookup(topoNodeTable, node, &fanoutNumber)) {
00293       continue;
00294     }
00295     mddId = Ntk_NodeReadMddId(node);
00296     assert(mddId != NTK_UNASSIGNED_MDD_ID);
00297     vertex = g_add_vertex(partition);
00298     name  = Ntk_NodeReadName(node);
00299     st_insert(PartPartitionReadNameToVertex(partition), name, vertex);
00300     st_insert(PartPartitionReadMddIdToVertex(partition), (char *)(long)mddId,
00301               vertex); 
00302 
00303     if (Ntk_NodeTestIsPseudoInput(node)){
00304       nodeMvf = NodeBuildPseudoInputMvf(node);
00305     }
00306     else {
00307       nodeMvf = Mvf_FunctionCreateFromVariable(mddManager,mddId);
00308     }
00309 
00310     if (fanoutNumber <= 0) {
00311       st_insert(nodeToMvfTable, (char *)node, NIL(char));
00312     }else
00313       st_insert(nodeToMvfTable, (char *)node, 
00314                 (char *)Mvf_FunctionDuplicate(nodeMvf));
00315 
00316     vertex->user_data = (gGeneric)PartVertexInfoCreateSingle(name, nodeMvf,
00317                                                              mddId);
00318   }
00319 
00320   st_free_table(leafNodesTable);
00321   
00322 
00323   fflush(vis_stdout);
00324 
00325   /* Go through the topologicalNodeList
00326    * a. If the node is of combinational input type, continue.
00327    *
00328    * b. Otherwise, Build the Mdd for this node, in terms of the function of the
00329    *    fanin nodes in. If the Mdd size exceeds the threshold, create an Mdd ID
00330    *    for this node.
00331    */
00332 
00333   lsForEachItem(topologicalNodeList, lsgen, node){
00334     if (st_is_member(nodeToMvfTable, (char *)node)) continue;
00335 
00336     nodeMvf = NodeBuildMvf2(node, nodeToMvfTable, topoNodeTable);
00337     bddSize = bdd_size_multiple(nodeMvf);
00338 
00339     if ((bddSize <= sizeThreshold) && !Ntk_NodeTestIsCombOutput(node)) {
00340       st_insert(nodeToMvfTable, node, nodeMvf);
00341       continue;
00342     }
00343 
00344     /* node either is a primary output, or has an mvf exceeding the
00345      * threshold. 
00346      */
00347     st_lookup(topoNodeTable, node, &fanoutNumber);
00348     if ( (bddSize > sizeThreshold) &&  fanoutNumber > 0 ) {
00349       if ((mddId = Ntk_NodeReadMddId(node)) == -1){
00350         Ord_NetworkAssignMddIdForNode(network, node);
00351         mddId = Ntk_NodeReadMddId(node);
00352       }
00353       st_insert(nodeToMvfTable, node,
00354                 Mvf_FunctionCreateFromVariable(mddManager,mddId));
00355     }else {
00356       if (fanoutNumber <= 0) {
00357         st_insert(nodeToMvfTable, node, NIL(char));
00358       }else
00359         st_insert(nodeToMvfTable, (char *)node, 
00360                   (char *)Mvf_FunctionDuplicate(nodeMvf));
00361     }
00362 
00363     vertex = g_add_vertex(partition);
00364     name  = Ntk_NodeReadName(node);
00365     mddId = Ntk_NodeReadMddId(node);
00366     st_insert(PartPartitionReadNameToVertex(partition), name, (char *)vertex);
00367     vertex->user_data = (gGeneric)PartVertexInfoCreateSingle(name, nodeMvf, 
00368                                                              mddId);
00369     if (mddId != -1){
00370       st_insert(PartPartitionReadMddIdToVertex(partition),
00371                 (char *)(long)mddId, (char *)vertex);
00372     }
00373   }/* for each member of topologicalNodeList */
00374   
00375 
00376   /* sanity check */
00377   st_foreach_item(nodeToMvfTable, stgen, &node, &nodeMvf) {
00378 #if 0
00379     if (nodeMvf != NIL(Mvf_Function_t)) {
00380       int chk = st_lookup(topoNodeTable, node, &fanoutNumber);
00381       Ntk_NodeForEachFanout(node, i, fanoutNode) {
00382         fprintf(vis_stdout, "\nunclean node %s   =>   %s", 
00383                 Ntk_NodeReadName(node),
00384                 Ntk_NodeReadName(fanoutNode));
00385         if (Ntk_NodeTestIsLatch(fanoutNode))
00386           fprintf(vis_stdout, "\t(latch)");
00387       }
00388     }
00389 #else
00390     assert (nodeMvf == NIL(Mvf_Function_t)) ;
00391 #endif
00392   }
00393 
00394   PartitionCreateEdges(partition);
00395   array_free(rootNodesArray);
00396   st_free_table(nodeToMvfTable);
00397   st_free_table(topoNodeTable);
00398   lsDestroy(topologicalNodeList, (void (*)(lsGeneric))0);
00399 }
00400 
00401 #if 0
00402 void
00403 PartPartitionFrontierOld(Ntk_Network_t *network,
00404                       graph_t *partition,
00405                       lsList  rootList,
00406                       lsList  leaveList,
00407                       mdd_t   *careSet)
00408 {
00409   Ntk_Node_t    *node;           /* Pointer to iterate over nodes */
00410   lsGen         gen;                /* To iterate over lists */
00411   vertex_t      *vertex;          /* Destination of the edge being added */
00412   char          *name;              /* Name of the node being processed */
00413   int           mddId;              /* Id of the node being processed */
00414   int           i;
00415   mdd_manager   *mddManager = PartPartitionReadMddManager(partition);
00416   /* nodeToMvfTable maps a node to the mvf in the form that is needed to build
00417      mvfs for the fanouts of the node.  I.e., a cutpoint node is mapped to an
00418      mdd for a new variable. */
00419   st_table *nodeToMvfTable = st_init_table(st_ptrcmp, st_ptrhash);
00420   st_table *leafNodesTable = st_init_table(st_ptrcmp, st_ptrhash);
00421   array_t *rootNodesArray;
00422   Mvf_Function_t *nodeMvf; 
00423   long bddSize;
00424   int sizeThreshold;
00425   lsList topologicalNodeList;
00426   lsGen lsgen;
00427   st_generator *stgen;
00428   char *flagValue =  Cmd_FlagReadByName("partition_threshold");
00429   if (flagValue == NIL(char)){
00430     sizeThreshold = 1000; /* the default value */
00431   }
00432   else {
00433     sizeThreshold = atoi(flagValue);
00434   }
00435 
00436   /* Put combinational inputs in the leafNodesTable. */
00437   if (leaveList == (lsList)0) {
00438     Ntk_NetworkForEachCombInput(network, gen, node) {
00439       st_insert(leafNodesTable, (char *)node, (char *) (long) (-1) );
00440     }
00441   } /* End of then */ 
00442   else {
00443     lsForEachItem(leaveList, gen, node) {
00444       st_insert(leafNodesTable, (char *)node, (char *) (long) (-1) );
00445     }
00446   } /* End of if-then-else */
00447 
00448   /*
00449    * For each leaf nodes, create a vertex in the partition, create the mvf, and
00450    * a mapping of name to vertex, and mddId to vertex.
00451    */
00452   st_foreach_item(leafNodesTable, stgen, &node, NULL){
00453     mddId = Ntk_NodeReadMddId(node);
00454     assert(mddId != NTK_UNASSIGNED_MDD_ID);
00455     vertex = g_add_vertex(partition);
00456     name  = Ntk_NodeReadName(node);
00457     st_insert(PartPartitionReadNameToVertex(partition), name, (char *)vertex);
00458     st_insert(PartPartitionReadMddIdToVertex(partition), (char *)(long)mddId,
00459               (char *)vertex); 
00460     if (Ntk_NodeTestIsPseudoInput(node)){
00461       nodeMvf = NodeBuildPseudoInputMvf(node);
00462     }
00463     else {
00464       nodeMvf = Mvf_FunctionCreateFromVariable(mddManager,mddId);
00465     }
00466     st_insert(nodeToMvfTable, (char *)node, (char *)nodeMvf);
00467     vertex->user_data = (gGeneric)PartVertexInfoCreateSingle(name, nodeMvf,
00468                                                              mddId);
00469   }
00470 
00471   
00472   /* Take the nodes in rootList as the roots */
00473   if (rootList == (lsList)0) {
00474     rootNodesArray = array_alloc(Ntk_Node_t *, 
00475                                Ntk_NetworkReadNumCombOutputs(network));
00476     i = 0;
00477     Ntk_NetworkForEachCombOutput(network, gen, node) {
00478       array_insert(Ntk_Node_t *, rootNodesArray, i++, node);
00479     }
00480   } /* End of then */ 
00481   else {
00482     rootNodesArray = array_alloc(Ntk_Node_t *, lsLength(rootList));
00483     i = 0;
00484     lsForEachItem(rootList, gen, node) {
00485       array_insert(Ntk_Node_t *, rootNodesArray, i++, node);
00486     }
00487   } /* End of if-then-else */
00488 
00489   
00490 
00491   /* Get an array of nodes sorted in topological order */
00492   topologicalNodeList = Ntk_NetworkComputeTopologicalOrder(network,
00493                                                            rootNodesArray,
00494                                                            leafNodesTable);   
00495   
00496   st_free_table(leafNodesTable);
00497   
00498 
00499   /* Go through the topologicalNodeList
00500    * a. If the node is of combinational input type, continue.
00501    *
00502    * b. Otherwise, Build the Mdd for this node, in terms of the function of the
00503    *    fanin nodes in. If the Mdd size exceeds the threshold, create an Mdd ID
00504    *    for this node.
00505    */
00506 
00507   lsForEachItem(topologicalNodeList, lsgen, node){
00508     if (st_is_member(nodeToMvfTable, (char *)node)) continue;
00509     nodeMvf = NodeBuildMvf(node, nodeToMvfTable);
00510     bddSize = bdd_size_multiple(nodeMvf);
00511     if ((bddSize <= sizeThreshold) &&
00512         (Ntk_NodeTestIsCombOutput(node) == 0)){
00513       st_insert(nodeToMvfTable, (char *)node, (char *)nodeMvf);
00514       continue;
00515     }
00516     /* node either is a primary output, or has an mvf exceeding the
00517        threshold. */
00518     vertex = g_add_vertex(partition);
00519     name  = Ntk_NodeReadName(node);
00520     st_insert(PartPartitionReadNameToVertex(partition), name,
00521               (char *)vertex);
00522     if ((bddSize > sizeThreshold) &&
00523         (Ntk_NodeReadNumFanouts(node) != 0)){
00524       if ((mddId = Ntk_NodeReadMddId(node)) == -1){
00525         Ord_NetworkAssignMddIdForNode(network, node);
00526         mddId = Ntk_NodeReadMddId(node);
00527       }
00528       st_insert(nodeToMvfTable, (char *)node,
00529                 (char *)Mvf_FunctionCreateFromVariable(mddManager,mddId));
00530     }
00531     else {
00532       /* Small mvf, or no fanout */
00533       st_insert(nodeToMvfTable, (char *)node, (char *)nodeMvf);
00534     }
00535     mddId = Ntk_NodeReadMddId(node);
00536     vertex->user_data = (gGeneric)PartVertexInfoCreateSingle(name,
00537                                                              nodeMvf, 
00538                                                              mddId);
00539     if (mddId != -1){
00540       st_insert(PartPartitionReadMddIdToVertex(partition),
00541                 (char *)(long)mddId, (char *)vertex);
00542     }
00543   }/* for each member of topologicalNodeList */
00544   
00545   /*
00546    * Free the Mvfs in nodeToMvfTable not associated with vertices in the
00547    * partition.  The mvfs of inputs are always in the partition; hence,
00548    * their mvfs should always be preserved.  For outputs, we have to free
00549    * the mvf in nodeToMvfTable if the output is also a cutpoint, because in
00550    * this case the mvf in the partition vertex and the one in the
00551    * nodeToMvfTable are different.
00552    */
00553 
00554   lsForEachItem(topologicalNodeList, gen, node){ 
00555     if (!Ntk_NodeTestIsCombInput(node)){
00556       if(!Ntk_NodeTestIsCombOutput(node)){ 
00557         st_lookup(nodeToMvfTable, node, &nodeMvf); 
00558         assert(nodeMvf != NIL(Mvf_Function_t)); 
00559         Mvf_FunctionFree(nodeMvf);
00560       } else {
00561         Mvf_Function_t *vertexMvf;
00562         
00563         name =  Ntk_NodeReadName(node);
00564         vertex = Part_PartitionFindVertexByName(partition, name);
00565         st_lookup(nodeToMvfTable, node, &nodeMvf);
00566         vertexMvf = PartVertexReadFunction(vertex);
00567         assert(nodeMvf != NIL(Mvf_Function_t) &&
00568                vertexMvf != NIL(Mvf_Function_t));
00569         if(vertexMvf != nodeMvf){
00570           Mvf_FunctionFree(nodeMvf);
00571         }
00572       }
00573     }/* not input */
00574   }/* for each node */
00575 
00576   PartitionCreateEdges(partition);
00577   array_free(rootNodesArray);
00578   st_free_table(nodeToMvfTable);
00579   lsDestroy(topologicalNodeList, (void (*)(lsGeneric))0);
00580 }
00581 #endif
00582 
00598 void
00599 PartUpdateFrontier(Ntk_Network_t *network,
00600                    graph_t *partition,
00601                    lsList  rootList,
00602                    lsList  leaveList,
00603                    mdd_t   *careSet)
00604 {
00605   Ntk_Node_t    *node;           /* Pointer to iterate over nodes */
00606   lsGen         gen;                /* To iterate over lists */
00607   vertex_t      *vertex;          /* Destination of the edge being added */
00608   char          *name;              /* Name of the node being processed */
00609   int           mddId;              /* Id of the node being processed */
00610   int           i, flag;
00611   mdd_manager   *mddManager = PartPartitionReadMddManager(partition);
00612   /* nodeToMvfTable maps a node to the mvf in the form that is needed to build
00613      mvfs for the fanouts of the node.  I.e., a cutpoint node is mapped to an
00614      mdd for a new variable. */
00615   st_table *nodeToMvfTable = st_init_table(st_ptrcmp, st_ptrhash);
00616   st_table *leafNodesTable = st_init_table(st_ptrcmp, st_ptrhash);
00617   array_t *rootNodesArray;
00618   Mvf_Function_t *nodeMvf; 
00619   long bddSize;
00620   int sizeThreshold;
00621   lsList topologicalNodeList;
00622   lsGen lsgen;
00623   st_generator *stgen;
00624   char *flagValue =  Cmd_FlagReadByName("partition_threshold");
00625   
00626   if (flagValue == NIL(char)){
00627     sizeThreshold = 1000; /* the default value */
00628   }
00629   else {
00630     sizeThreshold = atoi(flagValue);
00631   }
00632 
00633   /* Put combinational inputs in the leafNodesTable. */
00634   if (leaveList == (lsList)0) {
00635     Ntk_NetworkForEachCombInput(network, gen, node) {
00636       st_insert(leafNodesTable, (char *)node, (char *) (long) (-1) );
00637     }
00638   } /* End of then */ 
00639   else {
00640     lsForEachItem(leaveList, gen, node) {
00641       st_insert(leafNodesTable, (char *)node, (char *) (long) (-1) );
00642     }
00643   } /* End of if-then-else */
00644 
00645   /*
00646    * For each leaf nodes, create a vertex in the partition, create the mvf, and
00647    * a mapping of name to vertex, and mddId to vertex.
00648    * Notices that: if a vertex exists in the partition, use it instead of 
00649    * creating a new one.
00650    */
00651   st_foreach_item(leafNodesTable, stgen, &node, NULL){
00652     mddId = Ntk_NodeReadMddId(node);
00653     name  = Ntk_NodeReadName(node);
00654     assert(mddId != NTK_UNASSIGNED_MDD_ID);
00655     flag = st_lookup(PartPartitionReadNameToVertex(partition), 
00656                      name, &vertex);
00657     if (flag) {
00658       nodeMvf = ((PartVertexInfo_t *)(vertex->user_data))->functionality.mvf;
00659       st_insert(nodeToMvfTable, node, nodeMvf);
00660       /*
00661       name = Ntk_NodeReadName(node);
00662       fprintf(vis_stdout, "warning: node %s already in the partition\n",
00663               name);
00664       */
00665     }else {
00666       vertex = g_add_vertex(partition);
00667       st_insert(PartPartitionReadNameToVertex(partition), name, (char *)vertex);
00668       st_insert(PartPartitionReadMddIdToVertex(partition), (char *)(long)mddId,
00669                 (char *)vertex); 
00670       if (Ntk_NodeTestIsPseudoInput(node)){
00671         nodeMvf = NodeBuildPseudoInputMvf(node);
00672       }else {
00673         nodeMvf = Mvf_FunctionCreateFromVariable(mddManager,mddId);
00674       }
00675       st_insert(nodeToMvfTable, (char *)node, (char *)nodeMvf);
00676       vertex->user_data = (gGeneric)PartVertexInfoCreateSingle(name, nodeMvf,
00677                                                                mddId);
00678     }
00679   }
00680   
00681   /* Take the nodes in rootList as the roots */
00682   if (rootList == (lsList)0) {
00683     rootNodesArray = array_alloc(Ntk_Node_t *, 
00684                                Ntk_NetworkReadNumCombOutputs(network));
00685     i = 0;
00686     Ntk_NetworkForEachCombOutput(network, gen, node) {
00687       name = Ntk_NodeReadName(node);
00688       if ( !st_is_member(PartPartitionReadNameToVertex(partition), name) )
00689         array_insert(Ntk_Node_t *, rootNodesArray, i++, node);
00690     }
00691   } /* End of then */ 
00692   else {
00693     rootNodesArray = array_alloc(Ntk_Node_t *, lsLength(rootList));
00694     i = 0;
00695     lsForEachItem(rootList, gen, node) {
00696       name = Ntk_NodeReadName(node);
00697       if ( !st_is_member(PartPartitionReadNameToVertex(partition), name) )
00698         array_insert(Ntk_Node_t *, rootNodesArray, i++, node);
00699     }
00700   } /* End of if-then-else */
00701 
00702   
00703 
00704   /* Get an array of nodes sorted in topological order */
00705   topologicalNodeList = Ntk_NetworkComputeTopologicalOrder(network,
00706                                                            rootNodesArray,
00707                                                            leafNodesTable);   
00708   
00709   st_free_table(leafNodesTable);
00710   
00711 
00712   /* Go through the topologicalNodeList
00713    * a. If the node is of combinational input type, continue.
00714    *
00715    * b. Otherwise, Build the Mdd for this node, in terms of the function of the
00716    *    fanin nodes in. If the Mdd size exceeds the threshold, create an Mdd ID
00717    *    for this node.
00718    */
00719 
00720   lsForEachItem(topologicalNodeList, lsgen, node){
00721     if (st_is_member(nodeToMvfTable, node)) continue;
00722     name = Ntk_NodeReadName(node);
00723     flag = st_lookup(PartPartitionReadNameToVertex(partition), 
00724                      name, &vertex);
00725     if (flag) {
00726       mddId = Ntk_NodeReadMddId(node);
00727       if (mddId != -1)
00728         st_insert(nodeToMvfTable, node,
00729                   (char *)Mvf_FunctionCreateFromVariable(mddManager,mddId));
00730       else {
00731         nodeMvf = PartVertexReadFunction(vertex);
00732         st_insert(nodeToMvfTable, node, nodeMvf);
00733       }
00734       continue;
00735     }
00736     nodeMvf = NodeBuildMvf(node, nodeToMvfTable);
00737     bddSize = bdd_size_multiple(nodeMvf);
00738     if ((bddSize <= sizeThreshold) &&
00739         (Ntk_NodeTestIsCombOutput(node) == 0)){
00740       st_insert(nodeToMvfTable, (char *)node, (char *)nodeMvf);
00741       continue;
00742     }
00743     /* node either is a primary output, or has an mvf exceeding the
00744        threshold. */
00745     vertex = g_add_vertex(partition);
00746     name  = Ntk_NodeReadName(node);
00747     st_insert(PartPartitionReadNameToVertex(partition), name,
00748               (char *)vertex);
00749     if ((bddSize > sizeThreshold) &&
00750         (Ntk_NodeReadNumFanouts(node) != 0)){
00751       if ((mddId = Ntk_NodeReadMddId(node)) == -1){
00752         Ord_NetworkAssignMddIdForNode(network, node);
00753         mddId = Ntk_NodeReadMddId(node);
00754       }
00755       st_insert(nodeToMvfTable, (char *)node,
00756                 (char *)Mvf_FunctionCreateFromVariable(mddManager,mddId));
00757     }
00758     else {
00759       /* Small mvf, or no fanout */
00760       st_insert(nodeToMvfTable, (char *)node, (char *)nodeMvf);
00761     }
00762     mddId = Ntk_NodeReadMddId(node);
00763     vertex->user_data = (gGeneric)PartVertexInfoCreateSingle(name,
00764                                                              nodeMvf, 
00765                                                              mddId);
00766     if (mddId != -1){
00767       st_insert(PartPartitionReadMddIdToVertex(partition),
00768                 (char *)(long)mddId, (char *)vertex);
00769     }
00770   }/* for each member of topologicalNodeList */
00771   
00772   /*
00773    * Free the Mvfs in nodeToMvfTable not associated with vertices in the
00774    * partition.  The mvfs of inputs are always in the partition; hence,
00775    * their mvfs should always be preserved.  For outputs, we have to free
00776    * the mvf in nodeToMvfTable if the output is also a cutpoint, because in
00777    * this case the mvf in the partition vertex and the one in the
00778    * nodeToMvfTable are different.
00779    */
00780 
00781   lsForEachItem(topologicalNodeList, gen, node){ 
00782     if (!Ntk_NodeTestIsCombInput(node)){
00783       if(!Ntk_NodeTestIsCombOutput(node)){ 
00784         st_lookup(nodeToMvfTable, node, &nodeMvf); 
00785         assert(nodeMvf != NIL(Mvf_Function_t)); 
00786         Mvf_FunctionFree(nodeMvf);
00787       } else {
00788         Mvf_Function_t *vertexMvf;
00789         
00790         name =  Ntk_NodeReadName(node);
00791         vertex = Part_PartitionFindVertexByName(partition, name);
00792         st_lookup(nodeToMvfTable, node, &nodeMvf);
00793         vertexMvf = PartVertexReadFunction(vertex);
00794         assert(nodeMvf != NIL(Mvf_Function_t) &&
00795                vertexMvf != NIL(Mvf_Function_t));
00796         if(vertexMvf != nodeMvf){
00797           Mvf_FunctionFree(nodeMvf);
00798         }
00799       }
00800     }/* not input */
00801   }/* for each node */
00802 
00803   PartitionCreateEdges(partition);
00804   array_free(rootNodesArray);
00805   st_free_table(nodeToMvfTable);
00806   lsDestroy(topologicalNodeList, (void (*)(lsGeneric))0);
00807 }
00808 
00825 void
00826 PartInsertBnvs(
00827   Ntk_Network_t *network,
00828   st_table *coiLatchTable,
00829   st_table *coiBnvTable)
00830 {
00831   mdd_manager    *mddManager = Ntk_NetworkReadMddManager(network);
00832   st_table       *nodeToMvfTable = st_init_table(st_ptrcmp, st_ptrhash);
00833   st_table       *leafNodesTable = st_init_table(st_ptrcmp, st_ptrhash);
00834   lsList         topologicalNodeList;
00835   st_table       *topoNodeTable;
00836   array_t        *rootNodesArray;
00837   Ntk_Node_t     *fanoutNode, *node;
00838   Mvf_Function_t *nodeMvf; 
00839   long           bddSize, sizeThreshold, fanoutNumber, mddId;
00840   int            i;
00841   lsGen          lsgen;
00842   st_generator   *stgen;
00843   char           *flagValue;
00844 
00845   flagValue =  Cmd_FlagReadByName("partition_threshold");
00846   if (flagValue == NIL(char)){
00847     sizeThreshold = 1000; /* the default value */
00848   }
00849   else {
00850     sizeThreshold = atoi(flagValue);
00851   }
00852 
00853   /* Put latch data inputs in the rootNodesArray */
00854   rootNodesArray = array_alloc(Ntk_Node_t *, 0);
00855   st_foreach_item(coiLatchTable, stgen, &node, NULL) {
00856     array_insert_last(Ntk_Node_t *, rootNodesArray, 
00857                       Ntk_LatchReadDataInput(node));
00858     array_insert_last(Ntk_Node_t *, rootNodesArray, 
00859                       Ntk_LatchReadInitialInput(node));
00860   }
00861 
00862   /* Put combinational inputs, as well as the existing coiBnvs, in the
00863    * leafNodesTable. */
00864   Ntk_NetworkForEachCombInput(network, lsgen, node) {
00865     st_insert(leafNodesTable, node, (char *) (long) (-1) );
00866   }
00867   st_foreach_item(coiBnvTable, stgen, &node, NULL) {
00868     st_insert(leafNodesTable, node, (char *) (long) (-1) );
00869   }
00870   
00871   /* Get an array of nodes sorted in topological order */
00872   topologicalNodeList = Ntk_NetworkComputeTopologicalOrder(network,
00873                                                            rootNodesArray,
00874                                                            leafNodesTable);   
00875 
00876   /* For each node, compute the number of fanouts */
00877   topoNodeTable = st_init_table(st_ptrcmp, st_ptrhash);
00878   lsForEachItem(topologicalNodeList, lsgen, node){
00879     st_insert(topoNodeTable, (char *)node, NIL(char));
00880   }
00881   lsForEachItem(topologicalNodeList, lsgen, node){
00882     fanoutNumber = 0;
00883     Ntk_NodeForEachFanout(node, i, fanoutNode) {
00884       if (st_is_member(topoNodeTable, (char *)fanoutNode) &&
00885           !st_is_member(leafNodesTable, (char *)fanoutNode) )
00886         fanoutNumber++;
00887     }
00888     st_insert(topoNodeTable, (char *)node, (char *)fanoutNumber);
00889   }
00890 
00891   /* assign mddIds to latches if necessary */
00892   /* chao: this may be too slow! */
00893   /* chao: this order may not be as good as static_order */
00894   lsForEachItem(topologicalNodeList, lsgen, node){
00895     if (Ntk_NodeTestIsInput(node)) {
00896       Ord_NetworkAssignMddIdForNode(network, node);
00897     }else if (Ntk_NodeTestIsLatch(node)) {
00898       Ord_NetworkAssignMddIdForNode(network, node);
00899       Ord_NetworkAssignMddIdForNode(network, Ntk_NodeReadShadow(node));
00900     }
00901   }
00902   st_foreach_item(coiLatchTable, stgen, &node, NULL) {
00903     Ord_NetworkAssignMddIdForNode(network, node);
00904     Ord_NetworkAssignMddIdForNode(network, Ntk_NodeReadShadow(node));
00905   }
00906 
00907   /* create nodeMvf for leaf nodes */
00908   st_foreach_item(leafNodesTable, stgen, &node, NULL) {
00909     if (!st_lookup(topoNodeTable, node, &fanoutNumber)) {
00910       continue;
00911     }
00912     mddId = Ntk_NodeReadMddId(node);
00913     assert(mddId != NTK_UNASSIGNED_MDD_ID);
00914 
00915     if (Ntk_NodeTestIsPseudoInput(node)){
00916       nodeMvf = NodeBuildPseudoInputMvf(node);
00917     }
00918     else {
00919       nodeMvf = Mvf_FunctionCreateFromVariable(mddManager,mddId);
00920     }
00921 
00922     if (fanoutNumber <= 0) {
00923       Mvf_FunctionFree(nodeMvf);
00924       st_insert(nodeToMvfTable, (char *)node, NIL(char));
00925     }
00926     else
00927       st_insert(nodeToMvfTable, (char *)node, (char *)nodeMvf);
00928   }
00929 
00930   st_free_table(leafNodesTable);
00931 
00932 
00933   /* Go through the topologicalNodeList
00934    * a. If the node is of combinational input type, continue.
00935    *
00936    * b. Otherwise, Build the Mdd for this node, in terms of the function of the
00937    *    fanin nodes in. If the Mdd size exceeds the threshold, create an Mdd ID
00938    *    for this node.
00939    */
00940   lsForEachItem(topologicalNodeList, lsgen, node){
00941     if (st_is_member(nodeToMvfTable, node)) 
00942       continue;
00943 
00944     nodeMvf = NodeBuildMvf2(node, nodeToMvfTable, topoNodeTable);
00945     bddSize = bdd_size_multiple(nodeMvf);
00946     st_lookup(topoNodeTable, node, &fanoutNumber);
00947 
00948     if ((bddSize <= sizeThreshold) && !Ntk_NodeTestIsCombOutput(node)) {
00949       assert(fanoutNumber > 0);
00950       st_insert(nodeToMvfTable, node, nodeMvf);
00951       continue;
00952     }
00953     /* node either is a primary output, or has an mvf exceeding the
00954        threshold. */
00955     if ((bddSize > sizeThreshold) && fanoutNumber > 0) {
00956                                    /*(Ntk_NodeReadNumFanouts(node) != 0)) { */
00957       /* ADD A bnv !!! */
00958       st_insert(coiBnvTable, (char *)node, NIL(char));
00959 
00960       if ((mddId = Ntk_NodeReadMddId(node)) == -1){
00961         Ord_NetworkAssignMddIdForNode(network, node);
00962         mddId = Ntk_NodeReadMddId(node);
00963       }
00964 
00965       st_insert(nodeToMvfTable, (char *)node,
00966                 (char *)Mvf_FunctionCreateFromVariable(mddManager,mddId));
00967       Mvf_FunctionFree(nodeMvf);
00968     }else {
00969       if (fanoutNumber <= 0) {
00970         Mvf_FunctionFree(nodeMvf);
00971         st_insert(nodeToMvfTable, node, NIL(char));
00972       }
00973       else
00974         st_insert(nodeToMvfTable, node, (char *)nodeMvf);
00975     }
00976 
00977   }/* for each member of topologicalNodeList */
00978   
00979   /* sanity check */
00980   st_foreach_item(nodeToMvfTable, stgen, &node, &nodeMvf) {
00981 #if 0
00982     if (nodeMvf != NIL(Mvf_Function_t)) {
00983       st_lookup(topoNodeTable, node, &fanoutNumber);
00984       fprintf(vis_stdout, "\nunclean node = %s, fanout# = %d",
00985               Ntk_NodeReadName(node), fanoutNumber);
00986     }
00987 #else
00988     assert (nodeMvf == NIL(Mvf_Function_t));
00989 #endif
00990   }
00991 
00992   array_free(rootNodesArray);
00993   st_free_table(nodeToMvfTable);
00994   st_free_table(topoNodeTable);
00995   lsDestroy(topologicalNodeList, (void (*)(lsGeneric))0);
00996 }
00997 
01014 void
01015 PartPartitionWithExistingBnvs(
01016   Ntk_Network_t *network,
01017   graph_t *partition,
01018   st_table *coiBnvTable,
01019   st_table *absLatchTable,
01020   st_table *absBnvTable)
01021 {
01022   mdd_manager    *mddManager = PartPartitionReadMddManager(partition);
01023   st_table       *nodeToMvfTable = st_init_table(st_ptrcmp, st_ptrhash);
01024   st_table       *leafNodesTable = st_init_table(st_ptrcmp, st_ptrhash);
01025   array_t        *rootNodesArray, *combNodesArray;
01026   lsList         topologicalNodeList;
01027   st_table       *topoNodeTable;
01028   Ntk_Node_t     *fanoutNode, *node;
01029   Mvf_Function_t *nodeMvf; 
01030   vertex_t       *vertex;         
01031   long           mddId, fanoutNumber;
01032   char           *name;           
01033   lsGen          lsgen;
01034   st_generator   *stgen;
01035   int            i;
01036 
01037   /* Put latch data inputs in the rootNodesArray */
01038   rootNodesArray = array_alloc(Ntk_Node_t *, 0);
01039   st_foreach_item(absLatchTable, stgen, &node, NULL) {
01040     array_insert_last(Ntk_Node_t *, rootNodesArray, 
01041                       Ntk_LatchReadDataInput(node));
01042     array_insert_last(Ntk_Node_t *, rootNodesArray, 
01043                       Ntk_LatchReadInitialInput(node));
01044   }
01045 
01046   /* Put also latch initial inputs in the rootNodesArray */
01047   combNodesArray = Ntk_NodeComputeTransitiveFaninNodes(network,
01048                                                        rootNodesArray,
01049                                                        TRUE, TRUE);
01050   arrayForEachItem(Ntk_Node_t *, combNodesArray, i, node) {
01051     if ( Ntk_NodeTestIsLatch(node) && 
01052          !st_is_member(absLatchTable, (char *)node) )
01053       array_insert_last(Ntk_Node_t *, rootNodesArray, 
01054                         Ntk_LatchReadInitialInput(node));
01055   }
01056   array_free(combNodesArray);
01057 
01058 
01059   /* Put combinational inputs in the leafNodesTable. */
01060   Ntk_NetworkForEachCombInput(network, lsgen, node) {
01061     st_insert(leafNodesTable, (char *)node, (char *) (long) (-1) );
01062   }
01063   /* Put BNVs that are not in absBnvTable in the leafNodesTable */
01064   st_foreach_item(coiBnvTable, stgen, &node, NULL) {
01065     if (!st_is_member(absBnvTable, (char *)node))
01066       st_insert(leafNodesTable, node, (char *) (long) (-1) );
01067   }
01068 
01069   /* Get an array of nodes sorted in topological order  */
01070   topologicalNodeList = Ntk_NetworkComputeTopologicalOrder(network,
01071                                                            rootNodesArray,
01072                                                            leafNodesTable);
01073 
01074   /* For each node, compute the number of fanouts */
01075   topoNodeTable = st_init_table(st_ptrcmp, st_ptrhash);
01076   lsForEachItem(topologicalNodeList, lsgen, node){
01077     st_insert(topoNodeTable, (char *)node, NIL(char));
01078   }
01079   lsForEachItem(topologicalNodeList, lsgen, node){
01080     fanoutNumber = 0;
01081     Ntk_NodeForEachFanout(node, i, fanoutNode) {
01082       if (st_is_member(topoNodeTable, (char *)fanoutNode) &&
01083           !st_is_member(leafNodesTable, (char *)fanoutNode))
01084         fanoutNumber++;
01085     }
01086     st_insert(topoNodeTable, (char *)node, (char *)fanoutNumber);
01087    }
01088 
01089   /* Create partition vertices for the leaves 
01090    */
01091   st_foreach_item(leafNodesTable, stgen, &node, NULL){
01092     if (!st_lookup(topoNodeTable, node, &fanoutNumber))
01093       continue;
01094     mddId = Ntk_NodeReadMddId(node);
01095     if (mddId == NTK_UNASSIGNED_MDD_ID) {
01096         /* it is a input sign under the fanin cone of the initialInput
01097          * of some invisible latches */
01098         assert(Ntk_NodeTestIsInput(node));
01099         Ord_NetworkAssignMddIdForNode(network, node);
01100         mddId = Ntk_NodeReadMddId(node);
01101     }
01102     /*assert(mddId != NTK_UNASSIGNED_MDD_ID);*/
01103     vertex = g_add_vertex(partition);
01104     name  = Ntk_NodeReadName(node);
01105     st_insert(PartPartitionReadNameToVertex(partition), name, (char *)vertex);
01106     st_insert(PartPartitionReadMddIdToVertex(partition), (char *)(long)mddId,
01107               (char *)vertex); 
01108     if (Ntk_NodeTestIsPseudoInput(node)){
01109       nodeMvf = NodeBuildPseudoInputMvf(node);
01110     }
01111     else {
01112       nodeMvf = Mvf_FunctionCreateFromVariable(mddManager,mddId);
01113     }
01114 
01115     if (fanoutNumber <= 0) 
01116       st_insert(nodeToMvfTable, (char *)node, NIL(char));
01117     else
01118       st_insert(nodeToMvfTable, (char *)node, 
01119                 (char *)Mvf_FunctionDuplicate(nodeMvf));
01120 
01121     vertex->user_data = (gGeneric)PartVertexInfoCreateSingle(name, nodeMvf,
01122                                                              mddId);
01123   }
01124 
01125   /* Go through the topologicalNodeList, and build Mdds for nodes in
01126    * the absBnvTable
01127    */
01128   lsForEachItem(topologicalNodeList, lsgen, node){
01129     if (st_is_member(nodeToMvfTable, (char *)node)) continue;
01130 
01131     nodeMvf = NodeBuildMvf2(node, nodeToMvfTable, topoNodeTable);
01132 
01133     if ( !st_is_member(absBnvTable,(char *)node) && 
01134          !Ntk_NodeTestIsCombOutput(node)) {
01135       st_insert(nodeToMvfTable, (char *)node, (char *)nodeMvf);
01136       continue;  
01137     }
01138     
01139     /* node is either a primary output, or a boolean network var */
01140     vertex = g_add_vertex(partition);
01141     name  = Ntk_NodeReadName(node);
01142     st_insert(PartPartitionReadNameToVertex(partition), name, (char *)vertex);
01143 
01144     if (st_is_member(absBnvTable,node)) {
01145       /* ADD a bnv !!! */
01146       mddId = Ntk_NodeReadMddId(node);
01147       assert(mddId != -1);
01148       st_insert(nodeToMvfTable, node,
01149                 (char *)Mvf_FunctionCreateFromVariable(mddManager,mddId));
01150     }else {
01151       st_lookup(topoNodeTable, node, &fanoutNumber);
01152       if (fanoutNumber <= 0) 
01153         st_insert(nodeToMvfTable, node, NIL(char));
01154       else
01155         st_insert(nodeToMvfTable, node, 
01156                   (char *)Mvf_FunctionDuplicate(nodeMvf));
01157     }
01158 
01159     mddId = Ntk_NodeReadMddId(node);
01160     vertex->user_data = (gGeneric)PartVertexInfoCreateSingle(name, nodeMvf, 
01161                                                              mddId);
01162     if (mddId != -1){
01163       st_insert(PartPartitionReadMddIdToVertex(partition),
01164                 (char *)(long)mddId, (char *)vertex);
01165     }
01166   }/* for each member of topologicalNodeList */
01167 
01168   /* sanity check */
01169   st_foreach_item(nodeToMvfTable, stgen, &node, &nodeMvf) {
01170 #if 1
01171     if (nodeMvf != NIL(Mvf_Function_t)) {
01172       st_lookup(topoNodeTable, node, &fanoutNumber);
01173       fprintf(vis_stdout, "\nunclean node = %s, fanout# = %ld",
01174               Ntk_NodeReadName(node), fanoutNumber);
01175     }
01176 #else
01177     assert(nodeMvf == NIL(Mvf_Function_t));
01178 #endif
01179   }
01180 
01181   PartitionCreateEdges(partition);
01182   array_free(rootNodesArray);
01183   st_free_table(nodeToMvfTable);
01184   st_free_table(topoNodeTable);
01185   st_free_table(leafNodesTable);
01186   lsDestroy(topologicalNodeList, (void (*)(lsGeneric))0);
01187 }
01188 
01189 
01199 void
01200 PartPrintPartition(graph_t *partition)
01201 {
01202   vertex_t *vertex;
01203   lsList vertexList = g_get_vertices(partition);
01204   lsGen gen;
01205   st_table *vertexTable = st_init_table(st_ptrcmp, st_ptrhash);
01206   fprintf(vis_stdout,"******* Printing Partition *********\n");
01207   lsForEachItem(vertexList, gen, vertex){
01208     PrintPartitionRecursively(vertex,vertexTable,0);
01209   }
01210   fprintf(vis_stdout,"******* End Printing Partition *********\n");
01211   st_free_table(vertexTable);
01212 }
01213 
01214   
01215 /*---------------------------------------------------------------------------*/
01216 /* Definition of static functions                                            */
01217 /*---------------------------------------------------------------------------*/
01218 
01232 static void
01233 PartitionCreateEdges(graph_t *partition)
01234 {
01235   lsList vertexList;
01236   lsGen gen;
01237   vertex_t *toVertex;
01238   edge_t *edge;
01239 
01240   /* this will be executed only when used inside PartitionUpdateFrontier */
01241   foreach_edge(partition, gen, edge) {
01242     g_delete_edge(edge, (void(*)(gGeneric))0);
01243   }
01244 
01245   vertexList = g_get_vertices(partition);
01246 
01247   lsForEachItem(vertexList, gen, toVertex) {
01248     st_table     *mddSupport; /* To store the support of the Mvf_Function */
01249     st_generator *stGen;      /* To iterate over the MddIds of the support */
01250     vertex_t     *fromVertex; /* Will hold the current vertex in the support */
01251     Mvf_Function_t *mddFunction;
01252     long          mddId;
01253     
01254     mddFunction = PartVertexReadFunction(toVertex);
01255     mddSupport = PartCreateFunctionSupportTable(mddFunction);
01256     st_foreach_item(mddSupport, stGen, &mddId, NULL) {
01257       st_lookup(PartPartitionReadMddIdToVertex(partition), (char *) mddId,
01258                 &fromVertex);  
01259       /* 
01260        * Add the edge to the graph. Make sure a self loop is not added. The
01261        * self loop may be produced by a mdd that has in its support the same
01262        * variables that represent the mddId of the node.
01263        */
01264       if (fromVertex != toVertex) {
01265         g_add_edge(fromVertex, toVertex);
01266       }
01267     }
01268     st_free_table(mddSupport);
01269   } 
01270 }
01271 
01285 static Mvf_Function_t *
01286 NodeBuildMvf(Ntk_Node_t * node, st_table * nodeToMvfTable)
01287 {
01288   int i;
01289   Mvf_Function_t *resultMvf;
01290   Ntk_Node_t *faninNode;
01291   array_t *faninMvfs = array_alloc(Mvf_Function_t *,
01292                                             Ntk_NodeReadNumFanins(node));
01293   mdd_manager *mddMgr = Ntk_NetworkReadMddManager(Ntk_NodeReadNetwork(node)); 
01294   int columnIndex = Ntk_NodeReadOutputIndex(node);
01295   Tbl_Table_t *table = Ntk_NodeReadTable(node);
01296   
01297   Ntk_NodeForEachFanin(node, i, faninNode) {
01298     Mvf_Function_t *tmpMvf;
01299     st_lookup(nodeToMvfTable, faninNode, &tmpMvf); 
01300     assert(tmpMvf);
01301     array_insert(Mvf_Function_t *, faninMvfs, i, tmpMvf);
01302   }
01303   
01304   resultMvf = Tbl_TableBuildMvfFromFanins(table, columnIndex,
01305                                           faninMvfs, mddMgr);    
01306   
01307   /* Don't free the MVFs themselves, but just free the array. */
01308   array_free(faninMvfs);
01309   return resultMvf;
01310 }
01311     
01326 static Mvf_Function_t *
01327 NodeBuildMvf2(
01328   Ntk_Node_t * node, 
01329   st_table * nodeToMvfTable,
01330   st_table * faninNumberTable)
01331 {
01332   long faninNumber;
01333   int i;
01334   Mvf_Function_t *resultMvf;
01335   Ntk_Node_t *faninNode;
01336   array_t *faninMvfs = array_alloc(Mvf_Function_t *,
01337                                    Ntk_NodeReadNumFanins(node));
01338   mdd_manager *mddMgr = Ntk_NetworkReadMddManager(Ntk_NodeReadNetwork(node)); 
01339   int columnIndex = Ntk_NodeReadOutputIndex(node);
01340   Tbl_Table_t *table = Ntk_NodeReadTable(node);
01341   
01342   Ntk_NodeForEachFanin(node, i, faninNode) {
01343     Mvf_Function_t *tmpMvf;
01344     st_lookup(nodeToMvfTable, faninNode, &tmpMvf); 
01345     assert(tmpMvf);
01346     array_insert(Mvf_Function_t *, faninMvfs, i, tmpMvf);
01347   }
01348   
01349   resultMvf = Tbl_TableBuildMvfFromFanins(table, columnIndex,
01350                                           faninMvfs, mddMgr);    
01351   
01352   /* Don't free the MVFs themselves, but just free the array. */
01353   array_free(faninMvfs);
01354 
01355   /* if the fanin node is no longer useful, remove its Mvfs */
01356   Ntk_NodeForEachFanin(node, i, faninNode) {
01357     st_lookup(faninNumberTable, faninNode, &faninNumber);
01358     assert(faninNumber > 0);
01359     faninNumber--;
01360     st_insert(faninNumberTable, faninNode, (char *)faninNumber);
01361 
01362     if (faninNumber <= 0) {
01363       Mvf_Function_t *tmpMvf;
01364       st_lookup(nodeToMvfTable, faninNode, &tmpMvf); 
01365       Mvf_FunctionFree(tmpMvf);
01366       st_insert(nodeToMvfTable, faninNode, NIL(char));
01367     }
01368   }
01369 
01370   return resultMvf;
01371 }
01372     
01373       
01374 
01394 static Mvf_Function_t *
01395 NodeBuildPseudoInputMvf(
01396   Ntk_Node_t * node)
01397 {
01398   mdd_manager  *mddMgr = Ntk_NetworkReadMddManager(Ntk_NodeReadNetwork(node));
01399   int          mddId = Ntk_NodeReadMddId( node );
01400   int          columnIndex = Ntk_NodeReadOutputIndex( node );
01401   Tbl_Table_t  *table = Ntk_NodeReadTable( node );
01402   Mvf_Function_t *mvf = Tbl_TableBuildNonDetConstantMvf(table, columnIndex,
01403                                                         mddId, mddMgr);
01404 
01405   mdd_t *vMdd, *tMdd, *rMdd;
01406   int lIndex, needProcess, i;
01407 
01408   rMdd = mdd_zero(mddMgr);
01409   needProcess = 0;
01410   lIndex = 0;
01411   for(i=0; i<mvf->num; i++) {
01412     vMdd = array_fetch(mdd_t *, mvf, i);
01413     if(mdd_equal(vMdd, rMdd)) {
01414       needProcess = 1;
01415     }
01416     else {
01417       lIndex = i;
01418     }
01419   }
01420   if(needProcess) {
01421     for(i=0; i<lIndex; i++) {
01422       vMdd = array_fetch(mdd_t *, mvf, i);
01423       tMdd = mdd_or(vMdd, rMdd, 1, 1);
01424       mdd_free(rMdd);
01425       rMdd = tMdd;
01426     }
01427     vMdd = array_fetch(mdd_t *, mvf, lIndex);
01428     mdd_free(vMdd);
01429     tMdd = mdd_not(rMdd);
01430     mdd_free(rMdd);
01431     array_insert(mdd_t *, mvf, lIndex, tMdd);
01432   }
01433   else {
01434     mdd_free(rMdd);
01435   }
01436 
01437   return mvf;
01438 }
01439 
01440 
01450 static void
01451 PrintPartitionRecursively(vertex_t *vertex, st_table *vertexTable, int
01452                           indent)
01453 {
01454   int i;
01455   lsList faninEdges;
01456   lsGen gen;
01457   vertex_t *faninVertex;
01458   edge_t *faninEdge;
01459   
01460   if (st_is_member(vertexTable, (char *)vertex)) return;
01461   st_insert(vertexTable, (char *)vertex, NIL(char));
01462   for(i=0; i<= indent; i++) fprintf(vis_stdout," ");
01463   fprintf(vis_stdout,"%s %d\n", Part_VertexReadName(vertex),
01464           Part_VertexReadMddId(vertex)); 
01465   faninEdges = g_get_in_edges(vertex);
01466   if (lsLength(faninEdges) == 0) return;
01467   lsForEachItem(faninEdges, gen, faninEdge){
01468     faninVertex = g_e_source(faninEdge);
01469     PrintPartitionRecursively(faninVertex, vertexTable,indent+2);
01470   }
01471 }
01472