diff --git a/vpr/src/device/rr_graph_obj.cpp b/vpr/src/device/rr_graph_obj.cpp index 37ab22729..588edb17e 100644 --- a/vpr/src/device/rr_graph_obj.cpp +++ b/vpr/src/device/rr_graph_obj.cpp @@ -370,21 +370,24 @@ RRNodeId RRGraph::find_node(const short& x, const short& y, const t_rr_type& typ /* Check if x, y, type and ptc, side is valid */ if ((x < 0) /* See if x is smaller than the index of first element */ - || (size_t(x) > node_lookup_.dim_size(0) - 1)) { /* See if x is large than the index of last element */ + || (size_t(x) > node_lookup_.dim_size(0) - 1) /* See if x is large than the index of last element */ + || (0 == node_lookup_.dim_size(0))) { /* See if x is large than the index of last element */ /* Return a zero range! */ return RRNodeId::INVALID(); } /* Check if x, y, type and ptc, side is valid */ if ((y < 0) /* See if y is smaller than the index of first element */ - || (size_t(y) > node_lookup_.dim_size(1) - 1)) { /* See if y is large than the index of last element */ + || (size_t(y) > node_lookup_.dim_size(1) - 1) /* See if y is large than the index of last element */ + || (0 == node_lookup_.dim_size(1))) { /* See if y is large than the index of last element */ /* Return a zero range! */ return RRNodeId::INVALID(); } /* Check if x, y, type and ptc, side is valid */ /* itype is always larger than -1, we can skip checking */ - if (itype > node_lookup_.dim_size(2) - 1) { /* See if type is large than the index of last element */ + if ( (itype > node_lookup_.dim_size(2) - 1) /* See if type is large than the index of last element */ + || (0 == node_lookup_.dim_size(2))) { /* See if type is large than the index of last element */ /* Return a zero range! */ return RRNodeId::INVALID(); } @@ -399,7 +402,8 @@ RRNodeId RRGraph::find_node(const short& x, const short& y, const t_rr_type& typ /* Check if x, y, type and ptc, side is valid */ /* iside is always larger than -1, we can skip checking */ - if (iside > node_lookup_[x][y][type][ptc].size() - 1) { /* See if side is large than the index of last element */ + if ((iside > node_lookup_[x][y][type][ptc].size() - 1) /* See if side is large than the index of last element */ + || (0 == node_lookup_[x][y][type][ptc].size()) ) { /* See if side is large than the index of last element */ /* Return a zero range! */ return RRNodeId::INVALID(); } @@ -857,7 +861,7 @@ RRNodeId RRGraph::create_node(const t_rr_type& type) { RREdgeId RRGraph::create_edge(const RRNodeId& source, const RRNodeId& sink, const RRSwitchId& switch_id) { VTR_ASSERT(valid_node_id(source)); VTR_ASSERT(valid_node_id(sink)); - //VTR_ASSERT(valid_switch_id(switch_id)); + VTR_ASSERT(valid_switch_id(switch_id)); /* Allocate an ID */ RREdgeId edge_id = RREdgeId(num_edges_); diff --git a/vpr/src/device/rr_graph_obj.h b/vpr/src/device/rr_graph_obj.h index fedc90612..a81a5b301 100644 --- a/vpr/src/device/rr_graph_obj.h +++ b/vpr/src/device/rr_graph_obj.h @@ -725,6 +725,9 @@ class RRGraph { /* top-level function to free, should be called when to delete a RRGraph */ void clear(); + + /* Due to the rr_graph builder, we have to make this method public!!!! */ + void clear_switches(); public: /* Type implementations */ /* @@ -776,7 +779,6 @@ class RRGraph { private: /* Internal free functions */ void clear_nodes(); void clear_edges(); - void clear_switches(); void clear_segments(); private: /* Graph Compression related */ diff --git a/vpr/src/route/router_delay_profiling.h b/vpr/src/route/router_delay_profiling.h index 63b8bed65..0bd5e3296 100644 --- a/vpr/src/route/router_delay_profiling.h +++ b/vpr/src/route/router_delay_profiling.h @@ -15,7 +15,7 @@ class RouterDelayProfiler { const RouterLookahead* router_lookahead_; }; -vtr::vector calculate_all_path_delays_from_rr_node(int src_rr_node, const t_router_opts& router_opts); +vtr::vector calculate_all_path_delays_from_rr_node(const RRNodeId& src_rr_node, const t_router_opts& router_opts); void alloc_routing_structs(t_chan_width chan_width, const t_router_opts& router_opts, diff --git a/vpr/src/route/rr_graph.cpp b/vpr/src/route/rr_graph.cpp index 6e5ded8b1..a801098c6 100644 --- a/vpr/src/route/rr_graph.cpp +++ b/vpr/src/route/rr_graph.cpp @@ -251,6 +251,11 @@ static void alloc_and_load_rr_switch_inf(const int num_arch_switches, const int wire_to_arch_ipin_switch, int* wire_to_rr_ipin_switch); +static +t_rr_switch_inf create_rr_switch_from_arch_switch(int arch_switch_idx, + const float R_minW_nmos, + const float R_minW_pmos); + static void remap_rr_node_switch_indices(const t_arch_switch_fanin& switch_fanin); static void load_rr_switch_inf(const int num_arch_switches, const float R_minW_nmos, const float R_minW_pmos, const t_arch_switch_fanin& switch_fanin); @@ -704,6 +709,20 @@ static void build_rr_graph(const t_graph_type graph_type, /* END OPIN MAP */ bool Fc_clipped = false; + + /* Draft the switches as internal data of RRGraph object + * These are temporary switches copied from arch switches + * We use them to build the edges + * We will reset all the switches in the function + * alloc_and_load_rr_switch_inf() + */ + device_ctx.rr_graph.reserve_switches(device_ctx.num_arch_switches); + // Create the switches + for (size_t iswitch = 0; iswitch < device_ctx.num_arch_switches; ++iswitch) { + const t_rr_switch_inf& temp_rr_switch = create_rr_switch_from_arch_switch(iswitch, R_minW_nmos, R_minW_pmos); + device_ctx.rr_graph.create_switch(temp_rr_switch); + } + alloc_and_load_rr_graph(device_ctx.rr_graph.nodes().size(), device_ctx.rr_graph, segment_inf.size(), chan_details_x, chan_details_y, track_to_pin_lookup, opin_to_track_map, @@ -732,13 +751,34 @@ static void build_rr_graph(const t_graph_type graph_type, } } + /* First time to build edges so that we can remap the architecture switch to rr_switch + * This is a must-do before function alloc_and_load_rr_switch_inf() + */ + device_ctx.rr_graph.rebuild_node_edges(); + /* Allocate and load routing resource switches, which are derived from the switches from the architecture file, * based on their fanin in the rr graph. This routine also adjusts the rr nodes to point to these new rr switches */ alloc_and_load_rr_switch_inf(num_arch_switches, R_minW_nmos, R_minW_pmos, wire_to_arch_ipin_switch, wire_to_rr_ipin_switch); - //Partition the rr graph edges for efficient access to configurable/non-configurable - //edge subsets. Must be done after RR switches have been allocated - device_ctx.rr_graph.rebuild_node_edges(); + //Save the channel widths for the newly constructed graph + device_ctx.chan_width = nodes_per_chan; + + rr_graph_externals(segment_inf, max_chan_width, + *wire_to_rr_ipin_switch, base_cost_type); + + /* Rebuild the link between RRGraph node and segments + * Should be called only AFTER the function + * rr_graph_externals() + */ + for (const RRNodeId& inode : device_ctx.rr_graph.nodes()) { + if ( (CHANX != device_ctx.rr_graph.node_type(inode)) + && (CHANY != device_ctx.rr_graph.node_type(inode)) ) { + continue; + } + short irc_data = device_ctx.rr_graph.node_cost_index(inode); + short iseg = device_ctx.rr_indexed_data[irc_data].seg_index; + device_ctx.rr_graph.set_node_segment(inode, RRSegmentId(iseg)); + } /* Essential check for rr_graph, build look-up and */ if (false == device_ctx.rr_graph.validate()) { @@ -749,12 +789,6 @@ static void build_rr_graph(const t_graph_type graph_type, "Fundamental errors occurred when validating rr_graph object!\n"); } - //Save the channel widths for the newly constructed graph - device_ctx.chan_width = nodes_per_chan; - - rr_graph_externals(segment_inf, max_chan_width, - *wire_to_rr_ipin_switch, base_cost_type); - check_rr_graph(graph_type, grid, types); /* Error out if advanced checker of rr_graph fails */ if (false == check_rr_graph(device_ctx.rr_graph)) { @@ -922,6 +956,7 @@ static void load_rr_switch_inf(const int num_arch_switches, const float R_minW_n } /* Create switches as internal data of RRGraph object */ + device_ctx.rr_graph.clear_switches(); device_ctx.rr_graph.reserve_switches(device_ctx.rr_switch_inf.size()); // Create the switches for (size_t iswitch = 0; iswitch < device_ctx.rr_switch_inf.size(); ++iswitch) { @@ -930,6 +965,41 @@ static void load_rr_switch_inf(const int num_arch_switches, const float R_minW_n } +static +t_rr_switch_inf create_rr_switch_from_arch_switch(int arch_switch_idx, + const float R_minW_nmos, + const float R_minW_pmos) { + auto& device_ctx = g_vpr_ctx.mutable_device(); + t_rr_switch_inf rr_switch_inf; + + /* figure out, by looking at the arch switch's Tdel map, what the delay of the new + * rr switch should be */ + double rr_switch_Tdel = device_ctx.arch_switch_inf[arch_switch_idx].Tdel(0); + + /* copy over the arch switch to rr_switch_inf[rr_switch_idx], but with the changed Tdel value */ + rr_switch_inf.set_type(device_ctx.arch_switch_inf[arch_switch_idx].type()); + rr_switch_inf.R = device_ctx.arch_switch_inf[arch_switch_idx].R; + rr_switch_inf.Cin = device_ctx.arch_switch_inf[arch_switch_idx].Cin; + rr_switch_inf.Cinternal = device_ctx.arch_switch_inf[arch_switch_idx].Cinternal; + rr_switch_inf.Cout = device_ctx.arch_switch_inf[arch_switch_idx].Cout; + rr_switch_inf.Tdel = rr_switch_Tdel; + rr_switch_inf.mux_trans_size = device_ctx.arch_switch_inf[arch_switch_idx].mux_trans_size; + if (device_ctx.arch_switch_inf[arch_switch_idx].buf_size_type == BufferSize::AUTO) { + //Size based on resistance + rr_switch_inf.buf_size = trans_per_buf(device_ctx.arch_switch_inf[arch_switch_idx].R, R_minW_nmos, R_minW_pmos); + } else { + VTR_ASSERT(device_ctx.arch_switch_inf[arch_switch_idx].buf_size_type == BufferSize::ABSOLUTE); + //Use the specified size + rr_switch_inf.buf_size = device_ctx.arch_switch_inf[arch_switch_idx].buf_size; + } + rr_switch_inf.name = device_ctx.arch_switch_inf[arch_switch_idx].name; + rr_switch_inf.power_buffer_type = device_ctx.arch_switch_inf[arch_switch_idx].power_buffer_type; + rr_switch_inf.power_buffer_size = device_ctx.arch_switch_inf[arch_switch_idx].power_buffer_size; + + return rr_switch_inf; +} + + void load_rr_switch_from_arch_switch(int arch_switch_idx, int rr_switch_idx, int fanin,