add hierarchy writer to SDC generator
This commit is contained in:
parent
1943929353
commit
c651df6421
|
@ -33,6 +33,7 @@ int write_pnr_sdc(OpenfpgaContext& openfpga_ctx,
|
|||
CommandOptionId opt_flatten_names = cmd.option("flatten_names");
|
||||
CommandOptionId opt_hierarchical = cmd.option("hierarchical");
|
||||
CommandOptionId opt_time_unit = cmd.option("time_unit");
|
||||
CommandOptionId opt_output_hierarchy = cmd.option("output_hierarchy");
|
||||
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");
|
||||
|
@ -60,6 +61,8 @@ int write_pnr_sdc(OpenfpgaContext& openfpga_ctx,
|
|||
options.set_time_unit(string_to_time_unit(cmd_context.option_value(cmd, opt_time_unit)));
|
||||
}
|
||||
|
||||
options.set_output_hierarchy(cmd_context.option_enable(cmd, opt_output_hierarchy));
|
||||
|
||||
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));
|
||||
|
|
|
@ -32,6 +32,9 @@ ShellCommandId add_openfpga_write_pnr_sdc_command(openfpga::Shell<OpenfpgaContex
|
|||
/* Add an option '--hierarchical' */
|
||||
shell_cmd.add_option("hierarchical", false, "Output SDC files hierachically (without full path in hierarchy)");
|
||||
|
||||
/* Add an option '--output_hierarchy' */
|
||||
shell_cmd.add_option("output_hierarchy", false, "Output hierachy of Multiple-Instance-Blocks (MIBs) to plain text file. This is applied to constrain timing for grid, SBs and CBs");
|
||||
|
||||
/* Add an option '--time_unit' */
|
||||
CommandOptionId time_unit_opt = shell_cmd.add_option("time_unit", false, "Specify the time unit in SDC files. Acceptable is [a|f|p|n|u|m|kM]s");
|
||||
shell_cmd.set_option_require_value(time_unit_opt, openfpga::OPT_STRING);
|
||||
|
|
|
@ -44,6 +44,10 @@ float PnrSdcOption::time_unit() const {
|
|||
return time_unit_;
|
||||
}
|
||||
|
||||
bool PnrSdcOption::output_hierarchy() const {
|
||||
return output_hierarchy_;
|
||||
}
|
||||
|
||||
bool PnrSdcOption::generate_sdc_pnr() const {
|
||||
return constrain_global_port_
|
||||
|| constrain_grid_
|
||||
|
@ -109,6 +113,10 @@ void PnrSdcOption::set_time_unit(const float& time_unit) {
|
|||
time_unit_ = time_unit;
|
||||
}
|
||||
|
||||
void PnrSdcOption::set_output_hierarchy(const bool& output_hierarchy) {
|
||||
output_hierarchy_ = output_hierarchy;
|
||||
}
|
||||
|
||||
void PnrSdcOption::set_generate_sdc_pnr(const bool& generate_sdc_pnr) {
|
||||
constrain_global_port_ = generate_sdc_pnr;
|
||||
constrain_grid_ = generate_sdc_pnr;
|
||||
|
|
|
@ -19,6 +19,7 @@ class PnrSdcOption {
|
|||
bool flatten_names() const;
|
||||
bool hierarchical() const;
|
||||
float time_unit() const;
|
||||
bool output_hierarchy() const;
|
||||
bool generate_sdc_pnr() const;
|
||||
bool constrain_global_port() const;
|
||||
bool constrain_non_clock_global_port() const;
|
||||
|
@ -34,6 +35,7 @@ class PnrSdcOption {
|
|||
void set_flatten_names(const bool& flatten_names);
|
||||
void set_hierarchical(const bool& hierarchical);
|
||||
void set_time_unit(const float& time_unit);
|
||||
void set_output_hierarchy(const bool& output_hierarchy);
|
||||
void set_generate_sdc_pnr(const bool& generate_sdc_pnr);
|
||||
void set_constrain_global_port(const bool& constrain_global_port);
|
||||
void set_constrain_non_clock_global_port(const bool& constrain_non_clock_global_port);
|
||||
|
@ -49,6 +51,7 @@ class PnrSdcOption {
|
|||
bool flatten_names_;
|
||||
bool hierarchical_;
|
||||
float time_unit_;
|
||||
bool output_hierarchy_;
|
||||
bool constrain_global_port_;
|
||||
bool constrain_non_clock_global_port_;
|
||||
bool constrain_grid_;
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include "sdc_writer_utils.h"
|
||||
#include "sdc_memory_utils.h"
|
||||
#include "sdc_mux_utils.h"
|
||||
#include "sdc_hierarchy_writer.h"
|
||||
#include "pnr_sdc_global_port.h"
|
||||
#include "pnr_sdc_routing_writer.h"
|
||||
#include "pnr_sdc_grid_writer.h"
|
||||
|
@ -462,6 +463,15 @@ void print_pnr_sdc(const PnrSdcOption& sdc_options,
|
|||
}
|
||||
}
|
||||
|
||||
/* Output hierachy to plain text file */
|
||||
if ( (true == sdc_options.output_hierarchy())
|
||||
&& (true == compact_routing_hierarchy) ) {
|
||||
print_pnr_sdc_routing_sb_hierarchy(sdc_options.sdc_dir(),
|
||||
module_manager,
|
||||
top_module,
|
||||
device_rr_gsb);
|
||||
}
|
||||
|
||||
/* Output routing constraints for Connection Blocks */
|
||||
if (true == sdc_options.constrain_cb()) {
|
||||
if (true == compact_routing_hierarchy) {
|
||||
|
@ -486,6 +496,22 @@ void print_pnr_sdc(const PnrSdcOption& sdc_options,
|
|||
}
|
||||
}
|
||||
|
||||
/* Output hierachy to plain text file */
|
||||
if ( (true == sdc_options.output_hierarchy())
|
||||
&& (true == compact_routing_hierarchy) ) {
|
||||
print_pnr_sdc_routing_cb_hierarchy(sdc_options.sdc_dir(),
|
||||
module_manager,
|
||||
top_module,
|
||||
CHANX,
|
||||
device_rr_gsb);
|
||||
|
||||
print_pnr_sdc_routing_cb_hierarchy(sdc_options.sdc_dir(),
|
||||
module_manager,
|
||||
top_module,
|
||||
CHANY,
|
||||
device_rr_gsb);
|
||||
}
|
||||
|
||||
/* Output Timing constraints for Programmable blocks */
|
||||
if (true == sdc_options.constrain_grid()) {
|
||||
print_pnr_sdc_constrain_grid_timing(sdc_options.sdc_dir(),
|
||||
|
|
|
@ -0,0 +1,173 @@
|
|||
/***************************************************************************************
|
||||
* Output instance hierarchy in SDC to file formats
|
||||
***************************************************************************************/
|
||||
/* Headers from vtrutil library */
|
||||
#include "vtr_log.h"
|
||||
#include "vtr_assert.h"
|
||||
#include "vtr_time.h"
|
||||
|
||||
/* Headers from openfpgautil library */
|
||||
#include "openfpga_digest.h"
|
||||
|
||||
#include "openfpga_naming.h"
|
||||
|
||||
#include "sdc_writer_naming.h"
|
||||
#include "sdc_hierarchy_writer.h"
|
||||
|
||||
/* begin namespace openfpga */
|
||||
namespace openfpga {
|
||||
|
||||
/***************************************************************************************
|
||||
* Write the hierarchy of Switch Block module and its instances to a plain text file
|
||||
* e.g.,
|
||||
* <sdc_file_for_the_module>
|
||||
* <module_name>/<instance_name>
|
||||
* ...
|
||||
* This file is mainly used by hierarchical P&R flow
|
||||
*
|
||||
* Return 0 if successful
|
||||
* Return 1 if there are more serious bugs in the architecture
|
||||
* Return 2 if fail when creating files
|
||||
***************************************************************************************/
|
||||
void print_pnr_sdc_routing_sb_hierarchy(const std::string& sdc_dir,
|
||||
const ModuleManager& module_manager,
|
||||
const ModuleId& top_module,
|
||||
const DeviceRRGSB& device_rr_gsb) {
|
||||
|
||||
std::string fname(sdc_dir + std::string("sb_hierarchy.txt"));
|
||||
|
||||
std::string timer_message = std::string("Write Switch Block hierarchy to plain-text file '") + fname + std::string("'");
|
||||
|
||||
std::string dir_path = format_dir_path(find_path_dir_name(fname));
|
||||
|
||||
/* Create directories */
|
||||
create_directory(dir_path);
|
||||
|
||||
/* Start time count */
|
||||
vtr::ScopedStartFinishTimer timer(timer_message);
|
||||
|
||||
/* Use default name if user does not provide one */
|
||||
VTR_ASSERT(true != fname.empty());
|
||||
|
||||
/* Create a file handler*/
|
||||
std::fstream fp;
|
||||
/* Open a file */
|
||||
fp.open(fname, std::fstream::out | std::fstream::trunc);
|
||||
|
||||
/* Validate the file stream */
|
||||
check_file_stream(fname.c_str(), fp);
|
||||
|
||||
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);
|
||||
if (false == rr_gsb.is_sb_exist()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Find all the sb instance under this module
|
||||
* Create a regular expression to include these instance names
|
||||
*/
|
||||
vtr::Point<size_t> gsb_coordinate(rr_gsb.get_sb_x(), rr_gsb.get_sb_y());
|
||||
std::string sb_module_name = generate_switch_block_module_name(gsb_coordinate);
|
||||
|
||||
ModuleId sb_module = module_manager.find_module(sb_module_name);
|
||||
VTR_ASSERT(true == module_manager.valid_module_id(sb_module));
|
||||
|
||||
/* Create the file name for SDC */
|
||||
std::string sdc_fname(sdc_dir + generate_switch_block_module_name(gsb_coordinate) + std::string(SDC_FILE_NAME_POSTFIX));
|
||||
|
||||
fp << sdc_fname << "\n";
|
||||
|
||||
/* Go through all the instance */
|
||||
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);
|
||||
fp << " - ";
|
||||
fp << sb_module_name << "/" << sb_instance_name << "\n";
|
||||
}
|
||||
|
||||
fp << "\n";
|
||||
}
|
||||
|
||||
/* close a file */
|
||||
fp.close();
|
||||
}
|
||||
|
||||
/***************************************************************************************
|
||||
* Write the hierarchy of Switch Block module and its instances to a plain text file
|
||||
* e.g.,
|
||||
* <sdc_file_for_the_module>
|
||||
* <module_name>/<instance_name>
|
||||
* ...
|
||||
* This file is mainly used by hierarchical P&R flow
|
||||
*
|
||||
* Return 0 if successful
|
||||
* Return 1 if there are more serious bugs in the architecture
|
||||
* Return 2 if fail when creating files
|
||||
***************************************************************************************/
|
||||
void print_pnr_sdc_routing_cb_hierarchy(const std::string& sdc_dir,
|
||||
const ModuleManager& module_manager,
|
||||
const ModuleId& top_module,
|
||||
const t_rr_type& cb_type,
|
||||
const DeviceRRGSB& device_rr_gsb) {
|
||||
|
||||
/* TODO: This is dirty, should use constant to handle this */
|
||||
std::string fname(sdc_dir);
|
||||
if (CHANX == cb_type) {
|
||||
fname += std::string("cbx_hierarchy.txt");
|
||||
} else {
|
||||
VTR_ASSERT(CHANY == cb_type);
|
||||
fname += std::string("cby_hierarchy.txt");
|
||||
}
|
||||
|
||||
std::string timer_message = std::string("Write Connection Block hierarchy to plain-text file '") + fname + std::string("'");
|
||||
|
||||
std::string dir_path = format_dir_path(find_path_dir_name(fname));
|
||||
|
||||
/* Create directories */
|
||||
create_directory(dir_path);
|
||||
|
||||
/* Start time count */
|
||||
vtr::ScopedStartFinishTimer timer(timer_message);
|
||||
|
||||
/* Use default name if user does not provide one */
|
||||
VTR_ASSERT(true != fname.empty());
|
||||
|
||||
/* Create a file handler*/
|
||||
std::fstream fp;
|
||||
/* Open a file */
|
||||
fp.open(fname, std::fstream::out | std::fstream::trunc);
|
||||
|
||||
/* Validate the file stream */
|
||||
check_file_stream(fname.c_str(), fp);
|
||||
|
||||
/* Print SDC for unique X-direction connection block modules */
|
||||
for (size_t icb = 0; icb < device_rr_gsb.get_num_cb_unique_module(cb_type); ++icb) {
|
||||
const RRGSB& unique_mirror = device_rr_gsb.get_cb_unique_module(cb_type, icb);
|
||||
|
||||
/* Find all the cb instance under this module
|
||||
* Create a regular expression to include these instance names
|
||||
*/
|
||||
vtr::Point<size_t> gsb_coordinate(unique_mirror.get_cb_x(cb_type), unique_mirror.get_cb_y(cb_type));
|
||||
std::string cb_module_name = generate_connection_block_module_name(cb_type, gsb_coordinate);
|
||||
ModuleId cb_module = module_manager.find_module(cb_module_name);
|
||||
VTR_ASSERT(true == module_manager.valid_module_id(cb_module));
|
||||
|
||||
/* Create the file name for SDC */
|
||||
std::string sdc_fname(sdc_dir + generate_connection_block_module_name(cb_type, gsb_coordinate) + std::string(SDC_FILE_NAME_POSTFIX));
|
||||
|
||||
fp << sdc_fname << "\n";
|
||||
|
||||
/* Go through all the instance */
|
||||
for (const size_t& instance_id : module_manager.child_module_instances(top_module, cb_module)) {
|
||||
std::string cb_instance_name = module_manager.instance_name(top_module, cb_module, instance_id);
|
||||
fp << " - ";
|
||||
fp << cb_module_name << "/" << cb_instance_name << "\n";
|
||||
}
|
||||
|
||||
fp << "\n";
|
||||
}
|
||||
|
||||
/* close a file */
|
||||
fp.close();
|
||||
}
|
||||
|
||||
} /* end namespace openfpga */
|
Loading…
Reference in New Issue