now add SDC generator supports both hierarchical and flatten in writing timing constraints
This commit is contained in:
parent
7503c58fb2
commit
7e82c23f52
|
@ -30,6 +30,7 @@ int write_pnr_sdc(OpenfpgaContext& openfpga_ctx,
|
|||
|
||||
CommandOptionId opt_output_dir = cmd.option("file");
|
||||
CommandOptionId opt_flatten_names = cmd.option("flatten_names");
|
||||
CommandOptionId opt_hierarchical = cmd.option("hierarchical");
|
||||
CommandOptionId opt_constrain_global_port = cmd.option("constrain_global_port");
|
||||
CommandOptionId opt_constrain_non_clock_global_port = cmd.option("constrain_non_clock_global_port");
|
||||
CommandOptionId opt_constrain_grid = cmd.option("constrain_grid");
|
||||
|
@ -51,6 +52,7 @@ int write_pnr_sdc(OpenfpgaContext& openfpga_ctx,
|
|||
PnrSdcOption options(sdc_dir_path);
|
||||
|
||||
options.set_flatten_names(cmd_context.option_enable(cmd, opt_flatten_names));
|
||||
options.set_hierarchical(cmd_context.option_enable(cmd, opt_hierarchical));
|
||||
options.set_constrain_global_port(cmd_context.option_enable(cmd, opt_constrain_global_port));
|
||||
options.set_constrain_non_clock_global_port(cmd_context.option_enable(cmd, opt_constrain_non_clock_global_port));
|
||||
options.set_constrain_grid(cmd_context.option_enable(cmd, opt_constrain_grid));
|
||||
|
|
|
@ -29,6 +29,9 @@ ShellCommandId add_openfpga_write_pnr_sdc_command(openfpga::Shell<OpenfpgaContex
|
|||
/* Add an option '--flatten_name' */
|
||||
shell_cmd.add_option("flatten_names", false, "Use flatten names (no wildcards) in SDC files");
|
||||
|
||||
/* Add an option '--hierarchical' */
|
||||
shell_cmd.add_option("hierarchical", false, "Output SDC files hierachically (without full path in hierarchy)");
|
||||
|
||||
/* Add an option '--constrain_global_port' */
|
||||
shell_cmd.add_option("constrain_global_port", false, "Constrain all the global ports of FPGA fabric");
|
||||
|
||||
|
@ -91,7 +94,7 @@ ShellCommandId add_openfpga_write_analysis_sdc_command(openfpga::Shell<OpenfpgaC
|
|||
|
||||
/* Add an option '--flatten_name' */
|
||||
shell_cmd.add_option("flatten_names", false, "Use flatten names (no wildcards) in SDC 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);
|
||||
|
|
|
@ -11,6 +11,7 @@ namespace openfpga {
|
|||
********************************************************************/
|
||||
PnrSdcOption::PnrSdcOption(const std::string& sdc_dir) {
|
||||
sdc_dir_ = sdc_dir;
|
||||
hierarchical_ = false;
|
||||
flatten_names_ = false;
|
||||
constrain_global_port_ = false;
|
||||
constrain_non_clock_global_port_ = false;
|
||||
|
@ -34,6 +35,10 @@ bool PnrSdcOption::flatten_names() const {
|
|||
return flatten_names_;
|
||||
}
|
||||
|
||||
bool PnrSdcOption::hierarchical() const {
|
||||
return hierarchical_;
|
||||
}
|
||||
|
||||
bool PnrSdcOption::generate_sdc_pnr() const {
|
||||
return constrain_global_port_
|
||||
|| constrain_grid_
|
||||
|
@ -91,6 +96,10 @@ void PnrSdcOption::set_flatten_names(const bool& flatten_names) {
|
|||
flatten_names_ = flatten_names;
|
||||
}
|
||||
|
||||
void PnrSdcOption::set_hierarchical(const bool& hierarchical) {
|
||||
hierarchical_ = hierarchical;
|
||||
}
|
||||
|
||||
void PnrSdcOption::set_generate_sdc_pnr(const bool& generate_sdc_pnr) {
|
||||
constrain_global_port_ = generate_sdc_pnr;
|
||||
constrain_grid_ = generate_sdc_pnr;
|
||||
|
|
|
@ -17,6 +17,7 @@ class PnrSdcOption {
|
|||
public: /* Public accessors */
|
||||
std::string sdc_dir() const;
|
||||
bool flatten_names() const;
|
||||
bool hierarchical() const;
|
||||
bool generate_sdc_pnr() const;
|
||||
bool constrain_global_port() const;
|
||||
bool constrain_non_clock_global_port() const;
|
||||
|
@ -30,6 +31,7 @@ class PnrSdcOption {
|
|||
public: /* Public mutators */
|
||||
void set_sdc_dir(const std::string& sdc_dir);
|
||||
void set_flatten_names(const bool& flatten_names);
|
||||
void set_hierarchical(const bool& hierarchical);
|
||||
void set_generate_sdc_pnr(const bool& generate_sdc_pnr);
|
||||
void set_constrain_global_port(const bool& constrain_global_port);
|
||||
void set_constrain_non_clock_global_port(const bool& constrain_non_clock_global_port);
|
||||
|
@ -43,6 +45,7 @@ class PnrSdcOption {
|
|||
private: /* Internal data */
|
||||
std::string sdc_dir_;
|
||||
bool flatten_names_;
|
||||
bool hierarchical_;
|
||||
bool constrain_global_port_;
|
||||
bool constrain_non_clock_global_port_;
|
||||
bool constrain_grid_;
|
||||
|
|
|
@ -49,6 +49,8 @@ float find_pnr_sdc_switch_tmax(const t_rr_switch_inf& switch_inf) {
|
|||
*******************************************************************/
|
||||
static
|
||||
void print_pnr_sdc_constrain_sb_mux_timing(std::fstream& fp,
|
||||
const bool& hierarchical,
|
||||
const std::string& module_path,
|
||||
const ModuleManager& module_manager,
|
||||
const ModuleId& sb_module,
|
||||
const RRGraph& rr_graph,
|
||||
|
@ -96,11 +98,22 @@ void print_pnr_sdc_constrain_sb_mux_timing(std::fstream& fp,
|
|||
continue;
|
||||
}
|
||||
/* Constrain a path */
|
||||
print_pnr_sdc_constrain_port2port_timing(fp,
|
||||
module_manager,
|
||||
sb_module, module_input_port,
|
||||
sb_module, module_output_port,
|
||||
switch_delays[module_input_port]);
|
||||
if (false == hierarchical) {
|
||||
print_pnr_sdc_regexp_constrain_max_delay(fp,
|
||||
module_path,
|
||||
generate_sdc_port(module_manager.module_port(sb_module, module_input_port)),
|
||||
module_path,
|
||||
generate_sdc_port(module_manager.module_port(sb_module, module_output_port)),
|
||||
switch_delays[module_input_port]);
|
||||
|
||||
} else {
|
||||
VTR_ASSERT_SAFE(true == hierarchical);
|
||||
print_pnr_sdc_constrain_port2port_timing(fp,
|
||||
module_manager,
|
||||
sb_module, module_input_port,
|
||||
sb_module, module_output_port,
|
||||
switch_delays[module_input_port]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -114,6 +127,8 @@ void print_pnr_sdc_constrain_sb_mux_timing(std::fstream& fp,
|
|||
*******************************************************************/
|
||||
static
|
||||
void print_pnr_sdc_constrain_sb_timing(const std::string& sdc_dir,
|
||||
const bool& hierarchical,
|
||||
const std::string& module_path,
|
||||
const ModuleManager& module_manager,
|
||||
const RRGraph& rr_graph,
|
||||
const RRGSB& rr_gsb,
|
||||
|
@ -151,6 +166,8 @@ void print_pnr_sdc_constrain_sb_timing(const std::string& sdc_dir,
|
|||
}
|
||||
/* This is a MUX, constrain all the paths from an input to an output */
|
||||
print_pnr_sdc_constrain_sb_mux_timing(fp,
|
||||
hierarchical,
|
||||
module_path,
|
||||
module_manager, sb_module,
|
||||
rr_graph,
|
||||
rr_gsb,
|
||||
|
@ -169,7 +186,9 @@ void print_pnr_sdc_constrain_sb_timing(const std::string& sdc_dir,
|
|||
* This function is designed for flatten routing hierarchy
|
||||
*******************************************************************/
|
||||
void print_pnr_sdc_flatten_routing_constrain_sb_timing(const std::string& sdc_dir,
|
||||
const bool& hierarchical,
|
||||
const ModuleManager& module_manager,
|
||||
const ModuleId& top_module,
|
||||
const RRGraph& rr_graph,
|
||||
const DeviceRRGSB& device_rr_gsb,
|
||||
const bool& constrain_zero_delay_paths) {
|
||||
|
@ -177,6 +196,8 @@ void print_pnr_sdc_flatten_routing_constrain_sb_timing(const std::string& sdc_di
|
|||
/* Start time count */
|
||||
vtr::ScopedStartFinishTimer timer("Write SDC for constrain Switch Block timing for P&R flow");
|
||||
|
||||
std::string root_path = module_manager.module_name(top_module);
|
||||
|
||||
/* Get the range of SB array */
|
||||
vtr::Point<size_t> sb_range = device_rr_gsb.get_gsb_range();
|
||||
/* Go for each SB */
|
||||
|
@ -186,7 +207,24 @@ void print_pnr_sdc_flatten_routing_constrain_sb_timing(const std::string& sdc_di
|
|||
if (false == rr_gsb.is_sb_exist()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
vtr::Point<size_t> gsb_coordinate(rr_gsb.get_sb_x(), rr_gsb.get_sb_y());
|
||||
std::string sb_instance_name = generate_switch_block_module_name(gsb_coordinate);
|
||||
|
||||
ModuleId sb_module = module_manager.find_module(sb_instance_name);
|
||||
VTR_ASSERT(true == module_manager.valid_module_id(sb_module));
|
||||
|
||||
std::string module_path = root_path
|
||||
+ std::string("\\/")
|
||||
+ std::string("(");
|
||||
|
||||
/* Find all the instances in the top-level module */
|
||||
module_path += sb_instance_name;
|
||||
module_path += std::string(")") + std::string("\\");
|
||||
|
||||
print_pnr_sdc_constrain_sb_timing(sdc_dir,
|
||||
hierarchical,
|
||||
module_path,
|
||||
module_manager,
|
||||
rr_graph,
|
||||
rr_gsb,
|
||||
|
@ -200,7 +238,9 @@ void print_pnr_sdc_flatten_routing_constrain_sb_timing(const std::string& sdc_di
|
|||
* This function is designed for compact routing hierarchy
|
||||
*******************************************************************/
|
||||
void print_pnr_sdc_compact_routing_constrain_sb_timing(const std::string& sdc_dir,
|
||||
const bool& hierarchical,
|
||||
const ModuleManager& module_manager,
|
||||
const ModuleId& top_module,
|
||||
const RRGraph& rr_graph,
|
||||
const DeviceRRGSB& device_rr_gsb,
|
||||
const bool& constrain_zero_delay_paths) {
|
||||
|
@ -208,12 +248,43 @@ void print_pnr_sdc_compact_routing_constrain_sb_timing(const std::string& sdc_di
|
|||
/* Start time count */
|
||||
vtr::ScopedStartFinishTimer timer("Write SDC for constrain Switch Block timing for P&R flow");
|
||||
|
||||
std::string root_path = module_manager.module_name(top_module);
|
||||
|
||||
for (size_t isb = 0; isb < device_rr_gsb.get_num_sb_unique_module(); ++isb) {
|
||||
const RRGSB& rr_gsb = device_rr_gsb.get_sb_unique_module(isb);
|
||||
if (false == rr_gsb.is_sb_exist()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Find all the sb instance under this module
|
||||
* Create a regular expression to include these instance names
|
||||
*/
|
||||
vtr::Point<size_t> gsb_coordinate(rr_gsb.get_sb_x(), rr_gsb.get_sb_y());
|
||||
std::string sb_module_name = generate_switch_block_module_name(gsb_coordinate);
|
||||
|
||||
ModuleId sb_module = module_manager.find_module(sb_module_name);
|
||||
VTR_ASSERT(true == module_manager.valid_module_id(sb_module));
|
||||
|
||||
std::string module_path = root_path
|
||||
+ std::string("\\/")
|
||||
+ std::string("(");
|
||||
|
||||
/* Find all the instances in the top-level module */
|
||||
bool first_element = true;
|
||||
for (const size_t& instance_id : module_manager.child_module_instances(top_module, sb_module)) {
|
||||
std::string sb_instance_name = module_manager.instance_name(top_module, sb_module, instance_id);
|
||||
if (false == first_element) {
|
||||
module_path += std::string("|");
|
||||
}
|
||||
module_path += sb_instance_name;
|
||||
first_element = false;
|
||||
}
|
||||
|
||||
module_path += std::string(")") + std::string("\\");
|
||||
|
||||
print_pnr_sdc_constrain_sb_timing(sdc_dir,
|
||||
hierarchical,
|
||||
module_path,
|
||||
module_manager,
|
||||
rr_graph,
|
||||
rr_gsb,
|
||||
|
|
|
@ -18,13 +18,17 @@
|
|||
namespace openfpga {
|
||||
|
||||
void print_pnr_sdc_flatten_routing_constrain_sb_timing(const std::string& sdc_dir,
|
||||
const bool& hierarchical,
|
||||
const ModuleManager& module_manager,
|
||||
const ModuleId& top_module,
|
||||
const RRGraph& rr_graph,
|
||||
const DeviceRRGSB& device_rr_gsb,
|
||||
const bool& constrain_zero_delay_paths);
|
||||
|
||||
void print_pnr_sdc_compact_routing_constrain_sb_timing(const std::string& sdc_dir,
|
||||
const bool& hierarchical,
|
||||
const ModuleManager& module_manager,
|
||||
const ModuleId& top_module,
|
||||
const RRGraph& rr_graph,
|
||||
const DeviceRRGSB& device_rr_gsb,
|
||||
const bool& constrain_zero_delay_paths);
|
||||
|
|
|
@ -428,14 +428,18 @@ void print_pnr_sdc(const PnrSdcOption& sdc_options,
|
|||
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.hierarchical(),
|
||||
module_manager,
|
||||
top_module,
|
||||
device_ctx.rr_graph,
|
||||
device_rr_gsb,
|
||||
sdc_options.constrain_zero_delay_paths());
|
||||
} else {
|
||||
VTR_ASSERT_SAFE (false == compact_routing_hierarchy);
|
||||
print_pnr_sdc_flatten_routing_constrain_sb_timing(sdc_options.sdc_dir(),
|
||||
sdc_options.hierarchical(),
|
||||
module_manager,
|
||||
top_module,
|
||||
device_ctx.rr_graph,
|
||||
device_rr_gsb,
|
||||
sdc_options.constrain_zero_delay_paths());
|
||||
|
|
|
@ -101,6 +101,46 @@ void print_pnr_sdc_constrain_max_delay(std::fstream& fp,
|
|||
fp << std::endl;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Constrain a path between two ports of a module with a given maximum timing value
|
||||
* This function use regular expression and get_pins which are
|
||||
* from open-source SDC 2.1 format
|
||||
*******************************************************************/
|
||||
void print_pnr_sdc_regexp_constrain_max_delay(std::fstream& fp,
|
||||
const std::string& src_instance_name,
|
||||
const std::string& src_port_name,
|
||||
const std::string& des_instance_name,
|
||||
const std::string& des_port_name,
|
||||
const float& delay) {
|
||||
/* Validate file stream */
|
||||
valid_file_stream(fp);
|
||||
|
||||
fp << "set_max_delay";
|
||||
|
||||
fp << " -from ";
|
||||
fp << "[get_pins -regexp \"";
|
||||
if (!src_instance_name.empty()) {
|
||||
fp << src_instance_name << "/";
|
||||
}
|
||||
fp << src_port_name;
|
||||
|
||||
fp << "\"]";
|
||||
|
||||
fp << " -to ";
|
||||
fp << "[get_pins -regexp \"";
|
||||
|
||||
if (!des_instance_name.empty()) {
|
||||
fp << des_instance_name << "/";
|
||||
}
|
||||
fp << des_port_name;
|
||||
|
||||
fp << "\"]";
|
||||
|
||||
fp << " " << std::setprecision(10) << delay;
|
||||
|
||||
fp << std::endl;
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Constrain a path between two ports of a module with a given minimum timing value
|
||||
*******************************************************************/
|
||||
|
|
|
@ -28,6 +28,13 @@ void print_pnr_sdc_constrain_max_delay(std::fstream& fp,
|
|||
const std::string& des_port_name,
|
||||
const float& delay);
|
||||
|
||||
void print_pnr_sdc_regexp_constrain_max_delay(std::fstream& fp,
|
||||
const std::string& src_instance_name,
|
||||
const std::string& src_port_name,
|
||||
const std::string& des_instance_name,
|
||||
const std::string& des_port_name,
|
||||
const float& delay);
|
||||
|
||||
void print_pnr_sdc_constrain_min_delay(std::fstream& fp,
|
||||
const std::string& src_instance_name,
|
||||
const std::string& src_port_name,
|
||||
|
|
Loading…
Reference in New Issue