add options to enable SDC constraints on zero-delay paths

This commit is contained in:
tangxifan 2020-03-25 15:55:30 -06:00
parent 3a74fb7a04
commit 329b0a9cf1
9 changed files with 114 additions and 41 deletions

View File

@ -34,6 +34,7 @@ void write_pnr_sdc(OpenfpgaContext& openfpga_ctx,
CommandOptionId opt_constrain_configurable_memory_outputs = cmd.option("constrain_configurable_memory_outputs");
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");
/* This is an intermediate data structure which is designed to modularize the FPGA-SDC
* Keep it independent from any other outside data structures
@ -53,6 +54,7 @@ void write_pnr_sdc(OpenfpgaContext& openfpga_ctx,
options.set_constrain_configurable_memory_outputs(cmd_context.option_enable(cmd, opt_constrain_configurable_memory_outputs));
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));
/* We first turn on default sdc option and then disable part of them by following users' options */
if (false == options.generate_sdc_pnr()) {

View File

@ -50,6 +50,9 @@ ShellCommandId add_openfpga_write_pnr_sdc_command(openfpga::Shell<OpenfpgaContex
/* Add an option '--constrain_switch_block_outputs' */
shell_cmd.add_option("constrain_switch_block_outputs", false, "Constrain all the outputs of switch blocks of FPGA fabric");
/* 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 '--verbose' */
shell_cmd.add_option("verbose", false, "Enable verbose output");

View File

@ -46,7 +46,8 @@ void print_pnr_sdc_constrain_pb_pin_interc_timing(std::fstream& fp,
const ModuleManager& module_manager,
const ModuleId& parent_module,
t_pb_graph_pin* des_pb_graph_pin,
t_mode* physical_mode) {
t_mode* physical_mode,
const bool& constrain_zero_delay_paths) {
/* Validate file stream */
valid_file_stream(fp);
@ -138,6 +139,12 @@ void print_pnr_sdc_constrain_pb_pin_interc_timing(std::fstream& fp,
BasicPort des_port = module_manager.module_port(des_module, des_module_port_id);
des_port.set_width(des_pb_graph_pin->pin_number, des_pb_graph_pin->pin_number);
/* If we have a zero-delay path to contrain, we will skip unless users want so */
if ( (false == constrain_zero_delay_paths)
&& (0. == des_pb_graph_pin->input_edges[iedge]->delay_max) ) {
continue;
}
/* Print a SDC timing constraint */
print_pnr_sdc_constrain_max_delay(fp,
src_instance_name,
@ -158,7 +165,8 @@ void print_pnr_sdc_constrain_pb_interc_timing(std::fstream& fp,
const ModuleId& parent_module,
t_pb_graph_node* des_pb_graph_node,
const e_circuit_pb_port_type& pb_port_type,
t_mode* physical_mode) {
t_mode* physical_mode,
const bool& constrain_zero_delay_paths) {
/* Validate file stream */
valid_file_stream(fp);
@ -171,7 +179,8 @@ void print_pnr_sdc_constrain_pb_interc_timing(std::fstream& fp,
print_pnr_sdc_constrain_pb_pin_interc_timing(fp,
module_manager, parent_module,
&(des_pb_graph_node->input_pins[iport][ipin]),
physical_mode);
physical_mode,
constrain_zero_delay_paths);
}
}
break;
@ -182,7 +191,8 @@ void print_pnr_sdc_constrain_pb_interc_timing(std::fstream& fp,
print_pnr_sdc_constrain_pb_pin_interc_timing(fp,
module_manager, parent_module,
&(des_pb_graph_node->output_pins[iport][ipin]),
physical_mode);
physical_mode,
constrain_zero_delay_paths);
}
}
break;
@ -209,7 +219,8 @@ static
void print_pnr_sdc_constrain_pb_graph_node_timing(const std::string& sdc_dir,
const ModuleManager& module_manager,
t_pb_graph_node* parent_pb_graph_node,
t_mode* physical_mode) {
t_mode* physical_mode,
const bool& 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;
@ -242,7 +253,8 @@ void print_pnr_sdc_constrain_pb_graph_node_timing(const std::string& sdc_dir,
module_manager, pb_module,
parent_pb_graph_node,
CIRCUIT_PB_PORT_OUTPUT,
physical_mode);
physical_mode,
constrain_zero_delay_paths);
/* We check input_pins of child_pb_graph_node and its the input_edges
* Built the interconnections between inputs of cur_pb_graph_node and inputs of child_pb_graph_node
@ -259,7 +271,8 @@ void print_pnr_sdc_constrain_pb_graph_node_timing(const std::string& sdc_dir,
module_manager, pb_module,
child_pb_graph_node,
CIRCUIT_PB_PORT_INPUT,
physical_mode);
physical_mode,
constrain_zero_delay_paths);
/* Do NOT constrain clock here, it should be handled by Clock Tree Synthesis */
}
}
@ -277,7 +290,8 @@ static
void rec_print_pnr_sdc_constrain_pb_graph_timing(const std::string& sdc_dir,
const ModuleManager& module_manager,
const VprDeviceAnnotation& device_annotation,
t_pb_graph_node* parent_pb_graph_node) {
t_pb_graph_node* parent_pb_graph_node,
const bool& constrain_zero_delay_paths) {
/* Validate pb_graph node */
if (nullptr == parent_pb_graph_node) {
VTR_LOGF_ERROR(__FILE__, __LINE__,
@ -302,7 +316,8 @@ void rec_print_pnr_sdc_constrain_pb_graph_timing(const std::string& sdc_dir,
print_pnr_sdc_constrain_pb_graph_node_timing(sdc_dir,
module_manager,
parent_pb_graph_node,
physical_mode);
physical_mode,
constrain_zero_delay_paths);
/* 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
@ -310,7 +325,8 @@ void rec_print_pnr_sdc_constrain_pb_graph_timing(const std::string& sdc_dir,
for (int ipb = 0; ipb < physical_mode->num_pb_type_children; ++ipb) {
rec_print_pnr_sdc_constrain_pb_graph_timing(sdc_dir, module_manager,
device_annotation,
&(parent_pb_graph_node->child_pb_graph_nodes[physical_mode->index][ipb][0]));
&(parent_pb_graph_node->child_pb_graph_nodes[physical_mode->index][ipb][0]),
constrain_zero_delay_paths);
}
}
@ -320,7 +336,8 @@ void rec_print_pnr_sdc_constrain_pb_graph_timing(const std::string& sdc_dir,
void print_pnr_sdc_constrain_grid_timing(const std::string& sdc_dir,
const DeviceContext& device_ctx,
const VprDeviceAnnotation& device_annotation,
const ModuleManager& module_manager) {
const ModuleManager& module_manager,
const bool& constrain_zero_delay_paths) {
/* Start time count */
vtr::ScopedStartFinishTimer timer("Write SDC for constraining grid timing for P&R flow");
@ -338,7 +355,8 @@ void print_pnr_sdc_constrain_grid_timing(const std::string& sdc_dir,
/* Special for I/O block, generate one module for each border side */
rec_print_pnr_sdc_constrain_pb_graph_timing(sdc_dir, module_manager,
device_annotation,
pb_graph_head);
pb_graph_head,
constrain_zero_delay_paths);
}
}
}

View File

@ -20,7 +20,8 @@ namespace openfpga {
void print_pnr_sdc_constrain_grid_timing(const std::string& sdc_dir,
const DeviceContext& device_ctx,
const VprDeviceAnnotation& device_annotation,
const ModuleManager& module_manager);
const ModuleManager& module_manager,
const bool& constrain_zero_delay_paths);
} /* end namespace openfpga */

View File

@ -19,6 +19,7 @@ PnrSdcOption::PnrSdcOption(const std::string& sdc_dir) {
constrain_configurable_memory_outputs_ = false;
constrain_routing_multiplexer_outputs_ = false;
constrain_switch_block_outputs_ = false;
constrain_zero_delay_paths_ = false;
}
/********************************************************************
@ -70,6 +71,10 @@ bool PnrSdcOption::constrain_switch_block_outputs() const {
return constrain_switch_block_outputs_;
}
bool PnrSdcOption::constrain_zero_delay_paths() const {
return constrain_zero_delay_paths_;
}
/********************************************************************
* Public mutators
********************************************************************/
@ -119,4 +124,8 @@ void PnrSdcOption::set_constrain_switch_block_outputs(const bool& constrain_sb_o
constrain_switch_block_outputs_ = constrain_sb_outputs;
}
void PnrSdcOption::set_constrain_zero_delay_paths(const bool& constrain_zero_delay_paths) {
constrain_zero_delay_paths_ = constrain_zero_delay_paths;
}
} /* end namespace openfpga */

View File

@ -25,6 +25,7 @@ class PnrSdcOption {
bool constrain_configurable_memory_outputs() const;
bool constrain_routing_multiplexer_outputs() const;
bool constrain_switch_block_outputs() const;
bool constrain_zero_delay_paths() const;
public: /* Public mutators */
void set_sdc_dir(const std::string& sdc_dir);
void set_generate_sdc_pnr(const bool& generate_sdc_pnr);
@ -36,6 +37,7 @@ class PnrSdcOption {
void set_constrain_configurable_memory_outputs(const bool& constrain_config_mem_outputs);
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);
private: /* Internal data */
std::string sdc_dir_;
bool constrain_global_port_;
@ -46,6 +48,7 @@ class PnrSdcOption {
bool constrain_configurable_memory_outputs_;
bool constrain_routing_multiplexer_outputs_;
bool constrain_switch_block_outputs_;
bool constrain_zero_delay_paths_;
};
} /* end namespace openfpga */

View File

@ -54,7 +54,8 @@ void print_pnr_sdc_constrain_sb_mux_timing(std::fstream& fp,
const RRGraph& rr_graph,
const RRGSB& rr_gsb,
const e_side& output_node_side,
const RRNodeId& output_rr_node) {
const RRNodeId& output_rr_node,
const bool& constrain_zero_delay_paths) {
/* Validate file stream */
valid_file_stream(fp);
@ -89,6 +90,11 @@ void print_pnr_sdc_constrain_sb_mux_timing(std::fstream& fp,
/* Find the starting points */
for (const ModulePortId& module_input_port : module_input_ports) {
/* If we have a zero-delay path to contrain, we will skip unless users want so */
if ( (false == constrain_zero_delay_paths)
&& (0. == switch_delays[module_input_port]) ) {
continue;
}
/* Constrain a path */
print_pnr_sdc_constrain_port2port_timing(fp,
module_manager,
@ -110,7 +116,8 @@ static
void print_pnr_sdc_constrain_sb_timing(const std::string& sdc_dir,
const ModuleManager& module_manager,
const RRGraph& rr_graph,
const RRGSB& rr_gsb) {
const RRGSB& rr_gsb,
const bool& 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());
@ -148,7 +155,8 @@ void print_pnr_sdc_constrain_sb_timing(const std::string& sdc_dir,
rr_graph,
rr_gsb,
side_manager.get_side(),
chan_rr_node);
chan_rr_node,
constrain_zero_delay_paths);
}
}
@ -163,7 +171,8 @@ void print_pnr_sdc_constrain_sb_timing(const std::string& sdc_dir,
void print_pnr_sdc_flatten_routing_constrain_sb_timing(const std::string& sdc_dir,
const ModuleManager& module_manager,
const RRGraph& rr_graph,
const DeviceRRGSB& device_rr_gsb) {
const DeviceRRGSB& device_rr_gsb,
const bool& constrain_zero_delay_paths) {
/* Start time count */
vtr::ScopedStartFinishTimer timer("Write SDC for constrain Switch Block timing for P&R flow");
@ -180,7 +189,8 @@ void print_pnr_sdc_flatten_routing_constrain_sb_timing(const std::string& sdc_di
print_pnr_sdc_constrain_sb_timing(sdc_dir,
module_manager,
rr_graph,
rr_gsb);
rr_gsb,
constrain_zero_delay_paths);
}
}
}
@ -192,7 +202,8 @@ void print_pnr_sdc_flatten_routing_constrain_sb_timing(const std::string& sdc_di
void print_pnr_sdc_compact_routing_constrain_sb_timing(const std::string& sdc_dir,
const ModuleManager& module_manager,
const RRGraph& rr_graph,
const DeviceRRGSB& device_rr_gsb) {
const DeviceRRGSB& device_rr_gsb,
const bool& constrain_zero_delay_paths) {
/* Start time count */
vtr::ScopedStartFinishTimer timer("Write SDC for constrain Switch Block timing for P&R flow");
@ -205,7 +216,8 @@ void print_pnr_sdc_compact_routing_constrain_sb_timing(const std::string& sdc_di
print_pnr_sdc_constrain_sb_timing(sdc_dir,
module_manager,
rr_graph,
rr_gsb);
rr_gsb,
constrain_zero_delay_paths);
}
}
@ -220,7 +232,8 @@ void print_pnr_sdc_constrain_cb_mux_timing(std::fstream& fp,
const RRGraph& rr_graph,
const RRGSB& rr_gsb,
const t_rr_type& cb_type,
const RRNodeId& output_rr_node) {
const RRNodeId& output_rr_node,
const bool& constrain_zero_delay_paths) {
/* Validate file stream */
valid_file_stream(fp);
@ -275,6 +288,12 @@ void print_pnr_sdc_constrain_cb_mux_timing(std::fstream& fp,
/* Find the starting points */
for (const ModulePortId& module_input_port : module_input_ports) {
/* If we have a zero-delay path to contrain, we will skip unless users want so */
if ( (false == constrain_zero_delay_paths)
&& (0. == switch_delays[module_input_port]) ) {
continue;
}
/* Constrain a path */
print_pnr_sdc_constrain_port2port_timing(fp,
module_manager,
@ -284,7 +303,6 @@ void print_pnr_sdc_constrain_cb_mux_timing(std::fstream& fp,
}
}
/********************************************************************
* Print SDC timing constraints for a Connection block
* This function is designed for compact routing hierarchy
@ -294,7 +312,8 @@ void print_pnr_sdc_constrain_cb_timing(const std::string& sdc_dir,
const ModuleManager& module_manager,
const RRGraph& rr_graph,
const RRGSB& rr_gsb,
const t_rr_type& cb_type) {
const t_rr_type& cb_type,
const bool& 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));
@ -325,7 +344,8 @@ void print_pnr_sdc_constrain_cb_timing(const std::string& sdc_dir,
print_pnr_sdc_constrain_cb_mux_timing(fp,
module_manager, cb_module,
rr_graph, rr_gsb, cb_type,
ipin_rr_node);
ipin_rr_node,
constrain_zero_delay_paths);
}
}
@ -342,7 +362,8 @@ void print_pnr_sdc_flatten_routing_constrain_cb_timing(const std::string& sdc_di
const ModuleManager& module_manager,
const RRGraph& rr_graph,
const DeviceRRGSB& device_rr_gsb,
const t_rr_type& cb_type) {
const t_rr_type& cb_type,
const bool& constrain_zero_delay_paths) {
/* Build unique X-direction connection block modules */
vtr::Point<size_t> cb_range = device_rr_gsb.get_gsb_range();
@ -360,7 +381,8 @@ void print_pnr_sdc_flatten_routing_constrain_cb_timing(const std::string& sdc_di
module_manager,
rr_graph,
rr_gsb,
cb_type);
cb_type,
constrain_zero_delay_paths);
}
}
@ -373,7 +395,8 @@ void print_pnr_sdc_flatten_routing_constrain_cb_timing(const std::string& sdc_di
void print_pnr_sdc_flatten_routing_constrain_cb_timing(const std::string& sdc_dir,
const ModuleManager& module_manager,
const RRGraph& rr_graph,
const DeviceRRGSB& device_rr_gsb) {
const DeviceRRGSB& device_rr_gsb,
const bool& constrain_zero_delay_paths) {
/* Start time count */
vtr::ScopedStartFinishTimer timer("Write SDC for constrain Connection Block timing for P&R flow");
@ -381,12 +404,14 @@ void print_pnr_sdc_flatten_routing_constrain_cb_timing(const std::string& sdc_di
print_pnr_sdc_flatten_routing_constrain_cb_timing(sdc_dir, module_manager,
rr_graph,
device_rr_gsb,
CHANX);
CHANX,
constrain_zero_delay_paths);
print_pnr_sdc_flatten_routing_constrain_cb_timing(sdc_dir, module_manager,
rr_graph,
device_rr_gsb,
CHANY);
CHANY,
constrain_zero_delay_paths);
}
/********************************************************************
@ -396,7 +421,8 @@ void print_pnr_sdc_flatten_routing_constrain_cb_timing(const std::string& sdc_di
void print_pnr_sdc_compact_routing_constrain_cb_timing(const std::string& sdc_dir,
const ModuleManager& module_manager,
const RRGraph& rr_graph,
const DeviceRRGSB& device_rr_gsb) {
const DeviceRRGSB& device_rr_gsb,
const bool& constrain_zero_delay_paths) {
/* Start time count */
vtr::ScopedStartFinishTimer timer("Write SDC for constrain Connection Block timing for P&R flow");
@ -408,7 +434,8 @@ void print_pnr_sdc_compact_routing_constrain_cb_timing(const std::string& sdc_di
module_manager,
rr_graph,
unique_mirror,
CHANX);
CHANX,
constrain_zero_delay_paths);
}
/* Print SDC for unique Y-direction connection block modules */
@ -418,7 +445,8 @@ void print_pnr_sdc_compact_routing_constrain_cb_timing(const std::string& sdc_di
module_manager,
rr_graph,
unique_mirror,
CHANY);
CHANY,
constrain_zero_delay_paths);
}
}

View File

@ -20,22 +20,26 @@ namespace openfpga {
void print_pnr_sdc_flatten_routing_constrain_sb_timing(const std::string& sdc_dir,
const ModuleManager& module_manager,
const RRGraph& rr_graph,
const DeviceRRGSB& device_rr_gsb);
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 ModuleManager& module_manager,
const RRGraph& rr_graph,
const DeviceRRGSB& device_rr_gsb);
const DeviceRRGSB& device_rr_gsb,
const bool& constrain_zero_delay_paths);
void print_pnr_sdc_flatten_routing_constrain_cb_timing(const std::string& sdc_dir,
const ModuleManager& module_manager,
const RRGraph& rr_graph,
const DeviceRRGSB& device_rr_gsb);
const DeviceRRGSB& device_rr_gsb,
const bool& constrain_zero_delay_paths);
void print_pnr_sdc_compact_routing_constrain_cb_timing(const std::string& sdc_dir,
const ModuleManager& module_manager,
const RRGraph& rr_graph,
const DeviceRRGSB& device_rr_gsb);
const DeviceRRGSB& device_rr_gsb,
const bool& constrain_zero_delay_paths);
} /* end namespace openfpga */

View File

@ -296,13 +296,15 @@ void print_pnr_sdc(const PnrSdcOption& sdc_options,
print_pnr_sdc_compact_routing_constrain_sb_timing(sdc_options.sdc_dir(),
module_manager,
device_ctx.rr_graph,
device_rr_gsb);
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(),
module_manager,
device_ctx.rr_graph,
device_rr_gsb);
device_rr_gsb,
sdc_options.constrain_zero_delay_paths());
}
}
@ -312,13 +314,15 @@ void print_pnr_sdc(const PnrSdcOption& sdc_options,
print_pnr_sdc_compact_routing_constrain_cb_timing(sdc_options.sdc_dir(),
module_manager,
device_ctx.rr_graph,
device_rr_gsb);
device_rr_gsb,
sdc_options.constrain_zero_delay_paths());
} else {
VTR_ASSERT_SAFE (false == compact_routing_hierarchy);
print_pnr_sdc_flatten_routing_constrain_cb_timing(sdc_options.sdc_dir(),
module_manager,
device_ctx.rr_graph,
device_rr_gsb);
device_rr_gsb,
sdc_options.constrain_zero_delay_paths());
}
}
@ -327,7 +331,8 @@ void print_pnr_sdc(const PnrSdcOption& sdc_options,
print_pnr_sdc_constrain_grid_timing(sdc_options.sdc_dir(),
device_ctx,
device_annotation,
module_manager);
module_manager,
sdc_options.constrain_zero_delay_paths());
}
}