Merge pull request #608 from lnis-uofu/bit_dist

Include Configuration Region Statistics in Bitstream Distribution Report File
This commit is contained in:
tangxifan 2022-03-29 21:30:22 +08:00 committed by GitHub
commit b887b68938
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 313 additions and 89 deletions

View File

@ -5,41 +5,71 @@ Bitstream Distribution File (.xml)
The bitstream distribution file aims to show
- The total number of configuration bits under each block
- The number of configuration bits per block
- region-level bitstream distribution
- The total number of configuration bits under each region
An example of design constraints is shown as follows.
- block-level bitstream distribution
- The total number of configuration bits under each block
- The number of configuration bits per block
An example of the file is shown as follows.
.. code-block:: xml
<block name="fpga_top" number_of_bits="527">
<block name="grid_clb_1__1_" number_of_bits="136">
</block>
<block name="grid_io_top_1__2_" number_of_bits="8">
</block>
<block name="grid_io_right_2__1_" number_of_bits="8">
</block>
<block name="grid_io_bottom_1__0_" number_of_bits="8">
</block>
<block name="grid_io_left_0__1_" number_of_bits="8">
</block>
<block name="sb_0__0_" number_of_bits="58">
</block>
<block name="sb_0__1_" number_of_bits="57">
</block>
<block name="sb_1__0_" number_of_bits="59">
</block>
<block name="sb_1__1_" number_of_bits="56">
</block>
<block name="cbx_1__0_" number_of_bits="33">
</block>
<block name="cbx_1__1_" number_of_bits="33">
</block>
<block name="cby_0__1_" number_of_bits="30">
</block>
<block name="cby_1__1_" number_of_bits="33">
</block>
</block>
<bitstream_distribution>
<regions>
<region id="0" number_of_bits="2250">
</region>
</regions>
<blocks>
<block name="fpga_top" number_of_bits="2250">
<block name="grid_clb_1__1_" number_of_bits="1700">
</block>
<block name="grid_io_top_1__2_" number_of_bits="8">
</block>
<block name="grid_io_right_2__1_" number_of_bits="8">
</block>
<block name="grid_io_bottom_1__0_" number_of_bits="8">
</block>
<block name="grid_io_left_0__1_" number_of_bits="8">
</block>
<block name="sb_0__0_" number_of_bits="40">
</block>
<block name="sb_0__1_" number_of_bits="40">
</block>
<block name="sb_1__0_" number_of_bits="40">
</block>
<block name="sb_1__1_" number_of_bits="40">
</block>
<block name="cbx_1__0_" number_of_bits="88">
</block>
<block name="cbx_1__1_" number_of_bits="94">
</block>
<block name="cby_0__1_" number_of_bits="88">
</block>
<block name="cby_1__1_" number_of_bits="88">
</block>
</block>
</blocks>
</bitstream_distribution>
Region-Level Bitstream Distribution
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Region-level bitstream distribution is shown under the ``<regions>`` code block
.. option:: id="<string>"
The unique index of the region, which can be found in the :ref:`file_formats_fabric_key`
.. option:: number_of_bits="<string>"
The total number of configuration bits in this region
Block-Level Bitstream Distribution
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Block-level bitstream distribution is shown under the ``<blocks>`` code block
.. option:: name="<string>"

View File

@ -23,29 +23,6 @@
/* begin namespace openfpga */
namespace openfpga {
/********************************************************************
* This function write header information for an XML file of bitstream distribution
*******************************************************************/
static
void report_architecture_bitstream_distribution_xml_file_head(std::fstream& fp,
const bool& include_time_stamp) {
valid_file_stream(fp);
fp << "<!-- " << std::endl;
fp << "\t- Report Architecture Bitstream Distribution" << std::endl;
if (include_time_stamp) {
auto end = std::chrono::system_clock::now();
std::time_t end_time = std::chrono::system_clock::to_time_t(end);
/* Note that version is also a type of time stamp */
fp << "\t- Version: " << openfpga::VERSION << std::endl;
fp << "\t- Date: " << std::ctime(&end_time) ;
}
fp << "--> " << std::endl;
fp << std::endl;
}
/********************************************************************
* Recursively report the bitstream distribution of a block to a file
* This function will use a Depth-First Search in outputting bitstream
@ -91,27 +68,19 @@ void rec_report_block_bitstream_distribution_to_xml_file(std::fstream& fp,
* Notes:
* - The output format is a table whose format is compatible with RST files
*******************************************************************/
int report_architecture_bitstream_distribution(const BitstreamManager& bitstream_manager,
const std::string& fname,
const bool& include_time_stamp,
const size_t& max_hierarchy_level) {
/* Ensure that we have a valid file name */
if (true == fname.empty()) {
VTR_LOG_ERROR("Received empty file name to report bitstream!\n\tPlease specify a valid file name.\n");
return 1;
}
std::string timer_message = std::string("Report architecture bitstream distribution into XML file '") + fname + std::string("'");
int report_architecture_bitstream_distribution(std::fstream& fp,
const BitstreamManager& bitstream_manager,
const size_t& max_hierarchy_level,
const size_t& hierarchy_level) {
std::string timer_message = std::string("Report architecture bitstream distribution");
vtr::ScopedStartFinishTimer timer(timer_message);
/* Create the file stream */
std::fstream fp;
fp.open(fname, std::fstream::out | std::fstream::trunc);
/* Check the file stream */
valid_file_stream(fp);
check_file_stream(fname.c_str(), fp);
/* Put down a brief introduction */
report_architecture_bitstream_distribution_xml_file_head(fp, include_time_stamp);
int curr_level = hierarchy_level;
write_tab_to_file(fp, curr_level);
fp << "<blocks>" <<std::endl;
/* Find the top block, which has not parents */
std::vector<ConfigBlockId> top_block = find_bitstream_manager_top_blocks(bitstream_manager);
@ -119,10 +88,10 @@ int report_architecture_bitstream_distribution(const BitstreamManager& bitstream
VTR_ASSERT(1 == top_block.size());
/* Write bitstream, block by block, in a recursive way */
rec_report_block_bitstream_distribution_to_xml_file(fp, bitstream_manager, top_block[0], max_hierarchy_level, 0);
rec_report_block_bitstream_distribution_to_xml_file(fp, bitstream_manager, top_block[0], max_hierarchy_level + 2, curr_level + 1);
/* Close file handler */
fp.close();
write_tab_to_file(fp, curr_level);
fp << "</blocks>" <<std::endl;
return 0;
}

View File

@ -14,10 +14,10 @@
/* begin namespace openfpga */
namespace openfpga {
int report_architecture_bitstream_distribution(const BitstreamManager& bitstream_manager,
const std::string& fname,
const bool& include_time_stamp,
const size_t& max_hierarchy_level = 1);
int report_architecture_bitstream_distribution(std::fstream& fp,
const BitstreamManager& bitstream_manager,
const size_t& max_hierarchy_level,
const size_t& hierarchy_level);
} /* end namespace openfpga */

View File

@ -3,6 +3,7 @@
* 1. parser of data structures
* 2. writer of data structures
*******************************************************************/
#include <fstream>
/* Headers from vtrutils */
#include "vtr_assert.h"
#include "vtr_log.h"
@ -36,11 +37,12 @@ int main(int argc, const char** argv) {
* This is optional only used when there is a third argument
*/
if (4 <= argc) {
openfpga::report_architecture_bitstream_distribution(test_bitstream, argv[3], true);
VTR_LOG("Echo the bitstream distribution (with time stamp) to an XML file: %s.\n",
argv[3]);
openfpga::report_architecture_bitstream_distribution(test_bitstream, argv[3], false);
VTR_LOG("Echo the bitstream distribution (w/o time stamp) to an XML file: %s.\n",
/* Create the file stream */
std::fstream fp;
fp.open(argv[3], std::fstream::out | std::fstream::trunc);
openfpga::report_architecture_bitstream_distribution(fp, test_bitstream, 1, 0);
VTR_LOG("Echo the bitstream distribution to an XML file: %s.\n",
argv[3]);
}

View File

@ -15,7 +15,7 @@
/* Headers from fpgabitstream library */
#include "read_xml_arch_bitstream.h"
#include "write_xml_arch_bitstream.h"
#include "report_arch_bitstream_distribution.h"
#include "report_bitstream_distribution.h"
#include "openfpga_naming.h"
@ -218,10 +218,11 @@ int report_bitstream_distribution(const OpenfpgaContext& openfpga_ctx,
}
}
status = report_architecture_bitstream_distribution(openfpga_ctx.bitstream_manager(),
cmd_context.option_value(cmd, opt_file),
!cmd_context.option_enable(cmd, opt_no_time_stamp),
depth);
status = report_bitstream_distribution(cmd_context.option_value(cmd, opt_file),
openfpga_ctx.bitstream_manager(),
openfpga_ctx.fabric_bitstream(),
!cmd_context.option_enable(cmd, opt_no_time_stamp),
depth);
return status;
}

View File

@ -0,0 +1,96 @@
/********************************************************************
* This file includes functions that report distribution of bitstream by regions
*******************************************************************/
#include <chrono>
#include <ctime>
#include <fstream>
/* Headers from vtrutil library */
#include "vtr_assert.h"
#include "vtr_log.h"
#include "vtr_time.h"
/* Headers from openfpgautil library */
#include "openfpga_digest.h"
#include "openfpga_tokenizer.h"
#include "openfpga_version.h"
#include "openfpga_reserved_words.h"
#include "report_arch_bitstream_distribution.h"
#include "report_fabric_bitstream_distribution.h"
#include "report_bitstream_distribution.h"
/* begin namespace openfpga */
namespace openfpga {
/********************************************************************
* This function write header information for an XML file of bitstream distribution
*******************************************************************/
static
void report_bitstream_distribution_xml_file_head(std::fstream& fp,
const bool& include_time_stamp) {
valid_file_stream(fp);
fp << "<!-- " << std::endl;
fp << "\t- Report Bitstream Distribution" << std::endl;
if (include_time_stamp) {
auto end = std::chrono::system_clock::now();
std::time_t end_time = std::chrono::system_clock::to_time_t(end);
/* Note that version is also a type of time stamp */
fp << "\t- Version: " << openfpga::VERSION << std::endl;
fp << "\t- Date: " << std::ctime(&end_time) ;
}
fp << "--> " << std::endl;
fp << std::endl;
}
/********************************************************************
* Report the distribution of bitstream at architecture-level and fabric-level
* This function can generate a report to a file
*******************************************************************/
int report_bitstream_distribution(const std::string& fname,
const BitstreamManager& bitstream_manager,
const FabricBitstream& fabric_bitstream,
const bool& include_time_stamp,
const size_t& max_hierarchy_level) {
/* Ensure that we have a valid file name */
if (true == fname.empty()) {
VTR_LOG_ERROR("Received empty file name to report bitstream!\n\tPlease specify a valid file name.\n");
return 1;
}
std::string timer_message = std::string("Report bitstream distribution into XML file '") + fname + std::string("'");
vtr::ScopedStartFinishTimer timer(timer_message);
/* Create the file stream */
std::fstream fp;
fp.open(fname, std::fstream::out | std::fstream::trunc);
check_file_stream(fname.c_str(), fp);
/* Put down a brief introduction */
report_bitstream_distribution_xml_file_head(fp, include_time_stamp);
int curr_level = 0;
write_tab_to_file(fp, curr_level);
fp << "<bitstream_distribution>" <<std::endl;
int status = 0;
status = report_fabric_bitstream_distribution(fp, fabric_bitstream, curr_level + 1);
if (status == 1) {
return status;
}
status = report_architecture_bitstream_distribution(fp, bitstream_manager, max_hierarchy_level, curr_level + 1);
fp << "</bitstream_distribution>" <<std::endl;
/* Close file handler */
fp.close();
return status;
}
} /* end namespace openfpga */

View File

@ -0,0 +1,25 @@
#ifndef REPORT_BITSTREAM_DISTRIBUTION_H
#define REPORT_BITSTREAM_DISTRIBUTION_H
/********************************************************************
* Include header files that are required by function declaration
*******************************************************************/
#include <string>
#include "fabric_bitstream.h"
/********************************************************************
* Function declaration
*******************************************************************/
/* begin namespace openfpga */
namespace openfpga {
int report_bitstream_distribution(const std::string& fname,
const BitstreamManager& bitstream_manager,
const FabricBitstream& fabric_bitstream,
const bool& include_time_stamp,
const size_t& max_hierarchy_level = 1);
} /* end namespace openfpga */
#endif

View File

@ -0,0 +1,78 @@
/********************************************************************
* This file includes functions that report distribution of bitstream by regions
*******************************************************************/
#include <chrono>
#include <ctime>
#include <fstream>
/* Headers from vtrutil library */
#include "vtr_assert.h"
#include "vtr_log.h"
#include "vtr_time.h"
/* Headers from openfpgautil library */
#include "openfpga_digest.h"
#include "openfpga_tokenizer.h"
#include "openfpga_version.h"
#include "openfpga_reserved_words.h"
#include "bitstream_manager_utils.h"
#include "report_fabric_bitstream_distribution.h"
/* begin namespace openfpga */
namespace openfpga {
/********************************************************************
* Recursively report the bitstream distribution of a block to a file
* This function will use a Depth-First Search in outputting bitstream
* for each block
* For block with child blocks, we visit each child recursively
* The reporting can be stopped at a given maximum hierarchy level
* which is used to limit the length of the report
*******************************************************************/
static
void report_region_bitstream_distribution_to_xml_file(std::fstream& fp,
const FabricBitstream& fabric_bitstream,
const FabricBitRegionId& region,
const int& hierarchy_level) {
valid_file_stream(fp);
/* Write the bitstream distribution of this block */
write_tab_to_file(fp, hierarchy_level);
fp << "<region";
fp << " id=\"" << size_t(region) << "\"";
fp << " number_of_bits=\"" << fabric_bitstream.region_bits(region).size() << "\"";
fp << ">" << std::endl;
write_tab_to_file(fp, hierarchy_level);
fp << "</region>" <<std::endl;
}
/********************************************************************
* Report the distribution of bitstream by regions
* This function can generate a report to a file
*******************************************************************/
int report_fabric_bitstream_distribution(std::fstream& fp,
const FabricBitstream& fabric_bitstream,
const int& hierarchy_level) {
std::string timer_message = std::string("Report fabric bitstream distribution");
vtr::ScopedStartFinishTimer timer(timer_message);
valid_file_stream(fp);
/* Write bitstream, region by region, in a recursive way */
int curr_level = hierarchy_level;
for (const FabricBitRegionId& region : fabric_bitstream.regions()) {
write_tab_to_file(fp, curr_level);
fp << "<regions>" <<std::endl;
report_region_bitstream_distribution_to_xml_file(fp, fabric_bitstream, region, curr_level + 1);
write_tab_to_file(fp, curr_level);
fp << "</regions>" <<std::endl;
}
return 0;
}
} /* end namespace openfpga */

View File

@ -0,0 +1,23 @@
#ifndef REPORT_FABRIC_BITSTREAM_DISTRIBUTION_H
#define REPORT_FABRIC_BITSTREAM_DISTRIBUTION_H
/********************************************************************
* Include header files that are required by function declaration
*******************************************************************/
#include <string>
#include "fabric_bitstream.h"
/********************************************************************
* Function declaration
*******************************************************************/
/* begin namespace openfpga */
namespace openfpga {
int report_fabric_bitstream_distribution(std::fstream& fp,
const FabricBitstream& fabric_bitstream,
const int& hierarchy_level);
} /* end namespace openfpga */
#endif