Skip to content

Commit 9210a3d

Browse files
add OPIN--CHANZ edges
1 parent 027ab8b commit 9210a3d

File tree

3 files changed

+137
-65
lines changed

3 files changed

+137
-65
lines changed

vpr/src/route/router_lookahead/router_lookahead_map_utils.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1017,7 +1017,7 @@ static void dijkstra_flood_to_wires(int itile,
10171017

10181018
e_rr_type curr_rr_type = rr_graph.node_type(curr.node);
10191019
int curr_layer_num = rr_graph.node_layer_low(curr.node);
1020-
if (curr_rr_type == e_rr_type::CHANX || curr_rr_type == e_rr_type::CHANY || curr_rr_type == e_rr_type::SINK) {
1020+
if (curr_rr_type == e_rr_type::CHANX || curr_rr_type == e_rr_type::CHANY || curr_rr_type == e_rr_type::CHANZ || curr_rr_type == e_rr_type::SINK) {
10211021
//We stop expansion at any CHANX/CHANY/SINK
10221022
int seg_index;
10231023
if (curr_rr_type != e_rr_type::SINK) {

vpr/src/route/rr_graph_generation/build_scatter_gathers.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,7 @@ std::vector<t_bottleneck_link> alloc_and_load_scatter_gather_connections(const s
276276
scatter_loc.layer_num, scatter_loc.x, scatter_loc.y,
277277
scatter_wire_candidates.size());
278278

279-
continue;
279+
// continue;
280280
}
281281

282282
const bool is_3d_link = (sg_link.z_offset != 0);

vpr/src/route/rr_graph_generation/rr_graph.cpp

Lines changed: 135 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
#include <algorithm>
44
#include <utility>
55
#include <vector>
6+
#include <ranges>
7+
68
#include "alloc_and_load_rr_indexed_data.h"
79
#include "build_scatter_gathers.h"
810
#include "get_parallel_segs.h"
@@ -84,6 +86,15 @@ static vtr::NdMatrix<std::vector<int>, 4> alloc_and_load_pin_to_track_map(const
8486
const e_directionality directionality,
8587
const std::vector<t_segment_inf>& seg_inf,
8688
const std::vector<int>& sets_per_seg_type);
89+
90+
static void add_edges_opin_chanz(RRGraphBuilder& rr_graph_builder,
91+
const RRGraphView& rr_graph,
92+
int layer, int x, int y,
93+
const std::vector<vtr::Matrix<int>>& Fc_out,
94+
const t_unified_to_parallel_seg_index& seg_index_map,
95+
int num_seg_types,
96+
t_rr_edge_info_set& rr_edges_to_create,
97+
const std::vector<t_bottleneck_link>& interdie_3d_links);
8798
/**
8899
* @brief This routine calculates pin connections to tracks for a specific type and a specific segment based on the Fc value
89100
* defined for each pin in the architecture file. This routine is called twice for each combination of block type and segment
@@ -1293,13 +1304,7 @@ std::vector<vtr::Matrix<int>> alloc_and_load_actual_fc(const std::vector<t_physi
12931304

12941305
*Fc_clipped = false;
12951306

1296-
// Unidir tracks formed in pairs, otherwise no effect.
1297-
int fac = 1;
1298-
if (UNI_DIRECTIONAL == directionality) {
1299-
fac = 2;
1300-
}
1301-
1302-
VTR_ASSERT((nodes_per_chan->x_max % fac) == 0 && (nodes_per_chan->y_max % fac) == 0);
1307+
// VTR_ASSERT((nodes_per_chan->x_max % fac) == 0 && (nodes_per_chan->y_max % fac) == 0);
13031308

13041309
for (const t_physical_tile_type& type : types) { // Skip EMPTY
13051310
int itype = type.index;
@@ -1316,63 +1321,72 @@ std::vector<vtr::Matrix<int>> alloc_and_load_actual_fc(const std::vector<t_physi
13161321
for (int ipin : fc_spec.pins) {
13171322
Fc[itype][ipin][iseg] = 0;
13181323
}
1319-
} else {
1320-
// General case indicating that this pin connects to general-purpose routing
1321-
1322-
// Calculate how many connections there should be across all the pins in this fc_spec
1323-
int total_connections = 0;
1324-
if (fc_spec.fc_value_type == e_fc_value_type::FRACTIONAL) {
1325-
float conns_per_pin = fac * sets_per_seg_type[iseg] * fc_spec.fc_value;
1326-
float flt_total_connections = conns_per_pin * fc_spec.pins.size();
1327-
total_connections = vtr::nint(flt_total_connections); //Round to integer
1328-
} else {
1329-
VTR_ASSERT(fc_spec.fc_value_type == e_fc_value_type::ABSOLUTE);
1324+
continue;
1325+
}
13301326

1331-
if (std::fmod(fc_spec.fc_value, fac) != 0. && segment_inf[iseg].parallel_axis != e_parallel_axis::Z_AXIS) {
1332-
VPR_FATAL_ERROR(VPR_ERROR_ROUTE, "Absolute Fc value must be a multiple of %d (was %f) between block pin '%s' and wire segment '%s'",
1333-
fac, fc_spec.fc_value,
1334-
block_type_pin_index_to_name(&type, fc_spec.pins[0], is_flat).c_str(),
1335-
segment_inf[iseg].name.c_str());
1336-
}
1327+
// General case indicating that this pin connects to general-purpose routing
13371328

1338-
if (fc_spec.fc_value < fac && segment_inf[iseg].parallel_axis != e_parallel_axis::Z_AXIS) {
1339-
VPR_FATAL_ERROR(VPR_ERROR_ROUTE, "Absolute Fc value must be at least %d (was %f) between block pin '%s' to wire segment %s",
1340-
fac, fc_spec.fc_value,
1341-
block_type_pin_index_to_name(&type, fc_spec.pins[0], is_flat).c_str(),
1342-
segment_inf[iseg].name.c_str());
1343-
}
1329+
// Unidir tracks formed in pairs, otherwise no effect.
1330+
int fac = 1;
1331+
if (directionality == UNI_DIRECTIONAL && segment_inf[iseg].parallel_axis != e_parallel_axis::Z_AXIS) {
1332+
fac = 2;
1333+
}
1334+
1335+
// Calculate how many connections there should be across all the pins in this fc_spec
1336+
int total_connections = 0;
1337+
if (fc_spec.fc_value_type == e_fc_value_type::FRACTIONAL) {
1338+
float conns_per_pin = fac * sets_per_seg_type[iseg] * fc_spec.fc_value;
1339+
float flt_total_connections = conns_per_pin * fc_spec.pins.size();
1340+
total_connections = vtr::nint(flt_total_connections); //Round to integer
1341+
} else {
1342+
VTR_ASSERT(fc_spec.fc_value_type == e_fc_value_type::ABSOLUTE);
13441343

1345-
total_connections = vtr::nint(fc_spec.fc_value) * fc_spec.pins.size();
1344+
if (std::fmod(fc_spec.fc_value, fac) != 0. && segment_inf[iseg].parallel_axis != e_parallel_axis::Z_AXIS) {
1345+
VPR_FATAL_ERROR(VPR_ERROR_ROUTE, "Absolute Fc value must be a multiple of %d (was %f) between block pin '%s' and wire segment '%s'",
1346+
fac, fc_spec.fc_value,
1347+
block_type_pin_index_to_name(&type, fc_spec.pins[0], is_flat).c_str(),
1348+
segment_inf[iseg].name.c_str());
13461349
}
13471350

1348-
// Ensure that there are at least fac connections, this ensures that low Fc ports
1349-
// targeting small sets of segs get connection(s), even if flt_total_connections < fac.
1350-
total_connections = std::max(total_connections, fac);
1351-
1352-
// Ensure total evenly divides fac by adding the remainder
1353-
total_connections += (total_connections % fac);
1354-
1355-
VTR_ASSERT(total_connections > 0);
1356-
VTR_ASSERT(total_connections % fac == 0);
1357-
1358-
// We walk through all the pins this fc_spec applies to, adding fac connections
1359-
// to each pin, until we run out of connections. This should distribute the connections
1360-
// as evenly as possible (if total_connections % pins.size() != 0, there will be
1361-
// some inevitable imbalance).
1362-
int connections_remaining = total_connections;
1363-
while (connections_remaining != 0) {
1364-
// Add one set of connections to each pin
1365-
for (int ipin : fc_spec.pins) {
1366-
if (connections_remaining >= fac) {
1367-
Fc[itype][ipin][iseg] += fac;
1368-
connections_remaining -= fac;
1369-
} else {
1370-
VTR_ASSERT(connections_remaining == 0);
1371-
break;
1372-
}
1351+
if (fc_spec.fc_value < fac && segment_inf[iseg].parallel_axis != e_parallel_axis::Z_AXIS) {
1352+
VPR_FATAL_ERROR(VPR_ERROR_ROUTE, "Absolute Fc value must be at least %d (was %f) between block pin '%s' to wire segment %s",
1353+
fac, fc_spec.fc_value,
1354+
block_type_pin_index_to_name(&type, fc_spec.pins[0], is_flat).c_str(),
1355+
segment_inf[iseg].name.c_str());
1356+
}
1357+
1358+
total_connections = vtr::nint(fc_spec.fc_value) * fc_spec.pins.size();
1359+
}
1360+
1361+
// Ensure that there are at least fac connections, this ensures that low Fc ports
1362+
// targeting small sets of segs get connection(s), even if flt_total_connections < fac.
1363+
total_connections = std::max(total_connections, fac);
1364+
1365+
// Ensure total evenly divides fac by adding the remainder
1366+
total_connections += (total_connections % fac);
1367+
1368+
VTR_ASSERT(total_connections > 0);
1369+
VTR_ASSERT(total_connections % fac == 0);
1370+
1371+
// We walk through all the pins this fc_spec applies to, adding fac connections
1372+
// to each pin, until we run out of connections. This should distribute the connections
1373+
// as evenly as possible (if total_connections % pins.size() != 0, there will be
1374+
// some inevitable imbalance).
1375+
int connections_remaining = total_connections;
1376+
while (connections_remaining != 0) {
1377+
// Add one set of connections to each pin
1378+
for (int ipin : fc_spec.pins) {
1379+
if (connections_remaining >= fac) {
1380+
Fc[itype][ipin][iseg] += fac;
1381+
connections_remaining -= fac;
1382+
} else {
1383+
VTR_ASSERT(connections_remaining == 0);
1384+
break;
13731385
}
13741386
}
1387+
}
13751388

1389+
if (segment_inf[iseg].parallel_axis != e_parallel_axis::Z_AXIS) {
13761390
for (int ipin : fc_spec.pins) {
13771391
// It is possible that we may want more connections that wires of this type exist;
13781392
// clip to the maximum number of wires
@@ -1515,13 +1529,21 @@ static std::function<void(t_chan_width*)> alloc_and_load_rr_graph(RRGraphBuilder
15151529
*Fc_clipped = true;
15161530
}
15171531
}
1518-
1519-
// Create the actual OPIN->CHANX/CHANY edges
1520-
uniquify_edges(rr_edges_to_create);
1521-
alloc_and_load_edges(rr_graph_builder, rr_edges_to_create);
1522-
num_edges += rr_edges_to_create.size();
1523-
rr_edges_to_create.clear();
15241532
}
1533+
1534+
add_edges_opin_chanz(rr_graph_builder, rr_graph,
1535+
layer, i, j,
1536+
Fc_out,
1537+
seg_index_map,
1538+
num_seg_types,
1539+
rr_edges_to_create,
1540+
interdie_3d_links[i][j]);
1541+
1542+
// Create the actual OPIN->CHANX/CHANY edges
1543+
uniquify_edges(rr_edges_to_create);
1544+
alloc_and_load_edges(rr_graph_builder, rr_edges_to_create);
1545+
num_edges += rr_edges_to_create.size();
1546+
rr_edges_to_create.clear();
15251547
}
15261548
}
15271549
}
@@ -2800,6 +2822,57 @@ static vtr::NdMatrix<std::vector<int>, 4> alloc_and_load_track_to_pin_lookup(vtr
28002822
return track_to_pin_lookup;
28012823
}
28022824

2825+
static void add_edges_opin_chanz(RRGraphBuilder& rr_graph_builder,
2826+
const RRGraphView& rr_graph,
2827+
int layer, int x, int y,
2828+
const std::vector<vtr::Matrix<int>>& Fc_out,
2829+
const t_unified_to_parallel_seg_index& seg_index_map,
2830+
int num_seg_types,
2831+
t_rr_edge_info_set& rr_edges_to_create,
2832+
const std::vector<t_bottleneck_link>& interdie_3d_links) {
2833+
const RRSpatialLookup& node_lookup = rr_graph.node_lookup();
2834+
const DeviceGrid& grid = g_vpr_ctx.device().grid;
2835+
2836+
t_physical_tile_type_ptr type = grid.get_physical_type({x, y, layer});
2837+
2838+
std::vector<RRNodeId> opin_nodes = node_lookup.find_grid_nodes_at_all_sides(layer, x, y, e_rr_type::OPIN);
2839+
std::ranges::stable_sort(opin_nodes, std::less<>{}, [](RRNodeId id) noexcept { return size_t(id); });
2840+
// Remove adjacent duplicates
2841+
auto [unique_end, _] = std::ranges::unique(opin_nodes);
2842+
opin_nodes.erase(unique_end, opin_nodes.end());
2843+
2844+
std::vector<std::pair<RRNodeId, short>> selected_chanz_nodes;
2845+
2846+
for (int iseg = 0; iseg < num_seg_types; iseg++) {
2847+
int seg_index = get_parallel_seg_index(iseg, seg_index_map, e_parallel_axis::Z_AXIS);
2848+
if (seg_index < 0) {
2849+
continue;
2850+
}
2851+
2852+
selected_chanz_nodes.clear();
2853+
for (size_t track_num = 0; track_num < interdie_3d_links.size(); track_num++) {
2854+
const t_bottleneck_link& bottleneck_link = interdie_3d_links[track_num];
2855+
if (bottleneck_link.parallel_segment_index == seg_index && bottleneck_link.gather_loc.layer_num == layer) {
2856+
RRNodeId node_id = node_lookup.find_node(layer, x, y, e_rr_type::CHANZ, track_num);
2857+
selected_chanz_nodes.push_back({node_id, bottleneck_link.arch_wire_switch});
2858+
}
2859+
}
2860+
2861+
int chanz_idx = 0;
2862+
for (RRNodeId opin_node_id : opin_nodes) {
2863+
int pin_number = rr_graph.node_pin_num(opin_node_id);
2864+
int fc = Fc_out[type->index][pin_number][iseg];
2865+
2866+
for (int i = 0; i < fc; i++) {
2867+
RRNodeId chanz_node_id = selected_chanz_nodes[chanz_idx % selected_chanz_nodes.size()].first;
2868+
short switch_id = selected_chanz_nodes[chanz_idx % selected_chanz_nodes.size()].second;
2869+
chanz_idx++;
2870+
rr_edges_to_create.emplace_back(opin_node_id, chanz_node_id, switch_id, false);
2871+
}
2872+
}
2873+
}
2874+
}
2875+
28032876
static void build_unidir_rr_opins(RRGraphBuilder& rr_graph_builder,
28042877
const RRGraphView& rr_graph,
28052878
const int layer,
@@ -2824,7 +2897,6 @@ static void build_unidir_rr_opins(RRGraphBuilder& rr_graph_builder,
28242897
*Fc_clipped = false;
28252898

28262899
t_physical_tile_type_ptr type = grid.get_physical_type({i, j, layer});
2827-
28282900
int width_offset = grid.get_width_offset({i, j, layer});
28292901
int height_offset = grid.get_height_offset({i, j, layer});
28302902

0 commit comments

Comments
 (0)