[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, 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 ``,``.
When specified, only the GSBs whose names match the list will be outputted to files.
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,
- ``--gsb_list [gsb_2__4_, gsb_3__2_]``
- ``--gsb_list gsb_2__4_``
- ``--gsb_names [gsb_2__4_, gsb_3__2_]``
- ``--gsb_names gsb_2__4_``
.. 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 RRGraph& rr_graph,
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 */
std::string fname(fname_prefix);
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
* in a DeviceRRGSB to XML format
* Output internal structure (only the connection block part) of a RRGSB 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 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 RRGraph& rr_graph,
const DeviceRRGSB& device_rr_gsb,
const bool& unique,
const bool& verbose) {
std::string xml_dir_name = format_dir_path(std::string(sb_xml_dir));
const RRGSBWriterOption& options) {
std::string xml_dir_name = format_dir_path(options.output_directory);
/* Create directories */
create_directory(xml_dir_name);
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 */
if (unique) {
if (options.unique_module_only()) {
/* Only output unique GSB modules */
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) {
const RRGSB& rr_gsb = device_rr_gsb.get_gsb_unique_module(igsb);
write_rr_switch_block_to_xml(xml_dir_name, vpr_device_grid, vpr_device_annotation, rr_graph, rr_gsb, verbose);
gsb_counter++;
const RRGSB& rr_gsb = device_rr_gsb.get_sb_unique_module(igsb);
/* Write CBx, CBy, SB on need */
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 {
/* 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 iy = 0; iy < sb_range.y(); ++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);
gsb_counter++;
/* Write CBx, CBy, SB on need */
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",
gsb_counter,
VTR_LOG("Output %lu Switch blocks to XML files under directory '%s'\n",
sb_counter,
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 */

View File

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

View File

@ -213,6 +213,17 @@ ShellCommandId add_openfpga_write_gsb_command(openfpga::Shell<OpenfpgaContext>&
/* Add an option '--unique' */
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' */
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());
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");
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(),
g_vpr_ctx.device().grid,
write_device_rr_gsb_to_xml(g_vpr_ctx.device().grid,
openfpga_ctx.vpr_device_annotation(),
g_vpr_ctx.device().rr_graph,
openfpga_ctx.device_rr_gsb(),
cmd_context.option_enable(cmd, opt_unique),
cmd_context.option_enable(cmd, opt_verbose));
options);
/* TODO: should identify the error code from internal function execution */
return CMD_EXEC_SUCCESS;