From e419b34027a38698b3b5263b7bff9e0152b3f9ef Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 9 Aug 2018 19:10:50 -0700 Subject: [PATCH 1/5] Try with vector --- common/placer1.cc | 64 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 47 insertions(+), 17 deletions(-) diff --git a/common/placer1.cc b/common/placer1.cc index 91320240..95fa24a1 100644 --- a/common/placer1.cc +++ b/common/placer1.cc @@ -70,6 +70,20 @@ class SAPlacer fast_bels.at(type_idx).at(loc.x).at(loc.y).push_back(bel); } diameter = std::max(max_x, max_y) + 1; + + curr_cost.reserve(ctx->nets.size()); + new_cost.reserve(ctx->nets.size()); + old_udata.reserve(ctx->nets.size()); + decltype(NetInfo::udata) n = 0; + for (auto &net : ctx->nets) { + old_udata.emplace_back(net.second->udata); + net.second->udata = n++; + } + } + + ~SAPlacer() { + for (auto &net : ctx->nets) + net.second->udata = old_udata[net.second->udata]; } bool place() @@ -149,7 +163,8 @@ class SAPlacer curr_tns = 0; for (auto &net : ctx->nets) { wirelen_t wl = get_net_metric(ctx, net.second.get(), MetricType::COST, curr_tns); - metrics[net.first] = wl; + curr_cost[net.second->udata] = wl; + new_cost[net.second->udata] = -1; curr_metric += wl; } @@ -250,7 +265,8 @@ class SAPlacer curr_tns = 0; for (auto &net : ctx->nets) { wirelen_t wl = get_net_metric(ctx, net.second.get(), MetricType::COST, curr_tns); - metrics[net.first] = wl; + curr_cost[net.second->udata] = wl; + new_cost[net.second->udata] = -1; curr_metric += wl; } @@ -339,10 +355,8 @@ class SAPlacer // Attempt a SA position swap, return true on success or false on failure bool try_swap_position(CellInfo *cell, BelId newBel) { - static std::unordered_set update; - static std::vector> new_lengths; - new_lengths.clear(); - update.clear(); + static std::vector updates; + updates.clear(); BelId oldBel = cell->bel; CellInfo *other_cell = ctx->getBoundBelCell(newBel); if (other_cell != nullptr && other_cell->belStrength > STRENGTH_WEAK) { @@ -358,14 +372,23 @@ class SAPlacer ctx->unbindBel(newBel); } - for (const auto &port : cell->ports) - if (port.second.net != nullptr) - update.insert(port.second.net); + for (const auto &port : cell->ports) { + if (port.second.net != nullptr) { + auto &cost = new_cost[port.second.net->udata]; + if (cost == 0) continue; + cost = 0; + updates.emplace_back(port.second.net); + } + } if (other_cell != nullptr) { for (const auto &port : other_cell->ports) - if (port.second.net != nullptr) - update.insert(port.second.net); + if (port.second.net != nullptr) { + auto &cost = new_cost[port.second.net->udata]; + if (cost == 0) continue; + cost = 0; + updates.emplace_back(port.second.net); + } } ctx->bindBel(newBel, cell, STRENGTH_WEAK); @@ -383,12 +406,12 @@ class SAPlacer new_metric = curr_metric; // Recalculate metrics for all nets touched by the peturbation - for (auto net : update) { - new_metric -= metrics.at(net->name); + for (const auto &net : updates) { + new_metric -= curr_cost[net->udata]; float temp_tns = 0; wirelen_t net_new_wl = get_net_metric(ctx, net, MetricType::COST, temp_tns); new_metric += net_new_wl; - new_lengths.push_back(std::make_pair(net->name, net_new_wl)); + new_cost[net->udata] = net_new_wl; } new_dist = get_constraints_distance(ctx, cell); @@ -407,8 +430,10 @@ class SAPlacer goto swap_fail; } curr_metric = new_metric; - for (auto new_wl : new_lengths) - metrics.at(new_wl.first) = new_wl.second; + for (const auto &net : updates) { + curr_cost[net->udata] = new_cost[net->udata]; + new_cost[net->udata] = -1; + } return true; swap_fail: @@ -416,6 +441,8 @@ class SAPlacer if (other_cell != nullptr) { ctx->bindBel(newBel, other_cell, STRENGTH_WEAK); } + for (const auto &net : updates) + new_cost[net->udata] = -1; return false; } @@ -444,7 +471,6 @@ class SAPlacer } Context *ctx; - std::unordered_map metrics; wirelen_t curr_metric = std::numeric_limits::max(); float curr_tns = 0; float temp = 1000; @@ -459,6 +485,10 @@ class SAPlacer const float post_legalise_temp = 10; const float post_legalise_dia_scale = 1.5; Placer1Cfg cfg; + + std::vector curr_cost; + std::vector new_cost; + std::vector old_udata; }; bool placer1(Context *ctx, Placer1Cfg cfg) From 1514903ea909a65737b1595a2c4f46544ab5c3b6 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 9 Aug 2018 20:45:20 -0700 Subject: [PATCH 2/5] Get rid of map lookup by borrowing udata to use as index into vector --- common/placer1.cc | 39 ++++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/common/placer1.cc b/common/placer1.cc index 95fa24a1..2dafb069 100644 --- a/common/placer1.cc +++ b/common/placer1.cc @@ -71,8 +71,7 @@ class SAPlacer } diameter = std::max(max_x, max_y) + 1; - curr_cost.reserve(ctx->nets.size()); - new_cost.reserve(ctx->nets.size()); + costs.reserve(ctx->nets.size()); old_udata.reserve(ctx->nets.size()); decltype(NetInfo::udata) n = 0; for (auto &net : ctx->nets) { @@ -163,8 +162,7 @@ class SAPlacer curr_tns = 0; for (auto &net : ctx->nets) { wirelen_t wl = get_net_metric(ctx, net.second.get(), MetricType::COST, curr_tns); - curr_cost[net.second->udata] = wl; - new_cost[net.second->udata] = -1; + costs[net.second->udata] = CostChange{wl, -1}; curr_metric += wl; } @@ -265,8 +263,7 @@ class SAPlacer curr_tns = 0; for (auto &net : ctx->nets) { wirelen_t wl = get_net_metric(ctx, net.second.get(), MetricType::COST, curr_tns); - curr_cost[net.second->udata] = wl; - new_cost[net.second->udata] = -1; + costs[net.second->udata] = CostChange{wl, -1}; curr_metric += wl; } @@ -374,9 +371,9 @@ class SAPlacer for (const auto &port : cell->ports) { if (port.second.net != nullptr) { - auto &cost = new_cost[port.second.net->udata]; - if (cost == 0) continue; - cost = 0; + auto &cost = costs[port.second.net->udata]; + if (cost.new_cost == 0) continue; + cost.new_cost = 0; updates.emplace_back(port.second.net); } } @@ -384,9 +381,9 @@ class SAPlacer if (other_cell != nullptr) { for (const auto &port : other_cell->ports) if (port.second.net != nullptr) { - auto &cost = new_cost[port.second.net->udata]; - if (cost == 0) continue; - cost = 0; + auto &cost = costs[port.second.net->udata]; + if (cost.new_cost == 0) continue; + cost.new_cost = 0; updates.emplace_back(port.second.net); } } @@ -407,11 +404,12 @@ class SAPlacer // Recalculate metrics for all nets touched by the peturbation for (const auto &net : updates) { - new_metric -= curr_cost[net->udata]; + auto &c = costs[net->udata]; + new_metric -= c.curr_cost; float temp_tns = 0; wirelen_t net_new_wl = get_net_metric(ctx, net, MetricType::COST, temp_tns); new_metric += net_new_wl; - new_cost[net->udata] = net_new_wl; + c.new_cost = net_new_wl; } new_dist = get_constraints_distance(ctx, cell); @@ -431,8 +429,8 @@ class SAPlacer } curr_metric = new_metric; for (const auto &net : updates) { - curr_cost[net->udata] = new_cost[net->udata]; - new_cost[net->udata] = -1; + auto &c = costs[net->udata]; + c = CostChange{c.new_cost, -1}; } return true; @@ -442,7 +440,7 @@ class SAPlacer ctx->bindBel(newBel, other_cell, STRENGTH_WEAK); } for (const auto &net : updates) - new_cost[net->udata] = -1; + costs[net->udata].new_cost = -1; return false; } @@ -486,8 +484,11 @@ class SAPlacer const float post_legalise_dia_scale = 1.5; Placer1Cfg cfg; - std::vector curr_cost; - std::vector new_cost; + struct CostChange { + wirelen_t curr_cost; + wirelen_t new_cost; + }; + std::vector costs; std::vector old_udata; }; From 396cae51188a08e6f2909ae42f0be1650918f6a1 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 9 Aug 2018 20:53:33 -0700 Subject: [PATCH 3/5] Make containers static --- ice40/arch_place.cc | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/ice40/arch_place.cc b/ice40/arch_place.cc index bbddb7ee..2e2b9556 100644 --- a/ice40/arch_place.cc +++ b/ice40/arch_place.cc @@ -71,12 +71,13 @@ bool Arch::logicCellsCompatible(const std::vector &cells) cons bool Arch::isBelLocationValid(BelId bel) const { if (getBelType(bel) == id_ICESTORM_LC) { - std::vector bel_cells; + static std::vector bel_cells; + bel_cells.clear(); Loc bel_loc = getBelLocation(bel); for (auto bel_other : getBelsByTile(bel_loc.x, bel_loc.y)) { CellInfo *ci_other = getBoundBelCell(bel_other); if (ci_other != nullptr) { - bel_cells.push_back(ci_other); + bel_cells.emplace_back(ci_other); } } return logicCellsCompatible(bel_cells); @@ -94,16 +95,17 @@ bool Arch::isValidBelForCell(CellInfo *cell, BelId bel) const if (cell->type == id_ICESTORM_LC) { NPNR_ASSERT(getBelType(bel) == id_ICESTORM_LC); - std::vector bel_cells; + static std::vector bel_cells; + bel_cells.clear(); Loc bel_loc = getBelLocation(bel); for (auto bel_other : getBelsByTile(bel_loc.x, bel_loc.y)) { CellInfo *ci_other = getBoundBelCell(bel_other); if (ci_other != nullptr && bel_other != bel) { - bel_cells.push_back(ci_other); + bel_cells.emplace_back(ci_other); } } - bel_cells.push_back(cell); + bel_cells.emplace_back(cell); return logicCellsCompatible(bel_cells); } else if (cell->type == id_SB_IO) { // Do not allow placement of input SB_IOs on blocks where there a PLL is outputting to. From ded83086833db10bf9186aa04f90443dbcadf1fb Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 9 Aug 2018 21:03:07 -0700 Subject: [PATCH 4/5] std::vector::resize() not reserve() --- common/placer1.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/placer1.cc b/common/placer1.cc index 2dafb069..88f2fc47 100644 --- a/common/placer1.cc +++ b/common/placer1.cc @@ -71,7 +71,7 @@ class SAPlacer } diameter = std::max(max_x, max_y) + 1; - costs.reserve(ctx->nets.size()); + costs.resize(ctx->nets.size()); old_udata.reserve(ctx->nets.size()); decltype(NetInfo::udata) n = 0; for (auto &net : ctx->nets) { From a41500a015afe7fec5f7d122a37ccd1031f9fb51 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 10 Aug 2018 19:50:27 -0700 Subject: [PATCH 5/5] Rework Arch::logicCellsCompatible() to take pointer + size, allowing use of std::array --- ice40/arch.h | 2 +- ice40/arch_place.cc | 31 ++++++++++++++++--------------- ice40/chains.cc | 2 +- 3 files changed, 18 insertions(+), 17 deletions(-) diff --git a/ice40/arch.h b/ice40/arch.h index 561d75c3..1d91a9ae 100644 --- a/ice40/arch.h +++ b/ice40/arch.h @@ -802,7 +802,7 @@ struct Arch : BaseCtx bool isBelLocationValid(BelId bel) const; // Helper function for above - bool logicCellsCompatible(const std::vector &cells) const; + bool logicCellsCompatible(const CellInfo** it, const size_t size) const; // ------------------------------------------------- // Assign architecure-specific arguments to nets and cells, which must be diff --git a/ice40/arch_place.cc b/ice40/arch_place.cc index 2e2b9556..c69fd34f 100644 --- a/ice40/arch_place.cc +++ b/ice40/arch_place.cc @@ -23,15 +23,17 @@ #include "nextpnr.h" #include "util.h" +#include + NEXTPNR_NAMESPACE_BEGIN -bool Arch::logicCellsCompatible(const std::vector &cells) const +bool Arch::logicCellsCompatible(const CellInfo** it, const size_t size) const { bool dffs_exist = false, dffs_neg = false; const NetInfo *cen = nullptr, *clk = nullptr, *sr = nullptr; int locals_count = 0; - for (auto cell : cells) { + for (auto cell : boost::make_iterator_range(it, it+size)) { NPNR_ASSERT(cell->belType == id_ICESTORM_LC); if (cell->lcInfo.dffEnable) { if (!dffs_exist) { @@ -71,16 +73,15 @@ bool Arch::logicCellsCompatible(const std::vector &cells) cons bool Arch::isBelLocationValid(BelId bel) const { if (getBelType(bel) == id_ICESTORM_LC) { - static std::vector bel_cells; - bel_cells.clear(); + std::array bel_cells; + size_t num_cells = 0; Loc bel_loc = getBelLocation(bel); for (auto bel_other : getBelsByTile(bel_loc.x, bel_loc.y)) { CellInfo *ci_other = getBoundBelCell(bel_other); - if (ci_other != nullptr) { - bel_cells.emplace_back(ci_other); - } + if (ci_other != nullptr) + bel_cells[num_cells++] = ci_other; } - return logicCellsCompatible(bel_cells); + return logicCellsCompatible(bel_cells.data(), num_cells); } else { CellInfo *ci = getBoundBelCell(bel); if (ci == nullptr) @@ -95,18 +96,18 @@ bool Arch::isValidBelForCell(CellInfo *cell, BelId bel) const if (cell->type == id_ICESTORM_LC) { NPNR_ASSERT(getBelType(bel) == id_ICESTORM_LC); - static std::vector bel_cells; - bel_cells.clear(); + std::array bel_cells; + size_t num_cells = 0; + Loc bel_loc = getBelLocation(bel); for (auto bel_other : getBelsByTile(bel_loc.x, bel_loc.y)) { CellInfo *ci_other = getBoundBelCell(bel_other); - if (ci_other != nullptr && bel_other != bel) { - bel_cells.emplace_back(ci_other); - } + if (ci_other != nullptr && bel_other != bel) + bel_cells[num_cells++] = ci_other; } - bel_cells.emplace_back(cell); - return logicCellsCompatible(bel_cells); + bel_cells[num_cells++] = cell; + return logicCellsCompatible(bel_cells.data(), num_cells); } else if (cell->type == id_SB_IO) { // Do not allow placement of input SB_IOs on blocks where there a PLL is outputting to. diff --git a/ice40/chains.cc b/ice40/chains.cc index 8638a96c..bb20b60b 100644 --- a/ice40/chains.cc +++ b/ice40/chains.cc @@ -97,7 +97,7 @@ class ChainConstrainer } tile.push_back(cell); chains.back().cells.push_back(cell); - bool split_chain = (!ctx->logicCellsCompatible(tile)) || (int(chains.back().cells.size()) > max_length); + bool split_chain = (!ctx->logicCellsCompatible(tile.data(), tile.size())) || (int(chains.back().cells.size()) > max_length); if (split_chain) { CellInfo *passout = make_carry_pass_out(cell->ports.at(ctx->id("COUT"))); tile.pop_back();