Skip to content

Add tileable RR Graph #3134

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

Open
wants to merge 62 commits into
base: master
Choose a base branch
from
Open

Add tileable RR Graph #3134

wants to merge 62 commits into from

Conversation

amin1377
Copy link
Contributor

@amin1377 amin1377 commented Jun 11, 2025

Merging OpenFPGA branch into master branch. PR #2135 explains features of OpenFPGA.

@github-actions github-actions bot added VPR VPR FPGA Placement & Routing Tool libarchfpga Library for handling FPGA Architecture descriptions docs Documentation lang-cpp C/C++ code libvtrutil labels Jun 11, 2025
@amin1377 amin1377 requested a review from AlexandreSinger June 19, 2025 22:36
@amin1377
Copy link
Contributor Author

Hi @soheilshahrouz,

This PR is ready for your review. Since you're familiar with the RR Graph code, it would be great if you could take a look at the tileable RR Graph implementation.

@amin1377 amin1377 requested a review from soheilshahrouz June 19, 2025 22:37
Copy link
Contributor

@AlexandreSinger AlexandreSinger left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @amin1377 thanks for bringing this in! I recognize not all of this is your code. Overall the code is well structured however it needs some code style and data structure cleanup so it can fit in better with the rest of the VTR flow.

Some. of the data structure changes can be made into issues; however, the coding style things should probably be fixed now.

@amin1377
Copy link
Contributor Author

QoR comparison:
Titan: Link
Large VTR: Link

@amin1377
Copy link
Contributor Author

Thanks @AlexandreSinger; reviewing this amount of code is no small task, and I really appreciate your time. I've addressed your comments. Regarding your suggestions about replacing the vector of vectors with VTR data structures: while I agree with them in principle, I didn’t apply all of them since this part of the code is not performance-critical.

I think the code is now ready for the next round of reviews. I’ve also added @AmirhosseinPoolad to help with it.

Copy link
Contributor

@soheilshahrouz soheilshahrouz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this PR.
Since it's a large one, I’ve reviewed some files for now and will go through the rest soon.

@amin1377
Copy link
Contributor Author

@soheilshahrouz: Thank you for taking the time to review this PR. I’ve addressed all your comments, and I think this PR is now ready for the next round of review.

@amin1377 amin1377 requested a review from vaughnbetz June 26, 2025 17:38
Copy link
Contributor

@AlexandreSinger AlexandreSinger left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi Amin, thanks for fixing my prior comments. The reward for good work is more work my friend. I am just kidding; I gave this another pass focusing more on the documentation since I only glanced over it in my last review.


VIB Architecture
============
The VIB architecture adds modeling support for double-level MUX topology and bent wires. In past, switch blocks have only one level of routing MUXes, whose inputs are driven by outputs of programmable blocks and routing tracks. Now outputs of programmable blocks can shape the first level of routing MUXes, while the inputs of second level involves the outputs of first level and other routing tracks. This can reduce the number and input sizes of routing MUXes.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"In past" -> "In the past"
"switch blocks have" -> "switch blocks had"
"whose inputs are driven" -> "whose inputs were driven"

============
The VIB architecture adds modeling support for double-level MUX topology and bent wires. In past, switch blocks have only one level of routing MUXes, whose inputs are driven by outputs of programmable blocks and routing tracks. Now outputs of programmable blocks can shape the first level of routing MUXes, while the inputs of second level involves the outputs of first level and other routing tracks. This can reduce the number and input sizes of routing MUXes.

Figure 1 shows the proposed VIB architecture which is tile-based. Each tile is composed of a CLB and a VIB. Each CLB can interact with the corresponding VIB which contains all the routing programmable switches in one tile. Figure 2 shows an example of the detailed interconnect architecture in VIB. The CLB input muxes and the driving muxes of wire segments can share the same fanins. A routing path of a net with two sinks is presented red in the Figure.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be a good idea to spell out what the acronym "VIB" means in this context. "Versatile Interconnect Block (VIB)" or something just so its written down somewhere on this page.


FPGA Architecture File Modification (.xml)
--------------------------
For original tags of FPGA architecture file see :ref:`fpga_architecture_description`.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest: "For the original tags available for the standard FPGA architecture file see"

I feel like it can get confusing with all the architecture file words being thrown around.

For example, a length 4 wire has a bent pattern of ``- - U``.
A ``-`` indicates no bent at this position and a ``U`` indicates a conterclockwise bent at the position. (``D`` indicates a clockwise bent.)

.. note:: A bent wire should remain consistent in both the x and y axes.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does consistent mean in this context? If you know it may be a good idea to expand on this if this is important.

.. arch:tag:: <multistage_muxs>content</multistage_muxs>
:req_param content:
The detaild information for first and second MUXes.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"detaild" -> "detailed"

<direct name="scff_chain" from_pin="clb.sc_out" to_pin="clb.sc_in" x_offset="0" y_offset="-1" z_offset="0"/>
</directlist>
In OpenFPGA architecture:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"In a tileable architecture:"


In this figure, the red arrows represent the initial direct connection. The green arrows represent the point to point connection to connect all the columns of CLB.

A point to point connection can be applied in different ways than showed in the example section. To help the designer implement his point to point connection, a truth table with our new parameters id provided below.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"implement his point to point connection" -> "implement their point to point connection"

Anyone can be designers 😄

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"a truth table with our new parameters id provided below". Something is off about this sentence.

@@ -0,0 +1,11 @@
#include <vector>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file needs a pragma once.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Explain what this file is for (VIB-specific architecture file reading code. And a VIB is ....)

return node_storage_.edge_sink_node(edge);
}

/** @brief Get the source node for the iedge'th edge from specified RRNodeId.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing a return-carriage just before the "@brief"


if (priority < max_priority_type_loc.priority) {
//Lower priority, do not override
#ifdef VERBOSE
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am wondering if using VTR_LOG_DEBUG would be more appropriate and easier to work with.

InstPort in_pins(annot_in_str);
for (const auto& annot_out_str : vtr::split(annotation.output_pins)) {
for (const auto& annot_out_str : vtr::StringToken(annotation.output_pins).split(" \t\n")) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

auto

@@ -201,7 +201,7 @@ t_wire_switchpoints parse_wireconn_from_to_node(pugi::xml_node node, const pugiu
wire_switchpoints.segment_name = get_attribute(node, "type", loc_data).value();

auto points_str = get_attribute(node, "switchpoint", loc_data).value();
for (const auto& point_str : vtr::split(points_str, ",")) {
for (const auto& point_str : vtr::StringToken(points_str).split(",")) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

auto in lines 203 and 204

@@ -229,7 +229,7 @@ static void parse_switchpoint_order(const char* order, SwitchPointOrder& switchp
/* parses the wire types specified in the comma-separated 'ch' char array into the vector wire_points_vec.
* Spaces are trimmed off */
static void parse_comma_separated_wire_types(const char* ch, std::vector<t_wire_switchpoints>& wire_switchpoints) {
auto types = vtr::split(ch, ",");
auto types = vtr::StringToken(ch).split(",");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

auto

@@ -245,7 +245,7 @@ static void parse_comma_separated_wire_types(const char* ch, std::vector<t_wire_

/* parses the wirepoints specified in the comma-separated 'ch' char array into the vector wire_points_vec */
static void parse_comma_separated_wire_points(const char* ch, std::vector<t_wire_switchpoints>& wire_switchpoints) {
auto points = vtr::split(ch, ",");
auto points = vtr::StringToken(ch).split(",");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

auto

@@ -2262,7 +2282,7 @@ struct t_noc_inf {
std::string noc_router_tile_name;
};

/* Detailed routing architecture */
/* Detailed routing architecture */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

replace with // or write doxygen comment


/* Split the string using a given delim */
std::vector<std::string> StringToken::split(const std::string& delims) const {
/* Return vector */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

block comments
several instacnes in this file

return split(delims);
}

/* Split the string using a given delim */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can be moved to the header file as doxygen comment for the method
several instances

@@ -782,7 +782,7 @@ void FasmWriterVisitor::output_fasm_mux(std::string_view fasm_mux_str,
bool root_level_connection = interconnect->parent_mode->parent_pb_type ==
mux_input_pin->parent_node->pb_type;

auto fasm_features_str = vtr::join(vtr::split(mux_parts[1], ","), "\n");
auto fasm_features_str = vtr::join(vtr::StringToken(mux_parts[1]).split(","), "\n");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

auto
a few instances in this file

@@ -84,6 +84,10 @@ int binary_search_place_and_route(const Netlist<>& placement_net_list,
graph_directionality = e_graph_type::BIDIR;
} else {
graph_type = (det_routing_arch.directionality == BI_DIRECTIONAL ? e_graph_type::BIDIR : e_graph_type::UNIDIR);
/* Branch on tileable routing */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

//

@@ -136,7 +136,7 @@ void setup_clock_connections(const t_arch& Arch, FormulaParser& p) {
if (RoutingToClockConnection* routing_to_clock = dynamic_cast<RoutingToClockConnection*>(clock_connections_device.back().get())) {
//TODO: Add error check to check that clock name and tap name exist and that only
// two names are returned by the below function
auto names = vtr::split(clock_connection_arch.to, ".");
auto names = vtr::StringToken(clock_connection_arch.to).split(".");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

auto
a few cases

Copy link
Contributor

@vaughnbetz vaughnbetz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done reviewing up to the start of rr_spatial_lookup (more to do).
Lots of work here, thanks Amin!

Big picture comments:
Memory: don't allocate things we don't need to (bends, ptc_num array). Instead, allocate only if tileable is on, and add checking to the get/set functions for these.
Clarity: ptc_nums is confusing. Need to give it a different name to avoid confusion (can't have two ptc_nums). I suggest tileable_track_num or something like that.
bend_start / bend_end are mysterious. Need to completely explain what they are returning.

Various other comments in the text.
QoR: looks mostly good, but Titan routing slowed down 3%. May be due to the memory footprint --> making the allocation changes above will hopefully fix.
Longer term: doesn't have to be in this PR, but right afterwards we should get rid of the tiling data we added earlier to the RRgraph in an attempt to unify a bit of OpenFPGA and VTR code. Clearly we won't use that, so storing something of O(rr_nodes) is not a good idea when no one uses it.

@@ -2272,12 +2292,43 @@ struct t_arch {
/// Secure hash digest of the architecture file to uniquely identify this architecture
char* architecture_id;

// Options for tileable routing architectures
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You need to explain what tileable routing architectures are / what this means to the code. I.e., these are used for an alternative, tilable, rr-graph generator that can produce OpenFPGA-compatible FPGAs that can be implemented to silicon via the OpenFPGA flow. This seems like it might be a logical place for such a high-level comment and you have to have one like that somewhere.

std::vector<t_switchblock_inf> switchblocks;
float R_minW_nmos;
float R_minW_pmos;
int Fs;
int sub_fs;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment what this is. Comment that it is only valid with (VIB? tileable?)

std::string device_layout;

/// VIB grid layouts
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needs a more extensive comment, or a pointer to one. What is a VIB? Why does it have a different layout?
(The current comment pretty much removes _ from the variable name, which is not very helpful).

t_clock_arch_spec clock_arch; // Clock related data types

/// Stores NoC-related architectural information when there is an embedded NoC
t_noc_inf* noc = nullptr;

// added for vib
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need a high-level comment on VIB. What are vib_infs? Also, if you're going to add various VIB data I suggest putting it all together (group the variables together) and put a high-level comment on what VIB is above it.

Explain the individual variables as much as you can, but at the least group them and document as a group as I listed above.

* Note that sub_type does not support custom switch block pattern!!!
* If 'sub_type' is specified, the custom switch block for 'type' is not allowed!
*/
std::string sub_type_str = get_attribute(Cur, "sub_type", loc_data, BoolToReqOpt(false)).as_string("");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be good to move the sub_type and sub_fs processing into a subroutine, to keep this routine from getting to long and to help localize the extra tilable rr-graph code.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If that routine could go in the vib-specific reader file that would be even better (to localize the VIB code).

@@ -222,6 +229,24 @@ class RRGraphView {
inline short node_layer(RRNodeId node) const {
return node_storage_.node_layer(node);
}

/**
* @brief Return the bend start of a specified node.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, need to really define the use and the return value meaning.


/**
* @brief Return incoming edges for a given routing resource node
* Require build_in_edges() to be called first
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Require -> Requires.
Also all 3 functions below require build_in_edges() to be called first, so that should be commented on each.

/** @brief Validate if all the fan-in edge lists are valid */
bool validate_in_edges() const;
/** @brief Count the number of incoming edges for all the nodes */
size_t in_edges_count() const;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I need to call the build_in_edges function first for these?


/** A list of incoming edges for each routing resource node. This can be built optionally, as required by applications.
* By default, it is empty! Call build_in_edges() to construct it!!! */
const vtr::vector<RRNodeId, std::vector<RREdgeId>>& node_in_edges_;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove ! and !!

* By default, it is empty! Call build_in_edges() to construct it!!! */
const vtr::vector<RRNodeId, std::vector<RREdgeId>>& node_in_edges_;

/** A list of extra ptc numbers for each routing resource node. See details in RRGraphBuilder class */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rename to node_tileable_track_nums.
Say this is only loaded for tilable rr-graphs.
Change implementation to check if it is loaded before set/get operations.

Longer term: maybe we can store this more efficiently (it is a modolo computation, so I don't think we need to store it on every location along a wire).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
docs Documentation lang-cpp C/C++ code libarchfpga Library for handling FPGA Architecture descriptions libvtrutil VPR VPR FPGA Placement & Routing Tool
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants