put analysis sdc writer online. Minor bug in redudant '/' to be fixed

This commit is contained in:
tangxifan 2020-03-02 19:54:18 -07:00
parent 037c7e5c43
commit 3241d8bd37
8 changed files with 92 additions and 10 deletions

View File

@ -10,6 +10,7 @@
#include "circuit_library_utils.h"
#include "pnr_sdc_writer.h"
#include "analysis_sdc_writer.h"
#include "openfpga_sdc.h"
/* Include global variables of VPR */
@ -77,4 +78,38 @@ void write_pnr_sdc(OpenfpgaContext& openfpga_ctx,
}
}
/********************************************************************
* A wrapper function to call the analysis SDC generator of FPGA-SDC
*******************************************************************/
void write_analysis_sdc(OpenfpgaContext& openfpga_ctx,
const Command& cmd, const CommandContext& cmd_context) {
CommandOptionId opt_output_dir = cmd.option("file");
/* This is an intermediate data structure which is designed to modularize the FPGA-SDC
* Keep it independent from any other outside data structures
*/
std::string sdc_dir_path = format_dir_path(cmd_context.option_value(cmd, opt_output_dir));
/* Create directories */
create_dir_path(sdc_dir_path.c_str());
AnalysisSdcOption options(sdc_dir_path);
options.set_generate_sdc_analysis(true);
/* Collect global ports from the circuit library:
* TODO: should we place this in the OpenFPGA context?
*/
std::vector<CircuitPortId> global_ports = find_circuit_library_global_ports(openfpga_ctx.arch().circuit_lib);
if (true == options.generate_sdc_analysis()) {
print_analysis_sdc(options,
1./openfpga_ctx.arch().sim_setting.operating_clock_frequency(),
g_vpr_ctx,
openfpga_ctx,
global_ports,
openfpga_ctx.flow_manager().compress_routing());
}
}
} /* end namespace openfpga */

View File

@ -18,6 +18,9 @@ namespace openfpga {
void write_pnr_sdc(OpenfpgaContext& openfpga_ctx,
const Command& cmd, const CommandContext& cmd_context);
void write_analysis_sdc(OpenfpgaContext& openfpga_ctx,
const Command& cmd, const CommandContext& cmd_context);
} /* end namespace openfpga */
#endif

View File

@ -61,6 +61,36 @@ ShellCommandId add_openfpga_write_pnr_sdc_command(openfpga::Shell<OpenfpgaContex
return shell_cmd_id;
}
/********************************************************************
* - Add a command to Shell environment: generate PnR SDC
* - Add associated options
* - Add command dependency
*******************************************************************/
static
ShellCommandId add_openfpga_write_analysis_sdc_command(openfpga::Shell<OpenfpgaContext>& shell,
const ShellCommandClassId& cmd_class_id,
const std::vector<ShellCommandId>& dependent_cmds) {
Command shell_cmd("write_analysis_sdc");
/* Add an option '--file' in short '-f'*/
CommandOptionId output_opt = shell_cmd.add_option("file", true, "Specify the output directory for SDC files");
shell_cmd.set_option_short_name(output_opt, "f");
shell_cmd.set_option_require_value(output_opt, openfpga::OPT_STRING);
/* Add an option '--verbose' */
shell_cmd.add_option("verbose", false, "Enable verbose output");
/* Add command 'write_fabric_verilog' to the Shell */
ShellCommandId shell_cmd_id = shell.add_command(shell_cmd, "generate SDC files for timing analysis a PnRed FPGA fabric mapped by a benchmark");
shell.set_command_class(shell_cmd_id, cmd_class_id);
shell.set_command_execute_function(shell_cmd_id, write_analysis_sdc);
/* Add command dependency to the Shell */
shell.set_command_dependency(shell_cmd_id, dependent_cmds);
return shell_cmd_id;
}
void add_openfpga_sdc_commands(openfpga::Shell<OpenfpgaContext>& shell) {
/* Get the unique id of 'build_fabric' command which is to be used in creating the dependency graph */
const ShellCommandId& build_fabric_id = shell.command(std::string("build_fabric"));
@ -77,6 +107,17 @@ void add_openfpga_sdc_commands(openfpga::Shell<OpenfpgaContext>& shell) {
add_openfpga_write_pnr_sdc_command(shell,
openfpga_sdc_cmd_class,
pnr_sdc_cmd_dependency);
/********************************
* Command 'write_analysis_sdc'
*/
/* The 'write_analysis_sdc' command should NOT be executed before 'build_fabric' */
std::vector<ShellCommandId> analysis_sdc_cmd_dependency;
analysis_sdc_cmd_dependency.push_back(build_fabric_id);
add_openfpga_write_analysis_sdc_command(shell,
openfpga_sdc_cmd_class,
analysis_sdc_cmd_dependency);
}
} /* end namespace openfpga */

View File

@ -49,7 +49,7 @@ void rec_print_analysis_sdc_disable_unused_pb_graph_nodes(std::fstream& fp,
*/
fp << "set_disable_timing ";
fp << hierarchy_name;
fp << "/*";
fp << "*";
fp << std::endl;
/* Return if this is the primitive pb_type */
@ -74,7 +74,7 @@ void rec_print_analysis_sdc_disable_unused_pb_graph_nodes(std::fstream& fp,
/* Must have a valid instance name!!! */
VTR_ASSERT(false == child_instance_name.empty());
std::string updated_hierarchy_name = hierarchy_name + std::string("/") + child_instance_name + std::string("/");
std::string updated_hierarchy_name = hierarchy_name + child_instance_name + std::string("/");
rec_print_analysis_sdc_disable_unused_pb_graph_nodes(fp, device_annotation, module_manager, child_module, hierarchy_name,
&(physical_pb_graph_node->child_pb_graph_nodes[physical_mode->index][ichild][inst]));
@ -114,7 +114,6 @@ void disable_pb_graph_node_unused_pin(std::fstream& fp,
fp << "set_disable_timing ";
fp << hierarchy_name;
fp << "/";
fp << generate_sdc_port(port_to_disable);
fp << std::endl;
}
@ -407,7 +406,7 @@ void rec_print_analysis_sdc_disable_pb_graph_node_unused_resources(std::fstream&
/* Must have a valid instance name!!! */
VTR_ASSERT(false == child_instance_name.empty());
std::string updated_hierarchy_name = hierarchy_name + std::string("/") + child_instance_name + std::string("/");
std::string updated_hierarchy_name = hierarchy_name + child_instance_name + std::string("/");
rec_print_analysis_sdc_disable_pb_graph_node_unused_resources(fp, device_annotation,
module_manager, child_module, hierarchy_name,
@ -591,7 +590,7 @@ void print_analysis_sdc_disable_unused_grids(std::fstream& fp,
for (size_t ix = 1; ix < grids.width() - 1; ++ix) {
for (size_t iy = 1; iy < grids.height() - 1; ++iy) {
/* We should not meet any I/O grid */
VTR_ASSERT(false != is_io_type(grids[ix][iy].type));
VTR_ASSERT(false == is_io_type(grids[ix][iy].type));
print_analysis_sdc_disable_unused_grid(fp, vtr::Point<size_t>(ix, iy),
grids, device_annotation, cluster_annotation, place_annotation,

View File

@ -202,14 +202,14 @@ void print_analysis_sdc_disable_global_ports(std::fstream& fp,
* Top-level function outputs a SDC file
* that constrain a FPGA fabric (P&Red netlist) using a benchmark
*******************************************************************/
void print_analysis_sdc(const std::string& sdc_dir,
void print_analysis_sdc(const AnalysisSdcOption& option,
const float& critical_path_delay,
const VprContext& vpr_ctx,
const OpenfpgaContext& openfpga_ctx,
const std::vector<CircuitPortId>& global_ports,
const bool& compact_routing_hierarchy) {
/* Create the file name for Verilog netlist */
std::string sdc_fname(sdc_dir + std::string(SDC_ANALYSIS_FILE_NAME));
std::string sdc_fname(option.sdc_dir() + std::string(SDC_ANALYSIS_FILE_NAME));
std::string timer_message = std::string("Generating SDC for Timing/Power analysis on the mapped FPGA '")
+ sdc_fname

View File

@ -8,6 +8,7 @@
#include <vector>
#include "vpr_context.h"
#include "openfpga_context.h"
#include "analysis_sdc_option.h"
/********************************************************************
* Function declaration
@ -16,7 +17,7 @@
/* begin namespace openfpga */
namespace openfpga {
void print_analysis_sdc(const std::string& sdc_dir,
void print_analysis_sdc(const AnalysisSdcOption& option,
const float& critical_path_delay,
const VprContext& vpr_ctx,
const OpenfpgaContext& openfpga_ctx,

View File

@ -100,7 +100,7 @@ void disable_analysis_module_input_pin_net_sinks(std::fstream& fp,
module_manager.net_sink_pins(parent_module, module_net)[sink_id]);
/* Get the input id that is used! Disable the unused inputs! */
fp << "set_disable_timing ";
fp << parent_instance_name << "/";
fp << parent_instance_name;
fp << sink_instance_name << "/";
fp << generate_sdc_port(sink_port);
fp << std::endl;
@ -223,7 +223,7 @@ void disable_analysis_module_output_pin_net_sinks(std::fstream& fp,
module_manager.net_sink_pins(parent_module, module_net)[sink_id]);
/* Get the input id that is used! Disable the unused inputs! */
fp << "set_disable_timing ";
fp << parent_instance_name << "/";
fp << parent_instance_name;
fp << sink_instance_name << "/";
fp << generate_sdc_port(sink_port);
fp << std::endl;

View File

@ -52,5 +52,8 @@ write_verilog_testbench --file /var/tmp/xtang/openfpga_test_src/SRC --reference_
# - Turn on every options here
write_pnr_sdc --file /var/tmp/xtang/openfpga_test_src/SDC
# Write the SDC to run timing analysis for a mapped FPGA fabric
write_analysis_sdc --file /var/tmp/xtang/openfpga_test_src/SDC_analysis
# Finish and exit OpenFPGA
exit