diff options
-rw-r--r-- | common/command.cc | 19 | ||||
-rw-r--r-- | common/settings.h | 27 | ||||
-rw-r--r-- | docs/archapi.md | 11 | ||||
-rw-r--r-- | ecp5/arch.cc | 30 | ||||
-rw-r--r-- | ecp5/arch.h | 3 | ||||
-rw-r--r-- | ecp5/main.cc | 6 | ||||
-rw-r--r-- | generic/arch.cc | 15 | ||||
-rw-r--r-- | generic/arch.h | 3 | ||||
-rw-r--r-- | ice40/arch.cc | 15 | ||||
-rw-r--r-- | ice40/arch.h | 3 | ||||
-rw-r--r-- | ice40/main.cc | 4 |
11 files changed, 106 insertions, 30 deletions
diff --git a/common/command.cc b/common/command.cc index b7fc13e6..6f4137fe 100644 --- a/common/command.cc +++ b/common/command.cc @@ -27,6 +27,7 @@ #include "pybindings.h" #endif +#include <boost/algorithm/string/join.hpp> #include <boost/filesystem/convenience.hpp> #include <boost/program_options.hpp> #include <fstream> @@ -120,6 +121,13 @@ po::options_description CommandHandler::getGeneralOptions() general.add_options()("json", po::value<std::string>(), "JSON design file to ingest"); general.add_options()("seed", po::value<int>(), "seed value for random number generator"); general.add_options()("randomize-seed,r", "randomize seed value for random number generator"); + + general.add_options()( + "placer", po::value<std::string>(), + std::string("placer algorithm to use; available: " + boost::algorithm::join(Arch::availablePlacers, ", ") + + "; default: " + Arch::defaultPlacer) + .c_str()); + general.add_options()("slack_redist_iter", po::value<int>(), "number of iterations between slack redistribution"); general.add_options()("cstrweight", po::value<float>(), "placer weighting for relative constraint satisfaction"); general.add_options()("starttemp", po::value<float>(), "placer SA start temperature"); @@ -186,6 +194,17 @@ void CommandHandler::setupContext(Context *ctx) settings->set("timing/allowFail", true); } + if (vm.count("placer")) { + std::string placer = vm["placer"].as<std::string>(); + if (std::find(Arch::availablePlacers.begin(), Arch::availablePlacers.end(), placer) == + Arch::availablePlacers.end()) + log_error("Placer algorithm '%s' is not supported (available options: %s)\n", placer.c_str(), + boost::algorithm::join(Arch::availablePlacers, ", ").c_str()); + settings->set("placer", placer); + } else { + settings->set("placer", Arch::defaultPlacer); + } + if (vm.count("cstrweight")) { settings->set("placer1/constraintWeight", vm["cstrweight"].as<float>()); } diff --git a/common/settings.h b/common/settings.h index 0c4a67db..b57947c9 100644 --- a/common/settings.h +++ b/common/settings.h @@ -45,19 +45,30 @@ class Settings return defaultValue; } - template <typename T> void set(const char *name, T value) - { - IdString id = ctx->id(name); - auto pair = ctx->settings.emplace(id, std::to_string(value)); - if (!pair.second) { - ctx->settings[pair.first->first] = value; - } - } + template <typename T> void set(const char *name, T value); private: Context *ctx; }; +template <typename T> inline void Settings::set(const char *name, T value) +{ + IdString id = ctx->id(name); + auto pair = ctx->settings.emplace(id, std::to_string(value)); + if (!pair.second) { + ctx->settings[pair.first->first] = value; + } +} + +template <> inline void Settings::set<std::string>(const char *name, std::string value) +{ + IdString id = ctx->id(name); + auto pair = ctx->settings.emplace(id, value); + if (!pair.second) { + ctx->settings[pair.first->first] = value; + } +} + NEXTPNR_NAMESPACE_END #endif // SETTINGS_H diff --git a/docs/archapi.md b/docs/archapi.md index 3c938865..6e59ecdb 100644 --- a/docs/archapi.md +++ b/docs/archapi.md @@ -490,3 +490,14 @@ a certain number of different clock signals allowed for a group of bels. Returns true if a bell in the current configuration is valid, i.e. if `isValidBelForCell()` would return true for the current mapping. + + +### static const std::string defaultPlacer + +Name of the default placement algorithm for the architecture, if +`--placer` isn't specified on the command line. + +### static const std::vector\<std::string\> availablePlacers + +Name of available placer algorithms for the architecture, used +to provide help for and validate `--placer`.
\ No newline at end of file diff --git a/ecp5/arch.cc b/ecp5/arch.cc index d4b53f47..9da8abdf 100644 --- a/ecp5/arch.cc +++ b/ecp5/arch.cc @@ -508,21 +508,21 @@ bool Arch::getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay bool Arch::place() { - // HeAP is the default unless overriden or not built -#ifdef WITH_HEAP - if (bool_or_default(settings, id("sa_placer"), false)) { -#endif - if (!placer1(getCtx(), Placer1Cfg(getCtx()))) - return false; -#ifdef WITH_HEAP - } else { + std::string placer = str_or_default(settings, id("placer"), defaultPlacer); + + if (placer == "heap") { PlacerHeapCfg cfg(getCtx()); cfg.criticalityExponent = 7; cfg.ioBufTypes.insert(id_TRELLIS_IO); if (!placer_heap(getCtx(), cfg)) return false; + } else if (placer == "sa") { + if (!placer1(getCtx(), Placer1Cfg(getCtx()))) + return false; + } else { + log_error("ECP5 architecture does not support placer '%s'\n", placer.c_str()); } -#endif + permute_luts(); return true; } @@ -986,4 +986,16 @@ WireId Arch::getBankECLK(int bank, int eclk) return getWireByLocAndBasename(Location(0, 0), "G_BANK" + std::to_string(bank) + "ECLK" + std::to_string(eclk)); } +#ifdef WITH_HEAP +const std::string Arch::defaultPlacer = "heap"; +#else +const std::string Arch::defaultPlacer = "sa"; +#endif + +const std::vector<std::string> Arch::availablePlacers = {"sa", +#ifdef WITH_HEAP + "heap" +#endif +}; + NEXTPNR_NAMESPACE_END diff --git a/ecp5/arch.h b/ecp5/arch.h index 2e86988a..3de06a42 100644 --- a/ecp5/arch.h +++ b/ecp5/arch.h @@ -1045,6 +1045,9 @@ struct Arch : BaseCtx IdString id_srmode, id_mode; mutable std::unordered_map<DelayKey, std::pair<bool, DelayInfo>> celldelay_cache; + + static const std::string defaultPlacer; + static const std::vector<std::string> availablePlacers; }; NEXTPNR_NAMESPACE_END diff --git a/ecp5/main.cc b/ecp5/main.cc index de279e63..bb18aa58 100644 --- a/ecp5/main.cc +++ b/ecp5/main.cc @@ -59,8 +59,6 @@ po::options_description ECP5CommandHandler::getArchOptions() specific.add_options()("um5g-45k", "set device type to LFE5UM5G-45F"); specific.add_options()("um5g-85k", "set device type to LFE5UM5G-85F"); - specific.add_options()("sa-placer", "use pure simulated annealing placer instead of HeAP analytic placer"); - specific.add_options()("package", po::value<std::string>(), "select device package (defaults to CABGA381)"); specific.add_options()("speed", po::value<int>(), "select device speedgrade (6, 7 or 8)"); @@ -152,10 +150,6 @@ std::unique_ptr<Context> ECP5CommandHandler::createContext() } } auto ctx = std::unique_ptr<Context>(new Context(chipArgs)); - - if (vm.count("sa-placer")) - ctx->settings[ctx->id("sa_placer")] = "1"; - return ctx; } diff --git a/generic/arch.cc b/generic/arch.cc index 77417d27..aca81559 100644 --- a/generic/arch.cc +++ b/generic/arch.cc @@ -21,6 +21,7 @@ #include "nextpnr.h" #include "placer1.h" #include "router1.h" +#include "util.h" NEXTPNR_NAMESPACE_BEGIN @@ -439,7 +440,16 @@ bool Arch::getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay // --------------------------------------------------------------- -bool Arch::place() { return placer1(getCtx(), Placer1Cfg(getCtx())); } +bool Arch::place() +{ + std::string placer = str_or_default(settings, id("placer"), defaultPlacer); + // FIXME: No HeAP because it needs a list of IO buffers + if (placer == "sa") { + return placer1(getCtx(), Placer1Cfg(getCtx())); + } else { + log_error("Generic architecture does not support placer '%s'\n", placer.c_str()); + } +} bool Arch::route() { return router1(getCtx(), Router1Cfg(getCtx())); } @@ -476,4 +486,7 @@ TimingClockingInfo Arch::getPortClockingInfo(const CellInfo *cell, IdString port bool Arch::isValidBelForCell(CellInfo *cell, BelId bel) const { return true; } bool Arch::isBelLocationValid(BelId bel) const { return true; } +const std::string Arch::defaultPlacer = "sa"; +const std::vector<std::string> Arch::availablePlacers = {"sa"}; + NEXTPNR_NAMESPACE_END diff --git a/generic/arch.h b/generic/arch.h index dc4258cc..5b5d8c55 100644 --- a/generic/arch.h +++ b/generic/arch.h @@ -240,6 +240,9 @@ struct Arch : BaseCtx bool isValidBelForCell(CellInfo *cell, BelId bel) const; bool isBelLocationValid(BelId bel) const; + + static const std::string defaultPlacer; + static const std::vector<std::string> availablePlacers; }; NEXTPNR_NAMESPACE_END diff --git a/ice40/arch.cc b/ice40/arch.cc index ce824c83..b0839fa5 100644 --- a/ice40/arch.cc +++ b/ice40/arch.cc @@ -671,14 +671,17 @@ bool Arch::getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay bool Arch::place() { - if (bool_or_default(settings, id("heap_placer"), false)) { + std::string placer = str_or_default(settings, id("placer"), defaultPlacer); + if (placer == "heap") { PlacerHeapCfg cfg(getCtx()); cfg.ioBufTypes.insert(id_SB_IO); if (!placer_heap(getCtx(), cfg)) return false; - } else { + } else if (placer == "sa") { if (!placer1(getCtx(), Placer1Cfg(getCtx()))) return false; + } else { + log_error("iCE40 architecture does not support placer '%s'\n", placer.c_str()); } if (bool_or_default(settings, id("opt_timing"), false)) { TimingOptCfg tocfg(getCtx()); @@ -1205,4 +1208,12 @@ void Arch::assignCellInfo(CellInfo *cell) } } +const std::string Arch::defaultPlacer = "sa"; + +const std::vector<std::string> Arch::availablePlacers = {"sa", +#ifdef WITH_HEAP + "heap" +#endif +}; + NEXTPNR_NAMESPACE_END diff --git a/ice40/arch.h b/ice40/arch.h index 706043b2..ea29f4f1 100644 --- a/ice40/arch.h +++ b/ice40/arch.h @@ -897,6 +897,9 @@ struct Arch : BaseCtx IdString glb_net = getWireName(getBelPinWire(bel, id_GLOBAL_BUFFER_OUTPUT)); return std::stoi(std::string("") + glb_net.str(this).back()); } + + static const std::string defaultPlacer; + static const std::vector<std::string> availablePlacers; }; void ice40DelayFuzzerMain(Context *ctx); diff --git a/ice40/main.cc b/ice40/main.cc index 7233f169..9b79a08c 100644 --- a/ice40/main.cc +++ b/ice40/main.cc @@ -69,8 +69,6 @@ po::options_description Ice40CommandHandler::getArchOptions() specific.add_options()("promote-logic", "enable promotion of 'logic' globals (in addition to clk/ce/sr by default)"); specific.add_options()("no-promote-globals", "disable all global promotion"); - specific.add_options()("heap-placer", - "use HeAP analytic placer instead of simulated annealing (faster, experimental)"); specific.add_options()("opt-timing", "run post-placement timing optimisation pass (experimental)"); specific.add_options()("tmfuzz", "run path delay estimate fuzzer"); specific.add_options()("pcf-allow-unconstrained", "don't require PCF to constrain all IO"); @@ -178,8 +176,6 @@ std::unique_ptr<Context> Ice40CommandHandler::createContext() ctx->settings[ctx->id("opt_timing")] = "1"; if (vm.count("pcf-allow-unconstrained")) ctx->settings[ctx->id("pcf_allow_unconstrained")] = "1"; - if (vm.count("heap-placer")) - ctx->settings[ctx->id("heap_placer")] = "1"; return ctx; } |