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
@@ -3936,6 +3937,43 @@ static void ProcessSegments(pugi::xml_node Parent,
3936
3937
" Atleast one segment per-axis needs to get specified if no segments with non-specified (default) axis attribute exist." );
3937
3938
}
3938
3939
}
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
+
3939
3977
/* Processes the switchblocklist section from the xml architecture file.
3940
3978
* See vpr/SRC/route/build_switchblocks.c for a detailed description of this
3941
3979
* switch block format */
@@ -3947,6 +3985,14 @@ static void ProcessSwitchblocks(pugi::xml_node Parent, t_arch* arch, const pugiu
3947
3985
/* get the number of switchblocks */
3948
3986
int num_switchblocks = count_children (Parent, " switchblock" , loc_data);
3949
3987
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
+ }
3950
3996
3951
3997
/* read-in all switchblock data */
3952
3998
Node = get_first_child (Parent, " switchblock" , loc_data);
@@ -3977,20 +4023,56 @@ static void ProcessSwitchblocks(pugi::xml_node Parent, t_arch* arch, const pugiu
3977
4023
tmp = get_attribute (SubElem, " type" , loc_data).as_string (nullptr );
3978
4024
if (tmp) {
3979
4025
if (strcmp (tmp, " EVERYWHERE" ) == 0 ) {
3980
- sb.location = E_EVERYWHERE;
4026
+ sb.location = e_sb_location:: E_EVERYWHERE;
3981
4027
} else if (strcmp (tmp, " PERIMETER" ) == 0 ) {
3982
- sb.location = E_PERIMETER;
4028
+ sb.location = e_sb_location:: E_PERIMETER;
3983
4029
} else if (strcmp (tmp, " CORE" ) == 0 ) {
3984
- sb.location = E_CORE;
4030
+ sb.location = e_sb_location:: E_CORE;
3985
4031
} else if (strcmp (tmp, " CORNER" ) == 0 ) {
3986
- sb.location = E_CORNER;
4032
+ sb.location = e_sb_location:: E_CORNER;
3987
4033
} 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;
3989
4037
} else {
3990
4038
archfpga_throw (loc_data.filename_c_str (), loc_data.line (SubElem), " unrecognized switchblock location: %s\n " , tmp);
3991
4039
}
3992
4040
}
3993
4041
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
+
3994
4076
/* get switchblock permutation functions */
3995
4077
SubElem = get_first_child (Node, " switchfuncs" , loc_data);
3996
4078
read_sb_switchfuncs (SubElem, &sb, loc_data);
0 commit comments