diff --git a/docs/source/manual/file_formats/fabric_bitstream.rst b/docs/source/manual/file_formats/fabric_bitstream.rst
index ce321cc81..11faca959 100644
--- a/docs/source/manual/file_formats/fabric_bitstream.rst
+++ b/docs/source/manual/file_formats/fabric_bitstream.rst
@@ -19,11 +19,31 @@ The information depends on the type of configuration procotol.
.. option:: scan_chain
- A line consisting of ``0`` | ``1``
+ Multiple lines consisting of ``0`` | ``1``
+
+ For example, a bitstream for 1 configuration regions:
+
+ .. code-block:: xml
+
+ 0
+ 1
+ 0
+ 0
+
+ For example, a bitstream for 4 configuration regions:
+
+ .. code-block:: xml
+
+ 0000
+ 1010
+ 0110
+ 0120
+
+ .. note:: When there are multiple configuration regions, each line may consist of multiple bits. For example, ``0110`` represents the bits for 4 configuration regions, where the 4 digits correspond to the bits from region ``0, 1, 2, 3`` respectively.
.. option:: memory_bank
- Multiple lines will be included, each of which is organized as
.
+ Multiple lines will be included, each of which is organized as .
Note that due to the use of Bit-Line and Word-Line decoders, every two lines are paired.
The first line represents the Bit-Line address and configuration bit.
The second line represents the Word-Line address and configuration bit.
@@ -39,11 +59,15 @@ The information depends on the type of configuration procotol.
+ .. note:: When there are multiple configuration regions, each ```` may consist of multiple bits. For example, ``0110`` represents the bits for 4 configuration regions, where the 4 digits correspond to the bits from region ``0, 1, 2, 3`` respectively.
+
.. option:: frame_based
- Multiple lines will be included, each of which is organized as .
+ Multiple lines will be included, each of which is organized as .
Note that the address may include don't care bit which is denoted as ``x``.
- OpenFPGA automatically convert don't care bit to logic ``0`` when generating testbenches.
+
+ .. note:: OpenFPGA automatically convert don't care bit to logic ``0`` when generating testbenches.
+
For example
.. code-block:: xml
@@ -53,6 +77,7 @@ The information depends on the type of configuration procotol.
...
+ .. note:: When there are multiple configuration regions, each ```` may consist of multiple bits. For example, ``0110`` represents the bits for 4 configuration regions, where the 4 digits correspond to the bits from region ``0, 1, 2, 3`` respectively.
.. _file_formats_fabric_bitstream_xml:
@@ -61,7 +86,21 @@ XML (.xml)
This file format is designed to generate testbenches using external tools, e.g., CocoTB.
-In principle, the file consist a number of XML node ````, each bit contains the following attributes:
+In principle, the file consist a number of XML node ````, each region has a unique id, and contains a number of XML nodes ````.
+
+- ``id``: The unique id of a configuration region in the fabric bitstream.
+
+A quick example:
+
+.. code-block:: xml
+
+
+
+
+
+
+
+Each XML node ```` contains the following attributes:
- ``id``: The unique id of the configuration bit in the fabric bitstream.
diff --git a/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp b/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp
index f96747212..3fa604de1 100644
--- a/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp
+++ b/openfpga/src/fpga_bitstream/write_text_fabric_bitstream.cpp
@@ -17,6 +17,7 @@
#include "openfpga_naming.h"
#include "bitstream_manager_utils.h"
+#include "fabric_bitstream_utils.h"
#include "write_text_fabric_bitstream.h"
/* begin namespace openfpga */
@@ -80,6 +81,124 @@ int write_fabric_config_bit_to_text_file(std::fstream& fp,
return 0;
}
+
+/********************************************************************
+ * Write the flatten fabric bitstream to a plain text file
+ *
+ * Return:
+ * - 0 if succeed
+ * - 1 if critical errors occured
+ *******************************************************************/
+static
+int write_flatten_fabric_bitstream_to_text_file(std::fstream& fp,
+ const BitstreamManager& bitstream_manager,
+ const FabricBitstream& fabric_bitstream,
+ const ConfigProtocol& config_protocol) {
+ int status = 0;
+ for (const FabricBitId& fabric_bit : fabric_bitstream.bits()) {
+ status = write_fabric_config_bit_to_text_file(fp, bitstream_manager,
+ fabric_bitstream,
+ fabric_bit,
+ config_protocol.type());
+ if (1 == status) {
+ return status;
+ }
+ }
+
+ return status;
+}
+
+/********************************************************************
+ * Write the fabric bitstream fitting a configuration chain protocol
+ * to a plain text file
+ *
+ * Return:
+ * - 0 if succeed
+ * - 1 if critical errors occured
+ *******************************************************************/
+static
+int write_config_chain_fabric_bitstream_to_text_file(std::fstream& fp,
+ const BitstreamManager& bitstream_manager,
+ const FabricBitstream& fabric_bitstream) {
+ int status = 0;
+
+ size_t regional_bitstream_max_size = find_fabric_regional_bitstream_max_size(fabric_bitstream);
+ ConfigChainFabricBitstream regional_bitstreams = build_config_chain_fabric_bitstream_by_region(bitstream_manager, fabric_bitstream);
+
+ for (size_t ibit = 0; ibit < regional_bitstream_max_size; ++ibit) {
+ for (const auto& region_bitstream : regional_bitstreams) {
+ fp << region_bitstream[ibit];
+ }
+ fp << std::endl;
+ }
+
+ return status;
+}
+
+/********************************************************************
+ * Write the fabric bitstream fitting a memory bank protocol
+ * to a plain text file
+ *
+ * Return:
+ * - 0 if succeed
+ * - 1 if critical errors occured
+ *******************************************************************/
+static
+int write_memory_bank_fabric_bitstream_to_text_file(std::fstream& fp,
+ const FabricBitstream& fabric_bitstream) {
+ int status = 0;
+
+ MemoryBankFabricBitstream fabric_bits_by_addr = build_memory_bank_fabric_bitstream_by_address(fabric_bitstream);
+
+ for (const auto& addr_din_pair : fabric_bits_by_addr) {
+ /* Write BL address code */
+ fp << addr_din_pair.first.first;
+ fp << " ";
+
+ /* Write WL address code */
+ fp << addr_din_pair.first.second;
+ fp << " ";
+
+ /* Write data input */
+ for (const bool& din_value : addr_din_pair.second) {
+ fp << din_value;
+ }
+ fp << std::endl;
+ }
+
+ return status;
+}
+
+/********************************************************************
+ * Write the fabric bitstream fitting a frame-based protocol
+ * to a plain text file
+ *
+ * Return:
+ * - 0 if succeed
+ * - 1 if critical errors occured
+ *******************************************************************/
+static
+int write_frame_based_fabric_bitstream_to_text_file(std::fstream& fp,
+ const FabricBitstream& fabric_bitstream) {
+ int status = 0;
+
+ FrameFabricBitstream fabric_bits_by_addr = build_frame_based_fabric_bitstream_by_address(fabric_bitstream);
+
+ for (const auto& addr_din_pair : fabric_bits_by_addr) {
+ /* Write address code */
+ fp << addr_din_pair.first;
+ fp << " ";
+
+ /* Write data input */
+ for (const bool& din_value : addr_din_pair.second) {
+ fp << din_value;
+ }
+ fp << std::endl;
+ }
+
+ return status;
+}
+
/********************************************************************
* Write the fabric bitstream to a plain text file
* Notes:
@@ -113,15 +232,33 @@ int write_fabric_bitstream_to_text_file(const BitstreamManager& bitstream_manage
/* Output fabric bitstream to the file */
int status = 0;
- for (const FabricBitId& fabric_bit : fabric_bitstream.bits()) {
- status = write_fabric_config_bit_to_text_file(fp, bitstream_manager,
- fabric_bitstream,
- fabric_bit,
- config_protocol.type());
- if (1 == status) {
- break;
- }
+ switch (config_protocol.type()) {
+ case CONFIG_MEM_STANDALONE:
+ status = write_flatten_fabric_bitstream_to_text_file(fp,
+ bitstream_manager,
+ fabric_bitstream,
+ config_protocol);
+ break;
+ case CONFIG_MEM_SCAN_CHAIN:
+ status = write_config_chain_fabric_bitstream_to_text_file(fp,
+ bitstream_manager,
+ fabric_bitstream);
+ break;
+ case CONFIG_MEM_MEMORY_BANK:
+ status = write_memory_bank_fabric_bitstream_to_text_file(fp,
+ fabric_bitstream);
+ break;
+ case CONFIG_MEM_FRAME_BASED:
+ status = write_frame_based_fabric_bitstream_to_text_file(fp,
+ fabric_bitstream);
+ break;
+ default:
+ VTR_LOGF_ERROR(__FILE__, __LINE__,
+ "Invalid configuration protocol type!\n");
+ status = 1;
}
+
+
/* Print an end to the file here */
fp << std::endl;
diff --git a/openfpga/src/fpga_bitstream/write_xml_fabric_bitstream.cpp b/openfpga/src/fpga_bitstream/write_xml_fabric_bitstream.cpp
index 32d5a209c..adc12ce73 100644
--- a/openfpga/src/fpga_bitstream/write_xml_fabric_bitstream.cpp
+++ b/openfpga/src/fpga_bitstream/write_xml_fabric_bitstream.cpp
@@ -71,12 +71,13 @@ int write_fabric_config_bit_to_xml_file(std::fstream& fp,
const BitstreamManager& bitstream_manager,
const FabricBitstream& fabric_bitstream,
const FabricBitId& fabric_bit,
- const e_config_protocol_type& config_type) {
+ const e_config_protocol_type& config_type,
+ const int& xml_hierarchy_depth) {
if (false == valid_file_stream(fp)) {
return 1;
}
- write_tab_to_file(fp, 1);
+ write_tab_to_file(fp, xml_hierarchy_depth);
fp << "\n";
- write_tab_to_file(fp, 2);
+ write_tab_to_file(fp, xml_hierarchy_depth + 1);
fp << "\n";
return 0;
}
+/********************************************************************
+ * Write the fabric bitstream in a specific configuration region to an XML file
+ *
+ * Return:
+ * - 0 if succeed
+ * - 1 if critical errors occured
+ *******************************************************************/
+static
+int write_fabric_regional_config_bit_to_xml_file(std::fstream& fp,
+ const BitstreamManager& bitstream_manager,
+ const FabricBitstream& fabric_bitstream,
+ const FabricBitRegionId& fabric_region,
+ const e_config_protocol_type& config_type,
+ const int& xml_hierarchy_depth) {
+ if (false == valid_file_stream(fp)) {
+ return 1;
+ }
+
+ int status = 0;
+
+ write_tab_to_file(fp, xml_hierarchy_depth);
+ fp << "\n";
+
+ for (const FabricBitId& fabric_bit : fabric_bitstream.region_bits(fabric_region)) {
+ status = write_fabric_config_bit_to_xml_file(fp, bitstream_manager,
+ fabric_bitstream,
+ fabric_bit,
+ config_type,
+ xml_hierarchy_depth + 1);
+ if (1 == status) {
+ return status;
+ }
+ }
+
+ write_tab_to_file(fp, xml_hierarchy_depth);
+ fp << "\n";
+
+ return status;
+}
+
/********************************************************************
* Write the fabric bitstream to an XML file
* Notes:
@@ -173,15 +218,17 @@ int write_fabric_bitstream_to_xml_file(const BitstreamManager& bitstream_manager
/* Write XML head */
write_fabric_bitstream_xml_file_head(fp);
+ int xml_hierarchy_depth = 0;
fp << "\n";
/* Output fabric bitstream to the file */
int status = 0;
- for (const FabricBitId& fabric_bit : fabric_bitstream.bits()) {
- status = write_fabric_config_bit_to_xml_file(fp, bitstream_manager,
- fabric_bitstream,
- fabric_bit,
- config_protocol.type());
+ for (const FabricBitRegionId& region : fabric_bitstream.regions()) {
+ status = write_fabric_regional_config_bit_to_xml_file(fp, bitstream_manager,
+ fabric_bitstream,
+ region,
+ config_protocol.type(),
+ xml_hierarchy_depth + 1);
if (1 == status) {
break;
}
diff --git a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp
index 828779ec6..08b7cd2e8 100644
--- a/openfpga/src/fpga_verilog/verilog_top_testbench.cpp
+++ b/openfpga/src/fpga_verilog/verilog_top_testbench.cpp
@@ -1484,24 +1484,7 @@ void print_verilog_top_testbench_configuration_chain_bitstream(std::fstream& fp,
VTR_ASSERT(num_bits_to_skip < regional_bitstream_max_size);
/* Reorganize the regional bitstreams to be the same size */
- std::vector> regional_bitstreams;
- regional_bitstreams.reserve(fabric_bitstream.regions().size());
- for (const FabricBitRegionId& region : fabric_bitstream.regions()) {
- std::vector curr_regional_bitstream;
- curr_regional_bitstream.resize(regional_bitstream_max_size, false);
- /* Starting index should consider the offset between the current bitstream size and
- * the maximum size of regional bitstream
- */
- size_t offset = regional_bitstream_max_size - fabric_bitstream.region_bits(region).size();
- for (const FabricBitId& bit_id : fabric_bitstream.region_bits(region)) {
- curr_regional_bitstream[offset] = bitstream_manager.bit_value(fabric_bitstream.config_bit(bit_id));
- offset++;
- }
- VTR_ASSERT(offset == regional_bitstream_max_size);
-
- /* Add the adapt sub-bitstream */
- regional_bitstreams.push_back(curr_regional_bitstream);
- }
+ ConfigChainFabricBitstream regional_bitstreams = build_config_chain_fabric_bitstream_by_region(bitstream_manager, fabric_bitstream);
/* Attention: when the fast configuration is enabled, we will start from the first bit '1'
* This requires a reset signal (as we forced in the first clock cycle)
@@ -1602,7 +1585,7 @@ void print_verilog_top_testbench_memory_bank_bitstream(std::fstream& fp,
fp << std::endl;
/* Reorganize the fabric bitstream by the same address across regions */
- std::map, std::vector> fabric_bits_by_addr = build_memory_bank_fabric_bitstream_by_address(fabric_bitstream);
+ MemoryBankFabricBitstream fabric_bits_by_addr = build_memory_bank_fabric_bitstream_by_address(fabric_bitstream);
for (const auto& addr_din_pair : fabric_bits_by_addr) {
/* When fast configuration is enabled,
@@ -1711,7 +1694,7 @@ void print_verilog_top_testbench_frame_decoder_bitstream(std::fstream& fp,
fp << std::endl;
/* Reorganize the fabric bitstream by the same address across regions */
- std::map> fabric_bits_by_addr = build_frame_based_fabric_bitstream_by_address(fabric_bitstream);
+ FrameFabricBitstream fabric_bits_by_addr = build_frame_based_fabric_bitstream_by_address(fabric_bitstream);
for (const auto& addr_din_pair : fabric_bits_by_addr) {
/* When fast configuration is enabled,
diff --git a/openfpga/src/utils/fabric_bitstream_utils.cpp b/openfpga/src/utils/fabric_bitstream_utils.cpp
index b1beeb00d..52f81dcdb 100644
--- a/openfpga/src/utils/fabric_bitstream_utils.cpp
+++ b/openfpga/src/utils/fabric_bitstream_utils.cpp
@@ -67,6 +67,43 @@ size_t find_configuration_chain_fabric_bitstream_size_to_be_skipped(const Fabric
return num_bits_to_skip;
}
+/********************************************************************
+ * Build a fabric bitstream which can be directly loaded to a configuration
+ * chain (either single-head or multi-bit)
+ * We will organize the bitstreams in each region and align them
+ * Logic '0' bits may be deposited to those bitstream whose length is smaller
+ * than the maximum bitstream among all the regions
+ * For example:
+ * Region 0: 000000001111101010 <- max. bitstream length
+ * Region 1: 00000011010101 <- shorter bitstream than the max.; add zeros to the head
+ * Region 2: 0010101111000110 <- shorter bitstream than the max.; add zeros to the head
+ *******************************************************************/
+ConfigChainFabricBitstream build_config_chain_fabric_bitstream_by_region(const BitstreamManager& bitstream_manager,
+ const FabricBitstream& fabric_bitstream) {
+ /* Find the longest bitstream */
+ size_t regional_bitstream_max_size = find_fabric_regional_bitstream_max_size(fabric_bitstream);
+
+ ConfigChainFabricBitstream regional_bitstreams;
+ regional_bitstreams.reserve(fabric_bitstream.regions().size());
+ for (const FabricBitRegionId& region : fabric_bitstream.regions()) {
+ std::vector curr_regional_bitstream;
+ curr_regional_bitstream.resize(regional_bitstream_max_size, false);
+ /* Starting index should consider the offset between the current bitstream size and
+ * the maximum size of regional bitstream
+ */
+ size_t offset = regional_bitstream_max_size - fabric_bitstream.region_bits(region).size();
+ for (const FabricBitId& bit_id : fabric_bitstream.region_bits(region)) {
+ curr_regional_bitstream[offset] = bitstream_manager.bit_value(fabric_bitstream.config_bit(bit_id));
+ offset++;
+ }
+ VTR_ASSERT(offset == regional_bitstream_max_size);
+
+ /* Add the adapt sub-bitstream */
+ regional_bitstreams.push_back(curr_regional_bitstream);
+ }
+ return regional_bitstreams;
+}
+
/********************************************************************
* Reorganize the fabric bitstream for frame-based protocol
* by the same address across regions:
@@ -78,8 +115,8 @@ size_t find_configuration_chain_fabric_bitstream_size_to_be_skipped(const Fabric
*
* Note: the std::map may cause large memory footprint for large bitstream databases!
*******************************************************************/
-std::map> build_frame_based_fabric_bitstream_by_address(const FabricBitstream& fabric_bitstream) {
- std::map> fabric_bits_by_addr;
+FrameFabricBitstream build_frame_based_fabric_bitstream_by_address(const FabricBitstream& fabric_bitstream) {
+ FrameFabricBitstream fabric_bits_by_addr;
for (const FabricBitRegionId& region : fabric_bitstream.regions()) {
for (const FabricBitId& bit_id : fabric_bitstream.region_bits(region)) {
/* Create string for address */
@@ -129,7 +166,7 @@ std::map> build_frame_based_fabric_bitstream_by_a
*******************************************************************/
size_t find_frame_based_fast_configuration_fabric_bitstream_size(const FabricBitstream& fabric_bitstream,
const bool& bit_value_to_skip) {
- std::map> fabric_bits_by_addr = build_frame_based_fabric_bitstream_by_address(fabric_bitstream);
+ FrameFabricBitstream fabric_bits_by_addr = build_frame_based_fabric_bitstream_by_address(fabric_bitstream);
size_t num_bits = 0;
@@ -161,8 +198,8 @@ size_t find_frame_based_fast_configuration_fabric_bitstream_size(const FabricBit
*
* Note: the std::map may cause large memory footprint for large bitstream databases!
*******************************************************************/
-std::map, std::vector> build_memory_bank_fabric_bitstream_by_address(const FabricBitstream& fabric_bitstream) {
- std::map, std::vector> fabric_bits_by_addr;
+MemoryBankFabricBitstream build_memory_bank_fabric_bitstream_by_address(const FabricBitstream& fabric_bitstream) {
+ MemoryBankFabricBitstream fabric_bits_by_addr;
for (const FabricBitRegionId& region : fabric_bitstream.regions()) {
for (const FabricBitId& bit_id : fabric_bitstream.region_bits(region)) {
/* Create string for BL address */
@@ -217,7 +254,7 @@ std::map, std::vector> build_memory_ba
*******************************************************************/
size_t find_memory_bank_fast_configuration_fabric_bitstream_size(const FabricBitstream& fabric_bitstream,
const bool& bit_value_to_skip) {
- std::map, std::vector> fabric_bits_by_addr = build_memory_bank_fabric_bitstream_by_address(fabric_bitstream);
+ MemoryBankFabricBitstream fabric_bits_by_addr = build_memory_bank_fabric_bitstream_by_address(fabric_bitstream);
size_t num_bits = 0;
diff --git a/openfpga/src/utils/fabric_bitstream_utils.h b/openfpga/src/utils/fabric_bitstream_utils.h
index e34464a89..4da8c3c92 100644
--- a/openfpga/src/utils/fabric_bitstream_utils.h
+++ b/openfpga/src/utils/fabric_bitstream_utils.h
@@ -25,12 +25,21 @@ size_t find_configuration_chain_fabric_bitstream_size_to_be_skipped(const Fabric
const BitstreamManager& bitstream_manager,
const bool& bit_value_to_skip);
-std::map> build_frame_based_fabric_bitstream_by_address(const FabricBitstream& fabric_bitstream);
+/* Alias to a specific organization of bitstreams for frame-based configuration protocol */
+typedef std::vector> ConfigChainFabricBitstream;
+ConfigChainFabricBitstream build_config_chain_fabric_bitstream_by_region(const BitstreamManager& bitstream_manager,
+ const FabricBitstream& fabric_bitstream);
+
+/* Alias to a specific organization of bitstreams for frame-based configuration protocol */
+typedef std::map> FrameFabricBitstream;
+FrameFabricBitstream build_frame_based_fabric_bitstream_by_address(const FabricBitstream& fabric_bitstream);
size_t find_frame_based_fast_configuration_fabric_bitstream_size(const FabricBitstream& fabric_bitstream,
const bool& bit_value_to_skip);
-std::map, std::vector> build_memory_bank_fabric_bitstream_by_address(const FabricBitstream& fabric_bitstream);
+/* Alias to a specific organization of bitstreams for memory bank configuration protocol */
+typedef std::map, std::vector> MemoryBankFabricBitstream;
+MemoryBankFabricBitstream build_memory_bank_fabric_bitstream_by_address(const FabricBitstream& fabric_bitstream);
size_t find_memory_bank_fast_configuration_fabric_bitstream_size(const FabricBitstream& fabric_bitstream,
const bool& bit_value_to_skip);