source: vis_dev/vis-2.3/src/part/partGroup.c

Last change on this file was 14, checked in by cecile, 13 years ago

vis2.3

File size: 105.5 KB
Line 
1/**CFile***********************************************************************
2
3  FileName    [partGroup.c]
4
5  PackageName [part]
6
7  Synopsis    [Routines for grouping vertices.]
8
9  Description [The first method groups vertices based on the hierachy of the
10  system.  Normally, the hierachy is formed in the early phase of the
11  design. We use this information to group latches. The method expects the
12  high level description languages to BLIF conversion utilities such as vl2mv
13  to preserve the original hierachy. The second method is explained in the
14  following paper.
15    H. Cho, G. D. Hachtel, E. Macii, B. Plessier, F. Somenzi," A
16    Structural Approach to State Space Decomposition for Approximate
17    Reachability Analysis," ICCD, pp.236-239, 1994. Traversal," EDAC.
18  This method groups vertices based on the latch dependency(relation between
19  latches) and the latch correlation(resemblance of latches in terms of the
20  support variables.]
21
22  Author      [Woohyuk Lee, Jae-Young Jang]
23
24  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
25  All rights reserved.
26
27  Permission is hereby granted, without written agreement and without license
28  or royalty fees, to use, copy, modify, and distribute this software and its
29  documentation for any purpose, provided that the above copyright notice and
30  the following two paragraphs appear in all copies of this software.
31
32  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
33  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
34  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
35  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36
37  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
38  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
39  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
40  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
41  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
42
43******************************************************************************/
44
45#include "partInt.h"
46
47static char rcsid[] UNUSED = "$Id: partGroup.c,v 1.51 2005/04/28 14:15:50 fabio Exp $";
48
49/*---------------------------------------------------------------------------*/
50/* Constant declarations                                                     */
51/*---------------------------------------------------------------------------*/
52
53
54/*---------------------------------------------------------------------------*/
55/* Type declarations                                                         */
56/*---------------------------------------------------------------------------*/
57
58
59/*---------------------------------------------------------------------------*/
60/* Structure declarations                                                    */
61/*---------------------------------------------------------------------------*/
62
63
64/*---------------------------------------------------------------------------*/
65/* Variable declarations                                                     */
66/*---------------------------------------------------------------------------*/
67
68
69/*---------------------------------------------------------------------------*/
70/* Macro declarations                                                        */
71/*---------------------------------------------------------------------------*/
72
73
74/**AutomaticStart*************************************************************/
75
76/*---------------------------------------------------------------------------*/
77/* Static function prototypes                                                */
78/*---------------------------------------------------------------------------*/
79
80static char * PartCreateDependencyMatrix(Part_SubsystemInfo_t *partSubInfo, st_table *ptrToIndex);
81static float * PartCreateCorrelationMatrixFromSupport(Part_SubsystemInfo_t *partSubInfo);
82static float * PartCreateCorrelationMatrixFromBDD(Part_SubsystemInfo_t *partSubInfo);
83static float PartVertexComputeCorrelation(int index1, int index2, array_t *arrayOfInputSupportTable, Part_SubsystemInfo_t *partSubInfo);
84static array_t * PartVertexComputeAgreement(mdd_manager *mddMgr, int index1, int index2, array_t *arrayOfBddArray);
85static float * PartCreateAffinityMatrix(char *arrayOfConnectivity, float *arrayOfCorrelation, Part_SubsystemInfo_t *partSubInfo);
86static array_t * PartGetConnectedComponent(float *arrayOfAffinity, Part_SubsystemInfo_t *partSubInfo, st_table *indexToPtr);
87static void PartFindCC(int *next, int *ccId, array_t *arrayOfCCIndex, float *arrayOfAffinity, array_t *arrayOfFrom, Part_SubsystemInfo_t *PartSubInfo);
88static array_t * PartBreakingAggregating(array_t *arrayOfInit, float *arrayOfAffinity, Part_SubsystemInfo_t *partSubInfo, st_table *ptrToIndex, char *arrayOfDependency);
89static array_t * PartBreakingBigConnectedComponent(array_t *arrayOfCC, array_t *ccCheck, array_t *arrayOfSeed, float *arrayOfAffinity, Part_SubsystemInfo_t *partSubInfo, st_table *ptrToIndex);
90static array_t * PartAggregating(array_t *arrayOfSmall, float *arrayOfAffinity, Part_SubsystemInfo_t *partSubInfo, st_table *ptrToIndex);
91static array_t * PartCreateSubSystemWithGroupIndex(Part_SubsystemInfo_t *partSubInfo, array_t *arrayOfLatchNames, array_t *arrayOfGroupIndex);
92static Ntk_Node_t * PartSelectCloseNode(Ntk_Node_t *seed, array_t *arrayOfCC, array_t *ccCheck, float *arrayOfAffinity, st_table *ptrToIndex);
93static int PartSelectCloseSeedIndex(Ntk_Node_t *variable, array_t *arrayOfSeed, float *arrayOfAffinity, st_table *ptrToIndex, array_t *seedFull, int bound);
94static Ntk_Node_t * PartSelectFarNode(Ntk_Node_t *seed, array_t *cc, array_t *ccCheck, float *arrayOfAffinity, st_table *ptrToIndex);
95static float * PartGetGroupMatrixRegular(array_t *arrayOfCluster, char *arrayOfGivenMatrix, st_table *ptrToIndex, int nVertices);
96static float * PartGetGroupMatrixSym(array_t *arrayOfCluster, float *arrayOfGivenMatrix, st_table *ptrToIndex);
97static int PartSelectCCIndexOfMinSupport(array_t *arrayOfSmall, array_t *ccCheck, Part_SubsystemInfo_t *partSubInfo);
98static Ntk_Node_t * PartSelectNodeOfMinSupport(array_t *cc, array_t *ccCheck, Part_SubsystemInfo_t *partSubInfo);
99static int PartSelectFarCCIndex(int seedIndex, array_t *arrayOfSmall, float *arrayOfGroupAff, Part_SubsystemInfo_t *partSubInfo, array_t *ccCheck);
100static int PartSelectCloseCCIndex(int seedIndex, array_t *arrayOfSmall, float *arrayOfGroupAff, array_t *ccCheck);
101static Part_Subsystem_t* PartCreateSingleSubSystem(array_t *arrayOfNodes, Ntk_Network_t *network);
102static array_t * PartReadLatchNameFromLatchInput(Ntk_Network_t *network, Ntk_Node_t *latchInput);
103static void PartArrayOfArrayFree(array_t *arrayOfMatrix);
104static float PartGetElementFromSymMatrix(float *matrix, int i, int j);
105static void PartPrintArrayArray(void *arrayOfMatrix, int nVertices, int type);
106static int strCompare(const void * name1, const void * name2);
107static int numCompare(const void * num1, const void * num2);
108static array_t *PartCreateSubsystemWithCTL(Part_SubsystemInfo_t *, array_t *, array_t *, boolean , boolean );
109static array_t *PartCreateSubsystemWithCtlAndLtl(Part_SubsystemInfo_t *, array_t *, array_t *, array_t *, boolean , boolean, boolean );
110
111
112/**AutomaticEnd***************************************************************/
113
114
115/*---------------------------------------------------------------------------*/
116/* Definition of exported functions                                          */
117/*---------------------------------------------------------------------------*/
118
119/**Function********************************************************************
120
121  Synopsis    [From the given latch data inputs, create array of
122  sub-partitions.]
123
124  Description [From the given latch data inputs, create array of sub-partitions
125  of vertices. Latch data inputs are given as "latchDataInputNames" and
126  includes subset of all latches in a system.  Since the vertices are defined
127  as the latch-input nodes, one may think of the process as grouping of
128  latches in the network.  "amc_sizeof_group" value may be set by the user by
129  using the set command from the vis shell. The function uses this value to
130  limit the number of vertices(latches) in a single group(subsystem). More
131  vertices in a subsystem implies its representation is closer to the exact
132  system.  When the value is not given by the user, the default value of 8
133  vertices(latches) is used. The routine uses hierachical grouping method.
134  That is, the latches in the same sub-processes(i.e. same .subckt in BLIF
135  format), are grouped together whenever possible.
136
137  Initial partition must be performed before executing this routine.]
138
139  SideEffects []
140
141  SeeAlso     []
142
143******************************************************************************/
144array_t *
145Part_PartGroupVeriticesBasedOnHierarchy(
146  Ntk_Network_t *network,
147  array_t *latchDataInputNames)
148{
149  graph_t       *partition;
150  array_t       *arrayOfPartition = NIL(array_t);
151  array_t       *arrayOfGroups = NIL(array_t);
152  array_t       *arrayOfLatches = NIL(array_t);
153  array_t       *arrayOfLatchSort = NIL(array_t);
154  st_table      *vertexTable = NIL(st_table);
155  int           numOfVertex, reset;
156  int           i, j, k;
157  char          *numberOfVertexInGroup;
158  char          *flagValue;
159  char          *latchName, *name;
160  st_table      *latchDataInputNameTable;
161  Part_Subsystem_t *testSubsystem;
162
163  partition = Part_NetworkReadPartition(network);
164  if (partition == NIL(graph_t)) {
165    error_append("Network has no partition. Cannot create sub machines.");
166    return (NIL(array_t));
167  }
168
169  /*
170   * Convert graph of vertices into array of table of vertices.
171   */
172
173  numberOfVertexInGroup = Cmd_FlagReadByName("amc_sizeof_group");
174  if (numberOfVertexInGroup != NIL(char)) {
175    numOfVertex = atoi(numberOfVertexInGroup);
176    reset = atoi(numberOfVertexInGroup);
177  }
178  else {
179    /* default value */
180    numOfVertex = 8;
181    reset = 8;
182  }
183
184  latchDataInputNameTable = st_init_table(strcmp, st_strhash);
185
186  arrayForEachItem(char *, latchDataInputNames, i, name) {
187    st_insert(latchDataInputNameTable, (char *)name, (char *)NULL);
188  }
189
190  /*
191   * In the first phase, group latches by the processes.
192   * That is, group latches that are within same sub-circuit.
193   */
194
195  arrayOfGroups = array_alloc(array_t *, 0);
196
197  {
198    Ntk_Node_t  *latch;
199    lsGen       gen;
200    char        *groupName = util_strsav(" ");
201
202    arrayOfLatchSort = array_alloc(char *, 0);
203    Ntk_NetworkForEachLatch(network, gen, latch) {
204      Ntk_Node_t *latchInput = Ntk_LatchReadDataInput(latch);
205      char *latchInputName = Ntk_NodeReadName(latchInput);
206      vertex_t *vertex = Part_PartitionFindVertexByName(partition,
207                                                        latchInputName);
208      if ((vertex != NIL(vertex_t)) &&
209          (st_lookup(latchDataInputNameTable, latchInputName, NIL(char *)))) {
210        array_insert_last(char *, arrayOfLatchSort, Ntk_NodeReadName(latch));
211      }
212    }
213    array_sort(arrayOfLatchSort, strCompare);
214
215    arrayForEachItem(char *, arrayOfLatchSort, i, latchName) {
216      char *suffixLatchName, *currentGroupName;
217
218      suffixLatchName = util_strsav(latchName);
219
220      /* Extract out group name into the string "groupName" and leave
221         rest in suffixLatchName. */
222
223      currentGroupName = strtok(suffixLatchName, ".");
224
225      if (strcmp(groupName, currentGroupName)) {
226        if (strcmp(groupName, " ")) {
227          array_insert_last(array_t *, arrayOfGroups, arrayOfLatches);
228        }
229        FREE(groupName);
230        groupName = util_strsav(currentGroupName);
231        arrayOfLatches = array_alloc(char *, 0);
232      }
233      FREE(currentGroupName);
234      array_insert_last(char *, arrayOfLatches, latchName);
235    }
236    FREE(groupName);
237  }
238
239  array_free(arrayOfLatchSort);
240  st_free_table(latchDataInputNameTable);
241
242  /* Fill in the last arrayOfLatches */
243  array_insert_last(array_t *, arrayOfGroups, arrayOfLatches);
244
245  /*
246   * In the second phase, further break latch group into
247   * smaller group size according to the "amc_sizeof_group".
248   */
249
250  arrayOfPartition = array_alloc(Part_Subsystem_t *, 0);
251
252  arrayForEachItem(array_t *, arrayOfGroups, k, arrayOfLatches) {
253    char        *latchName;
254    int         numOfLatches = array_n(arrayOfLatches);
255
256    arrayForEachItem(char *, arrayOfLatches, i, latchName) {
257
258      if (numOfVertex == reset)
259        vertexTable = st_init_table(strcmp, st_strhash);
260
261      st_insert(vertexTable, latchName, (char *)NULL);
262
263      if ((numOfVertex == 1) || (numOfLatches == i+1)) {
264        /* testSubsystem freed by calling function  */
265        testSubsystem = ALLOC(Part_Subsystem_t, 1);
266        testSubsystem->vertexNameTable = vertexTable;
267        testSubsystem->subsystemFanIn = NIL(array_t);
268        testSubsystem->subsystemFanOut = NIL(array_t);
269
270        array_insert_last(Part_Subsystem_t *, arrayOfPartition, testSubsystem);
271        numOfVertex = reset;
272      }
273      else
274        numOfVertex--;
275    } /* End of arrayForEachItem(arrayOfLatches) */
276  } /* End of arrayForEachItem(arrayOfGroups) */
277
278  /* Free arrayOfGroups, arrayOfLatches */
279  arrayForEachItem(array_t *, arrayOfGroups, i, arrayOfLatches) {
280    array_free(arrayOfLatches);
281  }
282  array_free(arrayOfGroups);
283
284  /*
285   * Currently this function is used only from amc package.
286   * When the function gets popular use parameter passing rather that this
287   * ugly method.
288   */
289  flagValue = Cmd_FlagReadByName("amc_use_MBM");
290  if (flagValue != NIL(char)) {
291    array_t     *latchNodeArray;
292    array_t     *faninNodeArray;
293    array_t     *faninLatchArray;
294
295    /*
296     * Fill in the subsystem dependencies using the latch dependencies.
297     */
298
299    arrayForEachItem(Part_Subsystem_t *, arrayOfPartition, i, testSubsystem) {
300      array_t           *fanInArray = array_alloc(int, 0);
301      st_table          *vertexTable = testSubsystem->vertexNameTable;
302      st_generator      *stGen;
303      char              *latchName;
304      Ntk_Node_t        *latchNode;
305
306      latchNodeArray = array_alloc(Ntk_Node_t *, 0);
307      faninLatchArray = array_alloc(Ntk_Node_t *, 0);
308
309      /* Convert table of latch names into array of latch nodes */
310      st_foreach_item(vertexTable, stGen, &latchName, NIL(char *)) {
311        latchNode = Ntk_NetworkFindNodeByName(network, latchName);
312        array_insert_last(Ntk_Node_t *, latchNodeArray, latchNode);
313      }
314
315      /* Find the transitive fanin nodes */
316      faninNodeArray = Ntk_NodeComputeCombinationalSupport(network,
317                        latchNodeArray, FALSE);
318
319      /* Find the transitive fanin latches from the fanin nodes */
320      if (array_n(faninNodeArray) != 0) {
321        int x;
322        arrayForEachItem(Ntk_Node_t *, faninNodeArray, x, latchNode) {
323          if (Ntk_NodeTestIsLatch(latchNode) == TRUE) {
324            array_insert_last(Ntk_Node_t *, faninLatchArray, latchNode);
325          }
326        }
327      }
328
329      /* Find the fanin subsystems */
330      if (array_n(faninLatchArray) != 0) {
331        Part_Subsystem_t *scanSubsystem;
332        int y;
333
334        arrayForEachItem(Part_Subsystem_t *, arrayOfPartition, j,
335                scanSubsystem) {
336          /* Scan subsystems that aren't the currently considered subsytem */
337          st_table      *otherVertexTable = scanSubsystem->vertexNameTable;
338
339          if (i != j) {
340            arrayForEachItem(Ntk_Node_t *, faninLatchArray, y, latchNode) {
341              char *latchName = Ntk_NodeReadName(latchNode);
342              if (st_lookup(otherVertexTable, latchName, NIL(char *))) {
343                array_insert_last(int, fanInArray, j);
344                break;
345              }
346            } /* end of arrayForEachItem(Ntk_Node_t *) */
347          } /* end of if (i != j) */
348        }
349      } /* end of if (array_n(faninLatchArray) != 0) */
350
351      /* Update fanInArray into the subsystem */
352      testSubsystem->subsystemFanIn = fanInArray;
353
354      array_free(latchNodeArray);
355      array_free(faninNodeArray);
356      array_free(faninLatchArray);
357    } /* end of arrayForEachItem(Part_Subsystem_t *) */
358  } /* end of if (!flagValue) */
359
360  /*
361   * Currently this function is used only from amc package.
362   * When the function gets popular use parameter passing rather that this
363   * ugly method.
364   */
365
366  flagValue = Cmd_FlagReadByName("amc_use_MBM");
367  if (flagValue != NIL(char)) {
368    st_table *fanOutDependencies = Ntk_NetworkComputeLatchDependencies(network);
369
370    /*
371     * Fill in the fanout dependencies of subsystems.
372     */
373    arrayForEachItem(Part_Subsystem_t *, arrayOfPartition, i, testSubsystem) {
374      array_t           *fanOutArray = array_alloc(int, 0);
375      st_table          *vertexTable = testSubsystem->vertexNameTable;
376      st_generator      *stGen;
377      char              *latchName;
378      st_table          *everyFanOuts = st_init_table(st_ptrcmp, st_ptrhash);
379
380      /*
381       * For the latches in this subsystem,
382       * find all latches that transitively fanouts from the latches
383       * inside this subsystem. Store it in a hash table, "everyFanOuts".
384       */
385      st_foreach_item(vertexTable, stGen, &latchName, NIL(char *)) {
386        Ntk_Node_t      *latchNode;
387        lsList          fanOutLatchList;
388        lsGen           gen;
389        lsGeneric       data;
390
391        latchNode = Ntk_NetworkFindNodeByName(network, latchName);
392        st_lookup(fanOutDependencies, latchNode, &fanOutLatchList);
393
394        /* Obtain all fanout latches coming from latches of this subsystem */
395        gen = lsStart(fanOutLatchList);
396        while (lsNext(gen, &data, LS_NH) == LS_OK) {
397          st_insert(everyFanOuts, data, NULL);
398        }
399        (void) lsFinish(gen);
400        lsDestroy(fanOutLatchList, (void (*) (lsGeneric)) NULL);
401      }
402
403      /*
404       * Scan subsystems that aren't the currently considered subsytem.
405       */
406      {
407        Part_Subsystem_t *scanSubsystem;
408        arrayForEachItem(Part_Subsystem_t *, arrayOfPartition, j,
409                scanSubsystem) {
410          st_table      *otherVertexTable = scanSubsystem->vertexNameTable;
411
412          if (i != j) {
413            st_generator        *stGen;
414            Ntk_Node_t          *latchNode;
415
416            st_foreach_item(everyFanOuts, stGen, &latchNode, NULL) {
417              char *latchName = Ntk_NodeReadName(latchNode);
418              if (st_lookup(otherVertexTable, latchName, NIL(char *))) {
419                array_insert_last(int, fanOutArray, j);
420                break;
421              }
422            } /* end of  */
423          } /* end of if (i != j) */
424        } /* end of arrayForEachItem(Part_Subsystem_t *) */
425      }
426
427      st_free_table(everyFanOuts);
428
429      /* Update fanOutArray into the subsystem */
430      testSubsystem->subsystemFanOut = fanOutArray;
431    } /* end of arrayForEachItem(Part_Subsystem_t *) */
432
433    /* Free dependency hash table */
434    st_free_table(fanOutDependencies);
435  }
436
437  return(arrayOfPartition);
438}
439
440/**Function********************************************************************
441
442  Synopsis    [Create sub-systems based on latch relation]
443
444  Description [Create sub-systems based on latch dependency, connectivity,
445  correlation, and affinity. If arrayOfFunctionNames(latch data inputs) is
446  given, only those nodes are considered to make sub-systems. If arrayOfGroup-
447  Index(Ii) is given with arrayOfFunctionNames(Fi), Fi is put in Ii'th
448  sub-system.]
449
450  SideEffects []
451
452******************************************************************************/
453array_t *
454Part_PartCreateSubsystems(
455  Part_SubsystemInfo_t *subInfo,
456  array_t *arrayOfLatchNames,
457  array_t *arrayOfGroupIndex)
458{
459  if (subInfo->verbosity > 0) {
460    if (arrayOfLatchNames != NIL(array_t)) {
461      fprintf(vis_stdout, "Grouping: Array of latch data is given.\n");
462      fprintf(vis_stdout,
463        "Grouping: All latches related to the array will be grouped.\n");
464    } else if (Part_NetworkReadPartition(subInfo->network) == NIL(graph_t)) {
465      fprintf(vis_stdout, "Grouping: Network has no partition.\n");
466      fprintf(vis_stdout,
467        "Grouping: All latches in network will be grouped.\n");
468    } else {
469      fprintf(vis_stdout, "Grouping: Network has a partition.\n");
470      fprintf(vis_stdout,
471        "Grouping: All latches in partition will be grouped.\n");
472    }
473  }
474  return(PartCreateSubsystem(subInfo, arrayOfLatchNames, arrayOfGroupIndex));
475}
476
477/**Function********************************************************************
478
479  Synopsis    [Create sub-partitions based on latch relation]
480
481  Description [Create sub-partition based on latch dependency, connectivity,
482  correlation, and affinity. The first sub-system includes latches in CTL
483  formula, and latches with strong affinity are put in next sub-system. If
484  dynamicIncrease is TRUE, the first sub-system which has stringest realtion
485  with given formula and the second sub-system with all other latches are
486  returned.]
487
488  SideEffects []
489
490******************************************************************************/
491array_t *
492Part_PartCreateSubsystemsWithCTL(
493  Part_SubsystemInfo_t *subInfo,
494  array_t *ctlArray,
495  array_t *fairArray,
496  boolean dynamicIncrease,
497  boolean dynamicAndDependency)
498{
499  if (subInfo->verbosity > 0 ){
500    fprintf(vis_stdout,"Grouping: All latches related to ");
501    fprintf(vis_stdout,"the CTL will be grouped.\n");
502  }
503  return (PartCreateSubsystemWithCTL(subInfo, ctlArray, fairArray,
504                             dynamicIncrease,dynamicAndDependency));
505}
506
507/**Function********************************************************************
508
509  Synopsis    [Create sub-partitions based on latch relation]
510
511  Description [Create sub-partition based on latch dependency, connectivity,
512  correlation, and affinity. The first sub-system includes latches in CTL
513  formula, and latches with strong affinity are put in next sub-system. If
514  dynamicIncrease is TRUE, the first sub-system which has stringest realtion
515  with given formula and the second sub-system with all other latches are
516  returned.]
517
518  SideEffects []
519
520******************************************************************************/
521array_t *
522Part_PartCreateSubsystemsWithCtlAndLtl(
523  Part_SubsystemInfo_t *subInfo,
524  array_t *ctlArray,
525  array_t *ltlArray,
526  array_t *fairArray,
527  boolean dynamicIncrease,
528  boolean dynamicAndDependency,
529  boolean strictBound)
530{
531  if (subInfo->verbosity > 0 ){
532    fprintf(vis_stdout,"Grouping: All latches related to ");
533    fprintf(vis_stdout,"the CTL/LTL/fairness will be grouped.\n");
534  }
535  return (PartCreateSubsystemWithCtlAndLtl(subInfo, ctlArray, ltlArray,
536                                           fairArray,
537                                           dynamicIncrease,
538                                           dynamicAndDependency,
539                                           strictBound));
540}
541
542
543/**Function********************************************************************
544
545  Synopsis    [Read the table attached to a partitioned subsystem.]
546
547  SideEffects []
548
549******************************************************************************/
550st_table *
551Part_PartitionSubsystemReadVertexTable(
552  Part_Subsystem_t *partitionedSubsystem)
553{
554  return(partitionedSubsystem->vertexNameTable);
555}
556
557/**Function********************************************************************
558
559  Synopsis    [Read fan-in array attached to partitioned subsystem]
560
561  SideEffects []
562
563******************************************************************************/
564array_t *
565Part_PartitionSubsystemReadFanIn(
566  Part_Subsystem_t *partitionedSubsystem)
567{
568  return(partitionedSubsystem->subsystemFanIn);
569}
570
571/**Function********************************************************************
572
573  Synopsis    [Read fan-out array attached to partitioned subsystem]
574
575  SideEffects []
576
577******************************************************************************/
578array_t *
579Part_PartitionSubsystemReadFanOut(
580  Part_Subsystem_t *partitionedSubsystem)
581{
582  return(partitionedSubsystem->subsystemFanOut);
583}
584
585
586/**Function********************************************************************
587
588  Synopsis    [Initialize info structure for partitioning subsystem]
589
590  SideEffects []
591
592  SeeAlso     [Part_SubsystemInfo]
593
594******************************************************************************/
595Part_SubsystemInfo_t *
596Part_PartitionSubsystemInfoInit(
597  Ntk_Network_t *network)
598{
599  Part_SubsystemInfo_t *partSubInfo;
600
601  partSubInfo = ALLOC(Part_SubsystemInfo_t, 1);
602
603 /*
604  * set values as defaults
605  */
606  partSubInfo->network = network;
607  partSubInfo->arrayOfVertex = NIL(array_t);
608  partSubInfo->numberOfVertex = 0;
609  partSubInfo->partBM = Part_BFix_v;
610  partSubInfo->con_factor = PART_SUB_CON_FACTOR;
611  partSubInfo->cor_factor = PART_SUB_COR_FACTOR;
612  partSubInfo->aff_factor = PART_SUB_AFF_FACTOR;
613  partSubInfo->threshold = 0.0;
614  partSubInfo->bound = 8;
615  partSubInfo->verbosity = 0;
616  partSubInfo->corMethod = Part_CorrelationDefault;
617  partSubInfo->dupLatchTable = st_init_table(strcmp, st_strhash);
618  partSubInfo->latchNameTable = st_init_table(strcmp, st_strhash);
619  return(partSubInfo);
620}
621
622/**Function********************************************************************
623
624  Synopsis    [Free info structure for partitioning subsystem]
625
626  SideEffects []
627
628  SeeAlso     [Part_SubsystemInfo]
629
630******************************************************************************/
631void
632Part_PartitionSubsystemInfoFree(
633  Part_SubsystemInfo_t *partSubInfo)
634{
635  st_generator  *stGen;
636  char          *latchInputName;
637  array_t       *latchNames;
638
639  array_free(partSubInfo->arrayOfVertex);
640  st_foreach_item(partSubInfo->dupLatchTable, stGen, &latchInputName,
641        &latchNames) {
642    array_free(latchNames);
643  }
644  st_free_table(partSubInfo->dupLatchTable);
645  st_free_table(partSubInfo->latchNameTable);
646  FREE(partSubInfo);
647}
648
649
650/**Function********************************************************************
651
652  Synopsis    [Free subsystem structure for partitioning subsystem]
653
654  SideEffects []
655
656  SeeAlso     [Part_Subsystem]
657
658******************************************************************************/
659void
660Part_PartitionSubsystemFree(
661  Part_Subsystem_t *partSubsystem)
662{
663  st_free_table(partSubsystem->vertexNameTable);
664  array_free(partSubsystem->subsystemFanIn);
665  array_free(partSubsystem->subsystemFanOut);
666  FREE(partSubsystem);
667}
668
669/**Function********************************************************************
670
671  Synopsis    [Set breaking method of subsystem info]
672
673  SideEffects []
674
675  SeeAlso     [Part_SubsystemInfo]
676
677******************************************************************************/
678void
679Part_PartitionSubsystemInfoSetBreakingMethod(
680  Part_SubsystemInfo_t *subInfo,
681  Part_BMethod bMethod)
682{
683  subInfo->partBM = bMethod;
684}
685
686
687/**Function********************************************************************
688
689  Synopsis    [Set bound of subsystem info]
690
691  SideEffects []
692
693  SeeAlso     [Part_SubsystemInfo]
694
695******************************************************************************/
696void
697Part_PartitionSubsystemInfoSetBound(
698  Part_SubsystemInfo_t *subInfo,
699  int bound)
700{
701  subInfo->bound = bound;
702}
703
704/**Function********************************************************************
705
706  Synopsis    [Set threshold of subsystem info]
707
708  SideEffects []
709
710  SeeAlso     [Part_SubsystemInfo]
711
712******************************************************************************/
713void
714Part_PartitionSubsystemInfoSetThreshold(
715  Part_SubsystemInfo_t *subInfo,
716  float threshold)
717{
718  subInfo->threshold = threshold;
719}
720
721
722/**Function********************************************************************
723
724  Synopsis    [Set verbosity of subsystem info]
725
726  SideEffects []
727
728  SeeAlso     [Part_SubsystemInfo]
729
730******************************************************************************/
731void
732Part_PartitionSubsystemInfoSetVerbosity(
733  Part_SubsystemInfo_t *subInfo,
734  int verbosity)
735{
736  subInfo->verbosity = verbosity;
737}
738
739
740/**Function********************************************************************
741
742  Synopsis    [Set method for correlation]
743
744  SideEffects []
745
746  SeeAlso     [Part_SubsystemInfo]
747
748******************************************************************************/
749void
750Part_PartitionSubsystemInfoSetCorrelationMethod(
751  Part_SubsystemInfo_t *subInfo,
752  Part_CMethod corMethod)
753{
754  subInfo->corMethod = corMethod;
755}
756
757/**Function********************************************************************
758
759  Synopsis    [Set affinity factor]
760
761  SideEffects []
762
763  SeeAlso     [Part_SubsystemInfo]
764
765******************************************************************************/
766void
767Part_PartitionSubsystemInfoSetAffinityFactor(
768  Part_SubsystemInfo_t *subInfo,
769  float affinity)
770{
771  subInfo->aff_factor = affinity;
772}
773
774
775/**Function********************************************************************
776
777  Synopsis    [Create a sub-system with given latch data input in arrayOfNodes]
778
779  SideEffects []
780
781  SeeAlso     []
782
783******************************************************************************/
784Part_Subsystem_t*
785Part_PartCreateSingleSubSystem(
786  array_t *arrayOfNodes,
787  Ntk_Network_t *network)
788{
789  return PartCreateSingleSubSystem(arrayOfNodes, network);
790}
791
792
793/*---------------------------------------------------------------------------*/
794/* Definition of internal functions                                          */
795/*---------------------------------------------------------------------------*/
796
797
798/**Function********************************************************************
799
800  Synopsis    [Create an array of partitioned subsystems from array of latches]
801
802  Description [This is a main function to get subsystems. At first, look at
803  the circuit topology and next state functions, get the latch affinity.
804  Find the connected components to cluster latches which are stronly dependent
805  or correlated on each other.
806  After that, divide clusters bigger than the given bound and aggregate
807  smaller clusters. This function is called with network and partition graph.
808  If arrayOfFunctionNames are not NULL, this function generates sub-system with
809  those latch-data-inputs in that array. If arrayOfGroupIndex is not NILL and
810  size of this array is same as the size of arrayOfFunctionNames, this function
811  uses these two arrays as predefined grouping information and creates
812  sub-systems.]
813
814  SideEffects []
815
816  SeeAlso     [Part_SubsystemInfo]
817
818******************************************************************************/
819array_t *
820PartCreateSubsystem(
821  Part_SubsystemInfo_t *partSubInfo,
822  array_t *arrayOfLatchNames,
823  array_t *arrayOfGroupIndex)
824{
825  char          *arrayOfDependency = NIL(char);
826  float         *arrayOfCorrelation = NIL(float);
827  float         *arrayOfAffinity;
828  array_t       *arrayOfInit;
829  st_table      *indexToPtrInfo; /* index to pointer table */
830  st_table      *ptrToIndexInfo; /* pointer to index table */
831  array_t       *result;
832  Ntk_Node_t    *node;
833  char          *functionName;
834  char          *latchName;
835  lsList        vertexList;
836  lsGen         gen;
837  int           i;
838  vertex_t      *vertex;
839  array_t       *initArray;
840  array_t       *arrayOfVertex;
841  Ntk_Network_t *network = partSubInfo->network;
842  graph_t       *partition = Part_NetworkReadPartition(network);
843  long          initialTime = 0;
844  long          finalTime;
845
846  if (partition == NIL(graph_t)) {
847    if (partSubInfo->corMethod == Part_CorrelationWithBDD) {
848       error_append("Network has no partition. Correlation ");
849       error_append("with MDD operation can not be used.\n");
850       return NIL(array_t);
851    }
852  }
853  if (arrayOfGroupIndex != NIL(array_t)) {
854    if (!arrayOfLatchNames) {
855      error_append("Latch name array is not given.\n");
856      result = NIL(array_t);
857    }
858    if (array_n(arrayOfLatchNames) != array_n(arrayOfGroupIndex)) {
859      error_append("Given function names and index have different size.\n");
860      result = NIL(array_t);
861    }
862  }
863
864  if (arrayOfLatchNames && arrayOfGroupIndex) {
865    result = PartCreateSubSystemWithGroupIndex(partSubInfo,
866                arrayOfLatchNames, arrayOfGroupIndex);
867    return result;
868  }
869
870  arrayOfVertex = array_alloc(Ntk_Node_t *, 0);
871
872  /*
873   * Convert graph vertices into array of array of vertices.
874   */
875  if (partSubInfo->verbosity > 2) {
876    fprintf(vis_stdout, "\nGroupting: List of latches\n");
877    fprintf(vis_stdout, "----------------------------\n");
878  }
879  if (arrayOfLatchNames != NIL(array_t)) {
880    Ntk_Node_t  *latchNode, *latchInputNode;
881    char        *otherLatchName;
882    array_t     *latchNameArray;
883
884    arrayForEachItem(char *, arrayOfLatchNames, i, latchName) {
885      latchNode = Ntk_NetworkFindNodeByName(network, latchName);
886      latchInputNode = Ntk_LatchReadDataInput(latchNode);
887      functionName = Ntk_NodeReadName(latchInputNode);
888      if (partSubInfo->verbosity > 2)
889        fprintf(vis_stdout, "%s\n", latchName);
890      if (st_lookup(partSubInfo->latchNameTable, functionName,
891                &otherLatchName)) {
892        if (st_lookup(partSubInfo->dupLatchTable, functionName,
893            &latchNameArray)) {
894          array_insert_last(char *, latchNameArray, latchName);
895        } else {
896          latchNameArray = array_alloc(char *, 0);
897          array_insert_last(char *, latchNameArray, otherLatchName);
898          array_insert_last(char *, latchNameArray, latchName);
899          st_insert(partSubInfo->dupLatchTable, (char *)functionName,
900                (char *)latchNameArray);
901        }
902        continue;
903      }
904      st_insert(partSubInfo->latchNameTable, (char *)functionName,
905        (char *)latchName);
906      array_insert_last(Ntk_Node_t *, arrayOfVertex, latchInputNode);
907    }
908  } else if (partition == NIL(graph_t)) {
909    Ntk_NetworkForEachNode(network, gen, node) {
910      if (Ntk_NodeTestIsLatchDataInput(node)) {
911        array_insert_last(Ntk_Node_t *, arrayOfVertex, node);
912        arrayOfLatchNames = PartReadLatchNameFromLatchInput(network, node);
913        functionName = Ntk_NodeReadName(node);
914        latchName = array_fetch(char *, arrayOfLatchNames, 0);
915        st_insert(partSubInfo->latchNameTable, (char *)functionName,
916                (char *)latchName);
917        if (array_n(arrayOfLatchNames) > 1) {
918          st_insert(partSubInfo->dupLatchTable, (char *)functionName,
919                (char *)arrayOfLatchNames);
920          if (partSubInfo->verbosity > 2) {
921            char *nname;
922            arrayForEachItem(char *, arrayOfLatchNames, i, nname) {
923              fprintf(vis_stdout, "%s\n", nname);
924            }
925          }
926        } else {
927          array_free(arrayOfLatchNames);
928          if (partSubInfo->verbosity > 2)
929            fprintf(vis_stdout, "%s\n", latchName);
930        }
931      }
932    } /* End of Ntk_NetworkForEachNode */
933  } else {
934    vertexList = g_get_vertices(partition);
935    lsForEachItem(vertexList, gen, vertex) {
936      char *nodeName = PartVertexReadName(vertex);
937      node = Ntk_NetworkFindNodeByName(network, nodeName);
938      if (Ntk_NodeTestIsLatchDataInput(node)) {
939        array_insert_last(Ntk_Node_t *, arrayOfVertex, node);
940        arrayOfLatchNames = PartReadLatchNameFromLatchInput(network, node);
941        functionName = Ntk_NodeReadName(node);
942        latchName = array_fetch(char *, arrayOfLatchNames, 0);
943        st_insert(partSubInfo->latchNameTable, (char *)functionName,
944                (char *)latchName);
945        if (array_n(arrayOfLatchNames) > 1) {
946          st_insert(partSubInfo->dupLatchTable, (char *)functionName,
947                (char *)arrayOfLatchNames);
948          if (partSubInfo->verbosity > 2) {
949            char *nname;
950            arrayForEachItem(char *, arrayOfLatchNames, i, nname) {
951              fprintf(vis_stdout, "%s\n", nname);
952            }
953          }
954        } else {
955          array_free(arrayOfLatchNames);
956          if (partSubInfo->verbosity > 2)
957            fprintf(vis_stdout, "%s\n", latchName);
958        }
959      }
960    }
961  }
962
963  if (partSubInfo->verbosity > 2) {
964    fprintf(vis_stdout, "Total # of latch data input = %d\n",
965      array_n(arrayOfVertex));
966  }
967  partSubInfo->arrayOfVertex = arrayOfVertex;
968  partSubInfo->numberOfVertex = array_n(arrayOfVertex);
969
970 /*
971  * table from index to pointer and pointer to index
972  */
973  indexToPtrInfo = st_init_table(st_numcmp, st_numhash);
974  ptrToIndexInfo = st_init_table(st_ptrcmp, st_ptrhash);
975
976  arrayForEachItem(Ntk_Node_t *, partSubInfo->arrayOfVertex, i, node) {
977    st_insert(indexToPtrInfo, (char *)(long)i, (char *)node);
978    st_insert(ptrToIndexInfo, (char *)node, (char *)(long)i);
979  }
980
981 /*
982  * get a dependency matrix
983  */
984  if (partSubInfo->aff_factor > 0.0) {
985    if (partSubInfo->verbosity > 0)
986      initialTime = util_cpu_time();
987    arrayOfDependency = PartCreateDependencyMatrix(partSubInfo, ptrToIndexInfo);
988    if (partSubInfo->verbosity > 0) {
989      finalTime = util_cpu_time();
990      fprintf(vis_stdout, "time for computing dependency = %g\n",
991        (double)(finalTime - initialTime) / 1000.0);
992    }
993  }
994
995 /*
996  * get a correlation matrix
997  */
998  if (partSubInfo->aff_factor != 1.0) {
999    if (partSubInfo->verbosity > 0)
1000      initialTime = util_cpu_time();
1001    if (partSubInfo->corMethod == Part_CorrelationWithBDD)
1002      arrayOfCorrelation = PartCreateCorrelationMatrixFromBDD(partSubInfo);
1003    else if ((partSubInfo->corMethod == Part_CorrelationWithSupport) ||
1004             (partSubInfo->corMethod == Part_CorrelationDefault)) {
1005      arrayOfCorrelation = PartCreateCorrelationMatrixFromSupport(partSubInfo);
1006    }
1007    if (partSubInfo->verbosity > 0) {
1008      finalTime = util_cpu_time();
1009      fprintf(vis_stdout, "time for computing correlation = %g\n",
1010        (double)(finalTime - initialTime) / 1000.0);
1011    }
1012  }
1013
1014  if (partSubInfo->verbosity > 2) {
1015    if (arrayOfDependency) {
1016      fprintf(vis_stdout, "\nGrouping: Dependency\n");
1017      fprintf(vis_stdout, "--------------------\n");
1018      PartPrintArrayArray(arrayOfDependency, partSubInfo->numberOfVertex, 1);
1019    }
1020    if (arrayOfCorrelation) {
1021      fprintf(vis_stdout, "\nGrouping: Correlation\n");
1022      fprintf(vis_stdout, "---------------------\n");
1023      PartPrintArrayArray(arrayOfCorrelation, partSubInfo->numberOfVertex, 0);
1024    }
1025 }
1026
1027 /*
1028  * get an affinity matrix, arrayOfCorrelation is freed.
1029  */
1030  if (partSubInfo->verbosity > 0)
1031    initialTime = util_cpu_time();
1032  arrayOfAffinity = PartCreateAffinityMatrix(arrayOfDependency,
1033                        arrayOfCorrelation, partSubInfo);
1034  FREE(arrayOfCorrelation);
1035  if (partSubInfo->verbosity > 0) {
1036    finalTime = util_cpu_time();
1037    fprintf(vis_stdout, "time for computing affinity = %g\n",
1038      (double)(finalTime - initialTime) / 1000.0);
1039  }
1040
1041  if (partSubInfo->verbosity > 2) {
1042    fprintf(vis_stdout, "\nGrouping: Affinity\n");
1043    fprintf(vis_stdout, "------------------\n");
1044    PartPrintArrayArray(arrayOfAffinity, partSubInfo->numberOfVertex, 0);
1045  }
1046
1047 /*
1048  * get an initial subsysytm by searching for connected component in
1049  * vertex affinity matrix
1050  */
1051  if (partSubInfo->verbosity > 0)
1052    initialTime = util_cpu_time();
1053  arrayOfInit = PartGetConnectedComponent(arrayOfAffinity, partSubInfo,
1054                        indexToPtrInfo);
1055  if (partSubInfo->verbosity > 0) {
1056    finalTime = util_cpu_time();
1057    fprintf(vis_stdout, "time for computing connected component = %g\n",
1058      (double)(finalTime - initialTime) / 1000.0);
1059  }
1060
1061  if (partSubInfo->verbosity > 2) {
1062    fprintf(vis_stdout, "\nGrouping: Initial connected component size\n");
1063    fprintf(vis_stdout, "------------------------------------------\n\n");
1064    arrayForEachItem(array_t *, arrayOfInit, i, initArray) {
1065      fprintf(vis_stdout, "%3d group: size = %d\n", i, array_n(initArray));
1066    }
1067  }
1068
1069 /*
1070  * get a final subsystem by breaking big connected components and
1071  * aggregating small connected components.
1072  */
1073  if (partSubInfo->verbosity > 0)
1074    initialTime = util_cpu_time();
1075  result = PartBreakingAggregating(arrayOfInit, arrayOfAffinity, partSubInfo,
1076           ptrToIndexInfo, arrayOfDependency);
1077  if (partSubInfo->verbosity > 0) {
1078    finalTime = util_cpu_time();
1079    fprintf(vis_stdout, "time for breaking and aggregating = %g\n",
1080      (double)(finalTime - initialTime) / 1000.0);
1081  }
1082
1083  array_free(arrayOfInit);
1084
1085  if (partSubInfo->verbosity >= 2) {
1086    Part_Subsystem_t *sub;
1087    char *latchName;
1088    st_generator *stGen;
1089
1090    fprintf(vis_stdout, "\nGrouping: List of subsytem latches\n");
1091    fprintf(vis_stdout, "----------------------------------\n\n");
1092    arrayForEachItem(Part_Subsystem_t *, result, i, sub) {
1093      fprintf(vis_stdout, "[Subsystem %3d]\n", i);
1094      st_foreach_item(sub->vertexNameTable, stGen, &latchName, NIL(char *)) {
1095        fprintf(vis_stdout, "%s\n", latchName);
1096      }
1097      fprintf(vis_stdout, "\n");
1098    }
1099  }
1100
1101  if (partSubInfo->verbosity >= 1) {
1102    (void)fprintf(vis_stdout, "\nGrouping: grouping options\n");
1103    (void)fprintf(vis_stdout, "--------------------------\n\n");
1104    (void)fprintf(vis_stdout, "Threshold          : %f\n",
1105                partSubInfo->threshold);
1106    (void)fprintf(vis_stdout, "bound              : %d\n",
1107                partSubInfo->bound);
1108    (void)fprintf(vis_stdout, "connectivity factor: %f\n",
1109                partSubInfo->con_factor);
1110    (void)fprintf(vis_stdout, "correlation factor : %f\n",
1111                partSubInfo->cor_factor);
1112    (void)fprintf(vis_stdout, "affinity factor    : %f\n",
1113                partSubInfo->aff_factor);
1114    (void)fprintf(vis_stdout, "\n");
1115  }
1116
1117  st_free_table(indexToPtrInfo);
1118  st_free_table(ptrToIndexInfo);
1119  FREE(arrayOfDependency);
1120  FREE(arrayOfAffinity);
1121
1122  return result;
1123}
1124
1125/*---------------------------------------------------------------------------*/
1126/* Definition of static functions                                            */
1127/*---------------------------------------------------------------------------*/
1128
1129/**Function********************************************************************
1130
1131  Synopsis    [Create an array of subsystems from properties]
1132
1133  Description [The first couple of sub-systems include nodes which are in
1134  CTL formulae.  A node with biggest affinity is included in the next
1135  sub-system until the number of nodes is less than bound. If dynamicIncrease
1136  is FALSE, get all sub-systems with all support variables of CTL formula.
1137  If TRUE, the first sub-system includes variables in CTL and the second
1138  sub-system includes others.]
1139
1140  SideEffects []
1141
1142  SeeAlso     [Part_SubsystemInfo]
1143
1144******************************************************************************/
1145static
1146array_t *
1147PartCreateSubsystemWithCTL( 
1148  Part_SubsystemInfo_t *partSubInfo,
1149  array_t *ctlArray,
1150  array_t *fairArray,
1151  boolean dynamicIncrease,
1152  boolean dynamicAndDependency)
1153{
1154  return PartCreateSubsystemWithCtlAndLtl(partSubInfo, ctlArray, NIL(array_t),
1155                                          fairArray, dynamicIncrease,
1156                                          dynamicAndDependency, FALSE);
1157}
1158
1159/**Function********************************************************************
1160
1161  Synopsis    [Create an array of subsystems from properties]
1162
1163  Description [The first couple of sub-systems include nodes which are
1164  in CTL/LTL/fairness formulae.  A node with biggest affinity is
1165  included in the next sub-system until the number of nodes is less
1166  than bound. If dynamicIncrease is FALSE, get all sub-systems with
1167  all support variables of CTL formula.  If TRUE, the first sub-system
1168  includes variables in CTL and the second sub-system includes others.
1169
1170  When strictBound is FALSE, all the latches appearing in the formulae
1171  are put into the first subsystem -- making it possibly larger than
1172  the bound. Otherwise, no subsystem will have more than 'bound'
1173  latches.]
1174
1175  SideEffects []
1176
1177  SeeAlso     [Part_SubsystemInfo]
1178
1179******************************************************************************/
1180static
1181array_t *
1182PartCreateSubsystemWithCtlAndLtl(
1183  Part_SubsystemInfo_t *partSubInfo,
1184  array_t *ctlArray,
1185  array_t *ltlArray,
1186  array_t *fairArray,
1187  boolean dynamicIncrease,
1188  boolean dynamicAndDependency,
1189  boolean strictBound)
1190{
1191  int i, j, index, maxSize, maxIndex, leftNodes, numSeed;
1192  array_t *result = NIL(array_t);
1193  Ntk_Network_t *network = partSubInfo->network;
1194  lsList latchNodeList;
1195  lsGen  gen;
1196  char *arrayOfDependency = NIL(char);
1197  float *arrayOfCorrelation = NIL(float);
1198  float *arrayOfAffinity = NIL(float);
1199  array_t *arrayTemp = NIL(array_t);
1200  array_t *arrayOfVertex = NIL(array_t);
1201  array_t *arrayOfLatchNames = NIL(array_t);
1202  st_table *vertexToArrayOfLatchNames = NIL(st_table);
1203  array_t *arrayOfLatchNodeName = NIL(array_t);
1204  Ntk_Node_t *node = NIL(Ntk_Node_t);
1205  float affinity;
1206  char *name = NIL(char);
1207  st_table *indexToPtrInfo = NIL(st_table);
1208  st_table *ptrToIndexInfo = NIL(st_table);
1209  array_t *check = NIL(array_t);
1210  array_t *tempCheck = NIL(array_t);
1211  array_t *tempCC = NIL(array_t);
1212  st_generator *stGen = NIL(st_generator);
1213  array_t *arrayOfSeed = NIL(array_t);
1214  Ntk_Node_t *seedLast = NIL(Ntk_Node_t);
1215  Ntk_Node_t *seedNext = NIL(Ntk_Node_t);
1216  array_t *arrayOfBreak = NIL(array_t);
1217  array_t *arrayOfNodes = NIL(array_t);
1218  array_t *arrayOfIndex = NIL(array_t);
1219  st_table *dataInputNodes = NIL(st_table);
1220  Part_Subsystem_t *sub = NIL(Part_Subsystem_t);
1221  int numIncluded;
1222  float prevAffinity;
1223
1224  if (ctlArray == NIL(array_t) && ltlArray == NIL(array_t)){
1225    return NIL(array_t);
1226  }
1227
1228  /*
1229   * arrayOfLatchNodeName  <--  COI latch names
1230   */
1231  latchNodeList = lsCreate();
1232  PartGetLatchListFromCtlAndLtl(network, ctlArray, ltlArray,
1233                                fairArray, latchNodeList, FALSE);
1234  arrayOfLatchNodeName = array_alloc(Ntk_Node_t *, 0);
1235  lsForEachItem(latchNodeList, gen, node){
1236    array_insert_last(char *, arrayOfLatchNodeName, Ntk_NodeReadName(node));
1237  }
1238  lsDestroy(latchNodeList, (void (*)(lsGeneric))0);
1239
1240  /*
1241   * arrayOfVertex  <--  COI latch datainput nodes
1242   */
1243  array_sort(arrayOfLatchNodeName, strCompare);
1244  arrayOfVertex = array_alloc(Ntk_Node_t *, 0);
1245  vertexToArrayOfLatchNames = st_init_table(st_ptrcmp, st_ptrhash);
1246  /* multiple latch may correspond to the same  dataInput */ 
1247  arrayForEachItem(char *, arrayOfLatchNodeName, i, name){
1248    node = Ntk_NetworkFindNodeByName(network, name);
1249    node = Ntk_LatchReadDataInput(node);
1250    if (!st_lookup(vertexToArrayOfLatchNames, node, &arrayOfLatchNames) ) {
1251      arrayOfLatchNames = array_alloc(char *, 0);
1252      array_insert_last(char *, arrayOfLatchNames, name);
1253      st_insert(vertexToArrayOfLatchNames, node, arrayOfLatchNames);
1254     
1255      array_insert_last(Ntk_Node_t *, arrayOfVertex, node);
1256    }else 
1257      array_insert_last(char *, arrayOfLatchNames, name);
1258  }
1259
1260  /*
1261   * Print a list of latch names.
1262   */
1263  if (partSubInfo->verbosity >= 2){
1264    fprintf(vis_stdout,"\nGroupting: List of latches\n");
1265    fprintf(vis_stdout,"------------------------\n\n");
1266    arrayForEachItem(char *, arrayOfLatchNodeName, i, name){
1267      fprintf(vis_stdout,"%s\n", name);
1268    }
1269  }
1270  array_free(arrayOfLatchNodeName);
1271
1272
1273  /*
1274   * dataInputNodes <-- formulae latch datainput nodes
1275   */
1276  latchNodeList = lsCreate();
1277  PartGetLatchListFromCtlAndLtl(network, ctlArray, ltlArray,
1278                                fairArray, latchNodeList, TRUE);
1279  dataInputNodes = st_init_table( st_ptrcmp, st_ptrhash );
1280  lsForEachItem(latchNodeList, gen, node) {
1281    Ntk_Node_t *dataInputNode = Ntk_LatchReadDataInput(node);
1282    if (!st_is_member(dataInputNodes, (char *)dataInputNode))
1283      st_insert(dataInputNodes, (char *)dataInputNode, NIL(char));
1284  }
1285  lsDestroy(latchNodeList, (void (*)(lsGeneric))0);
1286
1287
1288 /*
1289  * table from index to pointer and pointer to index
1290  */
1291  partSubInfo->arrayOfVertex = arrayOfVertex;
1292  partSubInfo->numberOfVertex = array_n(arrayOfVertex);
1293
1294  indexToPtrInfo = st_init_table(st_numcmp, st_numhash);
1295  ptrToIndexInfo = st_init_table(st_ptrcmp, st_ptrhash);
1296
1297  arrayForEachItem(Ntk_Node_t *, partSubInfo->arrayOfVertex, i, node){
1298    st_insert(indexToPtrInfo, (char *)(long)i, (char *)node);
1299    st_insert(ptrToIndexInfo, (char *)node, (char *)(long)i);
1300  }
1301
1302  check = array_alloc(int, partSubInfo->numberOfVertex);
1303  for(i=0;i<partSubInfo->numberOfVertex;i++){
1304    array_insert(int, check, i, 0);
1305  }
1306
1307
1308  leftNodes = partSubInfo->numberOfVertex;
1309  arrayOfIndex = array_alloc(int, st_count(dataInputNodes));
1310  result = array_alloc(Part_Subsystem_t *, 0);
1311
1312
1313  /*
1314   * If (1) number of formula nodes is smaller than bound, or (2)
1315   * strictBound is FALSE, or (3) dynamicIncrease is TRUE, create a
1316   * subsystem and put all formula nodes in the sub-system
1317   */
1318  if ( !strictBound || st_count(dataInputNodes) <= partSubInfo->bound
1319       || dynamicIncrease ) {
1320    int numNodesInFirstSubsys;
1321
1322    if (!strictBound || st_count(dataInputNodes) <= partSubInfo->bound)
1323      numNodesInFirstSubsys = st_count(dataInputNodes);
1324    else 
1325      numNodesInFirstSubsys = partSubInfo->bound;
1326
1327    arrayOfNodes = array_alloc(Ntk_Node_t *, st_count(dataInputNodes));
1328    i=0;
1329    st_foreach_item(dataInputNodes, stGen, &node, NULL) {
1330      if (i == numNodesInFirstSubsys) break;
1331      st_lookup_int(ptrToIndexInfo, node, &index);
1332      array_insert(int, check, index, 1);
1333      array_insert(int, arrayOfIndex, i, index);
1334      array_insert(Ntk_Node_t *, arrayOfNodes, i++, node);
1335    }
1336    sub = PartCreateSingleSubSystem(arrayOfNodes, network);
1337    leftNodes -= array_n(arrayOfNodes);
1338    array_insert_last(Part_Subsystem_t *, result, sub);
1339    array_free(arrayOfNodes);
1340
1341    if (dynamicIncrease) {
1342      /* the second subsystem <-- remaining latches in dataInputTable
1343       * the thrid  subsystem <-- other COI latches
1344       */
1345      if ( dynamicAndDependency ) {
1346        if ( st_count(dataInputNodes) == numNodesInFirstSubsys )
1347          array_insert_last(Part_Subsystem_t *, result, NIL(Part_Subsystem_t));
1348        else {
1349          arrayOfNodes = array_alloc(Ntk_Node_t *, 0);
1350          i=0;
1351          st_foreach_item(dataInputNodes, stGen, &node, NULL) {
1352            st_lookup_int(ptrToIndexInfo, node, &index);
1353            if (array_fetch(int, check, index)==0){
1354              array_insert(int, check, index, 1);
1355              array_insert(int, arrayOfIndex, i, index);
1356              array_insert_last(Ntk_Node_t *, arrayOfNodes, node);
1357            }
1358          }
1359          sub = PartCreateSingleSubSystem(arrayOfNodes, network);
1360          leftNodes -= array_n(arrayOfNodes);
1361          array_insert_last(Part_Subsystem_t *, result, sub);
1362          array_free(arrayOfNodes);
1363        }
1364      }
1365     
1366      if (leftNodes > 0){
1367        arrayOfNodes = array_alloc(Ntk_Node_t *, 0);
1368        arrayForEachItem(Ntk_Node_t *, partSubInfo->arrayOfVertex, i, node){
1369          if (array_fetch(int, check, i)==0)
1370            array_insert_last(Ntk_Node_t *, arrayOfNodes, node);
1371        }
1372        sub = PartCreateSingleSubSystem(arrayOfNodes, network);
1373        array_free(arrayOfNodes);
1374      }else{
1375        sub = NIL(Part_Subsystem_t);
1376      }
1377      array_insert_last(Part_Subsystem_t *, result, sub);
1378
1379      array_free(check);
1380      array_free(arrayOfIndex);
1381      st_free_table(ptrToIndexInfo);
1382      st_free_table(indexToPtrInfo);
1383      st_free_table(dataInputNodes);
1384      return result;
1385    } /*if dynamicIncrease*/
1386
1387  }else {
1388    /*
1389     * If we don't want to put all formula nodes in the 1st subsystem,
1390     * we need to break them into several pieces.
1391     */
1392  }
1393
1394  /*
1395   * get a affinity matrix (dependency matrix, correlation matrix)
1396   */
1397  arrayOfDependency = PartCreateDependencyMatrix(partSubInfo, 
1398                                                 ptrToIndexInfo);
1399
1400  if (partSubInfo->corMethod == Part_CorrelationWithBDD)
1401    arrayOfCorrelation = PartCreateCorrelationMatrixFromBDD(partSubInfo);
1402  else if ((partSubInfo->corMethod == Part_CorrelationWithSupport) ||
1403           (partSubInfo->corMethod == Part_CorrelationDefault))
1404    arrayOfCorrelation = PartCreateCorrelationMatrixFromSupport(partSubInfo);
1405
1406  arrayOfAffinity = PartCreateAffinityMatrix(arrayOfDependency,
1407                                             arrayOfCorrelation, 
1408                                             partSubInfo);
1409 
1410  if (partSubInfo->verbosity > 2 ){
1411    fprintf(vis_stdout,"\nGrouping: Dependency\n");
1412    fprintf(vis_stdout,"--------------------\n");
1413    PartPrintArrayArray(arrayOfDependency, partSubInfo->numberOfVertex, 1);
1414    fprintf(vis_stdout,"\nGrouping: Correlation\n");
1415    fprintf(vis_stdout,"---------------------\n");
1416    PartPrintArrayArray(arrayOfCorrelation, partSubInfo->numberOfVertex, 0);
1417    fprintf(vis_stdout,"\nGrouping: Affinity\n");
1418    fprintf(vis_stdout,"------------------\n");
1419    PartPrintArrayArray(arrayOfAffinity, partSubInfo->numberOfVertex, 0);
1420  }
1421  FREE(arrayOfDependency);
1422  FREE(arrayOfCorrelation);
1423
1424
1425  /* If number of formula nodes are bigger than bound, break down into
1426   * bounded sized subsystems.
1427   */
1428  if (st_count(dataInputNodes) > partSubInfo->bound && strictBound ){
1429    tempCheck = array_alloc(int, partSubInfo->numberOfVertex);
1430    tempCC = array_alloc(Ntk_Node_t *, partSubInfo->numberOfVertex);
1431    for(i=0; i<partSubInfo->numberOfVertex; i++){
1432      array_insert(int, tempCheck, i, 1);
1433      array_insert(Ntk_Node_t *, tempCC, i, (Ntk_Node_t *)0);
1434    }
1435    i = 0;
1436    st_foreach_item(dataInputNodes, stGen, &node, NULL) {
1437      st_lookup_int(ptrToIndexInfo, node, &index);
1438      array_insert(int, arrayOfIndex, i++, index);
1439      array_insert(int, check, index, 1);
1440      array_insert(int, tempCheck, index, 0);
1441      array_insert(Ntk_Node_t *, tempCC, index, node);
1442    }
1443
1444    numSeed = (int) ceil((double)st_count(dataInputNodes)/(double)(partSubInfo->bound));
1445    arrayOfSeed = array_alloc(Ntk_Node_t *, numSeed);
1446    seedLast = PartSelectNodeOfMinSupport(tempCC,
1447                                          tempCheck, partSubInfo);
1448    array_insert(Ntk_Node_t *, arrayOfSeed, 0, seedLast);
1449    for (i=1; i< numSeed; i++){
1450      seedNext = PartSelectFarNode(seedLast, tempCC, tempCheck,
1451                                   arrayOfAffinity, ptrToIndexInfo);
1452      array_insert(Ntk_Node_t *, arrayOfSeed, i, seedNext);
1453      seedLast = seedNext;
1454    }
1455
1456   /*
1457    * Break formula nodes, put into table and insert into final result
1458    */
1459    arrayOfBreak = PartBreakingBigConnectedComponent(tempCC, tempCheck,
1460          arrayOfSeed, arrayOfAffinity, partSubInfo, ptrToIndexInfo);
1461    array_free(tempCheck);
1462    array_free(tempCC);
1463    array_free(arrayOfSeed);
1464
1465    assert(array_n(arrayOfBreak) > 0);
1466    maxSize = -1;
1467    maxIndex = -1; /* don't care value to suppress warning */
1468    arrayForEachItem(array_t *, arrayOfBreak, i, arrayOfNodes){
1469      if (array_n(arrayOfNodes)>maxSize){
1470        maxIndex = i;
1471        maxSize = array_n(arrayOfNodes);
1472      }
1473    }
1474    arrayOfNodes = array_fetch(array_t *, arrayOfBreak, maxIndex);
1475    sub = PartCreateSingleSubSystem(arrayOfNodes, network);
1476    leftNodes -= array_n(arrayOfNodes);
1477    array_insert_last(Part_Subsystem_t *, result, sub);
1478    arrayForEachItem(array_t *, arrayOfBreak, i, arrayOfNodes){
1479      if (i != maxIndex){
1480        sub = PartCreateSingleSubSystem(arrayOfNodes, network);
1481        leftNodes -= array_n(arrayOfNodes);
1482        array_insert_last(Part_Subsystem_t *, result, sub);
1483      }
1484    }
1485    PartArrayOfArrayFree(arrayOfBreak);
1486  }/* if (st_count(dataInputNodes) > partSubInfo->bound && strictBound)*/
1487  st_free_table(dataInputNodes);
1488
1489
1490  /*
1491   * Create new affinity matrix. Now new affinity is defined from
1492   * sub-system(s) created above to left nodes.
1493   */
1494  arrayTemp = NIL(array_t);
1495
1496  if (leftNodes > 0){
1497    arrayTemp = array_alloc(float, partSubInfo->numberOfVertex);
1498    arrayForEachItem(int, arrayOfIndex, i, index){
1499      for(j=0;j<partSubInfo->numberOfVertex;j++){
1500        affinity = PartGetElementFromSymMatrix(arrayOfAffinity,index,j);
1501        if (i==0){
1502          array_insert(float, arrayTemp, j, affinity);
1503        } else {
1504           prevAffinity = array_fetch(float, arrayTemp, j);
1505           array_insert(float, arrayTemp, j, affinity + prevAffinity);
1506        }
1507      }
1508    }
1509 
1510    array_free(arrayOfIndex);
1511    FREE(arrayOfAffinity);
1512
1513    if (partSubInfo->verbosity > 2 ){
1514      fprintf(vis_stdout,"\nGrouping:: combinded affinity\n");
1515      fprintf(vis_stdout,"------------------\n");
1516      arrayForEachItem(float, arrayTemp, i, affinity){
1517        fprintf(vis_stdout, "%.10f ", affinity);
1518      }
1519      fprintf(vis_stdout, "\n");
1520    }
1521  }else{
1522    array_free(arrayOfIndex);
1523    FREE(arrayOfAffinity);
1524  }
1525     
1526  /*
1527   * Create sub-system by choosing a nodes with biggest new affinity
1528   */
1529  while( leftNodes > 0 ){
1530    numIncluded = 0;
1531    arrayOfVertex = array_alloc(Ntk_Node_t *, 0);
1532    while ((numIncluded < partSubInfo->bound) && (leftNodes > 0)){
1533     /*
1534      * The node with maximum affinity to formula nodes is included
1535      * in next sub-system until number of nodes reaches to bound
1536      */
1537      prevAffinity = -1.0;
1538      maxIndex = 0;
1539      arrayForEachItem( float, arrayTemp, i, affinity){
1540        if ( array_fetch(int, check, i) != 1 ){
1541          if (affinity >= prevAffinity){
1542            prevAffinity = affinity;
1543            maxIndex = i;
1544          }
1545        }
1546      }
1547      st_lookup(indexToPtrInfo, (char *)(long)maxIndex, &node);
1548      array_insert_last(Ntk_Node_t *, arrayOfVertex, node);
1549      array_insert(int, check, maxIndex, 1);
1550      numIncluded++;
1551      leftNodes--;
1552    }
1553    sub = PartCreateSingleSubSystem(arrayOfVertex, network);
1554    array_free(arrayOfVertex);
1555    array_insert_last(Part_Subsystem_t *, result, sub);
1556  }
1557
1558  array_free(check);
1559  if (arrayTemp != NIL(array_t))
1560    array_free(arrayTemp);
1561  st_free_table(ptrToIndexInfo);
1562  st_free_table(indexToPtrInfo);
1563
1564
1565  if (partSubInfo->verbosity >= 2){
1566    Part_Subsystem_t *sub;
1567    char *latchName;
1568    st_generator *stGen;
1569
1570    fprintf(vis_stdout,"\nGrouping: List of subsytem latches\n");
1571    fprintf(vis_stdout,"----------------------------------\n\n");
1572    arrayForEachItem(Part_Subsystem_t *, result, i, sub){
1573      fprintf(vis_stdout,"[Subsystem %3d]\n",i);
1574      st_foreach_item(sub->vertexNameTable, stGen, &latchName, NIL(char *) ){
1575        fprintf(vis_stdout,"%s\n",latchName);
1576      }
1577      fprintf(vis_stdout,"\n");
1578    }
1579  }
1580
1581  return result;
1582}
1583
1584
1585/**Function********************************************************************
1586
1587  Synopsis    [Create the vertex dependency matrix]
1588
1589  Description [vertex 1 depends on vertex 2, if the support of the function
1590  attatched to vertex 1 contains vertex 2]
1591
1592  SideEffects []
1593
1594******************************************************************************/
1595static char *
1596PartCreateDependencyMatrix(
1597  Part_SubsystemInfo_t *partSubInfo,
1598  st_table *ptrToIndex)
1599{
1600  char          *result;
1601  array_t       *arrayNodeFrom;
1602  int           i, j, k;
1603  Ntk_Node_t    *node, *latchInputNode;
1604  array_t       *arrayOfSupport;
1605  Ntk_Network_t *network = partSubInfo->network;
1606  int           index, size;
1607
1608  size = partSubInfo->numberOfVertex;
1609  result = ALLOC(char, size * size);
1610  (void)memset((void *)result, 0, sizeof(char) * size * size);
1611
1612  for (i = 0; i < partSubInfo->numberOfVertex; i++) {
1613    node = array_fetch(Ntk_Node_t *, partSubInfo->arrayOfVertex, i);
1614    arrayNodeFrom = array_alloc(Ntk_Node_t *, 1);
1615    array_insert(Ntk_Node_t *, arrayNodeFrom, 0, node);
1616    arrayOfSupport = Ntk_NodeComputeCombinationalSupport(network,
1617                                                         arrayNodeFrom, 
1618                                                         FALSE);
1619    array_free(arrayNodeFrom);
1620    arrayForEachItem(Ntk_Node_t *, arrayOfSupport, j, node) {
1621      if (!Ntk_NodeTestIsLatch(node))
1622        continue;
1623      latchInputNode = Ntk_LatchReadDataInput(node);
1624      if (st_lookup_int(ptrToIndex, (char *)latchInputNode, &k)) {
1625        index = i * partSubInfo->numberOfVertex + k;
1626        result[index] = 1;
1627      } else {
1628        fprintf(vis_stderr,
1629                "** part error: can't find the latch input index.\n");
1630      }
1631    }
1632    array_free(arrayOfSupport);
1633  }
1634  return result;
1635}
1636
1637
1638/**Function********************************************************************
1639
1640  Synopsis    [Create the latch Correlation Matrix]
1641
1642  SideEffects []
1643
1644  SeeAlso     [Part_SubsystemInfo]
1645******************************************************************************/
1646static float *
1647PartCreateCorrelationMatrixFromSupport(
1648  Part_SubsystemInfo_t *partSubInfo)
1649{
1650  int i, j;
1651  float *result;
1652  float correlation;
1653  array_t *arrayOfSupport;
1654  st_table *tableOfSupport;
1655  array_t *arrayOfSupportTable;
1656  array_t *arrayNodeFrom;
1657  Ntk_Node_t *nodeFrom, *node;
1658  Ntk_Network_t *network = partSubInfo->network;
1659  int index;
1660
1661  result = ALLOC(float,
1662         partSubInfo->numberOfVertex * (partSubInfo->numberOfVertex - 1) / 2);
1663
1664  arrayOfSupportTable = array_alloc(st_table *, partSubInfo->numberOfVertex);
1665
1666  for (i = 0; i < partSubInfo->numberOfVertex; i++) {
1667    nodeFrom = array_fetch(Ntk_Node_t *, partSubInfo->arrayOfVertex, i);
1668    arrayNodeFrom = array_alloc(Ntk_Node_t *, 1);
1669    array_insert(Ntk_Node_t *, arrayNodeFrom, 0, nodeFrom);
1670    arrayOfSupport = Ntk_NodeComputeCombinationalSupport(network,
1671                                                         arrayNodeFrom, 
1672                                                         FALSE);
1673    array_free(arrayNodeFrom);
1674    tableOfSupport = st_init_table(st_ptrcmp, st_ptrhash);
1675    arrayForEachItem(Ntk_Node_t *, arrayOfSupport, j, node) {
1676      st_insert(tableOfSupport, (char *)node, (char *)NULL);
1677    }
1678    array_free(arrayOfSupport);
1679    array_insert(st_table *, arrayOfSupportTable, i, tableOfSupport);
1680  }
1681
1682  for (i = 1; i < partSubInfo->numberOfVertex; i++) {
1683    for (j = 0; j < i; j++) {
1684      correlation = PartVertexComputeCorrelation(i, j, arrayOfSupportTable,
1685                        partSubInfo);
1686      index = i * (i - 1) / 2 + j;
1687      result[index] = correlation;
1688    }
1689  }/* end of for */
1690
1691  for (i = 0; i < partSubInfo->numberOfVertex; i++)
1692    st_free_table(array_fetch(st_table *, arrayOfSupportTable, i));
1693  array_free(arrayOfSupportTable);
1694
1695  return result;
1696}
1697
1698
1699/**Function********************************************************************
1700
1701  Synopsis    [Create the latch Correlation Matrix]
1702
1703  SideEffects []
1704
1705  SeeAlso     [Part_SubsystemInfo]
1706******************************************************************************/
1707static float *
1708PartCreateCorrelationMatrixFromBDD(
1709  Part_SubsystemInfo_t *partSubInfo)
1710{
1711  int           i, j;
1712  float         *result;
1713  array_t       *agreeArray;
1714  array_t       *arrayOfMddArray;
1715  float         agreement;
1716  float         correlation = 0.0;
1717  char          *name;
1718  Ntk_Node_t    *node;
1719  Mvf_Function_t *mvf;
1720  vertex_t      *vertex;
1721  graph_t       *partition = Part_NetworkReadPartition(partSubInfo->network);
1722  mdd_manager   *mddmgr = PartPartitionReadMddManager(partition);
1723  int           index;
1724
1725  result = ALLOC(float,
1726         partSubInfo->numberOfVertex * (partSubInfo->numberOfVertex - 1) / 2);
1727
1728  arrayOfMddArray = array_alloc(array_t *, partSubInfo->numberOfVertex);
1729  for (i = 0; i < partSubInfo->numberOfVertex; i++) {
1730    node = array_fetch(Ntk_Node_t *, partSubInfo->arrayOfVertex, i);
1731    name = Ntk_NodeReadName(node);
1732    vertex = Part_PartitionFindVertexByName(partition, name);
1733    mvf = Part_VertexReadFunction(vertex);
1734    array_insert(array_t *, arrayOfMddArray, i, (array_t *)mvf);
1735  }
1736
1737  for (i = 1; i < partSubInfo->numberOfVertex; i++) {
1738    for (j = 0; j < i; j++) {
1739      int k;
1740      agreeArray = PartVertexComputeAgreement(mddmgr, i, j, arrayOfMddArray);
1741      correlation = 0.0;
1742      arrayForEachItem(float, agreeArray, k, agreement) {
1743        correlation += (float)pow(1.0 - 4.0 * agreement * (1.0 - agreement),
1744                                    partSubInfo->cor_factor);
1745      }
1746      correlation /= (float)array_n(agreeArray);
1747      array_free(agreeArray);
1748      index = i * (i - 1) / 2 + j;
1749      result[index] = correlation;
1750    }
1751  }/* end of for */
1752
1753  array_free(arrayOfMddArray);
1754  return result;
1755}
1756
1757
1758/**Function********************************************************************
1759
1760  Synopsis    [Gets the latch Correlation between two vertices]
1761
1762  SideEffects []
1763
1764  SeeAlso     [Part_SubsystemInfo]
1765******************************************************************************/
1766static float
1767PartVertexComputeCorrelation(
1768  int index1,
1769  int index2,
1770  array_t *arrayOfInputSupportTable,
1771  Part_SubsystemInfo_t *partSubInfo)
1772{
1773  st_generator *stGen;
1774  st_table *inputSupportTable1;
1775  st_table *inputSupportTable2;
1776  int sameSupportCount;
1777  float correlation;
1778  int inputSupportCount;
1779  Ntk_Node_t *node;
1780
1781  sameSupportCount = 0;
1782  inputSupportTable1 = array_fetch(st_table *, arrayOfInputSupportTable,
1783                                index1);
1784  inputSupportTable2 = array_fetch(st_table *, arrayOfInputSupportTable,
1785                                index2);
1786
1787  st_foreach_item(inputSupportTable1, stGen, &node, NULL) {
1788    if (st_is_member(inputSupportTable2, node)) {
1789      sameSupportCount++;
1790    }
1791  }
1792
1793  inputSupportCount = st_count(inputSupportTable1) +
1794                        st_count(inputSupportTable2) - sameSupportCount;
1795  if (inputSupportCount != 0) {
1796    correlation = (float)pow((double)sameSupportCount /
1797                             (double)inputSupportCount,
1798                             (double)partSubInfo->cor_factor);
1799  } else {
1800    correlation = 0.0;
1801  }
1802  return correlation;
1803}
1804
1805
1806/**Function********************************************************************
1807
1808  Synopsis    [Gets the latch Correlation between two vertices]
1809
1810  SideEffects []
1811
1812  SeeAlso     [Part_SubsystemInfo]
1813******************************************************************************/
1814static array_t *
1815PartVertexComputeAgreement(
1816  mdd_manager *mddMgr,
1817  int index1,
1818  int index2,
1819  array_t *arrayOfMddArray)
1820{
1821  int i, j;
1822  float agreement;
1823  mdd_t *mddFrom, *mddTo;
1824  array_t *mddArrayFrom, *mddArrayTo;
1825  array_t *agreeArray = array_alloc(float, 0);
1826
1827  mddArrayFrom = array_fetch(array_t *, arrayOfMddArray, index1);
1828  mddArrayTo   = array_fetch(array_t *, arrayOfMddArray, index2);
1829  arrayForEachItem(mdd_t *, mddArrayFrom, i, mddFrom) {
1830    arrayForEachItem(mdd_t *, mddArrayTo, j, mddTo) {
1831      agreement = bdd_correlation(mddFrom, mddTo);
1832      array_insert_last(float, agreeArray, agreement);
1833    }
1834  }
1835
1836  return agreeArray;
1837}
1838
1839
1840/**Function********************************************************************
1841
1842  Synopsis    [Create the latch Affinity Matrix]
1843
1844  Description [Affinity is a convex function of connectivity and correlation.
1845  For circuits which are more primary input sensitive, the latch
1846  correlation seems to be more important, while for circuit which are more
1847  state sensitive, the latch connectivity seems to be more important.The
1848  aff_factor controls the weight of two sides. The bigger the aff_factor is,
1849  the more weight is given to the latch connectivity.]
1850
1851  SideEffects [Each row element of arrayOfCorreletion is freed]
1852
1853  SeeAlso     [Part_SubsystemInfo]
1854******************************************************************************/
1855static float *
1856PartCreateAffinityMatrix(
1857  char *arrayOfDependency,
1858  float *arrayOfCorrelation,
1859  Part_SubsystemInfo_t *partSubInfo)
1860{
1861  float *result;
1862  int i, j;
1863  float dep1, dep2;
1864  float connectivity = 0.0;
1865  float correlation = 0.0;
1866  float affinity;
1867  int   index;
1868
1869  result = ALLOC(float,
1870         partSubInfo->numberOfVertex * (partSubInfo->numberOfVertex - 1) / 2);
1871
1872  for (i = 1; i < partSubInfo->numberOfVertex; i++) {
1873    for (j = 0; j < i; j++) {
1874      if (arrayOfDependency) {
1875        dep1 = dep2 = 0.0;
1876        index = i * partSubInfo->numberOfVertex + j;
1877        if (arrayOfDependency[index] == 1)
1878        dep1 = 1.0;
1879        index = j * partSubInfo->numberOfVertex + i;
1880        if (arrayOfDependency[index] == 1)
1881        dep2 = 1.0;
1882        connectivity = (dep1 + dep2 +
1883                        (partSubInfo->con_factor - 2) * dep1 * dep2) /
1884                        partSubInfo->con_factor;
1885      } else
1886        connectivity = 0.0;
1887
1888      if (arrayOfCorrelation)
1889        correlation = PartGetElementFromSymMatrix(arrayOfCorrelation, i, j);
1890      else
1891        correlation = 0.0;
1892
1893     /*
1894      * affinity is a convex function of connectivity and correlation
1895      */
1896      affinity = partSubInfo->aff_factor * connectivity +
1897                (1.0 - partSubInfo->aff_factor) * correlation;
1898      index = i * (i - 1) / 2 + j;
1899      result[index] = affinity;
1900    }
1901  }
1902  return result;
1903}
1904
1905/**Function********************************************************************
1906
1907  Synopsis    [Gets Conected Components of vertices]
1908
1909  Description [The affinity matrix is considered as graph, and higher value than
1910  threshold is considered edge between two verticies. And connected components
1911  are found by searching the graph]
1912
1913  SideEffects []
1914
1915  SeeAlso     []
1916******************************************************************************/
1917static array_t *
1918PartGetConnectedComponent(
1919  float *arrayOfAffinity,
1920  Part_SubsystemInfo_t *partSubInfo,
1921  st_table *indexToPtr)
1922{
1923  array_t  *arrayOfCCs; /* array of connected component */
1924  array_t  *connectedComponent;
1925  array_t  *arrayOfFrom;
1926  array_t  *arrayOfCCIndex; /* keep ccId of each vertex */
1927  float    affinity, affmax;
1928  float   affsum, density, nonZeroCount;
1929  int      next; /* serching connected component from this index */
1930  int      ccId; /* each connected component gets its own ccId */
1931  int      ccIndex;
1932  int      i, size;
1933  Ntk_Node_t *node;
1934
1935  next = 0;   /* keep the smallest index of vertex not included in CC */
1936  ccId = 0;   /* give ccId to each CC */
1937  affmax = 0.0;
1938  affsum = 0.0;
1939  nonZeroCount = 0;
1940
1941  arrayOfCCIndex = array_alloc(int, partSubInfo->numberOfVertex);
1942 /*
1943  * Initially, all vertecies are included in one component
1944  */
1945  for (i = 0; i < partSubInfo->numberOfVertex; i++) {
1946    array_insert(int, arrayOfCCIndex, i, 0);
1947  }
1948 /*
1949  * If the threshold is not defined, get an average of affinity in the matrix
1950  * and a density. Threshold is assigned between average of affinity and
1951  * the maximum value of affinity according to density. If the matrix is
1952  * dense(sparse), threshold goes up(goes down).
1953  */
1954  if (partSubInfo->threshold == 0.0) {
1955    size = partSubInfo->numberOfVertex * (partSubInfo->numberOfVertex - 1) / 2;
1956    for (i = 0; i < size; i++) {
1957      affinity = arrayOfAffinity[i];
1958      if (affmax < affinity) {
1959        affmax = affinity;
1960      }
1961      if (affinity > 0.0) {
1962        nonZeroCount += 1.0;
1963      }
1964      affsum += affinity;
1965    }
1966    density = nonZeroCount / pow((double)partSubInfo->numberOfVertex, 2.0);
1967    partSubInfo->threshold = (float)((affsum / nonZeroCount) +
1968                                (affmax - affsum / nonZeroCount) * density);
1969  }
1970
1971 /*
1972  * Get a connected component from the vertex which is pointed by 'next'
1973  * with its index. The 'next' is updated during searching CC in the function
1974  * PartFindCC
1975  */
1976  while (next < partSubInfo->numberOfVertex) {
1977    ccId++;
1978    array_insert(int, arrayOfCCIndex, next, ccId);
1979    if (next == partSubInfo->numberOfVertex - 1) {
1980      break;
1981    }
1982    arrayOfFrom = array_alloc(int, 1);
1983    array_insert(int, arrayOfFrom, 0, next);
1984    PartFindCC(&next, &ccId, arrayOfCCIndex, arrayOfAffinity, arrayOfFrom,
1985                partSubInfo);
1986  }
1987
1988 /*
1989  * initialize arrayOfCCs, which is the result.
1990  */
1991  arrayOfCCs = array_alloc(array_t *, ccId);
1992  for (i = 0; i < ccId; i++) {
1993    connectedComponent = array_alloc(Ntk_Node_t *, 0);
1994    array_insert(array_t *, arrayOfCCs, i, connectedComponent);
1995  }
1996
1997 /*
1998  * change index to vertex pointer and insert into each CC
1999  */
2000  arrayForEachItem(int, arrayOfCCIndex, i, ccIndex) {
2001    st_lookup(indexToPtr, (char *)(long)i, &node);
2002    connectedComponent = array_fetch(array_t *, arrayOfCCs, ccIndex-1);
2003    array_insert_last(Ntk_Node_t *, connectedComponent, node);
2004
2005  }
2006  array_free(arrayOfCCIndex);
2007  return arrayOfCCs;
2008}
2009
2010/**Function********************************************************************
2011
2012  Synopsis    [Get a conected component of vertices.]
2013
2014  SideEffects [The connected component is searched from 'arrayFrom' and
2015  each vertex in that connected component gets the index of the current
2016  connected component. And 'next' points the next possible vertex]
2017
2018  SeeAlso     []
2019******************************************************************************/
2020static void
2021PartFindCC(
2022  int *next,
2023  int *ccId,
2024  array_t *arrayOfCCIndex,
2025  float *arrayOfAffinity,
2026  array_t *arrayOfFrom,
2027  Part_SubsystemInfo_t *partSubInfo)
2028{
2029  int i, j, from;
2030  int arrayInd;
2031  float connected;
2032  array_t *arrayOfReached;
2033
2034 /*
2035  * Update next in order to let next keep the smallest vertex index which
2036  * is not traversed.
2037  */
2038  (*next)++;
2039  while (1) {
2040    if (*next == partSubInfo->numberOfVertex) {
2041      array_free(arrayOfFrom);
2042      return;
2043    }
2044    if (array_fetch(int, arrayOfCCIndex, *next) != 0) {
2045      (*next)++;
2046    } else {
2047      break;
2048    }
2049  }
2050
2051  arrayOfReached = array_alloc(int, 0); /* Reached set from arrayOfFrom */
2052
2053  /*
2054  * Find all vertecies which can be traversed from arrayOfFrom
2055  * and update next
2056  */
2057  while (array_n(arrayOfFrom) > 0) {
2058    arrayForEachItem(int, arrayOfFrom, i, from) {
2059      for (j = 0; j < partSubInfo->numberOfVertex; j++) {
2060        connected = PartGetElementFromSymMatrix(arrayOfAffinity, from, j);
2061        arrayInd = array_fetch(int, arrayOfCCIndex, j);
2062        if (connected > partSubInfo->threshold && arrayInd == 0) {
2063          array_insert_last(int, arrayOfReached, j);
2064          array_insert(int, arrayOfCCIndex, j, *ccId);
2065          if (*next == j) {
2066            (*next)++;
2067            while (1) {
2068              if (*next == partSubInfo->numberOfVertex) {
2069                array_free(arrayOfReached);
2070                array_free(arrayOfFrom);
2071                return;
2072              }
2073              if (array_fetch(int, arrayOfCCIndex, *next) != 0) {
2074                (*next)++;
2075              } else {
2076                break;
2077              }
2078            }/* end of while */
2079          }/* end if */
2080        }
2081      }/* end for */
2082    }/* end of arrayForEachItem(arrayOfFrom) */
2083    array_free(arrayOfFrom);
2084    arrayOfFrom = arrayOfReached;  /* Traverse with new reached set */
2085    arrayOfReached = array_alloc(int, 0);
2086  }/* end of while */
2087  array_free(arrayOfFrom);
2088  array_free(arrayOfReached);
2089  return;
2090}
2091
2092/**Function********************************************************************
2093
2094  Synopsis    [Gets an sub-partitions with bounded size]
2095
2096  Description [Break the connected component which has more verteices than
2097  bound and aggregate the connected components which have less vertecies
2098  than bound.]
2099
2100  SideEffects []
2101
2102  SeeAlso     []
2103******************************************************************************/
2104static array_t *
2105PartBreakingAggregating(
2106  array_t       *arrayOfInit,
2107  float         *arrayOfAffinity,
2108  Part_SubsystemInfo_t *partSubInfo,
2109  st_table      *ptrToIndex,
2110  char          *arrayOfDependency)
2111{
2112  array_t       *arrayOfAggregate;
2113  array_t       *arrayOfSeed;
2114  array_t       *arrayOfSmall;
2115  array_t       *arrayOfBreak;
2116  array_t       *arrayOfFinal;
2117  array_t       *arrayOfCCVertex;
2118  array_t       *arrayVertex;
2119  array_t       *arrayOfNew;
2120  array_t       *cc;
2121  array_t       *ccCheck; /* check cc which is included in final result */
2122  float         *groupDependency;
2123  st_table      *tableOfCC;
2124  float         groupDep;
2125  int           i, j, k, l;
2126  array_t       *arrayOfLatchNames;
2127  char          *name;
2128  Part_Subsystem_t *sub;
2129  Part_Subsystem_t *subIn;
2130  Part_Subsystem_t *subOut;
2131  Ntk_Node_t    *seedlast, *seednext, *node;
2132  char          *funcName;
2133
2134  arrayOfSmall = array_alloc(array_t *, 0);
2135  arrayOfFinal = array_alloc(Part_Subsystem_t *, 0);
2136  arrayOfCCVertex = array_alloc(array_t *, 0);
2137
2138  if (partSubInfo->bound == 0) {
2139    partSubInfo->bound = partSubInfo->numberOfVertex / array_n(arrayOfInit);
2140  }
2141
2142  arrayForEachItem(array_t *, arrayOfInit, i, cc) {
2143    if (array_n(cc) > partSubInfo->bound) {
2144     /*
2145      * If cc has more vertecies than bound, calculate how many seeds are needed
2146      * and get those seeds which are far away from each others
2147      */
2148      ccCheck = array_alloc(int, array_n(cc));
2149      for (j = 0; j < array_n(cc); j++) {
2150        array_insert(int, ccCheck, j, 0);
2151      }
2152
2153     /*
2154      * The first seed is the vertex which has the smallest support and
2155      * choose the next vertex which is the farthest from last seed
2156      */
2157      arrayOfSeed = array_alloc(Ntk_Node_t *, 0);
2158      seedlast = PartSelectNodeOfMinSupport(cc, ccCheck, partSubInfo);
2159      array_insert_last(Ntk_Node_t *, arrayOfSeed, seedlast);
2160      for (j = 1; j < ceil((double)array_n(cc) / (double)(partSubInfo->bound));
2161           j++) {
2162        seednext = PartSelectFarNode(seedlast, cc, ccCheck, arrayOfAffinity,
2163                        ptrToIndex);
2164        array_insert_last(Ntk_Node_t *, arrayOfSeed, seednext);
2165        seedlast = seednext;
2166      }
2167     /*
2168      * Break big CC, put into table and insert into final result
2169      */
2170      arrayOfBreak = PartBreakingBigConnectedComponent(cc, ccCheck,
2171            arrayOfSeed, arrayOfAffinity, partSubInfo, ptrToIndex);
2172      array_free(ccCheck);
2173      array_free(arrayOfSeed);
2174
2175      arrayForEachItem(array_t *, arrayOfBreak, j, arrayOfNew) {
2176        if (array_n(arrayOfNew) == partSubInfo->bound) {
2177          tableOfCC = st_init_table(strcmp, st_strhash);
2178          arrayVertex = array_alloc(Ntk_Node_t *, array_n(arrayOfNew));
2179          arrayForEachItem(Ntk_Node_t *, arrayOfNew, k, node) {
2180            funcName = Ntk_NodeReadName(node);
2181            if (st_lookup(partSubInfo->dupLatchTable, funcName,
2182                &arrayOfLatchNames)) {
2183              arrayForEachItem(char *, arrayOfLatchNames, l, name) {
2184                st_insert(tableOfCC, (char *)name, (char *)NULL);
2185              }
2186            } else {
2187              if (st_lookup(partSubInfo->latchNameTable, (char *)funcName,
2188                        (char **)&name)) {
2189                st_insert(tableOfCC, (char *)name, (char *)NULL);
2190              } else
2191                error_append("can't find the latch name.");
2192            }
2193            array_insert(Ntk_Node_t *, arrayVertex, k, node);
2194          }
2195          sub = ALLOC(Part_Subsystem_t, 1);
2196          sub->vertexNameTable = tableOfCC;
2197          sub->subsystemFanIn = array_alloc(int, 0);
2198          sub->subsystemFanOut = array_alloc(int, 0);
2199          array_insert_last(Part_Subsystem_t *, arrayOfFinal, sub);
2200          array_insert_last(array_t *, arrayOfCCVertex, arrayVertex);
2201          array_free(arrayOfNew);
2202        } else {
2203          array_insert_last(array_t *, arrayOfSmall, arrayOfNew);
2204        }
2205      }/* end of arrayForEachItem(arrayOfBreak) */
2206      array_free(arrayOfBreak);
2207      array_free(cc);
2208    } else if (array_n(cc) < partSubInfo->bound) {
2209     /*
2210      * If cc has less nodes than bound, put into arrayOfSmall
2211      */
2212      array_insert_last(array_t *, arrayOfSmall, cc);
2213    } else {
2214     /*
2215      * If cc has same number of verteices as bound, put into table and
2216      * insert into final result
2217      */
2218      tableOfCC = st_init_table(strcmp, st_strhash);
2219      arrayVertex = array_alloc(Ntk_Node_t *, array_n(cc));
2220      arrayForEachItem(Ntk_Node_t *, cc, j, node) {
2221        funcName = Ntk_NodeReadName(node);
2222        if (st_lookup(partSubInfo->dupLatchTable, funcName,
2223                &arrayOfLatchNames)) {
2224          arrayForEachItem(char *, arrayOfLatchNames, l, name) {
2225            st_insert(tableOfCC, (char *)name, (char *)NULL);
2226          }
2227        } else {
2228          if (st_lookup(partSubInfo->latchNameTable, (char *)funcName,
2229                (char **)&name)) {
2230            st_insert(tableOfCC, (char *)name, (char *)NULL);
2231          } else
2232            error_append("can't find the latch name.");
2233        }
2234        array_insert(Ntk_Node_t *, arrayVertex, j, node);
2235      }
2236      sub = ALLOC(Part_Subsystem_t, 1);
2237      sub->vertexNameTable = tableOfCC;
2238      sub->subsystemFanIn = array_alloc(int, 0);
2239      sub->subsystemFanOut = array_alloc(int, 0);
2240      array_insert_last(Part_Subsystem_t *, arrayOfFinal, sub);
2241      array_insert_last(array_t *, arrayOfCCVertex, arrayVertex);
2242      array_free(cc);
2243    }
2244  }
2245
2246 /*
2247  * aggregate small cc, put into table and insert into final resault
2248  */
2249  arrayOfAggregate = PartAggregating(arrayOfSmall, arrayOfAffinity,
2250                        partSubInfo, ptrToIndex);
2251
2252  array_free(arrayOfSmall);
2253
2254  arrayForEachItem(array_t *, arrayOfAggregate, i, arrayOfNew) {
2255    tableOfCC = st_init_table(strcmp, st_strhash);
2256    arrayVertex = array_alloc(Ntk_Node_t *, array_n(arrayOfNew));
2257    arrayForEachItem(Ntk_Node_t *, arrayOfNew, j, node) {
2258      funcName = Ntk_NodeReadName(node);
2259      if (st_lookup(partSubInfo->dupLatchTable, funcName,
2260                    &arrayOfLatchNames)) {
2261        arrayForEachItem(char *, arrayOfLatchNames, l, name) {
2262          st_insert(tableOfCC, (char *)name, (char *)NULL);
2263        }
2264      } else {
2265        if (st_lookup(partSubInfo->latchNameTable, (char *)funcName,
2266                (char **)&name)) {
2267          st_insert(tableOfCC, (char *)name, (char *)NULL);
2268        } else
2269          error_append("can't find the latch name.");
2270      }
2271      array_insert(Ntk_Node_t *, arrayVertex, j, node);
2272    }
2273    sub = ALLOC(Part_Subsystem_t, 1);
2274    sub->vertexNameTable = tableOfCC;
2275    sub->subsystemFanIn = array_alloc(int, 0);
2276    sub->subsystemFanOut = array_alloc(int, 0);
2277    array_insert_last(Part_Subsystem_t *, arrayOfFinal, sub);
2278    array_insert_last(array_t *, arrayOfCCVertex, arrayVertex);
2279    array_free(arrayOfNew);
2280  }/* end of arrayForEachItem(arrayOfAggregate) */
2281
2282  array_free(arrayOfAggregate);
2283
2284 /*
2285  * Get group dependency, which is dependency between two subsystems from
2286  * dependency between vertecies
2287  */
2288  groupDependency = PartGetGroupMatrixRegular(arrayOfCCVertex,
2289                        arrayOfDependency, ptrToIndex,
2290                        partSubInfo->numberOfVertex);
2291
2292  if (partSubInfo->verbosity >= 2) {
2293    int index;
2294    fprintf(vis_stdout, "\nGrouping: Group Dependency\n");
2295    fprintf(vis_stdout, "--------------------------\n");
2296    for (i = 0; i < array_n(arrayOfCCVertex); i++) {
2297      for (j = 0; j < array_n(arrayOfCCVertex); j++) {
2298        index = i * array_n(arrayOfCCVertex) + j;
2299        fprintf(vis_stdout, "%4.3f ", groupDependency[index]);
2300      }
2301      fprintf(vis_stdout, "\n");
2302    }
2303  }
2304
2305  for (i = 0; i < array_n(arrayOfCCVertex); i++) {
2306    subIn = array_fetch(Part_Subsystem_t *, arrayOfFinal, i);
2307    for (j = 0; j < array_n(arrayOfCCVertex); j++) {
2308      subOut = array_fetch(Part_Subsystem_t *, arrayOfFinal, j);
2309      if (i != j) {
2310        int     index;
2311
2312        index = i * array_n(arrayOfCCVertex) + j;
2313        groupDep = groupDependency[index];
2314        if (groupDep > 0.0) {
2315          array_insert_last(int, subIn ->subsystemFanIn, j);
2316          array_insert_last(int, subOut->subsystemFanOut, i);
2317        }
2318      }
2319    }
2320  }
2321  PartArrayOfArrayFree(arrayOfCCVertex);
2322  FREE(groupDependency);
2323  return arrayOfFinal;
2324}
2325
2326/**Function********************************************************************
2327
2328  Synopsis    [Create subsystems accoring to arrayOfGroupIndex]
2329
2330  Description [Each latch data input L(i) in array arrayOfLatchDataInputNamesi
2331  is put in I(i)'th subsystem. I is arrayOfGroupIndex. Index should start from
2332  0 to n as sequence.]
2333
2334  SideEffects []
2335
2336  SeeAlso     []
2337******************************************************************************/
2338static array_t *
2339PartCreateSubSystemWithGroupIndex(
2340  Part_SubsystemInfo_t *partSubInfo,
2341  array_t *arrayOfLatchNames,
2342  array_t *arrayOfGroupIndex)
2343{
2344  int           i, j;
2345  array_t       *result;
2346  char          *latchName;
2347  array_t       *arrayOfGroupVertex;
2348  array_t       *arrayOfVertex;
2349  array_t       *arrayOfLatchDataInputNames;
2350  Ntk_Node_t    *node, *latchNode, *latchInputNode;
2351  Part_Subsystem_t *sub;
2352  st_table      *groupIndexTable;
2353  st_table      **faninIndexTable, **fanoutIndexTable;
2354  char          *name;
2355  array_t       *arrayOfSupport;
2356  st_generator  *stGen;
2357  int           nLatches;
2358  int           nGroups = 0;
2359  int           preIndex, newIndex;
2360  long          index;
2361  char          *otherLatchName;
2362  array_t       *latchNameArray;
2363
2364  nLatches = array_n(arrayOfLatchNames);
2365
2366  /* reassign group index with counting the number of groups */
2367  groupIndexTable = st_init_table(st_numcmp, st_numhash);
2368  preIndex = -1;
2369  arrayForEachItem(int, arrayOfGroupIndex, i, index) {
2370    if (index == preIndex ||
2371        st_lookup_int(groupIndexTable, (char *)index, &newIndex)) {
2372      if (index != newIndex)
2373        array_insert(int, arrayOfGroupIndex, i, newIndex);
2374    } else {
2375      st_insert(groupIndexTable, (char *)index, (char *)(long)nGroups);
2376      newIndex = nGroups++;
2377      if (index != newIndex)
2378        array_insert(int, arrayOfGroupIndex, i, newIndex);
2379    }
2380    preIndex = (int) index;
2381  }
2382  st_free_table(groupIndexTable);
2383
2384  groupIndexTable = st_init_table(strcmp, st_strhash);
2385  faninIndexTable = ALLOC(st_table *, nGroups);
2386  fanoutIndexTable = ALLOC(st_table *, nGroups);
2387  for (i = 0; i < nGroups; i++) {
2388    faninIndexTable[i] = st_init_table(st_numcmp, st_numhash);
2389    fanoutIndexTable[i] = st_init_table(st_numcmp, st_numhash);
2390  }
2391
2392  /* makes an array of latch input names from latch names */
2393  arrayOfLatchDataInputNames = array_alloc(char *, 0);
2394  arrayForEachItem(char *, arrayOfLatchNames, i, latchName) {
2395    latchNode = Ntk_NetworkFindNodeByName(partSubInfo->network, latchName);
2396    latchInputNode = Ntk_LatchReadDataInput(latchNode);
2397    name = Ntk_NodeReadName(latchInputNode);
2398    array_insert_last(char *, arrayOfLatchDataInputNames, name);
2399  }
2400
2401  result = array_alloc(Part_Subsystem_t *, nGroups);
2402  arrayOfGroupVertex = array_alloc(array_t *, nGroups);
2403
2404  /* creates subsystems */
2405  for (i = 0; i < nGroups; i++) {
2406    sub = ALLOC(Part_Subsystem_t, 1);
2407    sub->vertexNameTable = st_init_table(strcmp, st_strhash);
2408    sub->subsystemFanIn = array_alloc(int, 0);
2409    sub->subsystemFanOut = array_alloc(int, 0);
2410    arrayOfVertex = array_alloc(Ntk_Node_t *, 0);
2411    array_insert(Part_Subsystem_t *, result, i, sub);
2412    array_insert(array_t *, arrayOfGroupVertex, i, arrayOfVertex);
2413  }
2414
2415  /* makes group index table and fills in the vertex name table */
2416  for (i = 0; i < nLatches; i++) {
2417    index = (long) array_fetch(int, arrayOfGroupIndex, i);
2418    name = array_fetch(char *, arrayOfLatchDataInputNames, i);
2419    latchName = array_fetch(char *, arrayOfLatchNames, i);
2420
2421    sub = array_fetch(Part_Subsystem_t *, result, (int) index);
2422    latchNode = Ntk_NetworkFindNodeByName(partSubInfo->network, latchName);
2423    latchName = Ntk_NodeReadName(latchNode);
2424    st_insert(sub->vertexNameTable, (char *)latchName, (char *)NULL);
2425
2426    if (st_lookup(partSubInfo->latchNameTable, name, &otherLatchName)) {
2427      if (st_lookup(partSubInfo->dupLatchTable, name, &latchNameArray)) {
2428        array_insert_last(char *, latchNameArray, latchName);
2429      } else {
2430        latchNameArray = array_alloc(char *, 0);
2431        array_insert_last(char *, latchNameArray, otherLatchName);
2432        array_insert_last(char *, latchNameArray, latchName);
2433        st_insert(partSubInfo->dupLatchTable, name, latchNameArray);
2434      }
2435      continue;
2436    }
2437
2438    st_insert(partSubInfo->latchNameTable, name, latchName);
2439    st_insert(groupIndexTable, name, (char *)index);
2440
2441    arrayOfVertex = array_fetch(array_t *, arrayOfGroupVertex, (int)index);
2442    node = Ntk_NetworkFindNodeByName(partSubInfo->network, name);
2443    array_insert_last(Ntk_Node_t *, arrayOfVertex, node);
2444  }
2445
2446  /* computes fanin and fanout table for each group */
2447  for (i = 0; i < nGroups; i++) {
2448    arrayOfVertex = array_fetch(array_t *, arrayOfGroupVertex, i);
2449    arrayOfSupport = Ntk_NodeComputeCombinationalSupport(partSubInfo->network,
2450        arrayOfVertex, FALSE);
2451    arrayForEachItem(Ntk_Node_t *, arrayOfSupport, j, node) {
2452      if (!Ntk_NodeTestIsLatch(node))
2453        continue;
2454      name = Ntk_NodeReadName(Ntk_LatchReadDataInput(node));
2455      if (st_lookup(groupIndexTable, name, &index)) {
2456        if (index == i)
2457          continue;
2458        st_insert(faninIndexTable[i], (char *)index, NIL(char));
2459        st_insert(fanoutIndexTable[index], (char *)(long)i, NIL(char));
2460      }
2461    }
2462    array_free(arrayOfSupport);
2463  }
2464
2465  /* makes fanin and fanout array for each subsystem */
2466  for (i = 0; i < nGroups; i++) {
2467    sub = array_fetch(Part_Subsystem_t *, result, i);
2468    st_foreach_item(faninIndexTable[i], stGen, &index, NULL) {
2469      array_insert_last(int, sub->subsystemFanIn, (int) index);
2470    }
2471    st_free_table(faninIndexTable[i]);
2472    array_sort(sub->subsystemFanIn, numCompare);
2473    st_foreach_item(fanoutIndexTable[i], stGen, &index, NULL) {
2474      array_insert_last(int, sub->subsystemFanOut, (int) index);
2475    }
2476    st_free_table(fanoutIndexTable[i]);
2477    array_sort(sub->subsystemFanOut, numCompare);
2478  }
2479
2480  FREE(faninIndexTable);
2481  FREE(fanoutIndexTable);
2482  array_free(arrayOfLatchDataInputNames);
2483  st_free_table(groupIndexTable);
2484  PartArrayOfArrayFree(arrayOfGroupVertex);
2485  return result;
2486}
2487
2488/**Function********************************************************************
2489
2490  Synopsis    [Gets bounded size blocks from big CC, Breaking]
2491
2492  Description [Gets bounded size blocks from big connected component]
2493
2494  SideEffects []
2495
2496  SeeAlso     []
2497******************************************************************************/
2498static array_t *
2499PartBreakingBigConnectedComponent(
2500  array_t *arrayOfCC,
2501  array_t *ccCheck,
2502  array_t *arrayOfSeed,
2503  float *arrayOfAffinity,
2504  Part_SubsystemInfo_t *partSubInfo,
2505  st_table *ptrToIndex)
2506{
2507  array_t *result;    /* array of groups with the proper size */
2508  array_t *resultRow; /* a group with the proper size */
2509  array_t *arrayTemp;
2510  array_t *seedFull;  /* array of seeds */
2511  int i, count;
2512  int totalCount;     /* how many vertixes are already computed */
2513  int indexOfSeed;    /* index of the seed which is closest from the vertex */
2514  Ntk_Node_t *seed, *variable, *pick;
2515
2516  result = array_alloc(array_t *, array_n(arrayOfSeed));
2517
2518  for (i = 0; i < array_n(arrayOfSeed); i++) {
2519    arrayTemp = array_alloc(Ntk_Node_t *, 0);
2520    seed = array_fetch(Ntk_Node_t *, arrayOfSeed, i);
2521    array_insert_last(Ntk_Node_t *, arrayTemp, seed);
2522    array_insert(array_t *, result, i, arrayTemp);
2523  }
2524
2525  switch (partSubInfo->partBM) {
2526   /*
2527    * Breaking Static Round Robin Seed Choice
2528    * Fixed order of seeds and each seed find the closest vertex
2529    */
2530    case Part_BSRR_s:
2531      totalCount = array_n(arrayOfSeed);
2532      arrayForEachItem(Ntk_Node_t *, arrayOfSeed, i, seed) {
2533        count = 1;
2534        resultRow = array_fetch(array_t *, result, i);
2535        while ((count < partSubInfo->bound) &&
2536              (totalCount < array_n(arrayOfCC))) {
2537          pick = PartSelectCloseNode(seed, arrayOfCC, ccCheck,
2538                        arrayOfAffinity, ptrToIndex);
2539          array_insert_last(Ntk_Node_t *, resultRow, pick);
2540          count++;
2541          totalCount++;
2542          seed = pick;
2543        }
2544      }
2545      break;
2546   /*
2547    * Breaking Fixed Order State Variable Choice
2548    * Fixed order of vertecies and each vertex find the closest seed
2549    */
2550    case Part_BFix_v:
2551     /*
2552      * Fixed order of nodes and each node find the closest seed
2553      */
2554      seedFull = array_alloc(int, 0);
2555      for (i = 0; i < array_n(arrayOfSeed); i++) {
2556        array_insert_last(int, seedFull, 1);
2557
2558      }
2559      arrayForEachItem(Ntk_Node_t *, arrayOfCC, i, variable) {
2560        if (array_fetch(int, ccCheck, i) != 1) {
2561          indexOfSeed = PartSelectCloseSeedIndex(variable, arrayOfSeed,
2562                arrayOfAffinity, ptrToIndex, seedFull, partSubInfo->bound);
2563          resultRow = array_fetch(array_t *, result, indexOfSeed);
2564          array_insert_last(Ntk_Node_t *, resultRow, variable);
2565          array_insert(int, ccCheck, i, 1);
2566        }
2567      }
2568      array_free(seedFull);
2569      break;
2570    default:
2571      break;
2572  }
2573  return result;
2574}
2575
2576
2577/**Function********************************************************************
2578
2579  Synopsis    [Gets bounded size blocks from small connected components.]
2580
2581  Description [The small connected components are aggregated by 'Static
2582  Round Robin Cluster Seed Algorithm(Fixed order of seed and each seed
2583  choose the closest connected component)'.]
2584
2585  SideEffects []
2586
2587******************************************************************************/
2588static array_t *
2589PartAggregating(
2590  array_t *arrayOfSmall,
2591  float *arrayOfAffinity,
2592  Part_SubsystemInfo_t *partSubInfo,
2593  st_table *ptrToIndex)
2594{
2595  float *arrayOfGroupAff;
2596  array_t *result;
2597  array_t *arraySeed;
2598  array_t *arraySeedIndex;
2599  array_t *arrayTemp;
2600  array_t *arrayRow;
2601  array_t *cc;
2602  array_t *ccCheck;
2603  array_t *seed;
2604  int i, j;
2605  int count;  /* total number of vertices in all small connected components */
2606  int pick, keepInd;
2607  int seedLast, seedNew, seedIndex;
2608  int numberOfSeed;
2609  boolean isDone;
2610  array_t *keep = array_alloc(int, 0);
2611
2612  count = 0;
2613
2614  arrayForEachItem(array_t *, arrayOfSmall, i, cc) {
2615    count += array_n(cc);
2616  }
2617
2618  numberOfSeed = (int) ceil((double)count/(double)partSubInfo->bound);
2619
2620  arrayOfGroupAff = PartGetGroupMatrixSym(arrayOfSmall, arrayOfAffinity,
2621                        ptrToIndex);
2622
2623  if (partSubInfo->verbosity >= 2) {
2624    fprintf(vis_stdout, "\nGrouping: Group affinity of initial ");
2625    fprintf(vis_stdout, "connected component\n");
2626    fprintf(vis_stdout, "------------------------------------");
2627    fprintf(vis_stdout, "-------------------\n");
2628    PartPrintArrayArray(arrayOfGroupAff, array_n(arrayOfSmall), 0);
2629  }
2630
2631  ccCheck = array_alloc(int, array_n(arrayOfSmall));
2632  for (i = 0; i < array_n(arrayOfSmall); i++) {
2633    array_insert(int, ccCheck, i, 0);
2634  }
2635
2636 /*
2637  * The first seed is the cc which has minmum support and the next
2638  * is the farthest cc
2639  */
2640  seedLast = PartSelectCCIndexOfMinSupport(arrayOfSmall,
2641             ccCheck, partSubInfo);
2642
2643  result = array_alloc(array_t *, numberOfSeed);
2644  arraySeed = array_alloc(array_t *, numberOfSeed);
2645  arraySeedIndex = array_alloc(int, numberOfSeed);
2646
2647  for (i = 0; i < numberOfSeed; i++) {
2648    seed = array_fetch(array_t *, arrayOfSmall, seedLast);
2649    array_insert(array_t *, arraySeed, i, seed);
2650    array_insert(int, arraySeedIndex, i, seedLast);
2651    array_insert(array_t *, result, i, seed);
2652    if (i<numberOfSeed-1) {
2653      seedNew = PartSelectFarCCIndex(seedLast, arrayOfSmall, arrayOfGroupAff,
2654                        partSubInfo, ccCheck);
2655      seedLast = seedNew;
2656    }
2657  }
2658
2659 /*
2660  * Static Round Robin Cluster Seed: Fixed order of seed and each seed
2661  * choose the closest connected component
2662  */
2663  isDone = FALSE;
2664  count = array_n(arraySeed);
2665  while ((!isDone) && count < array_n(arrayOfSmall)) {
2666    isDone = TRUE;
2667    arrayForEachItem(int, arraySeedIndex, i, seedIndex) {
2668      arrayRow = array_fetch(array_t *, result, i);
2669      pick = PartSelectCloseCCIndex(seedIndex, arrayOfSmall,
2670             arrayOfGroupAff, ccCheck);
2671      count++;
2672      /* check if not all cc is assigned */
2673      if (pick != -1) {
2674        arrayTemp = array_fetch(array_t *, arrayOfSmall, pick);
2675        if (array_n(array_fetch(array_t *, arrayOfSmall, seedIndex)) +
2676            array_n(arrayTemp) <= partSubInfo->bound) {
2677          array_append(arrayRow, arrayTemp);
2678          array_free(arrayTemp);
2679          isDone = FALSE;
2680        } else {
2681         /*
2682          * If pick cc is too big to be appended to seed, find new cc
2683          */
2684          array_insert_last(int, keep, pick);
2685          pick = PartSelectCloseCCIndex(seedIndex, arrayOfSmall,
2686                        arrayOfGroupAff, ccCheck);
2687          while (pick != -1) {
2688            arrayTemp = array_fetch(array_t *, arrayOfSmall, pick);
2689            if (array_n(array_fetch(array_t *, arrayOfSmall, seedIndex)) +
2690                array_n(arrayTemp) <= partSubInfo->bound) {
2691              array_append(arrayRow, arrayTemp);
2692              array_free(arrayTemp);
2693              isDone = FALSE;
2694              break;
2695            } else {
2696              array_insert_last(int, keep, pick);
2697              pick = PartSelectCloseCCIndex(seedIndex, arrayOfSmall,
2698                        arrayOfGroupAff, ccCheck);
2699            }
2700          } /* end while */
2701          if (pick == -1) {
2702            count--;
2703          }
2704          arrayForEachItem(int, keep, j, keepInd) {
2705            array_insert(int, ccCheck, keepInd, 0);
2706          }
2707          array_free(keep);
2708          keep = array_alloc(int, 0);
2709        } /* end if */
2710      } else {
2711        count--;
2712      }/* end if */
2713    }/* end arrayForEachItem */
2714   /*
2715    * If all seeds fail to find suitable cc and not all cc is assigned,
2716    *  get a new seed.
2717    */
2718    if (count < array_n(arrayOfSmall) && isDone) {
2719      seedIndex = PartSelectCCIndexOfMinSupport(arrayOfSmall,
2720                        ccCheck, partSubInfo);
2721      count++;
2722      seed = array_fetch(array_t *, arrayOfSmall, seedIndex);
2723      array_insert_last(array_t *, arraySeed, seed);
2724      array_insert_last(int, arraySeedIndex, seedIndex);
2725      array_insert_last(array_t *, result, seed);
2726      isDone = FALSE;
2727    }
2728  }
2729  array_free(arraySeed);
2730  array_free(arraySeedIndex);
2731  array_free(keep);
2732  array_free(ccCheck);
2733  FREE(arrayOfGroupAff);
2734  return result;
2735}
2736
2737/**Function********************************************************************
2738
2739  Synopsis    [Select the closest node from seed and return node pointer]
2740
2741  SideEffects [The Corresponding flag of ccCheck is set after selection]
2742
2743******************************************************************************/
2744static Ntk_Node_t *
2745PartSelectCloseNode(
2746  Ntk_Node_t    *seed,
2747  array_t       *arrayOfCC,
2748  array_t       *ccCheck,
2749  float         *arrayOfAffinity,
2750  st_table      *ptrToIndex)
2751{
2752  int           i;
2753  float         affinity;
2754  float         big; /* The bigest value of affinity of vertecies*/
2755  int           bigInd; /* the index of node with the biggest affinity */
2756  int           col;
2757  int           row;
2758  Ntk_Node_t    *node, *pick;
2759
2760  big = -1.0;
2761  bigInd = 0; /* to avoid warning */
2762  pick = NIL(Ntk_Node_t);
2763
2764  st_lookup_int(ptrToIndex, (char *)seed, &row);
2765
2766  arrayForEachItem(Ntk_Node_t *, arrayOfCC, i, node) {
2767    if (array_fetch(int, ccCheck, i) != 1) {
2768      st_lookup_int(ptrToIndex, (char *)node, &col);
2769      affinity = PartGetElementFromSymMatrix(arrayOfAffinity, row, col);
2770      if (affinity > big) {
2771         big = affinity;
2772         pick = node;
2773         bigInd = i;
2774      }
2775    }
2776  }
2777  array_insert(int, ccCheck, bigInd, 1);
2778  return pick;
2779}
2780
2781/**Function********************************************************************
2782
2783  Synopsis    [Select the closest seed from node and return seed index]
2784
2785  SideEffects []
2786
2787******************************************************************************/
2788static int
2789PartSelectCloseSeedIndex(
2790  Ntk_Node_t    *variable,
2791  array_t       *arrayOfSeed,
2792  float         *arrayOfAffinity,
2793  st_table      *ptrToIndex,
2794  array_t       *seedFull,
2795  int           bound)
2796{
2797  float         affinity;
2798  int           i;
2799  float         big;
2800  int           pick, row, col;
2801  Ntk_Node_t    *node;
2802
2803  big = -1.0;
2804  pick = -1;
2805
2806  st_lookup_int(ptrToIndex, (char *)variable, &row);
2807
2808  arrayForEachItem(Ntk_Node_t *, arrayOfSeed, i, node) {
2809    st_lookup_int(ptrToIndex, (char *)node, &col);
2810    affinity = PartGetElementFromSymMatrix(arrayOfAffinity, row, col);
2811    if (affinity > big && array_fetch(int, seedFull, i) < bound) {
2812      big = affinity;
2813      pick = i;
2814    }
2815  }
2816  array_insert(int, seedFull, pick, array_fetch(int, seedFull, pick) + 1);
2817  return pick;
2818}
2819
2820/**Function********************************************************************
2821
2822  Synopsis    [Select the farthest node from seed and return node pointer]
2823
2824  SideEffects [The Corresponding flag of ccCheck is set after selection]
2825
2826******************************************************************************/
2827static Ntk_Node_t *
2828PartSelectFarNode(
2829  Ntk_Node_t *seed,
2830  array_t *cc,
2831  array_t *ccCheck,
2832  float *arrayOfAffinity,
2833  st_table *ptrToIndex)
2834{
2835  float         affinity;
2836  int           i;
2837  float         small; /* the smallest affinity of vertecies */
2838  int           smallInd; /* index of vertex with the smallest affinity */
2839  int           col;
2840  int           row;
2841  Ntk_Node_t    *node, *pick;
2842
2843  small = (float)BIG_NUMBER;
2844  smallInd = 0; /* to avoid warning */
2845  pick = NIL(Ntk_Node_t);
2846
2847  st_lookup_int(ptrToIndex, (char *)seed, &row);
2848  arrayForEachItem(Ntk_Node_t *, cc, i, node) {
2849    if (array_fetch(int, ccCheck, i) != 1) {
2850      st_lookup_int(ptrToIndex, (char *)node, &col);
2851      affinity = PartGetElementFromSymMatrix(arrayOfAffinity, row, col);
2852      if (affinity < small) {
2853         small = affinity;
2854         pick = node;
2855         smallInd = i;
2856      }
2857    }
2858  }
2859  array_insert(int, ccCheck, smallInd, 1);
2860  return pick;
2861}
2862
2863
2864/**Function********************************************************************
2865
2866  Synopsis    [Get group matrix as regular matrix from given matrix
2867  according to the given clusters]
2868
2869  Description [Get matrix relation between each cluster, the values
2870  beetween
2871  each cluster are added]
2872
2873  SideEffects []
2874
2875******************************************************************************/
2876static float *
2877PartGetGroupMatrixRegular(
2878  array_t *arrayOfCluster,
2879  char *arrayOfGivenMatrix,
2880  st_table *ptrToIndex,
2881  int nVertices)
2882{
2883  float         *arrayOfGroupMatrix;  /* final result */
2884  array_t       *arrayClusterRow;
2885  array_t       *arrayClusterCol;
2886  float         subSum;
2887  int           row, col, i, j, k, l;
2888  Ntk_Node_t    *nodeRow, *nodeCol;
2889  int           index, size;
2890
2891  size = array_n(arrayOfCluster);
2892  arrayOfGroupMatrix = ALLOC(float, size * size);
2893
2894  arrayForEachItem(array_t *, arrayOfCluster, i, arrayClusterRow) {
2895    arrayForEachItem(array_t *, arrayOfCluster, j, arrayClusterCol) {
2896      if (i != j) {
2897        subSum = 0.0;
2898        arrayForEachItem(Ntk_Node_t *, arrayClusterRow, k, nodeRow) {
2899          st_lookup_int(ptrToIndex, (char *)nodeRow, &row);
2900          arrayForEachItem(Ntk_Node_t *, arrayClusterCol, l, nodeCol) {
2901            st_lookup_int(ptrToIndex, (char *)nodeCol, &col);
2902            index = row * nVertices + col;
2903            if (arrayOfGivenMatrix[index] == 1)
2904              subSum += 1.0;
2905          }
2906        }
2907        index = i * size + j;
2908        arrayOfGroupMatrix[index] = subSum /
2909                (float)(array_n(arrayClusterRow) * array_n(arrayClusterCol));
2910      } else {
2911        index = i * size + j;
2912        arrayOfGroupMatrix[index] = 0.0;
2913      }
2914    }
2915  }
2916  return arrayOfGroupMatrix;
2917}
2918
2919/**Function********************************************************************
2920
2921  Synopsis    [Get group matrix as symetric matrix from given matrix according
2922  to the given clusters]
2923
2924  Description [Get matrix relation between each cluster, the values beetween
2925  each cluster are added]
2926
2927  SideEffects []
2928
2929******************************************************************************/
2930static float *
2931PartGetGroupMatrixSym(
2932  array_t  *arrayOfCluster,
2933  float  *arrayOfGivenMatrix,
2934  st_table *ptrToIndex)
2935{
2936  float         *arrayOfGroupMatrix;  /* final result */
2937  array_t       *arrayClusterRow;
2938  array_t       *arrayClusterCol;
2939  float         subSum;
2940  int           row, col, i, j, k, l;
2941  Ntk_Node_t    *nodeRow, *nodeCol;
2942  int           index, size;
2943
2944  size = array_n(arrayOfCluster);
2945  arrayOfGroupMatrix = ALLOC(float, size * (size - 1) / 2);
2946
2947  for (i = 0; i < size; i++) {
2948    arrayClusterRow = array_fetch(array_t *, arrayOfCluster, i);
2949    for (j = 0; j < i; j++) {
2950      arrayClusterCol = array_fetch(array_t *, arrayOfCluster, j);
2951      if (i == j) {
2952        index = i * (i - 1) / 2 + j;
2953        arrayOfGroupMatrix[index] = 0.0;
2954      } else {
2955        subSum = 0.0;
2956        arrayForEachItem(Ntk_Node_t *, arrayClusterRow, k, nodeRow) {
2957          st_lookup_int(ptrToIndex, (char *)nodeRow, &row);
2958          arrayForEachItem(Ntk_Node_t *, arrayClusterCol, l, nodeCol) {
2959            st_lookup_int(ptrToIndex, (char *)nodeCol, &col);
2960            subSum += PartGetElementFromSymMatrix(arrayOfGivenMatrix, row, col);
2961          }
2962        }
2963        index = i * (i - 1) / 2 + j;
2964        arrayOfGroupMatrix[index] = subSum /
2965                (float)((array_n(arrayClusterRow)) * array_n(arrayClusterCol));
2966      }
2967    }
2968  }
2969  return arrayOfGroupMatrix;
2970}
2971
2972/**Function********************************************************************
2973
2974  Synopsis    [Select a connected component with minimum support variables]
2975
2976  SideEffects [The Corresponding flag of ccCheck is set after selection]
2977
2978******************************************************************************/
2979static int
2980PartSelectCCIndexOfMinSupport(
2981  array_t *arrayOfSmall,
2982  array_t *ccCheck,
2983  Part_SubsystemInfo_t *partSubInfo)
2984{
2985  array_t       *cc;
2986  array_t       *support;
2987  int           i, count, minCount, minIndex;
2988
2989  minCount = BIG_NUMBER;
2990  minIndex = -1;
2991
2992  for (i = 0; i < array_n(ccCheck); i++) {
2993    if (array_fetch(int, ccCheck, i) != 1) {
2994      cc = array_fetch(array_t *, arrayOfSmall, i);
2995      support = Ntk_NodeComputeCombinationalSupport(
2996        partSubInfo->network, cc, TRUE);
2997      count = array_n(support);
2998      array_free(support);
2999      if (count < minCount) {
3000        minIndex = i;
3001        minCount = count;
3002      }
3003    }
3004  }
3005  if (minIndex != -1) {
3006    array_insert(int, ccCheck, minIndex, 1);
3007  }
3008  return minIndex;
3009}
3010
3011/**Function********************************************************************
3012
3013  Synopsis    [Select a node with minimum support variables in network node
3014  set cc]
3015
3016  SideEffects [The Corresponding flag of ccCheck is set after selection]
3017
3018******************************************************************************/
3019static Ntk_Node_t *
3020PartSelectNodeOfMinSupport(
3021  array_t *cc,
3022  array_t *ccCheck,
3023  Part_SubsystemInfo_t *partSubInfo)
3024{
3025  array_t       *support;
3026  array_t       *nodeArray;
3027  int           i, minInd, count, min;
3028  Ntk_Node_t    *node;
3029  Ntk_Node_t    *minNode = NIL(Ntk_Node_t);
3030
3031  if (array_n(cc) == 0) {
3032    return NIL(Ntk_Node_t);
3033  }
3034
3035  min = BIG_NUMBER;
3036  minInd = 0; /* to avoid warning */
3037  arrayForEachItem(Ntk_Node_t *, cc, i, node) {
3038    if (array_fetch(int, ccCheck, i) != 1) {
3039      nodeArray = array_alloc(Ntk_Node_t *, 1);
3040      array_insert(Ntk_Node_t *, nodeArray, 0, node);
3041      support = Ntk_NodeComputeCombinationalSupport(
3042                        partSubInfo->network, nodeArray, TRUE);
3043      count = array_n(support);
3044      if (count < min) {
3045        minNode = node;
3046        min = count;
3047        minInd = i;
3048      }
3049      array_free(support);
3050      array_free(nodeArray);
3051    }
3052  }
3053  array_insert(int, ccCheck, minInd, 1);
3054  return minNode;
3055}
3056
3057/**Function********************************************************************
3058
3059  Synopsis    [Select an index of connected component from seed connected
3060  component]
3061
3062  SideEffects [The Corresponding flag of ccCheck is set after selection]
3063
3064******************************************************************************/
3065static int
3066PartSelectFarCCIndex(
3067  int seedIndex,
3068  array_t *arrayOfSmall,
3069  float *arrayOfGroupAff,
3070  Part_SubsystemInfo_t *partSubInfo,
3071  array_t *ccCheck)
3072{
3073  array_t *col;
3074  int i;
3075  float groupAff;
3076  float min;
3077  int minIndex;
3078
3079  min = (float)BIG_NUMBER;
3080  minIndex = -1;
3081
3082  arrayForEachItem(array_t *, arrayOfSmall, i, col) {
3083    if (array_fetch(int, ccCheck, i) != 1) {
3084      groupAff = PartGetElementFromSymMatrix(arrayOfGroupAff, seedIndex, i);
3085      if (groupAff < min) {
3086        minIndex = i;
3087        min = groupAff;
3088      }
3089    }
3090  }
3091  if (minIndex != -1) {
3092    array_insert(int, ccCheck, minIndex, 1);
3093  }
3094  return minIndex;
3095}
3096
3097/**Function********************************************************************
3098
3099  Synopsis    [Select an index of closest connected component from seed
3100  connected component]
3101
3102  SideEffects []
3103
3104******************************************************************************/
3105static int
3106PartSelectCloseCCIndex(
3107  int seedIndex,
3108  array_t *arrayOfSmall,
3109  float *arrayOfGroupAff,
3110  array_t *ccCheck)
3111{
3112  int i;
3113  float groupAff;
3114  float max;
3115  int maxIndex;
3116
3117  max = -1.0;
3118  maxIndex = -1;
3119
3120  for (i = 0; i < array_n(ccCheck); i++) {
3121    if (array_fetch(int, ccCheck, i) != 1) {
3122      groupAff = PartGetElementFromSymMatrix(arrayOfGroupAff, seedIndex, i);
3123      if (groupAff > max) {
3124        maxIndex = i;
3125        max = groupAff;
3126      }
3127    }
3128  }
3129  if (maxIndex != -1) {
3130    array_insert(int, ccCheck, maxIndex, 1);
3131  }
3132  return maxIndex;
3133}
3134
3135
3136/**Function********************************************************************
3137
3138  Synopsis    [Create a sub-system with given latch-data-input nodes]
3139
3140  SideEffects []
3141
3142  SeeAlso     []
3143******************************************************************************/
3144static Part_Subsystem_t*
3145PartCreateSingleSubSystem(
3146  array_t *arrayOfNodes,
3147  Ntk_Network_t *network)
3148{
3149  int           i, j;
3150  char          *name;
3151  Ntk_Node_t    *node;
3152  st_table      *vertexNameTable;
3153  array_t       *arrayOfLatchNames;
3154  Part_Subsystem_t *sub;
3155
3156  if (array_n(arrayOfNodes) == 0 || arrayOfNodes == NIL(array_t)) {
3157    return NIL(Part_Subsystem_t);
3158  }
3159
3160  vertexNameTable = st_init_table(strcmp, st_strhash);
3161  arrayForEachItem(Ntk_Node_t *, arrayOfNodes, i, node) {
3162    arrayOfLatchNames = PartReadLatchNameFromLatchInput(network, node);
3163    arrayForEachItem(char *, arrayOfLatchNames, j, name) {
3164      st_insert(vertexNameTable, (char *)name, (char *)NULL);
3165    }
3166    array_free(arrayOfLatchNames);
3167  }
3168  sub = ALLOC(Part_Subsystem_t, 1);
3169  sub->vertexNameTable = vertexNameTable;
3170  sub->subsystemFanIn = NIL(array_t);
3171  sub->subsystemFanOut = NIL(array_t);
3172
3173  return sub;
3174}
3175
3176/**Function********************************************************************
3177
3178  Synopsis    [Gets Latch Name from Latch Data Input]
3179
3180  SideEffects []
3181
3182  SeeAlso     []
3183******************************************************************************/
3184static array_t *
3185PartReadLatchNameFromLatchInput(
3186  Ntk_Network_t *network,
3187  Ntk_Node_t *latchInput)
3188{
3189  lsGen         gen;
3190  Ntk_Node_t    *latch, *temp1;
3191  char          *latchName = NIL(char);
3192  array_t       *arrayOfLatchNames;
3193
3194  arrayOfLatchNames = array_alloc(char *, 0);
3195  Ntk_NetworkForEachLatch(network, gen, latch) {
3196    temp1 = Ntk_LatchReadDataInput(latch);
3197    if (temp1 == latchInput) {
3198      latchName = Ntk_NodeReadName(latch);
3199      array_insert_last(char *, arrayOfLatchNames, latchName);
3200    }
3201  } /* end of Ntk_NetworkForEachLatch */
3202
3203  return arrayOfLatchNames;
3204}
3205
3206/**Function********************************************************************
3207
3208  Synopsis    [Free array of array]
3209
3210  SideEffects []
3211
3212******************************************************************************/
3213static void
3214PartArrayOfArrayFree(
3215  array_t *arrayOfMatrix)
3216{
3217  array_t *arrayRow;
3218  int i;
3219
3220  arrayForEachItem(array_t *, arrayOfMatrix, i, arrayRow) {
3221    array_free(arrayRow);
3222  }
3223  array_free(arrayOfMatrix);
3224}
3225
3226/**Function********************************************************************
3227
3228  Synopsis    [Get matrix(i,j) from symetric matrix]
3229
3230  SideEffects []
3231
3232******************************************************************************/
3233static float
3234PartGetElementFromSymMatrix(
3235  float *matrix,
3236  int i,
3237  int j)
3238{
3239  int index;
3240
3241  if (i == j)
3242    return(0.0);
3243  if (i < j) {
3244    int tmp;
3245
3246    tmp = i;
3247    i = j;
3248    j = tmp;
3249  }
3250  index = i * (i - 1) / 2 + j;
3251  return(matrix[index]);
3252}
3253
3254/**Function********************************************************************
3255
3256  Synopsis    [Print array of array]
3257
3258  Description [If type is 0, arrayArray is float regular matrix. If type = 1,
3259   arrayArray is char type symertic matrix.]
3260
3261  SideEffects []
3262
3263******************************************************************************/
3264static void
3265PartPrintArrayArray(
3266  void *arrayArray,
3267  int nVertices,
3268  int type)
3269{
3270  int i, j;
3271  float num;
3272  int index;
3273
3274  if (type == 0) { /* numerical data * symetric matrix */
3275    for (i = 0; i < nVertices; i++) {
3276      for (j = 0; j < nVertices; j++) {
3277        num = PartGetElementFromSymMatrix((float *)arrayArray, i, j);
3278        fprintf(vis_stdout, "%4.3f ", num);
3279      }
3280      fprintf(vis_stdout, "\n");
3281    }
3282  } else if (type == 1) { /* char data & regular */
3283    for (i = 0; i < nVertices; i++) {
3284      for (j = 0; j < nVertices; j++) {
3285        index = i * nVertices + j;
3286        if (((char *)arrayArray)[index] == 1) {
3287          fprintf(vis_stdout, "1 ");
3288        } else {
3289          fprintf(vis_stdout, "0 ");
3290        }
3291      }
3292      fprintf(vis_stdout, "\n");
3293    }
3294  }
3295  fprintf(vis_stdout, "\n");
3296}
3297
3298/**Function********************************************************************
3299
3300  Synopsis    [Compare procedure for string comparison.]
3301
3302  Description [Compare procedure for string comparison.]
3303
3304  SideEffects []
3305
3306******************************************************************************/
3307static int
3308strCompare(
3309  const void *name1,
3310  const void *name2)
3311{
3312    return(strcmp(*(char **)name1, *(char **)name2));
3313} /* end of strCompare */
3314
3315/**Function********************************************************************
3316
3317  Synopsis    [Compare procedure for number comparison.]
3318
3319  Description [Compare procedure for number comparison.]
3320
3321  SideEffects []
3322
3323******************************************************************************/
3324static int
3325numCompare(
3326  const void *num1,
3327  const void *num2)
3328{
3329    return(*(int *)num1 > *(int *)num2);
3330} /* end of strCompare */
Note: See TracBrowser for help on using the repository browser.