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

Merged
merged 12 commits into from
Jul 1, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
10 changes: 10 additions & 0 deletions doc/src/vpr/command_line_usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,16 @@ General Options

**Default:** ``on``

.. option:: --verify_route_file_switch_id {on | off}

Verify that the switch IDs in the routing file are consistent with those in the RR Graph.
Set this to false when switch IDs in the routing file may differ from the RR Graph.
For example, when analyzing different timing corners using the same netlist, placement, and routing files,
the RR switch IDs in the RR Graph may differ due to changes in delays.
In such cases, set this option to false so that the switch IDs from the RR Graph are used, and those in the routing file are ignored.

**Default:** ``on``

.. option:: --target_utilization <float>

Sets the target device utilization.
Expand Down
2 changes: 2 additions & 0 deletions vpr/src/base/SetupVPR.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -517,6 +517,8 @@ static void SetupRouterOpts(const t_options& Options, t_router_opts* RouterOpts)
RouterOpts->custom_3d_sb_fanin_fanout = Options.custom_3d_sb_fanin_fanout;
RouterOpts->with_timing_analysis = Options.timing_analysis;

RouterOpts->verify_route_file_switch_id = Options.verify_route_file_switch_id;

RouterOpts->generate_router_lookahead_report = Options.generate_router_lookahead_report.value();
}

Expand Down
71 changes: 33 additions & 38 deletions vpr/src/base/old_traceback.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
#include "route_common.h"

#include <vector>
#include <stack>

std::pair<t_trace*, t_trace*> traceback_from_route_tree_recurr(t_trace* head, t_trace* tail, const RouteTreeNode& node);
bool validate_traceback_recurr(t_trace* trace, std::set<int>& seen_rr_nodes);
void free_trace_data(t_trace* tptr);

/** Build a route tree from a traceback */
Expand Down Expand Up @@ -109,7 +109,7 @@ t_trace* TracebackCompat::traceback_from_route_tree(const RouteTree& tree) {

std::tie(head, tail) = traceback_from_route_tree_recurr(nullptr, nullptr, tree.root());

VTR_ASSERT(validate_traceback(head));
VTR_ASSERT(validate_and_update_traceback(head));

return head;
}
Expand Down Expand Up @@ -141,70 +141,65 @@ void print_traceback(const t_trace* trace) {
VTR_LOG("\n");
}

bool validate_traceback(t_trace* trace) {
std::set<int> seen_rr_nodes;

return validate_traceback_recurr(trace, seen_rr_nodes);
}

bool validate_traceback_recurr(t_trace* trace, std::set<int>& seen_rr_nodes) {
bool validate_and_update_traceback(t_trace* trace, bool verify_switch_id /* = true */) {
if (!trace) {
return true;
}

seen_rr_nodes.insert(trace->index);
std::set<int> seen_rr_nodes;
std::stack<t_trace*> trace_stack;
trace_stack.push(trace);

t_trace* next = trace->next;
while (!trace_stack.empty()) {
trace = trace_stack.top();
trace_stack.pop();
seen_rr_nodes.insert(trace->index);
t_trace* next = trace->next;

if (next) {
if (trace->iswitch == OPEN) { //End of a branch
if (next == nullptr) {
continue;
}

//Verify that the next element (branch point) has been already seen in the traceback so far
if (trace->iswitch == OPEN) { // End of a branch
// Verify that the next element (branch point) has been already seen in the traceback so far
if (!seen_rr_nodes.count(next->index)) {

Choose a reason for hiding this comment

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

Should check that index is a valid rr_node index (otherwise the validator could crash on invalid input). Print a helpful error message if it is out of range.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

validate_and_update_traceback is called within the process_nodes function. In this function, all relevant checks related to the node are performed when creating the trace.

VPR_FATAL_ERROR(VPR_ERROR_ROUTE, "Traceback branch point %d not found", next->index);
} else {
//Recurse along the new branch
return validate_traceback_recurr(next, seen_rr_nodes);
}
} else { //Midway along branch

//Check there is an edge connecting trace and next

auto& device_ctx = g_vpr_ctx.device();
const auto& rr_graph = device_ctx.rr_graph;
} else { // Midway along branch
// Check there is an edge connecting trace and next
const auto& rr_graph = g_vpr_ctx.device().rr_graph;
bool found = false;
for (t_edge_size iedge = 0; iedge < rr_graph.num_edges(RRNodeId(trace->index)); ++iedge) {
int to_node = size_t(rr_graph.edge_sink_node(RRNodeId(trace->index), iedge));

if (to_node == next->index) {
found = true;

//Verify that the switch matches
int rr_iswitch = rr_graph.edge_switch(RRNodeId(trace->index), iedge);
if (trace->iswitch != rr_iswitch) {
VPR_FATAL_ERROR(VPR_ERROR_ROUTE, "Traceback mismatched switch type: traceback %d rr_graph %d (RR nodes %d -> %d)\n",
trace->iswitch, rr_iswitch,
trace->index, to_node);
if (verify_switch_id) {
// Verify that the switch matches
if (trace->iswitch != rr_iswitch) {
VPR_FATAL_ERROR(VPR_ERROR_ROUTE, "Traceback mismatched switch type: traceback %d rr_graph %d (RR nodes %d -> %d)\n",
trace->iswitch, rr_iswitch,
trace->index, to_node);
}
} else {
// Update the switch ID in the traceback to match the RR Graph
trace->iswitch = rr_iswitch;
}
break;
}
}

if (!found) {
VPR_FATAL_ERROR(VPR_ERROR_ROUTE, "Traceback no RR edge between RR nodes %d -> %d\n", trace->index, next->index);
}

//Recurse
return validate_traceback_recurr(next, seen_rr_nodes);
}
// Recurse
trace_stack.push(next);
}

VTR_ASSERT(!next);
return true; //End of traceback
return true;
}

t_trace*
alloc_trace_data() {
t_trace* alloc_trace_data() {
return (t_trace*)malloc(sizeof(t_trace));
}

Expand Down
15 changes: 14 additions & 1 deletion vpr/src/base/old_traceback.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,17 @@ class TracebackCompat {
t_trace* alloc_trace_data();
void free_traceback(t_trace* trace);
void print_traceback(const t_trace* trace);
bool validate_traceback(t_trace* trace);

/**
* @brief Validate the integrity of the traceback rooted a trace: it should contain only valid rr nodes, branches in the routing tree
* should link to existing routing, and edges in the traceback should exist in the RRGraph.
* If verify_switch_id is true, this routine also checks that the switch types used in the traceback match those in the
* RRGraph. If verify_switch_id is false, the switch ids (types) are remapped to those in the RRGraph. This switch remapping is
* useful when an RRGraph with a more detailed delay model (and hence more switch types) is used with a prior routing.
*
* @param trace Pointer to the head of the routing trace of the net to validate and update.
* @param verify_switch_id Whether to verify the switch IDs in the traceback.
*
* @return true if the traceback is valid, false otherwise.
*/
bool validate_and_update_traceback(t_trace* trace, bool verify_switch_id = true);
10 changes: 10 additions & 0 deletions vpr/src/base/read_options.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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_route_file_switch_id, "--verify_route_file_switch_id")
.help(
"Verify that the switch IDs in the routing file are consistent with those in the RR Graph. "
"Set this to false when switch IDs in the routing file may differ from the RR Graph. "
"For example, when analyzing different timing corners using the same netlist, placement, and routing files, "
"the RR switch IDs in the RR Graph may differ due to changes in delays. "
"In such cases, set this option to false so that the switch IDs from the RR Graph are used, and those in the routing file are ignored.\n")
.default_value("on")
.show_in(argparse::ShowIn::HELP_ONLY);

gen_grp.add_argument(args.target_device_utilization, "--target_utilization")
.help(
"Sets the target device utilization."
Expand Down
1 change: 1 addition & 0 deletions vpr/src/base/read_options.h
Original file line number Diff line number Diff line change
Expand Up @@ -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_route_file_switch_id;
argparse::ArgValue<std::string> device_layout;
argparse::ArgValue<float> target_device_utilization;
argparse::ArgValue<e_constant_net_method> constant_net_method;
Expand Down
Loading