ABC: A System for Sequential Synthesis and Verification
 
Loading...
Searching...
No Matches
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"
Include dependency graph for place_partition.c:

Go to the source code of this file.

Classes

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.
 
void presortNets ()
 Sorts nets by corner positions.
 
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 repartitionHMetis (Partition *parent)
 Repartitions the two subpartitions using the hMetis min-cut library.
 
void repartitionFM (Partition *parent)
 Fiduccia-Matheyses mincut partitioning algorithm.
 
void partitionEqualArea (Partition *parent)
 Splits a partition into two halves of equal area.
 
void partitionScanlineMincut (Partition *parent)
 Scans the cells within a partition from left to right and chooses the min-cut.
 
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 incrementalSubpartition (Partition *p, ConcreteCell *newCells[], const int numNewCells)
 Adds new cells to an existing partition. Partition sizes/locations are unchanged.
 
void incrementalPartition ()
 Adds new cells to an existing partition. Partition sizes/locations are unchanged.
 

Variables

ABC_NAMESPACE_IMPL_START Partitiong_place_rootPartition = NULL
 
ConcreteNet ** allNetsR2 = NULL
 
ConcreteNet ** allNetsL2 = NULL
 
ConcreteNet ** allNetsB2 = NULL
 
ConcreteNet ** allNetsT2 = NULL
 

Typedef Documentation

◆ FM_cell

typedef struct FM_cell FM_cell

Function Documentation

◆ FM_updateGains()

void FM_updateGains ( ConcreteNet * net,
int partition,
int inc,
FM_cell target[],
FM_cell * bin[],
int count_1[],
int count_2[] )
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}
ConcreteCell ** g_place_concreteCells
Definition place_base.c:33
int cellSortByID(const void *a, const void *b)
Definition place_base.c:338
ABC_NAMESPACE_IMPL_START int g_place_numCells
Definition place_base.c:26
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()
VOID_HACK free()
char * malloc()
Here is the call graph for this function:
Here is the caller graph for this function:

◆ incrementalSubpartition()

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
1062 p->m_members = (ConcreteCell**)realloc(p->m_members,
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}
Cube * p
Definition exorList.c:222
char * realloc()
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}
float getCellArea(const ConcreteCell *cell)
Definition place_base.c:99
Rect g_place_coreBounds
Definition place_base.c:30
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
int g_place_numNets
Definition place_base.c:27
#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:

◆ presortNets()

void presortNets ( )

Sorts nets by corner positions.

Allocates allNetsX2 structures.

Definition at line 105 of file place_partition.c.

105 {
114 qsort(allNetsL2, (size_t)g_place_numNets, sizeof(ConcreteNet*), netSortByL);
115 qsort(allNetsR2, (size_t)g_place_numNets, sizeof(ConcreteNet*), netSortByR);
116 qsort(allNetsB2, (size_t)g_place_numNets, sizeof(ConcreteNet*), netSortByB);
117 qsort(allNetsT2, (size_t)g_place_numNets, sizeof(ConcreteNet*), netSortByT);
118}
ConcreteNet ** g_place_concreteNets
Definition place_base.c:35
int netSortByB(const void *a, const void *b)
Definition place_base.c:263
int netSortByR(const void *a, const void *b)
Definition place_base.c:249
int netSortByT(const void *a, const void *b)
Definition place_base.c:277
int netSortByL(const void *a, const void *b)
Sorts nets by position of one of its corners.
Definition place_base.c:235
Here is the call 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}
char * calloc()
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:

Variable Documentation

◆ allNetsB2

ConcreteNet ** allNetsB2 = NULL

Definition at line 37 of file place_partition.c.

◆ allNetsL2

ConcreteNet ** allNetsL2 = NULL

Definition at line 36 of file place_partition.c.

◆ allNetsR2

ConcreteNet** allNetsR2 = NULL

Definition at line 35 of file place_partition.c.

◆ allNetsT2

ConcreteNet ** allNetsT2 = NULL

Definition at line 38 of file place_partition.c.

◆ g_place_rootPartition

ABC_NAMESPACE_IMPL_START Partition* g_place_rootPartition = NULL

Definition at line 34 of file place_partition.c.