Skip to content

Commit 7829f79

Browse files
Merge pull request #2839 from verilog-to-routing/temp_faster_check_non_configurable_edges
Faster check_non_configurable_edges
2 parents b4f358a + 0e464f7 commit 7829f79

File tree

4 files changed

+101
-47
lines changed

4 files changed

+101
-47
lines changed

vpr/src/base/vpr_types.h

+14-6
Original file line numberDiff line numberDiff line change
@@ -1637,7 +1637,7 @@ typedef t_routing_status<AtomNetId> t_atom_net_routing_status;
16371637

16381638
/** Edge between two RRNodes */
16391639
struct t_node_edge {
1640-
t_node_edge(RRNodeId fnode, RRNodeId tnode)
1640+
t_node_edge(RRNodeId fnode, RRNodeId tnode) noexcept
16411641
: from_node(fnode)
16421642
, to_node(tnode) {}
16431643

@@ -1650,10 +1650,18 @@ struct t_node_edge {
16501650
}
16511651
};
16521652

1653-
///@brief Non-configurably connected nodes and edges in the RR graph
1653+
/**
1654+
* @brief Groups of non-configurably connected nodes and edges in the RR graph.
1655+
* @note Each group is represented by a node set and an edge set, stored at the same index.
1656+
*
1657+
* For example, in an architecture with L-shaped wires formed by an x- and y-directed segment
1658+
* connected by an electrical short, each L-shaped wire corresponds to a new group. The group's
1659+
* index provides access to its node set (containing two RRNodeIds) and edge set (containing two
1660+
* directed edge in opposite directions).
1661+
*/
16541662
struct t_non_configurable_rr_sets {
1655-
std::set<std::set<RRNodeId>> node_sets;
1656-
std::set<std::set<t_node_edge>> edge_sets;
1663+
std::vector<std::set<RRNodeId>> node_sets;
1664+
std::vector<std::set<t_node_edge>> edge_sets;
16571665
};
16581666

16591667
///@brief Power estimation options
@@ -1665,11 +1673,11 @@ struct t_power_opts {
16651673
* @param max= Maximum channel width between x_max and y_max.
16661674
* @param x_min= Minimum channel width of horizontal channels. Initialized when init_chan() is invoked in rr_graph2.cpp
16671675
* @param y_min= Same as above but for vertical channels.
1668-
* @param x_max= Maximum channel width of horiozntal channels. Initialized when init_chan() is invoked in rr_graph2.cpp
1676+
* @param x_max= Maximum channel width of horizontal channels. Initialized when init_chan() is invoked in rr_graph2.cpp
16691677
* @param y_max= Same as above but for vertical channels.
16701678
* @param x_list= Stores the channel width of all horizontal channels and thus goes from [0..grid.height()]
16711679
* (imagine a 2D Cartesian grid with horizontal lines starting at every grid point on a line parallel to the y-axis)
1672-
* @param y_list= Stores the channel width of all verical channels and thus goes from [0..grid.width()]
1680+
* @param y_list= Stores the channel width of all vertical channels and thus goes from [0..grid.width()]
16731681
* (imagine a 2D Cartesian grid with vertical lines starting at every grid point on a line parallel to the x-axis)
16741682
*/
16751683

vpr/src/route/check_route.cpp

+77-31
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
#include <cstdio>
1+
2+
#include "check_route.h"
23

34
#include "route_common.h"
45
#include "vtr_assert.h"
@@ -11,7 +12,7 @@
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+
*/
4248
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+
*/
4363
static 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+
4769
static 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()
600616
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+
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
616645
static 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.

vpr/src/route/edge_groups.cpp

+5-5
Original file line numberDiff line numberDiff line change
@@ -52,14 +52,14 @@ t_non_configurable_rr_sets EdgeGroups::output_sets() {
5252
std::set<t_node_edge> edge_set;
5353
std::set<RRNodeId> node_set(nodes.begin(), nodes.end());
5454

55-
for (const auto& src : node_set) {
56-
for (const auto& dest : graph_[src].edges) {
57-
edge_set.emplace(t_node_edge(src, dest));
55+
for (const RRNodeId src : node_set) {
56+
for (const RRNodeId dest : graph_[src].edges) {
57+
edge_set.emplace(src, dest);
5858
}
5959
}
6060

61-
sets.node_sets.emplace(std::move(node_set));
62-
sets.edge_sets.emplace(std::move(edge_set));
61+
sets.node_sets.emplace_back(std::move(node_set));
62+
sets.edge_sets.emplace_back(std::move(edge_set));
6363
}
6464

6565
return sets;

vpr/test/test_edge_groups.cpp

+5-5
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,12 @@ TEST_CASE("edge_groups_create_sets", "[vpr]") {
1919
// Build chains from the given connected sets
2020
int max_node_id = 0;
2121
std::vector<std::pair<int, int>> edges;
22-
for (auto set : connected_sets) {
22+
for (const auto& set : connected_sets) {
2323
int last = *set.cbegin();
2424
std::for_each(std::next(set.cbegin()),
2525
set.cend(),
2626
[&](int node) {
27-
edges.push_back(std::make_pair(last, node));
27+
edges.emplace_back(last, node);
2828
last = node;
2929
max_node_id = std::max(max_node_id, node);
3030
});
@@ -36,7 +36,7 @@ TEST_CASE("edge_groups_create_sets", "[vpr]") {
3636
// Initialize nodes to [0, 1, ..., max_node_id]
3737
std::iota(nodes.begin(), nodes.end(), 0);
3838

39-
// Create a Mersenne Twister psuedo-random number generator with seed 1
39+
// Create a Mersenne Twister pseudo-random number generator with seed 1
4040
std::mt19937 g(1);
4141

4242
// Run the test many times, the PRNG will give differently shuffled inputs
@@ -66,12 +66,12 @@ TEST_CASE("edge_groups_create_sets", "[vpr]") {
6666
t_non_configurable_rr_sets sets = groups.output_sets();
6767

6868
// Check for the expected sets
69-
for (auto set : connected_sets) {
69+
for (const auto& set : connected_sets) {
7070
std::set<RRNodeId> random_set;
7171
for (auto elem : set) {
7272
random_set.insert(RRNodeId(random_nodes[elem]));
7373
}
74-
REQUIRE(sets.node_sets.find(random_set) != sets.node_sets.end());
74+
REQUIRE(std::find(sets.node_sets.begin(), sets.node_sets.end(), random_set) != sets.node_sets.end());
7575
}
7676
}
7777
}

0 commit comments

Comments
 (0)