diff --git a/openfpga/src/base/openfpga_verilog_command_template.h b/openfpga/src/base/openfpga_verilog_command_template.h index 5c9531c37..fa40faff9 100644 --- a/openfpga/src/base/openfpga_verilog_command_template.h +++ b/openfpga/src/base/openfpga_verilog_command_template.h @@ -291,7 +291,7 @@ ShellCommandId add_write_mock_fpga_wrapper_command_template( /* add an option '--top_module'*/ CommandOptionId top_module_opt = - shell_cmd.add_option("dut_module", false, + shell_cmd.add_option("top_module", false, "specify the top-level module name to be used in the " "wrapper, which matters the I/O names. Can be either " "fpga_top or fpga_core. By default, it is fpga_top."); diff --git a/openfpga/src/base/openfpga_verilog_template.h b/openfpga/src/base/openfpga_verilog_template.h index 6c7fc746b..d5b41d8e1 100644 --- a/openfpga/src/base/openfpga_verilog_template.h +++ b/openfpga/src/base/openfpga_verilog_template.h @@ -228,6 +228,7 @@ template int write_mock_fpga_wrapper_template(const T& openfpga_ctx, const Command& cmd, const CommandContext& cmd_context) { CommandOptionId opt_output_dir = cmd.option("file"); + CommandOptionId opt_top_module = cmd.option("top_module"); CommandOptionId opt_pcf = cmd.option("pin_constraints_file"); CommandOptionId opt_bgf = cmd.option("bus_group_file"); CommandOptionId opt_explicit_port_mapping = @@ -249,6 +250,10 @@ int write_mock_fpga_wrapper_template(const T& openfpga_ctx, const Command& cmd, options.set_time_stamp(!cmd_context.option_enable(cmd, opt_no_time_stamp)); options.set_verbose_output(cmd_context.option_enable(cmd, opt_verbose)); + if (true == cmd_context.option_enable(cmd, opt_top_module)) { + options.set_dut_module(cmd_context.option_value(cmd, opt_top_module)); + } + if (true == cmd_context.option_enable(cmd, opt_default_net_type)) { options.set_default_net_type( cmd_context.option_value(cmd, opt_default_net_type)); @@ -271,7 +276,7 @@ int write_mock_fpga_wrapper_template(const T& openfpga_ctx, const Command& cmd, return fpga_verilog_mock_fpga_wrapper( openfpga_ctx.module_graph(), g_vpr_ctx.atom(), g_vpr_ctx.placement(), pin_constraints, bus_group, openfpga_ctx.io_location_map(), - openfpga_ctx.fabric_global_port_info(), + openfpga_ctx.io_name_map(), openfpga_ctx.fabric_global_port_info(), openfpga_ctx.vpr_netlist_annotation(), options); } diff --git a/openfpga/src/fpga_verilog/verilog_api.cpp b/openfpga/src/fpga_verilog/verilog_api.cpp index 4690aa2e0..e5c58b5b4 100644 --- a/openfpga/src/fpga_verilog/verilog_api.cpp +++ b/openfpga/src/fpga_verilog/verilog_api.cpp @@ -237,6 +237,7 @@ int fpga_verilog_mock_fpga_wrapper( const ModuleManager &module_manager, const AtomContext &atom_ctx, const PlacementContext &place_ctx, const PinConstraints &pin_constraints, const BusGroup &bus_group, const IoLocationMap &io_location_map, + const IoNameMap &io_name_map, const FabricGlobalPortInfo &fabric_global_port_info, const VprNetlistAnnotation &netlist_annotation, const VerilogTestbenchOption &options) { @@ -261,8 +262,8 @@ int fpga_verilog_mock_fpga_wrapper( std::string netlist_file_path = src_dir_path + netlist_file_name; status = print_verilog_mock_fpga_wrapper( module_manager, fabric_global_port_info, atom_ctx, place_ctx, - pin_constraints, bus_group, io_location_map, netlist_annotation, - netlist_name, netlist_file_path, options); + pin_constraints, bus_group, io_location_map, io_name_map, + netlist_annotation, netlist_name, netlist_file_path, options); /* Add fname to the netlist name list */ NetlistId nlist_id = NetlistId::INVALID(); diff --git a/openfpga/src/fpga_verilog/verilog_api.h b/openfpga/src/fpga_verilog/verilog_api.h index db448aae5..3a590820c 100644 --- a/openfpga/src/fpga_verilog/verilog_api.h +++ b/openfpga/src/fpga_verilog/verilog_api.h @@ -75,6 +75,7 @@ int fpga_verilog_mock_fpga_wrapper( const ModuleManager& module_manager, const AtomContext& atom_ctx, const PlacementContext& place_ctx, const PinConstraints& pin_constraints, const BusGroup& bus_group, const IoLocationMap& io_location_map, + const IoNameMap& io_name_map, const FabricGlobalPortInfo& fabric_global_port_info, const VprNetlistAnnotation& netlist_annotation, const VerilogTestbenchOption& options); diff --git a/openfpga/src/fpga_verilog/verilog_mock_fpga_wrapper.cpp b/openfpga/src/fpga_verilog/verilog_mock_fpga_wrapper.cpp index a28b9ffaa..018ab3d77 100644 --- a/openfpga/src/fpga_verilog/verilog_mock_fpga_wrapper.cpp +++ b/openfpga/src/fpga_verilog/verilog_mock_fpga_wrapper.cpp @@ -44,7 +44,7 @@ static void print_verilog_mock_fpga_wrapper_connect_ios( std::fstream& fp, const ModuleManager& module_manager, const ModuleId& top_module, const AtomContext& atom_ctx, const PlacementContext& place_ctx, const IoLocationMap& io_location_map, - const PinConstraints& pin_constraints, + const IoNameMap& io_name_map, const PinConstraints& pin_constraints, const FabricGlobalPortInfo& global_ports, const VprNetlistAnnotation& netlist_annotation, const std::string& net_name_postfix, @@ -199,10 +199,17 @@ static void print_verilog_mock_fpga_wrapper_connect_ios( print_verilog_comment( fp, std::string("----- Blif Benchmark input " + block_name + " is mapped to FPGA IOPAD " + - module_mapped_io_port.get_name() + "[" + - std::to_string(io_index) + "] -----")); - print_verilog_wire_connection(fp, benchmark_io_port, - module_mapped_io_port, false); + module_mapped_io_port.to_verilog_string() + " -----")); + /* Consider possible I/O naming rules */ + BasicPort renamed_module_mapped_io_port = + io_name_map.fpga_top_port(module_mapped_io_port); + if (renamed_module_mapped_io_port.is_valid()) { + print_verilog_wire_connection(fp, benchmark_io_port, + renamed_module_mapped_io_port, false); + } else { + print_verilog_wire_connection(fp, benchmark_io_port, + module_mapped_io_port, false); + } } else { VTR_ASSERT(AtomBlockType::OUTPAD == atom_ctx.nlist.block_type(atom_blk)); benchmark_io_port.set_name( @@ -210,10 +217,17 @@ static void print_verilog_mock_fpga_wrapper_connect_ios( print_verilog_comment( fp, std::string("----- Blif Benchmark output " + block_name + " is mapped to FPGA IOPAD " + - module_mapped_io_port.get_name() + "[" + - std::to_string(io_index) + "] -----")); - print_verilog_wire_connection(fp, module_mapped_io_port, - benchmark_io_port, false); + module_mapped_io_port.to_verilog_string() + " -----")); + /* Consider possible I/O naming rules */ + BasicPort renamed_module_mapped_io_port = + io_name_map.fpga_top_port(module_mapped_io_port); + if (renamed_module_mapped_io_port.is_valid()) { + print_verilog_wire_connection(fp, renamed_module_mapped_io_port, + benchmark_io_port, false); + } else { + print_verilog_wire_connection(fp, module_mapped_io_port, + benchmark_io_port, false); + } } /* Mark this I/O has been used/wired */ @@ -250,8 +264,16 @@ static void print_verilog_mock_fpga_wrapper_connect_ios( std::vector default_values(module_unused_io_port.get_width(), unused_io_value); - print_verilog_wire_constant_values(fp, module_unused_io_port, - default_values); + /* Consider possible I/O naming rules */ + BasicPort renamed_module_unused_io_port = + io_name_map.fpga_top_port(module_unused_io_port); + if (renamed_module_unused_io_port.is_valid()) { + print_verilog_wire_constant_values(fp, renamed_module_unused_io_port, + default_values); + } else { + print_verilog_wire_constant_values(fp, module_unused_io_port, + default_values); + } } /* Add an empty line as a splitter */ @@ -267,7 +289,7 @@ static void print_verilog_mock_fpga_wrapper_connect_ios( static int print_verilog_mock_fpga_wrapper_connect_global_ports( std::fstream& fp, const ModuleManager& module_manager, const ModuleId& top_module, const PinConstraints& pin_constraints, - const FabricGlobalPortInfo& fabric_global_ports, + const FabricGlobalPortInfo& fabric_global_ports, const IoNameMap& io_name_map, const std::vector& benchmark_clock_port_names) { /* Validate the file stream */ valid_file_stream(fp); @@ -330,8 +352,16 @@ static int print_verilog_mock_fpga_wrapper_connect_global_ports( clock_name_to_connect += std::string(APPINST_PORT_POSTFIX); BasicPort benchmark_clock_pin(clock_name_to_connect, 1); - print_verilog_wire_connection(fp, benchmark_clock_pin, module_clock_pin, - false); + /* If io naming is applicable, just consider the renaming port */ + BasicPort actual_module_clock_pin = + io_name_map.fpga_top_port(module_clock_pin); + if (!actual_module_clock_pin.is_valid()) { + print_verilog_wire_connection(fp, benchmark_clock_pin, + module_clock_pin, false); + } else { + print_verilog_wire_connection(fp, benchmark_clock_pin, + actual_module_clock_pin, false); + } } /* Finish, go to the next */ continue; @@ -363,8 +393,16 @@ static int print_verilog_mock_fpga_wrapper_connect_global_ports( if ((false == pin_constraints.unconstrained_net(constrained_net_name)) && (false == pin_constraints.unmapped_net(constrained_net_name))) { BasicPort benchmark_pin(constrained_net_name, 1); - print_verilog_wire_connection(fp, benchmark_pin, module_global_pin, - false); + /* If io naming is applicable, just consider the renaming port */ + BasicPort actual_module_global_pin = + io_name_map.fpga_top_port(module_global_pin); + if (!actual_module_global_pin.is_valid()) { + print_verilog_wire_connection(fp, benchmark_pin, module_global_pin, + false); + } else { + print_verilog_wire_connection(fp, benchmark_pin, + actual_module_global_pin, false); + } } } } @@ -407,7 +445,7 @@ int print_verilog_mock_fpga_wrapper( const ModuleManager& module_manager, const FabricGlobalPortInfo& global_ports, const AtomContext& atom_ctx, const PlacementContext& place_ctx, const PinConstraints& pin_constraints, const BusGroup& bus_group, - const IoLocationMap& io_location_map, + const IoLocationMap& io_location_map, const IoNameMap& io_name_map, const VprNetlistAnnotation& netlist_annotation, const std::string& circuit_name, const std::string& verilog_fname, const VerilogTestbenchOption& options) { @@ -434,9 +472,37 @@ int print_verilog_mock_fpga_wrapper( print_verilog_file_header(fp, title, options.time_stamp()); /* Find the top_module */ - ModuleId top_module = - module_manager.find_module(generate_fpga_top_module_name()); - VTR_ASSERT(true == module_manager.valid_module_id(top_module)); + ModuleId top_module = module_manager.find_module(options.dut_module()); + if (!module_manager.valid_module_id(top_module)) { + VTR_LOG_ERROR( + "Unable to find the DUT module '%s'. Please check if you create " + "dedicated module when building the fabric!\n", + options.dut_module().c_str()); + return CMD_EXEC_FATAL_ERROR; + } + /* Note that we always need the core module as it contains the original port + * names before possible renaming at top-level module. If there is no core + * module, it means that the current top module is the core module */ + ModuleId core_module = + module_manager.find_module(generate_fpga_core_module_name()); + if (!module_manager.valid_module_id(core_module)) { + core_module = top_module; + } + + /* Precheck on the top module and decide if we need to consider I/O naming + * - If we do have a fpga_core module added, and dut is fpga_top, we need a + * I/O naming + * - If we do NOT have a fpga_core module added, and dut is fpga_top, we do + * NOT need a I/O naming + * - If we do have a fpga_core module added, and dut is fpga_core, we do NOT + * need a I/O naming + * - If we do NOT have a fpga_core module added, and dut is fpga_core, it + * should error out earlier. + */ + bool require_io_naming = false; + if (top_module != core_module) { + require_io_naming = true; + } /* Print module declaration */ print_verilog_module_declaration(fp, module_manager, top_module, @@ -466,16 +532,17 @@ int print_verilog_mock_fpga_wrapper( /* Connect FPGA top module global ports to constant or benchmark global * signals! */ status = print_verilog_mock_fpga_wrapper_connect_global_ports( - fp, module_manager, top_module, pin_constraints, global_ports, - benchmark_clock_port_names); + fp, module_manager, core_module, pin_constraints, global_ports, + require_io_naming ? io_name_map : IoNameMap(), benchmark_clock_port_names); if (CMD_EXEC_FATAL_ERROR == status) { return status; } /* Connect I/Os to benchmark I/Os or constant driver */ print_verilog_mock_fpga_wrapper_connect_ios( - fp, module_manager, top_module, atom_ctx, place_ctx, io_location_map, - pin_constraints, global_ports, netlist_annotation, std::string(), + fp, module_manager, core_module, atom_ctx, place_ctx, io_location_map, + require_io_naming ? io_name_map : IoNameMap(), pin_constraints, + global_ports, netlist_annotation, std::string(), std::string(APPINST_PORT_POSTFIX), std::string(APPINST_PORT_POSTFIX), benchmark_clock_port_names, (size_t)VERILOG_DEFAULT_SIGNAL_INIT_VALUE); diff --git a/openfpga/src/fpga_verilog/verilog_mock_fpga_wrapper.h b/openfpga/src/fpga_verilog/verilog_mock_fpga_wrapper.h index 62f2f5d71..4632811a6 100644 --- a/openfpga/src/fpga_verilog/verilog_mock_fpga_wrapper.h +++ b/openfpga/src/fpga_verilog/verilog_mock_fpga_wrapper.h @@ -13,6 +13,7 @@ #include "config_protocol.h" #include "fabric_global_port_info.h" #include "io_location_map.h" +#include "io_name_map.h" #include "module_manager.h" #include "pin_constraints.h" #include "verilog_testbench_options.h" @@ -30,7 +31,7 @@ int print_verilog_mock_fpga_wrapper( const ModuleManager& module_manager, const FabricGlobalPortInfo& global_ports, const AtomContext& atom_ctx, const PlacementContext& place_ctx, const PinConstraints& pin_constraints, const BusGroup& bus_group, - const IoLocationMap& io_location_map, + const IoLocationMap& io_location_map, const IoNameMap& io_name_map, const VprNetlistAnnotation& netlist_annotation, const std::string& circuit_name, const std::string& verilog_fname, const VerilogTestbenchOption& options); diff --git a/openfpga/src/utils/fabric_global_port_info_utils.cpp b/openfpga/src/utils/fabric_global_port_info_utils.cpp index 533df628f..aaba4b123 100644 --- a/openfpga/src/utils/fabric_global_port_info_utils.cpp +++ b/openfpga/src/utils/fabric_global_port_info_utils.cpp @@ -74,10 +74,16 @@ bool port_is_fabric_global_reset_port( const FabricGlobalPortInfo& fabric_global_port_info, const ModuleManager& module_manager, const BasicPort& port) { /* Find the top_module: the fabric global ports are always part of the ports - * of the top module */ + * of the top/core module. If there is a core module, we should consider core + * only */ ModuleId top_module = module_manager.find_module(generate_fpga_top_module_name()); VTR_ASSERT(true == module_manager.valid_module_id(top_module)); + ModuleId core_module = + module_manager.find_module(generate_fpga_core_module_name()); + if (module_manager.valid_module_id(core_module)) { + top_module = core_module; + } for (const FabricGlobalPortId& fabric_global_port_id : fabric_global_port_info.global_ports()) { @@ -107,10 +113,16 @@ FabricGlobalPortId find_fabric_global_port( const FabricGlobalPortInfo& fabric_global_port_info, const ModuleManager& module_manager, const BasicPort& port) { /* Find the top_module: the fabric global ports are always part of the ports - * of the top module */ + * of the top/core module. If there is a core module, we should consider core + * only */ ModuleId top_module = module_manager.find_module(generate_fpga_top_module_name()); VTR_ASSERT(true == module_manager.valid_module_id(top_module)); + ModuleId core_module = + module_manager.find_module(generate_fpga_core_module_name()); + if (module_manager.valid_module_id(core_module)) { + top_module = core_module; + } for (const FabricGlobalPortId& fabric_global_port_id : fabric_global_port_info.global_ports()) {