Use settings for placer1 and router1
diff --git a/common/command.cc b/common/command.cc
index d5639e9..ab0c92f 100644
--- a/common/command.cc
+++ b/common/command.cc
@@ -144,7 +144,7 @@
     }
 
     if (vm.count("cstrweight")) {
-        // ctx->placer_constraintWeight = vm["cstrweight"].as<float>();
+        settings->set("placer1/constraintWeight", vm["cstrweight"].as<float>());
     }
 
     if (vm.count("freq")) {
@@ -261,6 +261,7 @@
         } else {
             ctx = createContext();
         }
+        settings = std::unique_ptr<Settings>(new Settings(ctx.get()));
         setupContext(ctx.get());
         setupArchContext(ctx.get());
         return executeMain(std::move(ctx));
diff --git a/common/command.h b/common/command.h
index 13d5a25..900cf74 100644
--- a/common/command.h
+++ b/common/command.h
@@ -24,6 +24,7 @@
 #include <boost/program_options.hpp>
 #include "nextpnr.h"
 #include "project.h"
+#include "settings.h"
 
 NEXTPNR_NAMESPACE_BEGIN
 
@@ -56,6 +57,7 @@
   protected:
     po::variables_map vm;
     ArchArgs chipArgs;
+    std::unique_ptr<Settings> settings;
 
   private:
     po::options_description options;
diff --git a/common/placer1.cc b/common/placer1.cc
index 9132024..4171e21 100644
--- a/common/placer1.cc
+++ b/common/placer1.cc
@@ -23,6 +23,7 @@
 
 #include "placer1.h"
 #include <algorithm>
+#include <boost/lexical_cast.hpp>
 #include <cmath>
 #include <iostream>
 #include <limits>
@@ -95,14 +96,12 @@
                 if (bel_type != cell->type) {
                     log_error("Bel \'%s\' of type \'%s\' does not match cell "
                               "\'%s\' of type \'%s\'\n",
-                              loc_name.c_str(), bel_type.c_str(ctx), cell->name.c_str(ctx),
-                              cell->type.c_str(ctx));
+                              loc_name.c_str(), bel_type.c_str(ctx), cell->name.c_str(ctx), cell->type.c_str(ctx));
                 }
                 if (!ctx->isValidBelForCell(cell, bel)) {
                     log_error("Bel \'%s\' of type \'%s\' is not valid for cell "
                               "\'%s\' of type \'%s\'\n",
-                              loc_name.c_str(), bel_type.c_str(ctx), cell->name.c_str(ctx),
-                              cell->type.c_str(ctx));
+                              loc_name.c_str(), bel_type.c_str(ctx), cell->name.c_str(ctx), cell->type.c_str(ctx));
                 }
 
                 ctx->bindBel(bel, cell, STRENGTH_USER);
@@ -461,6 +460,8 @@
     Placer1Cfg cfg;
 };
 
+Placer1Cfg::Placer1Cfg(Context *ctx) : Settings(ctx) { constraintWeight = get<float>("placer1/constraintWeight", 10); }
+
 bool placer1(Context *ctx, Placer1Cfg cfg)
 {
     try {
diff --git a/common/placer1.h b/common/placer1.h
index d8f64b8..55db1fa 100644
--- a/common/placer1.h
+++ b/common/placer1.h
@@ -20,12 +20,14 @@
 #define PLACE_H
 
 #include "nextpnr.h"
+#include "settings.h"
 
 NEXTPNR_NAMESPACE_BEGIN
 
-struct Placer1Cfg
+struct Placer1Cfg : public Settings
 {
-    float constraintWeight = 10;
+    Placer1Cfg(Context *ctx);
+    float constraintWeight;
 };
 
 extern bool placer1(Context *ctx, Placer1Cfg cfg);
diff --git a/common/router1.cc b/common/router1.cc
index 0733a61..5cd4414 100644
--- a/common/router1.cc
+++ b/common/router1.cc
@@ -682,6 +682,14 @@
 
 NEXTPNR_NAMESPACE_BEGIN
 
+Router1Cfg::Router1Cfg(Context *ctx) : Settings(ctx)
+{
+    maxIterCnt = get<int>("router1/maxIterCnt", 200);
+    cleanupReroute = get<bool>("router1/cleanupReroute", true);
+    fullCleanupReroute = get<bool>("router1/fullCleanupReroute", true);
+    useEstimate = get<bool>("router1/useEstimate", true);
+}
+
 bool router1(Context *ctx, const Router1Cfg &cfg)
 {
     try {
@@ -953,7 +961,7 @@
                                   std::unordered_map<WireId, PipId> *route, bool useEstimate)
 {
     RipupScoreboard scores;
-    Router1Cfg cfg;
+    Router1Cfg cfg(this);
     cfg.useEstimate = useEstimate;
 
     Router router(this, cfg, scores, src_wire, dst_wire);
diff --git a/common/router1.h b/common/router1.h
index 0380adc..a184cbe 100644
--- a/common/router1.h
+++ b/common/router1.h
@@ -21,15 +21,18 @@
 #define ROUTER1_H
 
 #include "nextpnr.h"
+#include "settings.h"
 
 NEXTPNR_NAMESPACE_BEGIN
 
-struct Router1Cfg
+struct Router1Cfg : Settings
 {
-    int maxIterCnt = 200;
-    bool cleanupReroute = true;
-    bool fullCleanupReroute = true;
-    bool useEstimate = true;
+    Router1Cfg(Context *ctx);
+
+    int maxIterCnt;
+    bool cleanupReroute;
+    bool fullCleanupReroute;
+    bool useEstimate;
 };
 
 extern bool router1(Context *ctx, const Router1Cfg &cfg);
diff --git a/common/settings.h b/common/settings.h
new file mode 100644
index 0000000..c7ef201
--- /dev/null
+++ b/common/settings.h
@@ -0,0 +1,57 @@
+/*
+ *  nextpnr -- Next Generation Place and Route
+ *
+ *  Copyright (C) 2018  Miodrag Milanovic <miodrag@symbioticeda.com>
+ *
+ *  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 SETTINGS_H
+#define SETTINGS_H
+
+#include <boost/lexical_cast.hpp>
+#include "nextpnr.h"
+
+NEXTPNR_NAMESPACE_BEGIN
+
+class Settings
+{
+  public:
+    explicit Settings(Context *ctx) : ctx(ctx) {}
+
+    template <typename T> T get(const char *name, T defaultValue)
+    {
+        IdString id = ctx->id(name);
+        if (ctx->settings.find(id) != ctx->settings.end())
+            return boost::lexical_cast<T>(ctx->settings[id]);
+        ctx->settings.emplace(id, std::to_string(defaultValue));
+        return defaultValue;
+    }
+
+    template <typename T> void set(const char *name, T value)
+    {
+        IdString id = ctx->id(name);
+        if (ctx->settings.find(id) != ctx->settings.end()) {
+            ctx->settings[id] = value;
+            return;
+        }
+        ctx->settings.emplace(id, std::to_string(value));
+    }
+
+  private:
+    Context *ctx;
+};
+
+NEXTPNR_NAMESPACE_END
+
+#endif // SETTINGS_H
diff --git a/ecp5/arch.cc b/ecp5/arch.cc
index 4358fda..047f551 100644
--- a/ecp5/arch.cc
+++ b/ecp5/arch.cc
@@ -383,13 +383,9 @@
 
 // -----------------------------------------------------------------------
 
-bool Arch::place() { return placer1(getCtx(), Placer1Cfg()); }
+bool Arch::place() { return placer1(getCtx(), Placer1Cfg(getCtx())); }
 
-bool Arch::route()
-{
-    Router1Cfg cfg;
-    return router1(getCtx(), cfg);
-}
+bool Arch::route() { return router1(getCtx(), Router1Cfg(getCtx())); }
 
 // -----------------------------------------------------------------------
 
diff --git a/generic/arch.cc b/generic/arch.cc
index d306a9e..b37f53b 100644
--- a/generic/arch.cc
+++ b/generic/arch.cc
@@ -425,9 +425,9 @@
 
 // ---------------------------------------------------------------
 
-bool Arch::place() { return placer1(getCtx(), Placer1Cfg()); }
+bool Arch::place() { return placer1(getCtx(), Placer1Cfg(getCtx())); }
 
-bool Arch::route() { return router1(getCtx(), Router1Cfg()); }
+bool Arch::route() { return router1(getCtx(), Router1Cfg(getCtx())); }
 
 // ---------------------------------------------------------------
 
diff --git a/ice40/arch.cc b/ice40/arch.cc
index 7e2dd7f..357b301 100644
--- a/ice40/arch.cc
+++ b/ice40/arch.cc
@@ -565,18 +565,9 @@
 
 // -----------------------------------------------------------------------
 
-bool Arch::place()
-{
-    Placer1Cfg cfg;
-    cfg.constraintWeight = placer_constraintWeight;
-    return placer1(getCtx(), cfg);
-}
+bool Arch::place() { return placer1(getCtx(), Placer1Cfg(getCtx())); }
 
-bool Arch::route()
-{
-    Router1Cfg cfg;
-    return router1(getCtx(), cfg);
-}
+bool Arch::route() { return router1(getCtx(), Router1Cfg(getCtx())); }
 
 // -----------------------------------------------------------------------
 
diff --git a/ice40/arch.h b/ice40/arch.h
index 4c093ef..2f2a0f3 100644
--- a/ice40/arch.h
+++ b/ice40/arch.h
@@ -832,8 +832,6 @@
         }
         NPNR_ASSERT_FALSE("Expected PLL pin to share an output with an SB_IO D_IN_{0,1}");
     }
-
-    float placer_constraintWeight = 10;
 };
 
 void ice40DelayFuzzerMain(Context *ctx);