From 9a441fa5cc10ea39ac9789d94bdebb039f92bb8f Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 9 Jan 2021 18:47:12 -0700 Subject: [PATCH] [Tool] Upgrade openfpga to support extended global tile port definition --- .../src/read_xml_tile_annotation.cpp | 54 +++-- .../libarchopenfpga/src/tile_annotation.cpp | 28 ++- .../libarchopenfpga/src/tile_annotation.h | 20 +- .../src/write_xml_tile_annotation.cpp | 18 +- .../fabric/build_top_module_connection.cpp | 227 ++++++++++++------ .../src/fpga_bitstream/fabric_bitstream.cpp | 3 + openfpga/src/utils/check_tile_annotation.cpp | 204 +++++++++------- 7 files changed, 353 insertions(+), 201 deletions(-) diff --git a/libopenfpga/libarchopenfpga/src/read_xml_tile_annotation.cpp b/libopenfpga/libarchopenfpga/src/read_xml_tile_annotation.cpp index 28d2a6ab8..aa15e1136 100644 --- a/libopenfpga/libarchopenfpga/src/read_xml_tile_annotation.cpp +++ b/libopenfpga/libarchopenfpga/src/read_xml_tile_annotation.cpp @@ -30,25 +30,12 @@ static void read_xml_tile_global_port_annotation(pugi::xml_node& xml_tile, const pugiutil::loc_data& loc_data, openfpga::TileAnnotation& tile_annotation) { - /* We have two mandatory XML attributes - * 1. name of the port - * 2. name of the tile and ports in the format of . + /* We have mandatory XML attributes: + * - name of the port */ const std::string& name_attr = get_attribute(xml_tile, "name", loc_data).as_string(); - const std::string& tile_port_name_attr = get_attribute(xml_tile, "tile_port", loc_data).as_string(); - /* Extract the tile name */ - openfpga::StringToken tokenizer(tile_port_name_attr); - std::vector tile_port_tokens = tokenizer.split('.'); - if (2 != tile_port_tokens.size()) { - archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_tile), - "Invalid tile_port attribute '%s'! Valid format is .\n", - tile_port_name_attr.c_str()); - } - /* Extract the tile port information */ - openfpga::PortParser tile_port_parser(tile_port_tokens[1]); - - TileGlobalPortId tile_global_port_id = tile_annotation.create_global_port(name_attr, tile_port_tokens[0], tile_port_parser.port()); + TileGlobalPortId tile_global_port_id = tile_annotation.create_global_port(name_attr); /* Report any duplicated port names */ if (TileGlobalPortId::INVALID() == tile_global_port_id) { @@ -57,6 +44,39 @@ void read_xml_tile_global_port_annotation(pugi::xml_node& xml_tile, name_attr.c_str()); } + /* Iterate over the children under this node, + * each child should be named after + */ + for (pugi::xml_node xml_tile_port : xml_tile.children()) { + /* Error out if the XML child has an invalid name! */ + if (xml_tile_port.name() != std::string("tile")) { + bad_tag(xml_tile_port, loc_data, xml_tile, {"tile"}); + } + /* Parse the name of the tiles and ports */ + const std::string& tile_name_attr = get_attribute(xml_tile_port, "name", loc_data).as_string(); + const std::string& port_name_attr = get_attribute(xml_tile_port, "port", loc_data).as_string(); + + /* Extract the tile port information */ + openfpga::PortParser tile_port_parser(port_name_attr); + + /* Parse tile coordinates */ + vtr::Point tile_coord(get_attribute(xml_tile_port, "x", loc_data).as_int(-1), + get_attribute(xml_tile_port, "y", loc_data).as_int(-1)); + + /* Add tile port information */ + tile_annotation.add_global_port_tile_information(tile_global_port_id, + tile_name_attr, + tile_port_parser.port(), + tile_coord); + } + + /* Check: Must have at least one global port tile information */ + if (true == tile_annotation.global_port_tile_names(tile_global_port_id).empty()) { + archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_tile), + "Invalid tile annotation for global port '%s'! At least 1 tile port definition is expected!\n", + name_attr.c_str()); + } + /* Get is_clock attributes */ tile_annotation.set_global_port_is_clock(tile_global_port_id, get_attribute(xml_tile, "is_clock", loc_data, pugiutil::ReqOpt::OPTIONAL).as_bool(false)); @@ -81,7 +101,7 @@ void read_xml_tile_global_port_annotation(pugi::xml_node& xml_tile, * Top function to parse XML description about tile annotation *******************************************************************/ openfpga::TileAnnotation read_xml_tile_annotations(pugi::xml_node& Node, - const pugiutil::loc_data& loc_data) { + const pugiutil::loc_data& loc_data) { openfpga::TileAnnotation tile_annotations; /* Parse configuration protocol root node */ diff --git a/libopenfpga/libarchopenfpga/src/tile_annotation.cpp b/libopenfpga/libarchopenfpga/src/tile_annotation.cpp index 5bef68a31..a1268aefa 100644 --- a/libopenfpga/libarchopenfpga/src/tile_annotation.cpp +++ b/libopenfpga/libarchopenfpga/src/tile_annotation.cpp @@ -30,16 +30,21 @@ std::string TileAnnotation::global_port_name(const TileGlobalPortId& global_port return global_port_names_[global_port_id]; } -std::string TileAnnotation::global_port_tile_name(const TileGlobalPortId& global_port_id) const { +std::vector TileAnnotation::global_port_tile_names(const TileGlobalPortId& global_port_id) const { VTR_ASSERT(valid_global_port_id(global_port_id)); return global_port_tile_names_[global_port_id]; } -BasicPort TileAnnotation::global_port_tile_port(const TileGlobalPortId& global_port_id) const { +std::vector TileAnnotation::global_port_tile_ports(const TileGlobalPortId& global_port_id) const { VTR_ASSERT(valid_global_port_id(global_port_id)); return global_port_tile_ports_[global_port_id]; } +std::vector> TileAnnotation::global_port_tile_coordinates(const TileGlobalPortId& global_port_id) const { + VTR_ASSERT(valid_global_port_id(global_port_id)); + return global_port_tile_coordinates_[global_port_id]; +} + bool TileAnnotation::global_port_is_clock(const TileGlobalPortId& global_port_id) const { VTR_ASSERT(valid_global_port_id(global_port_id)); return global_port_is_clock_[global_port_id]; @@ -63,9 +68,7 @@ size_t TileAnnotation::global_port_default_value(const TileGlobalPortId& global_ /************************************************************************ * Public Mutators ***********************************************************************/ -TileGlobalPortId TileAnnotation::create_global_port(const std::string& port_name, - const std::string& tile_name, - const BasicPort& tile_port) { +TileGlobalPortId TileAnnotation::create_global_port(const std::string& port_name) { /* Ensure that the name is unique */ std::map::iterator it = global_port_name2ids_.find(port_name); if (it != global_port_name2ids_.end()) { @@ -76,8 +79,9 @@ TileGlobalPortId TileAnnotation::create_global_port(const std::string& port_name TileGlobalPortId port_id = TileGlobalPortId(global_port_ids_.size()); global_port_ids_.push_back(port_id); global_port_names_.push_back(port_name); - global_port_tile_names_.push_back(tile_name); - global_port_tile_ports_.push_back(tile_port); + global_port_tile_names_.emplace_back(); + global_port_tile_ports_.emplace_back(); + global_port_tile_coordinates_.emplace_back(); global_port_is_clock_.push_back(false); global_port_is_set_.push_back(false); global_port_is_reset_.push_back(false); @@ -89,6 +93,16 @@ TileGlobalPortId TileAnnotation::create_global_port(const std::string& port_name return port_id; } +void TileAnnotation::add_global_port_tile_information(const TileGlobalPortId& global_port_id, + const std::string& tile_name, + const BasicPort& tile_port, + const vtr::Point& tile_coord) { + VTR_ASSERT(valid_global_port_id(global_port_id)); + global_port_tile_names_[global_port_id].push_back(tile_name); + global_port_tile_ports_[global_port_id].push_back(tile_port); + global_port_tile_coordinates_[global_port_id].push_back(tile_coord); +} + void TileAnnotation::set_global_port_is_clock(const TileGlobalPortId& global_port_id, const bool& is_clock) { VTR_ASSERT(valid_global_port_id(global_port_id)); diff --git a/libopenfpga/libarchopenfpga/src/tile_annotation.h b/libopenfpga/libarchopenfpga/src/tile_annotation.h index b87ceb74a..1f863d1ac 100644 --- a/libopenfpga/libarchopenfpga/src/tile_annotation.h +++ b/libopenfpga/libarchopenfpga/src/tile_annotation.h @@ -9,6 +9,7 @@ #include #include "vtr_vector.h" +#include "vtr_geometry.h" #include "openfpga_port.h" @@ -39,8 +40,9 @@ class TileAnnotation { global_port_range global_ports() const; public: /* Public accessors */ std::string global_port_name(const TileGlobalPortId& global_port_id) const; - std::string global_port_tile_name(const TileGlobalPortId& global_port_id) const; - BasicPort global_port_tile_port(const TileGlobalPortId& global_port_id) const; + std::vector global_port_tile_names(const TileGlobalPortId& global_port_id) const; + std::vector global_port_tile_ports(const TileGlobalPortId& global_port_id) const; + std::vector> global_port_tile_coordinates(const TileGlobalPortId& global_port_id) const; bool global_port_is_clock(const TileGlobalPortId& global_port_id) const; bool global_port_is_set(const TileGlobalPortId& global_port_id) const; bool global_port_is_reset(const TileGlobalPortId& global_port_id) const; @@ -49,9 +51,12 @@ class TileAnnotation { /* By default, we do not set it as a clock. * Users should set it through the set_global_port_is_clock() function */ - TileGlobalPortId create_global_port(const std::string& port_name, - const std::string& tile_name, - const BasicPort& tile_port); + TileGlobalPortId create_global_port(const std::string& port_name); + /* Add tile port information */ + void add_global_port_tile_information(const TileGlobalPortId& global_port_id, + const std::string& tile_name, + const BasicPort& tile_port, + const vtr::Point& tile_coord); void set_global_port_is_clock(const TileGlobalPortId& global_port_id, const bool& is_clock); void set_global_port_is_set(const TileGlobalPortId& global_port_id, @@ -70,8 +75,9 @@ class TileAnnotation { /* Global port information for tiles */ vtr::vector global_port_ids_; vtr::vector global_port_names_; - vtr::vector global_port_tile_names_; - vtr::vector global_port_tile_ports_; + vtr::vector> global_port_tile_names_; + vtr::vector>> global_port_tile_coordinates_; + vtr::vector> global_port_tile_ports_; vtr::vector global_port_is_clock_; vtr::vector global_port_is_reset_; vtr::vector global_port_is_set_; diff --git a/libopenfpga/libarchopenfpga/src/write_xml_tile_annotation.cpp b/libopenfpga/libarchopenfpga/src/write_xml_tile_annotation.cpp index a3214d4df..69a568fc5 100644 --- a/libopenfpga/libarchopenfpga/src/write_xml_tile_annotation.cpp +++ b/libopenfpga/libarchopenfpga/src/write_xml_tile_annotation.cpp @@ -51,11 +51,6 @@ void write_xml_tile_annotation_global_port(std::fstream& fp, write_xml_attribute(fp, "name", tile_annotation.global_port_name(global_port_id).c_str()); - std::string tile_port_attr = tile_annotation.global_port_tile_name(global_port_id) - + "." - + generate_tile_port_name(tile_annotation.global_port_tile_port(global_port_id)); - write_xml_attribute(fp, "tile_port", tile_port_attr.c_str()); - write_xml_attribute(fp, "is_clock", tile_annotation.global_port_is_clock(global_port_id)); write_xml_attribute(fp, "is_set", tile_annotation.global_port_is_set(global_port_id)); @@ -64,7 +59,18 @@ void write_xml_tile_annotation_global_port(std::fstream& fp, write_xml_attribute(fp, "default_value", tile_annotation.global_port_default_value(global_port_id)); - fp << "/>" << "\n"; + fp << ">" << "\n"; + + for (size_t tile_info_id = 0; tile_info_id < tile_annotation.global_port_tile_names(global_port_id).size(); ++tile_info_id) { + fp << "\t\t\t" << ""; + } + + fp << "\t\t" << ""; } /******************************************************************** diff --git a/openfpga/src/fabric/build_top_module_connection.cpp b/openfpga/src/fabric/build_top_module_connection.cpp index 8843f5210..103c1a8ff 100644 --- a/openfpga/src/fabric/build_top_module_connection.cpp +++ b/openfpga/src/fabric/build_top_module_connection.cpp @@ -695,27 +695,36 @@ void add_top_module_nets_connect_grids_and_gsbs(ModuleManager& module_manager, * that are defined as global in tile annotation *******************************************************************/ static -void build_top_module_global_net_for_given_grid_module(ModuleManager& module_manager, - const ModuleId& top_module, - const ModulePortId& top_module_port, - const TileAnnotation& tile_annotation, - const TileGlobalPortId& tile_global_port, - const DeviceGrid& grids, - const vtr::Point& grid_coordinate, - const e_side& border_side, - const vtr::Matrix& grid_instance_ids) { +int build_top_module_global_net_for_given_grid_module(ModuleManager& module_manager, + const ModuleId& top_module, + const ModulePortId& top_module_port, + const TileAnnotation& tile_annotation, + const TileGlobalPortId& tile_global_port, + const BasicPort& tile_port_to_connect, + const DeviceGrid& grids, + const vtr::Point& grid_coordinate, + const e_side& border_side, + const vtr::Matrix& grid_instance_ids) { t_physical_tile_type_ptr physical_tile = grids[grid_coordinate.x()][grid_coordinate.y()].type; - /* Ensure physical tile matches the global port definition */ - VTR_ASSERT(std::string(physical_tile->name) == tile_annotation.global_port_tile_name(tile_global_port)); /* Find the port of the grid module according to the tile annotation */ int grid_pin_index = physical_tile->num_pins; for (const t_physical_tile_port& tile_port : physical_tile->ports) { - if (std::string(tile_port.name) == tile_annotation.global_port_tile_port(tile_global_port).get_name()) { + if (std::string(tile_port.name) == tile_port_to_connect.get_name()) { + BasicPort ref_tile_port(tile_port.name, tile_port.num_pins); /* Port size must match!!! */ - VTR_ASSERT(size_t(tile_port.num_pins) == tile_annotation.global_port_tile_port(tile_global_port).get_width()); - /* TODO: Should check there is only port matching!!! */ + if (false == ref_tile_port.contained(tile_port_to_connect)) { + VTR_LOG_ERROR("Tile annotation '%s' port '%s[%lu:%lu]' is out of the range of physical tile port '%s[%lu:%lu]'!", + tile_annotation.global_port_name(tile_global_port).c_str(), + tile_port_to_connect.get_name().c_str(), + tile_port_to_connect.get_lsb(), + tile_port_to_connect.get_msb(), + ref_tile_port.get_name().c_str(), + ref_tile_port.get_lsb(), + ref_tile_port.get_msb()); + return CMD_EXEC_FATAL_ERROR; + } grid_pin_index = tile_port.absolute_first_pin_index; break; } @@ -746,7 +755,19 @@ void build_top_module_global_net_for_given_grid_module(ModuleManager& module_man add_module_bus_nets(module_manager, top_module, top_module, 0, top_module_port, grid_module, grid_instance, grid_port_id); + BasicPort src_port = module_manager.module_port(top_module, top_module_port); + for (size_t pin_id = 0; pin_id < tile_port_to_connect.pins().size(); ++pin_id) { + ModuleNetId net = create_module_source_pin_net(module_manager, top_module, + top_module, 0, + top_module_port, src_port.pins()[pin_id]); + VTR_ASSERT(ModuleNetId::INVALID() != net); + + /* Configure the net sink */ + module_manager.add_module_net_sink(top_module, net, grid_module, grid_instance, grid_port_id, tile_port_to_connect.pins()[pin_id]); + } } + + return CMD_EXEC_SUCCESS; } /******************************************************************** @@ -757,17 +778,23 @@ int add_top_module_global_ports_from_grid_modules(ModuleManager& module_manager, const TileAnnotation& tile_annotation, const DeviceGrid& grids, const vtr::Matrix& grid_instance_ids) { + int status = CMD_EXEC_SUCCESS; - /* Add the global ports which are yet added to the top-level module + /* Add the global ports which are NOT yet added to the top-level module * (in different names than the global ports defined in circuit library */ std::vector global_ports_to_add; for (const TileGlobalPortId& tile_global_port : tile_annotation.global_ports()) { ModulePortId module_port = module_manager.find_module_port(top_module, tile_annotation.global_port_name(tile_global_port)); + /* The global port size is derived from the maximum port size among all the tile port defintion */ if (ModulePortId::INVALID() == module_port) { BasicPort global_port_to_add; global_port_to_add.set_name(tile_annotation.global_port_name(tile_global_port)); - global_port_to_add.set_width(tile_annotation.global_port_tile_port(tile_global_port).get_width()); + size_t max_port_size = 0; + for (const BasicPort& tile_port : tile_annotation.global_port_tile_ports(tile_global_port)) { + max_port_size = std::max(tile_port.get_width(), max_port_size); + } + global_port_to_add.set_width(max_port_size); global_ports_to_add.push_back(global_port_to_add); } } @@ -784,72 +811,130 @@ int add_top_module_global_ports_from_grid_modules(ModuleManager& module_manager, ModulePortId top_module_port = module_manager.find_module_port(top_module, tile_annotation.global_port_name(tile_global_port)); VTR_ASSERT(ModulePortId::INVALID() != top_module_port); - /* Spot the port from child modules from core grids */ - for (size_t ix = 1; ix < grids.width() - 1; ++ix) { - for (size_t iy = 1; iy < grids.height() - 1; ++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; - } + 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; - /* Bypass the tiles whose names do not match */ - if (std::string(grids[ix][iy].type->name) != tile_annotation.global_port_tile_name(tile_global_port)) { - continue; + /* -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()); } - - /* Create nets and finish connection build-up */ - build_top_module_global_net_for_given_grid_module(module_manager, - top_module, - top_module_port, - tile_annotation, - tile_global_port, - grids, - vtr::Point(ix, iy), - NUM_SIDES, - grid_instance_ids); - } - } - /* 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; - } + /* -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, + 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; - } + /* 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_annotation.global_port_tile_name(tile_global_port)) { - continue; - } + /* Bypass the tiles whose names do not match */ + if (std::string(grids[io_coordinate.x()][io_coordinate.y()].type->name) != tile_name) { + continue; + } - /* Create nets and finish connection build-up */ - build_top_module_global_net_for_given_grid_module(module_manager, - top_module, - top_module_port, - tile_annotation, - tile_global_port, - grids, - io_coordinate, - io_side, - grid_instance_ids); + /* 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, + grids, + io_coordinate, + io_side, + grid_instance_ids); + if (CMD_EXEC_FATAL_ERROR == status) { + return status; + } + } } } } - return CMD_EXEC_SUCCESS; + return status; } } /* end namespace openfpga */ diff --git a/openfpga/src/fpga_bitstream/fabric_bitstream.cpp b/openfpga/src/fpga_bitstream/fabric_bitstream.cpp index 6ea5c8168..785327661 100644 --- a/openfpga/src/fpga_bitstream/fabric_bitstream.cpp +++ b/openfpga/src/fpga_bitstream/fabric_bitstream.cpp @@ -21,6 +21,9 @@ FabricBitstream::FabricBitstream() { num_regions_ = 0; invalid_region_ids_.clear(); + + use_address_ = false; + use_wl_address_ = false; } /************************************************** diff --git a/openfpga/src/utils/check_tile_annotation.cpp b/openfpga/src/utils/check_tile_annotation.cpp index 75d1eeaf5..df209644d 100644 --- a/openfpga/src/utils/check_tile_annotation.cpp +++ b/openfpga/src/utils/check_tile_annotation.cpp @@ -102,107 +102,125 @@ int check_tile_annotation_conflicts_with_physical_tile(const TileAnnotation& til int num_err = 0; for (const TileGlobalPortId& tile_global_port : tile_annotation.global_ports()) { - /* Must find a valid physical tile in the same name */ - size_t found_matched_physical_tile = 0; - size_t found_matched_physical_tile_port = 0; - for (const t_physical_tile_type& physical_tile : physical_tile_types) { - if (std::string(physical_tile.name) != tile_annotation.global_port_tile_name(tile_global_port)) { - continue; - } + for (size_t tile_info_id = 0; tile_info_id < tile_annotation.global_port_tile_names(tile_global_port).size(); ++tile_info_id) { + /* Must find a valid physical tile in the same name */ + size_t found_matched_physical_tile = 0; + size_t found_matched_physical_tile_port = 0; - /* Found a match, increment the counter */ - found_matched_physical_tile++; + std::string required_tile_name = tile_annotation.global_port_tile_names(tile_global_port)[tile_info_id]; + BasicPort required_tile_port = tile_annotation.global_port_tile_ports(tile_global_port)[tile_info_id]; - /* Must found a valid port where both port name and port size must match!!! */ - for (const t_physical_tile_port& tile_port : physical_tile.ports) { - if (std::string(tile_port.name) != tile_annotation.global_port_tile_port(tile_global_port).get_name()) { + for (const t_physical_tile_type& physical_tile : physical_tile_types) { + if (std::string(physical_tile.name) != required_tile_name) { continue; } - if (size_t(tile_port.num_pins) != tile_annotation.global_port_tile_port(tile_global_port).get_width()) { - continue; + + /* Found a match, increment the counter */ + found_matched_physical_tile++; + + /* Must found a valid port where both port name and port size must match!!! */ + for (const t_physical_tile_port& tile_port : physical_tile.ports) { + if (std::string(tile_port.name) != required_tile_port.get_name()) { + continue; + } + + BasicPort ref_tile_port(tile_port.name, tile_port.num_pins); + /* Port size must be in range!!! */ + if (false == ref_tile_port.contained(required_tile_port)) { + VTR_LOG_ERROR("Tile annotation port '%s[%lu:%lu]' is out of the range of physical tile port '%s[%lu:%lu]'!", + required_tile_port.get_name().c_str(), + required_tile_port.get_lsb(), + required_tile_port.get_msb(), + ref_tile_port.get_name().c_str(), + ref_tile_port.get_lsb(), + ref_tile_port.get_msb()); + num_err++; + continue; + } + + + /* Check if port property matches */ + int grid_pin_index = tile_port.absolute_first_pin_index; + + if (tile_port.is_clock != tile_annotation.global_port_is_clock(tile_global_port)) { + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Tile port '%s.%s[%ld:%ld]' in tile annotation '%s' does not match physical tile port %s.%s in clock property (one is defined as clock while the other is not)!\n", + required_tile_name.c_str(), + required_tile_port.get_name().c_str(), + required_tile_port.get_lsb(), + required_tile_port.get_msb(), + tile_annotation.global_port_name(tile_global_port).c_str(), + physical_tile.name, tile_port.name); + num_err++; + } + + if ((false == tile_port.is_clock) + && (false == tile_port.is_non_clock_global)) { + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Tile port '%s.%s[%ld:%ld]' in tile annotation '%s' match physical tile port %s.%s but is not defined as a non-clock global port!\n", + required_tile_name.c_str(), + required_tile_port.get_name().c_str(), + required_tile_port.get_lsb(), + required_tile_port.get_msb(), + tile_annotation.global_port_name(tile_global_port).c_str(), + physical_tile.name, tile_port.name); + num_err++; + } + + float pin_Fc = find_physical_tile_pin_Fc(&physical_tile, grid_pin_index); + if (0. != pin_Fc) { + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Tile port '%s.%s[%ld:%ld]' in tile annotation '%s' match physical tile port %s.%s but its Fc is not zero '%g' !\n", + required_tile_name.c_str(), + required_tile_port.get_name().c_str(), + required_tile_port.get_lsb(), + required_tile_port.get_msb(), + tile_annotation.global_port_name(tile_global_port).c_str(), + physical_tile.name, tile_port.name, pin_Fc); + + } + + found_matched_physical_tile_port++; } - - /* Check if port property matches */ - int grid_pin_index = tile_port.absolute_first_pin_index; - - if (tile_port.is_clock != tile_annotation.global_port_is_clock(tile_global_port)) { - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Tile port '%s.%s[%ld:%ld]' in tile annotation '%s' does not match physical tile port %s.%s in clock property (one is defined as clock while the other is not)!\n", - tile_annotation.global_port_tile_name(tile_global_port).c_str(), - tile_annotation.global_port_tile_port(tile_global_port).get_name().c_str(), - tile_annotation.global_port_tile_port(tile_global_port).get_lsb(), - tile_annotation.global_port_tile_port(tile_global_port).get_msb(), - tile_annotation.global_port_name(tile_global_port).c_str(), - physical_tile.name, tile_port.name); - num_err++; - } - - if ((false == tile_port.is_clock) - && (false == tile_port.is_non_clock_global)) { - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Tile port '%s.%s[%ld:%ld]' in tile annotation '%s' match physical tile port %s.%s but is not defined as a non-clock global port!\n", - tile_annotation.global_port_tile_name(tile_global_port).c_str(), - tile_annotation.global_port_tile_port(tile_global_port).get_name().c_str(), - tile_annotation.global_port_tile_port(tile_global_port).get_lsb(), - tile_annotation.global_port_tile_port(tile_global_port).get_msb(), - tile_annotation.global_port_name(tile_global_port).c_str(), - physical_tile.name, tile_port.name); - num_err++; - } - - float pin_Fc = find_physical_tile_pin_Fc(&physical_tile, grid_pin_index); - if (0. != pin_Fc) { - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Tile port '%s.%s[%ld:%ld]' in tile annotation '%s' match physical tile port %s.%s but its Fc is not zero '%g' !\n", - tile_annotation.global_port_tile_name(tile_global_port).c_str(), - tile_annotation.global_port_tile_port(tile_global_port).get_name().c_str(), - tile_annotation.global_port_tile_port(tile_global_port).get_lsb(), - tile_annotation.global_port_tile_port(tile_global_port).get_msb(), - tile_annotation.global_port_name(tile_global_port).c_str(), - physical_tile.name, tile_port.name, pin_Fc); - - } - - found_matched_physical_tile_port++; } - } - /* If we found no match, error out */ - if (0 == found_matched_physical_tile) { - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Tile name '%s' in tile annotation '%s' does not match any physical tile!\n", - tile_annotation.global_port_tile_name(tile_global_port).c_str(), - tile_annotation.global_port_name(tile_global_port).c_str()); - num_err++; - } - if (0 == found_matched_physical_tile_port) { - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Tile port '%s.%s[%ld:%ld]' in tile annotation '%s' does not match any physical tile port!\n", - tile_annotation.global_port_tile_name(tile_global_port).c_str(), - tile_annotation.global_port_tile_port(tile_global_port).get_name().c_str(), - tile_annotation.global_port_tile_port(tile_global_port).get_lsb(), - tile_annotation.global_port_tile_port(tile_global_port).get_msb(), - tile_annotation.global_port_name(tile_global_port).c_str()); - num_err++; - } + /* If we found no match, error out */ + if (0 == found_matched_physical_tile) { + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Tile name '%s' in tile annotation '%s' does not match any physical tile!\n", + required_tile_name.c_str(), + tile_annotation.global_port_name(tile_global_port).c_str()); + num_err++; + } + if (0 == found_matched_physical_tile_port) { + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Tile port '%s.%s[%ld:%ld]' in tile annotation '%s' does not match any physical tile port!\n", + required_tile_name.c_str(), + required_tile_port.get_name().c_str(), + required_tile_port.get_lsb(), + required_tile_port.get_msb(), + tile_annotation.global_port_name(tile_global_port).c_str()); + num_err++; + } - /* If we found more than 1 match, error out */ - if (1 < found_matched_physical_tile) { - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Tile name '%s' in tile annotation '%s' match more than 1 physical tile!\n", - tile_annotation.global_port_tile_name(tile_global_port).c_str(), - tile_annotation.global_port_name(tile_global_port).c_str()); - num_err++; - } - if (1 < found_matched_physical_tile_port) { - VTR_LOGF_ERROR(__FILE__, __LINE__, - "Tile port '%s.%s[%ld:%ld]' in tile annotation '%s' match more than 1physical tile port!\n", - tile_annotation.global_port_tile_name(tile_global_port).c_str(), - tile_annotation.global_port_tile_port(tile_global_port).get_name().c_str(), - tile_annotation.global_port_tile_port(tile_global_port).get_lsb(), - tile_annotation.global_port_tile_port(tile_global_port).get_msb(), - tile_annotation.global_port_name(tile_global_port).c_str()); - num_err++; + /* If we found more than 1 match, error out */ + if (1 < found_matched_physical_tile) { + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Tile name '%s' in tile annotation '%s' match more than 1 physical tile!\n", + required_tile_name.c_str(), + tile_annotation.global_port_name(tile_global_port).c_str()); + num_err++; + } + if (1 < found_matched_physical_tile_port) { + VTR_LOGF_ERROR(__FILE__, __LINE__, + "Tile port '%s.%s[%ld:%ld]' in tile annotation '%s' match more than 1 physical tile port!\n", + required_tile_name.c_str(), + required_tile_port.get_name().c_str(), + required_tile_port.get_lsb(), + required_tile_port.get_msb(), + tile_annotation.global_port_name(tile_global_port).c_str()); + num_err++; + } } }