From a3c3f2b8920e5066099d69803fad897ea936d38f Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 8 May 2019 20:49:21 -0600 Subject: [PATCH] developing compact routing hierarchy --- vpr7_x2p/vpr/SRC/base/OptionTokens.c | 1 + vpr7_x2p/vpr/SRC/base/OptionTokens.h | 1 + vpr7_x2p/vpr/SRC/base/ReadOptions.c | 3 + vpr7_x2p/vpr/SRC/base/SetupVPR.c | 6 + vpr7_x2p/vpr/SRC/base/vpr_api.c | 1 + vpr7_x2p/vpr/SRC/base/vpr_types.h | 26 +++ .../base/fpga_x2p_backannotate_utils.c | 20 ++ .../fpga_x2p/base/fpga_x2p_identify_routing.c | 200 ++++++++++++++++++ .../fpga_x2p/base/fpga_x2p_identify_routing.h | 13 ++ .../vpr/SRC/fpga_x2p/base/fpga_x2p_setup.c | 14 +- .../SRC/fpga_x2p/shell/cmd_fpga_x2p_setup.c | 1 + .../SRC/fpga_x2p/shell/cmd_fpga_x2p_setup.h | 1 + 12 files changed, 286 insertions(+), 1 deletion(-) create mode 100644 vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_identify_routing.c create mode 100644 vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_identify_routing.h diff --git a/vpr7_x2p/vpr/SRC/base/OptionTokens.c b/vpr7_x2p/vpr/SRC/base/OptionTokens.c index d96645aac..18b502e01 100644 --- a/vpr7_x2p/vpr/SRC/base/OptionTokens.c +++ b/vpr7_x2p/vpr/SRC/base/OptionTokens.c @@ -61,6 +61,7 @@ struct s_TokenPair OptionBaseTokenList[] = { { "fpga_x2p_rename_illegal_port", OT_FPGA_X2P_RENAME_ILLEGAL_PORT }, /* Xifan TANG: rename illegal port names */ { "fpga_x2p_signal_density_weight", OT_FPGA_X2P_SIGNAL_DENSITY_WEIGHT }, /* The weight of signal density */ { "fpga_x2p_sim_window_size", OT_FPGA_X2P_SIM_WINDOW_SIZE }, /* Window size in determining number of clock cycles in simulation */ + { "fpga_x2p_compact_routing_hierarchy", OT_FPGA_X2P_COMPACT_ROUTING_HIERARCHY }, /* use a compact routing hierarchy in SPICE/Verilog generation */ /* Xifan TANG: FPGA SPICE Support */ { "fpga_spice", OT_FPGA_SPICE },/* Xifan TANG: SPICE Model Support, turn on the functionality*/ { "fpga_spice_dir", OT_FPGA_SPICE_DIR },/* Xifan TANG: SPICE Model Support, directory of spice netlists*/ diff --git a/vpr7_x2p/vpr/SRC/base/OptionTokens.h b/vpr7_x2p/vpr/SRC/base/OptionTokens.h index af7392806..b188cb08e 100644 --- a/vpr7_x2p/vpr/SRC/base/OptionTokens.h +++ b/vpr7_x2p/vpr/SRC/base/OptionTokens.h @@ -78,6 +78,7 @@ enum e_OptionBaseToken { OT_FPGA_X2P_RENAME_ILLEGAL_PORT, OT_FPGA_X2P_SIGNAL_DENSITY_WEIGHT, /* The weight of signal density in determining number of clock cycles in simulation */ OT_FPGA_X2P_SIM_WINDOW_SIZE, /* Window size in determining number of clock cycles in simulation */ + OT_FPGA_X2P_COMPACT_ROUTING_HIERARCHY, /* use a compact routing hierarchy in SPICE/Verilog generation */ /* Xifan TANG: FPGA SPICE Support */ OT_FPGA_SPICE, /* Xifan TANG: FPGA SPICE Model Support */ OT_FPGA_SPICE_DIR, /* Xifan TANG: FPGA SPICE Model Support */ diff --git a/vpr7_x2p/vpr/SRC/base/ReadOptions.c b/vpr7_x2p/vpr/SRC/base/ReadOptions.c index 6d3697e69..c6d1a4186 100644 --- a/vpr7_x2p/vpr/SRC/base/ReadOptions.c +++ b/vpr7_x2p/vpr/SRC/base/ReadOptions.c @@ -481,6 +481,9 @@ ProcessOption(INP char **Args, INOUTP t_options * Options) { return ReadFloat(Args, &Options->fpga_spice_signal_density_weight); case OT_FPGA_X2P_SIM_WINDOW_SIZE: return ReadFloat(Args, &Options->fpga_spice_sim_window_size); + case OT_FPGA_X2P_COMPACT_ROUTING_HIERARCHY: + /* use a compact routing hierarchy in SPICE/Verilog generation */ + return Args; /* Xifan TANG: FPGA SPICE Model Options*/ case OT_FPGA_SPICE: return Args; diff --git a/vpr7_x2p/vpr/SRC/base/SetupVPR.c b/vpr7_x2p/vpr/SRC/base/SetupVPR.c index 304ec022a..e8038bc30 100644 --- a/vpr7_x2p/vpr/SRC/base/SetupVPR.c +++ b/vpr7_x2p/vpr/SRC/base/SetupVPR.c @@ -1235,6 +1235,12 @@ static void SetupFpgaSpiceOpts(t_options Options, fpga_spice_opts->sim_window_size = Options.fpga_spice_sim_window_size; } + /* Check if user wants to use a compact routing hierarchy */ + fpga_spice_opts->compact_routing_hierarchy = FALSE; + if (Options.Count[OT_FPGA_X2P_COMPACT_ROUTING_HIERARCHY]) { + fpga_spice_opts->compact_routing_hierarchy = TRUE; + } + /* Decide if we need to do FPGA-SPICE */ fpga_spice_opts->do_fpga_spice = FALSE; if (( TRUE == fpga_spice_opts->SpiceOpts.do_spice) diff --git a/vpr7_x2p/vpr/SRC/base/vpr_api.c b/vpr7_x2p/vpr/SRC/base/vpr_api.c index 24fa4ed77..9fecb247e 100644 --- a/vpr7_x2p/vpr/SRC/base/vpr_api.c +++ b/vpr7_x2p/vpr/SRC/base/vpr_api.c @@ -170,6 +170,7 @@ void vpr_print_usage(void) { vpr_printf(TIO_MESSAGE_INFO, "\t--fpga_x2p_rename_illegal_port\n"); vpr_printf(TIO_MESSAGE_INFO, "\t--fpga_x2p_signal_density_weight \n"); vpr_printf(TIO_MESSAGE_INFO, "\t--fpga_x2p_sim_window_size \n"); + vpr_printf(TIO_MESSAGE_INFO, "\t--fpga_x2p_compact_routing_hierarchy\n"); vpr_printf(TIO_MESSAGE_INFO, "SPICE Support Options:\n"); vpr_printf(TIO_MESSAGE_INFO, "\t--fpga_spice\n"); vpr_printf(TIO_MESSAGE_INFO, "\t--fpga_spice_dir \n"); diff --git a/vpr7_x2p/vpr/SRC/base/vpr_types.h b/vpr7_x2p/vpr/SRC/base/vpr_types.h index aeea025db..08daffb98 100755 --- a/vpr7_x2p/vpr/SRC/base/vpr_types.h +++ b/vpr7_x2p/vpr/SRC/base/vpr_types.h @@ -1153,6 +1153,18 @@ struct s_sb { int num_reserved_conf_bits; /* number of reserved configuration bits */ int conf_bits_lsb; /* LSB of configuration bits */ int conf_bits_msb; /* MSB of configuration bits */ + + /* For identical SBs */ + t_sb* mirror; /* an exact mirror of this switch block, with same connection & switches */ + /* an rotatable mirror of this switch block, + * the two switch blocks will be same in terms of connection & switches + * by applying an offset to the connection & switches + */ + t_sb* rotatable; + /* Offset to be applied for each side of nodes */ + int* offset_ipin; /* [0, ..., num_sides-1]*/ + int* offset_opin; /* [0, ..., num_sides-1]*/ + int* offset_chan; /* [0, ..., num_sides-1]*/ }; /* Information for each conneciton block */ @@ -1188,6 +1200,18 @@ struct s_cb { int num_reserved_conf_bits; /* number of reserved configuration bits */ int conf_bits_lsb; /* LSB of configuration bits */ int conf_bits_msb; /* MSB of configuration bits */ + + /* For identical SBs */ + t_cb* mirror; /* an exact mirror of this connection block, with same connection & switches */ + /* an rotatable mirror of this connection block, + * the two connection blocks will be same in terms of connection & switches + * by applying an offset to the connection & switches + */ + t_cb* rotatable; + /* Offset to be applied for each side of nodes */ + int* offset_ipin; /* [0, ..., num_sides-1]*/ + int* offset_opin; /* [0, ..., num_sides-1]*/ + int* offset_chan; /* [0, ..., num_sides-1]*/ }; /* Xifan TANG: SPICE Support*/ @@ -1255,6 +1279,8 @@ struct s_fpga_spice_opts { t_syn_verilog_opts SynVerilogOpts; /* Xifan TANG: Synthesizable verilog dumping*/ t_bitstream_gen_opts BitstreamGenOpts; /* Xifan Bitsteam Generator */ + boolean compact_routing_hierarchy; /* use compact routing hierarchy */ + /* Signal Density */ float signal_density_weight; float sim_window_size; diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_backannotate_utils.c b/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_backannotate_utils.c index 438ba3746..eb66b22d9 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_backannotate_utils.c +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_backannotate_utils.c @@ -206,6 +206,12 @@ void init_one_sb_info(t_sb* cur_sb) { cur_sb->conf_bits_lsb = 0; cur_sb->conf_bits_msb = 0; + cur_sb->mirror = NULL; + cur_sb->rotatable = NULL; + cur_sb->offset_ipin = NULL; + cur_sb->offset_opin = NULL; + cur_sb->offset_chan = NULL; + return; } @@ -237,6 +243,10 @@ void free_one_sb_info(t_sb* cur_sb) { my_free(cur_sb->opin_rr_node); my_free(cur_sb->opin_rr_node_grid_side); + my_free(cur_sb->offset_ipin); + my_free(cur_sb->offset_opin); + my_free(cur_sb->offset_chan); + return; } @@ -299,6 +309,12 @@ void init_one_cb_info(t_cb* cur_cb) { cur_cb->conf_bits_lsb = 0; cur_cb->conf_bits_msb = 0; + cur_cb->mirror = NULL; + cur_cb->rotatable = NULL; + cur_cb->offset_ipin = NULL; + cur_cb->offset_opin = NULL; + cur_cb->offset_chan = NULL; + return; } @@ -330,6 +346,10 @@ void free_one_cb_info(t_cb* cur_cb) { my_free(cur_cb->opin_rr_node); my_free(cur_cb->opin_rr_node_grid_side); + my_free(cur_cb->offset_ipin); + my_free(cur_cb->offset_opin); + my_free(cur_cb->offset_chan); + return; } diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_identify_routing.c b/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_identify_routing.c new file mode 100644 index 000000000..b9fa237a8 --- /dev/null +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_identify_routing.c @@ -0,0 +1,200 @@ +/***********************************/ +/* SPICE Modeling for VPR */ +/* Xifan TANG, EPFL/LSI */ +/***********************************/ +#include +#include +#include +#include +#include +#include +#include +#include + +/* Include vpr structs*/ +#include "util.h" +#include "physical_types.h" +#include "vpr_types.h" +#include "globals.h" +#include "rr_graph_util.h" +#include "rr_graph.h" +#include "rr_graph2.h" +#include "vpr_utils.h" +#include "path_delay.h" +#include "stats.h" +#include "route_common.h" + +/* Include spice support headers*/ +#include "read_xml_spice_util.h" +#include "linkedlist.h" +#include "fpga_x2p_types.h" +#include "fpga_x2p_globals.h" +#include "fpga_x2p_utils.h" + + +void assign_switch_block_mirror(t_sb* src, t_sb* des) { + assert ( (NULL != src) && (NULL != des) ); + /* check if the mirror of the first SB is assigned */ + if (NULL != src->mirror) { + /* Assign mirror of the first SB to the second SB */ + /* traceback to the upstream */ + t_sb* temp = src->mirror; + while (NULL != temp->mirror) { + /* go to the next */ + temp = temp->mirror; + } + /* We reach the upstream, ensure its mirror is empty */ + assert(NULL == temp->mirror); + des->mirror = temp; + } else { + /* Assign the first SB as the mirror to the second SB */ + des->mirror = src; + } + + return; +} + +/* Idenify mirror Switch blocks + * Check each two switch blocks: + * 1. Number of channel/opin/ipin rr_nodes are same + * For channel rr_nodes + * 2. check if their track_ids (ptc_num) are same + * 3. Check if the switches (ids) are same + * For opin/ipin rr_nodes, + * 4. check if their parent type_descriptors same, + * 5. check if pin class id and pin id are same + * If all above are satisfied, the two switch blocks are mirrors! + */ +boolean is_two_switch_blocks_mirror(t_sb* src, t_sb* des) { + return FALSE; +} + +/* Walk through all the switch blocks, + * Make one-to-one comparison, + * If we have a pair, update the 1st SB to be the base and label the 2nd as a mirror + * If the 1st SB is already a mirror to another, we will trace back to the upstream base and update the 2nd SB + */ +void assign_mirror_switch_blocks() { + + /* Walkthrough each column, and find mirrors */ + for (int ix = 0; ix < (nx + 1); ++ix) { + for (int iy = 0; iy < (ny + 1); ++iy) { + for (int jy = iy; jy < (ny + 1); ++jy) { + /* Do one-to-one comparison */ + if (FALSE == is_two_switch_blocks_mirror(&(sb_info[ix][iy]), &(sb_info[ix][jy]))) { + /* Nothing to do if the two switch blocks are not equivalent */ + continue; + } + /* configure the mirror of the second switch block */ + assign_switch_block_mirror(&(sb_info[ix][iy]), &(sb_info[ix][jy])); + } + } + } + /* Now mirror switch blocks in each column has been annotated */ + + /* Walkthrough each row, and find mirrors */ + for (int iy = 0; iy < (ny + 1); ++iy) { + for (int ix = 0; ix < (nx + 1); ++ix) { + for (int jx = ix; jx < (nx + 1); ++jx) { + /* Do one-to-one comparison */ + if (FALSE == is_two_switch_blocks_mirror(&(sb_info[ix][iy]), &(sb_info[jx][iy]))) { + /* Nothing to do if the two switch blocks are not equivalent */ + continue; + } + /* configure the mirror of the second switch block */ + assign_switch_block_mirror(&(sb_info[ix][iy]), &(sb_info[jx][iy])); + } + } + } + + return; +} + +/* Validate the mirror of a switch block is the upstream + * with NULL mirror + */ +boolean validate_one_switch_block_mirror(t_sb* cur_sb) { + if (NULL == cur_sb->mirror) { + /* This is the upstream */ + return TRUE; + } + if (NULL == cur_sb->mirror->mirror) { + return FALSE; + } + return TRUE; +} + +/* update the mirror of each switch block */ +void update_one_switch_block_mirror(t_sb* cur_sb) { + + if (NULL == cur_sb->mirror) { + /* This is the upstream */ + return; + } + + /* Assign mirror of the first SB to the second SB */ + /* traceback to the upstream */ + t_sb* temp = cur_sb->mirror; + while (NULL != temp->mirror) { + /* go to the next */ + temp = temp->mirror; + } + /* We reach the upstream, ensure its mirror is empty */ + assert(NULL == temp->mirror); + cur_sb->mirror = temp; + + return; +} + +/* Validate the mirror of each switch block is the upstream */ +boolean validate_mirror_switch_blocks() { + boolean ret = TRUE; + + /* Walkthrough each column, and find mirrors */ + for (int ix = 0; ix < (nx + 1); ++ix) { + for (int iy = 0; iy < (ny + 1); ++iy) { + if (FALSE == validate_one_switch_block_mirror(&(sb_info[ix][iy]))) { + ret = FALSE; + } + } + } + + return ret; +} + +/* Validate the mirror of each switch block is the upstream */ +void update_mirror_switch_blocks() { + + /* Walkthrough each column, and find mirrors */ + for (int ix = 0; ix < (nx + 1); ++ix) { + for (int iy = 0; iy < (ny + 1); ++iy) { + update_one_switch_block_mirror(&(sb_info[ix][iy])); + } + } + + return; +} + + + +void identify_mirror_switch_blocks() { + /* Assign the mirror of each switch block */ + assign_mirror_switch_blocks(); + + /* Ensure all the mirror are the upstream */ + update_mirror_switch_blocks(); + + /* Validate the mirror of switch blocks, everyone should be the upstream */ + assert(TRUE == validate_mirror_switch_blocks()); +} + +/* Idenify mirror Connection blocks */ +void identify_mirror_connection_blocks() { + return; +} + + +/* Rotatable will be done in the next step +void identify_rotatable_switch_blocks(); +void identify_rotatable_connection_blocks(); +*/ diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_identify_routing.h b/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_identify_routing.h new file mode 100644 index 000000000..bb3649850 --- /dev/null +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_identify_routing.h @@ -0,0 +1,13 @@ +/* Avoid repeated header inclusion */ +#ifndef FPGA_X2P_IDENTIFY_ROUTING +#define FPGA_X2P_IDENTIFY_ROUTING + +void identify_mirror_switch_blocks(); +void identify_mirror_connection_blocks(); + +/* Rotatable will be done in the next step +identify_rotatable_switch_blocks(); +identify_rotatable_connection_blocks(); +*/ + +#endif diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_setup.c b/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_setup.c index 8c828ac71..9ccc92fc7 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_setup.c +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_setup.c @@ -31,6 +31,7 @@ #include "fpga_x2p_backannotate_utils.h" #include "fpga_x2p_pbtypes_utils.h" #include "verilog_api.h" +#include "fpga_x2p_identify_routing.h" #include "fpga_x2p_setup.h" /***** Subroutines Declarations *****/ @@ -1302,7 +1303,7 @@ void fpga_x2p_free(t_arch* Arch) { /* Top-level function of FPGA-SPICE setup */ void fpga_x2p_setup(t_vpr_setup vpr_setup, - t_arch* Arch) { + t_arch* Arch) { int num_rename_violation = 0; int num_clocks = 0; float vpr_crit_path_delay = 0.; @@ -1386,6 +1387,17 @@ void fpga_x2p_setup(t_vpr_setup vpr_setup, vpr_setup.FPGA_SPICE_Opts.read_act_file, vpr_setup.FPGA_SPICE_Opts.SpiceOpts.fpga_spice_parasitic_net_estimation); + /* Try to use mirror SBs/CBs if enabled by user */ + if (TRUE == vpr_setup.FPGA_SPICE_Opts.compact_routing_hierarchy) { + /* Idenify mirror and rotatable Switch blocks and Connection blocks */ + identify_mirror_switch_blocks(); + identify_mirror_connection_blocks(); + /* Rotatable will be done in the next step + identify_rotatable_switch_blocks(); + identify_rotatable_connection_blocks(); + */ + } + /* Not should be done when read_act_file is disabled */ if (FALSE == vpr_setup.FPGA_SPICE_Opts.read_act_file) { return; diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/shell/cmd_fpga_x2p_setup.c b/vpr7_x2p/vpr/SRC/fpga_x2p/shell/cmd_fpga_x2p_setup.c index fd55acb66..0b3a9b449 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/shell/cmd_fpga_x2p_setup.c +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/shell/cmd_fpga_x2p_setup.c @@ -31,6 +31,7 @@ boolean shell_setup_fpga_x2p_setup(t_shell_env* env, t_opt_info* opts) { env->vpr_setup.FPGA_SPICE_Opts.rename_illegal_port = is_opt_set(opts, "rename_illegal_port", FALSE); env->vpr_setup.FPGA_SPICE_Opts.signal_density_weight = get_opt_float_val(opts, "signal_density_weight", 1.); env->vpr_setup.FPGA_SPICE_Opts.sim_window_size = get_opt_float_val(opts, "sim_window_size", 0.5); + env->vpr_setup.FPGA_SPICE_Opts.compact_routing_hierarchy = is_opt_set(opts, "compact_routing_hierarchy", FALSE); return TRUE; } diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/shell/cmd_fpga_x2p_setup.h b/vpr7_x2p/vpr/SRC/fpga_x2p/shell/cmd_fpga_x2p_setup.h index 3d967900d..23b418dfa 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/shell/cmd_fpga_x2p_setup.h +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/shell/cmd_fpga_x2p_setup.h @@ -6,6 +6,7 @@ t_opt_info fpga_x2p_setup_opts[] = { {"rename_illegal_port", "-rip,--rename_illegal_port", 0, OPT_NONVAL, OPT_CHAR, OPT_OPT, OPT_NONDEF, "Rename illegal ports that violates Verilog syntax"}, {"signal_density_weight", "-sdw,--signal_density_weight", 0, OPT_WITHVAL, OPT_FLOAT, OPT_OPT, OPT_NONDEF, "Specify the signal density weight when doing the average number"}, {"sim_window_size", "-sws,--sim_window_size", 0, OPT_WITHVAL, OPT_FLOAT, OPT_OPT, OPT_NONDEF, "Specify the size of window when doing simulation"}, + {"compact_routing_hierarchy", "-crh,--compact_routing_hierarchy", 0, OPT_NONVAL, OPT_CHAR, OPT_OPT, OPT_NONDEF, "Specify if use a compact routing hierarchy in SPIC/Verilog generation"}, {HELP_OPT_TAG, HELP_OPT_NAME, 0, OPT_NONVAL, OPT_CHAR, OPT_OPT, OPT_NONDEF, "Launch help desk"}, {LAST_OPT_TAG, LAST_OPT_NAME, 0, OPT_NONVAL, OPT_CHAR, OPT_OPT, OPT_NONDEF, "Launch help desk"} };