1
- #include < cstdio>
1
+
2
+ #include " check_route.h"
2
3
3
4
#include " route_common.h"
4
5
#include " vtr_assert.h"
11
12
12
13
#include " globals.h"
13
14
#include " route_export.h"
14
- # include " check_route.h "
15
+
15
16
#include " rr_graph.h"
16
17
#include " check_rr_graph.h"
17
18
#include " read_xml_arch_file.h"
@@ -39,11 +40,32 @@ static void check_locally_used_clb_opins(const t_clb_opins_used& clb_opins_used_
39
40
enum e_route_type route_type,
40
41
bool is_flat);
41
42
43
+ /* *
44
+ * Checks that all non-configurable edges are in a legal configuration.
45
+ * @param net_list The netlist whose routing is to be checked.
46
+ * @param is_flat True if flat routing is enabled; otherwise false.
47
+ */
42
48
static void check_all_non_configurable_edges (const Netlist<>& net_list, bool is_flat);
49
+
50
+ /* *
51
+ * @brief Checks that the specified routing is legal with respect to non-configurable edges.
52
+ * For routing to be valid, if any non-configurable edge is used, all nodes in the same set
53
+ * and the required connecting edges in the set must also be used.
54
+ *
55
+ * @param net_list A reference to the netlist.
56
+ * @param net The net id for which the check is done.
57
+ * @param non_configurable_rr_sets Node and edge sets that constitute non-configurable RR sets.
58
+ * @param rrnode_set_id Specifies which RR sets each RR node is part of. These indices can be used to
59
+ * access elements of node_sets and edge_sets in non_configurable_rr_sets.
60
+ * @param is_flat Indicates whether flat routing is enabled.
61
+ * @return True if check is done successfully; otherwise false.
62
+ */
43
63
static bool check_non_configurable_edges (const Netlist<>& net_list,
44
64
ParentNetId net,
45
65
const t_non_configurable_rr_sets& non_configurable_rr_sets,
66
+ const vtr::vector<RRNodeId, int >& rrnode_set_id,
46
67
bool is_flat);
68
+
47
69
static void check_net_for_stubs (const Netlist<>& net_list,
48
70
ParentNetId net,
49
71
bool is_flat);
@@ -65,13 +87,9 @@ void check_route(const Netlist<>& net_list,
65
87
return ;
66
88
}
67
89
68
- int max_pins;
69
- unsigned int ipin;
70
- bool valid, connects;
71
-
72
- auto & device_ctx = g_vpr_ctx.device ();
90
+ const auto & device_ctx = g_vpr_ctx.device ();
73
91
const auto & rr_graph = device_ctx.rr_graph ;
74
- auto & route_ctx = g_vpr_ctx.routing ();
92
+ const auto & route_ctx = g_vpr_ctx.routing ();
75
93
76
94
const size_t num_switches = rr_graph.num_rr_switches ();
77
95
@@ -83,7 +101,7 @@ void check_route(const Netlist<>& net_list,
83
101
* is a successful routing, but I want to double check it here. */
84
102
85
103
recompute_occupancy_from_scratch (net_list, is_flat);
86
- valid = feasible_routing ();
104
+ const bool valid = feasible_routing ();
87
105
if (valid == false ) {
88
106
VPR_ERROR (VPR_ERROR_ROUTE,
89
107
" Error in check_route -- routing resources are overused.\n " );
@@ -95,7 +113,7 @@ void check_route(const Netlist<>& net_list,
95
113
is_flat);
96
114
}
97
115
98
- max_pins = 0 ;
116
+ int max_pins = 0 ;
99
117
for (auto net_id : net_list.nets ())
100
118
max_pins = std::max (max_pins, (int )net_list.net_pins (net_id).size ());
101
119
@@ -129,7 +147,7 @@ void check_route(const Netlist<>& net_list,
129
147
check_switch (rt_node, num_switches);
130
148
131
149
if (rt_node.parent ()) {
132
- connects = check_adjacent (rt_node.parent ()->inode , rt_node.inode , is_flat);
150
+ bool connects = check_adjacent (rt_node.parent ()->inode , rt_node.inode , is_flat);
133
151
if (!connects) {
134
152
VPR_ERROR (VPR_ERROR_ROUTE,
135
153
" in check_route: found non-adjacent segments in traceback while checking net %d:\n "
@@ -154,7 +172,7 @@ void check_route(const Netlist<>& net_list,
154
172
num_sinks, net_list.net_sinks (net_id).size ());
155
173
}
156
174
157
- for (ipin = 0 ; ipin < net_list.net_pins (net_id).size (); ipin++) {
175
+ for (size_t ipin = 0 ; ipin < net_list.net_pins (net_id).size (); ipin++) {
158
176
if (pin_done[ipin] == false ) {
159
177
VPR_FATAL_ERROR (VPR_ERROR_ROUTE,
160
178
" in check_route: net %zu does not connect to pin %d.\n " , size_t (net_id), ipin);
@@ -194,7 +212,7 @@ static void check_sink(const Netlist<>& net_list,
194
212
inode, net_list.net_name (net_id).c_str (), size_t (net_id));
195
213
}
196
214
197
- VTR_ASSERT (!pin_done[net_pin_index]); /* Should not have found a routed cnnection to it before */
215
+ VTR_ASSERT (!pin_done[net_pin_index]); /* Should not have found a routed connection to it before */
198
216
pin_done[net_pin_index] = true ;
199
217
}
200
218
@@ -595,43 +613,71 @@ static void check_node_and_range(RRNodeId inode,
595
613
is_flat);
596
614
}
597
615
598
- // Checks that all non-configurable edges are in a legal configuration
599
- // This check is slow, so it has been moved out of check_route()
600
616
static void check_all_non_configurable_edges (const Netlist<>& net_list, bool is_flat) {
617
+ const auto & rr_graph = g_vpr_ctx.device ().rr_graph ;
618
+
601
619
vtr::ScopedStartFinishTimer timer (" Checking to ensure non-configurable edges are legal" );
602
- auto non_configurable_rr_sets = identify_non_configurable_rr_sets ();
620
+ const t_non_configurable_rr_sets non_configurable_rr_sets = identify_non_configurable_rr_sets ();
621
+
622
+ // Specifies which RR set each node is part of.
623
+ vtr::vector<RRNodeId, int > rrnode_set_ids (rr_graph.num_nodes (), -1 );
624
+
625
+ const size_t num_non_cfg_rr_sets = non_configurable_rr_sets.node_sets .size ();
626
+
627
+ // Populate rrnode_set_ids
628
+ for (size_t non_cfg_rr_set_id = 0 ; non_cfg_rr_set_id < num_non_cfg_rr_sets; non_cfg_rr_set_id++) {
629
+ const std::set<RRNodeId>& node_set = non_configurable_rr_sets.node_sets [non_cfg_rr_set_id];
630
+ for (const RRNodeId node_id : node_set) {
631
+ VTR_ASSERT_SAFE (rrnode_set_ids[node_id] == -1 );
632
+ rrnode_set_ids[node_id] = (int )non_cfg_rr_set_id;
633
+ }
634
+ }
603
635
604
636
for (auto net_id : net_list.nets ()) {
605
637
check_non_configurable_edges (net_list,
606
638
net_id,
607
639
non_configurable_rr_sets,
640
+ rrnode_set_ids,
608
641
is_flat);
609
642
}
610
643
}
611
644
612
- // Checks that the specified routing is legal with respect to non-configurable edges
613
- //
614
- // For routing to be legal if *any* non-configurable edge is used, so must *all*
615
- // other non-configurable edges in the same set
616
645
static bool check_non_configurable_edges (const Netlist<>& net_list,
617
646
ParentNetId net,
618
647
const t_non_configurable_rr_sets& non_configurable_rr_sets,
648
+ const vtr::vector<RRNodeId, int >& rrnode_set_id,
619
649
bool is_flat) {
620
650
const auto & device_ctx = g_vpr_ctx.device ();
621
- auto & route_ctx = g_vpr_ctx.mutable_routing ();
651
+ const auto & route_ctx = g_vpr_ctx.routing ();
622
652
623
653
if (!route_ctx.route_trees [net]) // no routing
624
654
return true ;
625
655
626
- // Collect all the edges used by this net's routing
656
+ // Collect all the nodes, edges, and non-configurable RR set ids used by this net's routing
627
657
std::set<t_node_edge> routing_edges;
628
658
std::set<RRNodeId> routing_nodes;
629
- for (auto & rt_node : route_ctx.route_trees [net].value ().all_nodes ()) {
659
+ std::set<int > routing_non_configurable_rr_set_ids;
660
+ for (const RouteTreeNode& rt_node : route_ctx.route_trees [net].value ().all_nodes ()) {
630
661
routing_nodes.insert (rt_node.inode );
631
662
if (!rt_node.parent ())
632
663
continue ;
633
664
t_node_edge edge = {rt_node.parent ()->inode , rt_node.inode };
634
665
routing_edges.insert (edge);
666
+
667
+ if (rrnode_set_id[rt_node.inode ] >= 0 ) { // The node belongs to a non-configurable RR set
668
+ routing_non_configurable_rr_set_ids.insert (rrnode_set_id[rt_node.inode ]);
669
+ }
670
+ }
671
+
672
+ // Copy used non-configurable RR sets
673
+ // This is done to check legality only for used non-configurable RR sets. If a non-configurable RR set
674
+ // is not used by a net's routing, it cannot violate the requirements of using that non-configurable RR set.
675
+ t_non_configurable_rr_sets used_non_configurable_rr_sets;
676
+ used_non_configurable_rr_sets.node_sets .reserve (routing_non_configurable_rr_set_ids.size ());
677
+ used_non_configurable_rr_sets.edge_sets .reserve (routing_non_configurable_rr_set_ids.size ());
678
+ for (const int set_idx : routing_non_configurable_rr_set_ids) {
679
+ used_non_configurable_rr_sets.node_sets .emplace_back (non_configurable_rr_sets.node_sets [set_idx]);
680
+ used_non_configurable_rr_sets.edge_sets .emplace_back (non_configurable_rr_sets.edge_sets [set_idx]);
635
681
}
636
682
637
683
// We need to perform two types of checks:
@@ -640,13 +686,13 @@ static bool check_non_configurable_edges(const Netlist<>& net_list,
640
686
// 2) That all (required) non-configurable edges are used
641
687
//
642
688
// We need to check (2) in addition to (1) to ensure that (1) did not pass
643
- // because the nodes 'happend ' to be connected together by configurable
689
+ // because the nodes 'happened ' to be connected together by configurable
644
690
// routing (to be legal, by definition, they must be connected by
645
691
// non-configurable routing).
646
692
647
- // Check that all nodes in each non-configurable set are full included if any element
693
+ // Check that all nodes in each non-configurable set are fully included if any element
648
694
// within a set is used by the routing
649
- for (const auto & rr_nodes : non_configurable_rr_sets .node_sets ) {
695
+ for (const auto & rr_nodes : used_non_configurable_rr_sets .node_sets ) {
650
696
// Compute the intersection of the routing and current non-configurable nodes set
651
697
std::vector<RRNodeId> intersection;
652
698
std::set_intersection (routing_nodes.begin (), routing_nodes.end (),
@@ -668,7 +714,7 @@ static bool check_non_configurable_edges(const Netlist<>& net_list,
668
714
routing_nodes.begin (), routing_nodes.end (),
669
715
std::back_inserter (difference));
670
716
671
- VTR_ASSERT (difference.size () > 0 );
717
+ VTR_ASSERT (! difference.empty () );
672
718
std::string msg = vtr::string_fmt (
673
719
" Illegal routing for net '%s' (#%zu) some "
674
720
" required non-configurably connected nodes are missing:\n " ,
@@ -685,7 +731,7 @@ static bool check_non_configurable_edges(const Netlist<>& net_list,
685
731
686
732
// Check that any sets of non-configurable RR graph edges are fully included
687
733
// in the routing, if any of a set's edges are used
688
- for (const auto & rr_edges : non_configurable_rr_sets .edge_sets ) {
734
+ for (const auto & rr_edges : used_non_configurable_rr_sets .edge_sets ) {
689
735
// Compute the intersection of the routing and current non-configurable edge set
690
736
std::vector<t_node_edge> intersection;
691
737
std::set_intersection (routing_edges.begin (), routing_edges.end (),
@@ -698,7 +744,7 @@ static bool check_non_configurable_edges(const Netlist<>& net_list,
698
744
// Since at least one non-configurable edge is used, to be legal
699
745
// the full set of non-configurably connected edges must be used.
700
746
//
701
- // This is somewhat complicted by the fact that non-configurable edges
747
+ // This is somewhat complicated by the fact that non-configurable edges
702
748
// are sometimes bi-directional (e.g. electrical shorts) and so appear
703
749
// in rr_edges twice (once forward, once backward). Only one of the
704
750
// paired edges need appear to be correct.
@@ -791,9 +837,9 @@ class StubFinder {
791
837
std::set<int > stub_nodes_;
792
838
};
793
839
794
- // Cheks for stubs in a net's routing.
840
+ // Checks for stubs in a net's routing.
795
841
//
796
- // Stubs (routing branches which don't connect to SINKs) serve no purpose, and only chew up wiring unecessarily .
842
+ // Stubs (routing branches which don't connect to SINKs) serve no purpose, and only chew up wiring unnecessarily .
797
843
// The only exception are stubs required by non-configurable switches (e.g. shorts).
798
844
//
799
845
// We treat any configurable stubs as an error.
0 commit comments