[core] fixed the bug on io location map for tiled top module

This commit is contained in:
tangxifan 2023-07-24 14:50:39 -07:00
parent da36b735c6
commit 812473ef04
4 changed files with 146 additions and 4 deletions

View File

@ -186,7 +186,7 @@ int build_fabric_template(T& openfpga_ctx, const Command& cmd,
/* Build I/O location map */
openfpga_ctx.mutable_io_location_map() = build_fabric_io_location_map(
openfpga_ctx.module_graph(), g_vpr_ctx.device().grid);
openfpga_ctx.module_graph(), g_vpr_ctx.device().grid, cmd_context.option_enable(cmd, opt_group_tile));
/* Build fabric global port information */
openfpga_ctx.mutable_fabric_global_port_info() =

View File

@ -31,7 +31,7 @@ namespace openfpga {
*io_children() list of top-level module. Here we just build a fast lookup from
*(x, y, z) coordinate to the actual indices
*******************************************************************/
IoLocationMap build_fabric_io_location_map(const ModuleManager& module_manager,
static IoLocationMap build_fabric_fine_grained_io_location_map(const ModuleManager& module_manager,
const DeviceGrid& grids) {
vtr::ScopedStartFinishTimer timer(
"Create I/O location mapping for top module");
@ -114,7 +114,6 @@ IoLocationMap build_fabric_io_location_map(const ModuleManager& module_manager,
if (curr_io_index == io_counter.end()) {
io_counter[gpio_port.get_name()] = 0;
}
/* FIXME: Will cause critical bugs when tile modules are added */
io_location_map.set_io_index(coord.x(), coord.y(), subchild_coord.x(),
gpio_port.get_name(),
io_counter[gpio_port.get_name()]);
@ -145,4 +144,143 @@ IoLocationMap build_fabric_io_location_map(const ModuleManager& module_manager,
return io_location_map;
}
/********************************************************************
* Find all the GPIO ports in the tile modules
* and cache their port/pin index in the top-level module
*
* .. note:: The I/O sequence(indexing) is already determined in the
*io_children() list of top-level module. Here we just build a fast lookup from
*(x, y, z) coordinate to the actual indices
*******************************************************************/
static IoLocationMap build_fabric_tiled_io_location_map(const ModuleManager& module_manager,
const DeviceGrid& grids) {
vtr::ScopedStartFinishTimer timer(
"Create I/O location mapping for top module");
IoLocationMap io_location_map;
std::map<std::string, size_t> io_counter;
std::string top_module_name = generate_fpga_top_module_name();
ModuleId top_module = module_manager.find_module(top_module_name);
VTR_ASSERT(true == module_manager.valid_module_id(top_module));
/* Walk through the I/O child list */
for (size_t ichild = 0;
ichild < module_manager.io_children(top_module).size(); ++ichild) {
ModuleId child = module_manager.io_children(top_module)[ichild];
vtr::Point<int> coord =
module_manager.io_child_coordinates(top_module)[ichild];
t_physical_tile_type_ptr phy_tile_type =
grids.get_physical_type(coord.x(), coord.y());
/* Bypass EMPTY grid */
if (true == is_empty_type(phy_tile_type)) {
continue;
}
/* Skip width or height > 1 tiles (mostly heterogeneous blocks) */
if ((0 < grids.get_width_offset(coord.x(), coord.y())) ||
(0 < grids.get_height_offset(coord.x(), coord.y()))) {
continue;
}
VTR_ASSERT_SAFE(true == module_manager.valid_module_id(child));
/* 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
*/
if (size_t(phy_tile_type->capacity) !=
module_manager.io_children(child).size()) {
VTR_LOG("%s[%ld][%ld] capacity: %d while io_child number is %d",
phy_tile_type->name, coord.x(), coord.y(),
phy_tile_type->capacity,
module_manager.io_children(child).size());
}
VTR_ASSERT(size_t(phy_tile_type->capacity) ==
module_manager.io_children(child).size());
for (ModuleId tile_child : module_manager.io_children(child)) {
/* Note that we should use the subchild of the subchild module when checking the GPIO
* ports. The child module is the tile module while the subchild module is actually the grid-level I/O module, while
* the subchild module is the subtile inside grid-level I/O modules. Note
* that grid-level I/O module contains all the GPIO ports while the
* subtile may have part of it. For example, a grid I/O module may have 24
* GPINs and 12 GPOUTs, while the first subtile only have 4 GPINs, and the
* second subtile only have 3 GPOUTs. Therefore, to accurately build the
* I/O location map downto subtile level, we need to check the subchild
* module here.
*/
for (size_t isubchild = 0;
isubchild < module_manager.io_children(tile_child).size(); ++isubchild) {
ModuleId subchild = module_manager.io_children(tile_child)[isubchild];
vtr::Point<int> subchild_coord =
module_manager.io_child_coordinates(tile_child)[isubchild];
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(subchild,
module_io_port_type)) {
/* Only care mappable I/O */
if (false ==
module_manager.port_is_mappable_io(subchild, gpio_port_id)) {
continue;
}
const BasicPort& gpio_port =
module_manager.module_port(subchild, 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;
}
/* This is a dirty hack! */
io_location_map.set_io_index(coord.x(), coord.y(), subchild_coord.x(),
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 */
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(top_module,
module_io_port_type)) {
/* Only care mappable I/O */
if (false ==
module_manager.port_is_mappable_io(top_module, gpio_port_id)) {
continue;
}
const BasicPort& gpio_port =
module_manager.module_port(top_module, gpio_port_id);
VTR_ASSERT(io_counter[gpio_port.get_name()] == gpio_port.get_width());
}
}
return io_location_map;
}
/********************************************************************
* Top-level function, if tile modules are built under the top-level module
* The data to access for I/O location is different than the fine-grained grid modules
* FIXME: Think about a unified way for the two kinds of fabrics!!!
*******************************************************************/
IoLocationMap build_fabric_io_location_map(const ModuleManager& module_manager,
const DeviceGrid& grids,
const bool& tiled_fabric) {
if (tiled_fabric) {
return build_fabric_tiled_io_location_map(module_manager, grids);
}
return build_fabric_fine_grained_io_location_map(module_manager, grids);
}
} /* end namespace openfpga */

View File

@ -19,7 +19,8 @@
namespace openfpga {
IoLocationMap build_fabric_io_location_map(const ModuleManager& module_manager,
const DeviceGrid& grids);
const DeviceGrid& grids,
const bool& tiled_fabric);
} /* end namespace openfpga */

View File

@ -1071,6 +1071,9 @@ static int build_tile_module(
VTR_LOGV(verbose, "Added programmable module '%s' to tile[%lu][%lu]\n",
pb_module_name.c_str(), tile_coord.x(), tile_coord.y());
pb_instances.push_back(pb_instance);
/* Add a custom I/O child with the grid */
module_manager.add_io_child(tile_module, pb_module, pb_instance,
vtr::Point<int>(grid_coord.x(), grid_coord.y()));
}
}