@@ -31,6 +31,7 @@ using namespace std;
31
31
#include " atom_netlist.h"
32
32
#include " vpr_utils.h"
33
33
#include " pack_types.h"
34
+ #include " pb_type_graph.h"
34
35
#include " lb_type_rr_graph.h"
35
36
#include " cluster_router.h"
36
37
@@ -154,7 +155,8 @@ static bool route_has_conflict(t_lb_trace *rt, t_lb_router_data *router_data) {
154
155
155
156
int cur_mode = -1 ;
156
157
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 );
158
160
if (cur_mode != -1 && cur_mode != new_mode) {
159
161
return true ;
160
162
}
@@ -167,6 +169,86 @@ static bool route_has_conflict(t_lb_trace *rt, t_lb_router_data *router_data) {
167
169
return false ;
168
170
}
169
171
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
+ }
170
252
171
253
/* ****************************************************************************************
172
254
* Routing Functions
@@ -389,6 +471,16 @@ bool try_intra_lb_route(t_lb_router_data *router_data,
389
471
390
472
commit_remove_rt (lb_nets[idx].rt_tree , router_data, RT_COMMIT);
391
473
}
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
+
392
484
if (is_impossible == false ) {
393
485
is_routed = is_route_success (router_data);
394
486
} else {
0 commit comments