From ba153585645838ec457e54d6510f91e6c37d3e8e Mon Sep 17 00:00:00 2001 From: tangxifan Date: Tue, 18 Jun 2019 18:06:21 -0600 Subject: [PATCH] developing ipin2track mapping for tiles --- .../rr_graph/rr_graph_tileable_builder.c | 137 +++++------- .../rr_graph/rr_graph_tileable_sbox.cpp | 211 ++++++++++++++++++ .../device/rr_graph/rr_graph_tileable_sbox.h | 12 + 3 files changed, 279 insertions(+), 81 deletions(-) create mode 100755 vpr7_x2p/vpr/SRC/device/rr_graph/rr_graph_tileable_sbox.cpp create mode 100755 vpr7_x2p/vpr/SRC/device/rr_graph/rr_graph_tileable_sbox.h diff --git a/vpr7_x2p/vpr/SRC/device/rr_graph/rr_graph_tileable_builder.c b/vpr7_x2p/vpr/SRC/device/rr_graph/rr_graph_tileable_builder.c index 4aaffddc1..54cea15ea 100644 --- a/vpr7_x2p/vpr/SRC/device/rr_graph/rr_graph_tileable_builder.c +++ b/vpr7_x2p/vpr/SRC/device/rr_graph/rr_graph_tileable_builder.c @@ -56,7 +56,7 @@ #include "ReadOptions.h" #include "rr_graph.h" #include "rr_graph2.h" -#include "rr_graph_sbox.h" +#include "rr_graph_tileable_sbox.h" #include "route_common.h" #include "fpga_x2p_types.h" #include "rr_graph_tileable_builder.h" @@ -1384,6 +1384,52 @@ void build_edges_for_one_tileable_rr_gsb(t_rr_graph* rr_graph, RRGSB* rr_gsb, return; } +/************************************************************************ + * Convert the track_to_ipin_look[0..nodes_per_chan-1][0..height][0..3][pin_numbers] + * to the existing routing resources in the General Switch Block (GSB) + * The resulting matrix will be oragnized in + * track2ipin_lookup[gsb_side][0..chan_width-1][ipin_indices] + ***********************************************************************/ +static +std::vector < std::vector< std::vector > > build_gsb_track_to_ipin_lookup(const RRGSB& rr_gsb, + std::vector< std::vector > grids, + int** Fc_in, + int***** ipin_to_track_map) { + std::vector < std::vector< std::vector > > track2ipin_lookup; /* [0..gsb_side][0..num_tracks][0..Fc-1] */ + /* Resize the matrix */ + track2ipin_lookup.resize(rr_gsb.get_num_sides()); + + /* Walk through each side */ + for (size_t side = 0; side < rr_gsb.get_num_sides(); ++side) { + Side side_manager(side); + enum e_side gsb_side = side_manager.get_side(); + /* Get channel width and resize the matrix */ + size_t chan_width = rr_gsb.get_chan_width(gsb_side); + track2ipin_lookup[side].resize(chan_width); + /* Find the ipin nodes */ + for (size_t inode = 0; inode < rr_gsb.get_num_ipin_nodes(gsb_side); ++inode) { + t_rr_node* ipin_node = rr_gsb.get_ipin_node(gsb_side, inode); + /* For each IPIN, we find the type_descriptor, offset and pin_side on the grid */ + int grid_type_id = grids[ipin_node->xlow][ipin_node->ylow].type->index; + int offset = grid[ipin_node->xlow][ipin_node->ylow].offset; + enum e_side pin_side = rr_gsb.get_ipin_node_grid_side(gsb_side, inode); + /* Now, we fill the return matrix */ + /* Bypass empty array */ + if (NULL == ipin_to_track_map[grid_type_id][ipin_node->ptc_num][offset][0]) { + continue; + } + /* Get each track_id */ + for (int iconn = 0; iconn < Fc_in[grid_type_id][ipin_node->ptc_num]; ++iconn) { + int track_id = ipin_to_track_map[grid_type_id][ipin_node->ptc_num][offset][pin_side][iconn]; + track2ipin_lookup[gsb_side][track_id].push_back(inode); + } + } + } + + return track2ipin_lookup; +} + + /************************************************************************ * Build the edges of each rr_node tile by tile: * We classify rr_nodes into a general switch block (GSB) data structure @@ -1399,10 +1445,12 @@ void build_edges_for_one_tileable_rr_gsb(t_rr_graph* rr_graph, RRGSB* rr_gsb, static void build_rr_graph_edges(t_rr_graph* rr_graph, const DeviceCoordinator& device_size, + std::vector< std::vector > grids, std::vector device_chan_width, std::vector segment_inf, int L_num_types, t_type_ptr types, - struct s_ivec**** track_to_ipin_lookup, int***** opin_to_track_map, + int** Fc_in, int** Fc_out, + int***** ipin_to_track_map, int***** opin_to_track_map, vtr::NdMatrix,3> switch_block_conn, int num_directs, t_clb_to_clb_directs* clb_to_clb_directs, int num_switches, int delayless_switch) { @@ -1414,11 +1462,12 @@ void build_rr_graph_edges(t_rr_graph* rr_graph, /* Create a GSB object */ RRGSB rr_gsb = build_one_tileable_rr_gsb(device_range, device_chan_width, segment_inf, gsb_coordinator, rr_graph); /* adapt the track_to_ipin_lookup for the GSB nodes */ - std::vector < std::vector< std::vector > > track2ipin_lookup; /* [0..gsb_side][0..num_tracks][0..Fc] */ + std::vector < std::vector< std::vector > > track2ipin_lookup; /* [0..gsb_side][0..num_tracks][0..Fc-1] */ + track2ipin_lookup = build_gsb_track_to_ipin_lookup(rr_gsb, grids, Fc_in, ipin_to_track_map); /* adapt the opin_to_track_map for the GSB nodes */ - std::vector < std::vector< std::vector > > opin2track_map; /* [0..gsb_side][0..num_opin_node][0..Fc] */ + std::vector < std::vector< std::vector > > opin2track_map; /* [0..gsb_side][0..num_opin_node][0..Fc-1] */ /* adapt the switch_block_conn for the GSB nodes */ - std::vector < std::vector< std::vector > > sb_conn; /* [0..gsb_side][0..chan_width][0..Fc] */ + std::vector < std::vector< std::vector > > sb_conn; /* [0..from_gsb_side][0..to_gsb_side][0..chan_width-1] */ /* Build edges for a GSB */ build_edges_for_one_tileable_rr_gsb(rr_graph, &rr_gsb, track2ipin_lookup, opin2track_map, sb_conn, @@ -1431,76 +1480,6 @@ void build_rr_graph_edges(t_rr_graph* rr_graph, return; } -/************************************************************************ - * Build internal connection pattern for a switch block - * This function is adapt to fit the tileable routing context from - * rr_graph_sbox.c : alloc_and_load_switch_block_conn - * Switch box: * - * TOP (CHANY) * - * | | | | | | * - * +-----------+ * - * --| |-- * - * --| |-- * - * LEFT --| |-- RIGHT * - * (CHANX)--| |--(CHANX) * - * --| |-- * - * --| |-- * - * +-----------+ * - * | | | | | | * - * BOTTOM (CHANY) - * - * [0..3][0..3][0..nodes_per_chan-1]. Structure below is indexed as: * - * [from_side][to_side][from_track]. That yields an integer vector (ivec) * - * of the tracks to which from_track connects in the proper to_location. * - * For simple switch boxes this is overkill, but it will allow complicated * - * switch boxes with Fs > 3, etc. without trouble. - ***********************************************************************/ -static -vtr::NdMatrix,3> alloc_and_load_tileable_switch_block_conn(size_t chan_width, - enum e_switch_block_type switch_block_type, - int Fs) { - - /* Currently Fs must be 3 since each track maps once to each other side */ - VTR_ASSERT(3 == Fs); - - vtr::NdMatrix,3> switch_block_conn({4, 4, chan_width}); - - for (e_side from_side : {TOP, RIGHT, BOTTOM, LEFT}) { - for (e_side to_side : {TOP, RIGHT, BOTTOM, LEFT}) { - for (size_t from_track = 0; from_track < chan_width; from_track++) { - if (from_side != to_side) { - switch_block_conn[from_side][to_side][from_track].resize(1); - - switch_block_conn[from_side][to_side][from_track][0] = get_simple_switch_block_track(from_side, to_side, - from_track, switch_block_type, - chan_width); - } else { /* from_side == to_side -> no connection. */ - switch_block_conn[from_side][to_side][from_track].clear(); - } - } - } - } - - if (getEchoEnabled()) { - FILE *out = fopen("switch_block_conn.echo", "w"); - for (int l = 0; l < 4; ++l) { - for (int k = 0; k < 4; ++k) { - fprintf(out, "Side %d to %d\n", l, k); - for (size_t j = 0; j < chan_width; ++j) { - fprintf(out, "%zu: ", j); - for (unsigned i = 0; i < switch_block_conn[l][k][j].size(); ++i) { - fprintf(out, "%d ", switch_block_conn[l][k][j][i]); - } - fprintf(out, "\n"); - } - fprintf(out, "\n"); - } - } - fclose(out); - } - return switch_block_conn; -} - /************************************************************************ * Main function of this file * Builder for a detailed uni-directional tileable rr_graph @@ -1646,13 +1625,10 @@ void build_tileable_unidir_rr_graph(INP int L_num_types, /* START IPINP MAP */ /* Create ipin map lookups */ int***** ipin_to_track_map = (int*****) my_calloc(L_num_types, sizeof(int****)); - struct s_ivec**** track_to_ipin_lookup = (struct s_ivec****) my_calloc(L_num_types, sizeof(struct s_ivec***)); boolean* perturb_ipins = alloc_and_load_perturb_ipins(chan_width, L_num_types, Fc_in, Fc_out, UNI_DIRECTIONAL); for (int i = 0; i < L_num_types; ++i) { ipin_to_track_map[i] = alloc_and_load_pin_to_track_map(RECEIVER, chan_width, Fc_in[i], &types[i], perturb_ipins[i], UNI_DIRECTIONAL); - track_to_ipin_lookup[i] = alloc_and_load_track_to_pin_lookup(ipin_to_track_map[i], Fc_in[i], - types[i].height, types[i].num_pins, chan_width); } /* END IPINP MAP */ @@ -1683,8 +1659,8 @@ void build_tileable_unidir_rr_graph(INP int L_num_types, } /* Create edges for a tileable rr_graph */ - build_rr_graph_edges(&rr_graph, device_size, device_chan_width, segment_infs, - L_num_types, types, track_to_ipin_lookup, opin_to_track_map, switch_block_conn, + build_rr_graph_edges(&rr_graph, device_size, grids, device_chan_width, segment_infs, + L_num_types, types, Fc_in, Fc_out, ipin_to_track_map, opin_to_track_map, switch_block_conn, num_directs, clb_to_clb_directs, num_switches, delayless_switch); /************************************************************************ @@ -1731,7 +1707,6 @@ void build_tileable_unidir_rr_graph(INP int L_num_types, } free_type_pin_to_track_map(ipin_to_track_map, types); - free_type_track_to_ipin_map(track_to_ipin_lookup, types, chan_width); if(clb_to_clb_directs != NULL) { free(clb_to_clb_directs); } diff --git a/vpr7_x2p/vpr/SRC/device/rr_graph/rr_graph_tileable_sbox.cpp b/vpr7_x2p/vpr/SRC/device/rr_graph/rr_graph_tileable_sbox.cpp new file mode 100755 index 000000000..f30ceed2d --- /dev/null +++ b/vpr7_x2p/vpr/SRC/device/rr_graph/rr_graph_tileable_sbox.cpp @@ -0,0 +1,211 @@ +#include "vtr_assert.h" + +#include "vtr_util.h" +#include "vtr_memory.h" + +#include "vpr_types.h" +#include "rr_graph_tileable_sbox.h" +#include "rr_graph_util.h" +#include "ReadOptions.h" + +static +int get_tileable_simple_switch_block_track(const enum e_side from_side, + const enum e_side to_side, const int from_track, + const enum e_switch_block_type switch_block_type, const int nodes_per_chan); + +/************************************************************************ + * Build internal connection pattern for a switch block + * This function is adapt to fit the tileable routing context from + * rr_graph_sbox.c : alloc_and_load_switch_block_conn + * Switch box: * + * TOP (CHANY) * + * | | | | | | * + * +-----------+ * + * --| |-- * + * --| |-- * + * LEFT --| |-- RIGHT * + * (CHANX)--| |--(CHANX) * + * --| |-- * + * --| |-- * + * +-----------+ * + * | | | | | | * + * BOTTOM (CHANY) * + * + * [0..3][0..3][0..nodes_per_chan-1]. Structure below is indexed as: * + * [from_side][to_side][from_track]. That yields an integer vector (ivec) * + * of the tracks to which from_track connects in the proper to_location. * + * For simple switch boxes this is overkill, but it will allow complicated * + * switch boxes with Fs > 3, etc. without trouble. * + ***********************************************************************/ + +/* Allocates and loads the switch_block_conn data structure. This structure * + * lists which tracks connect to which at each switch block. This is for + * bidir. */ +vtr::NdMatrix,3> alloc_and_load_tileable_switch_block_conn(const size_t nodes_per_chan, + const e_switch_block_type switch_block_type, + const int Fs) { + + /* Currently Fs must be 3 since each track maps once to each other side */ + VTR_ASSERT(3 == Fs); + + vtr::NdMatrix,3> switch_block_conn({4, 4, nodes_per_chan}); + + for (e_side from_side : {TOP, RIGHT, BOTTOM, LEFT}) { + for (e_side to_side : {TOP, RIGHT, BOTTOM, LEFT}) { + for (size_t from_track = 0; from_track < nodes_per_chan; from_track++) { + if (from_side != to_side) { + switch_block_conn[from_side][to_side][from_track].resize(1); + + switch_block_conn[from_side][to_side][from_track][0] = get_tileable_simple_switch_block_track(from_side, to_side, + from_track, switch_block_type, nodes_per_chan); + } else { /* from_side == to_side -> no connection. */ + switch_block_conn[from_side][to_side][from_track].clear(); + } + } + } + } + + if (getEchoEnabled()) { + FILE *out = vtr::fopen("switch_block_conn.echo", "w"); + for (int l = 0; l < 4; ++l) { + for (int k = 0; k < 4; ++k) { + fprintf(out, "Side %d to %d\n", l, k); + for (size_t j = 0; j < nodes_per_chan; ++j) { + fprintf(out, "%zu: ", j); + for (unsigned i = 0; i < switch_block_conn[l][k][j].size(); ++i) { + fprintf(out, "%d ", switch_block_conn[l][k][j][i]); + } + fprintf(out, "\n"); + } + fprintf(out, "\n"); + } + } + fclose(out); + } + return switch_block_conn; +} + +#define SBOX_ERROR -1 + +/* This routine permutes the track number to connect for topologies + * SUBSET, UNIVERSAL, and WILTON. I added FULL (for fully flexible topology) + * but the returned value is simply a dummy, since we don't need to permute + * what connections to make for FULL (connect to EVERYTHING) */ +static +int get_tileable_simple_switch_block_track(const enum e_side from_side, + const enum e_side to_side, const int from_track, + const enum e_switch_block_type switch_block_type, const int nodes_per_chan) { + + /* This routine returns the track number to which the from_track should * + * connect. It supports three simple, Fs = 3, switch blocks. */ + + int to_track = SBOX_ERROR; /* Can check to see if it's not set later. */ + + if (switch_block_type == SUBSET) { /* NB: Global routing uses SUBSET too */ + to_track = from_track; + } + + /* See S. Wilton Phd thesis, U of T, 1996 p. 103 for details on following. */ + + else if (switch_block_type == WILTON) { + + if (from_side == LEFT) { + + if (to_side == RIGHT) { /* CHANX to CHANX */ + to_track = from_track; + } else if (to_side == TOP) { /* from CHANX to CHANY */ + to_track = (nodes_per_chan - (from_track % nodes_per_chan)) % nodes_per_chan; + } else if (to_side == BOTTOM) { + to_track = (nodes_per_chan + from_track - 1) % nodes_per_chan; + } + } + + else if (from_side == RIGHT) { + if (to_side == LEFT) { /* CHANX to CHANX */ + to_track = from_track; + } else if (to_side == TOP) { /* from CHANX to CHANY */ + to_track = (nodes_per_chan + from_track - 1) % nodes_per_chan; + } else if (to_side == BOTTOM) { + to_track = (2 * nodes_per_chan - 2 - from_track) % nodes_per_chan; + } + } + + else if (from_side == BOTTOM) { + if (to_side == TOP) { /* CHANY to CHANY */ + to_track = from_track; + } else if (to_side == LEFT) { /* from CHANY to CHANX */ + to_track = (from_track + 1) % nodes_per_chan; + } else if (to_side == RIGHT) { + to_track = (2 * nodes_per_chan - 2 - from_track) % nodes_per_chan; + } + } + + else if (from_side == TOP) { + if (to_side == BOTTOM) { /* CHANY to CHANY */ + to_track = from_track; + } else if (to_side == LEFT) { /* from CHANY to CHANX */ + to_track = (nodes_per_chan - (from_track % nodes_per_chan)) % nodes_per_chan; + } else if (to_side == RIGHT) { + to_track = (from_track + 1) % nodes_per_chan; + } + } + + /* Force to_track to UN_SET if it falls outside the min/max channel width range */ + if (to_track < 0 || to_track >= nodes_per_chan) { + to_track = -1; + } + } + /* End switch_block_type == WILTON case. */ + else if (switch_block_type == UNIVERSAL) { + + if (from_side == LEFT) { + + if (to_side == RIGHT) { /* CHANX to CHANX */ + to_track = from_track; + } else if (to_side == TOP) { /* from CHANX to CHANY */ + to_track = nodes_per_chan - 1 - from_track; + } else if (to_side == BOTTOM) { + to_track = from_track; + } + } + + else if (from_side == RIGHT) { + if (to_side == LEFT) { /* CHANX to CHANX */ + to_track = from_track; + } else if (to_side == TOP) { /* from CHANX to CHANY */ + to_track = from_track; + } else if (to_side == BOTTOM) { + to_track = nodes_per_chan - 1 - from_track; + } + } + + else if (from_side == BOTTOM) { + if (to_side == TOP) { /* CHANY to CHANY */ + to_track = from_track; + } else if (to_side == LEFT) { /* from CHANY to CHANX */ + to_track = from_track; + } else if (to_side == RIGHT) { + to_track = nodes_per_chan - 1 - from_track; + } + } + + else if (from_side == TOP) { + if (to_side == BOTTOM) { /* CHANY to CHANY */ + to_track = from_track; + } else if (to_side == LEFT) { /* from CHANY to CHANX */ + to_track = nodes_per_chan - 1 - from_track; + } else if (to_side == RIGHT) { + to_track = from_track; + } + } + } + + /* End switch_block_type == UNIVERSAL case. */ + /* UDSD Modification by WMF Begin */ + if (switch_block_type == FULL) { /* Just a placeholder. No meaning in reality */ + to_track = from_track; + } + /* UDSD Modification by WMF End */ + + return (to_track); +} diff --git a/vpr7_x2p/vpr/SRC/device/rr_graph/rr_graph_tileable_sbox.h b/vpr7_x2p/vpr/SRC/device/rr_graph/rr_graph_tileable_sbox.h new file mode 100755 index 000000000..93f3ea5ea --- /dev/null +++ b/vpr7_x2p/vpr/SRC/device/rr_graph/rr_graph_tileable_sbox.h @@ -0,0 +1,12 @@ +#ifndef RR_GRAPH_TILEABLE_SBOX_H +#define RR_GRAPH_TILEABLE_SBOX_H + +#include + +#include "vtr_ndmatrix.h" + +vtr::NdMatrix,3> alloc_and_load_tileable_switch_block_conn(size_t nodes_per_chan, + enum e_switch_block_type switch_block_type, int Fs); + +#endif +