start refactoring the switch block verilog generation

This commit is contained in:
tangxifan 2019-09-17 20:40:26 -06:00
parent 7be83235a0
commit d7ac7d3649
9 changed files with 431 additions and 7 deletions

View File

@ -19,4 +19,5 @@ end_section "OpenFPGA.build"
start_section "OpenFPGA.TaskTun" "${GREEN}..Running_Regression..${NC}"
cd -
python3 openfpga_flow/scripts/run_fpga_task.py blif_vpr_flow
python3 openfpga_flow/scripts/run_fpga_task.py tileable_routing
end_section "OpenFPGA.TaskTun"

View File

@ -38,7 +38,7 @@ vpr_fpga_verilog_print_user_defined_template=
#vpr_fpga_verilog_print_report_timing_tcl=
vpr_fpga_verilog_print_sdc_pnr=
vpr_fpga_verilog_print_sdc_analysis=
vpr_fpga_x2p_compact_routing_hierarchy=
#vpr_fpga_x2p_compact_routing_hierarchy=
end_flow_with_test=
#[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH]

View File

@ -8,6 +8,7 @@
********************************************************************/
#include "vtr_assert.h"
#include "sides.h"
#include "fpga_x2p_naming.h"
/************************************************
@ -199,3 +200,85 @@ std::string generate_routing_channel_module_name(const t_rr_type& chan_type,
return std::string( module_prefix_map[chan_type] + std::to_string(coordinate.x()) + std::string("_") + std::to_string(coordinate.y()) + std::string("_") );
}
/*********************************************************************
* Generate the port name for a routing track with a given coordinate
* and port direction
*********************************************************************/
std::string generate_routing_track_port_name(const t_rr_type& chan_type,
const vtr::Point<size_t>& coordinate,
const size_t& track_id,
const PORTS& port_direction) {
/* Channel must be either CHANX or CHANY */
VTR_ASSERT( (CHANX == chan_type) || (CHANY == chan_type) );
/* Create a map between chan_type and module_prefix */
std::map<t_rr_type, std::string> module_prefix_map;
/* TODO: use a constexpr string to replace the fixed name? */
module_prefix_map[CHANX] = std::string("chanx");
module_prefix_map[CHANY] = std::string("chany");
std::string port_name = module_prefix_map[chan_type];
port_name += std::string("_" + std::to_string(coordinate.x()) + std::string("__") + std::to_string(coordinate.y()) + std::string("__"));
switch (port_direction) {
case OUT_PORT:
port_name += std::string("out_");
break;
case IN_PORT:
port_name += std::string("in_");
break;
default:
vpr_printf(TIO_MESSAGE_ERROR, "(File: %s [LINE%d]) Invalid direction of chan_rr_node!\n",
__FILE__, __LINE__);
exit(1);
}
/* Add the track id to the port name */
port_name += std::to_string(track_id) + std::string("_");
return port_name;
}
/*********************************************************************
* Generate the module name for a switch block with a given coordinate
*********************************************************************/
std::string generate_switch_block_module_name(const vtr::Point<size_t>& coordinate) {
return std::string( "sb_" + std::to_string(coordinate.x()) + std::string("__") + std::to_string(coordinate.y()) + std::string("_") );
}
/*********************************************************************
* Generate the port name for a Grid
* TODO: add more comments about why we need different names for
* top and non-top netlists
*********************************************************************/
std::string generate_grid_port_name(const vtr::Point<size_t>& coordinate,
const size_t& height,
const e_side& side,
const size_t& pin_id,
const bool& for_top_netlist) {
if (true == for_top_netlist) {
std::string port_name = "grid_";
port_name += std::to_string(coordinate.x());
port_name += "__";
port_name += std::to_string(coordinate.y());
port_name += "__pin_";
port_name += std::to_string(height);
port_name += "__";
port_name += std::to_string(size_t(side));
port_name += "__";
port_name += std::to_string(pin_id);
port_name += "_";
return port_name;
}
/* For non-top netlist */
VTR_ASSERT( false == for_top_netlist );
Side side_manager(side);
std::string port_name = std::string(side_manager.to_string());
port_name += "_height_";
port_name += std::to_string(height);
port_name += "__pin_";
port_name += std::to_string(pin_id);
port_name += "_";
return port_name;
}

View File

@ -52,6 +52,19 @@ std::string generate_routing_channel_module_name(const t_rr_type& chan_type,
const size_t& block_id);
std::string generate_routing_channel_module_name(const t_rr_type& chan_type,
const vtr::Point<size_t>& block_id);
const vtr::Point<size_t>& coordinate);
std::string generate_routing_track_port_name(const t_rr_type& chan_type,
const vtr::Point<size_t>& coordinate,
const size_t& track_id,
const PORTS& port_direction);
std::string generate_switch_block_module_name(const vtr::Point<size_t>& coordinate);
std::string generate_grid_port_name(const vtr::Point<size_t>& coordinate,
const size_t& height,
const e_side& side,
const size_t& pin_id,
const bool& for_top_netlist);
#endif

View File

@ -0,0 +1,62 @@
/********************************************************************
* This file includes most utilized function for rr_block data structures
*******************************************************************/
#include <vector>
#include <algorithm>
#include "vtr_assert.h"
#include "vpr_types.h"
#include "fpga_x2p_types.h"
#include "rr_blocks_utils.h"
/*********************************************************************
* This function will find the global ports required by a Switch Block
* module. It wil find all the circuit models in the circuit library
* that may be included in the Switch Block
* Collect the global ports from the circuit_models and merge with the same name
********************************************************************/
std::vector<CircuitPortId> find_switch_block_global_ports(const RRGSB& rr_gsb,
const CircuitLibrary& circuit_lib,
const std::vector<t_switch_inf>& switch_lib) {
std::vector<CircuitModelId> sub_models;
/* Walk through the OUTPUT nodes at each side of a GSB,
* get the switch id of incoming edges
* and get the circuit model linked to the switch id
*/
for (size_t side = 0; side < rr_gsb.get_num_sides(); ++side) {
Side side_manager(side);
for (size_t itrack = 0; itrack < rr_gsb.get_chan_width(side_manager.get_side()); ++itrack) {
if (OUT_PORT != rr_gsb.get_chan_node_direction(side_manager.get_side(), itrack)) {
continue;
}
/* Find the driver switch of the node */
short driver_switch = rr_gsb.get_chan_node(side_manager.get_side(), itrack)->drive_switches[DEFAULT_SWITCH_ID];
/* Find the circuit model id of the driver switch */
VTR_ASSERT( (size_t)driver_switch < switch_lib.size() );
/* Get the model, and try to add to the sub_model list */
CircuitModelId switch_circuit_model = switch_lib[driver_switch].circuit_model;
/* Make sure it is a valid id */
VTR_ASSERT( CircuitModelId::INVALID() == switch_circuit_model );
/* Get the model, and try to add to the sub_model list */
if (sub_models.end() == std::find(sub_models.begin(), sub_models.end(), switch_circuit_model)) {
/* Not yet in the list, add it */
sub_models.push_back(switch_circuit_model);
}
}
}
std::vector<CircuitPortId> global_ports;
/* Iterate over the model list, and add the global ports*/
for (const auto& model : sub_models) {
std::vector<CircuitPortId> temp_global_ports = circuit_lib.model_global_ports(model, true);
/* Add the temp_global_ports to the list to be returned, make sure we do not have any duplicated ports */
for (const auto& port_candidate : temp_global_ports) {
if (global_ports.end() == std::find(global_ports.begin(), global_ports.end(), port_candidate)) {
/* Not yet in the list, add it */
global_ports.push_back(port_candidate);
}
}
}
return global_ports;
}

View File

@ -0,0 +1,17 @@
/********************************************************************
* Header file for rr_block_utils.cpp
*******************************************************************/
#ifndef RR_BLOCKS_UTILS_H
#define RR_BLOCKS_UTILS_H
/* Include other header file required by the function declaration */
#include <vector>
#include "physical_types.h"
#include "circuit_library.h"
#include "rr_blocks.h"
std::vector<CircuitPortId> find_switch_block_global_ports(const RRGSB& rr_gsb,
const CircuitLibrary& circuit_lib,
const std::vector<t_switch_inf>& switch_lib);
#endif

View File

@ -280,7 +280,7 @@ void vpr_fpga_verilog(t_vpr_setup vpr_setup,
vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts);
/* Dump routing resources: switch blocks, connection blocks and channel tracks */
print_verilog_routing_resources(module_manager, sram_verilog_orgz_info, src_dir_path, rr_dir_path, Arch, vpr_setup.RoutingArch,
print_verilog_routing_resources(module_manager, mux_lib, sram_verilog_orgz_info, src_dir_path, rr_dir_path, Arch, vpr_setup.RoutingArch,
num_rr_nodes, rr_node, rr_node_indices, rr_indexed_data,
vpr_setup.FPGA_SPICE_Opts);

View File

@ -30,6 +30,7 @@
/* Include SPICE support headers*/
#include "linkedlist.h"
#include "rr_blocks.h"
#include "rr_blocks_utils.h"
#include "fpga_x2p_types.h"
#include "fpga_x2p_utils.h"
#include "fpga_x2p_backannotate_utils.h"
@ -2121,6 +2122,218 @@ void update_routing_connection_box_conf_bits(t_sram_orgz_info* cur_sram_orgz_inf
return;
}
/*********************************************************************
* Generate the Verilog module for a Switch Box.
* A Switch Box module consists of following ports:
* 1. Channel Y [x][y] inputs
* 2. Channel X [x+1][y] inputs
* 3. Channel Y [x][y-1] outputs
* 4. Channel X [x][y] outputs
* 5. Grid[x][y+1] Right side outputs pins
* 6. Grid[x+1][y+1] Left side output pins
* 7. Grid[x+1][y+1] Bottom side output pins
* 8. Grid[x+1][y] Top side output pins
* 9. Grid[x+1][y] Left side output pins
* 10. Grid[x][y] Right side output pins
* 11. Grid[x][y] Top side output pins
* 12. Grid[x][y+1] Bottom side output pins
*
* Location of a Switch Box in FPGA fabric:
*
* -------------- --------------
* | | | |
* | 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] |
* | | | |
* -------------- --------------
*
* Switch Block pin location map
*
* Grid[x][y+1] ChanY[x][y+1] Grid[x+1][y+1]
* right_pins inputs/outputs left_pins
* | ^ |
* | | |
* v v v
* +-----------------------------------------------+
* | |
* Grid[x][y+1] | | Grid[x+1][y+1]
* bottom_pins---->| |<---- bottom_pins
* | |
* ChanX[x][y] | Switch Box [x][y] | ChanX[x+1][y]
* inputs/outputs<--->| |<---> inputs/outputs
* | |
* Grid[x][y+1] | | Grid[x+1][y+1]
* top_pins---->| |<---- top_pins
* | |
* +-----------------------------------------------+
* ^ ^ ^
* | | |
* | v |
* Grid[x][y] ChanY[x][y] Grid[x+1][y]
* right_pins inputs/outputs left_pins
*
*
********************************************************************/
static
void print_verilog_routing_switch_box_unique_module(ModuleManager& module_manager,
const CircuitLibrary& circuit_lib,
const MuxLibrary& mux_lib,
const std::vector<t_switch_inf>& rr_switches,
t_sram_orgz_info* cur_sram_orgz_info,
const std::string& verilog_dir,
const std::string& subckt_dir,
const RRGSB& rr_sb,
const bool& is_explicit_mapping) {
/* TODO: move this part to another function where we count the conf bits for all the switch blocks !!!*/
/* 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);
int esti_sram_cnt = cur_num_sram + num_conf_bits;
RRGSB rr_gsb = rr_sb; /* IMPORTANT: this copy will be removed when the config ports are initialized when created!!! */
rr_gsb.set_sb_num_reserved_conf_bits(num_reserved_conf_bits);
rr_gsb.set_sb_conf_bits_lsb(cur_num_sram);
rr_gsb.set_sb_conf_bits_msb(cur_num_sram + num_conf_bits - 1);
/* Create the netlist */
vtr::Point<size_t> gsb_coordinate(rr_gsb.get_sb_x(), rr_gsb.get_sb_y());
std::string verilog_fname(subckt_dir + generate_routing_block_netlist_name(sb_verilog_file_name_prefix, gsb_coordinate, std::string(verilog_netlist_file_postfix)));
/* TODO: remove the bak file when the file is ready */
verilog_fname += ".bak";
/* Create the file stream */
std::fstream fp;
fp.open(verilog_fname, std::fstream::out | std::fstream::trunc);
check_file_handler(fp);
print_verilog_file_header(fp, std::string("Verilog modules for Unique Switch Blocks[" + std::to_string(rr_gsb.get_sb_x()) + "]["+ std::to_string(rr_gsb.get_sb_y()) + "]"));
/* Print preprocessing flags */
print_verilog_include_defines_preproc_file(fp, verilog_dir);
/* Create a Verilog Module based on the circuit model, and add to module manager */
ModuleId module_id = module_manager.add_module(generate_switch_block_module_name(gsb_coordinate));
/* Add ports to the module */
/* Global ports:
* In the circuit_library, find all the circuit models that may be included in the Switch Block
* Collect the global ports from the circuit_models and merge with the same name
*/
std::vector<CircuitPortId> global_ports = find_switch_block_global_ports(rr_gsb, circuit_lib, rr_switches);
for (const auto& port : global_ports) {
BasicPort module_port(circuit_lib.port_lib_name(port), circuit_lib.port_size(port));
module_manager.add_port(module_id, module_port, ModuleManager::MODULE_GLOBAL_PORT);
}
/* Add routing channel ports at each side of the GSB */
for (size_t side = 0; side < rr_gsb.get_num_sides(); ++side) {
Side side_manager(side);
DeviceCoordinator port_coordinator = rr_gsb.get_side_block_coordinator(side_manager.get_side());
for (size_t itrack = 0; itrack < rr_gsb.get_chan_width(side_manager.get_side()); ++itrack) {
vtr::Point<size_t> port_coord(port_coordinator.get_x(), port_coordinator.get_y());
std::string port_name = generate_routing_track_port_name(rr_gsb.get_chan_node(side_manager.get_side(), itrack)->type,
port_coord, itrack,
rr_gsb.get_chan_node_direction(side_manager.get_side(), itrack));
BasicPort module_port(port_name, 1); /* Every track has a port size of 1 */
switch (rr_gsb.get_chan_node_direction(side_manager.get_side(), itrack)) {
case OUT_PORT:
module_manager.add_port(module_id, module_port, ModuleManager::MODULE_OUTPUT_PORT);
break;
case IN_PORT:
module_manager.add_port(module_id, module_port, ModuleManager::MODULE_INPUT_PORT);
break;
default:
vpr_printf(TIO_MESSAGE_ERROR,
"(File: %s [LINE%d]) Invalid direction of chan[%d][%d]_track[%d]!\n",
__FILE__, __LINE__, rr_gsb.get_sb_x(), rr_gsb.get_sb_y(), itrack);
exit(1);
}
}
/* Dump OPINs of adjacent CLBs */
for (size_t inode = 0; inode < rr_gsb.get_num_opin_nodes(side_manager.get_side()); ++inode) {
vtr::Point<size_t> port_coord(rr_gsb.get_opin_node(side_manager.get_side(), inode)->xlow,
rr_gsb.get_opin_node(side_manager.get_side(), inode)->ylow);
std::string port_name = generate_grid_side_port_name(port_coord,
rr_gsb.get_opin_node_grid_side(side_manager.get_side(), inode),
rr_gsb.get_opin_node(side_manager.get_side(), inode)->ptc_num);
BasicPort module_port(port_name, 1); /* Every grid output has a port size of 1 */
/* Grid outputs are inputs of switch blocks */
module_manager.add_port(module_id, module_port, ModuleManager::MODULE_INPUT_PORT);
}
}
/* Add configuration ports */
/* TODO: Reserved sram ports */
/*
if (0 < rr_sb.get_sb_num_reserved_conf_bits()) {
dump_verilog_reserved_sram_ports(fp, cur_sram_orgz_info,
rr_gsb.get_sb_reserved_conf_bits_lsb(),
rr_gsb.get_sb_reserved_conf_bits_msb(),
VERILOG_PORT_INPUT);
fprintf(fp, ",\n");
}
*/
/* TODO: Normal sram ports */
/*
dump_verilog_sram_ports(fp, cur_sram_orgz_info,
rr_gsb.get_sb_conf_bits_lsb(),
rr_gsb.get_sb_conf_bits_msb(),
VERILOG_PORT_INPUT);
*/
/* Dump ports only visible during formal verification*/
/*
if (0 < rr_sb.get_sb_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_gsb.get_sb_conf_bits_lsb(),
rr_gsb.get_sb_conf_bits_msb(),
VERILOG_PORT_INPUT, is_explicit_mapping);
fprintf(fp, "\n");
fprintf(fp, "`endif\n");
}
fprintf(fp, "); \n");
*/
/* TODO: Local wires for memory configurations */
/*
dump_verilog_sram_config_bus_internal_wires(fp, cur_sram_orgz_info,
rr_gsb.get_sb_conf_bits_lsb(),
rr_gsb.get_sb_conf_bits_msb());
*/
/* Put an end to the Verilog module */
print_verilog_module_end(fp, module_manager.module_name(module_id));
/* Add an empty line as a splitter */
fp << std::endl;
/* Close file handler */
fp.close();
/* 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, verilog_fname.c_str());
*/
return;
}
/* Task: Print the subckt of a Switch Box.
* A Switch Box subckt consists of following ports:
* 1. Channel Y [x][y] inputs
@ -3797,6 +4010,24 @@ void dump_verilog_routing_connection_box_subckt(t_sram_orgz_info* cur_sram_orgz_
return;
}
/*********************************************************************
* Generate the port name for a Grid
*********************************************************************/
std::string generate_grid_side_port_name(const vtr::Point<size_t>& coordinate,
const e_side& side,
const size_t& pin_id) {
/* Output the pins on the side*/
int height = get_grid_pin_height(coordinate.x(), coordinate.y(), (int)pin_id);
if (1 != grid[coordinate.x()][coordinate.y()].type->pinloc[height][side][pin_id]) {
vpr_printf(TIO_MESSAGE_ERROR,
"(File:%s, [LINE%d])Fail to generate a grid pin (x=%lu, y=%lu, height=%lu, side=%s, index=%d)\n",
__FILE__, __LINE__,
coordinate.x(), coordinate.y(), height, convert_side_index_to_string(side), pin_id);
exit(1);
}
return generate_grid_port_name(coordinate, (size_t)height, side, pin_id, true);
}
/*********************************************************************
* Top-level function:
* Build the Verilog modules for global routing architecture
@ -3814,6 +4045,7 @@ void dump_verilog_routing_connection_box_subckt(t_sram_orgz_info* cur_sram_orgz_
* unique modules in terms of internal logics
*********************************************************************/
void print_verilog_routing_resources(ModuleManager& module_manager,
const MuxLibrary& mux_lib,
t_sram_orgz_info* cur_sram_orgz_info,
char* verilog_dir,
char* subckt_dir,
@ -3827,6 +4059,13 @@ void print_verilog_routing_resources(ModuleManager& module_manager,
boolean compact_routing_hierarchy = FPGA_SPICE_Opts.compact_routing_hierarchy;
boolean explicit_port_mapping = FPGA_SPICE_Opts.SynVerilogOpts.dump_explicit_verilog;
/* Create a vector of switch infs. TODO: this should be replaced switch objects!!! */
std::vector<t_switch_inf> rr_switches;
for (short i = 0; i < routing_arch.num_switch; ++i) {
rr_switches.push_back(switch_inf[i]);
}
/* Two major tasks:
* 1. Generate sub-circuits for Routing Channels
* 2. Generate sub-circuits for Switch Boxes
@ -3902,12 +4141,15 @@ void print_verilog_routing_resources(ModuleManager& module_manager,
/* Output unique modules */
for (size_t isb = 0; isb < device_rr_gsb.get_num_sb_unique_module(); ++isb) {
const RRGSB& unique_mirror = device_rr_gsb.get_sb_unique_module(isb);
/*
dump_verilog_routing_switch_box_unique_module(cur_sram_orgz_info, verilog_dir,
subckt_dir, unique_mirror, explicit_port_mapping);
*/
dump_verilog_routing_switch_box_unique_subckt(cur_sram_orgz_info, verilog_dir,
subckt_dir, unique_mirror, explicit_port_mapping);
/*
print_verilog_routing_switch_box_unique_module(module_manager, arch.spice->circuit_lib, mux_lib,
rr_switches,
cur_sram_orgz_info, std::string(verilog_dir),
std::string(subckt_dir), unique_mirror,
explicit_port_mapping);
*/
}
/* Restore sram_orgz_info to the base */

View File

@ -5,6 +5,7 @@
#define VERILOG_ROUTING_H
/* Include other header files which are dependency on the function declared below */
#include "mux_library.h"
#include "module_manager.h"
void dump_verilog_routing_chan_subckt(t_sram_orgz_info* cur_sram_orgz_info,
@ -140,7 +141,12 @@ void dump_verilog_routing_connection_box_subckt(t_sram_orgz_info* cur_sram_orgz_
bool is_explicit_mapping);
std::string generate_grid_side_port_name(const vtr::Point<size_t>& coordinate,
const e_side& side,
const size_t& pin_id);
void print_verilog_routing_resources(ModuleManager& module_manager,
const MuxLibrary& mux_lib,
t_sram_orgz_info* cur_sram_orgz_info,
char* verilog_dir,
char* subckt_dir,