diff --git a/openfpga/src/fpga_sdc/sdc_writer_naming.h b/openfpga/src/fpga_sdc/sdc_writer_naming.h new file mode 100644 index 000000000..9783e29f2 --- /dev/null +++ b/openfpga/src/fpga_sdc/sdc_writer_naming.h @@ -0,0 +1,20 @@ +#ifndef SDC_WRITER_NAMING_H +#define SDC_WRITER_NAMING_H + +/* begin namespace openfpga */ +namespace openfpga { + +constexpr char* SDC_FILE_NAME_POSTFIX = ".sdc"; + +constexpr char* SDC_GLOBAL_PORTS_FILE_NAME = "global_ports.sdc"; +constexpr char* SDC_BENCHMARK_ANALYSIS_FILE_NAME= "fpga_top_analysis.sdc"; +constexpr char* SDC_DISABLE_CONFIG_MEM_OUTPUTS_FILE_NAME = "disable_configurable_memory_outputs.sdc"; +constexpr char* SDC_DISABLE_MUX_OUTPUTS_FILE_NAME = "disable_routing_multiplexer_outputs.sdc"; +constexpr char* SDC_DISABLE_SB_OUTPUTS_FILE_NAME = "disable_sb_outputs.sdc"; +constexpr char* SDC_CB_FILE_NAME = "cb.sdc"; + +constexpr char* SDC_ANALYSIS_FILE_NAME = "fpga_top_analysis.sdc"; + +} /* end namespace openfpga */ + +#endif diff --git a/openfpga/src/fpga_sdc/sdc_writer_utils.cpp b/openfpga/src/fpga_sdc/sdc_writer_utils.cpp new file mode 100644 index 000000000..328f87ce6 --- /dev/null +++ b/openfpga/src/fpga_sdc/sdc_writer_utils.cpp @@ -0,0 +1,202 @@ +/******************************************************************** + * This file include most utilized functions to be used in SDC writers + *******************************************************************/ +#include +#include +#include + +/* Headers from openfpgautil library */ +#include "openfpga_digest.h" + +#include "sdc_writer_utils.h" + +/* begin namespace openfpga */ +namespace openfpga { + +/******************************************************************** + * Write a head (description) in SDC file + *******************************************************************/ +void print_sdc_file_header(std::fstream& fp, + const std::string& usage) { + + 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); + fp << "#############################################" << std::endl; + fp << std::endl; +} + +/******************************************************************** + * Write a port in SDC format + *******************************************************************/ +std::string generate_sdc_port(const BasicPort& port) { + std::string sdc_line; + + std::string size_str = "[" + std::to_string(port.get_lsb()) + ":" + std::to_string(port.get_msb()) + "]"; + + /* Only connection require a format of [:] + * others require a format of [:] + */ + /* When LSB == MSB, we can use a simplified format []*/ + if ( 1 == port.get_width()) { + size_str = "[" + std::to_string(port.get_lsb()) + "]"; + } + sdc_line = port.get_name() + size_str; + + return sdc_line; +} + +/******************************************************************** + * Constrain a path between two ports of a module with a given maximum timing value + *******************************************************************/ +void print_pnr_sdc_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 "; + if (!src_instance_name.empty()) { + fp << src_instance_name << "/"; + } + fp << src_port_name; + + fp << " -to "; + + if (!des_instance_name.empty()) { + fp << des_instance_name << "/"; + } + fp << des_port_name; + + fp << " " << std::setprecision(10) << delay; + + fp << std::endl; +} + +/******************************************************************** + * Constrain a path between two ports of a module with a given timing value + * Note: this function uses set_max_delay !!! + *******************************************************************/ +void print_pnr_sdc_constrain_module_port2port_timing(std::fstream& fp, + const ModuleManager& module_manager, + const ModuleId& input_parent_module_id, + const ModulePortId& module_input_port_id, + const ModuleId& output_parent_module_id, + const ModulePortId& module_output_port_id, + const float& tmax) { + print_pnr_sdc_constrain_max_delay(fp, + module_manager.module_name(input_parent_module_id), + generate_sdc_port(module_manager.module_port(input_parent_module_id, module_input_port_id)), + module_manager.module_name(output_parent_module_id), + generate_sdc_port(module_manager.module_port(output_parent_module_id, module_output_port_id)), + tmax); + +} + +/******************************************************************** + * Constrain a path between two ports of a module with a given timing value + * This function will NOT output the module name + * Note: this function uses set_max_delay !!! + *******************************************************************/ +void print_pnr_sdc_constrain_port2port_timing(std::fstream& fp, + const ModuleManager& module_manager, + const ModuleId& input_parent_module_id, + const ModulePortId& module_input_port_id, + const ModuleId& output_parent_module_id, + const ModulePortId& module_output_port_id, + const float& tmax) { + print_pnr_sdc_constrain_max_delay(fp, + std::string(), + generate_sdc_port(module_manager.module_port(input_parent_module_id, module_input_port_id)), + std::string(), + generate_sdc_port(module_manager.module_port(output_parent_module_id, module_output_port_id)), + tmax); + +} + +/******************************************************************** + * Disable timing for a port + *******************************************************************/ +void print_sdc_disable_port_timing(std::fstream& fp, + const BasicPort& port) { + /* Validate file stream */ + valid_file_stream(fp); + + fp << "set_disable_timing "; + + fp << generate_sdc_port(port); + + fp << std::endl; +} + +/******************************************************************** + * Set the input delay for a port in SDC format + * Note that the input delay will be bounded by a clock port + *******************************************************************/ +void print_sdc_set_port_input_delay(std::fstream& fp, + const BasicPort& port, + const BasicPort& clock_port, + const float& delay) { + /* Validate file stream */ + valid_file_stream(fp); + + fp << "set_input_delay "; + + fp << "-clock "; + + fp << generate_sdc_port(clock_port); + + fp << " -max "; + + fp << std::setprecision(10) << delay; + + fp << " "; + + fp << generate_sdc_port(port); + + fp << std::endl; +} + +/******************************************************************** + * Set the output delay for a port in SDC format + * Note that the output delay will be bounded by a clock port + *******************************************************************/ +void print_sdc_set_port_output_delay(std::fstream& fp, + const BasicPort& port, + const BasicPort& clock_port, + const float& delay) { + /* Validate file stream */ + valid_file_stream(fp); + + fp << "set_output_delay "; + + fp << "-clock "; + + fp << generate_sdc_port(clock_port); + + fp << " -max "; + + fp << std::setprecision(10) << delay; + + fp << " "; + + fp << generate_sdc_port(port); + + fp << std::endl; +} + +} /* end namespace openfpga */ diff --git a/openfpga/src/fpga_sdc/sdc_writer_utils.h b/openfpga/src/fpga_sdc/sdc_writer_utils.h new file mode 100644 index 000000000..4e0d86839 --- /dev/null +++ b/openfpga/src/fpga_sdc/sdc_writer_utils.h @@ -0,0 +1,62 @@ +#ifndef SDC_WRITER_UTILS_H +#define SDC_WRITER_UTILS_H + +/******************************************************************** + * Include header files that are required by function declaration + *******************************************************************/ +#include +#include +#include "openfpga_port.h" +#include "module_manager.h" + +/******************************************************************** + * Function declaration + *******************************************************************/ + +/* begin namespace openfpga */ +namespace openfpga { + +void print_sdc_file_header(std::fstream& fp, + const std::string& usage); + +std::string generate_sdc_port(const BasicPort& port); + +void print_pnr_sdc_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_module_port2port_timing(std::fstream& fp, + const ModuleManager& module_manager, + const ModuleId& input_parent_module_id, + const ModulePortId& module_input_port_id, + const ModuleId& output_parent_module_id, + const ModulePortId& module_output_port_id, + const float& tmax); + +void print_pnr_sdc_constrain_port2port_timing(std::fstream& fp, + const ModuleManager& module_manager, + const ModuleId& input_parent_module_id, + const ModulePortId& module_input_port_id, + const ModuleId& output_parent_module_id, + const ModulePortId& module_output_port_id, + const float& tmax); + +void print_sdc_disable_port_timing(std::fstream& fp, + const BasicPort& port); + +void print_sdc_set_port_input_delay(std::fstream& fp, + const BasicPort& port, + const BasicPort& clock_port, + const float& delay); + +void print_sdc_set_port_output_delay(std::fstream& fp, + const BasicPort& port, + const BasicPort& clock_port, + const float& delay); + +} /* end namespace openfpga */ + +#endif