diff --git a/libopenfpga/libopenfpgautil/src/openfpga_wildcard_string.cpp b/libopenfpga/libopenfpgautil/src/openfpga_wildcard_string.cpp new file mode 100644 index 000000000..67031a2a5 --- /dev/null +++ b/libopenfpga/libopenfpgautil/src/openfpga_wildcard_string.cpp @@ -0,0 +1,105 @@ +/************************************************************************ + * Member functions for WildCardString class + ***********************************************************************/ +#include + +/* Headers from vtrutil library */ +#include "vtr_assert.h" +#include "vtr_log.h" + +#include "openfpga_wildcard_string.h" + +/* namespace openfpga begins */ +namespace openfpga { + +/************************************************************************ + * Constructors + ***********************************************************************/ +WildCardString::WildCardString(const std::string& data) { + set_data(data); +} + +/************************************************************************ + * Public Accessors + ***********************************************************************/ +std::string WildCardString::data() const { + return data_; +} + +/************************************************************************ + * Public Mutators + ***********************************************************************/ +void WildCardString::set_data(const std::string& data) { + data_ = data; + + set_default_wildcard_char(); + set_default_sensitive_chars(); + apply_wildcard_char(); + compress(); +} + +/************************************************************************ + * Internal Mutators + ***********************************************************************/ +void WildCardString::set_default_wildcard_char() { + wildcard_char_ = '*'; +} + +void WildCardString::set_default_sensitive_chars() { + sensitive_chars_.clear(); + sensitive_chars_.reserve(10); + sensitive_chars_.push_back('0'); + sensitive_chars_.push_back('1'); + sensitive_chars_.push_back('2'); + sensitive_chars_.push_back('3'); + sensitive_chars_.push_back('4'); + sensitive_chars_.push_back('5'); + sensitive_chars_.push_back('6'); + sensitive_chars_.push_back('7'); + sensitive_chars_.push_back('8'); + sensitive_chars_.push_back('9'); +} + +void WildCardString::apply_wildcard_char() { + /* Step by step: + * For each sensitive character, + * replace all of its occurance in the string data_ with wildcard character + */ + for (const char& char_to_replace : sensitive_chars_) { + size_t cur_pos = 0; + std::string::size_type found; + while (std::string::npos != (found = data_.find_first_of(char_to_replace, cur_pos))) { + data_.replace(found, 1, 1, wildcard_char_); + cur_pos = found + 1; + } + } +} + +void WildCardString::compress() { + for (std::string::size_type i = 0; i < data_.size(); ++i) { + /* Care only wildcard character */ + if (wildcard_char_ != data_[i]) { + continue; + } + + /* Finish if this is the end of string */ + if (data_.size() - 1 == i) { + break; + } + + /* Try to find the next element and see if the same as wild card + * Keep erase the next element until we have a non-wildcard character + */ + while (data_[i] == data_[i + 1]) { + /* Erase the next element */ + data_.erase(i + 1, 1); + + /* Finish if this is the end of string */ + if (data_.size() - 1 == i) { + break; + } + } + } +} + +} /* namespace openfpga ends */ diff --git a/libopenfpga/libopenfpgautil/src/openfpga_wildcard_string.h b/libopenfpga/libopenfpgautil/src/openfpga_wildcard_string.h new file mode 100644 index 000000000..874641cf4 --- /dev/null +++ b/libopenfpga/libopenfpgautil/src/openfpga_wildcard_string.h @@ -0,0 +1,57 @@ +#ifndef OPENFPGA_WILDCARD_STRING_H +#define OPENFPGA_WILDCARD_STRING_H + +/******************************************************************** + * Include header files that are required by data structure declaration + *******************************************************************/ +#include +#include + +/* namespace openfpga begins */ +namespace openfpga { + +/************************************************************************ + * This file includes a object that can apply wildcard characters + * By default it will replace any digital numbers with a '*' character + * Users can set the wildcard character on their needs + * + * Example: + * std::string orig_str; + * WildCardString wc_str(orig_str); + * std::string output = wc_str.data(); + * + ***********************************************************************/ + +class WildCardString { + public : /* Constructors*/ + WildCardString (const std::string& data); + + public : /* Public Accessors */ + std::string data() const; + + public : /* Public Mutators */ + /* Give a string to apply wildcards */ + void set_data(const std::string& data); + + private : /* Private Mutators */ + /* Use default wildcard character '*' */ + void set_default_wildcard_char(); + + /* Use default sensitive words which are numbers */ + void set_default_sensitive_chars(); + + /* Replace sensitive words with wildcard characters */ + void apply_wildcard_char(); + + /* Remove redundant wildcard chars (which are next to each other) */ + void compress(); + + private : /* Internal data */ + std::string data_; /* Lines to be splited */ + std::vector sensitive_chars_; + char wildcard_char_; +}; + +} /* namespace openfpga ends */ + +#endif diff --git a/openfpga/src/base/openfpga_naming.cpp b/openfpga/src/base/openfpga_naming.cpp index 0796d4df1..74750fca5 100644 --- a/openfpga/src/base/openfpga_naming.cpp +++ b/openfpga/src/base/openfpga_naming.cpp @@ -30,6 +30,20 @@ std::string generate_instance_name(const std::string& instance_name, return instance_name + std::string("_") + std::to_string(instance_id) + std::string("_"); } +/************************************************ + * A generic function to generate the instance name + * in the following format: + * __ + * This is mainly used by module manager to give a default + * name for each instance when outputting the module + * in Verilog/SPICE format + ***********************************************/ +std::string generate_instance_wildcard_name(const std::string& instance_name, + const std::string& wildcard_str) { + return instance_name + std::string("_") + wildcard_str + std::string("_"); +} + + /************************************************ * Generate the node name for a multiplexing structure * Case 1 : If there is an intermediate buffer followed by, diff --git a/openfpga/src/base/openfpga_naming.h b/openfpga/src/base/openfpga_naming.h index d3307fe3c..9896dddd4 100644 --- a/openfpga/src/base/openfpga_naming.h +++ b/openfpga/src/base/openfpga_naming.h @@ -26,6 +26,9 @@ namespace openfpga { std::string generate_instance_name(const std::string& instance_name, const size_t& instance_id); +std::string generate_instance_wildcard_name(const std::string& instance_name, + const std::string& wildcard_str); + std::string generate_mux_node_name(const size_t& node_level, const bool& add_buffer_postfix); diff --git a/openfpga/src/base/openfpga_sdc.cpp b/openfpga/src/base/openfpga_sdc.cpp index 21a3ab8fb..c0c5b3f22 100644 --- a/openfpga/src/base/openfpga_sdc.cpp +++ b/openfpga/src/base/openfpga_sdc.cpp @@ -29,6 +29,7 @@ int write_pnr_sdc(OpenfpgaContext& openfpga_ctx, const Command& cmd, const CommandContext& cmd_context) { CommandOptionId opt_output_dir = cmd.option("file"); + CommandOptionId opt_flatten_names = cmd.option("flatten_names"); 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"); @@ -49,6 +50,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_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)); @@ -95,6 +97,7 @@ int write_analysis_sdc(OpenfpgaContext& openfpga_ctx, const Command& cmd, const CommandContext& cmd_context) { CommandOptionId opt_output_dir = cmd.option("file"); + CommandOptionId opt_flatten_names = cmd.option("flatten_names"); /* This is an intermediate data structure which is designed to modularize the FPGA-SDC * Keep it independent from any other outside data structures @@ -106,6 +109,7 @@ int write_analysis_sdc(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)); /* Collect global ports from the circuit library: * TODO: should we place this in the OpenFPGA context? diff --git a/openfpga/src/base/openfpga_sdc_command.cpp b/openfpga/src/base/openfpga_sdc_command.cpp index 551b37d2b..02595a10c 100644 --- a/openfpga/src/base/openfpga_sdc_command.cpp +++ b/openfpga/src/base/openfpga_sdc_command.cpp @@ -26,6 +26,9 @@ ShellCommandId add_openfpga_write_pnr_sdc_command(openfpga::Shell skip_mib; + std::map> wildcard_names; + /* For each configurable child, we will go one level down in priority */ for (size_t child_index = 0; child_index < module_manager.configurable_children(parent_module).size(); ++child_index) { std::string child_module_path = parent_module_path; ModuleId child_module_id = module_manager.configurable_children(parent_module)[child_index]; size_t child_instance_id = module_manager.configurable_child_instances(parent_module)[child_index]; + std::string child_instance_name; if (true == module_manager.instance_name(parent_module, child_module_id, child_instance_id).empty()) { - if (0 < skip_mib.count(child_module_id)) { - VTR_ASSERT(skip_mib.at(child_module_id) = true); + child_instance_name = generate_instance_name(module_manager.module_name(child_module_id), child_instance_id); + } else { + child_instance_name = module_manager.instance_name(parent_module, child_module_id, child_instance_id); + } + + if (false == flatten_names) { + /* Try to adapt to a wildcard name: replace all the numbers with a wildcard character '*' */ + WildCardString wildcard_str(child_instance_name); + /* If the wildcard name is already in the list, we can skip this + * Otherwise, we have to + * - output this instance + * - record the wildcard name in the map + */ + if ( (0 < wildcard_names.count(child_module_id)) + && (wildcard_names.at(child_module_id).end() != std::find(wildcard_names.at(child_module_id).begin(), + wildcard_names.at(child_module_id).end(), + wildcard_str.data())) ) { continue; } - /* Give a default name __ */ - child_module_path += module_manager.module_name(child_module_id); - child_module_path += "_"; - child_module_path += "*"; - //child_module_path += std::to_string(child_instance_id); - child_module_path += "_"; - /* If we use wild card to disable all the other instance - * So we can skip later if there is no specific instance name - */ - skip_mib[child_module_id] = true; + + child_module_path += wildcard_str.data(); + + wildcard_names[child_module_id].push_back(wildcard_str.data()); } else { - child_module_path += module_manager.instance_name(parent_module, child_module_id, child_instance_id); + child_module_path += child_instance_name; } + child_module_path = format_dir_path(child_module_path); - rec_print_pnr_sdc_disable_configurable_memory_module_output(fp, module_manager, + rec_print_pnr_sdc_disable_configurable_memory_module_output(fp, flatten_names, + module_manager, child_module_id, child_module_path); } diff --git a/openfpga/src/fpga_sdc/sdc_memory_utils.h b/openfpga/src/fpga_sdc/sdc_memory_utils.h index 7fbf92294..576b3a36e 100644 --- a/openfpga/src/fpga_sdc/sdc_memory_utils.h +++ b/openfpga/src/fpga_sdc/sdc_memory_utils.h @@ -16,6 +16,7 @@ namespace openfpga { void rec_print_pnr_sdc_disable_configurable_memory_module_output(std::fstream& fp, + const bool& flatten_names, const ModuleManager& module_manager, const ModuleId& parent_module, const std::string& parent_module_path);