add fast configuration option to fpga_verilog to speed up full testbench simulation

This commit is contained in:
tangxifan 2020-05-29 18:07:21 -06:00
parent 22648cdb9c
commit 8b3e79766c
10 changed files with 145 additions and 8 deletions

View File

@ -67,6 +67,7 @@ int write_verilog_testbench(OpenfpgaContext& openfpga_ctx,
CommandOptionId opt_output_dir = cmd.option("file");
CommandOptionId opt_reference_benchmark = cmd.option("reference_benchmark_file_path");
CommandOptionId opt_print_top_testbench = cmd.option("print_top_testbench");
CommandOptionId opt_fast_configuration = cmd.option("fast_configuration");
CommandOptionId opt_print_formal_verification_top_netlist = cmd.option("print_formal_verification_top_netlist");
CommandOptionId opt_print_preconfig_top_testbench = cmd.option("print_preconfig_top_testbench");
CommandOptionId opt_print_simulation_ini = cmd.option("print_simulation_ini");
@ -81,6 +82,7 @@ int write_verilog_testbench(OpenfpgaContext& openfpga_ctx,
options.set_reference_benchmark_file_path(cmd_context.option_value(cmd, opt_reference_benchmark));
options.set_print_formal_verification_top_netlist(cmd_context.option_enable(cmd, opt_print_formal_verification_top_netlist));
options.set_print_preconfig_top_testbench(cmd_context.option_enable(cmd, opt_print_preconfig_top_testbench));
options.set_fast_configuration(cmd_context.option_enable(cmd, opt_fast_configuration));
options.set_print_top_testbench(cmd_context.option_enable(cmd, opt_print_top_testbench));
options.set_print_simulation_ini(cmd_context.option_value(cmd, opt_print_simulation_ini));
options.set_explicit_port_mapping(cmd_context.option_enable(cmd, opt_explicit_port_mapping));

View File

@ -79,6 +79,9 @@ ShellCommandId add_openfpga_write_verilog_testbench_command(openfpga::Shell<Open
/* Add an option '--print_top_testbench' */
shell_cmd.add_option("print_top_testbench", false, "Generate a full testbench for top-level fabric module with autocheck capability");
/* Add an option '--fast_configuration' */
shell_cmd.add_option("fast_configuration", false, "Reduce the period of configuration by skip zero data points");
/* Add an option '--print_formal_verification_top_netlist' */
shell_cmd.add_option("print_formal_verification_top_netlist", false, "Generate a top-level module which can be used in formal verification");

View File

@ -213,6 +213,7 @@ void fpga_verilog_testbench(const ModuleManager& module_manager,
netlist_name,
top_testbench_file_path,
simulation_setting,
options.fast_configuration(),
options.explicit_port_mapping());
}

View File

@ -46,6 +46,10 @@ bool VerilogTestbenchOption::print_top_testbench() const {
return print_top_testbench_;
}
bool VerilogTestbenchOption::fast_configuration() const {
return fast_configuration_;
}
bool VerilogTestbenchOption::print_simulation_ini() const {
return !simulation_ini_path_.empty();
}
@ -82,6 +86,10 @@ void VerilogTestbenchOption::set_print_formal_verification_top_netlist(const boo
print_formal_verification_top_netlist_ = enabled;
}
void VerilogTestbenchOption::set_fast_configuration(const bool& enabled) {
fast_configuration_ = enabled;
}
void VerilogTestbenchOption::set_print_preconfig_top_testbench(const bool& enabled) {
print_preconfig_top_testbench_ = enabled
&& (!reference_benchmark_file_path_.empty());

View File

@ -24,6 +24,7 @@ class VerilogTestbenchOption {
public: /* Public accessors */
std::string output_directory() const;
std::string reference_benchmark_file_path() const;
bool fast_configuration() const;
bool print_formal_verification_top_netlist() const;
bool print_preconfig_top_testbench() const;
bool print_top_testbench() const;
@ -44,6 +45,7 @@ class VerilogTestbenchOption {
void set_print_formal_verification_top_netlist(const bool& enabled);
/* The preconfig top testbench generation can be enabled only when formal verification top netlist is enabled */
void set_print_preconfig_top_testbench(const bool& enabled);
void set_fast_configuration(const bool& enabled);
void set_print_top_testbench(const bool& enabled);
void set_print_simulation_ini(const std::string& simulation_ini_path);
void set_explicit_port_mapping(const bool& enabled);
@ -51,6 +53,7 @@ class VerilogTestbenchOption {
private: /* Internal Data */
std::string output_directory_;
std::string reference_benchmark_file_path_;
bool fast_configuration_;
bool print_formal_verification_top_netlist_;
bool print_preconfig_top_testbench_;
bool print_top_testbench_;

View File

@ -481,6 +481,48 @@ void print_verilog_top_testbench_ports(std::fstream& fp,
fp << "\tinteger " << TOP_TESTBENCH_ERROR_COUNTER << "= 0;" << std::endl;
}
/********************************************************************
* Estimate the number of configuration clock cycles
* by traversing the linked-list and count the number of SRAM=1 or BL=1&WL=1 in it.
* We plus 1 additional config clock cycle here because we need to reset everything during the first clock cycle
* If we consider fast configuration, the number of clock cycles will be
* the number of non-zero data points in the fabric bitstream
* Note that this will not applicable to configuration chain!!!
*******************************************************************/
static
size_t calculate_num_config_clock_cycles(const e_config_protocol_type& sram_orgz_type,
const bool& fast_configuration,
const FabricBitstream& fabric_bitstream) {
size_t num_config_clock_cycles = 1 + fabric_bitstream.bits().size();
/* Branch on the type of configuration protocol */
switch (sram_orgz_type) {
case CONFIG_MEM_STANDALONE:
case CONFIG_MEM_SCAN_CHAIN:
case CONFIG_MEM_MEMORY_BANK:
/* TODO */
break;
case CONFIG_MEM_FRAME_BASED: {
/* For fast configuration, we will skip all the zero data points */
if (true == fast_configuration) {
num_config_clock_cycles = 1;
for (const FabricBitId& bit_id : fabric_bitstream.bits()) {
if (true == fabric_bitstream.bit_din(bit_id)) {
num_config_clock_cycles++;
}
}
}
break;
}
default:
VTR_LOGF_ERROR(__FILE__, __LINE__,
"Invalid SRAM organization type!\n");
exit(1);
}
return num_config_clock_cycles;
}
/********************************************************************
* Instanciate the input benchmark module
*******************************************************************/
@ -865,6 +907,7 @@ void print_verilog_top_testbench_configuration_chain_bitstream(std::fstream& fp,
*******************************************************************/
static
void print_verilog_top_testbench_frame_decoder_bitstream(std::fstream& fp,
const bool& fast_configuration,
const ModuleManager& module_manager,
const ModuleId& top_module,
const FabricBitstream& fabric_bitstream) {
@ -904,6 +947,12 @@ void print_verilog_top_testbench_frame_decoder_bitstream(std::fstream& fp,
* We will visit the fabric bitstream in a reverse way
*/
for (const FabricBitId& bit_id : fabric_bitstream.bits()) {
/* When fast configuration is enabled, we skip zero data_in values */
if ((true == fast_configuration)
&& (false == fabric_bitstream.bit_din(bit_id))) {
continue;
}
fp << "\t\t" << std::string(TOP_TESTBENCH_PROG_TASK_NAME);
fp << "(" << addr_port.get_width() << "'b";
VTR_ASSERT(addr_port.get_width() == fabric_bitstream.bit_address(bit_id).size());
@ -957,6 +1006,7 @@ void print_verilog_top_testbench_frame_decoder_bitstream(std::fstream& fp,
static
void print_verilog_top_testbench_bitstream(std::fstream& fp,
const e_config_protocol_type& sram_orgz_type,
const bool& fast_configuration,
const ModuleManager& module_manager,
const ModuleId& top_module,
const BitstreamManager& bitstream_manager,
@ -973,7 +1023,7 @@ void print_verilog_top_testbench_bitstream(std::fstream& fp,
/* TODO */
break;
case CONFIG_MEM_FRAME_BASED:
print_verilog_top_testbench_frame_decoder_bitstream(fp,
print_verilog_top_testbench_frame_decoder_bitstream(fp, fast_configuration,
module_manager, top_module,
fabric_bitstream);
break;
@ -1017,6 +1067,7 @@ void print_verilog_top_testbench(const ModuleManager& module_manager,
const std::string& circuit_name,
const std::string& verilog_fname,
const SimulationSetting& simulation_parameters,
const bool& fast_configuration,
const bool& explicit_port_mapping) {
std::string timer_message = std::string("Write autocheck testbench for FPGA top-level Verilog netlist for '") + circuit_name + std::string("'");
@ -1050,11 +1101,10 @@ void print_verilog_top_testbench(const ModuleManager& module_manager,
/* Find the clock period */
float prog_clock_period = (1./simulation_parameters.programming_clock_frequency());
float op_clock_period = (1./simulation_parameters.operating_clock_frequency());
/* Estimate the number of configuration clock cycles
* by traversing the linked-list and count the number of SRAM=1 or BL=1&WL=1 in it.
* We plus 1 additional config clock cycle here because we need to reset everything during the first clock cycle
*/
size_t num_config_clock_cycles = 1 + fabric_bitstream.bits().size();
/* Estimate the number of configuration clock cycles */
size_t num_config_clock_cycles = calculate_num_config_clock_cycles(sram_orgz_type,
fast_configuration,
fabric_bitstream);
/* Generate stimuli for general control signals */
print_verilog_top_testbench_generic_stimulus(fp,
@ -1095,6 +1145,7 @@ void print_verilog_top_testbench(const ModuleManager& module_manager,
/* load bitstream to FPGA fabric in a configuration phase */
print_verilog_top_testbench_bitstream(fp, sram_orgz_type,
fast_configuration,
module_manager, top_module,
bitstream_manager, fabric_bitstream);

View File

@ -35,6 +35,7 @@ void print_verilog_top_testbench(const ModuleManager& module_manager,
const std::string& circuit_name,
const std::string& verilog_fname,
const SimulationSetting& simulation_parameters,
const bool& fast_configuration,
const bool& explicit_port_mapping);
} /* end namespace openfpga */

View File

@ -49,7 +49,7 @@ write_fabric_verilog --file ./SRC --explicit_port_mapping --include_timing --inc
# - 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_verilog_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --print_top_testbench --print_preconfig_top_testbench --print_simulation_ini ./SimulationDeck/simulation_deck.ini --explicit_port_mapping
write_verilog_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --print_top_testbench --print_preconfig_top_testbench --print_simulation_ini ./SimulationDeck/simulation_deck.ini --explicit_port_mapping --fast_configuration
# Write the SDC files for PnR backend
# - Turn on every options here

View File

@ -0,0 +1,68 @@
# Run VPR for the 'and' design
#--write_rr_graph example_rr_graph.xml
vpr ${VPR_ARCH_FILE} ${VPR_TESTBENCH_BLIF} --clock_modeling route
# Read OpenFPGA architecture definition
read_openfpga_arch -f ${OPENFPGA_ARCH_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 clustering nets based on routing results
pb_pin_fixup --verbose
# 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 --file fabric_indepenent_bitstream.xml
# Build fabric-dependent bitstream
build_fabric_bitstream --verbose
# 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 --include_signal_init --support_icarus_simulator --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_verilog_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --print_top_testbench --print_preconfig_top_testbench --print_simulation_ini ./SimulationDeck/simulation_deck.ini --explicit_port_mapping
# 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

@ -8,7 +8,7 @@
[GENERAL]
run_engine=openfpga_shell
openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/OpenFPGAShellScripts/configuration_frame_example_script.openfpga
openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/OpenFPGAShellScripts/full_testbench_example_script.openfpga
power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml
power_analysis = true
spice_output=false