Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix for Handling Missing Switch Types in RR Graph Builder #2674

Merged
merged 13 commits into from
Aug 15, 2024
Merged
142 changes: 88 additions & 54 deletions vpr/src/route/rr_graph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -264,14 +264,27 @@ static void connect_tile_src_sink_to_pins(RRGraphBuilder& rr_graph_builder,
const int delayless_switch,
t_physical_tile_type_ptr physical_type_ptr);

/**
* Add the edges between IPIN to SINK and SOURCE to OPIN to rr_edges_to_create
* @param rr_graph_builder RR Graph Bulder object which contain the RR Graph storage
* @param class_num_vec Class physical numbers to add the edges connected to them
* @param layer The layer number of the block to add the SINK/SRC connections of it.
* @param i The x location of the block to add the SINK/SRC connections of it.
* @param j The y location of the block to add the SINK/SRC connections of it
* @param rr_edges_to_create An object which store all of the edges created in this function.
* @param delayless_switch Switch ID of the delayless switch.
* @param physical_type_ptr A pointer to the physical type of the block for which the edges are created.
* @param switches_remapped A flag to indicate whether edge switch IDs are remapped
*/
static void connect_src_sink_to_pins(RRGraphBuilder& rr_graph_builder,
const std::vector<int>& class_num_vec,
const int layer,
const int i,
const int j,
t_rr_edge_info_set& rr_edges_to_create,
const int delayless_switch,
t_physical_tile_type_ptr physical_type_ptr);
t_physical_tile_type_ptr physical_type_ptr,
bool switches_remapped);

static void alloc_and_load_tile_rr_graph(RRGraphBuilder& rr_graph_builder,
std::map<int, t_arch_switch_inf>& arch_sw_inf_map,
Expand Down Expand Up @@ -374,11 +387,13 @@ static void add_pb_edges(RRGraphBuilder& rr_graph_builder,
t_logical_block_type_ptr logical_block,
const t_pb* pb,
const t_cluster_pin_chain& nodes_to_collapse,
float R_minW_nmos,
float R_minW_pmos,
int rel_cap,
int layer,
int i,
int j,
bool is_remapped);
bool switches_remapped);

/**
* Edges going in/out of collapse nodes are not added by the normal routine. This function add those edges
Expand Down Expand Up @@ -656,6 +671,15 @@ static void build_intra_cluster_rr_graph(const t_graph_type graph_type,
bool is_flat,
bool load_rr_graph);

/**
* Return the ID for delayess switch. If the RR graph is loaded from a file, then the assumption
* is that the returned ID should be a RR switch ID not architecture ID.
* @param det_routing_arch Contain the information from architecture file
* @param load_rr_graph Indicate whether the RR graph is loaded from a file
*/
static int get_delayless_switch_id(t_det_routing_arch* det_routing_arch,
bool load_rr_graph);

/******************* Subroutine definitions *******************************/

void create_rr_graph(const t_graph_type graph_type,
Expand Down Expand Up @@ -741,11 +765,13 @@ void create_rr_graph(const t_graph_type graph_type,
}

if (is_flat) {
int delayless_switch = get_delayless_switch_id(det_routing_arch, load_rr_graph);
VTR_ASSERT(delayless_switch != OPEN);
build_intra_cluster_rr_graph(graph_type,
grid,
block_types,
device_ctx.rr_graph,
det_routing_arch->delayless_switch,
delayless_switch,
det_routing_arch->R_minW_nmos,
det_routing_arch->R_minW_pmos,
mutable_device_ctx.rr_graph_builder,
Expand Down Expand Up @@ -1512,6 +1538,26 @@ static void build_intra_cluster_rr_graph(const t_graph_type graph_type,
is_flat);
}

static int get_delayless_switch_id(t_det_routing_arch* det_routing_arch,
bool load_rr_graph) {
const auto& device_ctx = g_vpr_ctx.device();
int delayless_switch = OPEN;
if (load_rr_graph) {
const auto& rr_switches = device_ctx.rr_graph.rr_switch();
for (size_t switch_id = 0; switch_id < rr_switches.size(); switch_id++){
const auto& rr_switch = rr_switches[RRSwitchId(switch_id)];
if (rr_switch.name.find("delayless") != std::string::npos) {
delayless_switch = static_cast<int>(switch_id);
break;
}
}
} else {
delayless_switch = static_cast<int>(det_routing_arch->delayless_switch);
}

return delayless_switch;
}

void build_tile_rr_graph(RRGraphBuilder& rr_graph_builder,
const t_det_routing_arch& det_routing_arch,
t_physical_tile_type_ptr physical_tile,
Expand Down Expand Up @@ -2021,6 +2067,10 @@ static std::function<void(t_chan_width*)> alloc_and_load_rr_graph(RRGraphBuilder
/* If Fc gets clipped, this will be flagged to true */
*Fc_clipped = false;

/* This function is called to build the general routing graph resoruces. Thus,
the edges are not remapped yet.*/
bool switches_remapped = false;

int num_edges = 0;
/* Connection SINKS and SOURCES to their pins - Initializing IPINs/OPINs. */
for (int layer = 0; layer < grid.get_num_layers(); ++layer) {
Expand Down Expand Up @@ -2053,7 +2103,8 @@ static std::function<void(t_chan_width*)> alloc_and_load_rr_graph(RRGraphBuilder
j,
rr_edges_to_create,
delayless_switch,
physical_tile);
physical_tile,
switches_remapped);

//Create the actual SOURCE->OPIN, IPIN->SINK edges
uniquify_edges(rr_edges_to_create);
Expand Down Expand Up @@ -2270,7 +2321,8 @@ static void alloc_and_load_intra_cluster_rr_graph(RRGraphBuilder& rr_graph_build
j,
rr_edges_to_create,
delayless_switch,
physical_tile);
physical_tile,
load_rr_graph);

//Create the actual SOURCE->OPIN, IPIN->SINK edges
uniquify_edges(rr_edges_to_create);
Expand Down Expand Up @@ -2424,17 +2476,6 @@ static void connect_tile_src_sink_to_pins(RRGraphBuilder& rr_graph_builder,
continue;
}
auto pin_type = get_pin_type_from_pin_physical_num(physical_type_ptr, pin_num);
/*int sw_id = -1;
* if (is_primitive || pin_type == RECEIVER) {
* VTR_ASSERT(logical_block != nullptr);
* float primitive_comb_delay = get_pin_primitive_comb_delay(physical_type_ptr,
* logical_block,
* pin_num);
* sw_id = find_create_intra_cluster_sw_arch_idx(arch_sw_inf_map,
* primitive_comb_delay);
* } else {
* sw_id = delayless_switch;
* }*/
if (class_type == DRIVER) {
VTR_ASSERT(pin_type == DRIVER);
rr_edges_to_create.emplace_back(class_rr_node_id, pin_rr_node_id, delayless_switch, false);
Expand All @@ -2454,7 +2495,8 @@ static void connect_src_sink_to_pins(RRGraphBuilder& rr_graph_builder,
const int j,
t_rr_edge_info_set& rr_edges_to_create,
const int delayless_switch,
t_physical_tile_type_ptr physical_type_ptr) {
t_physical_tile_type_ptr physical_type_ptr,
bool switches_remapped) {
for (auto class_num : class_num_vec) {
const auto& pin_list = get_pin_list_from_class_physical_num(physical_type_ptr, class_num);
auto class_type = get_class_type_from_class_physical_num(physical_type_ptr, class_num);
Expand All @@ -2474,11 +2516,11 @@ static void connect_src_sink_to_pins(RRGraphBuilder& rr_graph_builder,
auto pin_type = get_pin_type_from_pin_physical_num(physical_type_ptr, pin_num);
if (class_type == DRIVER) {
VTR_ASSERT(pin_type == DRIVER);
rr_edges_to_create.emplace_back(class_rr_node_id, pin_rr_node_id, delayless_switch, false);
rr_edges_to_create.emplace_back(class_rr_node_id, pin_rr_node_id, delayless_switch, switches_remapped);
} else {
VTR_ASSERT(class_type == RECEIVER);
VTR_ASSERT(pin_type == RECEIVER);
rr_edges_to_create.emplace_back(pin_rr_node_id, class_rr_node_id, delayless_switch, false);
rr_edges_to_create.emplace_back(pin_rr_node_id, class_rr_node_id, delayless_switch, switches_remapped);
}
}
}
Expand Down Expand Up @@ -2682,6 +2724,8 @@ static void build_cluster_internal_edges(RRGraphBuilder& rr_graph_builder,
logical_block,
pb,
nodes_to_collapse,
R_minW_nmos,
R_minW_pmos,
rel_cap,
layer,
i,
Expand Down Expand Up @@ -2714,11 +2758,13 @@ static void add_pb_edges(RRGraphBuilder& rr_graph_builder,
t_logical_block_type_ptr logical_block,
const t_pb* pb,
const t_cluster_pin_chain& nodes_to_collapse,
float R_minW_nmos,
float R_minW_pmos,
int rel_cap,
int layer,
int i,
int j,
bool is_remapped) {
bool switches_remapped) {
auto pin_num_range = get_pb_pins(physical_type,
sub_tile,
logical_block,
Expand Down Expand Up @@ -2772,26 +2818,18 @@ static void add_pb_edges(RRGraphBuilder& rr_graph_builder,
pin_physical_num,
conn_pin_physical_num);

if (is_remapped) {
bool found = false;
if (switches_remapped) {
auto& all_sw_inf = g_vpr_ctx.mutable_device().all_sw_inf;
float delay = g_vpr_ctx.device().all_sw_inf.at(sw_idx).Tdel();
const auto& rr_switches = rr_graph_builder.rr_switch();
for (int sw_id = 0; sw_id < (int)rr_switches.size(); sw_id++) {
const auto& rr_switch = rr_switches[RRSwitchId(sw_id)];
if (rr_switch.intra_tile) {
if (rr_switch.Tdel == delay) {
sw_idx = sw_id;
found = true;
break;
}
}
}
// If the graph is loaded from a file, we expect that all sw types are already listed there since currently, we are not doing any further
// Optimization. If the optimization done when the rr graph file was generated is different from the current optimization, in the case that
// these optimizations create different RR switches, this VTR ASSERT can be removed.
VTR_ASSERT(found);
bool is_new_sw;
std::tie(is_new_sw, sw_idx) = find_create_intra_cluster_sw(rr_graph_builder,
amin1377 marked this conversation as resolved.
Show resolved Hide resolved
all_sw_inf,
R_minW_nmos,
R_minW_pmos,
switches_remapped,
delay);
}
rr_edges_to_create.emplace_back(parent_pin_node_id, conn_pin_node_id, sw_idx, is_remapped);
rr_edges_to_create.emplace_back(parent_pin_node_id, conn_pin_node_id, sw_idx, switches_remapped);
}
}
}
Expand Down Expand Up @@ -2960,22 +2998,6 @@ static void add_chain_node_fan_in_edges(RRGraphBuilder& rr_graph_builder,
is_rr_sw_id,
delay);

amin1377 marked this conversation as resolved.
Show resolved Hide resolved
if (!is_rr_sw_id && is_new_sw) {
// Currently we assume that if rr graph is read from a file, we shouldn't get into this block
VTR_ASSERT(!load_rr_graph);
// The internal edges are added after switch_fanin_remap is initialized; thus, if a new arch_sw is added,
// switch _fanin_remap should be updated.
t_rr_switch_inf rr_sw_inf = create_rr_switch_from_arch_switch(create_internal_arch_sw(delay),
R_minW_nmos,
R_minW_pmos);
auto rr_sw_id = rr_graph_builder.add_rr_switch(rr_sw_inf);
// If rr graph is loaded from a file, switch_fanin_remap is going to be empty
if (!load_rr_graph) {
auto& switch_fanin_remap = g_vpr_ctx.mutable_device().switch_fanin_remap;
switch_fanin_remap.push_back({{UNDEFINED, size_t(rr_sw_id)}});
}
}

rr_edges_to_create.emplace_back(src_pair.first, sink_rr_node_id, sw_id, is_rr_sw_id);
}
}
Expand Down Expand Up @@ -4934,6 +4956,18 @@ static std::pair<bool, int> find_create_intra_cluster_sw(RRGraphBuilder& rr_grap
// If this assumption proven to not be accurate, the implementation needs to be changed.
VTR_ASSERT(arch_sw.fixed_Tdel());

t_rr_switch_inf new_rr_switch_inf = create_rr_switch_from_arch_switch(create_internal_arch_sw(delay),
R_minW_nmos,
R_minW_pmos);
RRSwitchId rr_switch_id = rr_graph.add_rr_switch(new_rr_switch_inf);

/*If the switch found inside the cluster has not seen before and RR graph is not read from a file,
we need to add this switch to switch_fanin_remap data strcutre which is used later to remap switch IDs
from architecture ID to RR graph switch ID. The reason why we don't this when RR graph is read from a file
is that in that case, the switch IDs of edges are alreay RR graph switch IDs. */
auto& switch_fanin_remap = g_vpr_ctx.mutable_device().switch_fanin_remap;
switch_fanin_remap.push_back({{UNDEFINED, size_t(rr_switch_id)}});

return std::make_pair(true, new_key_num);
} else {
return std::make_pair(false, find_res->first);
Expand Down
Loading