developing compact routing hierarchy
This commit is contained in:
parent
4c6639218e
commit
a3c3f2b892
|
@ -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*/
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 <float>\n");
|
||||
vpr_printf(TIO_MESSAGE_INFO, "\t--fpga_x2p_sim_window_size <float>\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 <directory_path_output_spice_netlists>\n");
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,200 @@
|
|||
/***********************************/
|
||||
/* SPICE Modeling for VPR */
|
||||
/* Xifan TANG, EPFL/LSI */
|
||||
/***********************************/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <time.h>
|
||||
#include <assert.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/* 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();
|
||||
*/
|
|
@ -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
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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"}
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue