abc-master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
place_partition.c File Reference
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <stdio.h>
#include <limits.h>
#include <assert.h>
#include "place_base.h"
#include "place_gordian.h"
#include "libhmetis.h"

Go to the source code of this file.

Data Structures

struct  FM_cell
 

Typedefs

typedef struct FM_cell FM_cell
 

Functions

void FM_updateGains (ConcreteNet *net, int partition, int inc, FM_cell target[], FM_cell *bin[], int count_1[], int count_2[])
 
void initPartitioning ()
 Initializes data structures necessary for partitioning. More...
 
void presortNets ()
 Sorts nets by corner positions. More...
 
bool refinePartitions ()
 Splits large leaf partitions. More...
 
void reallocPartitions ()
 Reallocates the partitions based on placement information. More...
 
bool refinePartition (Partition *p)
 Splits any large leaves within a partition. More...
 
void repartitionHMetis (Partition *parent)
 Repartitions the two subpartitions using the hMetis min-cut library. More...
 
void repartitionFM (Partition *parent)
 Fiduccia-Matheyses mincut partitioning algorithm. More...
 
void partitionEqualArea (Partition *parent)
 Splits a partition into two halves of equal area. More...
 
void partitionScanlineMincut (Partition *parent)
 Scans the cells within a partition from left to right and chooses the min-cut. More...
 
void reallocPartition (Partition *p)
 Reallocates a partition and all of its children. More...
 
void resizePartition (Partition *p)
 Recomputes the bounding boxes of the child partitions based on their relative areas. More...
 
void incrementalSubpartition (Partition *p, ConcreteCell *newCells[], const int numNewCells)
 Adds new cells to an existing partition. Partition sizes/locations are unchanged. More...
 
void incrementalPartition ()
 Adds new cells to an existing partition. Partition sizes/locations are unchanged. More...
 

Variables

ABC_NAMESPACE_IMPL_START
Partition
g_place_rootPartition = NULL
 
ConcreteNet ** allNetsR2 = NULL
 
ConcreteNet ** allNetsL2 = NULL
 
ConcreteNet ** allNetsB2 = NULL
 
ConcreteNet ** allNetsT2 = NULL
 

Typedef Documentation

typedef struct FM_cell FM_cell

Function Documentation

void FM_updateGains ( ConcreteNet net,
int  partition,
int  inc,
FM_cell  target[],
FM_cell bin[],
int  count_1[],
int  count_2[] 
)
void incrementalPartition ( )

Adds new cells to an existing partition. Partition sizes/locations are unchanged.

The function recurses, adding new cells to appropriate subpartitions.

Definition at line 1103 of file place_partition.c.

1103  {
1104  int c = 0, c2 = 0;
1105  int numNewCells = 0;
1106  ConcreteCell **allCells = (ConcreteCell **)malloc(sizeof(ConcreteCell*)*g_place_numCells),
1107  **newCells = (ConcreteCell **)malloc(sizeof(ConcreteCell*)*g_place_numCells);
1108 
1110 
1111  // update cell list of root partition
1113  qsort(allCells, g_place_numCells, sizeof(ConcreteCell*), cellSortByID);
1115  sizeof(ConcreteCell*), cellSortByID);
1116 
1117  // scan sorted lists and collect cells not in partitions
1118  while(!allCells[c++]);
1119  while(!g_place_rootPartition->m_members[c2++]);
1120 
1121  for(; c<g_place_numCells; c++, c2++) {
1122  while(c2 < g_place_rootPartition->m_numMembers &&
1123  allCells[c]->m_id > g_place_rootPartition->m_members[c2]->m_id) c2++;
1124  while(c < g_place_numCells &&
1126  allCells[c]->m_id < g_place_rootPartition->m_members[c2]->m_id)) {
1127  // a new cell!
1128  newCells[numNewCells++] = allCells[c];
1129  c++;
1130  }
1131  }
1132 
1133  printf("QPRT-50 : \tincremental partitioning with %d new cells\n", numNewCells);
1134  if (numNewCells>0) incrementalSubpartition(g_place_rootPartition, newCells, numNewCells);
1135 
1136  free(allCells);
1137  free(newCells);
1138 }
char * malloc()
VOID_HACK free()
char * memcpy()
ConcreteCell ** g_place_concreteCells
Definition: place_base.c:33
ABC_NAMESPACE_IMPL_START Partition * g_place_rootPartition
void incrementalSubpartition(Partition *p, ConcreteCell *newCells[], const int numNewCells)
Adds new cells to an existing partition. Partition sizes/locations are unchanged. ...
int cellSortByID(const void *a, const void *b)
Definition: place_base.c:338
ConcreteCell ** m_members
Definition: place_gordian.h:49
int m_numMembers
Definition: place_gordian.h:48
#define assert(ex)
Definition: util_old.h:213
ABC_NAMESPACE_IMPL_START int g_place_numCells
Definition: place_base.c:26
void incrementalSubpartition ( Partition p,
ConcreteCell newCells[],
const int  numNewCells 
)

Adds new cells to an existing partition. Partition sizes/locations are unchanged.

The function recurses, adding new cells to appropriate subpartitions.

Definition at line 1052 of file place_partition.c.

1052  {
1053  int c;
1054  ConcreteCell **newCells1 = (ConcreteCell **)malloc(sizeof(ConcreteCell*)*numNewCells),
1055  **newCells2 = (ConcreteCell **)malloc(sizeof(ConcreteCell*)*numNewCells);
1056  int numNewCells1 = 0, numNewCells2 = 0;
1057  float cut_loc;
1058 
1059  assert(p);
1060 
1061  // add new cells to partition list
1063  sizeof(ConcreteCell*)*(p->m_numMembers+numNewCells));
1064  memcpy(&(p->m_members[p->m_numMembers]), newCells, sizeof(ConcreteCell*)*numNewCells);
1065  p->m_numMembers += numNewCells;
1066 
1067  // if is a leaf partition, finished
1068  if (p->m_leaf) return;
1069 
1070  // split new cells into sub-partitions based on location
1071  if (p->m_vertical) {
1072  cut_loc = p->m_sub2->m_bounds.x;
1073  for(c=0; c<numNewCells; c++)
1074  if (newCells[c]->m_x < cut_loc)
1075  newCells1[numNewCells1++] = newCells[c];
1076  else
1077  newCells2[numNewCells2++] = newCells[c];
1078  } else {
1079  cut_loc = p->m_sub2->m_bounds.y;
1080  for(c=0; c<numNewCells; c++)
1081  if (newCells[c]->m_y < cut_loc)
1082  newCells1[numNewCells1++] = newCells[c];
1083  else
1084  newCells2[numNewCells2++] = newCells[c];
1085  }
1086 
1087  if (numNewCells1 > 0) incrementalSubpartition(p->m_sub1, newCells1, numNewCells1);
1088  if (numNewCells2 > 0) incrementalSubpartition(p->m_sub2, newCells2, numNewCells2);
1089 
1090  free(newCells1);
1091  free(newCells2);
1092 }
struct Partition * m_sub1
Definition: place_gordian.h:56
char * malloc()
VOID_HACK free()
float x
Definition: place_base.h:35
char * memcpy()
float y
Definition: place_base.h:35
char * realloc()
struct Partition * m_sub2
Definition: place_gordian.h:56
void incrementalSubpartition(Partition *p, ConcreteCell *newCells[], const int numNewCells)
Adds new cells to an existing partition. Partition sizes/locations are unchanged. ...
bool m_vertical
Definition: place_gordian.h:51
ConcreteCell ** m_members
Definition: place_gordian.h:49
Rect m_bounds
Definition: place_gordian.h:50
int m_numMembers
Definition: place_gordian.h:48
#define assert(ex)
Definition: util_old.h:213
void initPartitioning ( )

Initializes data structures necessary for partitioning.

Creates a valid g_place_rootPartition.

Definition at line 67 of file place_partition.c.

67  {
68  int i;
69  float area;
70 
71  // create root partition
81 
82  // add all of the cells to this partition
85  for (i=0; i<g_place_numCells; i++)
86  if (g_place_concreteCells[i]) {
87  if (!g_place_concreteCells[i]->m_fixed) {
92  }
93  }
94 }
char * malloc()
ABC_NAMESPACE_IMPL_START int g_place_numPartitions
Definition: place_gordian.c:28
VOID_HACK free()
ConcreteCell ** g_place_concreteCells
Definition: place_base.c:33
ABC_NAMESPACE_IMPL_START Partition * g_place_rootPartition
float getCellArea(const ConcreteCell *cell)
Definition: place_base.c:99
bool m_vertical
Definition: place_gordian.h:51
ConcreteCell ** m_members
Definition: place_gordian.h:49
Rect g_place_coreBounds
Definition: place_base.c:30
Rect m_bounds
Definition: place_gordian.h:50
int m_numMembers
Definition: place_gordian.h:48
ABC_NAMESPACE_IMPL_START int g_place_numCells
Definition: place_base.c:26
float m_area
Definition: place_gordian.h:54
void partitionEqualArea ( Partition parent)

Splits a partition into two halves of equal area.

Definition at line 834 of file place_partition.c.

834  {
835  float halfArea, area;
836  int i=0;
837 
838  // which way to sort?
839  if (parent->m_vertical)
840  // sort by X position
841  qsort(parent->m_members, parent->m_numMembers, sizeof(ConcreteCell*), cellSortByX);
842  else
843  // sort by Y position
844  qsort(parent->m_members, parent->m_numMembers, sizeof(ConcreteCell*), cellSortByY);
845 
846  // split the list
847  halfArea = parent->m_area*0.5;
848  parent->m_sub1->m_area = 0.0;
849  parent->m_sub1->m_numMembers = 0;
850  parent->m_sub1->m_members = (ConcreteCell**)realloc(parent->m_sub1->m_members,
851  sizeof(ConcreteCell*)*parent->m_numMembers);
852  parent->m_sub2->m_area = 0.0;
853  parent->m_sub2->m_numMembers = 0;
854  parent->m_sub2->m_members = (ConcreteCell**)realloc(parent->m_sub2->m_members,
855  sizeof(ConcreteCell*)*parent->m_numMembers);
856 
857  for(; parent->m_sub1->m_area < halfArea; i++)
858  if (parent->m_members[i]) {
859  area = getCellArea(parent->m_members[i]);
860  parent->m_sub1->m_members[parent->m_sub1->m_numMembers++] = parent->m_members[i];
861  parent->m_sub1->m_area += area;
862  }
863  for(; i<parent->m_numMembers; i++)
864  if (parent->m_members[i]) {
865  area = getCellArea(parent->m_members[i]);
866  parent->m_sub2->m_members[parent->m_sub2->m_numMembers++] = parent->m_members[i];
867  parent->m_sub2->m_area += area;
868  }
869 
870 }
int cellSortByX(const void *a, const void *b)
Sorts cells by either position coordinate.
Definition: place_base.c:314
struct Partition * m_sub1
Definition: place_gordian.h:56
int cellSortByY(const void *a, const void *b)
Definition: place_base.c:326
char * realloc()
struct Partition * m_sub2
Definition: place_gordian.h:56
float getCellArea(const ConcreteCell *cell)
Definition: place_base.c:99
bool m_vertical
Definition: place_gordian.h:51
ConcreteCell ** m_members
Definition: place_gordian.h:49
int m_numMembers
Definition: place_gordian.h:48
float m_area
Definition: place_gordian.h:54
void partitionScanlineMincut ( Partition parent)

Scans the cells within a partition from left to right and chooses the min-cut.

Definition at line 879 of file place_partition.c.

879  {
880 #if 0
881  int current_cuts = 0;
882  int minimum_cuts = INT_MAX;
883  ConcreteCell *minimum_location = NULL;
884  double currentArea = 0, halfArea = parent->m_area * 0.5;
885  double areaFlexibility = parent->m_area * MAX_PARTITION_NONSYMMETRY;
886  double newLine, oldLine = -DBL_MAX;
887 
888  for(ConcreteNetList::iterator n_it = m_design->nets.begin(); !n_it; n_it++)
889  (*n_it)->m_mark = 0;
890  for(h::list<ConcreteCell *>::iterator i = parent->m_members.begin();
891  !i.isDone(); i++) {
892  assert(*i);
893  for(ConcretePinMap::iterator j = (*i)->getPins().begin();
894  !j.isDone(); j++) {
895  assert(*j);
896  if((*j)->isAttached()) {
897  (*j)->getNet()->m_mark = 1;
898  }
899  }
900  }
901 
902  if (parent->vertical) {
903  parent->m_members.sort(sortByX);
904  int all1 = 0, all2 = 0;
905  h::list<ConcreteCell *>::iterator local = parent->m_members.begin();
906  for(; !local.isDone(); local++) {
907  currentArea += (*local)->getArea();
908  if (currentArea < halfArea-areaFlexibility)
909  continue;
910  if (currentArea > halfArea+areaFlexibility)
911  break;
912  newLine = (*local)->temp_x;
913  while(all1 < g_place_numNets && allNetsL2[all1]->getBoundingBox().left() <= newLine) {
914  if(allNetsL2[all1]->m_mark) {
915  current_cuts++;
916  }
917  all1++;
918  }
919  while(all2 < g_place_numNets && allNetsR2[all2]->getBoundingBox().right() <= newLine) {
920  if(allNetsR2[all2]->m_mark) {
921  current_cuts--;
922  }
923  all2++;
924  }
925  if (current_cuts < minimum_cuts) {
926  minimum_cuts = current_cuts;
927  minimum_location = *local;
928  }
929  oldLine = newLine;
930  }
931  }
932  else {
933  parent->m_members.sort(sortByY);
934  int all1 = 0, all2 = 0;
935  h::list<ConcreteCell *>::iterator local = parent->m_members.begin();
936  for(; !local.isDone(); local++) {
937  currentArea += (*local)->getArea();
938  if (currentArea < halfArea-areaFlexibility)
939  continue;
940  if (currentArea > halfArea+areaFlexibility)
941  break;
942  newLine = (*local)->temp_y;
943  while(all1 < g_place_numNets && allNetsB2[all1]->getBoundingBox().top() <= newLine) {
944  if(allNetsB2[all1]->m_mark) {
945  current_cuts++;
946  }
947  all1++;
948  }
949  while(all2 < g_place_numNets && allNetsT2[all2]->getBoundingBox().bottom() <= newLine) {
950  if(allNetsT2[all2]->m_mark) {
951  current_cuts--;
952  }
953  all2++;
954  }
955  if (current_cuts < minimum_cuts) {
956  minimum_cuts = current_cuts;
957  minimum_location = *local;
958  }
959  oldLine = newLine;
960  }
961  }
962  if (minimum_location == NULL) {
963  return partitionEqualArea(parent);
964  }
965  h::list<ConcreteCell *>::iterator it = parent->m_members.begin();
966  parent->m_sub1->m_members.clear();
967  parent->m_sub1->m_area = 0;
968  for(; *it != minimum_location; it++) {
969  parent->m_sub1->m_members.push_front(*it);
970  parent->m_sub1->m_area += (*it)->getArea();
971  }
972  parent->m_sub2->m_members.clear();
973  parent->m_sub2->m_area = 0;
974  for(; !it; it++) {
975  parent->m_sub2->m_members.push_front(*it);
976  parent->m_sub2->m_area += (*it)->getArea();
977  }
978 #endif
979 }
void partitionEqualArea(Partition *parent)
Splits a partition into two halves of equal area.
struct Partition * m_sub1
Definition: place_gordian.h:56
ConcreteNet ** allNetsT2
#define MAX_PARTITION_NONSYMMETRY
Definition: place_gordian.h:30
ConcreteNet ** allNetsR2
struct Partition * m_sub2
Definition: place_gordian.h:56
ConcreteNet ** allNetsL2
ConcreteNet ** allNetsB2
#define local
Definition: adler32.c:17
ConcreteCell ** m_members
Definition: place_gordian.h:49
int g_place_numNets
Definition: place_base.c:27
#define assert(ex)
Definition: util_old.h:213
float m_area
Definition: place_gordian.h:54
void presortNets ( )

Sorts nets by corner positions.

Allocates allNetsX2 structures.

Definition at line 105 of file place_partition.c.

105  {
114  qsort(allNetsL2, g_place_numNets, sizeof(ConcreteNet*), netSortByL);
115  qsort(allNetsR2, g_place_numNets, sizeof(ConcreteNet*), netSortByR);
116  qsort(allNetsB2, g_place_numNets, sizeof(ConcreteNet*), netSortByB);
117  qsort(allNetsT2, g_place_numNets, sizeof(ConcreteNet*), netSortByT);
118 }
ConcreteNet ** allNetsT2
ConcreteNet ** g_place_concreteNets
Definition: place_base.c:35
int netSortByR(const void *a, const void *b)
Definition: place_base.c:249
int netSortByB(const void *a, const void *b)
Definition: place_base.c:263
char * memcpy()
char * realloc()
ConcreteNet ** allNetsR2
ConcreteNet ** allNetsL2
int netSortByT(const void *a, const void *b)
Definition: place_base.c:277
ConcreteNet ** allNetsB2
int g_place_numNets
Definition: place_base.c:27
int netSortByL(const void *a, const void *b)
Sorts nets by position of one of its corners.
Definition: place_base.c:235
void reallocPartition ( Partition p)

Reallocates a partition and all of its children.

Definition at line 988 of file place_partition.c.

988  {
989 
990  if (p->m_leaf) {
991  return;
992  }
993 
994  // --- INITIAL PARTITION
995 
998  else
1000 
1001  resizePartition(p);
1002 
1003  // --- PARTITION IMPROVEMENT
1004  if (p->m_level < REPARTITION_LEVEL_DEPTH) {
1005  if (REPARTITION_HMETIS)
1006  repartitionHMetis(p);
1007 
1008  resizePartition(p);
1009  }
1010 
1013 }
void partitionEqualArea(Partition *parent)
Splits a partition into two halves of equal area.
struct Partition * m_sub1
Definition: place_gordian.h:56
void partitionScanlineMincut(Partition *parent)
Scans the cells within a partition from left to right and chooses the min-cut.
void resizePartition(Partition *p)
Recomputes the bounding boxes of the child partitions based on their relative areas.
struct Partition * m_sub2
Definition: place_gordian.h:56
void reallocPartition(Partition *p)
Reallocates a partition and all of its children.
#define REPARTITION_HMETIS
Definition: place_gordian.h:36
void repartitionHMetis(Partition *parent)
Repartitions the two subpartitions using the hMetis min-cut library.
#define REPARTITION_LEVEL_DEPTH
Definition: place_gordian.h:33
#define PARTITION_AREA_ONLY
Definition: place_gordian.h:26
void reallocPartitions ( )

Reallocates the partitions based on placement information.

Definition at line 138 of file place_partition.c.

138  {
139 
141 }
ABC_NAMESPACE_IMPL_START Partition * g_place_rootPartition
void reallocPartition(Partition *p)
Reallocates a partition and all of its children.
bool refinePartition ( Partition p)

Splits any large leaves within a partition.

Definition at line 150 of file place_partition.c.

150  {
151  bool degenerate = false;
152  int nonzeroCount = 0;
153  int i;
154 
155  assert(p);
156 
157  // is this partition completed?
158  if (p->m_done) return true;
159 
160  // is this partition a non-leaf node?
161  if (!p->m_leaf) {
162  p->m_done = refinePartition(p->m_sub1);
163  p->m_done &= refinePartition(p->m_sub2);
164  return p->m_done;
165  }
166 
167  // leaf...
168  // create two new subpartitions
170  p->m_sub1 = malloc(sizeof(Partition));
171  p->m_sub1->m_level = p->m_level+1;
172  p->m_sub1->m_leaf = true;
173  p->m_sub1->m_done = false;
174  p->m_sub1->m_area = 0;
175  p->m_sub1->m_vertical = !p->m_vertical;
176  p->m_sub1->m_numMembers = 0;
177  p->m_sub1->m_members = NULL;
178  p->m_sub2 = malloc(sizeof(Partition));
179  p->m_sub2->m_level = p->m_level+1;
180  p->m_sub2->m_leaf = true;
181  p->m_sub2->m_done = false;
182  p->m_sub2->m_area = 0;
183  p->m_sub2->m_vertical = !p->m_vertical;
184  p->m_sub2->m_numMembers = 0;
185  p->m_sub2->m_members = NULL;
186  p->m_leaf = false;
187 
188  // --- INITIAL PARTITION
189 
192  else
194 
195  resizePartition(p);
196 
197  // --- PARTITION IMPROVEMENT
198 
199  if (p->m_level < REPARTITION_LEVEL_DEPTH) {
200  if (REPARTITION_FM)
201  repartitionFM(p);
202  else if (REPARTITION_HMETIS)
204  }
205 
206  resizePartition(p);
207 
208  // fix imbalances due to zero-area cells
209  for(i=0; i<p->m_sub1->m_numMembers; i++)
210  if (p->m_sub1->m_members[i])
211  if (getCellArea(p->m_sub1->m_members[i]) > 0) {
212  nonzeroCount++;
213  }
214 
215  // is this leaf now done?
216  if (nonzeroCount <= LARGEST_FINAL_SIZE)
217  p->m_sub1->m_done = true;
218  if (nonzeroCount == 0)
219  degenerate = true;
220 
221  nonzeroCount = 0;
222  for(i=0; i<p->m_sub2->m_numMembers; i++)
223  if (p->m_sub2->m_members[i])
224  if (getCellArea(p->m_sub2->m_members[i]) > 0) {
225  nonzeroCount++;
226  }
227 
228  // is this leaf now done?
229  if (nonzeroCount <= LARGEST_FINAL_SIZE)
230  p->m_sub2->m_done = true;
231  if (nonzeroCount == 0)
232  degenerate = true;
233 
234  // have we found a degenerate partitioning?
235  if (degenerate) {
236  printf("QPART-35 : WARNING: degenerate partition generated\n");
238  resizePartition(p);
239  p->m_sub1->m_done = true;
240  p->m_sub2->m_done = true;
241  }
242 
243  // is this parent now finished?
244  if (p->m_sub1->m_done && p->m_sub2->m_done) p->m_done = true;
245 
246  return p->m_done;
247 }
void partitionEqualArea(Partition *parent)
Splits a partition into two halves of equal area.
struct Partition * m_sub1
Definition: place_gordian.h:56
char * malloc()
bool refinePartition(Partition *p)
Splits any large leaves within a partition.
ABC_NAMESPACE_IMPL_START int g_place_numPartitions
Definition: place_gordian.c:28
void partitionScanlineMincut(Partition *parent)
Scans the cells within a partition from left to right and chooses the min-cut.
void resizePartition(Partition *p)
Recomputes the bounding boxes of the child partitions based on their relative areas.
struct Partition * m_sub2
Definition: place_gordian.h:56
float getCellArea(const ConcreteCell *cell)
Definition: place_base.c:99
#define REPARTITION_HMETIS
Definition: place_gordian.h:36
bool m_vertical
Definition: place_gordian.h:51
#define REPARTITION_FM
Definition: place_gordian.h:35
void repartitionHMetis(Partition *parent)
Repartitions the two subpartitions using the hMetis min-cut library.
void repartitionFM(Partition *parent)
Fiduccia-Matheyses mincut partitioning algorithm.
ConcreteCell ** m_members
Definition: place_gordian.h:49
#define LARGEST_FINAL_SIZE
Definition: place_gordian.h:25
#define REPARTITION_LEVEL_DEPTH
Definition: place_gordian.h:33
int m_numMembers
Definition: place_gordian.h:48
#define assert(ex)
Definition: util_old.h:213
#define PARTITION_AREA_ONLY
Definition: place_gordian.h:26
float m_area
Definition: place_gordian.h:54
bool refinePartitions ( )

Splits large leaf partitions.

Definition at line 126 of file place_partition.c.

126  {
127 
129 }
bool refinePartition(Partition *p)
Splits any large leaves within a partition.
ABC_NAMESPACE_IMPL_START Partition * g_place_rootPartition
void repartitionFM ( Partition parent)

Fiduccia-Matheyses mincut partitioning algorithm.

UNIMPLEMENTED (well, un-C-ified)

Definition at line 435 of file place_partition.c.

435  {
436 #if 0
437  assert(!parent->leaf && parent->m_sub1->leaf && parent->m_sub2->leaf);
438 
439  // count of each net's number of cells in each bipartition
440  int count_1[m_design->nets.length()];
441  memset(count_1, 0, sizeof(int)*m_design->nets.length());
442  int count_2[m_design->nets.length()];
443  memset(count_2, 0, sizeof(int)*m_design->nets.length());
444 
445  FM_cell target[m_design->cells.length()];
446  memset(target, 0, sizeof(FM_cell)*m_design->cells.length());
447  FM_cell *bin[FM_MAX_BIN+1];
448  FM_cell *locked = 0;
449  memset(bin, 0, sizeof(FM_cell *)*(FM_MAX_BIN+1));
450 
451  int max_gain = 0;
452  int before_cuts = 0, current_cuts = 0;
453  double initial_cut;
454  int targets = 0;
455  long cell_id;
456  double halfArea = parent->m_area / 2.0;
457  double areaFlexibility = parent->m_area * MAX_PARTITION_NONSYMMETRY;
458  ConcreteNet *net;
459 
460  // INITIALIZATION
461  // select cells to partition
462 
463  if (parent->vertical) {
464  // vertical
465 
466  initial_cut = parent->m_sub2->m_bounds.x;
467 
468  // initialize all cells
469  for(h::list<ConcreteCell *>::iterator it = rootPartition->m_members.begin(); !it; it++) {
470  cell_id = (*it)->getID();
471  if ((*it)->temp_x < initial_cut)
472  target[cell_id].loc = -1;
473  else
474  target[cell_id].loc = -2;
475  target[cell_id].cell = *it;
476  target[cell_id].gain = 0;
477  }
478 
479  // initialize cells in partition 1
480  for(h::list<ConcreteCell *>::iterator it = parent->m_sub1->m_members.begin(); !it; it++) {
481  cell_id = (*it)->getID();
482  // pay attention to cells that are close to the cut
483  if (abs((*it)->temp_x-initial_cut) < parent->m_bounds.w*REPARTITION_TARGET_FRACTION) {
484  targets++;
485  target[cell_id].loc = 1;
486  }
487  }
488 
489  // initialize cells in partition 2
490  for(h::list<ConcreteCell *>::iterator it = parent->m_sub2->m_members.begin(); !it; it++) {
491  cell_id = (*it)->getID();
492  // pay attention to cells that are close to the cut
493  if (abs((*it)->temp_x-initial_cut) < parent->m_bounds.w*REPARTITION_TARGET_FRACTION) {
494  targets++;
495  target[cell_id].loc = 2;
496  }
497  }
498 
499  // count the number of cells on each side of the partition for every net
500  for(h::hash_map<ConcreteNet *>::iterator n_it = m_design->nets.begin(); !n_it; n_it++) {
501  for(ConcretePinList::iterator p_it = (net = *n_it)->getPins().begin(); !p_it; p_it++)
502  if (abs(target[(*p_it)->getCell()->getID()].loc) == 1)
503  count_1[net->getID()]++;
504  else if (abs(target[(*p_it)->getCell()->getID()].loc) == 2)
505  count_2[net->getID()]++;
506  else if ((*p_it)->getCell()->temp_x < initial_cut)
507  count_1[net->getID()]++;
508  else
509  count_2[net->getID()]++;
510  if (count_1[net->getID()] > 0 && count_2[net->getID()] > 0) before_cuts++;
511  }
512 
513  } else {
514  // horizontal
515 
516  initial_cut = parent->m_sub2->m_bounds.y;
517 
518  // initialize all cells
519  for(h::list<ConcreteCell *>::iterator it = rootPartition->m_members.begin(); !it; it++) {
520  cell_id = (*it)->getID();
521  if ((*it)->temp_y < initial_cut)
522  target[cell_id].loc = -1;
523  else
524  target[cell_id].loc = -2;
525  target[cell_id].cell = *it;
526  target[cell_id].gain = 0;
527  }
528 
529  // initialize cells in partition 1
530  for(h::list<ConcreteCell *>::iterator it = parent->m_sub1->m_members.begin(); !it; it++) {
531  cell_id = (*it)->getID();
532  // pay attention to cells that are close to the cut
533  if (abs((*it)->temp_y-initial_cut) < parent->m_bounds.h*REPARTITION_TARGET_FRACTION) {
534  targets++;
535  target[cell_id].loc = 1;
536  }
537  }
538 
539  // initialize cells in partition 2
540  for(h::list<ConcreteCell *>::iterator it = parent->m_sub2->m_members.begin(); !it; it++) {
541  cell_id = (*it)->getID();
542  // pay attention to cells that are close to the cut
543  if (abs((*it)->temp_y-initial_cut) < parent->m_bounds.h*REPARTITION_TARGET_FRACTION) {
544  targets++;
545  target[cell_id].loc = 2;
546  }
547  }
548 
549  // count the number of cells on each side of the partition for every net
550  for(h::hash_map<ConcreteNet *>::iterator n_it = m_design->nets.begin(); !n_it; n_it++) {
551  for(ConcretePinList::iterator p_it = (net = *n_it)->getPins().begin(); !p_it; p_it++)
552  if (abs(target[(*p_it)->getCell()->getID()].loc) == 1)
553  count_1[net->getID()]++;
554  else if (abs(target[(*p_it)->getCell()->getID()].loc) == 2)
555  count_2[net->getID()]++;
556  else if ((*p_it)->getCell()->temp_y < initial_cut)
557  count_1[net->getID()]++;
558  else
559  count_2[net->getID()]++;
560  if (count_1[net->getID()] > 0 && count_2[net->getID()] > 0) before_cuts++;
561  }
562  }
563 
564  // INITIAL GAIN CALCULATION
565  for(long id=0; id < m_design->cells.length(); id++)
566  if (target[id].loc > 0) {
567  assert(target[id].cell != 0);
568  assert(target[id].gain == 0);
569 
570  // examine counts for the net on each pin
571  for(ConcretePinMap::iterator p_it = target[id].cell->getPins().begin(); !p_it; p_it++)
572  if ((*p_it)->isAttached()) {
573  int n_id = (*p_it)->getNet()->getID();
574  if (target[id].loc == 1 && count_1[n_id] == 1) target[id].gain++;
575  if (target[id].loc == 1 && count_2[n_id] == 0) target[id].gain--;
576  if (target[id].loc == 2 && count_1[n_id] == 0) target[id].gain--;
577  if (target[id].loc == 2 && count_2[n_id] == 1) target[id].gain++;
578  }
579 
580  assert(target[id].cell->getPins().length() >= abs(target[id].gain));
581 
582  // add it to a bin
583  int bin_num = min(max(0, target[id].gain),FM_MAX_BIN);
584  max_gain = max(max_gain, bin_num);
585 
586  assert(bin_num >= 0 && bin_num <= FM_MAX_BIN);
587  target[id].next = bin[bin_num];
588  target[id].prev = 0;
589  if (bin[bin_num] != 0)
590  bin[bin_num]->prev = &target[id];
591  bin[bin_num] = &target[id];
592  }
593 
594  // OUTER F-M LOOP
595  current_cuts = before_cuts;
596  int num_moves = 1;
597  int pass = 0;
598  while(num_moves > 0 && pass < FM_MAX_PASSES) {
599  pass++;
600  num_moves = 0;
601 
602  // check_list(bin, locked, targets); // DEBUG
603 
604  // move all locked cells back
605  int moved_back = 0;
606  while(locked != 0) {
607  FM_cell *current = locked;
608  current->locked = false;
609 
610  int bin_num = min(max(0, current->gain),FM_MAX_BIN);
611  max_gain = max(max_gain, bin_num);
612 
613  locked = current->next;
614  if (locked != 0)
615  locked->prev = 0;
616 
617  if (bin[bin_num] != 0)
618  bin[bin_num]->prev = current;
619  current->next = bin[bin_num];
620  bin[bin_num] = current;
621 
622  moved_back++;
623  }
624  // cout << "\tmoved back: " << moved_back << endl;
625  // check_list(bin, locked, targets); // DEBUG
626 
627  max_gain = FM_MAX_BIN;
628  while(bin[max_gain] == 0 && max_gain > 0) max_gain--;
629 
630  // INNER F-M LOOP (single pass)
631  while(1) {
632 
633  int bin_num = FM_MAX_BIN;
634  FM_cell *current = bin[bin_num];
635 
636  // look for next cell to move
637  while (bin_num > 0 && (current == 0 ||
638  (current->loc==1 && current->cell->getArea()+parent->m_sub2->m_area > halfArea+areaFlexibility) ||
639  (current->loc==2 && current->cell->getArea()+parent->m_sub1->m_area > halfArea+areaFlexibility))) {
640 
641  if (current == 0) current = bin[--bin_num]; else current = current->next;
642  }
643  if (bin_num == 0)
644  break;
645 
646  num_moves++;
647  current->locked = true;
648  // cout << "moving cell " << current->cell->getID() << " gain=" << current->gain << " pins= " << current->cell->getPins().length() << " from " << current->loc;
649 
650  // change partition marking and areas
651  if (current->loc == 1) {
652  current->loc = 2;
653  parent->m_sub1->m_area -= current->cell->getArea();
654  parent->m_sub2->m_area += current->cell->getArea();
655 
656  // update partition counts on all nets attached to this cell
657  for(ConcretePinMap::iterator p_it = current->cell->getPins().begin();
658  !p_it; p_it++) {
659 
660  if (!(*p_it)->isAttached()) // ignore unattached pins
661  continue;
662  net = (*p_it)->getNet();
663 
664  count_1[net->getID()]--;
665  count_2[net->getID()]++;
666 
667  // cout << "\tnet " << net->getID() << " was " << count_1[net->getID()]+1 << "/" << count_2[net->getID()]-1 << " now " << count_1[net->getID()] << "/" << count_2[net->getID()] << endl;
668 
669  // if net becomes critical, update gains on attached cells and resort bins
670  if (count_1[net->getID()] == 0) { current_cuts--; FM_updateGains(net, 2, -1, target, bin, count_1, count_2); }
671  if (count_2[net->getID()] == 1) { current_cuts++; FM_updateGains(net, 1, -1, target, bin, count_1, count_2); }
672 
673  // check_list(bin, locked, targets); // DEBUG
674  }
675 
676  } else {
677  current->loc = 1;
678  parent->m_sub2->m_area -= current->cell->getArea();
679  parent->m_sub1->m_area += current->cell->getArea();
680 
681  // update gains on all nets attached to this cell
682  for(ConcretePinMap::iterator p_it = current->cell->getPins().begin();
683  !p_it; p_it++) {
684 
685  if (!(*p_it)->isAttached()) // ignore unattached pins
686  continue;
687  net = (*p_it)->getNet();
688  count_2[net->getID()]--;
689  count_1[net->getID()]++;
690 
691  // cout << "\tnet " << net->getID() << " was " << count_1[net->getID()]-1 << "/" << count_2[net->getID()]+1 << " now " << count_1[net->getID()] << "/" << count_2[net->getID()] << endl;
692 
693  if (count_2[net->getID()] == 0) { current_cuts--; FM_updateGains(net, 2, -1, target, bin, count_1, count_2); }
694  if (count_1[net->getID()] == 1) { current_cuts++; FM_updateGains(net, 1, -1, target, bin, count_1, count_2); }
695 
696  // check_list(bin, locked, targets); // DEBUG
697  }
698  }
699 
700  //cout << " cuts=" << current_cuts << endl;
701 
702  // move current to locked
703 
704 /*
705  cout << "b=" << bin[bin_num] << " ";
706  cout << current->prev << "-> ";
707  if (current->prev == 0)
708  cout << "X";
709  else cout << current->prev->next;
710  cout << "=" << current << "=";
711  if (current->next == 0)
712  cout << "X";
713  else
714  cout << current->next->prev;
715  cout << " ->" << current->next << endl;
716 */
717 
718  if (bin[bin_num] == current)
719  bin[bin_num] = current->next;
720  if (current->prev != 0)
721  current->prev->next = current->next;
722  if (current->next != 0)
723  current->next->prev = current->prev;
724 
725 /*
726  cout << "b=" << bin[bin_num] << " ";
727  cout << current->prev << "-> ";
728  if (current->prev == 0)
729  cout << "X";
730  else cout << current->prev->next;
731  cout << "=" << current << "=";
732  if (current->next == 0)
733  cout << "X";
734  else
735  cout << current->next->prev;
736  cout << " ->" << current->next << endl;
737 */
738 
739  current->prev = 0;
740  current->next = locked;
741  if (locked != 0)
742  locked->prev = current;
743  locked = current;
744 
745  // check_list(bin, locked, targets); // DEBUG
746 
747  // update max_gain
748  max_gain = FM_MAX_BIN;
749  while(bin[max_gain] == 0 && max_gain > 0) max_gain--;
750  }
751 
752  // cout << "\tcurrent cuts= " << current_cuts << " moves= " << num_moves << endl;
753  }
754 
755  // reassign members to subpartitions
756  cout << "FIDM-20 : \tbalance before " << parent->m_sub1->m_members.length() << "/"
757  << parent->m_sub2->m_members.length() << " ";
758  parent->m_sub1->m_members.clear();
759  parent->m_sub1->m_area = 0;
760  parent->m_sub2->m_members.clear();
761  parent->m_sub2->m_area = 0;
762  for(h::list<ConcreteCell *>::iterator it = parent->m_members.begin(); !it; it++) {
763  if (target[(*it)->getID()].loc == 1 || target[(*it)->getID()].loc == -1) {
764  parent->m_sub1->m_members.push_back(*it);
765  parent->m_sub1->m_area += (*it)->getArea();
766  }
767  else {
768  parent->m_sub2->m_members.push_back(*it);
769  parent->m_sub2->m_area += (*it)->getArea();
770  }
771  }
772  cout << " after " << parent->m_sub1->m_members.length() << "/"
773  << parent->m_sub2->m_members.length() << endl;
774 
775 
776  cout << "FIDM-21 : \tloc: " << initial_cut << " targetting: " << targets*100/parent->m_members.length() << "%" << endl;
777  cout << "FIDM-22 : \tstarting cuts= " << before_cuts << " final cuts= " << current_cuts << endl;
778 #endif
779 }
char * memset()
struct Partition * m_sub1
Definition: place_gordian.h:56
float h
Definition: place_base.h:36
float x
Definition: place_base.h:35
#define FM_MAX_PASSES
Definition: place_gordian.h:40
struct FM_cell * next
#define MAX_PARTITION_NONSYMMETRY
Definition: place_gordian.h:30
float y
Definition: place_base.h:35
struct Partition * m_sub2
Definition: place_gordian.h:56
#define FM_MAX_BIN
Definition: place_gordian.h:39
static double max
Definition: cuddSubsetHB.c:134
void FM_updateGains(ConcreteNet *net, int partition, int inc, FM_cell target[], FM_cell *bin[], int count_1[], int count_2[])
ConcreteCell ** m_members
Definition: place_gordian.h:49
float w
Definition: place_base.h:36
#define REPARTITION_TARGET_FRACTION
Definition: place_gordian.h:34
Rect m_bounds
Definition: place_gordian.h:50
#define assert(ex)
Definition: util_old.h:213
ConcreteCell * cell
struct FM_cell * prev
float m_area
Definition: place_gordian.h:54
void repartitionHMetis ( Partition parent)

Repartitions the two subpartitions using the hMetis min-cut library.

The number of cut nets between the two partitions will be minimized.

Definition at line 258 of file place_partition.c.

258  {
259 #if defined(NO_HMETIS)
260  printf("QPAR_02 : \t\tERROR: hMetis not available. Ignoring.\n");
261 #else
262 
263  int n,c,t, i;
264  float area;
265  int *edgeConnections = NULL;
266  int *partitionAssignment = (int *)calloc(g_place_numCells, sizeof(int));
267  int *vertexWeights = (int *)calloc(g_place_numCells, sizeof(int));
268  int *edgeDegree = (int *)malloc(sizeof(int)*(g_place_numNets+1));
269  int numConnections = 0;
270  int numEdges = 0;
271  float initial_cut;
272  int targets = 0;
273  ConcreteCell *cell = NULL;
274  int options[9];
275  int afterCuts = 0;
276 
277  assert(parent);
278  assert(parent->m_sub1);
279  assert(parent->m_sub2);
280 
281  printf("QPAR-02 : \t\trepartitioning with hMetis\n");
282 
283  // count edges
284  edgeDegree[0] = 0;
285  for(n=0; n<g_place_numNets; n++) if (g_place_concreteNets[n])
286  if (g_place_concreteNets[n]->m_numTerms > 1) {
287  numConnections += g_place_concreteNets[n]->m_numTerms;
288  edgeDegree[++numEdges] = numConnections;
289  }
290 
291  if (parent->m_vertical) {
292  // vertical
293  initial_cut = parent->m_sub2->m_bounds.x;
294 
295  // initialize all cells
296  for(c=0; c<g_place_numCells; c++) if (g_place_concreteCells[c]) {
297  if (g_place_concreteCells[c]->m_x < initial_cut)
298  partitionAssignment[c] = 0;
299  else
300  partitionAssignment[c] = 1;
301  }
302 
303  // initialize cells in partition 1
304  for(t=0; t<parent->m_sub1->m_numMembers; t++) if (parent->m_sub1->m_members[t]) {
305  cell = parent->m_sub1->m_members[t];
306  vertexWeights[cell->m_id] = getCellArea(cell);
307  // pay attention to cells that are close to the cut
308  if (abs(cell->m_x-initial_cut) < parent->m_bounds.w*REPARTITION_TARGET_FRACTION) {
309  targets++;
310  partitionAssignment[cell->m_id] = -1;
311  }
312  }
313 
314  // initialize cells in partition 2
315  for(t=0; t<parent->m_sub2->m_numMembers; t++) if (parent->m_sub2->m_members[t]) {
316  cell = parent->m_sub2->m_members[t];
317  vertexWeights[cell->m_id] = getCellArea(cell);
318  // pay attention to cells that are close to the cut
319  if (abs(cell->m_x-initial_cut) < parent->m_bounds.w*REPARTITION_TARGET_FRACTION) {
320  targets++;
321  partitionAssignment[cell->m_id] = -1;
322  }
323  }
324 
325  } else {
326  // horizontal
327  initial_cut = parent->m_sub2->m_bounds.y;
328 
329  // initialize all cells
330  for(c=0; c<g_place_numCells; c++) if (g_place_concreteCells[c]) {
331  if (g_place_concreteCells[c]->m_y < initial_cut)
332  partitionAssignment[c] = 0;
333  else
334  partitionAssignment[c] = 1;
335  }
336 
337  // initialize cells in partition 1
338  for(t=0; t<parent->m_sub1->m_numMembers; t++) if (parent->m_sub1->m_members[t]) {
339  cell = parent->m_sub1->m_members[t];
340  vertexWeights[cell->m_id] = getCellArea(cell);
341  // pay attention to cells that are close to the cut
342  if (abs(cell->m_y-initial_cut) < parent->m_bounds.h*REPARTITION_TARGET_FRACTION) {
343  targets++;
344  partitionAssignment[cell->m_id] = -1;
345  }
346  }
347 
348  // initialize cells in partition 2
349  for(t=0; t<parent->m_sub2->m_numMembers; t++) if (parent->m_sub2->m_members[t]) {
350  cell = parent->m_sub2->m_members[t];
351  vertexWeights[cell->m_id] = getCellArea(cell);
352  // pay attention to cells that are close to the cut
353  if (abs(cell->m_y-initial_cut) < parent->m_bounds.h*REPARTITION_TARGET_FRACTION) {
354  targets++;
355  partitionAssignment[cell->m_id] = -1;
356  }
357  }
358  }
359 
360  options[0] = 1; // any non-default values?
361  options[1] = 3; // num bisections
362  options[2] = 1; // grouping scheme
363  options[3] = 1; // refinement scheme
364  options[4] = 1; // cycle refinement scheme
365  options[5] = 0; // reconstruction scheme
366  options[6] = 0; // fixed assignments?
367  options[7] = 12261980; // random seed
368  options[8] = 0; // debugging level
369 
370  edgeConnections = (int *)malloc(sizeof(int)*numConnections);
371 
372  i = 0;
373  for(n=0; n<g_place_numNets; n++) if (g_place_concreteNets[n]) {
374  if (g_place_concreteNets[n]->m_numTerms > 1)
375  for(t=0; t<g_place_concreteNets[n]->m_numTerms; t++)
376  edgeConnections[i++] = g_place_concreteNets[n]->m_terms[t]->m_id;
377  }
378 
379  HMETIS_PartRecursive(g_place_numCells, numEdges, vertexWeights,
380  edgeDegree, edgeConnections, NULL,
381  2, (int)(100*MAX_PARTITION_NONSYMMETRY),
382  options, partitionAssignment, &afterCuts);
383 
384  /*
385  printf("HMET-20 : \t\t\tbalance before %d / %d ... ", parent->m_sub1->m_numMembers,
386  parent->m_sub2->m_numMembers);
387  */
388 
389  // reassign members to subpartitions
390  parent->m_sub1->m_numMembers = 0;
391  parent->m_sub1->m_area = 0;
392  parent->m_sub2->m_numMembers = 0;
393  parent->m_sub2->m_area = 0;
394  parent->m_sub1->m_members = (ConcreteCell**)realloc(parent->m_sub1->m_members,
395  sizeof(ConcreteCell*)*parent->m_numMembers);
396  parent->m_sub2->m_members = (ConcreteCell**)realloc(parent->m_sub2->m_members,
397  sizeof(ConcreteCell*)*parent->m_numMembers);
398 
399  for(t=0; t<parent->m_numMembers; t++) if (parent->m_members[t]) {
400  cell = parent->m_members[t];
401  area = getCellArea(cell);
402  if (partitionAssignment[cell->m_id] == 0) {
403  parent->m_sub1->m_members[parent->m_sub1->m_numMembers++] = cell;
404  parent->m_sub1->m_area += area;
405  }
406  else {
407  parent->m_sub2->m_members[parent->m_sub2->m_numMembers++] = cell;
408  parent->m_sub2->m_area += area;
409  }
410  }
411  /*
412  printf("after %d / %d\n", parent->m_sub1->m_numMembers,
413  parent->m_sub2->m_numMembers);
414  */
415 
416  // cout << "HMET-21 : \t\t\tloc: " << initial_cut << " targetting: " << targets*100/parent->m_members.length() << "%" << endl;
417  // cout << "HMET-22 : \t\t\tstarting cuts= " << beforeCuts << " final cuts= " << afterCuts << endl;
418 
419  free(edgeConnections);
420  free(vertexWeights);
421  free(edgeDegree);
422  free(partitionAssignment);
423 #endif
424 }
struct Partition * m_sub1
Definition: place_gordian.h:56
char * malloc()
static ABC_NAMESPACE_HEADER_START void HMETIS_PartRecursive(int nvtxs, int nhedges, int *vwgts, int *eptr, int *eind, int *hewgts, int nparts, int nbfactor, int *options, int *part, int *edgecnt)
Definition: libhmetis.h:10
VOID_HACK free()
ConcreteNet ** g_place_concreteNets
Definition: place_base.c:35
float h
Definition: place_base.h:36
float x
Definition: place_base.h:35
#define MAX_PARTITION_NONSYMMETRY
Definition: place_gordian.h:30
float y
Definition: place_base.h:35
ConcreteCell ** g_place_concreteCells
Definition: place_base.c:33
char * realloc()
struct Partition * m_sub2
Definition: place_gordian.h:56
float getCellArea(const ConcreteCell *cell)
Definition: place_base.c:99
bool m_vertical
Definition: place_gordian.h:51
ConcreteCell ** m_members
Definition: place_gordian.h:49
int m_numTerms
Definition: place_base.h:71
float w
Definition: place_base.h:36
int g_place_numNets
Definition: place_base.c:27
#define REPARTITION_TARGET_FRACTION
Definition: place_gordian.h:34
char * calloc()
Rect m_bounds
Definition: place_gordian.h:50
int m_numMembers
Definition: place_gordian.h:48
#define assert(ex)
Definition: util_old.h:213
ABC_NAMESPACE_IMPL_START int g_place_numCells
Definition: place_base.c:26
float m_area
Definition: place_gordian.h:54
void resizePartition ( Partition p)

Recomputes the bounding boxes of the child partitions based on their relative areas.

Definition at line 1022 of file place_partition.c.

1022  {
1023  // compute the new bounding box
1024  p->m_sub1->m_bounds.x = p->m_bounds.x;
1025  p->m_sub1->m_bounds.y = p->m_bounds.y;
1026  if (p->m_vertical) {
1027  p->m_sub1->m_bounds.w = p->m_bounds.w*(p->m_sub1->m_area/p->m_area);
1028  p->m_sub1->m_bounds.h = p->m_bounds.h;
1029  p->m_sub2->m_bounds.x = p->m_bounds.x + p->m_sub1->m_bounds.w;
1030  p->m_sub2->m_bounds.w = p->m_bounds.w*(p->m_sub2->m_area/p->m_area);
1031  p->m_sub2->m_bounds.y = p->m_bounds.y;
1032  p->m_sub2->m_bounds.h = p->m_bounds.h;
1033  } else {
1034  p->m_sub1->m_bounds.h = p->m_bounds.h*(p->m_sub1->m_area/p->m_area);
1035  p->m_sub1->m_bounds.w = p->m_bounds.w;
1036  p->m_sub2->m_bounds.y = p->m_bounds.y + p->m_sub1->m_bounds.h;
1037  p->m_sub2->m_bounds.h = p->m_bounds.h*(p->m_sub2->m_area/p->m_area);
1038  p->m_sub2->m_bounds.x = p->m_bounds.x;
1039  p->m_sub2->m_bounds.w = p->m_bounds.w;
1040  }
1041 }
struct Partition * m_sub1
Definition: place_gordian.h:56
float h
Definition: place_base.h:36
float x
Definition: place_base.h:35
float y
Definition: place_base.h:35
struct Partition * m_sub2
Definition: place_gordian.h:56
bool m_vertical
Definition: place_gordian.h:51
float w
Definition: place_base.h:36
Rect m_bounds
Definition: place_gordian.h:50
float m_area
Definition: place_gordian.h:54

Variable Documentation

ConcreteNet ** allNetsB2 = NULL

Definition at line 37 of file place_partition.c.

ConcreteNet ** allNetsL2 = NULL

Definition at line 36 of file place_partition.c.

ConcreteNet** allNetsR2 = NULL

Definition at line 35 of file place_partition.c.

ConcreteNet ** allNetsT2 = NULL

Definition at line 38 of file place_partition.c.

ABC_NAMESPACE_IMPL_START Partition* g_place_rootPartition = NULL

Definition at line 34 of file place_partition.c.