Skip to content

Commit ba8d65d

Browse files
Merge pull request #3276 from verilog-to-routing/temp_3d_sg
Scatter-gather patterns for 3D architectures
2 parents ed1e7f0 + fdccbc5 commit ba8d65d

File tree

112 files changed

+2676
-52275
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

112 files changed

+2676
-52275
lines changed

doc/src/arch/reference.rst

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2001,16 +2001,16 @@ Wire Segments
20012001
The content within the ``<segmentlist>`` tag consists of a group of ``<segment>`` tags.
20022002
The ``<segment>`` tag and its contents are described below.
20032003
2004-
.. arch:tag:: <segment axis="{x|y}" name="unique_name" length="int" type="{bidir|unidir}" res_type="{GCLK|GENERAL}" freq="float" Rmetal="float" Cmetal="float">content</segment>
2004+
.. arch:tag:: <segment axis="{x|y|z}" name="unique_name" length="int" type="{bidir|unidir}" res_type="{GCLK|GENERAL}" freq="float" Rmetal="float" Cmetal="float">content</segment>
20052005
20062006
20072007
:opt_param axis:
2008-
Specifies if the given segment applies to either x or y channels only. If this tag is not given, it is assumed that the given segment
2009-
description applies to both x-directed and y-directed channels.
2008+
Specifies if the given segment applies to x, y, or z channels only. If this tag is not given, it is assumed that the given segment
2009+
description applies to both x-directed and y-directed channels (and not to z-directed channels).
20102010
20112011
.. note:: It is required that both x and y segment axis details are given or that at least one segment within ``segmentlist``
20122012
is specified without the ``axis`` tag (i.e. at least one segment applies to both x-directed and y-directed
2013-
chanels).
2013+
channels). For 3-d architectures, it is required that at least one wire segment with `axis="z"` is defined.
20142014
20152015
:req_param name:
20162016
A unique alphanumeric name to identify this segment type.
@@ -2670,7 +2670,7 @@ The number of any additional wires or muxes created by scatter-gather specificat
26702670
Overview of how scatter-gather patterns work. First, connections from a switchblock location are selected according to the specification.
26712671
These selected connection are then muxed and passed through the scatter-gather node, which is typically a wire segment. The scatter-gather node then fans out or scatters in another switchblock location.
26722672
2673-
.. note:: Scatter-Gather patterns are work in progress and experimental. Currently, VPR does not support this specification and using this tag would not result in any modifications to the RR-Graph.
2673+
.. note:: Scatter-Gather patterns are only supported for 3D architectures where the scatter-gather links are unidirectional. They are not currently supported in 2D architectures or with bidirectional sg_links.
26742674
26752675
When instantiated, a scatter-gather pattern gathers connections from a switchblock and passes the connection through a multiplexer and the scatter-gather node which is typically a wire segment, then scatters or fans out somewhere else in the device. These patterns can be used to define 3D switchblocks. An example is shown below:
26762676

libs/libarchfpga/src/echo_arch.cpp

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -185,13 +185,13 @@ void PrintArchInfo(FILE* Echo, const t_arch* arch) {
185185
}
186186

187187
switch (arch->sb_type) {
188-
case (WILTON):
188+
case e_switch_block_type::WILTON:
189189
fprintf(Echo, "\tSwitch Block: type wilton fs %d\n", arch->Fs);
190190
break;
191-
case (UNIVERSAL):
191+
case (e_switch_block_type::UNIVERSAL):
192192
fprintf(Echo, "\tSwitch Block: type universal fs %d\n", arch->Fs);
193193
break;
194-
case (SUBSET):
194+
case e_switch_block_type::SUBSET:
195195
fprintf(Echo, "\tSwitch Block: type subset fs %d\n", arch->Fs);
196196
break;
197197
default:
@@ -201,7 +201,7 @@ void PrintArchInfo(FILE* Echo, const t_arch* arch) {
201201
fprintf(Echo, "\tInput Connect Block Switch Name Within a Same Die: %s\n", arch->ipin_cblock_switch_name[ipin_cblock_switch_index_within_die].c_str());
202202

203203
//if there is more than one layer available, print the connection block switch name that is used for connection between two dice
204-
for (const auto& layout : arch->grid_layouts) {
204+
for (const t_grid_def& layout : arch->grid_layouts) {
205205
int num_layers = (int)layout.layers.size();
206206
if (num_layers > 1) {
207207
fprintf(Echo, "\tInput Connect Block Switch Name Between Two Dice: %s\n", arch->ipin_cblock_switch_name[ipin_cblock_switch_index_between_dice].c_str());
@@ -257,14 +257,6 @@ void PrintArchInfo(FILE* Echo, const t_arch* arch) {
257257
//wire_switch == arch_opin_switch
258258
fprintf(Echo, "\t\t\t\ttype unidir mux_name for within die connections: %s\n",
259259
arch->switches[seg.arch_wire_switch].name.c_str());
260-
//if there is more than one layer available, print the segment switch name that is used for connection between two dice
261-
for (const auto& layout : arch->grid_layouts) {
262-
int num_layers = (int)layout.layers.size();
263-
if (num_layers > 1) {
264-
fprintf(Echo, "\t\t\t\ttype unidir mux_name for between two dice connections: %s\n",
265-
arch->switches[seg.arch_inter_die_switch].name.c_str());
266-
}
267-
}
268260
} else { //Should be bidir
269261
fprintf(Echo, "\t\t\t\ttype bidir wire_switch %s arch_opin_switch %s\n",
270262
arch->switches[seg.arch_wire_switch].name.c_str(),

libs/libarchfpga/src/logic_types.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,9 @@ enum class e_parallel_axis {
3131
/** Y_AXIS: Data that describes an y-directed wire segment (CHANY) */
3232
Y_AXIS,
3333
/** BOTH_AXIS: Data that can be applied to both x-directed and y-directed wire segment */
34-
BOTH_AXIS
34+
BOTH_AXIS,
35+
/** Z_AXIS: Data that describes an z-directed wire segment (CHANZ) */
36+
Z_AXIS
3537
};
3638

3739
/*

libs/libarchfpga/src/parse_switchblocks.cpp

Lines changed: 14 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ using vtr::t_formula_data;
3535
/*---- Functions for Parsing Switchblocks from Architecture ----*/
3636

3737
//Process the desired order of a wireconn
38-
static void parse_switchpoint_order(const char* order, SwitchPointOrder& switchpoint_order);
38+
static void parse_switchpoint_order(std::string_view order, e_switch_point_order& switchpoint_order);
3939

4040
/**
4141
* @brief Parses an inline `<wireconn>` node using its attributes.
@@ -86,7 +86,7 @@ static void parse_comma_separated_wire_points(const char* ch, std::vector<t_wire
8686
static void parse_num_conns(std::string num_conns, t_wireconn_inf& wireconn);
8787

8888
/* Set connection from_side and to_side for custom switch block pattern*/
89-
static void set_switch_func_type(SBSideConnection& conn, const char* func_type);
89+
static void set_switch_func_type(SBSideConnection& conn, std::string_view func_type);
9090

9191
/* parse switch_override in wireconn */
9292
static void parse_switch_override(const char* switch_override, t_wireconn_inf& wireconn, const std::vector<t_arch_switch_inf>& switches);
@@ -282,13 +282,13 @@ static t_wire_switchpoints parse_wireconn_from_to_node(pugi::xml_node node, cons
282282
return wire_switchpoints;
283283
}
284284

285-
static void parse_switchpoint_order(const char* order, SwitchPointOrder& switchpoint_order) {
286-
if (order == std::string("")) {
287-
switchpoint_order = SwitchPointOrder::SHUFFLED; //Default
288-
} else if (order == std::string("fixed")) {
289-
switchpoint_order = SwitchPointOrder::FIXED;
290-
} else if (order == std::string("shuffled")) {
291-
switchpoint_order = SwitchPointOrder::SHUFFLED;
285+
static void parse_switchpoint_order(std::string_view order, e_switch_point_order& switchpoint_order) {
286+
if (order == "") {
287+
switchpoint_order = e_switch_point_order::SHUFFLED; //Default
288+
} else if (order == "fixed") {
289+
switchpoint_order = e_switch_point_order::FIXED;
290+
} else if (order == "shuffled") {
291+
switchpoint_order = e_switch_point_order::SHUFFLED;
292292
} else {
293293
archfpga_throw(__FILE__, __LINE__, "Unrecognized switchpoint order '%s'", order);
294294
}
@@ -328,19 +328,18 @@ static void parse_comma_separated_wire_points(const char* ch, std::vector<t_wire
328328
}
329329

330330
static void parse_num_conns(std::string num_conns, t_wireconn_inf& wireconn) {
331-
//num_conns is now interpretted as a formula and processed in build_switchblocks
331+
// num_conns is now interpreted as a formula and processed in build_switchblocks
332332
wireconn.num_conns_formula = num_conns;
333333
}
334334

335-
//set sides for a specific conn for custom switch block pattern
336-
static void set_switch_func_type(SBSideConnection& conn, const char* func_type) {
335+
static void set_switch_func_type(SBSideConnection& conn, std::string_view func_type) {
337336

338-
if (std::string(func_type).length() != 2) {
337+
if (func_type.length() != 2) {
339338
archfpga_throw(__FILE__, __LINE__, "Custom switchblock func type must be 2 characters long: %s\n", func_type);
340339
}
341340

342-
// Only valid sides are right, top, left, bottom, above and under
343-
if (std::string(func_type).find_first_not_of("rtlbauRTLBAU") != std::string::npos) {
341+
// Only valid sides are right, top, left, bottom
342+
if (func_type.find_first_not_of("rtlbRTLB") != std::string::npos) {
344343
archfpga_throw(__FILE__, __LINE__, "Unknown direction specified: %s\n", func_type);
345344
}
346345

@@ -352,12 +351,6 @@ static void set_switch_func_type(SBSideConnection& conn, const char* func_type)
352351
archfpga_throw(__FILE__, __LINE__, "Unknown permutation function specified, cannot go from side to same side: %s\n", func_type);
353352
}
354353

355-
// We don't allow specification of patterns that imply edges going over 2 or more layers
356-
// (this doesn't seem electrically logical), so we disallow going from above/under to above/under.
357-
if ((to_side == ABOVE || to_side == UNDER) && (from_side == ABOVE || from_side == UNDER)) {
358-
archfpga_throw(__FILE__, __LINE__, "Unknown permutation function specified, cannot go from above/under to above/under: %s\n", func_type);
359-
}
360-
361354
conn.set_sides(from_side, to_side);
362355
}
363356

libs/libarchfpga/src/physical_types.h

Lines changed: 3 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@
3232
#include <unordered_map>
3333
#include <string>
3434
#include <map>
35-
#include <unordered_map>
3635
#include <limits>
3736
#include <unordered_set>
3837

@@ -1574,28 +1573,6 @@ enum class SegResType {
15741573
/// String versions of segment resource types
15751574
constexpr std::array<const char*, static_cast<size_t>(SegResType::NUM_RES_TYPES)> RES_TYPE_STRING{"GCLK", "GENERAL"};
15761575

1577-
/// Defines the type of switch block used in FPGA routing.
1578-
enum e_switch_block_type {
1579-
/// If the type is SUBSET, I use a Xilinx-like switch block where track i in one channel always
1580-
/// connects to track i in other channels.
1581-
SUBSET,
1582-
1583-
/// If type is WILTON, I use a switch block where track i
1584-
/// does not always connect to track i in other channels.
1585-
/// See Steve Wilton, PhD Thesis, University of Toronto, 1996.
1586-
WILTON,
1587-
1588-
/// The UNIVERSAL switch block is from Y. W. Chang et al, TODAES, Jan. 1996, pp. 80 - 101.
1589-
UNIVERSAL,
1590-
1591-
/// The FULL switch block type allows for complete connectivity between tracks.
1592-
FULL,
1593-
1594-
/// A CUSTOM switch block has also been added which allows a user to describe custom permutation functions and connection patterns.
1595-
/// See comment at top of SRC/route/build_switchblocks.c
1596-
CUSTOM
1597-
};
1598-
15991576
enum e_Fc_type {
16001577
ABSOLUTE,
16011578
FRACTIONAL
@@ -1634,22 +1611,22 @@ struct t_segment_inf {
16341611
* specified in the architecture file. If -1, this value was not set in the
16351612
* architecture file and arch_wire_switch should be used for "DEC_DIR" wire segments.
16361613
*/
1637-
short arch_wire_switch_dec = -1;
1614+
short arch_wire_switch_dec = ARCH_FPGA_UNDEFINED_VAL;
16381615

16391616
/**
16401617
* @brief Same as arch_opin_switch but used only for decremental tracks if
16411618
* it is specified in the architecture file. If -1, this value was not set in
16421619
* the architecture file and arch_opin_switch should be used for "DEC_DIR" wire segments.
16431620
*/
1644-
short arch_opin_switch_dec = -1;
1621+
short arch_opin_switch_dec = ARCH_FPGA_UNDEFINED_VAL;
16451622

16461623
/**
16471624
* @brief Index of the switch type that connects output pins (OPINs) to this
16481625
* segment from another die (layer). Note that this index is in relation to
16491626
* the switches from the architecture file, not the expanded list of switches
16501627
* that is built at the end of build_rr_graph.
16511628
*/
1652-
short arch_inter_die_switch = -1;
1629+
short arch_inter_die_switch = ARCH_FPGA_UNDEFINED_VAL;
16531630

16541631
/**
16551632
* @brief The fraction of logic blocks along its length to which this segment can connect.
@@ -1729,7 +1706,6 @@ inline bool operator==(const t_segment_inf& a, const t_segment_inf& b) {
17291706
&& a.length == b.length
17301707
&& a.arch_wire_switch == b.arch_wire_switch
17311708
&& a.arch_opin_switch == b.arch_opin_switch
1732-
&& a.arch_inter_die_switch == b.arch_inter_die_switch
17331709
&& a.frac_cb == b.frac_cb
17341710
&& a.frac_sb == b.frac_sb
17351711
&& a.longline == b.longline

libs/libarchfpga/src/read_fpga_interchange_arch.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2328,7 +2328,7 @@ struct ArchReader {
23282328
arch_->Chans.chan_y_dist.xpeak = 0;
23292329
arch_->Chans.chan_y_dist.dc = 0;
23302330
arch_->ipin_cblock_switch_name.push_back(std::string("generic"));
2331-
arch_->sb_type = WILTON;
2331+
arch_->sb_type = e_switch_block_type::WILTON;
23322332
arch_->Fs = 3;
23332333
default_fc_.specified = true;
23342334
default_fc_.in_value_type = e_fc_value_type::FRACTIONAL;

0 commit comments

Comments
 (0)