vpr: Fix congestion costs for non-configurably connected nodes

Previously the router would add the congestion cost of an entire
non-configurably connected node set *each* time a node from that set
was expanded. This could substantially over-cost nodes such nodes if the
router's partial path traversed through multiple nodes in the set.

We now only add the congestion cost (for the entire set) once (when the
router first expands into the set). Any other nodes which are in the set
(i.e. reached by non-configurable edges) have no additional congestion
cost added.
diff --git a/vpr/src/route/route_timing.cpp b/vpr/src/route/route_timing.cpp
index 54ef468..580fee3 100644
--- a/vpr/src/route/route_timing.cpp
+++ b/vpr/src/route/route_timing.cpp
@@ -299,6 +299,8 @@
 
 static void prune_unused_non_configurable_nets(CBRR& connections_inf);
 
+static bool same_non_config_node_set(int from_node, int to_node);
+
 /************************ Subroutine definitions *****************************/
 bool try_timing_driven_route(const t_router_opts& router_opts,
                              const t_analysis_opts& analysis_opts,
@@ -2023,9 +2025,27 @@
     //Second, we adjust the Tdel to account for the delay caused by the internal capacitance.
     Tdel += Rdel_adjust * switch_Cinternal;
 
+    bool reached_configurably = device_ctx.rr_nodes[from_node].edge_is_configurable(iconn);
+
+    float cong_cost = 0.;
+    if (reached_configurably) {
+        cong_cost = get_rr_cong_cost(to_node);
+    } else {
+        //Reached by a non-configurable edge.
+        //Therefore the from_node and to_node are part of the same non-configurable node set.
+        VTR_ASSERT_SAFE_MSG(same_non_config_node_set(from_node, to_node),
+                            "Non-configurably connected edges should be part of the same node set");
+
+        //The congestion cost of all nodes in the set has already been accounted for (when
+        //the current path first expanded a node in the set). Therefore do *not* re-add the congestion
+        //cost.
+        cong_cost = 0.;
+    }
+
     //Update the backward cost (upstream already included)
-    to->backward_path_cost += (1. - cost_params.criticality) * get_rr_cong_cost(to_node); //Congestion cost
-    to->backward_path_cost += cost_params.criticality * Tdel;                             //Delay cost
+    to->backward_path_cost += (1. - cost_params.criticality) * cong_cost; //Congestion cost
+    to->backward_path_cost += cost_params.criticality * Tdel;             //Delay cost
+
     if (cost_params.bend_cost != 0.) {
         t_rr_type from_type = device_ctx.rr_nodes[from_node].type();
         t_rr_type to_type = device_ctx.rr_nodes[to_node].type();
@@ -2865,3 +2885,18 @@
         free_route_tree(rt_root);
     }
 }
+
+//Returns true if both nodes are part of the same non-configurable edge set
+static bool same_non_config_node_set(int from_node, int to_node) {
+    auto& device_ctx = g_vpr_ctx.device();
+
+    auto from_itr = device_ctx.rr_node_to_non_config_node_set.find(from_node);
+    auto to_itr = device_ctx.rr_node_to_non_config_node_set.find(to_node);
+
+    if (from_itr == device_ctx.rr_node_to_non_config_node_set.end()
+        || to_itr == device_ctx.rr_node_to_non_config_node_set.end()) {
+        return false; //Not part of a non-config node set
+    }
+
+    return from_itr->second == to_itr->second; //Check for same non-config set IDs
+}