VIS

src/part/partGroup.c

Go to the documentation of this file.
00001 
00045 #include "partInt.h"
00046 
00047 static char rcsid[] UNUSED = "$Id: partGroup.c,v 1.51 2005/04/28 14:15:50 fabio Exp $";
00048 
00049 /*---------------------------------------------------------------------------*/
00050 /* Constant declarations                                                     */
00051 /*---------------------------------------------------------------------------*/
00052 
00053 
00054 /*---------------------------------------------------------------------------*/
00055 /* Type declarations                                                         */
00056 /*---------------------------------------------------------------------------*/
00057 
00058 
00059 /*---------------------------------------------------------------------------*/
00060 /* Structure declarations                                                    */
00061 /*---------------------------------------------------------------------------*/
00062 
00063 
00064 /*---------------------------------------------------------------------------*/
00065 /* Variable declarations                                                     */
00066 /*---------------------------------------------------------------------------*/
00067 
00068 
00069 /*---------------------------------------------------------------------------*/
00070 /* Macro declarations                                                        */
00071 /*---------------------------------------------------------------------------*/
00072 
00073 
00076 /*---------------------------------------------------------------------------*/
00077 /* Static function prototypes                                                */
00078 /*---------------------------------------------------------------------------*/
00079 
00080 static char * PartCreateDependencyMatrix(Part_SubsystemInfo_t *partSubInfo, st_table *ptrToIndex);
00081 static float * PartCreateCorrelationMatrixFromSupport(Part_SubsystemInfo_t *partSubInfo);
00082 static float * PartCreateCorrelationMatrixFromBDD(Part_SubsystemInfo_t *partSubInfo);
00083 static float PartVertexComputeCorrelation(int index1, int index2, array_t *arrayOfInputSupportTable, Part_SubsystemInfo_t *partSubInfo);
00084 static array_t * PartVertexComputeAgreement(mdd_manager *mddMgr, int index1, int index2, array_t *arrayOfBddArray);
00085 static float * PartCreateAffinityMatrix(char *arrayOfConnectivity, float *arrayOfCorrelation, Part_SubsystemInfo_t *partSubInfo);
00086 static array_t * PartGetConnectedComponent(float *arrayOfAffinity, Part_SubsystemInfo_t *partSubInfo, st_table *indexToPtr);
00087 static void PartFindCC(int *next, int *ccId, array_t *arrayOfCCIndex, float *arrayOfAffinity, array_t *arrayOfFrom, Part_SubsystemInfo_t *PartSubInfo);
00088 static array_t * PartBreakingAggregating(array_t *arrayOfInit, float *arrayOfAffinity, Part_SubsystemInfo_t *partSubInfo, st_table *ptrToIndex, char *arrayOfDependency);
00089 static array_t * PartBreakingBigConnectedComponent(array_t *arrayOfCC, array_t *ccCheck, array_t *arrayOfSeed, float *arrayOfAffinity, Part_SubsystemInfo_t *partSubInfo, st_table *ptrToIndex);
00090 static array_t * PartAggregating(array_t *arrayOfSmall, float *arrayOfAffinity, Part_SubsystemInfo_t *partSubInfo, st_table *ptrToIndex);
00091 static array_t * PartCreateSubSystemWithGroupIndex(Part_SubsystemInfo_t *partSubInfo, array_t *arrayOfLatchNames, array_t *arrayOfGroupIndex);
00092 static Ntk_Node_t * PartSelectCloseNode(Ntk_Node_t *seed, array_t *arrayOfCC, array_t *ccCheck, float *arrayOfAffinity, st_table *ptrToIndex);
00093 static int PartSelectCloseSeedIndex(Ntk_Node_t *variable, array_t *arrayOfSeed, float *arrayOfAffinity, st_table *ptrToIndex, array_t *seedFull, int bound);
00094 static Ntk_Node_t * PartSelectFarNode(Ntk_Node_t *seed, array_t *cc, array_t *ccCheck, float *arrayOfAffinity, st_table *ptrToIndex);
00095 static float * PartGetGroupMatrixRegular(array_t *arrayOfCluster, char *arrayOfGivenMatrix, st_table *ptrToIndex, int nVertices);
00096 static float * PartGetGroupMatrixSym(array_t *arrayOfCluster, float *arrayOfGivenMatrix, st_table *ptrToIndex);
00097 static int PartSelectCCIndexOfMinSupport(array_t *arrayOfSmall, array_t *ccCheck, Part_SubsystemInfo_t *partSubInfo);
00098 static Ntk_Node_t * PartSelectNodeOfMinSupport(array_t *cc, array_t *ccCheck, Part_SubsystemInfo_t *partSubInfo);
00099 static int PartSelectFarCCIndex(int seedIndex, array_t *arrayOfSmall, float *arrayOfGroupAff, Part_SubsystemInfo_t *partSubInfo, array_t *ccCheck);
00100 static int PartSelectCloseCCIndex(int seedIndex, array_t *arrayOfSmall, float *arrayOfGroupAff, array_t *ccCheck);
00101 static Part_Subsystem_t* PartCreateSingleSubSystem(array_t *arrayOfNodes, Ntk_Network_t *network);
00102 static array_t * PartReadLatchNameFromLatchInput(Ntk_Network_t *network, Ntk_Node_t *latchInput);
00103 static void PartArrayOfArrayFree(array_t *arrayOfMatrix);
00104 static float PartGetElementFromSymMatrix(float *matrix, int i, int j);
00105 static void PartPrintArrayArray(void *arrayOfMatrix, int nVertices, int type);
00106 static int strCompare(const void * name1, const void * name2);
00107 static int numCompare(const void * num1, const void * num2);
00108 static array_t *PartCreateSubsystemWithCTL(Part_SubsystemInfo_t *, array_t *, array_t *, boolean , boolean );
00109 static array_t *PartCreateSubsystemWithCtlAndLtl(Part_SubsystemInfo_t *, array_t *, array_t *, array_t *, boolean , boolean, boolean );
00110 
00111 
00115 /*---------------------------------------------------------------------------*/
00116 /* Definition of exported functions                                          */
00117 /*---------------------------------------------------------------------------*/
00118 
00144 array_t *
00145 Part_PartGroupVeriticesBasedOnHierarchy(
00146   Ntk_Network_t *network,
00147   array_t *latchDataInputNames)
00148 {
00149   graph_t       *partition;
00150   array_t       *arrayOfPartition = NIL(array_t);
00151   array_t       *arrayOfGroups = NIL(array_t);
00152   array_t       *arrayOfLatches = NIL(array_t);
00153   array_t       *arrayOfLatchSort = NIL(array_t);
00154   st_table      *vertexTable = NIL(st_table);
00155   int           numOfVertex, reset;
00156   int           i, j, k;
00157   char          *numberOfVertexInGroup;
00158   char          *flagValue;
00159   char          *latchName, *name;
00160   st_table      *latchDataInputNameTable;
00161   Part_Subsystem_t *testSubsystem;
00162 
00163   partition = Part_NetworkReadPartition(network);
00164   if (partition == NIL(graph_t)) {
00165     error_append("Network has no partition. Cannot create sub machines.");
00166     return (NIL(array_t));
00167   }
00168 
00169   /*
00170    * Convert graph of vertices into array of table of vertices.
00171    */
00172 
00173   numberOfVertexInGroup = Cmd_FlagReadByName("amc_sizeof_group");
00174   if (numberOfVertexInGroup != NIL(char)) {
00175     numOfVertex = atoi(numberOfVertexInGroup);
00176     reset = atoi(numberOfVertexInGroup);
00177   }
00178   else {
00179     /* default value */
00180     numOfVertex = 8;
00181     reset = 8;
00182   }
00183 
00184   latchDataInputNameTable = st_init_table(strcmp, st_strhash);
00185 
00186   arrayForEachItem(char *, latchDataInputNames, i, name) {
00187     st_insert(latchDataInputNameTable, (char *)name, (char *)NULL);
00188   }
00189 
00190   /*
00191    * In the first phase, group latches by the processes.
00192    * That is, group latches that are within same sub-circuit.
00193    */
00194 
00195   arrayOfGroups = array_alloc(array_t *, 0);
00196 
00197   {
00198     Ntk_Node_t  *latch;
00199     lsGen       gen;
00200     char        *groupName = util_strsav(" ");
00201 
00202     arrayOfLatchSort = array_alloc(char *, 0);
00203     Ntk_NetworkForEachLatch(network, gen, latch) {
00204       Ntk_Node_t *latchInput = Ntk_LatchReadDataInput(latch);
00205       char *latchInputName = Ntk_NodeReadName(latchInput);
00206       vertex_t *vertex = Part_PartitionFindVertexByName(partition,
00207                                                         latchInputName);
00208       if ((vertex != NIL(vertex_t)) &&
00209           (st_lookup(latchDataInputNameTable, latchInputName, NIL(char *)))) {
00210         array_insert_last(char *, arrayOfLatchSort, Ntk_NodeReadName(latch));
00211       }
00212     }
00213     array_sort(arrayOfLatchSort, strCompare);
00214 
00215     arrayForEachItem(char *, arrayOfLatchSort, i, latchName) {
00216       char *suffixLatchName, *currentGroupName;
00217 
00218       suffixLatchName = util_strsav(latchName);
00219 
00220       /* Extract out group name into the string "groupName" and leave
00221          rest in suffixLatchName. */
00222 
00223       currentGroupName = strtok(suffixLatchName, ".");
00224 
00225       if (strcmp(groupName, currentGroupName)) {
00226         if (strcmp(groupName, " ")) {
00227           array_insert_last(array_t *, arrayOfGroups, arrayOfLatches);
00228         }
00229         FREE(groupName);
00230         groupName = util_strsav(currentGroupName);
00231         arrayOfLatches = array_alloc(char *, 0);
00232       }
00233       FREE(currentGroupName);
00234       array_insert_last(char *, arrayOfLatches, latchName);
00235     }
00236     FREE(groupName);
00237   }
00238 
00239   array_free(arrayOfLatchSort);
00240   st_free_table(latchDataInputNameTable);
00241 
00242   /* Fill in the last arrayOfLatches */
00243   array_insert_last(array_t *, arrayOfGroups, arrayOfLatches);
00244 
00245   /*
00246    * In the second phase, further break latch group into
00247    * smaller group size according to the "amc_sizeof_group".
00248    */
00249 
00250   arrayOfPartition = array_alloc(Part_Subsystem_t *, 0);
00251 
00252   arrayForEachItem(array_t *, arrayOfGroups, k, arrayOfLatches) {
00253     char        *latchName;
00254     int         numOfLatches = array_n(arrayOfLatches);
00255 
00256     arrayForEachItem(char *, arrayOfLatches, i, latchName) {
00257 
00258       if (numOfVertex == reset)
00259         vertexTable = st_init_table(strcmp, st_strhash);
00260 
00261       st_insert(vertexTable, latchName, (char *)NULL);
00262 
00263       if ((numOfVertex == 1) || (numOfLatches == i+1)) {
00264         /* testSubsystem freed by calling function  */
00265         testSubsystem = ALLOC(Part_Subsystem_t, 1);
00266         testSubsystem->vertexNameTable = vertexTable;
00267         testSubsystem->subsystemFanIn = NIL(array_t);
00268         testSubsystem->subsystemFanOut = NIL(array_t);
00269 
00270         array_insert_last(Part_Subsystem_t *, arrayOfPartition, testSubsystem);
00271         numOfVertex = reset;
00272       }
00273       else
00274         numOfVertex--;
00275     } /* End of arrayForEachItem(arrayOfLatches) */
00276   } /* End of arrayForEachItem(arrayOfGroups) */
00277 
00278   /* Free arrayOfGroups, arrayOfLatches */
00279   arrayForEachItem(array_t *, arrayOfGroups, i, arrayOfLatches) {
00280     array_free(arrayOfLatches);
00281   }
00282   array_free(arrayOfGroups);
00283 
00284   /*
00285    * Currently this function is used only from amc package.
00286    * When the function gets popular use parameter passing rather that this
00287    * ugly method.
00288    */
00289   flagValue = Cmd_FlagReadByName("amc_use_MBM");
00290   if (flagValue != NIL(char)) {
00291     array_t     *latchNodeArray;
00292     array_t     *faninNodeArray;
00293     array_t     *faninLatchArray;
00294 
00295     /*
00296      * Fill in the subsystem dependencies using the latch dependencies.
00297      */
00298 
00299     arrayForEachItem(Part_Subsystem_t *, arrayOfPartition, i, testSubsystem) {
00300       array_t           *fanInArray = array_alloc(int, 0);
00301       st_table          *vertexTable = testSubsystem->vertexNameTable;
00302       st_generator      *stGen;
00303       char              *latchName;
00304       Ntk_Node_t        *latchNode;
00305 
00306       latchNodeArray = array_alloc(Ntk_Node_t *, 0);
00307       faninLatchArray = array_alloc(Ntk_Node_t *, 0);
00308 
00309       /* Convert table of latch names into array of latch nodes */
00310       st_foreach_item(vertexTable, stGen, &latchName, NIL(char *)) {
00311         latchNode = Ntk_NetworkFindNodeByName(network, latchName);
00312         array_insert_last(Ntk_Node_t *, latchNodeArray, latchNode);
00313       }
00314 
00315       /* Find the transitive fanin nodes */
00316       faninNodeArray = Ntk_NodeComputeCombinationalSupport(network,
00317                         latchNodeArray, FALSE);
00318 
00319       /* Find the transitive fanin latches from the fanin nodes */
00320       if (array_n(faninNodeArray) != 0) {
00321         int x;
00322         arrayForEachItem(Ntk_Node_t *, faninNodeArray, x, latchNode) {
00323           if (Ntk_NodeTestIsLatch(latchNode) == TRUE) {
00324             array_insert_last(Ntk_Node_t *, faninLatchArray, latchNode);
00325           }
00326         }
00327       }
00328 
00329       /* Find the fanin subsystems */
00330       if (array_n(faninLatchArray) != 0) {
00331         Part_Subsystem_t *scanSubsystem;
00332         int y;
00333 
00334         arrayForEachItem(Part_Subsystem_t *, arrayOfPartition, j,
00335                 scanSubsystem) {
00336           /* Scan subsystems that aren't the currently considered subsytem */
00337           st_table      *otherVertexTable = scanSubsystem->vertexNameTable;
00338 
00339           if (i != j) {
00340             arrayForEachItem(Ntk_Node_t *, faninLatchArray, y, latchNode) {
00341               char *latchName = Ntk_NodeReadName(latchNode);
00342               if (st_lookup(otherVertexTable, latchName, NIL(char *))) {
00343                 array_insert_last(int, fanInArray, j);
00344                 break;
00345               }
00346             } /* end of arrayForEachItem(Ntk_Node_t *) */
00347           } /* end of if (i != j) */
00348         }
00349       } /* end of if (array_n(faninLatchArray) != 0) */
00350 
00351       /* Update fanInArray into the subsystem */
00352       testSubsystem->subsystemFanIn = fanInArray;
00353 
00354       array_free(latchNodeArray);
00355       array_free(faninNodeArray);
00356       array_free(faninLatchArray);
00357     } /* end of arrayForEachItem(Part_Subsystem_t *) */
00358   } /* end of if (!flagValue) */
00359 
00360   /*
00361    * Currently this function is used only from amc package.
00362    * When the function gets popular use parameter passing rather that this
00363    * ugly method.
00364    */
00365 
00366   flagValue = Cmd_FlagReadByName("amc_use_MBM");
00367   if (flagValue != NIL(char)) {
00368     st_table *fanOutDependencies = Ntk_NetworkComputeLatchDependencies(network);
00369 
00370     /*
00371      * Fill in the fanout dependencies of subsystems.
00372      */
00373     arrayForEachItem(Part_Subsystem_t *, arrayOfPartition, i, testSubsystem) {
00374       array_t           *fanOutArray = array_alloc(int, 0);
00375       st_table          *vertexTable = testSubsystem->vertexNameTable;
00376       st_generator      *stGen;
00377       char              *latchName;
00378       st_table          *everyFanOuts = st_init_table(st_ptrcmp, st_ptrhash);
00379 
00380       /*
00381        * For the latches in this subsystem,
00382        * find all latches that transitively fanouts from the latches
00383        * inside this subsystem. Store it in a hash table, "everyFanOuts".
00384        */
00385       st_foreach_item(vertexTable, stGen, &latchName, NIL(char *)) {
00386         Ntk_Node_t      *latchNode;
00387         lsList          fanOutLatchList;
00388         lsGen           gen;
00389         lsGeneric       data;
00390 
00391         latchNode = Ntk_NetworkFindNodeByName(network, latchName);
00392         st_lookup(fanOutDependencies, latchNode, &fanOutLatchList);
00393 
00394         /* Obtain all fanout latches coming from latches of this subsystem */
00395         gen = lsStart(fanOutLatchList);
00396         while (lsNext(gen, &data, LS_NH) == LS_OK) {
00397           st_insert(everyFanOuts, data, NULL);
00398         }
00399         (void) lsFinish(gen);
00400         lsDestroy(fanOutLatchList, (void (*) (lsGeneric)) NULL);
00401       }
00402 
00403       /*
00404        * Scan subsystems that aren't the currently considered subsytem.
00405        */
00406       {
00407         Part_Subsystem_t *scanSubsystem;
00408         arrayForEachItem(Part_Subsystem_t *, arrayOfPartition, j,
00409                 scanSubsystem) {
00410           st_table      *otherVertexTable = scanSubsystem->vertexNameTable;
00411 
00412           if (i != j) {
00413             st_generator        *stGen;
00414             Ntk_Node_t          *latchNode;
00415 
00416             st_foreach_item(everyFanOuts, stGen, &latchNode, NULL) {
00417               char *latchName = Ntk_NodeReadName(latchNode);
00418               if (st_lookup(otherVertexTable, latchName, NIL(char *))) {
00419                 array_insert_last(int, fanOutArray, j);
00420                 break;
00421               }
00422             } /* end of  */
00423           } /* end of if (i != j) */
00424         } /* end of arrayForEachItem(Part_Subsystem_t *) */
00425       }
00426 
00427       st_free_table(everyFanOuts);
00428 
00429       /* Update fanOutArray into the subsystem */
00430       testSubsystem->subsystemFanOut = fanOutArray;
00431     } /* end of arrayForEachItem(Part_Subsystem_t *) */
00432 
00433     /* Free dependency hash table */
00434     st_free_table(fanOutDependencies);
00435   }
00436 
00437   return(arrayOfPartition);
00438 }
00439 
00453 array_t *
00454 Part_PartCreateSubsystems(
00455   Part_SubsystemInfo_t *subInfo,
00456   array_t *arrayOfLatchNames,
00457   array_t *arrayOfGroupIndex)
00458 {
00459   if (subInfo->verbosity > 0) {
00460     if (arrayOfLatchNames != NIL(array_t)) {
00461       fprintf(vis_stdout, "Grouping: Array of latch data is given.\n");
00462       fprintf(vis_stdout,
00463         "Grouping: All latches related to the array will be grouped.\n");
00464     } else if (Part_NetworkReadPartition(subInfo->network) == NIL(graph_t)) {
00465       fprintf(vis_stdout, "Grouping: Network has no partition.\n");
00466       fprintf(vis_stdout,
00467         "Grouping: All latches in network will be grouped.\n");
00468     } else {
00469       fprintf(vis_stdout, "Grouping: Network has a partition.\n");
00470       fprintf(vis_stdout,
00471         "Grouping: All latches in partition will be grouped.\n");
00472     }
00473   }
00474   return(PartCreateSubsystem(subInfo, arrayOfLatchNames, arrayOfGroupIndex));
00475 }
00476 
00491 array_t *
00492 Part_PartCreateSubsystemsWithCTL(
00493   Part_SubsystemInfo_t *subInfo,
00494   array_t *ctlArray,
00495   array_t *fairArray,
00496   boolean dynamicIncrease,
00497   boolean dynamicAndDependency)
00498 {
00499   if (subInfo->verbosity > 0 ){
00500     fprintf(vis_stdout,"Grouping: All latches related to ");
00501     fprintf(vis_stdout,"the CTL will be grouped.\n");
00502   }
00503   return (PartCreateSubsystemWithCTL(subInfo, ctlArray, fairArray,
00504                              dynamicIncrease,dynamicAndDependency));
00505 }
00506 
00521 array_t *
00522 Part_PartCreateSubsystemsWithCtlAndLtl(
00523   Part_SubsystemInfo_t *subInfo,
00524   array_t *ctlArray,
00525   array_t *ltlArray,
00526   array_t *fairArray,
00527   boolean dynamicIncrease,
00528   boolean dynamicAndDependency,
00529   boolean strictBound)
00530 {
00531   if (subInfo->verbosity > 0 ){
00532     fprintf(vis_stdout,"Grouping: All latches related to ");
00533     fprintf(vis_stdout,"the CTL/LTL/fairness will be grouped.\n");
00534   }
00535   return (PartCreateSubsystemWithCtlAndLtl(subInfo, ctlArray, ltlArray,
00536                                            fairArray,
00537                                            dynamicIncrease,
00538                                            dynamicAndDependency,
00539                                            strictBound));
00540 }
00541 
00542 
00550 st_table *
00551 Part_PartitionSubsystemReadVertexTable(
00552   Part_Subsystem_t *partitionedSubsystem)
00553 {
00554   return(partitionedSubsystem->vertexNameTable);
00555 }
00556 
00564 array_t *
00565 Part_PartitionSubsystemReadFanIn(
00566   Part_Subsystem_t *partitionedSubsystem)
00567 {
00568   return(partitionedSubsystem->subsystemFanIn);
00569 }
00570 
00578 array_t *
00579 Part_PartitionSubsystemReadFanOut(
00580   Part_Subsystem_t *partitionedSubsystem)
00581 {
00582   return(partitionedSubsystem->subsystemFanOut);
00583 }
00584 
00585 
00595 Part_SubsystemInfo_t *
00596 Part_PartitionSubsystemInfoInit(
00597   Ntk_Network_t *network)
00598 {
00599   Part_SubsystemInfo_t *partSubInfo;
00600 
00601   partSubInfo = ALLOC(Part_SubsystemInfo_t, 1);
00602 
00603  /*
00604   * set values as defaults
00605   */
00606   partSubInfo->network = network;
00607   partSubInfo->arrayOfVertex = NIL(array_t);
00608   partSubInfo->numberOfVertex = 0;
00609   partSubInfo->partBM = Part_BFix_v;
00610   partSubInfo->con_factor = PART_SUB_CON_FACTOR;
00611   partSubInfo->cor_factor = PART_SUB_COR_FACTOR;
00612   partSubInfo->aff_factor = PART_SUB_AFF_FACTOR;
00613   partSubInfo->threshold = 0.0;
00614   partSubInfo->bound = 8;
00615   partSubInfo->verbosity = 0;
00616   partSubInfo->corMethod = Part_CorrelationDefault;
00617   partSubInfo->dupLatchTable = st_init_table(strcmp, st_strhash);
00618   partSubInfo->latchNameTable = st_init_table(strcmp, st_strhash);
00619   return(partSubInfo);
00620 }
00621 
00631 void
00632 Part_PartitionSubsystemInfoFree(
00633   Part_SubsystemInfo_t *partSubInfo)
00634 {
00635   st_generator  *stGen;
00636   char          *latchInputName;
00637   array_t       *latchNames;
00638 
00639   array_free(partSubInfo->arrayOfVertex);
00640   st_foreach_item(partSubInfo->dupLatchTable, stGen, &latchInputName,
00641         &latchNames) {
00642     array_free(latchNames);
00643   }
00644   st_free_table(partSubInfo->dupLatchTable);
00645   st_free_table(partSubInfo->latchNameTable);
00646   FREE(partSubInfo);
00647 }
00648 
00649 
00659 void
00660 Part_PartitionSubsystemFree(
00661   Part_Subsystem_t *partSubsystem)
00662 {
00663   st_free_table(partSubsystem->vertexNameTable);
00664   array_free(partSubsystem->subsystemFanIn);
00665   array_free(partSubsystem->subsystemFanOut);
00666   FREE(partSubsystem);
00667 }
00668 
00678 void
00679 Part_PartitionSubsystemInfoSetBreakingMethod(
00680   Part_SubsystemInfo_t *subInfo,
00681   Part_BMethod bMethod)
00682 {
00683   subInfo->partBM = bMethod;
00684 }
00685 
00686 
00696 void
00697 Part_PartitionSubsystemInfoSetBound(
00698   Part_SubsystemInfo_t *subInfo,
00699   int bound)
00700 {
00701   subInfo->bound = bound;
00702 }
00703 
00713 void
00714 Part_PartitionSubsystemInfoSetThreshold(
00715   Part_SubsystemInfo_t *subInfo,
00716   float threshold)
00717 {
00718   subInfo->threshold = threshold;
00719 }
00720 
00721 
00731 void
00732 Part_PartitionSubsystemInfoSetVerbosity(
00733   Part_SubsystemInfo_t *subInfo,
00734   int verbosity)
00735 {
00736   subInfo->verbosity = verbosity;
00737 }
00738 
00739 
00749 void
00750 Part_PartitionSubsystemInfoSetCorrelationMethod(
00751   Part_SubsystemInfo_t *subInfo,
00752   Part_CMethod corMethod)
00753 {
00754   subInfo->corMethod = corMethod;
00755 }
00756 
00766 void
00767 Part_PartitionSubsystemInfoSetAffinityFactor(
00768   Part_SubsystemInfo_t *subInfo,
00769   float affinity)
00770 {
00771   subInfo->aff_factor = affinity;
00772 }
00773 
00774 
00784 Part_Subsystem_t*
00785 Part_PartCreateSingleSubSystem(
00786   array_t *arrayOfNodes,
00787   Ntk_Network_t *network)
00788 {
00789   return PartCreateSingleSubSystem(arrayOfNodes, network);
00790 }
00791 
00792 
00793 /*---------------------------------------------------------------------------*/
00794 /* Definition of internal functions                                          */
00795 /*---------------------------------------------------------------------------*/
00796 
00797 
00819 array_t *
00820 PartCreateSubsystem(
00821   Part_SubsystemInfo_t *partSubInfo,
00822   array_t *arrayOfLatchNames,
00823   array_t *arrayOfGroupIndex)
00824 {
00825   char          *arrayOfDependency = NIL(char);
00826   float         *arrayOfCorrelation = NIL(float);
00827   float         *arrayOfAffinity;
00828   array_t       *arrayOfInit;
00829   st_table      *indexToPtrInfo; /* index to pointer table */
00830   st_table      *ptrToIndexInfo; /* pointer to index table */
00831   array_t       *result;
00832   Ntk_Node_t    *node;
00833   char          *functionName;
00834   char          *latchName;
00835   lsList        vertexList;
00836   lsGen         gen;
00837   int           i;
00838   vertex_t      *vertex;
00839   array_t       *initArray;
00840   array_t       *arrayOfVertex;
00841   Ntk_Network_t *network = partSubInfo->network;
00842   graph_t       *partition = Part_NetworkReadPartition(network);
00843   long          initialTime = 0;
00844   long          finalTime;
00845 
00846   if (partition == NIL(graph_t)) {
00847     if (partSubInfo->corMethod == Part_CorrelationWithBDD) {
00848        error_append("Network has no partition. Correlation ");
00849        error_append("with MDD operation can not be used.\n");
00850        return NIL(array_t);
00851     }
00852   }
00853   if (arrayOfGroupIndex != NIL(array_t)) {
00854     if (!arrayOfLatchNames) {
00855       error_append("Latch name array is not given.\n");
00856       result = NIL(array_t);
00857     }
00858     if (array_n(arrayOfLatchNames) != array_n(arrayOfGroupIndex)) {
00859       error_append("Given function names and index have different size.\n");
00860       result = NIL(array_t);
00861     }
00862   }
00863 
00864   if (arrayOfLatchNames && arrayOfGroupIndex) {
00865     result = PartCreateSubSystemWithGroupIndex(partSubInfo,
00866                 arrayOfLatchNames, arrayOfGroupIndex);
00867     return result;
00868   }
00869 
00870   arrayOfVertex = array_alloc(Ntk_Node_t *, 0);
00871 
00872   /*
00873    * Convert graph vertices into array of array of vertices.
00874    */
00875   if (partSubInfo->verbosity > 2) {
00876     fprintf(vis_stdout, "\nGroupting: List of latches\n");
00877     fprintf(vis_stdout, "----------------------------\n");
00878   }
00879   if (arrayOfLatchNames != NIL(array_t)) {
00880     Ntk_Node_t  *latchNode, *latchInputNode;
00881     char        *otherLatchName;
00882     array_t     *latchNameArray;
00883 
00884     arrayForEachItem(char *, arrayOfLatchNames, i, latchName) {
00885       latchNode = Ntk_NetworkFindNodeByName(network, latchName);
00886       latchInputNode = Ntk_LatchReadDataInput(latchNode);
00887       functionName = Ntk_NodeReadName(latchInputNode);
00888       if (partSubInfo->verbosity > 2)
00889         fprintf(vis_stdout, "%s\n", latchName);
00890       if (st_lookup(partSubInfo->latchNameTable, functionName,
00891                 &otherLatchName)) {
00892         if (st_lookup(partSubInfo->dupLatchTable, functionName,
00893             &latchNameArray)) {
00894           array_insert_last(char *, latchNameArray, latchName);
00895         } else {
00896           latchNameArray = array_alloc(char *, 0);
00897           array_insert_last(char *, latchNameArray, otherLatchName);
00898           array_insert_last(char *, latchNameArray, latchName);
00899           st_insert(partSubInfo->dupLatchTable, (char *)functionName,
00900                 (char *)latchNameArray);
00901         }
00902         continue;
00903       }
00904       st_insert(partSubInfo->latchNameTable, (char *)functionName,
00905         (char *)latchName);
00906       array_insert_last(Ntk_Node_t *, arrayOfVertex, latchInputNode);
00907     }
00908   } else if (partition == NIL(graph_t)) {
00909     Ntk_NetworkForEachNode(network, gen, node) {
00910       if (Ntk_NodeTestIsLatchDataInput(node)) {
00911         array_insert_last(Ntk_Node_t *, arrayOfVertex, node);
00912         arrayOfLatchNames = PartReadLatchNameFromLatchInput(network, node);
00913         functionName = Ntk_NodeReadName(node);
00914         latchName = array_fetch(char *, arrayOfLatchNames, 0);
00915         st_insert(partSubInfo->latchNameTable, (char *)functionName,
00916                 (char *)latchName);
00917         if (array_n(arrayOfLatchNames) > 1) {
00918           st_insert(partSubInfo->dupLatchTable, (char *)functionName,
00919                 (char *)arrayOfLatchNames);
00920           if (partSubInfo->verbosity > 2) {
00921             char *nname;
00922             arrayForEachItem(char *, arrayOfLatchNames, i, nname) {
00923               fprintf(vis_stdout, "%s\n", nname);
00924             }
00925           }
00926         } else {
00927           array_free(arrayOfLatchNames);
00928           if (partSubInfo->verbosity > 2)
00929             fprintf(vis_stdout, "%s\n", latchName);
00930         }
00931       }
00932     } /* End of Ntk_NetworkForEachNode */
00933   } else {
00934     vertexList = g_get_vertices(partition);
00935     lsForEachItem(vertexList, gen, vertex) {
00936       char *nodeName = PartVertexReadName(vertex);
00937       node = Ntk_NetworkFindNodeByName(network, nodeName);
00938       if (Ntk_NodeTestIsLatchDataInput(node)) {
00939         array_insert_last(Ntk_Node_t *, arrayOfVertex, node);
00940         arrayOfLatchNames = PartReadLatchNameFromLatchInput(network, node);
00941         functionName = Ntk_NodeReadName(node);
00942         latchName = array_fetch(char *, arrayOfLatchNames, 0);
00943         st_insert(partSubInfo->latchNameTable, (char *)functionName,
00944                 (char *)latchName);
00945         if (array_n(arrayOfLatchNames) > 1) {
00946           st_insert(partSubInfo->dupLatchTable, (char *)functionName,
00947                 (char *)arrayOfLatchNames);
00948           if (partSubInfo->verbosity > 2) {
00949             char *nname;
00950             arrayForEachItem(char *, arrayOfLatchNames, i, nname) {
00951               fprintf(vis_stdout, "%s\n", nname);
00952             }
00953           }
00954         } else {
00955           array_free(arrayOfLatchNames);
00956           if (partSubInfo->verbosity > 2)
00957             fprintf(vis_stdout, "%s\n", latchName);
00958         }
00959       }
00960     }
00961   }
00962 
00963   if (partSubInfo->verbosity > 2) {
00964     fprintf(vis_stdout, "Total # of latch data input = %d\n",
00965       array_n(arrayOfVertex));
00966   }
00967   partSubInfo->arrayOfVertex = arrayOfVertex;
00968   partSubInfo->numberOfVertex = array_n(arrayOfVertex);
00969 
00970  /*
00971   * table from index to pointer and pointer to index
00972   */
00973   indexToPtrInfo = st_init_table(st_numcmp, st_numhash);
00974   ptrToIndexInfo = st_init_table(st_ptrcmp, st_ptrhash);
00975 
00976   arrayForEachItem(Ntk_Node_t *, partSubInfo->arrayOfVertex, i, node) {
00977     st_insert(indexToPtrInfo, (char *)(long)i, (char *)node);
00978     st_insert(ptrToIndexInfo, (char *)node, (char *)(long)i);
00979   }
00980 
00981  /*
00982   * get a dependency matrix
00983   */
00984   if (partSubInfo->aff_factor > 0.0) {
00985     if (partSubInfo->verbosity > 0)
00986       initialTime = util_cpu_time();
00987     arrayOfDependency = PartCreateDependencyMatrix(partSubInfo, ptrToIndexInfo);
00988     if (partSubInfo->verbosity > 0) {
00989       finalTime = util_cpu_time();
00990       fprintf(vis_stdout, "time for computing dependency = %g\n",
00991         (double)(finalTime - initialTime) / 1000.0);
00992     }
00993   }
00994 
00995  /*
00996   * get a correlation matrix
00997   */
00998   if (partSubInfo->aff_factor != 1.0) {
00999     if (partSubInfo->verbosity > 0)
01000       initialTime = util_cpu_time();
01001     if (partSubInfo->corMethod == Part_CorrelationWithBDD)
01002       arrayOfCorrelation = PartCreateCorrelationMatrixFromBDD(partSubInfo);
01003     else if ((partSubInfo->corMethod == Part_CorrelationWithSupport) ||
01004              (partSubInfo->corMethod == Part_CorrelationDefault)) {
01005       arrayOfCorrelation = PartCreateCorrelationMatrixFromSupport(partSubInfo);
01006     }
01007     if (partSubInfo->verbosity > 0) {
01008       finalTime = util_cpu_time();
01009       fprintf(vis_stdout, "time for computing correlation = %g\n",
01010         (double)(finalTime - initialTime) / 1000.0);
01011     }
01012   }
01013 
01014   if (partSubInfo->verbosity > 2) {
01015     if (arrayOfDependency) {
01016       fprintf(vis_stdout, "\nGrouping: Dependency\n");
01017       fprintf(vis_stdout, "--------------------\n");
01018       PartPrintArrayArray(arrayOfDependency, partSubInfo->numberOfVertex, 1);
01019     }
01020     if (arrayOfCorrelation) {
01021       fprintf(vis_stdout, "\nGrouping: Correlation\n");
01022       fprintf(vis_stdout, "---------------------\n");
01023       PartPrintArrayArray(arrayOfCorrelation, partSubInfo->numberOfVertex, 0);
01024     }
01025  }
01026 
01027  /*
01028   * get an affinity matrix, arrayOfCorrelation is freed.
01029   */
01030   if (partSubInfo->verbosity > 0)
01031     initialTime = util_cpu_time();
01032   arrayOfAffinity = PartCreateAffinityMatrix(arrayOfDependency,
01033                         arrayOfCorrelation, partSubInfo);
01034   FREE(arrayOfCorrelation);
01035   if (partSubInfo->verbosity > 0) {
01036     finalTime = util_cpu_time();
01037     fprintf(vis_stdout, "time for computing affinity = %g\n",
01038       (double)(finalTime - initialTime) / 1000.0);
01039   }
01040 
01041   if (partSubInfo->verbosity > 2) {
01042     fprintf(vis_stdout, "\nGrouping: Affinity\n");
01043     fprintf(vis_stdout, "------------------\n");
01044     PartPrintArrayArray(arrayOfAffinity, partSubInfo->numberOfVertex, 0);
01045   }
01046 
01047  /*
01048   * get an initial subsysytm by searching for connected component in
01049   * vertex affinity matrix
01050   */
01051   if (partSubInfo->verbosity > 0)
01052     initialTime = util_cpu_time();
01053   arrayOfInit = PartGetConnectedComponent(arrayOfAffinity, partSubInfo,
01054                         indexToPtrInfo);
01055   if (partSubInfo->verbosity > 0) {
01056     finalTime = util_cpu_time();
01057     fprintf(vis_stdout, "time for computing connected component = %g\n",
01058       (double)(finalTime - initialTime) / 1000.0);
01059   }
01060 
01061   if (partSubInfo->verbosity > 2) {
01062     fprintf(vis_stdout, "\nGrouping: Initial connected component size\n");
01063     fprintf(vis_stdout, "------------------------------------------\n\n");
01064     arrayForEachItem(array_t *, arrayOfInit, i, initArray) {
01065       fprintf(vis_stdout, "%3d group: size = %d\n", i, array_n(initArray));
01066     }
01067   }
01068 
01069  /*
01070   * get a final subsystem by breaking big connected components and
01071   * aggregating small connected components.
01072   */
01073   if (partSubInfo->verbosity > 0)
01074     initialTime = util_cpu_time();
01075   result = PartBreakingAggregating(arrayOfInit, arrayOfAffinity, partSubInfo,
01076            ptrToIndexInfo, arrayOfDependency);
01077   if (partSubInfo->verbosity > 0) {
01078     finalTime = util_cpu_time();
01079     fprintf(vis_stdout, "time for breaking and aggregating = %g\n",
01080       (double)(finalTime - initialTime) / 1000.0);
01081   }
01082 
01083   array_free(arrayOfInit);
01084 
01085   if (partSubInfo->verbosity >= 2) {
01086     Part_Subsystem_t *sub;
01087     char *latchName;
01088     st_generator *stGen;
01089 
01090     fprintf(vis_stdout, "\nGrouping: List of subsytem latches\n");
01091     fprintf(vis_stdout, "----------------------------------\n\n");
01092     arrayForEachItem(Part_Subsystem_t *, result, i, sub) {
01093       fprintf(vis_stdout, "[Subsystem %3d]\n", i);
01094       st_foreach_item(sub->vertexNameTable, stGen, &latchName, NIL(char *)) {
01095         fprintf(vis_stdout, "%s\n", latchName);
01096       }
01097       fprintf(vis_stdout, "\n");
01098     }
01099   }
01100 
01101   if (partSubInfo->verbosity >= 1) {
01102     (void)fprintf(vis_stdout, "\nGrouping: grouping options\n");
01103     (void)fprintf(vis_stdout, "--------------------------\n\n");
01104     (void)fprintf(vis_stdout, "Threshold          : %f\n",
01105                 partSubInfo->threshold);
01106     (void)fprintf(vis_stdout, "bound              : %d\n",
01107                 partSubInfo->bound);
01108     (void)fprintf(vis_stdout, "connectivity factor: %f\n",
01109                 partSubInfo->con_factor);
01110     (void)fprintf(vis_stdout, "correlation factor : %f\n",
01111                 partSubInfo->cor_factor);
01112     (void)fprintf(vis_stdout, "affinity factor    : %f\n",
01113                 partSubInfo->aff_factor);
01114     (void)fprintf(vis_stdout, "\n");
01115   }
01116 
01117   st_free_table(indexToPtrInfo);
01118   st_free_table(ptrToIndexInfo);
01119   FREE(arrayOfDependency);
01120   FREE(arrayOfAffinity);
01121 
01122   return result;
01123 }
01124 
01125 /*---------------------------------------------------------------------------*/
01126 /* Definition of static functions                                            */
01127 /*---------------------------------------------------------------------------*/
01128 
01145 static
01146 array_t *
01147 PartCreateSubsystemWithCTL( 
01148   Part_SubsystemInfo_t *partSubInfo,
01149   array_t *ctlArray,
01150   array_t *fairArray,
01151   boolean dynamicIncrease,
01152   boolean dynamicAndDependency)
01153 {
01154   return PartCreateSubsystemWithCtlAndLtl(partSubInfo, ctlArray, NIL(array_t),
01155                                           fairArray, dynamicIncrease,
01156                                           dynamicAndDependency, FALSE);
01157 }
01158 
01180 static
01181 array_t *
01182 PartCreateSubsystemWithCtlAndLtl(
01183   Part_SubsystemInfo_t *partSubInfo,
01184   array_t *ctlArray,
01185   array_t *ltlArray,
01186   array_t *fairArray,
01187   boolean dynamicIncrease,
01188   boolean dynamicAndDependency,
01189   boolean strictBound)
01190 {
01191   int i, j, index, maxSize, maxIndex, leftNodes, numSeed;
01192   array_t *result = NIL(array_t);
01193   Ntk_Network_t *network = partSubInfo->network;
01194   lsList latchNodeList;
01195   lsGen  gen;
01196   char *arrayOfDependency = NIL(char);
01197   float *arrayOfCorrelation = NIL(float);
01198   float *arrayOfAffinity = NIL(float);
01199   array_t *arrayTemp = NIL(array_t);
01200   array_t *arrayOfVertex = NIL(array_t);
01201   array_t *arrayOfLatchNames = NIL(array_t);
01202   st_table *vertexToArrayOfLatchNames = NIL(st_table);
01203   array_t *arrayOfLatchNodeName = NIL(array_t);
01204   Ntk_Node_t *node = NIL(Ntk_Node_t);
01205   float affinity;
01206   char *name = NIL(char);
01207   st_table *indexToPtrInfo = NIL(st_table);
01208   st_table *ptrToIndexInfo = NIL(st_table);
01209   array_t *check = NIL(array_t);
01210   array_t *tempCheck = NIL(array_t);
01211   array_t *tempCC = NIL(array_t);
01212   st_generator *stGen = NIL(st_generator);
01213   array_t *arrayOfSeed = NIL(array_t);
01214   Ntk_Node_t *seedLast = NIL(Ntk_Node_t);
01215   Ntk_Node_t *seedNext = NIL(Ntk_Node_t);
01216   array_t *arrayOfBreak = NIL(array_t);
01217   array_t *arrayOfNodes = NIL(array_t);
01218   array_t *arrayOfIndex = NIL(array_t);
01219   st_table *dataInputNodes = NIL(st_table);
01220   Part_Subsystem_t *sub = NIL(Part_Subsystem_t);
01221   int numIncluded;
01222   float prevAffinity;
01223 
01224   if (ctlArray == NIL(array_t) && ltlArray == NIL(array_t)){
01225     return NIL(array_t);
01226   }
01227 
01228   /*
01229    * arrayOfLatchNodeName  <--  COI latch names
01230    */
01231   latchNodeList = lsCreate();
01232   PartGetLatchListFromCtlAndLtl(network, ctlArray, ltlArray,
01233                                 fairArray, latchNodeList, FALSE);
01234   arrayOfLatchNodeName = array_alloc(Ntk_Node_t *, 0);
01235   lsForEachItem(latchNodeList, gen, node){
01236     array_insert_last(char *, arrayOfLatchNodeName, Ntk_NodeReadName(node));
01237   }
01238   lsDestroy(latchNodeList, (void (*)(lsGeneric))0);
01239 
01240   /*
01241    * arrayOfVertex  <--  COI latch datainput nodes
01242    */
01243   array_sort(arrayOfLatchNodeName, strCompare);
01244   arrayOfVertex = array_alloc(Ntk_Node_t *, 0);
01245   vertexToArrayOfLatchNames = st_init_table(st_ptrcmp, st_ptrhash);
01246   /* multiple latch may correspond to the same  dataInput */ 
01247   arrayForEachItem(char *, arrayOfLatchNodeName, i, name){
01248     node = Ntk_NetworkFindNodeByName(network, name);
01249     node = Ntk_LatchReadDataInput(node);
01250     if (!st_lookup(vertexToArrayOfLatchNames, node, &arrayOfLatchNames) ) {
01251       arrayOfLatchNames = array_alloc(char *, 0);
01252       array_insert_last(char *, arrayOfLatchNames, name);
01253       st_insert(vertexToArrayOfLatchNames, node, arrayOfLatchNames);
01254       
01255       array_insert_last(Ntk_Node_t *, arrayOfVertex, node);
01256     }else 
01257       array_insert_last(char *, arrayOfLatchNames, name);
01258   }
01259 
01260   /*
01261    * Print a list of latch names.
01262    */
01263   if (partSubInfo->verbosity >= 2){
01264     fprintf(vis_stdout,"\nGroupting: List of latches\n");
01265     fprintf(vis_stdout,"------------------------\n\n");
01266     arrayForEachItem(char *, arrayOfLatchNodeName, i, name){
01267       fprintf(vis_stdout,"%s\n", name);
01268     }
01269   }
01270   array_free(arrayOfLatchNodeName);
01271 
01272 
01273   /*
01274    * dataInputNodes <-- formulae latch datainput nodes
01275    */
01276   latchNodeList = lsCreate();
01277   PartGetLatchListFromCtlAndLtl(network, ctlArray, ltlArray,
01278                                 fairArray, latchNodeList, TRUE);
01279   dataInputNodes = st_init_table( st_ptrcmp, st_ptrhash );
01280   lsForEachItem(latchNodeList, gen, node) {
01281     Ntk_Node_t *dataInputNode = Ntk_LatchReadDataInput(node);
01282     if (!st_is_member(dataInputNodes, (char *)dataInputNode))
01283       st_insert(dataInputNodes, (char *)dataInputNode, NIL(char));
01284   }
01285   lsDestroy(latchNodeList, (void (*)(lsGeneric))0);
01286 
01287 
01288  /*
01289   * table from index to pointer and pointer to index
01290   */
01291   partSubInfo->arrayOfVertex = arrayOfVertex;
01292   partSubInfo->numberOfVertex = array_n(arrayOfVertex);
01293 
01294   indexToPtrInfo = st_init_table(st_numcmp, st_numhash);
01295   ptrToIndexInfo = st_init_table(st_ptrcmp, st_ptrhash);
01296 
01297   arrayForEachItem(Ntk_Node_t *, partSubInfo->arrayOfVertex, i, node){
01298     st_insert(indexToPtrInfo, (char *)(long)i, (char *)node);
01299     st_insert(ptrToIndexInfo, (char *)node, (char *)(long)i);
01300   }
01301 
01302   check = array_alloc(int, partSubInfo->numberOfVertex);
01303   for(i=0;i<partSubInfo->numberOfVertex;i++){
01304     array_insert(int, check, i, 0);
01305   }
01306 
01307 
01308   leftNodes = partSubInfo->numberOfVertex;
01309   arrayOfIndex = array_alloc(int, st_count(dataInputNodes));
01310   result = array_alloc(Part_Subsystem_t *, 0);
01311 
01312 
01313   /* 
01314    * If (1) number of formula nodes is smaller than bound, or (2)
01315    * strictBound is FALSE, or (3) dynamicIncrease is TRUE, create a
01316    * subsystem and put all formula nodes in the sub-system
01317    */
01318   if ( !strictBound || st_count(dataInputNodes) <= partSubInfo->bound 
01319        || dynamicIncrease ) {
01320     int numNodesInFirstSubsys;
01321 
01322     if (!strictBound || st_count(dataInputNodes) <= partSubInfo->bound)
01323       numNodesInFirstSubsys = st_count(dataInputNodes);
01324     else 
01325       numNodesInFirstSubsys = partSubInfo->bound;
01326 
01327     arrayOfNodes = array_alloc(Ntk_Node_t *, st_count(dataInputNodes));
01328     i=0;
01329     st_foreach_item(dataInputNodes, stGen, &node, NULL) {
01330       if (i == numNodesInFirstSubsys) break;
01331       st_lookup_int(ptrToIndexInfo, node, &index);
01332       array_insert(int, check, index, 1);
01333       array_insert(int, arrayOfIndex, i, index);
01334       array_insert(Ntk_Node_t *, arrayOfNodes, i++, node);
01335     }
01336     sub = PartCreateSingleSubSystem(arrayOfNodes, network);
01337     leftNodes -= array_n(arrayOfNodes);
01338     array_insert_last(Part_Subsystem_t *, result, sub);
01339     array_free(arrayOfNodes);
01340 
01341     if (dynamicIncrease) {
01342       /* the second subsystem <-- remaining latches in dataInputTable
01343        * the thrid  subsystem <-- other COI latches
01344        */
01345       if ( dynamicAndDependency ) {
01346         if ( st_count(dataInputNodes) == numNodesInFirstSubsys )
01347           array_insert_last(Part_Subsystem_t *, result, NIL(Part_Subsystem_t));
01348         else {
01349           arrayOfNodes = array_alloc(Ntk_Node_t *, 0);
01350           i=0;
01351           st_foreach_item(dataInputNodes, stGen, &node, NULL) {
01352             st_lookup_int(ptrToIndexInfo, node, &index);
01353             if (array_fetch(int, check, index)==0){
01354               array_insert(int, check, index, 1);
01355               array_insert(int, arrayOfIndex, i, index);
01356               array_insert_last(Ntk_Node_t *, arrayOfNodes, node);
01357             }
01358           }
01359           sub = PartCreateSingleSubSystem(arrayOfNodes, network);
01360           leftNodes -= array_n(arrayOfNodes);
01361           array_insert_last(Part_Subsystem_t *, result, sub);
01362           array_free(arrayOfNodes);
01363         }
01364       }
01365       
01366       if (leftNodes > 0){
01367         arrayOfNodes = array_alloc(Ntk_Node_t *, 0);
01368         arrayForEachItem(Ntk_Node_t *, partSubInfo->arrayOfVertex, i, node){
01369           if (array_fetch(int, check, i)==0)
01370             array_insert_last(Ntk_Node_t *, arrayOfNodes, node);
01371         }
01372         sub = PartCreateSingleSubSystem(arrayOfNodes, network);
01373         array_free(arrayOfNodes);
01374       }else{
01375         sub = NIL(Part_Subsystem_t);
01376       }
01377       array_insert_last(Part_Subsystem_t *, result, sub);
01378 
01379       array_free(check);
01380       array_free(arrayOfIndex);
01381       st_free_table(ptrToIndexInfo);
01382       st_free_table(indexToPtrInfo);
01383       st_free_table(dataInputNodes);
01384       return result;
01385     } /*if dynamicIncrease*/
01386 
01387   }else {
01388     /*
01389      * If we don't want to put all formula nodes in the 1st subsystem,
01390      * we need to break them into several pieces.
01391      */
01392   }
01393 
01394   /*
01395    * get a affinity matrix (dependency matrix, correlation matrix)
01396    */
01397   arrayOfDependency = PartCreateDependencyMatrix(partSubInfo, 
01398                                                  ptrToIndexInfo);
01399 
01400   if (partSubInfo->corMethod == Part_CorrelationWithBDD)
01401     arrayOfCorrelation = PartCreateCorrelationMatrixFromBDD(partSubInfo);
01402   else if ((partSubInfo->corMethod == Part_CorrelationWithSupport) ||
01403            (partSubInfo->corMethod == Part_CorrelationDefault))
01404     arrayOfCorrelation = PartCreateCorrelationMatrixFromSupport(partSubInfo);
01405 
01406   arrayOfAffinity = PartCreateAffinityMatrix(arrayOfDependency,
01407                                              arrayOfCorrelation, 
01408                                              partSubInfo);
01409   
01410   if (partSubInfo->verbosity > 2 ){
01411     fprintf(vis_stdout,"\nGrouping: Dependency\n");
01412     fprintf(vis_stdout,"--------------------\n");
01413     PartPrintArrayArray(arrayOfDependency, partSubInfo->numberOfVertex, 1);
01414     fprintf(vis_stdout,"\nGrouping: Correlation\n");
01415     fprintf(vis_stdout,"---------------------\n");
01416     PartPrintArrayArray(arrayOfCorrelation, partSubInfo->numberOfVertex, 0);
01417     fprintf(vis_stdout,"\nGrouping: Affinity\n");
01418     fprintf(vis_stdout,"------------------\n");
01419     PartPrintArrayArray(arrayOfAffinity, partSubInfo->numberOfVertex, 0);
01420   }
01421   FREE(arrayOfDependency);
01422   FREE(arrayOfCorrelation);
01423 
01424 
01425   /* If number of formula nodes are bigger than bound, break down into
01426    * bounded sized subsystems.
01427    */
01428   if (st_count(dataInputNodes) > partSubInfo->bound && strictBound ){
01429     tempCheck = array_alloc(int, partSubInfo->numberOfVertex);
01430     tempCC = array_alloc(Ntk_Node_t *, partSubInfo->numberOfVertex);
01431     for(i=0; i<partSubInfo->numberOfVertex; i++){
01432       array_insert(int, tempCheck, i, 1);
01433       array_insert(Ntk_Node_t *, tempCC, i, (Ntk_Node_t *)0);
01434     }
01435     i = 0;
01436     st_foreach_item(dataInputNodes, stGen, &node, NULL) {
01437       st_lookup_int(ptrToIndexInfo, node, &index);
01438       array_insert(int, arrayOfIndex, i++, index);
01439       array_insert(int, check, index, 1);
01440       array_insert(int, tempCheck, index, 0);
01441       array_insert(Ntk_Node_t *, tempCC, index, node);
01442     }
01443 
01444     numSeed = (int) ceil((double)st_count(dataInputNodes)/(double)(partSubInfo->bound));
01445     arrayOfSeed = array_alloc(Ntk_Node_t *, numSeed);
01446     seedLast = PartSelectNodeOfMinSupport(tempCC,
01447                                           tempCheck, partSubInfo);
01448     array_insert(Ntk_Node_t *, arrayOfSeed, 0, seedLast);
01449     for (i=1; i< numSeed; i++){
01450       seedNext = PartSelectFarNode(seedLast, tempCC, tempCheck,
01451                                    arrayOfAffinity, ptrToIndexInfo);
01452       array_insert(Ntk_Node_t *, arrayOfSeed, i, seedNext);
01453       seedLast = seedNext;
01454     }
01455 
01456    /*
01457     * Break formula nodes, put into table and insert into final result
01458     */
01459     arrayOfBreak = PartBreakingBigConnectedComponent(tempCC, tempCheck,
01460           arrayOfSeed, arrayOfAffinity, partSubInfo, ptrToIndexInfo);
01461     array_free(tempCheck);
01462     array_free(tempCC);
01463     array_free(arrayOfSeed);
01464 
01465     assert(array_n(arrayOfBreak) > 0);
01466     maxSize = -1;
01467     maxIndex = -1; /* don't care value to suppress warning */
01468     arrayForEachItem(array_t *, arrayOfBreak, i, arrayOfNodes){
01469       if (array_n(arrayOfNodes)>maxSize){
01470         maxIndex = i;
01471         maxSize = array_n(arrayOfNodes);
01472       }
01473     }
01474     arrayOfNodes = array_fetch(array_t *, arrayOfBreak, maxIndex);
01475     sub = PartCreateSingleSubSystem(arrayOfNodes, network);
01476     leftNodes -= array_n(arrayOfNodes);
01477     array_insert_last(Part_Subsystem_t *, result, sub);
01478     arrayForEachItem(array_t *, arrayOfBreak, i, arrayOfNodes){
01479       if (i != maxIndex){
01480         sub = PartCreateSingleSubSystem(arrayOfNodes, network);
01481         leftNodes -= array_n(arrayOfNodes);
01482         array_insert_last(Part_Subsystem_t *, result, sub);
01483       }
01484     }
01485     PartArrayOfArrayFree(arrayOfBreak);
01486   }/* if (st_count(dataInputNodes) > partSubInfo->bound && strictBound)*/
01487   st_free_table(dataInputNodes);
01488 
01489 
01490   /*
01491    * Create new affinity matrix. Now new affinity is defined from
01492    * sub-system(s) created above to left nodes.
01493    */
01494   arrayTemp = NIL(array_t);
01495 
01496   if (leftNodes > 0){
01497     arrayTemp = array_alloc(float, partSubInfo->numberOfVertex);
01498     arrayForEachItem(int, arrayOfIndex, i, index){
01499       for(j=0;j<partSubInfo->numberOfVertex;j++){
01500         affinity = PartGetElementFromSymMatrix(arrayOfAffinity,index,j);
01501         if (i==0){
01502           array_insert(float, arrayTemp, j, affinity);
01503         } else {
01504            prevAffinity = array_fetch(float, arrayTemp, j);
01505            array_insert(float, arrayTemp, j, affinity + prevAffinity);
01506         }
01507       }
01508     }
01509  
01510     array_free(arrayOfIndex);
01511     FREE(arrayOfAffinity);
01512 
01513     if (partSubInfo->verbosity > 2 ){
01514       fprintf(vis_stdout,"\nGrouping:: combinded affinity\n");
01515       fprintf(vis_stdout,"------------------\n");
01516       arrayForEachItem(float, arrayTemp, i, affinity){
01517         fprintf(vis_stdout, "%.10f ", affinity);
01518       }
01519       fprintf(vis_stdout, "\n");
01520     }
01521   }else{
01522     array_free(arrayOfIndex);
01523     FREE(arrayOfAffinity);
01524   }
01525      
01526   /*
01527    * Create sub-system by choosing a nodes with biggest new affinity
01528    */
01529   while( leftNodes > 0 ){
01530     numIncluded = 0;
01531     arrayOfVertex = array_alloc(Ntk_Node_t *, 0);
01532     while ((numIncluded < partSubInfo->bound) && (leftNodes > 0)){
01533      /*
01534       * The node with maximum affinity to formula nodes is included
01535       * in next sub-system until number of nodes reaches to bound
01536       */
01537       prevAffinity = -1.0;
01538       maxIndex = 0;
01539       arrayForEachItem( float, arrayTemp, i, affinity){
01540         if ( array_fetch(int, check, i) != 1 ){
01541           if (affinity >= prevAffinity){
01542             prevAffinity = affinity;
01543             maxIndex = i;
01544           }
01545         }
01546       }
01547       st_lookup(indexToPtrInfo, (char *)(long)maxIndex, &node);
01548       array_insert_last(Ntk_Node_t *, arrayOfVertex, node);
01549       array_insert(int, check, maxIndex, 1);
01550       numIncluded++;
01551       leftNodes--;
01552     }
01553     sub = PartCreateSingleSubSystem(arrayOfVertex, network);
01554     array_free(arrayOfVertex);
01555     array_insert_last(Part_Subsystem_t *, result, sub);
01556   }
01557 
01558   array_free(check);
01559   if (arrayTemp != NIL(array_t))
01560     array_free(arrayTemp);
01561   st_free_table(ptrToIndexInfo);
01562   st_free_table(indexToPtrInfo);
01563 
01564 
01565   if (partSubInfo->verbosity >= 2){
01566     Part_Subsystem_t *sub;
01567     char *latchName;
01568     st_generator *stGen;
01569 
01570     fprintf(vis_stdout,"\nGrouping: List of subsytem latches\n");
01571     fprintf(vis_stdout,"----------------------------------\n\n");
01572     arrayForEachItem(Part_Subsystem_t *, result, i, sub){
01573       fprintf(vis_stdout,"[Subsystem %3d]\n",i);
01574       st_foreach_item(sub->vertexNameTable, stGen, &latchName, NIL(char *) ){
01575         fprintf(vis_stdout,"%s\n",latchName);
01576       }
01577       fprintf(vis_stdout,"\n");
01578     }
01579   }
01580 
01581   return result;
01582 }
01583 
01584 
01595 static char *
01596 PartCreateDependencyMatrix(
01597   Part_SubsystemInfo_t *partSubInfo,
01598   st_table *ptrToIndex)
01599 {
01600   char          *result;
01601   array_t       *arrayNodeFrom;
01602   int           i, j, k;
01603   Ntk_Node_t    *node, *latchInputNode;
01604   array_t       *arrayOfSupport;
01605   Ntk_Network_t *network = partSubInfo->network;
01606   int           index, size;
01607 
01608   size = partSubInfo->numberOfVertex;
01609   result = ALLOC(char, size * size);
01610   (void)memset((void *)result, 0, sizeof(char) * size * size);
01611 
01612   for (i = 0; i < partSubInfo->numberOfVertex; i++) {
01613     node = array_fetch(Ntk_Node_t *, partSubInfo->arrayOfVertex, i);
01614     arrayNodeFrom = array_alloc(Ntk_Node_t *, 1);
01615     array_insert(Ntk_Node_t *, arrayNodeFrom, 0, node);
01616     arrayOfSupport = Ntk_NodeComputeCombinationalSupport(network,
01617                                                          arrayNodeFrom, 
01618                                                          FALSE);
01619     array_free(arrayNodeFrom);
01620     arrayForEachItem(Ntk_Node_t *, arrayOfSupport, j, node) {
01621       if (!Ntk_NodeTestIsLatch(node))
01622         continue;
01623       latchInputNode = Ntk_LatchReadDataInput(node);
01624       if (st_lookup_int(ptrToIndex, (char *)latchInputNode, &k)) {
01625         index = i * partSubInfo->numberOfVertex + k;
01626         result[index] = 1;
01627       } else {
01628         fprintf(vis_stderr,
01629                 "** part error: can't find the latch input index.\n");
01630       }
01631     }
01632     array_free(arrayOfSupport);
01633   }
01634   return result;
01635 }
01636 
01637 
01646 static float *
01647 PartCreateCorrelationMatrixFromSupport(
01648   Part_SubsystemInfo_t *partSubInfo)
01649 {
01650   int i, j;
01651   float *result;
01652   float correlation;
01653   array_t *arrayOfSupport;
01654   st_table *tableOfSupport;
01655   array_t *arrayOfSupportTable;
01656   array_t *arrayNodeFrom;
01657   Ntk_Node_t *nodeFrom, *node;
01658   Ntk_Network_t *network = partSubInfo->network;
01659   int index;
01660 
01661   result = ALLOC(float,
01662          partSubInfo->numberOfVertex * (partSubInfo->numberOfVertex - 1) / 2);
01663 
01664   arrayOfSupportTable = array_alloc(st_table *, partSubInfo->numberOfVertex);
01665 
01666   for (i = 0; i < partSubInfo->numberOfVertex; i++) {
01667     nodeFrom = array_fetch(Ntk_Node_t *, partSubInfo->arrayOfVertex, i);
01668     arrayNodeFrom = array_alloc(Ntk_Node_t *, 1);
01669     array_insert(Ntk_Node_t *, arrayNodeFrom, 0, nodeFrom);
01670     arrayOfSupport = Ntk_NodeComputeCombinationalSupport(network,
01671                                                          arrayNodeFrom, 
01672                                                          FALSE);
01673     array_free(arrayNodeFrom);
01674     tableOfSupport = st_init_table(st_ptrcmp, st_ptrhash);
01675     arrayForEachItem(Ntk_Node_t *, arrayOfSupport, j, node) {
01676       st_insert(tableOfSupport, (char *)node, (char *)NULL);
01677     }
01678     array_free(arrayOfSupport);
01679     array_insert(st_table *, arrayOfSupportTable, i, tableOfSupport);
01680   }
01681 
01682   for (i = 1; i < partSubInfo->numberOfVertex; i++) {
01683     for (j = 0; j < i; j++) {
01684       correlation = PartVertexComputeCorrelation(i, j, arrayOfSupportTable,
01685                         partSubInfo);
01686       index = i * (i - 1) / 2 + j;
01687       result[index] = correlation;
01688     }
01689   }/* end of for */
01690 
01691   for (i = 0; i < partSubInfo->numberOfVertex; i++)
01692     st_free_table(array_fetch(st_table *, arrayOfSupportTable, i));
01693   array_free(arrayOfSupportTable);
01694 
01695   return result;
01696 }
01697 
01698 
01707 static float *
01708 PartCreateCorrelationMatrixFromBDD(
01709   Part_SubsystemInfo_t *partSubInfo)
01710 {
01711   int           i, j;
01712   float         *result;
01713   array_t       *agreeArray;
01714   array_t       *arrayOfMddArray;
01715   float         agreement;
01716   float         correlation = 0.0;
01717   char          *name;
01718   Ntk_Node_t    *node;
01719   Mvf_Function_t *mvf;
01720   vertex_t      *vertex;
01721   graph_t       *partition = Part_NetworkReadPartition(partSubInfo->network);
01722   mdd_manager   *mddmgr = PartPartitionReadMddManager(partition);
01723   int           index;
01724 
01725   result = ALLOC(float,
01726          partSubInfo->numberOfVertex * (partSubInfo->numberOfVertex - 1) / 2);
01727 
01728   arrayOfMddArray = array_alloc(array_t *, partSubInfo->numberOfVertex);
01729   for (i = 0; i < partSubInfo->numberOfVertex; i++) {
01730     node = array_fetch(Ntk_Node_t *, partSubInfo->arrayOfVertex, i);
01731     name = Ntk_NodeReadName(node);
01732     vertex = Part_PartitionFindVertexByName(partition, name);
01733     mvf = Part_VertexReadFunction(vertex);
01734     array_insert(array_t *, arrayOfMddArray, i, (array_t *)mvf);
01735   }
01736 
01737   for (i = 1; i < partSubInfo->numberOfVertex; i++) {
01738     for (j = 0; j < i; j++) {
01739       int k;
01740       agreeArray = PartVertexComputeAgreement(mddmgr, i, j, arrayOfMddArray);
01741       correlation = 0.0;
01742       arrayForEachItem(float, agreeArray, k, agreement) {
01743         correlation += (float)pow(1.0 - 4.0 * agreement * (1.0 - agreement),
01744                                     partSubInfo->cor_factor);
01745       }
01746       correlation /= (float)array_n(agreeArray);
01747       array_free(agreeArray);
01748       index = i * (i - 1) / 2 + j;
01749       result[index] = correlation;
01750     }
01751   }/* end of for */
01752 
01753   array_free(arrayOfMddArray);
01754   return result;
01755 }
01756 
01757 
01766 static float
01767 PartVertexComputeCorrelation(
01768   int index1,
01769   int index2,
01770   array_t *arrayOfInputSupportTable,
01771   Part_SubsystemInfo_t *partSubInfo)
01772 {
01773   st_generator *stGen;
01774   st_table *inputSupportTable1;
01775   st_table *inputSupportTable2;
01776   int sameSupportCount;
01777   float correlation;
01778   int inputSupportCount;
01779   Ntk_Node_t *node;
01780 
01781   sameSupportCount = 0;
01782   inputSupportTable1 = array_fetch(st_table *, arrayOfInputSupportTable,
01783                                 index1);
01784   inputSupportTable2 = array_fetch(st_table *, arrayOfInputSupportTable,
01785                                 index2);
01786 
01787   st_foreach_item(inputSupportTable1, stGen, &node, NULL) {
01788     if (st_is_member(inputSupportTable2, node)) {
01789       sameSupportCount++;
01790     }
01791   }
01792 
01793   inputSupportCount = st_count(inputSupportTable1) +
01794                         st_count(inputSupportTable2) - sameSupportCount;
01795   if (inputSupportCount != 0) {
01796     correlation = (float)pow((double)sameSupportCount /
01797                              (double)inputSupportCount,
01798                              (double)partSubInfo->cor_factor);
01799   } else {
01800     correlation = 0.0;
01801   }
01802   return correlation;
01803 }
01804 
01805 
01814 static array_t *
01815 PartVertexComputeAgreement(
01816   mdd_manager *mddMgr,
01817   int index1,
01818   int index2,
01819   array_t *arrayOfMddArray)
01820 {
01821   int i, j;
01822   float agreement;
01823   mdd_t *mddFrom, *mddTo;
01824   array_t *mddArrayFrom, *mddArrayTo;
01825   array_t *agreeArray = array_alloc(float, 0);
01826 
01827   mddArrayFrom = array_fetch(array_t *, arrayOfMddArray, index1);
01828   mddArrayTo   = array_fetch(array_t *, arrayOfMddArray, index2);
01829   arrayForEachItem(mdd_t *, mddArrayFrom, i, mddFrom) {
01830     arrayForEachItem(mdd_t *, mddArrayTo, j, mddTo) {
01831       agreement = bdd_correlation(mddFrom, mddTo);
01832       array_insert_last(float, agreeArray, agreement);
01833     }
01834   }
01835 
01836   return agreeArray;
01837 }
01838 
01839 
01855 static float *
01856 PartCreateAffinityMatrix(
01857   char *arrayOfDependency,
01858   float *arrayOfCorrelation,
01859   Part_SubsystemInfo_t *partSubInfo)
01860 {
01861   float *result;
01862   int i, j;
01863   float dep1, dep2;
01864   float connectivity = 0.0;
01865   float correlation = 0.0;
01866   float affinity;
01867   int   index;
01868 
01869   result = ALLOC(float,
01870          partSubInfo->numberOfVertex * (partSubInfo->numberOfVertex - 1) / 2);
01871 
01872   for (i = 1; i < partSubInfo->numberOfVertex; i++) {
01873     for (j = 0; j < i; j++) {
01874       if (arrayOfDependency) {
01875         dep1 = dep2 = 0.0;
01876         index = i * partSubInfo->numberOfVertex + j;
01877         if (arrayOfDependency[index] == 1)
01878         dep1 = 1.0;
01879         index = j * partSubInfo->numberOfVertex + i;
01880         if (arrayOfDependency[index] == 1)
01881         dep2 = 1.0;
01882         connectivity = (dep1 + dep2 +
01883                         (partSubInfo->con_factor - 2) * dep1 * dep2) /
01884                         partSubInfo->con_factor;
01885       } else
01886         connectivity = 0.0;
01887 
01888       if (arrayOfCorrelation)
01889         correlation = PartGetElementFromSymMatrix(arrayOfCorrelation, i, j);
01890       else
01891         correlation = 0.0;
01892 
01893      /*
01894       * affinity is a convex function of connectivity and correlation
01895       */
01896       affinity = partSubInfo->aff_factor * connectivity +
01897                 (1.0 - partSubInfo->aff_factor) * correlation;
01898       index = i * (i - 1) / 2 + j;
01899       result[index] = affinity;
01900     }
01901   }
01902   return result;
01903 }
01904 
01917 static array_t *
01918 PartGetConnectedComponent(
01919   float *arrayOfAffinity,
01920   Part_SubsystemInfo_t *partSubInfo,
01921   st_table *indexToPtr)
01922 {
01923   array_t  *arrayOfCCs; /* array of connected component */
01924   array_t  *connectedComponent;
01925   array_t  *arrayOfFrom;
01926   array_t  *arrayOfCCIndex; /* keep ccId of each vertex */
01927   float    affinity, affmax;
01928   float   affsum, density, nonZeroCount;
01929   int      next; /* serching connected component from this index */
01930   int      ccId; /* each connected component gets its own ccId */
01931   int      ccIndex;
01932   int      i, size;
01933   Ntk_Node_t *node;
01934 
01935   next = 0;   /* keep the smallest index of vertex not included in CC */
01936   ccId = 0;   /* give ccId to each CC */
01937   affmax = 0.0;
01938   affsum = 0.0;
01939   nonZeroCount = 0;
01940 
01941   arrayOfCCIndex = array_alloc(int, partSubInfo->numberOfVertex);
01942  /*
01943   * Initially, all vertecies are included in one component
01944   */
01945   for (i = 0; i < partSubInfo->numberOfVertex; i++) {
01946     array_insert(int, arrayOfCCIndex, i, 0);
01947   }
01948  /*
01949   * If the threshold is not defined, get an average of affinity in the matrix
01950   * and a density. Threshold is assigned between average of affinity and
01951   * the maximum value of affinity according to density. If the matrix is
01952   * dense(sparse), threshold goes up(goes down).
01953   */
01954   if (partSubInfo->threshold == 0.0) {
01955     size = partSubInfo->numberOfVertex * (partSubInfo->numberOfVertex - 1) / 2;
01956     for (i = 0; i < size; i++) {
01957       affinity = arrayOfAffinity[i];
01958       if (affmax < affinity) {
01959         affmax = affinity;
01960       }
01961       if (affinity > 0.0) {
01962         nonZeroCount += 1.0;
01963       }
01964       affsum += affinity;
01965     }
01966     density = nonZeroCount / pow((double)partSubInfo->numberOfVertex, 2.0);
01967     partSubInfo->threshold = (float)((affsum / nonZeroCount) +
01968                                 (affmax - affsum / nonZeroCount) * density);
01969   }
01970 
01971  /*
01972   * Get a connected component from the vertex which is pointed by 'next'
01973   * with its index. The 'next' is updated during searching CC in the function
01974   * PartFindCC
01975   */
01976   while (next < partSubInfo->numberOfVertex) {
01977     ccId++;
01978     array_insert(int, arrayOfCCIndex, next, ccId);
01979     if (next == partSubInfo->numberOfVertex - 1) {
01980       break;
01981     }
01982     arrayOfFrom = array_alloc(int, 1);
01983     array_insert(int, arrayOfFrom, 0, next);
01984     PartFindCC(&next, &ccId, arrayOfCCIndex, arrayOfAffinity, arrayOfFrom,
01985                 partSubInfo);
01986   }
01987 
01988  /*
01989   * initialize arrayOfCCs, which is the result.
01990   */
01991   arrayOfCCs = array_alloc(array_t *, ccId);
01992   for (i = 0; i < ccId; i++) {
01993     connectedComponent = array_alloc(Ntk_Node_t *, 0);
01994     array_insert(array_t *, arrayOfCCs, i, connectedComponent);
01995   }
01996 
01997  /*
01998   * change index to vertex pointer and insert into each CC
01999   */
02000   arrayForEachItem(int, arrayOfCCIndex, i, ccIndex) {
02001     st_lookup(indexToPtr, (char *)(long)i, &node);
02002     connectedComponent = array_fetch(array_t *, arrayOfCCs, ccIndex-1);
02003     array_insert_last(Ntk_Node_t *, connectedComponent, node);
02004 
02005   }
02006   array_free(arrayOfCCIndex);
02007   return arrayOfCCs;
02008 }
02009 
02020 static void
02021 PartFindCC(
02022   int *next,
02023   int *ccId,
02024   array_t *arrayOfCCIndex,
02025   float *arrayOfAffinity,
02026   array_t *arrayOfFrom,
02027   Part_SubsystemInfo_t *partSubInfo)
02028 {
02029   int i, j, from;
02030   int arrayInd;
02031   float connected;
02032   array_t *arrayOfReached;
02033 
02034  /*
02035   * Update next in order to let next keep the smallest vertex index which
02036   * is not traversed.
02037   */
02038   (*next)++;
02039   while (1) {
02040     if (*next == partSubInfo->numberOfVertex) {
02041       array_free(arrayOfFrom);
02042       return;
02043     }
02044     if (array_fetch(int, arrayOfCCIndex, *next) != 0) {
02045       (*next)++;
02046     } else {
02047       break;
02048     }
02049   }
02050 
02051   arrayOfReached = array_alloc(int, 0); /* Reached set from arrayOfFrom */
02052 
02053   /*
02054   * Find all vertecies which can be traversed from arrayOfFrom
02055   * and update next
02056   */
02057   while (array_n(arrayOfFrom) > 0) {
02058     arrayForEachItem(int, arrayOfFrom, i, from) {
02059       for (j = 0; j < partSubInfo->numberOfVertex; j++) {
02060         connected = PartGetElementFromSymMatrix(arrayOfAffinity, from, j);
02061         arrayInd = array_fetch(int, arrayOfCCIndex, j);
02062         if (connected > partSubInfo->threshold && arrayInd == 0) {
02063           array_insert_last(int, arrayOfReached, j);
02064           array_insert(int, arrayOfCCIndex, j, *ccId);
02065           if (*next == j) {
02066             (*next)++;
02067             while (1) {
02068               if (*next == partSubInfo->numberOfVertex) {
02069                 array_free(arrayOfReached);
02070                 array_free(arrayOfFrom);
02071                 return;
02072               }
02073               if (array_fetch(int, arrayOfCCIndex, *next) != 0) {
02074                 (*next)++;
02075               } else {
02076                 break;
02077               }
02078             }/* end of while */
02079           }/* end if */
02080         }
02081       }/* end for */
02082     }/* end of arrayForEachItem(arrayOfFrom) */
02083     array_free(arrayOfFrom);
02084     arrayOfFrom = arrayOfReached;  /* Traverse with new reached set */
02085     arrayOfReached = array_alloc(int, 0);
02086   }/* end of while */
02087   array_free(arrayOfFrom);
02088   array_free(arrayOfReached);
02089   return;
02090 }
02091 
02104 static array_t *
02105 PartBreakingAggregating(
02106   array_t       *arrayOfInit,
02107   float         *arrayOfAffinity,
02108   Part_SubsystemInfo_t *partSubInfo,
02109   st_table      *ptrToIndex,
02110   char          *arrayOfDependency)
02111 {
02112   array_t       *arrayOfAggregate;
02113   array_t       *arrayOfSeed;
02114   array_t       *arrayOfSmall;
02115   array_t       *arrayOfBreak;
02116   array_t       *arrayOfFinal;
02117   array_t       *arrayOfCCVertex;
02118   array_t       *arrayVertex;
02119   array_t       *arrayOfNew;
02120   array_t       *cc;
02121   array_t       *ccCheck; /* check cc which is included in final result */
02122   float         *groupDependency;
02123   st_table      *tableOfCC;
02124   float         groupDep;
02125   int           i, j, k, l;
02126   array_t       *arrayOfLatchNames;
02127   char          *name;
02128   Part_Subsystem_t *sub;
02129   Part_Subsystem_t *subIn;
02130   Part_Subsystem_t *subOut;
02131   Ntk_Node_t    *seedlast, *seednext, *node;
02132   char          *funcName;
02133 
02134   arrayOfSmall = array_alloc(array_t *, 0);
02135   arrayOfFinal = array_alloc(Part_Subsystem_t *, 0);
02136   arrayOfCCVertex = array_alloc(array_t *, 0);
02137 
02138   if (partSubInfo->bound == 0) {
02139     partSubInfo->bound = partSubInfo->numberOfVertex / array_n(arrayOfInit);
02140   }
02141 
02142   arrayForEachItem(array_t *, arrayOfInit, i, cc) {
02143     if (array_n(cc) > partSubInfo->bound) {
02144      /*
02145       * If cc has more vertecies than bound, calculate how many seeds are needed
02146       * and get those seeds which are far away from each others
02147       */
02148       ccCheck = array_alloc(int, array_n(cc));
02149       for (j = 0; j < array_n(cc); j++) {
02150         array_insert(int, ccCheck, j, 0);
02151       }
02152 
02153      /*
02154       * The first seed is the vertex which has the smallest support and
02155       * choose the next vertex which is the farthest from last seed
02156       */
02157       arrayOfSeed = array_alloc(Ntk_Node_t *, 0);
02158       seedlast = PartSelectNodeOfMinSupport(cc, ccCheck, partSubInfo);
02159       array_insert_last(Ntk_Node_t *, arrayOfSeed, seedlast);
02160       for (j = 1; j < ceil((double)array_n(cc) / (double)(partSubInfo->bound));
02161            j++) {
02162         seednext = PartSelectFarNode(seedlast, cc, ccCheck, arrayOfAffinity,
02163                         ptrToIndex);
02164         array_insert_last(Ntk_Node_t *, arrayOfSeed, seednext);
02165         seedlast = seednext;
02166       }
02167      /*
02168       * Break big CC, put into table and insert into final result
02169       */
02170       arrayOfBreak = PartBreakingBigConnectedComponent(cc, ccCheck,
02171             arrayOfSeed, arrayOfAffinity, partSubInfo, ptrToIndex);
02172       array_free(ccCheck);
02173       array_free(arrayOfSeed);
02174 
02175       arrayForEachItem(array_t *, arrayOfBreak, j, arrayOfNew) {
02176         if (array_n(arrayOfNew) == partSubInfo->bound) {
02177           tableOfCC = st_init_table(strcmp, st_strhash);
02178           arrayVertex = array_alloc(Ntk_Node_t *, array_n(arrayOfNew));
02179           arrayForEachItem(Ntk_Node_t *, arrayOfNew, k, node) {
02180             funcName = Ntk_NodeReadName(node);
02181             if (st_lookup(partSubInfo->dupLatchTable, funcName,
02182                 &arrayOfLatchNames)) {
02183               arrayForEachItem(char *, arrayOfLatchNames, l, name) {
02184                 st_insert(tableOfCC, (char *)name, (char *)NULL);
02185               }
02186             } else {
02187               if (st_lookup(partSubInfo->latchNameTable, (char *)funcName,
02188                         (char **)&name)) {
02189                 st_insert(tableOfCC, (char *)name, (char *)NULL);
02190               } else
02191                 error_append("can't find the latch name.");
02192             }
02193             array_insert(Ntk_Node_t *, arrayVertex, k, node);
02194           }
02195           sub = ALLOC(Part_Subsystem_t, 1);
02196           sub->vertexNameTable = tableOfCC;
02197           sub->subsystemFanIn = array_alloc(int, 0);
02198           sub->subsystemFanOut = array_alloc(int, 0);
02199           array_insert_last(Part_Subsystem_t *, arrayOfFinal, sub);
02200           array_insert_last(array_t *, arrayOfCCVertex, arrayVertex);
02201           array_free(arrayOfNew);
02202         } else {
02203           array_insert_last(array_t *, arrayOfSmall, arrayOfNew);
02204         }
02205       }/* end of arrayForEachItem(arrayOfBreak) */
02206       array_free(arrayOfBreak);
02207       array_free(cc);
02208     } else if (array_n(cc) < partSubInfo->bound) {
02209      /*
02210       * If cc has less nodes than bound, put into arrayOfSmall
02211       */
02212       array_insert_last(array_t *, arrayOfSmall, cc);
02213     } else {
02214      /*
02215       * If cc has same number of verteices as bound, put into table and
02216       * insert into final result
02217       */
02218       tableOfCC = st_init_table(strcmp, st_strhash);
02219       arrayVertex = array_alloc(Ntk_Node_t *, array_n(cc));
02220       arrayForEachItem(Ntk_Node_t *, cc, j, node) {
02221         funcName = Ntk_NodeReadName(node);
02222         if (st_lookup(partSubInfo->dupLatchTable, funcName,
02223                 &arrayOfLatchNames)) {
02224           arrayForEachItem(char *, arrayOfLatchNames, l, name) {
02225             st_insert(tableOfCC, (char *)name, (char *)NULL);
02226           }
02227         } else {
02228           if (st_lookup(partSubInfo->latchNameTable, (char *)funcName,
02229                 (char **)&name)) {
02230             st_insert(tableOfCC, (char *)name, (char *)NULL);
02231           } else
02232             error_append("can't find the latch name.");
02233         }
02234         array_insert(Ntk_Node_t *, arrayVertex, j, node);
02235       }
02236       sub = ALLOC(Part_Subsystem_t, 1);
02237       sub->vertexNameTable = tableOfCC;
02238       sub->subsystemFanIn = array_alloc(int, 0);
02239       sub->subsystemFanOut = array_alloc(int, 0);
02240       array_insert_last(Part_Subsystem_t *, arrayOfFinal, sub);
02241       array_insert_last(array_t *, arrayOfCCVertex, arrayVertex);
02242       array_free(cc);
02243     }
02244   }
02245 
02246  /*
02247   * aggregate small cc, put into table and insert into final resault
02248   */
02249   arrayOfAggregate = PartAggregating(arrayOfSmall, arrayOfAffinity,
02250                         partSubInfo, ptrToIndex);
02251 
02252   array_free(arrayOfSmall);
02253 
02254   arrayForEachItem(array_t *, arrayOfAggregate, i, arrayOfNew) {
02255     tableOfCC = st_init_table(strcmp, st_strhash);
02256     arrayVertex = array_alloc(Ntk_Node_t *, array_n(arrayOfNew));
02257     arrayForEachItem(Ntk_Node_t *, arrayOfNew, j, node) {
02258       funcName = Ntk_NodeReadName(node);
02259       if (st_lookup(partSubInfo->dupLatchTable, funcName,
02260                     &arrayOfLatchNames)) {
02261         arrayForEachItem(char *, arrayOfLatchNames, l, name) {
02262           st_insert(tableOfCC, (char *)name, (char *)NULL);
02263         }
02264       } else {
02265         if (st_lookup(partSubInfo->latchNameTable, (char *)funcName,
02266                 (char **)&name)) {
02267           st_insert(tableOfCC, (char *)name, (char *)NULL);
02268         } else
02269           error_append("can't find the latch name.");
02270       }
02271       array_insert(Ntk_Node_t *, arrayVertex, j, node);
02272     }
02273     sub = ALLOC(Part_Subsystem_t, 1);
02274     sub->vertexNameTable = tableOfCC;
02275     sub->subsystemFanIn = array_alloc(int, 0);
02276     sub->subsystemFanOut = array_alloc(int, 0);
02277     array_insert_last(Part_Subsystem_t *, arrayOfFinal, sub);
02278     array_insert_last(array_t *, arrayOfCCVertex, arrayVertex);
02279     array_free(arrayOfNew);
02280   }/* end of arrayForEachItem(arrayOfAggregate) */
02281 
02282   array_free(arrayOfAggregate);
02283 
02284  /*
02285   * Get group dependency, which is dependency between two subsystems from
02286   * dependency between vertecies
02287   */
02288   groupDependency = PartGetGroupMatrixRegular(arrayOfCCVertex,
02289                         arrayOfDependency, ptrToIndex,
02290                         partSubInfo->numberOfVertex);
02291 
02292   if (partSubInfo->verbosity >= 2) {
02293     int index;
02294     fprintf(vis_stdout, "\nGrouping: Group Dependency\n");
02295     fprintf(vis_stdout, "--------------------------\n");
02296     for (i = 0; i < array_n(arrayOfCCVertex); i++) {
02297       for (j = 0; j < array_n(arrayOfCCVertex); j++) {
02298         index = i * array_n(arrayOfCCVertex) + j;
02299         fprintf(vis_stdout, "%4.3f ", groupDependency[index]);
02300       }
02301       fprintf(vis_stdout, "\n");
02302     }
02303   }
02304 
02305   for (i = 0; i < array_n(arrayOfCCVertex); i++) {
02306     subIn = array_fetch(Part_Subsystem_t *, arrayOfFinal, i);
02307     for (j = 0; j < array_n(arrayOfCCVertex); j++) {
02308       subOut = array_fetch(Part_Subsystem_t *, arrayOfFinal, j);
02309       if (i != j) {
02310         int     index;
02311 
02312         index = i * array_n(arrayOfCCVertex) + j;
02313         groupDep = groupDependency[index];
02314         if (groupDep > 0.0) {
02315           array_insert_last(int, subIn ->subsystemFanIn, j);
02316           array_insert_last(int, subOut->subsystemFanOut, i);
02317         }
02318       }
02319     }
02320   }
02321   PartArrayOfArrayFree(arrayOfCCVertex);
02322   FREE(groupDependency);
02323   return arrayOfFinal;
02324 }
02325 
02338 static array_t *
02339 PartCreateSubSystemWithGroupIndex(
02340   Part_SubsystemInfo_t *partSubInfo,
02341   array_t *arrayOfLatchNames,
02342   array_t *arrayOfGroupIndex)
02343 {
02344   int           i, j;
02345   array_t       *result;
02346   char          *latchName;
02347   array_t       *arrayOfGroupVertex;
02348   array_t       *arrayOfVertex;
02349   array_t       *arrayOfLatchDataInputNames;
02350   Ntk_Node_t    *node, *latchNode, *latchInputNode;
02351   Part_Subsystem_t *sub;
02352   st_table      *groupIndexTable;
02353   st_table      **faninIndexTable, **fanoutIndexTable;
02354   char          *name;
02355   array_t       *arrayOfSupport;
02356   st_generator  *stGen;
02357   int           nLatches;
02358   int           nGroups = 0;
02359   int           preIndex, newIndex;
02360   long          index;
02361   char          *otherLatchName;
02362   array_t       *latchNameArray;
02363 
02364   nLatches = array_n(arrayOfLatchNames);
02365 
02366   /* reassign group index with counting the number of groups */
02367   groupIndexTable = st_init_table(st_numcmp, st_numhash);
02368   preIndex = -1;
02369   arrayForEachItem(int, arrayOfGroupIndex, i, index) {
02370     if (index == preIndex ||
02371         st_lookup_int(groupIndexTable, (char *)index, &newIndex)) {
02372       if (index != newIndex)
02373         array_insert(int, arrayOfGroupIndex, i, newIndex);
02374     } else {
02375       st_insert(groupIndexTable, (char *)index, (char *)(long)nGroups);
02376       newIndex = nGroups++;
02377       if (index != newIndex)
02378         array_insert(int, arrayOfGroupIndex, i, newIndex);
02379     }
02380     preIndex = (int) index;
02381   }
02382   st_free_table(groupIndexTable);
02383 
02384   groupIndexTable = st_init_table(strcmp, st_strhash);
02385   faninIndexTable = ALLOC(st_table *, nGroups);
02386   fanoutIndexTable = ALLOC(st_table *, nGroups);
02387   for (i = 0; i < nGroups; i++) {
02388     faninIndexTable[i] = st_init_table(st_numcmp, st_numhash);
02389     fanoutIndexTable[i] = st_init_table(st_numcmp, st_numhash);
02390   }
02391 
02392   /* makes an array of latch input names from latch names */
02393   arrayOfLatchDataInputNames = array_alloc(char *, 0);
02394   arrayForEachItem(char *, arrayOfLatchNames, i, latchName) {
02395     latchNode = Ntk_NetworkFindNodeByName(partSubInfo->network, latchName);
02396     latchInputNode = Ntk_LatchReadDataInput(latchNode);
02397     name = Ntk_NodeReadName(latchInputNode);
02398     array_insert_last(char *, arrayOfLatchDataInputNames, name);
02399   }
02400 
02401   result = array_alloc(Part_Subsystem_t *, nGroups);
02402   arrayOfGroupVertex = array_alloc(array_t *, nGroups);
02403 
02404   /* creates subsystems */
02405   for (i = 0; i < nGroups; i++) {
02406     sub = ALLOC(Part_Subsystem_t, 1);
02407     sub->vertexNameTable = st_init_table(strcmp, st_strhash);
02408     sub->subsystemFanIn = array_alloc(int, 0);
02409     sub->subsystemFanOut = array_alloc(int, 0);
02410     arrayOfVertex = array_alloc(Ntk_Node_t *, 0);
02411     array_insert(Part_Subsystem_t *, result, i, sub);
02412     array_insert(array_t *, arrayOfGroupVertex, i, arrayOfVertex);
02413   }
02414 
02415   /* makes group index table and fills in the vertex name table */
02416   for (i = 0; i < nLatches; i++) {
02417     index = (long) array_fetch(int, arrayOfGroupIndex, i);
02418     name = array_fetch(char *, arrayOfLatchDataInputNames, i);
02419     latchName = array_fetch(char *, arrayOfLatchNames, i);
02420 
02421     sub = array_fetch(Part_Subsystem_t *, result, (int) index);
02422     latchNode = Ntk_NetworkFindNodeByName(partSubInfo->network, latchName);
02423     latchName = Ntk_NodeReadName(latchNode);
02424     st_insert(sub->vertexNameTable, (char *)latchName, (char *)NULL);
02425 
02426     if (st_lookup(partSubInfo->latchNameTable, name, &otherLatchName)) {
02427       if (st_lookup(partSubInfo->dupLatchTable, name, &latchNameArray)) {
02428         array_insert_last(char *, latchNameArray, latchName);
02429       } else {
02430         latchNameArray = array_alloc(char *, 0);
02431         array_insert_last(char *, latchNameArray, otherLatchName);
02432         array_insert_last(char *, latchNameArray, latchName);
02433         st_insert(partSubInfo->dupLatchTable, name, latchNameArray);
02434       }
02435       continue;
02436     }
02437 
02438     st_insert(partSubInfo->latchNameTable, name, latchName);
02439     st_insert(groupIndexTable, name, (char *)index);
02440 
02441     arrayOfVertex = array_fetch(array_t *, arrayOfGroupVertex, (int)index);
02442     node = Ntk_NetworkFindNodeByName(partSubInfo->network, name);
02443     array_insert_last(Ntk_Node_t *, arrayOfVertex, node);
02444   }
02445 
02446   /* computes fanin and fanout table for each group */
02447   for (i = 0; i < nGroups; i++) {
02448     arrayOfVertex = array_fetch(array_t *, arrayOfGroupVertex, i);
02449     arrayOfSupport = Ntk_NodeComputeCombinationalSupport(partSubInfo->network,
02450         arrayOfVertex, FALSE);
02451     arrayForEachItem(Ntk_Node_t *, arrayOfSupport, j, node) {
02452       if (!Ntk_NodeTestIsLatch(node))
02453         continue;
02454       name = Ntk_NodeReadName(Ntk_LatchReadDataInput(node));
02455       if (st_lookup(groupIndexTable, name, &index)) {
02456         if (index == i)
02457           continue;
02458         st_insert(faninIndexTable[i], (char *)index, NIL(char));
02459         st_insert(fanoutIndexTable[index], (char *)(long)i, NIL(char));
02460       }
02461     }
02462     array_free(arrayOfSupport);
02463   }
02464 
02465   /* makes fanin and fanout array for each subsystem */
02466   for (i = 0; i < nGroups; i++) {
02467     sub = array_fetch(Part_Subsystem_t *, result, i);
02468     st_foreach_item(faninIndexTable[i], stGen, &index, NULL) {
02469       array_insert_last(int, sub->subsystemFanIn, (int) index);
02470     }
02471     st_free_table(faninIndexTable[i]);
02472     array_sort(sub->subsystemFanIn, numCompare);
02473     st_foreach_item(fanoutIndexTable[i], stGen, &index, NULL) {
02474       array_insert_last(int, sub->subsystemFanOut, (int) index);
02475     }
02476     st_free_table(fanoutIndexTable[i]);
02477     array_sort(sub->subsystemFanOut, numCompare);
02478   }
02479 
02480   FREE(faninIndexTable);
02481   FREE(fanoutIndexTable);
02482   array_free(arrayOfLatchDataInputNames);
02483   st_free_table(groupIndexTable);
02484   PartArrayOfArrayFree(arrayOfGroupVertex);
02485   return result;
02486 }
02487 
02498 static array_t *
02499 PartBreakingBigConnectedComponent(
02500   array_t *arrayOfCC,
02501   array_t *ccCheck,
02502   array_t *arrayOfSeed,
02503   float *arrayOfAffinity,
02504   Part_SubsystemInfo_t *partSubInfo,
02505   st_table *ptrToIndex)
02506 {
02507   array_t *result;    /* array of groups with the proper size */
02508   array_t *resultRow; /* a group with the proper size */
02509   array_t *arrayTemp;
02510   array_t *seedFull;  /* array of seeds */
02511   int i, count;
02512   int totalCount;     /* how many vertixes are already computed */
02513   int indexOfSeed;    /* index of the seed which is closest from the vertex */
02514   Ntk_Node_t *seed, *variable, *pick;
02515 
02516   result = array_alloc(array_t *, array_n(arrayOfSeed));
02517 
02518   for (i = 0; i < array_n(arrayOfSeed); i++) {
02519     arrayTemp = array_alloc(Ntk_Node_t *, 0);
02520     seed = array_fetch(Ntk_Node_t *, arrayOfSeed, i);
02521     array_insert_last(Ntk_Node_t *, arrayTemp, seed);
02522     array_insert(array_t *, result, i, arrayTemp);
02523   }
02524 
02525   switch (partSubInfo->partBM) {
02526    /*
02527     * Breaking Static Round Robin Seed Choice
02528     * Fixed order of seeds and each seed find the closest vertex
02529     */
02530     case Part_BSRR_s:
02531       totalCount = array_n(arrayOfSeed);
02532       arrayForEachItem(Ntk_Node_t *, arrayOfSeed, i, seed) {
02533         count = 1;
02534         resultRow = array_fetch(array_t *, result, i);
02535         while ((count < partSubInfo->bound) &&
02536               (totalCount < array_n(arrayOfCC))) {
02537           pick = PartSelectCloseNode(seed, arrayOfCC, ccCheck,
02538                         arrayOfAffinity, ptrToIndex);
02539           array_insert_last(Ntk_Node_t *, resultRow, pick);
02540           count++;
02541           totalCount++;
02542           seed = pick;
02543         }
02544       }
02545       break;
02546    /*
02547     * Breaking Fixed Order State Variable Choice
02548     * Fixed order of vertecies and each vertex find the closest seed
02549     */
02550     case Part_BFix_v:
02551      /*
02552       * Fixed order of nodes and each node find the closest seed
02553       */
02554       seedFull = array_alloc(int, 0);
02555       for (i = 0; i < array_n(arrayOfSeed); i++) {
02556         array_insert_last(int, seedFull, 1);
02557 
02558       }
02559       arrayForEachItem(Ntk_Node_t *, arrayOfCC, i, variable) {
02560         if (array_fetch(int, ccCheck, i) != 1) {
02561           indexOfSeed = PartSelectCloseSeedIndex(variable, arrayOfSeed,
02562                 arrayOfAffinity, ptrToIndex, seedFull, partSubInfo->bound);
02563           resultRow = array_fetch(array_t *, result, indexOfSeed);
02564           array_insert_last(Ntk_Node_t *, resultRow, variable);
02565           array_insert(int, ccCheck, i, 1);
02566         }
02567       }
02568       array_free(seedFull);
02569       break;
02570     default:
02571       break;
02572   }
02573   return result;
02574 }
02575 
02576 
02588 static array_t *
02589 PartAggregating(
02590   array_t *arrayOfSmall,
02591   float *arrayOfAffinity,
02592   Part_SubsystemInfo_t *partSubInfo,
02593   st_table *ptrToIndex)
02594 {
02595   float *arrayOfGroupAff;
02596   array_t *result;
02597   array_t *arraySeed;
02598   array_t *arraySeedIndex;
02599   array_t *arrayTemp;
02600   array_t *arrayRow;
02601   array_t *cc;
02602   array_t *ccCheck;
02603   array_t *seed;
02604   int i, j;
02605   int count;  /* total number of vertices in all small connected components */
02606   int pick, keepInd;
02607   int seedLast, seedNew, seedIndex;
02608   int numberOfSeed;
02609   boolean isDone;
02610   array_t *keep = array_alloc(int, 0);
02611 
02612   count = 0;
02613 
02614   arrayForEachItem(array_t *, arrayOfSmall, i, cc) {
02615     count += array_n(cc);
02616   }
02617 
02618   numberOfSeed = (int) ceil((double)count/(double)partSubInfo->bound);
02619 
02620   arrayOfGroupAff = PartGetGroupMatrixSym(arrayOfSmall, arrayOfAffinity,
02621                         ptrToIndex);
02622 
02623   if (partSubInfo->verbosity >= 2) {
02624     fprintf(vis_stdout, "\nGrouping: Group affinity of initial ");
02625     fprintf(vis_stdout, "connected component\n");
02626     fprintf(vis_stdout, "------------------------------------");
02627     fprintf(vis_stdout, "-------------------\n");
02628     PartPrintArrayArray(arrayOfGroupAff, array_n(arrayOfSmall), 0);
02629   }
02630 
02631   ccCheck = array_alloc(int, array_n(arrayOfSmall));
02632   for (i = 0; i < array_n(arrayOfSmall); i++) {
02633     array_insert(int, ccCheck, i, 0);
02634   }
02635 
02636  /*
02637   * The first seed is the cc which has minmum support and the next
02638   * is the farthest cc
02639   */
02640   seedLast = PartSelectCCIndexOfMinSupport(arrayOfSmall,
02641              ccCheck, partSubInfo);
02642 
02643   result = array_alloc(array_t *, numberOfSeed);
02644   arraySeed = array_alloc(array_t *, numberOfSeed);
02645   arraySeedIndex = array_alloc(int, numberOfSeed);
02646 
02647   for (i = 0; i < numberOfSeed; i++) {
02648     seed = array_fetch(array_t *, arrayOfSmall, seedLast);
02649     array_insert(array_t *, arraySeed, i, seed);
02650     array_insert(int, arraySeedIndex, i, seedLast);
02651     array_insert(array_t *, result, i, seed);
02652     if (i<numberOfSeed-1) {
02653       seedNew = PartSelectFarCCIndex(seedLast, arrayOfSmall, arrayOfGroupAff,
02654                         partSubInfo, ccCheck);
02655       seedLast = seedNew;
02656     }
02657   }
02658 
02659  /*
02660   * Static Round Robin Cluster Seed: Fixed order of seed and each seed
02661   * choose the closest connected component
02662   */
02663   isDone = FALSE;
02664   count = array_n(arraySeed);
02665   while ((!isDone) && count < array_n(arrayOfSmall)) {
02666     isDone = TRUE;
02667     arrayForEachItem(int, arraySeedIndex, i, seedIndex) {
02668       arrayRow = array_fetch(array_t *, result, i);
02669       pick = PartSelectCloseCCIndex(seedIndex, arrayOfSmall,
02670              arrayOfGroupAff, ccCheck);
02671       count++;
02672       /* check if not all cc is assigned */
02673       if (pick != -1) {
02674         arrayTemp = array_fetch(array_t *, arrayOfSmall, pick);
02675         if (array_n(array_fetch(array_t *, arrayOfSmall, seedIndex)) +
02676             array_n(arrayTemp) <= partSubInfo->bound) {
02677           array_append(arrayRow, arrayTemp);
02678           array_free(arrayTemp);
02679           isDone = FALSE;
02680         } else {
02681          /*
02682           * If pick cc is too big to be appended to seed, find new cc
02683           */
02684           array_insert_last(int, keep, pick);
02685           pick = PartSelectCloseCCIndex(seedIndex, arrayOfSmall,
02686                         arrayOfGroupAff, ccCheck);
02687           while (pick != -1) {
02688             arrayTemp = array_fetch(array_t *, arrayOfSmall, pick);
02689             if (array_n(array_fetch(array_t *, arrayOfSmall, seedIndex)) +
02690                 array_n(arrayTemp) <= partSubInfo->bound) {
02691               array_append(arrayRow, arrayTemp);
02692               array_free(arrayTemp);
02693               isDone = FALSE;
02694               break;
02695             } else {
02696               array_insert_last(int, keep, pick);
02697               pick = PartSelectCloseCCIndex(seedIndex, arrayOfSmall,
02698                         arrayOfGroupAff, ccCheck);
02699             }
02700           } /* end while */
02701           if (pick == -1) {
02702             count--;
02703           }
02704           arrayForEachItem(int, keep, j, keepInd) {
02705             array_insert(int, ccCheck, keepInd, 0);
02706           }
02707           array_free(keep);
02708           keep = array_alloc(int, 0);
02709         } /* end if */
02710       } else {
02711         count--;
02712       }/* end if */
02713     }/* end arrayForEachItem */
02714    /*
02715     * If all seeds fail to find suitable cc and not all cc is assigned,
02716     *  get a new seed.
02717     */
02718     if (count < array_n(arrayOfSmall) && isDone) {
02719       seedIndex = PartSelectCCIndexOfMinSupport(arrayOfSmall,
02720                         ccCheck, partSubInfo);
02721       count++;
02722       seed = array_fetch(array_t *, arrayOfSmall, seedIndex);
02723       array_insert_last(array_t *, arraySeed, seed);
02724       array_insert_last(int, arraySeedIndex, seedIndex);
02725       array_insert_last(array_t *, result, seed);
02726       isDone = FALSE;
02727     }
02728   }
02729   array_free(arraySeed);
02730   array_free(arraySeedIndex);
02731   array_free(keep);
02732   array_free(ccCheck);
02733   FREE(arrayOfGroupAff);
02734   return result;
02735 }
02736 
02744 static Ntk_Node_t *
02745 PartSelectCloseNode(
02746   Ntk_Node_t    *seed,
02747   array_t       *arrayOfCC,
02748   array_t       *ccCheck,
02749   float         *arrayOfAffinity,
02750   st_table      *ptrToIndex)
02751 {
02752   int           i;
02753   float         affinity;
02754   float         big; /* The bigest value of affinity of vertecies*/
02755   int           bigInd; /* the index of node with the biggest affinity */
02756   int           col;
02757   int           row;
02758   Ntk_Node_t    *node, *pick;
02759 
02760   big = -1.0;
02761   bigInd = 0; /* to avoid warning */
02762   pick = NIL(Ntk_Node_t);
02763 
02764   st_lookup_int(ptrToIndex, (char *)seed, &row);
02765 
02766   arrayForEachItem(Ntk_Node_t *, arrayOfCC, i, node) {
02767     if (array_fetch(int, ccCheck, i) != 1) {
02768       st_lookup_int(ptrToIndex, (char *)node, &col);
02769       affinity = PartGetElementFromSymMatrix(arrayOfAffinity, row, col);
02770       if (affinity > big) {
02771          big = affinity;
02772          pick = node;
02773          bigInd = i;
02774       }
02775     }
02776   }
02777   array_insert(int, ccCheck, bigInd, 1);
02778   return pick;
02779 }
02780 
02788 static int
02789 PartSelectCloseSeedIndex(
02790   Ntk_Node_t    *variable,
02791   array_t       *arrayOfSeed,
02792   float         *arrayOfAffinity,
02793   st_table      *ptrToIndex,
02794   array_t       *seedFull,
02795   int           bound)
02796 {
02797   float         affinity;
02798   int           i;
02799   float         big;
02800   int           pick, row, col;
02801   Ntk_Node_t    *node;
02802 
02803   big = -1.0;
02804   pick = -1;
02805 
02806   st_lookup_int(ptrToIndex, (char *)variable, &row);
02807 
02808   arrayForEachItem(Ntk_Node_t *, arrayOfSeed, i, node) {
02809     st_lookup_int(ptrToIndex, (char *)node, &col);
02810     affinity = PartGetElementFromSymMatrix(arrayOfAffinity, row, col);
02811     if (affinity > big && array_fetch(int, seedFull, i) < bound) {
02812       big = affinity;
02813       pick = i;
02814     }
02815   }
02816   array_insert(int, seedFull, pick, array_fetch(int, seedFull, pick) + 1);
02817   return pick;
02818 }
02819 
02827 static Ntk_Node_t *
02828 PartSelectFarNode(
02829   Ntk_Node_t *seed,
02830   array_t *cc,
02831   array_t *ccCheck,
02832   float *arrayOfAffinity,
02833   st_table *ptrToIndex)
02834 {
02835   float         affinity;
02836   int           i;
02837   float         small; /* the smallest affinity of vertecies */
02838   int           smallInd; /* index of vertex with the smallest affinity */
02839   int           col;
02840   int           row;
02841   Ntk_Node_t    *node, *pick;
02842 
02843   small = (float)BIG_NUMBER;
02844   smallInd = 0; /* to avoid warning */
02845   pick = NIL(Ntk_Node_t);
02846 
02847   st_lookup_int(ptrToIndex, (char *)seed, &row);
02848   arrayForEachItem(Ntk_Node_t *, cc, i, node) {
02849     if (array_fetch(int, ccCheck, i) != 1) {
02850       st_lookup_int(ptrToIndex, (char *)node, &col);
02851       affinity = PartGetElementFromSymMatrix(arrayOfAffinity, row, col);
02852       if (affinity < small) {
02853          small = affinity;
02854          pick = node;
02855          smallInd = i;
02856       }
02857     }
02858   }
02859   array_insert(int, ccCheck, smallInd, 1);
02860   return pick;
02861 }
02862 
02863 
02876 static float *
02877 PartGetGroupMatrixRegular(
02878   array_t *arrayOfCluster,
02879   char *arrayOfGivenMatrix,
02880   st_table *ptrToIndex,
02881   int nVertices)
02882 {
02883   float         *arrayOfGroupMatrix;  /* final result */
02884   array_t       *arrayClusterRow;
02885   array_t       *arrayClusterCol;
02886   float         subSum;
02887   int           row, col, i, j, k, l;
02888   Ntk_Node_t    *nodeRow, *nodeCol;
02889   int           index, size;
02890 
02891   size = array_n(arrayOfCluster);
02892   arrayOfGroupMatrix = ALLOC(float, size * size);
02893 
02894   arrayForEachItem(array_t *, arrayOfCluster, i, arrayClusterRow) {
02895     arrayForEachItem(array_t *, arrayOfCluster, j, arrayClusterCol) {
02896       if (i != j) {
02897         subSum = 0.0;
02898         arrayForEachItem(Ntk_Node_t *, arrayClusterRow, k, nodeRow) {
02899           st_lookup_int(ptrToIndex, (char *)nodeRow, &row);
02900           arrayForEachItem(Ntk_Node_t *, arrayClusterCol, l, nodeCol) {
02901             st_lookup_int(ptrToIndex, (char *)nodeCol, &col);
02902             index = row * nVertices + col;
02903             if (arrayOfGivenMatrix[index] == 1)
02904               subSum += 1.0;
02905           }
02906         }
02907         index = i * size + j;
02908         arrayOfGroupMatrix[index] = subSum /
02909                 (float)(array_n(arrayClusterRow) * array_n(arrayClusterCol));
02910       } else {
02911         index = i * size + j;
02912         arrayOfGroupMatrix[index] = 0.0;
02913       }
02914     }
02915   }
02916   return arrayOfGroupMatrix;
02917 }
02918 
02930 static float *
02931 PartGetGroupMatrixSym(
02932   array_t  *arrayOfCluster,
02933   float  *arrayOfGivenMatrix,
02934   st_table *ptrToIndex)
02935 {
02936   float         *arrayOfGroupMatrix;  /* final result */
02937   array_t       *arrayClusterRow;
02938   array_t       *arrayClusterCol;
02939   float         subSum;
02940   int           row, col, i, j, k, l;
02941   Ntk_Node_t    *nodeRow, *nodeCol;
02942   int           index, size;
02943 
02944   size = array_n(arrayOfCluster);
02945   arrayOfGroupMatrix = ALLOC(float, size * (size - 1) / 2);
02946 
02947   for (i = 0; i < size; i++) {
02948     arrayClusterRow = array_fetch(array_t *, arrayOfCluster, i);
02949     for (j = 0; j < i; j++) {
02950       arrayClusterCol = array_fetch(array_t *, arrayOfCluster, j);
02951       if (i == j) {
02952         index = i * (i - 1) / 2 + j;
02953         arrayOfGroupMatrix[index] = 0.0;
02954       } else {
02955         subSum = 0.0;
02956         arrayForEachItem(Ntk_Node_t *, arrayClusterRow, k, nodeRow) {
02957           st_lookup_int(ptrToIndex, (char *)nodeRow, &row);
02958           arrayForEachItem(Ntk_Node_t *, arrayClusterCol, l, nodeCol) {
02959             st_lookup_int(ptrToIndex, (char *)nodeCol, &col);
02960             subSum += PartGetElementFromSymMatrix(arrayOfGivenMatrix, row, col);
02961           }
02962         }
02963         index = i * (i - 1) / 2 + j;
02964         arrayOfGroupMatrix[index] = subSum /
02965                 (float)((array_n(arrayClusterRow)) * array_n(arrayClusterCol));
02966       }
02967     }
02968   }
02969   return arrayOfGroupMatrix;
02970 }
02971 
02979 static int
02980 PartSelectCCIndexOfMinSupport(
02981   array_t *arrayOfSmall,
02982   array_t *ccCheck,
02983   Part_SubsystemInfo_t *partSubInfo)
02984 {
02985   array_t       *cc;
02986   array_t       *support;
02987   int           i, count, minCount, minIndex;
02988 
02989   minCount = BIG_NUMBER;
02990   minIndex = -1;
02991 
02992   for (i = 0; i < array_n(ccCheck); i++) {
02993     if (array_fetch(int, ccCheck, i) != 1) {
02994       cc = array_fetch(array_t *, arrayOfSmall, i);
02995       support = Ntk_NodeComputeCombinationalSupport(
02996         partSubInfo->network, cc, TRUE);
02997       count = array_n(support);
02998       array_free(support);
02999       if (count < minCount) {
03000         minIndex = i;
03001         minCount = count;
03002       }
03003     }
03004   }
03005   if (minIndex != -1) {
03006     array_insert(int, ccCheck, minIndex, 1);
03007   }
03008   return minIndex;
03009 }
03010 
03019 static Ntk_Node_t *
03020 PartSelectNodeOfMinSupport(
03021   array_t *cc,
03022   array_t *ccCheck,
03023   Part_SubsystemInfo_t *partSubInfo)
03024 {
03025   array_t       *support;
03026   array_t       *nodeArray;
03027   int           i, minInd, count, min;
03028   Ntk_Node_t    *node;
03029   Ntk_Node_t    *minNode = NIL(Ntk_Node_t);
03030 
03031   if (array_n(cc) == 0) {
03032     return NIL(Ntk_Node_t);
03033   }
03034 
03035   min = BIG_NUMBER;
03036   minInd = 0; /* to avoid warning */
03037   arrayForEachItem(Ntk_Node_t *, cc, i, node) {
03038     if (array_fetch(int, ccCheck, i) != 1) {
03039       nodeArray = array_alloc(Ntk_Node_t *, 1);
03040       array_insert(Ntk_Node_t *, nodeArray, 0, node);
03041       support = Ntk_NodeComputeCombinationalSupport(
03042                         partSubInfo->network, nodeArray, TRUE);
03043       count = array_n(support);
03044       if (count < min) {
03045         minNode = node;
03046         min = count;
03047         minInd = i;
03048       }
03049       array_free(support);
03050       array_free(nodeArray);
03051     }
03052   }
03053   array_insert(int, ccCheck, minInd, 1);
03054   return minNode;
03055 }
03056 
03065 static int
03066 PartSelectFarCCIndex(
03067   int seedIndex,
03068   array_t *arrayOfSmall,
03069   float *arrayOfGroupAff,
03070   Part_SubsystemInfo_t *partSubInfo,
03071   array_t *ccCheck)
03072 {
03073   array_t *col;
03074   int i;
03075   float groupAff;
03076   float min;
03077   int minIndex;
03078 
03079   min = (float)BIG_NUMBER;
03080   minIndex = -1;
03081 
03082   arrayForEachItem(array_t *, arrayOfSmall, i, col) {
03083     if (array_fetch(int, ccCheck, i) != 1) {
03084       groupAff = PartGetElementFromSymMatrix(arrayOfGroupAff, seedIndex, i);
03085       if (groupAff < min) {
03086         minIndex = i;
03087         min = groupAff;
03088       }
03089     }
03090   }
03091   if (minIndex != -1) {
03092     array_insert(int, ccCheck, minIndex, 1);
03093   }
03094   return minIndex;
03095 }
03096 
03105 static int
03106 PartSelectCloseCCIndex(
03107   int seedIndex,
03108   array_t *arrayOfSmall,
03109   float *arrayOfGroupAff,
03110   array_t *ccCheck)
03111 {
03112   int i;
03113   float groupAff;
03114   float max;
03115   int maxIndex;
03116 
03117   max = -1.0;
03118   maxIndex = -1;
03119 
03120   for (i = 0; i < array_n(ccCheck); i++) {
03121     if (array_fetch(int, ccCheck, i) != 1) {
03122       groupAff = PartGetElementFromSymMatrix(arrayOfGroupAff, seedIndex, i);
03123       if (groupAff > max) {
03124         maxIndex = i;
03125         max = groupAff;
03126       }
03127     }
03128   }
03129   if (maxIndex != -1) {
03130     array_insert(int, ccCheck, maxIndex, 1);
03131   }
03132   return maxIndex;
03133 }
03134 
03135 
03144 static Part_Subsystem_t*
03145 PartCreateSingleSubSystem(
03146   array_t *arrayOfNodes,
03147   Ntk_Network_t *network)
03148 {
03149   int           i, j;
03150   char          *name;
03151   Ntk_Node_t    *node;
03152   st_table      *vertexNameTable;
03153   array_t       *arrayOfLatchNames;
03154   Part_Subsystem_t *sub;
03155 
03156   if (array_n(arrayOfNodes) == 0 || arrayOfNodes == NIL(array_t)) {
03157     return NIL(Part_Subsystem_t);
03158   }
03159 
03160   vertexNameTable = st_init_table(strcmp, st_strhash);
03161   arrayForEachItem(Ntk_Node_t *, arrayOfNodes, i, node) {
03162     arrayOfLatchNames = PartReadLatchNameFromLatchInput(network, node);
03163     arrayForEachItem(char *, arrayOfLatchNames, j, name) {
03164       st_insert(vertexNameTable, (char *)name, (char *)NULL);
03165     }
03166     array_free(arrayOfLatchNames);
03167   }
03168   sub = ALLOC(Part_Subsystem_t, 1);
03169   sub->vertexNameTable = vertexNameTable;
03170   sub->subsystemFanIn = NIL(array_t);
03171   sub->subsystemFanOut = NIL(array_t);
03172 
03173   return sub;
03174 }
03175 
03184 static array_t *
03185 PartReadLatchNameFromLatchInput(
03186   Ntk_Network_t *network,
03187   Ntk_Node_t *latchInput)
03188 {
03189   lsGen         gen;
03190   Ntk_Node_t    *latch, *temp1;
03191   char          *latchName = NIL(char);
03192   array_t       *arrayOfLatchNames;
03193 
03194   arrayOfLatchNames = array_alloc(char *, 0);
03195   Ntk_NetworkForEachLatch(network, gen, latch) {
03196     temp1 = Ntk_LatchReadDataInput(latch);
03197     if (temp1 == latchInput) {
03198       latchName = Ntk_NodeReadName(latch);
03199       array_insert_last(char *, arrayOfLatchNames, latchName);
03200     }
03201   } /* end of Ntk_NetworkForEachLatch */
03202 
03203   return arrayOfLatchNames;
03204 }
03205 
03213 static void
03214 PartArrayOfArrayFree(
03215   array_t *arrayOfMatrix)
03216 {
03217   array_t *arrayRow;
03218   int i;
03219 
03220   arrayForEachItem(array_t *, arrayOfMatrix, i, arrayRow) {
03221     array_free(arrayRow);
03222   }
03223   array_free(arrayOfMatrix);
03224 }
03225 
03233 static float
03234 PartGetElementFromSymMatrix(
03235   float *matrix,
03236   int i,
03237   int j)
03238 {
03239   int index;
03240 
03241   if (i == j)
03242     return(0.0);
03243   if (i < j) {
03244     int tmp;
03245 
03246     tmp = i;
03247     i = j;
03248     j = tmp;
03249   }
03250   index = i * (i - 1) / 2 + j;
03251   return(matrix[index]);
03252 }
03253 
03264 static void
03265 PartPrintArrayArray(
03266   void *arrayArray,
03267   int nVertices,
03268   int type)
03269 {
03270   int i, j;
03271   float num;
03272   int index;
03273 
03274   if (type == 0) { /* numerical data * symetric matrix */
03275     for (i = 0; i < nVertices; i++) {
03276       for (j = 0; j < nVertices; j++) {
03277         num = PartGetElementFromSymMatrix((float *)arrayArray, i, j);
03278         fprintf(vis_stdout, "%4.3f ", num);
03279       }
03280       fprintf(vis_stdout, "\n");
03281     }
03282   } else if (type == 1) { /* char data & regular */
03283     for (i = 0; i < nVertices; i++) {
03284       for (j = 0; j < nVertices; j++) {
03285         index = i * nVertices + j;
03286         if (((char *)arrayArray)[index] == 1) {
03287           fprintf(vis_stdout, "1 ");
03288         } else {
03289           fprintf(vis_stdout, "0 ");
03290         }
03291       }
03292       fprintf(vis_stdout, "\n");
03293     }
03294   }
03295   fprintf(vis_stdout, "\n");
03296 }
03297 
03307 static int
03308 strCompare(
03309   const void *name1,
03310   const void *name2)
03311 {
03312     return(strcmp(*(char **)name1, *(char **)name2));
03313 } /* end of strCompare */
03314 
03324 static int
03325 numCompare(
03326   const void *num1,
03327   const void *num2)
03328 {
03329     return(*(int *)num1 > *(int *)num2);
03330 } /* end of strCompare */