Skip to content

Commit 762e816

Browse files
authored
Merge pull request #2664 from verilog-to-routing/specify_loc_for_custom_SB
Specify a single location or a specific region for a custom switch block
2 parents f85b422 + b3d803b commit 762e816

File tree

8 files changed

+48543
-137
lines changed

8 files changed

+48543
-137
lines changed

libs/libarchfpga/src/physical_types.h

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -253,12 +253,23 @@ typedef enum e_power_estimation_method_ e_power_estimation_method;
253253
typedef enum e_power_estimation_method_ t_power_estimation_method;
254254

255255
/* Specifies what part of the FPGA a custom switchblock should be built in (i.e. perimeter, core, everywhere) */
256-
enum e_sb_location {
256+
enum class e_sb_location {
257257
E_PERIMETER = 0,
258258
E_CORNER,
259259
E_FRINGE, /* perimeter minus corners */
260260
E_CORE,
261-
E_EVERYWHERE
261+
E_EVERYWHERE,
262+
E_XY_SPECIFIED
263+
};
264+
265+
/**
266+
* @brief Describes regions that a specific switch block specifications should be applied to
267+
*/
268+
struct t_sb_loc_spec {
269+
int start = -1;
270+
int repeat = -1;
271+
int incr = -1;
272+
int end = -1;
262273
};
263274

264275
/*************************************************************************************************/
@@ -1933,6 +1944,13 @@ struct t_switchblock_inf {
19331944
e_sb_location location; /* where on the FPGA this switchblock should be built (i.e. perimeter, core, everywhere) */
19341945
e_directionality directionality; /* the directionality of this switchblock (unidir/bidir) */
19351946

1947+
int x = -1; /* The exact x-axis location that this SB is used, meaningful when type is set to E_XY_specified */
1948+
int y = -1; /* The exact y-axis location that this SB is used, meanignful when type is set to E_XY_specified */
1949+
1950+
/* We can also define a region to apply this SB to all locations falls into this region using regular expression in the architecture file*/
1951+
t_sb_loc_spec reg_x;
1952+
t_sb_loc_spec reg_y;
1953+
19361954
t_permutation_map permutation_map; /* map holding the permutation functions attributed to this switchblock */
19371955

19381956
std::vector<t_wireconn_inf> wireconns; /* list of wire types/groups this SB will connect */
@@ -2086,6 +2104,11 @@ struct t_arch {
20862104
std::vector<std::string> ipin_cblock_switch_name;
20872105

20882106
std::vector<t_grid_def> grid_layouts; //Set of potential device layouts
2107+
2108+
//the layout that is chosen to be used with command line options
2109+
//It is used to generate custom SB for a specific locations within the device
2110+
//If the layout is not specified in the command line options, this variable will be set to "auto"
2111+
std::string device_layout;
20892112

20902113
t_clock_arch_spec clock_arch; // Clock related data types
20912114

libs/libarchfpga/src/read_xml_arch_file.cpp

Lines changed: 87 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
#include "parse_switchblocks.h"
6565

6666
#include "physical_types_util.h"
67+
#include "vtr_expr_eval.h"
6768

6869
#include "read_xml_arch_file_noc_tag.h"
6970

@@ -3936,6 +3937,43 @@ static void ProcessSegments(pugi::xml_node Parent,
39363937
"Atleast one segment per-axis needs to get specified if no segments with non-specified (default) axis attribute exist.");
39373938
}
39383939
}
3940+
3941+
3942+
static void calculate_custom_SB_locations(const pugiutil::loc_data& loc_data, const pugi::xml_node& SubElem, const int grid_width, const int grid_height, t_switchblock_inf& sb){
3943+
auto startx_attr = get_attribute(SubElem, "startx", loc_data, ReqOpt::OPTIONAL);
3944+
auto endx_attr = get_attribute(SubElem, "endx", loc_data, ReqOpt::OPTIONAL);
3945+
3946+
auto starty_attr = get_attribute(SubElem, "starty", loc_data, ReqOpt::OPTIONAL);
3947+
auto endy_attr = get_attribute(SubElem, "endy", loc_data, ReqOpt::OPTIONAL);
3948+
3949+
auto repeatx_attr = get_attribute(SubElem, "repeatx", loc_data, ReqOpt::OPTIONAL);
3950+
auto repeaty_attr = get_attribute(SubElem, "repeaty", loc_data, ReqOpt::OPTIONAL);
3951+
3952+
auto incrx_attr = get_attribute(SubElem, "incrx", loc_data, ReqOpt::OPTIONAL);
3953+
auto incry_attr = get_attribute(SubElem, "incry", loc_data, ReqOpt::OPTIONAL);
3954+
3955+
//parse the values from the architecture file and fill out SB region information
3956+
vtr::FormulaParser p;
3957+
3958+
vtr::t_formula_data vars;
3959+
vars.set_var_value("W", grid_width);
3960+
vars.set_var_value("H", grid_height);
3961+
3962+
3963+
sb.reg_x.start = startx_attr.empty() ? 0 : p.parse_formula(startx_attr.value(), vars);
3964+
sb.reg_y.start = starty_attr.empty() ? 0 : p.parse_formula(starty_attr.value(), vars);
3965+
3966+
sb.reg_x.end = endx_attr.empty() ? (grid_width - 1) : p.parse_formula(endx_attr.value(), vars);
3967+
sb.reg_y.end = endy_attr.empty() ? (grid_height -1) : p.parse_formula(endy_attr.value(), vars);
3968+
3969+
sb.reg_x.repeat = repeatx_attr.empty() ? 0 : p.parse_formula(repeatx_attr.value(), vars);
3970+
sb.reg_y.repeat = repeaty_attr.empty() ? 0 : p.parse_formula(repeaty_attr.value(), vars);
3971+
3972+
sb.reg_x.incr = incrx_attr.empty() ? 1 : p.parse_formula(incrx_attr.value(), vars);
3973+
sb.reg_y.incr = incry_attr.empty() ? 1 : p.parse_formula(incry_attr.value(), vars);
3974+
3975+
}
3976+
39393977
/* Processes the switchblocklist section from the xml architecture file.
39403978
* See vpr/SRC/route/build_switchblocks.c for a detailed description of this
39413979
* switch block format */
@@ -3947,6 +3985,14 @@ static void ProcessSwitchblocks(pugi::xml_node Parent, t_arch* arch, const pugiu
39473985
/* get the number of switchblocks */
39483986
int num_switchblocks = count_children(Parent, "switchblock", loc_data);
39493987
arch->switchblocks.reserve(num_switchblocks);
3988+
3989+
int layout_index = -1;
3990+
for(layout_index = 0; layout_index < (int) arch->grid_layouts.size(); layout_index++){
3991+
if(arch->grid_layouts.at(layout_index).name == arch->device_layout){
3992+
//found the used layout
3993+
break;
3994+
}
3995+
}
39503996

39513997
/* read-in all switchblock data */
39523998
Node = get_first_child(Parent, "switchblock", loc_data);
@@ -3977,20 +4023,56 @@ static void ProcessSwitchblocks(pugi::xml_node Parent, t_arch* arch, const pugiu
39774023
tmp = get_attribute(SubElem, "type", loc_data).as_string(nullptr);
39784024
if (tmp) {
39794025
if (strcmp(tmp, "EVERYWHERE") == 0) {
3980-
sb.location = E_EVERYWHERE;
4026+
sb.location = e_sb_location::E_EVERYWHERE;
39814027
} else if (strcmp(tmp, "PERIMETER") == 0) {
3982-
sb.location = E_PERIMETER;
4028+
sb.location = e_sb_location::E_PERIMETER;
39834029
} else if (strcmp(tmp, "CORE") == 0) {
3984-
sb.location = E_CORE;
4030+
sb.location = e_sb_location::E_CORE;
39854031
} else if (strcmp(tmp, "CORNER") == 0) {
3986-
sb.location = E_CORNER;
4032+
sb.location = e_sb_location::E_CORNER;
39874033
} else if (strcmp(tmp, "FRINGE") == 0) {
3988-
sb.location = E_FRINGE;
4034+
sb.location = e_sb_location::E_FRINGE;
4035+
} else if (strcmp(tmp, "XY_SPECIFIED") == 0) {
4036+
sb.location = e_sb_location::E_XY_SPECIFIED;
39894037
} else {
39904038
archfpga_throw(loc_data.filename_c_str(), loc_data.line(SubElem), "unrecognized switchblock location: %s\n", tmp);
39914039
}
39924040
}
39934041

4042+
/* get the switchblock coordinate only if sb.location is set to E_XY_SPECIFIED*/
4043+
if(sb.location == e_sb_location::E_XY_SPECIFIED){
4044+
if (arch->device_layout == "auto"){
4045+
archfpga_throw(loc_data.filename_c_str(), loc_data.line(SubElem), "Specifying SB locations for auto layout devices are not supported yet!\n");
4046+
}
4047+
expect_only_attributes(SubElem,
4048+
{"x", "y", "type",
4049+
"startx", "endx", "repeatx", "incrx",
4050+
"starty", "endy", "repeaty", "incry"},
4051+
loc_data);
4052+
4053+
int grid_width = arch->grid_layouts.at(layout_index).width;
4054+
int grid_height = arch->grid_layouts.at(layout_index).height;
4055+
4056+
/* Absolute location that this SB must be applied to, -1 if not specified*/
4057+
sb.x = get_attribute(SubElem, "x", loc_data, ReqOpt::OPTIONAL).as_int(-1);
4058+
sb.y = get_attribute(SubElem, "y", loc_data, ReqOpt::OPTIONAL).as_int(-1);
4059+
4060+
//check if the absolute value is within the device grid width and height
4061+
if(sb.x >= grid_width || sb.y >= grid_height) {
4062+
archfpga_throw(loc_data.filename_c_str(), loc_data.line(SubElem), \
4063+
"Location (%d,%d) is not valid within the grid! grid dimensions are: (%d,%d)\n", sb.x, sb.y, grid_width, grid_height);
4064+
}
4065+
4066+
/* if the the switchblock exact location is not specified and a region is specified within the architecture file,
4067+
* we have to parse the region specification and apply the SB pattern to all the locations fall into the specified
4068+
* region based on device width and height.
4069+
*/
4070+
if (sb.x == -1 && sb.y == -1) {
4071+
calculate_custom_SB_locations(loc_data, SubElem, grid_width, grid_height, sb);
4072+
}
4073+
4074+
}
4075+
39944076
/* get switchblock permutation functions */
39954077
SubElem = get_first_child(Node, "switchfuncs", loc_data);
39964078
read_sb_switchfuncs(SubElem, &sb, loc_data);

0 commit comments

Comments
 (0)