ABC: A System for Sequential Synthesis and Verification
 
Loading...
Searching...
No Matches
place_gordian.h File Reference
#include "place_base.h"
#include "place_qpsolver.h"
Include dependency graph for place_gordian.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

struct  Partition
 

Macros

#define ABC__phys__place__place_gordian_h
 
#define CLIQUE_PENALTY   1.0
 
#define IGNORE_NETSIZE   20
 
#define LARGEST_FINAL_SIZE   20
 
#define PARTITION_AREA_ONLY   true
 
#define REALLOCATE_PARTITIONS   false
 
#define FINAL_REALLOCATE_PARTITIONS   false
 
#define IGNORE_COG   false
 
#define MAX_PARTITION_NONSYMMETRY   0.30
 
#define REPARTITION_LEVEL_DEPTH   4
 
#define REPARTITION_TARGET_FRACTION   0.15
 
#define REPARTITION_FM   false
 
#define REPARTITION_HMETIS   true
 
#define FM_MAX_BIN   10
 
#define FM_MAX_PASSES   10
 

Typedefs

typedef struct Partition Partition
 

Functions

void initPartitioning ()
 Initializes data structures necessary for partitioning.
 
void incrementalPartition ()
 Adds new cells to an existing partition. Partition sizes/locations are unchanged.
 
bool refinePartitions ()
 Splits large leaf partitions.
 
void reallocPartitions ()
 Reallocates the partitions based on placement information.
 
bool refinePartition (Partition *p)
 Splits any large leaves within a partition.
 
void resizePartition (Partition *p)
 Recomputes the bounding boxes of the child partitions based on their relative areas.
 
void reallocPartition (Partition *p)
 Reallocates a partition and all of its children.
 
void repartitionHMetis (Partition *parent)
 Repartitions the two subpartitions using the hMetis min-cut library.
 
void repartitionFM (Partition *parent)
 Fiduccia-Matheyses mincut partitioning algorithm.
 
void partitionScanlineMincut (Partition *parent)
 Scans the cells within a partition from left to right and chooses the min-cut.
 
void partitionEqualArea (Partition *parent)
 Splits a partition into two halves of equal area.
 
void sanitizePlacement ()
 Moves any cells that are outside of the core bounds to the nearest location within.
 
void constructQuadraticProblem ()
 Constructs the matrices necessary to do analytical placement.
 
void solveQuadraticProblem (bool useCOG)
 Calls quadratic solver.
 

Variables

int g_place_numPartitions
 
qps_problem_tg_place_qpProb
 
Partitiong_place_rootPartition
 

Macro Definition Documentation

◆ ABC__phys__place__place_gordian_h

#define ABC__phys__place__place_gordian_h

Definition at line 11 of file place_gordian.h.

◆ CLIQUE_PENALTY

#define CLIQUE_PENALTY   1.0

Definition at line 21 of file place_gordian.h.

◆ FINAL_REALLOCATE_PARTITIONS

#define FINAL_REALLOCATE_PARTITIONS   false

Definition at line 28 of file place_gordian.h.

◆ FM_MAX_BIN

#define FM_MAX_BIN   10

Definition at line 39 of file place_gordian.h.

◆ FM_MAX_PASSES

#define FM_MAX_PASSES   10

Definition at line 40 of file place_gordian.h.

◆ IGNORE_COG

#define IGNORE_COG   false

Definition at line 29 of file place_gordian.h.

◆ IGNORE_NETSIZE

#define IGNORE_NETSIZE   20

Definition at line 22 of file place_gordian.h.

◆ LARGEST_FINAL_SIZE

#define LARGEST_FINAL_SIZE   20

Definition at line 25 of file place_gordian.h.

◆ MAX_PARTITION_NONSYMMETRY

#define MAX_PARTITION_NONSYMMETRY   0.30

Definition at line 30 of file place_gordian.h.

◆ PARTITION_AREA_ONLY

#define PARTITION_AREA_ONLY   true

Definition at line 26 of file place_gordian.h.

◆ REALLOCATE_PARTITIONS

#define REALLOCATE_PARTITIONS   false

Definition at line 27 of file place_gordian.h.

◆ REPARTITION_FM

#define REPARTITION_FM   false

Definition at line 35 of file place_gordian.h.

◆ REPARTITION_HMETIS

#define REPARTITION_HMETIS   true

Definition at line 36 of file place_gordian.h.

◆ REPARTITION_LEVEL_DEPTH

#define REPARTITION_LEVEL_DEPTH   4

Definition at line 33 of file place_gordian.h.

◆ REPARTITION_TARGET_FRACTION

#define REPARTITION_TARGET_FRACTION   0.15

Definition at line 34 of file place_gordian.h.

Typedef Documentation

◆ Partition

typedef struct Partition Partition

Function Documentation

◆ constructQuadraticProblem()

void constructQuadraticProblem ( )

Constructs the matrices necessary to do analytical placement.

Definition at line 53 of file place_genqp.c.

53 {
54 int maxConnections = 1;
55 int ignoreNum = 0;
56 int n,t,c,c2,p;
57 ConcreteCell *cell;
58 ConcreteNet *net;
59 int *cell_numTerms = calloc(g_place_numCells, sizeof(int));
60 ConcreteNet ***cell_terms = calloc(g_place_numCells, sizeof(ConcreteNet**));
61 bool incremental = false;
62 int nextIndex = 1;
63 int *seen = calloc(g_place_numCells, sizeof(int));
64 float weight;
65 int last_index;
66
67 // create problem object
68 if (!g_place_qpProb) {
70 g_place_qpProb->area = NULL;
71 g_place_qpProb->x = NULL;
72 g_place_qpProb->y = NULL;
73 g_place_qpProb->fixed = NULL;
74 g_place_qpProb->connect = NULL;
75 g_place_qpProb->edge_weight = NULL;
76 }
77
78 // count the maximum possible number of non-sparse entries
79 for(n=0; n<g_place_numNets; n++) if (g_place_concreteNets[n]) {
81 if (net->m_numTerms > IGNORE_NETSIZE) {
82 ignoreNum++;
83 }
84 else {
85 maxConnections += net->m_numTerms*(net->m_numTerms-1);
86 for(t=0; t<net->m_numTerms; t++) {
87 c = net->m_terms[t]->m_id;
88 p = ++cell_numTerms[c];
89 cell_terms[c] = (ConcreteNet**)realloc(cell_terms[c], p*sizeof(ConcreteNet*));
90 cell_terms[c][p-1] = net;
91 }
92 }
93 }
94 if(ignoreNum) {
95 printf("QMAN-10 : \t\t%d large nets ignored\n", ignoreNum);
96 }
97
98 // initialize the data structures
100 maxConnections += g_place_numCells + 1;
101
103 sizeof(float)*g_place_numCells);// "area" matrix
104 g_place_qpProb->edge_weight = realloc(g_place_qpProb->edge_weight,
105 sizeof(float)*maxConnections); // "weight" matrix
106 g_place_qpProb->connect = realloc(g_place_qpProb->connect,
107 sizeof(int)*maxConnections); // "connectivity" matrix
108 g_place_qpProb->fixed = realloc(g_place_qpProb->fixed,
109 sizeof(int)*g_place_numCells); // "fixed" matrix
110
111 // initialize or keep preexisting locations
112 if (g_place_qpProb->x != NULL && g_place_qpProb->y != NULL) {
113 printf("QMAN-10 :\tperforming incremental placement\n");
114 incremental = true;
115 }
116 g_place_qpProb->x = (float*)realloc(g_place_qpProb->x, sizeof(float)*g_place_numCells);
117 g_place_qpProb->y = (float*)realloc(g_place_qpProb->y, sizeof(float)*g_place_numCells);
118
119 // form a row for each cell
120 // build data
121 for(c = 0; c < g_place_numCells; c++) if (g_place_concreteCells[c]) {
122 cell = g_place_concreteCells[c];
123
124 // fill in the characteristics for this cell
125 g_place_qpProb->area[c] = getCellArea(cell);
126 if (cell->m_fixed || cell->m_parent->m_pad) {
127 g_place_qpProb->x[c] = cell->m_x;
128 g_place_qpProb->y[c] = cell->m_y;
129 g_place_qpProb->fixed[c] = 1;
130 } else {
131 if (!incremental) {
134 }
135 g_place_qpProb->fixed[c] = 0;
136 }
137
138 // update connectivity matrices
139 last_index = nextIndex;
140 for(n=0; n<cell_numTerms[c]; n++) {
141 net = cell_terms[c][n];
142 weight = net->m_weight / splitPenalty(net->m_numTerms);
143 for(t=0; t<net->m_numTerms; t++) {
144 c2 = net->m_terms[t]->m_id;
145 if (c2 == c) continue;
146 if (seen[c2] < last_index) {
147 // not seen
148 g_place_qpProb->connect[nextIndex-1] = c2;
149 g_place_qpProb->edge_weight[nextIndex-1] = weight;
150 seen[c2] = nextIndex;
151 nextIndex++;
152 } else {
153 // seen
154 g_place_qpProb->edge_weight[seen[c2]-1] += weight;
155 }
156 }
157 }
158 g_place_qpProb->connect[nextIndex-1] = -1;
159 g_place_qpProb->edge_weight[nextIndex-1] = -1.0;
160 nextIndex++;
161 } else {
162 // fill in dummy values for connectivity matrices
163 g_place_qpProb->connect[nextIndex-1] = -1;
164 g_place_qpProb->edge_weight[nextIndex-1] = -1.0;
165 nextIndex++;
166 }
167
168 free(cell_numTerms);
169 free(cell_terms);
170 free(seen);
171}
Cube * p
Definition exorList.c:222
ConcreteCell ** g_place_concreteCells
Definition place_base.c:33
ConcreteNet ** g_place_concreteNets
Definition place_base.c:35
float getCellArea(const ConcreteCell *cell)
Definition place_base.c:99
int g_place_numNets
Definition place_base.c:27
ABC_NAMESPACE_IMPL_START int g_place_numCells
Definition place_base.c:26
Rect g_place_coreBounds
Definition place_base.c:30
ABC_NAMESPACE_IMPL_START qps_problem_t * g_place_qpProb
Definition place_genqp.c:28
float splitPenalty(int pins)
Returns a weight for all of the edges in the clique for a multipin net.
Definition place_genqp.c:37
#define IGNORE_NETSIZE
struct qps_problem qps_problem_t
AbstractCell * m_parent
Definition place_base.h:57
ConcreteCell ** m_terms
Definition place_base.h:72
float m_weight
Definition place_base.h:74
char * calloc()
VOID_HACK free()
char * malloc()
char * realloc()
Here is the call graph for this function:
Here is the caller graph for this function:

◆ incrementalPartition()

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;
1107 **newCells = (ConcreteCell **)malloc(sizeof(ConcreteCell*)*g_place_numCells);
1108
1110
1111 // update cell list of root partition
1112 memcpy(allCells, (size_t)g_place_concreteCells, sizeof(ConcreteCell*)*g_place_numCells);
1113 qsort(allCells, (size_t)g_place_numCells, sizeof(ConcreteCell*), cellSortByID);
1114 qsort(g_place_rootPartition->m_members, (size_t)g_place_rootPartition->m_numMembers,
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 &&
1125 (c2 >= g_place_rootPartition->m_numMembers ||
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}
int cellSortByID(const void *a, const void *b)
Definition place_base.c:338
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.
#define assert(ex)
Definition util_old.h:213
char * memcpy()
Here is the call graph for this function:
Here is the caller graph for this function:

◆ initPartitioning()

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
75 g_place_rootPartition->m_level = 0;
76 g_place_rootPartition->m_area = 0;
78 g_place_rootPartition->m_vertical = false;
79 g_place_rootPartition->m_done = false;
80 g_place_rootPartition->m_leaf = true;
81
82 // add all of the cells to this partition
84 g_place_rootPartition->m_numMembers = 0;
85 for (i=0; i<g_place_numCells; i++)
86 if (g_place_concreteCells[i]) {
87 if (!g_place_concreteCells[i]->m_fixed) {
89 g_place_rootPartition->m_members[g_place_rootPartition->m_numMembers++] =
91 g_place_rootPartition->m_area += area;
92 }
93 }
94}
ABC_NAMESPACE_IMPL_START int g_place_numPartitions
Here is the call graph for this function:
Here is the caller graph for this function:

◆ partitionEqualArea()

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, (size_t)parent->m_numMembers, sizeof(ConcreteCell*), cellSortByX);
842 else
843 // sort by Y position
844 qsort(parent->m_members, (size_t)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 cellSortByY(const void *a, const void *b)
Definition place_base.c:326
int cellSortByX(const void *a, const void *b)
Sorts cells by either position coordinate.
Definition place_base.c:314
Here is the call graph for this function:
Here is the caller graph for this function:

◆ partitionScanlineMincut()

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}
#define local
Definition adler32.c:17
#define MAX_PARTITION_NONSYMMETRY
ConcreteNet ** allNetsR2
ConcreteNet ** allNetsB2
void partitionEqualArea(Partition *parent)
Splits a partition into two halves of equal area.
ConcreteNet ** allNetsT2
ConcreteNet ** allNetsL2
Here is the call graph for this function:
Here is the caller graph for this function:

◆ reallocPartition()

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
1002
1003 // --- PARTITION IMPROVEMENT
1004 if (p->m_level < REPARTITION_LEVEL_DEPTH) {
1007
1009 }
1010
1011 reallocPartition(p->m_sub1);
1012 reallocPartition(p->m_sub2);
1013}
#define PARTITION_AREA_ONLY
#define REPARTITION_HMETIS
#define REPARTITION_LEVEL_DEPTH
void repartitionHMetis(Partition *parent)
Repartitions the two subpartitions using the hMetis min-cut library.
void reallocPartition(Partition *p)
Reallocates a partition and all of its children.
void resizePartition(Partition *p)
Recomputes the bounding boxes of the child partitions based on their relative areas.
void partitionScanlineMincut(Partition *parent)
Scans the cells within a partition from left to right and chooses the min-cut.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ reallocPartitions()

void reallocPartitions ( )

Reallocates the partitions based on placement information.

Definition at line 138 of file place_partition.c.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ refinePartition()

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
196
197 // --- PARTITION IMPROVEMENT
198
199 if (p->m_level < REPARTITION_LEVEL_DEPTH) {
200 if (REPARTITION_FM)
202 else if (REPARTITION_HMETIS)
204 }
205
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");
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}
#define REPARTITION_FM
#define LARGEST_FINAL_SIZE
void repartitionFM(Partition *parent)
Fiduccia-Matheyses mincut partitioning algorithm.
bool refinePartition(Partition *p)
Splits any large leaves within a partition.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ refinePartitions()

bool refinePartitions ( )

Splits large leaf partitions.

Definition at line 126 of file place_partition.c.

126 {
127
129}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ repartitionFM()

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}
#define FM_MAX_PASSES
#define FM_MAX_BIN
#define REPARTITION_TARGET_FRACTION
void FM_updateGains(ConcreteNet *net, int partition, int inc, FM_cell target[], FM_cell *bin[], int count_1[], int count_2[])
struct FM_cell * next
ConcreteCell * cell
struct FM_cell * prev
char * memset()
Here is the call graph for this function:
Here is the caller graph for this function:

◆ repartitionHMetis()

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}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ resizePartition()

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}
Here is the caller graph for this function:

◆ sanitizePlacement()

void sanitizePlacement ( )

Moves any cells that are outside of the core bounds to the nearest location within.

Definition at line 125 of file place_gordian.c.

125 {
126 int c;
127 float order_width = g_place_rowHeight;
128 float x, y, edge, w, h;
129
130 printf("QCLN-10 : \tsanitizing placement\n");
131
132 for(c=0; c<g_place_numCells; c++) if (g_place_concreteCells[c]) {
134 if (cell->m_fixed || cell->m_parent->m_pad) {
135 continue;
136 }
137 // the new locations of the cells will be distributed within
138 // a small margin inside the border so that ordering is preserved
139 order_width = g_place_rowHeight;
140
141 x = cell->m_x, y = cell->m_y,
142 w = cell->m_parent->m_width, h = cell->m_parent->m_height;
143
144 if ((edge=x-w*0.5) < g_place_coreBounds.x) {
145 x = g_place_coreBounds.x+w*0.5 +
146 order_width/(1.0+g_place_coreBounds.x-edge);
147 }
148 else if ((edge=x+w*0.5) > g_place_coreBounds.x+g_place_coreBounds.w) {
150 order_width/(1.0+edge-g_place_coreBounds.x-g_place_coreBounds.w);
151 }
152 if ((edge=y-h*0.5) < g_place_coreBounds.y) {
153 y = g_place_coreBounds.y+h*0.5 +
154 order_width/(1.0+g_place_coreBounds.y-edge);
155 }
156 else if ((edge=y+h*0.5) > g_place_coreBounds.y+g_place_coreBounds.h) {
158 order_width/(1.0+edge-g_place_coreBounds.x-g_place_coreBounds.w);
159 }
160 cell->m_x = x;
161 cell->m_y = y;
162 }
163}
unsigned edge
Definition giaNewBdd.h:40
float g_place_rowHeight
Definition place_base.c:28
float m_width
Definition place_base.h:45
float m_height
Definition place_base.h:45
Here is the caller graph for this function:

◆ solveQuadraticProblem()

void solveQuadraticProblem ( bool useCOG)

Calls quadratic solver.

Definition at line 275 of file place_genqp.c.

275 {
276 int c;
277
279
281 g_place_qpProb->cog_x = malloc(sizeof(float)*g_place_numPartitions);
282 g_place_qpProb->cog_y = malloc(sizeof(float)*g_place_numPartitions);
283
284 // memset(g_place_qpProb->x, 0, sizeof(float)*g_place_numCells);
285 // memset(g_place_qpProb->y, 0, sizeof(float)*g_place_numCells);
286
288
289 if (useCOG)
290 g_place_qpProb->cog_num = generateCoGConstraints(COG_rev);
291 else
292 g_place_qpProb->cog_num = 0;
293
294 g_place_qpProb->loop_num = 0;
295
297
299
300 // set the positions
301 for(c = 0; c < g_place_numCells; c++) if (g_place_concreteCells[c]) {
304 }
305
306 // clean up
307 free(g_place_qpProb->cog_list);
308 free(g_place_qpProb->cog_x);
309 free(g_place_qpProb->cog_y);
310
311 free(COG_rev);
312}
int generateCoGConstraints(reverseCOG COG_rev[])
Generates center of gravity constraints.
void qps_init(qps_problem_t *p)
void qps_solve(qps_problem_t *p)
void qps_clean(qps_problem_t *p)
Here is the call graph for this function:
Here is the caller graph for this function:

Variable Documentation

◆ g_place_numPartitions

int g_place_numPartitions
extern

Definition at line 28 of file place_gordian.c.

◆ g_place_qpProb

qps_problem_t* g_place_qpProb
extern

Definition at line 28 of file place_genqp.c.

◆ g_place_rootPartition

Partition* g_place_rootPartition
extern

Definition at line 34 of file place_partition.c.