Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

3D NoC #2649

Merged
merged 42 commits into from
Sep 17, 2024
Merged

3D NoC #2649

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
402de31
update generate_noc_mesh() to support 3d mesh
soheilshahrouz Jul 5, 2024
82a8dce
add pairs() method to vtr::vector
soheilshahrouz Jul 5, 2024
ee02db0
check that logical and physical routers are on the same layer in crea…
soheilshahrouz Jul 5, 2024
c32a0cb
fix compilation errors in test_setup_noc.cpp
soheilshahrouz Jul 5, 2024
097b5ee
update XYRouting to support 3d noc
soheilshahrouz Jul 5, 2024
6d30232
3d support in negative first routing algrotihtm
soheilshahrouz Jul 5, 2024
2c872bf
select_next_direction() method is no longer pure virtual
soheilshahrouz Jul 5, 2024
b3649d3
3d north-last routing algorithm
soheilshahrouz Jul 5, 2024
6defaef
forbid 6 90-degree turns in 3d north-last algorithm
soheilshahrouz Jul 8, 2024
75eae08
3d west-first routing algorithm
soheilshahrouz Jul 8, 2024
6b17b25
remove select_next_direction() override in westfirstrouting
soheilshahrouz Jul 9, 2024
ba20efc
3d support in OddEvenRouting::is_turn_legal()
soheilshahrouz Jul 9, 2024
d1df108
rename directions
soheilshahrouz Jul 9, 2024
adb503c
Update TurnModelRouting::move_to_next_router() for 3d support
soheilshahrouz Jul 9, 2024
5948545
temp commit before changing the get_legal_directions()' signature
soheilshahrouz Jul 10, 2024
29ddd6e
add prev_dir argument to get_legal_directions()
soheilshahrouz Jul 10, 2024
381ff61
add is_noc_3d() method
soheilshahrouz Jul 10, 2024
2de853e
add noc_is_3d arg to is_turn_legal()
soheilshahrouz Jul 14, 2024
18b9e76
add route_2d and route_3d methods
soheilshahrouz Jul 15, 2024
f464e5d
implemented OddEvenRouting::route_3d() method
soheilshahrouz Jul 15, 2024
a183c2c
avoid using global state in OddEvenRouting
soheilshahrouz Jul 15, 2024
f087f41
add simple tests for odd-even routing
soheilshahrouz Jul 15, 2024
ae70992
test source-destination pair that are arbitrary rows and columns
soheilshahrouz Jul 15, 2024
8e2283e
check turn legality in odd-even routing unit test
soheilshahrouz Jul 15, 2024
07d8bcd
Merge branch 'master' into 3d_noc
soheilshahrouz Jul 16, 2024
75228d4
add a 3d noc arch file
soheilshahrouz Jul 16, 2024
55787af
resize the fixed layout
soheilshahrouz Jul 16, 2024
638fce2
update config files to add 3d noc arch file
soheilshahrouz Jul 16, 2024
5a9df1f
fix arch file name in config files
soheilshahrouz Jul 16, 2024
639ee62
add missing expected tags
soheilshahrouz Jul 16, 2024
76a4131
fix typos
soheilshahrouz Jul 17, 2024
89dfb32
spread noc pins across two layers
soheilshahrouz Jul 17, 2024
e8feb3e
write the correct layer number to noc placement file
soheilshahrouz Jul 17, 2024
1585edb
add get_compressed_noc_grid()
soheilshahrouz Jul 22, 2024
3318060
applied PR comments
soheilshahrouz Aug 10, 2024
0bace2e
fix compilation error in test_read_xml_arch_file.cpp
soheilshahrouz Aug 10, 2024
72f08ce
fix clang compilation error
soheilshahrouz Aug 12, 2024
8554635
fix unit test failures in test_setup_noc
soheilshahrouz Aug 12, 2024
af31b4d
Merge branch 'master' into 3d_noc
vaughnbetz Aug 15, 2024
feb308b
call the correct version of determine_legal_directions_xd in odd even…
soheilshahrouz Aug 18, 2024
748ce39
add the missing element to time_elapsed_ for noc biased centroid move
soheilshahrouz Aug 27, 2024
8228d52
Merge branch 'master' into 3d_noc and resolve conflicts
soheilshahrouz Aug 31, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions libs/libarchfpga/src/physical_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -822,10 +822,11 @@ struct t_physical_pin {

/**
* @brief Describes The location of a physical tile
* @param layer_num The die number of the physical tile. If the FPGA only has one die, or the physical tile is located
* on the base die, layer_num is equal to zero. If it is one the die above base die, it is one, etc.
* @param x The x location of the physical tile on the given die
* @param y The y location of the physical tile on the given die
* @param layer_num The die number of the physical tile. If the FPGA only has one die, or the physical tile is located
* on the base die, layer_num is equal to zero. If the physical tile is location on the die immediately
* above the base die, the layer_num is 1 and so on.
*/
struct t_physical_tile_loc {
int x = OPEN;
Expand Down Expand Up @@ -1975,10 +1976,12 @@ struct t_router {

/** A value representing the approximate horizontal position on the FPGA device where the router
* tile is located*/
double device_x_position = -1;
float device_x_position = -1;
/** A value representing the approximate vertical position on the FPGA device where the router
* tile is located*/
double device_y_position = -1;
float device_y_position = -1;
/** A value representing the exact layer in the FPGA device where the router tile is located.*/
int device_layer_position = -1;

/** A list of router ids that are connected to the current router*/
std::vector<int> connection_list;
Expand Down
134 changes: 81 additions & 53 deletions libs/libarchfpga/src/read_xml_arch_file_noc_tag.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,9 @@ static void process_mesh_topology(pugi::xml_node mesh_topology_tag,
static void generate_noc_mesh(pugi::xml_node mesh_topology_tag,
const pugiutil::loc_data& loc_data,
t_noc_inf* noc_ref,
double mesh_region_start_x, double mesh_region_end_x,
double mesh_region_start_y, double mesh_region_end_y,
float mesh_region_start_x, float mesh_region_end_x,
float mesh_region_start_y, float mesh_region_end_y,
int mesh_region_start_layer, int mesh_region_end_layer,
int mesh_size);

/**
Expand Down Expand Up @@ -227,17 +228,19 @@ static void process_mesh_topology(pugi::xml_node mesh_topology_tag,
constexpr int ATTRIBUTE_CONVERSION_FAILURE = -1;

// a list of attributes that should be found for the mesh tag
std::vector<std::string> expected_router_attributes = {"startx", "endx", "starty", "endy", "size"};
std::vector<std::string> expected_router_attributes = {"startx", "endx", "starty", "endy", "startlayer", "endlayer", "size"};

// verify that only the acceptable attributes were supplied
pugiutil::expect_only_attributes(mesh_topology_tag, expected_router_attributes, loc_data);

// go through the attributes and store their values
double mesh_region_start_x = pugiutil::get_attribute(mesh_topology_tag, "startx", loc_data, pugiutil::REQUIRED).as_double(ATTRIBUTE_CONVERSION_FAILURE);
double mesh_region_end_x = pugiutil::get_attribute(mesh_topology_tag, "endx", loc_data, pugiutil::REQUIRED).as_double(ATTRIBUTE_CONVERSION_FAILURE);
double mesh_region_start_y = pugiutil::get_attribute(mesh_topology_tag, "starty", loc_data, pugiutil::REQUIRED).as_double(ATTRIBUTE_CONVERSION_FAILURE);
double mesh_region_end_y = pugiutil::get_attribute(mesh_topology_tag, "endy", loc_data, pugiutil::REQUIRED).as_double(ATTRIBUTE_CONVERSION_FAILURE);
float mesh_region_start_x = pugiutil::get_attribute(mesh_topology_tag, "startx", loc_data, pugiutil::REQUIRED).as_float(ATTRIBUTE_CONVERSION_FAILURE);
float mesh_region_end_x = pugiutil::get_attribute(mesh_topology_tag, "endx", loc_data, pugiutil::REQUIRED).as_float(ATTRIBUTE_CONVERSION_FAILURE);
float mesh_region_start_y = pugiutil::get_attribute(mesh_topology_tag, "starty", loc_data, pugiutil::REQUIRED).as_float(ATTRIBUTE_CONVERSION_FAILURE);
float mesh_region_end_y = pugiutil::get_attribute(mesh_topology_tag, "endy", loc_data, pugiutil::REQUIRED).as_float(ATTRIBUTE_CONVERSION_FAILURE);

int mesh_region_start_layer = pugiutil::get_attribute(mesh_topology_tag, "startlayer", loc_data, pugiutil::OPTIONAL).as_int(ATTRIBUTE_CONVERSION_FAILURE);
int mesh_region_end_layer = pugiutil::get_attribute(mesh_topology_tag, "endlayer", loc_data, pugiutil::OPTIONAL).as_int(ATTRIBUTE_CONVERSION_FAILURE);
int mesh_size = pugiutil::get_attribute(mesh_topology_tag, "size", loc_data, pugiutil::REQUIRED).as_int(ATTRIBUTE_CONVERSION_FAILURE);

// verify that the attributes provided were legal
Expand All @@ -246,16 +249,29 @@ static void process_mesh_topology(pugi::xml_node mesh_topology_tag,
"The parameters for the mesh topology have to be positive values.");
}

if (mesh_region_start_layer == ATTRIBUTE_CONVERSION_FAILURE || mesh_region_end_layer == ATTRIBUTE_CONVERSION_FAILURE) {
VTR_LOGF_WARN(loc_data.filename_c_str(), loc_data.line(mesh_topology_tag),
"Optional 'startlayer' and 'endlayer' attributes were not set for the <mesh> tag. "
"The default value of zero is used for both of them.\n");
mesh_region_start_layer = 0;
mesh_region_end_layer = 0;
}

// now create the mesh topology for the noc
// create routers, make connections and determine positions
generate_noc_mesh(mesh_topology_tag, loc_data, noc_ref, mesh_region_start_x, mesh_region_end_x, mesh_region_start_y, mesh_region_end_y, mesh_size);
generate_noc_mesh(mesh_topology_tag, loc_data, noc_ref,
mesh_region_start_x, mesh_region_end_x,
mesh_region_start_y, mesh_region_end_y,
mesh_region_start_layer, mesh_region_end_layer,
mesh_size);
}

static void generate_noc_mesh(pugi::xml_node mesh_topology_tag,
const pugiutil::loc_data& loc_data,
t_noc_inf* noc_ref,
double mesh_region_start_x, double mesh_region_end_x,
double mesh_region_start_y, double mesh_region_end_y,
float mesh_region_start_x, float mesh_region_end_x,
float mesh_region_start_y, float mesh_region_end_y,
int mesh_region_start_layer, int mesh_region_end_layer,
int mesh_size) {
// check that the mesh size of the router is not 0
if (mesh_size == 0) {
Expand Down Expand Up @@ -285,62 +301,74 @@ static void generate_noc_mesh(pugi::xml_node mesh_topology_tag,
*
* THe reasoning for this is to reduce the number of calculated router positions.
*/
double vertical_router_separation = (mesh_region_end_y - mesh_region_start_y) / (mesh_size - 1);
double horizontal_router_separation = (mesh_region_end_x - mesh_region_start_x) / (mesh_size - 1);

t_router temp_router;
float vertical_router_separation = (mesh_region_end_y - mesh_region_start_y) / (mesh_size - 1);
float horizontal_router_separation = (mesh_region_end_x - mesh_region_start_x) / (mesh_size - 1);

// improper region check
if ((vertical_router_separation <= 0) || (horizontal_router_separation <= 0)) {
if (vertical_router_separation <= 0 || horizontal_router_separation <= 0 ||
mesh_region_end_layer < mesh_region_start_layer) {
archfpga_throw(loc_data.filename_c_str(), loc_data.line(mesh_topology_tag),
"The NoC region is invalid.");
}

// create routers and their connections
// start with router id 0 (bottom left of the chip) to the maximum router id (top right of the chip)
for (int j = 0; j < mesh_size; j++) {
for (int i = 0; i < mesh_size; i++) {
// assign router id
temp_router.id = (mesh_size * j) + i;

// calculate router position
/* The first and last router of each column or row will be located on the mesh region boundary,
* the remaining routers will be placed within the region and seperated from other routers
* using the distance calculated previously.
*/
temp_router.device_x_position = (i * horizontal_router_separation) + mesh_region_start_x;
temp_router.device_y_position = (j * vertical_router_separation) + mesh_region_start_y;

// assign connections
// check if there is a router to the left
if ((i - 1) >= 0) {
// add the left router as a connection
temp_router.connection_list.push_back((mesh_size * j) + i - 1);
}
for (int l = mesh_region_start_layer; l <= mesh_region_end_layer; l++) {
for (int j = 0; j < mesh_size; j++) {
for (int i = 0; i < mesh_size; i++) {
t_router temp_router;

// assign router id
temp_router.id = (mesh_size * mesh_size * (l - mesh_region_start_layer)) + (mesh_size * j) + i;

// calculate router position
/* The first and last router of each column or row will be located on the mesh region boundary,
* the remaining routers will be placed within the region and seperated from other routers
* using the distance calculated previously.
*/
temp_router.device_x_position = (i * horizontal_router_separation) + mesh_region_start_x;
temp_router.device_y_position = (j * vertical_router_separation) + mesh_region_start_y;
temp_router.device_layer_position = l;

// assign connections

// check if there is a router to the left
if (i >= 1) {
// add the left router as a connection
temp_router.connection_list.push_back(temp_router.id - 1);
}

// check if there is a router to the top
if ((j + 1) <= (mesh_size - 1)) {
// add the top router as a connection
temp_router.connection_list.push_back((mesh_size * (j + 1)) + i);
}
// check if there is a router to the top
if (j <= mesh_size - 2) {
// add the top router as a connection
temp_router.connection_list.push_back(temp_router.id + mesh_size);
}

// check if there is a router to the right
if ((i + 1) <= (mesh_size - 1)) {
// add the router located to the right
temp_router.connection_list.push_back((mesh_size * j) + i + 1);
}
// check if there is a router to the right
if (i <= mesh_size - 2) {
// add the router located to the right
temp_router.connection_list.push_back(temp_router.id + 1);
}

// check of there is a router below
if ((j - 1) >= (0)) {
// add the bottom router as a connection
temp_router.connection_list.push_back((mesh_size * (j - 1)) + i);
}
// check if there is a router below
if (j >= 1) {
// add the bottom router as a connection
temp_router.connection_list.push_back(temp_router.id - mesh_size);
}

// add the router to the list
noc_ref->router_list.push_back(temp_router);
// check if there is a router on the layer above
if (l < mesh_region_end_layer) {
temp_router.connection_list.push_back(temp_router.id + (mesh_size * mesh_size));
}

// clear the current router information for the next router
temp_router.connection_list.clear();
// check if there is a router on the layer below
if (l > mesh_region_start_layer) {
temp_router.connection_list.push_back(temp_router.id - (mesh_size * mesh_size));
}

// add the router to the list
noc_ref->router_list.push_back(temp_router);
}
}
}
}
Expand Down
30 changes: 16 additions & 14 deletions libs/libarchfpga/test/test_read_xml_arch_file.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -148,19 +148,21 @@ TEST_CASE("Verifying mesh topology creation", "[NoC Arch Tests]") {
t_noc_inf test_noc;

// mesh parameters
double mesh_start_x = 10;
double mesh_start_y = 10;
double mesh_end_x = 5;
double mesh_end_y = 56;
double mesh_size = 0;
float mesh_start_x = 10;
float mesh_start_y = 10;
float mesh_end_x = 5;
float mesh_end_y = 56;
float mesh_size = 0;
int mesh_start_layer = 0;
int mesh_end_layer = 0;

SECTION("Check the error where a mesh size was illegal.") {
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.");
REQUIRE_THROWS_WITH(generate_noc_mesh(test, test_location, &test_noc, mesh_start_x, mesh_end_x, mesh_start_y, mesh_end_y, mesh_start_layer, mesh_end_layer, mesh_size), "The NoC mesh size cannot be 0.");
}
SECTION("Check the error where a mesh region size was invalid.") {
mesh_size = 3;

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.");
REQUIRE_THROWS_WITH(generate_noc_mesh(test, test_location, &test_noc, mesh_start_x, mesh_end_x, mesh_start_y, mesh_end_y, mesh_start_layer, mesh_end_layer, mesh_size), "The NoC region is invalid.");
}
SECTION("Check the mesh creation for integer precision coordinates.") {
// define test parameters
Expand All @@ -173,8 +175,8 @@ TEST_CASE("Verifying mesh topology creation", "[NoC Arch Tests]") {
mesh_end_y = 4;

// create the golden results
double golden_results_x[9];
double golden_results_y[9];
float golden_results_x[9];
float golden_results_y[9];

// first row of the mesh
golden_results_x[0] = 0;
Expand All @@ -200,7 +202,7 @@ TEST_CASE("Verifying mesh topology creation", "[NoC Arch Tests]") {
golden_results_x[8] = 4;
golden_results_y[8] = 4;

generate_noc_mesh(test, test_location, &test_noc, mesh_start_x, mesh_end_x, mesh_start_y, mesh_end_y, mesh_size);
generate_noc_mesh(test, test_location, &test_noc, mesh_start_x, mesh_end_x, mesh_start_y, mesh_end_y, mesh_start_layer, mesh_end_layer, mesh_size);

// go through all the expected routers
for (int expected_router_id = 0; expected_router_id < (mesh_size * mesh_size); expected_router_id++) {
Expand All @@ -224,9 +226,9 @@ TEST_CASE("Verifying mesh topology creation", "[NoC Arch Tests]") {
mesh_end_x = 10.8;
mesh_end_y = 6.4;

// create the golden golden results
double golden_results_x[9];
double golden_results_y[9];
// create the golden results
float golden_results_x[9];
float golden_results_y[9];

// first row of the mesh
golden_results_x[0] = 3.5;
Expand All @@ -252,7 +254,7 @@ TEST_CASE("Verifying mesh topology creation", "[NoC Arch Tests]") {
golden_results_x[8] = 10.8;
golden_results_y[8] = 6.4;

generate_noc_mesh(test, test_location, &test_noc, mesh_start_x, mesh_end_x, mesh_start_y, mesh_end_y, mesh_size);
generate_noc_mesh(test, test_location, &test_noc, mesh_start_x, mesh_end_x, mesh_start_y, mesh_end_y, mesh_start_layer, mesh_end_layer, mesh_size);

// go through all the expected routers
for (int expected_router_id = 0; expected_router_id < (mesh_size * mesh_size); expected_router_id++) {
Expand Down
31 changes: 31 additions & 0 deletions libs/libvtrutil/src/vtr_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,25 @@ std::string join(Container container, std::string_view delim);
template<typename T>
std::string join(std::initializer_list<T> list, std::string_view delim);

/**
* @brief Checks if exactly `k` conditions are true.
*
* @tparam Conditions A variadic template parameter pack representing the types of the conditions,
* which should all be convertible to `bool`.
* @param k The exact number of conditions that should evaluate to true.
* @param conditions A variable number of boolean expressions or conditions to evaluate.
* @return `true` if exactly `k` of the provided conditions are true; otherwise `false`.
*
* @example
* @code
* bool result = exactly_k_conditions(2, true, false, true); // Returns true
* result = exactly_k_conditions(1, true, false, false); // Returns true
* result = exactly_k_conditions(3, true, true, false); // Returns false
* @endcode
*/
template<typename... Conditions>
soheilshahrouz marked this conversation as resolved.
Show resolved Hide resolved
bool exactly_k_conditions(int k, Conditions... conditions);

template<typename Container>
void uniquify(Container container);

Expand Down Expand Up @@ -116,6 +135,18 @@ void uniquify(Container container) {
container.end());
}

template<typename... Conditions>
bool exactly_k_conditions(int k, Conditions... conditions) {
bool conditionArray[] = {conditions...};
int count = 0;
for (bool condition : conditionArray) {
if (condition) {
count++;
}
}
return count == k;
}

int get_pid();

} // namespace vtr
Expand Down
Loading