add module nets to connect grids and sbs
This commit is contained in:
parent
4b56b755f2
commit
071757dc52
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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));
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue