[engine] updating gsb writer; Unfinished!!!

This commit is contained in:
tangxifan 2022-08-29 16:58:48 -07:00
parent adbc69f081
commit 12a30196e0
7 changed files with 322 additions and 27 deletions

View File

@ -127,15 +127,18 @@ write_gsb_to_xml
- ``--exclude sb`` - ``--exclude sb``
- ``--exclude [sb, cbx]`` - ``--exclude [sb, cbx]``
.. option:: --gsb_list <string> .. option:: --gsb_names <string>
Specify the name of GSB to be outputted. Users can specify multiple GSBs by using a splitter ``,``. Specify the name of GSB to be outputted. Users can specify multiple GSBs by using a splitter ``,``.
When specified, only the GSBs whose names match the list will be outputted to files. When specified, only the GSBs whose names match the list will be outputted to files.
If not specified, all the GSBs will be outputted. If not specified, all the GSBs will be outputted.
.. note:: When option ``--unique`` is enable, the given name of GSBs should match the unique modules!
For example, For example,
- ``--gsb_list [gsb_2__4_, gsb_3__2_]`` - ``--gsb_names [gsb_2__4_, gsb_3__2_]``
- ``--gsb_list gsb_2__4_`` - ``--gsb_names gsb_2__4_``
.. option:: --verbose .. option:: --verbose

View File

@ -0,0 +1,120 @@
/******************************************************************************
* Memember functions for data structure RRGSBWriterOption
******************************************************************************/
#include "vtr_assert.h"
#include "vtr_log.h"
#include "rr_gsb_writer_option.h"
#include "openfpga_tokenizer.h"
/* begin namespace openfpga */
namespace openfpga {
/**************************************************
* Public Constructors
*************************************************/
RRGSBWriterOption::RRGSBWriterOption() {
output_directory_.clear();
unique_module_only_ = false;
exclude_content_ = {false, false, false, false};
gsb_names_.clear();
verbose_output_ = false;
num_parse_errors_ = 0;
}
/**************************************************
* Public Accessors
*************************************************/
std::string RRGSBWriterOption::output_directory() const {
return output_directory_;
}
bool RRGSBWriterOption::unique_module_only() const {
return unique_module_only_;
}
bool RRGSBWriterOption::include_rr_info() const {
return !exclude_content_[0];
}
bool RRGSBWriterOption::include_cb_content(const t_rr_type& cb_type) const {
if (cb_type == CHANX) {
return !exclude_content_[1];
}
VTR_ASSERT(cb_type == CHANY);
return !exclude_content_[2];
}
bool RRGSBWriterOption::include_sb_content() const {
return !exclude_content_[3];
}
std::vector<std::string> RRGSBWriterOption::include_gsb_names() const {
return include_gsb_names_;
}
bool RRGSBWriterOption::verbose_output() const {
return verbose_output_;
}
/******************************************************************************
* Private Mutators
******************************************************************************/
void RRGSBWriterOption::set_output_directory(const std::string& output_dir) {
output_directory_ = output_dir;
}
void RRGSBWriterOption::set_unique_module_only(const bool& enabled) {
unique_module_only_ = enabled;
}
void RRGSBWriterOption::set_exclude_rr_info(const bool& enabled) {
exclude_content_[0] = enabled;
}
void RRGSBWriterOption::set_exclude_content(const std::string& content) {
num_parse_errors_ = 0;
/* Split the content using a tokenizer */
StringToken tokenizer(content);
std::string tokens = tokenizer.split(',');
/* Parse each token */
std::map<std::string, int> token2index = { {"sb", 3}, {"cbx", 1}, {"cby", 2} };
for (std::string token : tokens) {
auto result = token2index.find(token);
if (result == token2index.end()) {
/* Cannot find a valid keyword, error out */
std::string keyword_list;
for (auto pair : token2index) {
keyword_list += pair.first + "|";
}
keyword_list.pop_back();
VTR_LOG_ERROR("Invalid content '" + token + "' to skip, expect [ " + keyword_list + " ]");
num_parse_errors_++;
continue;
}
/* Now we should have a valid keyword, assign to designated flag */
exclude_content_[result->second] = true;
}
}
void RRGSBWriterOption::set_include_gsb_names(const std::string& gsb_names) {
/* Split the content using a tokenizer */
StringToken tokenizer(content);
gsb_names_ = tokenizer.split(',');
}
void RRGSBWriterOption::set_verbose_output(const bool& enabled) {
verbose_output_ = enabled;
}
bool RRGSBWriterOption::valid() const {
if (output_directory_.empty()) {
return false;
}
if (num_parse_errors_) {
return false;
}
return true;
}
} /* end namespace openfpga */

View File

@ -0,0 +1,65 @@
#ifndef RR_GSB_WRITER_OPTION_H
#define RR_GSB_WRITER_OPTION_H
/********************************************************************
* Include header files required by the data structure definition
*******************************************************************/
#include <string>
/* Begin namespace openfpga */
namespace openfpga {
/********************************************************************
* Options for RRGSB writer
*******************************************************************/
class RRGSBWriterOption {
public: /* Public constructor */
/* Set default options */
RRGSBWriterOption();
public: /* Public accessors */
std::string output_directory() const;
bool unique_module_only() const;
bool include_rr_info() const;
bool include_cb_content(const t_rr_type& cb_type) const;
bool include_sb_content() const;
std::vector<std::string> include_gsb_names() const;
bool verbose_output() const;
public: /* Public mutators */
void set_output_directory(const std::string& output_dir);
void set_unique_module_only(const bool& enabled);
void set_exclude_rr_info(const bool& enabled);
/* Parse the string which contains the content to be excluded
* Accepted string format is [sb|cbx|cby]
* Allow the use ',' as splitter
* For example: sb,cby
*/
void set_exclude_content(const std::string& content);
void set_include_gsb_names(const std::string& gsb_names);
void set_verbose_output(const bool& enabled);
public: /* Public validators */
/* Check if the following internal data is valid or not:
* - output directory is assigned
* - no parsing errors
*/
bool valid() const;
private: /* Internal Data */
std::string output_directory_;
bool unique_module_only_;
/* Flags to mark what content to be skipped when outputting:
* 0 : rr_info
* 1 : cbx
* 2 : cby
* 3 : sb
*/
std::array<bool, 4> exclude_content_;
std::vector<std::string> gsb_names_;
bool verbose_output_;
/* A flag to indicate if the data parse is invalid or not */
int num_parse_errors_;
};
} /* End namespace openfpga*/
#endif

View File

@ -182,7 +182,12 @@ void write_rr_switch_block_to_xml(const std::string fname_prefix,
const VprDeviceAnnotation& vpr_device_annotation, const VprDeviceAnnotation& vpr_device_annotation,
const RRGraph& rr_graph, const RRGraph& rr_graph,
const RRGSB& rr_gsb, const RRGSB& rr_gsb,
const bool& verbose) { const RRGSBWriterOption& options) {
/* If there is a list of gsb list, we skip those which are not in the list */
if (!include_gsb_names.empty() && include_gsb_names.end() != std::find(include_gsb_names.begin(), include_gsb_names.end(), curr_gsb_name()
write_rr_switch_block_to_xml(xml_dir_name, vpr_device_grid, vpr_device_annotation, rr_graph, rr_gsb, options);
/* Prepare file name */ /* Prepare file name */
std::string fname(fname_prefix); std::string fname(fname_prefix);
vtr::Point<size_t> gsb_coordinate(rr_gsb.get_sb_x(), rr_gsb.get_sb_y()); vtr::Point<size_t> gsb_coordinate(rr_gsb.get_sb_x(), rr_gsb.get_sb_y());
@ -225,48 +230,132 @@ void write_rr_switch_block_to_xml(const std::string fname_prefix,
} }
/*************************************************************************************** /***************************************************************************************
* Output internal structure (only the switch block part) of all the RRGSBs * Output internal structure (only the connection block part) of a RRGSB to XML format
* in a DeviceRRGSB to XML format
***************************************************************************************/ ***************************************************************************************/
void write_device_rr_gsb_to_xml(const char* sb_xml_dir, static
void write_rr_connection_block_to_xml(const std::string fname_prefix,
const DeviceGrid& vpr_device_grid, const DeviceGrid& vpr_device_grid,
const VprDeviceAnnotation& vpr_device_annotation,
const RRGraph& rr_graph,
const RRGSB& rr_gsb,
const t_rr_type& cb_type,
const RRGSBWriterOption& options) {
/* If there is a list of gsb list, we skip those which are not in the list */
if (!include_gsb_names.empty() && include_gsb_names.end() != std::find(include_gsb_names.begin(), include_gsb_names.end(), curr_gsb_name()
write_rr_switch_block_to_xml(xml_dir_name, vpr_device_grid, vpr_device_annotation, rr_graph, rr_gsb, options);
/* Prepare file name */
std::string fname(fname_prefix);
vtr::Point<size_t> cb_coordinate(rr_gsb.get_cb_x(cb_type), rr_gsb.get_cb_y(cb_type));
fname += generate_connection_block_module_name(cb_type, cb_coordinate);
fname += ".xml";
VTR_LOGV(verbose,
"Output internal structure of Connection Block to '%s'\n",
fname.c_str());
/* Create a file handler*/
std::fstream fp;
/* Open a file */
fp.open(fname, std::fstream::out | std::fstream::trunc);
/* Validate the file stream */
check_file_stream(fname.c_str(), fp);
/* Output location of the Switch Block */
fp << "<rr_cb x=\"" << rr_gsb.get_cb_x(cb_type) << "\" y=\"" << rr_gsb.get_cb_y(cb_type) << "\""
<< " num_sides=\"" << rr_gsb.get_num_sides() << "\">" << std::endl;
/* Output each side */
for (size_t side = 0; side < rr_gsb.get_cb_ipin_sides(cb_type); ++side) {
SideManager gsb_side_manager(side);
enum e_side gsb_side = gsb_side_manager.get_side();
/* IPIN nodes and related connections */
write_rr_gsb_ipin_connection_to_xml(fp, rr_graph, rr_gsb, gsb_side);
}
fp << "</rr_cb>"
<< std::endl;
/* close a file */
fp.close();
}
/***************************************************************************************
* Output internal structure (only the switch block part) of all the RRGSBs
* in a DeviceRRGSB to XML format
***************************************************************************************/
void write_device_rr_gsb_to_xml(const DeviceGrid& vpr_device_grid,
const VprDeviceAnnotation& vpr_device_annotation, const VprDeviceAnnotation& vpr_device_annotation,
const RRGraph& rr_graph, const RRGraph& rr_graph,
const DeviceRRGSB& device_rr_gsb, const DeviceRRGSB& device_rr_gsb,
const bool& unique, const RRGSBWriterOption& options) {
const bool& verbose) { std::string xml_dir_name = format_dir_path(options.output_directory);
std::string xml_dir_name = format_dir_path(std::string(sb_xml_dir));
/* Create directories */ /* Create directories */
create_directory(xml_dir_name); create_directory(xml_dir_name);
vtr::Point<size_t> sb_range = device_rr_gsb.get_gsb_range(); vtr::Point<size_t> sb_range = device_rr_gsb.get_gsb_range();
size_t gsb_counter = 0; size_t sb_counter = 0;
std::map<t_rr_type, size_t> cb_counters = 0;
std::map<t_rr_type, std::string> cb_names = { {CHANX, "X-direction"}, {CHANY, "Y-direction"} };
std::vector<std::string> include_gsb_names = options.include_gsb_names();
/* For each switch block, an XML file will be outputted */ /* For each switch block, an XML file will be outputted */
if (unique) { if (options.unique_module_only()) {
/* Only output unique GSB modules */ /* Only output unique GSB modules */
VTR_LOG("Only output unique GSB modules to XML\n"); VTR_LOG("Only output unique GSB modules to XML\n");
for (size_t igsb = 0; igsb < device_rr_gsb.get_num_gsb_unique_module(); ++igsb) { for (size_t igsb = 0; igsb < device_rr_gsb.get_num_gsb_unique_module(); ++igsb) {
const RRGSB& rr_gsb = device_rr_gsb.get_gsb_unique_module(igsb); const RRGSB& rr_gsb = device_rr_gsb.get_sb_unique_module(igsb);
write_rr_switch_block_to_xml(xml_dir_name, vpr_device_grid, vpr_device_annotation, rr_graph, rr_gsb, verbose); /* Write CBx, CBy, SB on need */
gsb_counter++; if (options.include_sb_content()) {
write_rr_switch_block_to_xml(xml_dir_name, vpr_device_grid, vpr_device_annotation, rr_graph, rr_gsb, options);
}
sb_counter++;
}
for (size_t igsb = 0; igsb < device_rr_gsb.get_num_gsb_unique_module(); ++igsb) {
const RRGSB& rr_gsb = device_rr_gsb.get_sb_unique_module(igsb);
for (t_rr_type cb_type : {CHANX, CHANY}) {
if (options.include_cb_content(cb_type)) {
write_rr_connection_block_to_xml(xml_dir_name, vpr_device_grid, vpr_device_annotation, rr_graph, rr_gsb, cb_type, options);
cb_counters[cb_type]++;
}
}
} }
} else { } else {
/* Output all GSB instances in the fabric (some instances may share the same module) */ /* Output all GSB instances in the fabric (some instances may share the same module) */
for (size_t ix = 0; ix < sb_range.x(); ++ix) { for (size_t ix = 0; ix < sb_range.x(); ++ix) {
for (size_t iy = 0; iy < sb_range.y(); ++iy) { for (size_t iy = 0; iy < sb_range.y(); ++iy) {
const RRGSB& rr_gsb = device_rr_gsb.get_gsb(ix, iy); const RRGSB& rr_gsb = device_rr_gsb.get_gsb(ix, iy);
write_rr_switch_block_to_xml(xml_dir_name, vpr_device_grid, vpr_device_annotation, rr_graph, rr_gsb, verbose); /* Write CBx, CBy, SB on need */
gsb_counter++; if (options.include_sb_content()) {
write_rr_switch_block_to_xml(xml_dir_name, vpr_device_grid, vpr_device_annotation, rr_graph, rr_gsb, options);
sb_counter++;
}
for (t_rr_type cb_type : {CHANX, CHANY}) {
if (options.include_cb_content(cb_type)) {
write_rr_connection_block_to_xml(xml_dir_name, vpr_device_grid, vpr_device_annotation, rr_graph, rr_gsb, cb_type, options);
cb_counters[cb_type]++;
}
}
} }
} }
} }
VTR_LOG("Output %lu XML files to directory '%s'\n", VTR_LOG("Output %lu Switch blocks to XML files under directory '%s'\n",
gsb_counter, sb_counter,
xml_dir_name.c_str()); xml_dir_name.c_str());
for (t_rr_type cb_type : {CHANX, CHANY}) {
VTR_LOG("Output %lu %s Connection blocks to XML files under directory '%s'\n",
cb_counters[cb_type],
cb_names[cb_type].c_str(),
xml_dir_name.c_str());
}
} }
} /* end namespace openfpga */ } /* end namespace openfpga */

View File

@ -9,6 +9,7 @@
#include "device_grid.h" #include "device_grid.h"
#include "vpr_device_annotation.h" #include "vpr_device_annotation.h"
#include "device_rr_gsb.h" #include "device_rr_gsb.h"
#include "rr_gsb_writer_option.h"
/******************************************************************** /********************************************************************
* Function declaration * Function declaration
@ -17,13 +18,11 @@
/* begin namespace openfpga */ /* begin namespace openfpga */
namespace openfpga { namespace openfpga {
void write_device_rr_gsb_to_xml(const char* sb_xml_dir, void write_device_rr_gsb_to_xml(const DeviceGrid& vpr_device_grid,
const DeviceGrid& vpr_device_grid,
const VprDeviceAnnotation& vpr_device_annotation, const VprDeviceAnnotation& vpr_device_annotation,
const RRGraph& rr_graph, const RRGraph& rr_graph,
const DeviceRRGSB& device_rr_gsb, const DeviceRRGSB& device_rr_gsb,
const bool& unique, const RRGSBWriterOption& options);
const bool& verbose);
} /* end namespace openfpga */ } /* end namespace openfpga */

View File

@ -213,6 +213,17 @@ ShellCommandId add_openfpga_write_gsb_command(openfpga::Shell<OpenfpgaContext>&
/* Add an option '--unique' */ /* Add an option '--unique' */
shell_cmd.add_option("unique", false, "Only output unique GSB blocks"); shell_cmd.add_option("unique", false, "Only output unique GSB blocks");
/* Add an option '--exclude_rr_info' */
shell_cmd.add_option("exclude_rr_info", false, "Exclude routing resource graph information from output files, e.g., node id as well as other attributes. This is useful to check the connection inside GSBs purely.");
/* Add an option '--exclude'*/
CommandOptionId opt_exclude = shell_cmd.add_option("exclude", false, "Exclude part of the GSB data to be outputted. Can be [``sb``|``cbx``|``cby``]. Users can exclude multiple parts by using a splitter ``,``");
shell_cmd.set_option_require_value(opt_exclude, openfpga::OPT_STRING);
/* Add an option '--gsb_names'*/
CommandOptionId opt_gsb_names = shell_cmd.add_option("gsb_names", false, "Specify the name of GSB to be outputted. Users can specify multiple GSBs by using a splitter ``,``");
shell_cmd.set_option_require_value(opt_gsb_names, openfpga::OPT_STRING);
/* Add an option '--verbose' */ /* Add an option '--verbose' */
shell_cmd.add_option("verbose", false, "Show verbose outputs"); shell_cmd.add_option("verbose", false, "Show verbose outputs");

View File

@ -34,17 +34,25 @@ int write_gsb(const OpenfpgaContext& openfpga_ctx,
VTR_ASSERT(false == cmd_context.option_value(cmd, opt_file).empty()); VTR_ASSERT(false == cmd_context.option_value(cmd, opt_file).empty());
CommandOptionId opt_unique = cmd.option("unique"); CommandOptionId opt_unique = cmd.option("unique");
CommandOptionId opt_exclude_rr_info = cmd.option("exclude_rr_info");
CommandOptionId opt_exclude = cmd.option("exclude");
CommandOptionId opt_gsb_names = cmd.option("gsb_names");
CommandOptionId opt_verbose = cmd.option("verbose"); CommandOptionId opt_verbose = cmd.option("verbose");
std::string sb_file_name = cmd_context.option_value(cmd, opt_file); /* Build the options for the writer */
RRGSBWriterOption options;
options.set_output_directory(cmd_context.option_value(cmd, opt_file));
options.set_unique_module_only(cmd_context.option_enable(cmd, opt_unique));
options.set_exclude_rr_info(cmd_context.option_enable(cmd, opt_exclude_rr_info));
options.set_exclude_content(cmd_context.option_value(cmd, opt_exclude));
options.set_include_gsb_list(cmd_context.option_value(cmd, opt_gsb_names));
options.set_verbose_output(cmd_context.option_enable(cmd, opt_verbose));
write_device_rr_gsb_to_xml(sb_file_name.c_str(), write_device_rr_gsb_to_xml(g_vpr_ctx.device().grid,
g_vpr_ctx.device().grid,
openfpga_ctx.vpr_device_annotation(), openfpga_ctx.vpr_device_annotation(),
g_vpr_ctx.device().rr_graph, g_vpr_ctx.device().rr_graph,
openfpga_ctx.device_rr_gsb(), openfpga_ctx.device_rr_gsb(),
cmd_context.option_enable(cmd, opt_unique), options);
cmd_context.option_enable(cmd, opt_verbose));
/* TODO: should identify the error code from internal function execution */ /* TODO: should identify the error code from internal function execution */
return CMD_EXEC_SUCCESS; return CMD_EXEC_SUCCESS;