[core] supporting io naming for verilog testbench generators

This commit is contained in:
tangxifan 2023-06-25 15:29:27 -07:00
parent 987a562e0f
commit 150653287d
13 changed files with 153 additions and 47 deletions

View File

@ -252,16 +252,15 @@ int add_fpga_core_to_fabric_template(T& openfpga_ctx, const Command& cmd,
}
/* Handle I/O naming rules if defined */
IoNameMap io_name_map;
CommandOptionId opt_io_naming = cmd.option("io_naming");
if (true == cmd_context.option_enable(cmd, opt_io_naming)) {
read_xml_io_name_map(cmd_context.option_value(cmd, opt_io_naming).c_str(),
io_name_map);
openfpga_ctx.mutable_io_name_map());
}
return add_fpga_core_to_device_module_graph(
openfpga_ctx.mutable_module_graph(), io_name_map, core_inst_name,
frame_view, verbose_output);
openfpga_ctx.mutable_module_graph(), openfpga_ctx.io_name_map(),
core_inst_name, frame_view, verbose_output);
}
} /* end namespace openfpga */

View File

@ -11,6 +11,7 @@
#include "fabric_bitstream.h"
#include "fabric_global_port_info.h"
#include "io_location_map.h"
#include "io_name_map.h"
#include "memory_bank_shift_register_banks.h"
#include "module_manager.h"
#include "mux_library.h"
@ -104,6 +105,7 @@ class OpenfpgaContext : public Context {
const openfpga::IoLocationMap& io_location_map() const {
return io_location_map_;
}
const openfpga::IoNameMap& io_name_map() const { return io_name_map_; }
const openfpga::FabricGlobalPortInfo& fabric_global_port_info() const {
return fabric_global_port_info_;
}
@ -162,6 +164,7 @@ class OpenfpgaContext : public Context {
openfpga::IoLocationMap& mutable_io_location_map() {
return io_location_map_;
}
openfpga::IoNameMap& mutable_io_name_map() { return io_name_map_; }
openfpga::FabricGlobalPortInfo& mutable_fabric_global_port_info() {
return fabric_global_port_info_;
}
@ -216,6 +219,7 @@ class OpenfpgaContext : public Context {
/* Fabric module graph */
openfpga::ModuleManager module_graph_;
openfpga::IoLocationMap io_location_map_;
openfpga::IoNameMap io_name_map_;
openfpga::FabricGlobalPortInfo fabric_global_port_info_;
/* Bitstream database */

View File

@ -77,6 +77,7 @@ int write_full_testbench_template(const T& openfpga_ctx, const Command& cmd,
const CommandContext& cmd_context) {
CommandOptionId opt_output_dir = cmd.option("file");
CommandOptionId opt_bitstream = cmd.option("bitstream");
CommandOptionId opt_dut_module = cmd.option("dut_module");
CommandOptionId opt_fabric_netlist = cmd.option("fabric_netlist_file_path");
CommandOptionId opt_pcf = cmd.option("pin_constraints_file");
CommandOptionId opt_bgf = cmd.option("bus_group_file");
@ -96,6 +97,7 @@ int write_full_testbench_template(const T& openfpga_ctx, const Command& cmd,
*/
VerilogTestbenchOption options;
options.set_output_directory(cmd_context.option_value(cmd, opt_output_dir));
options.set_dut_module(cmd_context.option_value(cmd, opt_dut_module));
options.set_fabric_netlist_file_path(
cmd_context.option_value(cmd, opt_fabric_netlist));
options.set_reference_benchmark_file_path(
@ -135,7 +137,8 @@ int write_full_testbench_template(const T& openfpga_ctx, const Command& cmd,
openfpga_ctx.fabric_bitstream(), openfpga_ctx.blwl_shift_register_banks(),
g_vpr_ctx.atom(), g_vpr_ctx.placement(), pin_constraints, bus_group,
cmd_context.option_value(cmd, opt_bitstream),
openfpga_ctx.io_location_map(), openfpga_ctx.fabric_global_port_info(),
openfpga_ctx.io_location_map(), openfpga_ctx.io_name_map(),
openfpga_ctx.fabric_global_port_info(),
openfpga_ctx.vpr_netlist_annotation(), openfpga_ctx.arch().circuit_lib,
openfpga_ctx.simulation_setting(), openfpga_ctx.arch().config_protocol,
options);
@ -150,6 +153,7 @@ int write_preconfigured_fabric_wrapper_template(
const T& openfpga_ctx, const Command& cmd,
const CommandContext& cmd_context) {
CommandOptionId opt_output_dir = cmd.option("file");
CommandOptionId opt_dut_module = cmd.option("dut_module");
CommandOptionId opt_fabric_netlist = cmd.option("fabric_netlist_file_path");
CommandOptionId opt_pcf = cmd.option("pin_constraints_file");
CommandOptionId opt_bgf = cmd.option("bus_group_file");
@ -166,6 +170,7 @@ int write_preconfigured_fabric_wrapper_template(
*/
VerilogTestbenchOption options;
options.set_output_directory(cmd_context.option_value(cmd, opt_output_dir));
options.set_dut_module(cmd_context.option_value(cmd, opt_dut_module));
options.set_fabric_netlist_file_path(
cmd_context.option_value(cmd, opt_fabric_netlist));
options.set_explicit_port_mapping(
@ -203,7 +208,8 @@ int write_preconfigured_fabric_wrapper_template(
return fpga_verilog_preconfigured_fabric_wrapper(
openfpga_ctx.module_graph(), openfpga_ctx.bitstream_manager(),
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_location_map(), openfpga_ctx.io_name_map(),
openfpga_ctx.fabric_global_port_info(),
openfpga_ctx.vpr_netlist_annotation(), openfpga_ctx.arch().circuit_lib,
openfpga_ctx.arch().config_protocol, options);
}

View File

@ -148,6 +148,7 @@ int fpga_verilog_full_testbench(
const AtomContext &atom_ctx, const PlacementContext &place_ctx,
const PinConstraints &pin_constraints, const BusGroup &bus_group,
const std::string &bitstream_file, const IoLocationMap &io_location_map,
const IoNameMap &io_name_map,
const FabricGlobalPortInfo &fabric_global_port_info,
const VprNetlistAnnotation &netlist_annotation,
const CircuitLibrary &circuit_lib,
@ -174,7 +175,7 @@ int fpga_verilog_full_testbench(
print_verilog_full_testbench(
module_manager, bitstream_manager, fabric_bitstream, blwl_sr_banks,
circuit_lib, config_protocol, fabric_global_port_info, atom_ctx, place_ctx,
pin_constraints, bus_group, bitstream_file, io_location_map,
pin_constraints, bus_group, bitstream_file, io_location_map, io_name_map,
netlist_annotation, netlist_name, top_testbench_file_path,
simulation_setting, options);
@ -197,6 +198,7 @@ int fpga_verilog_preconfigured_fabric_wrapper(
const BitstreamManager &bitstream_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 CircuitLibrary &circuit_lib, const ConfigProtocol &config_protocol,
@ -221,7 +223,7 @@ int fpga_verilog_preconfigured_fabric_wrapper(
status = print_verilog_preconfig_top_module(
module_manager, bitstream_manager, config_protocol, circuit_lib,
fabric_global_port_info, atom_ctx, place_ctx, pin_constraints, bus_group,
io_location_map, netlist_annotation, netlist_name,
io_location_map, io_name_map, netlist_annotation, netlist_name,
formal_verification_top_netlist_file_path, options);
return status;

View File

@ -18,6 +18,7 @@
#include "fabric_global_port_info.h"
#include "fabric_verilog_options.h"
#include "io_location_map.h"
#include "io_name_map.h"
#include "memory_bank_shift_register_banks.h"
#include "module_manager.h"
#include "mux_library.h"
@ -52,6 +53,7 @@ int fpga_verilog_full_testbench(
const AtomContext& atom_ctx, const PlacementContext& place_ctx,
const PinConstraints& pin_constraints, const BusGroup& bus_group,
const std::string& bitstream_file, const IoLocationMap& io_location_map,
const IoNameMap& io_name_map,
const FabricGlobalPortInfo& fabric_global_port_info,
const VprNetlistAnnotation& netlist_annotation,
const CircuitLibrary& circuit_lib,
@ -63,6 +65,7 @@ int fpga_verilog_preconfigured_fabric_wrapper(
const BitstreamManager& bitstream_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 CircuitLibrary& circuit_lib, const ConfigProtocol& config_protocol,

View File

@ -545,7 +545,7 @@ int print_verilog_preconfig_top_module(
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 VprNetlistAnnotation &netlist_annotation,
const IoNameMap &io_name_map, const VprNetlistAnnotation &netlist_annotation,
const std::string &circuit_name, const std::string &verilog_fname,
const VerilogTestbenchOption &options) {
std::string timer_message =
@ -577,20 +577,33 @@ int print_verilog_preconfig_top_module(
print_verilog_preconfig_top_module_ports(fp, circuit_name, atom_ctx,
netlist_annotation, bus_group);
/* 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));
/* Spot the dut 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;
}
/* Print internal wires */
print_verilog_preconfig_top_module_internal_wires(fp, module_manager,
top_module);
core_module);
/* Instanciate FPGA top-level module */
print_verilog_testbench_fpga_instance(
fp, module_manager, top_module,
fp, module_manager, top_module, core_module,
std::string(FORMAL_VERIFICATION_TOP_MODULE_UUT_NAME),
std::string(FORMAL_VERIFICATION_TOP_MODULE_PORT_POSTFIX),
std::string(FORMAL_VERIFICATION_TOP_MODULE_PORT_POSTFIX), io_name_map,
options.explicit_port_mapping());
/* Find clock ports in benchmark */
@ -600,7 +613,7 @@ int print_verilog_preconfig_top_module(
/* Connect FPGA top module global ports to constant or benchmark global
* signals! */
status = print_verilog_preconfig_top_module_connect_global_ports(
fp, module_manager, top_module, pin_constraints, global_ports,
fp, module_manager, core_module, pin_constraints, global_ports,
benchmark_clock_port_names);
if (CMD_EXEC_FATAL_ERROR == status) {
return status;
@ -608,7 +621,7 @@ int print_verilog_preconfig_top_module(
/* Connect I/Os to benchmark I/Os or constant driver */
print_verilog_testbench_connect_fpga_ios(
fp, module_manager, top_module, atom_ctx, place_ctx, io_location_map,
fp, module_manager, core_module, atom_ctx, place_ctx, io_location_map,
netlist_annotation, bus_group,
std::string(FORMAL_VERIFICATION_TOP_MODULE_PORT_POSTFIX), std::string(),
std::string(), std::vector<std::string>(),

View File

@ -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"
@ -33,7 +34,7 @@ int print_verilog_preconfig_top_module(
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 VprNetlistAnnotation& netlist_annotation,
const IoNameMap& io_name_map, const VprNetlistAnnotation& netlist_annotation,
const std::string& circuit_name, const std::string& verilog_fname,
const VerilogTestbenchOption& options);

View File

@ -3,6 +3,7 @@
******************************************************************************/
#include "verilog_testbench_options.h"
#include "openfpga_naming.h"
#include "vtr_assert.h"
#include "vtr_log.h"
@ -14,6 +15,7 @@ namespace openfpga {
*************************************************/
VerilogTestbenchOption::VerilogTestbenchOption() {
output_directory_.clear();
dut_module_ = "fpga_top";
fabric_netlist_file_path_.clear();
reference_benchmark_file_path_.clear();
print_preconfig_top_testbench_ = false;
@ -37,6 +39,8 @@ std::string VerilogTestbenchOption::output_directory() const {
return output_directory_;
}
std::string VerilogTestbenchOption::dut_module() const { return dut_module_; }
std::string VerilogTestbenchOption::fabric_netlist_file_path() const {
return fabric_netlist_file_path_;
}
@ -108,6 +112,19 @@ void VerilogTestbenchOption::set_output_directory(
output_directory_ = output_dir;
}
void VerilogTestbenchOption::set_dut_module(const std::string& dut_module) {
/* Precheck: only accept two legal names */
if (dut_module != generate_fpga_top_module_name() &&
dut_module != generate_fpga_core_module_name()) {
VTR_LOG_ERROR(
"Invalid module name '%s' for Design Under Test (DUT)! Expect [%s|%s]\n",
dut_module.c_str(), generate_fpga_top_module_name().c_str(),
generate_fpga_core_module_name().c_str());
exit(1);
}
dut_module_ = dut_module;
}
void VerilogTestbenchOption::set_fabric_netlist_file_path(
const std::string& fabric_netlist_file_path) {
fabric_netlist_file_path_ = fabric_netlist_file_path;

View File

@ -37,6 +37,7 @@ class VerilogTestbenchOption {
public: /* Public accessors */
std::string output_directory() const;
std::string dut_module() const;
std::string fabric_netlist_file_path() const;
std::string reference_benchmark_file_path() const;
bool fast_configuration() const;
@ -60,6 +61,7 @@ class VerilogTestbenchOption {
public: /* Public mutators */
void set_output_directory(const std::string& output_dir);
void set_dut_module(const std::string& dut_module);
/* The reference verilog file path is the key parameters that will have an
* impact on other options:
* - print_preconfig_top_testbench
@ -93,6 +95,7 @@ class VerilogTestbenchOption {
private: /* Internal Data */
std::string output_directory_;
std::string dut_module_;
std::string fabric_netlist_file_path_;
std::string reference_benchmark_file_path_;
bool fast_configuration_;

View File

@ -34,12 +34,11 @@ namespace openfpga {
.out(out_postfix>)
);
*******************************************************************/
void print_verilog_testbench_fpga_instance(std::fstream& fp,
const ModuleManager& module_manager,
const ModuleId& top_module,
const std::string& top_instance_name,
const std::string& net_postfix,
const bool& explicit_port_mapping) {
void print_verilog_testbench_fpga_instance(
std::fstream& fp, const ModuleManager& module_manager,
const ModuleId& top_module, const ModuleId& core_module,
const std::string& top_instance_name, const std::string& net_postfix,
const IoNameMap& io_name_map, const bool& explicit_port_mapping) {
/* Validate the file stream */
valid_file_stream(fp);
@ -47,8 +46,24 @@ void print_verilog_testbench_fpga_instance(std::fstream& fp,
print_verilog_comment(
fp, std::string("----- FPGA top-level module to be capsulated -----"));
/* 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;
}
/* Create an empty port-to-port name mapping, because we use default names */
std::map<std::string, BasicPort> port2port_name_map;
if (!require_io_naming) {
if (!net_postfix.empty()) {
for (const ModulePortId& module_port_id :
module_manager.module_ports(top_module)) {
@ -59,6 +74,35 @@ void print_verilog_testbench_fpga_instance(std::fstream& fp,
port2port_name_map[module_port.get_name()] = net_port;
}
}
} else {
VTR_ASSERT_SAFE(require_io_naming);
/* We walk through the ports under top module. Find renamed ports at
* core-level and use them as net names */
for (const ModulePortId& module_port_id :
module_manager.module_ports(top_module)) {
BasicPort module_port =
module_manager.module_port(top_module, module_port_id);
/* Bypass dummy port: the port does not exist at core module */
if (io_name_map.fpga_top_port_is_dummy(module_port)) {
ModulePortId core_module_port =
module_manager.find_module_port(core_module, module_port.get_name());
if (!module_manager.valid_module_port_id(core_module,
core_module_port)) {
continue;
}
}
/* Not a dummy port, if it is renamed, use the new name. Otherwise, keep
* the old name */
BasicPort net_port = io_name_map.fpga_core_port(module_port);
if (net_port.is_valid()) {
net_port.set_name(net_port.get_name() + net_postfix);
} else {
net_port = module_port;
net_port.set_name(module_port.get_name() + net_postfix);
}
port2port_name_map[module_port.get_name()] = net_port;
}
}
/* Use explicit port mapping for a clean instanciation */
print_verilog_module_instance(fp, module_manager, top_module,

View File

@ -12,6 +12,7 @@
#include "circuit_library.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 "simulation_setting.h"
@ -25,12 +26,11 @@
/* begin namespace openfpga */
namespace openfpga {
void print_verilog_testbench_fpga_instance(std::fstream& fp,
const ModuleManager& module_manager,
const ModuleId& top_module,
const std::string& top_instance_name,
const std::string& net_postfix,
const bool& explicit_port_mapping);
void print_verilog_testbench_fpga_instance(
std::fstream& fp, const ModuleManager& module_manager,
const ModuleId& top_module, const ModuleId& core_module,
const std::string& top_instance_name, const std::string& net_postfix,
const IoNameMap& io_name_map, const bool& explicit_port_mapping);
void print_verilog_testbench_benchmark_instance(
std::fstream& fp, const std::string& module_name,

View File

@ -2435,7 +2435,7 @@ int print_verilog_full_testbench(
const FabricGlobalPortInfo& global_ports, const AtomContext& atom_ctx,
const PlacementContext& place_ctx, const PinConstraints& pin_constraints,
const BusGroup& bus_group, const std::string& bitstream_file,
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 SimulationSetting& simulation_parameters,
@ -2465,10 +2465,23 @@ int print_verilog_full_testbench(
circuit_name;
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));
/* Spot the dut 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;
}
/* Preparation: find all the clock ports */
std::vector<std::string> clock_port_names =
@ -2492,7 +2505,7 @@ int print_verilog_full_testbench(
/* Start of testbench */
print_verilog_top_testbench_ports(
fp, module_manager, top_module, atom_ctx, netlist_annotation,
fp, module_manager, core_module, atom_ctx, netlist_annotation,
clock_port_names, global_ports, pin_constraints, simulation_parameters,
config_protocol, circuit_name, options);
@ -2522,7 +2535,7 @@ int print_verilog_full_testbench(
/* Generate stimuli for programming interface */
int status = CMD_EXEC_SUCCESS;
status = print_verilog_top_testbench_configuration_protocol_stimulus(
fp, config_protocol, simulation_parameters, module_manager, top_module,
fp, config_protocol, simulation_parameters, module_manager, core_module,
fast_configuration, bit_value_to_skip, fabric_bitstream, blwl_sr_banks,
prog_clock_period, VERILOG_SIM_TIMESCALE);
@ -2557,19 +2570,19 @@ int print_verilog_full_testbench(
/* Generate stimuli for global ports or connect them to existed signals */
print_verilog_top_testbench_global_ports_stimuli(
fp, module_manager, top_module, pin_constraints, config_protocol,
fp, module_manager, core_module, pin_constraints, config_protocol,
global_ports, simulation_parameters, active_global_prog_reset,
active_global_prog_set);
/* Instanciate FPGA top-level module */
print_verilog_testbench_fpga_instance(
fp, module_manager, top_module,
std::string(TOP_TESTBENCH_FPGA_INSTANCE_NAME), std::string(),
fp, module_manager, top_module, core_module,
std::string(TOP_TESTBENCH_FPGA_INSTANCE_NAME), std::string(), io_name_map,
explicit_port_mapping);
/* Connect I/Os to benchmark I/Os or constant driver */
print_verilog_testbench_connect_fpga_ios(
fp, module_manager, top_module, atom_ctx, place_ctx, io_location_map,
fp, module_manager, core_module, atom_ctx, place_ctx, io_location_map,
netlist_annotation, BusGroup(), std::string(),
std::string(TOP_TESTBENCH_SHARED_INPUT_POSTFIX),
std::string(TOP_TESTBENCH_FPGA_OUTPUT_POSTFIX), clock_port_names,
@ -2585,7 +2598,7 @@ int print_verilog_full_testbench(
/* load bitstream to FPGA fabric in a configuration phase */
print_verilog_full_testbench_bitstream(
fp, bitstream_file, config_protocol, apply_fast_configuration,
bit_value_to_skip, module_manager, top_module, bitstream_manager,
bit_value_to_skip, module_manager, core_module, bitstream_manager,
fabric_bitstream, blwl_sr_banks);
/* Add signal initialization:

View File

@ -14,6 +14,7 @@
#include "fabric_bitstream.h"
#include "fabric_global_port_info.h"
#include "io_location_map.h"
#include "io_name_map.h"
#include "memory_bank_shift_register_banks.h"
#include "module_manager.h"
#include "pin_constraints.h"
@ -38,7 +39,7 @@ int print_verilog_full_testbench(
const FabricGlobalPortInfo& global_ports, const AtomContext& atom_ctx,
const PlacementContext& place_ctx, const PinConstraints& pin_constraints,
const BusGroup& bus_group, const std::string& bitstream_file,
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 SimulationSetting& simulation_parameters,