64
64
#include " parse_switchblocks.h"
65
65
66
66
#include " physical_types_util.h"
67
+ #include " vtr_expr_eval.h"
67
68
68
69
#include " read_xml_arch_file_noc_tag.h"
69
70
@@ -4100,6 +4101,43 @@ static void ProcessSegments(pugi::xml_node Parent,
4100
4101
" Atleast one segment per-axis needs to get specified if no segments with non-specified (default) axis attribute exist." );
4101
4102
}
4102
4103
}
4104
+
4105
+
4106
+ 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){
4107
+ auto startx_attr = get_attribute (SubElem, " startx" , loc_data, ReqOpt::OPTIONAL);
4108
+ auto endx_attr = get_attribute (SubElem, " endx" , loc_data, ReqOpt::OPTIONAL);
4109
+
4110
+ auto starty_attr = get_attribute (SubElem, " starty" , loc_data, ReqOpt::OPTIONAL);
4111
+ auto endy_attr = get_attribute (SubElem, " endy" , loc_data, ReqOpt::OPTIONAL);
4112
+
4113
+ auto repeatx_attr = get_attribute (SubElem, " repeatx" , loc_data, ReqOpt::OPTIONAL);
4114
+ auto repeaty_attr = get_attribute (SubElem, " repeaty" , loc_data, ReqOpt::OPTIONAL);
4115
+
4116
+ auto incrx_attr = get_attribute (SubElem, " incrx" , loc_data, ReqOpt::OPTIONAL);
4117
+ auto incry_attr = get_attribute (SubElem, " incry" , loc_data, ReqOpt::OPTIONAL);
4118
+
4119
+ // parse the values from the architecture file and fill out SB region information
4120
+ vtr::FormulaParser p;
4121
+
4122
+ vtr::t_formula_data vars;
4123
+ vars.set_var_value (" W" , grid_width);
4124
+ vars.set_var_value (" H" , grid_height);
4125
+
4126
+
4127
+ sb.reg_x .start = startx_attr.empty () ? 0 : p.parse_formula (startx_attr.value (), vars);
4128
+ sb.reg_y .start = starty_attr.empty () ? 0 : p.parse_formula (starty_attr.value (), vars);
4129
+
4130
+ sb.reg_x .end = endx_attr.empty () ? (grid_width - 1 ) : p.parse_formula (endx_attr.value (), vars);
4131
+ sb.reg_y .end = endy_attr.empty () ? (grid_height -1 ) : p.parse_formula (endy_attr.value (), vars);
4132
+
4133
+ sb.reg_x .repeat = repeatx_attr.empty () ? 0 : p.parse_formula (repeatx_attr.value (), vars);
4134
+ sb.reg_y .repeat = repeaty_attr.empty () ? 0 : p.parse_formula (repeaty_attr.value (), vars);
4135
+
4136
+ sb.reg_x .incr = incrx_attr.empty () ? 1 : p.parse_formula (incrx_attr.value (), vars);
4137
+ sb.reg_y .incr = incry_attr.empty () ? 1 : p.parse_formula (incry_attr.value (), vars);
4138
+
4139
+ }
4140
+
4103
4141
/* Processes the switchblocklist section from the xml architecture file.
4104
4142
* See vpr/SRC/route/build_switchblocks.c for a detailed description of this
4105
4143
* switch block format */
@@ -4111,6 +4149,14 @@ static void ProcessSwitchblocks(pugi::xml_node Parent, t_arch* arch, const pugiu
4111
4149
/* get the number of switchblocks */
4112
4150
int num_switchblocks = count_children (Parent, " switchblock" , loc_data);
4113
4151
arch->switchblocks .reserve (num_switchblocks);
4152
+
4153
+ int layout_index = -1 ;
4154
+ for (layout_index = 0 ; layout_index < (int ) arch->grid_layouts .size (); layout_index++){
4155
+ if (arch->grid_layouts .at (layout_index).name == arch->device_layout ){
4156
+ // found the used layout
4157
+ break ;
4158
+ }
4159
+ }
4114
4160
4115
4161
/* read-in all switchblock data */
4116
4162
Node = get_first_child (Parent, " switchblock" , loc_data);
@@ -4141,20 +4187,56 @@ static void ProcessSwitchblocks(pugi::xml_node Parent, t_arch* arch, const pugiu
4141
4187
tmp = get_attribute (SubElem, " type" , loc_data).as_string (nullptr );
4142
4188
if (tmp) {
4143
4189
if (strcmp (tmp, " EVERYWHERE" ) == 0 ) {
4144
- sb.location = E_EVERYWHERE;
4190
+ sb.location = e_sb_location:: E_EVERYWHERE;
4145
4191
} else if (strcmp (tmp, " PERIMETER" ) == 0 ) {
4146
- sb.location = E_PERIMETER;
4192
+ sb.location = e_sb_location:: E_PERIMETER;
4147
4193
} else if (strcmp (tmp, " CORE" ) == 0 ) {
4148
- sb.location = E_CORE;
4194
+ sb.location = e_sb_location:: E_CORE;
4149
4195
} else if (strcmp (tmp, " CORNER" ) == 0 ) {
4150
- sb.location = E_CORNER;
4196
+ sb.location = e_sb_location:: E_CORNER;
4151
4197
} else if (strcmp (tmp, " FRINGE" ) == 0 ) {
4152
- sb.location = E_FRINGE;
4198
+ sb.location = e_sb_location::E_FRINGE;
4199
+ } else if (strcmp (tmp, " XY_SPECIFIED" ) == 0 ) {
4200
+ sb.location = e_sb_location::E_XY_SPECIFIED;
4153
4201
} else {
4154
4202
archfpga_throw (loc_data.filename_c_str (), loc_data.line (SubElem), " unrecognized switchblock location: %s\n " , tmp);
4155
4203
}
4156
4204
}
4157
4205
4206
+ /* get the switchblock coordinate only if sb.location is set to E_XY_SPECIFIED*/
4207
+ if (sb.location == e_sb_location::E_XY_SPECIFIED){
4208
+ if (arch->device_layout == " auto" ){
4209
+ archfpga_throw (loc_data.filename_c_str (), loc_data.line (SubElem), " Specifying SB locations for auto layout devices are not supported yet!\n " );
4210
+ }
4211
+ expect_only_attributes (SubElem,
4212
+ {" x" , " y" , " type" ,
4213
+ " startx" , " endx" , " repeatx" , " incrx" ,
4214
+ " starty" , " endy" , " repeaty" , " incry" },
4215
+ loc_data);
4216
+
4217
+ int grid_width = arch->grid_layouts .at (layout_index).width ;
4218
+ int grid_height = arch->grid_layouts .at (layout_index).height ;
4219
+
4220
+ /* Absolute location that this SB must be applied to, -1 if not specified*/
4221
+ sb.x = get_attribute (SubElem, " x" , loc_data, ReqOpt::OPTIONAL).as_int (-1 );
4222
+ sb.y = get_attribute (SubElem, " y" , loc_data, ReqOpt::OPTIONAL).as_int (-1 );
4223
+
4224
+ // check if the absolute value is within the device grid width and height
4225
+ if (sb.x >= grid_width || sb.y >= grid_height) {
4226
+ archfpga_throw (loc_data.filename_c_str (), loc_data.line (SubElem), \
4227
+ " Location (%d,%d) is not valid within the grid! grid dimensions are: (%d,%d)\n " , sb.x , sb.y , grid_width, grid_height);
4228
+ }
4229
+
4230
+ /* if the the switchblock exact location is not specified and a region is specified within the architecture file,
4231
+ * we have to parse the region specification and apply the SB pattern to all the locations fall into the specified
4232
+ * region based on device width and height.
4233
+ */
4234
+ if (sb.x == -1 && sb.y == -1 ) {
4235
+ calculate_custom_SB_locations (loc_data, SubElem, grid_width, grid_height, sb);
4236
+ }
4237
+
4238
+ }
4239
+
4158
4240
/* get switchblock permutation functions */
4159
4241
SubElem = get_first_child (Node, " switchfuncs" , loc_data);
4160
4242
read_sb_switchfuncs (SubElem, &sb, loc_data);
0 commit comments