From 099d9f32f42316ca97f01d340ae852acbc90cb45 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 1 Mar 2023 16:08:15 -0800 Subject: [PATCH] [core] dev --- .../src/base/clock_network.cpp | 8 + .../fabric/build_top_module_connection.cpp | 302 +++++++++++------- 2 files changed, 188 insertions(+), 122 deletions(-) diff --git a/libs/libclkarchopenfpga/src/base/clock_network.cpp b/libs/libclkarchopenfpga/src/base/clock_network.cpp index a8a065ffe..73a53d343 100644 --- a/libs/libclkarchopenfpga/src/base/clock_network.cpp +++ b/libs/libclkarchopenfpga/src/base/clock_network.cpp @@ -331,6 +331,14 @@ std::vector ClockNetwork::tree_flatten_taps( return flatten_taps; } +ClockTreeId ClockNetwork::find_tree(const std::string& name) const { + auto result = tree_name2id_map_.find(name); + if (result == tree_name2id_map_.end()) { + return ClockTreeId::INVALID(); + } + return result->second; +} + ClockSpineId ClockNetwork::find_spine(const std::string& name) const { auto result = spine_name2id_map_.find(name); if (result == spine_name2id_map_.end()) { diff --git a/openfpga/src/fabric/build_top_module_connection.cpp b/openfpga/src/fabric/build_top_module_connection.cpp index 01c3a5a01..b6ba80f2a 100644 --- a/openfpga/src/fabric/build_top_module_connection.cpp +++ b/openfpga/src/fabric/build_top_module_connection.cpp @@ -974,6 +974,175 @@ static int build_top_module_global_net_for_given_grid_module( return CMD_EXEC_SUCCESS; } +/******************************************************************** + * Add nets between a global port and its sinks at each grid modules + *******************************************************************/ +static +int build_top_module_global_net_from_grid_modules( + ModuleManager& module_manager, const ModuleId& top_module, const ModulePortId& top_module_port, + const TileAnnotation& tile_annotation, const TileGlobalPortId& tile_global_port, + const VprDeviceAnnotation& vpr_device_annotation, const DeviceGrid& grids, + const vtr::Matrix& grid_instance_ids) { + int status = CMD_EXEC_SUCCESS; + for (size_t tile_info_id = 0; + tile_info_id < + tile_annotation.global_port_tile_names(tile_global_port).size(); + ++tile_info_id) { + std::string tile_name = + tile_annotation.global_port_tile_names(tile_global_port)[tile_info_id]; + BasicPort tile_port = + tile_annotation.global_port_tile_ports(tile_global_port)[tile_info_id]; + /* Find the coordinates for the wanted tiles */ + vtr::Point start_coord(1, 1); + vtr::Point end_coord(grids.width() - 1, grids.height() - 1); + vtr::Point range = tile_annotation.global_port_tile_coordinates( + tile_global_port)[tile_info_id]; + bool out_of_range = false; + + /* -1 means all the x should be considered */ + if (size_t(-1) != range.x()) { + if ((range.x() < start_coord.x()) || (range.x() > end_coord.x())) { + out_of_range = true; + } else { + /* Set the range */ + start_coord.set_x(range.x()); + end_coord.set_x(range.x()); + } + } + + /* -1 means all the y should be considered */ + if (size_t(-1) != range.y()) { + if ((range.y() < start_coord.y()) || (range.y() > end_coord.y())) { + out_of_range = true; + } else { + /* Set the range */ + start_coord.set_y(range.y()); + end_coord.set_y(range.y()); + } + } + + /* Error out immediately if the coordinate is not valid! */ + if (true == out_of_range) { + VTR_LOG_ERROR( + "Coordinate (%lu, %lu) in tile annotation for tile '%s' is out of " + "range (%lu:%lu, %lu:%lu)!", + range.x(), range.y(), tile_name.c_str(), start_coord.x(), + end_coord.x(), start_coord.y(), end_coord.y()); + return CMD_EXEC_FATAL_ERROR; + } + + /* Spot the port from child modules from core grids */ + for (size_t ix = start_coord.x(); ix < end_coord.x(); ++ix) { + for (size_t iy = start_coord.y(); iy < end_coord.y(); ++iy) { + /* Bypass EMPTY tiles */ + 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; + } + + /* Bypass the tiles whose names do not match */ + if (std::string(grids[ix][iy].type->name) != tile_name) { + continue; + } + + /* Create nets and finish connection build-up */ + status = build_top_module_global_net_for_given_grid_module( + module_manager, top_module, top_module_port, tile_annotation, + tile_global_port, tile_port, vpr_device_annotation, grids, + vtr::Point(ix, iy), NUM_SIDES, grid_instance_ids); + if (CMD_EXEC_FATAL_ERROR == status) { + return status; + } + } + } + + /* Walk through all the grids on the perimeter, which are I/O grids */ + for (const e_side& io_side : FPGA_SIDES_CLOCKWISE) { + for (const vtr::Point& io_coordinate : + io_coordinates[io_side]) { + /* Bypass EMPTY grid */ + if (true == + is_empty_type(grids[io_coordinate.x()][io_coordinate.y()].type)) { + continue; + } + + /* Skip width or height > 1 tiles (mostly heterogeneous blocks) */ + if ((0 < grids[io_coordinate.x()][io_coordinate.y()].width_offset) || + (0 < grids[io_coordinate.x()][io_coordinate.y()].height_offset)) { + continue; + } + + /* Bypass the tiles whose names do not match */ + if (std::string( + grids[io_coordinate.x()][io_coordinate.y()].type->name) != + tile_name) { + continue; + } + + /* Check if the coordinate satisfy the tile coordinate defintion + * - Bypass if the x is a specific number (!= -1), and io_coordinate + * is different + * - Bypass if the y is a specific number (!= -1), and io_coordinate + * is different + */ + if ((size_t(-1) != range.x()) && (range.x() != io_coordinate.x())) { + continue; + } + if ((size_t(-1) != range.y()) && (range.y() != io_coordinate.y())) { + continue; + } + + /* Create nets and finish connection build-up */ + status = build_top_module_global_net_for_given_grid_module( + module_manager, top_module, top_module_port, tile_annotation, + tile_global_port, tile_port, vpr_device_annotation, grids, + io_coordinate, io_side, grid_instance_ids); + if (CMD_EXEC_FATAL_ERROR == status) { + return status; + } + } + } + } + + return status; +} + +/******************************************************************** + * Add nets between a global port and its sinks at an entry point of clock tree + *******************************************************************/ +int build_top_module_global_net_from_clock_arch_tree( + ModuleManager& module_manager, const ModuleId& top_module, const ModulePortId& top_module_port, + const ClockNetwork& clk_ntwk, const std::string& clk_tree_name, const RRClockSpatialLookup& rr_clock_lookup) { + int status = CMD_EXEC_SUCCESS; + + /* Ensure the clock arch tree name is valid */ + ClockTreeId clk_tree = clk_ntwk.find_tree(clk_tree_name); + if (!clk_ntwk.valid_tree_id(clk_tree)) { + VTR_LOG("Fail to find a matched clock tree '%s' in the clock architecture definition", clk_tree_name.c_str()); + return CMD_EXEC_FATAL_ERROR; + } + + /* Ensure the clock tree width matches the global port size */ + if (clk_ntwk.tree_width(clk_tree) != module_manager.module_port(top_module, top_module_port).get_width()) { + VTR_LOG("Clock tree '%s' does not have the same width '%lu' as the port '%'s of FPGA top module", clk_tree_name.c_str(), clk_ntwk.tree_width(clk_tree), module_manager.module_port(top_module, top_module_port).get_name().c_str()); + return CMD_EXEC_FATAL_ERROR; + } + + for (ClockTreePinId pin : clk_ntwk.pins(clk_tree)) { + /* TODO: Find the routing resource node of the entry point */ + + /* TODO: Get the connection block module and instance at the entry point */ + + /* TODO: Add the module net */ + } + + return status; +} + /******************************************************************** * Add global ports from grid ports that are defined as global in tile *annotation @@ -1025,128 +1194,17 @@ int add_top_module_global_ports_from_grid_modules( top_module, tile_annotation.global_port_name(tile_global_port)); VTR_ASSERT(ModulePortId::INVALID() != top_module_port); - for (size_t tile_info_id = 0; - tile_info_id < - tile_annotation.global_port_tile_names(tile_global_port).size(); - ++tile_info_id) { - std::string tile_name = - tile_annotation.global_port_tile_names(tile_global_port)[tile_info_id]; - BasicPort tile_port = - tile_annotation.global_port_tile_ports(tile_global_port)[tile_info_id]; - /* Find the coordinates for the wanted tiles */ - vtr::Point start_coord(1, 1); - vtr::Point end_coord(grids.width() - 1, grids.height() - 1); - vtr::Point range = tile_annotation.global_port_tile_coordinates( - tile_global_port)[tile_info_id]; - bool out_of_range = false; - - /* -1 means all the x should be considered */ - if (size_t(-1) != range.x()) { - if ((range.x() < start_coord.x()) || (range.x() > end_coord.x())) { - out_of_range = true; - } else { - /* Set the range */ - start_coord.set_x(range.x()); - end_coord.set_x(range.x()); - } - } - - /* -1 means all the y should be considered */ - if (size_t(-1) != range.y()) { - if ((range.y() < start_coord.y()) || (range.y() > end_coord.y())) { - out_of_range = true; - } else { - /* Set the range */ - start_coord.set_y(range.y()); - end_coord.set_y(range.y()); - } - } - - /* Error out immediately if the coordinate is not valid! */ - if (true == out_of_range) { - VTR_LOG_ERROR( - "Coordinate (%lu, %lu) in tile annotation for tile '%s' is out of " - "range (%lu:%lu, %lu:%lu)!", - range.x(), range.y(), tile_name.c_str(), start_coord.x(), - end_coord.x(), start_coord.y(), end_coord.y()); - return CMD_EXEC_FATAL_ERROR; - } - - /* Spot the port from child modules from core grids */ - for (size_t ix = start_coord.x(); ix < end_coord.x(); ++ix) { - for (size_t iy = start_coord.y(); iy < end_coord.y(); ++iy) { - /* Bypass EMPTY tiles */ - 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; - } - - /* Bypass the tiles whose names do not match */ - if (std::string(grids[ix][iy].type->name) != tile_name) { - continue; - } - - /* Create nets and finish connection build-up */ - status = build_top_module_global_net_for_given_grid_module( - module_manager, top_module, top_module_port, tile_annotation, - tile_global_port, tile_port, vpr_device_annotation, grids, - vtr::Point(ix, iy), NUM_SIDES, grid_instance_ids); - if (CMD_EXEC_FATAL_ERROR == status) { - return status; - } - } - } - - /* Walk through all the grids on the perimeter, which are I/O grids */ - for (const e_side& io_side : FPGA_SIDES_CLOCKWISE) { - for (const vtr::Point& io_coordinate : - io_coordinates[io_side]) { - /* Bypass EMPTY grid */ - if (true == - is_empty_type(grids[io_coordinate.x()][io_coordinate.y()].type)) { - continue; - } - - /* Skip width or height > 1 tiles (mostly heterogeneous blocks) */ - if ((0 < grids[io_coordinate.x()][io_coordinate.y()].width_offset) || - (0 < grids[io_coordinate.x()][io_coordinate.y()].height_offset)) { - continue; - } - - /* Bypass the tiles whose names do not match */ - if (std::string( - grids[io_coordinate.x()][io_coordinate.y()].type->name) != - tile_name) { - continue; - } - - /* Check if the coordinate satisfy the tile coordinate defintion - * - Bypass if the x is a specific number (!= -1), and io_coordinate - * is different - * - Bypass if the y is a specific number (!= -1), and io_coordinate - * is different - */ - if ((size_t(-1) != range.x()) && (range.x() != io_coordinate.x())) { - continue; - } - if ((size_t(-1) != range.y()) && (range.y() != io_coordinate.y())) { - continue; - } - - /* Create nets and finish connection build-up */ - status = build_top_module_global_net_for_given_grid_module( - module_manager, top_module, top_module_port, tile_annotation, - tile_global_port, tile_port, vpr_device_annotation, grids, - io_coordinate, io_side, grid_instance_ids); - if (CMD_EXEC_FATAL_ERROR == status) { - return status; - } - } - } + /* There are two cases when building the nets: + * - If the net will go through a dedicated clock tree network, the net will drive an input of a routing block + * - If the net will be directly wired to tiles, the net will drive an input of a tile + */ + if (!tile_annotation.global_port_clock_arch_tree_name(tile_global_port).empty()) { + status = build_top_module_global_net_from_clock_arch_tree(module_manager, top_module, top_module_port); + } else { + status = build_top_module_global_net_from_grid_modules(module_manager, top_module, top_module_port, tile_annotation, tile_global_port, vpr_device_annotation, grids, grid_instance_ids); + } + if (status == CMD_EXEC_FATAL_ERROR) { + return status; } }