[core] code complete for the core wrapper creator. Start debugging

This commit is contained in:
tangxifan 2023-06-18 19:17:42 -07:00
parent 8bc70b590a
commit c7ade72200
9 changed files with 201 additions and 10 deletions

View File

@ -12,6 +12,8 @@ namespace openfpga {
/* Top-level module name */
constexpr const char* FPGA_TOP_MODULE_NAME = "fpga_top";
constexpr const char* FPGA_CORE_MODULE_NAME = "fpga_core";
constexpr const char* FPGA_CORE_INSTANCE_NAME = "fpga_instance";
/* Configuration chain naming constant strings */
constexpr const char* CONFIGURABLE_MEMORY_CHAIN_IN_NAME = "ccff_head";

View File

@ -14,6 +14,7 @@
#include "fabric_hierarchy_writer.h"
#include "fabric_key_writer.h"
#include "globals.h"
#include "openfpga_naming.h"
#include "read_xml_fabric_key.h"
#include "vtr_log.h"
#include "vtr_time.h"
@ -237,10 +238,20 @@ int write_fabric_io_info_template(const T& openfpga_ctx, const Command& cmd,
template <class T>
int add_fpga_core_to_fabric_template(T& openfpga_ctx, const Command& cmd,
const CommandContext& cmd_context) {
CommandOptionId opt_frame_view = cmd.option("frame_view");
bool frame_view = cmd_context.option_enable(cmd, opt_frame_view);
CommandOptionId opt_verbose = cmd.option("verbose");
bool verbose_output = cmd_context.option_enable(cmd, opt_verbose);
return add_fpga_core_to_device_module_graph(openfpga_ctx.mutable_module_graph(), verbose_output);
CommandOptionId opt_inst_name = cmd.option("instance_name");
std::string core_inst_name = generate_fpga_core_instance_name();
if (true == cmd_context.option_enable(cmd, opt_inst_name)) {
core_inst_name = cmd_context.option_value(cmd, opt_inst_name);
}
return add_fpga_core_to_device_module_graph(
openfpga_ctx.mutable_module_graph(), core_inst_name, frame_view,
verbose_output);
}
} /* end namespace openfpga */

View File

@ -1399,6 +1399,22 @@ std::string generate_fpga_top_module_name() {
return std::string(FPGA_TOP_MODULE_NAME);
}
/*********************************************************************
* Generate the module name for the fpga core module
* We give a fixed name here, because it is independent from benchmark file
********************************************************************/
std::string generate_fpga_core_module_name() {
return std::string(FPGA_CORE_MODULE_NAME);
}
/*********************************************************************
* Generate the module name for the fpga core module
* We give a fixed name here, because it is independent from benchmark file
********************************************************************/
std::string generate_fpga_core_instance_name() {
return std::string(FPGA_CORE_INSTANCE_NAME);
}
/*********************************************************************
* Generate the netlist name for the top-level module
* The top-level module is actually the FPGA fabric

View File

@ -258,6 +258,10 @@ std::string generate_fpga_global_io_port_name(
std::string generate_fpga_top_module_name();
std::string generate_fpga_core_module_name();
std::string generate_fpga_core_instance_name();
std::string generate_fpga_top_netlist_name(const std::string& postfix);
std::string generate_const_value_module_name(const size_t& const_val);

View File

@ -703,13 +703,25 @@ ShellCommandId add_add_fpga_core_to_fabric_command_template(
const std::vector<ShellCommandId>& dependent_cmds, const bool& hidden) {
Command shell_cmd("add_fpga_core_to_fabric");
/* Add an option '--instance_name'*/
CommandOptionId opt_inst_name = shell_cmd.add_option(
"instance_name", false, "specify the instance of fpga_core under fpga_top");
shell_cmd.set_option_require_value(opt_inst_name, openfpga::OPT_STRING);
/* Add an option '--verbose' */
shell_cmd.add_option(
"frame_view", false,
"Build only frame view of the fabric (nets are skipped)");
/* Add an option '--verbose' */
shell_cmd.add_option("verbose", false, "Show verbose outputs");
/* Add command 'pb_pin_fixup' to the Shell */
ShellCommandId shell_cmd_id = shell.add_command(
shell_cmd,
"Add fpga_core as an intermediate layer to FPGA fabric. After this command, the fpga_top will remain the top-level module while there is a new module fpga_core under it. Under fpga_core, there will be the detailed building blocks",
"Add fpga_core as an intermediate layer to FPGA fabric. After this "
"command, the fpga_top will remain the top-level module while there is a "
"new module fpga_core under it. Under fpga_core, there will be the "
"detailed building blocks",
hidden);
shell.set_command_class(shell_cmd_id, cmd_class_id);
shell.set_command_execute_function(shell_cmd_id,
@ -906,8 +918,10 @@ void add_setup_command_templates(openfpga::Shell<T>& shell,
* 'build_fabric' */
std::vector<ShellCommandId> add_fpga_core_to_fabric_dependent_cmds;
add_fpga_core_to_fabric_dependent_cmds.push_back(build_fabric_cmd_id);
ShellCommandId add_fpga_core_to_fabric_cmd_id = add_add_fpga_core_to_fabric_command_template<T>(
shell, openfpga_setup_cmd_class, add_fpga_core_to_fabric_dependent_cmds, hidden);
ShellCommandId add_fpga_core_to_fabric_cmd_id =
add_add_fpga_core_to_fabric_command_template<T>(
shell, openfpga_setup_cmd_class, add_fpga_core_to_fabric_dependent_cmds,
hidden);
/********************************
* Command 'write_fabric_hierarchy'

View File

@ -20,6 +20,7 @@
#include "build_top_module.h"
#include "build_wire_modules.h"
#include "command_exit_codes.h"
#include "openfpga_naming.h"
/* begin namespace openfpga */
namespace openfpga {
@ -127,11 +128,15 @@ int build_device_module_graph(
}
/********************************************************************
* The main function to be called for adding the fpga_core wrapper to a FPGA fabric
* The main function to be called for adding the fpga_core wrapper to a FPGA
*fabric
* - Rename existing fpga_top to fpga_core
* - Create a wrapper module 'fpga_top' on the fpga_core
*******************************************************************/
int add_fpga_core_to_device_module_graph(ModuleManager& module_manager, const bool& verbose) {
int add_fpga_core_to_device_module_graph(ModuleManager& module_manager,
const std::string& core_inst_name,
const bool& frame_view,
const bool& verbose) {
int status = CMD_EXEC_SUCCESS;
/* Execute the module graph api */
@ -140,15 +145,24 @@ int add_fpga_core_to_device_module_graph(ModuleManager& module_manager, const bo
if (!module_manager.valid_module_id(top_module)) {
return CMD_EXEC_FATAL_ERROR;
}
/* TODO: Use a constant for the top_module name */
/* Rename existing top module to fpga_core */
module_manager.set_module_name(top_module, "fpga_core");
std::string core_module_name = generate_fpga_core_module_name();
module_manager.set_module_name(top_module, core_module_name);
VTR_LOGV(verbose, "Rename current top-level module '%s' to '%s'\n",
top_module_name.c_str(), core_module_name.c_str());
/* Create a wrapper module under the existing fpga_top */
ModuleId new_top_module = module_manager.create_wrapper(top_module, top_module_name),
ModuleId new_top_module = module_manager.create_wrapper_module(
top_module, top_module_name, core_inst_name, frame_view);
if (!module_manager.valid_module_id(new_top_module)) {
VTR_LOGV_ERROR(verbose,
"Failed to create a wrapper module '%s' on top of '%s'!\n",
top_module_name.c_str(), core_module_name.c_str());
return CMD_EXEC_FATAL_ERROR;
}
VTR_LOGV(verbose, "Created a wrapper module '%s' on top of '%s'\n",
top_module_name.c_str(), core_module_name.c_str());
return status;
}

View File

@ -23,7 +23,10 @@ int build_device_module_graph(
const bool& duplicate_grid_pin, const FabricKey& fabric_key,
const bool& generate_random_fabric_key, const bool& verbose);
int add_fpga_core_to_device_module_graph(ModuleManager& module_manager, const bool& verbose);
int add_fpga_core_to_device_module_graph(ModuleManager& module_manager,
const std::string& core_inst_name,
const bool& frame_view,
const bool& verbose);
} /* end namespace openfpga */

View File

@ -768,6 +768,14 @@ void ModuleManager::set_port_is_wire(const ModuleId& module,
port_is_wire_[module][port] = is_wire;
}
/* Set a port to be a wire */
void ModuleManager::set_port_is_wire(const ModuleId& module,
const ModulePortId& port_id,
const bool& is_wire) {
VTR_ASSERT(valid_module_port_id(module, port_id));
port_is_wire_[module][port_id] = is_wire;
}
/* Set a port to be a mappable I/O */
void ModuleManager::set_port_is_mappable_io(const ModuleId& module,
const ModulePortId& port_id,
@ -788,6 +796,14 @@ void ModuleManager::set_port_is_register(const ModuleId& module,
port_is_register_[module][port] = is_register;
}
/* Set a port to be a register */
void ModuleManager::set_port_is_register(const ModuleId& module,
const ModulePortId& port_id,
const bool& is_register) {
VTR_ASSERT(valid_module_port_id(module, port_id));
port_is_register_[module][port_id] = is_register;
}
/* Set the preprocessing flag for a port */
void ModuleManager::set_port_preproc_flag(const ModuleId& module,
const ModulePortId& port,
@ -1185,6 +1201,93 @@ ModuleNetSinkId ModuleManager::add_module_net_sink(
return net_sink;
}
ModuleId ModuleManager::create_wrapper_module(
const ModuleId& existing_module, const std::string& wrapper_module_name,
const std::string& instance_name, const bool& add_nets) {
/* Create a new module with the given name */
ModuleId wrapper_module = add_module(wrapper_module_name);
if (!wrapper_module) {
return wrapper_module;
}
/* Add the existing module as an instance */
add_child_module(wrapper_module, existing_module, false);
set_child_instance_name(wrapper_module, existing_module, 0, instance_name);
/* A fast-lookup on the port linking: wrapper_module port -> existing_module
* port */
std::map<ModulePortId, ModulePortId> port_map;
/* Herit ports */
for (ModulePortId existing_port : module_ports(existing_module)) {
/* Create new port */
BasicPort existing_port_info = module_port(existing_module, existing_port);
ModuleManager::e_module_port_type existing_port_type =
port_type(existing_module, existing_port);
ModulePortId new_port =
add_port(wrapper_module, existing_port_info, existing_port_type);
/* Set port attributes */
set_port_is_wire(wrapper_module, new_port,
port_is_wire(existing_module, existing_port));
set_port_is_mappable_io(
wrapper_module, new_port,
port_is_mappable_io(existing_module, existing_port));
set_port_is_register(wrapper_module, new_port,
port_is_register(existing_module, existing_port));
set_port_preproc_flag(wrapper_module, new_port,
port_preproc_flag(existing_module, existing_port));
/* Register in port mapping */
port_map[new_port] = existing_port;
}
/* Add nets */
if (!add_nets) {
return wrapper_module;
}
/* The number of nets are the sum of input and output pins */
size_t num_nets_to_reserve = 0;
for (ModulePortId new_port : module_ports(wrapper_module)) {
BasicPort new_port_info = module_port(wrapper_module, new_port);
num_nets_to_reserve += new_port_info.get_width();
}
reserve_module_nets(wrapper_module, num_nets_to_reserve);
for (ModulePortId new_port : module_ports(wrapper_module)) {
BasicPort new_port_info = module_port(wrapper_module, new_port);
/* Create new net */
ModuleNetId new_net = create_module_net(wrapper_module);
VTR_ASSERT(valid_module_net_id(wrapper_module, new_net));
/* For each input pin, create a new source */
ModuleManager::e_module_port_type new_port_type =
port_type(wrapper_module, new_port);
/* Check if the pin size are matching or not */
ModulePortId existing_port = port_map[new_port];
BasicPort existing_port_info = module_port(existing_module, existing_port);
VTR_ASSERT(existing_port_info == new_port_info);
reserve_module_net_sources(wrapper_module, new_net,
new_port_info.pins().size());
reserve_module_net_sinks(wrapper_module, new_net,
new_port_info.pins().size());
if (new_port_type !=
ModuleManager::e_module_port_type::MODULE_OUTPUT_PORT) {
for (auto pin : new_port_info.pins()) {
add_module_net_source(wrapper_module, new_net, wrapper_module, 0,
new_port, pin);
add_module_net_sink(wrapper_module, new_net, existing_module, 0,
existing_port, pin);
}
} else {
VTR_ASSERT_SAFE(new_port_type ==
ModuleManager::e_module_port_type::MODULE_OUTPUT_PORT);
for (auto pin : new_port_info.pins()) {
add_module_net_source(wrapper_module, new_net, existing_module, 0,
existing_port, pin);
add_module_net_sink(wrapper_module, new_net, wrapper_module, 0,
new_port, pin);
}
}
}
return wrapper_module;
}
/******************************************************************************
* Public Deconstructor
******************************************************************************/

View File

@ -317,6 +317,8 @@ class ModuleManager {
/* Set a port to be a wire */
void set_port_is_wire(const ModuleId& module, const std::string& port_name,
const bool& is_wire);
void set_port_is_wire(const ModuleId& module, const ModulePortId& port_id,
const bool& is_wire);
/* Set a port to be mappable to an I/O from users' implemenations */
void set_port_is_mappable_io(const ModuleId& module,
const ModulePortId& port_id,
@ -325,6 +327,8 @@ class ModuleManager {
void set_port_is_register(const ModuleId& module,
const std::string& port_name,
const bool& is_register);
void set_port_is_register(const ModuleId& module, const ModulePortId& port_id,
const bool& is_register);
/* Set the preprocessing flag for a port */
void set_port_preproc_flag(const ModuleId& module, const ModulePortId& port,
const std::string& preproc_flag);
@ -423,6 +427,26 @@ class ModuleManager {
const ModulePortId& sink_port,
const size_t& sink_pin);
/** @brief Create a wrapper module on an existing module. The wrapper module
* will herit all the ports with the same direction, width and names from the
* selected module. The wrapper module will contain the existing module. For
* example,
*
* Wrapper module
* +------------------------+
* | existing module |
* | +------------------+ |
* | | | |
* a ->+->+ a b-+--+-> b
* | | | |
* | +------------------+ |
* +------------------------+
*/
ModuleId create_wrapper_module(const ModuleId& existing_module,
const std::string& wrapper_module_name,
const std::string& instance_name,
const bool& add_nets);
public: /* Public deconstructors */
/* This is a strong function which will remove all the configurable children
* under a given parent module