add module nets to connect grids and sbs

This commit is contained in:
tangxifan 2019-10-15 16:08:51 -06:00
parent 4b56b755f2
commit 071757dc52
8 changed files with 469 additions and 68 deletions

View File

@ -669,6 +669,23 @@ std::string generate_mux_sram_port_name(const CircuitLibrary& circuit_lib,
return generate_local_sram_port_name(prefix, mux_instance_id, port_type);
}
/*********************************************************************
* Generate the prefix for naming a grid block netlist or a grid module
* This function will consider the io side and add it to the prefix
**********************************************************************/
std::string generate_grid_block_prefix(const std::string& prefix,
const e_side& io_side) {
std::string block_prefix(prefix);
if (NUM_SIDES != io_side) {
Side side_manager(io_side);
block_prefix += std::string("_");
block_prefix += std::string(side_manager.to_string());
}
return block_prefix;
}
/*********************************************************************
* Generate the netlist name of a grid block
**********************************************************************/
@ -680,9 +697,7 @@ std::string generate_grid_block_netlist_name(const std::string& block_name,
std::string module_name(block_name);
if (true == is_block_io) {
Side side_manager(io_side);
module_name += std::string("_");
module_name += std::string(side_manager.to_string());
module_name = generate_grid_block_prefix(block_name, io_side);
}
module_name += postfix;
@ -704,6 +719,7 @@ std::string generate_grid_block_module_name(const std::string& prefix,
return module_name;
}
/*********************************************************************
* Generate the module name of a physical block
* To ensure a unique name for each physical block inside the graph of complex blocks
@ -758,6 +774,65 @@ std::string generate_physical_block_module_name(const std::string& prefix,
return module_name;
}
/*********************************************************************
* This function is a wrapper for the function generate_physical_block_module_name()
* which can automatically decode the io_side and add a prefix
**********************************************************************/
std::string generate_grid_physical_block_module_name(const std::string& prefix,
t_pb_type* pb_type,
const e_side& border_side) {
std::string module_name_prefix = generate_grid_block_prefix(prefix, border_side);
return generate_physical_block_module_name(module_name_prefix, pb_type);
}
/********************************************************************
* This function try to infer if a grid locates at the border of a
* FPGA fabric, i.e., TOP/RIGHT/BOTTOM/LEFT sides
* 1. if this grid is on the border, it will return the side it locates,
* 2. if this grid is in the center, it will return an valid value NUM_SIDES
*
* In this function, we assume that the corner grids are actually empty!
*
* +-------+ +----------------------------+ +-------+
* | EMPTY | | TOP side I/O | | EMPTY |
* +-------+ +----------------------------+ +-------+
*
* +-------+ +----------------------------+ +-------+
* | | | | | |
* | | | | | |
* | | | | | |
* | LEFT | | | | RIGHT |
* | side | | Core grids | | side |
* | I/O | | | | I/O |
* | | | | | |
* | | | | | |
* | | | | | |
* | | | | | |
* +-------+ +----------------------------+ +-------+
*
* +-------+ +----------------------------+ +-------+
* | EMPTY | | BOTTOM side I/O | | EMPTY |
* +-------+ +----------------------------+ +-------+
*******************************************************************/
e_side find_grid_border_side(const vtr::Point<size_t>& device_size,
const vtr::Point<size_t>& grid_coordinate) {
e_side grid_side = NUM_SIDES;
if (device_size.y() - 1 == grid_coordinate.y()) {
return TOP;
}
if (device_size.x() - 1 == grid_coordinate.x()) {
return RIGHT;
}
if (0 == grid_coordinate.y()) {
return BOTTOM;
}
if (0 == grid_coordinate.x()) {
return LEFT;
}
return grid_side;
}
/*********************************************************************
* Generate the port name of a Verilog module describing a pb_type

View File

@ -128,6 +128,9 @@ std::string generate_mux_sram_port_name(const CircuitLibrary& circuit_lib,
const size_t& mux_instance_id,
const e_spice_model_port_type& port_type);
std::string generate_grid_block_prefix(const std::string& prefix,
const e_side& io_side);
std::string generate_grid_block_netlist_name(const std::string& block_name,
const bool& is_block_io,
const e_side& io_side,
@ -141,6 +144,13 @@ std::string generate_grid_block_module_name(const std::string& prefix,
std::string generate_physical_block_module_name(const std::string& prefix,
t_pb_type* physical_pb_type);
std::string generate_grid_physical_block_module_name(const std::string& prefix,
t_pb_type* pb_type,
const e_side& border_side);
e_side find_grid_border_side(const vtr::Point<size_t>& device_size,
const vtr::Point<size_t>& grid_coordinate);
std::string generate_pb_type_port_name(t_port* pb_type_port);
std::string generate_fpga_global_io_port_name(const std::string& prefix,

View File

@ -2136,6 +2136,27 @@ t_pb* get_hardlogic_child_pb(t_pb* cur_hardlogic_pb,
return (&(cur_hardlogic_pb->child_pbs[0][0]));
}
/********************************************************************
* Find the height of a pin in a grid definition
*******************************************************************/
size_t find_grid_pin_height(const std::vector<std::vector<t_grid_tile>>& grids,
const vtr::Point<size_t>& grid_coordinate,
const size_t& pin_index) {
t_type_ptr grid_type = grids[grid_coordinate.x()][grid_coordinate.y()].type;
/* Return if this is an empty type */
if ( (NULL == grid_type)
|| (EMPTY_TYPE == grid_type)) {
return size_t(-1);
}
/* Check if the pin index is in the range */
VTR_ASSERT(pin_index < size_t(grid_type->num_pins));
/* Find the pin_height */
return grid_type->pin_height[pin_index];
}
int get_grid_pin_height(int grid_x, int grid_y, int pin_index) {
int pin_height;
t_type_ptr grid_type = NULL;

View File

@ -4,7 +4,9 @@
/* Only include header files those are required by the data types in the following function declaration */
#include <vector>
#include <map>
#include "vtr_geometry.h"
#include "device_port.h"
#include "vpr_types.h"
#include "circuit_library.h"
#include "fpga_x2p_types.h"
#include "fpga_x2p_bitstream_utils.h"
@ -165,6 +167,10 @@ t_phy_pb* get_lut_child_phy_pb(t_phy_pb* cur_lut_pb,
t_pb* get_hardlogic_child_pb(t_pb* cur_hardlogic_pb,
int mode_index);
size_t find_grid_pin_height(const std::vector<std::vector<t_grid_tile>>& grids,
const vtr::Point<size_t>& grid_coordinate,
const size_t& pin_index);
int get_grid_pin_height(int grid_x, int grid_y, int pin_index);
int get_grid_pin_side(int grid_x, int grid_y, int pin_index);

View File

@ -70,10 +70,7 @@ void add_grid_module_pb_type_ports(ModuleManager& module_manager,
if (IO_TYPE == grid_type_descriptor) {
grid_pin_sides.push_back(find_grid_module_pin_side(grid_type_descriptor, border_side));
} else {
grid_pin_sides.push_back(TOP);
grid_pin_sides.push_back(RIGHT);
grid_pin_sides.push_back(BOTTOM);
grid_pin_sides.push_back(LEFT);
grid_pin_sides = {TOP, RIGHT, BOTTOM, LEFT};
}
/* Create a map between pin class type and grid pin direction */
@ -286,13 +283,7 @@ void print_verilog_primitive_block(std::fstream& fp,
CircuitModelId& primitive_model = primitive_pb_graph_node->pb_type->circuit_model;
/* Generate the module name for this primitive pb_graph_node*/
std::string primitive_module_name_prefix(grid_verilog_file_name_prefix);
/* Add side string to the name if it is valid, this is mainly for I/O block */
if (NUM_SIDES != io_side) {
Side side_manager(io_side);
primitive_module_name_prefix += std::string(side_manager.to_string());
primitive_module_name_prefix += std::string("_");
}
std::string primitive_module_name_prefix = generate_grid_block_prefix(std::string(grid_verilog_file_name_prefix), io_side);
std::string primitive_module_name = generate_physical_block_module_name(primitive_module_name_prefix, primitive_pb_graph_node->pb_type);
/* Create a module of the primitive LUT and register it to module manager */
@ -901,13 +892,7 @@ void print_verilog_physical_blocks_rec(std::fstream& fp,
}
/* Generate the name of the Verilog module for this pb_type */
std::string pb_module_name_prefix(grid_verilog_file_name_prefix);
/* Add side string to the name if it is valid */
if (NUM_SIDES != io_side) {
Side side_manager(io_side);
pb_module_name_prefix += std::string(side_manager.to_string());
pb_module_name_prefix += std::string("_");
}
std::string pb_module_name_prefix = generate_grid_block_prefix(std::string(grid_verilog_file_name_prefix), io_side);
std::string pb_module_name = generate_physical_block_module_name(pb_module_name_prefix, physical_pb_type);
/* Register the Verilog module in module manager */
@ -1096,7 +1081,7 @@ void print_verilog_grid(ModuleManager& module_manager,
print_verilog_comment(fp, std::string("---- END Sub-module of physical block:" + std::string(phy_block_type->name) + " ----"));
/* Create a Verilog Module for the top-level physical block, and add to module manager */
std::string grid_module_name = generate_grid_block_module_name(std::string(grid_verilog_file_name_prefix), phy_block_type->name, IO_TYPE == phy_block_type, border_side);
std::string grid_module_name = generate_grid_block_module_name(std::string(grid_verilog_file_name_prefix), std::string(phy_block_type->name), IO_TYPE == phy_block_type, border_side);
ModuleId grid_module = module_manager.add_module(grid_module_name);
VTR_ASSERT(true == module_manager.valid_module_id(grid_module));
@ -1114,13 +1099,7 @@ void print_verilog_grid(ModuleManager& module_manager,
/* Generate the name of the Verilog module for this pb_type */
std::string pb_module_name_prefix(grid_verilog_file_name_prefix);
/* Add side string to the name if it is valid */
if (NUM_SIDES != border_side) {
Side side_manager(border_side);
pb_module_name_prefix += std::string(side_manager.to_string());
pb_module_name_prefix += std::string("_");
}
std::string pb_module_name = generate_physical_block_module_name(pb_module_name_prefix, phy_block_type->pb_graph_head->pb_type);
std::string pb_module_name = generate_grid_physical_block_module_name(pb_module_name_prefix, phy_block_type->pb_graph_head->pb_type, border_side);
ModuleId pb_module = module_manager.find_module(pb_module_name);
VTR_ASSERT(true == module_manager.valid_module_id(pb_module));

View File

@ -5186,6 +5186,11 @@ void dump_verilog_routing_connection_box_subckt(t_sram_orgz_info* cur_sram_orgz_
/*********************************************************************
* Generate the port name for a Grid
* This is a wrapper function for generate_port_name()
* which can automatically decode the port name by the pin side and height
*
* TODO: This function is dependent on the global variable: grid
* This should be replaced by a local variable!!!
*********************************************************************/
std::string generate_grid_side_port_name(const vtr::Point<size_t>& coordinate,
const e_side& side,

View File

@ -7,6 +7,7 @@
/* Include other header files which are dependency on the function declared below */
#include "mux_library.h"
#include "module_manager.h"
#include "rr_blocks.h"
void dump_verilog_routing_chan_subckt(t_sram_orgz_info* cur_sram_orgz_info,
char* verilog_dir,

View File

@ -12,35 +12,56 @@
#include "fpga_x2p_naming.h"
#include "fpga_x2p_utils.h"
#include "fpga_x2p_pbtypes_utils.h"
#include "module_manager_utils.h"
#include "verilog_global.h"
#include "verilog_routing.h"
#include "verilog_writer_utils.h"
#include "verilog_module_writer.h"
#include "verilog_top_module.h"
/********************************************************************
* Generate the name for a grid block, by considering
* 1. if it locates on the border with given device size
* 2. its type
*
* This function is mainly used in the top-level module generation
*******************************************************************/
static
std::string generate_grid_block_module_name_in_top_module(const std::string& prefix,
const vtr::Point<size_t>& device_size,
const std::vector<std::vector<t_grid_tile>>& grids,
const vtr::Point<size_t>& grid_coordinate) {
/* Determine if the grid locates at the border */
e_side border_side = find_grid_border_side(device_size, grid_coordinate);
return generate_grid_block_module_name(prefix, std::string(grids[grid_coordinate.x()][grid_coordinate.y()].type->name),
IO_TYPE == grids[grid_coordinate.x()][grid_coordinate.y()].type, border_side);
}
/********************************************************************
* Add a instance of a grid module to the top module
*******************************************************************/
static
void add_top_module_grid_instance(ModuleManager& module_manager,
const ModuleId& top_module,
t_type_ptr grid_type,
const e_side& border_side) {
size_t add_top_module_grid_instance(ModuleManager& module_manager,
const ModuleId& top_module,
t_type_ptr grid_type,
const e_side& border_side) {
/* Find the module name for this type of grid */
std::string grid_module_name_prefix(grid_verilog_file_name_prefix);
/* Add side string to the name if it is valid */
if (NUM_SIDES != border_side) {
Side side_manager(border_side);
grid_module_name_prefix += std::string(side_manager.to_string());
grid_module_name_prefix += std::string("_");
}
std::string grid_module_name = generate_physical_block_module_name(grid_module_name_prefix, grid_type->pb_graph_head->pb_type);
std::string grid_module_name = generate_grid_block_module_name(grid_module_name_prefix, std::string(grid_type->name), IO_TYPE == grid_type, border_side);
ModuleId grid_module = module_manager.find_module(grid_module_name);
VTR_ASSERT(true == module_manager.valid_module_id(grid_module));
/* Record the instance id */
size_t grid_instance = module_manager.num_instance(top_module, grid_module);
/* Add the module to top_module */
module_manager.add_child_module(top_module, grid_module);
printf("Added grid module %s to top-level module\n", grid_module_name.c_str());
return grid_instance;
}
/********************************************************************
@ -50,8 +71,12 @@ void add_top_module_grid_instance(ModuleManager& module_manager,
* Here, we will iterate over the full fabric (coordinates)
* and instanciate the grid modules
*
* Return an 2-D array of instance ids of the grid modules that
* have been added
*
* This function assumes an island-style floorplanning for FPGA fabric
*
*
* +-----------------------------------+
* | I/O grids |
* | TOP side |
@ -71,10 +96,18 @@ void add_top_module_grid_instance(ModuleManager& module_manager,
*
*******************************************************************/
static
void add_top_module_grid_instances(ModuleManager& module_manager,
const ModuleId& top_module,
const vtr::Point<size_t>& device_size,
const std::vector<std::vector<t_grid_tile>>& grids) {
std::vector<std::vector<size_t>> add_top_module_grid_instances(ModuleManager& module_manager,
const ModuleId& top_module,
const vtr::Point<size_t>& device_size,
const std::vector<std::vector<t_grid_tile>>& grids) {
/* Reserve an array for the instance ids */
std::vector<std::vector<size_t>> grid_instance_ids;
grid_instance_ids.resize(grids.size());
for (size_t x = 0; x < grids.size(); ++x) {
/* Deposite an invalid value */
grid_instance_ids[x].resize(grids[x].size(), size_t(-1));
}
/* Instanciate core grids */
for (size_t ix = 1; ix < device_size.x() - 1; ++ix) {
for (size_t iy = 1; iy < device_size.y() - 1; ++iy) {
@ -89,9 +122,9 @@ void add_top_module_grid_instances(ModuleManager& module_manager,
/* We should not meet any I/O grid */
VTR_ASSERT(IO_TYPE != grids[ix][iy].type);
/* Add a grid module to top_module*/
add_top_module_grid_instance(module_manager, top_module,
grids[ix][iy].type,
NUM_SIDES);
grid_instance_ids[ix][iy] = add_top_module_grid_instance(module_manager, top_module,
grids[ix][iy].type,
NUM_SIDES);
}
}
@ -134,22 +167,33 @@ void add_top_module_grid_instances(ModuleManager& module_manager,
/* We should not meet any I/O grid */
VTR_ASSERT(IO_TYPE == grids[io_coordinate.x()][io_coordinate.y()].type);
/* Add a grid module to top_module*/
add_top_module_grid_instance(module_manager, top_module,
grids[io_coordinate.x()][io_coordinate.y()].type,
io_side);
grid_instance_ids[io_coordinate.x()][io_coordinate.y()] = add_top_module_grid_instance(module_manager, top_module, grids[io_coordinate.x()][io_coordinate.y()].type, io_side);
}
}
return grid_instance_ids;
}
/********************************************************************
* Add switch blocks across the FPGA fabric to the top-level module
* Return an 2-D array of instance ids of the switch blocks that
* have been added
*******************************************************************/
static
void add_top_module_switch_block_instances(ModuleManager& module_manager,
const ModuleId& top_module,
const DeviceRRGSB& L_device_rr_gsb,
const bool& compact_routing_hierarchy) {
std::vector<std::vector<size_t>> add_top_module_switch_block_instances(ModuleManager& module_manager,
const ModuleId& top_module,
const DeviceRRGSB& L_device_rr_gsb,
const bool& compact_routing_hierarchy) {
DeviceCoordinator sb_range = L_device_rr_gsb.get_gsb_range();
/* Reserve an array for the instance ids */
std::vector<std::vector<size_t>> sb_instance_ids;
sb_instance_ids.resize(sb_range.get_x());
for (size_t x = 0; x < sb_range.get_x(); ++x) {
/* Deposite an invalid value */
sb_instance_ids[x].resize(sb_range.get_y(), size_t(-1));
}
for (size_t ix = 0; ix < sb_range.get_x(); ++ix) {
for (size_t iy = 0; iy < sb_range.get_y(); ++iy) {
vtr::Point<size_t> sb_coordinate(ix, iy);
@ -163,22 +207,35 @@ void add_top_module_switch_block_instances(ModuleManager& module_manager,
std::string sb_module_name = generate_switch_block_module_name(sb_coordinate);
ModuleId sb_module = module_manager.find_module(sb_module_name);
VTR_ASSERT(true == module_manager.valid_module_id(sb_module));
/* Record the instance id */
sb_instance_ids[ix][iy] = module_manager.num_instance(top_module, sb_module);
/* Add the module to top_module */
module_manager.add_child_module(top_module, sb_module);
}
}
return sb_instance_ids;
}
/********************************************************************
* Add switch blocks across the FPGA fabric to the top-level module
*******************************************************************/
static
void add_top_module_connection_block_instances(ModuleManager& module_manager,
const ModuleId& top_module,
const DeviceRRGSB& L_device_rr_gsb,
const t_rr_type& cb_type,
const bool& compact_routing_hierarchy) {
std::vector<std::vector<size_t>> add_top_module_connection_block_instances(ModuleManager& module_manager,
const ModuleId& top_module,
const DeviceRRGSB& L_device_rr_gsb,
const t_rr_type& cb_type,
const bool& compact_routing_hierarchy) {
DeviceCoordinator cb_range = L_device_rr_gsb.get_gsb_range();
/* Reserve an array for the instance ids */
std::vector<std::vector<size_t>> cb_instance_ids;
cb_instance_ids.resize(cb_range.get_x());
for (size_t x = 0; x < cb_range.get_x(); ++x) {
/* Deposite an invalid value */
cb_instance_ids[x].resize(cb_range.get_y(), size_t(-1));
}
for (size_t ix = 0; ix < cb_range.get_x(); ++ix) {
for (size_t iy = 0; iy < cb_range.get_y(); ++iy) {
vtr::Point<size_t> cb_coordinate(ix, iy);
@ -202,10 +259,254 @@ void add_top_module_connection_block_instances(ModuleManager& module_manager,
std::string cb_module_name = generate_connection_block_module_name(cb_type, cb_coordinate);
ModuleId cb_module = module_manager.find_module(cb_module_name);
VTR_ASSERT(true == module_manager.valid_module_id(cb_module));
/* Record the instance id */
cb_instance_ids[ix][iy] = module_manager.num_instance(top_module, cb_module);
/* Add the module to top_module */
module_manager.add_child_module(top_module, cb_module);
}
}
return cb_instance_ids;
}
/********************************************************************
* Add module nets to connect a GSB to adjacent grid ports/pins
* as well as connection blocks
* This function will create nets for the following types of connections
* between grid output pins of Switch block and adjacent grids
* In this case, the net source is the grid pin, while the net sink
* is the switch block pin
*
* +------------+ +------------+
* | | | |
* | Grid | | Grid |
* | [x][y+1] | | [x+1][y+1] |
* | | | |
* +------------+ +------------+
* | |
* | +------------+ |
* +------>| |<-----+
* | Switch |
* | Block |
* +------>| [x][y] |<-----+
* | +------------+ |
* | |
* | |
* +------------+ +------------+
* | | | |
* | Grid | | Grid |
* | [x][y] | | [x+1][y] |
* | | | |
* +------------+ +------------+
*
*******************************************************************/
static
void add_top_module_nets_connect_grids_and_sb(ModuleManager& module_manager,
const ModuleId& top_module,
const vtr::Point<size_t>& device_size,
const std::vector<std::vector<t_grid_tile>>& grids,
const std::vector<std::vector<size_t>>& grid_instance_ids,
const RRGSB& rr_gsb,
const std::vector<std::vector<size_t>>& sb_instance_ids) {
vtr::Point<size_t> sb_coordinate(rr_gsb.get_sb_x(), rr_gsb.get_sb_y());
/* Connect grid output pins (OPIN) to switch block grid pins */
for (size_t side = 0; side < rr_gsb.get_num_sides(); ++side) {
Side side_manager(side);
for (size_t inode = 0; inode < rr_gsb.get_num_opin_nodes(side_manager.get_side()); ++inode) {
/* Collect source-related information */
/* Generate the grid module name by considering if it locates on the border */
vtr::Point<size_t> grid_coordinate(rr_gsb.get_opin_node(side_manager.get_side(), inode)->xlow, (rr_gsb.get_opin_node(side_manager.get_side(), inode)->ylow));
std::string src_grid_module_name = generate_grid_block_module_name_in_top_module(std::string(grid_verilog_file_name_prefix), device_size, grids, grid_coordinate);
ModuleId src_grid_module = module_manager.find_module(src_grid_module_name);
VTR_ASSERT(true == module_manager.valid_module_id(src_grid_module));
size_t src_grid_instance = grid_instance_ids[grid_coordinate.x()][grid_coordinate.y()];
size_t src_grid_pin_index = rr_gsb.get_opin_node(side_manager.get_side(), inode)->ptc_num;
size_t src_grid_pin_height = find_grid_pin_height(grids, grid_coordinate, src_grid_pin_index);
std::string src_grid_port_name = generate_grid_port_name(grid_coordinate, src_grid_pin_height, rr_gsb.get_opin_node_grid_side(side_manager.get_side(), inode), src_grid_pin_index, false);
ModulePortId src_grid_port_id = module_manager.find_module_port(src_grid_module, src_grid_port_name);
VTR_ASSERT(true == module_manager.valid_module_port_id(src_grid_module, src_grid_port_id));
BasicPort src_grid_port = module_manager.module_port(src_grid_module, src_grid_port_id);
/* Collect sink-related information */
std::string sink_sb_module_name = generate_switch_block_module_name(sb_coordinate);
ModuleId sink_sb_module = module_manager.find_module(sink_sb_module_name);
VTR_ASSERT(true == module_manager.valid_module_id(sink_sb_module));
size_t sink_sb_instance = sb_instance_ids[sb_coordinate.x()][sb_coordinate.y()];
vtr::Point<size_t> sink_sb_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 sink_sb_port_name = generate_grid_side_port_name(sink_sb_port_coord,
rr_gsb.get_opin_node_grid_side(side_manager.get_side(), inode),
src_grid_pin_index);
ModulePortId sink_sb_port_id = module_manager.find_module_port(sink_sb_module, sink_sb_port_name);
VTR_ASSERT(true == module_manager.valid_module_port_id(sink_sb_module, sink_sb_port_id));
BasicPort sink_sb_port = module_manager.module_port(sink_sb_module, sink_sb_port_id);
/* Source and sink port should match in size */
VTR_ASSERT(src_grid_port.get_width() == sink_sb_port.get_width());
/* Create a net for each pin */
for (size_t pin_id = 0; pin_id < src_grid_port.pins().size(); ++pin_id) {
ModuleNetId net = module_manager.create_module_net(top_module);
/* Configure the net source */
printf("src_grid_module_name: %s[%lu][%lu], src_grid_instance_id: %lu (%lu)\n",
src_grid_module_name.c_str(),
grid_coordinate.x(),grid_coordinate.y(),
src_grid_instance, module_manager.num_instance(top_module, src_grid_module));
module_manager.add_module_net_source(top_module, net, src_grid_module, src_grid_instance, src_grid_port_id, src_grid_port.pins()[pin_id]);
/* Configure the net sink */
module_manager.add_module_net_sink(top_module, net, sink_sb_module, sink_sb_instance, sink_sb_port_id, sink_sb_port.pins()[pin_id]);
}
}
}
}
/********************************************************************
* TODO: This function will create nets for the connections
* between grid input pins and connection blocks
* In this case, the net source is the connection block pin,
* while the net sink is the grid input
*
* +------------+ +------------------+ +------------+
* | | | | | |
* | Grid |<-----| Connection Block |----->| Grid |
* | [x][y+1] | | Y-direction | | [x+1][y+1] |
* | | | [x][y+1] | | |
* +------------+ +------------------+ +------------+
* ^
* |
* +------------+ +------------------+
* | Connection | | |
* | Block | | Switch Block |
* | X-direction| | [x][y] |
* | [x][y] | | |
* +------------+ +------------------+
* |
* v
* +------------+
* | |
* | Grid |
* | [x][y] |
* | |
* +------------+
*
*******************************************************************/
static
void add_top_module_nets_connect_grids_and_cb(ModuleManager& module_manager,
const ModuleId& top_module,
const vtr::Point<size_t>& device_size,
const std::vector<std::vector<t_grid_tile>>& grids,
const std::vector<std::vector<size_t>>& grid_instance_ids,
const RRGSB& rr_gsb,
const std::vector<std::vector<size_t>>& cbx_instance_ids,
const std::vector<std::vector<size_t>>& cby_instance_ids) {
}
/********************************************************************
* TODO: This function will create nets for the connections
* between connection block and switch block pins
* Two cases should be considered:
* a. The switch block pin denotes an input of a routing track
* The net source is an output of a routing track of connection block
* while the net sink is an input of a routing track of switch block
* b. The switch block pin denotes an output of a routing track
* The net source is an output of routing track of switch block
* while the net sink is an input of a routing track of connection block
*
* +------------+ +------------------+ +------------+
* | | | | | |
* | Grid | | Connection Block | | Grid |
* | [x][y+1] | | Y-direction | | [x+1][y+1] |
* | | | [x][y+1] | | |
* +------------+ +------------------+ +------------+
* | ^
* v |
* +------------+ +------------------+ +------------+
* | Connection |----->| |----->| Connection |
* | Block | | Switch Block | | Block |
* | X-direction|<-----| [x][y] |<-----| X-direction|
* | [x][y] | | | | [x+1][y] |
* +------------+ +------------------+ +------------+
* | ^
* v |
* +------------+ +------------------+
* | | | |
* | Grid | | Connection Block |
* | [x][y] | | Y-direction |
* | | | [x][y] |
* +------------+ +------------------+
*******************************************************************/
static
void add_top_module_nets_connect_sb_and_cb(ModuleManager& module_manager,
const ModuleId& top_module,
const RRGSB& rr_gsb,
const std::vector<std::vector<size_t>>& sb_instance_ids,
const std::vector<std::vector<size_t>>& cbx_instance_ids,
const std::vector<std::vector<size_t>>& cby_instance_ids) {
}
/********************************************************************
* Add module nets to connect the grid ports/pins to Connection Blocks
* and Switch Blocks
* To make it easy, this function will iterate over all the General
* Switch Blocks (GSBs), through which we can obtain the coordinates
* of all the grids, connection blocks and switch blocks that are
* supposed to be connected tightly.
*
* As such, we have completed all the connection for each grid.
* There is no need to iterate over the grids
*
* +-------------------------+ +---------------------------------+
* | | | Y-direction CB |
* | Grid[x][y+1] | | [x][y + 1] |
* | | +---------------------------------+
* +-------------------------+
* TOP SIDE
* +-------------+ +---------------------------------+
* | | | OPIN_NODE CHAN_NODES OPIN_NODES |
* | | | |
* | | | OPIN_NODES OPIN_NODES |
* | X-direction | | |
* | CB | LEFT SIDE | Switch Block | RIGHT SIDE
* | [x][y] | | [x][y] |
* | | | |
* | | | CHAN_NODES CHAN_NODES |
* | | | |
* | | | OPIN_NODES OPIN_NODES |
* | | | |
* | | | OPIN_NODE CHAN_NODES OPIN_NODES |
* +-------------+ +---------------------------------+
* BOTTOM SIDE
*******************************************************************/
static
void add_top_module_nets_connect_grids_and_gsbs(ModuleManager& module_manager,
const ModuleId& top_module,
const vtr::Point<size_t>& device_size,
const std::vector<std::vector<t_grid_tile>>& grids,
const std::vector<std::vector<size_t>>& grid_instance_ids,
const DeviceRRGSB& L_device_rr_gsb,
const std::vector<std::vector<size_t>>& sb_instance_ids,
const std::vector<std::vector<size_t>>& cbx_instance_ids,
const std::vector<std::vector<size_t>>& cby_instance_ids) {
DeviceCoordinator gsb_range = L_device_rr_gsb.get_gsb_range();
for (size_t ix = 0; ix < gsb_range.get_x(); ++ix) {
for (size_t iy = 0; iy < gsb_range.get_y(); ++iy) {
vtr::Point<size_t> gsb_coordinate(ix, iy);
const RRGSB& rr_gsb = L_device_rr_gsb.get_gsb(ix, iy);
/* Connect the grid pins of the GSB to adjacent grids */
add_top_module_nets_connect_grids_and_sb(module_manager, top_module,
device_size, grids, grid_instance_ids,
rr_gsb, sb_instance_ids);
add_top_module_nets_connect_grids_and_cb(module_manager, top_module,
device_size, grids, grid_instance_ids,
rr_gsb, cbx_instance_ids, cby_instance_ids);
add_top_module_nets_connect_sb_and_cb(module_manager, top_module,
rr_gsb, sb_instance_ids, cbx_instance_ids, cby_instance_ids);
}
}
}
/********************************************************************
@ -235,33 +536,36 @@ void print_verilog_top_module(ModuleManager& module_manager,
/* Add sub modules, which are grid, SB and CBX/CBY modules as instances */
/* Add all the grids across the fabric */
add_top_module_grid_instances(module_manager, top_module, device_size, grids);
std::vector<std::vector<size_t>> grid_instance_ids = add_top_module_grid_instances(module_manager, top_module, device_size, grids);
/* Add all the SBs across the fabric */
add_top_module_switch_block_instances(module_manager, top_module, L_device_rr_gsb, compact_routing_hierarchy);
std::vector<std::vector<size_t>> sb_instance_ids = add_top_module_switch_block_instances(module_manager, top_module, L_device_rr_gsb, compact_routing_hierarchy);
/* Add all the CBX and CBYs across the fabric */
add_top_module_connection_block_instances(module_manager, top_module, L_device_rr_gsb, CHANX, compact_routing_hierarchy);
add_top_module_connection_block_instances(module_manager, top_module, L_device_rr_gsb, CHANY, compact_routing_hierarchy);
std::vector<std::vector<size_t>> cbx_instance_ids = add_top_module_connection_block_instances(module_manager, top_module, L_device_rr_gsb, CHANX, compact_routing_hierarchy);
std::vector<std::vector<size_t>> cby_instance_ids = add_top_module_connection_block_instances(module_manager, top_module, L_device_rr_gsb, CHANY, compact_routing_hierarchy);
/* TODO: Add module nets to connect the sub modules */
add_top_module_nets_connect_grids_and_gsbs(module_manager, top_module,
device_size, grids, grid_instance_ids,
L_device_rr_gsb, sb_instance_ids, cbx_instance_ids, cby_instance_ids);
/* TODO: Add inter-CLB direct connections */
/* TODO: Add global ports to the top-level module */
/* TODO: Add ports to the top-level module */
/* TODO: Add module nets to connect the top-level ports to sub modules */
/* TODO: Add global ports to the pb_module:
/* Add global ports to the pb_module:
* This is a much easier job after adding sub modules (instances),
* we just need to find all the global ports from the child modules and build a list of it
*/
add_module_global_ports_from_child_modules(module_manager, top_module);
/* TODO: Count GPIO ports from the sub-modules under this Verilog module
/* Add GPIO ports from the sub-modules under this Verilog module
* This is a much easier job after adding sub modules (instances),
* we just need to find all the I/O ports from the child modules and build a list of it
*/
add_module_gpio_ports_from_child_modules(module_manager, top_module);
/* TODO: Count shared SRAM ports from the sub-modules under this Verilog module
/* Add shared SRAM ports from the sub-modules under this Verilog module
* This is a much easier job after adding sub modules (instances),
* we just need to find all the I/O ports from the child modules and build a list of it
*/
@ -276,7 +580,7 @@ void print_verilog_top_module(ModuleManager& module_manager,
CircuitModelId sram_model = circuit_lib.model(mem_model->name);
VTR_ASSERT(CircuitModelId::INVALID() != sram_model);
/* TODO: Count SRAM ports from the sub-modules under this Verilog module
/* Add SRAM ports from the sub-modules under this Verilog module
* This is a much easier job after adding sub modules (instances),
* we just need to find all the I/O ports from the child modules and build a list of it
*/