Connect U_/D_ globals to BRANCHes, completing global routing connections.
diff --git a/libtrellis/src/RoutingGraph.cpp b/libtrellis/src/RoutingGraph.cpp
index e0d41f3..a63abbf 100644
--- a/libtrellis/src/RoutingGraph.cpp
+++ b/libtrellis/src/RoutingGraph.cpp
@@ -3,6 +3,7 @@
#include "Tile.hpp"
#include <regex>
#include <iostream>
+#include <algorithm>
namespace Trellis {
@@ -358,7 +359,8 @@
// All globals in the center tile get a nominal position of the center
// tile. We have to use regexes because a number of these connections
- // in the center mux have config bits spread across multiple tiles.
+ // in the center mux have config bits spread across multiple tiles
+ // (although few nets actually have routing bits which cross 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,
@@ -380,9 +382,7 @@
// If more than one arc has this problem, we may need to change this
// function signature to be device-specific, and find a better way to
// store this info along with the routing graph besides special-casing.
- if((db_name.find("G_VPRXCLKI0") != string::npos) &&
- row == 9 &&
- col == 12)
+ if((db_name.find("G_VPRXCLKI0") != string::npos) && row == 9 && col == 12)
return RoutingId();
curr_global.id = ident(db_name);
@@ -416,6 +416,16 @@
// 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)) {
+
+ std::vector<int> & ud_conns_in_col = global_data_machxo2.ud_conns[col];
+
+ // First check whether the requested global is in the current column.
+ // If not, no point in continuing.
+ if(std::find(ud_conns_in_col.begin(), ud_conns_in_col.end(),
+ std::stoi(m.str(1))) == ud_conns_in_col.end()) {
+ return RoutingId();
+ }
+
// 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'));
@@ -448,10 +458,45 @@
// 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;
+ std::vector<int> candidate_cols;
+
+ if(col == 0) {
+ candidate_cols.push_back(0);
+ candidate_cols.push_back(1);
+ } else if(col == 1) {
+ candidate_cols.push_back(0);
+ candidate_cols.push_back(1);
+ candidate_cols.push_back(2);
+ } else if(col == max_col) {
+ candidate_cols.push_back(max_col - 2);
+ candidate_cols.push_back(max_col - 1);
+ candidate_cols.push_back(max_col);
+ } else {
+ candidate_cols.push_back(col - 2);
+ candidate_cols.push_back(col - 1);
+ candidate_cols.push_back(col);
+ candidate_cols.push_back(col + 1);
+ }
+
+ for(auto curr_col : candidate_cols) {
+ std::vector<int> & ud_conns_in_col = global_data_machxo2.ud_conns[curr_col];
+
+ // First check whether the requested global is in the current column.
+ // If not, no point in continuing.
+ if(std::find(ud_conns_in_col.begin(), ud_conns_in_col.end(),
+ std::stoi(m.str(1))) != ud_conns_in_col.end()) {
+ curr_global.id = ident(db_name);
+ curr_global.loc.x = curr_col;
+ curr_global.loc.y = row;
+ return curr_global;
+ }
+ }
+
+ // One of the candidate columns should have had the correct U/D
+ // connection to route to.
+ assert(false);
+ return RoutingId();
+
// 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.