VIS

src/part/partPart.c

Go to the documentation of this file.
00001 
00020 #include "partInt.h"
00021 
00022 static char rcsid[] UNUSED = "$Id: partPart.c,v 1.45 2009/04/11 01:47:18 fabio Exp $";
00023 
00026 /*---------------------------------------------------------------------------*/
00027 /* Static function prototypes                                                */
00028 /*---------------------------------------------------------------------------*/
00029 
00030 static void PrintVertexDescription(FILE *fp, vertex_t *vertexPtr, int order);
00031 
00034 /*---------------------------------------------------------------------------*/
00035 /* Definition of exported functions                                          */
00036 /*---------------------------------------------------------------------------*/
00037 
00048 void
00049 Part_PartitionFree(
00050    graph_t *partition)
00051 {
00052   /* Delete the graph information */
00053   g_free(partition, PartPartitionInfoFree, PartVertexInfoFree,
00054          (void (*)(gGeneric))0);
00055 } /* End of Part_PartitionFree */
00056 
00057 
00072 void
00073 Part_PartitionFreeCallback(
00074    void *data)
00075 {
00076   Part_PartitionFree((graph_t *) data);
00077 } /* End of Part_PartitionFreeCallback */
00078 
00092 vertex_t *
00093 Part_PartitionFindVertexByName(
00094   graph_t *partition,
00095   char *name)
00096 {
00097   vertex_t *result = NIL(vertex_t);
00098   st_table *table = PartPartitionReadNameToVertex(partition);
00099 
00100   if (table != NIL(st_table)) {
00101     st_lookup(table, name, &result);
00102   } /* End of if */
00103 
00104   return result;
00105 } /* End of Part_PartitionFindVertexByName */
00106 
00120 vertex_t *
00121 Part_PartitionFindVertexByMddId(
00122   graph_t *partition,
00123   int mddId)
00124 {
00125   vertex_t *result = NIL(vertex_t);
00126   st_table *table = PartPartitionReadMddIdToVertex(partition);
00127 
00128   if (table != NIL(st_table)) {
00129     st_lookup(table, (char *)(long)mddId, &result);
00130   } /* End of if */
00131 
00132   return result;
00133 } /* End of Part_PartitionFindVertexByMddId */
00134 
00145 char *
00146 Part_PartitionReadName(
00147    graph_t *partition)
00148 {
00149   return PartPartitionReadName(partition);
00150 } /* End of Part_PartitionReadName */
00151 
00161 Part_PartitionMethod
00162 Part_PartitionReadMethod(
00163   graph_t *partition)
00164 {
00165   Part_PartitionMethod  method;
00166 
00167   method = PartPartitionReadMethod(partition);
00168   if (method == Part_Default_c)
00169     method = Part_Frontier_c;
00170   return(method);
00171 } /* End of Part_PartitionReadMethod */
00172 
00187 char *
00188 Part_PartitionObtainMethodAsString(
00189   graph_t *partition)
00190 {
00191   char *resultString;
00192 
00193   assert(partition != NIL(graph_t));
00194 
00195   switch(PartPartitionReadMethod(partition)) {
00196     case Part_Total_c:
00197       resultString = util_strsav("Total");
00198       break;
00199     case Part_Partial_c:
00200       resultString = util_strsav("Partial");
00201       break;
00202     case Part_InOut_c:
00203       resultString = util_strsav("Inputs-Outputs");
00204       break;
00205     case Part_Frontier_c:
00206     case Part_Default_c:
00207       resultString = util_strsav("Frontier");
00208       break;
00209     case Part_Boundary_c:
00210       resultString = util_strsav("Boundary");
00211       break;
00212     case Part_Fine_c:
00213       resultString = util_strsav("Fine");
00214       break;
00215     default:
00216       fail("Unexpected Partition method.");
00217   }
00218 
00219   return resultString;
00220 } /* End of Part_PartitionObtainMethodAsString */
00221 
00231 mdd_manager *
00232 Part_PartitionReadMddManager(
00233   graph_t *partition)
00234 {
00235   return PartPartitionReadMddManager(partition);
00236 } /* End of Part_PartitionReadMddManager */
00237 
00247 Part_VertexType
00248 Part_VertexReadType(
00249   vertex_t *vertexPtr)
00250 {
00251   return PartVertexReadType(vertexPtr);
00252 } /* End of Part_VertexReadType */
00253 
00263 char *
00264 Part_VertexReadName(
00265   vertex_t *vertexPtr)
00266 {
00267   return PartVertexReadName(vertexPtr);
00268 } /* End of Part_VertexReadName */
00269 
00282 array_t *
00283 Part_VertexReadClusterMembers(
00284   vertex_t *vertexPtr)
00285 {
00286   return PartVertexReadClusterMembers(vertexPtr);
00287 } /* End of Part_VertexReadClusterMembers */
00288 
00301 Mvf_Function_t *
00302 Part_VertexReadFunction(
00303   vertex_t *vertexPtr)
00304 {
00305     return PartVertexReadFunction(vertexPtr);
00306 } /* End of Part_VertexReadFunction */
00307 
00308 
00318 void
00319 Part_VertexSetFunction(
00320   vertex_t *vertexPtr,
00321   Mvf_Function_t *mvf)
00322 {
00323   assert(PartVertexReadType(vertexPtr) != Part_VertexCluster_c);
00324 
00325   PartVertexSetFunction(vertexPtr, mvf);
00326 } /* End of Part_VertexSetFunction */
00327 
00328 
00338 int
00339 Part_VertexReadMddId(
00340   vertex_t *vertexPtr)
00341 {
00342     return PartVertexReadMddId(vertexPtr);
00343 } /* End of Part_VertexReadMddId */
00344 
00354 boolean
00355 Part_VertexTestIsClustered(
00356   vertex_t *vertexPtr)
00357 {
00358   return PartVertexTestIsClustered(vertexPtr);
00359 } /* End of Part_VertexTestIsClustered */
00360 
00398 graph_t *
00399 Part_NetworkCreatePartition(
00400   Ntk_Network_t *network,
00401   Hrc_Node_t *hnode,
00402   char *name,
00403   lsList rootList,
00404   lsList leaveList,
00405   mdd_t *careSet,
00406   Part_PartitionMethod method,
00407   lsList nodes,
00408   boolean inTermsOfLeaves,
00409   int verbose,
00410   int sanityCheck)
00411 {
00412   graph_t    *partition;
00413   long       lap = 0;
00414 
00415   if (verbose) {
00416     lap = util_cpu_time();
00417   } /* End of if */
00418 
00419   /* Create the new graph to represent the partition */
00420   partition = g_alloc();
00421   partition->user_data =
00422     (gGeneric)PartPartitionInfoCreate(name,
00423                                       Ntk_NetworkReadMddManager(network),
00424                                       method);
00425 
00426   switch (method) {
00427     case Part_Partial_c:
00428       if (verbose) {
00429         (void) fprintf(vis_stdout, "Partitioning the system by the Partial");
00430         (void) fprintf(vis_stdout, " method\n");
00431       } /* End of if */
00432       PartPartitionPartial(network, partition, rootList, leaveList, careSet,
00433                            nodes, inTermsOfLeaves);
00434       break;
00435     case Part_Boundary_c:
00436       if (verbose) {
00437         (void) fprintf(vis_stdout, "Partitioning the system by the Boundary");
00438         (void) fprintf(vis_stdout, " method\n");
00439       } /* End of if */
00440       PartPartitionBoundary(network, hnode, partition, rootList, leaveList, careSet,
00441                            inTermsOfLeaves);
00442       break;
00443     case Part_Total_c:
00444       if (verbose) {
00445         (void) fprintf(vis_stdout, "Partitioning the circuit by the Total");
00446         (void) fprintf(vis_stdout, " method\n");
00447       } /* End of if */
00448       PartPartitionTotal(network, partition, rootList, leaveList, careSet,
00449                          inTermsOfLeaves);
00450       break;
00451     case Part_Frontier_c:
00452     case Part_Default_c:
00453       if (verbose) {
00454         (void) fprintf(vis_stdout, "Partitioning the circuit by the Frontier");
00455         (void) fprintf(vis_stdout, " method\n");
00456       } /* End of if */
00457       PartPartitionFrontier(network, partition, rootList, leaveList, careSet);
00458       break;
00459     case Part_Fine_c:
00460       if (verbose) {
00461         (void) fprintf(vis_stdout, "Partitioning the circuit for the fine-grain");
00462         (void) fprintf(vis_stdout, " method\n");
00463       } /* End of if */
00464       PartPartitionFineGrain(network, partition, careSet);
00465       break;
00466     case Part_InOut_c:
00467       if (verbose) {
00468         (void) fprintf(vis_stdout, "Partitioning the circuit by the");
00469         (void) fprintf(vis_stdout, " Input-Output method\n");
00470       } /* End of if */
00471       PartPartitionInputsOutputs(network, partition, rootList,
00472                                  leaveList, careSet);
00473       break;
00474     default:
00475       (void) fprintf(vis_stdout, "Partition method not implemented yet\n");
00476       break;
00477   }
00478 
00479   if (sanityCheck >0) {
00480     PartPartitionSanityCheck(partition, sanityCheck);
00481   }
00482 
00483   if (verbose) {
00484     (void) fprintf(vis_stdout, "%.2f (secs) spent in partitioning.\n",
00485                    (util_cpu_time() - lap)/1000.0);
00486   } /* End of if */
00487 
00488   return partition;
00489 } /* End of Part_NetworkCreatePartition */
00490 
00500 graph_t *
00501 Part_PartitionDuplicate(
00502   graph_t *partition)
00503 {
00504   graph_t          *result;
00505   lsGen            gen;
00506   vertex_t         *fromVertex;
00507   vertex_t         *toVertex;
00508   edge_t           *edgePtr;
00509 
00510   result = g_alloc();
00511   result->user_data =
00512     (gGeneric)PartPartitionInfoCreate(PartPartitionReadName(partition),
00513                                       PartPartitionReadMddManager(partition),
00514                                       PartPartitionReadMethod(partition));
00515   foreach_vertex(partition, gen, fromVertex) {
00516     char *name;
00517     int  mddId;
00518 
00519     name = PartVertexReadName(fromVertex);
00520     mddId = PartVertexReadMddId(fromVertex);
00521     toVertex = g_add_vertex(result);
00522 
00523     st_insert(PartPartitionReadNameToVertex(result), name, (char *)toVertex);
00524 
00525     if (mddId != NTK_UNASSIGNED_MDD_ID) {
00526       st_insert(PartPartitionReadMddIdToVertex(result), (char *)(long)mddId,
00527                 (char *)toVertex);
00528     } /* End of if */
00529 
00530     if (PartVertexReadType(fromVertex) == Part_VertexSingle_c) {
00531       Mvf_Function_t *mdd;
00532 
00533       mdd = Mvf_FunctionDuplicate(PartVertexReadFunction(fromVertex));
00534       toVertex->user_data = (gGeneric)PartVertexInfoCreateSingle(name, mdd,
00535                                                                  mddId);
00536     }
00537     if (PartVertexReadType(fromVertex) == Part_VertexCluster_c) {
00538       toVertex->user_data =
00539         (gGeneric)PartVertexInfoCreateCluster(name, Part_VertexReadClusterMembers(fromVertex));
00540     }
00541   }
00542 
00543   foreach_edge(partition, gen, edgePtr) {
00544     vertex_t *fromVertexCopy;
00545     vertex_t *toVertexCopy;
00546 
00547     fromVertex = g_e_source(edgePtr);
00548     toVertex = g_e_dest(edgePtr);
00549 
00550     st_lookup(PartPartitionReadNameToVertex(result),
00551               PartVertexReadName(fromVertex), &fromVertexCopy);
00552     st_lookup(PartPartitionReadNameToVertex(result),
00553               PartVertexReadName(toVertex), &toVertexCopy);
00554 
00555     g_add_edge(fromVertexCopy, toVertexCopy);
00556   }
00557 
00558   return result;
00559 } /* End of Part_PartitionDuplicate */
00560 
00561 
00574 graph_t *
00575 Part_PartCreatePartitionWithCTL(
00576   Hrc_Manager_t **hmgr,
00577   Part_PartitionMethod method,
00578   int verbose,
00579   int sanityCheck,
00580   boolean inTermsOfLeaves,
00581   array_t *ctlArray,
00582   array_t *fairArray)
00583 {
00584   return Part_PartCreatePartitionWithCtlAndLtl(hmgr, method, verbose,
00585                                                sanityCheck, inTermsOfLeaves,
00586                                                ctlArray, NIL(array_t),
00587                                                fairArray);
00588 }
00589 
00602 graph_t *
00603 Part_PartCreatePartitionWithCtlAndLtl(
00604   Hrc_Manager_t **hmgr,
00605   Part_PartitionMethod method,
00606   int verbose,
00607   int sanityCheck,
00608   boolean inTermsOfLeaves,
00609   array_t *ctlArray,
00610   array_t *ltlArray,
00611   array_t *fairArray)
00612 {
00613   char          *modelName;
00614   Hrc_Node_t    *currentNode;
00615   graph_t       *partition;
00616   lsList        latchInputList;
00617   lsGen         gen;
00618   Ntk_Node_t    *node;
00619   Ntk_Network_t *network = Ntk_HrcManagerReadCurrentNetwork(*hmgr);
00620 
00621   latchInputList = lsCreate();
00622   currentNode = Hrc_ManagerReadCurrentNode(*hmgr);
00623   modelName = Hrc_NodeReadModelName(currentNode);
00624 
00625   if (method != Part_InOut_c){
00626     return NIL(graph_t);
00627   }
00628 
00629   PartGetLatchInputListFromCtlAndLtl(network, ctlArray, ltlArray, fairArray,
00630                                      latchInputList, FALSE);
00631 
00632   Ntk_NetworkForEachCombOutput(network, gen, node){
00633     if (Ntk_NodeTestIsLatchInitialInput(node)){
00634       lsNewEnd(latchInputList, (lsGeneric)node, LS_NH);
00635     }
00636   }
00637 
00638   /*
00639    * Execute the partition algorithm. If rootList and leaveList are null,
00640    * graph includes all network nodes
00641    */
00642   partition = Part_NetworkCreatePartition(network, currentNode, modelName,
00643                  latchInputList, (lsList)0, NIL(mdd_t), method, (lsList)0,
00644                  inTermsOfLeaves, verbose, sanityCheck);
00645 
00646   lsDestroy(latchInputList, (void (*)(lsGeneric))0);
00647   return partition;
00648 }
00649 
00650 
00663 int
00664 Part_PartitionChangeRoots(
00665   Ntk_Network_t *network,
00666   graph_t *partition,
00667   lsList  rootList,
00668   int verbosity)
00669 {
00670   if (Part_PartitionReadMethod(partition) != Part_InOut_c){
00671     return 0;
00672   }
00673 
00674   return
00675    PartPartitionInOutChangeRoots(network, partition, rootList, verbosity);
00676 }
00677 
00678 
00688 graph_t *
00689 Part_NetworkReadPartition(
00690   Ntk_Network_t *network)
00691 {
00692   return (graph_t *)Ntk_NetworkReadApplInfo(network, PART_NETWORK_APPL_KEY);
00693 } /* End of Part_NetworkReadPartition */
00694 
00695 
00705 vertex_t *
00706 Part_PartitionCreateClusterVertex(
00707   graph_t *partition,
00708   char *name,
00709   array_t *arrayOfVertices)
00710 {
00711   vertex_t *newVertex;
00712 
00713   newVertex = g_add_vertex(partition);
00714   newVertex->user_data = (gGeneric)PartVertexInfoCreateCluster(name,
00715                                                                arrayOfVertices);
00716 
00717   return(newVertex);
00718 
00719 } /* End of Part_PartitionCreateClusterVertex */
00720 
00737 void
00738 Part_UpdatePartitionFrontier(
00739   Ntk_Network_t *network,
00740   graph_t *partition,
00741   lsList  rootList,
00742   lsList  leaveList,
00743   mdd_t   *careSet)
00744 {
00745   PartUpdateFrontier(network, partition, rootList, leaveList, careSet);
00746 }
00747 
00757 void
00758 Part_VertexInfoFreeCluster(
00759   vertex_t *vertexPtr)
00760 {
00761   if (PartVertexReadType(vertexPtr) == Part_VertexCluster_c) {
00762     g_delete_vertex(vertexPtr, PartVertexInfoFree, (void (*)(gGeneric))0);
00763   } /* End of then */
00764   else {
00765     (void) fprintf(vis_stderr, "Warning -- Inconsistent vertex deletion in");
00766     (void) fprintf(vis_stderr, " partition package\n");
00767   }
00768 } /* End of Part_VertexInfoFreeCluster */
00769 
00784 boolean
00785 Part_PartitionTestCompletelySp(
00786   graph_t *partition,
00787   array_t *roots,
00788   st_table *leaves)
00789 {
00790   array_t *mvfFunctions;
00791   vertex_t *vertexPtr;
00792   Mvf_Function_t *functionPtr;
00793   boolean result = TRUE;
00794   int i;
00795   char *vertexName;
00796 
00797   mvfFunctions = Part_PartitionCollapse(partition, roots, leaves, NIL(mdd_t));
00798 
00799   arrayForEachItem(Mvf_Function_t *, mvfFunctions, i, functionPtr) {
00800     vertexPtr = array_fetch(vertex_t *, roots, i);
00801     vertexName = PartVertexReadName(vertexPtr);
00802     if (!Mvf_FunctionTestIsCompletelySpecified(functionPtr)) {
00803       error_append("Vertex ");
00804       error_append(vertexName);
00805       error_append(" is not completely specified\n");
00806       result = FALSE;
00807     } /* End of if */
00808 
00809     /* We don't need the Mvf_Function any more, so we delete it */
00810     Mvf_FunctionFree(functionPtr);
00811   }
00812 
00813   /* Clean up*/
00814   array_free(mvfFunctions);
00815 
00816   return result;
00817 } /* End of Part_PartitionTestCompletelySp */
00818 
00833 boolean
00834 Part_PartitionTestDeterministic(
00835   graph_t *partition,
00836   array_t *roots,
00837   st_table *leaves)
00838 {
00839   array_t *mvfFunctions;
00840   vertex_t *vertexPtr;
00841   Mvf_Function_t *functionPtr;
00842   boolean result = TRUE;
00843   int i;
00844   char *vertexName;
00845 
00846   mvfFunctions = Part_PartitionCollapse(partition, roots, leaves, NIL(mdd_t));
00847 
00848   arrayForEachItem(Mvf_Function_t *, mvfFunctions, i, functionPtr) {
00849     vertexPtr = array_fetch(vertex_t *, roots, i);
00850     vertexName = PartVertexReadName(vertexPtr);
00851     if (!Mvf_FunctionTestIsDeterministic(functionPtr)) {
00852       error_append("Vertex ");
00853       error_append(vertexName);
00854       error_append(" is non-deterministic\n");
00855       result = FALSE;
00856     } /* End of if */
00857 
00858     /* We don't need the Mvf_Function any more, so we delete it */
00859     Mvf_FunctionFree(functionPtr);
00860   }
00861 
00862   /* Clean up*/
00863   array_free(mvfFunctions);
00864 
00865   return result;
00866 } /* End of Part_PartitionTestDeterministic */
00867 
00880 int
00881 Part_PartitionGetLatchInputListFromCTL(
00882   Ntk_Network_t *network,
00883   array_t *ctlArray,
00884   array_t *fairArray,
00885   lsList  latchInputList)
00886 {
00887   return PartGetLatchInputListFromCTL( network, ctlArray, fairArray,
00888                                        latchInputList);
00889 }
00890 
00903 int
00904 Part_PartitionGetLatchInputListFromCtlAndLtl(
00905   Ntk_Network_t *network,
00906   array_t *ctlArray,
00907   array_t *ltlArray,
00908   array_t *fairArray,
00909   lsList  latchInputList,
00910   boolean stopAtLatch)
00911 {
00912   return PartGetLatchInputListFromCtlAndLtl( network, ctlArray, ltlArray,
00913                                              fairArray,
00914                                              latchInputList, stopAtLatch);
00915 }
00916 
00929 void
00930 Part_PartitionPrintStats(
00931   FILE *fp,
00932   graph_t *partition,
00933   boolean printNodeNames)
00934 {
00935   lsList vertexList = g_get_vertices(partition);
00936   vertex_t *vertexPtr;
00937   array_t *functions;
00938   Mvf_Function_t* vertexFunction;
00939   mdd_t *mddPtr;
00940   lsGen gen;
00941   char *methodName;
00942   int numVertices = lsLength(vertexList);
00943   int numSources;
00944   int numSinks;
00945   int i;
00946 
00947   /* Obtain the method name as a string */
00948   methodName = Part_PartitionObtainMethodAsString(partition);
00949 
00950   /*
00951    * Count the number of sources and sinks and at the same time store all the
00952    * bdd_t of every vertex in a common array to compute the shared size.
00953    */
00954   numSources = 0;
00955   numSinks = 0;
00956   functions = array_alloc(mdd_t *, 0);
00957   if (printNodeNames) {
00958     (void) fprintf(fp, "Network nodes represented as vertices in the ");
00959     (void) fprintf(fp, "partition:\n");
00960   }
00961   foreach_vertex(partition, gen, vertexPtr) {
00962     if (lsLength(g_get_in_edges(vertexPtr)) == 0) {
00963       numSources++;
00964     } /* End of if */
00965     if (lsLength(g_get_out_edges(vertexPtr)) == 0) {
00966       numSinks++;
00967     } /* End of if */
00968     if (PartVertexReadType(vertexPtr) == Part_VertexSingle_c) {
00969       if (printNodeNames) {
00970         if (PartVertexReadName(vertexPtr) != NIL(char)) {
00971           (void) fprintf(fp, "%s\n", PartVertexReadName(vertexPtr));
00972         }
00973       }
00974       vertexFunction = PartVertexReadFunction(vertexPtr);
00975       if (vertexFunction != NIL(Mvf_Function_t)) {
00976         Mvf_FunctionForEachComponent(vertexFunction, i, mddPtr) {
00977           array_insert_last(mdd_t *, functions, mddPtr);
00978         }
00979       } /* End of if */
00980     } /* End of if */
00981   } /* foreach_vertex*/
00982 
00983   /* Print results */
00984   (void)fprintf(fp, "Method %s, %d sinks, %d sources,", methodName, numSinks, numSources);
00985   (void)fprintf(fp, " %d total vertices,", numVertices);
00986   (void)fprintf(fp, " %ld mdd nodes\n", bdd_size_multiple(functions));
00987 
00988   /* Clean up */
00989   FREE(methodName);
00990   array_free(functions);
00991 
00992   return;
00993 } /* End of Part_PartitionPrintStats */
00994 
00995 /*---------------------------------------------------------------------------*/
00996 /* Definition of internal functions                                          */
00997 /*---------------------------------------------------------------------------*/
00998 
01012 PartPartitionInfo_t *
01013 PartPartitionInfoCreate(
01014   char *name,
01015   mdd_manager *manager,
01016   Part_PartitionMethod method)
01017 {
01018   PartPartitionInfo_t *recordPartition = ALLOC(PartPartitionInfo_t, 1);
01019 
01020   recordPartition->name          = util_strsav(name);
01021   recordPartition->method        = method;
01022   recordPartition->mddManager    = manager;
01023   recordPartition->nameToVertex  = st_init_table(strcmp,st_strhash);
01024   recordPartition->mddIdToVertex = st_init_table(st_numcmp, st_numhash);
01025 
01026   return recordPartition;
01027 } /* End of PartPartitionInfoCreate */
01028 
01041 void
01042 PartPartitionInfoFree(
01043   gGeneric partitionInfo)
01044 {
01045   if (((PartPartitionInfo_t *)partitionInfo)->name != NIL(char)) {
01046     FREE(((PartPartitionInfo_t *)partitionInfo)->name);
01047   }
01048 
01049   st_free_table(((PartPartitionInfo_t *)partitionInfo)->nameToVertex);
01050   st_free_table(((PartPartitionInfo_t *)partitionInfo)->mddIdToVertex);
01051 
01052   FREE(partitionInfo);
01053 } /* End of PartPartitionInfoFree */
01054 
01064 PartVertexInfo_t *
01065 PartVertexInfoCreateSingle(
01066   char *name,
01067   Mvf_Function_t *mvf,
01068   int mddId)
01069 {
01070   PartVertexInfo_t *result;
01071 
01072   result                    = ALLOC(PartVertexInfo_t, 1);
01073   result->type              = Part_VertexSingle_c;
01074   result->name              = util_strsav(name);
01075   result->functionality.mvf = mvf;
01076   result->mddId             = mddId;
01077   result->isClustered       = 0;
01078 
01079   return result;
01080 } /* End of PartVertexInfoCreateSingle */
01081 
01091 PartVertexInfo_t *
01092 PartVertexInfoCreateCluster(
01093   char *name,
01094   array_t *vertexArray)
01095 {
01096   PartVertexInfo_t *result;
01097   vertex_t *auxPtr;
01098   int i;
01099 
01100   /* Make sure all the nodes are simple nodes */
01101   for(i = 0; i < array_n(vertexArray); i++) {
01102     auxPtr = array_fetch(vertex_t *, vertexArray, i);
01103     if (PartVertexReadType(auxPtr) == Part_VertexCluster_c) {
01104       fail("Only one level of hierarchy allowed in the partition");
01105     } /* End of if */
01106     if (PartVertexTestIsClustered(auxPtr)) {
01107       fail("Partition: Clustering vertex already member of another cluster");
01108     } /* End of then */
01109     else {
01110       PartVertexSetIsClustered(auxPtr, 1);
01111     }
01112   } /* End of for */
01113 
01114   result                               = ALLOC(PartVertexInfo_t, 1);
01115   result->type                         = Part_VertexCluster_c;
01116   result->name                         = util_strsav(name);
01117   result->functionality.clusterMembers = array_dup(vertexArray);
01118 
01119   result->mddId                        = NTK_UNASSIGNED_MDD_ID;
01120   result->isClustered                  = 0;
01121 
01122   return result;
01123 } /* End of PartVertexInfoCreateCluster */
01124 
01134 void
01135 PartVertexInfoFree(
01136   gGeneric vertexInfo
01137    )
01138 {
01139   if (((PartVertexInfo_t *)vertexInfo)->type == Part_VertexSingle_c) {
01140     /* Free the function attached to the node if any */
01141     if (((PartVertexInfo_t *)vertexInfo)->functionality.mvf !=
01142         NIL(Mvf_Function_t)) {
01143       Mvf_FunctionFree(((PartVertexInfo_t *)vertexInfo)->functionality.mvf);
01144     } /* End of if */
01145   } /* End of then */
01146   else {
01147     if (((PartVertexInfo_t *)vertexInfo)->functionality.clusterMembers !=
01148         NIL(array_t)) {
01149       array_free(((PartVertexInfo_t *)vertexInfo)->functionality.clusterMembers);
01150     } /* End of if */
01151   } /* End of if-then-else */
01152 
01153   if (((PartVertexInfo_t *)vertexInfo)->name != NIL(char)) {
01154     FREE(((PartVertexInfo_t *)vertexInfo)->name);
01155   }
01156 
01157   FREE(vertexInfo);
01158 } /* End of PartVertexInfoFree */
01159 
01170 void
01171 PartPartitionSanityCheck(
01172   graph_t *partition,
01173   int intensity)
01174 {
01175   st_table *table;
01176   lsList vertexList = g_get_vertices(partition);
01177   lsGen lgen;
01178   vertex_t *vertex, *rvertex;
01179 
01180   /* Consistency in the nameToVertex table */
01181   table = PartPartitionReadNameToVertex(partition);
01182 
01183   /*
01184    * The number of elements in the nameToVertex table and the number
01185    * of vertices agrees
01186    */
01187   if (lsLength(g_get_vertices(partition)) != st_count(table)) {
01188     (void) fprintf(vis_stderr, "Warning -- NameToVertex table incomplete in ");
01189     (void) fprintf(vis_stderr, " graph\n");
01190     if (intensity > 1) {
01191       (void) fprintf(vis_stderr, "  %d vertices in the graph and %d entries",
01192                      lsLength(g_get_vertices(partition)),
01193                      st_count(table));
01194       (void) fprintf(vis_stderr, " in the nameToVertex table\n");
01195     } /* End of if */
01196   } /* End of if */
01197 
01198   lsForEachItem(vertexList, lgen, vertex) {
01199     char *name = PartVertexReadName(vertex);
01200     if (!st_lookup(table, name, &rvertex) ||
01201         strcmp(PartVertexReadName(vertex),PartVertexReadName(rvertex)) != 0) {
01202       (void) fprintf(vis_stderr, "Warning -- Inconsistency detected in");
01203       (void) fprintf(vis_stderr, " the partition data-base\n");
01204     }
01205   }
01206 
01207   /* Consistency in the mddIdToVertexTable */
01208   table = PartPartitionReadMddIdToVertex(partition);
01209   lsForEachItem(vertexList, lgen, vertex) {
01210     int mddId = PartVertexReadMddId(vertex);
01211     if((mddId != NTK_UNASSIGNED_MDD_ID) &&
01212        (!st_lookup(table, (char *)(long)mddId, &rvertex) ||
01213         PartVertexReadMddId(vertex) != PartVertexReadMddId(rvertex))) {
01214       (void) fprintf(vis_stderr, "Warning -- Inconsistency detected in the");
01215       (void) fprintf(vis_stderr, " partition data-base\n");
01216     }
01217   }
01218 
01219   /*
01220    * Make sure that the mdd Id NTK_UNASSIGNED_MDD_ID does not appear in the
01221    * mddIdToVertex node.
01222    */
01223   table = PartPartitionReadMddIdToVertex(partition);
01224   if (st_is_member(table, (char *) NTK_UNASSIGNED_MDD_ID)) {
01225     (void) fprintf(vis_stderr, "Warning -- Inconsistency detected in the");
01226     (void) fprintf(vis_stderr, " partition data-base\n");
01227   } /* End of if */
01228 
01229   /* Check the Mvfs in the vertices of the partition.*/
01230   if (intensity > 1) {
01231     lsForEachItem(vertexList, lgen, vertex) {
01232       Mvf_Function_t *function = PartVertexReadFunction(vertex);
01233       int i;
01234 
01235       (void) fprintf(vis_stderr, "Vertex: %s, mddId: %d, Clustered: %c\n",
01236                      PartVertexReadName(vertex),
01237                      PartVertexReadMddId(vertex),
01238                      (PartVertexReadType(vertex) == Part_VertexCluster_c)?'t':'f');
01239       for(i = 0; i < Mvf_FunctionReadNumComponents(function); i ++) {
01240         mdd_t *unit = Mvf_FunctionObtainComponent(function, i);
01241         boolean x;
01242 
01243         if (intensity > 2) {
01244           (void) fprintf(vis_stderr, "BDD_T: %lx, %lx\n",
01245                          (unsigned long) bdd_get_node(unit, &x),
01246                          (unsigned long) mdd_get_manager(unit));
01247         }
01248       } /* End of for */
01249     }
01250   } /* End of if */
01251 
01252   /* ToDo: Check for redundant name in the list of vertices */
01253 } /* End of PartPartitionSanityCheck */
01254 
01270 st_table *
01271 PartCreateFunctionSupportTable(
01272   Mvf_Function_t *mvf)
01273 {
01274   mdd_manager  *mddManager;        /* Manager for the MDDs */
01275   array_t      *support;
01276   st_table     *mddSupport = st_init_table(st_numcmp, st_numhash);
01277   int          numComponents = Mvf_FunctionReadNumComponents(mvf);
01278   int          j, k;
01279   mdd_t        *unit;
01280 
01281   assert(numComponents!= 0);
01282 
01283   mddManager = Mvf_FunctionReadMddManager(mvf);
01284 
01285   /*
01286    * compute the support of an mdd as the union of supports of every
01287    * function component
01288    */
01289   for(j = 0; j < numComponents; j++) {
01290     unit = Mvf_FunctionReadComponent(mvf, j);
01291     support = mdd_get_support(mddManager, unit);
01292 
01293     /* For every element of its support */
01294     for(k = 0; k < array_n(support); k++) {
01295       st_insert(mddSupport, (char *)(long)array_fetch(int, support, k), (char *)0);
01296     } /* End of for */
01297     array_free(support);
01298   } /* End of for */
01299 
01300   return mddSupport;
01301 } /* End of PartCreateFunctionSupportTable */
01302 
01314 void
01315 PartPartitionCreateVertexFaninEdges(
01316   graph_t  *partition,
01317   vertex_t *vertexPtr)
01318 {
01319   vertex_t       *fromVertex;
01320   Mvf_Function_t *vertexFunction;
01321   st_table       *support;
01322   st_table       *mddIdToVertex;
01323   st_generator   *stGen;
01324   long            mddId;
01325 
01326   mddIdToVertex = PartPartitionReadMddIdToVertex(partition);
01327   vertexFunction = PartVertexReadFunction(vertexPtr);
01328   support = PartCreateFunctionSupportTable(vertexFunction);
01329 
01330   /* Create the edges for every element in support */
01331   st_foreach_item(support, stGen, &mddId, NULL) {
01332     st_lookup(mddIdToVertex, (char *)mddId, &fromVertex);
01333     /* Make sure no self loops are created */
01334     if (fromVertex != vertexPtr) {
01335       g_add_edge(fromVertex, vertexPtr);
01336     } /* End of if */
01337   }
01338 
01339   st_free_table(support);
01340 } /* End of PartPartitionCreateVertexFaninEdges */
01341 
01357 int
01358 PartPartitionPrint(
01359   FILE *fp,
01360   graph_t *partition)
01361 {
01362   lsGen      gen;           /* To iterate over edges */
01363   edge_t     *edgePtr;      /* Will hold the edge being processed */
01364   vertex_t   *fromVertex;   /* Will hold the vertex source of the edge */
01365   vertex_t   *toVertex;     /* Will hold the destination of the edge */
01366   st_table   *vertexToId;   /* To lookup the ordinal of a vertex */
01367   time_t      now           = time(0);
01368   struct tm  *nowStructPtr  = localtime(& now);
01369   char       *nowTxt        = asctime(nowStructPtr);
01370   char       *partitionName = PartPartitionReadName(partition);
01371   int        vertexId;
01372   int        clusterId;
01373 
01374   /*
01375    * Write out the header for the output file.
01376    */
01377 
01378   (void) fprintf(fp, "# %s\n", Vm_VisReadVersion());
01379   (void) fprintf(fp, "# partition name: %s\n", partitionName);
01380   (void) fprintf(fp, "# generated: %s", nowTxt);
01381   (void) fprintf(fp, "#\n");
01382 
01383   (void) fprintf(fp, "# Partition with %d vertices and %d edges\n",
01384                  lsLength(g_get_vertices(partition)),
01385                  lsLength(g_get_edges(partition)));
01386 
01387   (void) fprintf(fp, "digraph \"%s\" {\n  rotate=90;\n", partitionName);
01388   (void) fprintf(fp, "  margin=0.5;\n  label=\"%s\";\n", partitionName);
01389   (void) fprintf(fp, "  size=\"10,7.5\";\n  ratio=\"fill\";\n");
01390 
01391 
01392   vertexToId = st_init_table(st_ptrcmp, st_ptrhash);
01393 
01394   vertexId = 0;
01395   clusterId = 0;
01396   foreach_vertex(partition, gen, fromVertex) {
01397     if (PartVertexReadType(fromVertex) == Part_VertexCluster_c) {
01398       array_t *members = PartVertexReadClusterMembers(fromVertex);
01399       vertex_t *auxPtr;
01400       int i;
01401 
01402       (void) fprintf(fp, "  subgraph cluster%d {\n", clusterId++);
01403       (void) fprintf(fp, "    label = \"%s\";\n",
01404                      PartVertexReadName(fromVertex));
01405       arrayForEachItem(vertex_t *, members, i, auxPtr) {
01406         (void) fprintf(fp, "  ");
01407         st_insert(vertexToId, (char *)auxPtr, (char *)(long)vertexId);
01408         PrintVertexDescription(fp, auxPtr, vertexId++);
01409       }
01410       (void) fprintf(fp, "  }\n");
01411     } /* End of then */
01412     else if (!PartVertexTestIsClustered(fromVertex)) {
01413       st_insert(vertexToId, (char *)fromVertex, (char *)(long)vertexId);
01414       PrintVertexDescription(fp, fromVertex, vertexId++);
01415     }
01416 
01417   }
01418 
01419   foreach_edge(partition, gen, edgePtr) {
01420     fromVertex = g_e_source(edgePtr);
01421     toVertex = g_e_dest(edgePtr);
01422 
01423     st_lookup_int(vertexToId, (char *)fromVertex, &vertexId);
01424     (void) fprintf(fp, "  node%d -> ", vertexId);
01425 
01426     st_lookup_int(vertexToId, (char *)toVertex, &vertexId);
01427     (void) fprintf(fp, "node%d;\n", vertexId);
01428   } /* End of foreach_edge */
01429 
01430   (void) fprintf(fp, "}\n");
01431 
01432   st_free_table(vertexToId);
01433 
01434   return 1;
01435 } /* End of PartPartitionPrint */
01436 
01437 
01450 int
01451 PartGetLatchInputListFromCTL(
01452   Ntk_Network_t *network,
01453   array_t *ctlArray,
01454   array_t *fairArray,
01455   lsList  latchInputList)
01456 {
01457   return PartGetLatchInputListFromCtlAndLtl(network, ctlArray, NIL(array_t),
01458                                             fairArray, latchInputList,
01459                                             FALSE);
01460 }
01461 
01476 int
01477 PartGetLatchInputListFromCtlAndLtl(
01478   Ntk_Network_t *network,
01479   array_t *ctlArray,
01480   array_t *ltlArray,
01481   array_t *fairArray,
01482   lsList  latchInputList,
01483   boolean stopAtLatch)
01484 {
01485   int i;
01486   Ctlp_Formula_t  *ctlFormula;
01487   Ctlsp_Formula_t *ltlFormula;
01488   st_table *formulaNodes;
01489   st_generator *stGen;
01490   array_t *nodeArray;
01491   array_t *formulaCombNodes;
01492   Ntk_Node_t *node;
01493 
01494 
01495   formulaNodes = st_init_table( st_ptrcmp, st_ptrhash );
01496 
01497   if ( formulaNodes == NIL(st_table)){
01498     return 0;
01499   }
01500 
01501  /*
01502   * Extract nodes in CTL/LTL properties
01503   */
01504   if ( ctlArray != NIL(array_t)){
01505     arrayForEachItem( Ctlp_Formula_t *, ctlArray, i, ctlFormula ) {
01506       Mc_NodeTableAddCtlFormulaNodes( network, ctlFormula, formulaNodes );
01507     }
01508   }
01509   if ( ltlArray != NIL(array_t)){
01510     arrayForEachItem( Ctlsp_Formula_t *, ltlArray, i, ltlFormula ) {
01511       Mc_NodeTableAddLtlFormulaNodes( network, ltlFormula, formulaNodes );
01512     }
01513   }
01514 
01515  /*
01516   * Extract nodes in fairness properties
01517   */
01518   if ( fairArray != NIL(array_t)){
01519     arrayForEachItem( Ctlp_Formula_t *, fairArray, i, ctlFormula ) {
01520       Mc_NodeTableAddCtlFormulaNodes( network, ctlFormula, formulaNodes );
01521     }
01522   }
01523 
01524   nodeArray = array_alloc( Ntk_Node_t *, 0 );
01525   st_foreach_item( formulaNodes, stGen, &node, NULL) {
01526     array_insert_last( Ntk_Node_t *, nodeArray, node );
01527   }
01528 
01529   st_free_table( formulaNodes );
01530 
01531  /*
01532   * Get all combinational support nodes in network from formula nodes
01533   */
01534   formulaCombNodes = Ntk_NodeComputeCombinationalSupport( network,
01535                      nodeArray, stopAtLatch );
01536   array_free(nodeArray);
01537  /*
01538   * Root list includes latch data input nodes
01539   */
01540   arrayForEachItem( Ntk_Node_t *, formulaCombNodes, i, node ) {
01541     if ( Ntk_NodeTestIsLatch( node ) ) {
01542       Ntk_Node_t *tempNode = Ntk_LatchReadDataInput( node );
01543       lsNewEnd(latchInputList, (lsGeneric)tempNode, LS_NH);
01544     }
01545   }
01546 
01547   array_free(formulaCombNodes);
01548 
01549   return 1;
01550 }
01551 
01566 int
01567 PartGetLatchListFromCtlAndLtl(
01568   Ntk_Network_t *network,
01569   array_t *ctlArray,
01570   array_t *ltlArray,
01571   array_t *fairArray,
01572   lsList  latchInputList,
01573   boolean stopAtLatch)
01574 {
01575   int i;
01576   Ctlp_Formula_t  *ctlFormula;
01577   Ctlsp_Formula_t *ltlFormula;
01578   st_table *formulaNodes;
01579   st_generator *stGen;
01580   array_t *nodeArray;
01581   array_t *formulaCombNodes;
01582   Ntk_Node_t *node;
01583 
01584 
01585   formulaNodes = st_init_table( st_ptrcmp, st_ptrhash );
01586 
01587   if ( formulaNodes == NIL(st_table)){
01588     return 0;
01589   }
01590 
01591  /*
01592   * Extract nodes in CTL/LTL properties
01593   */
01594   if ( ctlArray != NIL(array_t)){
01595     arrayForEachItem( Ctlp_Formula_t *, ctlArray, i, ctlFormula ) {
01596       Mc_NodeTableAddCtlFormulaNodes( network, ctlFormula, formulaNodes );
01597     }
01598   }
01599   if ( ltlArray != NIL(array_t)){
01600     arrayForEachItem( Ctlsp_Formula_t *, ltlArray, i, ltlFormula ) {
01601       Mc_NodeTableAddLtlFormulaNodes( network, ltlFormula, formulaNodes );
01602     }
01603   }
01604 
01605  /*
01606   * Extract nodes in fairness properties
01607   */
01608   if ( fairArray != NIL(array_t)){
01609     arrayForEachItem( Ctlp_Formula_t *, fairArray, i, ctlFormula ) {
01610       Mc_NodeTableAddCtlFormulaNodes( network, ctlFormula, formulaNodes );
01611     }
01612   }
01613 
01614   nodeArray = array_alloc( Ntk_Node_t *, 0 );
01615   st_foreach_item( formulaNodes, stGen, &node, NULL) {
01616     array_insert_last( Ntk_Node_t *, nodeArray, node );
01617   }
01618 
01619   st_free_table( formulaNodes );
01620 
01621  /*
01622   * Get all combinational support nodes in network from formula nodes
01623   */
01624   formulaCombNodes = Ntk_NodeComputeCombinationalSupport( network,
01625                      nodeArray, stopAtLatch );
01626   array_free(nodeArray);
01627  /*
01628   * Root list includes latch data input nodes
01629   */
01630   arrayForEachItem( Ntk_Node_t *, formulaCombNodes, i, node ) {
01631     if ( Ntk_NodeTestIsLatch( node ) ) {
01632       lsNewEnd(latchInputList, (lsGeneric)node, LS_NH);
01633     }
01634   }
01635 
01636   array_free(formulaCombNodes);
01637 
01638   return 1;
01639 }
01640 
01641 /*---------------------------------------------------------------------------*/
01642 /* Definition of static functions                                            */
01643 /*---------------------------------------------------------------------------*/
01644 
01645 
01655 static void
01656 PrintVertexDescription(
01657   FILE *fp,
01658   vertex_t *vertexPtr,
01659   int order)
01660 {
01661   char *name = PartVertexReadName(vertexPtr);
01662 
01663   (void) fprintf(fp, "  node%d [label=", order);
01664   if (name != NIL(char)) {
01665     (void) fprintf(fp, "\"%s\"", name);
01666   }
01667   else {
01668     (void) fprintf(fp, "\"None\"");
01669   }
01670   (void) fprintf(fp, "]; \n");
01671 } /* End of PrintVertexDescription */