1- #include < cstdio>
1+
2+ #include " check_route.h"
23
34#include " route_common.h"
45#include " vtr_assert.h"
1112
1213#include " globals.h"
1314#include " route_export.h"
14- # include " check_route.h "
15+
1516#include " rr_graph.h"
1617#include " check_rr_graph.h"
1718#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_
3940 enum e_route_type route_type,
4041 bool is_flat);
4142
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+ */
4248static 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+ */
4363static bool check_non_configurable_edges (const Netlist<>& net_list,
4464 ParentNetId net,
4565 const t_non_configurable_rr_sets& non_configurable_rr_sets,
66+ const vtr::vector<RRNodeId, int >& rrnode_set_id,
4667 bool is_flat);
68+
4769static void check_net_for_stubs (const Netlist<>& net_list,
4870 ParentNetId net,
4971 bool is_flat);
@@ -65,13 +87,9 @@ void check_route(const Netlist<>& net_list,
6587 return ;
6688 }
6789
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 ();
7391 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 ();
7593
7694 const size_t num_switches = rr_graph.num_rr_switches ();
7795
@@ -83,7 +101,7 @@ void check_route(const Netlist<>& net_list,
83101 * is a successful routing, but I want to double check it here. */
84102
85103 recompute_occupancy_from_scratch (net_list, is_flat);
86- valid = feasible_routing ();
104+ const bool valid = feasible_routing ();
87105 if (valid == false ) {
88106 VPR_ERROR (VPR_ERROR_ROUTE,
89107 " Error in check_route -- routing resources are overused.\n " );
@@ -95,7 +113,7 @@ void check_route(const Netlist<>& net_list,
95113 is_flat);
96114 }
97115
98- max_pins = 0 ;
116+ int max_pins = 0 ;
99117 for (auto net_id : net_list.nets ())
100118 max_pins = std::max (max_pins, (int )net_list.net_pins (net_id).size ());
101119
@@ -129,7 +147,7 @@ void check_route(const Netlist<>& net_list,
129147 check_switch (rt_node, num_switches);
130148
131149 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);
133151 if (!connects) {
134152 VPR_ERROR (VPR_ERROR_ROUTE,
135153 " 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,
154172 num_sinks, net_list.net_sinks (net_id).size ());
155173 }
156174
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++) {
158176 if (pin_done[ipin] == false ) {
159177 VPR_FATAL_ERROR (VPR_ERROR_ROUTE,
160178 " 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,
194212 inode, net_list.net_name (net_id).c_str (), size_t (net_id));
195213 }
196214
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 */
198216 pin_done[net_pin_index] = true ;
199217}
200218
@@ -595,43 +613,71 @@ static void check_node_and_range(RRNodeId inode,
595613 is_flat);
596614}
597615
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()
600616static 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+
601619 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+ }
603635
604636 for (auto net_id : net_list.nets ()) {
605637 check_non_configurable_edges (net_list,
606638 net_id,
607639 non_configurable_rr_sets,
640+ rrnode_set_ids,
608641 is_flat);
609642 }
610643}
611644
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
616645static bool check_non_configurable_edges (const Netlist<>& net_list,
617646 ParentNetId net,
618647 const t_non_configurable_rr_sets& non_configurable_rr_sets,
648+ const vtr::vector<RRNodeId, int >& rrnode_set_id,
619649 bool is_flat) {
620650 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 ();
622652
623653 if (!route_ctx.route_trees [net]) // no routing
624654 return true ;
625655
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
627657 std::set<t_node_edge> routing_edges;
628658 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 ()) {
630661 routing_nodes.insert (rt_node.inode );
631662 if (!rt_node.parent ())
632663 continue ;
633664 t_node_edge edge = {rt_node.parent ()->inode , rt_node.inode };
634665 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]);
635681 }
636682
637683 // We need to perform two types of checks:
@@ -640,13 +686,13 @@ static bool check_non_configurable_edges(const Netlist<>& net_list,
640686 // 2) That all (required) non-configurable edges are used
641687 //
642688 // 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
644690 // routing (to be legal, by definition, they must be connected by
645691 // non-configurable routing).
646692
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
648694 // 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 ) {
650696 // Compute the intersection of the routing and current non-configurable nodes set
651697 std::vector<RRNodeId> intersection;
652698 std::set_intersection (routing_nodes.begin (), routing_nodes.end (),
@@ -668,7 +714,7 @@ static bool check_non_configurable_edges(const Netlist<>& net_list,
668714 routing_nodes.begin (), routing_nodes.end (),
669715 std::back_inserter (difference));
670716
671- VTR_ASSERT (difference.size () > 0 );
717+ VTR_ASSERT (! difference.empty () );
672718 std::string msg = vtr::string_fmt (
673719 " Illegal routing for net '%s' (#%zu) some "
674720 " required non-configurably connected nodes are missing:\n " ,
@@ -685,7 +731,7 @@ static bool check_non_configurable_edges(const Netlist<>& net_list,
685731
686732 // Check that any sets of non-configurable RR graph edges are fully included
687733 // 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 ) {
689735 // Compute the intersection of the routing and current non-configurable edge set
690736 std::vector<t_node_edge> intersection;
691737 std::set_intersection (routing_edges.begin (), routing_edges.end (),
@@ -698,7 +744,7 @@ static bool check_non_configurable_edges(const Netlist<>& net_list,
698744 // Since at least one non-configurable edge is used, to be legal
699745 // the full set of non-configurably connected edges must be used.
700746 //
701- // This is somewhat complicted by the fact that non-configurable edges
747+ // This is somewhat complicated by the fact that non-configurable edges
702748 // are sometimes bi-directional (e.g. electrical shorts) and so appear
703749 // in rr_edges twice (once forward, once backward). Only one of the
704750 // paired edges need appear to be correct.
@@ -791,9 +837,9 @@ class StubFinder {
791837 std::set<int > stub_nodes_;
792838};
793839
794- // Cheks for stubs in a net's routing.
840+ // Checks for stubs in a net's routing.
795841//
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 .
797843// The only exception are stubs required by non-configurable switches (e.g. shorts).
798844//
799845// We treat any configurable stubs as an error.
0 commit comments