Merge pull request #968 from lnis-uofu/vpr_single_step

Now VPR can be run independently in OpenFPGA shell
This commit is contained in:
tangxifan 2022-12-30 21:45:30 -08:00 committed by GitHub
commit 2931e03d86
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 247 additions and 4 deletions

View File

@ -8,4 +8,28 @@ vpr
OpenFPGA allows users to call ``vpr`` in the standard way as documented in the vtr_project_.
.. note:: This command will run vpr in a standalone way, whose results will be kept and used by other commands. Suggest to use when this is the final run of VPR.
For example, vpr commands may be called in the following way:
.. code-block:: shell
# VPR standalone runs, no results will be kept for downstream commands
vpr_standalone <some_options>
vpr_standalone <some_options>
# More standalone runs may be expected
vpr_standalone <some_options>
# Final VPR run, results are kept for downstream commands
vpr <some_options>
# Other commands that use VPR results
.. _vtr_project: https://github.com/verilog-to-routing/vtr-verilog-to-routing
vpr_standalone
~~~~~~~~~~~~~~
OpenFPGA allows users to call ``vpr`` in the standard way as documented in the vtr_project_.
.. note:: This command will run vpr in a standalone way, whose results will **not** be kept and **not** used by other commands. Suggest to use when only some stages of VPR are needed.
.. _vtr_project: https://github.com/verilog-to-routing/vtr-verilog-to-routing

View File

@ -18,9 +18,23 @@ void add_vpr_commands(openfpga::Shell<OpenfpgaContext>& shell) {
ShellCommandId shell_cmd_vpr_id =
shell.add_command(shell_cmd_vpr,
"Start VPR core engine to pack, place and route a BLIF "
"design on a FPGA architecture");
"design on a FPGA architecture; Note that this command "
"will keep VPR results!");
shell.set_command_class(shell_cmd_vpr_id, vpr_cmd_class);
shell.set_command_execute_function(shell_cmd_vpr_id, vpr::vpr);
shell.set_command_execute_function(shell_cmd_vpr_id, vpr::vpr_wrapper);
/* Create a macro command of 'vpr_standalone' which will call the main engine
* of vpr in a standalone way
*/
Command shell_cmd_vpr_stdalone("vpr_standalone");
ShellCommandId shell_cmd_vpr_stdalone_id = shell.add_command(
shell_cmd_vpr_stdalone,
"Start a standalone VPR core engine to pack, place and route a BLIF "
"design on a FPGA architecture; Note that this command will NOT keep VPR "
"results!");
shell.set_command_class(shell_cmd_vpr_stdalone_id, vpr_cmd_class);
shell.set_command_execute_function(shell_cmd_vpr_stdalone_id,
vpr::vpr_standalone_wrapper);
}
} /* end namespace openfpga */

View File

@ -8,6 +8,7 @@
#include <cstring>
#include <ctime>
#include "command_exit_codes.h"
#include "globals.h"
#include "tatum/error.hpp"
#include "vpr_api.h"
@ -23,6 +24,7 @@
namespace vpr {
/**
* VPR program without clean up
* VPR program
* Generate FPGA architecture given architecture description
* Pack, place, and route circuit into FPGA architecture
@ -34,7 +36,7 @@ namespace vpr {
* 3. Place-and-route and timing analysis
* 4. Clean up
*/
int vpr(int argc, char** argv) {
static int vpr(int argc, char** argv) {
vtr::ScopedFinishTimer t("The entire flow of VPR");
t_options Options = t_options();
@ -93,4 +95,85 @@ int vpr(int argc, char** argv) {
return SUCCESS_EXIT_CODE;
}
/* A wrapper to return proper codes for openfpga shell */
int vpr_wrapper(int argc, char** argv) {
if (SUCCESS_EXIT_CODE != vpr(argc, argv)) {
return openfpga::CMD_EXEC_FATAL_ERROR;
}
return openfpga::CMD_EXEC_SUCCESS;
}
/**
* VPR program with clean up
*/
static int vpr_standalone(int argc, char** argv) {
vtr::ScopedFinishTimer t("The entire flow of VPR");
t_options Options = t_options();
t_arch Arch = t_arch();
t_vpr_setup vpr_setup = t_vpr_setup();
try {
vpr_install_signal_handler();
/* Read options, architecture, and circuit netlist */
vpr_init(argc, const_cast<const char**>(argv), &Options, &vpr_setup, &Arch);
if (Options.show_version) {
vpr_free_all(Arch, vpr_setup);
return SUCCESS_EXIT_CODE;
}
bool flow_succeeded = vpr_flow(vpr_setup, Arch);
if (!flow_succeeded) {
VTR_LOG("VPR failed to implement circuit\n");
vpr_free_all(Arch, vpr_setup);
return UNIMPLEMENTABLE_EXIT_CODE;
}
auto& timing_ctx = g_vpr_ctx.timing();
print_timing_stats("Flow", timing_ctx.stats);
/* free data structures */
vpr_free_all(Arch, vpr_setup);
VTR_LOG("VPR succeeded\n");
} catch (const tatum::Error& tatum_error) {
VTR_LOG_ERROR("%s\n", format_tatum_error(tatum_error).c_str());
vpr_free_all(Arch, vpr_setup);
return ERROR_EXIT_CODE;
} catch (const VprError& vpr_error) {
vpr_print_error(vpr_error);
if (vpr_error.type() == VPR_ERROR_INTERRUPTED) {
vpr_free_all(Arch, vpr_setup);
return INTERRUPTED_EXIT_CODE;
} else {
vpr_free_all(Arch, vpr_setup);
return ERROR_EXIT_CODE;
}
} catch (const vtr::VtrError& vtr_error) {
VTR_LOG_ERROR("%s:%d %s\n", vtr_error.filename_c_str(), vtr_error.line(),
vtr_error.what());
vpr_free_all(Arch, vpr_setup);
return ERROR_EXIT_CODE;
}
/* Signal success to scripts */
return SUCCESS_EXIT_CODE;
}
/* A wrapper to return proper codes for openfpga shell */
int vpr_standalone_wrapper(int argc, char** argv) {
if (SUCCESS_EXIT_CODE != vpr_standalone(argc, argv)) {
return openfpga::CMD_EXEC_FATAL_ERROR;
}
return openfpga::CMD_EXEC_SUCCESS;
}
} /* End namespace vpr */

View File

@ -4,7 +4,9 @@
/* Begin namespace vpr */
namespace vpr {
int vpr(int argc, char** argv);
int vpr_wrapper(int argc, char** argv);
int vpr_standalone_wrapper(int argc, char** argv);
} /* End namespace vpr */

View File

@ -0,0 +1,80 @@
# Run VPR for the 'and' design
# Run packing stage only
vpr_standalone ${VPR_ARCH_FILE} ${VPR_TESTBENCH_BLIF} --pack --device ${OPENFPGA_VPR_DEVICE_LAYOUT} --route_chan_width ${OPENFPGA_VPR_ROUTE_CHAN_WIDTH}
# Run placement stage only
vpr_standalone ${VPR_ARCH_FILE} ${VPR_TESTBENCH_BLIF} --place --device ${OPENFPGA_VPR_DEVICE_LAYOUT} --route_chan_width ${OPENFPGA_VPR_ROUTE_CHAN_WIDTH}
# Run routing
vpr_standalone ${VPR_ARCH_FILE} ${VPR_TESTBENCH_BLIF} --route --device ${OPENFPGA_VPR_DEVICE_LAYOUT} --route_chan_width ${OPENFPGA_VPR_ROUTE_CHAN_WIDTH}
# Run analysis as final results
vpr ${VPR_ARCH_FILE} ${VPR_TESTBENCH_BLIF} --analysis --device ${OPENFPGA_VPR_DEVICE_LAYOUT} --route_chan_width ${OPENFPGA_VPR_ROUTE_CHAN_WIDTH}
# 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
# 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} --explicit_port_mapping --include_signal_init --bitstream fabric_bitstream.bit
write_preconfigured_fabric_wrapper --embed_bitstream iverilog --file ./SRC --explicit_port_mapping
write_preconfigured_testbench --file ./SRC --reference_benchmark_file_path ${REFERENCE_VERILOG_TESTBENCH} --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,6 +8,9 @@ PYTHON_EXEC=python3.8
##############################################
echo -e "Basic regression tests";
echo -e "Test multiple runs of vpr"
run-task basic_tests/vpr_standalone $@
echo -e "Testing configuration chain of a K4N4 FPGA";
run-task basic_tests/full_testbench/configuration_chain $@
run-task basic_tests/full_testbench/configuration_chain_no_time_stamp $@

View File

@ -0,0 +1,37 @@
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
# 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/vpr_standalone_example_script.openfpga
openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k4_N4_40nm_cc_openfpga.xml
openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml
openfpga_vpr_device_layout=2x2
openfpga_vpr_route_chan_width=20
[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
[SYNTHESIS_PARAM]
bench_read_verilog_options_common = -nolatches
bench0_top = and2
[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH]
end_flow_with_test=
vpr_fpga_verilog_formal_verification_top_netlist=