[core] add a new option for simulator type to verilog full testbench generator

This commit is contained in:
tangxifan 2023-12-08 13:07:25 -08:00
parent 0e945d6e71
commit 5e181cbe72
7 changed files with 101 additions and 12 deletions

View File

@ -104,6 +104,11 @@ ShellCommandId add_write_full_testbench_command_template(
"bitstream", true, "specify the bitstream to be loaded in the testbench"); "bitstream", true, "specify the bitstream to be loaded in the testbench");
shell_cmd.set_option_require_value(bitstream_opt, openfpga::OPT_STRING); shell_cmd.set_option_require_value(bitstream_opt, openfpga::OPT_STRING);
/* add an option '--simulator'*/
CommandOptionId sim_opt = shell_cmd.add_option(
"simulator", false, "specify the simulator to be used for the testbench");
shell_cmd.set_option_require_value(sim_opt, openfpga::OPT_STRING);
/* add an option '--fabric_netlist_file_path'*/ /* add an option '--fabric_netlist_file_path'*/
CommandOptionId fabric_netlist_opt = CommandOptionId fabric_netlist_opt =
shell_cmd.add_option("fabric_netlist_file_path", false, shell_cmd.add_option("fabric_netlist_file_path", false,

View File

@ -74,6 +74,7 @@ int write_full_testbench_template(const T& openfpga_ctx, const Command& cmd,
const CommandContext& cmd_context) { const CommandContext& cmd_context) {
CommandOptionId opt_output_dir = cmd.option("file"); CommandOptionId opt_output_dir = cmd.option("file");
CommandOptionId opt_bitstream = cmd.option("bitstream"); CommandOptionId opt_bitstream = cmd.option("bitstream");
CommandOptionId opt_sim = cmd.option("simulator");
CommandOptionId opt_dut_module = cmd.option("dut_module"); CommandOptionId opt_dut_module = cmd.option("dut_module");
CommandOptionId opt_fabric_netlist = cmd.option("fabric_netlist_file_path"); CommandOptionId opt_fabric_netlist = cmd.option("fabric_netlist_file_path");
CommandOptionId opt_pcf = cmd.option("pin_constraints_file"); CommandOptionId opt_pcf = cmd.option("pin_constraints_file");
@ -132,6 +133,12 @@ int write_full_testbench_template(const T& openfpga_ctx, const Command& cmd,
read_xml_bus_group(cmd_context.option_value(cmd, opt_bgf).c_str()); read_xml_bus_group(cmd_context.option_value(cmd, opt_bgf).c_str());
} }
/* Configure the simulator */
if (true == cmd_context.option_enable(cmd, opt_sim)) {
options.set_simulator_type(
cmd_context.option_value(cmd, opt_sim));
}
return fpga_verilog_full_testbench( return fpga_verilog_full_testbench(
openfpga_ctx.module_graph(), openfpga_ctx.bitstream_manager(), openfpga_ctx.module_graph(), openfpga_ctx.bitstream_manager(),
openfpga_ctx.fabric_bitstream(), openfpga_ctx.blwl_shift_register_banks(), openfpga_ctx.fabric_bitstream(), openfpga_ctx.blwl_shift_register_banks(),

View File

@ -30,7 +30,10 @@ VerilogTestbenchOption::VerilogTestbenchOption() {
time_unit_ = 1E-3; time_unit_ = 1E-3;
time_stamp_ = true; time_stamp_ = true;
use_relative_path_ = false; use_relative_path_ = false;
simulator_type_ = e_simulator_type::IVERILOG;
verbose_output_ = false; verbose_output_ = false;
SIMULATOR_TYPE_STRING_ = {{"iverilog", "vcs"}};
} }
/************************************************** /**************************************************
@ -107,6 +110,8 @@ bool VerilogTestbenchOption::use_relative_path() const {
bool VerilogTestbenchOption::verbose_output() const { return verbose_output_; } bool VerilogTestbenchOption::verbose_output() const { return verbose_output_; }
VerilogTestbenchOption::e_simulator_type VerilogTestbenchOption::simulator_type() const { return simulator_type_; }
/****************************************************************************** /******************************************************************************
* Private Mutators * Private Mutators
******************************************************************************/ ******************************************************************************/
@ -259,4 +264,45 @@ void VerilogTestbenchOption::set_verbose_output(const bool& enabled) {
verbose_output_ = enabled; verbose_output_ = enabled;
} }
int VerilogTestbenchOption::set_simulator_type(const std::string& value) {
simulator_type_ = str2simulator_type(value);
return valid_simulator_type(simulator_type_);
}
std::string VerilogTestbenchOption::simulator_type_all2str() const {
std::string full_types = "[";
for (int itype = size_t(VerilogTestbenchOption::e_simulator_type::IVERILOG);
itype != size_t(VerilogTestbenchOption::e_simulator_type::NUM_TYPES); ++itype) {
full_types += std::string(SIMULATOR_TYPE_STRING_[itype]) + std::string("|");
}
full_types.pop_back();
full_types += "]";
return full_types;
}
VerilogTestbenchOption::e_simulator_type VerilogTestbenchOption::str2simulator_type(const std::string& type_str, const bool& verbose) const {
for (int itype = size_t(VerilogTestbenchOption::e_simulator_type::IVERILOG);
itype != size_t(VerilogTestbenchOption::e_simulator_type::NUM_TYPES); ++itype) {
if (type_str == std::string(SIMULATOR_TYPE_STRING_[itype])) {
return static_cast<VerilogTestbenchOption::e_simulator_type>(itype);
}
}
VTR_LOGV_ERROR(verbose, "Invalid simulator type! Expect %s\n",
simulator_type_all2str().c_str());
return VerilogTestbenchOption::e_simulator_type::NUM_TYPES;
}
std::string VerilogTestbenchOption::simulator_type2str(const VerilogTestbenchOption::e_simulator_type& sim_type, const bool& verbose) const {
if (!valid_simulator_type(sim_type)) {
VTR_LOGV_ERROR(verbose, "Invalid type for simulator! Expect %s\n",
simulator_type_all2str().c_str());
return std::string();
}
return std::string(SIMULATOR_TYPE_STRING_[size_t(sim_type)]);
}
bool VerilogTestbenchOption::valid_simulator_type(const VerilogTestbenchOption::e_simulator_type& sim_type) const {
return sim_type != VerilogTestbenchOption::e_simulator_type::NUM_TYPES;
}
} /* end namespace openfpga */ } /* end namespace openfpga */

View File

@ -31,6 +31,19 @@ constexpr std::array<const char*, NUM_EMBEDDED_BITSTREAM_HDL_TYPES + 1>
* *
*******************************************************************/ *******************************************************************/
class VerilogTestbenchOption { class VerilogTestbenchOption {
/* Public types */
public:
/* Embedded bitstream code style */
enum class e_simulator_type {
IVERILOG = 0,
VCS,
NUM_TYPES
};
/* Constants */
private:
/* String version of simulator types. Used for debugging/error messages */
std::array<const char*, size_t(e_simulator_type::NUM_TYPES)>
SIMULATOR_TYPE_STRING_;
public: /* Public constructor */ public: /* Public constructor */
/* Set default options */ /* Set default options */
VerilogTestbenchOption(); VerilogTestbenchOption();
@ -56,6 +69,7 @@ class VerilogTestbenchOption {
bool time_stamp() const; bool time_stamp() const;
bool use_relative_path() const; bool use_relative_path() const;
bool verbose_output() const; bool verbose_output() const;
e_simulator_type simulator_type() const;
public: /* Public validator */ public: /* Public validator */
bool validate() const; bool validate() const;
@ -95,6 +109,15 @@ class VerilogTestbenchOption {
void set_use_relative_path(const bool& enabled); void set_use_relative_path(const bool& enabled);
void set_verbose_output(const bool& enabled); void set_verbose_output(const bool& enabled);
/* @brief Create the simulator type by parsing a given string. Return error when failed */
int set_simulator_type(const std::string& value);
private: /* Private utility and validators */
e_simulator_type str2simulator_type(const std::string& value, const bool& verbose = false) const;
std::string simulator_type2str(const e_simulator_type& sim_type, const bool& verbose = false) const;
std::string simulator_type_all2str() const;
bool valid_simulator_type(const e_simulator_type& sim_type) const;
private: /* Internal Data */ private: /* Internal Data */
std::string output_directory_; std::string output_directory_;
std::string top_module_; std::string top_module_;
@ -111,10 +134,12 @@ class VerilogTestbenchOption {
bool include_signal_init_; bool include_signal_init_;
e_verilog_default_net_type default_net_type_; e_verilog_default_net_type default_net_type_;
e_embedded_bitstream_hdl_type embedded_bitstream_hdl_type_; e_embedded_bitstream_hdl_type embedded_bitstream_hdl_type_;
e_simulator_type simulator_type_;
float time_unit_; float time_unit_;
bool time_stamp_; bool time_stamp_;
bool use_relative_path_; bool use_relative_path_;
bool verbose_output_; bool verbose_output_;
}; };
} /* End namespace openfpga*/ } /* End namespace openfpga*/

View File

@ -1423,7 +1423,8 @@ static int print_verilog_top_testbench_configuration_protocol_stimulus(
const ModuleId& top_module, const bool& fast_configuration, const ModuleId& top_module, const bool& fast_configuration,
const bool& bit_value_to_skip, const FabricBitstream& fabric_bitstream, const bool& bit_value_to_skip, const FabricBitstream& fabric_bitstream,
const MemoryBankShiftRegisterBanks& blwl_sr_banks, const MemoryBankShiftRegisterBanks& blwl_sr_banks,
const float& prog_clock_period, const float& timescale) { const float& prog_clock_period, const float& timescale,
const VerilogTestbenchOption::e_simulator_type sim_type) {
/* Validate the file stream */ /* Validate the file stream */
valid_file_stream(fp); valid_file_stream(fp);
@ -1437,7 +1438,7 @@ static int print_verilog_top_testbench_configuration_protocol_stimulus(
return print_verilog_top_testbench_configuration_protocol_ql_memory_bank_stimulus( return print_verilog_top_testbench_configuration_protocol_ql_memory_bank_stimulus(
fp, config_protocol, sim_settings, module_manager, top_module, fp, config_protocol, sim_settings, module_manager, top_module,
fast_configuration, bit_value_to_skip, fabric_bitstream, blwl_sr_banks, fast_configuration, bit_value_to_skip, fabric_bitstream, blwl_sr_banks,
prog_clock_period, timescale); prog_clock_period, timescale, sim_type);
break; break;
case CONFIG_MEM_MEMORY_BANK: case CONFIG_MEM_MEMORY_BANK:
case CONFIG_MEM_FRAME_BASED: { case CONFIG_MEM_FRAME_BASED: {
@ -2564,7 +2565,7 @@ int print_verilog_full_testbench(
status = print_verilog_top_testbench_configuration_protocol_stimulus( status = print_verilog_top_testbench_configuration_protocol_stimulus(
fp, config_protocol, simulation_parameters, module_manager, core_module, fp, config_protocol, simulation_parameters, module_manager, core_module,
fast_configuration, bit_value_to_skip, fabric_bitstream, blwl_sr_banks, fast_configuration, bit_value_to_skip, fabric_bitstream, blwl_sr_banks,
prog_clock_period, VERILOG_SIM_TIMESCALE); prog_clock_period, VERILOG_SIM_TIMESCALE, options.simulator_type());
if (status == CMD_EXEC_FATAL_ERROR) { if (status == CMD_EXEC_FATAL_ERROR) {
return status; return status;

View File

@ -317,7 +317,8 @@ void print_verilog_top_testbench_global_shift_register_clock_ports_stimuli(
static void static void
print_verilog_full_testbench_ql_memory_bank_shift_register_virtual_clock_generator( print_verilog_full_testbench_ql_memory_bank_shift_register_virtual_clock_generator(
std::fstream& fp, const BasicPort& start_sr_port, std::fstream& fp, const BasicPort& start_sr_port,
const BasicPort& sr_clock_port, const float& sr_clock_period) { const BasicPort& sr_clock_port, const float& sr_clock_period,
const VerilogTestbenchOption::e_simulator_type sim_type) {
/* Validate the file stream */ /* Validate the file stream */
valid_file_stream(fp); valid_file_stream(fp);
@ -346,10 +347,12 @@ print_verilog_full_testbench_ql_memory_bank_shift_register_virtual_clock_generat
fp << std::endl; fp << std::endl;
// The following code does not work when using Synopsys VCS. Comment them out. See if iverilog is fine or not // The following code does not work when using Synopsys VCS. Comment them out. See if iverilog is fine or not
//fp << "\t"; if (sim_type == VerilogTestbenchOption::e_simulator_type::IVERILOG) {
//fp << generate_verilog_port_constant_values( fp << "\t";
// sr_clock_port, std::vector<size_t>(sr_clock_port.get_width(), 0), true); fp << generate_verilog_port_constant_values(
//fp << ";" << std::endl; sr_clock_port, std::vector<size_t>(sr_clock_port.get_width(), 0), true);
fp << ";" << std::endl;
}
fp << "end"; fp << "end";
fp << std::endl; fp << std::endl;
@ -454,7 +457,8 @@ int print_verilog_top_testbench_configuration_protocol_ql_memory_bank_stimulus(
const ModuleId& top_module, const bool& fast_configuration, const ModuleId& top_module, const bool& fast_configuration,
const bool& bit_value_to_skip, const FabricBitstream& fabric_bitstream, const bool& bit_value_to_skip, const FabricBitstream& fabric_bitstream,
const MemoryBankShiftRegisterBanks& blwl_sr_banks, const MemoryBankShiftRegisterBanks& blwl_sr_banks,
const float& prog_clock_period, const float& timescale) { const float& prog_clock_period, const float& timescale,
const VerilogTestbenchOption::e_simulator_type sim_type) {
ModulePortId en_port_id = module_manager.find_module_port( ModulePortId en_port_id = module_manager.find_module_port(
top_module, std::string(DECODER_ENABLE_PORT_NAME)); top_module, std::string(DECODER_ENABLE_PORT_NAME));
BasicPort en_port(std::string(DECODER_ENABLE_PORT_NAME), 1); BasicPort en_port(std::string(DECODER_ENABLE_PORT_NAME), 1);
@ -532,7 +536,7 @@ int print_verilog_top_testbench_configuration_protocol_ql_memory_bank_stimulus(
print_verilog_comment( print_verilog_comment(
fp, "----- BL Shift register virtual clock generator -----"); fp, "----- BL Shift register virtual clock generator -----");
print_verilog_full_testbench_ql_memory_bank_shift_register_virtual_clock_generator( print_verilog_full_testbench_ql_memory_bank_shift_register_virtual_clock_generator(
fp, start_bl_sr_port, virtual_bl_sr_clock_port, bl_sr_clock_period); fp, start_bl_sr_port, virtual_bl_sr_clock_port, bl_sr_clock_period, sim_type);
print_verilog_comment(fp, print_verilog_comment(fp,
"----- BL Shift register clock generator -----"); "----- BL Shift register clock generator -----");
@ -544,7 +548,7 @@ int print_verilog_top_testbench_configuration_protocol_ql_memory_bank_stimulus(
print_verilog_comment( print_verilog_comment(
fp, "----- WL Shift register virtual clock generator -----"); fp, "----- WL Shift register virtual clock generator -----");
print_verilog_full_testbench_ql_memory_bank_shift_register_virtual_clock_generator( print_verilog_full_testbench_ql_memory_bank_shift_register_virtual_clock_generator(
fp, start_wl_sr_port, virtual_wl_sr_clock_port, wl_sr_clock_period); fp, start_wl_sr_port, virtual_wl_sr_clock_port, wl_sr_clock_period, sim_type);
print_verilog_comment(fp, print_verilog_comment(fp,
"----- WL Shift register clock generator -----"); "----- WL Shift register clock generator -----");
print_verilog_full_testbench_ql_memory_bank_shift_register_clock_generator( print_verilog_full_testbench_ql_memory_bank_shift_register_clock_generator(

View File

@ -54,7 +54,8 @@ int print_verilog_top_testbench_configuration_protocol_ql_memory_bank_stimulus(
const ModuleId& top_module, const bool& fast_configuration, const ModuleId& top_module, const bool& fast_configuration,
const bool& bit_value_to_skip, const FabricBitstream& fabric_bitstream, const bool& bit_value_to_skip, const FabricBitstream& fabric_bitstream,
const MemoryBankShiftRegisterBanks& blwl_sr_banks, const MemoryBankShiftRegisterBanks& blwl_sr_banks,
const float& prog_clock_period, const float& timescale); const float& prog_clock_period, const float& timescale,
const VerilogTestbenchOption::e_simulator_type sim_type);
/** /**
* @brief Print stimulus for a FPGA fabric with a memory bank configuration * @brief Print stimulus for a FPGA fabric with a memory bank configuration