diff --git a/libs/libarchopenfpga/src/read_xml_tile_annotation.cpp b/libs/libarchopenfpga/src/read_xml_tile_annotation.cpp index 6b27d0017d..d01b81b64f 100644 --- a/libs/libarchopenfpga/src/read_xml_tile_annotation.cpp +++ b/libs/libarchopenfpga/src/read_xml_tile_annotation.cpp @@ -125,6 +125,22 @@ static void read_xml_tile_global_port_annotation( } } +/******************************************************************** + * Parse XML description for an interconnection annotation + * under a XML node + *******************************************************************/ +static void read_xml_tile_merge_port_annotation( + pugi::xml_node& xml_tile, const pugiutil::loc_data& loc_data, + openfpga::TileAnnotation& tile_annotation) { + const std::string& tile_attr = + get_attribute(xml_tile, "tile", loc_data).as_string(); + + const std::string& port_attr = + get_attribute(xml_tile, "port", loc_data).as_string(); + + tile_annotation.add_merge_subtile_ports(tile_attr, port_attr); +} + /******************************************************************** * Top function to parse XML description about tile annotation *******************************************************************/ @@ -146,11 +162,15 @@ openfpga::TileAnnotation read_xml_tile_annotations( */ for (pugi::xml_node xml_tile_global_port : xml_annotations.children()) { /* Error out if the XML child has an invalid name! */ - if (xml_tile_global_port.name() != std::string("global_port")) { - bad_tag(xml_tile_global_port, loc_data, xml_annotations, {"global_port"}); + if (xml_tile_global_port.name() == std::string("global_port")) { + read_xml_tile_global_port_annotation(xml_tile_global_port, loc_data, + tile_annotations); + } else if (xml_tile_global_port.name() == std::string("merge_subtile_ports")) { + read_xml_tile_merge_port_annotation(xml_tile_global_port, loc_data, + tile_annotations); + } else { + bad_tag(xml_tile_global_port, loc_data, xml_annotations, {"global_port or merge_subtile_ports"}); } - read_xml_tile_global_port_annotation(xml_tile_global_port, loc_data, - tile_annotations); } return tile_annotations; diff --git a/libs/libarchopenfpga/src/tile_annotation.cpp b/libs/libarchopenfpga/src/tile_annotation.cpp index 7cf41f02e1..d9ac5c0f56 100644 --- a/libs/libarchopenfpga/src/tile_annotation.cpp +++ b/libs/libarchopenfpga/src/tile_annotation.cpp @@ -2,8 +2,11 @@ * Member functions for class TileAnnotation ***********************************************************************/ #include "tile_annotation.h" +#include "command_exit_codes.h" +#include #include "vtr_assert.h" +#include "vtr_log.h" /* namespace openfpga begins */ namespace openfpga { @@ -20,6 +23,24 @@ TileAnnotation::global_port_range TileAnnotation::global_ports() const { return vtr::make_range(global_port_ids_.begin(), global_port_ids_.end()); } +std::vector tiles_to_merge_ports() const { + std::vector tile_names; + for (auto it = tile_ports_to_merge_.begin(); it != tile_ports_to_merge_.end(); it++) { + tile_names.push_back(it->first); + } + return tile_names; +} + +std::vector tile_ports_to_merge(const std::string& tile_name) const { + std::vector port_names; + const auto& result = tile_ports_to_merge_.find(tile_name); + if (result == tile_ports_to_merge.end()) { + VTR_LOG_WARN("Tile '%s' does not contain any ports to merge!\n", tile_name.c_str()); + return port_names; + } + return result.second; +} + /************************************************************************ * Public Accessors ***********************************************************************/ @@ -178,4 +199,21 @@ bool TileAnnotation::valid_global_port_attributes( return ((0 == attribute_counter) || (1 == attribute_counter)); } +int TileAnnotation::add_merge_subtile_ports(const std::string& tile_name, const std::string& port_name) { + auto result = tile_ports_to_merge_.find(tile_name); + if (result == tile_ports_to_merge_.end()) { + /* Empty list: add a new element */ + tile_ports_to_merge_[tile_name].push_back(port_name); + } else { + /* Check if the port name is already in the list, if yes, error out */ + if (result->second.end() == std::find(result->secnd.begin(), result->second.end(), port_name)) { + tile_ports_to_merge_[tile_name].push_back(port_name); + } else { + VTR_LOG_ERROR("Port '%s' has already been defined twice for tile '%s' to be merged!", port_name.c_str(), tile_name.c_str()); + return CMD_EXEC_FATAL_ERROR; + } + } + return CMD_EXEC_SUCCESS; +} + } // namespace openfpga diff --git a/libs/libarchopenfpga/src/tile_annotation.h b/libs/libarchopenfpga/src/tile_annotation.h index ddf9511090..de5a40a082 100644 --- a/libs/libarchopenfpga/src/tile_annotation.h +++ b/libs/libarchopenfpga/src/tile_annotation.h @@ -39,6 +39,8 @@ class TileAnnotation { public: /* Public accessors: aggregators */ global_port_range global_ports() const; + std::vector tiles_to_merge_ports() const; + std::vector tile_ports_to_merge(const std::string& tile_name) const; public: /* Public accessors */ std::string global_port_name(const TileGlobalPortId& global_port_id) const; @@ -77,6 +79,8 @@ class TileAnnotation { void set_global_port_default_value(const TileGlobalPortId& global_port_id, const size_t& default_value); + int add_merge_subtile_ports(const std::string& tile_name, const std::string& port_name); + public: /* Public validator */ bool valid_global_port_id(const TileGlobalPortId& global_port_id) const; /* Validate attributes of a given global port @@ -102,6 +106,9 @@ class TileAnnotation { /* A fast lookup for port names */ std::map global_port_name2ids_; + + /* Merge port information for tiles */ + std::map> tile_ports_to_merge_; // tile_name -> port_name }; } // namespace openfpga diff --git a/libs/libarchopenfpga/src/write_xml_tile_annotation.cpp b/libs/libarchopenfpga/src/write_xml_tile_annotation.cpp index af6bab25a5..5bccbc2c69 100644 --- a/libs/libarchopenfpga/src/write_xml_tile_annotation.cpp +++ b/libs/libarchopenfpga/src/write_xml_tile_annotation.cpp @@ -87,6 +87,25 @@ static void write_xml_tile_annotation_global_port( << ""; } +/******************************************************************** + * A writer to output a device variation in a technology library to XML format + *******************************************************************/ +static void write_xml_tile_annotation_subtile_port_to_merge( + std::fstream& fp, const char* fname, + const std::string& tile_name, + const std::string& port_name) { + /* Validate the file stream */ + openfpga::check_file_stream(fname, fp); + + fp << "\t\t" + << ""; +} + /******************************************************************** * A writer to output tile annotations to XML format *******************************************************************/ @@ -109,6 +128,11 @@ void write_xml_tile_annotations(std::fstream& fp, const char* fname, write_xml_tile_annotation_global_port(fp, fname, tile_annotation, global_port_id); } + for (std::string tile_name : tile_annotation.tiles_to_merge_ports()) { + for (std::string port_name : tile_annotation.tile_ports_to_merge(tile_name)) { + write_xml_tile_annotation_subtile_port_to_merge(fp, fname, tile_name, port_name); + } + } /* Write the root node for pb_type annotations */ fp << "\t"