diff --git a/common/place_common.cc b/common/place_common.cc index 591985f1..12345a89 100644 --- a/common/place_common.cc +++ b/common/place_common.cc @@ -21,6 +21,7 @@ #include #include "log.h" #include "util.h" + NEXTPNR_NAMESPACE_BEGIN // Get the total estimated wirelength for a net @@ -118,12 +119,16 @@ bool place_single_cell(Context *ctx, CellInfo *cell, bool require_legality) 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 == 0) + wirelen = ctx->rng(100); if (wirelen <= best_wirelen) { best_wirelen = wirelen; best_bel = bel; } } else { wirelen_t wirelen = get_cell_wirelength_at_bel(ctx, cell, bel); + if (wirelen == 0) + wirelen = ctx->rng(100); if (wirelen <= best_ripup_wirelen) { ripup_target = ctx->cells.at(ctx->getBoundBelCell(bel)).get(); if (ripup_target->belStrength < STRENGTH_STRONG) { @@ -135,7 +140,11 @@ bool place_single_cell(Context *ctx, CellInfo *cell, bool require_legality) } } if (best_bel == BelId()) { - if (iters == 0 || ripup_bel == BelId()) { + if (iters == 0) { + log_error("failed to place cell '%s' of type '%s' (ripup iteration limit exceeded)\n", + cell->name.c_str(ctx), cell->type.c_str(ctx)); + } + if (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; diff --git a/common/place_sa.cc b/common/place_sa.cc index ed584d60..d8ab24ce 100644 --- a/common/place_sa.cc +++ b/common/place_sa.cc @@ -38,7 +38,8 @@ #include #include "log.h" #include "place_common.h" - +#include "place_legaliser.h" +#include "util.h" NEXTPNR_NAMESPACE_BEGIN class SAPlacer @@ -206,6 +207,17 @@ class SAPlacer } } + if (temp < legalise_temp && !require_legal) { + legalise_design(ctx); + require_legal = true; + autoplaced.clear(); + for (auto cell : sorted(ctx->cells)) { + if (cell.second->belStrength < STRENGTH_STRONG) + autoplaced.push_back(cell.second); + } + ctx->shuffle(autoplaced); + } + // Recalculate total wirelength entirely to avoid rounding errors // accumulating over time curr_wirelength = 0; @@ -254,7 +266,7 @@ class SAPlacer } BelType targetType = ctx->belTypeFromId(cell->type); for (auto bel : ctx->getBels()) { - if (ctx->getBelType(bel) == targetType && ctx->isValidBelForCell(cell, bel)) { + if (ctx->getBelType(bel) == targetType && (ctx->isValidBelForCell(cell, bel) || !require_legal)) { if (ctx->checkBelAvail(bel)) { uint64_t score = ctx->rng64(); if (score <= best_score) { @@ -298,10 +310,14 @@ class SAPlacer BelId oldBel = cell->bel; IdString other = ctx->getBoundBelCell(newBel); CellInfo *other_cell = nullptr; + if (other != IdString()) { + other_cell = ctx->cells[other].get(); + if (other_cell->belStrength > STRENGTH_WEAK) + return false; + } wirelen_t new_wirelength = 0, delta; ctx->unbindBel(oldBel); if (other != IdString()) { - other_cell = ctx->cells[other].get(); ctx->unbindBel(newBel); } @@ -320,12 +336,13 @@ class SAPlacer if (other != IdString()) { ctx->bindBel(oldBel, other_cell->name, STRENGTH_WEAK); } - - if (!ctx->isBelLocationValid(newBel) || ((other != IdString() && !ctx->isBelLocationValid(oldBel)))) { - ctx->unbindBel(newBel); - if (other != IdString()) - ctx->unbindBel(oldBel); - goto swap_fail; + if (require_legal) { + if (!ctx->isBelLocationValid(newBel) || ((other != IdString() && !ctx->isBelLocationValid(oldBel)))) { + ctx->unbindBel(newBel); + if (other != IdString()) + ctx->unbindBel(oldBel); + goto swap_fail; + } } new_wirelength = curr_wirelength; @@ -402,6 +419,8 @@ class SAPlacer std::unordered_map bel_types; std::vector>>> fast_bels; std::unordered_set locked_bels; + bool require_legal = false; + const float legalise_temp = 20; }; bool place_design_sa(Context *ctx, bool timing_driven) diff --git a/dummy/main.cc b/dummy/main.cc index 6f4774d1..d025d8d4 100644 --- a/dummy/main.cc +++ b/dummy/main.cc @@ -75,16 +75,18 @@ int main(int argc, char *argv[]) } if (vm.count("help") || argc == 1) { - std::cout << boost::filesystem::basename(argv[0]) << " -- Next Generation Place and Route (git " - "sha1 " GIT_COMMIT_HASH_STR ")\n"; + std::cout << boost::filesystem::basename(argv[0]) + << " -- Next Generation Place and Route (git " + "sha1 " GIT_COMMIT_HASH_STR ")\n"; std::cout << "\n"; std::cout << options << "\n"; return argc != 1; } if (vm.count("version")) { - std::cout << boost::filesystem::basename(argv[0]) << " -- Next Generation Place and Route (git " - "sha1 " GIT_COMMIT_HASH_STR ")\n"; + std::cout << boost::filesystem::basename(argv[0]) + << " -- Next Generation Place and Route (git " + "sha1 " GIT_COMMIT_HASH_STR ")\n"; return 1; } diff --git a/dummy/place_legaliser.cc b/dummy/place_legaliser.cc new file mode 100644 index 00000000..610a9681 --- /dev/null +++ b/dummy/place_legaliser.cc @@ -0,0 +1,28 @@ +/* + * nextpnr -- Next Generation Place and Route + * + * Copyright (C) 2018 David Shah + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include "place_legaliser.h" + +NEXTPNR_NAMESPACE_BEGIN + +bool legalise_design(Context *ctx) { + return true; +} + +NEXTPNR_NAMESPACE_END diff --git a/dummy/place_legaliser.h b/dummy/place_legaliser.h new file mode 100644 index 00000000..5f4df6aa --- /dev/null +++ b/dummy/place_legaliser.h @@ -0,0 +1,31 @@ +/* + * nextpnr -- Next Generation Place and Route + * + * Copyright (C) 2018 David Shah + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#ifndef PLACE_LEGALISER_H +#define PLACE_LEGALISER_H + +#include "nextpnr.h" + +NEXTPNR_NAMESPACE_BEGIN + +bool legalise_design(Context *ctx); + +NEXTPNR_NAMESPACE_END + +#endif diff --git a/ice40/main.cc b/ice40/main.cc index 8f500efb..732a62f4 100644 --- a/ice40/main.cc +++ b/ice40/main.cc @@ -372,7 +372,6 @@ int main(int argc, char *argv[]) if (!vm.count("pack-only")) { if (!place_design_sa(&ctx, timing_driven) && !ctx.force) log_error("Placing design failed.\n"); - legalise_design(&ctx); ctx.check(); if (!route_design(&ctx) && !ctx.force) log_error("Routing design failed.\n");