Fixed memory problem by creating separate function clear_rr_node_to_rt_node
diff --git a/vpr/src/draw/draw.cpp b/vpr/src/draw/draw.cpp index b6d5dd4..f5ce456 100644 --- a/vpr/src/draw/draw.cpp +++ b/vpr/src/draw/draw.cpp
@@ -3240,7 +3240,9 @@ std::reverse(rr_nodes_on_path.begin(), rr_nodes_on_path.end()); if (allocated_route_tree_structs) { - free_route_tree_timing_structs(); //Clean-up + clear_rr_node_to_rt_node(); //Clean-up + free_route_tree_timing_structs(); + //See discussion in route_tree_timing.cpp on clear_rr_node_to_rt_node usage. } return rr_nodes_on_path; }
diff --git a/vpr/src/route/route_timing.cpp b/vpr/src/route/route_timing.cpp index 85b80e3..8a8a501 100644 --- a/vpr/src/route/route_timing.cpp +++ b/vpr/src/route/route_timing.cpp
@@ -827,6 +827,9 @@ free(sink_order + 1); // coverity[offset_free : Intentional] free(rt_node_of_sink + 1); + + //See discussion in route_tree_timing.cpp on clear_rr_node_to_rt_node usage. + clear_rr_node_to_rt_node(); free_route_tree_timing_structs(); }
diff --git a/vpr/src/route/route_tree_timing.cpp b/vpr/src/route/route_tree_timing.cpp index 5cb0490..e2619ce 100644 --- a/vpr/src/route/route_tree_timing.cpp +++ b/vpr/src/route/route_tree_timing.cpp
@@ -21,11 +21,7 @@ * about the partial routing during timing-driven routing, so the routines * in this module are used to keep a tree representation of the partial * routing during timing-driven routing. This allows rapid incremental - * timing analysis. The net_delay module does timing analysis in one step - * (not incrementally as pieces of the routing are added). I could probably - * one day remove a lot of net_delay.c and call the corresponding routines - * here, but it's useful to have a from-scratch delay calculator to check - * the results of this one. */ + * timing analysis. */ /********************** Variables local to this module ***********************/ @@ -93,6 +89,25 @@ return true; } +void clear_rr_node_to_rt_node() { + /* This is a function which clears the rr_node_to_rt_node vector. + * We do not include this inside free_route_tree_timing_structs() + * because of a VTR_SAFE_ASSERT(timing_check_net_delays) in + * route_timing.cpp. Doing so would clear the vector during routing + * and result in undefined behavior. It is encouraged to use + * free_route_tree_timing_structs() with clear_rr_node_to_rt_node() + * in external modules. + * Example usage: + * + * module(){ + * ... + * clear_rr_node_to_rt_node(); + * free_route_tree_timing_structs(); + * ... + * } */ + rr_node_to_rt_node.clear(); +} + void free_route_tree_timing_structs() { /* Frees the structures needed to build routing trees, and really frees * (i.e. calls free) all the data on the free lists. */ @@ -100,8 +115,6 @@ t_rt_node *rt_node, *next_node; t_linked_rt_edge *rt_edge, *next_edge; - rr_node_to_rt_node.clear(); - rt_node = rt_node_free_list; while (rt_node != nullptr) {
diff --git a/vpr/src/route/route_tree_timing.h b/vpr/src/route/route_tree_timing.h index 8c8c12f..7e17eca 100644 --- a/vpr/src/route/route_tree_timing.h +++ b/vpr/src/route/route_tree_timing.h
@@ -36,6 +36,8 @@ bool verify_route_tree(t_rt_node* root); bool verify_traceback_route_tree_equivalent(const t_trace* trace_head, const t_rt_node* rt_root); +void clear_rr_node_to_rt_node(); + /********** Incremental reroute ***********/ // instead of ripping up a net that has some congestion, cut the branches // that don't legally lead to a sink and start routing with that partial route tree
diff --git a/vpr/src/route/router_delay_profiling.cpp b/vpr/src/route/router_delay_profiling.cpp index 7ed4657..7217eed 100644 --- a/vpr/src/route/router_delay_profiling.cpp +++ b/vpr/src/route/router_delay_profiling.cpp
@@ -203,5 +203,7 @@ free_route_structs(); free_trace_structs(); + //See discussion in route_tree_timing.cpp on clear_rr_node_to_rt_node usage. + clear_rr_node_to_rt_node(); free_route_tree_timing_structs(); }
diff --git a/vpr/src/timing/net_delay.cpp b/vpr/src/timing/net_delay.cpp index 38c67cc..93db645 100644 --- a/vpr/src/timing/net_delay.cpp +++ b/vpr/src/timing/net_delay.cpp
@@ -74,7 +74,7 @@ void load_net_delay_from_routing(vtr::vector<ClusterNetId, float*>& net_delay) { /* This routine loads net_delay[0..nets.size()-1][1..num_pins-1]. Each entry * - * is the Elmore delay from the net source to the appropriate sink. Both * + * is the Elmore delay from the net source to the appropriate sink. Both * * the rr_graph and the routing traceback must be completely constructed * * before this routine is called, and the net_delay array must have been * * allocated. */ @@ -91,15 +91,15 @@ } static void load_one_net_delay(vtr::vector<ClusterNetId, float*>& net_delay, ClusterNetId net_id) { - /* This routine loads delay values of one net of the 2-d data structure i.e. * - * net_delay[net_id][1..num_pins-1]. First, it constructs the route tree * - * from the traceback, next it updates the values for R, C, and Tdel. * + /* This routine loads delay values for one net in * + * net_delay[net_id][1..num_pins-1]. First, from the traceback, it * + * the route tree and computes its values for R, C, and Tdel. * * Next, it walks the route tree recursively, storing the time delays for * * each node into the map inode_to_Tdel. Then, while looping through the * * net_delay array we search for the inode corresponding to the pin * - * identifiers, and updated the entry in net_delay. * - * array during the traversal. Finally, it frees the route tree and clears * - * the inode_to_Tdel_map associated with that net. */ + * identifiers, and correspondingly update the entry in net_delay. * + * Finally, it frees the route tree and clears the inode_to_Tdel_map * + * associated with that net. */ auto& route_ctx = g_vpr_ctx.routing(); @@ -115,14 +115,14 @@ load_new_subtree_R_upstream(rt_root); // load in the resistance values for the route tree load_new_subtree_C_downstream(rt_root); // load in the capacitance values for the route tree load_route_tree_Tdel(rt_root, 0.); // load the time delay values for the route tree - load_one_net_delay_recurr(rt_root, net_id); // recursively the tree and load entries into the inode_to_Tdel map + load_one_net_delay_recurr(rt_root, net_id); // recursively traverse the tree and load entries into the inode_to_Tdel map for (unsigned int ipin = 1; ipin < cluster_ctx.clb_nlist.net_pins(net_id).size(); ipin++) { inode = route_ctx.net_rr_terminals[net_id][ipin]; // look for the inode corresponding to the net_delay indices net_delay[net_id][ipin] = inode_to_Tdel_map.find(inode)->second; // search for the value of Tdel in the inode map and load into net_delay } free_route_tree(rt_root); // free the route tree - inode_to_Tdel_map.clear(); // clear the net pairs from the map + inode_to_Tdel_map.clear(); // clear the map } static void load_one_net_delay_recurr(t_rt_node* node, ClusterNetId net_id) {