Skip to content

Commit b30b9fa

Browse files
authored
Merge pull request verilog-to-routing#2010 from verilog-to-routing/noc_description_support
Noc description support and modelling in VPR
2 parents f725f36 + 7c841f5 commit b30b9fa

40 files changed

+54103
-3
lines changed

libs/libarchfpga/CMakeLists.txt

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.9)
22

33
project("libarchfpga")
44

5-
file(GLOB_RECURSE EXEC_SOURCES main.cpp)
5+
file(GLOB_RECURSE EXEC_SOURCES src/main.cpp)
66
file(GLOB_RECURSE LIB_SOURCES src/*.cpp)
77
file(GLOB_RECURSE LIB_HEADERS src/*.h)
88
files_to_dirs(LIB_HEADERS LIB_INCLUDE_DIRS)
@@ -41,3 +41,10 @@ if (READ_ARCH_USES_IPO)
4141
endif()
4242

4343
install(TARGETS libarchfpga read_arch DESTINATION bin)
44+
45+
#
46+
# Unit Tests
47+
#
48+
file(GLOB_RECURSE TEST_SOURCES test/*.cpp)
49+
add_executable(test_archfpga ${TEST_SOURCES})
50+
target_link_libraries(test_archfpga Catch2::Catch2WithMain libarchfpga)

libs/libarchfpga/src/arch_util.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,8 @@ void free_arch(t_arch* arch) {
204204
if (arch->clocks) {
205205
vtr::free(arch->clocks->clock_inf);
206206
}
207+
208+
delete (arch->noc);
207209
}
208210

209211
//Frees all models in the linked list

libs/libarchfpga/src/physical_types.h

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1791,6 +1791,43 @@ struct t_lut_element {
17911791
}
17921792
};
17931793

1794+
/**
1795+
* Represents a Network-on-chip(NoC) Router data type. It is used
1796+
* to store individual router information when parsing the arch file.
1797+
* */
1798+
struct t_router {
1799+
/** A unique id provided by the user to identify a router. Must be a positive value*/
1800+
int id = -1;
1801+
1802+
/** A value representing the approximate horizontal position on the FPGA device where the router
1803+
* tile is located*/
1804+
double device_x_position = -1;
1805+
/** A value representing the approximate vertical position on the FPGA device where the router
1806+
* tile is located*/
1807+
double device_y_position = -1;
1808+
1809+
/** A list of router ids that are connected to the current router*/
1810+
std::vector<int> connection_list;
1811+
};
1812+
1813+
/**
1814+
* Network-on-chip(NoC) data type used to store the network properties
1815+
* when parsing the arh file. This is used when building the dedicated on-chip
1816+
* network during the device creation.
1817+
* */
1818+
struct t_noc_inf {
1819+
double link_bandwidth; /*!< The maximum bandwidth supported in the NoC. This value is the same for all links. units in bps*/
1820+
double link_latency; /*!< The worst case latency seen when traversing a link. This value is the same for all links. units in seconds*/
1821+
double router_latency; /*!< The worst case latency seen when traversing a router. This value is the same for all routers, units in seconds*/
1822+
1823+
/** A list of all routers in the NoC*/
1824+
std::vector<t_router> router_list;
1825+
1826+
/** Represents the name of a router tile on the FPGA device. This should match the name used in the arch file when
1827+
* describing a NoC router tile within the FPGA device*/
1828+
std::string noc_router_tile_name;
1829+
};
1830+
17941831
/* Detailed routing architecture */
17951832
struct t_arch {
17961833
mutable vtr::string_internment strings;
@@ -1851,6 +1888,9 @@ struct t_arch {
18511888
std::vector<t_grid_def> grid_layouts; //Set of potential device layouts
18521889

18531890
t_clock_arch_spec clock_arch; // Clock related data types
1891+
1892+
// if we have an embedded NoC in the architecture, then we store it here
1893+
t_noc_inf* noc = nullptr;
18541894
};
18551895

18561896
#endif

libs/libarchfpga/src/read_xml_arch_file.cpp

Lines changed: 456 additions & 0 deletions
Large diffs are not rendered by default.

libs/libarchfpga/test/main.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#define CATCH_CONFIG_MAIN
2+
#include "catch2/catch_test_macros.hpp"
Lines changed: 269 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,269 @@
1+
// test framework
2+
#include "catch2/catch_test_macros.hpp"
3+
#include "catch2/matchers/catch_matchers_all.hpp"
4+
5+
// testting statuc functions so include whole source file it is in
6+
#include "read_xml_arch_file.cpp"
7+
8+
// for comparing floats
9+
#include "vtr_math.h"
10+
11+
TEST_CASE("Updating router info in arch", "[NoC Arch Tests]") {
12+
std::map<int, std::pair<int, int>> test_router_list;
13+
14+
std::map<int, std::pair<int, int>>::iterator it;
15+
16+
// initial conditions
17+
int router_id = 1;
18+
bool router_is_from_connection_list = false;
19+
20+
// we initially need the map to be empty
21+
REQUIRE(test_router_list.size() == 0);
22+
23+
SECTION("Update the number of declarations for a router for the first time ") {
24+
update_router_info_in_arch(router_id, router_is_from_connection_list, test_router_list);
25+
26+
it = test_router_list.find(router_id);
27+
28+
// check first that the router was newly added to the router databse
29+
REQUIRE(it != test_router_list.end());
30+
31+
// no verify the components of the router parameter
32+
REQUIRE(it->second.first == 1);
33+
REQUIRE(it->second.second == 0);
34+
}
35+
SECTION("Update the number of connections for a router for the first time") {
36+
router_is_from_connection_list = true;
37+
38+
update_router_info_in_arch(router_id, router_is_from_connection_list, test_router_list);
39+
40+
it = test_router_list.find(router_id);
41+
42+
// check first that the router was newly added to the router databse
43+
REQUIRE(it != test_router_list.end());
44+
45+
// no verify the components of the router parameter
46+
REQUIRE(it->second.first == 0);
47+
REQUIRE(it->second.second == 1);
48+
}
49+
SECTION("Update the number of declarations for a router when it already exists") {
50+
update_router_info_in_arch(router_id, router_is_from_connection_list, test_router_list);
51+
52+
// verify that a router was added
53+
REQUIRE(test_router_list.size() != 0);
54+
55+
update_router_info_in_arch(router_id, router_is_from_connection_list, test_router_list);
56+
57+
it = test_router_list.find(router_id);
58+
59+
// check first that the router was newly added to the router databse
60+
REQUIRE(it != test_router_list.end());
61+
62+
// no verify the components of the router parameter
63+
REQUIRE(it->second.first == 2);
64+
REQUIRE(it->second.second == 0);
65+
}
66+
SECTION("Update the number of connections for a router when it already exists") {
67+
router_is_from_connection_list = true;
68+
69+
update_router_info_in_arch(router_id, router_is_from_connection_list, test_router_list);
70+
71+
// verify that a router was added
72+
REQUIRE(test_router_list.size() != 0);
73+
74+
update_router_info_in_arch(router_id, router_is_from_connection_list, test_router_list);
75+
76+
it = test_router_list.find(router_id);
77+
78+
// check first that the router was newly added to the router databse
79+
REQUIRE(it != test_router_list.end());
80+
81+
// no verify the components of the router parameter
82+
REQUIRE(it->second.first == 0);
83+
REQUIRE(it->second.second == 2);
84+
}
85+
}
86+
87+
TEST_CASE("Verifying a parsed NoC topology", "[NoC Arch Tests]") {
88+
std::map<int, std::pair<int, int>> test_router_list;
89+
90+
REQUIRE(test_router_list.size() == 0);
91+
92+
SECTION("Check the error where a router in the NoC is not connected to other routers.") {
93+
// error router
94+
test_router_list.insert(std::pair<int, std::pair<int, int>>(1, std::pair<int, int>(1, 0)));
95+
96+
// sonme normal routers
97+
test_router_list.insert(std::pair<int, std::pair<int, int>>(2, std::pair<int, int>(1, 5)));
98+
99+
test_router_list.insert(std::pair<int, std::pair<int, int>>(3, std::pair<int, int>(1, 6)));
100+
101+
REQUIRE(test_router_list.size() == 3);
102+
103+
REQUIRE_THROWS_WITH(verify_noc_topology(test_router_list), "The router with id:'1' is not connected to any other router in the NoC.");
104+
}
105+
SECTION("Check the error where a router in the NoC is connected to other routers but missing a declaration in the arch file.") {
106+
// normal routers
107+
test_router_list.insert(std::pair<int, std::pair<int, int>>(1, std::pair<int, int>(1, 5)));
108+
109+
test_router_list.insert(std::pair<int, std::pair<int, int>>(2, std::pair<int, int>(1, 3)));
110+
111+
// error router
112+
test_router_list.insert(std::pair<int, std::pair<int, int>>(3, std::pair<int, int>(0, 5)));
113+
114+
test_router_list.insert(std::pair<int, std::pair<int, int>>(4, std::pair<int, int>(1, 10)));
115+
116+
REQUIRE(test_router_list.size() == 4);
117+
118+
REQUIRE_THROWS_WITH(verify_noc_topology(test_router_list), "The router with id:'3' was found to be connected to another router but missing in the architecture file. Add the router using the <router> tag.");
119+
}
120+
SECTION("Check the error where the router is included more than once in the architecture file.") {
121+
// normal routers
122+
test_router_list.insert(std::pair<int, std::pair<int, int>>(1, std::pair<int, int>(1, 5)));
123+
124+
test_router_list.insert(std::pair<int, std::pair<int, int>>(2, std::pair<int, int>(1, 3)));
125+
126+
test_router_list.insert(std::pair<int, std::pair<int, int>>(3, std::pair<int, int>(1, 10)));
127+
128+
// error routers
129+
test_router_list.insert(std::pair<int, std::pair<int, int>>(4, std::pair<int, int>(2, 10)));
130+
131+
// normal routers
132+
test_router_list.insert(std::pair<int, std::pair<int, int>>(5, std::pair<int, int>(1, 3)));
133+
134+
test_router_list.insert(std::pair<int, std::pair<int, int>>(6, std::pair<int, int>(1, 10)));
135+
136+
REQUIRE(test_router_list.size() == 6);
137+
138+
REQUIRE_THROWS_WITH(verify_noc_topology(test_router_list), "The router with id:'4' was included more than once in the architecture file. Routers should only be declared once.");
139+
}
140+
}
141+
142+
TEST_CASE("Verifying mesh topology creation", "[NoC Arch Tests]") {
143+
// data for the xml parsing
144+
pugi::xml_node test;
145+
pugiutil::loc_data test_location;
146+
147+
// the noc storage
148+
t_noc_inf test_noc;
149+
150+
// mesh parameters
151+
double mesh_start_x = 10;
152+
double mesh_start_y = 10;
153+
double mesh_end_x = 5;
154+
double mesh_end_y = 56;
155+
double mesh_size = 0;
156+
157+
SECTION("Check the error where a mesh size was illegal.") {
158+
REQUIRE_THROWS_WITH(generate_noc_mesh(test, test_location, &test_noc, mesh_start_x, mesh_end_x, mesh_start_y, mesh_end_y, mesh_size), "The NoC mesh size cannot be 0.");
159+
}
160+
SECTION("Check the error where a mesh region size was invalid.") {
161+
mesh_size = 3;
162+
163+
REQUIRE_THROWS_WITH(generate_noc_mesh(test, test_location, &test_noc, mesh_start_x, mesh_end_x, mesh_start_y, mesh_end_y, mesh_size), "The NoC region is invalid.");
164+
}
165+
SECTION("Check the mesh creation for integer precision coordinates.") {
166+
// define test parameters
167+
mesh_size = 3;
168+
169+
mesh_start_x = 0;
170+
mesh_start_y = 0;
171+
172+
mesh_end_x = 4;
173+
mesh_end_y = 4;
174+
175+
// create the golden golden results
176+
double golden_results_x[9];
177+
double golden_results_y[9];
178+
179+
// first row of the mesh
180+
golden_results_x[0] = 0;
181+
golden_results_y[0] = 0;
182+
golden_results_x[1] = 2;
183+
golden_results_y[1] = 0;
184+
golden_results_x[2] = 4;
185+
golden_results_y[2] = 0;
186+
187+
// second row of the mesh
188+
golden_results_x[3] = 0;
189+
golden_results_y[3] = 2;
190+
golden_results_x[4] = 2;
191+
golden_results_y[4] = 2;
192+
golden_results_x[5] = 4;
193+
golden_results_y[5] = 2;
194+
195+
// third row of the mesh
196+
golden_results_x[6] = 0;
197+
golden_results_y[6] = 4;
198+
golden_results_x[7] = 2;
199+
golden_results_y[7] = 4;
200+
golden_results_x[8] = 4;
201+
golden_results_y[8] = 4;
202+
203+
generate_noc_mesh(test, test_location, &test_noc, mesh_start_x, mesh_end_x, mesh_start_y, mesh_end_y, mesh_size);
204+
205+
// go through all the expected routers
206+
for (int expected_router_id = 0; expected_router_id < (mesh_size * mesh_size); expected_router_id++) {
207+
// make sure the router ids match
208+
REQUIRE(test_noc.router_list[expected_router_id].id == expected_router_id);
209+
210+
// make sure the position of the routers are correct
211+
// x position
212+
REQUIRE(golden_results_x[expected_router_id] == test_noc.router_list[expected_router_id].device_x_position);
213+
// y position
214+
REQUIRE(golden_results_y[expected_router_id] == test_noc.router_list[expected_router_id].device_y_position);
215+
}
216+
}
217+
SECTION("Check the mesh creation for double precision coordinates.") {
218+
// define test parameters
219+
mesh_size = 3;
220+
221+
mesh_start_x = 3.5;
222+
mesh_start_y = 5.7;
223+
224+
mesh_end_x = 10.8;
225+
mesh_end_y = 6.4;
226+
227+
// create the golden golden results
228+
double golden_results_x[9];
229+
double golden_results_y[9];
230+
231+
// first row of the mesh
232+
golden_results_x[0] = 3.5;
233+
golden_results_y[0] = 5.7;
234+
golden_results_x[1] = 7.15;
235+
golden_results_y[1] = 5.7;
236+
golden_results_x[2] = 10.8;
237+
golden_results_y[2] = 5.7;
238+
239+
// second row of the mesh
240+
golden_results_x[3] = 3.5;
241+
golden_results_y[3] = 6.05;
242+
golden_results_x[4] = 7.15;
243+
golden_results_y[4] = 6.05;
244+
golden_results_x[5] = 10.8;
245+
golden_results_y[5] = 6.05;
246+
247+
// third row of the mesh
248+
golden_results_x[6] = 3.5;
249+
golden_results_y[6] = 6.4;
250+
golden_results_x[7] = 7.15;
251+
golden_results_y[7] = 6.4;
252+
golden_results_x[8] = 10.8;
253+
golden_results_y[8] = 6.4;
254+
255+
generate_noc_mesh(test, test_location, &test_noc, mesh_start_x, mesh_end_x, mesh_start_y, mesh_end_y, mesh_size);
256+
257+
// go through all the expected routers
258+
for (int expected_router_id = 0; expected_router_id < (mesh_size * mesh_size); expected_router_id++) {
259+
// make sure the router ids match
260+
REQUIRE(test_noc.router_list[expected_router_id].id == expected_router_id);
261+
262+
// make sure the position of the routers are correct
263+
// x position
264+
REQUIRE(vtr::isclose(golden_results_x[expected_router_id], test_noc.router_list[expected_router_id].device_x_position));
265+
// y position
266+
REQUIRE(vtr::isclose(golden_results_y[expected_router_id], test_noc.router_list[expected_router_id].device_y_position));
267+
}
268+
}
269+
}

vpr/src/base/SetupVPR.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ static void SetupPlacerOpts(const t_options& Options,
3535
static void SetupAnnealSched(const t_options& Options,
3636
t_annealing_sched* AnnealSched);
3737
static void SetupRouterOpts(const t_options& Options, t_router_opts* RouterOpts);
38+
static void SetupNocOpts(const t_options& Options,
39+
t_noc_opts* NocOpts);
3840
static void SetupRoutingArch(const t_arch& Arch, t_det_routing_arch* RoutingArch);
3941
static void SetupTiming(const t_options& Options, const bool TimingEnabled, t_timing_inf* Timing);
4042
static void SetupSwitches(const t_arch& Arch,
@@ -64,6 +66,7 @@ void SetupVPR(const t_options* Options,
6466
t_annealing_sched* AnnealSched,
6567
t_router_opts* RouterOpts,
6668
t_analysis_opts* AnalysisOpts,
69+
t_noc_opts* NocOpts,
6770
t_det_routing_arch* RoutingArch,
6871
std::vector<t_lb_type_rr_node>** PackerRRGraphs,
6972
std::vector<t_segment_inf>& Segments,
@@ -108,6 +111,7 @@ void SetupVPR(const t_options* Options,
108111
SetupRouterOpts(*Options, RouterOpts);
109112
SetupAnalysisOpts(*Options, *AnalysisOpts);
110113
SetupPowerOpts(*Options, PowerOpts, Arch);
114+
SetupNocOpts(*Options, NocOpts);
111115

112116
if (readArchFile == true) {
113117
vtr::ScopedStartFinishTimer t("Loading Architecture Description");
@@ -655,6 +659,16 @@ static void SetupPowerOpts(const t_options& Options, t_power_opts* power_opts, t
655659
}
656660
}
657661

662+
/*
663+
* Go through all the NoC options supplied by the user and store them internally.
664+
*/
665+
static void SetupNocOpts(const t_options& Options, t_noc_opts* NocOpts) {
666+
// assign the noc specific options from the command line
667+
NocOpts->noc = Options.noc;
668+
669+
return;
670+
}
671+
658672
static int find_ipin_cblock_switch_index(const t_arch& Arch) {
659673
int ipin_cblock_switch_index = UNDEFINED;
660674
for (int i = 0; i < Arch.num_switches; ++i) {

0 commit comments

Comments
 (0)