aboutsummaryrefslogtreecommitdiffstats
path: root/common/place_common.cc
diff options
context:
space:
mode:
authorDavid Shah <davey1576@gmail.com>2018-06-27 12:18:52 +0200
committerDavid Shah <davey1576@gmail.com>2018-06-27 12:18:52 +0200
commitb0b16a344a951c7144783f799232a1b9d85ddc8a (patch)
tree350df2d246c261be1fe36ad5573edad1fe2f4286 /common/place_common.cc
parent87a5b7212667daa55a72f62c35cc248bdce2c744 (diff)
downloadnextpnr-b0b16a344a951c7144783f799232a1b9d85ddc8a.tar.gz
nextpnr-b0b16a344a951c7144783f799232a1b9d85ddc8a.tar.bz2
nextpnr-b0b16a344a951c7144783f799232a1b9d85ddc8a.zip
Improving post-ripup placement in the legaliser
Signed-off-by: David Shah <davey1576@gmail.com>
Diffstat (limited to 'common/place_common.cc')
-rw-r--r--common/place_common.cc64
1 files changed, 63 insertions, 1 deletions
diff --git a/common/place_common.cc b/common/place_common.cc
index 86060cd8..591985f1 100644
--- a/common/place_common.cc
+++ b/common/place_common.cc
@@ -79,7 +79,8 @@ wirelen_t get_cell_wirelength(const Context *ctx, const CellInfo *cell)
{
std::set<IdString> nets;
for (auto p : cell->ports) {
- nets.insert(p.first);
+ if (p.second.net)
+ nets.insert(p.second.net->name);
}
wirelen_t wirelength = 0;
float tns = 0;
@@ -89,4 +90,65 @@ wirelen_t get_cell_wirelength(const Context *ctx, const CellInfo *cell)
return wirelength;
}
+static wirelen_t get_cell_wirelength_at_bel(const Context *ctx, CellInfo *cell, BelId bel)
+{
+ BelId oldBel = cell->bel;
+ cell->bel = bel;
+ wirelen_t wirelen = get_cell_wirelength(ctx, cell);
+ cell->bel = oldBel;
+ return wirelen;
+}
+
+// Placing a single cell
+bool place_single_cell(Context *ctx, CellInfo *cell, bool require_legality)
+{
+ bool all_placed = false;
+ int iters = 25;
+ while (!all_placed) {
+ BelId best_bel = BelId();
+ wirelen_t best_wirelen = std::numeric_limits<wirelen_t>::max(),
+ best_ripup_wirelen = std::numeric_limits<wirelen_t>::max();
+ CellInfo *ripup_target = nullptr;
+ BelId ripup_bel = BelId();
+ if (cell->bel != BelId()) {
+ ctx->unbindBel(cell->bel);
+ }
+ BelType targetType = ctx->belTypeFromId(cell->type);
+ for (auto bel : ctx->getBels()) {
+ if (ctx->getBelType(bel) == targetType && (!require_legality || ctx->isValidBelForCell(cell, bel))) {
+ if (ctx->checkBelAvail(bel)) {
+ wirelen_t wirelen = get_cell_wirelength_at_bel(ctx, cell, bel);
+ if (wirelen <= best_wirelen) {
+ best_wirelen = wirelen;
+ best_bel = bel;
+ }
+ } else {
+ wirelen_t wirelen = get_cell_wirelength_at_bel(ctx, cell, bel);
+ if (wirelen <= best_ripup_wirelen) {
+ ripup_target = ctx->cells.at(ctx->getBoundBelCell(bel)).get();
+ if (ripup_target->belStrength < STRENGTH_STRONG) {
+ best_ripup_wirelen = wirelen;
+ ripup_bel = bel;
+ }
+ }
+ }
+ }
+ }
+ if (best_bel == BelId()) {
+ if (iters == 0 || ripup_bel == BelId()) {
+ log_error("failed to place cell '%s' of type '%s'\n", cell->name.c_str(ctx), cell->type.c_str(ctx));
+ }
+ --iters;
+ ctx->unbindBel(ripup_target->bel);
+ best_bel = ripup_bel;
+ } else {
+ all_placed = true;
+ }
+ ctx->bindBel(best_bel, cell->name, STRENGTH_WEAK);
+
+ cell = ripup_target;
+ }
+ return true;
+}
+
NEXTPNR_NAMESPACE_END