Skip to content

Commit 71064cb

Browse files
Merge branch 'noc_turn_model_routing' into noc_pack_part
2 parents c74ed3b + 023239a commit 71064cb

File tree

74 files changed

+8676
-553
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

74 files changed

+8676
-553
lines changed

libs/libvtrutil/src/vtr_util.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ std::string string_fmt(const char* fmt, ...) {
125125

126126
///@brief Returns a std::string formatted using a printf-style format string taking an explicit va_list
127127
std::string vstring_fmt(const char* fmt, va_list args) {
128-
// We need to copy the args so we don't change them before the true formating
128+
// We need to copy the args so we don't change them before the true formatting
129129
va_list va_args_copy;
130130
va_copy(va_args_copy, args);
131131

vpr/src/base/SetupVPR.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -735,6 +735,7 @@ static void SetupNocOpts(const t_options& Options, t_noc_opts* NocOpts) {
735735
NocOpts->noc_flows_file = Options.noc_flows_file;
736736
NocOpts->noc_routing_algorithm = Options.noc_routing_algorithm;
737737
NocOpts->noc_placement_weighting = Options.noc_placement_weighting;
738+
NocOpts->noc_aggregate_bandwidth_weighting = Options.noc_agg_bandwidth_weighting;
738739
NocOpts->noc_latency_constraints_weighting = Options.noc_latency_constraints_weighting;
739740
NocOpts->noc_latency_weighting = Options.noc_latency_weighting;
740741
NocOpts->noc_congestion_weighting = Options.noc_congestion_weighting;

vpr/src/base/ShowSetup.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -608,7 +608,7 @@ static void ShowPlacerOpts(const t_placer_opts& PlacerOpts,
608608
}
609609

610610
VTR_LOG("PlacerOpts.constraints_file: ");
611-
if (PlacerOpts.constraints_file == "") {
611+
if (PlacerOpts.constraints_file.empty()) {
612612
VTR_LOG("No constraints file given\n");
613613
} else {
614614
VTR_LOG("Using constraints file '%s'\n", PlacerOpts.constraints_file.c_str());
@@ -795,6 +795,7 @@ static void ShowNocOpts(const t_noc_opts& NocOpts) {
795795
VTR_LOG("NocOpts.noc_flows_file: %s\n", NocOpts.noc_flows_file.c_str());
796796
VTR_LOG("NocOpts.noc_routing_algorithm: %s\n", NocOpts.noc_routing_algorithm.c_str());
797797
VTR_LOG("NocOpts.noc_placement_weighting: %f\n", NocOpts.noc_placement_weighting);
798+
VTR_LOG("NocOpts.noc_aggregate_bandwidth_weighting: %f\n", NocOpts.noc_aggregate_bandwidth_weighting);
798799
VTR_LOG("NocOpts.noc_latency_constraints_weighting: %f\n", NocOpts.noc_latency_constraints_weighting);
799800
VTR_LOG("NocOpts.noc_latency_weighting: %f\n", NocOpts.noc_latency_weighting);
800801
VTR_LOG("NocOpts.noc_congestion_weighting: %f\n", NocOpts.noc_congestion_weighting);

vpr/src/base/read_options.cpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2810,7 +2810,8 @@ argparse::ArgumentParser create_arg_parser(std::string prog_name, t_options& arg
28102810
"* bfs_routing: Uses the breadth first search algorithm. The objective is to find a route that uses a minimum number of links.\n"
28112811
"This can be used with any NoC topology\n")
28122812
.default_value("bfs_routing")
2813-
.choices({"xy_routing", "bfs_routing"})
2813+
.choices({"xy_routing", "bfs_routing", "west_first_routing", "north_last_routing", "negative_first_routing",
2814+
"odd_even_routing"})
28142815
.show_in(argparse::ShowIn::HELP_ONLY);
28152816

28162817
noc_grp.add_argument<double>(args.noc_placement_weighting, "--noc_placement_weighting")
@@ -2822,6 +2823,16 @@ argparse::ArgumentParser create_arg_parser(std::string prog_name, t_options& arg
28222823
.default_value("5.0")
28232824
.show_in(argparse::ShowIn::HELP_ONLY);
28242825

2826+
noc_grp.add_argument<double>(args.noc_agg_bandwidth_weighting, "--noc_aggregate_bandwidth_weighting")
2827+
.help(
2828+
"Controls the importance of minimizing the NoC aggregate bandwidth.\n"
2829+
"This value can be >=0, where 0 would mean the aggregate bandwidth has no relevance to placement.\n"
2830+
"Other positive numbers specify the importance of minimizing the NoC aggregate bandwidth to other NoC-related cost terms.\n"
2831+
"Weighting factors for NoC-related cost terms are normalized internally. Therefore, their absolute values are not important, and"
2832+
"only their relative ratios determine the importance of each cost term.")
2833+
.default_value("0.38")
2834+
.show_in(argparse::ShowIn::HELP_ONLY);
2835+
28252836
noc_grp.add_argument<double>(args.noc_latency_constraints_weighting, "--noc_latency_constraints_weighting")
28262837
.help(
28272838
"Controls the importance of meeting all the NoC traffic flow latency constraints.\n"

vpr/src/base/read_options.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ struct t_options {
153153
argparse::ArgValue<std::string> noc_flows_file;
154154
argparse::ArgValue<std::string> noc_routing_algorithm;
155155
argparse::ArgValue<double> noc_placement_weighting;
156+
argparse::ArgValue<double> noc_agg_bandwidth_weighting;
156157
argparse::ArgValue<double> noc_latency_constraints_weighting;
157158
argparse::ArgValue<double> noc_latency_weighting;
158159
argparse::ArgValue<double> noc_congestion_weighting;

vpr/src/noc/bfs_routing.cpp

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
1-
#
1+
2+
#include <queue>
23

34
#include "bfs_routing.h"
45

5-
BFSRouting::~BFSRouting() {}
6+
BFSRouting::~BFSRouting() = default;
67

7-
void BFSRouting::route_flow(NocRouterId src_router_id, NocRouterId sink_router_id, std::vector<NocLinkId>& flow_route, const NocStorage& noc_model) {
8+
void BFSRouting::route_flow(NocRouterId src_router_id,
9+
NocRouterId sink_router_id,
10+
NocTrafficFlowId /*traffic_flow_id*/,
11+
std::vector<NocLinkId>& flow_route,
12+
const NocStorage& noc_model) {
813
const NocRouter& src_router = noc_model.get_single_noc_router(src_router_id);
914
const NocRouter& sink_router = noc_model.get_single_noc_router(sink_router_id);
1015

@@ -15,7 +20,7 @@ void BFSRouting::route_flow(NocRouterId src_router_id, NocRouterId sink_router_i
1520
* Keeps track of which routers have been reached already
1621
* while traversing the NoC. This variable will help prevent
1722
* the algorithm from getting stuck visiting routers that
18-
* jave already been visited.
23+
* have already been visited.
1924
*
2025
*/
2126
std::unordered_set<NocRouterId> visited_routers;
@@ -46,7 +51,7 @@ void BFSRouting::route_flow(NocRouterId src_router_id, NocRouterId sink_router_i
4651
}
4752

4853
// Explore the NoC from the starting router and try to find a path to the destination router
49-
// We finish searching when there are no more routers to process or we found the destination router
54+
// We finish searching when there are no more routers to process, or we found the destination router
5055
while (!routers_to_process.empty() && !found_sink_router) {
5156
// get the next router to process
5257
NocRouterId processing_router = routers_to_process.front();
@@ -88,13 +93,17 @@ void BFSRouting::route_flow(NocRouterId src_router_id, NocRouterId sink_router_i
8893
generate_route(sink_router_id, flow_route, noc_model, router_parent_link);
8994
} else {
9095
// a path was not found so throw an error to the user
91-
VPR_FATAL_ERROR(VPR_ERROR_OTHER, "No route could be found from starting router with id:'%d' and the destination router with id:'%d' using the breadth-first search routing algorithm.", src_router.get_router_user_id(), sink_router.get_router_user_id());
96+
VPR_FATAL_ERROR(VPR_ERROR_OTHER,
97+
"No route could be found from starting router with id:'%d' and the destination router with id:'%d' using the breadth-first search routing algorithm.",
98+
src_router.get_router_user_id(),
99+
sink_router.get_router_user_id());
92100
}
93-
94-
return;
95101
}
96102

97-
void BFSRouting::generate_route(NocRouterId start_router_id, std::vector<NocLinkId>& flow_route, const NocStorage& noc_model, const std::unordered_map<NocRouterId, NocLinkId>& router_parent_link) {
103+
void BFSRouting::generate_route(NocRouterId start_router_id,
104+
std::vector<NocLinkId>& flow_route,
105+
const NocStorage& noc_model,
106+
const std::unordered_map<NocRouterId, NocLinkId>& router_parent_link) {
98107
// The intermediate router being visited while tracing the path back from the destination router to the starting router in the flow.
99108
// Initially this is set to the router at the end of the path (destination router)
100109
NocRouterId curr_intermediate_router = start_router_id;
@@ -104,11 +113,11 @@ void BFSRouting::generate_route(NocRouterId start_router_id, std::vector<NocLink
104113
auto route_beginning = flow_route.begin();
105114

106115
// get the parent link of the start router
107-
std::unordered_map<NocRouterId, NocLinkId>::const_iterator curr_intermediate_router_parent_link = router_parent_link.find(curr_intermediate_router);
116+
auto curr_intermediate_router_parent_link = router_parent_link.find(curr_intermediate_router);
108117

109-
// keep tracking baackwards from each router in the path until a router doesn't have a parent link (this means we reached the starting router in the flow)
118+
// keep tracking backwards from each router in the path until a router doesn't have a parent link (this means we reached the starting router in the flow)
110119
while (curr_intermediate_router_parent_link != router_parent_link.end()) {
111-
// add the parent link to the path. Since we are tracing backwards we need to store the links in fron of the last link.
120+
// add the parent link to the path. Since we are tracing backwards we need to store the links in front of the last link.
112121
flow_route.emplace(route_beginning, curr_intermediate_router_parent_link->second);
113122

114123
// update the reference to the beginning of the route
@@ -119,6 +128,4 @@ void BFSRouting::generate_route(NocRouterId start_router_id, std::vector<NocLink
119128
// now get the parent of the router we moved to
120129
curr_intermediate_router_parent_link = router_parent_link.find(curr_intermediate_router);
121130
}
122-
123-
return;
124131
}

vpr/src/noc/bfs_routing.h

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,13 @@
1414
* traffic flow. Once the destination router is found a path from the source to
1515
* the destination router is generated. The main advantage of this algorithm is
1616
* that the found path from the source to the destination router uses the
17-
* minimum number of links required within the NoC.
18-
*
17+
* minimum number of links required within the NoC. This algorithm does not
18+
* guarantee deadlock freedom. In other words, the algorithm might generate
19+
* routes that form cycles in channel dependency graph.
1920
*/
2021

2122
#include <vector>
2223
#include <unordered_map>
23-
#include <queue>
2424

2525
#include "noc_routing.h"
2626

@@ -41,6 +41,7 @@ class BFSRouting : public NocRouting {
4141
* @param sink_router_id The destination router of a traffic flow.
4242
* Identifies the ending point of the route within the NoC.This represents a
4343
* physical router on the FPGA.
44+
* @param traffic_flow_id The unique ID for the traffic flow being routed.
4445
* @param flow_route Stores the path returned by this fuction
4546
* as a series of NoC links found by
4647
* a NoC routing algorithm between two routers in a traffic flow.
@@ -50,7 +51,11 @@ class BFSRouting : public NocRouting {
5051
* @param noc_model A model of the NoC. This is used to traverse the
5152
* NoC and find a route between the two routers.
5253
*/
53-
void route_flow(NocRouterId src_router_id, NocRouterId sink_router_id, std::vector<NocLinkId>& flow_route, const NocStorage& noc_model) override;
54+
void route_flow(NocRouterId src_router_id,
55+
NocRouterId sink_router_id,
56+
NocTrafficFlowId traffic_flow_id,
57+
std::vector<NocLinkId>& flow_route,
58+
const NocStorage& noc_model) override;
5459

5560
// internally used helper functions
5661
private:
@@ -76,7 +81,10 @@ class BFSRouting : public NocRouting {
7681
* router in the NoC (parent link is the link used to visit the router during
7782
* the BFS routing algorithm).
7883
*/
79-
void generate_route(NocRouterId sink_router_id, std::vector<NocLinkId>& flow_route, const NocStorage& noc_model, const std::unordered_map<NocRouterId, NocLinkId>& router_parent_link);
84+
void generate_route(NocRouterId sink_router_id,
85+
std::vector<NocLinkId>& flow_route,
86+
const NocStorage& noc_model,
87+
const std::unordered_map<NocRouterId, NocLinkId>& router_parent_link);
8088
};
8189

8290
#endif
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
2+
#include "channel_dependency_graph.h"
3+
#include "vtr_assert.h"
4+
5+
#include <stack>
6+
7+
ChannelDependencyGraph::ChannelDependencyGraph(size_t n_links,
8+
const vtr::vector<NocTrafficFlowId, std::vector<NocLinkId>>& traffic_flow_routes) {
9+
adjacency_list_.clear();
10+
// In channel dependency graph, vertices represent NoC links.
11+
// reserve enough space so that all vertices can store their outgoing neighbors
12+
adjacency_list_.resize(n_links);
13+
14+
/*
15+
* A traffic flow travels through some NoC links. In channel dependency graph (CDG),
16+
* consecutive NoC links travelled by the flow are connected using an edge.
17+
* More specifically, for each pair of consecutive NoC links in a traffic flow route,
18+
* there exists a directed edge from the NoC link travelled first to the other one.
19+
* For example, if traffic flow T travels NoC links L0, L2, and L5 to reach its
20+
* destination, we need to add (L0, L2) and (L2, L5) edges to CDG.
21+
*/
22+
23+
// iterate over all traffic flows and populate the channel dependency graph
24+
for (const auto& traffic_flow_route : traffic_flow_routes) {
25+
auto prev_link_id = NocLinkId::INVALID();
26+
for (auto cur_link_id : traffic_flow_route) {
27+
VTR_ASSERT(prev_link_id != cur_link_id);
28+
if (prev_link_id != NocLinkId::INVALID()) {
29+
adjacency_list_[prev_link_id].push_back(cur_link_id);
30+
}
31+
prev_link_id = cur_link_id;
32+
}
33+
}
34+
35+
// remove repetitive neighbors
36+
for (auto& neighboring_nodes : adjacency_list_) {
37+
// sort neighbors so that repetitive nodes are put beside each other
38+
std::sort(neighboring_nodes.begin(), neighboring_nodes.end());
39+
40+
// remove consecutive duplicates
41+
auto it = std::unique(neighboring_nodes.begin(), neighboring_nodes.end());
42+
43+
// erase the elements from the iterator to the end
44+
neighboring_nodes.erase(it, neighboring_nodes.end());
45+
}
46+
}
47+
48+
bool ChannelDependencyGraph::has_cycles() {
49+
// get the number vertices in CDG
50+
const size_t n_vertices = adjacency_list_.size();
51+
52+
// indicates whether a node (NoC link) in CDG is visited during DFS
53+
vtr::vector<NocLinkId, bool> visited(n_vertices, false);
54+
// indicates whether a node (NoC links) is currently in stack
55+
vtr::vector<NocLinkId, bool> on_stack(n_vertices, false);
56+
// the stack used to perform graph traversal (DFS). Contains to-be-visited vertices
57+
std::stack<NocLinkId> stack;
58+
59+
// iterate over all vertices (NoC links)
60+
for (NocLinkId noc_link_id : adjacency_list_.keys()) {
61+
// the node (NoC link) has already been visited
62+
if (visited[noc_link_id]) {
63+
continue;
64+
}
65+
66+
// An un-visited node is found. Add to the stack
67+
stack.push(noc_link_id);
68+
69+
// continue the traversal until the stack is empty
70+
while (!stack.empty()) {
71+
auto current_vertex_id = stack.top();
72+
73+
if (!visited[current_vertex_id]) {
74+
on_stack[current_vertex_id] = true;
75+
visited[current_vertex_id] = true;
76+
} else { // the neighboring vertices have already been processed
77+
// remove it from the stack
78+
stack.pop();
79+
on_stack[current_vertex_id] = false;
80+
}
81+
82+
// get the outgoing edges of the current vertex
83+
const auto& neighbor_ids = adjacency_list_[current_vertex_id];
84+
85+
// iterate over all outgoing neighbors
86+
for (auto& neighbor_id : neighbor_ids) {
87+
if (!visited[neighbor_id]) {
88+
stack.push(neighbor_id);
89+
} else if (on_stack[neighbor_id]) { // the current vertex is pointing to one of its ancestors
90+
return true;
91+
}
92+
}
93+
}
94+
}
95+
96+
// if no vertex in the graph points to at least one of its ancestors, the graph does not have any cycles
97+
return false;
98+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
#ifndef VTR_CHANNEL_DEPENDENCY_GRAPH_H
2+
#define VTR_CHANNEL_DEPENDENCY_GRAPH_H
3+
4+
/**
5+
* @file
6+
* @brief This file declares the ChannelDependencyGraph class.
7+
*
8+
* Overview
9+
* ========
10+
* The NoC routing algorithm might generate routes that cause a deadlock.
11+
* The Channel Dependency Graph (CDG) is formed by associating a node with each
12+
* link in the NoC topology. For each traffic flow route, we consider the
13+
* consecutive links traversed to reach the destination. For each consecutively
14+
* traversed link pair (Li, Lj) in the given topology, we add an directed edge from
15+
* Vi to Vj, where Vi and Vj are nodes in CDG that are associated with Li and Lj.
16+
* Absence of cycles in the formed CDG guarantees deadlock freedom.
17+
*
18+
* To learn more about channel dependency graph, refer to the following papers:
19+
* 1) Glass, C. J., & Ni, L. M. (1992). The turn model for adaptive routing.
20+
* ACM SIGARCH Computer Architecture News, 20(2), 278-287.
21+
* 2) Dally, & Seitz. (1987). Deadlock-free message routing in multiprocessor
22+
* interconnection networks. IEEE Transactions on computers, 100(5), 547-553.
23+
*/
24+
25+
#include "vtr_vector.h"
26+
#include "noc_data_types.h"
27+
28+
class ChannelDependencyGraph {
29+
public:
30+
ChannelDependencyGraph() = delete;
31+
32+
/**
33+
* @brief Constructor
34+
*
35+
* @param n_links The total number of NoC links.
36+
* @param traffic_flow_routes The route of each traffic flow generated
37+
* by a routing algorithm.
38+
*/
39+
ChannelDependencyGraph(size_t n_links,
40+
const vtr::vector<NocTrafficFlowId, std::vector<NocLinkId>>& traffic_flow_routes);
41+
42+
/**
43+
* @brief Checks whether CDG has any cycles. A cycle implies that
44+
* deadlocks are possible. If CDG has no cycles, deadlock freedom
45+
* is guaranteed.
46+
*
47+
* @return True if the CDG has any cycles, otherwise false is returned.
48+
*/
49+
bool has_cycles();
50+
51+
private:
52+
/** An adjacency list used to represent channel dependency graph.*/
53+
vtr::vector<NocLinkId, std::vector<NocLinkId>> adjacency_list_;
54+
};
55+
56+
#endif //VTR_CHANNEL_DEPENDENCY_GRAPH_H

0 commit comments

Comments
 (0)