From 441de129366d77d218bb6d0b18642f4cea1782ad Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 6 Mar 2020 14:43:12 -0700 Subject: [PATCH 1/7] adapt Fc in gsb connection builder to use VPR8 Fc builder --- .../tileable_rr_graph_edge_builder.cpp | 3 +- .../tileable_rr_graph_edge_builder.h | 4 +- .../tileable_rr_graph_gsb.cpp | 57 +++++++++++++------ .../tileable_rr_graph/tileable_rr_graph_gsb.h | 4 +- 4 files changed, 47 insertions(+), 21 deletions(-) diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.cpp index 185e4923b..fd2d4db62 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.cpp +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.cpp @@ -92,7 +92,8 @@ void build_rr_graph_edges(RRGraph& rr_graph, const DeviceGrid& grids, const vtr::Point& device_chan_width, const std::vector& segment_inf, - int** Fc_in, int** Fc_out, + const std::vector>& Fc_in, + const std::vector>& Fc_out, const e_switch_block_type& sb_type, const int& Fs, const e_switch_block_type& sb_subtype, const int& subFs, const bool& wire_opposite_side) { diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.h b/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.h index 34c2ced24..4a643fcda 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.h +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_edge_builder.h @@ -7,6 +7,7 @@ #include /* Headers from vtrutil library */ +#include "vtr_ndmatrix.h" #include "vtr_geometry.h" #include "physical_types.h" @@ -26,7 +27,8 @@ void build_rr_graph_edges(RRGraph& rr_graph, const DeviceGrid& grids, const vtr::Point& device_chan_width, const std::vector& segment_inf, - int** Fc_in, int** Fc_out, + const std::vector>& Fc_in, + const std::vector>& Fc_out, const e_switch_block_type& sb_type, const int& Fs, const e_switch_block_type& sb_subtype, const int& subFs, const bool& wire_opposite_side); diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp index e2bf6e4ce..cca9e001c 100755 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp @@ -966,7 +966,7 @@ void build_gsb_one_ipin_track2pin_map(const RRGraph& rr_graph, const RRGSB& rr_gsb, const enum e_side& ipin_side, const size_t& ipin_node_id, - const size_t& Fc, + const std::vector& Fc, const size_t& offset, const std::vector& segment_inf, t_track2pin_map& track2ipin_map) { @@ -995,7 +995,7 @@ void build_gsb_one_ipin_track2pin_map(const RRGraph& rr_graph, VTR_ASSERT(0 == actual_track_list.size() % 2); /* Scale Fc */ - int actual_Fc = std::ceil((float)Fc * (float)actual_track_list.size() / (float)chan_width); + int actual_Fc = std::ceil((float)Fc[iseg] * (float)actual_track_list.size() / (float)chan_width); /* Minimum Fc should be 2 : ensure we will connect to a pair of routing tracks */ actual_Fc = std::max(1, actual_Fc); /* Compute the step between two connection from this IPIN to tracks: @@ -1060,7 +1060,7 @@ void build_gsb_one_opin_pin2track_map(const RRGraph& rr_graph, const RRGSB& rr_gsb, const enum e_side& opin_side, const size_t& opin_node_id, - const size_t& Fc, + const std::vector& Fc, const size_t& offset, const std::vector& segment_inf, t_pin2track_map& opin2track_map) { @@ -1094,7 +1094,7 @@ void build_gsb_one_opin_pin2track_map(const RRGraph& rr_graph, } /* Scale Fc */ - int actual_Fc = std::ceil((float)Fc * (float)actual_track_list.size() / (float)chan_width); + int actual_Fc = std::ceil((float)Fc[iseg] * (float)actual_track_list.size() / (float)chan_width); /* Minimum Fc should be 1 : ensure we will drive 1 routing track */ actual_Fc = std::max(1, actual_Fc); /* Compute the step between two connection from this IPIN to tracks: @@ -1144,8 +1144,6 @@ void build_gsb_one_opin_pin2track_map(const RRGraph& rr_graph, } */ } - - return; } @@ -1163,7 +1161,7 @@ t_track2pin_map build_gsb_track_to_ipin_map(const RRGraph& rr_graph, const RRGSB& rr_gsb, const DeviceGrid& grids, const std::vector& segment_inf, - int** Fc_in) { + const std::vector>& Fc_in) { t_track2pin_map track2ipin_map; /* Resize the matrix */ track2ipin_map.resize(rr_gsb.get_num_sides()); @@ -1202,16 +1200,29 @@ t_track2pin_map build_gsb_track_to_ipin_map(const RRGraph& rr_graph, if (true == is_empty_type(grids[rr_graph.node_xlow(ipin_node)][rr_graph.node_ylow(ipin_node)].type)) { continue; } + int grid_type_index = grids[rr_graph.node_xlow(ipin_node)][rr_graph.node_ylow(ipin_node)].type->index; /* Get Fc of the ipin */ - int ipin_Fc = Fc_in[grid_type_index][rr_graph.node_pin_num(ipin_node)]; - /* skip Fc = 0 */ - if ( (-1 == ipin_Fc) - || (0 == ipin_Fc) ) { + /* skip Fc = 0 or unintialized, those pins are in the */ + bool skip_conn2track = true; + std::vector ipin_Fc_out; + for (size_t iseg = 0; iseg < segment_inf.size(); ++iseg) { + int ipin_Fc = Fc_in[grid_type_index][rr_graph.node_pin_num(ipin_node)][iseg]; + ipin_Fc_out.push_back(ipin_Fc); + if (0 != ipin_Fc) { + skip_conn2track = false; + break; + } + } + + if (true == skip_conn2track) { continue; } + + VTR_ASSERT(ipin_Fc_out.size() == segment_inf.size()); + /* Build track2ipin_map for this IPIN */ - build_gsb_one_ipin_track2pin_map(rr_graph, rr_gsb, ipin_side, inode, ipin_Fc, + build_gsb_one_ipin_track2pin_map(rr_graph, rr_gsb, ipin_side, inode, ipin_Fc_out, /* Give an offset for the first track that this ipin will connect to */ offset[chan_side_manager.to_size_t()], segment_inf, track2ipin_map); @@ -1240,7 +1251,7 @@ t_pin2track_map build_gsb_opin_to_track_map(const RRGraph& rr_graph, const RRGSB& rr_gsb, const DeviceGrid& grids, const std::vector& segment_inf, - int** Fc_out) { + const std::vector>& Fc_out) { t_pin2track_map opin2track_map; /* Resize the matrix */ opin2track_map.resize(rr_gsb.get_num_sides()); @@ -1269,15 +1280,27 @@ t_pin2track_map build_gsb_opin_to_track_map(const RRGraph& rr_graph, continue; } int grid_type_index = grids[rr_graph.node_xlow(opin_node)][rr_graph.node_ylow(opin_node)].type->index; + /* Get Fc of the ipin */ - int opin_Fc = Fc_out[grid_type_index][rr_graph.node_pin_num(opin_node)]; /* skip Fc = 0 or unintialized, those pins are in the */ - if ( (-1 == opin_Fc) - || (0 == opin_Fc) ) { + bool skip_conn2track = true; + std::vector opin_Fc_out; + for (size_t iseg = 0; iseg < segment_inf.size(); ++iseg) { + int opin_Fc = Fc_out[grid_type_index][rr_graph.node_pin_num(opin_node)][iseg]; + opin_Fc_out.push_back(opin_Fc); + if (0 != opin_Fc) { + skip_conn2track = false; + break; + } + } + + if (true == skip_conn2track) { continue; } + VTR_ASSERT(opin_Fc_out.size() == segment_inf.size()); + /* Build track2ipin_map for this IPIN */ - build_gsb_one_opin_pin2track_map(rr_graph, rr_gsb, opin_side, inode, opin_Fc, + build_gsb_one_opin_pin2track_map(rr_graph, rr_gsb, opin_side, inode, opin_Fc_out, /* Give an offset for the first track that this ipin will connect to */ offset[side_manager.to_size_t()], segment_inf, opin2track_map); diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.h b/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.h index 7c7568fb9..adf6118fb 100755 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.h +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.h @@ -59,13 +59,13 @@ t_track2pin_map build_gsb_track_to_ipin_map(const RRGraph& rr_graph, const RRGSB& rr_gsb, const DeviceGrid& grids, const std::vector& segment_inf, - int** Fc_in); + const std::vector>& Fc_in); t_pin2track_map build_gsb_opin_to_track_map(const RRGraph& rr_graph, const RRGSB& rr_gsb, const DeviceGrid& grids, const std::vector& segment_inf, - int** Fc_out); + const std::vector>& Fc_out); void build_direct_connections_for_one_gsb(RRGraph& rr_graph, const DeviceGrid& grids, From 441a30710084631f5da10a07c5a253a407b1cd5c Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 6 Mar 2020 14:54:40 -0700 Subject: [PATCH 2/7] add routing chan width corrector to rr_graph builder utils --- .../tileable_rr_graph/rr_graph_builder_utils.cpp | 15 +++++++++++++++ .../tileable_rr_graph/rr_graph_builder_utils.h | 2 ++ .../tileable_chan_details_builder.cpp | 7 ++----- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/vpr/src/tileable_rr_graph/rr_graph_builder_utils.cpp b/vpr/src/tileable_rr_graph/rr_graph_builder_utils.cpp index 47926e8c7..446518faf 100644 --- a/vpr/src/tileable_rr_graph/rr_graph_builder_utils.cpp +++ b/vpr/src/tileable_rr_graph/rr_graph_builder_utils.cpp @@ -15,6 +15,21 @@ /* begin namespace openfpga */ namespace openfpga { +/************************************************************************ + * Correct number of routing channel width to be compatible to + * uni-directional routing architecture + ***********************************************************************/ +size_t find_unidir_routing_channel_width(const size_t& chan_width) { + size_t actual_chan_width = chan_width; + /* Correct the chan_width: it should be an even number */ + if (0 != actual_chan_width % 2) { + actual_chan_width++; /* increment it to be even */ + } + VTR_ASSERT(0 == actual_chan_width % 2); + + return actual_chan_width; +} + /************************************************************************ * Get the class index of a grid pin ***********************************************************************/ diff --git a/vpr/src/tileable_rr_graph/rr_graph_builder_utils.h b/vpr/src/tileable_rr_graph/rr_graph_builder_utils.h index 1367466d4..b63afa59d 100644 --- a/vpr/src/tileable_rr_graph/rr_graph_builder_utils.h +++ b/vpr/src/tileable_rr_graph/rr_graph_builder_utils.h @@ -15,6 +15,8 @@ /* begin namespace openfpga */ namespace openfpga { +size_t find_unidir_routing_channel_width(const size_t& chan_width); + int get_grid_pin_class_index(const t_grid_tile& cur_grid, const int pin_index); diff --git a/vpr/src/tileable_rr_graph/tileable_chan_details_builder.cpp b/vpr/src/tileable_rr_graph/tileable_chan_details_builder.cpp index 23c1d7c07..ec02b1bb1 100644 --- a/vpr/src/tileable_rr_graph/tileable_chan_details_builder.cpp +++ b/vpr/src/tileable_rr_graph/tileable_chan_details_builder.cpp @@ -11,6 +11,7 @@ #include "vtr_assert.h" #include "vtr_log.h" +#include "rr_graph_builder_utils.h" #include "tileable_chan_details_builder.h" /* begin namespace openfpga */ @@ -167,11 +168,7 @@ ChanNodeDetails build_unidir_chan_node_details(const size_t& chan_width, const bool& force_end, const std::vector& segment_inf) { ChanNodeDetails chan_node_details; - size_t actual_chan_width = chan_width; - /* Correct the chan_width: it should be an even number */ - if (0 != actual_chan_width % 2) { - actual_chan_width++; /* increment it to be even */ - } + size_t actual_chan_width = find_unidir_routing_channel_width(chan_width); VTR_ASSERT(0 == actual_chan_width % 2); /* Reserve channel width */ From 3eb59d201f10308870304022cbacfa65b065ae96 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 6 Mar 2020 15:24:26 -0700 Subject: [PATCH 3/7] adapt top function of tileable rr_graph builder --- vpr/src/device/rr_graph_obj.h | 12 +- vpr/src/route/check_rr_graph.h | 1 + vpr/src/route/rr_graph.cpp | 56 +-- vpr/src/route/rr_graph.h | 27 ++ .../tileable_chan_details_builder.cpp | 1 - .../tileable_chan_details_builder.h | 4 + .../tileable_rr_graph_builder.cpp | 323 ++++++++++++++++++ .../tileable_rr_graph_builder.h | 38 +++ 8 files changed, 413 insertions(+), 49 deletions(-) create mode 100644 vpr/src/tileable_rr_graph/tileable_rr_graph_builder.cpp create mode 100644 vpr/src/tileable_rr_graph/tileable_rr_graph_builder.h diff --git a/vpr/src/device/rr_graph_obj.h b/vpr/src/device/rr_graph_obj.h index 08abf682c..648934554 100644 --- a/vpr/src/device/rr_graph_obj.h +++ b/vpr/src/device/rr_graph_obj.h @@ -583,6 +583,12 @@ class RRGraph { /* Validate is the edge id does exist in the RRGraph */ bool valid_edge_id(const RREdgeId& edge) const; + /* Validate switch list */ + bool valid_switch_id(const RRSwitchId& switch_id) const; + + /* Validate segment list */ + bool valid_segment_id(const RRSegmentId& segment_id) const; + public: /* Mutators */ /* Reserve the lists of nodes, edges, switches etc. to be memory efficient. * This function is mainly used to reserve memory space inside RRGraph, @@ -835,12 +841,6 @@ class RRGraph { bool validate_edge_src_nodes() const; bool validate_edge_sink_nodes() const; - /* Validate switch list */ - bool valid_switch_id(const RRSwitchId& switch_id) const; - - /* Validate segment list */ - bool valid_segment_id(const RRSegmentId& segment_id) const; - private: /* Internal Data */ /* Node related data */ size_t num_nodes_; /* Range of node ids */ diff --git a/vpr/src/route/check_rr_graph.h b/vpr/src/route/check_rr_graph.h index 71d435e70..2416fe666 100644 --- a/vpr/src/route/check_rr_graph.h +++ b/vpr/src/route/check_rr_graph.h @@ -1,6 +1,7 @@ #ifndef CHECK_RR_GRAPH_H #define CHECK_RR_GRAPH_H #include "physical_types.h" +#include "vpr_context.h" void check_rr_graph(const t_graph_type graph_type, const DeviceGrid& grid, diff --git a/vpr/src/route/rr_graph.cpp b/vpr/src/route/rr_graph.cpp index ae6e2593e..50f2799d9 100644 --- a/vpr/src/route/rr_graph.cpp +++ b/vpr/src/route/rr_graph.cpp @@ -236,30 +236,12 @@ void uniquify_edges(t_rr_edge_info_set& rr_edges_to_create); void alloc_and_load_edges(RRGraph& rr_graph, const t_rr_edge_info_set& rr_edges_to_create); -static void alloc_and_load_rr_switch_inf(const int num_arch_switches, - const float R_minW_nmos, - const float R_minW_pmos, - 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); static void alloc_rr_switch_inf(t_arch_switch_fanin& switch_fanin); -static void rr_graph_externals(const std::vector& segment_inf, - int max_chan_width, - int wire_to_rr_ipin_switch, - enum e_base_cost_type base_cost_type); - -static t_clb_to_clb_directs* alloc_and_load_clb_to_clb_directs(const t_direct_inf* directs, const int num_directs, const int delayless_switch); - static void free_type_track_to_pin_map(t_track_to_pin_lookup& track_to_pin_map, const std::vector& types, int max_chan_width); @@ -267,15 +249,6 @@ static void free_type_track_to_pin_map(t_track_to_pin_lookup& track_to_pin_map, static t_seg_details* alloc_and_load_global_route_seg_details(const int global_route_switch, int* num_seg_details = nullptr); -static std::vector> alloc_and_load_actual_fc(const std::vector& types, - const int max_pins, - const std::vector& segment_inf, - const int* sets_per_seg_type, - const int max_chan_width, - const e_fc_type fc_type, - const enum e_directionality directionality, - bool* Fc_clipped); - static RRNodeId pick_best_direct_connect_target_rr_node(const RRGraph& rr_graph, const RRNodeId& from_rr, const std::vector& candidate_rr_nodes); @@ -836,7 +809,7 @@ static void build_rr_graph(const t_graph_type graph_type, * and count how many different fan-ins exist for each arch switch. * Then we create these rr switches and update the switch indices * of rr_nodes to index into the rr_switch_inf array. */ -static void alloc_and_load_rr_switch_inf(const int num_arch_switches, const float R_minW_nmos, const float R_minW_pmos, const int wire_to_arch_ipin_switch, int* wire_to_rr_ipin_switch) { +void alloc_and_load_rr_switch_inf(const int num_arch_switches, const float R_minW_nmos, const float R_minW_pmos, const int wire_to_arch_ipin_switch, int* wire_to_rr_ipin_switch) { /* we will potentially be creating a couple of versions of each arch switch where * each version corresponds to a different fan-in. We will need to fill device_ctx.rr_switch_inf * with this expanded list of switches. @@ -962,7 +935,6 @@ 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) { @@ -1057,10 +1029,10 @@ static void remap_rr_node_switch_indices(const t_arch_switch_fanin& switch_fanin } } -static void rr_graph_externals(const std::vector& segment_inf, - int max_chan_width, - int wire_to_rr_ipin_switch, - enum e_base_cost_type base_cost_type) { +void rr_graph_externals(const std::vector& segment_inf, + int max_chan_width, + int wire_to_rr_ipin_switch, + enum e_base_cost_type base_cost_type) { auto& device_ctx = g_vpr_ctx.device(); add_rr_graph_C_from_switches(device_ctx.rr_switch_inf[wire_to_rr_ipin_switch].Cin); @@ -1152,14 +1124,14 @@ static t_seg_details* alloc_and_load_global_route_seg_details(const int global_r } /* Calculates the number of track connections from each block pin to each segment type */ -static std::vector> alloc_and_load_actual_fc(const std::vector& types, - const int max_pins, - const std::vector& segment_inf, - const int* sets_per_seg_type, - const int max_chan_width, - const e_fc_type fc_type, - const enum e_directionality directionality, - bool* Fc_clipped) { +std::vector> alloc_and_load_actual_fc(const std::vector& types, + const int max_pins, + const std::vector& segment_inf, + const int* sets_per_seg_type, + const int max_chan_width, + const e_fc_type fc_type, + const enum e_directionality directionality, + bool* Fc_clipped) { //Initialize Fc of all blocks to zero auto zeros = vtr::Matrix({size_t(max_pins), segment_inf.size()}, 0); std::vector> Fc(types.size(), zeros); @@ -2775,7 +2747,7 @@ static void build_unidir_rr_opins(const int i, const int j, * This data structure supplements the the info in the "directs" data structure * TODO: The function that does this parsing in placement is poorly done because it lacks generality on heterogeniety, should replace with this one */ -static t_clb_to_clb_directs* alloc_and_load_clb_to_clb_directs(const t_direct_inf* directs, const int num_directs, int delayless_switch) { +t_clb_to_clb_directs* alloc_and_load_clb_to_clb_directs(const t_direct_inf* directs, const int num_directs, int delayless_switch) { int i; t_clb_to_clb_directs* clb_to_clb_directs; char *tile_name, *port_name; diff --git a/vpr/src/route/rr_graph.h b/vpr/src/route/rr_graph.h index 1f60b1afc..35ddcc138 100644 --- a/vpr/src/route/rr_graph.h +++ b/vpr/src/route/rr_graph.h @@ -7,6 +7,7 @@ #define INCLUDE_TRACK_BUFFERS false #include "device_grid.h" +#include "clb2clb_directs.h" enum e_graph_type { GRAPH_GLOBAL, /* One node per channel with wire capacity > 1 and full connectivity */ @@ -56,4 +57,30 @@ void load_rr_switch_from_arch_switch(int arch_switch_idx, t_non_configurable_rr_sets identify_non_configurable_rr_sets(); +void rr_graph_externals(const std::vector& segment_inf, + int max_chan_width, + int wire_to_rr_ipin_switch, + enum e_base_cost_type base_cost_type); + +void alloc_and_load_rr_switch_inf(const int num_arch_switches, + const float R_minW_nmos, + const float R_minW_pmos, + const int wire_to_arch_ipin_switch, + int* wire_to_rr_ipin_switch); + +t_clb_to_clb_directs* alloc_and_load_clb_to_clb_directs(const t_direct_inf* directs, const int num_directs, const int delayless_switch); + +std::vector> alloc_and_load_actual_fc(const std::vector& types, + const int max_pins, + const std::vector& segment_inf, + const int* sets_per_seg_type, + const int max_chan_width, + const e_fc_type fc_type, + const enum e_directionality directionality, + bool* Fc_clipped); + +t_rr_switch_inf create_rr_switch_from_arch_switch(int arch_switch_idx, + const float R_minW_nmos, + const float R_minW_pmos); + #endif diff --git a/vpr/src/tileable_rr_graph/tileable_chan_details_builder.cpp b/vpr/src/tileable_rr_graph/tileable_chan_details_builder.cpp index ec02b1bb1..67c8dbe27 100644 --- a/vpr/src/tileable_rr_graph/tileable_chan_details_builder.cpp +++ b/vpr/src/tileable_rr_graph/tileable_chan_details_builder.cpp @@ -26,7 +26,6 @@ namespace openfpga { * therefore, we assign tracks one by one until we meet the frequency requirement * In this way, we can assign the number of tracks with repect to frequency ***********************************************************************/ -static std::vector get_num_tracks_per_seg_type(const size_t& chan_width, const std::vector& segment_inf, const bool& use_full_seg_groups) { diff --git a/vpr/src/tileable_rr_graph/tileable_chan_details_builder.h b/vpr/src/tileable_rr_graph/tileable_chan_details_builder.h index b1a1198b9..e6adb7162 100644 --- a/vpr/src/tileable_rr_graph/tileable_chan_details_builder.h +++ b/vpr/src/tileable_rr_graph/tileable_chan_details_builder.h @@ -15,6 +15,10 @@ /* begin namespace openfpga */ namespace openfpga { +std::vector get_num_tracks_per_seg_type(const size_t& chan_width, + const std::vector& segment_inf, + const bool& use_full_seg_groups); + int adapt_to_tileable_route_chan_width(const int& chan_width, const std::vector& segment_inf); ChanNodeDetails build_unidir_chan_node_details(const size_t& chan_width, diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_builder.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_builder.cpp new file mode 100644 index 000000000..d9f98d895 --- /dev/null +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_builder.cpp @@ -0,0 +1,323 @@ +/************************************************************************ + * This file contains a builder for the complex rr_graph data structure + * Different from VPR rr_graph builders, this builder aims to create a + * highly regular rr_graph, where each Connection Block (CB), Switch + * Block (SB) is the same (except for those on the borders). Thus, the + * rr_graph is called tileable, which brings significant advantage in + * producing large FPGA fabrics. + ***********************************************************************/ +/* Headers from vtrutil library */ +#include "vtr_assert.h" +#include "vtr_time.h" +#include "vtr_log.h" +#include "vtr_memory.h" + +#include "vpr_error.h" +#include "vpr_utils.h" + +#include "rr_graph.h" +#include "check_rr_graph.h" +#include "check_rr_graph_obj.h" + +#include "rr_graph_builder_utils.h" +#include "tileable_chan_details_builder.h" +#include "tileable_rr_graph_node_builder.h" +#include "tileable_rr_graph_edge_builder.h" +#include "tileable_rr_graph_builder.h" + +#include "globals.h" + +/* begin namespace openfpga */ +namespace openfpga { + +/************************************************************************ + * Main function of this file + * Builder for a detailed uni-directional tileable rr_graph + * Global graph is not supported here, the VPR rr_graph generator can be used + * It follows the procedures to complete the rr_graph generation + * 1. Assign the segments for each routing channel, + * To be specific, for each routing track, we assign a routing segment. + * The assignment is subject to users' specifications, such as + * a. length of each type of segment + * b. frequency of each type of segment. + * c. routing channel width + * 2. Estimate the number of nodes in the rr_graph + * This will estimate the number of + * a. IPINs, input pins of each grid + * b. OPINs, output pins of each grid + * c. SOURCE, virtual node which drives OPINs + * d. SINK, virtual node which is connected to IPINs + * e. CHANX and CHANY, routing segments of each channel + * 3. Create the connectivity of OPINs + * a. Evenly assign connections to OPINs to routing tracks + * b. the connection pattern should be same across the fabric + * 4. Create the connectivity of IPINs + * a. Evenly assign connections from routing tracks to IPINs + * b. the connection pattern should be same across the fabric + * 5. Create the switch block patterns, + * It is based on the type of switch block, the supported patterns are + * a. Disjoint, which connects routing track (i)th from (i)th and (i)th routing segments + * b. Universal, which connects routing track (i)th from (i)th and (M-i)th routing segments + * c. Wilton, which rotates the connection of Disjoint by 1 track + * 6. Allocate rr_graph, fill the node information + * For each node, fill + * a. basic information: coordinate(xlow, xhigh, ylow, yhigh), ptc_num + * b. edges (both incoming and outcoming) + * c. handle direct-connections + * 7. Build fast look-up for the rr_graph + * 8. Allocate external data structures + * a. cost_index + * b. RC tree + ***********************************************************************/ +void build_tileable_unidir_rr_graph(const std::vector& types, + const DeviceGrid& grids, + const t_chan_width& chan_width, + const e_switch_block_type& sb_type, const int& Fs, + const e_switch_block_type& sb_subtype, const int& subFs, + const std::vector& segment_inf, + const int& delayless_switch, + const int& wire_to_arch_ipin_switch, + const float R_minW_nmos, + const float R_minW_pmos, + const enum e_base_cost_type& base_cost_type, + const t_direct_inf *directs, + const int& num_directs, + int* wire_to_rr_ipin_switch, + const bool& wire_opposite_side, + int *Warnings) { + + vtr::ScopedStartFinishTimer timer("Build tileable routing resource graph"); + + /* Reset warning flag */ + *Warnings = RR_GRAPH_NO_WARN; + + /* Create a matrix of grid */ + /* Create a vector of channel width, we support X-direction and Y-direction has different W */ + vtr::Point device_chan_width(chan_width.x_max, chan_width.y_max); + + VTR_LOG("X-direction routing channel width is %lu\n", device_chan_width.x()); + VTR_LOG("Y-direction routing channel width is %lu\n", device_chan_width.y()); + + /* Get a mutable device ctx so that we have a mutable rr_graph */ + DeviceContext& device_ctx = g_vpr_ctx.mutable_device(); + + /* The number of segments are in general small, reserve segments may not bring + * significant memory efficiency */ + device_ctx.rr_graph.reserve_segments(segment_inf.size()); + /* Create the segments */ + for (size_t iseg = 0; iseg < segment_inf.size(); ++iseg) { + device_ctx.rr_graph.create_segment(segment_inf[iseg]); + } + + /* TODO: Load architecture switch to rr_graph switches + * 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() + */ + /* TODO: Spot the switch id in the architecture switch list */ + RRSwitchId wire_to_ipin_rr_switch = RRSwitchId::INVALID(); + RRSwitchId delayless_rr_switch = RRSwitchId::INVALID(); + + device_ctx.rr_graph.reserve_switches(device_ctx.num_arch_switches); + /* Create the switches */ + for (int 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); + RRSwitchId rr_switch = device_ctx.rr_graph.create_switch(temp_rr_switch); + if (iswitch == wire_to_arch_ipin_switch) { + wire_to_ipin_rr_switch = rr_switch; + } + if (iswitch == delayless_switch) { + delayless_rr_switch = rr_switch; + } + } + /* Validate the special switches */ + VTR_ASSERT(true == device_ctx.rr_graph.valid_switch_id(wire_to_ipin_rr_switch)); + VTR_ASSERT(true == device_ctx.rr_graph.valid_switch_id(delayless_rr_switch)); + + /* A temp data about the driver switch ids for each rr_node */ + vtr::vector rr_node_driver_switches; + + /* A temp data about the track ids for each CHANX and CHANY rr_node */ + std::map> rr_node_track_ids; + + /************************ + * Allocate the rr_nodes + ************************/ + alloc_tileable_rr_graph_nodes(device_ctx.rr_graph, + rr_node_driver_switches, + grids, + device_chan_width, + segment_inf); + + /************************ + * Create all the rr_nodes + ************************/ + create_tileable_rr_graph_nodes(device_ctx.rr_graph, + rr_node_driver_switches, + rr_node_track_ids, + grids, + device_chan_width, + segment_inf, + wire_to_ipin_rr_switch, + delayless_rr_switch); + + /************************************************************************ + * Create the connectivity of OPINs + * a. Evenly assign connections to OPINs to routing tracks + * b. the connection pattern should be same across the fabric + * + * Create the connectivity of IPINs + * a. Evenly assign connections from routing tracks to IPINs + * b. the connection pattern should be same across the fabric + ***********************************************************************/ + /* Global routing uses a single longwire track */ + int max_chan_width = find_unidir_routing_channel_width(chan_width.max); + VTR_ASSERT(max_chan_width > 0); + + /* get maximum number of pins across all blocks */ + int max_pins = types[0].num_pins; + for (const auto& type : types) { + if (is_empty_type(&type)) { + continue; + } + + if (type.num_pins > max_pins) { + max_pins = type.num_pins; + } + } + + /* Fc assignment still uses the old function from VPR. + * Should use tileable version so that we have can have full control + */ + std::vector num_tracks = get_num_tracks_per_seg_type(max_chan_width / 2, segment_inf, false); + int* sets_per_seg_type = (int*)vtr::malloc(sizeof(int) * segment_inf.size()); + VTR_ASSERT(num_tracks.size() == segment_inf.size()); + for (size_t iseg = 0; iseg < num_tracks.size(); ++iseg) { + sets_per_seg_type[iseg] = num_tracks[iseg]; + } + + bool Fc_clipped = false; + /* [0..num_types-1][0..num_pins-1] */ + std::vector> Fc_in; + Fc_in = alloc_and_load_actual_fc(types, max_pins, segment_inf, sets_per_seg_type, max_chan_width, + e_fc_type::IN, UNI_DIRECTIONAL, &Fc_clipped); + if (Fc_clipped) { + *Warnings |= RR_GRAPH_WARN_FC_CLIPPED; + } + + Fc_clipped = false; + /* [0..num_types-1][0..num_pins-1] */ + std::vector> Fc_out; + Fc_out = alloc_and_load_actual_fc(types, max_pins, segment_inf, sets_per_seg_type, max_chan_width, + e_fc_type::OUT, UNI_DIRECTIONAL, &Fc_clipped); + + if (Fc_clipped) { + *Warnings |= RR_GRAPH_WARN_FC_CLIPPED; + } + + /************************************************************************ + * Build the connections tile by tile: + * We classify rr_nodes into a general switch block (GSB) data structure + * where we create edges to each rr_nodes in the GSB with respect to + * Fc_in and Fc_out, switch block patterns + * In addition, we will also handle direct-connections: + * Add edges that bridge OPINs and IPINs to the rr_graph + ***********************************************************************/ + /* Create edges for a tileable rr_graph */ + build_rr_graph_edges(device_ctx.rr_graph, + rr_node_driver_switches, + grids, + device_chan_width, + segment_inf, + Fc_in, Fc_out, + sb_type, Fs, sb_subtype, subFs, + wire_opposite_side); + + /************************************************************************ + * Build direction connection lists + * TODO: use tile direct builder + ***********************************************************************/ + /* Create data structure of direct-connections */ + t_clb_to_clb_directs* clb_to_clb_directs = NULL; + if (num_directs > 0) { + clb_to_clb_directs = alloc_and_load_clb_to_clb_directs(directs, num_directs, delayless_switch); + } + std::vector arch_directs; + std::vector clb2clb_directs; + for (int idirect = 0; idirect < num_directs; ++idirect) { + arch_directs.push_back(directs[idirect]); + clb2clb_directs.push_back(clb_to_clb_directs[idirect]); + } + + build_rr_graph_direct_connections(device_ctx.rr_graph, grids, delayless_rr_switch, + arch_directs, clb2clb_directs); + + /* 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(device_ctx.num_arch_switches, R_minW_nmos, R_minW_pmos, wire_to_arch_ipin_switch, wire_to_rr_ipin_switch); + + /* Save the channel widths for the newly constructed graph */ + device_ctx.chan_width = chan_width; + + /************************************************************************ + * Allocate external data structures + * a. cost_index + * b. RC tree + ***********************************************************************/ + 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)); + } + + /************************************************************************ + * Sanitizer for the rr_graph, check connectivities of rr_nodes + ***********************************************************************/ + /* Essential check for rr_graph, build look-up and */ + if (false == device_ctx.rr_graph.validate()) { + /* Error out if built-in validator of rr_graph fails */ + vpr_throw(VPR_ERROR_ROUTE, + __FILE__, + __LINE__, + "Fundamental errors occurred when validating rr_graph object!\n"); + } + + check_rr_graph(GRAPH_UNIDIR, grids, types); + /* Error out if advanced checker of rr_graph fails */ + if (false == check_rr_graph(device_ctx.rr_graph)) { + vpr_throw(VPR_ERROR_ROUTE, + __FILE__, + __LINE__, + "Advanced checking rr_graph object fails! Routing may still work " + "but not smooth\n"); + } + + /************************************************************************ + * Free all temp stucts + ***********************************************************************/ + free(sets_per_seg_type); + + if (nullptr != clb_to_clb_directs) { + free(clb_to_clb_directs); + } +} + +} /* end namespace openfpga */ diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_builder.h b/vpr/src/tileable_rr_graph/tileable_rr_graph_builder.h new file mode 100644 index 000000000..601c7de18 --- /dev/null +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_builder.h @@ -0,0 +1,38 @@ +#ifndef TILEABLE_RR_GRAPH_BUILDER_H +#define TILEABLE_RR_GRAPH_BUILDER_H + +/******************************************************************** + * Include header files that are required by function declaration + *******************************************************************/ +#include + +#include "physical_types.h" +#include "device_grid.h" + +/******************************************************************** + * Function declaration + *******************************************************************/ + +/* begin namespace openfpga */ +namespace openfpga { + +void build_tileable_unidir_rr_graph(const std::vector& types, + const DeviceGrid& grids, + const t_chan_width& chan_width, + const e_switch_block_type& sb_type, const int& Fs, + const e_switch_block_type& sb_subtype, const int& subFs, + const std::vector& segment_inf, + const int& delayless_switch, + const int& wire_to_arch_ipin_switch, + const float R_minW_nmos, + const float R_minW_pmos, + const enum e_base_cost_type& base_cost_type, + const t_direct_inf *directs, + const int& num_directs, + int* wire_to_rr_ipin_switch, + const bool& wire_opposite_side, + int *Warnings); + +} /* end namespace openfpga */ + +#endif From 245a379c4fbb27b280c84fe279d0437bb597b5d4 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 6 Mar 2020 16:03:00 -0700 Subject: [PATCH 4/7] start plug in tileable rr_graph builder --- vpr/src/base/vpr_context.h | 5 ++ vpr/src/base/vpr_types.h | 6 ++ vpr/src/route/rr_graph.cpp | 75 ++++++++++------ .../tileable_rr_graph_builder.cpp | 3 + .../tileable_rr_graph_gsb.cpp | 90 +++++++++++++++++++ 5 files changed, 153 insertions(+), 26 deletions(-) diff --git a/vpr/src/base/vpr_context.h b/vpr/src/base/vpr_context.h index 487382480..d823c921b 100644 --- a/vpr/src/base/vpr_context.h +++ b/vpr/src/base/vpr_context.h @@ -148,6 +148,11 @@ struct DeviceContext : public Context { /* RRGraph object */ RRGraph rr_graph; + /* Track ids for each rr_node in the rr_graph. + * This is used by drawer for tileable routing resource graph + */ + std::map> rr_node_track_ids; + /* Structures to define the routing architecture of the FPGA. */ std::vector rr_nodes; /* autogenerated in build_rr_graph */ diff --git a/vpr/src/base/vpr_types.h b/vpr/src/base/vpr_types.h index dee5fd7e6..009887d71 100644 --- a/vpr/src/base/vpr_types.h +++ b/vpr/src/base/vpr_types.h @@ -1004,6 +1004,12 @@ struct t_det_routing_arch { enum e_switch_block_type switch_block_type; std::vector switchblocks; + /* Xifan Tang: subtype of switch blocks. + * Sub type and Fs are applied to pass tracks + */ + int subFs; + enum e_switch_block_type switch_block_subtype; + short global_route_switch; short delayless_switch; int wire_to_arch_ipin_switch; diff --git a/vpr/src/route/rr_graph.cpp b/vpr/src/route/rr_graph.cpp index 50f2799d9..b21310ad4 100644 --- a/vpr/src/route/rr_graph.cpp +++ b/vpr/src/route/rr_graph.cpp @@ -41,6 +41,8 @@ #include "rr_graph_obj_util.h" #include "check_rr_graph_obj.h" +#include "tileable_rr_graph_builder.h" + #include "clb2clb_directs.h" //#define VERBOSE @@ -318,33 +320,54 @@ void create_rr_graph(const t_graph_type graph_type, free_rr_graph(); - build_rr_graph(graph_type, - block_types, - grid, - nodes_per_chan, - det_routing_arch->switch_block_type, - det_routing_arch->Fs, - det_routing_arch->switchblocks, - num_arch_switches, - segment_inf, - det_routing_arch->global_route_switch, - det_routing_arch->wire_to_arch_ipin_switch, - det_routing_arch->delayless_switch, - det_routing_arch->R_minW_nmos, - det_routing_arch->R_minW_pmos, - base_cost_type, - trim_empty_channels, - trim_obs_channels, - directs, num_directs, - &det_routing_arch->wire_to_rr_ipin_switch, - Warnings); + if (GRAPH_UNIDIR_TILEABLE != graph_type) { + build_rr_graph(graph_type, + block_types, + grid, + nodes_per_chan, + det_routing_arch->switch_block_type, + det_routing_arch->Fs, + det_routing_arch->switchblocks, + num_arch_switches, + segment_inf, + det_routing_arch->global_route_switch, + det_routing_arch->wire_to_arch_ipin_switch, + det_routing_arch->delayless_switch, + det_routing_arch->R_minW_nmos, + det_routing_arch->R_minW_pmos, + base_cost_type, + trim_empty_channels, + trim_obs_channels, + directs, num_directs, + &det_routing_arch->wire_to_rr_ipin_switch, + Warnings); - if (clock_modeling == DEDICATED_NETWORK) { - ClockRRGraphBuilder::create_and_append_clock_rr_graph(segment_inf, - det_routing_arch->R_minW_nmos, - det_routing_arch->R_minW_pmos, - det_routing_arch->wire_to_rr_ipin_switch, - base_cost_type); + if (clock_modeling == DEDICATED_NETWORK) { + ClockRRGraphBuilder::create_and_append_clock_rr_graph(segment_inf, + det_routing_arch->R_minW_nmos, + det_routing_arch->R_minW_pmos, + det_routing_arch->wire_to_rr_ipin_switch, + base_cost_type); + } + } else { + /* We do not support dedicated network for clocks in tileable rr_graph generation */ + openfpga::build_tileable_unidir_rr_graph(block_types, + grid, + nodes_per_chan, + det_routing_arch->switch_block_type, + det_routing_arch->Fs, + det_routing_arch->switch_block_subtype, + det_routing_arch->subFs, + segment_inf, + det_routing_arch->wire_to_arch_ipin_switch, + det_routing_arch->delayless_switch, + det_routing_arch->R_minW_nmos, + det_routing_arch->R_minW_pmos, + base_cost_type, + directs, num_directs, + &det_routing_arch->wire_to_rr_ipin_switch, + false, /* Do not allow passing tracks to be wired to the same routing channels */ + Warnings); } /* Xifan Tang - Create rr_graph object: load rr_nodes to the object */ diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_builder.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_builder.cpp index d9f98d895..f103fb545 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_builder.cpp +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_builder.cpp @@ -266,6 +266,9 @@ void build_tileable_unidir_rr_graph(const std::vector& typ /* Save the channel widths for the newly constructed graph */ device_ctx.chan_width = chan_width; + /* Save the track ids for tileable routing resource graph */ + device_ctx.rr_node_track_ids = rr_node_track_ids; + /************************************************************************ * Allocate external data structures * a. cost_index diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp index cca9e001c..b37265dfb 100755 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_gsb.cpp @@ -1316,4 +1316,94 @@ t_pin2track_map build_gsb_opin_to_track_map(const RRGraph& rr_graph, return opin2track_map; } +/************************************************************************ + * Add all direct clb-pin-to-clb-pin edges to given opin + ***********************************************************************/ +void build_direct_connections_for_one_gsb(RRGraph& rr_graph, + const DeviceGrid& grids, + const vtr::Point& from_grid_coordinate, + const RRSwitchId& delayless_switch, + const std::vector& directs, + const std::vector& clb_to_clb_directs) { + VTR_ASSERT(directs.size() == clb_to_clb_directs.size()); + + const t_grid_tile& from_grid = grids[from_grid_coordinate.x()][from_grid_coordinate.y()]; + t_physical_tile_type_ptr grid_type = from_grid.type; + + /* Iterate through all direct connections */ + for (size_t i = 0; i < directs.size(); ++i) { + /* Bypass unmatched direct clb-to-clb connections */ + if (grid_type != clb_to_clb_directs[i].from_clb_type) { + continue; + } + + /* This opin is specified to connect directly to an ipin, + * now compute which ipin to connect to + */ + vtr::Point to_grid_coordinate(from_grid_coordinate.x() + directs[i].x_offset, + from_grid_coordinate.y() + directs[i].y_offset); + + /* Bypass unmatched direct clb-to-clb connections */ + t_physical_tile_type_ptr to_grid_type = grids[to_grid_coordinate.x()][to_grid_coordinate.y()].type; + /* Check if to_grid if the same grid */ + if (to_grid_type != clb_to_clb_directs[i].to_clb_type) { + continue; + } + + bool swap; + int max_index, min_index; + /* Compute index of opin with regards to given pins */ + if ( clb_to_clb_directs[i].from_clb_pin_start_index + > clb_to_clb_directs[i].from_clb_pin_end_index) { + swap = true; + max_index = clb_to_clb_directs[i].from_clb_pin_start_index; + min_index = clb_to_clb_directs[i].from_clb_pin_end_index; + } else { + swap = false; + min_index = clb_to_clb_directs[i].from_clb_pin_start_index; + max_index = clb_to_clb_directs[i].from_clb_pin_end_index; + } + + /* get every opin in the range */ + for (int opin = min_index; opin <= max_index; ++opin) { + int offset = opin - min_index; + + if ( (to_grid_coordinate.x() < grids.width() - 1) + && (to_grid_coordinate.y() < grids.height() - 1) ) { + int ipin = OPEN; + if ( clb_to_clb_directs[i].to_clb_pin_start_index + > clb_to_clb_directs[i].to_clb_pin_end_index) { + if (true == swap) { + ipin = clb_to_clb_directs[i].to_clb_pin_end_index + offset; + } else { + ipin = clb_to_clb_directs[i].to_clb_pin_start_index - offset; + } + } else { + if(true == swap) { + ipin = clb_to_clb_directs[i].to_clb_pin_end_index - offset; + } else { + ipin = clb_to_clb_directs[i].to_clb_pin_start_index + offset; + } + } + + /* Get the pin index in the rr_graph */ + int from_grid_width_ofs = from_grid.width_offset; + int from_grid_height_ofs = from_grid.height_offset; + int to_grid_width_ofs = grids[to_grid_coordinate.x()][to_grid_coordinate.y()].width_offset; + int to_grid_height_ofs = grids[to_grid_coordinate.x()][to_grid_coordinate.y()].height_offset; + const RRNodeId& opin_node_id = rr_graph.find_node(from_grid_coordinate.x() - from_grid_width_ofs, + from_grid_coordinate.y() - from_grid_height_ofs, + OPIN, opin); + const RRNodeId& ipin_node_id = rr_graph.find_node(to_grid_coordinate.x() - to_grid_width_ofs, + to_grid_coordinate.y() - to_grid_height_ofs, + IPIN, ipin); + /* add edges to the opin_node */ + rr_graph.create_edge(opin_node_id, ipin_node_id, + delayless_switch); + } + } + } +} + + } /* end namespace openfpga */ From 5be118d695ed6682e6bf6e5a78a0062511cee7a2 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 6 Mar 2020 16:18:45 -0700 Subject: [PATCH 5/7] tileable rr_graph builder ready to debug --- libs/libarchfpga/src/physical_types.h | 4 ++++ libs/libarchfpga/src/read_xml_arch_file.cpp | 21 ++++++++++++++++++--- openfpga/test_vpr_arch/k6_frac_N10_40nm.xml | 4 ++-- vpr/src/base/SetupVPR.cpp | 2 ++ 4 files changed, 26 insertions(+), 5 deletions(-) diff --git a/libs/libarchfpga/src/physical_types.h b/libs/libarchfpga/src/physical_types.h index c72a57378..d1cfae62a 100644 --- a/libs/libarchfpga/src/physical_types.h +++ b/libs/libarchfpga/src/physical_types.h @@ -1589,13 +1589,17 @@ struct t_clock_arch_spec { /* Detailed routing architecture */ struct t_arch { char* architecture_id; //Secure hash digest of the architecture file to uniquely identify this architecture + + bool tileable; t_chan_width_dist Chans; enum e_switch_block_type SBType; + enum e_switch_block_type SBSubType; std::vector switchblocks; float R_minW_nmos; float R_minW_pmos; int Fs; + int subFs; float grid_logic_tile_area; std::vector Segments; t_arch_switch_inf* Switches = nullptr; diff --git a/libs/libarchfpga/src/read_xml_arch_file.cpp b/libs/libarchfpga/src/read_xml_arch_file.cpp index 32381faca..1c2bba875 100644 --- a/libs/libarchfpga/src/read_xml_arch_file.cpp +++ b/libs/libarchfpga/src/read_xml_arch_file.cpp @@ -2533,8 +2533,10 @@ static void ProcessModelPorts(pugi::xml_node port_group, t_model* model, std::se static void ProcessLayout(pugi::xml_node layout_tag, t_arch* arch, const pugiutil::loc_data& loc_data) { VTR_ASSERT(layout_tag.name() == std::string("layout")); - //Expect no attributes on - expect_only_attributes(layout_tag, {}, loc_data); + //Expect only tileable attributes on + //expect_only_attributes(layout_tag, {"tileable"}, loc_data); + + arch->tileable = get_attribute(layout_tag, "tileable", loc_data).as_bool(); //Count the number of or tags size_t auto_layout_cnt = 0; @@ -2882,7 +2884,7 @@ static void ProcessDevice(pugi::xml_node Node, t_arch* arch, t_default_fc_spec& // tag Cur = get_single_child(Node, "switch_block", loc_data); - expect_only_attributes(Cur, {"type", "fs"}, loc_data); + //expect_only_attributes(Cur, {"type", "fs", "sub_type", "sub_fs"}, loc_data); Prop = get_attribute(Cur, "type", loc_data).value(); if (strcmp(Prop, "wilton") == 0) { arch->SBType = WILTON; @@ -2898,8 +2900,21 @@ static void ProcessDevice(pugi::xml_node Node, t_arch* arch, t_default_fc_spec& "Unknown property %s for switch block type x\n", Prop); } + Prop = get_attribute(Cur, "sub_type", loc_data, BoolToReqOpt(false)).value(); + if (strcmp(Prop, "wilton") == 0) { + arch->SBSubType = WILTON; + } else if (strcmp(Prop, "universal") == 0) { + arch->SBSubType = UNIVERSAL; + } else if (strcmp(Prop, "subset") == 0) { + arch->SBSubType = SUBSET; + } else { + archfpga_throw(loc_data.filename_c_str(), loc_data.line(Cur), + "Unknown property %s for switch block subtype x\n", Prop); + } + ReqOpt CUSTOM_SWITCHBLOCK_REQD = BoolToReqOpt(!custom_switch_block); arch->Fs = get_attribute(Cur, "fs", loc_data, CUSTOM_SWITCHBLOCK_REQD).as_int(3); + arch->subFs = get_attribute(Cur, "sub_fs", loc_data, BoolToReqOpt(false)).as_int(3); Cur = get_single_child(Node, "default_fc", loc_data, ReqOpt::OPTIONAL); if (Cur) { diff --git a/openfpga/test_vpr_arch/k6_frac_N10_40nm.xml b/openfpga/test_vpr_arch/k6_frac_N10_40nm.xml index 44e2ef289..f5a4b31fa 100644 --- a/openfpga/test_vpr_arch/k6_frac_N10_40nm.xml +++ b/openfpga/test_vpr_arch/k6_frac_N10_40nm.xml @@ -76,7 +76,7 @@ - + @@ -110,7 +110,7 @@ - + diff --git a/vpr/src/base/SetupVPR.cpp b/vpr/src/base/SetupVPR.cpp index 4fd21004e..0cf69a9bb 100644 --- a/vpr/src/base/SetupVPR.cpp +++ b/vpr/src/base/SetupVPR.cpp @@ -309,9 +309,11 @@ static void SetupSwitches(const t_arch& Arch, static void SetupRoutingArch(const t_arch& Arch, t_det_routing_arch* RoutingArch) { RoutingArch->switch_block_type = Arch.SBType; + RoutingArch->switch_block_subtype = Arch.SBSubType; RoutingArch->R_minW_nmos = Arch.R_minW_nmos; RoutingArch->R_minW_pmos = Arch.R_minW_pmos; RoutingArch->Fs = Arch.Fs; + RoutingArch->subFs = Arch.subFs; RoutingArch->directionality = BI_DIRECTIONAL; if (Arch.Segments.size()) { RoutingArch->directionality = Arch.Segments[0].directionality; From f54f46483bcfe56808992773ac017681d7caccd3 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 6 Mar 2020 17:02:22 -0700 Subject: [PATCH 6/7] start debugging tileable rr_graph generator --- vpr/src/base/vpr_api.cpp | 5 +++++ vpr/src/route/rr_graph.cpp | 1 + 2 files changed, 6 insertions(+) diff --git a/vpr/src/base/vpr_api.cpp b/vpr/src/base/vpr_api.cpp index f2900d0d2..53ec0e732 100644 --- a/vpr/src/base/vpr_api.cpp +++ b/vpr/src/base/vpr_api.cpp @@ -829,6 +829,11 @@ void vpr_create_rr_graph(t_vpr_setup& vpr_setup, const t_arch& arch, int chan_wi graph_type = GRAPH_GLOBAL; } else { graph_type = (det_routing_arch->directionality == BI_DIRECTIONAL ? GRAPH_BIDIR : GRAPH_UNIDIR); + /* Branch on tileable routing */ + if ( (UNI_DIRECTIONAL == det_routing_arch->directionality) + && (true == arch.tileable) ) { + graph_type = GRAPH_UNIDIR_TILEABLE; + } } int warnings = 0; diff --git a/vpr/src/route/rr_graph.cpp b/vpr/src/route/rr_graph.cpp index b21310ad4..f80c450c7 100644 --- a/vpr/src/route/rr_graph.cpp +++ b/vpr/src/route/rr_graph.cpp @@ -1504,6 +1504,7 @@ void free_rr_graph() { /* Xifan Tang - Clear the rr_graph object */ device_ctx.rr_graph.clear(); + device_ctx.rr_node_track_ids.clear(); } static void build_rr_sinks_sources(const int i, From c36c3020521c62a557cf838f0f9f608f7cd9b3a9 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 6 Mar 2020 17:16:53 -0700 Subject: [PATCH 7/7] looks like tileable routing is working --- .../tileable_rr_graph/tileable_rr_graph_node_builder.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp b/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp index 2928ed335..57f98b584 100644 --- a/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp +++ b/vpr/src/tileable_rr_graph/tileable_rr_graph_node_builder.cpp @@ -376,8 +376,8 @@ void load_one_grid_opin_nodes_basic_info(RRGraph& rr_graph, /* node bounding box */ rr_graph.set_node_bounding_box(node, vtr::Rect(grid_coordinate.x() + width, - grid_coordinate.x() + width, grid_coordinate.y() + height, + grid_coordinate.x() + width, grid_coordinate.y() + height)); rr_graph.set_node_side(node, side_manager.get_side()); rr_graph.set_node_pin_num(node, pin_num); @@ -439,8 +439,8 @@ void load_one_grid_ipin_nodes_basic_info(RRGraph& rr_graph, /* node bounding box */ rr_graph.set_node_bounding_box(node, vtr::Rect(grid_coordinate.x() + width, - grid_coordinate.x() + width, grid_coordinate.y() + height, + grid_coordinate.x() + width, grid_coordinate.y() + height)); rr_graph.set_node_side(node, side_manager.get_side()); rr_graph.set_node_pin_num(node, pin_num); @@ -491,8 +491,8 @@ void load_one_grid_source_nodes_basic_info(RRGraph& rr_graph, /* node bounding box */ rr_graph.set_node_bounding_box(node, vtr::Rect(grid_coordinate.x(), - grid_coordinate.x(), grid_coordinate.y(), + grid_coordinate.x(), grid_coordinate.y())); rr_graph.set_node_class_num(node, iclass); @@ -542,8 +542,8 @@ void load_one_grid_sink_nodes_basic_info(RRGraph& rr_graph, /* node bounding box */ rr_graph.set_node_bounding_box(node, vtr::Rect(grid_coordinate.x(), - grid_coordinate.x(), grid_coordinate.y(), + grid_coordinate.x(), grid_coordinate.y())); rr_graph.set_node_class_num(node, iclass);