diff --git a/.github/workflows/arch_ci.yml b/.github/workflows/arch_ci.yml index 394181e2..c5be6100 100644 --- a/.github/workflows/arch_ci.yml +++ b/.github/workflows/arch_ci.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest env: DEPS_PATH: ${{ github.workspace }}/deps - YOSYS_REVISION: bd7ee79486d4e8788f36de8c25a3fb2df451d682 + YOSYS_REVISION: 7045cf509e1d95cbc973746674cf2d7c73c02e50 ICESTORM_REVISION: 9f66f9ce16941c6417813cb87653c735a78b53ae TRELLIS_REVISION: 36c615d1740473cc3574464c7f0bed44da20e5b6 PRJOXIDE_REVISION: c3fb1526cf4a2165e15b74f4a994d153c7695fe4 diff --git a/common/kernel/command.cc b/common/kernel/command.cc index 44482946..dc178cd2 100644 --- a/common/kernel/command.cc +++ b/common/kernel/command.cc @@ -197,7 +197,7 @@ void init_share_dirname() npnr_share_dirname = proc_share_path; return; } - proc_share_path = proc_self_path + "..\\share\\"; + proc_share_path = proc_self_path + "..\\share\\" + "nextpnr\\"; if (check_file_exists(proc_share_path, true)) { npnr_share_dirname = proc_share_path; return; @@ -389,6 +389,9 @@ po::options_description CommandHandler::getGeneralOptions() "allow placer to attempt up to max(10000, total cells^2 / N) iterations to place a cell (int " "N, default: 8, 0 for no timeout)"); + general.add_options()("static-dump-density", "write density csv files during placer-static flow"); + + #if !defined(NPNR_DISABLE_THREADS) general.add_options()("parallel-refine", "use new experimental parallelised engine for placement refinement"); #endif @@ -543,6 +546,10 @@ void CommandHandler::setupContext(Context *ctx) if (vm.count("router2-alt-weights")) ctx->settings[ctx->id("router2/alt-weights")] = true; + if (vm.count("static-dump-density")) + ctx->settings[ctx->id("static/dump_density")] = true; + + // Setting default values if (ctx->settings.find(ctx->id("target_freq")) == ctx->settings.end()) ctx->settings[ctx->id("target_freq")] = std::to_string(12e6); diff --git a/common/kernel/design_utils.cc b/common/kernel/design_utils.cc index f52cc304..cd7063cd 100644 --- a/common/kernel/design_utils.cc +++ b/common/kernel/design_utils.cc @@ -44,7 +44,7 @@ void print_utilisation(const Context *ctx) for (auto type : available_types) { IdString type_id = type.first; int used_bels = get_or_default(used_types, type.first, 0); - log_info("\t%20s: %5d/%5d %5d%%\n", type_id.c_str(ctx), used_bels, type.second, 100 * used_bels / type.second); + log_info("\t%20s: %7d/%7d %5d%%\n", type_id.c_str(ctx), used_bels, type.second, 100 * used_bels / type.second); } log_break(); } diff --git a/common/place/placer_static.cc b/common/place/placer_static.cc index 56e46032..d47429c2 100644 --- a/common/place/placer_static.cc +++ b/common/place/placer_static.cc @@ -254,6 +254,7 @@ class StaticPlacer int width, height; int iter = 0; bool fft_debug = false; + bool dump_density = false; // legalisation queue std::priority_queue> to_legalise; @@ -586,8 +587,8 @@ class StaticPlacer height = bin_h; } - double x0 = pos.x - (width / 2), x1 = pos.x + (width / 2); - double y0 = pos.y - (height / 2), y1 = pos.y + (height / 2); + double x0 = pos.x, x1 = pos.x + width; + double y0 = pos.y, y1 = pos.y + height; for (int y = int(y0 / bin_h); y <= int(y1 / bin_h); y++) { for (int x = int(x0 / bin_w); x <= int(x1 / bin_w); x++) { int xb = std::max(0, std::min(x, m - 1)); @@ -658,7 +659,8 @@ class StaticPlacer if (!overlap_str.empty()) overlap_str += ", "; overlap_str += stringf("%s=%.1f%%", cfg.cell_groups.at(idx).name.c_str(ctx), g.overlap * 100); - g.conc_density.write_csv(stringf("out_conc_density_%d_%d.csv", iter, idx)); + if (dump_density) + g.conc_density.write_csv(stringf("out_conc_density_%d_%d.csv", iter, idx)); } log_info("overlap: %s\n", overlap_str.c_str()); } @@ -792,15 +794,15 @@ class StaticPlacer auto &pd = nd.ports.at(port.second.type == PORT_OUT ? (nd.ports.size() - 1) : port.second.user_idx.idx()); // From Replace // TODO: check these derivatives on paper - float d_min = 0, d_max = 0; + double d_min = 0, d_max = 0; if (pd.has_min_exp(axis)) { - float min_sum = nd.min_exp.at(axis), x_min_sum = nd.x_min_exp.at(axis); + double min_sum = nd.min_exp.at(axis), x_min_sum = nd.x_min_exp.at(axis); d_min = (min_sum * (pd.min_exp.at(axis) * (1.0f - wl_coeff.at(axis) * loc.at(axis))) + wl_coeff.at(axis) * pd.min_exp.at(axis) * x_min_sum) / (min_sum * min_sum); } if (pd.has_max_exp(axis)) { - float max_sum = nd.max_exp.at(axis), x_max_sum = nd.x_max_exp.at(axis); + double max_sum = nd.max_exp.at(axis), x_max_sum = nd.x_max_exp.at(axis); d_max = (max_sum * (pd.max_exp.at(axis) * (1.0f + wl_coeff.at(axis) * loc.at(axis))) - wl_coeff.at(axis) * pd.max_exp.at(axis) * x_max_sum) / (max_sum * max_sum); @@ -917,16 +919,20 @@ class StaticPlacer { float coord_dist = 0; float grad_dist = 0; + int n = 0; for (auto &cell : mcells) { + if (cell.is_fixed || cell.is_dark) + continue; coord_dist += (cell.ref_pos.x - cell.last_ref_pos.x) * (cell.ref_pos.x - cell.last_ref_pos.x); coord_dist += (cell.ref_pos.y - cell.last_ref_pos.y) * (cell.ref_pos.y - cell.last_ref_pos.y); grad_dist += (cell.ref_total_grad.x - cell.last_total_grad.x) * (cell.ref_total_grad.x - cell.last_total_grad.x); grad_dist += (cell.ref_total_grad.y - cell.last_total_grad.y) * (cell.ref_total_grad.y - cell.last_total_grad.y); + n++; } - coord_dist = std::sqrt(coord_dist / (2 * float(mcells.size()))); - grad_dist = std::sqrt(grad_dist / (2 * float(mcells.size()))); + coord_dist = std::sqrt(coord_dist / (2 * float(n))); + grad_dist = std::sqrt(grad_dist / (2 * float(n))); log_info("coord_dist: %f grad_dist: %f\n", coord_dist, grad_dist); return coord_dist / grad_dist; // return 0.1; @@ -969,7 +975,7 @@ class StaticPlacer update_gradients(true, true, /* init_penalty */ true); // compute a "fake" previous position based on an arbitrary steplength and said gradients for nesterov for (auto &cell : mcells) { - if (cell.is_fixed) + if (cell.is_fixed || cell.is_dark) continue; // save current position in last_pos cell.last_pos = cell.pos; @@ -981,6 +987,8 @@ class StaticPlacer update_gradients(true); // Now we have the fake previous state in the current state for (auto &cell : mcells) { + if (cell.is_fixed || cell.is_dark) + continue; std::swap(cell.last_ref_pos, cell.ref_pos); std::swap(cell.ref_total_grad, cell.last_total_grad); std::swap(cell.ref_wl_grad, cell.last_wl_grad); @@ -1035,7 +1043,11 @@ class StaticPlacer { // TODO: update penalties; wirelength factor; etc steplen = get_steplen(); - log_info("iter=%d steplen=%f a=%f\n", iter, steplen, nesterov_a); + std::string penalty_str = ""; + for (auto p : dens_penalty) { + penalty_str += stringf("%s%.2f", penalty_str.empty() ? "" : ", ", p); + } + log_info("iter=%d steplen=%f a=%f penalty=[%s]\n", iter, steplen, nesterov_a, penalty_str.c_str()); float a_next = (1.0f + std::sqrt(4.0f * nesterov_a * nesterov_a + 1)) / 2.0f; // Update positions using Nesterov's for (auto &cell : mcells) { @@ -1381,6 +1393,7 @@ class StaticPlacer groups.resize(cfg.cell_groups.size()); tmg.setup_only = true; tmg.setup(); + dump_density = ctx->setting("static/dump_density", false); }; void place() { diff --git a/himbaechel/arch.cc b/himbaechel/arch.cc index 1270934e..044b1a6c 100644 --- a/himbaechel/arch.cc +++ b/himbaechel/arch.cc @@ -22,6 +22,7 @@ #include "chipdb.h" #include "log.h" #include "nextpnr.h" +#include #include "command.h" #include "placer1.h" @@ -62,8 +63,10 @@ void Arch::load_chipdb(const std::string &path) db_path = args.chipdb_override; } else { db_path = proc_share_dirname(); - db_path += "/himbaechel/"; + db_path += "himbaechel/"; db_path += path; + boost::filesystem::path p(db_path); + db_path = p.make_preferred().string(); } try { blob_file.open(db_path); diff --git a/nexus/pack.cc b/nexus/pack.cc index 9991d49d..75ceb309 100644 --- a/nexus/pack.cc +++ b/nexus/pack.cc @@ -916,19 +916,47 @@ struct NexusPacker { // Keep running until we reach a fixed point log_info("Placing globals...\n"); - bool did_something = true; - while (did_something) { - did_something = false; - for (auto &cell : ctx->cells) { - CellInfo *ci = cell.second.get(); - if (ci->type == id_OSC_CORE) - did_something |= preplace_singleton(ci); - else if (ci->type == id_DCC) - did_something |= preplace_prim(ci, id_CLKI, false); - else if (ci->type == id_PLL_CORE) - did_something |= preplace_prim(ci, id_REFCK, false); + TopoSort sorter; + auto is_glb_cell = [&](const CellInfo *cell) { + return cell->type.in(id_OSC_CORE, id_DCC, id_PLL_CORE, id_DCS); + }; + + for (auto &cell : ctx->cells) { + CellInfo *ci = cell.second.get(); + if (is_glb_cell(ci)) { + sorter.node(ci->name); + + auto do_pin = [&](IdString pin) { + NetInfo *net = ci->getPort(pin); + if (!net || !net->driver.cell || !is_glb_cell(net->driver.cell)) + return; + sorter.edge(net->driver.cell->name, ci->name); + }; + + if (ci->type == id_PLL_CORE) { + do_pin(id_REFCK); + } else if (ci->type == id_DCC) { + do_pin(id_CLKI); + } else if (ci->type == id_DCS) { + do_pin(id_CLK0); + do_pin(id_CLK1); + } } } + + sorter.sort(); + + for (IdString cell_name : sorter.sorted) { + CellInfo *ci = ctx->cells.at(cell_name).get(); + if (ci->type == id_OSC_CORE) + preplace_singleton(ci); + else if (ci->type == id_DCC) + preplace_prim(ci, id_CLKI, false); + else if (ci->type == id_PLL_CORE) + preplace_prim(ci, id_REFCK, false); + else if (ci->type == id_DCS) + preplace_prim(ci, id_CLK0, false); + } } // Get a bus port name