now disable_sb_output support wildcard
This commit is contained in:
parent
ecdbdcb592
commit
d0793d9029
|
@ -27,7 +27,7 @@ ShellCommandId add_openfpga_write_pnr_sdc_command(openfpga::Shell<OpenfpgaContex
|
|||
shell_cmd.set_option_require_value(output_opt, openfpga::OPT_STRING);
|
||||
|
||||
/* Add an option '--flatten_name' */
|
||||
shell_cmd.add_option("flatten_names", false, "Use flatten names to compress SDC file size");
|
||||
shell_cmd.add_option("flatten_names", false, "Use flatten names (no wildcards) in SDC files");
|
||||
|
||||
/* Add an option '--constrain_global_port' */
|
||||
shell_cmd.add_option("constrain_global_port", false, "Constrain all the global ports of FPGA fabric");
|
||||
|
@ -90,7 +90,7 @@ ShellCommandId add_openfpga_write_analysis_sdc_command(openfpga::Shell<OpenfpgaC
|
|||
shell_cmd.add_option("verbose", false, "Enable verbose output");
|
||||
|
||||
/* Add an option '--flatten_name' */
|
||||
shell_cmd.add_option("flatten_names", false, "Use flatten names to compress SDC file size");
|
||||
shell_cmd.add_option("flatten_names", false, "Use flatten names (no wildcards) in SDC files");
|
||||
|
||||
/* Add command 'write_fabric_verilog' to the Shell */
|
||||
ShellCommandId shell_cmd_id = shell.add_command(shell_cmd, "generate SDC files for timing analysis a PnRed FPGA fabric mapped by a benchmark");
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
/* Headers from openfpgautil library */
|
||||
#include "openfpga_port.h"
|
||||
#include "openfpga_wildcard_string.h"
|
||||
#include "openfpga_digest.h"
|
||||
|
||||
#include "mux_utils.h"
|
||||
|
@ -135,61 +136,7 @@ void print_sdc_disable_routing_multiplexer_outputs(const std::string& sdc_dir,
|
|||
*******************************************************************/
|
||||
static
|
||||
void print_pnr_sdc_flatten_routing_disable_switch_block_outputs(const std::string& sdc_dir,
|
||||
const ModuleManager& module_manager,
|
||||
const DeviceRRGSB& device_rr_gsb) {
|
||||
/* Create the file name for Verilog netlist */
|
||||
std::string sdc_fname(sdc_dir + std::string(SDC_DISABLE_SB_OUTPUTS_FILE_NAME));
|
||||
|
||||
/* Start time count */
|
||||
std::string timer_message = std::string("Write SDC to disable switch block outputs for P&R flow '") + sdc_fname + std::string("'");
|
||||
vtr::ScopedStartFinishTimer timer(timer_message);
|
||||
|
||||
/* Create the file stream */
|
||||
std::fstream fp;
|
||||
fp.open(sdc_fname, std::fstream::out | std::fstream::trunc);
|
||||
|
||||
check_file_stream(sdc_fname.c_str(), fp);
|
||||
|
||||
/* Generate the descriptions*/
|
||||
print_sdc_file_header(fp, std::string("Disable Switch Block outputs for PnR"));
|
||||
|
||||
/* Get the range of SB array */
|
||||
vtr::Point<size_t> sb_range = device_rr_gsb.get_gsb_range();
|
||||
/* Go for each SB */
|
||||
for (size_t ix = 0; ix < sb_range.x(); ++ix) {
|
||||
for (size_t iy = 0; iy < sb_range.y(); ++iy) {
|
||||
const RRGSB& rr_gsb = device_rr_gsb.get_gsb(ix, iy);
|
||||
|
||||
if (false == rr_gsb.is_sb_exist()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
vtr::Point<size_t> gsb_coordinate(rr_gsb.get_sb_x(), rr_gsb.get_sb_y());
|
||||
std::string sb_instance_name = generate_switch_block_module_name(gsb_coordinate);
|
||||
|
||||
ModuleId sb_module = module_manager.find_module(sb_instance_name);
|
||||
VTR_ASSERT(true == module_manager.valid_module_id(sb_module));
|
||||
|
||||
/* Disable the outputs of the module */
|
||||
for (const BasicPort& output_port : module_manager.module_ports_by_type(sb_module, ModuleManager::MODULE_OUTPUT_PORT)) {
|
||||
fp << "set_disable_timing " << sb_instance_name << "/" << output_port.get_name() << std::endl;
|
||||
fp << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Close file handler */
|
||||
fp.close();
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Break combinational loops in FPGA fabric, which mainly come from
|
||||
* loops of multiplexers.
|
||||
* To handle this, we disable the timing at outputs of Switch blocks
|
||||
* This function is designed for compact routing hierarchy
|
||||
*******************************************************************/
|
||||
static
|
||||
void print_pnr_sdc_compact_routing_disable_switch_block_outputs(const std::string& sdc_dir,
|
||||
const bool& flatten_names,
|
||||
const ModuleManager& module_manager,
|
||||
const ModuleId& top_module,
|
||||
const DeviceRRGSB& device_rr_gsb) {
|
||||
|
@ -209,6 +156,131 @@ void print_pnr_sdc_compact_routing_disable_switch_block_outputs(const std::strin
|
|||
/* Generate the descriptions*/
|
||||
print_sdc_file_header(fp, std::string("Disable Switch Block outputs for PnR"));
|
||||
|
||||
std::string root_path = format_dir_path(module_manager.module_name(top_module));
|
||||
|
||||
/* 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;
|
||||
|
||||
/* Get the range of SB array */
|
||||
vtr::Point<size_t> sb_range = device_rr_gsb.get_gsb_range();
|
||||
/* Go for each SB */
|
||||
for (size_t ix = 0; ix < sb_range.x(); ++ix) {
|
||||
for (size_t iy = 0; iy < sb_range.y(); ++iy) {
|
||||
const RRGSB& rr_gsb = device_rr_gsb.get_gsb(ix, iy);
|
||||
|
||||
if (false == rr_gsb.is_sb_exist()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string module_path = root_path;
|
||||
|
||||
vtr::Point<size_t> gsb_coordinate(rr_gsb.get_sb_x(), rr_gsb.get_sb_y());
|
||||
std::string sb_instance_name = generate_switch_block_module_name(gsb_coordinate);
|
||||
|
||||
ModuleId sb_module = module_manager.find_module(sb_instance_name);
|
||||
VTR_ASSERT(true == module_manager.valid_module_id(sb_module));
|
||||
|
||||
if (false == flatten_names) {
|
||||
/* Try to adapt to a wildcard name: replace all the numbers with a wildcard character '*' */
|
||||
WildCardString wildcard_str(sb_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(sb_module))
|
||||
&& (wildcard_names.at(sb_module).end() != std::find(wildcard_names.at(sb_module).begin(),
|
||||
wildcard_names.at(sb_module).end(),
|
||||
wildcard_str.data())) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
module_path += wildcard_str.data();
|
||||
|
||||
wildcard_names[sb_module].push_back(wildcard_str.data());
|
||||
} else {
|
||||
module_path += sb_instance_name;
|
||||
}
|
||||
|
||||
module_path = format_dir_path(module_path);
|
||||
|
||||
std::vector<std::string> port_wildcard_names;
|
||||
|
||||
/* Disable the outputs of the module */
|
||||
for (const BasicPort& output_port : module_manager.module_ports_by_type(sb_module, ModuleManager::MODULE_OUTPUT_PORT)) {
|
||||
std::string port_name = output_port.get_name();
|
||||
|
||||
if (false == flatten_names) {
|
||||
/* Try to adapt to a wildcard name: replace all the numbers with a wildcard character '*' */
|
||||
WildCardString port_wildcard_str(output_port.get_name());
|
||||
/* If the wildcard name is already in the list, we can skip this
|
||||
* Otherwise, we have to
|
||||
* - output this port
|
||||
* - record the wildcard name in the vector
|
||||
*/
|
||||
if (port_wildcard_names.end() != std::find(port_wildcard_names.begin(),
|
||||
port_wildcard_names.end(),
|
||||
port_wildcard_str.data())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
port_name = port_wildcard_str.data();
|
||||
|
||||
port_wildcard_names.push_back(port_wildcard_str.data());
|
||||
}
|
||||
|
||||
fp << "set_disable_timing ";
|
||||
fp << module_path;
|
||||
fp << port_name << std::endl;
|
||||
|
||||
fp << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Close file handler */
|
||||
fp.close();
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* Break combinational loops in FPGA fabric, which mainly come from
|
||||
* loops of multiplexers.
|
||||
* To handle this, we disable the timing at outputs of Switch blocks
|
||||
* This function is designed for compact routing hierarchy
|
||||
*******************************************************************/
|
||||
static
|
||||
void print_pnr_sdc_compact_routing_disable_switch_block_outputs(const std::string& sdc_dir,
|
||||
const bool& flatten_names,
|
||||
const ModuleManager& module_manager,
|
||||
const ModuleId& top_module,
|
||||
const DeviceRRGSB& device_rr_gsb) {
|
||||
/* Create the file name for Verilog netlist */
|
||||
std::string sdc_fname(sdc_dir + std::string(SDC_DISABLE_SB_OUTPUTS_FILE_NAME));
|
||||
|
||||
/* Start time count */
|
||||
std::string timer_message = std::string("Write SDC to disable switch block outputs for P&R flow '") + sdc_fname + std::string("'");
|
||||
vtr::ScopedStartFinishTimer timer(timer_message);
|
||||
|
||||
/* Create the file stream */
|
||||
std::fstream fp;
|
||||
fp.open(sdc_fname, std::fstream::out | std::fstream::trunc);
|
||||
|
||||
check_file_stream(sdc_fname.c_str(), fp);
|
||||
|
||||
/* Generate the descriptions*/
|
||||
print_sdc_file_header(fp, std::string("Disable Switch Block outputs for PnR"));
|
||||
|
||||
std::string root_path = format_dir_path(module_manager.module_name(top_module));
|
||||
|
||||
/* 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;
|
||||
|
||||
/* Build unique switch block modules */
|
||||
for (size_t isb = 0; isb < device_rr_gsb.get_num_sb_unique_module(); ++isb) {
|
||||
const RRGSB& rr_gsb = device_rr_gsb.get_sb_unique_module(isb);
|
||||
|
@ -217,13 +289,66 @@ void print_pnr_sdc_compact_routing_disable_switch_block_outputs(const std::strin
|
|||
|
||||
ModuleId sb_module = module_manager.find_module(sb_module_name);
|
||||
VTR_ASSERT(true == module_manager.valid_module_id(sb_module));
|
||||
|
||||
std::string module_path = root_path;
|
||||
|
||||
/* Find all the instances in the top-level module */
|
||||
for (const size_t& instance_id : module_manager.child_module_instances(top_module, sb_module)) {
|
||||
std::string sb_instance_name = module_manager.instance_name(top_module, sb_module, instance_id);
|
||||
|
||||
if (false == flatten_names) {
|
||||
/* Try to adapt to a wildcard name: replace all the numbers with a wildcard character '*' */
|
||||
WildCardString wildcard_str(sb_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(sb_module))
|
||||
&& (wildcard_names.at(sb_module).end() != std::find(wildcard_names.at(sb_module).begin(),
|
||||
wildcard_names.at(sb_module).end(),
|
||||
wildcard_str.data())) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
module_path += wildcard_str.data();
|
||||
|
||||
wildcard_names[sb_module].push_back(wildcard_str.data());
|
||||
} else {
|
||||
module_path += sb_instance_name;
|
||||
}
|
||||
|
||||
module_path = format_dir_path(module_path);
|
||||
|
||||
std::vector<std::string> port_wildcard_names;
|
||||
|
||||
/* Disable the outputs of the module */
|
||||
for (const BasicPort& output_port : module_manager.module_ports_by_type(sb_module, ModuleManager::MODULE_OUTPUT_PORT)) {
|
||||
fp << "set_disable_timing " << sb_instance_name << "/" << output_port.get_name() << std::endl;
|
||||
std::string port_name = output_port.get_name();
|
||||
|
||||
if (false == flatten_names) {
|
||||
/* Try to adapt to a wildcard name: replace all the numbers with a wildcard character '*' */
|
||||
WildCardString port_wildcard_str(output_port.get_name());
|
||||
/* If the wildcard name is already in the list, we can skip this
|
||||
* Otherwise, we have to
|
||||
* - output this port
|
||||
* - record the wildcard name in the vector
|
||||
*/
|
||||
if (port_wildcard_names.end() != std::find(port_wildcard_names.begin(),
|
||||
port_wildcard_names.end(),
|
||||
port_wildcard_str.data())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
port_name = port_wildcard_str.data();
|
||||
|
||||
port_wildcard_names.push_back(port_wildcard_str.data());
|
||||
}
|
||||
|
||||
fp << "set_disable_timing ";
|
||||
fp << module_path;
|
||||
fp << port_name << std::endl;
|
||||
|
||||
fp << std::endl;
|
||||
}
|
||||
}
|
||||
|
@ -282,12 +407,14 @@ void print_pnr_sdc(const PnrSdcOption& sdc_options,
|
|||
if (true == sdc_options.constrain_switch_block_outputs()) {
|
||||
if (true == compact_routing_hierarchy) {
|
||||
print_pnr_sdc_compact_routing_disable_switch_block_outputs(sdc_options.sdc_dir(),
|
||||
sdc_options.flatten_names(),
|
||||
module_manager, top_module,
|
||||
device_rr_gsb);
|
||||
} else {
|
||||
VTR_ASSERT_SAFE (false == compact_routing_hierarchy);
|
||||
print_pnr_sdc_flatten_routing_disable_switch_block_outputs(sdc_options.sdc_dir(),
|
||||
module_manager,
|
||||
sdc_options.flatten_names(),
|
||||
module_manager, top_module,
|
||||
device_rr_gsb);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue