diff --git a/docs/source/manual/file_formats/bus_group_file.rst b/docs/source/manual/file_formats/bus_group_file.rst
new file mode 100644
index 000000000..bf14fec4e
--- /dev/null
+++ b/docs/source/manual/file_formats/bus_group_file.rst
@@ -0,0 +1,40 @@
+.. _file_format_bus_group_file:
+
+Bus Group File (.xml)
+=====================
+
+The bus group file aims to show
+
+- How bus ports are flatten by EDA engines, e.g., synthesis.
+- What are the pins in post-routing corresponding to the bus ports before synthesis
+
+An example of file is shown as follows.
+
+.. code-block:: xml
+
+
+
+
+
+
+
+
+
+
+Bus-related Syntax
+------------------
+
+.. option:: name=""
+
+ The bus port defined before synthesis, e.g., addr[0:3]
+
+Pin-related Syntax
+------------------
+
+.. option:: id=""
+
+ The index of the current pin in a bus port. The index must be the range of **[LSB, MSB-1]** that are defined in the bus.
+
+.. option:: name=""
+
+ The pin name after bus flatten in synthesis results
diff --git a/docs/source/manual/file_formats/index.rst b/docs/source/manual/file_formats/index.rst
index 7ed213012..c00f46b6b 100644
--- a/docs/source/manual/file_formats/index.rst
+++ b/docs/source/manual/file_formats/index.rst
@@ -25,3 +25,5 @@ OpenFPGA widely uses XML format for interchangable files
io_mapping_file
bitstream_distribution_file
+
+ bus_group_file
diff --git a/docs/source/manual/openfpga_shell/openfpga_commands/fpga_verilog_commands.rst b/docs/source/manual/openfpga_shell/openfpga_commands/fpga_verilog_commands.rst
index 9f39f8250..6a872a1d1 100644
--- a/docs/source/manual/openfpga_shell/openfpga_commands/fpga_verilog_commands.rst
+++ b/docs/source/manual/openfpga_shell/openfpga_commands/fpga_verilog_commands.rst
@@ -68,6 +68,11 @@ write_full_testbench
Specify the *Pin Constraints File* (PCF) if you want to custom stimulus in testbenches. For example, ``-pin_constraints_file pin_constraints.xml``
Strongly recommend for multi-clock simulations. See detailed file format about :ref:`file_format_pin_constraints_file`.
+ .. option:: --bus_group_file or -bgf
+
+ Specify the *Bus Group File* (BGF) if you want to group pins to buses. For example, ``-bgf bus_group.xml``
+ Strongly recommend when input HDL contains bus ports. See detailed file format about :ref:`file_format_bus_group_file`.
+
.. option:: --fast_configuration
Enable fast configuration phase for the top-level testbench in order to reduce runtime of simulations. It is applicable to configuration chain, memory bank and frame-based configuration protocols. For configuration chain, when enabled, the zeros at the head of the bitstream will be skipped. For memory bank and frame-based, when enabled, all the zero configuration bits will be skipped. So ensure that your memory cells can be correctly reset to zero with a reset signal.
@@ -120,6 +125,11 @@ write_preconfigured_fabric_wrapper
Specify the *Pin Constraints File* (PCF) if you want to custom stimulus in testbenches. For example, ``-pin_constraints_file pin_constraints.xml``
Strongly recommend for multi-clock simulations. See detailed file format about :ref:`file_format_pin_constraints_file`.
+ .. option:: --bus_group_file or -bgf
+
+ Specify the *Bus Group File* (BGF) if you want to group pins to buses. For example, ``-bgf bus_group.xml``
+ Strongly recommend when input HDL contains bus ports. See detailed file format about :ref:`file_format_bus_group_file`.
+
.. option:: --explicit_port_mapping
Use explicit port mapping when writing the Verilog netlists
@@ -180,6 +190,11 @@ write_preconfigured_testbench
Specify the *Pin Constraints File* (PCF) if you want to custom stimulus in testbenches. For example, ``-pin_constraints_file pin_constraints.xml``
Strongly recommend for multi-clock simulations. See detailed file format about :ref:`file_format_pin_constraints_file`.
+ .. option:: --bus_group_file or -bgf
+
+ Specify the *Bus Group File* (BGF) if you want to group pins to buses. For example, ``-bgf bus_group.xml``
+ Strongly recommend when input HDL contains bus ports. See detailed file format about :ref:`file_format_bus_group_file`.
+
.. option:: --explicit_port_mapping
Use explicit port mapping when writing the Verilog netlists
diff --git a/docs/source/tutorials/getting_started/tools.rst b/docs/source/tutorials/getting_started/tools.rst
index 7f1b7f850..ebff3c77c 100644
--- a/docs/source/tutorials/getting_started/tools.rst
+++ b/docs/source/tutorials/getting_started/tools.rst
@@ -11,7 +11,7 @@ To enable various design purposes, OpenFPGA integrates several tools to i.e., FP
.. _fig_openfpga_tools:
.. figure:: figures/openfpga_tools.svg
- :scale: 25%
+ :width: 100%
:alt: map to buried treasure
OpenFPGA tool suites and design flows
diff --git a/libopenfpga/CMakeLists.txt b/libopenfpga/CMakeLists.txt
index 62dc6d596..36bce10b6 100644
--- a/libopenfpga/CMakeLists.txt
+++ b/libopenfpga/CMakeLists.txt
@@ -7,3 +7,4 @@ add_subdirectory(libfabrickey)
add_subdirectory(librepackdc)
add_subdirectory(libfpgabitstream)
add_subdirectory(libpcf)
+add_subdirectory(libbusgroup)
diff --git a/libopenfpga/libbusgroup/CMakeLists.txt b/libopenfpga/libbusgroup/CMakeLists.txt
new file mode 100644
index 000000000..a2cbea164
--- /dev/null
+++ b/libopenfpga/libbusgroup/CMakeLists.txt
@@ -0,0 +1,35 @@
+cmake_minimum_required(VERSION 3.9)
+
+project("libbusgroup")
+
+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(libbusgroup STATIC
+ ${LIB_HEADERS}
+ ${LIB_SOURCES})
+target_include_directories(libbusgroup PUBLIC ${LIB_INCLUDE_DIRS})
+set_target_properties(libbusgroup PROPERTIES PREFIX "") #Avoid extra 'lib' prefix
+
+#Specify link-time dependancies
+target_link_libraries(libbusgroup
+ libopenfpgautil
+ libarchopenfpga
+ libvtrutil
+ libpugixml
+ 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} libbusgroup)
+endforeach(testsourcefile ${EXEC_SOURCES})
diff --git a/libopenfpga/libbusgroup/example/bus_group_example.xml b/libopenfpga/libbusgroup/example/bus_group_example.xml
new file mode 100644
index 000000000..2d31fb76a
--- /dev/null
+++ b/libopenfpga/libbusgroup/example/bus_group_example.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/libopenfpga/libbusgroup/src/bus_group.cpp b/libopenfpga/libbusgroup/src/bus_group.cpp
new file mode 100644
index 000000000..7aed69215
--- /dev/null
+++ b/libopenfpga/libbusgroup/src/bus_group.cpp
@@ -0,0 +1,170 @@
+#include
+
+#include "vtr_assert.h"
+#include "vtr_log.h"
+
+#include "bus_group.h"
+
+namespace openfpga { // Begin namespace openfpga
+
+/************************************************************************
+ * Member functions for class BusGroup
+ ***********************************************************************/
+
+/************************************************************************
+ * Constructors
+ ***********************************************************************/
+BusGroup::BusGroup() {
+ return;
+}
+
+/************************************************************************
+ * Public Accessors : aggregates
+ ***********************************************************************/
+BusGroup::bus_group_range BusGroup::buses() const {
+ return vtr::make_range(bus_ids_.begin(), bus_ids_.end());
+}
+
+/************************************************************************
+ * Public Accessors : Basic data query
+ ***********************************************************************/
+openfpga::BasicPort BusGroup::bus_port(const BusGroupId& bus_id) const {
+ VTR_ASSERT(valid_bus_id(bus_id));
+ return bus_ports_[bus_id];
+}
+
+std::vector BusGroup::bus_pins(const BusGroupId& bus_id) const {
+ VTR_ASSERT(valid_bus_id(bus_id));
+ return bus_pin_ids_[bus_id];
+}
+
+int BusGroup::pin_index(const BusPinId& pin_id) const {
+ VTR_ASSERT(valid_pin_id(pin_id));
+ return pin_indices_[pin_id];
+}
+
+std::string BusGroup::pin_name(const BusPinId& pin_id) const {
+ VTR_ASSERT(valid_pin_id(pin_id));
+ return pin_names_[pin_id];
+}
+
+BusGroupId BusGroup::find_pin_bus(const std::string& pin_name) const {
+ std::map::const_iterator result = pin_name2id_map_.find(pin_name);
+ if (result == pin_name2id_map_.end()) {
+ /* Not found, return an invalid id */
+ return BusGroupId::INVALID();
+ }
+ /* Found, we should get the parent bus */
+ BusPinId pin_id = result->second;
+ return pin_parent_bus_ids_[pin_id];
+}
+
+BusGroupId BusGroup::find_bus(const std::string& bus_name) const {
+ std::map::const_iterator result = bus_name2id_map_.find(bus_name);
+ if (result == bus_name2id_map_.end()) {
+ /* Not found, return an invalid id */
+ return BusGroupId::INVALID();
+ }
+ /* Found, we should get the parent bus */
+ return result->second;
+}
+
+BusPinId BusGroup::find_pin(const std::string& pin_name) const {
+ std::map::const_iterator result = pin_name2id_map_.find(pin_name);
+ if (result == pin_name2id_map_.end()) {
+ /* Not found, return an invalid id */
+ return BusPinId::INVALID();
+ }
+ /* Found, we should get the parent bus */
+ return result->second;
+}
+
+bool BusGroup::empty() const {
+ return 0 == bus_ids_.size();
+}
+
+/************************************************************************
+ * Public Mutators
+ ***********************************************************************/
+void BusGroup::reserve_buses(const size_t& num_buses) {
+ bus_ids_.reserve(num_buses);
+ bus_ports_.reserve(num_buses);
+ bus_pin_ids_.reserve(num_buses);
+}
+
+void BusGroup::reserve_pins(const size_t& num_pins) {
+ pin_ids_.reserve(num_pins);
+ pin_indices_.reserve(num_pins);
+ pin_names_.reserve(num_pins);
+ pin_parent_bus_ids_.reserve(num_pins);
+}
+
+BusGroupId BusGroup::create_bus(const openfpga::BasicPort& bus_port) {
+ /* Create a new id */
+ BusGroupId bus_id = BusGroupId(bus_ids_.size());
+
+ bus_ids_.push_back(bus_id);
+ bus_ports_.push_back(bus_port);
+ bus_pin_ids_.emplace_back();
+
+ /* Register to fast look-up */
+ auto result = bus_name2id_map_.find(bus_port.get_name());
+ if (result == bus_name2id_map_.end()) {
+ bus_name2id_map_[bus_port.get_name()] = bus_id;
+ } else {
+ VTR_LOG_ERROR("Duplicated bus name '%s' in bus group", bus_port.get_name().c_str());
+ exit(1);
+ }
+
+ return bus_id;
+}
+
+BusPinId BusGroup::create_pin(const BusGroupId& bus_id, const int& index) {
+ /* Create a new id */
+ BusPinId pin_id = BusPinId(pin_ids_.size());
+
+ pin_ids_.push_back(pin_id);
+
+ pin_indices_.push_back(index);
+ pin_names_.emplace_back();
+
+ /* Register the pin to the bus */
+ VTR_ASSERT(valid_bus_id(bus_id));
+ pin_parent_bus_ids_.push_back(bus_id);
+
+ /* If the pin index is beyond the range of the bus_pin_ids, resize it */
+ if (size_t(index) >= bus_pin_ids_[bus_id].size()) {
+ bus_pin_ids_[bus_id].resize(index + 1);
+ }
+ bus_pin_ids_[bus_id][index] = pin_id;
+
+ return pin_id;
+}
+
+
+void BusGroup::set_pin_name(const BusPinId& pin_id, const std::string& name) {
+ VTR_ASSERT(valid_pin_id(pin_id));
+ pin_names_[pin_id] = name;
+
+ /* Register to fast look-up */
+ auto result = pin_name2id_map_.find(name);
+ if (result == pin_name2id_map_.end()) {
+ pin_name2id_map_[name] = pin_id;
+ } else {
+ VTR_LOG_ERROR("Duplicated pin name '%s' in bus group", name.c_str());
+ exit(1);
+ }
+}
+
+/************************************************************************
+ * Internal invalidators/validators
+ ***********************************************************************/
+bool BusGroup::valid_bus_id(const BusGroupId& bus_id) const {
+ return ( size_t(bus_id) < bus_ids_.size() ) && ( bus_id == bus_ids_[bus_id] );
+}
+
+bool BusGroup::valid_pin_id(const BusPinId& pin_id) const {
+ return ( size_t(pin_id) < pin_ids_.size() ) && ( pin_id == pin_ids_[pin_id] );
+}
+
+} // End of namespace openfpga
diff --git a/libopenfpga/libbusgroup/src/bus_group.h b/libopenfpga/libbusgroup/src/bus_group.h
new file mode 100644
index 000000000..da63fb210
--- /dev/null
+++ b/libopenfpga/libbusgroup/src/bus_group.h
@@ -0,0 +1,125 @@
+#ifndef BUS_GROUP_H
+#define BUS_GROUP_H
+
+/********************************************************************
+ * This file include the declaration of pin constraints
+ *******************************************************************/
+#include
+#include