now SDC to disable routing multiplexer outputs can use wildcards
This commit is contained in:
parent
609115e51f
commit
0e44cf3ea3
|
@ -29,6 +29,7 @@
|
|||
#include "sdc_writer_naming.h"
|
||||
#include "sdc_writer_utils.h"
|
||||
#include "sdc_memory_utils.h"
|
||||
#include "sdc_mux_utils.h"
|
||||
#include "pnr_sdc_global_port.h"
|
||||
#include "pnr_sdc_routing_writer.h"
|
||||
#include "pnr_sdc_grid_writer.h"
|
||||
|
@ -80,9 +81,11 @@ void print_pnr_sdc_constrain_configurable_memory_outputs(const std::string& sdc_
|
|||
*******************************************************************/
|
||||
static
|
||||
void print_sdc_disable_routing_multiplexer_outputs(const std::string& sdc_dir,
|
||||
const bool& flatten_names,
|
||||
const MuxLibrary& mux_lib,
|
||||
const CircuitLibrary& circuit_lib,
|
||||
const ModuleManager& module_manager) {
|
||||
const ModuleManager& module_manager,
|
||||
const ModuleId& top_module) {
|
||||
/* Create the file name for Verilog netlist */
|
||||
std::string sdc_fname(sdc_dir + std::string(SDC_DISABLE_MUX_OUTPUTS_FILE_NAME));
|
||||
|
||||
|
@ -112,16 +115,22 @@ void print_sdc_disable_routing_multiplexer_outputs(const std::string& sdc_dir,
|
|||
std::string mux_module_name = generate_mux_subckt_name(circuit_lib, mux_model,
|
||||
find_mux_num_datapath_inputs(circuit_lib, mux_model, mux_graph.num_inputs()),
|
||||
std::string(""));
|
||||
|
||||
/* Find the module name in module manager */
|
||||
ModuleId mux_module = module_manager.find_module(mux_module_name);
|
||||
VTR_ASSERT(true == module_manager.valid_module_id(mux_module));
|
||||
|
||||
/* Disable the timing for the output ports */
|
||||
for (const BasicPort& output_port : module_manager.module_ports_by_type(mux_module, ModuleManager::MODULE_OUTPUT_PORT)) {
|
||||
fp << "set_disable_timing [get_pins -filter \"name =~ " << output_port.get_name() << "*\" ";
|
||||
fp << "-of [get_cells -hier -filter \"ref_lib_cell_name == " << mux_module_name << "\"]]" << std::endl;
|
||||
fp << std::endl;
|
||||
}
|
||||
/* Go recursively in the module manager,
|
||||
* starting from the top-level module: instance id of the top-level module is 0 by default
|
||||
* Disable all the outputs of child modules that matches the mux_module id
|
||||
*/
|
||||
rec_print_pnr_sdc_disable_routing_multiplexer_outputs(fp,
|
||||
flatten_names,
|
||||
module_manager,
|
||||
top_module,
|
||||
mux_module,
|
||||
format_dir_path(module_manager.module_name(top_module)));
|
||||
|
||||
}
|
||||
|
||||
/* Close file handler */
|
||||
|
@ -398,14 +407,19 @@ void print_pnr_sdc(const PnrSdcOption& sdc_options,
|
|||
|
||||
/* Output Design Constraints to disable outputs of memory cells */
|
||||
if (true == sdc_options.constrain_configurable_memory_outputs()) {
|
||||
print_pnr_sdc_constrain_configurable_memory_outputs(sdc_options.sdc_dir(), sdc_options.flatten_names(), module_manager, top_module);
|
||||
print_pnr_sdc_constrain_configurable_memory_outputs(sdc_options.sdc_dir(),
|
||||
sdc_options.flatten_names(),
|
||||
module_manager,
|
||||
top_module);
|
||||
}
|
||||
|
||||
/* Break loops from Multiplexer Output */
|
||||
if (true == sdc_options.constrain_routing_multiplexer_outputs()) {
|
||||
print_sdc_disable_routing_multiplexer_outputs(sdc_options.sdc_dir(),
|
||||
sdc_options.flatten_names(),
|
||||
mux_lib, circuit_lib,
|
||||
module_manager);
|
||||
module_manager,
|
||||
top_module);
|
||||
}
|
||||
|
||||
/* Break loops from any SB output */
|
||||
|
|
|
@ -0,0 +1,113 @@
|
|||
/********************************************************************
|
||||
* Most utilized function used to constrain routing multiplexers in FPGA
|
||||
* fabric using SDC commands
|
||||
*******************************************************************/
|
||||
|
||||
/* Headers from vtrutil library */
|
||||
#include "vtr_assert.h"
|
||||
#include "vtr_log.h"
|
||||
|
||||
/* Headers from openfpgautil library */
|
||||
#include "openfpga_wildcard_string.h"
|
||||
#include "openfpga_digest.h"
|
||||
|
||||
#include "openfpga_naming.h"
|
||||
|
||||
#include "sdc_writer_utils.h"
|
||||
|
||||
#include "sdc_mux_utils.h"
|
||||
|
||||
/* begin namespace openfpga */
|
||||
namespace openfpga {
|
||||
|
||||
/********************************************************************
|
||||
* Print SDC commands to disable outputs of routing multiplexer modules
|
||||
* in a given module id
|
||||
* This function will be executed in a recursive way,
|
||||
* using a Depth-First Search (DFS) strategy
|
||||
* It will iterate over all the configurable children under each module
|
||||
* and print a SDC command to disable its outputs
|
||||
*
|
||||
* Note:
|
||||
* - When flatten_names is true
|
||||
* this function will not apply any wildcard to names
|
||||
* - When flatten_names is false
|
||||
* It will straightforwardly output the instance name and port name
|
||||
* This function will try to apply wildcard to names
|
||||
* so that SDC file size can be minimal
|
||||
*******************************************************************/
|
||||
void rec_print_pnr_sdc_disable_routing_multiplexer_outputs(std::fstream& fp,
|
||||
const bool& flatten_names,
|
||||
const ModuleManager& module_manager,
|
||||
const ModuleId& parent_module,
|
||||
const ModuleId& mux_module,
|
||||
const std::string& parent_module_path) {
|
||||
|
||||
/* Build wildcard names for the instance names of multiple-instanced-blocks (MIB)
|
||||
* We will find all the instance names and see there are common prefix
|
||||
* If so, we can use wildcards
|
||||
*/
|
||||
std::map<ModuleId, std::vector<std::string>> wildcard_names;
|
||||
|
||||
/* For each child, we will go one level down in priority */
|
||||
for (const ModuleId& child_module : module_manager.child_modules(parent_module)) {
|
||||
|
||||
std::string child_module_path = parent_module_path;
|
||||
|
||||
/* Iterate over the child instances*/
|
||||
for (const size_t& child_instance : module_manager.child_module_instances(parent_module, child_module)) {
|
||||
std::string child_instance_name;
|
||||
if (true == module_manager.instance_name(parent_module, child_module, child_instance).empty()) {
|
||||
child_instance_name = generate_instance_name(module_manager.module_name(child_module), child_instance);
|
||||
} else {
|
||||
child_instance_name = module_manager.instance_name(parent_module, child_module, child_instance);
|
||||
}
|
||||
|
||||
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))
|
||||
&& (wildcard_names.at(child_module).end() != std::find(wildcard_names.at(child_module).begin(),
|
||||
wildcard_names.at(child_module).end(),
|
||||
wildcard_str.data())) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
child_module_path += wildcard_str.data();
|
||||
|
||||
wildcard_names[child_module].push_back(wildcard_str.data());
|
||||
} else {
|
||||
child_module_path += child_instance_name;
|
||||
}
|
||||
|
||||
child_module_path = format_dir_path(child_module_path);
|
||||
|
||||
/* If this is NOT the MUX module we want, we go recursively */
|
||||
if (mux_module != child_module) {
|
||||
rec_print_pnr_sdc_disable_routing_multiplexer_outputs(fp, flatten_names,
|
||||
module_manager,
|
||||
child_module,
|
||||
mux_module,
|
||||
child_module_path);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Validate file stream */
|
||||
valid_file_stream(fp);
|
||||
|
||||
/* Reach here, this is the MUX module we want, disable the outputs */
|
||||
for (const BasicPort& output_port : module_manager.module_ports_by_type(mux_module, ModuleManager::MODULE_OUTPUT_PORT)) {
|
||||
fp << "set_disable_timing ";
|
||||
fp << child_module_path << output_port.get_name();
|
||||
fp << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} /* end namespace openfpga */
|
|
@ -0,0 +1,28 @@
|
|||
#ifndef SDC_MUX_UTILS_H
|
||||
#define SDC_MUX_UTILS_H
|
||||
|
||||
/********************************************************************
|
||||
* Include header files that are required by function declaration
|
||||
*******************************************************************/
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include "module_manager.h"
|
||||
|
||||
/********************************************************************
|
||||
* Function declaration
|
||||
*******************************************************************/
|
||||
|
||||
/* begin namespace openfpga */
|
||||
namespace openfpga {
|
||||
|
||||
void rec_print_pnr_sdc_disable_routing_multiplexer_outputs(std::fstream& fp,
|
||||
const bool& flatten_names,
|
||||
const ModuleManager& module_manager,
|
||||
const ModuleId& parent_module,
|
||||
const ModuleId& mux_module,
|
||||
const std::string& parent_module_path);
|
||||
|
||||
|
||||
} /* end namespace openfpga */
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue