[core] fixed the bug on io location map for tiled top module
This commit is contained in:
parent
da36b735c6
commit
812473ef04
|
@ -186,7 +186,7 @@ int build_fabric_template(T& openfpga_ctx, const Command& cmd,
|
||||||
|
|
||||||
/* Build I/O location map */
|
/* Build I/O location map */
|
||||||
openfpga_ctx.mutable_io_location_map() = build_fabric_io_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 */
|
/* Build fabric global port information */
|
||||||
openfpga_ctx.mutable_fabric_global_port_info() =
|
openfpga_ctx.mutable_fabric_global_port_info() =
|
||||||
|
|
|
@ -31,7 +31,7 @@ namespace openfpga {
|
||||||
*io_children() list of top-level module. Here we just build a fast lookup from
|
*io_children() list of top-level module. Here we just build a fast lookup from
|
||||||
*(x, y, z) coordinate to the actual indices
|
*(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) {
|
const DeviceGrid& grids) {
|
||||||
vtr::ScopedStartFinishTimer timer(
|
vtr::ScopedStartFinishTimer timer(
|
||||||
"Create I/O location mapping for top module");
|
"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()) {
|
if (curr_io_index == io_counter.end()) {
|
||||||
io_counter[gpio_port.get_name()] = 0;
|
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(),
|
io_location_map.set_io_index(coord.x(), coord.y(), subchild_coord.x(),
|
||||||
gpio_port.get_name(),
|
gpio_port.get_name(),
|
||||||
io_counter[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;
|
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 */
|
} /* end namespace openfpga */
|
||||||
|
|
|
@ -19,7 +19,8 @@
|
||||||
namespace openfpga {
|
namespace openfpga {
|
||||||
|
|
||||||
IoLocationMap build_fabric_io_location_map(const ModuleManager& module_manager,
|
IoLocationMap build_fabric_io_location_map(const ModuleManager& module_manager,
|
||||||
const DeviceGrid& grids);
|
const DeviceGrid& grids,
|
||||||
|
const bool& tiled_fabric);
|
||||||
|
|
||||||
} /* end namespace openfpga */
|
} /* end namespace openfpga */
|
||||||
|
|
||||||
|
|
|
@ -1071,6 +1071,9 @@ static int build_tile_module(
|
||||||
VTR_LOGV(verbose, "Added programmable module '%s' to tile[%lu][%lu]\n",
|
VTR_LOGV(verbose, "Added programmable module '%s' to tile[%lu][%lu]\n",
|
||||||
pb_module_name.c_str(), tile_coord.x(), tile_coord.y());
|
pb_module_name.c_str(), tile_coord.x(), tile_coord.y());
|
||||||
pb_instances.push_back(pb_instance);
|
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()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue