Merge pull request #71 from SymbiFlow/ddrn

IO primitive fixes
diff --git a/libtrellis/include/Bels.hpp b/libtrellis/include/Bels.hpp
index 0141c83..cb4b5ea 100644
--- a/libtrellis/include/Bels.hpp
+++ b/libtrellis/include/Bels.hpp
@@ -19,7 +19,7 @@
 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);
+void add_ioclk_bel(RoutingGraph &graph, const std::string &name, int x, int y, int i, int bank = -1);
 }
 }
 
diff --git a/libtrellis/src/Bels.cpp b/libtrellis/src/Bels.cpp
index da6f71f..7a84774 100644
--- a/libtrellis/src/Bels.cpp
+++ b/libtrellis/src/Bels.cpp
@@ -517,7 +517,7 @@
     graph.add_bel(bel);
 }
 
-void add_ioclk_bel(RoutingGraph &graph, const std::string &name, int x, int y, int i) {
+void add_ioclk_bel(RoutingGraph &graph, const std::string &name, int x, int y, int i, int bank) {
     std::string postfix;
     RoutingBel bel;
 
@@ -541,15 +541,20 @@
         add_output("CDIVX");
     } else if (name == "ECLKSYNCB") {
         postfix = "ECLKSYNC" + std::to_string(i);
-        bel.name = graph.ident(postfix);
-        bel.z = 2 + i;
+        bel.name = graph.ident(postfix + "_BK" + std::to_string(bank));
+        bel.z = 8 + i;
         add_input("ECLKI", false);
         add_input("STOP");
         add_output("ECLKO");
+    } else if (name == "TRELLIS_ECLKBUF") {
+        bel.z = 10 + i;
+        bel.name = graph.ident("ECLKBUF" + std::to_string(i));
+        graph.add_bel_input(bel, graph.ident("ECLKI"), x, y, graph.ident(fmt("JECLK" << i)));
+        graph.add_bel_output(bel, graph.ident("ECLKO"), 0, 0, graph.ident(fmt("G_BANK" << bank << "ECLK" << i)));
     } else if (name == "DLLDELD") {
         postfix = "DLLDEL";
         bel.name = graph.ident(postfix);
-        bel.z = 4;
+        bel.z = 12;
         add_input("A");
         add_input("DDRDEL", false);
         add_input("LOADN");
diff --git a/libtrellis/src/Chip.cpp b/libtrellis/src/Chip.cpp
index 52ac8c9..a95f2e3 100644
--- a/libtrellis/src/Chip.cpp
+++ b/libtrellis/src/Chip.cpp
@@ -199,12 +199,16 @@
         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, "CLKDIVF", x-2, y, 0, 7);
+            Bels::add_ioclk_bel(*rg, "CLKDIVF", x-2, y, 1, 6);
+            Bels::add_ioclk_bel(*rg, "ECLKSYNCB", x-2, y, 0, 7);
+            Bels::add_ioclk_bel(*rg, "ECLKSYNCB", x-2, y, 1, 7);
+            Bels::add_ioclk_bel(*rg, "ECLKSYNCB", x-2, y+1, 0, 6);
+            Bels::add_ioclk_bel(*rg, "ECLKSYNCB", x-2, y+1, 1, 6);
+            Bels::add_ioclk_bel(*rg, "TRELLIS_ECLKBUF", x-2, y, 0, 7);
+            Bels::add_ioclk_bel(*rg, "TRELLIS_ECLKBUF", x-2, y, 1, 7);
+            Bels::add_ioclk_bel(*rg, "TRELLIS_ECLKBUF", x-2, y+1, 0, 6);
+            Bels::add_ioclk_bel(*rg, "TRELLIS_ECLKBUF", x-2, y+1, 1, 6);
             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);
@@ -213,10 +217,14 @@
         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, "ECLKSYNCB", x+2, y, 0, 2);
+            Bels::add_ioclk_bel(*rg, "ECLKSYNCB", x+2, y, 1, 2);
+            Bels::add_ioclk_bel(*rg, "ECLKSYNCB", x+2, y+1, 0, 3);
+            Bels::add_ioclk_bel(*rg, "ECLKSYNCB", x+2, y+1, 1, 3);
+            Bels::add_ioclk_bel(*rg, "TRELLIS_ECLKBUF", x+2, y, 0, 2);
+            Bels::add_ioclk_bel(*rg, "TRELLIS_ECLKBUF", x+2, y, 1, 2);
+            Bels::add_ioclk_bel(*rg, "TRELLIS_ECLKBUF", x+2, y+1, 0, 3);
+            Bels::add_ioclk_bel(*rg, "TRELLIS_ECLKBUF", x+2, y+1, 1, 3);
             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);
diff --git a/libtrellis/src/RoutingGraph.cpp b/libtrellis/src/RoutingGraph.cpp
index 2f1b39d..728a9bd 100644
--- a/libtrellis/src/RoutingGraph.cpp
+++ b/libtrellis/src/RoutingGraph.cpp
@@ -62,8 +62,6 @@
             return RoutingId();
         }
     }
-    if (stripped_name.find("BNK_") == 0 || stripped_name.find("DQSG_") == 0) // Not yet implemented
-        return RoutingId();
     // Workaround for PCSA/B sharing tile dbs
     if (col >= 69) {
         size_t pcsa_pos = stripped_name.find("PCSA");