diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_unique_routing.c b/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_unique_routing.c index 427368340..5aca29cba 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_unique_routing.c +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_unique_routing.c @@ -1234,6 +1234,7 @@ DeviceRRSwitchBlock build_device_rr_switch_blocks(boolean output_sb_xml, char* s } + /* Build a list of unique modules for each Switch Block */ LL_device_rr_switch_block.build_unique_mirror(); /* Report number of unique mirrors */ @@ -1241,6 +1242,17 @@ DeviceRRSwitchBlock build_device_rr_switch_blocks(boolean output_sb_xml, char* s "Detect %d independent switch blocks from %d switch blocks.\n", LL_device_rr_switch_block.get_num_unique_mirror(), (nx + 1) * (ny + 1) ); + /* Build a list of unique modules for each side of each Switch Block */ + LL_device_rr_switch_block.build_unique_module(); + /* Report number of unique mirrors */ + for (size_t side = 0; side < LL_device_rr_switch_block.get_max_num_sides(); ++side) { + Side side_manager(side); + vpr_printf(TIO_MESSAGE_INFO, + "For side %s: Detect %d independent switch blocks from %d switch blocks.\n", + side_manager.to_string(), LL_device_rr_switch_block.get_num_unique_module(side_manager.get_side()), + (nx + 1) * (ny + 1) ); + } + /* Create directory if needed */ if (TRUE == output_sb_xml) { create_dir_path(sb_xml_dir); diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_utils.c b/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_utils.c index c49bd6653..c69e3566f 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_utils.c +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_utils.c @@ -654,7 +654,7 @@ char* my_itoa(int input) { /* Generate a filename (string) for a grid subckt SPICE netlist, * with given x and y coordinates */ -char* fpga_spice_create_one_subckt_filename(char* file_name_prefix, +char* fpga_spice_create_one_subckt_filename(const char* file_name_prefix, int subckt_x, int subckt_y, char* file_name_postfix) { char* fname = NULL; diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_utils.h b/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_utils.h index 8f53d82f2..fae141188 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_utils.h +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/base/fpga_x2p_utils.h @@ -61,7 +61,7 @@ char* my_itobin(int in_int, int bin_len); char* my_itoa(int input); -char* fpga_spice_create_one_subckt_filename(char* file_name_prefix, +char* fpga_spice_create_one_subckt_filename(const char* file_name_prefix, int subckt_x, int subckt_y, char* file_name_postfix); diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/base/rr_blocks.cpp b/vpr7_x2p/vpr/SRC/fpga_x2p/base/rr_blocks.cpp index 800061b13..9989d8ea6 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/base/rr_blocks.cpp +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/base/rr_blocks.cpp @@ -1097,6 +1097,44 @@ char* RRSwitchBlock::gen_verilog_instance_name() const { return ret; } +/* Public Accessors Verilog writer */ +char* RRSwitchBlock::gen_verilog_side_module_name(enum e_side side) const { + char* ret = NULL; + Side side_manager(side); + + std::string x_str = std::to_string(get_x()); + std::string y_str = std::to_string(get_y()); + std::string side_str(side_manager.to_string()); + + ret = (char*)my_malloc(2 + 1 + x_str.length() + + 2 + y_str.length() + + 2 + side_str.length() + + 1 + 1); + + sprintf(ret, "sb_%lu__%lu__%s_", + get_x(), get_y(), side_manager.to_string()); + + return ret; +} + +char* RRSwitchBlock::gen_verilog_side_instance_name(enum e_side side) const { + char* ret = NULL; + Side side_manager(side); + + std::string x_str = std::to_string(get_x()); + std::string y_str = std::to_string(get_y()); + std::string side_str(side_manager.to_string()); + + ret = (char*)my_malloc(2 + 1 + x_str.length() + + 2 + y_str.length() + + 2 + side_str.length() + + 4 + 1); + + sprintf(ret, "sb_%lu__%lu__%s__0_", + get_x(), get_y(), side_manager.to_string()); + + return ret; +} /* Public mutators */ @@ -1744,6 +1782,16 @@ size_t DeviceRRSwitchBlock::get_num_rotatable_mirror() const { return rotatable_mirror_.size(); } +/* Get a rr switch block which is a unique module of a side of SB */ +RRSwitchBlock DeviceRRSwitchBlock::get_unique_side_module(size_t index, enum e_side side) const { + assert (validate_unique_module_index(index, side)); + + Side side_manager(side); + assert (validate_side(side)); + + return rr_switch_block_[unique_module_[side_manager.to_size_t()][index].get_x()][unique_module_[side_manager.to_size_t()][index].get_y()]; +} + /* Get a rr switch block which a unique mirror */ RRSwitchBlock DeviceRRSwitchBlock::get_unique_mirror(size_t index) const { assert (validate_unique_mirror_index(index)); @@ -2086,3 +2134,14 @@ bool DeviceRRSwitchBlock::validate_rotatable_mirror_index(size_t index) const { } return true; } + +/* Validate if the index in the range of unique_mirror vector*/ +bool DeviceRRSwitchBlock::validate_unique_module_index(size_t index, enum e_side side) const { + assert( validate_side(side)); + Side side_manager(side); + + if (index >= unique_module_[side_manager.get_side()].size()) { + return false; + } + return true; +} diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/base/rr_blocks.h b/vpr7_x2p/vpr/SRC/fpga_x2p/base/rr_blocks.h index f2bc88576..7557b6d71 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/base/rr_blocks.h +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/base/rr_blocks.h @@ -171,6 +171,8 @@ class RRSwitchBlock { public: /* Verilog writer */ char* gen_verilog_module_name() const; char* gen_verilog_instance_name() const; + char* gen_verilog_side_module_name(enum e_side side) const; + char* gen_verilog_side_instance_name(enum e_side side) const; public: /* Mutators */ void set(const RRSwitchBlock& src); /* get a copy from a source */ void set_coordinator(size_t x, size_t y); @@ -243,6 +245,7 @@ class DeviceRRSwitchBlock { size_t get_num_unique_module(enum e_side side) const; /* get the number of unique mirrors of switch blocks */ size_t get_num_unique_mirror() const; /* get the number of unique mirrors of switch blocks */ size_t get_num_rotatable_mirror() const; /* get the number of rotatable mirrors of switch blocks */ + RRSwitchBlock get_unique_side_module(size_t index, enum e_side side) const; /* Get a rr switch block which a unique mirror */ RRSwitchBlock get_unique_mirror(size_t index) const; /* Get a rr switch block which a unique mirror */ RRSwitchBlock get_unique_mirror(DeviceCoordinator& coordinator) const; /* Get a rr switch block which a unique mirror */ RRSwitchBlock get_rotatable_mirror(size_t index) const; /* Get a rr switch block which a unique mirror */ @@ -268,7 +271,7 @@ class DeviceRRSwitchBlock { bool validate_side(enum e_side side) const; /* validate if side is in the range of unique_side_module_ */ bool validate_unique_mirror_index(size_t index) const; /* Validate if the index in the range of unique_mirror vector*/ bool validate_rotatable_mirror_index(size_t index) const; /* Validate if the index in the range of unique_mirror vector*/ - bool validate_unique_side_module_index(enum e_side side, size_t index); + bool validate_unique_module_index(size_t index, enum e_side side) const; /* Validate if the index in the range of unique_module vector */ private: /* Internal Data */ std::vector< std::vector > rr_switch_block_; diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_routing.c b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_routing.c index 19305c5f6..0f5dd2f02 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_routing.c +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_routing.c @@ -1657,6 +1657,37 @@ int count_verilog_switch_box_reserved_conf_bits(t_sram_orgz_info* cur_sram_orgz_ return num_reserved_conf_bits; } +/* Count the number of configuration bits of a Switch Box */ +static +size_t count_verilog_switch_box_side_reserved_conf_bits(t_sram_orgz_info* cur_sram_orgz_info, + RRSwitchBlock& rr_sb, enum e_side side) { + size_t num_reserved_conf_bits = 0; + size_t temp_num_reserved_conf_bits = 0; + Side side_manager(side); + + for (size_t itrack = 0; itrack < rr_sb.get_chan_width(side); ++itrack) { + switch (rr_sb.get_chan_node_direction(side, itrack)) { + case OUT_PORT: + temp_num_reserved_conf_bits = + count_verilog_switch_box_interc_reserved_conf_bits(cur_sram_orgz_info, rr_sb, side, + rr_sb.get_chan_node(side, itrack)); + /* Always select the largest number of reserved conf_bits */ + num_reserved_conf_bits = std::max(num_reserved_conf_bits, temp_num_reserved_conf_bits); + break; + case IN_PORT: + break; + default: + vpr_printf(TIO_MESSAGE_ERROR, + "(File: %s [LINE%d]) Invalid direction of port Channel node[%s] track[%d]!\n", + __FILE__, __LINE__, side_manager.to_string(), itrack); + exit(1); + } + } + + return num_reserved_conf_bits; +} + + /* Count the number of configuration bits of a Switch Box */ static size_t count_verilog_switch_box_reserved_conf_bits(t_sram_orgz_info* cur_sram_orgz_info, @@ -1666,24 +1697,9 @@ size_t count_verilog_switch_box_reserved_conf_bits(t_sram_orgz_info* cur_sram_or for (size_t side = 0; side < rr_sb.get_num_sides(); ++side) { Side side_manager(side); - for (size_t itrack = 0; itrack < rr_sb.get_chan_width(side_manager.get_side()); ++itrack) { - switch (rr_sb.get_chan_node_direction(side_manager.get_side(), itrack)) { - case OUT_PORT: - temp_num_reserved_conf_bits = - count_verilog_switch_box_interc_reserved_conf_bits(cur_sram_orgz_info, rr_sb, side_manager.get_side(), - rr_sb.get_chan_node(side_manager.get_side(), itrack)); - /* Always select the largest number of reserved conf_bits */ - num_reserved_conf_bits = std::max(num_reserved_conf_bits, temp_num_reserved_conf_bits); - break; - case IN_PORT: - break; - default: - vpr_printf(TIO_MESSAGE_ERROR, - "(File: %s [LINE%d]) Invalid direction of port Channel node[%d] track[%d]!\n", - __FILE__, __LINE__, side, itrack); - exit(1); - } - } + temp_num_reserved_conf_bits = count_verilog_switch_box_side_reserved_conf_bits(cur_sram_orgz_info, rr_sb, side_manager.get_side()); + /* Always select the largest number of reserved conf_bits */ + num_reserved_conf_bits = std::max(num_reserved_conf_bits, temp_num_reserved_conf_bits); } return num_reserved_conf_bits; @@ -1717,6 +1733,32 @@ int count_verilog_switch_box_conf_bits(t_sram_orgz_info* cur_sram_orgz_info, return num_conf_bits; } +/* Count the number of configuration bits of a Switch Box */ +static +size_t count_verilog_switch_box_side_conf_bits(t_sram_orgz_info* cur_sram_orgz_info, + RRSwitchBlock& rr_sb, enum e_side side) { + size_t num_conf_bits = 0; + Side side_manager(side); + + for (size_t itrack = 0; itrack < rr_sb.get_chan_width(side); ++itrack) { + switch (rr_sb.get_chan_node_direction(side, itrack)) { + case OUT_PORT: + num_conf_bits += count_verilog_switch_box_interc_conf_bits(cur_sram_orgz_info, rr_sb, side, + rr_sb.get_chan_node(side, itrack)); + break; + case IN_PORT: + break; + default: + vpr_printf(TIO_MESSAGE_ERROR, + "(File: %s [LINE%d]) Invalid direction of port Channel node[%s] track[%d]!\n", + __FILE__, __LINE__, side_manager.to_string(), itrack); + exit(1); + } + } + + return num_conf_bits; +} + /* Count the number of configuration bits of a Switch Box */ static size_t count_verilog_switch_box_conf_bits(t_sram_orgz_info* cur_sram_orgz_info, @@ -1725,21 +1767,7 @@ size_t count_verilog_switch_box_conf_bits(t_sram_orgz_info* cur_sram_orgz_info, for (size_t side = 0; side < rr_sb.get_num_sides(); ++side) { Side side_manager(side); - for (size_t itrack = 0; itrack < rr_sb.get_chan_width(side_manager.get_side()); ++itrack) { - switch (rr_sb.get_chan_node_direction(side_manager.get_side(), itrack)) { - case OUT_PORT: - num_conf_bits += count_verilog_switch_box_interc_conf_bits(cur_sram_orgz_info, rr_sb, side_manager.get_side(), - rr_sb.get_chan_node(side_manager.get_side(), itrack)); - break; - case IN_PORT: - break; - default: - vpr_printf(TIO_MESSAGE_ERROR, - "(File: %s [LINE%d]) Invalid direction of port Channel node[%d] track[%d]!\n", - __FILE__, __LINE__, side, itrack); - exit(1); - } - } + num_conf_bits += count_verilog_switch_box_side_conf_bits(cur_sram_orgz_info, rr_sb, side_manager.get_side()); } return num_conf_bits; @@ -1773,6 +1801,456 @@ void update_routing_switch_box_conf_bits(t_sram_orgz_info* cur_sram_orgz_info, return; } +/* Dump port list of a subckt describing a side of a switch block + * Only output ports will be printed on the specified side + * Only input ports will be printed on the other sides + */ +static +void dump_verilog_routing_switch_box_unique_side_subckt_portmap(FILE* fp, + RRSwitchBlock& rr_sb, + enum e_side sb_side, + boolean dump_port_type) { + /* Check file handler*/ + if (NULL == fp) { + vpr_printf(TIO_MESSAGE_ERROR, + "(FILE:%s,LINE[%d])Invalid file handler!\n", + __FILE__, __LINE__); + exit(1); + } + + /* Create a side manager */ + Side sb_side_manager(sb_side); + + for (size_t side = 0; side < rr_sb.get_num_sides(); ++side) { + Side side_manager(side); + /* Print ports */ + fprintf(fp, "//----- Inputs/outputs of %s side -----\n", side_manager.to_string()); + DeviceCoordinator port_coordinator = rr_sb.get_side_block_coordinator(side_manager.get_side()); + + for (size_t itrack = 0; itrack < rr_sb.get_chan_width(side_manager.get_side()); ++itrack) { + switch (rr_sb.get_chan_node_direction(side_manager.get_side(), itrack)) { + case OUT_PORT: + /* if this is the specified side, we only consider output ports */ + if (sb_side_manager.get_side() != side_manager.get_side()) { + break; + } + fprintf(fp, " "); + if (TRUE == dump_port_type) { + fprintf(fp, "output "); + } + fprintf(fp, "%s,\n", + gen_verilog_routing_channel_one_pin_name(rr_sb.get_chan_node(side_manager.get_side(), itrack), + port_coordinator.get_x(), port_coordinator.get_y(), itrack, + rr_sb.get_chan_node_direction(side_manager.get_side(), itrack))); + break; + case IN_PORT: + /* if this is not the specified side, we only consider input ports */ + if (sb_side_manager.get_side() == side_manager.get_side()) { + break; + } + fprintf(fp, " "); + if (TRUE == dump_port_type) { + fprintf(fp, "input "); + } + fprintf(fp, "%s,\n", + gen_verilog_routing_channel_one_pin_name(rr_sb.get_chan_node(side_manager.get_side(), itrack), + port_coordinator.get_x(), port_coordinator.get_y(), itrack, + rr_sb.get_chan_node_direction(side_manager.get_side(), itrack))); + break; + default: + vpr_printf(TIO_MESSAGE_ERROR, + "(File: %s [LINE%d]) Invalid direction of chan[%d][%d]_track[%d]!\n", + __FILE__, __LINE__, rr_sb.get_x(), rr_sb.get_y(), itrack); + exit(1); + } + } + + /* Dump OPINs of adjacent CLBs */ + for (size_t inode = 0; inode < rr_sb.get_num_opin_nodes(side_manager.get_side()); ++inode) { + fprintf(fp, " "); + dump_verilog_grid_side_pin_with_given_index(fp, OPIN, /* This is an input of a SB */ + rr_sb.get_opin_node(side_manager.get_side(), inode)->ptc_num, + rr_sb.get_opin_node_grid_side(side_manager.get_side(), inode), + rr_sb.get_opin_node(side_manager.get_side(), inode)->xlow, + rr_sb.get_opin_node(side_manager.get_side(), inode)->ylow, + dump_port_type); /* Dump the direction of the port ! */ + fprintf(fp, ",\n"); + } + } + + return; +} + + +/* Task: Print the subckt of a side of a Switch Box. + * For TOP side: + * 1. Channel Y [x][y+1] inputs + * 2. Grid[x][y+1] Right side outputs pins + * 3. Grid[x+1][y+1] Left side output pins + * For RIGHT side: + * 1. Channel X [x+1][y] inputs + * 2. Grid[x+1][y+1] Bottom side output pins + * 3. Grid[x+1][y] Top side output pins + * For BOTTOM side: + * 1. Channel Y [x][y] outputs + * 2. Grid[x][y] Right side output pins + * 3. Grid[x+1][y] Left side output pins + * For LEFT side: + * 1. Channel X [x][y] outputs + * 2. Grid[x][y] Top side output pins + * 3. Grid[x][y+1] Bottom side output pins + * + * -------------- -------------- + * | | | | + * | Grid | ChanY | Grid | + * | [x][y+1] | [x][y+1] | [x+1][y+1] | + * | | | | + * -------------- -------------- + * ---------- + * ChanX | Switch | ChanX + * [x][y] | Box | [x+1][y] + * | [x][y] | + * ---------- + * -------------- -------------- + * | | | | + * | Grid | ChanY | Grid | + * | [x][y] | [x][y] | [x+1][y] | + * | | | | + * -------------- -------------- + */ +static +void dump_verilog_routing_switch_box_unique_side_module(t_sram_orgz_info* cur_sram_orgz_info, + char* verilog_dir, char* subckt_dir, size_t module_id, + RRSwitchBlock& rr_sb, enum e_side side) { + FILE* fp = NULL; + char* fname = NULL; + Side side_manager(side); + + /* Get the channel width on this side, if it is zero, we return */ + if (0 == rr_sb.get_chan_width(side)) { + return; + } + + /* Count the number of configuration bits to be consumed by this Switch block */ + int num_conf_bits = count_verilog_switch_box_side_conf_bits(cur_sram_orgz_info, rr_sb, side); + /* Count the number of reserved configuration bits to be consumed by this Switch block */ + int num_reserved_conf_bits = count_verilog_switch_box_side_reserved_conf_bits(cur_sram_orgz_info, rr_sb, side); + /* Estimate the sram_verilog_model->cnt */ + int cur_num_sram = get_sram_orgz_info_num_mem_bit(cur_sram_orgz_info); + int esti_sram_cnt = cur_num_sram + num_conf_bits; + + /* Create file name */ + std::string fname_prefix(sb_verilog_file_name_prefix); + fname_prefix += side_manager.to_string(); + + std::string file_description("Unique module for Switch Block side: "); + file_description += side_manager.to_string(); + + /* Create file handler */ + fp = verilog_create_one_subckt_file(subckt_dir, file_description.c_str(), + fname_prefix.c_str(), module_id, -1, &fname); + + /* Print preprocessing flags */ + verilog_include_defines_preproc_file(fp, verilog_dir); + + /* Comment lines */ + fprintf(fp, + "//----- Verilog Module of Unique Switch Box[%lu][%lu] at Side %s -----\n", + rr_sb.get_x(), rr_sb.get_y(), side_manager.to_string()); + /* Print the definition of subckt*/ + fprintf(fp, "module %s ( \n", rr_sb.gen_verilog_side_module_name(side)); + /* dump global ports */ + if (0 < dump_verilog_global_ports(fp, global_ports_head, TRUE)) { + fprintf(fp, ",\n"); + } + + dump_verilog_routing_switch_box_unique_side_subckt_portmap(fp, rr_sb, side, TRUE); + + /* Put down configuration port */ + /* output of each configuration bit */ + /* Reserved sram ports */ + dump_verilog_reserved_sram_ports(fp, cur_sram_orgz_info, + 0, + num_reserved_conf_bits - 1, + VERILOG_PORT_INPUT); + if (0 < num_reserved_conf_bits) { + fprintf(fp, ",\n"); + } + /* Normal sram ports */ + dump_verilog_sram_ports(fp, cur_sram_orgz_info, + cur_num_sram, + esti_sram_cnt - 1, + VERILOG_PORT_INPUT); + + /* Dump ports only visible during formal verification*/ + if (0 < num_conf_bits) { + fprintf(fp, "\n"); + fprintf(fp, "`ifdef %s\n", verilog_formal_verification_preproc_flag); + fprintf(fp, ",\n"); + dump_verilog_formal_verification_sram_ports(fp, cur_sram_orgz_info, + cur_num_sram, + esti_sram_cnt - 1, + VERILOG_PORT_OUTPUT); + fprintf(fp, "\n"); + fprintf(fp, "`endif\n"); + } + fprintf(fp, "); \n"); + + /* Local wires for memory configurations */ + dump_verilog_sram_config_bus_internal_wires(fp, cur_sram_orgz_info, + cur_num_sram, + esti_sram_cnt - 1); + + /* Put down all the multiplexers */ + fprintf(fp, "//----- %s side Multiplexers -----\n", + side_manager.to_string()); + for (size_t itrack = 0; itrack < rr_sb.get_chan_width(side_manager.get_side()); ++itrack) { + assert((CHANX == rr_sb.get_chan_node(side_manager.get_side(), itrack)->type) + ||(CHANY == rr_sb.get_chan_node(side_manager.get_side(), itrack)->type)); + /* We care INC_DIRECTION tracks at this side*/ + if (OUT_PORT == rr_sb.get_chan_node_direction(side_manager.get_side(), itrack)) { + dump_verilog_unique_switch_box_interc(cur_sram_orgz_info, fp, rr_sb, + side_manager.get_side(), + rr_sb.get_chan_node(side_manager.get_side(), itrack)); + } + } + + fprintf(fp, "endmodule\n"); + + /* Comment lines */ + fprintf(fp, + "//----- END Verilog Module of Switch Box[%lu][%lu] Side %s -----\n\n", + rr_sb.get_x(), rr_sb.get_y(), side_manager.to_string()); + + /* Check */ + assert(esti_sram_cnt == get_sram_orgz_info_num_mem_bit(cur_sram_orgz_info)); + + /* Close file handler */ + fclose(fp); + + /* Add fname to the linked list */ + routing_verilog_subckt_file_path_head = add_one_subckt_file_name_to_llist(routing_verilog_subckt_file_path_head, fname); + + /* Free chan_rr_nodes */ + my_free(fname); + + return; +} + +/* Task: Print the subckt of a Switch Box. + * Call the four submodules dumped in function: unique_side_module + * + * -------------- -------------- + * | | | | + * | Grid | ChanY | Grid | + * | [x][y+1] | [x][y+1] | [x+1][y+1] | + * | | | | + * -------------- -------------- + * ---------- + * ChanX | Switch | ChanX + * [x][y] | Box | [x+1][y] + * | [x][y] | + * ---------- + * -------------- -------------- + * | | | | + * | Grid | ChanY | Grid | + * | [x][y] | [x][y] | [x+1][y] | + * | | | | + * -------------- -------------- + */ +static +void dump_verilog_routing_switch_box_unique_module(t_sram_orgz_info* cur_sram_orgz_info, + char* verilog_dir, char* subckt_dir, + RRSwitchBlock& rr_sb) { + FILE* fp = NULL; + char* fname = NULL; + + /* Count the number of configuration bits to be consumed by this Switch block */ + int num_conf_bits = count_verilog_switch_box_conf_bits(cur_sram_orgz_info, rr_sb); + /* Count the number of reserved configuration bits to be consumed by this Switch block */ + int num_reserved_conf_bits = count_verilog_switch_box_reserved_conf_bits(cur_sram_orgz_info, rr_sb); + /* Estimate the sram_verilog_model->cnt */ + int cur_num_sram = get_sram_orgz_info_num_mem_bit(cur_sram_orgz_info); + rr_sb.set_num_reserved_conf_bits(num_reserved_conf_bits); + rr_sb.set_conf_bits_lsb(cur_num_sram); + rr_sb.set_conf_bits_msb(cur_num_sram + num_conf_bits - 1); + + /* Create file handler */ + fp = verilog_create_one_subckt_file(subckt_dir, "Unique Switch Block ", + sb_verilog_file_name_prefix, rr_sb.get_x(), rr_sb.get_y(), &fname); + + /* Print preprocessing flags */ + verilog_include_defines_preproc_file(fp, verilog_dir); + + /* Comment lines */ + fprintf(fp, "//----- Verilog Module of Unique Switch Box[%lu][%lu] -----\n", rr_sb.get_x(), rr_sb.get_y()); + /* Print the definition of subckt*/ + fprintf(fp, "module %s ( \n", rr_sb.gen_verilog_module_name()); + /* dump global ports */ + if (0 < dump_verilog_global_ports(fp, global_ports_head, TRUE)) { + fprintf(fp, ",\n"); + } + + for (size_t side = 0; side < rr_sb.get_num_sides(); ++side) { + Side side_manager(side); + /* Print ports */ + fprintf(fp, "//----- Inputs/outputs of %s side -----\n", side_manager.to_string()); + DeviceCoordinator port_coordinator = rr_sb.get_side_block_coordinator(side_manager.get_side()); + + for (size_t itrack = 0; itrack < rr_sb.get_chan_width(side_manager.get_side()); ++itrack) { + switch (rr_sb.get_chan_node_direction(side_manager.get_side(), itrack)) { + case OUT_PORT: + fprintf(fp, " output %s,\n", + gen_verilog_routing_channel_one_pin_name(rr_sb.get_chan_node(side_manager.get_side(), itrack), + port_coordinator.get_x(), port_coordinator.get_y(), itrack, + rr_sb.get_chan_node_direction(side_manager.get_side(), itrack))); + break; + case IN_PORT: + fprintf(fp, " input %s,\n", + gen_verilog_routing_channel_one_pin_name(rr_sb.get_chan_node(side_manager.get_side(), itrack), + port_coordinator.get_x(), port_coordinator.get_y(), itrack, + rr_sb.get_chan_node_direction(side_manager.get_side(), itrack))); + break; + default: + vpr_printf(TIO_MESSAGE_ERROR, + "(File: %s [LINE%d]) Invalid direction of chan[%d][%d]_track[%d]!\n", + __FILE__, __LINE__, rr_sb.get_x(), rr_sb.get_y(), itrack); + exit(1); + } + } + /* Dump OPINs of adjacent CLBs */ + for (size_t inode = 0; inode < rr_sb.get_num_opin_nodes(side_manager.get_side()); ++inode) { + fprintf(fp, " "); + dump_verilog_grid_side_pin_with_given_index(fp, OPIN, /* This is an input of a SB */ + rr_sb.get_opin_node(side_manager.get_side(), inode)->ptc_num, + rr_sb.get_opin_node_grid_side(side_manager.get_side(), inode), + rr_sb.get_opin_node(side_manager.get_side(), inode)->xlow, + rr_sb.get_opin_node(side_manager.get_side(), inode)->ylow, + TRUE); /* Dump the direction of the port ! */ + } + } + + /* Put down configuration port */ + /* output of each configuration bit */ + /* Reserved sram ports */ + dump_verilog_reserved_sram_ports(fp, cur_sram_orgz_info, + rr_sb.get_reserved_conf_bits_lsb(), + rr_sb.get_reserved_conf_bits_msb(), + VERILOG_PORT_INPUT); + if (0 < rr_sb.get_num_reserved_conf_bits()) { + fprintf(fp, ",\n"); + } + /* Normal sram ports */ + dump_verilog_sram_ports(fp, cur_sram_orgz_info, + rr_sb.get_conf_bits_lsb(), + rr_sb.get_conf_bits_msb(), + VERILOG_PORT_INPUT); + + /* Dump ports only visible during formal verification*/ + if (0 < rr_sb.get_num_conf_bits()) { + fprintf(fp, "\n"); + fprintf(fp, "`ifdef %s\n", verilog_formal_verification_preproc_flag); + fprintf(fp, ",\n"); + dump_verilog_formal_verification_sram_ports(fp, cur_sram_orgz_info, + rr_sb.get_conf_bits_lsb(), + rr_sb.get_conf_bits_msb(), + VERILOG_PORT_OUTPUT); + fprintf(fp, "\n"); + fprintf(fp, "`endif\n"); + } + fprintf(fp, "); \n"); + + /* Local wires for memory configurations */ + dump_verilog_sram_config_bus_internal_wires(fp, cur_sram_orgz_info, + rr_sb.get_conf_bits_lsb(), + rr_sb.get_conf_bits_msb()); + + /* Call submodules */ + int cur_sram_lsb = cur_num_sram; + int cur_sram_msb = cur_num_sram; + for (size_t side = 0; side < rr_sb.get_num_sides(); ++side) { + Side side_manager(side); + fprintf(fp, "//----- %s side Submodule -----\n", + side_manager.to_string()); + + /* Get the channel width on this side, if it is zero, we return */ + if (0 == rr_sb.get_chan_width(side_manager.get_side())) { + continue; + } + + /* Count the number of configuration bits to be consumed by this Switch block */ + int side_num_conf_bits = count_verilog_switch_box_side_conf_bits(cur_sram_orgz_info, rr_sb, side_manager.get_side()); + /* Count the number of reserved configuration bits to be consumed by this Switch block */ + int side_num_reserved_conf_bits = count_verilog_switch_box_side_reserved_conf_bits(cur_sram_orgz_info, rr_sb, side_manager.get_side()); + + /* Cache the sram counter */ + cur_sram_msb += side_num_conf_bits - 1; + + /* Instanciate the subckt*/ + fprintf(fp, + "%s %s ( \n", + rr_sb.gen_verilog_side_module_name(side_manager.get_side()), + rr_sb.gen_verilog_side_instance_name(side_manager.get_side())); + /* dump global ports */ + if (0 < dump_verilog_global_ports(fp, global_ports_head, FALSE)) { + fprintf(fp, ",\n"); + } + + dump_verilog_routing_switch_box_unique_side_subckt_portmap(fp, rr_sb, side_manager.get_side(), FALSE); + + /* Put down configuration port */ + /* output of each configuration bit */ + /* Reserved sram ports */ + dump_verilog_reserved_sram_ports(fp, cur_sram_orgz_info, + 0, + side_num_reserved_conf_bits - 1, + VERILOG_PORT_INPUT); + if (0 < side_num_reserved_conf_bits) { + fprintf(fp, ",\n"); + } + /* Normal sram ports */ + dump_verilog_sram_ports(fp, cur_sram_orgz_info, + cur_sram_lsb, + cur_sram_msb, + VERILOG_PORT_INPUT); + + /* Dump ports only visible during formal verification*/ + if (0 < num_conf_bits) { + fprintf(fp, "\n"); + fprintf(fp, "`ifdef %s\n", verilog_formal_verification_preproc_flag); + fprintf(fp, ",\n"); + dump_verilog_formal_verification_sram_ports(fp, cur_sram_orgz_info, + cur_sram_lsb, + cur_sram_msb, + VERILOG_PORT_OUTPUT); + fprintf(fp, "\n"); + fprintf(fp, "`endif\n"); + } + fprintf(fp, "); \n"); + + /* Update sram_lsb */ + cur_sram_lsb = cur_sram_msb + 1; + } + + fprintf(fp, "endmodule\n"); + + /* Comment lines */ + fprintf(fp, "//----- END Verilog Module of Switch Box[%lu][%lu] -----\n\n", rr_sb.get_x(), rr_sb.get_y()); + + /* Close file handler */ + fclose(fp); + + /* Add fname to the linked list */ + routing_verilog_subckt_file_path_head = add_one_subckt_file_name_to_llist(routing_verilog_subckt_file_path_head, fname); + + /* Free chan_rr_nodes */ + my_free(fname); + + return; +} + + + /* Task: Print the subckt of a Switch Box. * A Switch Box subckt consists of following ports: * 1. Channel Y [x][y] inputs @@ -2928,10 +3406,19 @@ void dump_verilog_routing_resources(t_sram_orgz_info* cur_sram_orgz_info, /* Create a snapshot on sram_orgz_info */ t_sram_orgz_info* stamped_sram_orgz_info = snapshot_sram_orgz_info(cur_sram_orgz_info); + /* Output unique side modules */ + for (size_t side = 0; side < device_rr_switch_block.get_max_num_sides(); ++side) { + Side side_manager(side); + for (size_t isb = 0; isb < device_rr_switch_block.get_num_unique_module(side_manager.get_side()); ++isb) { + RRSwitchBlock unique_mirror = device_rr_switch_block.get_unique_side_module(isb, side_manager.get_side()); + dump_verilog_routing_switch_box_unique_side_module(cur_sram_orgz_info, verilog_dir, subckt_dir, isb, unique_mirror, side_manager.get_side()); + } + } + + /* Output unique modules */ for (size_t isb = 0; isb < device_rr_switch_block.get_num_unique_mirror(); ++isb) { - /* Output unique mirrors */ RRSwitchBlock unique_mirror = device_rr_switch_block.get_unique_mirror(isb); - dump_verilog_routing_switch_box_unique_subckt(cur_sram_orgz_info, verilog_dir, subckt_dir, unique_mirror); + dump_verilog_routing_switch_box_unique_module(cur_sram_orgz_info, verilog_dir, subckt_dir, unique_mirror); } /* Restore sram_orgz_info to the base */ diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_utils.c b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_utils.c index 7bf957db7..1d006b950 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_utils.c +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_utils.c @@ -347,8 +347,8 @@ void verilog_include_simulation_defines_file(FILE* fp, /* Create a file handler for a subckt Verilog netlist */ FILE* verilog_create_one_subckt_file(char* subckt_dir, - char* subckt_name_prefix, - char* verilog_subckt_file_name_prefix, + const char* subckt_name_prefix, + const char* verilog_subckt_file_name_prefix, int grid_x, int grid_y, char** verilog_fname) { FILE* fp = NULL; diff --git a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_utils.h b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_utils.h index a9d30139e..b7ed1f99a 100644 --- a/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_utils.h +++ b/vpr7_x2p/vpr/SRC/fpga_x2p/verilog/verilog_utils.h @@ -31,8 +31,8 @@ void verilog_include_defines_preproc_file(FILE* fp, char* formatted_verilog_dir); FILE* verilog_create_one_subckt_file(char* subckt_dir, - char* subckt_name_prefix, - char* verilog_subckt_file_name_prefix, + const char* subckt_name_prefix, + const char* verilog_subckt_file_name_prefix, int grid_x, int grid_y, char** verilog_fname);