Covert find_machxo2_global_position to use regexes- find isn't precise enough.
diff --git a/libtrellis/src/RoutingGraph.cpp b/libtrellis/src/RoutingGraph.cpp
index 2280adb..e5abd1e 100644
--- a/libtrellis/src/RoutingGraph.cpp
+++ b/libtrellis/src/RoutingGraph.cpp
@@ -281,18 +281,93 @@
     // we can use heuristics to connect globals to the rest of the routing
     // graph properly, given the current tile position and the global's
     // identifier.
+
+    // First copy regexs from utils.nets.machxo2, adjusting as necessary for
+    // prefixes and regex syntax. Commented-out ones are not ready yet:
+    // Globals
+    static const std::regex global_entry(R"(G_VPRX(\d){2}00)", std::regex::optimize);
+    static const std::regex global_left_right(R"([LR]_HPSX(\d){2}00)", std::regex::optimize);
+    static const std::regex global_left_right_g(R"(G_HPSX(\d){2}00)", std::regex::optimize);
+    static const std::regex global_up_down(R"([UD]_VPTX(\d){2}00)", std::regex::optimize);
+    static const std::regex global_up_down_g(R"(G_VPTX(\d){2}00)", std::regex::optimize);
+    static const std::regex global_branch(R"(BRANCH_HPBX(\d){2}00)", std::regex::optimize);
+
+    // High Fanout Secondary Nets
+    // static const std::regex hfsn_entry(R"(G_VSRX(\d){2}00)", std::regex::optimize);
+    // static const std::regex hfsn_left_right(R"(G_HSSX(\d){2}00)", std::regex::optimize);
+    // L2Rs control bidirectional portion of HFSNs!!
+    // static const std::regex hfsn_l2r(R"(G_HSSX(\d){2}00_[RL]2[LR])", std::regex::optimize);
+    // static const std::regex hfsn_up_down(R"(G_VSTX(\d){2}00)", std::regex::optimize);
+    // HSBX(\d){2}00 are fixed connections to HSBX(\d){2}01s.
+    // static const std::regex hfsn_branch(R"(G_HSBX(\d){2}0[01])", std::regex::optimize);
+
+    // Center Mux
+    // Outputs- entry to DCCs connected to globals (VPRXI -> DCC -> VPRX) *
+    static const std::regex center_mux_glb_out(R"(G_VPRXCLKI\d+)", std::regex::optimize);
+    // Outputs- connected to ECLKBRIDGEs *
+    // static const std::regex center_mux_ebrg_out(R"(G_EBRG(\d){1}CLK(\d){1})", std::regex::optimize);
+
+    // Inputs- CIB routing to HFSNs
+    // static const std::regex cib_out_to_hfsn(R"(G_JSNETCIB([TBRL]|MID)(\d){1})", std::regex::optimize);
+    // Inputs- CIB routing to globals
+    static const std::regex cib_out_to_glb(R"(G_J?PCLKCIB(L[TBRL]Q|MID|VIQ[TBRL])(\d){1})", std::regex::optimize);
+    // Inputs- CIB routing to ECLKBRIDGEs
+    // static const std::regex cib_out_to_eclk(R"(G_J?ECLKCIB[TBRL](\d){1})", std::regex::optimize);
+
+    // Inputs- Edge clocks dividers
+    // static const std::regex eclk_out(R"(G_J?[TBRL]CDIV(X(\d){1}|(\d){2}))", std::regex::optimize);
+    // Inputs- PLL
+    // static const std::regex pll_out(R"(G_J?[LR]PLLCLK\d+)", std::regex::optimize);
+    // Inputs- Clock pads
+    // static const std::regex clock_pin(R"(G_J?PCLK[TBLR]\d+)", std::regex::optimize);
+
+    // Part of center-mux but can also be found elsewhere
+    // DCCs connected to globals *
+    static const std::regex dcc_sig(R"(G_J?(CLK[IO]|CE)(\d){1}[TB]?_DCC)", std::regex::optimize);
+
+    // DCMs- connected to DCCs on globals 6 and 7 *
+    static const std::regex dcm_sig(R"(G_J?(CLK(\d){1}_|SEL|DCMOUT)(\d){1}_DCM)", std::regex::optimize);
+
+    // ECLKBRIDGEs- TODO
+    // static const std::regex eclkbridge_sig(R"(G_J?(CLK(\d){1}_|SEL|ECSOUT)(\d){1}_ECLKBRIDGECS)", std::regex::optimize);
+
+    // Oscillator output
+    static const std::regex osc_clk(R"(G_J?OSC_.*)", std::regex::optimize);
+
+    // Soft Error Detection Clock *
+    // static const std::regex sed_clk(R"(G_J?SEDCLKOUT)", std::regex::optimize);
+
+    // PLL/DLL Clocks
+    // static const std::regex pll_clk(R"(G_[TB]ECLK\d)", std::regex::optimize);
+
+    // PG/INRD/LVDS
+    // static const std::regex pg(R"(G_PG)", std::regex::optimize);
+    // static const std::regex inrd(R"(G_INRD)", std::regex::optimize);
+    // static const std::regex vds(R"(G_LVDS)", std::regex::optimize);
+
+    // DDR
+    // static const std::regex ddrclkpol(R"(G_DDRCLKPOL)", std::regex::optimize);
+    // static const std::regex dqsr90(R"(G_DQSR90)", std::regex::optimize);
+    // static const std::regex qsw90(R"(G_DQSW90)", std::regex::optimize);
+
     // Globals are given their nominal position, even if they span multiple
     // tiles, by the following rules:
-
-    static const std::regex clk_dcc(R"(^G_CLK[IO]\d[TB]_DCC)", std::regex::optimize);
-
     smatch m;
     pair<int, int> center = center_map[make_pair(max_row, max_col)];
     RoutingId curr_global;
 
     // All globals in the center tile get a nominal position of the center
-    // tile. This handles L/R_HPSX as well.
-    if(make_pair(row, col) == center) {
+    // tile. We have to use regexes because a number of these connections
+    // in the center mux have config bits spread across multiple tiles.
+    //
+    // This handles L/R_HPSX as well. DCCs are handled a bit differently
+    // until we can determine they only truly exist in center tile (the row,
+    // col, and db_name will still be enough to distinguish them).
+    if(regex_match(db_name, m, global_entry) ||
+        regex_match(db_name, m, global_left_right) ||
+        regex_match(db_name, m, center_mux_glb_out) ||
+        regex_match(db_name, m, cib_out_to_glb) ||
+        regex_match(db_name, m, dcm_sig)) {
         curr_global.id = ident(db_name);
         curr_global.loc.x = center.second;
         curr_global.loc.y = center.first;
@@ -301,7 +376,7 @@
     // If we found a global emanating from the CENTER MUX, return a L_/R_
     // global net in the center tile based upon the current tile position
     // (specifically column).
-    } else if(db_name.find("HPSX") != string::npos) {
+    } else if(regex_match(db_name, m, global_left_right_g)) {
         assert(row == center.first);
         // Prefixes only required in the center tile.
         assert(db_name[0] == 'G');
@@ -321,7 +396,9 @@
         return curr_global;
 
     // U/D wires get the nominal position of center row, current column.
-    } else if(db_name.find("VPTX") != string::npos) {
+    // Both U_/D_ and G_ prefixes are handled here.
+    } else if(regex_match(db_name, m, global_up_down) ||
+        regex_match(db_name, m, global_up_down_g)) {
         // Special case the center row, which will have both U/D wires.
         if(row == center.first) {
             assert((db_name[0] == 'U') || (db_name[0] == 'D'));
@@ -350,23 +427,25 @@
             curr_global.loc.y = center.first;
             return curr_global;
         }
-    } else if(db_name.find("BRANCH") != string::npos) {
+    // BRANCH wires get nominal position of the row/col where they connect
+    // to U_/D_ routing. We need the global_data_machxo2 struct to figure
+    // out this information.
+    } else if(regex_match(db_name, m, global_branch)) {
         curr_global.id = ident(db_name);
         curr_global.loc.x = -2;
         curr_global.loc.y = -2;
         return curr_global;
-    } else if(regex_match(db_name, m, clk_dcc) ||
-        db_name.find("G_JOSC_OSC") != string::npos ||
-        db_name.find("_DCM") != string::npos) {
-
-        // TODO: _DCM should really be a regex.
-        // Assign nominal position of current requested tile.
+    // For OSCH, and DCCs assign nominal position of current requested tile.
+    // DCM only exist in center tile but have their routing spread out
+    // across tiles.
+    } else if(regex_match(db_name, m, dcc_sig) ||
+        regex_match(db_name, m, osc_clk)) {
         curr_global.id = ident(db_name);
         curr_global.loc.x = col;
         curr_global.loc.y = row;
         return curr_global;
     } else {
-        // TODO: Not fuzzed yet!
+        // TODO: Not fuzzed and/or handled yet!
         return RoutingId();
     }
 }