From 3bc959dcec56dec8c484de32ecb7e3fc26cef38b Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 14 Jul 2023 12:13:31 -0700 Subject: [PATCH] [lib] create tile config lib and start integration to core --- libs/CMakeLists.txt | 1 + libs/libtileconfig/CMakeLists.txt | 37 +++++++++ .../example/tile_config_example.xml | 1 + libs/libtileconfig/src/base/tile_config.cpp | 80 +++++++++++++++++++ libs/libtileconfig/src/base/tile_config.h | 60 ++++++++++++++ .../src/io/read_xml_tile_config.cpp | 55 +++++++++++++ .../src/io/read_xml_tile_config.h | 21 +++++ .../src/io/tile_config_xml_constants.h | 8 ++ .../src/io/write_xml_tile_config.cpp | 60 ++++++++++++++ .../src/io/write_xml_tile_config.h | 20 +++++ .../libtileconfig/test/xml_io_tile_config.cpp | 37 +++++++++ openfpga/CMakeLists.txt | 1 + .../src/base/openfpga_build_fabric_template.h | 2 +- 13 files changed, 382 insertions(+), 1 deletion(-) create mode 100644 libs/libtileconfig/CMakeLists.txt create mode 100644 libs/libtileconfig/example/tile_config_example.xml create mode 100644 libs/libtileconfig/src/base/tile_config.cpp create mode 100644 libs/libtileconfig/src/base/tile_config.h create mode 100644 libs/libtileconfig/src/io/read_xml_tile_config.cpp create mode 100644 libs/libtileconfig/src/io/read_xml_tile_config.h create mode 100644 libs/libtileconfig/src/io/tile_config_xml_constants.h create mode 100644 libs/libtileconfig/src/io/write_xml_tile_config.cpp create mode 100644 libs/libtileconfig/src/io/write_xml_tile_config.h create mode 100644 libs/libtileconfig/test/xml_io_tile_config.cpp diff --git a/libs/CMakeLists.txt b/libs/CMakeLists.txt index 9a8c23e43..ab8e6dbd8 100644 --- a/libs/CMakeLists.txt +++ b/libs/CMakeLists.txt @@ -9,3 +9,4 @@ add_subdirectory(libfpgabitstream) add_subdirectory(libpcf) add_subdirectory(libbusgroup) add_subdirectory(libionamemap) +add_subdirectory(libtileconfig) diff --git a/libs/libtileconfig/CMakeLists.txt b/libs/libtileconfig/CMakeLists.txt new file mode 100644 index 000000000..96d2da1d2 --- /dev/null +++ b/libs/libtileconfig/CMakeLists.txt @@ -0,0 +1,37 @@ +cmake_minimum_required(VERSION 3.9) + +project("libtileconfig") + +file(GLOB_RECURSE EXEC_SOURCES test/*.cpp) +file(GLOB_RECURSE LIB_SOURCES src/*/*.cpp) +file(GLOB_RECURSE LIB_HEADERS src/*/*.h) +files_to_dirs(LIB_HEADERS LIB_INCLUDE_DIRS) + +#Remove test executable from library +list(REMOVE_ITEM LIB_SOURCES ${EXEC_SOURCES}) + +#Create the library +add_library(libtileconfig STATIC + ${LIB_HEADERS} + ${LIB_SOURCES}) +target_include_directories(libtileconfig PUBLIC ${LIB_INCLUDE_DIRS}) +set_target_properties(libtileconfig PROPERTIES PREFIX "") #Avoid extra 'lib' prefix + +#Specify link-time dependancies +target_link_libraries(libtileconfig + libarchopenfpga + libopenfpgautil + libopenfpgashell + libvtrutil + libpugiutil) + +#Create the test executable +foreach(testsourcefile ${EXEC_SOURCES}) + # Use a simple string replace, to cut off .cpp. + get_filename_component(testname ${testsourcefile} NAME_WE) + add_executable(${testname} ${testsourcefile}) + # Make sure the library is linked to each test executable + target_link_libraries(${testname} libtileconfig) +endforeach(testsourcefile ${EXEC_SOURCES}) + +install(TARGETS libtileconfig DESTINATION bin) diff --git a/libs/libtileconfig/example/tile_config_example.xml b/libs/libtileconfig/example/tile_config_example.xml new file mode 100644 index 000000000..1a1f3f6e8 --- /dev/null +++ b/libs/libtileconfig/example/tile_config_example.xml @@ -0,0 +1 @@ + diff --git a/libs/libtileconfig/src/base/tile_config.cpp b/libs/libtileconfig/src/base/tile_config.cpp new file mode 100644 index 000000000..35f13a2c7 --- /dev/null +++ b/libs/libtileconfig/src/base/tile_config.cpp @@ -0,0 +1,80 @@ +/****************************************************************************** + * Memember functions for data structure TileConfig + ******************************************************************************/ +#include "tile_config.h" + +#include + +#include "command_exit_codes.h" +#include "vtr_assert.h" +#include "vtr_log.h" +#include "vtr_time.h" + +/* begin namespace openfpga */ +namespace openfpga { + +TileConfig::TileConfig() { + style_ = TileConfig::e_style::NUM_TYPES; /* Deposit an invalid value */ + STYLE_STRING_ = {"top_left", "top_right", "bottom_left", "bottom_right", "custom"}; +} + +/************************************************** + * Public Accessors + *************************************************/ +TileConfig::e_style TileConfig::style() const { + return style_; +} + +std::string TileConfig::style_to_string() const { + return style2str(style_); +} + +bool TileConfig::is_valid() const { + return style_ != TileConfig::e_style::NUM_TYPES; +} + +int TileConfig::set_style(const std::string& value) { + style_ = str2style(value); + return valid_style(style_); +} + +std::string TileConfig::style_all2str() const { + std::string full_types = "["; + for (int itype = size_t(TileConfig::e_style::TOP_LEFT); + itype != size_t(TileConfig::e_style::NUM_TYPES); ++itype) { + full_types += std::string(STYLE_STRING_[itype]) + std::string("|"); + } + full_types.pop_back(); + full_types += "]"; + return full_types; +} + +TileConfig::e_style TileConfig::str2style( + const std::string& style_str, const bool& verbose) const { + for (int itype = size_t(TileConfig::e_style::TOP_LEFT); + itype != size_t(TileConfig::e_style::NUM_TYPES); ++itype) { + if (style_str == std::string(STYLE_STRING_[itype])) { + return static_cast(itype); + } + } + VTR_LOGV_ERROR(verbose, "Invalid style for tile configuration! Expect %s\n", + style_all2str().c_str()); + return TileConfig::e_style::NUM_TYPES; +} + +std::string TileConfig::style2str(const TileConfig::e_style& style, + const bool& verbose) const { + if (!valid_style(style)) { + VTR_LOGV_ERROR(verbose, "Invalid style for tile configuration! Expect %s\n", + style_all2str().c_str()); + return std::string(); + } + return std::string(STYLE_STRING_[size_t(style)]); +} + +bool TileConfig::valid_style( + const TileConfig::e_style& style) const { + return style != TileConfig::e_style::NUM_TYPES; +} + +} /* end namespace openfpga */ diff --git a/libs/libtileconfig/src/base/tile_config.h b/libs/libtileconfig/src/base/tile_config.h new file mode 100644 index 000000000..e4e1f3d40 --- /dev/null +++ b/libs/libtileconfig/src/base/tile_config.h @@ -0,0 +1,60 @@ +#ifndef TILE_CONFIG_H +#define TILE_CONFIG_H + +/******************************************************************** + * Include header files required by the data structure definition + *******************************************************************/ +#include +#include + +/* Begin namespace openfpga */ +namespace openfpga { + +/** + * @brief tile configuration is a data structure to represent how programmable blocks and routing blocks are grouped into tiles + */ +class TileConfig { + public: /* Types */ + enum class e_style { TOP_LEFT = 0, TOP_RIGHT, BOTTOM_LEFT, BOTTOM_RIGHT, CUSTOM, NUM_TYPES }; + public: /* Constructors */ + TileConfig(); + + public: /* Public accessors */ + /** @brief Get all the fpga style */ + e_style style() const; + std::string style_to_string() const; + + public: /* Public mutators */ + /** @brief Create the one-on-one mapping between an port of fpga_top and + * fpga_core. Return 0 for success, return 1 for fail */ + int set_style(const std::string& value); + + public: /* Public utility */ + /** @brief identify if the tile config is valid or not */ + bool is_valid() const; + /** @brief Parse the style from string to valid type. Parser + * error can be turned on */ + e_style str2style(const std::string& style_str, + const bool& verbose = false) const; + /** @brief Output the string representing style */ + std::string style2str(const e_style& style, + const bool& verbose = false) const; + /** @brief Validate the style */ + bool valid_style( + const e_style& style) const; + + private: /* Internal utility */ + /* Generate a string include all the valid style + * Useful for printing debugging messages */ + std::string style_all2str() const; + + private: /* Internal Data */ + e_style style_; + /* Constants */ + std::array + STYLE_STRING_; +}; + +} /* End namespace openfpga*/ + +#endif diff --git a/libs/libtileconfig/src/io/read_xml_tile_config.cpp b/libs/libtileconfig/src/io/read_xml_tile_config.cpp new file mode 100644 index 000000000..4bf093d99 --- /dev/null +++ b/libs/libtileconfig/src/io/read_xml_tile_config.cpp @@ -0,0 +1,55 @@ +/******************************************************************** + * This file includes the top-level function of this library + * which reads an XML of clock network file to the associated + * data structures + *******************************************************************/ +#include + +/* Headers from pugi XML library */ +#include "pugixml.hpp" +#include "pugixml_util.hpp" + +/* Headers from vtr util library */ +#include "vtr_assert.h" +#include "vtr_log.h" +#include "vtr_time.h" + +/* Headers from libarchfpga */ +#include "arch_error.h" +#include "command_exit_codes.h" +#include "tile_config_xml_constants.h" +#include "read_xml_tile_config.h" +#include "read_xml_util.h" + +namespace openfpga { // Begin namespace openfpga + +/******************************************************************** + * Parse XML codes about to an object of ClockNetwork + *******************************************************************/ +int read_xml_tile_config(const char* fname, TileConfig& tile_config) { + vtr::ScopedStartFinishTimer timer("Read tile configuration rules"); + + int status = CMD_EXEC_SUCCESS; + + /* Parse the file */ + pugi::xml_document doc; + pugiutil::loc_data loc_data; + + try { + loc_data = pugiutil::load_xml(doc, fname); + + pugi::xml_node xml_root = + get_single_child(doc, XML_TILE_CONFIG_ROOT_NAME, loc_data); + + std::string style = + get_attribute(xml_root, XML_TILE_CONFIG_ATTRIBUTE_STYLE_NAME, loc_data) + .as_string(); + tile_config.set_style(style); + } catch (pugiutil::XmlError& e) { + archfpga_throw(fname, e.line(), "%s", e.what()); + } + + return status; +} + +} // End of namespace openfpga diff --git a/libs/libtileconfig/src/io/read_xml_tile_config.h b/libs/libtileconfig/src/io/read_xml_tile_config.h new file mode 100644 index 000000000..2c84b5538 --- /dev/null +++ b/libs/libtileconfig/src/io/read_xml_tile_config.h @@ -0,0 +1,21 @@ +#ifndef READ_XML_TILE_CONFIG_H +#define READ_XML_TILE_CONFIG_H + +/******************************************************************** + * Include header files that are required by function declaration + *******************************************************************/ +#include "tile_config.h" +#include "pugixml.hpp" +#include "pugixml_util.hpp" + +/******************************************************************** + * Function declaration + *******************************************************************/ + +namespace openfpga { // Begin namespace openfpga + +int read_xml_tile_config(const char* fname, TileConfig& tile_config); + +} // End of namespace openfpga + +#endif diff --git a/libs/libtileconfig/src/io/tile_config_xml_constants.h b/libs/libtileconfig/src/io/tile_config_xml_constants.h new file mode 100644 index 000000000..583aa8d3c --- /dev/null +++ b/libs/libtileconfig/src/io/tile_config_xml_constants.h @@ -0,0 +1,8 @@ +#ifndef TILE_CONFIG_XML_CONSTANTS_H +#define TILE_CONFIG_XML_CONSTANTS_H + +/* Constants required by XML parser */ +constexpr const char* XML_TILE_CONFIG_ROOT_NAME = "tiles"; +constexpr const char* XML_TILE_CONFIG_ATTRIBUTE_STYLE_NAME = "style"; + +#endif diff --git a/libs/libtileconfig/src/io/write_xml_tile_config.cpp b/libs/libtileconfig/src/io/write_xml_tile_config.cpp new file mode 100644 index 000000000..528f2131b --- /dev/null +++ b/libs/libtileconfig/src/io/write_xml_tile_config.cpp @@ -0,0 +1,60 @@ +/******************************************************************** + * This file includes functions that outputs a clock network object to XML + *format + *******************************************************************/ +/* Headers from system goes first */ +#include +#include + +/* Headers from vtr util library */ +#include "vtr_assert.h" +#include "vtr_log.h" +#include "vtr_time.h" + +/* Headers from arch openfpga library */ +#include "openfpga_digest.h" +#include "write_xml_utils.h" + +/* Headers from pin constraint library */ +#include "tile_config_xml_constants.h" +#include "write_xml_tile_config.h" + +namespace openfpga { // Begin namespace openfpga + +/******************************************************************** + * A writer to output an object to XML format + * + * Return 0 if successful + * Return 1 if there are more serious bugs in the architecture + * Return 2 if fail when creating files + *******************************************************************/ +int write_xml_tile_config(const char* fname, const TileConfig& tile_config) { + vtr::ScopedStartFinishTimer timer("Write tile configuration rules"); + + /* Create a file handler */ + std::fstream fp; + /* Open the file stream */ + fp.open(std::string(fname), std::fstream::out | std::fstream::trunc); + + /* Validate the file stream */ + openfpga::check_file_stream(fname, fp); + + int err_code = 0; + + /* Write the root node */ + fp << "<" << XML_TILE_CONFIG_ROOT_NAME; + + write_xml_attribute(fp, XML_TILE_CONFIG_ATTRIBUTE_STYLE_NAME, + tile_config.style_to_string().c_str()); + /* Finish writing the root node */ + fp << "/>" + << "\n"; + + + /* Close the file stream */ + fp.close(); + + return err_code; +} + +} // End of namespace openfpga diff --git a/libs/libtileconfig/src/io/write_xml_tile_config.h b/libs/libtileconfig/src/io/write_xml_tile_config.h new file mode 100644 index 000000000..f0456db38 --- /dev/null +++ b/libs/libtileconfig/src/io/write_xml_tile_config.h @@ -0,0 +1,20 @@ +#ifndef WRITE_XML_TILE_CONFIG_H +#define WRITE_XML_TILE_CONFIG_H + +/******************************************************************** + * Include header files that are required by function declaration + *******************************************************************/ +#include + +#include "tile_config.h" + +/******************************************************************** + * Function declaration + *******************************************************************/ +namespace openfpga { // Begin namespace openfpga + +int write_xml_tile_config(const char* fname, const TileConfig& tile_config); + +} // End of namespace openfpga + +#endif diff --git a/libs/libtileconfig/test/xml_io_tile_config.cpp b/libs/libtileconfig/test/xml_io_tile_config.cpp new file mode 100644 index 000000000..bd4a15c9d --- /dev/null +++ b/libs/libtileconfig/test/xml_io_tile_config.cpp @@ -0,0 +1,37 @@ +/******************************************************************** + * Unit test functions to validate the correctness of + * 1. parser of data structures + * 2. writer of data structures + *******************************************************************/ +/* Headers from vtrutils */ +#include "vtr_assert.h" +#include "vtr_log.h" + +/* Headers from readarchopenfpga */ +#include "read_xml_tile_config.h" +#include "write_xml_tile_config.h" + +int main(int argc, const char** argv) { + /* Ensure we have only one or two argument */ + VTR_ASSERT((2 == argc) || (3 == argc)); + + int status = 0; + + /* Parse the circuit library from an XML file */ + openfpga::TileConfig tile_config; + status = openfpga::read_xml_tile_config(argv[1], tile_config); + if (status != 0) { + return status; + } + VTR_LOG("Parsed tile configuration from XML file: %s\n", argv[1]); + + /* Output the bus group to an XML file + * This is optional only used when there is a second argument + */ + if (3 <= argc) { + status = openfpga::write_xml_tile_config(argv[2], tile_config); + VTR_LOG("Write the tile configuration to an XML file: %s.\n", argv[2]); + } + + return status; +} diff --git a/openfpga/CMakeLists.txt b/openfpga/CMakeLists.txt index 7c6efe83a..bea2fa94d 100644 --- a/openfpga/CMakeLists.txt +++ b/openfpga/CMakeLists.txt @@ -42,6 +42,7 @@ target_link_libraries(libopenfpga libvtrutil libbusgroup libionamemap + libtileconfig libpugixml libvpr) diff --git a/openfpga/src/base/openfpga_build_fabric_template.h b/openfpga/src/base/openfpga_build_fabric_template.h index dae619276..a8a81adb1 100644 --- a/openfpga/src/base/openfpga_build_fabric_template.h +++ b/openfpga/src/base/openfpga_build_fabric_template.h @@ -138,7 +138,7 @@ int build_fabric_template(T& openfpga_ctx, const Command& cmd, VTR_LOG_ERROR("Group tile is applicable only when compress routing is enabled!\n"); return CMD_EXEC_FATAL_ERROR; } - curr_status = read_xml_tile_config(cmd_context.option_value(cmd, opt_group_file).c_str(), tile_config); + curr_status = read_xml_tile_config(cmd_context.option_value(cmd, opt_group_tile).c_str(), tile_config); if (CMD_EXEC_SUCCESS != curr_status) { return CMD_EXEC_FATAL_ERROR; }