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

Specify different switch type to drive wires with different directions #2647

Merged
merged 18 commits into from
Aug 26, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
b4be0a5
changed the architecture parser to allow definition of mux_inc and mu…
saaramahmoudi Jul 16, 2024
5ea2e53
changed the RR graph switch selection for wires with different direct…
saaramahmoudi Jul 16, 2024
4610a9d
added the extra missing condition for bidir segments
saaramahmoudi Jul 16, 2024
1d3946b
Merge branch 'master' into diff_switches_for_inc_dec_wires
saaramahmoudi Jul 17, 2024
f11aaea
update documentation for segment definition in the architecture file
saaramahmoudi Jul 18, 2024
762ac7c
added a simple architecture to test different mux for inc and dec wires
saaramahmoudi Jul 18, 2024
bada3f4
added a single task to compare diff mux for inc/dec with normal archi…
saaramahmoudi Jul 18, 2024
87ad1b9
added a similar task for odin
saaramahmoudi Jul 18, 2024
b8ef971
update task list for both strong and strong_odin
saaramahmoudi Jul 18, 2024
4cea89f
update the <mux> tag within wire segments
saaramahmoudi Jul 18, 2024
443c2c8
Merge branch 'master' into diff_switches_for_inc_dec_wires
saaramahmoudi Jul 18, 2024
4d2affa
initialize the dec muxes to -1 to avoid any random values if not spec…
saaramahmoudi Jul 18, 2024
7948773
Merge branch 'master' into diff_switches_for_inc_dec_wires
saaramahmoudi Jul 22, 2024
ba408fd
Fixed a typo in task list
saaramahmoudi Jul 22, 2024
a48ed5f
Merge branch 'master' into diff_switches_for_inc_dec_wires
saaramahmoudi Jul 25, 2024
f520da9
Merge branch 'master' into diff_switches_for_inc_dec_wires
saaramahmoudi Aug 9, 2024
cc7cdbf
Merge branch 'master' into diff_switches_for_inc_dec_wires
saaramahmoudi Aug 26, 2024
30f61a8
changed documentation, VB suggestions applied
saaramahmoudi Aug 26, 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
14 changes: 11 additions & 3 deletions libs/libarchfpga/src/physical_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -1561,6 +1561,12 @@ enum e_Fc_type {
* relation to the switches from the architecture file, *
* not the expanded list of switches that is built *
* at the end of build_rr_graph *
* @param arch_wire_switch_dec: Same as arch_wire_switch but used only for *
* decremental tracks if it is specified in the *
* architecture file. *
saaramahmoudi marked this conversation as resolved.
Show resolved Hide resolved
* @param arch_opin_switch_dec: Same as arch_opin_switch but used only for *
* decremental tracks if it is specified in the *
* architecture file *
saaramahmoudi marked this conversation as resolved.
Show resolved Hide resolved
* *
* @param arch_opin_between_dice_switch: Index of the switch type that *
* connects output pins (OPINs) *to* this segment from *
Expand All @@ -1579,14 +1585,14 @@ enum e_Fc_type {
* Cmetal: Capacitance of a routing track, per unit logic block length. *
* Rmetal: Resistance of a routing track, per unit logic block length. *
* (UDSD by AY) drivers: How do signals driving a routing track connect to *
* the track?
* the track? *
* seg_index: The index of the segment as stored in the appropriate Segs list*
* Upon loading the architecture, we use this field to keep track *
* the segment's index in the unified segment_inf vector. This is *
* useful when building the rr_graph for different Y & X channels *
* in terms of track distribution and segment type. *
* in terms of track distribution and segment type. *
* res_type: Determines the routing network to which the segment belongs. *
* Possible values are:
* Possible values are: *
* - GENERAL: The segment is part of the general routing *
* resources. *
* - GCLK: The segment is part of the global routing network. *
Expand All @@ -1600,6 +1606,8 @@ struct t_segment_inf {
int length;
short arch_wire_switch;
short arch_opin_switch;
short arch_wire_switch_dec;
short arch_opin_switch_dec;
short arch_opin_between_dice_switch = -1;
float frac_cb;
float frac_sb;
Expand Down
88 changes: 71 additions & 17 deletions libs/libarchfpga/src/read_xml_arch_file.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3766,6 +3766,10 @@ static void ProcessSegments(pugi::xml_node Parent,
//Unidir requires the following tags
expected_subtags.emplace_back("mux");
expected_subtags.emplace_back("mux_inter_die");
//with the following two tags, we can allow the architecture file to define
//different muxes with different delays for wires with different directions
expected_subtags.emplace_back("mux_inc");
expected_subtags.emplace_back("mux_dec");
}

else {
Expand Down Expand Up @@ -3796,28 +3800,78 @@ static void ProcessSegments(pugi::xml_node Parent,
/* Get the wire and opin switches, or mux switch if unidir */
if (UNI_DIRECTIONAL == Segs[i].directionality) {
//Get the switch name for same die wire and track connections
SubElem = get_single_child(Node, "mux", loc_data);
tmp = get_attribute(SubElem, "name", loc_data).value();

/* Match names */
for (j = 0; j < NumSwitches; ++j) {
if (0 == strcmp(tmp, Switches[j].name.c_str())) {
break; /* End loop so j is where we want it */
SubElem = get_single_child(Node, "mux", loc_data, ReqOpt::OPTIONAL);
tmp = get_attribute(SubElem, "name", loc_data, ReqOpt::OPTIONAL).as_string(nullptr);

//check if <mux> tag is defined in the architecture, otherwise we should look for <mux_inc> and <mux_dec>
if(tmp){
/* Match names */
for (j = 0; j < NumSwitches; ++j) {
if (0 == strcmp(tmp, Switches[j].name.c_str())) {
break; /* End loop so j is where we want it */
}
}
if (j >= NumSwitches) {
archfpga_throw(loc_data.filename_c_str(), loc_data.line(SubElem),
"'%s' is not a valid mux name.\n", tmp);
}

/* Unidir muxes must have the same switch
* for wire and opin fanin since there is
* really only the mux in unidir. */
Segs[i].arch_wire_switch = j;
Segs[i].arch_opin_switch = j;
}
if (j >= NumSwitches) {
archfpga_throw(loc_data.filename_c_str(), loc_data.line(SubElem),
"'%s' is not a valid mux name.\n", tmp);
}
else { //if a general mux is not defined, we should look for specific mux for each direction in the architecture file
SubElem = get_single_child(Node, "mux_inc", loc_data, ReqOpt::OPTIONAL);
tmp = get_attribute(SubElem, "name", loc_data, ReqOpt::OPTIONAL).as_string(nullptr);
if(!tmp){
archfpga_throw(loc_data.filename_c_str(), loc_data.line(SubElem),
"if mux is not specified in a wire segment, both mux_inc and mux_dec should be specified");
} else{
/* Match names */
for (j = 0; j < NumSwitches; ++j) {
if (0 == strcmp(tmp, Switches[j].name.c_str())) {
break; /* End loop so j is where we want it */
}
}
if (j >= NumSwitches) {
archfpga_throw(loc_data.filename_c_str(), loc_data.line(SubElem),
"'%s' is not a valid mux name.\n", tmp);
}

/* Unidir muxes must have the same switch
* for wire and opin fanin since there is
* really only the mux in unidir. */
Segs[i].arch_wire_switch = j;
Segs[i].arch_opin_switch = j;
/* Unidir muxes must have the same switch
* for wire and opin fanin since there is
* really only the mux in unidir. */
Segs[i].arch_wire_switch = j;
Segs[i].arch_opin_switch = j;
}

}
SubElem = get_single_child(Node, "mux_dec", loc_data, ReqOpt::OPTIONAL);
tmp = get_attribute(SubElem, "name", loc_data, ReqOpt::OPTIONAL).as_string(nullptr);
if(!tmp){
archfpga_throw(loc_data.filename_c_str(), loc_data.line(SubElem),
"if mux is not specified in a wire segment, both mux_inc and mux_dec should be specified");
} else{
/* Match names */
for (j = 0; j < NumSwitches; ++j) {
if (0 == strcmp(tmp, Switches[j].name.c_str())) {
break; /* End loop so j is where we want it */
}
}
if (j >= NumSwitches) {
archfpga_throw(loc_data.filename_c_str(), loc_data.line(SubElem),
"'%s' is not a valid mux name.\n", tmp);
}

/* Unidir muxes must have the same switch
* for wire and opin fanin since there is
* really only the mux in unidir. */
Segs[i].arch_wire_switch_dec = j;
Segs[i].arch_opin_switch_dec = j;
}
}
}
else {
VTR_ASSERT(BI_DIRECTIONAL == Segs[i].directionality);
SubElem = get_single_child(Node, "wire_switch", loc_data);
Expand Down
21 changes: 17 additions & 4 deletions vpr/src/route/rr_graph2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,8 @@ t_seg_details* alloc_and_load_seg_details(int* max_chan_width,
* as they will not be staggered by different segment start points. */

int cur_track, ntracks, itrack, length, j, index;
int arch_wire_switch, arch_opin_switch, fac, num_sets, tmp;
int fac, num_sets, tmp;
int arch_wire_switch, arch_opin_switch, arch_wire_switch_dec, arch_opin_switch_dec;
int arch_opin_between_dice_switch;
int group_start, first_track;
std::unique_ptr<int[]> sets_per_seg_type;
Expand Down Expand Up @@ -352,8 +353,10 @@ t_seg_details* alloc_and_load_seg_details(int* max_chan_width,

arch_wire_switch = segment_inf[i].arch_wire_switch;
arch_opin_switch = segment_inf[i].arch_opin_switch;
arch_wire_switch_dec = segment_inf[i].arch_wire_switch_dec;
arch_opin_switch_dec = segment_inf[i].arch_opin_switch_dec;
arch_opin_between_dice_switch = segment_inf[i].arch_opin_between_dice_switch;
VTR_ASSERT((arch_wire_switch == arch_opin_switch) || (directionality != UNI_DIRECTIONAL));
VTR_ASSERT((arch_wire_switch == arch_opin_switch && arch_wire_switch_dec == arch_opin_switch_dec) || (directionality != UNI_DIRECTIONAL));

/* Set up the tracks of same type */
group_start = 0;
Expand Down Expand Up @@ -416,8 +419,6 @@ t_seg_details* alloc_and_load_seg_details(int* max_chan_width,
seg_details[cur_track].Cmetal = segment_inf[i].Cmetal;
//seg_details[cur_track].Cmetal_per_m = segment_inf[i].Cmetal_per_m;

seg_details[cur_track].arch_wire_switch = arch_wire_switch;
seg_details[cur_track].arch_opin_switch = arch_opin_switch;
seg_details[cur_track].arch_opin_between_dice_switch = arch_opin_between_dice_switch;

if (BI_DIRECTIONAL == directionality) {
Expand All @@ -427,6 +428,18 @@ t_seg_details* alloc_and_load_seg_details(int* max_chan_width,
seg_details[cur_track].direction = (itrack % 2) ? Direction::DEC : Direction::INC;
}

//check for directionality to set the wire_switch and opin_switch
//if not specified in the architecture file, we will use a same mux for both directions
if (seg_details[cur_track].direction == Direction::INC || seg_details[cur_track].direction == Direction::BIDIR || arch_wire_switch_dec == -1){
seg_details[cur_track].arch_opin_switch = arch_opin_switch;
seg_details[cur_track].arch_wire_switch = arch_wire_switch;
}
else {
VTR_ASSERT(seg_details[cur_track].direction == Direction::DEC);
seg_details[cur_track].arch_opin_switch = arch_opin_switch_dec;
seg_details[cur_track].arch_wire_switch = arch_wire_switch_dec;
}

seg_details[cur_track].index = i;
seg_details[cur_track].abs_index = segment_inf[i].seg_index;

Expand Down
Loading