Merge pull request #1484 from lnis-uofu/xt_hotfix

Support VCS simulator for QL memory bank in full testbench
This commit is contained in:
tangxifan 2023-12-08 16:35:47 -08:00 committed by GitHub
commit b494740781
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 238 additions and 12 deletions

View File

@ -61,6 +61,10 @@ write_full_testbench
The bitstream file to be loaded to the full testbench, which should be in the same file format that OpenFPGA can outputs (See detailes in :ref:`file_formats_fabric_bitstream_plain_text`). For example, ``--bitstream and2.bit``
.. option:: --simulator <string>
Specify the type of simulator which the full testbench will be used for. Currently support ``iverilog`` | ``vcs``. By default, assume the simulator is iverilog. For example, ``--simulator iverilog``. For different types of simulator, some syntax in the testbench may differ to help fast convergence.
.. option:: --fabric_netlist_file_path <string>
Specify the fabric Verilog file if they are not in the same directory as the testbenches to be generated. If not specified, OpenFPGA will assume that the fabric netlists are the in the same directory as testbenches and assign default names. For example, ``--file /temp/fabric/fabric_netlists.v``

View File

@ -104,6 +104,11 @@ ShellCommandId add_write_full_testbench_command_template(
"bitstream", true, "specify the bitstream to be loaded in the testbench");
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'*/
CommandOptionId fabric_netlist_opt =
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) {
CommandOptionId opt_output_dir = cmd.option("file");
CommandOptionId opt_bitstream = cmd.option("bitstream");
CommandOptionId opt_sim = cmd.option("simulator");
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");
@ -132,6 +133,11 @@ 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());
}
/* 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(
openfpga_ctx.module_graph(), openfpga_ctx.bitstream_manager(),
openfpga_ctx.fabric_bitstream(), openfpga_ctx.blwl_shift_register_banks(),

View File

@ -30,7 +30,10 @@ VerilogTestbenchOption::VerilogTestbenchOption() {
time_unit_ = 1E-3;
time_stamp_ = true;
use_relative_path_ = false;
simulator_type_ = e_simulator_type::IVERILOG;
verbose_output_ = false;
SIMULATOR_TYPE_STRING_ = {{"iverilog", "vcs"}};
}
/**************************************************
@ -107,6 +110,11 @@ bool VerilogTestbenchOption::use_relative_path() const {
bool VerilogTestbenchOption::verbose_output() const { return verbose_output_; }
VerilogTestbenchOption::e_simulator_type
VerilogTestbenchOption::simulator_type() const {
return simulator_type_;
}
/******************************************************************************
* Private Mutators
******************************************************************************/
@ -259,4 +267,52 @@ void VerilogTestbenchOption::set_verbose_output(const bool& 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 */

View File

@ -31,6 +31,16 @@ constexpr std::array<const char*, NUM_EMBEDDED_BITSTREAM_HDL_TYPES + 1>
*
*******************************************************************/
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 */
/* Set default options */
VerilogTestbenchOption();
@ -56,6 +66,7 @@ class VerilogTestbenchOption {
bool time_stamp() const;
bool use_relative_path() const;
bool verbose_output() const;
e_simulator_type simulator_type() const;
public: /* Public validator */
bool validate() const;
@ -95,6 +106,18 @@ class VerilogTestbenchOption {
void set_use_relative_path(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 */
std::string output_directory_;
std::string top_module_;
@ -111,6 +134,7 @@ class VerilogTestbenchOption {
bool include_signal_init_;
e_verilog_default_net_type default_net_type_;
e_embedded_bitstream_hdl_type embedded_bitstream_hdl_type_;
e_simulator_type simulator_type_;
float time_unit_;
bool time_stamp_;
bool use_relative_path_;

View File

@ -1423,7 +1423,8 @@ static int print_verilog_top_testbench_configuration_protocol_stimulus(
const ModuleId& top_module, const bool& fast_configuration,
const bool& bit_value_to_skip, const FabricBitstream& fabric_bitstream,
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 */
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(
fp, config_protocol, sim_settings, module_manager, top_module,
fast_configuration, bit_value_to_skip, fabric_bitstream, blwl_sr_banks,
prog_clock_period, timescale);
prog_clock_period, timescale, sim_type);
break;
case CONFIG_MEM_MEMORY_BANK:
case CONFIG_MEM_FRAME_BASED: {
@ -2564,7 +2565,7 @@ int print_verilog_full_testbench(
status = print_verilog_top_testbench_configuration_protocol_stimulus(
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);
prog_clock_period, VERILOG_SIM_TIMESCALE, options.simulator_type());
if (status == CMD_EXEC_FATAL_ERROR) {
return status;

View File

@ -317,7 +317,8 @@ void print_verilog_top_testbench_global_shift_register_clock_ports_stimuli(
static void
print_verilog_full_testbench_ql_memory_bank_shift_register_virtual_clock_generator(
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 */
valid_file_stream(fp);
@ -345,10 +346,14 @@ print_verilog_full_testbench_ql_memory_bank_shift_register_virtual_clock_generat
fp << "end";
fp << std::endl;
fp << "\t";
fp << generate_verilog_port_constant_values(
sr_clock_port, std::vector<size_t>(sr_clock_port.get_width(), 0), true);
fp << ";" << std::endl;
// The following code does not work when using Synopsys VCS. Comment them out.
// See if iverilog is fine or not
if (sim_type == VerilogTestbenchOption::e_simulator_type::IVERILOG) {
fp << "\t";
fp << generate_verilog_port_constant_values(
sr_clock_port, std::vector<size_t>(sr_clock_port.get_width(), 0), true);
fp << ";" << std::endl;
}
fp << "end";
fp << std::endl;
@ -453,7 +458,8 @@ int print_verilog_top_testbench_configuration_protocol_ql_memory_bank_stimulus(
const ModuleId& top_module, const bool& fast_configuration,
const bool& bit_value_to_skip, const FabricBitstream& fabric_bitstream,
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(
top_module, std::string(DECODER_ENABLE_PORT_NAME));
BasicPort en_port(std::string(DECODER_ENABLE_PORT_NAME), 1);
@ -531,7 +537,8 @@ int print_verilog_top_testbench_configuration_protocol_ql_memory_bank_stimulus(
print_verilog_comment(
fp, "----- BL 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,
"----- BL Shift register clock generator -----");
@ -543,7 +550,8 @@ int print_verilog_top_testbench_configuration_protocol_ql_memory_bank_stimulus(
print_verilog_comment(
fp, "----- WL 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,
"----- WL 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 bool& bit_value_to_skip, const FabricBitstream& fabric_bitstream,
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

View File

@ -0,0 +1,71 @@
# Run VPR for the 'and' design
#--write_rr_graph example_rr_graph.xml
vpr ${VPR_ARCH_FILE} ${VPR_TESTBENCH_BLIF} --clock_modeling ideal ${OPENFPGA_VPR_DEVICE_LAYOUT}
# Read OpenFPGA architecture definition
read_openfpga_arch -f ${OPENFPGA_ARCH_FILE}
# Read OpenFPGA simulation settings
read_openfpga_simulation_setting -f ${OPENFPGA_SIM_SETTING_FILE}
# Annotate the OpenFPGA architecture to VPR data base
# to debug use --verbose options
link_openfpga_arch --activity_file ${ACTIVITY_FILE} --sort_gsb_chan_node_in_edges
# Check and correct any naming conflicts in the BLIF netlist
check_netlist_naming_conflict --fix --report ./netlist_renaming.xml
# Apply fix-up to Look-Up Table truth tables based on packing results
lut_truth_table_fixup
# Build the module graph
# - Enabled compression on routing architecture modules
# - Enable pin duplication on grid modules
build_fabric --compress_routing #--verbose
# Write the fabric hierarchy of module graph to a file
# This is used by hierarchical PnR flows
write_fabric_hierarchy --file ./fabric_hierarchy.txt
# Repack the netlist to physical pbs
# This must be done before bitstream generator and testbench generation
# Strongly recommend it is done after all the fix-up have been applied
repack #--verbose
# Build the bitstream
# - Output the fabric-independent bitstream to a file
build_architecture_bitstream --verbose --write_file fabric_independent_bitstream.xml
# Build fabric-dependent bitstream
build_fabric_bitstream --verbose
# Write fabric-dependent bitstream
write_fabric_bitstream --file fabric_bitstream.bit --format plain_text ${OPENFPGA_FAST_CONFIGURATION}
# Write the Verilog netlist for FPGA fabric
# - Enable the use of explicit port mapping in Verilog netlist
write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --print_user_defined_template --verbose
# Write the Verilog testbench for FPGA fabric
# - We suggest the use of same output directory as fabric Verilog netlists
# - Must specify the reference benchmark file if you want to output any testbenches
# - Enable top-level testbench which is a full verification including programming circuit and core logic of FPGA
# - Enable pre-configured top-level testbench which is a fast verification skipping programming phase
# - Simulation ini file is optional and is needed only when you need to interface different HDL simulators using openfpga flow-run scripts
write_full_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --include_signal_init --explicit_port_mapping --bitstream fabric_bitstream.bit ${OPENFPGA_FAST_CONFIGURATION} ${OPENFPGA_SIMULATOR}
# Write the SDC files for PnR backend
# - Turn on every options here
write_pnr_sdc --file ./SDC
# Write SDC to disable timing for configure ports
write_sdc_disable_timing_configure_ports --file ./SDC/disable_configure_ports.sdc
# Write the SDC to run timing analysis for a mapped FPGA fabric
write_analysis_sdc --file ./SDC_analysis
# Finish and exit OpenFPGA
exit
# Note :
# To run verification at the end of the flow maintain source in ./SRC directory

View File

@ -83,6 +83,9 @@ run-task basic_tests/full_testbench/ql_memory_bank_shift_register $@
run-task basic_tests/full_testbench/ql_memory_bank_shift_register_use_wlr $@
run-task basic_tests/full_testbench/ql_memory_bank_shift_register_multi_chain $@
echo -e "Testing simulator support";
run-task basic_tests/full_testbench/ql_memory_bank_shift_register_vcs $@
echo -e "Testing testbenches without self checking features";
run-task basic_tests/full_testbench/full_testbench_without_self_checking $@
run-task basic_tests/preconfig_testbench/preconfigured_testbench_without_self_checking $@

View File

@ -0,0 +1,47 @@
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
# Configuration file for running experiments
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
# timeout_each_job : FPGA Task script splits fpga flow into multiple jobs
# Each job execute fpga_flow script on combination of architecture & benchmark
# timeout_each_job is timeout for each job
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
[GENERAL]
run_engine=openfpga_shell
power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml
power_analysis = true
spice_output=false
verilog_output=true
timeout_each_job = 20*60
fpga_flow=yosys_vpr
[OpenFPGA_SHELL]
openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/write_full_testbench_simulator_support_example_script.openfpga
openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_qlbanksr_openfpga.xml
openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_shift_register_sim_openfpga.xml
openfpga_vpr_device_layout=
openfpga_fast_configuration=
openfpga_simulator=--simulator vcs
[ARCHITECTURES]
arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k4_N4_tileable_40nm.xml
[BENCHMARKS]
bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.v
bench1=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/or2/or2.v
bench2=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2_latch/and2_latch.v
[SYNTHESIS_PARAM]
bench_read_verilog_options_common = -nolatches
bench0_top = and2
bench0_chan_width = 300
bench1_top = or2
bench1_chan_width = 300
bench2_top = and2_latch
bench2_chan_width = 300
[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH]
#end_flow_with_test=