Skip to content

RR Edge ID Verification #3164

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 3 commits into
base: master
Choose a base branch
from
Open

RR Edge ID Verification #3164

wants to merge 3 commits into from

Conversation

amin1377
Copy link
Contributor

Description

In a .route file, each edge between two nodes includes a switch ID, which is used to retrieve the electrical characteristics of that edge. When reading the .route file, this switch ID is compared against the corresponding switch ID from the RR Graph for consistency. If they do not match, an error is raised.

This consistency check is generally helpful. However, when analyzing multiple timing corners, each corner may have a different RR Graph with varying timing information (graph topologies are the same). As a result, the number and ordering of switch types may differ between corners. To allow reuse of the same .route file for fair comparisons across different timing corners, this strict verification can become a limitation.

To address this issue, a new CLI parameter verify_rr_switch_id has been introduced. By default, it is set to on, enforcing the consistency check. When set to off, the switch ID from the .route file is ignored, and the switch ID from the RR Graph is used instead.

@github-actions github-actions bot added VPR VPR FPGA Placement & Routing Tool lang-cpp C/C++ code labels Jun 24, 2025
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 @amin1377.

I left a few comment for improving the readability a bit.

@@ -1637,6 +1637,16 @@ argparse::ArgumentParser create_arg_parser(const std::string& prog_name, t_optio
.default_value("on")
.show_in(argparse::ShowIn::HELP_ONLY);

gen_grp.add_argument<bool, ParseOnOff>(args.verify_rr_switch_id, "--verify_rr_switch_id")
.help(
"Verify that the switch IDs in the routing file are consistent with those in the RR Graph."
Copy link
Contributor

Choose a reason for hiding this comment

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

Add a space or '\n' at the end of each line.

Copy link
Contributor

Choose a reason for hiding this comment

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

document this new option in the rst file

@@ -1637,6 +1637,16 @@ argparse::ArgumentParser create_arg_parser(const std::string& prog_name, t_optio
.default_value("on")
.show_in(argparse::ShowIn::HELP_ONLY);

gen_grp.add_argument<bool, ParseOnOff>(args.verify_rr_switch_id, "--verify_rr_switch_id")
Copy link
Contributor

Choose a reason for hiding this comment

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

If this is a routing option, add it to route_grp

@@ -73,6 +73,7 @@ struct t_options {
argparse::ArgValue<e_timing_update_type> timing_update_type;
argparse::ArgValue<bool> CreateEchoFile;
argparse::ArgValue<bool> verify_file_digests;
argparse::ArgValue<bool> verify_rr_switch_id;
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 this option is only applicable to the routing stage and its variable should move there

static void process_route(const Netlist<>& net_list, std::ifstream& fp, const char* filename, int& lineno, bool is_flat);
static void process_nodes(const Netlist<>& net_list, std::ifstream& fp, ClusterNetId inet, const char* filename, int& lineno);
static void process_nets(const Netlist<>& net_list, std::ifstream& fp, ClusterNetId inet, std::string name, std::vector<std::string> input_tokens, const char* filename, int& lineno, bool is_flat);
static void process_route(const Netlist<>& net_list,
Copy link
Contributor

Choose a reason for hiding this comment

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

The definition of some of these have doxygen comments. Can you move them to the declaration?

Copy link
Contributor

Choose a reason for hiding this comment

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

Thank you for breaking long lines. Can you do the same for the definition of these functions?

bool verify_rr_switch_id,
bool is_flat);

static void update_rr_switch_id(t_trace* trace, std::set<int>& seen_rr_nodes);
Copy link
Contributor

Choose a reason for hiding this comment

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

Doxygen comment

//Verify that the next element (branch point) has been already seen in the traceback so far
if (!seen_rr_nodes.count(next->index)) {
VPR_FATAL_ERROR(VPR_ERROR_ROUTE, "Traceback branch point %d not found", next->index);
} else {
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this else statement necessary?
I think we can remove it. Then, both branches of if (trace->iswitch == OPEN) call update_rr_switch_id(next, seen_rr_nodes). So, we can move it outside the conditional statement.

//Check there is an edge connecting trace and next

auto& device_ctx = g_vpr_ctx.device();
const auto& rr_graph = device_ctx.rr_graph;
Copy link
Contributor

Choose a reason for hiding this comment

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

The only usage of device_ctx is to access rr_graph.
const auto& rr_graph = g_vpr_ctx.device().rr_graph would be more concise.

}
} else { //Midway along branch

//Check there is an edge connecting trace and next
Copy link
Contributor

Choose a reason for hiding this comment

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

To be consistent with the coding style guide, add a space after //

@@ -1343,6 +1343,8 @@ struct t_router_opts {

bool with_timing_analysis;

bool verify_rr_switch_id;
Copy link
Contributor

Choose a reason for hiding this comment

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

doxygen comment

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 you could name this better. Isn't this controlling whether you verify the switch id in route files? Hence a better name would be --verify_route_file_switch_id (and you'd change this in the command line, documentation and code).

if (!found) {
VPR_FATAL_ERROR(VPR_ERROR_ROUTE, "Traceback no RR edge between RR nodes %d -> %d\n", trace->index, next->index);
}
//Recurse
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 an iterative function that uses std::stack is easier to understand and eliminates the possiblity of stack overflow.
With an iterative function, you don't need to pass std::set as an argument, making the function self-contained.

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.

Seems like there may be some code duplication ... I suggest some changes.

}
}

tokens.clear();
}

///@brief Check if the net is global or not, and process appropriately
static void process_nets(const Netlist<>& net_list, std::ifstream& fp, ClusterNetId inet, std::string name, std::vector<std::string> input_tokens, const char* filename, int& lineno, bool is_flat) {
static void process_nets(const Netlist<>& net_list, std::ifstream& fp, ClusterNetId inet, std::string name, std::vector<std::string> input_tokens, const char* filename, int& lineno, bool verify_rr_switch_id, bool is_flat) {
Copy link
Contributor

Choose a reason for hiding this comment

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

When moving the comment, see if you can improve it. What does "process appropriately" mean?

VTR_ASSERT(validate_traceback(head_ptr));
} else {
std::set<int> seen_rr_nodes;
update_rr_switch_id(head_ptr, seen_rr_nodes);
Copy link
Contributor

Choose a reason for hiding this comment

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

It looks like update_rr_switch_id has much of the functionality of validate_traceback inside it. I think it would be more clear to rename validate_traceback to validate_and_update_traceback and pass it a flag remap_switch_id which makes it do the remapping behaviour as it validates.

If it is safe to remap before validation (which it might not be if the traceback is invalid) you could alternatively make a more limited remapping function that you call before traceback validation.

@@ -1343,6 +1343,8 @@ struct t_router_opts {

bool with_timing_analysis;

bool verify_rr_switch_id;
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 you could name this better. Isn't this controlling whether you verify the switch id in route files? Hence a better name would be --verify_route_file_switch_id (and you'd change this in the command line, documentation and code).

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

Successfully merging this pull request may close these issues.

3 participants