Skip to content

Commit b5ae26b

Browse files
authored
Merge pull request verilog-to-routing#6 from litghost/cluster_fix
Add check to ensure that clustering uses consistent modes.
2 parents 1169f2e + 81bd8ea commit b5ae26b

File tree

4 files changed

+129
-15
lines changed

4 files changed

+129
-15
lines changed

vpr/src/pack/cluster_router.cpp

Lines changed: 93 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ using namespace std;
3131
#include "atom_netlist.h"
3232
#include "vpr_utils.h"
3333
#include "pack_types.h"
34+
#include "pb_type_graph.h"
3435
#include "lb_type_rr_graph.h"
3536
#include "cluster_router.h"
3637

@@ -154,7 +155,8 @@ static bool route_has_conflict(t_lb_trace *rt, t_lb_router_data *router_data) {
154155

155156
int cur_mode = -1;
156157
for (unsigned int i = 0; i < rt->next_nodes.size(); i++) {
157-
int new_mode = get_lb_type_rr_graph_edge_mode(lb_type_graph, rt->current_node, rt->next_nodes[i].current_node);
158+
int new_mode = get_lb_type_rr_graph_edge_mode(lb_type_graph,
159+
rt->current_node, rt->next_nodes[i].current_node);
158160
if (cur_mode != -1 && cur_mode != new_mode) {
159161
return true;
160162
}
@@ -167,6 +169,86 @@ static bool route_has_conflict(t_lb_trace *rt, t_lb_router_data *router_data) {
167169
return false;
168170
}
169171

172+
// Check one edge for mode conflict.
173+
static bool check_edge_for_route_conflicts(
174+
std::unordered_map<const t_pb_graph_node *, const t_mode *> *mode_map,
175+
const t_pb_graph_pin *driver_pin, const t_pb_graph_pin *pin) {
176+
if(driver_pin == nullptr) {
177+
return false;
178+
}
179+
180+
// Only check pins that are OUT_PORTs.
181+
if(pin == nullptr || pin->port == nullptr || pin->port->type != OUT_PORT) {
182+
return false;
183+
}
184+
VTR_ASSERT(!pin->port->is_clock);
185+
186+
auto *pb_graph_node = pin->parent_node;
187+
VTR_ASSERT(pb_graph_node->pb_type == pin->port->parent_pb_type);
188+
189+
const t_pb_graph_edge *edge = get_edge_between_pins(driver_pin, pin);
190+
VTR_ASSERT(edge != nullptr);
191+
192+
auto mode_of_edge = edge->interconnect->parent_mode_index;
193+
auto *mode = &pb_graph_node->pb_type->modes[mode_of_edge];
194+
195+
auto result = mode_map->insert(std::make_pair(
196+
pb_graph_node, mode));
197+
if(!result.second) {
198+
if(result.first->second != mode) {
199+
std::cout << vtr::string_fmt(
200+
"Differing modes for block. Got %s previously and %s for interconnect %s.",
201+
mode->name, result.first->second->name,
202+
edge->interconnect->name) << std::endl;
203+
return true;
204+
}
205+
}
206+
207+
return false;
208+
}
209+
210+
// Walk one net and either add the pb_type modes to mode_map, or if they already
211+
// exist, ensure that the edges in the net are not in conflict.
212+
static bool check_net_for_route_conflicts(
213+
std::unordered_map<const t_pb_graph_node *, const t_mode *> *mode_map,
214+
const t_lb_trace *driver, const t_lb_router_data *router_data) {
215+
VTR_ASSERT(driver != nullptr);
216+
217+
vector <t_lb_type_rr_node> & lb_type_graph = *router_data->lb_type_graph;
218+
auto &driver_node = lb_type_graph[driver->current_node];
219+
auto *driver_pin = driver_node.pb_graph_pin;
220+
221+
// Check each driver_pin -> pin edge.
222+
if(driver_pin != nullptr) {
223+
for (const auto &next_node : driver->next_nodes) {
224+
auto &node = lb_type_graph[next_node.current_node];
225+
if(check_edge_for_route_conflicts(mode_map, driver_pin, node.pb_graph_pin)) {
226+
return true;
227+
}
228+
}
229+
}
230+
231+
// Walk the rest of the net.
232+
for (const auto &next_node : driver->next_nodes) {
233+
if (check_net_for_route_conflicts(mode_map, &next_node, router_data)) {
234+
return true;
235+
}
236+
}
237+
238+
return false;
239+
}
240+
241+
// Walk nets and check if each pb_type has the same mode.
242+
static bool check_for_route_conflicts(const vector <t_intra_lb_net> &lb_nets, const t_lb_router_data *router_data) {
243+
std::unordered_map<const t_pb_graph_node *, const t_mode *> mode_map;
244+
for(const auto &net : lb_nets) {
245+
if(check_net_for_route_conflicts(&mode_map, net.rt_tree, router_data)) {
246+
return true;
247+
}
248+
}
249+
250+
return false;
251+
}
170252

171253
/*****************************************************************************************
172254
* Routing Functions
@@ -389,6 +471,16 @@ bool try_intra_lb_route(t_lb_router_data *router_data,
389471

390472
commit_remove_rt(lb_nets[idx].rt_tree, router_data, RT_COMMIT);
391473
}
474+
475+
if(is_impossible == false) {
476+
// We've checked that each net has no mode conflicts within the
477+
// net via route_has_conflict, however this is in insufficient.
478+
//
479+
// All nets from each pb_type must not have a mode conflict between
480+
// the nets.
481+
is_impossible = check_for_route_conflicts(lb_nets, router_data);
482+
}
483+
392484
if(is_impossible == false) {
393485
is_routed = is_route_success(router_data);
394486
} else {

vpr/src/pack/output_clustering.cpp

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ using namespace std;
2323
#include "atom_netlist.h"
2424
#include "pack_types.h"
2525
#include "cluster_router.h"
26+
#include "pb_type_graph.h"
2627
#include "output_clustering.h"
2728
#include "read_xml_arch_file.h"
2829
#include "vpr_utils.h"
@@ -209,22 +210,20 @@ static void clustering_xml_open_block(pugi::xml_node parent_node, t_type_ptr typ
209210
if (pb_type->ports[i].type == OUT_PORT) {
210211
VTR_ASSERT(!pb_type->ports[i].is_clock);
211212
for (j = 0; j < pb_type->ports[i].num_pins; j++) {
212-
node_index = pb_graph_node->output_pins[port_index][j].pin_count_in_cluster;
213+
const t_pb_graph_pin * pin = &pb_graph_node->output_pins[port_index][j];
214+
node_index = pin->pin_count_in_cluster;
213215
if (pb_type->num_modes > 0 && pb_route[node_index].atom_net_id) {
214216
prev_node = pb_route[node_index].driver_pb_pin_id;
215-
t_pb_graph_pin *prev_pin = pb_graph_pin_lookup_from_index_by_type[type->index][prev_node];
216-
for(prev_edge = 0; prev_edge < prev_pin->num_output_edges; prev_edge++) {
217-
VTR_ASSERT(prev_pin->output_edges[prev_edge]->num_output_pins == 1);
218-
if(prev_pin->output_edges[prev_edge]->output_pins[0]->pin_count_in_cluster == node_index) {
219-
break;
220-
}
221-
}
222-
VTR_ASSERT(prev_edge < prev_pin->num_output_edges);
223-
mode_of_edge = prev_pin->output_edges[prev_edge]->interconnect->parent_mode_index;
217+
const t_pb_graph_pin *prev_pin = pb_graph_pin_lookup_from_index_by_type[type->index][prev_node];
218+
const t_pb_graph_edge *edge = get_edge_between_pins(prev_pin, pin);
219+
220+
mode_of_edge = edge->interconnect->parent_mode_index;
224221
if(mode != nullptr && &pb_type->modes[mode_of_edge] != mode) {
225222
vpr_throw(VPR_ERROR_PACK, __FILE__, __LINE__,
226-
"Differing modes for block. Got %s previously and %s for edge %d.",
227-
mode->name, pb_type->modes[mode_of_edge].name, port_index);
223+
"Differing modes for block. Got %s previously and %s for edge %d (interconnect %s).",
224+
mode->name, pb_type->modes[mode_of_edge].name,
225+
port_index,
226+
prev_pin->output_edges[prev_edge]->interconnect->name);
228227
}
229228
VTR_ASSERT(mode == nullptr || &pb_type->modes[mode_of_edge] == mode);
230229
mode = &pb_type->modes[mode_of_edge];
@@ -313,8 +312,7 @@ static void clustering_xml_open_block(pugi::xml_node parent_node, t_type_ptr typ
313312
is_used = false;
314313
for (k = 0; k < child_pb_type->num_ports && !is_used; k++) {
315314
if (child_pb_type->ports[k].type == OUT_PORT) {
316-
for (m = 0; m < child_pb_type->ports[k].num_pins;
317-
m++) {
315+
for (m = 0; m < child_pb_type->ports[k].num_pins; m++) {
318316
node_index =
319317
pb_graph_node->child_pb_graph_nodes[mode_of_edge][i][j].output_pins[port_index][m].pin_count_in_cluster;
320318
if (pb_route[node_index].atom_net_id) {

vpr/src/pack/pb_type_graph.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1784,3 +1784,20 @@ static bool check_input_pins_equivalence(const t_pb_graph_pin* cur_pin,
17841784
return pins_equivalent;
17851785
}
17861786

1787+
const t_pb_graph_edge *get_edge_between_pins(const t_pb_graph_pin *driver_pin, const t_pb_graph_pin *pin) {
1788+
if(driver_pin == nullptr || pin == nullptr) {
1789+
return nullptr;
1790+
}
1791+
1792+
auto node_index = pin->pin_count_in_cluster;
1793+
for(int iedge = 0; iedge < driver_pin->num_output_edges; iedge++) {
1794+
auto *edge = driver_pin->output_edges[iedge];
1795+
VTR_ASSERT(edge->num_output_pins == 1);
1796+
1797+
if(edge->output_pins[0]->pin_count_in_cluster == node_index) {
1798+
return edge;
1799+
}
1800+
}
1801+
1802+
return nullptr;
1803+
}

vpr/src/pack/pb_type_graph.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,13 @@ struct t_pb_graph_edge_comparator{
99
t_pb_graph_edge* parent_edge;
1010
};
1111

12+
// Find the edge between driver_pin and pin.
13+
//
14+
// Returns nullptr on invalid input or error.
15+
const t_pb_graph_edge *get_edge_between_pins(
16+
const t_pb_graph_pin *driver_pin,
17+
const t_pb_graph_pin *pin);
18+
1219
void alloc_and_load_all_pb_graphs(bool load_power_structures);
1320
void echo_pb_graph(char * filename);
1421
void free_pb_graph_edges();

0 commit comments

Comments
 (0)