VIS
|
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 */