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;
}