[Tool] Adapted tools to support I/O in center grid
This commit is contained in:
parent
6001da3a40
commit
5be9e9b736
|
@ -1003,7 +1003,7 @@ std::string generate_grid_block_netlist_name(const std::string& block_name,
|
|||
/* Add the name of physical block */
|
||||
std::string module_name(block_name);
|
||||
|
||||
if (true == is_block_io) {
|
||||
if ((true == is_block_io) && (NUM_SIDES != io_side)) {
|
||||
SideManager side_manager(io_side);
|
||||
module_name += std::string("_");
|
||||
module_name += std::string(side_manager.to_string());
|
||||
|
|
|
@ -99,6 +99,65 @@ IoLocationMap build_fabric_io_location_map(const ModuleManager& module_manager,
|
|||
}
|
||||
}
|
||||
|
||||
/* Walk through all the center grids, which may include I/O grids */
|
||||
for (size_t ix = 1; ix < grids.width() - 1; ++ix) {
|
||||
for (size_t iy = 1; iy < grids.height() - 1; ++iy) {
|
||||
/* Bypass EMPTY grid */
|
||||
if (true == is_empty_type(grids[ix][iy].type)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Skip width or height > 1 tiles (mostly heterogeneous blocks) */
|
||||
if ( (0 < grids[ix][iy].width_offset)
|
||||
|| (0 < grids[ix][iy].height_offset)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
t_physical_tile_type_ptr grid_type = grids[ix][iy].type;
|
||||
|
||||
/* Find the module name for this type of grid */
|
||||
std::string grid_module_name_prefix(GRID_MODULE_NAME_PREFIX);
|
||||
std::string grid_module_name = generate_grid_block_module_name(grid_module_name_prefix, std::string(grid_type->name), is_io_type(grid_type), NUM_SIDES);
|
||||
ModuleId grid_module = module_manager.find_module(grid_module_name);
|
||||
VTR_ASSERT(true == module_manager.valid_module_id(grid_module));
|
||||
|
||||
/* Find all the GPIO ports in the grid module */
|
||||
|
||||
/* MUST DO: register in io location mapping!
|
||||
* I/O location mapping is a critical look-up for testbench generators
|
||||
* As we add the I/O grid instances to top module by following order:
|
||||
* TOP -> RIGHT -> BOTTOM -> LEFT
|
||||
* The I/O index will increase in this way as well.
|
||||
* This organization I/O indices is also consistent to the way
|
||||
* that GPIOs are wired in function connect_gpio_module()
|
||||
*
|
||||
* Note: if you change the GPIO function, you should update here as well!
|
||||
*/
|
||||
for (int z = 0; z < grids[ix][iy].type->capacity; ++z) {
|
||||
for (const ModuleManager::e_module_port_type& module_io_port_type : MODULE_IO_PORT_TYPES) {
|
||||
for (const ModulePortId& gpio_port_id : module_manager.module_port_ids_by_type(grid_module, module_io_port_type)) {
|
||||
/* Only care mappable I/O */
|
||||
if (false == module_manager.port_is_mappable_io(grid_module, gpio_port_id)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const BasicPort& gpio_port = module_manager.module_port(grid_module, gpio_port_id);
|
||||
|
||||
auto curr_io_index = io_counter.find(gpio_port.get_name());
|
||||
/* Index always start from zero */
|
||||
if (curr_io_index == io_counter.end()) {
|
||||
io_counter[gpio_port.get_name()] = 0;
|
||||
}
|
||||
io_location_map.set_io_index(ix, iy, z,
|
||||
gpio_port.get_name(),
|
||||
io_counter[gpio_port.get_name()]);
|
||||
io_counter[gpio_port.get_name()]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Check all the GPIO ports in the top-level module has been mapped */
|
||||
std::string top_module_name = generate_fpga_top_module_name();
|
||||
ModuleId top_module = module_manager.find_module(top_module_name);
|
||||
|
|
|
@ -66,7 +66,7 @@ void add_grid_module_duplicated_pb_type_ports(ModuleManager& module_manager,
|
|||
* Otherwise, we will iterate all the 4 sides
|
||||
*/
|
||||
if (true == is_io_type(grid_type_descriptor)) {
|
||||
grid_pin_sides.push_back(find_grid_module_pin_side(grid_type_descriptor, border_side));
|
||||
grid_pin_sides = find_grid_module_pin_sides(grid_type_descriptor, border_side);
|
||||
} else {
|
||||
grid_pin_sides = {TOP, RIGHT, BOTTOM, LEFT};
|
||||
}
|
||||
|
@ -147,12 +147,9 @@ void add_grid_module_net_connect_duplicated_pb_graph_pin(ModuleManager& module_m
|
|||
* Otherwise, we will iterate all the 4 sides
|
||||
*/
|
||||
if (true == is_io_type(grid_type_descriptor)) {
|
||||
grid_pin_sides.push_back(find_grid_module_pin_side(grid_type_descriptor, border_side));
|
||||
grid_pin_sides = find_grid_module_pin_sides(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};
|
||||
}
|
||||
|
||||
/* num_pins/capacity = the number of pins that each type_descriptor has.
|
||||
|
|
|
@ -23,13 +23,19 @@ namespace openfpga {
|
|||
* 2. I/O grids on the right side of FPGA only have ports on its left side
|
||||
* 3. I/O grids on the bottom side of FPGA only have ports on its top side
|
||||
* 4. I/O grids on the left side of FPGA only have ports on its right side
|
||||
* 5. I/O grids in the center part of FPGA can have ports on any side
|
||||
*******************************************************************/
|
||||
e_side find_grid_module_pin_side(t_physical_tile_type_ptr grid_type_descriptor,
|
||||
std::vector<e_side> find_grid_module_pin_sides(t_physical_tile_type_ptr grid_type_descriptor,
|
||||
const e_side& border_side) {
|
||||
/* We must have an regular (non-I/O) type here */
|
||||
VTR_ASSERT(true == is_io_type(grid_type_descriptor));
|
||||
SideManager side_manager(border_side);
|
||||
return side_manager.get_opposite();
|
||||
|
||||
if (NUM_SIDES == border_side) {
|
||||
return {TOP, RIGHT, BOTTOM, LEFT};
|
||||
}
|
||||
|
||||
return std::vector<e_side>(1, side_manager.get_opposite());
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
|
@ -50,12 +56,9 @@ void add_grid_module_net_connect_pb_graph_pin(ModuleManager& module_manager,
|
|||
* Otherwise, we will iterate all the 4 sides
|
||||
*/
|
||||
if (true == is_io_type(grid_type_descriptor)) {
|
||||
grid_pin_sides.push_back(find_grid_module_pin_side(grid_type_descriptor, border_side));
|
||||
grid_pin_sides = find_grid_module_pin_sides(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};
|
||||
}
|
||||
|
||||
/* num_pins/capacity = the number of pins that each type_descriptor has.
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
/* begin namespace openfpga */
|
||||
namespace openfpga {
|
||||
|
||||
e_side find_grid_module_pin_side(t_physical_tile_type_ptr grid_type_descriptor,
|
||||
std::vector<e_side> find_grid_module_pin_sides(t_physical_tile_type_ptr grid_type_descriptor,
|
||||
const e_side& border_side);
|
||||
|
||||
void add_grid_module_net_connect_pb_graph_pin(ModuleManager& module_manager,
|
||||
|
|
|
@ -52,7 +52,7 @@ void add_grid_module_pb_type_ports(ModuleManager& module_manager,
|
|||
* Otherwise, we will iterate all the 4 sides
|
||||
*/
|
||||
if (true == is_io_type(grid_type_descriptor)) {
|
||||
grid_pin_sides.push_back(find_grid_module_pin_side(grid_type_descriptor, border_side));
|
||||
grid_pin_sides = find_grid_module_pin_sides(grid_type_descriptor, border_side);
|
||||
} else {
|
||||
grid_pin_sides = {TOP, RIGHT, BOTTOM, LEFT};
|
||||
}
|
||||
|
@ -981,11 +981,6 @@ void build_physical_tile_module(ModuleManager& module_manager,
|
|||
const e_side& border_side,
|
||||
const bool& duplicate_grid_pin,
|
||||
const bool& verbose) {
|
||||
/* Check code: if this is an IO block, the border side MUST be valid */
|
||||
if (true == is_io_type(phy_block_type)) {
|
||||
VTR_ASSERT(NUM_SIDES != border_side);
|
||||
}
|
||||
|
||||
/* Create a 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_MODULE_NAME_PREFIX),
|
||||
std::string(phy_block_type->name),
|
||||
|
|
|
@ -120,8 +120,6 @@ vtr::Matrix<size_t> add_top_module_grid_instances(ModuleManager& module_manager,
|
|||
grid_instance_ids[ix][iy] = grid_instance_ids[root_grid_coord.x()][root_grid_coord.y()];
|
||||
continue;
|
||||
}
|
||||
/* We should not meet any I/O grid */
|
||||
VTR_ASSERT(false == is_io_type(grids[ix][iy].type));
|
||||
/* Add a grid module to top_module*/
|
||||
vtr::Point<size_t> grid_coord(ix, iy);
|
||||
grid_instance_ids[ix][iy] = add_top_module_grid_instance(module_manager, top_module,
|
||||
|
|
|
@ -710,8 +710,6 @@ void build_grid_bitstream(BitstreamManager& bitstream_manager,
|
|||
|| (0 < grids[ix][iy].height_offset) ) {
|
||||
continue;
|
||||
}
|
||||
/* We should not meet any I/O grid */
|
||||
VTR_ASSERT(true != is_io_type(grids[ix][iy].type));
|
||||
/* Add a grid module to top_module*/
|
||||
vtr::Point<size_t> grid_coord(ix, iy);
|
||||
build_physical_block_bitstream(bitstream_manager, top_block, module_manager,
|
||||
|
|
|
@ -463,6 +463,11 @@ void build_connection_block_bitstreams(BitstreamManager& bitstream_manager,
|
|||
ModuleId cb_module = module_manager.find_module(cb_module_name);
|
||||
VTR_ASSERT(true == module_manager.valid_module_id(cb_module));
|
||||
|
||||
/* Bypass empty blocks which have none configurable children */
|
||||
if (0 == count_module_manager_module_configurable_children(module_manager, cb_module)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Create a block for the bitstream which corresponds to the Switch block */
|
||||
ConfigBlockId cb_configurable_block = bitstream_manager.add_block(generate_connection_block_module_name(cb_type, cb_coord));
|
||||
/* Set switch block as a child of top block */
|
||||
|
@ -530,6 +535,11 @@ void build_routing_bitstream(BitstreamManager& bitstream_manager,
|
|||
ModuleId sb_module = module_manager.find_module(sb_module_name);
|
||||
VTR_ASSERT(true == module_manager.valid_module_id(sb_module));
|
||||
|
||||
/* Bypass empty blocks which have none configurable children */
|
||||
if (0 == count_module_manager_module_configurable_children(module_manager, sb_module)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Create a block for the bitstream which corresponds to the Switch block */
|
||||
ConfigBlockId sb_configurable_block = bitstream_manager.add_block(generate_switch_block_module_name(sb_coord));
|
||||
/* Set switch block as a child of top block */
|
||||
|
|
|
@ -618,9 +618,6 @@ void print_analysis_sdc_disable_unused_grids(std::fstream& fp,
|
|||
/* Process unused core grids */
|
||||
for (size_t ix = 1; ix < grids.width() - 1; ++ix) {
|
||||
for (size_t iy = 1; iy < grids.height() - 1; ++iy) {
|
||||
/* We should not meet any I/O grid */
|
||||
VTR_ASSERT(false == is_io_type(grids[ix][iy].type));
|
||||
|
||||
print_analysis_sdc_disable_unused_grid(fp, vtr::Point<size_t>(ix, iy),
|
||||
grids, device_annotation, cluster_annotation, place_annotation,
|
||||
module_manager, NUM_SIDES);
|
||||
|
|
|
@ -286,11 +286,6 @@ void print_verilog_physical_tile_netlist(NetlistManager& netlist_manager,
|
|||
t_physical_tile_type_ptr phy_block_type,
|
||||
const e_side& border_side,
|
||||
const bool& use_explicit_mapping) {
|
||||
/* Check code: if this is an IO block, the border side MUST be valid */
|
||||
if (true == is_io_type(phy_block_type)) {
|
||||
VTR_ASSERT(NUM_SIDES != border_side);
|
||||
}
|
||||
|
||||
/* Give a name to the Verilog netlist */
|
||||
/* Create the file name for Verilog */
|
||||
std::string verilog_fname(subckt_dir
|
||||
|
|
Loading…
Reference in New Issue