[FPGA-SDC] Add a new option ``--no_time_stamp`` to all the commands

This commit is contained in:
tangxifan 2022-01-25 15:51:28 -08:00
parent dd40057992
commit 33064ca4cf
22 changed files with 199 additions and 200 deletions

View File

@ -45,6 +45,7 @@ int write_pnr_sdc(const OpenfpgaContext& openfpga_ctx,
CommandOptionId opt_constrain_routing_multiplexer_outputs = cmd.option("constrain_routing_multiplexer_outputs");
CommandOptionId opt_constrain_switch_block_outputs = cmd.option("constrain_switch_block_outputs");
CommandOptionId opt_constrain_zero_delay_paths = cmd.option("constrain_zero_delay_paths");
CommandOptionId opt_no_time_stamp = cmd.option("no_time_stamp");
/* This is an intermediate data structure which is designed to modularize the FPGA-SDC
* Keep it independent from any other outside data structures
@ -74,6 +75,7 @@ int write_pnr_sdc(const OpenfpgaContext& openfpga_ctx,
options.set_constrain_routing_multiplexer_outputs(cmd_context.option_enable(cmd, opt_constrain_routing_multiplexer_outputs));
options.set_constrain_switch_block_outputs(cmd_context.option_enable(cmd, opt_constrain_switch_block_outputs));
options.set_constrain_zero_delay_paths(cmd_context.option_enable(cmd, opt_constrain_zero_delay_paths));
options.set_time_stamp(!cmd_context.option_enable(cmd, opt_no_time_stamp));
/* We first turn on default sdc option and then disable part of them by following users' options */
if (false == options.generate_sdc_pnr()) {
@ -118,6 +120,7 @@ int write_configuration_chain_sdc(const OpenfpgaContext& openfpga_ctx,
CommandOptionId opt_time_unit = cmd.option("time_unit");
CommandOptionId opt_min_delay = cmd.option("min_delay");
CommandOptionId opt_max_delay = cmd.option("max_delay");
CommandOptionId opt_no_time_stamp = cmd.option("no_time_stamp");
std::string sdc_dir_path = format_dir_path(cmd_context.option_value(cmd, opt_output_dir));
@ -128,6 +131,7 @@ int write_configuration_chain_sdc(const OpenfpgaContext& openfpga_ctx,
time_unit,
std::stof(cmd_context.option_value(cmd, opt_max_delay)),
std::stof(cmd_context.option_value(cmd, opt_min_delay)),
!cmd_context.option_enable(cmd, opt_no_time_stamp),
openfpga_ctx.module_graph());
return CMD_EXEC_SUCCESS;
@ -143,6 +147,7 @@ int write_sdc_disable_timing_configure_ports(const OpenfpgaContext& openfpga_ctx
/* Get command options */
CommandOptionId opt_output_dir = cmd.option("file");
CommandOptionId opt_flatten_names = cmd.option("flatten_names");
CommandOptionId opt_no_time_stamp = cmd.option("no_time_stamp");
CommandOptionId opt_verbose = cmd.option("verbose");
std::string sdc_dir_path = format_dir_path(cmd_context.option_value(cmd, opt_output_dir));
@ -154,6 +159,7 @@ int write_sdc_disable_timing_configure_ports(const OpenfpgaContext& openfpga_ctx
openfpga_ctx.mux_lib(),
openfpga_ctx.arch().circuit_lib,
openfpga_ctx.module_graph(),
!cmd_context.option_enable(cmd, opt_no_time_stamp),
cmd_context.option_enable(cmd, opt_verbose))) {
return CMD_EXEC_FATAL_ERROR;
}
@ -170,6 +176,7 @@ int write_analysis_sdc(const OpenfpgaContext& openfpga_ctx,
CommandOptionId opt_output_dir = cmd.option("file");
CommandOptionId opt_flatten_names = cmd.option("flatten_names");
CommandOptionId opt_time_unit = cmd.option("time_unit");
CommandOptionId opt_no_time_stamp = cmd.option("no_time_stamp");
/* This is an intermediate data structure which is designed to modularize the FPGA-SDC
* Keep it independent from any other outside data structures
@ -182,6 +189,7 @@ int write_analysis_sdc(const OpenfpgaContext& openfpga_ctx,
AnalysisSdcOption options(sdc_dir_path);
options.set_generate_sdc_analysis(true);
options.set_flatten_names(cmd_context.option_enable(cmd, opt_flatten_names));
options.set_time_stamp(!cmd_context.option_enable(cmd, opt_no_time_stamp));
if (true == cmd_context.option_enable(cmd, opt_time_unit)) {
options.set_time_unit(string_to_time_unit(cmd_context.option_value(cmd, opt_time_unit)));

View File

@ -66,6 +66,9 @@ ShellCommandId add_openfpga_write_pnr_sdc_command(openfpga::Shell<OpenfpgaContex
/* Add an option '--constrain_zero_delay_paths' */
shell_cmd.add_option("constrain_zero_delay_paths", false, "Constrain zero-delay paths in FPGA fabric");
/* Add an option '--no_time_stamp' */
shell_cmd.add_option("no_time_stamp", false, "Do not print time stamp in output files");
/* Add an option '--verbose' */
shell_cmd.add_option("verbose", false, "Enable verbose output");
@ -108,6 +111,9 @@ ShellCommandId add_openfpga_write_configuration_chain_sdc_command(openfpga::Shel
CommandOptionId max_dly_opt = shell_cmd.add_option("max_delay", false, "Specify the maximum delay to be used.");
shell_cmd.set_option_require_value(max_dly_opt, openfpga::OPT_STRING);
/* Add an option '--no_time_stamp' */
shell_cmd.add_option("no_time_stamp", false, "Do not print time stamp in output files");
/* Add command 'write_configuration_chain_sdc' to the Shell */
ShellCommandId shell_cmd_id = shell.add_command(shell_cmd, "generate SDC files to constrain the configuration chain for FPGA fabric");
shell.set_command_class(shell_cmd_id, cmd_class_id);
@ -138,6 +144,9 @@ ShellCommandId add_openfpga_write_sdc_disable_timing_configure_ports_command(ope
/* Add an option '--flatten_name' */
shell_cmd.add_option("flatten_names", false, "Use flatten names (no wildcards) in SDC files");
/* Add an option '--no_time_stamp' */
shell_cmd.add_option("no_time_stamp", false, "Do not print time stamp in output files");
/* Add an option '--verbose' */
shell_cmd.add_option("verbose", false, "Enable verbose outputs");
@ -178,6 +187,9 @@ ShellCommandId add_openfpga_write_analysis_sdc_command(openfpga::Shell<OpenfpgaC
CommandOptionId time_unit_opt = shell_cmd.add_option("time_unit", false, "Specify the time unit in SDC files. Acceptable is [a|f|p|n|u|m|kM]s");
shell_cmd.set_option_require_value(time_unit_opt, openfpga::OPT_STRING);
/* Add an option '--no_time_stamp' */
shell_cmd.add_option("no_time_stamp", false, "Do not print time stamp in output files");
/* 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);

View File

@ -13,6 +13,7 @@ AnalysisSdcOption::AnalysisSdcOption(const std::string& sdc_dir) {
sdc_dir_ = sdc_dir;
flatten_names_ = false;
time_unit_ = 1.;
time_stamp_ = true;
generate_sdc_analysis_ = false;
}
@ -31,6 +32,10 @@ float AnalysisSdcOption::time_unit() const {
return time_unit_;
}
bool AnalysisSdcOption::time_stamp() const {
return time_stamp_;
}
bool AnalysisSdcOption::generate_sdc_analysis() const {
return generate_sdc_analysis_;
}
@ -50,6 +55,10 @@ void AnalysisSdcOption::set_time_unit(const float& time_unit) {
time_unit_ = time_unit;
}
void AnalysisSdcOption::set_time_stamp(const bool& enable) {
time_stamp_ = enable;
}
void AnalysisSdcOption::set_generate_sdc_analysis(const bool& generate_sdc_analysis) {
generate_sdc_analysis_ = generate_sdc_analysis;
}

View File

@ -19,9 +19,11 @@ class AnalysisSdcOption {
bool flatten_names() const;
float time_unit() const;
bool generate_sdc_analysis() const;
bool time_stamp() const;
public: /* Public mutators */
void set_sdc_dir(const std::string& sdc_dir);
void set_flatten_names(const bool& flatten_names);
void set_time_stamp(const bool& time_stamp);
void set_time_unit(const float& time_unit);
void set_generate_sdc_analysis(const bool& generate_sdc_analysis);
private: /* Internal data */
@ -29,6 +31,7 @@ class AnalysisSdcOption {
bool generate_sdc_analysis_;
bool flatten_names_;
float time_unit_;
bool time_stamp_;
};
} /* end namespace openfpga */

View File

@ -235,7 +235,9 @@ void print_analysis_sdc(const AnalysisSdcOption& option,
check_file_stream(sdc_fname.c_str(), fp);
/* Generate the descriptions*/
print_sdc_file_header(fp, std::string("Constrain for Timing/Power analysis on the mapped FPGA"));
print_sdc_file_header(fp,
std::string("Constrain for Timing/Power analysis on the mapped FPGA"),
option.time_stamp());
/* Find the top_module */
ModuleId top_module = openfpga_ctx.module_graph().find_module(generate_fpga_top_module_name());

View File

@ -133,6 +133,7 @@ void print_pnr_sdc_constrain_configurable_chain(const std::string& sdc_fname,
const float& time_unit,
const float& max_delay,
const float& min_delay,
const bool& include_time_stamp,
const ModuleManager& module_manager) {
/* Create the directory */
@ -149,7 +150,9 @@ void print_pnr_sdc_constrain_configurable_chain(const std::string& sdc_fname,
check_file_stream(sdc_fname.c_str(), fp);
/* Generate the descriptions*/
print_sdc_file_header(fp, std::string("Timing constraints for configurable chains used in PnR"));
print_sdc_file_header(fp,
std::string("Timing constraints for configurable chains used in PnR"),
include_time_stamp);
/* Print time unit for the SDC file */
print_sdc_timescale(fp, time_unit_to_string(time_unit));

View File

@ -19,6 +19,7 @@ void print_pnr_sdc_constrain_configurable_chain(const std::string& sdc_fname,
const float& time_unit,
const float& max_delay,
const float& min_delay,
const bool& include_time_stamp,
const ModuleManager& module_manager);
} /* end namespace openfpga */

View File

@ -187,6 +187,7 @@ int print_sdc_disable_timing_configure_ports(const std::string& sdc_fname,
const MuxLibrary& mux_lib,
const CircuitLibrary& circuit_lib,
const ModuleManager& module_manager,
const bool& include_time_stamp,
const bool& verbose) {
/* Create the directory */
create_directory(find_path_dir_name(sdc_fname));
@ -202,7 +203,9 @@ int print_sdc_disable_timing_configure_ports(const std::string& sdc_fname,
check_file_stream(sdc_fname.c_str(), fp);
/* Generate the descriptions*/
print_sdc_file_header(fp, std::string("Disable configuration outputs of all the programmable cells for PnR"));
print_sdc_file_header(fp,
std::string("Disable configuration outputs of all the programmable cells for PnR"),
include_time_stamp);
std::string top_module_name = generate_fpga_top_module_name();
ModuleId top_module = module_manager.find_module(top_module_name);

View File

@ -20,6 +20,7 @@ int print_sdc_disable_timing_configure_ports(const std::string& sdc_fname,
const MuxLibrary& mux_lib,
const CircuitLibrary& circuit_lib,
const ModuleManager& module_manager,
const bool& include_time_stamp,
const bool& verbose);
} /* end namespace openfpga */

View File

@ -163,13 +163,16 @@ void print_pnr_sdc_global_non_clock_ports(std::fstream& fp,
* should be treated in CTS or not
* In general, we do not recommend to do this
*******************************************************************/
void print_pnr_sdc_global_ports(const std::string& sdc_dir,
const float& time_unit,
void print_pnr_sdc_global_ports(const PnrSdcOption& options,
const ModuleManager& module_manager,
const ModuleId& top_module,
const FabricGlobalPortInfo& global_ports,
const SimulationSetting& sim_setting,
const bool& constrain_non_clock_port) {
const SimulationSetting& sim_setting) {
std::string sdc_dir = options.sdc_dir();
float time_unit = options.time_unit();
bool include_time_stamp = options.time_stamp();
bool constrain_non_clock_port = options.constrain_non_clock_global_port();
/* Create the file name for Verilog netlist */
std::string sdc_fname(sdc_dir + std::string(SDC_GLOBAL_PORTS_FILE_NAME));
@ -185,7 +188,9 @@ void print_pnr_sdc_global_ports(const std::string& sdc_dir,
check_file_stream(sdc_fname.c_str(), fp);
/* Generate the descriptions*/
print_sdc_file_header(fp, std::string("Clock contraints for PnR"));
print_sdc_file_header(fp,
std::string("Clock contraints for PnR"),
include_time_stamp);
/* Print time unit for the SDC file */
print_sdc_timescale(fp, time_unit_to_string(time_unit));

View File

@ -9,6 +9,7 @@
#include "module_manager.h"
#include "fabric_global_port_info.h"
#include "simulation_setting.h"
#include "pnr_sdc_option.h"
/********************************************************************
* Function declaration
@ -17,13 +18,11 @@
/* begin namespace openfpga */
namespace openfpga {
void print_pnr_sdc_global_ports(const std::string& sdc_dir,
const float& time_unit,
void print_pnr_sdc_global_ports(const PnrSdcOption& options,
const ModuleManager& module_manager,
const ModuleId& top_module,
const FabricGlobalPortInfo& global_ports,
const SimulationSetting& sim_setting,
const bool& constrain_non_clock_port);
const SimulationSetting& sim_setting);
} /* end namespace openfpga */

View File

@ -240,14 +240,16 @@ void print_pnr_sdc_constrain_pb_interc_timing(std::fstream& fp,
* 3. output port of child_pb_graph_node and input port of child_pb_graph_nodes
*******************************************************************/
static
void print_pnr_sdc_constrain_pb_graph_node_timing(const std::string& sdc_dir,
const float& time_unit,
const bool& hierarchical,
void print_pnr_sdc_constrain_pb_graph_node_timing(const PnrSdcOption& options,
const std::string& module_path,
const ModuleManager& module_manager,
t_pb_graph_node* parent_pb_graph_node,
t_mode* physical_mode,
const bool& constrain_zero_delay_paths) {
t_mode* physical_mode) {
std::string sdc_dir = options.sdc_dir();
float time_unit = options.time_unit();
bool hierarchical = options.hierarchical();
bool include_time_stamp = options.time_stamp();
bool constrain_zero_delay_paths = options.constrain_zero_delay_paths();
/* Get the pb_type definition related to the node */
t_pb_type* physical_pb_type = parent_pb_graph_node->pb_type;
@ -267,7 +269,9 @@ void print_pnr_sdc_constrain_pb_graph_node_timing(const std::string& sdc_dir,
check_file_stream(sdc_fname.c_str(), fp);
/* Generate the descriptions*/
print_sdc_file_header(fp, std::string("Timing constraints for Grid " + pb_module_name + " in PnR"));
print_sdc_file_header(fp,
std::string("Timing constraints for Grid " + pb_module_name + " in PnR"),
include_time_stamp);
/* Print time unit for the SDC file */
print_sdc_timescale(fp, time_unit_to_string(time_unit));
@ -326,13 +330,10 @@ void print_pnr_sdc_constrain_pb_graph_node_timing(const std::string& sdc_dir,
* When PnR the modules, we want to minimize the interconnect delay
*******************************************************************/
static
void print_pnr_sdc_constrain_primitive_pb_graph_node(const std::string& sdc_dir,
const float& time_unit,
const bool& hierarchical,
void print_pnr_sdc_constrain_primitive_pb_graph_node(const PnrSdcOption& options,
const std::string& module_path,
const ModuleManager& module_manager,
t_pb_graph_node* primitive_pb_graph_node,
const bool& constrain_zero_delay_paths) {
t_pb_graph_node* primitive_pb_graph_node) {
/* Validate pb_graph node */
if (nullptr == primitive_pb_graph_node) {
VTR_LOGF_ERROR(__FILE__, __LINE__,
@ -378,7 +379,7 @@ void print_pnr_sdc_constrain_primitive_pb_graph_node(const std::string& sdc_dir,
VTR_ASSERT(true == module_manager.valid_module_id(pb_module));
/* Create the file name for SDC */
std::string sdc_fname(sdc_dir + pb_module_name + std::string(SDC_FILE_NAME_POSTFIX));
std::string sdc_fname(options.sdc_dir() + pb_module_name + std::string(SDC_FILE_NAME_POSTFIX));
/* Create the file stream */
std::fstream fp;
@ -387,10 +388,12 @@ void print_pnr_sdc_constrain_primitive_pb_graph_node(const std::string& sdc_dir,
check_file_stream(sdc_fname.c_str(), fp);
/* Generate the descriptions*/
print_sdc_file_header(fp, std::string("Timing constraints for Grid " + pb_module_name + " in PnR"));
print_sdc_file_header(fp,
std::string("Timing constraints for Grid " + pb_module_name + " in PnR"),
options.time_stamp());
/* Print time unit for the SDC file */
print_sdc_timescale(fp, time_unit_to_string(time_unit));
print_sdc_timescale(fp, time_unit_to_string(options.time_unit()));
/* We traverse the pb_graph pins where we can find pin-to-pin timing annotation
* We walk through input pins here, build timing constraints by pair each input to output
@ -424,32 +427,32 @@ void print_pnr_sdc_constrain_primitive_pb_graph_node(const std::string& sdc_dir,
/* Generate module path in hierarchy depending if the hierarchical is enabled */
std::string module_hie_path = pb_module_name;
if (false == hierarchical) {
if (false == options.hierarchical()) {
module_hie_path = module_path + pb_module_name;
}
/* If the delay is zero, constrain only when user wants it */
if ( (true == constrain_zero_delay_paths)
if ( (true == options.constrain_zero_delay_paths())
|| (0. != tmax) ) {
print_pnr_sdc_constrain_max_delay(fp,
module_hie_path,
generate_sdc_port(src_port),
module_hie_path,
generate_sdc_port(sink_port),
tmax / time_unit);
tmax / options.time_unit());
}
/* Find min delay between src and sink pin */
float tmin = src_pin->pin_timing_del_min[itiming];
/* If the delay is zero, constrain only when user wants it */
if ( (true == constrain_zero_delay_paths)
if ( (true == options.constrain_zero_delay_paths())
|| (0. != tmin) ) {
print_pnr_sdc_constrain_min_delay(fp,
module_hie_path,
generate_sdc_port(src_port),
module_hie_path,
generate_sdc_port(sink_port),
tmin / time_unit);
tmin / options.time_unit());
}
}
}
@ -465,14 +468,11 @@ void print_pnr_sdc_constrain_primitive_pb_graph_node(const std::string& sdc_dir,
* constraining the pin-to-pin timing
*******************************************************************/
static
void rec_print_pnr_sdc_constrain_pb_graph_timing(const std::string& sdc_dir,
const float& time_unit,
const bool& hierarchical,
void rec_print_pnr_sdc_constrain_pb_graph_timing(const PnrSdcOption& options,
const std::string& module_path,
const ModuleManager& module_manager,
const VprDeviceAnnotation& device_annotation,
t_pb_graph_node* parent_pb_graph_node,
const bool& constrain_zero_delay_paths) {
t_pb_graph_node* parent_pb_graph_node) {
/* Validate pb_graph node */
if (nullptr == parent_pb_graph_node) {
VTR_LOGF_ERROR(__FILE__, __LINE__,
@ -485,13 +485,10 @@ void rec_print_pnr_sdc_constrain_pb_graph_timing(const std::string& sdc_dir,
/* Constrain the primitive node if a timing matrix is defined */
if (true == is_primitive_pb_type(parent_pb_type)) {
print_pnr_sdc_constrain_primitive_pb_graph_node(sdc_dir,
time_unit,
hierarchical,
print_pnr_sdc_constrain_primitive_pb_graph_node(options,
module_path,
module_manager,
parent_pb_graph_node,
constrain_zero_delay_paths);
parent_pb_graph_node);
return;
}
@ -501,41 +498,32 @@ void rec_print_pnr_sdc_constrain_pb_graph_timing(const std::string& sdc_dir,
t_mode* physical_mode = device_annotation.physical_mode(parent_pb_type);
/* Write a SDC file for this pb_type */
print_pnr_sdc_constrain_pb_graph_node_timing(sdc_dir,
time_unit,
hierarchical,
print_pnr_sdc_constrain_pb_graph_node_timing(options,
module_path,
module_manager,
parent_pb_graph_node,
physical_mode,
constrain_zero_delay_paths);
physical_mode);
/* Go recursively to the lower level in the pb_graph
* Note that we assume a full hierarchical P&R, we will only visit pb_graph_node of unique pb_type
*/
for (int ipb = 0; ipb < physical_mode->num_pb_type_children; ++ipb) {
rec_print_pnr_sdc_constrain_pb_graph_timing(sdc_dir,
time_unit,
hierarchical,
rec_print_pnr_sdc_constrain_pb_graph_timing(options,
format_dir_path(module_path + generate_physical_block_instance_name(&(physical_mode->pb_type_children[ipb]), ipb)),
module_manager,
device_annotation,
&(parent_pb_graph_node->child_pb_graph_nodes[physical_mode->index][ipb][0]),
constrain_zero_delay_paths);
&(parent_pb_graph_node->child_pb_graph_nodes[physical_mode->index][ipb][0]));
}
}
/********************************************************************
* Top-level function to print timing constraints for pb_types
*******************************************************************/
void print_pnr_sdc_constrain_grid_timing(const std::string& sdc_dir,
const float& time_unit,
const bool& hierarchical,
void print_pnr_sdc_constrain_grid_timing(const PnrSdcOption& options,
const DeviceContext& device_ctx,
const VprDeviceAnnotation& device_annotation,
const ModuleManager& module_manager,
const ModuleId& top_module,
const bool& constrain_zero_delay_paths) {
const ModuleId& top_module) {
/* Start time count */
vtr::ScopedStartFinishTimer timer("Write SDC for constraining grid timing for P&R flow");
@ -580,14 +568,11 @@ void print_pnr_sdc_constrain_grid_timing(const std::string& sdc_dir,
std::string module_path = format_dir_path(root_path + grid_module_name);
module_path = format_dir_path(module_path + generate_physical_block_instance_name(pb_graph_head->pb_type, pb_graph_head->placement_index));
rec_print_pnr_sdc_constrain_pb_graph_timing(sdc_dir,
time_unit,
hierarchical,
rec_print_pnr_sdc_constrain_pb_graph_timing(options,
module_path,
module_manager,
device_annotation,
pb_graph_head,
constrain_zero_delay_paths);
pb_graph_head);
}
} else {
/* For CLB and heterogenenous blocks */
@ -602,14 +587,11 @@ void print_pnr_sdc_constrain_grid_timing(const std::string& sdc_dir,
std::string module_path = format_dir_path(root_path + grid_module_name);
module_path = format_dir_path(module_path + generate_physical_block_instance_name(pb_graph_head->pb_type, pb_graph_head->placement_index));
rec_print_pnr_sdc_constrain_pb_graph_timing(sdc_dir,
time_unit,
hierarchical,
rec_print_pnr_sdc_constrain_pb_graph_timing(options,
module_path,
module_manager,
device_annotation,
pb_graph_head,
constrain_zero_delay_paths);
pb_graph_head);
}
}
}

View File

@ -9,6 +9,7 @@
#include "vpr_context.h"
#include "vpr_device_annotation.h"
#include "module_manager.h"
#include "pnr_sdc_option.h"
/********************************************************************
* Function declaration
@ -17,14 +18,11 @@
/* begin namespace openfpga */
namespace openfpga {
void print_pnr_sdc_constrain_grid_timing(const std::string& sdc_dir,
const float& time_unit,
const bool& hierarchical,
void print_pnr_sdc_constrain_grid_timing(const PnrSdcOption& options,
const DeviceContext& device_ctx,
const VprDeviceAnnotation& device_annotation,
const ModuleManager& module_manager,
const ModuleId& top_module,
const bool& constrain_zero_delay_paths);
const ModuleId& top_module);
} /* end namespace openfpga */

View File

@ -23,6 +23,7 @@ PnrSdcOption::PnrSdcOption(const std::string& sdc_dir) {
constrain_routing_multiplexer_outputs_ = false;
constrain_switch_block_outputs_ = false;
constrain_zero_delay_paths_ = false;
time_stamp_ = true;
}
/********************************************************************
@ -94,6 +95,10 @@ bool PnrSdcOption::constrain_zero_delay_paths() const {
return constrain_zero_delay_paths_;
}
bool PnrSdcOption::time_stamp() const {
return time_stamp_;
}
/********************************************************************
* Public mutators
********************************************************************/
@ -163,4 +168,8 @@ void PnrSdcOption::set_constrain_zero_delay_paths(const bool& constrain_zero_del
constrain_zero_delay_paths_ = constrain_zero_delay_paths;
}
void PnrSdcOption::set_time_stamp(const bool& enable) {
time_stamp_ = enable;
}
} /* end namespace openfpga */

View File

@ -30,6 +30,7 @@ class PnrSdcOption {
bool constrain_routing_multiplexer_outputs() const;
bool constrain_switch_block_outputs() const;
bool constrain_zero_delay_paths() const;
bool time_stamp() const;
public: /* Public mutators */
void set_sdc_dir(const std::string& sdc_dir);
void set_flatten_names(const bool& flatten_names);
@ -46,6 +47,7 @@ class PnrSdcOption {
void set_constrain_routing_multiplexer_outputs(const bool& constrain_routing_mux_outputs);
void set_constrain_switch_block_outputs(const bool& constrain_sb_outputs);
void set_constrain_zero_delay_paths(const bool& constrain_zero_delay_paths);
void set_time_stamp(const bool& enable);
private: /* Internal data */
std::string sdc_dir_;
bool flatten_names_;
@ -61,6 +63,7 @@ class PnrSdcOption {
bool constrain_routing_multiplexer_outputs_;
bool constrain_switch_block_outputs_;
bool constrain_zero_delay_paths_;
bool time_stamp_;
};
} /* end namespace openfpga */

View File

@ -142,16 +142,18 @@ void print_pnr_sdc_constrain_sb_mux_timing(std::fstream& fp,
* file for each unique SB module
*******************************************************************/
static
void print_pnr_sdc_constrain_sb_timing(const std::string& sdc_dir,
const float& time_unit,
const bool& hierarchical,
void print_pnr_sdc_constrain_sb_timing(const PnrSdcOption& options,
const std::string& module_path,
const ModuleManager& module_manager,
const VprDeviceAnnotation& device_annotation,
const DeviceGrid& grids,
const RRGraph& rr_graph,
const RRGSB& rr_gsb,
const bool& constrain_zero_delay_paths) {
const RRGSB& rr_gsb) {
std::string sdc_dir = options.sdc_dir();
float time_unit = options.time_unit();
bool hierarchical = options.hierarchical();
bool include_time_stamp = options.time_stamp();
bool constrain_zero_delay_paths = options.constrain_zero_delay_paths();
/* Create the file name for Verilog netlist */
vtr::Point<size_t> gsb_coordinate(rr_gsb.get_sb_x(), rr_gsb.get_sb_y());
@ -169,7 +171,9 @@ void print_pnr_sdc_constrain_sb_timing(const std::string& sdc_dir,
VTR_ASSERT(true == module_manager.valid_module_id(sb_module));
/* Generate the descriptions*/
print_sdc_file_header(fp, std::string("Constrain timing of Switch Block " + sb_module_name + " for PnR"));
print_sdc_file_header(fp,
std::string("Constrain timing of Switch Block " + sb_module_name + " for PnR"),
include_time_stamp);
/* Print time unit for the SDC file */
print_sdc_timescale(fp, time_unit_to_string(time_unit));
@ -210,16 +214,13 @@ void print_pnr_sdc_constrain_sb_timing(const std::string& sdc_dir,
* Print SDC timing constraints for Switch blocks
* This function is designed for flatten routing hierarchy
*******************************************************************/
void print_pnr_sdc_flatten_routing_constrain_sb_timing(const std::string& sdc_dir,
const float& time_unit,
const bool& hierarchical,
void print_pnr_sdc_flatten_routing_constrain_sb_timing(const PnrSdcOption& options,
const ModuleManager& module_manager,
const ModuleId& top_module,
const VprDeviceAnnotation& device_annotation,
const DeviceGrid& grids,
const RRGraph& rr_graph,
const DeviceRRGSB& device_rr_gsb,
const bool& constrain_zero_delay_paths) {
const DeviceRRGSB& device_rr_gsb) {
/* Start time count */
vtr::ScopedStartFinishTimer timer("Write SDC for constrain Switch Block timing for P&R flow");
@ -244,16 +245,13 @@ void print_pnr_sdc_flatten_routing_constrain_sb_timing(const std::string& sdc_di
std::string module_path = format_dir_path(root_path) + sb_instance_name;
print_pnr_sdc_constrain_sb_timing(sdc_dir,
time_unit,
hierarchical,
print_pnr_sdc_constrain_sb_timing(options,
module_path,
module_manager,
device_annotation,
grids,
rr_graph,
rr_gsb,
constrain_zero_delay_paths);
rr_gsb);
}
}
}
@ -262,16 +260,13 @@ void print_pnr_sdc_flatten_routing_constrain_sb_timing(const std::string& sdc_di
* Print SDC timing constraints for Switch blocks
* This function is designed for compact routing hierarchy
*******************************************************************/
void print_pnr_sdc_compact_routing_constrain_sb_timing(const std::string& sdc_dir,
const float& time_unit,
const bool& hierarchical,
void print_pnr_sdc_compact_routing_constrain_sb_timing(const PnrSdcOption& options,
const ModuleManager& module_manager,
const ModuleId& top_module,
const VprDeviceAnnotation& device_annotation,
const DeviceGrid& grids,
const RRGraph& rr_graph,
const DeviceRRGSB& device_rr_gsb,
const bool& constrain_zero_delay_paths) {
const DeviceRRGSB& device_rr_gsb) {
/* Start time count */
vtr::ScopedStartFinishTimer timer("Write SDC for constrain Switch Block timing for P&R flow");
@ -295,16 +290,13 @@ void print_pnr_sdc_compact_routing_constrain_sb_timing(const std::string& sdc_di
std::string module_path = format_dir_path(root_path) + sb_module_name;
print_pnr_sdc_constrain_sb_timing(sdc_dir,
time_unit,
hierarchical,
print_pnr_sdc_constrain_sb_timing(options,
module_path,
module_manager,
device_annotation,
grids,
rr_graph,
rr_gsb,
constrain_zero_delay_paths);
rr_gsb);
}
}
@ -420,17 +412,20 @@ void print_pnr_sdc_constrain_cb_mux_timing(std::fstream& fp,
* This function is designed for compact routing hierarchy
*******************************************************************/
static
void print_pnr_sdc_constrain_cb_timing(const std::string& sdc_dir,
const float& time_unit,
const bool& hierarchical,
void print_pnr_sdc_constrain_cb_timing(const PnrSdcOption& options,
const std::string& module_path,
const ModuleManager& module_manager,
const VprDeviceAnnotation& device_annotation,
const DeviceGrid& grids,
const RRGraph& rr_graph,
const RRGSB& rr_gsb,
const t_rr_type& cb_type,
const bool& constrain_zero_delay_paths) {
const t_rr_type& cb_type) {
std::string sdc_dir = options.sdc_dir();
float time_unit = options.time_unit();
bool include_time_stamp = options.time_stamp();
bool hierarchical = options.hierarchical();
bool constrain_zero_delay_paths = options.constrain_zero_delay_paths();
/* Create the netlist */
vtr::Point<size_t> gsb_coordinate(rr_gsb.get_cb_x(cb_type), rr_gsb.get_cb_y(cb_type));
@ -449,7 +444,9 @@ void print_pnr_sdc_constrain_cb_timing(const std::string& sdc_dir,
VTR_ASSERT(true == module_manager.valid_module_id(cb_module));
/* Generate the descriptions*/
print_sdc_file_header(fp, std::string("Constrain timing of Connection Block " + cb_module_name + " for PnR"));
print_sdc_file_header(fp,
std::string("Constrain timing of Connection Block " + cb_module_name + " for PnR"),
include_time_stamp);
/* Print time unit for the SDC file */
print_sdc_timescale(fp, time_unit_to_string(time_unit));
@ -538,17 +535,14 @@ void print_pnr_sdc_constrain_cb_timing(const std::string& sdc_dir,
* and print SDC file for each of them
*******************************************************************/
static
void print_pnr_sdc_flatten_routing_constrain_cb_timing(const std::string& sdc_dir,
const float& time_unit,
const bool& hierarchical,
void print_pnr_sdc_flatten_routing_constrain_cb_timing(const PnrSdcOption& options,
const ModuleManager& module_manager,
const ModuleId& top_module,
const VprDeviceAnnotation& device_annotation,
const DeviceGrid& grids,
const RRGraph& rr_graph,
const DeviceRRGSB& device_rr_gsb,
const t_rr_type& cb_type,
const bool& constrain_zero_delay_paths) {
const t_rr_type& cb_type) {
/* Build unique X-direction connection block modules */
vtr::Point<size_t> cb_range = device_rr_gsb.get_gsb_range();
@ -575,17 +569,14 @@ void print_pnr_sdc_flatten_routing_constrain_cb_timing(const std::string& sdc_di
std::string module_path = format_dir_path(root_path) + cb_instance_name;
print_pnr_sdc_constrain_cb_timing(sdc_dir,
time_unit,
hierarchical,
print_pnr_sdc_constrain_cb_timing(options,
module_path,
module_manager,
device_annotation,
grids,
rr_graph,
rr_gsb,
cb_type,
constrain_zero_delay_paths);
cb_type);
}
}
@ -595,55 +586,45 @@ void print_pnr_sdc_flatten_routing_constrain_cb_timing(const std::string& sdc_di
* Iterate over all the connection blocks in a device
* and print SDC file for each of them
*******************************************************************/
void print_pnr_sdc_flatten_routing_constrain_cb_timing(const std::string& sdc_dir,
const float& time_unit,
const bool& hierarchical,
void print_pnr_sdc_flatten_routing_constrain_cb_timing(const PnrSdcOption& options,
const ModuleManager& module_manager,
const ModuleId& top_module,
const VprDeviceAnnotation& device_annotation,
const DeviceGrid& grids,
const RRGraph& rr_graph,
const DeviceRRGSB& device_rr_gsb,
const bool& constrain_zero_delay_paths) {
const DeviceRRGSB& device_rr_gsb) {
/* Start time count */
vtr::ScopedStartFinishTimer timer("Write SDC for constrain Connection Block timing for P&R flow");
print_pnr_sdc_flatten_routing_constrain_cb_timing(sdc_dir, time_unit,
hierarchical,
print_pnr_sdc_flatten_routing_constrain_cb_timing(options,
module_manager, top_module,
device_annotation,
grids,
rr_graph,
device_rr_gsb,
CHANX,
constrain_zero_delay_paths);
CHANX);
print_pnr_sdc_flatten_routing_constrain_cb_timing(sdc_dir, time_unit,
hierarchical,
print_pnr_sdc_flatten_routing_constrain_cb_timing(options,
module_manager, top_module,
device_annotation,
grids,
rr_graph,
device_rr_gsb,
CHANY,
constrain_zero_delay_paths);
CHANY);
}
/********************************************************************
* Print SDC timing constraints for Connection blocks
* This function is designed for compact routing hierarchy
*******************************************************************/
void print_pnr_sdc_compact_routing_constrain_cb_timing(const std::string& sdc_dir,
const float& time_unit,
const bool& hierarchical,
void print_pnr_sdc_compact_routing_constrain_cb_timing(const PnrSdcOption& options,
const ModuleManager& module_manager,
const ModuleId& top_module,
const VprDeviceAnnotation& device_annotation,
const DeviceGrid& grids,
const RRGraph& rr_graph,
const DeviceRRGSB& device_rr_gsb,
const bool& constrain_zero_delay_paths) {
const DeviceRRGSB& device_rr_gsb) {
/* Start time count */
vtr::ScopedStartFinishTimer timer("Write SDC for constrain Connection Block timing for P&R flow");
@ -664,17 +645,14 @@ void print_pnr_sdc_compact_routing_constrain_cb_timing(const std::string& sdc_di
std::string module_path = format_dir_path(root_path) + cb_module_name;
print_pnr_sdc_constrain_cb_timing(sdc_dir,
time_unit,
hierarchical,
print_pnr_sdc_constrain_cb_timing(options,
module_path,
module_manager,
device_annotation,
grids,
rr_graph,
unique_mirror,
CHANX,
constrain_zero_delay_paths);
CHANX);
}
/* Print SDC for unique Y-direction connection block modules */
@ -691,17 +669,14 @@ void print_pnr_sdc_compact_routing_constrain_cb_timing(const std::string& sdc_di
std::string module_path = format_dir_path(root_path) + cb_module_name;
print_pnr_sdc_constrain_cb_timing(sdc_dir,
time_unit,
hierarchical,
print_pnr_sdc_constrain_cb_timing(options,
module_path,
module_manager,
device_annotation,
grids,
rr_graph,
unique_mirror,
CHANY,
constrain_zero_delay_paths);
CHANY);
}
}

View File

@ -11,6 +11,7 @@
#include "rr_graph_obj.h"
#include "device_grid.h"
#include "vpr_device_annotation.h"
#include "pnr_sdc_option.h"
/********************************************************************
* Function declaration
@ -19,49 +20,37 @@
/* begin namespace openfpga */
namespace openfpga {
void print_pnr_sdc_flatten_routing_constrain_sb_timing(const std::string& sdc_dir,
const float& time_unit,
const bool& hierarchical,
void print_pnr_sdc_flatten_routing_constrain_sb_timing(const PnrSdcOption& options,
const ModuleManager& module_manager,
const ModuleId& top_module,
const VprDeviceAnnotation& device_annotation,
const DeviceGrid& grids,
const RRGraph& rr_graph,
const DeviceRRGSB& device_rr_gsb,
const bool& constrain_zero_delay_paths);
const DeviceRRGSB& device_rr_gsb);
void print_pnr_sdc_compact_routing_constrain_sb_timing(const std::string& sdc_dir,
const float& time_unit,
const bool& hierarchical,
void print_pnr_sdc_compact_routing_constrain_sb_timing(const PnrSdcOption& options,
const ModuleManager& module_manager,
const ModuleId& top_module,
const VprDeviceAnnotation& device_annotation,
const DeviceGrid& grids,
const RRGraph& rr_graph,
const DeviceRRGSB& device_rr_gsb,
const bool& constrain_zero_delay_paths);
const DeviceRRGSB& device_rr_gsb);
void print_pnr_sdc_flatten_routing_constrain_cb_timing(const std::string& sdc_dir,
const float& time_unit,
const bool& hierarchical,
void print_pnr_sdc_flatten_routing_constrain_cb_timing(const PnrSdcOption& options,
const ModuleManager& module_manager,
const ModuleId& top_module,
const VprDeviceAnnotation& device_annotation,
const DeviceGrid& grids,
const RRGraph& rr_graph,
const DeviceRRGSB& device_rr_gsb,
const bool& constrain_zero_delay_paths);
const DeviceRRGSB& device_rr_gsb);
void print_pnr_sdc_compact_routing_constrain_cb_timing(const std::string& sdc_dir,
const float& time_unit,
const bool& hierarchical,
void print_pnr_sdc_compact_routing_constrain_cb_timing(const PnrSdcOption& options,
const ModuleManager& module_manager,
const ModuleId& top_module,
const VprDeviceAnnotation& device_annotation,
const DeviceGrid& grids,
const RRGraph& rr_graph,
const DeviceRRGSB& device_rr_gsb,
const bool& constrain_zero_delay_paths);
const DeviceRRGSB& device_rr_gsb);
} /* end namespace openfpga */

View File

@ -47,6 +47,7 @@ namespace openfpga {
static
void print_pnr_sdc_constrain_configurable_memory_outputs(const std::string& sdc_dir,
const bool& flatten_names,
const bool& include_time_stamp,
const ModuleManager& module_manager,
const ModuleId& top_module) {
@ -64,7 +65,7 @@ void print_pnr_sdc_constrain_configurable_memory_outputs(const std::string& sdc_
check_file_stream(sdc_fname.c_str(), fp);
/* Generate the descriptions*/
print_sdc_file_header(fp, std::string("Disable configurable memory outputs for PnR"));
print_sdc_file_header(fp, std::string("Disable configurable memory outputs for PnR"), include_time_stamp);
/* Go recursively in the module manager, starting from the top-level module: instance id of the top-level module is 0 by default */
rec_print_pnr_sdc_disable_configurable_memory_module_output(fp, flatten_names,
@ -84,6 +85,7 @@ void print_pnr_sdc_constrain_configurable_memory_outputs(const std::string& sdc_
static
void print_pnr_sdc_flatten_routing_disable_switch_block_outputs(const std::string& sdc_dir,
const bool& flatten_names,
const bool& include_time_stamp,
const ModuleManager& module_manager,
const ModuleId& top_module,
const DeviceRRGSB& device_rr_gsb) {
@ -101,7 +103,7 @@ void print_pnr_sdc_flatten_routing_disable_switch_block_outputs(const std::strin
check_file_stream(sdc_fname.c_str(), fp);
/* Generate the descriptions*/
print_sdc_file_header(fp, std::string("Disable Switch Block outputs for PnR"));
print_sdc_file_header(fp, std::string("Disable Switch Block outputs for PnR"), include_time_stamp);
std::string root_path = format_dir_path(module_manager.module_name(top_module));
@ -201,6 +203,7 @@ void print_pnr_sdc_flatten_routing_disable_switch_block_outputs(const std::strin
static
void print_pnr_sdc_compact_routing_disable_switch_block_outputs(const std::string& sdc_dir,
const bool& flatten_names,
const bool& include_time_stamp,
const ModuleManager& module_manager,
const ModuleId& top_module,
const DeviceRRGSB& device_rr_gsb) {
@ -218,7 +221,7 @@ void print_pnr_sdc_compact_routing_disable_switch_block_outputs(const std::strin
check_file_stream(sdc_fname.c_str(), fp);
/* Generate the descriptions*/
print_sdc_file_header(fp, std::string("Disable Switch Block outputs for PnR"));
print_sdc_file_header(fp, std::string("Disable Switch Block outputs for PnR"), include_time_stamp);
std::string root_path = format_dir_path(module_manager.module_name(top_module));
@ -335,17 +338,16 @@ void print_pnr_sdc(const PnrSdcOption& sdc_options,
/* Constrain global ports */
if (true == sdc_options.constrain_global_port()) {
print_pnr_sdc_global_ports(sdc_options.sdc_dir(),
sdc_options.time_unit(),
print_pnr_sdc_global_ports(sdc_options,
module_manager, top_module, global_ports,
sim_setting,
sdc_options.constrain_non_clock_global_port());
sim_setting);
}
/* Output Design Constraints to disable outputs of memory cells */
if (true == sdc_options.constrain_configurable_memory_outputs()) {
print_pnr_sdc_constrain_configurable_memory_outputs(sdc_options.sdc_dir(),
sdc_options.flatten_names(),
sdc_options.time_stamp(),
module_manager,
top_module);
}
@ -354,6 +356,7 @@ void print_pnr_sdc(const PnrSdcOption& sdc_options,
if (true == sdc_options.constrain_routing_multiplexer_outputs()) {
print_sdc_disable_routing_multiplexer_outputs(sdc_options.sdc_dir(),
sdc_options.flatten_names(),
sdc_options.time_stamp(),
mux_lib, circuit_lib,
module_manager,
top_module);
@ -364,12 +367,14 @@ void print_pnr_sdc(const PnrSdcOption& sdc_options,
if (true == compact_routing_hierarchy) {
print_pnr_sdc_compact_routing_disable_switch_block_outputs(sdc_options.sdc_dir(),
sdc_options.flatten_names(),
sdc_options.time_stamp(),
module_manager, top_module,
device_rr_gsb);
} else {
VTR_ASSERT_SAFE (false == compact_routing_hierarchy);
print_pnr_sdc_flatten_routing_disable_switch_block_outputs(sdc_options.sdc_dir(),
sdc_options.flatten_names(),
sdc_options.time_stamp(),
module_manager, top_module,
device_rr_gsb);
}
@ -378,28 +383,22 @@ void print_pnr_sdc(const PnrSdcOption& sdc_options,
/* Output routing constraints for Switch Blocks */
if (true == sdc_options.constrain_sb()) {
if (true == compact_routing_hierarchy) {
print_pnr_sdc_compact_routing_constrain_sb_timing(sdc_options.sdc_dir(),
sdc_options.time_unit(),
sdc_options.hierarchical(),
print_pnr_sdc_compact_routing_constrain_sb_timing(sdc_options,
module_manager,
top_module,
device_annotation,
device_ctx.grid,
device_ctx.rr_graph,
device_rr_gsb,
sdc_options.constrain_zero_delay_paths());
device_rr_gsb);
} else {
VTR_ASSERT_SAFE (false == compact_routing_hierarchy);
print_pnr_sdc_flatten_routing_constrain_sb_timing(sdc_options.sdc_dir(),
sdc_options.time_unit(),
sdc_options.hierarchical(),
print_pnr_sdc_flatten_routing_constrain_sb_timing(sdc_options,
module_manager,
top_module,
device_annotation,
device_ctx.grid,
device_ctx.rr_graph,
device_rr_gsb,
sdc_options.constrain_zero_delay_paths());
device_rr_gsb);
}
}
@ -416,28 +415,22 @@ void print_pnr_sdc(const PnrSdcOption& sdc_options,
/* Output routing constraints for Connection Blocks */
if (true == sdc_options.constrain_cb()) {
if (true == compact_routing_hierarchy) {
print_pnr_sdc_compact_routing_constrain_cb_timing(sdc_options.sdc_dir(),
sdc_options.time_unit(),
sdc_options.hierarchical(),
print_pnr_sdc_compact_routing_constrain_cb_timing(sdc_options,
module_manager,
top_module,
device_annotation,
device_ctx.grid,
device_ctx.rr_graph,
device_rr_gsb,
sdc_options.constrain_zero_delay_paths());
device_rr_gsb);
} else {
VTR_ASSERT_SAFE (false == compact_routing_hierarchy);
print_pnr_sdc_flatten_routing_constrain_cb_timing(sdc_options.sdc_dir(),
sdc_options.time_unit(),
sdc_options.hierarchical(),
print_pnr_sdc_flatten_routing_constrain_cb_timing(sdc_options,
module_manager,
top_module,
device_annotation,
device_ctx.grid,
device_ctx.rr_graph,
device_rr_gsb,
sdc_options.constrain_zero_delay_paths());
device_rr_gsb);
}
}
@ -460,14 +453,11 @@ void print_pnr_sdc(const PnrSdcOption& sdc_options,
/* Output Timing constraints for Programmable blocks */
if (true == sdc_options.constrain_grid()) {
print_pnr_sdc_constrain_grid_timing(sdc_options.sdc_dir(),
sdc_options.time_unit(),
sdc_options.hierarchical(),
print_pnr_sdc_constrain_grid_timing(sdc_options,
device_ctx,
device_annotation,
module_manager,
top_module,
sdc_options.constrain_zero_delay_paths());
top_module);
}
if ( (true == sdc_options.constrain_grid())

View File

@ -35,6 +35,7 @@ namespace openfpga {
*******************************************************************/
void print_sdc_disable_routing_multiplexer_outputs(const std::string& sdc_dir,
const bool& flatten_names,
const bool& include_time_stamp,
const MuxLibrary& mux_lib,
const CircuitLibrary& circuit_lib,
const ModuleManager& module_manager,
@ -53,7 +54,7 @@ void print_sdc_disable_routing_multiplexer_outputs(const std::string& sdc_dir,
check_file_stream(sdc_fname.c_str(), fp);
/* Generate the descriptions*/
print_sdc_file_header(fp, std::string("Disable routing multiplexer outputs for PnR"));
print_sdc_file_header(fp, std::string("Disable routing multiplexer outputs for PnR"), include_time_stamp);
/* Iterate over the MUX modules */
for (const MuxId& mux_id : mux_lib.muxes()) {

View File

@ -19,6 +19,7 @@ namespace openfpga {
void print_sdc_disable_routing_multiplexer_outputs(const std::string& sdc_dir,
const bool& flatten_names,
const bool& include_time_stamp,
const MuxLibrary& mux_lib,
const CircuitLibrary& circuit_lib,
const ModuleManager& module_manager,

View File

@ -24,20 +24,24 @@ namespace openfpga {
* Write a head (description) in SDC file
*******************************************************************/
void print_sdc_file_header(std::fstream& fp,
const std::string& usage) {
const std::string& usage,
const bool& include_time_stamp) {
valid_file_stream(fp);
auto end = std::chrono::system_clock::now();
std::time_t end_time = std::chrono::system_clock::to_time_t(end);
fp << "#############################################" << std::endl;
fp << "#\tSynopsys Design Constraints (SDC)" << std::endl;
fp << "#\tFor FPGA fabric " << std::endl;
fp << "#\tDescription: " << usage << std::endl;
fp << "#\tAuthor: Xifan TANG " << std::endl;
fp << "#\tOrganization: University of Utah " << std::endl;
fp << "#\tDate: " << std::ctime(&end_time);
if (include_time_stamp) {
auto end = std::chrono::system_clock::now();
std::time_t end_time = std::chrono::system_clock::to_time_t(end);
fp << "#\tDate: " << std::ctime(&end_time);
}
fp << "#############################################" << std::endl;
fp << std::endl;
}

View File

@ -17,7 +17,8 @@
namespace openfpga {
void print_sdc_file_header(std::fstream& fp,
const std::string& usage);
const std::string& usage,
const bool& include_time_stamp);
void print_sdc_timescale(std::fstream& fp,
const std::string& timescale);