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