Merge branch 'miscbels'
diff --git a/libtrellis/include/Bels.hpp b/libtrellis/include/Bels.hpp
index ad1f44c..0141c83 100644
--- a/libtrellis/include/Bels.hpp
+++ b/libtrellis/include/Bels.hpp
@@ -18,6 +18,8 @@
 void add_extref(RoutingGraph &graph, int x, int y);
 void add_pcsclkdiv(RoutingGraph &graph, int x, int y, int z);
 void add_iologic(RoutingGraph &graph, int x, int y, int z, bool s);
+void add_misc(RoutingGraph &graph, const std::string &name, int x, int y);
+void add_ioclk_bel(RoutingGraph &graph, const std::string &name, int x, int y, int i);
 }
 }
 
diff --git a/libtrellis/src/Bels.cpp b/libtrellis/src/Bels.cpp
index 2a8154e..da6f71f 100644
--- a/libtrellis/src/Bels.cpp
+++ b/libtrellis/src/Bels.cpp
@@ -446,5 +446,170 @@
     graph.add_bel(bel);
 }
 
+void add_misc(RoutingGraph &graph, const std::string &name, int x, int y) {
+    std::string postfix;
+    RoutingBel bel;
+
+    auto add_input = [&](const std::string &pin, bool j = true) {
+        graph.add_bel_input(bel, graph.ident(pin), x, y, graph.ident(fmt((j ? "J" : "") << pin << "_" << postfix)));
+    };
+    auto add_output = [&](const std::string &pin, bool j = true) {
+        graph.add_bel_output(bel, graph.ident(pin), x, y, graph.ident(fmt((j ? "J" : "") << pin << "_" << postfix)));
+    };
+    bel.name = graph.ident(name);
+    bel.type = graph.ident(name);
+    bel.loc.x = x;
+    bel.loc.y = y;
+
+    if (name == "GSR") {
+        postfix = "GSR";
+        bel.z = 0;
+        add_input("GSR");
+        add_input("CLK");
+    } else if (name == "JTAGG") {
+        postfix = "JTAG";
+        bel.z = 1;
+        add_input("TCK");
+        add_input("TMS");
+        add_input("TDI");
+        add_input("JTDO2");
+        add_input("JTDO1");
+        add_output("TDO");
+        add_output("JTDI");
+        add_output("JTCK");
+        add_output("JRTI2");
+        add_output("JRTI1");
+        add_output("JSHIFT");
+        add_output("JUPDATE");
+        add_output("JRSTN");
+        add_output("JCE2");
+        add_output("JCE1");
+    } else if (name == "OSCG") {
+        postfix = "OSC";
+        bel.z = 2;
+        graph.add_bel_output(bel, graph.ident("OSC"), 0, 0, graph.ident("G_JOSC_OSC"));
+        add_output("SEDSTDBY", false);
+    } else if (name == "SEDGA") {
+        postfix = "SED";
+        bel.z = 3;
+        add_input("SEDENABLE");
+        add_input("SEDSTART");
+        add_input("SEDFRCERR");
+        add_output("SEDDONE");
+        add_output("SEDINPROG");
+        add_output("SEDERR");
+        add_input("SEDSTDBY", false);
+    } else if (name == "DTR") {
+        postfix = "DTR";
+        bel.z = 0;
+        add_input("STARTPULSE");
+        for (int i = 0; i < 8; i++)
+            add_output("DTROUT" + std::to_string(i));
+    } else if (name == "USRMCLK") {
+        postfix = "CCLK";
+        bel.z = 0;
+        add_input("PADDO");
+        add_input("PADDT");
+        add_output("PADDI");
+    } else {
+        throw runtime_error("unknown Bel " + name);
+    }
+    graph.add_bel(bel);
 }
+
+void add_ioclk_bel(RoutingGraph &graph, const std::string &name, int x, int y, int i) {
+    std::string postfix;
+    RoutingBel bel;
+
+    auto add_input = [&](const std::string &pin, bool j = true) {
+        graph.add_bel_input(bel, graph.ident(pin), x, y, graph.ident(fmt((j ? "J" : "") << pin << "_" << postfix)));
+    };
+    auto add_output = [&](const std::string &pin, bool j = true) {
+        graph.add_bel_output(bel, graph.ident(pin), x, y, graph.ident(fmt((j ? "J" : "") << pin << "_" << postfix)));
+    };
+    bel.type = graph.ident(name);
+    bel.loc.x = x;
+    bel.loc.y = y;
+
+    if (name == "CLKDIVF") {
+        postfix = "CLKDIV" + std::to_string(i);
+        bel.name = graph.ident(postfix);
+        bel.z = i;
+        add_input("CLKI", false);
+        add_input("RST");
+        add_input("ALIGNWD");
+        add_output("CDIVX");
+    } else if (name == "ECLKSYNCB") {
+        postfix = "ECLKSYNC" + std::to_string(i);
+        bel.name = graph.ident(postfix);
+        bel.z = 2 + i;
+        add_input("ECLKI", false);
+        add_input("STOP");
+        add_output("ECLKO");
+    } else if (name == "DLLDELD") {
+        postfix = "DLLDEL";
+        bel.name = graph.ident(postfix);
+        bel.z = 4;
+        add_input("A");
+        add_input("DDRDEL", false);
+        add_input("LOADN");
+        add_input("MOVE");
+        add_input("DIRECTION");
+        add_output("Z", false);
+        add_output("CFLAG");
+    } else if (name == "DDRDLL") {
+        postfix = "DDRDLL";
+        bel.name = graph.ident(postfix);
+        bel.z = 0;
+        add_input("CLK");
+        add_input("RST");
+        add_input("UDDCNTLN");
+        add_input("FREEZE");
+        add_output("DDRDEL", false);
+        add_output("LOCK");
+        add_output("DIVOSC");
+        for (int j = 0; j < 8; j++)
+            add_output("DCNTL" + std::to_string(j));
+    } else if (name == "DQSBUFM") {
+        postfix = "DQS";
+        bel.name = graph.ident("DQSBUF");
+        bel.z = 8;
+        add_input("DQSI");
+        add_input("READ1");
+        add_input("READ0");
+        add_input("READCLKSEL2");
+        add_input("READCLKSEL1");
+        add_input("READCLKSEL0");
+        add_input("DDRDEL", false);
+        add_input("ECLK", false);
+        add_input("SCLK");
+        add_input("RST");
+        for (int j = 0; j < 8; j++)
+            add_input("DYNDELAY" + std::to_string(j));
+        add_input("PAUSE");
+        add_input("RDLOADN");
+        add_input("RDMOVE");
+        add_input("RDDIRECTION");
+        add_input("WRLOADN");
+        add_input("WRMOVE");
+        add_input("WRDIRECTION");
+        add_output("DQSR90");
+        add_output("DQSW");
+        add_output("DQSW270");
+        for (int j = 0; j < 3; j++) {
+            add_output("RDPNTR" + std::to_string(j), false);
+            add_output("WRPNTR" + std::to_string(j), false);
+        }
+        add_output("DATAVALID");
+        add_output("BURSTDET");
+        add_output("RDCFLAG");
+        add_output("WRCFLAG");
+    } else {
+        throw runtime_error("unknown Bel " + name);
+    }
+    graph.add_bel(bel);
 }
+
+
+}
+}
\ No newline at end of file
diff --git a/libtrellis/src/Chip.cpp b/libtrellis/src/Chip.cpp
index 7b08dac..52ac8c9 100644
--- a/libtrellis/src/Chip.cpp
+++ b/libtrellis/src/Chip.cpp
@@ -187,6 +187,55 @@
         if (tile->info.type == "BMID_0H")
             for (int z = 0; z < 2; z++)
                 Bels::add_pcsclkdiv(*rg, x, y-1, z);
+        // Config/system Bels
+        if (tile->info.type == "EFB0_PICB0") {
+            Bels::add_misc(*rg, "GSR", x, y-1);
+            Bels::add_misc(*rg, "JTAGG", x, y-1);
+            Bels::add_misc(*rg, "OSCG", x, y-1);
+            Bels::add_misc(*rg, "SEDGA", x, y-1);
+        }
+        if (tile->info.type == "DTR")
+            Bels::add_misc(*rg, "DTR", x, y-1);
+        if (tile->info.type == "EFB1_PICB1")
+            Bels::add_misc(*rg, "USRMCLK", x-5, y);
+        if (tile->info.type == "ECLK_L") {
+            Bels::add_ioclk_bel(*rg, "CLKDIVF", x-2, y, 0);
+            Bels::add_ioclk_bel(*rg, "CLKDIVF", x-2, y, 1);
+            Bels::add_ioclk_bel(*rg, "ECLKSYNCB", x-2, y, 0);
+            Bels::add_ioclk_bel(*rg, "ECLKSYNCB", x-2, y, 1);
+            Bels::add_ioclk_bel(*rg, "ECLKSYNCB", x-2, y+1, 0);
+            Bels::add_ioclk_bel(*rg, "ECLKSYNCB", x-2, y+1, 1);
+            Bels::add_ioclk_bel(*rg, "DLLDELD", x-2, y-1, 0);
+            Bels::add_ioclk_bel(*rg, "DLLDELD", x-2, y, 0);
+            Bels::add_ioclk_bel(*rg, "DLLDELD", x-2, y+1, 0);
+            Bels::add_ioclk_bel(*rg, "DLLDELD", x-2, y+2, 0);
+        }
+        if (tile->info.type == "ECLK_R") {
+            Bels::add_ioclk_bel(*rg, "CLKDIVF", x+2, y, 0);
+            Bels::add_ioclk_bel(*rg, "CLKDIVF", x+2, y, 1);
+            Bels::add_ioclk_bel(*rg, "ECLKSYNCB", x+2, y, 0);
+            Bels::add_ioclk_bel(*rg, "ECLKSYNCB", x+2, y, 1);
+            Bels::add_ioclk_bel(*rg, "ECLKSYNCB", x+2, y+1, 0);
+            Bels::add_ioclk_bel(*rg, "ECLKSYNCB", x+2, y+1, 1);
+            Bels::add_ioclk_bel(*rg, "DLLDELD", x+2, y-1, 0);
+            Bels::add_ioclk_bel(*rg, "DLLDELD", x+2, y, 0);
+            Bels::add_ioclk_bel(*rg, "DLLDELD", x+2, y+1, 0);
+            Bels::add_ioclk_bel(*rg, "DLLDELD", x+2, y+2, 0);
+        }
+        if (tile->info.type == "DDRDLL_UL")
+            Bels::add_ioclk_bel(*rg, "DDRDLL", x-2, y-10, 0);
+        if (tile->info.type == "DDRDLL_ULA")
+            Bels::add_ioclk_bel(*rg, "DDRDLL", x-2, y-13, 0);
+        if (tile->info.type == "DDRDLL_UR")
+            Bels::add_ioclk_bel(*rg, "DDRDLL", x+2, y-10, 0);
+        if (tile->info.type == "DDRDLL_URA")
+            Bels::add_ioclk_bel(*rg, "DDRDLL", x+2, y-13, 0);
+        if (tile->info.type == "DDRDLL_LL")
+            Bels::add_ioclk_bel(*rg, "DDRDLL", x-2, y+13, 0);
+        if (tile->info.type == "DDRDLL_LR")
+            Bels::add_ioclk_bel(*rg, "DDRDLL", x+2, y+13, 0);
+        if (tile->info.type == "PICL0_DQS2" || tile->info.type == "PICR0_DQS2")
+            Bels::add_ioclk_bel(*rg, "DQSBUFM", x, y, 0);
 
     }
     return rg;