[core] developing tile module builder

This commit is contained in:
tangxifan 2023-07-16 15:18:09 -07:00
parent c8a840f5ad
commit ba4b7e3522
11 changed files with 314 additions and 30 deletions

View File

@ -17,6 +17,33 @@ vtr::Point<size_t> FabricTile::tile_coordinate(
return coords_[tile_id];
}
std::vector<vtr::Point<size_t>> FabricTile::pb_coordinates(
const FabricTileId& tile_id) const {
VTR_ASSERT(valid_tile_id(tile_id));
return pb_coords_[tile_id];
}
std::vector<vtr::Point<size_t>> FabricTile::cb_coordinates(
const FabricTileId& tile_id, const t_rr_type& cb_type) const {
VTR_ASSERT(valid_tile_id(tile_id));
switch (cb_type) {
case CHANX:
return cbx_coords_[tile_id];
case CHANY:
return cby_coords_[tile_id];
default:
VTR_LOG("Invalid type of connection block!\n");
exit(1);
}
return std::vector<vtr::Point<size_t>>();
}
std::vector<vtr::Point<size_t>> FabricTile::sb_coordinates(
const FabricTileId& tile_id) const {
VTR_ASSERT(valid_tile_id(tile_id));
return sb_coords_[tile_id];
}
FabricTileId FabricTile::unique_tile(const vtr::Point<size_t>& coord) const {
/* Return invalid Id when out of range! */
if (coord.x() < tile_coord2unique_tile_ids_.size()) {
@ -45,6 +72,10 @@ FabricTileId FabricTile::find_tile(const vtr::Point<size_t>& coord) const {
return tile_coord2id_lookup_[coord.x()][coord.y()];
}
std::vector<FabricTileId> FabricTile::unique_tiles() const {
return unique_tile_ids_;
}
FabricTileId FabricTile::create_tile(const vtr::Point<size_t>& coord) {
FabricTileId tile_id = FabricTileId(ids_.size());
ids_.push_back(tile_id);
@ -117,19 +148,24 @@ bool FabricTile::set_tile_coordinate(const FabricTileId& tile_id,
void FabricTile::add_pb_coordinate(const FabricTileId& tile_id,
const vtr::Point<size_t>& coord) {
VTR_ASSERT(valid_tile_id(tile_id));
pb_coords_[tile_id] = coord;
pb_coords_[tile_id].push_back(coord);
}
void FabricTile::add_cbx_coordinate(const FabricTileId& tile_id,
const vtr::Point<size_t>& coord) {
void FabricTile::add_cb_coordinate(const FabricTileId& tile_id,
const t_rr_type& cb_type,
const vtr::Point<size_t>& coord) {
VTR_ASSERT(valid_tile_id(tile_id));
cbx_coords_[tile_id].push_back(coord);
}
void FabricTile::add_cby_coordinate(const FabricTileId& tile_id,
const vtr::Point<size_t>& coord) {
VTR_ASSERT(valid_tile_id(tile_id));
cby_coords_[tile_id].push_back(coord);
switch (cb_type) {
case CHANX:
cbx_coords_[tile_id].push_back(coord);
break;
case CHANY:
cby_coords_[tile_id].push_back(coord);
break;
default:
VTR_LOG("Invalid type of connection block!\n");
exit(1);
}
}
void FabricTile::add_sb_coordinate(const FabricTileId& tile_id,
@ -158,17 +194,22 @@ bool FabricTile::equivalent_tile(const FabricTileId& tile_a,
const FabricTileId& tile_b,
const DeviceGrid& grids,
const DeviceRRGSB& device_rr_gsb) const {
/* The pb of two tiles should be the same, otherwise not equivalent */
if (grids.get_physical_type(pb_coords_[tile_a].x(), pb_coords_[tile_a].y()) !=
grids.get_physical_type(pb_coords_[tile_b].x(), pb_coords_[tile_b].y())) {
return false;
}
/* The number of cbx, cby and sb blocks should be the same */
if (cbx_coords_[tile_a].size() != cbx_coords_[tile_b].size() ||
if (pb_coords_[tile_a].size() != pb_coords_[tile_b].size() ||
cbx_coords_[tile_a].size() != cbx_coords_[tile_b].size() ||
cby_coords_[tile_a].size() != cby_coords_[tile_b].size() ||
sb_coords_[tile_a].size() != sb_coords_[tile_b].size()) {
return false;
}
/* The pb of two tiles should be the same, otherwise not equivalent */
for (size_t iblk = 0; iblk < pb_coords_[tile_a].size(); ++iblk) {
if (grids.get_physical_type(pb_coords_[tile_a][iblk].x(),
pb_coords_[tile_a][iblk].y()) !=
grids.get_physical_type(pb_coords_[tile_b][iblk].x(),
pb_coords_[tile_b][iblk].y())) {
return false;
}
}
/* Each CBx should have the same unique modules in the device rr_gsb */
for (size_t iblk = 0; iblk < cbx_coords_[tile_a].size(); ++iblk) {
if (device_rr_gsb.get_cb_unique_module_index(CHANX,

View File

@ -28,11 +28,19 @@ class FabricTile {
public: /* Accessors */
vtr::Point<size_t> tile_coordinate(const FabricTileId& tile_id) const;
std::vector<vtr::Point<size_t>> pb_coordinates(
const FabricTileId& tile_id) const;
std::vector<vtr::Point<size_t>> cb_coordinates(
const FabricTileId& tile_id, const t_rr_type& cb_type) const;
std::vector<vtr::Point<size_t>> sb_coordinates(
const FabricTileId& tile_id) const;
/** @brief With a given coordinate, find the id of the unique tile (which is
* the same as the tile in structure) */
FabricTileId unique_tile(const vtr::Point<size_t>& coord) const;
/** @brief Find the tile info with a given coordinate */
FabricTileId find_tile(const vtr::Point<size_t>& coord) const;
/** @brief Return a list of unique tiles */
std::vector<FabricTileId> unique_tiles() const;
public: /* Mutators */
FabricTileId create_tile(const vtr::Point<size_t>& coord);
@ -40,10 +48,8 @@ class FabricTile {
const vtr::Point<size_t>& coord);
void add_pb_coordinate(const FabricTileId& tile_id,
const vtr::Point<size_t>& coord);
void add_cbx_coordinate(const FabricTileId& tile_id,
const vtr::Point<size_t>& coord);
void add_cby_coordinate(const FabricTileId& tile_id,
const vtr::Point<size_t>& coord);
void add_cb_coordinate(const FabricTileId& tile_id, const t_rr_type& cb_type,
const vtr::Point<size_t>& coord);
void add_sb_coordinate(const FabricTileId& tile_id,
const vtr::Point<size_t>& coord);
/** @brief Build a list of unique tiles by comparing the coordinates in
@ -76,7 +82,7 @@ class FabricTile {
vtr::vector<FabricTileId, FabricTileId> ids_;
vtr::vector<FabricTileId, vtr::Point<size_t>> coords_;
/* Coordinates w.r.t. RRGSB */
vtr::vector<FabricTileId, vtr::Point<size_t>> pb_coords_;
vtr::vector<FabricTileId, std::vector<vtr::Point<size_t>>> pb_coords_;
vtr::vector<FabricTileId, std::vector<vtr::Point<size_t>>> cbx_coords_;
vtr::vector<FabricTileId, std::vector<vtr::Point<size_t>>> cby_coords_;
vtr::vector<FabricTileId, std::vector<vtr::Point<size_t>>> sb_coords_;

View File

@ -497,6 +497,13 @@ std::string generate_switch_block_module_name(
std::string("_"));
}
/*********************************************************************
* Generate the module name for a switch block with a given index
*********************************************************************/
std::string generate_tile_module_name(const size_t& index) {
return std::string("tile_" + std::to_string(index));
}
/*********************************************************************
* Generate the module name for a connection block with a given coordinate
*********************************************************************/

View File

@ -110,6 +110,8 @@ std::string generate_switch_block_module_name(
std::string generate_connection_block_module_name(
const t_rr_type& cb_type, const vtr::Point<size_t>& coordinate);
std::string generate_tile_module_name(const size_t& index);
std::string generate_sb_mux_instance_name(const std::string& prefix,
const e_side& sb_side,
const size_t& track_id,

View File

@ -18,6 +18,7 @@
#include "build_memory_modules.h"
#include "build_mux_modules.h"
#include "build_routing_modules.h"
#include "build_tile_modules.h"
#include "build_top_module.h"
#include "build_wire_modules.h"
#include "command_exit_codes.h"
@ -105,14 +106,17 @@ int build_device_module_graph(
FabricTile fabric_tile(vtr::Point<size_t>(vpr_device_ctx.grid.width(),
vpr_device_ctx.grid.height()));
if (!tile_config.is_valid()) {
/* TODO: Build detailed tile-level information */
/* Build detailed tile-level information */
status = build_fabric_tile(fabric_tile, tile_config, vpr_device_ctx.grid,
openfpga_ctx.device_rr_gsb());
if (CMD_EXEC_FATAL_ERROR == status) {
return status;
}
/* TODO: Build the modules */
// build_tile_modules(module_manager, fabric_tile);
build_tile_modules(module_manager, fabric_tile, vpr_device_ctx.grid,
openfpga_ctx.device_rr_gsb(),
openfpga_ctx.arch().circuit_lib, sram_model,
openfpga_ctx.arch().config_protocol.type(), verbose);
}
/* Build FPGA fabric top-level module */

View File

@ -114,6 +114,7 @@ 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()]);

View File

@ -93,13 +93,11 @@ static int build_fabric_tile_style_top_left(FabricTile& fabric_tile,
continue;
}
const RRGSB& curr_rr_gsb = device_rr_gsb.get_gsb(curr_gsb_coord);
if (curr_rr_gsb.is_cb_exist(CHANX)) {
fabric_tile.add_cbx_coordinate(curr_tile_id,
curr_rr_gsb.get_sb_coordinate());
}
if (curr_rr_gsb.is_cb_exist(CHANY)) {
fabric_tile.add_cby_coordinate(curr_tile_id,
curr_rr_gsb.get_sb_coordinate());
for (t_rr_type cb_type : {CHANX, CHANY}) {
if (curr_rr_gsb.is_cb_exist(cb_type)) {
fabric_tile.add_cb_coordinate(curr_tile_id, cb_type,
curr_rr_gsb.get_sb_coordinate());
}
}
if (curr_rr_gsb.is_sb_exist()) {
fabric_tile.add_sb_coordinate(curr_tile_id,

View File

@ -0,0 +1,166 @@
/********************************************************************
* This file includes functions that are used to build the location
* map information for the top-level module of the FPGA fabric
* It helps OpenFPGA to link the I/O port index in top-level module
* to the VPR I/O mapping results
*******************************************************************/
#include <algorithm>
#include <map>
/* Headers from vtrutil library */
#include "command_exit_codes.h"
#include "vtr_assert.h"
#include "vtr_log.h"
#include "vtr_time.h"
/* Headers from vpr library */
#include "build_tile_modules.h"
#include "module_manager_utils.h"
#include "openfpga_device_grid_utils.h"
#include "openfpga_naming.h"
#include "openfpga_reserved_words.h"
/* begin namespace openfpga */
namespace openfpga {
/********************************************************************
* Build all the tile modules
*******************************************************************/
static int build_tile_module(
ModuleManager& module_manager, const FabricTile& fabric_tile,
const FabricTileId& fabric_tile_id, const DeviceGrid& grids,
const DeviceRRGSB& device_rr_gsb, const CircuitLibrary& circuit_lib,
const CircuitModelId& sram_model,
const e_config_protocol_type& sram_orgz_type, const bool& verbose) {
int status_code = CMD_EXEC_SUCCESS;
/* Create the module */
std::string module_name = generate_tile_module_name(size_t(fabric_tile_id));
VTR_LOGV(verbose, "Building tile module '%s'...\n");
ModuleId tile_module = module_manager.add_module(module_name);
vtr::Point<size_t> tile_coord = fabric_tile.tile_coordinate(fabric_tile_id);
/* Add instance of programmable block */
for (vtr::Point<size_t> grid_gsb_coord :
fabric_tile.pb_coordinates(fabric_tile_id)) {
const RRGSB& grid_rr_gsb = device_rr_gsb.get_gsb(grid_gsb_coord);
vtr::Point<size_t> grid_coord = grid_rr_gsb.get_grid_coordinate();
t_physical_tile_type_ptr phy_tile =
grids.get_physical_type(grid_coord.x(), grid_coord.y());
/* Empty type does not require a module */
if (!is_empty_type(phy_tile)) {
e_side grid_side = find_grid_side_by_coordinate(grids, grid_coord);
std::string pb_module_name = generate_grid_block_module_name(
std::string(GRID_MODULE_NAME_PREFIX), std::string(phy_tile->name),
is_io_type(phy_tile), grid_side);
ModuleId pb_module = module_manager.find_module(pb_module_name);
if (!pb_module) {
VTR_LOG_ERROR(
"Failed to find pb module '%s' required by tile[%lu][%lu]!\n",
pb_module_name.c_str(), tile_coord.x(), tile_coord.y());
}
size_t pb_instance = module_manager.num_instance(tile_module, pb_module);
module_manager.add_child_module(tile_module, pb_module);
if (0 < find_module_num_config_bits(module_manager, pb_module,
circuit_lib, sram_model,
sram_orgz_type)) {
module_manager.add_configurable_child(tile_module, pb_module,
pb_instance);
}
VTR_LOGV(verbose, "Added programmable module '%s' to tile[%lu][%lu]\n",
pb_module_name.c_str(), tile_coord.x(), tile_coord.y());
}
}
/* Add instance of connection blocks */
for (t_rr_type cb_type : {CHANX, CHANY}) {
for (vtr::Point<size_t> cb_coord :
fabric_tile.cb_coordinates(fabric_tile_id, cb_type)) {
/* get the unique module coord */
const RRGSB& unique_rr_gsb =
device_rr_gsb.get_cb_unique_module(cb_type, cb_coord);
vtr::Point<size_t> unique_cb_coord(unique_rr_gsb.get_cb_x(cb_type),
unique_rr_gsb.get_cb_y(cb_type));
std::string cb_module_name =
generate_connection_block_module_name(cb_type, unique_cb_coord);
ModuleId cb_module = module_manager.find_module(cb_module_name);
if (!cb_module) {
VTR_LOG_ERROR(
"Failed to find connection block module '%s' required by "
"tile[%lu][%lu]!\n",
cb_module_name.c_str(), tile_coord.x(), tile_coord.y());
}
size_t cb_instance = module_manager.num_instance(tile_module, cb_module);
module_manager.add_child_module(tile_module, cb_module);
if (0 < find_module_num_config_bits(module_manager, cb_module,
circuit_lib, sram_model,
sram_orgz_type)) {
module_manager.add_configurable_child(tile_module, cb_module,
cb_instance);
}
VTR_LOGV(verbose,
"Added connection block module '%s' to tile[%lu][%lu]\n",
cb_module_name.c_str(), tile_coord.x(), tile_coord.y());
}
}
/* Add instance of switch blocks */
for (vtr::Point<size_t> sb_coord :
fabric_tile.sb_coordinates(fabric_tile_id)) {
/* get the unique module coord */
const RRGSB& unique_rr_gsb = device_rr_gsb.get_sb_unique_module(sb_coord);
vtr::Point<size_t> unique_sb_coord(unique_rr_gsb.get_sb_x(),
unique_rr_gsb.get_sb_y());
std::string sb_module_name =
generate_switch_block_module_name(unique_sb_coord);
ModuleId sb_module = module_manager.find_module(sb_module_name);
if (!sb_module) {
VTR_LOG_ERROR(
"Failed to find switch block module '%s' required by tile[%lu][%lu]!\n",
sb_module_name.c_str(), tile_coord.x(), tile_coord.y());
}
size_t sb_instance = module_manager.num_instance(tile_module, sb_module);
module_manager.add_child_module(tile_module, sb_module);
if (0 < find_module_num_config_bits(module_manager, sb_module, circuit_lib,
sram_model, sram_orgz_type)) {
module_manager.add_configurable_child(tile_module, sb_module,
sb_instance);
}
VTR_LOGV(verbose, "Added switch block module '%s' to tile[%lu][%lu]\n",
sb_module_name.c_str(), tile_coord.x(), tile_coord.y());
}
/* TODO: Add module nets and ports */
VTR_LOGV(verbose, "Done\n");
return status_code;
}
/********************************************************************
* Build all the tile modules
*******************************************************************/
int build_tile_modules(ModuleManager& module_manager,
const FabricTile& fabric_tile, const DeviceGrid& grids,
const DeviceRRGSB& device_rr_gsb,
const CircuitLibrary& circuit_lib,
const CircuitModelId& sram_model,
const e_config_protocol_type& sram_orgz_type,
const bool& verbose) {
vtr::ScopedStartFinishTimer timer("Build tile modules for the FPGA fabric");
int status_code = CMD_EXEC_SUCCESS;
/* Build a module for each unique tile */
for (FabricTileId fabric_tile_id : fabric_tile.unique_tiles()) {
status_code = build_tile_module(module_manager, fabric_tile, fabric_tile_id,
grids, device_rr_gsb, circuit_lib,
sram_model, sram_orgz_type, verbose);
if (status_code != CMD_EXEC_SUCCESS) {
return CMD_EXEC_FATAL_ERROR;
}
}
return status_code;
}
} /* end namespace openfpga */

View File

@ -0,0 +1,34 @@
#ifndef BUILD_TILE_MODULES_H
#define BUILD_TILE_MODULES_H
/********************************************************************
* Include header files that are required by function declaration
*******************************************************************/
#include <string>
#include "circuit_library.h"
#include "config_protocol.h"
#include "device_grid.h"
#include "device_rr_gsb.h"
#include "fabric_tile.h"
#include "module_manager.h"
/********************************************************************
* Function declaration
*******************************************************************/
/* begin namespace openfpga */
namespace openfpga {
int build_tile_modules(ModuleManager& module_manager,
const FabricTile& fabric_tile, const DeviceGrid& grids,
const DeviceRRGSB& device_rr_gsb,
const CircuitLibrary& circuit_lib,
const CircuitModelId& sram_model,
const e_config_protocol_type& sram_orgz_type,
const bool& verbose);
} /* end namespace openfpga */
#endif

View File

@ -13,6 +13,28 @@
/* begin namespace openfpga */
namespace openfpga {
/********************************************************************
* Identify if a grid locates the side of an FPGA fabric
* - If on a side, return the side
* - If not, return an invalid side
*******************************************************************/
e_side find_grid_side_by_coordinate(const DeviceGrid& grids,
const vtr::Point<size_t>& coord) {
if (coord.x() == 0) {
return LEFT;
}
if (coord.y() == 0) {
return BOTTOM;
}
if (coord.x() == grids.width() - 1) {
return RIGHT;
}
if (coord.y() == grids.height() - 1) {
return TOP;
}
return NUM_SIDES;
}
/********************************************************************
* Create a list of the coordinates for the grids on the device perimeter
* It follows a clockwise sequence when including the coordinates.

View File

@ -18,6 +18,9 @@
/* begin namespace openfpga */
namespace openfpga {
e_side find_grid_side_by_coordinate(const DeviceGrid& grids,
const vtr::Point<size_t>& coord);
/* A constant array to walk through FPGA border sides clockwise*/
constexpr std::array<e_side, 4> FPGA_SIDES_CLOCKWISE{TOP, RIGHT, BOTTOM, LEFT};