Skip to content

Commit b69fa0e

Browse files
authored
Merge pull request #2647 from verilog-to-routing/diff_switches_for_inc_dec_wires
Specify different switch type to drive wires with different directions
2 parents 79a5bc8 + 30f61a8 commit b69fa0e

File tree

11 files changed

+479
-26
lines changed

11 files changed

+479
-26
lines changed

doc/src/arch/reference.rst

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2031,17 +2031,40 @@ The ``<segment>`` tag and its contents are described below.
20312031
.. arch:tag:: <mux name="string"/>
20322032
20332033
:req_param name: Name of the mux switch type used to drive this type of segment by default, from both block outputs and other wires. This information is used during rr-graph construction, and a custom switch block can override this switch type for specific connections if desired.
2034+
The switch type specified with the <mux> tag will be used for both the incrementing and decrementing wires within this segment.
2035+
If more control is needed, the mux_inc and mux_dec tags can be used to assign different muxes to drive incremental and decremental wires within the segment.
20342036
20352037
.. note:: For UNIDIRECTIONAL only.
20362038
20372039
Tag must be included and ``name`` must be the same as the name you give in ``<switch type="mux" name="...``
20382040
2041+
.. arch:tag:: <mux_inc name="string"/>
2042+
2043+
:req_param name:
2044+
Name of the mux switch type used to drive the incremental wires in this segment from both block outputs and other wires.
2045+
Incremental wires are tracks within this segment that are heading in the "right" direction on the x-axis and the "top" direction on the y-axis.
2046+
This information is used during rr-graph construction, and a custom switch block can override this switch type for specific connections if desired.
2047+
2048+
.. note:: For UNIDIRECTIONAL only.
2049+
2050+
.. arch:tag:: <mux_dec name="string">
2051+
2052+
:req_param name:
2053+
Name of the mux switch type used to drive the decremental wires in this segment from both block outputs and other wires.
2054+
Incremental wires are tracks within this segment that are heading in the "left" direction on the x-axis and the "bottom" direction on the y-axis.
2055+
This information is used during rr-graph construction, and a custom switch block can override this switch type for specific connections if desired.
2056+
2057+
.. note:: For UNIDIRECTIONAL only.
2058+
2059+
.. note:: For unidirectional segments, either <mux> tag or both <mux_inc> and <mux_dec> should be defined in the architecture file. If only the <mux> tag is defined, we assume that the same mux drives both incremental and decremental wires within this segment.
2060+
20392061
.. arch:tag:: <mux_inter_die name="string"/>
20402062
20412063
:req_param name: Name of the mux switch type used to drive this segment type when the driver (block outputs and other wires) is located on a different die than the segment. This information is utilized during rr-graph construction.
20422064

20432065
Tag must be included and ``name`` must be the same as the name you give in ``<switch type="mux" name="...``
20442066

2067+
20452068
.. arch:tag:: <wire_switch name="string"/>
20462069
20472070
:req_param name: Name of the switch type used by other wires to drive this type of segment by default. This information is used during rr-graph construction, and a custom switch block can override this switch type for specific connections if desired.

libs/libarchfpga/src/physical_types.h

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1567,7 +1567,16 @@ enum e_Fc_type {
15671567
* relation to the switches from the architecture file, *
15681568
* not the expanded list of switches that is built *
15691569
* at the end of build_rr_graph *
1570-
* *
1570+
* @param arch_wire_switch_dec: Same as arch_wire_switch but used only for *
1571+
* decremental tracks if it is specified in the *
1572+
* architecture file. If -1, this value was not set in *
1573+
* the architecture file and arch_wire_switch should be *
1574+
* used for "DEC_DIR" wire segments. *
1575+
* @param arch_opin_switch_dec: Same as arch_opin_switch but used only for *
1576+
* decremental tracks if it is specified in the *
1577+
* architecture file. If -1, this value was not set in *
1578+
* the architecture file and arch_opin_switch should be *
1579+
* used for "DEC_DIR" wire segments. *
15711580
* @param arch_opin_between_dice_switch: Index of the switch type that *
15721581
* connects output pins (OPINs) *to* this segment from *
15731582
* *another die (layer)*. Note that this index is in *
@@ -1585,14 +1594,14 @@ enum e_Fc_type {
15851594
* Cmetal: Capacitance of a routing track, per unit logic block length. *
15861595
* Rmetal: Resistance of a routing track, per unit logic block length. *
15871596
* (UDSD by AY) drivers: How do signals driving a routing track connect to *
1588-
* the track?
1597+
* the track? *
15891598
* seg_index: The index of the segment as stored in the appropriate Segs list*
15901599
* Upon loading the architecture, we use this field to keep track *
15911600
* the segment's index in the unified segment_inf vector. This is *
15921601
* useful when building the rr_graph for different Y & X channels *
1593-
* in terms of track distribution and segment type. *
1602+
* in terms of track distribution and segment type. *
15941603
* res_type: Determines the routing network to which the segment belongs. *
1595-
* Possible values are:
1604+
* Possible values are: *
15961605
* - GENERAL: The segment is part of the general routing *
15971606
* resources. *
15981607
* - GCLK: The segment is part of the global routing network. *
@@ -1606,6 +1615,8 @@ struct t_segment_inf {
16061615
int length;
16071616
short arch_wire_switch;
16081617
short arch_opin_switch;
1618+
short arch_wire_switch_dec = -1;
1619+
short arch_opin_switch_dec = -1;
16091620
short arch_opin_between_dice_switch = -1;
16101621
float frac_cb;
16111622
float frac_sb;

libs/libarchfpga/src/read_xml_arch_file.cpp

Lines changed: 71 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3766,6 +3766,10 @@ static void ProcessSegments(pugi::xml_node Parent,
37663766
//Unidir requires the following tags
37673767
expected_subtags.emplace_back("mux");
37683768
expected_subtags.emplace_back("mux_inter_die");
3769+
//with the following two tags, we can allow the architecture file to define
3770+
//different muxes with different delays for wires with different directions
3771+
expected_subtags.emplace_back("mux_inc");
3772+
expected_subtags.emplace_back("mux_dec");
37693773
}
37703774

37713775
else {
@@ -3796,28 +3800,78 @@ static void ProcessSegments(pugi::xml_node Parent,
37963800
/* Get the wire and opin switches, or mux switch if unidir */
37973801
if (UNI_DIRECTIONAL == Segs[i].directionality) {
37983802
//Get the switch name for same die wire and track connections
3799-
SubElem = get_single_child(Node, "mux", loc_data);
3800-
tmp = get_attribute(SubElem, "name", loc_data).value();
3801-
3802-
/* Match names */
3803-
for (j = 0; j < NumSwitches; ++j) {
3804-
if (0 == strcmp(tmp, Switches[j].name.c_str())) {
3805-
break; /* End loop so j is where we want it */
3803+
SubElem = get_single_child(Node, "mux", loc_data, ReqOpt::OPTIONAL);
3804+
tmp = get_attribute(SubElem, "name", loc_data, ReqOpt::OPTIONAL).as_string(nullptr);
3805+
3806+
//check if <mux> tag is defined in the architecture, otherwise we should look for <mux_inc> and <mux_dec>
3807+
if(tmp){
3808+
/* Match names */
3809+
for (j = 0; j < NumSwitches; ++j) {
3810+
if (0 == strcmp(tmp, Switches[j].name.c_str())) {
3811+
break; /* End loop so j is where we want it */
3812+
}
38063813
}
3814+
if (j >= NumSwitches) {
3815+
archfpga_throw(loc_data.filename_c_str(), loc_data.line(SubElem),
3816+
"'%s' is not a valid mux name.\n", tmp);
3817+
}
3818+
3819+
/* Unidir muxes must have the same switch
3820+
* for wire and opin fanin since there is
3821+
* really only the mux in unidir. */
3822+
Segs[i].arch_wire_switch = j;
3823+
Segs[i].arch_opin_switch = j;
38073824
}
3808-
if (j >= NumSwitches) {
3809-
archfpga_throw(loc_data.filename_c_str(), loc_data.line(SubElem),
3810-
"'%s' is not a valid mux name.\n", tmp);
3811-
}
3825+
else { //if a general mux is not defined, we should look for specific mux for each direction in the architecture file
3826+
SubElem = get_single_child(Node, "mux_inc", loc_data, ReqOpt::OPTIONAL);
3827+
tmp = get_attribute(SubElem, "name", loc_data, ReqOpt::OPTIONAL).as_string(nullptr);
3828+
if(!tmp){
3829+
archfpga_throw(loc_data.filename_c_str(), loc_data.line(SubElem),
3830+
"if mux is not specified in a wire segment, both mux_inc and mux_dec should be specified");
3831+
} else{
3832+
/* Match names */
3833+
for (j = 0; j < NumSwitches; ++j) {
3834+
if (0 == strcmp(tmp, Switches[j].name.c_str())) {
3835+
break; /* End loop so j is where we want it */
3836+
}
3837+
}
3838+
if (j >= NumSwitches) {
3839+
archfpga_throw(loc_data.filename_c_str(), loc_data.line(SubElem),
3840+
"'%s' is not a valid mux name.\n", tmp);
3841+
}
38123842

3813-
/* Unidir muxes must have the same switch
3814-
* for wire and opin fanin since there is
3815-
* really only the mux in unidir. */
3816-
Segs[i].arch_wire_switch = j;
3817-
Segs[i].arch_opin_switch = j;
3843+
/* Unidir muxes must have the same switch
3844+
* for wire and opin fanin since there is
3845+
* really only the mux in unidir. */
3846+
Segs[i].arch_wire_switch = j;
3847+
Segs[i].arch_opin_switch = j;
3848+
}
38183849

3819-
}
3850+
SubElem = get_single_child(Node, "mux_dec", loc_data, ReqOpt::OPTIONAL);
3851+
tmp = get_attribute(SubElem, "name", loc_data, ReqOpt::OPTIONAL).as_string(nullptr);
3852+
if(!tmp){
3853+
archfpga_throw(loc_data.filename_c_str(), loc_data.line(SubElem),
3854+
"if mux is not specified in a wire segment, both mux_inc and mux_dec should be specified");
3855+
} else{
3856+
/* Match names */
3857+
for (j = 0; j < NumSwitches; ++j) {
3858+
if (0 == strcmp(tmp, Switches[j].name.c_str())) {
3859+
break; /* End loop so j is where we want it */
3860+
}
3861+
}
3862+
if (j >= NumSwitches) {
3863+
archfpga_throw(loc_data.filename_c_str(), loc_data.line(SubElem),
3864+
"'%s' is not a valid mux name.\n", tmp);
3865+
}
38203866

3867+
/* Unidir muxes must have the same switch
3868+
* for wire and opin fanin since there is
3869+
* really only the mux in unidir. */
3870+
Segs[i].arch_wire_switch_dec = j;
3871+
Segs[i].arch_opin_switch_dec = j;
3872+
}
3873+
}
3874+
}
38213875
else {
38223876
VTR_ASSERT(BI_DIRECTIONAL == Segs[i].directionality);
38233877
SubElem = get_single_child(Node, "wire_switch", loc_data);

vpr/src/route/rr_graph2.cpp

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,8 @@ t_seg_details* alloc_and_load_seg_details(int* max_chan_width,
300300
* as they will not be staggered by different segment start points. */
301301

302302
int cur_track, ntracks, itrack, length, j, index;
303-
int arch_wire_switch, arch_opin_switch, fac, num_sets, tmp;
303+
int fac, num_sets, tmp;
304+
int arch_wire_switch, arch_opin_switch, arch_wire_switch_dec, arch_opin_switch_dec;
304305
int arch_opin_between_dice_switch;
305306
int group_start, first_track;
306307
std::unique_ptr<int[]> sets_per_seg_type;
@@ -352,8 +353,10 @@ t_seg_details* alloc_and_load_seg_details(int* max_chan_width,
352353

353354
arch_wire_switch = segment_inf[i].arch_wire_switch;
354355
arch_opin_switch = segment_inf[i].arch_opin_switch;
356+
arch_wire_switch_dec = segment_inf[i].arch_wire_switch_dec;
357+
arch_opin_switch_dec = segment_inf[i].arch_opin_switch_dec;
355358
arch_opin_between_dice_switch = segment_inf[i].arch_opin_between_dice_switch;
356-
VTR_ASSERT((arch_wire_switch == arch_opin_switch) || (directionality != UNI_DIRECTIONAL));
359+
VTR_ASSERT((arch_wire_switch == arch_opin_switch && arch_wire_switch_dec == arch_opin_switch_dec) || (directionality != UNI_DIRECTIONAL));
357360

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

419-
seg_details[cur_track].arch_wire_switch = arch_wire_switch;
420-
seg_details[cur_track].arch_opin_switch = arch_opin_switch;
421422
seg_details[cur_track].arch_opin_between_dice_switch = arch_opin_between_dice_switch;
422423

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

431+
//check for directionality to set the wire_switch and opin_switch
432+
//if not specified in the architecture file, we will use a same mux for both directions
433+
if (seg_details[cur_track].direction == Direction::INC || seg_details[cur_track].direction == Direction::BIDIR || arch_wire_switch_dec == -1){
434+
seg_details[cur_track].arch_opin_switch = arch_opin_switch;
435+
seg_details[cur_track].arch_wire_switch = arch_wire_switch;
436+
}
437+
else {
438+
VTR_ASSERT(seg_details[cur_track].direction == Direction::DEC);
439+
seg_details[cur_track].arch_opin_switch = arch_opin_switch_dec;
440+
seg_details[cur_track].arch_wire_switch = arch_wire_switch_dec;
441+
}
442+
430443
seg_details[cur_track].index = i;
431444
seg_details[cur_track].abs_index = segment_inf[i].seg_index;
432445

0 commit comments

Comments
 (0)