From 329b0a9cf1d3b5ac9a8686b8017211c981222751 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Wed, 25 Mar 2020 15:55:30 -0600 Subject: [PATCH] add options to enable SDC constraints on zero-delay paths --- openfpga/src/base/openfpga_sdc.cpp | 2 + openfpga/src/base/openfpga_sdc_command.cpp | 3 + openfpga/src/fpga_sdc/pnr_sdc_grid_writer.cpp | 42 ++++++++---- openfpga/src/fpga_sdc/pnr_sdc_grid_writer.h | 3 +- openfpga/src/fpga_sdc/pnr_sdc_option.cpp | 9 +++ openfpga/src/fpga_sdc/pnr_sdc_option.h | 3 + .../src/fpga_sdc/pnr_sdc_routing_writer.cpp | 66 +++++++++++++------ .../src/fpga_sdc/pnr_sdc_routing_writer.h | 12 ++-- openfpga/src/fpga_sdc/pnr_sdc_writer.cpp | 15 +++-- 9 files changed, 114 insertions(+), 41 deletions(-) diff --git a/openfpga/src/base/openfpga_sdc.cpp b/openfpga/src/base/openfpga_sdc.cpp index a83d0b797..cb2e1bf72 100644 --- a/openfpga/src/base/openfpga_sdc.cpp +++ b/openfpga/src/base/openfpga_sdc.cpp @@ -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()) { diff --git a/openfpga/src/base/openfpga_sdc_command.cpp b/openfpga/src/base/openfpga_sdc_command.cpp index 7d194ba5b..551b37d2b 100644 --- a/openfpga/src/base/openfpga_sdc_command.cpp +++ b/openfpga/src/base/openfpga_sdc_command.cpp @@ -50,6 +50,9 @@ ShellCommandId add_openfpga_write_pnr_sdc_command(openfpga::Shellpin_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); } } } diff --git a/openfpga/src/fpga_sdc/pnr_sdc_grid_writer.h b/openfpga/src/fpga_sdc/pnr_sdc_grid_writer.h index 91c1b7030..400ca1616 100644 --- a/openfpga/src/fpga_sdc/pnr_sdc_grid_writer.h +++ b/openfpga/src/fpga_sdc/pnr_sdc_grid_writer.h @@ -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 */ diff --git a/openfpga/src/fpga_sdc/pnr_sdc_option.cpp b/openfpga/src/fpga_sdc/pnr_sdc_option.cpp index a5143776e..153ac4fac 100644 --- a/openfpga/src/fpga_sdc/pnr_sdc_option.cpp +++ b/openfpga/src/fpga_sdc/pnr_sdc_option.cpp @@ -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 */ diff --git a/openfpga/src/fpga_sdc/pnr_sdc_option.h b/openfpga/src/fpga_sdc/pnr_sdc_option.h index b81bfaefe..71dc1a806 100644 --- a/openfpga/src/fpga_sdc/pnr_sdc_option.h +++ b/openfpga/src/fpga_sdc/pnr_sdc_option.h @@ -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 */ diff --git a/openfpga/src/fpga_sdc/pnr_sdc_routing_writer.cpp b/openfpga/src/fpga_sdc/pnr_sdc_routing_writer.cpp index dd0914d14..d4f1ce522 100644 --- a/openfpga/src/fpga_sdc/pnr_sdc_routing_writer.cpp +++ b/openfpga/src/fpga_sdc/pnr_sdc_routing_writer.cpp @@ -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 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 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 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); } } diff --git a/openfpga/src/fpga_sdc/pnr_sdc_routing_writer.h b/openfpga/src/fpga_sdc/pnr_sdc_routing_writer.h index 65ce60ca8..0ced07938 100644 --- a/openfpga/src/fpga_sdc/pnr_sdc_routing_writer.h +++ b/openfpga/src/fpga_sdc/pnr_sdc_routing_writer.h @@ -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 */ diff --git a/openfpga/src/fpga_sdc/pnr_sdc_writer.cpp b/openfpga/src/fpga_sdc/pnr_sdc_writer.cpp index b005ca6ce..b7ac5bb43 100644 --- a/openfpga/src/fpga_sdc/pnr_sdc_writer.cpp +++ b/openfpga/src/fpga_sdc/pnr_sdc_writer.cpp @@ -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()); } }