[core] rework fabric hierarchy writer

This commit is contained in:
tangxifan 2024-05-02 18:05:38 -07:00
parent fddb700d7b
commit 4d3447f773
4 changed files with 124 additions and 35 deletions

View File

@ -270,6 +270,7 @@ template <class T>
int write_fabric_hierarchy_template(const T& openfpga_ctx, const Command& cmd, int write_fabric_hierarchy_template(const T& openfpga_ctx, const Command& cmd,
const CommandContext& cmd_context) { const CommandContext& cmd_context) {
CommandOptionId opt_verbose = cmd.option("verbose"); CommandOptionId opt_verbose = cmd.option("verbose");
CommandOptionId opt_exclude_empty_modules = cmd.option("exclude_empty_modules");
/* Check the option '--file' is enabled or not /* Check the option '--file' is enabled or not
* Actually, it must be enabled as the shell interface will check * Actually, it must be enabled as the shell interface will check
@ -279,6 +280,18 @@ int write_fabric_hierarchy_template(const T& openfpga_ctx, const Command& cmd,
VTR_ASSERT(true == cmd_context.option_enable(cmd, opt_file)); VTR_ASSERT(true == cmd_context.option_enable(cmd, opt_file));
VTR_ASSERT(false == cmd_context.option_value(cmd, opt_file).empty()); VTR_ASSERT(false == cmd_context.option_value(cmd, opt_file).empty());
CommandOptionId opt_module = cmd.option("module");
std::string root_module = generate_fpga_top_module_name();
if (true == cmd_context.option_enable(cmd, opt_module)) {
root_module = cmd_context.option_value(cmd, opt_module);
}
CommandOptionId opt_filter = cmd.option("filter");
std::string filter("*");
if (true == cmd_context.option_enable(cmd, opt_filter)) {
filter = cmd_context.option_value(cmd, opt_filter);
}
/* Default depth requirement, will not stop until the leaf */ /* Default depth requirement, will not stop until the leaf */
int depth = -1; int depth = -1;
CommandOptionId opt_depth = cmd.option("depth"); CommandOptionId opt_depth = cmd.option("depth");
@ -296,8 +309,14 @@ int write_fabric_hierarchy_template(const T& openfpga_ctx, const Command& cmd,
/* Write hierarchy to a file */ /* Write hierarchy to a file */
return write_fabric_hierarchy_to_text_file( return write_fabric_hierarchy_to_text_file(
openfpga_ctx.module_graph(), openfpga_ctx.module_name_map(), hie_file_name, openfpga_ctx.module_graph(),
size_t(depth), cmd_context.option_enable(cmd, opt_verbose)); openfpga_ctx.module_name_map(),
hie_file_name,
root_module,
filter,
size_t(depth),
cmd_context.option_enable(cmd, opt_exclude_empty_modules),
cmd_context.option_enable(cmd, opt_verbose));
} }
/******************************************************************** /********************************************************************

View File

@ -461,12 +461,22 @@ ShellCommandId add_write_fabric_hierarchy_command_template(
shell_cmd.set_option_short_name(opt_file, "f"); shell_cmd.set_option_short_name(opt_file, "f");
shell_cmd.set_option_require_value(opt_file, openfpga::OPT_STRING); shell_cmd.set_option_require_value(opt_file, openfpga::OPT_STRING);
/* Add an option '--module' */
CommandOptionId opt_module = shell_cmd.add_option(
"module", false, "Specify the root module name(s) which should be considered. By default, it is fpga_top. Regular expression is supported");
shell_cmd.set_option_require_value(opt_module, openfpga::OPT_STRING);
CommandOptionId opt_filter = shell_cmd.add_option(
"filter", false, "Specify the filter which allows user to select modules to appear under each root module tree. By default, it is *. Regular expression is supported");
shell_cmd.set_option_require_value(opt_filter, openfpga::OPT_STRING);
/* Add an option '--depth' */ /* Add an option '--depth' */
CommandOptionId opt_depth = shell_cmd.add_option( CommandOptionId opt_depth = shell_cmd.add_option(
"depth", false, "depth", false,
"Specify the depth of hierarchy to which the writer should stop"); "Specify the depth of hierarchy to which the writer should stop");
shell_cmd.set_option_require_value(opt_depth, openfpga::OPT_INT); shell_cmd.set_option_require_value(opt_depth, openfpga::OPT_INT);
shell_cmd.add_option("exclude_empty_modules", false, "Exclude modules with no qualified children (match the names defined through filter) from the output file");
/* 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

@ -1,6 +1,7 @@
/*************************************************************************************** /***************************************************************************************
* Output internal structure of Module Graph hierarchy to file formats * Output internal structure of Module Graph hierarchy to file formats
***************************************************************************************/ ***************************************************************************************/
#include <regex>
/* Headers from vtrutil library */ /* Headers from vtrutil library */
#include "vtr_assert.h" #include "vtr_assert.h"
#include "vtr_log.h" #include "vtr_log.h"
@ -10,6 +11,7 @@
#include "fabric_hierarchy_writer.h" #include "fabric_hierarchy_writer.h"
#include "openfpga_digest.h" #include "openfpga_digest.h"
#include "openfpga_naming.h" #include "openfpga_naming.h"
#include "command_exit_codes.h"
/* begin namespace openfpga */ /* begin namespace openfpga */
namespace openfpga { namespace openfpga {
@ -23,36 +25,54 @@ namespace openfpga {
static int rec_output_module_hierarchy_to_text_file( static int rec_output_module_hierarchy_to_text_file(
std::fstream& fp, const size_t& hie_depth_to_stop, std::fstream& fp, const size_t& hie_depth_to_stop,
const size_t& current_hie_depth, const ModuleManager& module_manager, const size_t& current_hie_depth, const ModuleManager& module_manager,
const ModuleId& parent_module, const bool& verbose) { const ModuleId& parent_module,
const std::string& module_name_filter,
const bool& verbose) {
/* Stop if hierarchy depth is beyond the stop line */ /* Stop if hierarchy depth is beyond the stop line */
if (hie_depth_to_stop < current_hie_depth) { if (hie_depth_to_stop < current_hie_depth) {
return 0; return CMD_EXEC_SUCCESS;
} }
if (false == valid_file_stream(fp)) { if (false == valid_file_stream(fp)) {
return 2; return CMD_EXEC_FATAL_ERROR;
} }
/* Iterate over all the child module */ /* Iterate over all the child module */
for (const ModuleId& child_module : for (const ModuleId& child_module :
module_manager.child_modules(parent_module)) { module_manager.child_modules(parent_module)) {
if (false == write_space_to_file(fp, current_hie_depth * 2)) { if (false == write_space_to_file(fp, current_hie_depth * 2)) {
return 2; return CMD_EXEC_FATAL_ERROR;
} }
if (true != module_manager.valid_module_id(child_module)) { if (true != module_manager.valid_module_id(child_module)) {
VTR_LOGV_ERROR(verbose, "Unable to find the child module '%u'!\n", VTR_LOGV_ERROR(verbose, "Unable to find the child module '%s' under its parent '%s'!\n",
size_t(child_module)); module_manager.module_name(child_module).c_str(),
return 1; module_manager.module_name(parent_module).c_str());
return CMD_EXEC_FATAL_ERROR;
} }
/* Filter out the names which do not match the pattern */
std::string child_module_name = module_manager.module_name(child_module);
std::string pattern = module_name_filter;
std::regex star_replace("\\*");
std::regex questionmark_replace("\\?");
std::string wildcard_pattern =
std::regex_replace(std::regex_replace(pattern, star_replace, ".*"),
questionmark_replace, ".");
std::regex wildcard_regex(wildcard_pattern);
if (!std::regex_match(child_module_name, wildcard_regex)) {
continue;
}
if (hie_depth_to_stop == current_hie_depth || module_manager.child_modules(child_module).empty()) {
fp << "- "; fp << "- ";
}
fp << module_manager.module_name(child_module); fp << module_manager.module_name(child_module);
/* If this is the leaf node, we leave a new line /* If this is the leaf node, we leave a new line
* Otherwise, we will leave a ':' to be compatible to YAML file format * Otherwise, we will leave a ':' to be compatible to YAML file format
*/ */
if ((0 != module_manager.child_modules(child_module).size()) && if ((!module_manager.child_modules(child_module).empty()) &&
(hie_depth_to_stop >= current_hie_depth + 1)) { (hie_depth_to_stop >= current_hie_depth + 1)) {
fp << ":"; fp << ":";
} }
@ -62,13 +82,13 @@ static int rec_output_module_hierarchy_to_text_file(
int status = rec_output_module_hierarchy_to_text_file( int status = rec_output_module_hierarchy_to_text_file(
fp, hie_depth_to_stop, fp, hie_depth_to_stop,
current_hie_depth + 1, /* Increment the depth for the next level */ current_hie_depth + 1, /* Increment the depth for the next level */
module_manager, child_module, verbose); module_manager, child_module, module_name_filter, verbose);
if (0 != status) { if (status != CMD_EXEC_SUCCESS) {
return status; return status;
} }
} }
return 0; return CMD_EXEC_SUCCESS;
} }
/*************************************************************************************** /***************************************************************************************
@ -86,7 +106,10 @@ static int rec_output_module_hierarchy_to_text_file(
int write_fabric_hierarchy_to_text_file(const ModuleManager& module_manager, int write_fabric_hierarchy_to_text_file(const ModuleManager& module_manager,
const ModuleNameMap& module_name_map, const ModuleNameMap& module_name_map,
const std::string& fname, const std::string& fname,
const std::string& root_module_names,
const std::string& module_name_filter,
const size_t& hie_depth_to_stop, const size_t& hie_depth_to_stop,
const bool& exclude_empty_modules,
const bool& verbose) { const bool& verbose) {
std::string timer_message = std::string timer_message =
std::string("Write fabric hierarchy to plain-text file '") + fname + std::string("Write fabric hierarchy to plain-text file '") + fname +
@ -111,30 +134,63 @@ int write_fabric_hierarchy_to_text_file(const ModuleManager& module_manager,
/* Validate the file stream */ /* Validate the file stream */
check_file_stream(fname.c_str(), fp); check_file_stream(fname.c_str(), fp);
/* Find top-level module */ size_t cnt = 0;
std::string top_module_name = /* Use regular expression to capture the module whose name matches the pattern
module_name_map.name(generate_fpga_top_module_name()); */
ModuleId top_module = module_manager.find_module(top_module_name); for (ModuleId curr_module : module_manager.modules()) {
if (true != module_manager.valid_module_id(top_module)) { std::string curr_module_name = module_manager.module_name(curr_module);
VTR_LOGV_ERROR(verbose, "Unable to find the top-level module '%s'!\n", std::string pattern = root_module_names;
top_module_name.c_str()); std::regex star_replace("\\*");
return 1; std::regex questionmark_replace("\\?");
std::string wildcard_pattern =
std::regex_replace(std::regex_replace(pattern, star_replace, ".*"),
questionmark_replace, ".");
std::regex wildcard_regex(wildcard_pattern);
if (!std::regex_match(curr_module_name, wildcard_regex)) {
continue;
}
/* Filter out module without children if required */
if (exclude_empty_modules) {
bool expect_empty_module = true;
for (const ModuleId& child_module :
module_manager.child_modules(curr_module)) {
/* Filter out the names which do not match the pattern */
std::string child_module_name = module_manager.module_name(child_module);
std::string pattern = module_name_filter;
std::regex star_replace("\\*");
std::regex questionmark_replace("\\?");
std::string wildcard_pattern =
std::regex_replace(std::regex_replace(pattern, star_replace, ".*"),
questionmark_replace, ".");
std::regex wildcard_regex(wildcard_pattern);
if (std::regex_match(child_module_name, wildcard_regex)) {
expect_empty_module = false;
break;
}
}
if (expect_empty_module) {
continue;
}
} }
/* Record current depth of module: top module is the root with 0 depth */ /* Record current depth of module: top module is the root with 0 depth */
size_t hie_depth = 0; size_t hie_depth = 0;
if (hie_depth_to_stop < hie_depth) { fp << curr_module_name << ":"
return 0;
}
fp << top_module_name << ":"
<< "\n"; << "\n";
/* Visit child module recursively and output the hierarchy */ /* Visit child module recursively and output the hierarchy */
int err_code = rec_output_module_hierarchy_to_text_file( int err_code = rec_output_module_hierarchy_to_text_file(
fp, hie_depth_to_stop, hie_depth + 1, /* Start with level 1 */ fp, hie_depth_to_stop, hie_depth + 1, /* Start with level 1 */
module_manager, top_module, verbose); module_manager, curr_module, module_name_filter, exclude_empty_modules, verbose);
/* Catch error code and exit if required */
cnt++;
}
if (cnt == 0) {
VTR_LOGV_ERROR(verbose, "Unable to find any module matching the root module name pattern '%s'!\n",
root_module_names.c_str());
return CMD_EXEC_FATAL_ERROR;
}
/* close a file */ /* close a file */
fp.close(); fp.close();

View File

@ -17,7 +17,11 @@ namespace openfpga {
int write_fabric_hierarchy_to_text_file(const ModuleManager& module_manager, int write_fabric_hierarchy_to_text_file(const ModuleManager& module_manager,
const ModuleNameMap& module_name_map, const ModuleNameMap& module_name_map,
const std::string& fname, const std::string& fname,
const std::string& root_module_names,
const std::string& module_name_filter,
const size_t& hie_depth_to_stop, const size_t& hie_depth_to_stop,
const bool& use_list_in_leaf,
const bool& exclude_empty_modules,
const bool& verbose); const bool& verbose);
} /* end namespace openfpga */ } /* end namespace openfpga */