22 #if !defined(NO_HMETIS)
56 int count_1 [],
int count_2 []);
73 if (g_place_rootPartition)
free(g_place_rootPartition);
75 g_place_rootPartition->
m_level = 0;
76 g_place_rootPartition->
m_area = 0;
79 g_place_rootPartition->
m_done =
false;
80 g_place_rootPartition->
m_leaf =
true;
91 g_place_rootPartition->
m_area += area;
151 bool degenerate =
false;
152 int nonzeroCount = 0;
158 if (p->
m_done)
return true;
218 if (nonzeroCount == 0)
231 if (nonzeroCount == 0)
236 printf(
"QPART-35 : WARNING: degenerate partition generated\n");
259 #if defined(NO_HMETIS)
260 printf(
"QPAR_02 : \t\tERROR: hMetis not available. Ignoring.\n");
265 int *edgeConnections = NULL;
269 int numConnections = 0;
281 printf(
"QPAR-02 : \t\trepartitioning with hMetis\n");
288 edgeDegree[++numEdges] = numConnections;
298 partitionAssignment[c] = 0;
300 partitionAssignment[c] = 1;
310 partitionAssignment[cell->
m_id] = -1;
321 partitionAssignment[cell->
m_id] = -1;
332 partitionAssignment[c] = 0;
334 partitionAssignment[c] = 1;
344 partitionAssignment[cell->
m_id] = -1;
355 partitionAssignment[cell->
m_id] = -1;
367 options[7] = 12261980;
370 edgeConnections = (
int *)
malloc(
sizeof(
int)*numConnections);
380 edgeDegree, edgeConnections, NULL,
382 options, partitionAssignment, &afterCuts);
402 if (partitionAssignment[cell->
m_id] == 0) {
419 free(edgeConnections);
422 free(partitionAssignment);
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());
445 FM_cell target[m_design->cells.length()];
452 int before_cuts = 0, current_cuts = 0;
456 double halfArea = parent->
m_area / 2.0;
463 if (parent->vertical) {
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;
474 target[cell_id].loc = -2;
475 target[cell_id].cell = *it;
476 target[cell_id].gain = 0;
480 for(h::list<ConcreteCell *>::iterator it = parent->
m_sub1->
m_members.begin(); !it; it++) {
481 cell_id = (*it)->getID();
485 target[cell_id].loc = 1;
490 for(h::list<ConcreteCell *>::iterator it = parent->
m_sub2->
m_members.begin(); !it; it++) {
491 cell_id = (*it)->getID();
495 target[cell_id].loc = 2;
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()]++;
509 count_2[net->getID()]++;
510 if (count_1[net->getID()] > 0 && count_2[net->getID()] > 0) before_cuts++;
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;
524 target[cell_id].loc = -2;
525 target[cell_id].cell = *it;
526 target[cell_id].gain = 0;
530 for(h::list<ConcreteCell *>::iterator it = parent->
m_sub1->
m_members.begin(); !it; it++) {
531 cell_id = (*it)->getID();
535 target[cell_id].loc = 1;
540 for(h::list<ConcreteCell *>::iterator it = parent->
m_sub2->
m_members.begin(); !it; it++) {
541 cell_id = (*it)->getID();
545 target[cell_id].loc = 2;
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()]++;
559 count_2[net->getID()]++;
560 if (count_1[net->getID()] > 0 && count_2[net->getID()] > 0) before_cuts++;
565 for(
long id=0;
id < m_design->cells.length();
id++)
566 if (target[
id].
loc > 0) {
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++;
580 assert(target[
id].
cell->getPins().length() >= abs(target[
id].
gain));
584 max_gain =
max(max_gain, bin_num);
587 target[id].next = bin[bin_num];
589 if (bin[bin_num] != 0)
590 bin[bin_num]->prev = &target[id];
591 bin[bin_num] = &target[id];
595 current_cuts = before_cuts;
611 max_gain =
max(max_gain, bin_num);
613 locked = current->
next;
617 if (bin[bin_num] != 0)
618 bin[bin_num]->
prev = current;
619 current->
next = bin[bin_num];
620 bin[bin_num] = current;
628 while(bin[max_gain] == 0 && max_gain > 0) max_gain--;
634 FM_cell *current = bin[bin_num];
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))) {
641 if (current == 0) current = bin[--bin_num];
else current = current->
next;
651 if (current->
loc == 1) {
657 for(ConcretePinMap::iterator p_it = current->
cell->getPins().begin();
660 if (!(*p_it)->isAttached())
662 net = (*p_it)->getNet();
664 count_1[net->getID()]--;
665 count_2[net->getID()]++;
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); }
682 for(ConcretePinMap::iterator p_it = current->
cell->getPins().begin();
685 if (!(*p_it)->isAttached())
687 net = (*p_it)->getNet();
688 count_2[net->getID()]--;
689 count_1[net->getID()]++;
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); }
718 if (bin[bin_num] == current)
719 bin[bin_num] = current->
next;
720 if (current->
prev != 0)
722 if (current->
next != 0)
742 locked->
prev = current;
749 while(bin[max_gain] == 0 && max_gain > 0) max_gain--;
756 cout <<
"FIDM-20 : \tbalance before " << parent->
m_sub1->
m_members.length() <<
"/"
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) {
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;
786 int count_1 [],
int count_2 []) {
788 for(ConcretePinList::iterator it = net->getPins().begin(); !it; it++) {
789 FM_cell *current = &(target[(*it)->getCell()->getID()]);
792 int old_gain = current->
gain;
796 for(ConcretePinMap::iterator p_it = current->
cell->getPins().begin(); !p_it; p_it++)
797 if ((*p_it)->isAttached()) {
798 int n_id = (*p_it)->getNet()->getID();
799 if (current->
loc == 1 && count_1[n_id] == 1) current->
gain++;
800 if (current->
loc == 1 && count_2[n_id] == 0) current->
gain--;
801 if (current->
loc == 2 && count_1[n_id] == 0) current->
gain--;
802 if (current->
loc == 2 && count_2[n_id] == 1) current->
gain++;
808 if (bin[bin_num] == current)
809 bin[bin_num] = current->
next;
810 if (current->
prev != 0)
812 if (current->
next != 0)
817 current->
next = bin[bin_num];
818 if (bin[bin_num] != 0)
819 bin[bin_num]->
prev = current;
820 bin[bin_num] = current;
835 float halfArea, area;
847 halfArea = parent->
m_area*0.5;
881 int current_cuts = 0;
882 int minimum_cuts = INT_MAX;
884 double currentArea = 0, halfArea = parent->
m_area * 0.5;
886 double newLine, oldLine = -DBL_MAX;
888 for(ConcreteNetList::iterator n_it = m_design->nets.begin(); !n_it; n_it++)
890 for(h::list<ConcreteCell *>::iterator i = parent->
m_members.begin();
893 for(ConcretePinMap::iterator j = (*i)->getPins().begin();
896 if((*j)->isAttached()) {
897 (*j)->getNet()->m_mark = 1;
902 if (parent->vertical) {
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)
910 if (currentArea > halfArea+areaFlexibility)
912 newLine = (*local)->temp_x;
919 while(all2 <
g_place_numNets && allNetsR2[all2]->getBoundingBox().right() <= newLine) {
920 if(allNetsR2[all2]->m_mark) {
925 if (current_cuts < minimum_cuts) {
926 minimum_cuts = current_cuts;
927 minimum_location = *
local;
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)
940 if (currentArea > halfArea+areaFlexibility)
942 newLine = (*local)->temp_y;
955 if (current_cuts < minimum_cuts) {
956 minimum_cuts = current_cuts;
957 minimum_location = *
local;
962 if (minimum_location == NULL) {
965 h::list<ConcreteCell *>::iterator it = parent->
m_members.begin();
968 for(; *it != minimum_location; it++) {
1056 int numNewCells1 = 0, numNewCells2 = 0;
1073 for(c=0; c<numNewCells; c++)
1074 if (newCells[c]->m_x < cut_loc)
1075 newCells1[numNewCells1++] = newCells[c];
1077 newCells2[numNewCells2++] = newCells[c];
1080 for(c=0; c<numNewCells; c++)
1081 if (newCells[c]->m_y < cut_loc)
1082 newCells1[numNewCells1++] = newCells[c];
1084 newCells2[numNewCells2++] = newCells[c];
1105 int numNewCells = 0;
1109 assert(g_place_rootPartition);
1118 while(!allCells[c++]);
1119 while(!g_place_rootPartition->
m_members[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 &&
1128 newCells[numNewCells++] = allCells[c];
1133 printf(
"QPRT-50 : \tincremental partitioning with %d new cells\n", numNewCells);
void partitionEqualArea(Partition *parent)
Splits a partition into two halves of equal area.
int cellSortByX(const void *a, const void *b)
Sorts cells by either position coordinate.
struct Partition * m_sub1
bool refinePartition(Partition *p)
Splits any large leaves within a partition.
ABC_NAMESPACE_IMPL_START int g_place_numPartitions
int cellSortByY(const void *a, const void *b)
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)
ConcreteNet ** g_place_concreteNets
int netSortByR(const void *a, const void *b)
void partitionScanlineMincut(Partition *parent)
Scans the cells within a partition from left to right and chooses the min-cut.
#define MAX_PARTITION_NONSYMMETRY
void resizePartition(Partition *p)
Recomputes the bounding boxes of the child partitions based on their relative areas.
int netSortByB(const void *a, const void *b)
ConcreteCell ** g_place_concreteCells
void reallocPartitions()
Reallocates the partitions based on placement information.
struct Partition * m_sub2
ABC_NAMESPACE_IMPL_START Partition * g_place_rootPartition
float getCellArea(const ConcreteCell *cell)
void reallocPartition(Partition *p)
Reallocates a partition and all of its children.
#define REPARTITION_HMETIS
void incrementalSubpartition(Partition *p, ConcreteCell *newCells[], const int numNewCells)
Adds new cells to an existing partition. Partition sizes/locations are unchanged. ...
void presortNets()
Sorts nets by corner positions.
int netSortByT(const void *a, const void *b)
static int partition(int *a, int n, int m)
#define ABC_NAMESPACE_IMPL_END
int cellSortByID(const void *a, const void *b)
void FM_updateGains(ConcreteNet *net, int partition, int inc, FM_cell target[], FM_cell *bin[], int count_1[], int count_2[])
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
#define ABC_NAMESPACE_IMPL_START
#define REPARTITION_TARGET_FRACTION
#define LARGEST_FINAL_SIZE
void incrementalPartition()
Adds new cells to an existing partition. Partition sizes/locations are unchanged. ...
#define REPARTITION_LEVEL_DEPTH
ABC_NAMESPACE_IMPL_START int g_place_numCells
void initPartitioning()
Initializes data structures necessary for partitioning.
bool refinePartitions()
Splits large leaf partitions.
#define PARTITION_AREA_ONLY
int netSortByL(const void *a, const void *b)
Sorts nets by position of one of its corners.