aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--common/command.cc19
-rw-r--r--common/settings.h27
-rw-r--r--docs/archapi.md11
-rw-r--r--ecp5/arch.cc30
-rw-r--r--ecp5/arch.h3
-rw-r--r--ecp5/main.cc6
-rw-r--r--generic/arch.cc15
-rw-r--r--generic/arch.h3
-rw-r--r--ice40/arch.cc15
-rw-r--r--ice40/arch.h3
-rw-r--r--ice40/main.cc4
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;
}