diff --git a/openfpga/src/base/openfpga_build_fabric_template.h b/openfpga/src/base/openfpga_build_fabric_template.h index ba8db6e2c..2e5578c01 100644 --- a/openfpga/src/base/openfpga_build_fabric_template.h +++ b/openfpga/src/base/openfpga_build_fabric_template.h @@ -157,11 +157,11 @@ int build_fabric_template(T& openfpga_ctx, const Command& cmd, std::string fkey_fname = cmd_context.option_value(cmd, opt_write_fabric_key); VTR_ASSERT(false == fkey_fname.empty()); - curr_status = - write_fabric_key_to_xml_file(openfpga_ctx.module_graph(), fkey_fname, - openfpga_ctx.arch().config_protocol, - openfpga_ctx.blwl_shift_register_banks(), - cmd_context.option_enable(cmd, opt_verbose)); + curr_status = write_fabric_key_to_xml_file( + openfpga_ctx.module_graph(), fkey_fname, + openfpga_ctx.arch().config_protocol, + openfpga_ctx.blwl_shift_register_banks(), false, + cmd_context.option_enable(cmd, opt_verbose)); /* If there is any error, final status cannot be overwritten by a success * flag */ if (CMD_EXEC_SUCCESS != curr_status) { @@ -172,6 +172,32 @@ int build_fabric_template(T& openfpga_ctx, const Command& cmd, return final_status; } +/******************************************************************** + * Write fabric key of the module graph for FPGA device to a file + *******************************************************************/ +template +int write_fabric_key_template(const T& openfpga_ctx, const Command& cmd, + const CommandContext& cmd_context) { + CommandOptionId opt_verbose = cmd.option("verbose"); + CommandOptionId opt_include_module_keys = cmd.option("include_module_keys"); + + /* Check the option '--file' is enabled or not + * Actually, it must be enabled as the shell interface will check + * before reaching this fuction + */ + CommandOptionId opt_file = cmd.option("file"); + VTR_ASSERT(true == cmd_context.option_enable(cmd, opt_file)); + VTR_ASSERT(false == cmd_context.option_value(cmd, opt_file).empty()); + + /* Write fabric key to a file */ + return write_fabric_key_to_xml_file( + openfpga_ctx.module_graph(), cmd_context.option_value(cmd, opt_file), + openfpga_ctx.arch().config_protocol, + openfpga_ctx.blwl_shift_register_banks(), + cmd_context.option_enable(cmd, opt_include_module_keys), + cmd_context.option_enable(cmd, opt_verbose)); +} + /******************************************************************** * Write hierarchy of the module graph for FPGA device to a file *******************************************************************/ diff --git a/openfpga/src/base/openfpga_setup_command_template.h b/openfpga/src/base/openfpga_setup_command_template.h index 845873e7e..403372c4e 100644 --- a/openfpga/src/base/openfpga_setup_command_template.h +++ b/openfpga/src/base/openfpga_setup_command_template.h @@ -738,6 +738,40 @@ ShellCommandId add_add_fpga_core_to_fabric_command_template( return shell_cmd_id; } +/******************************************************************** + * - Add a command to Shell environment: write_fabric_key + * - Add associated options + * - Add command dependency + *******************************************************************/ +template +ShellCommandId add_write_fabric_key_command_template( + openfpga::Shell& shell, const ShellCommandClassId& cmd_class_id, + const std::vector& dependent_cmds, const bool& hidden) { + Command shell_cmd("write_fabric_key"); + /* Add an option '--file' in short '-f'*/ + CommandOptionId opt_file = + shell_cmd.add_option("file", true, "file path to the fabric key XML"); + shell_cmd.set_option_short_name(opt_file, "f"); + shell_cmd.set_option_require_value(opt_file, openfpga::OPT_STRING); + + /* Add an option '--include_module_keys'*/ + shell_cmd.add_option("include_module_keys", false, + "Include module-level keys"); + shell_cmd.add_option("verbose", false, "Show verbose outputs"); + + /* Add command to the Shell */ + ShellCommandId shell_cmd_id = shell.add_command( + shell_cmd, "write fabric key of the FPGA fabric to file", hidden); + shell.set_command_class(shell_cmd_id, cmd_class_id); + shell.set_command_const_execute_function(shell_cmd_id, + write_fabric_key_template); + + /* Add command dependency to the Shell */ + shell.set_command_dependency(shell_cmd_id, dependent_cmds); + + return shell_cmd_id; +} + template void add_setup_command_templates(openfpga::Shell& shell, const bool& hidden = false) { @@ -927,6 +961,16 @@ void add_setup_command_templates(openfpga::Shell& shell, shell, openfpga_setup_cmd_class, add_fpga_core_to_fabric_dependent_cmds, hidden); + /******************************** + * Command 'write_fabric_key' + */ + /* The 'write_fabric_key' command should NOT be executed before + * 'build_fabric' */ + std::vector write_fabric_key_dependent_cmds; + write_fabric_key_dependent_cmds.push_back(build_fabric_cmd_id); + add_write_fabric_key_command_template( + shell, openfpga_setup_cmd_class, write_fabric_key_dependent_cmds, hidden); + /******************************** * Command 'write_fabric_hierarchy' */ diff --git a/openfpga/src/fabric/fabric_key_writer.cpp b/openfpga/src/fabric/fabric_key_writer.cpp index d5e7ef978..9a7e41791 100644 --- a/openfpga/src/fabric/fabric_key_writer.cpp +++ b/openfpga/src/fabric/fabric_key_writer.cpp @@ -7,6 +7,7 @@ #include "vtr_time.h" /* Headers from openfpgautil library */ +#include "command_exit_codes.h" #include "openfpga_digest.h" /* Headers from archopenfpga library */ @@ -18,6 +19,51 @@ /* begin namespace openfpga */ namespace openfpga { +/*************************************************************************************** + * Add module-level keys to fabric key + ***************************************************************************************/ +static int add_module_keys_to_fabric_key(const ModuleManager& module_manager, + const ModuleId& curr_module, + FabricKey& fabric_key) { + /* Bypass top-level module */ + std::string module_name = module_manager.module_name(curr_module); + if (module_name == generate_fpga_top_module_name() || + module_name == generate_fpga_core_module_name()) { + return CMD_EXEC_SUCCESS; + } + /* Bypass modules which does not have any configurable children */ + if (module_manager.configurable_children(curr_module).empty()) { + return CMD_EXEC_SUCCESS; + } + /* Now create the module and add subkey one by one */ + FabricKeyModuleId key_module_id = fabric_key.create_module(module_name); + if (!key_module_id) { + return CMD_EXEC_FATAL_ERROR; + } + size_t num_config_child = + module_manager.configurable_children(curr_module).size(); + for (size_t ichild = 0; ichild < num_config_child; ++ichild) { + ModuleId child_module = + module_manager.configurable_children(curr_module)[ichild]; + size_t child_instance = + module_manager.configurable_child_instances(curr_module)[ichild]; + + FabricSubKeyId sub_key = fabric_key.create_module_key(key_module_id); + fabric_key.set_sub_key_name(sub_key, + module_manager.module_name(child_module)); + fabric_key.set_sub_key_value(sub_key, child_instance); + + if (false == + module_manager.instance_name(curr_module, child_module, child_instance) + .empty()) { + fabric_key.set_sub_key_alias( + sub_key, module_manager.instance_name(curr_module, child_module, + child_instance)); + } + } + return CMD_EXEC_SUCCESS; +} + /*************************************************************************************** * Write the fabric key of top module to an XML file * We will use the writer API in libfabrickey @@ -29,7 +75,9 @@ namespace openfpga { int write_fabric_key_to_xml_file( const ModuleManager& module_manager, const std::string& fname, const ConfigProtocol& config_protocol, - const MemoryBankShiftRegisterBanks& blwl_sr_banks, const bool& verbose) { + const MemoryBankShiftRegisterBanks& blwl_sr_banks, + const bool& include_module_keys, const bool& verbose) { + int err_code = CMD_EXEC_SUCCESS; std::string timer_message = std::string("Write fabric key to XML file '") + fname + std::string("'"); @@ -47,10 +95,18 @@ int write_fabric_key_to_xml_file( /* Find top-level module */ std::string top_module_name = generate_fpga_top_module_name(); ModuleId top_module = module_manager.find_module(top_module_name); - if (true != module_manager.valid_module_id(top_module)) { - VTR_LOGV_ERROR(verbose, "Unable to find the top-level module '%s'!\n", - top_module_name.c_str()); - return 1; + std::string core_module_name = generate_fpga_core_module_name(); + ModuleId core_module = module_manager.find_module(core_module_name); + if (!module_manager.valid_module_id(top_module) && + !module_manager.valid_module_id(core_module)) { + VTR_LOGV_ERROR( + verbose, "Unable to find the top-level/core-level module '%s' or '%s'!\n", + top_module_name.c_str(), core_module_name.c_str()); + return CMD_EXEC_FATAL_ERROR; + } + if (module_manager.valid_module_id(top_module) && + module_manager.valid_module_id(core_module)) { + top_module = core_module; } /* Build a fabric key database by visiting all the configurable children */ @@ -165,8 +221,19 @@ int write_fabric_key_to_xml_file( VTR_LOGV(verbose, "Created %lu regions and %lu keys for the top module %s.\n", num_regions, num_keys, top_module_name.c_str()); + /* Output module subkeys if specified */ + if (include_module_keys) { + for (ModuleId submodule : module_manager.modules()) { + err_code = + add_module_keys_to_fabric_key(module_manager, submodule, fabric_key); + if (err_code != CMD_EXEC_SUCCESS) { + return CMD_EXEC_FATAL_ERROR; + } + } + } + /* Call the XML writer for fabric key */ - int err_code = write_xml_fabric_key(fname.c_str(), fabric_key); + err_code = write_xml_fabric_key(fname.c_str(), fabric_key); return err_code; } diff --git a/openfpga/src/fabric/fabric_key_writer.h b/openfpga/src/fabric/fabric_key_writer.h index 34327d307..77413b812 100644 --- a/openfpga/src/fabric/fabric_key_writer.h +++ b/openfpga/src/fabric/fabric_key_writer.h @@ -20,7 +20,8 @@ namespace openfpga { int write_fabric_key_to_xml_file( const ModuleManager& module_manager, const std::string& fname, const ConfigProtocol& config_protocol, - const MemoryBankShiftRegisterBanks& blwl_sr_banks, const bool& verbose); + const MemoryBankShiftRegisterBanks& blwl_sr_banks, + const bool& include_module_keys, const bool& verbose); } /* end namespace openfpga */