HeAP: Make cut-based spreading recursive

Signed-off-by: David Shah <dave@ds0.me>
This commit is contained in:
David Shah 2019-01-23 14:25:34 +00:00
parent b483008cdf
commit 030b02588b

View File

@ -144,14 +144,14 @@ class HeAPPlacer
} }
// legalise_with_cuts(true); // legalise_with_cuts(true);
CutLegaliser(this, ctx->id("ICESTORM_LC")).run(); // CutLegaliser(this, ctx->id("ICESTORM_LC")).run();
NPNR_ASSERT(false); //NPNR_ASSERT(false);
bool valid = false; bool valid = false;
wirelen_t solved_hpwl = 0, legal_hpwl = 1, best_hpwl = std::numeric_limits<wirelen_t>::max(); wirelen_t solved_hpwl = 0, legal_hpwl = 0, best_hpwl = std::numeric_limits<wirelen_t>::max();
int iter = 0, stalled = 0; int iter = 0, stalled = 0;
while (!valid || (stalled < 5 && (solved_hpwl < legal_hpwl * 0.8))) { while (!valid || (stalled < 5 && (solved_hpwl < legal_hpwl * 0.8))) {
if ((solved_hpwl < legal_hpwl * 0.8) || (stalled > 5)) { if (!valid && ((solved_hpwl > legal_hpwl * 0.8) || (stalled > 5))) {
stalled = 0; stalled = 0;
best_hpwl = std::numeric_limits<wirelen_t>::max(); best_hpwl = std::numeric_limits<wirelen_t>::max();
valid = true; valid = true;
@ -171,11 +171,15 @@ class HeAPPlacer
log_info("Solved HPWL = %d\n", int(solved_hpwl)); log_info("Solved HPWL = %d\n", int(solved_hpwl));
update_all_chains(); update_all_chains();
CutLegaliser(this, ctx->id("ICESTORM_LC")).run();
update_all_chains();
legal_hpwl = total_hpwl();
log_info("Spread HPWL = %d\n", int(legal_hpwl));
legalise_placement_simple(valid); legalise_placement_simple(valid);
update_all_chains(); update_all_chains();
legal_hpwl = total_hpwl(); legal_hpwl = total_hpwl();
log_info("Legalised HPWL = %d\n", int(legal_hpwl)); log_info("Legalised HPWL = %d (%s)\n", int(legal_hpwl), valid ? "valid" : "invalid");
if (legal_hpwl < best_hpwl) { if (legal_hpwl < best_hpwl) {
best_hpwl = legal_hpwl; best_hpwl = legal_hpwl;
stalled = 0; stalled = 0;
@ -715,12 +719,26 @@ class HeAPPlacer
init(); init();
find_overused_regions(); find_overused_regions();
expand_regions(); expand_regions();
std::queue<std::pair<int, bool>> workqueue;
for (auto &r : regions) { for (auto &r : regions) {
if (merged_regions.count(r.id)) if (merged_regions.count(r.id))
continue; continue;
log_info("%s (%d, %d) |_> (%d, %d) %d/%d\n", beltype.c_str(ctx), r.x0, r.y0, r.x1, r.y1, r.cells, /*log_info("%s (%d, %d) |_> (%d, %d) %d/%d\n", beltype.c_str(ctx), r.x0, r.y0, r.x1, r.y1, r.cells,
r.bels); r.bels);*/
cut_region(r, false); workqueue.emplace(r.id, false);
//cut_region(r, false);
}
while (!workqueue.empty()) {
auto front = workqueue.front();
workqueue.pop();
auto &r = regions.at(front.first);
/*log_info("%s (%d, %d) |_> (%d, %d) %d/%d\n", beltype.c_str(ctx), r.x0, r.y0, r.x1, r.y1, r.cells,
r.bels);*/
auto res = cut_region(r, front.second);
if (res) {
workqueue.emplace(res->first, !front.second);
workqueue.emplace(res->second, !front.second);
}
} }
} }
@ -989,11 +1007,22 @@ class HeAPPlacer
{ {
cut_cells.clear(); cut_cells.clear();
auto &cal = dir ? cells_at_location_sy : cells_at_location_sx; auto &cal = dir ? cells_at_location_sy : cells_at_location_sx;
for (int x = r.x0; x <= r.x1; x++) { if (dir) {
for (int y = r.y0; y <= r.y1; y++) { for (int y = r.y0; y <= r.y1; y++) {
std::copy(cal.at(x).at(y).begin(), cal.at(x).at(y).end(), std::back_inserter(cut_cells)); for (int x = r.x0; x <= r.x1; x++) {
//log_info("%d\n", int(cal.at(x).at(y).size()));
std::copy(cal.at(x).at(y).begin(), cal.at(x).at(y).end(), std::back_inserter(cut_cells));
}
}
} else {
for (int x = r.x0; x <= r.x1; x++) {
for (int y = r.y0; y <= r.y1; y++) {
std::copy(cal.at(x).at(y).begin(), cal.at(x).at(y).end(), std::back_inserter(cut_cells));
}
} }
} }
if (cut_cells.empty())
return {};
// Find the cells midpoint, counting chains in terms of their total size - making the initial source cut // Find the cells midpoint, counting chains in terms of their total size - making the initial source cut
int pivot_cells = 0; int pivot_cells = 0;
int pivot = 0; int pivot = 0;
@ -1003,7 +1032,9 @@ class HeAPPlacer
break; break;
pivot++; pivot++;
} }
log_info("orig pivot %d lc %d rc %d\n", pivot, pivot_cells, r.cells - pivot_cells); if (pivot == int(cut_cells.size()))
pivot = int(cut_cells.size()) - 1;
//log_info("orig pivot %d lc %d rc %d\n", pivot, pivot_cells, r.cells - pivot_cells);
// Find the clearance required either side of the pivot // Find the clearance required either side of the pivot
int clearance_l = 0, clearance_r = 0; int clearance_l = 0, clearance_r = 0;
@ -1048,7 +1079,7 @@ class HeAPPlacer
break; break;
trimmed_r--; trimmed_r--;
} }
log_info("tl %d tr %d cl %d cr %d\n", trimmed_l, trimmed_r, clearance_l, clearance_r); //log_info("tl %d tr %d cl %d cr %d\n", trimmed_l, trimmed_r, clearance_l, clearance_r);
if ((trimmed_r - trimmed_l + 1) <= std::max(clearance_l, clearance_r)) if ((trimmed_r - trimmed_l + 1) <= std::max(clearance_l, clearance_r))
return {}; return {};
// Now find the initial target cut that minimises utilisation imbalance, whilst // Now find the initial target cut that minimises utilisation imbalance, whilst
@ -1079,7 +1110,7 @@ class HeAPPlacer
NPNR_ASSERT(best_tgt_cut != -1); NPNR_ASSERT(best_tgt_cut != -1);
left_bels = target_cut_bels.first; left_bels = target_cut_bels.first;
right_bels = target_cut_bels.second; right_bels = target_cut_bels.second;
log_info("pivot %d target cut %d lc %d lb %d rc %d rb %d\n", pivot, best_tgt_cut, left_cells, left_bels, right_cells, right_bels); //log_info("pivot %d target cut %d lc %d lb %d rc %d rb %d\n", pivot, best_tgt_cut, left_cells, left_bels, right_cells, right_bels);
// Peturb the source cut to eliminate overutilisation // Peturb the source cut to eliminate overutilisation
while (pivot > 0 && (left_cells > left_bels)) { while (pivot > 0 && (left_cells > left_bels)) {
@ -1096,10 +1127,18 @@ class HeAPPlacer
right_cells -= size; right_cells -= size;
pivot++; pivot++;
} }
log_info("peturbed pivot %d lc %d lb %d rc %d rb %d\n", pivot, left_cells, left_bels, right_cells, right_bels); //log_info("peturbed pivot %d lc %d lb %d rc %d rb %d\n", pivot, left_cells, left_bels, right_cells, right_bels);
// Split regions into bins, and then spread cells by linear interpolation within those bins // Split regions into bins, and then spread cells by linear interpolation within those bins
auto spread_binlerp = [&](int cells_start, int cells_end, double area_l, double area_r) { auto spread_binlerp = [&](int cells_start, int cells_end, double area_l, double area_r) {
int N = 1 + cells_end - cells_start; int N = cells_end - cells_start;
if (N <= 2) {
for (int i = cells_start; i < cells_end; i++) {
auto &pos = dir ? p->cell_locs.at(cut_cells.at(i)->name).rawy
: p->cell_locs.at(cut_cells.at(i)->name).rawx;
pos = area_l + i * ((area_r - area_l) / N);
}
return;
}
// Split region into up to 10 (K) bins // Split region into up to 10 (K) bins
int K = std::min<int>(N, 10); int K = std::min<int>(N, 10);
std::vector<std::pair<int, double>> bin_bounds; // [start, end] std::vector<std::pair<int, double>> bin_bounds; // [start, end]
@ -1120,7 +1159,6 @@ class HeAPPlacer
auto &pos = dir ? p->cell_locs.at(cut_cells.at(j)->name).rawy auto &pos = dir ? p->cell_locs.at(cut_cells.at(j)->name).rawy
: p->cell_locs.at(cut_cells.at(j)->name).rawx; : p->cell_locs.at(cut_cells.at(j)->name).rawx;
pos = bl.second + m * (pos - orig_left); pos = bl.second + m * (pos - orig_left);
log_info("spread pos %f\n", pos);
} }
} }
}; };
@ -1135,9 +1173,10 @@ class HeAPPlacer
for (auto cell : cut_cells) { for (auto cell : cut_cells) {
auto &cl = p->cell_locs.at(cell->name); auto &cl = p->cell_locs.at(cell->name);
cl.x = std::min(r.x1, std::max(r.x0, int(cl.rawx + 0.5))); cl.x = std::min(r.x1, std::max(r.x0, int(cl.rawx + 0.5)));
cl.y = std::min(r.y1, std::max(r.y1, int(cl.rawy + 0.5))); cl.y = std::min(r.y1, std::max(r.y0, int(cl.rawy + 0.5)));
cells_at_location_sx.at(cl.x).at(cl.y).push_back(cell); cells_at_location_sx.at(cl.x).at(cl.y).push_back(cell);
cells_at_location_sy.at(cl.x).at(cl.y).push_back(cell); cells_at_location_sy.at(cl.x).at(cl.y).push_back(cell);
//log_info("spread pos %d %d\n", cl.x, cl.y);
} }
for (int x = r.x0; x <= r.x1; x++) for (int x = r.x0; x <= r.x1; x++)
for (int y = r.y0; y <= r.y1; y++) { for (int y = r.y0; y <= r.y1; y++) {